---@class UGCPlayerPawn_C:BP_UGCPlayerPawn_C --Edit Below-- ---@type UGCPlayerPawn_C local UGCPlayerPawn = {}; function UGCPlayerPawn:ReceiveBeginPlay() self.SuperClass.ReceiveBeginPlay(self); self.bVaultIsOpen = DefaultSettings.OpenVault; self.DamageNotifyDelegate:Add(self.PlayerInjury, self) --- 仅客户端 --self.OnCharacterShootDelegate:Add(function(Pawn, Weapon) -- UGCLogSystem.Log("[UGCPlayerPawn:ReceiveBeginPlay] %s 开始射击", UE.GetName(Weapon)); --end, self); --self.OnCharacterStartFireDelegate:Add(function(Pawn, Weapon) -- UGCLogSystem.Log("[UGCPlayerPawn:ReceiveBeginPlay] Weapon = %s 开火", UE.GetName(Weapon)) --end, self) end --function UGCPlayerPawn:ReceiveTick(DeltaTime) -- self.SuperClass.ReceiveTick(self, DeltaTime); --end function UGCPlayerPawn:ReceiveEndPlay() if GlobalTickTool then GlobalTickTool:RemoveTickByOwner(self) end self.SuperClass.ReceiveEndPlay(self); end --function UGCPlayerPawn:GetReplicatedProperties() -- return; --end function UGCPlayerPawn:GetAvailableServerRPCs() return "UpdateWeaponParts" end function UGCPlayerPawn:ReceivePossessed(NewController) self.SuperClass.ReceivePossessed(self, NewController); UGCLogSystem.Log("[UGCPlayerPawn:ReceivePossessed] 是否可以滑铲:%s", tostring(GameState.EnableShovel)); UGCPawnSystem.DisabledPawnState(self, EPawnState.Shoveling, not GameState.EnableShovel); table.func(MiniManager, "OnPlayerPossessed", self, NewController); end ---@return bool 是否开启掉落盒子 function UGCPlayerPawn:IsSkipSpawnDeadTombBox(EventInstigater) return DefaultSettings.EnableDeadBox; end ----------------------------------------- 玩家伤害处理 ----------------------------------------- function UGCPlayerPawn:PreInstigatedDamage(DamageAmount, DamageEvent, DamageCauser, Victim) UGCLogSystem.Log("[UGCPlayerPawn:PreInstigatedDamage] DamageAmount = %f", DamageAmount); return DamageAmount; end ---@param ShootWeapon ASTExtraShootWeapon ---@param Bullet ASTExtraShootWeaponBulletBase function UGCPlayerPawn:UGC_WeaponShootBulletEvent(ShootWeapon, Bullet) self.SuperClass.UGC_WeaponShootBulletEvent(self, ShootWeapon, Bullet); end --- 武器攻击到什么东西的时候 ---@param ShootWeapon ASTExtraShootWeapon ---@param Bullet ASTExtraShootWeaponBulletBase ---@param HitInfo FHitResult function UGCPlayerPawn:UGC_WeaponBulletHitEvent(ShootWeapon, Bullet, HitInfo) --local HitActor = HitInfo.Actor:Get() --if HitActor and UE.IsValid(HitActor) and UE.Is then -- UGCLogSystem.Log("[UGCPlayerPawn:UGC_WeaponBulletHitEvent] 击中 %s", UE.GetName(HitActor)); -- --end end function UGCPlayerPawn:PlayerInjury(DamageInfo) if IsServer then local DamageData = self:GetDamageData(DamageInfo) MiniManager:OnPlayerInjury(DamageData.VictimKey, DamageData.CauserKey, DamageData); end end ---@param DamageInfo FDamageInfoCollection function UGCPlayerPawn:GetDamageData(DamageInfo) local CauserController = DamageInfo.Instigator local WeaponID = -1 local CauserKey = CauserController and CauserController.PlayerKey or -1 local VictimKey = self.PlayerKey local CauserItemID = DamageInfo.CauserItemID UGCLogSystem.LogTree(string.format("[UGCPlayerPawn:GetDamageData] DamageInfo ="), DamageInfo) --- 近战投掷、投掷手雷 if CauserItemID then WeaponID = CauserItemID; end UGCLogSystem.Log("[UGCPlayerPawn_GetDamageInfoCollectionInfo] WeaponID:%d", WeaponID) --local Distance = 0. --if CauserController and CauserController.Pawn then -- Distance = VectorHelper.GetDistance(self:K2_GetActorLocation(), CauserController.Pawn:K2_GetActorLocation()) --end local IsHeadShotDamage = (DamageInfo.Hit.BoneName == "head"); return { VictimKey = VictimKey, -- 受伤者 CauserKey = CauserKey, -- 导致者 WeaponID = WeaponID, -- 武器ID DamageType = DamageInfo.DamageType, IsHeadShotDamage = IsHeadShotDamage, -- 暴击 --Distance = Distance, -- 距离, Damage = DamageInfo.Damage, }; end -------------------------------- 玩家物品处理 -------------------------------- --- 添加物品,如果是要添加武器,可以在后面的选项进行配置,可添加选项为 是否需要添加对应的配件 武器无限子弹配置 EFillBulletType (bool&EFillBulletType | EFillBulletType) ---@param InItemId int32 ---@param InItemCount int32 function UGCPlayerPawn:AddItem(InItemId, InItemCount, ...) UGCLogSystem.Log("[UGCPlayerPawn:AddItem] InItemId = %d", InItemId); ItemTool.AddItem(self, InItemId, InItemCount, ...); UGCLogSystem.Log("[ItemTool.AddItem] 执行") ItemTool.FillAllWeaponBullets(self); UGCEventSystem.SetTimer(self, function() UGCLogSystem.Log("[ItemTool.AddItem] 再次添加子弹") ItemTool.FillAllWeaponBullets(self); end, 1); end --- 添加初始物品 function UGCPlayerPawn:AddInitItems(Weapons) if table.isEmpty(Weapons) then Weapons = DefaultSettings.PlayerInitEquipment end if not table.isEmpty(Weapons) then for i, v in pairs(Weapons) do local ItemId = -1; if type(v[1]) == 'string' then local Item = EnglishNamedWeapon[v[1]] if Item == nil then ItemId = ItemNameTable[v[1]] == nil and ItemId or ItemNameTable[v[1]] else ItemId = Item.ItemId; end elseif type(v[1]) == 'number' then ItemId = v[1]; end local Params = {}; if #v > 1 then for c = 2, #v do Params[#Params + 1] = v[c]; end end UGCLogSystem.LogTree(string.format("[UGCPlayerPawn:AddInitItems] First = %s, Params =", v[1]), Params) if ItemId ~= -1 then self:AddItem(ItemId, table.unpackTable(Params)); end end end end --- ---@param slot ESurviveWeaponPropSlot ---@overload fun(slot:ESurviveWeaponPropSlot) OnEquipWeapon function UGCPlayerPawn:OnEquipWeapon(slot) --UGCLogSystem.Log("[UGCPlayerPawn:OnEquipWeapon] slot = %s, ESurviveWeaponPropSlot.SWPS_HandProp = %d", tostring(slot), ESurviveWeaponPropSlot.SWPS_HandProp); --if slot == ESurviveWeaponPropSlot.SWPS_HandProp then -- UGCLogSystem.Log("[UGCPlayerPawn:OnEquipWeapon] 切换成拳头") --end UGCEventSystem.SendEvent(EventTypes.PlayerChangeWeapon, self, slot, UGCWeaponManagerSystem.GetWeaponBySlot(self, slot)); end --- 当玩家获取武器之后执行 ---@param Weapon ASTExtraShootWeapon function UGCPlayerPawn:OnPostGetWeapon(Weapon) table.func(MiniManager, "OnPlayerGetWeapon", self, Weapon) --- 绑定 delegate if ItemTool.IsShootWeapon(Weapon) then --- 客户端 --Weapon.OnBulletNumChangeDelegate:Add(function() -- UGCLogSystem.Log("[UGCPlayerPawn:OnPostGetWeapon] 子弹数量改变"); --end, self); -- --Weapon.OnWeaponShootDelegate:Add(function() -- UGCLogSystem.Log("[UGCPlayerPawn:OnPostGetWeapon] 武器开火") --end, self); Weapon.OnDSBulletNumChangeDelegate:Add(self.OnBulletNumChanged, self); end end --- 玩家是否有近战武器 function UGCPlayerPawn:IsPawnHasMeleeWeapon(WeaponID, Count) local HadCount = 0; local AllDatas = UGCBackPackSystem.GetAllItemData(self); for i, Info in pairs(AllDatas) do if Info.ItemID == WeaponID then HadCount = HadCount + Info.Count; end end if Count == HadCount then return true; end return false, Count; end --- 检查玩家是否在 Slot 上有武器 function UGCPlayerPawn:IsPawnHasShootWeapon(WeaponID, Slot) if Slot then local Weapon = UGCWeaponManagerSystem.GetWeaponBySlot(self, Slot); if Weapon and UE.IsValid(Weapon) then if Weapon:GetWeaponItemID() == WeaponID then return true; end end else for i, Enum in pairs(ShootWeaponEnums) do local Weapon = UGCWeaponManagerSystem.GetWeaponBySlot(self, Enum) if Weapon and UE.IsValid(Weapon) then if Weapon:GetWeaponItemID() == WeaponID then return true; end end end end return false; end UGCPlayerPawn.CheckSlotWeaponsTimer = nil; function UGCPlayerPawn:CloseCheckSlotWeaponsTimer() if self.CheckSlotWeaponsTimer then UGCEventSystem.StopTimer(self.CheckSlotWeaponsTimer); self.CheckSlotWeaponsTimer = nil; end end ---@type table 插槽武器 UGCPlayerPawn.SlotWeapons = {}; ---@param Weapons table 插槽武器 function UGCPlayerPawn:UpdateSlotWeapons(Weapons) self.SlotWeapons = TableHelper.DeepCopyTable(Weapons); for i = 0, ESurviveWeaponPropSlot.SWPS_Max do if self.SlotWeapons[i] then self:CheckHasSlotWeapon(i, self.SlotWeapons[i]); end end self:CheckSlotWeapons(); end --- 通过插槽检查武器,需要先配置好之后再启动,该方法仅限两把武器,如果只有一把武器,SlotWeapons的第一个值必须为 SWPS_MainShootWeapon1 function UGCPlayerPawn:CheckSlotWeapons() if table.isEmpty(self.SlotWeapons) then return self:CloseCheckSlotWeaponsTimer(); end UGCLogSystem.Log("[UGCPlayerPawn:CheckSlotWeapons] 开始检测是否添加") self.CheckSlotWeaponsTimer = UGCEventSystem.SetTimerLoop(self, function() for i = 0, ESurviveWeaponPropSlot.SWPS_Max do if self.SlotWeapons[i] then self:CheckHasSlotWeapon(i, self.SlotWeapons[i]); end end end, 1); end ---@param Slot ESurviveWeaponPropSlot ---@param WeaponID int32 function UGCPlayerPawn:CheckHasSlotWeapon(Slot, WeaponID) if Slot == nil then return ; end if self.SlotWeapons[Slot] == nil then self.SlotWeapons[Slot] = WeaponID; end local Weapon = UGCWeaponManagerSystem.GetWeaponBySlot(self, Slot); if Weapon == nil or not UE.IsValid(Weapon) then ItemTool.AddWeaponItem(self, WeaponID, 1, true, EFillBulletType.ClipInfinite); return ; end local SlotWeaponID = Weapon:GetWeaponItemID(); if SlotWeaponID == WeaponID then self.SlotWeapons[Slot] = nil; return ; end local DefineID = Weapon:GetItemDefineID(); ItemTool.RemoveWeapon(self, Weapon); ItemTool.AddWeaponItem(self, WeaponID, 1, true, EFillBulletType.ClipInfinite); end UGCPlayerPawn.CurrBulletNum = -1; function UGCPlayerPawn:OnBulletNumChanged(Weapon) local BulletCount = Weapon.CurBulletNumInClip; if self.CurrBulletNum == -1 then self.CurrBulletNum = BulletCount; end if self.CurrBulletNum > BulletCount then local ItemID = Weapon:GetWeaponItemID(); table.func(MiniManager, "OnBulletNumChange", self.PlayerKey, ItemID, self.CurrBulletNum, BulletCount); end self.CurrBulletNum = BulletCount; end --- 替换配件 ---@param InPartId int32 ---@param InType EWeaponPartType function UGCPlayerPawn:ReplacePartId(InPartId, InType) UGCLogSystem.Log("[UGCPlayerPawn:ReplacePartId] 替换 InPartId = %s", tostring(InPartId)); -- 移除当前 local Weapon = UGCWeaponManagerSystem.GetCurrentWeapon(self); if Weapon == nil or (not UE.IsValid(Weapon)) then return UGCLogSystem.Log("[UGCPlayerPawn:ReplacePartId] 不存在武器 或 武器无效"); end local ItemID = Weapon:GetWeaponItemID(); if table.isEmpty(WeaponSuits[ItemID]) then return UGCLogSystem.Log("[UGCPlayerPawn:ReplacePartId] 武器不是 射击武器") end -- 找到类型 if InType == nil then InType = WeaponParts[InPartId].Type end local SocketType = ItemTool.GetWeaponAttachmentSocketType(InType); local DefineID = ItemTool.GetDefineIDBySocketType(Weapon, SocketType); if DefineID then ItemTool.RemoveItemByDefineID(self, DefineID); end if InPartId ~= 0 then UGCGunSystem.CreateAndAddGunAttachment(Weapon, InPartId); UGCLogSystem.Log("[UGCPlayerPawn:ReplacePartId] 添加配件: %d", InPartId); -- 检查武器上是否有这个配件 local PartDefineID = ItemTool.GetDefineIDBySocketType(Weapon, SocketType); if PartDefineID == nil or PartDefineID.TypeSpecificID ~= InPartId then UGCGunSystem.CreateAndAddGunAttachment(Weapon, InPartId); local ItemIds = ItemTool.GetWeaponParts(Weapon); UGCLogSystem.LogTree(string.format("[UGCPlayerPawn:ReplacePartId] ItemIds ="), ItemIds); end end if ArchiveTable[self.PlayerKey].Weapons == nil then ArchiveTable[self.PlayerKey].Weapons = {}; end ArchiveTable[self.PlayerKey].Weapons[ItemID] = ItemTool.GetWeaponParts(Weapon); end --- 更新武器配件 function UGCPlayerPawn:UpdateWeaponParts(WeaponID, WeaponParts) ArchiveTable[self.PlayerKey].Weapons[WeaponID] = WeaponParts; local Weapons = {}; for i, Enum in pairs(AllWeaponEnums) do local Weapon = UGCWeaponManagerSystem.GetWeaponBySlot(self, Enum); if Weapon and UE.IsValid(Weapon) then if Weapon:GetWeaponItemID() == WeaponID then table.insert(Weapons, Weapon); end end end -- for i, Weapon in pairs(Weapons) do local HadSet = false; if Weapon and UE.IsValid(Weapon) then local CurrWeaponID = Weapon:GetWeaponItemID(); if CurrWeaponID == WeaponID then -- 直接设置 Parts ItemTool.SetWeaponParts(Weapon, WeaponParts); HadSet = true; end end if not HadSet then UGCLogSystem.LogError("[UGCPlayerPawn:UpdateWeaponParts] 当前武器跟设置的武器不相同,检查一下, WeaponID : %d", WeaponID); end end UnrealNetwork.CallUnrealRPC(self:GetPlayerControllerSafety(), self, "RecvWeaponParts", WeaponID, WeaponParts); end function UGCPlayerPawn:RecvWeaponParts(WeaponID, Parts) if table.isEmpty(ArchiveTable[LocalPlayerKey]) then ArchiveTable[LocalPlayerKey] = {}; end if table.isEmpty(ArchiveTable[LocalPlayerKey].Weapons) then ArchiveTable[LocalPlayerKey].Weapons = {}; end ArchiveTable[LocalPlayerKey].Weapons[WeaponID] = Parts; UGCLogSystem.LogTree(string.format("[UGCPlayerPawn:RecvWeaponParts] Parts ="), Parts) UGCEventSystem.SendEvent(EventTypes.UpdateWeapons, WeaponID) end --- 发送 RPC 进行再次同步 function UGCPlayerPawn:UpdateEnterWeapons(Index, Weapons) if table.isEmpty(ArchiveTable[self.PlayerKey]) then ArchiveTable[self.PlayerKey] = {}; end if table.isEmpty(ArchiveTable[self.PlayerKey].EnterWeapons) then ArchiveTable[self.PlayerKey].EnterWeapons = {}; end ArchiveTable[self.PlayerKey].EnterWeapons[Index] = Weapons; UGCEventSystem.SendEvent(EventTypes.UpdateEnterWeapons); end --- 处理飘字 客户端触发 function UGCPlayerPawn:UGC_GetDamageNumberConfigIndex(Damage, IsHeadShot, InstigatorController, DamageCauser, DamageType) if DefaultSettings.EnableDamageText then if InstigatorController == LocalPlayerController then return LocalPlayerController.EnableDamageText and 0 or -1; end end return -1 end -------------------------------- 测试 -------------------------------- function UGCPlayerPawn:AddOutline() if IsClient then if DefaultSettings.EnableOutline then if self.PlayerKey ~= LocalPlayerKey then UGCLogSystem.Log("[UGCPlayerPawn:AddOutline] 尝试添加") STExtraBlueprintFunctionLibrary.EnablePlayerAvatarOutline(self, true); --UGCGameSystem.GameState:RegisterPostProcessMgr(self); end end end end return UGCPlayerPawn;