---@class UGCPlayerPawn_C:BP_UGCPlayerPawn_C --Edit Below-- ---@type UGCPlayerPawn_C local UGCPlayerPawn = {}; UGCPlayerPawn.Strong = 1.; UGCPlayerPawn.Defence = 1.; UGCPlayerPawn.PoisonDefence = 1.; --- 启用毒圈 UGCPlayerPawn.DashDuration = -1 UGCPlayerPawn.CachedSTCharacterMovementGravityScale = 1.5 --- 毒圈伤害 UGCPlayerPawn.PoisonDamage = 0; function UGCPlayerPawn:ReceiveBeginPlay() self.SuperClass.ReceiveBeginPlay(self); self:AddEvent() -- 开启攀爬 self.bVaultIsOpen = true; -- 开启滑铲 self.IsOpenShovelAbility = true; if self:HasAuthority() then -- 装备一下 local PC = UGCGameSystem.GetPlayerControllerByPlayerKey(self.PlayerKey); if UE.IsValid(PC) then end -- 检查是否存在 Soldier Type local SoldierType = UGCGameSystem.GameState.PlayerSoldierType[self.PlayerKey]; if SoldierType ~= nil then self:OnSetSoldierType(SoldierType); -- 改变对应数据即可 end self:EnablePickUp(false); else UGCEventSystem.AddListener(EventTypes.SkillBenefit, self.OnSkillBenefit, self) end ---- 缓存一下 self:Client_OnShootEmitter(nil); self.DamageNotifyDelegate:Add(self.OnDamageNotify_Test, self) -- 获取 Init UGCEventSystem.SetTimer(self, function() self:InitPawn() end, 1.3) end --function UGCPlayerPawn:ReceivePossessed(NewController) -- NewController:SetCanMove(false); --end function UGCPlayerPawn:AddEvent() if self:HasAuthority() then self.DeadNotifyDelegate:Add(self.PlayerDead, self) self.DamageNotifyDelegate:Add(self.PlayerInjury, self) else end end function UGCPlayerPawn:RemoveEvent() if self:HasAuthority() then self.DeadNotifyDelegate:Remove(self.PlayerDead, self) self.DamageNotifyDelegate:Remove(self.PlayerInjury, self) else end end function UGCPlayerPawn:InitPawn() -- 执行初始化 if IsClient then local MainControlPanel = GameBusinessManager.GetWidgetFromName(ingame, "MainControlPanelTochButton_C"); MainControlPanel:SetVisibility(ESlateVisibility.SelfHitTestInvisible); end end function UGCPlayerPawn:ReceiveTick(DeltaTime) self.SuperClass.ReceiveTick(self, DeltaTime); --self:TickDash(DeltaTime) end function UGCPlayerPawn:ReceiveEndPlay() self:RemoveEvent() self.SuperClass.ReceiveEndPlay(self); end --- 设置兵种特征(在玩家进入的时候) ---@param InType int32 兵种类型 function UGCPlayerPawn:OnSetSoldierType(InType) local Feature = SoldierConfig.Features[InType] if table.isEmpty(Feature) then return ; end for i, v in pairs(Feature) do if i == SoldierConfig.ESpecialType.Health then UGCPawnAttrSystem.SetHealthMax(self, UGCPawnAttrSystem.GetHealthMax(self) * v) UGCPawnAttrSystem.SetHealth(self, UGCPawnAttrSystem.GetHealthMax(self)); elseif i == SoldierConfig.ESpecialType.Speed then UGCPawnAttrSystem.SetSpeedScale(self, UGCPawnAttrSystem.GetSpeedScale(self) * v) elseif i == SoldierConfig.ESpecialType.Damage then -- 设置对应数据即可 self:SetParam('Strong', self.Strong * v); elseif i == SoldierConfig.ESpecialType.Poison then self.Defence = self.Defence * v; -- 永久改变 elseif i == SoldierConfig.ESpecialType.Jump then UGCPawnAttrSystem.SetJumpZVelocity(self, UGCPawnAttrSystem.GetJumpZVelocity(self) * v); end end end function UGCPlayerPawn:GetReplicatedProperties() return { "PoisonDamage", "Lazy" } end function UGCPlayerPawn:GetAvailableServerRPCs() return "ReplacePartId" end ---100000 - 199999 武器 ---200000 - 299999 配件 ---300000 - 399999 子弹 ---400000 - 499999 衣服 ---500000 - 599999 背包 / 护甲 / 头盔等 ---600000 - 699999 补给品、投掷物等 ---700000 - 799999 降落伞 ---800000 - 899999 头盔、护甲皮肤 --- 清楚所有武器配件 function UGCPlayerPawn:ClearAllWeaponsAndProp() local AllItem = UGCBackPackSystem.GetAllItemData(self) if AllItem then for Index, Item in pairs(AllItem) do if (Item.ItemID > 100000 and Item.ItemID < 400000) -- 武器、配件、子弹等 or (Item.ItemID >= 8300000) -- 自定义的东西 or (Item.ItemID > 500000 and Item.ItemID < 700000) -- 补给品 then UGCBackPackSystem.DropItem(self, Item.ItemID, Item.Count, true) end end end end --- 添加物品 ---@param InItemId int32 ---@param InCount int32 function UGCPlayerPawn:AddItem(InItemId, InCount) return UGCBackPackSystem.AddItem(self, InItemId, InCount); end function UGCPlayerPawn:PostAddItems() end function UGCPlayerPawn:OnSkillBenefit(InUseKey, InBenefitPlayers, InBuffType) -- 分别执行不同的特效 UGCLogSystem.LogTree(string.format("[UGCPlayerPawn:OnSkillBenefit] 操作的玩家:%d, InBenefitPlayers =", InUseKey), InBenefitPlayers) end UGCPlayerPawn.PlayerUseBuffs = {}; function UGCPlayerPawn:OnPlayerUseBuff(InPlayerKey, InBuffType, InBuffInfo, InServerTime) -- 全局提示 local Params = { InPlayerKey = InPlayerKey, InBuffType = InBuffType, InBuffInfo = InBuffInfo, InServerTime = InServerTime }; UGCLogSystem.LogTree('[UGCPlayerPawn:OnPlayerUseBuff] Params = ', Params); UGCLogSystem.Log("[UGCPlayerPawn:OnPlayerUseBuff] self = %s", tostring(self)) local TeamId = UGCGameSystem.GameState:GetPlayerTeamId(InPlayerKey); if TeamId == DefaultSettings.LocalTeamId then local Name = UGCGameSystem.GameState:GetPlayerNameByPlayerKey(InPlayerKey); UGCLogSystem.Log("[UGCPlayerPawn:OnPlayerUseBuff] Name = %s", Name) if self.PlayerUseBuffs[InServerTime] == nil then self.PlayerUseBuffs[InServerTime] = InPlayerKey; UGCWidgetManagerSystem.ShowTipsUI(string.format('%s 启动了技能:%s', Name, BuffConfig.BuffInfo[InBuffType].Desc)); end end end UGCPlayerPawn.CachedGravity = 1; UGCPlayerPawn.ImpulseLength = 9; UGCPlayerPawn.ImpulseMoveTime = 0.1; UGCPlayerPawn.StartLoc = nil; UGCPlayerPawn.LimitDis = 50.; --- 给定一个方向 function UGCPlayerPawn:AddImpulse(InImpulse) UGCLogSystem.Log("[UGCPlayerPawn:AddImpulse] Impulse = %s", VectorHelper.ToString(InImpulse)); -- 缓存重力 self.StartLoc = self:K2_GetActorLocation(); self.CharacterMovement.Velocity = VectorHelper.MulNumber(InImpulse, VectorHelper.Length(self.CharacterMovement.Velocity)); self.CharacterMovement:AddImpulse(VectorHelper.MulNumber(InImpulse, self.ImpulseLength * 40), true); if IsServer then UnrealNetwork.CallUnrealRPC(UGCGameSystem.GetPlayerControllerByPlayerKey(self.PlayerKey), self, "AddImpulse", InImpulse); UGCEventSystem.SetTimer(self, function() self:StopImpulse(); end, self.ImpulseMoveTime); end GlobalTickTool:AddTick(self, function(o, dt, ServerTime) o.CharacterMovement:AddImpulse(VectorHelper.MulNumber(InImpulse, self.ImpulseLength * dt), true); if o.CharacterMovement.MovementMode ~= EMovementMode.MOVE_Falling then o.CharacterMovement:SetMovementMode(EMovementMode.MOVE_Falling); end self.CharacterMovement.Velocity = VectorHelper.MulNumber(InImpulse, math.clamp(VectorHelper.Length(self.CharacterMovement.Velocity), 0, 300)); -- 计算距离,超过 local Dis = VectorHelper.GetDistance(self:K2_GetActorLocation(), self.StartLoc); if Dis > self.LimitDis then self:StopImpulse(); GlobalTickTool:RemoveTick(self); end end, nil, self.ImpulseMoveTime); end function UGCPlayerPawn:StopImpulse() if IsServer then UnrealNetwork.CallUnrealRPC(UGCGameSystem.GetPlayerControllerByPlayerKey(self.PlayerKey), self, "StopImpulse"); end end --------------------------------- Damage --------------------------------- ---@public ---@param InParamName string ---@param InVal float function UGCPlayerPawn:SetParam(InParamName, InVal) if self[InParamName] ~= nil then self[InParamName] = InVal; end UGCLogSystem.Log("[UGCPlayerPawn:SetParam] Pawn: %s %s To %s", UE.GetName(self), InParamName, tostring(InVal)); end ---@public ---@param InParamName string ---@return float function UGCPlayerPawn:GetParam(InParamName) return self[InParamName]; end --- 接收到伤害之后执行 --- S & C ---@field BPReceiveDamage fun(Damage:float,DamageType:UDamageType,InstigatedBy:AController,DamageCauser:AActor) function UGCPlayerPawn:BPReceiveDamage(Damage, DamageType, InstigatedBy, DamageCauser) UGCLogSystem.Log("[UGCPlayerPawn:BPReceiveDamage] Damage = %s", tostring(Damage)); -- 此时已经是玩家受到伤害了,用当前玩家的血量进行判断 end UGCPlayerPawn.InPoisonDamage = false; function UGCPlayerPawn:HandlePoisonDamage(InDamage, InCurrHealth, InMaxHealth) -- 显示毒圈标识 self.InPoisonDamage = true; self.PoisonDamage = InDamage; UGCEventSystem.SendEvent(EventTypes.PlayerPoisonDamage, self.PlayerKey, InDamage); end -- 死亡之后不掉落死亡盒子 function UGCPlayerPawn:IsSkipSpawnDeadTombBox(EventInstigater) return true; end function UGCPlayerPawn:GetKillAssists() return self.KillAssists; end --- 玩家获取武器 ---@param Weapon ASTExtraShootWeapon function UGCPlayerPawn:OnPostGetWeapon(Weapon) if UGCGameSystem.IsServer() then local ItemId = Weapon:GetWeaponItemID(); if ItemId == 107001 then -- 产生一个放射性伤害 Weapon:SetReloadTime(0.3); end -- 检测当前是否是志愿兵 local SoldierType = UGCGameSystem.GameState:GetSoldierTypeByPlayerKey(self.PlayerKey) if SoldierType == SoldierConfig.ESoldierType.Volunteer then UGCGunSystem.EnableClipInfiniteBullets(Weapon, true); end end end --- 玩家装备武器 ---@param slot ESurviveWeaponPropSlot function UGCPlayerPawn:OnEquipWeapon(slot) -- 玩家装备武器 if slot == ESurviveWeaponPropSlot.SWPS_HandProp then return ; end local Weapon = UGCWeaponManagerSystem.GetWeaponBySlot(self, slot); if Weapon ~= nil and UE.IsValid(Weapon) then UGCEventSystem.SendEvent(EventTypes.PlayerChangeWeapon, self, slot, Weapon); end end --- 替换配件 ---@param InPartId int32 ---@param InType EWeaponPartType function UGCPlayerPawn:ReplacePartId(InPartId, InType) UGCLogSystem.Log("[UGCPlayerPawn:ReplacePartId] 替换 InPartId = %d", InPartId); -- 移除当前 local Weapon = UGCWeaponManagerSystem.GetCurrentWeapon(self); if Weapon == nil then return ; end if not ItemTool.IsShootWeapon(Weapon) then return ; end local DefineID = ItemTool.GetDefineIDBySocketType(Weapon, ItemTool.GetWeaponAttachmentSocketType(InType)); if DefineID then UGCBackPackSystem.DropItemByInstanceID(self, DefineID.InstanceID, 1, true); end if InPartId ~= 0 then ItemTool.AddItem(self, InPartId, 1) end local PS = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey); table.func(PS, "UpdateWeaponAttachment", self, Weapon); end --- 武器攻击到什么东西的时候 ---@param ShootWeapon ASTExtraShootWeapon ---@param Bullet ASTExtraShootWeaponBulletBase ---@param HitInfo FHitResult function UGCPlayerPawn:UGC_WeaponBulletHitEvent(ShootWeapon, Bullet, HitInfo) if UGCGameSystem.IsServer() then local ItemId = ShootWeapon:GetWeaponItemID(); local Loc = VectorHelper.Add(HitInfo.Location, { X = 0, Y = 0, Z = 30 }); if ItemId == 107001 then local DamageChannel = ECollisionChannel.ECC_Visibility; UGCGameSystem.ApplyRadialDamage( 60, 10, Loc, 10, 200, 4, EDamageType.RadialDamage, {}, ShootWeapon, UGCGameSystem.GetPlayerControllerByPlayerKey(self.PlayerKey), DamageChannel, ItemId ); UnrealNetwork.CallUnrealRPC_Multicast(self, "Client_OnShootEmitter", Loc); end end end function UGCPlayerPawn:Client_OnShootEmitter(Location) local Path = '/Game/Arts_Effect/ParticleSystems/Share/P_AH6_baozha_01.P_AH6_baozha_01'; UE.AsyncLoadObject_Cached(Path, function(TargetObject) if Location == nil then return ; end GameplayStatics.SpawnEmitterAtLocation(self, TargetObject, Location, VectorHelper.RotZero(), VectorHelper.ScaleOne(), true); end) end -------------------------------------------------- Delegate -------------------------------------------------- ---@param DamageInfo FDamageInfoCollection ---@return uint, uint, int, EDamageType, bool, float, float VictimKey, CauserKey, WeaponID, DamageType, IsHeadShotDamage, Distance, DamageValue function UGCPlayerPawn:GetDamageInfoCollectionInfo(DamageInfo) local CauserController = DamageInfo.Instigator local WeaponID = -1 local CauserKey = CauserController and CauserController.PlayerKey or -1 local VictimKey = self.PlayerKey local CauserItemID = DamageInfo.CauserItemID --- 近战投掷、投掷手雷 if CauserItemID then WeaponID = CauserItemID end UGCLogSystem.Log("[UGCPlayerPawn_GetDamageInfoCollectionInfo] WeaponID: %d", WeaponID) local Distance = 0. if CauserController and CauserController:GetPlayerCharacterSafety() then Distance = VectorHelper.GetDistance(self:K2_GetActorLocation(), CauserController:GetPlayerCharacterSafety():K2_GetActorLocation()) end local IsHeadShotDamage = (DamageInfo.Hit.BoneName == "head") return VictimKey, CauserKey, WeaponID, DamageInfo.DamageType, IsHeadShotDamage, Distance, DamageInfo.Damage end ---@param DamageInfo FDamageInfoCollection function UGCPlayerPawn:PlayerDead(DamageInfo) local VictimKey, CauserKey, WeaponID, DamageType, IsHeadShotDamage, Distance, DamageValue = self:GetDamageInfoCollectionInfo(DamageInfo) UGCSendRPCSystem.RPCEvent(nil, EventTypes.PlayerDeathInfo, VictimKey, CauserKey, WeaponID, DamageType, IsHeadShotDamage, Distance, DamageValue) UGCEventSystem.SendEvent(EventTypes.PlayerDeathInfo, VictimKey, CauserKey, WeaponID, DamageType, IsHeadShotDamage, Distance, DamageValue) end ---@param DamageInfo FDamageInfoCollection ---@param ReturnValue float function UGCPlayerPawn:PlayerInjury(DamageInfo) local VictimKey, CauserKey, WeaponID, DamageType, IsHeadShotDamage, Distance, DamageValue = self:GetDamageInfoCollectionInfo(DamageInfo) UGCSendRPCSystem.RPCEvent(CauserKey, EventTypes.PlayerInjuryInfo, VictimKey, CauserKey, WeaponID, DamageType, IsHeadShotDamage, Distance, DamageValue) end ------------------------------------------------ Delegate End ------------------------------------------------ function UGCPlayerPawn:PlayerDashSkill(Duration, DashForce) --local ForwardV = self:GetActorForwardVector() --self.DashDuration = 0.5 --self.LaunchCharacterForce = VectorHelper.MulNumber(ForwardV, 10000) self:DashTo(self:GetActorForwardVector(), Duration, DashForce) UGCSendRPCSystem.ActorRPCNotify(nil, self, "DashTo", VectorHelper.ToLuaTable(self:GetActorForwardVector()), Duration, DashForce) UGCLogSystem.Log("[UGCPlayerPawn_PlayerSprintSkill] Finish") end --- 关闭重力影响 ---@param On bool function UGCPlayerPawn:TurnOffGravityScale(On) if On then self.STCharacterMovement.GravityScale = 0; else self.STCharacterMovement.GravityScale = self.CachedSTCharacterMovementGravityScale; end end function UGCPlayerPawn:EnableDashTo(On) self:TurnOffGravityScale(On); end function UGCPlayerPawn:TickDash(DeltaTime) -- 冲刺时间 if self.DashDuration > 0 then self.DashDuration = self.DashDuration - DeltaTime; if self.DashDuration <= 0 then self.LaunchDir = nil; self:EnableDashTo(false); end if self.LaunchDir then local TargetLocation = VectorHelper.Add(self:K2_GetActorLocation(), VectorHelper.MulNumber(self.LaunchDir, self.LaunchCharacterForce * DeltaTime)) local bMoveSucceed, HitRes = self:K2_SetActorLocation(TargetLocation, true) -- 平移过程要检测下落 if self.CharacterMovement.MovementMode ~= EMovementMode.MOVE_Falling then --UGCLog.Log("[MoveMode] %s -> %s", tostring(self.CharacterMovement.MovementMode), tostring(EMovementMode.MOVE_Falling)); self.CharacterMovement:SetMovementMode(EMovementMode.MOVE_Falling); end end end end function UGCPlayerPawn:DashTo(Dir, Duration, DashForce) self.LaunchCharacterForce = DashForce; self.DashDuration = Duration; self:EnableDashTo(true); self.LaunchDir = Dir; end ---@param DamageInfo FDamageInfoCollection function UGCPlayerPawn:OnDamageNotify_Test(DamageInfo) UGCLogSystem.Log("[UGCPlayerPawn:OnDamageNotify_Test] Damage = %s", tostring(DamageInfo.Damage)); end ----------------------------------- 装备 ----------------------------------- return UGCPlayerPawn;