---@class BP_TriggerDevice_C:STExtraCharacter ---@field Capsule UCapsuleComponent ---@field BlockBox UStaticMeshComponent ---@field P_TriggerDevicce UParticleSystemComponent ---@field P_TriggerDevicce_Disable UParticleSystemComponent ---@field ParticleSystem UParticleSystemComponent ---@field Core USceneComponent ---@field CG014_Version_2050_Transport_03 UStaticMeshComponent ---@field FacingToPlayerComponent USceneComponent ---@field TargetDevice USceneComponent ---@field Device USceneComponent ---@field DirectionGuidance USceneComponent ---@field ParticleContact UParticleSystemComponent ---@field Mechanism ABP_TriggerMechanismBase_C ---@field ParticleContactLength float ---@field DefaultParticleColor FLinearColor ---@field RotationalSpeed float ---@field WidgetOffset FVector ---@field bInAir bool ---@field ActiveAnim UAnimSequence --Edit Below-- ---@type BP_TriggerDevice_C local BP_TriggerDevice = { bTriggering = false; MaxEnergyValue = 0; EnergyValue = 0; TriggeredPlayerKey = -1; ShowInfoWidgetPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/MechanismActor/TriggerDevice/W_ShowTriggerDeviceInfo_3.W_ShowTriggerDeviceInfo_3_C'); TipPlayerInRangeWidgetPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/MechanismActor/TriggerDevice/W_TipPlayerCanTrigger.W_TipPlayerCanTrigger_C'); ShowInfoWidgetID = nil; TipActivationWidgetID = nil; RangeTeams = {}; GetRangeTeamsFrequency = 5; LocalCanActive = false; }; function BP_TriggerDevice:ReceiveBeginPlay() self.SuperClass.ReceiveBeginPlay(self); if UGCGameSystem.IsServer() then if UE.IsValid(self.Mechanism) then self.MaxEnergyValue = self.Mechanism:GetMaxEnergyValue() UGCLogSystem.Log("[BP_TriggerDevice_ReceiveBeginPlay] Begin") if self.Mechanism:GetEnableTipPlayerInRange() and not self.Mechanism:GetGlobalScope() then UGCLogSystem.Log("[BP_TriggerDevice_ReceiveBeginPlay] Enable TipPlayerInRange") self.TeamWithinTheActivationRangeHandle = UGCEventSystem.SetTimerLoop(self, self.GetTheTeamWithinTheActivationRange, 1./ self.GetRangeTeamsFrequency) end else UGCLogSystem.LogError("[BP_TriggerDevice_ReceiveBeginPlay] Mechanism is nil") end --Test self.OnTakeAnyDamage:Add(self.BindTakeAnyDamage, self) -- UGCSystemLibrary.BindBeginOverlapFunc(self.Capsule, self.CheckMeleeWeaponDamage, self) --TestEnd else UGCLogSystem.Log("[BP_TriggerDevice)ReceiveBeginPlay] Begin") self:UpdateDirectionGuidance() self:Create3DWidget() --- 隔帧初始化 防止未能拿到Widget self.InitHandle = UGCEventSystem.SetTimerLoop(self, self.ClientInit, 1.) if self.bInAir then -- 隐藏底座 self:HidePedestal() self.Mesh:SetHiddenInGame(true) else self.Device:SetVisibility(false, true) end --- 判断玩家是否满足触发该机关 self.LoopSetCanActive = UGCEventSystem.SetTimerLoop(self, self.CheckCanActive, 0.2) UGCLogSystem.Log("[BP_TriggerDevice_ReceiveBeginPlay] Finish %s", KismetSystemLibrary.GetObjectName(self)) end end function BP_TriggerDevice:HidePedestal() -- self.CG014_Version_2050_Transport_03:SetHiddenInGame(true) end function BP_TriggerDevice:ClientInit() if UE.IsValid(self:GetShowInfoWidget()) then UGCEventSystem.StopTimer(self.InitHandle) self:InitClientDeviceInfo() if self.bTriggering then self:EnableClientTriggerEffects(self.TriggeredPlayerKey) else self:DisableClientTriggerEffects() UGCLogSystem.Log("[BP_TriggerDevice_ClientInit]") end UGCLogSystem.Log("[BP_TriggerDevice_ClientInit] Finish") end if UE.IsValid(self:GetTipActivationWidget()) then self:UpdateTempTeams(self.RangeTeams) end end function BP_TriggerDevice:UpdateDirectionGuidance() if UE.IsValid(self.Mechanism) then local MechanismPos = self.Mechanism:GetConePos() local DirectionGuidancePos = self.DirectionGuidance:K2_GetComponentLocation() local Dir = VectorHelper.Sub(MechanismPos, DirectionGuidancePos) local TargetRot = KismetMathLibrary.MakeRotFromX(Dir) local TargetScaleY = VectorHelper.Length(Dir) / self.ParticleContactLength local DirectionGuidanceScale = self.DirectionGuidance:K2_GetComponentScale() UGCLogSystem.Log("[BP_TriggerDevice_UpdateDirectionGuidance] TargetRot:%s, TargetScale:%s", VectorHelper.RotToString(TargetRot), tostring(TargetScaleY)) --self.DirectionGuidance:SetWorldScale3D({X = DirectionGuidanceScale.X, Y = TargetScaleY, Z = DirectionGuidanceScale.Z}) self.ParticleContact:SetFloatParameter("LifeTime", VectorHelper.Length(Dir) / 100. - 1) self.DirectionGuidance:K2_SetWorldRotation(TargetRot) UGCLogSystem.Log("[BP_TriggerDevice_UpdateDirectionGuidance] Finish") else UGCLogSystem.LogError("[BP_TriggerDevice_UpdateDirectionGuidance] Mechanism is nil") end end --function BP_TriggerDevice:ReceiveAnyDamage(Damage, DamageType, InstigatedBy, DamageCauser) -- UGCLogSystem.Log("[BP_TriggerDevice_ReceiveAnyDamage]") -- if UE.IsValid(InstigatedBy) and InstigatedBy.PlayerKey then -- self:Trigger(InstigatedBy.PlayerKey) -- end --end ---@field Add:fun(Callback:fun(DamagedActor:AActor,Damage:float,DamageType:UDamageType,InstigatedBy:AController,DamageCauser:AActor),DelegateWrapper:UObject) function BP_TriggerDevice:BindTakeAnyDamage(DamagedActor, Damage, DamageType, InstigatedBy, DamageCauser) UGCLogSystem.Log("[BP_TriggerDevice_BindTakeAnyDamage]") if UE.IsValid(InstigatedBy) and InstigatedBy.PlayerKey then self:Trigger(InstigatedBy.PlayerKey) else UGCLogSystem.Log("[BP_TriggerDevice_BindTakeAnyDamage] DamageCauser:%s", tostring(KismetSystemLibrary.GetObjectName(DamageCauser))) end end ---@field Add:fun(Callback:fun(OverlappedComponent:UPrimitiveComponent,OtherActor:AActor,OtherComp:UPrimitiveComponent,OtherBodyIndex:int32,bFromSweep:bool,SweepResult:FHitResult),DelegateWrapper:UObject) function BP_TriggerDevice:CheckMeleeWeaponDamage(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex) UGCLogSystem.Log("[BP_TriggerDevice_CheckMeleeWeaponDamage] ActorName:%s", tostring(KismetSystemLibrary.GetObjectName(OtherActor))) UGCLogSystem.Log("[BP_TriggerDevice_CheckMeleeWeaponDamage] OverlappedComponentName:%s", tostring(KismetSystemLibrary.GetObjectName(OtherComp))) UGCLogSystem.Log("[BP_TriggerDevice_CheckMeleeWeaponDamage] Name:%s, ClassName:%s", UE.GetName(OtherComp), GetClassName(OtherComp)) end --function BP_TriggerDevice:BP_CharacterModifyDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser) -- if UE.IsValid(EventInstigator) and EventInstigator.PlayerKey then -- self:Trigger(EventInstigator.PlayerKey) -- end -- return 0. --end function BP_TriggerDevice:Trigger(InTriggeredPlayer) if not self:CheckTriggerCondition(InTriggeredPlayer) then return end self.TriggeredPlayerKey = InTriggeredPlayer self.bTriggering = true local TriggeredPlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.TriggeredPlayerKey) local InputEnergyValue = 0 --- 扣除玩家的能量 if TriggeredPlayerPawn:GetMechanismEnergy() > self.Mechanism:GetMaxEnergyValue() then InputEnergyValue = self.Mechanism:GetMaxEnergyValue() else InputEnergyValue = TriggeredPlayerPawn:GetMechanismEnergy() end TriggeredPlayerPawn:AddMechanismEnergy(-InputEnergyValue) UGCGameSystem.GameState:AddTechnicalScore(self.TriggeredPlayerKey , InputEnergyValue) --- 触发机关 self.Mechanism:Trigger(self.TriggeredPlayerKey, self, InputEnergyValue) DOREPONCE(self, "TriggeredPlayerKey") DOREPONCE(self, "EnergyValue") -- UnrealNetwork.CallUnrealRPC_Multicast(self, "EnableClientTriggerEffects", self.TriggeredPlayerKey) UGCSendRPCSystem.ActorRPCNotify(nil, self, "EnableClientTriggerEffects", self.TriggeredPlayerKey) --- 向队伍成员发送已启用机关的提示 local Teammates = UGCTeamSystem.GetTeammates(InTriggeredPlayer) UGCLogSystem.LogTree("[BP_TriggerDevice_Trigger] Teammates", Teammates) UGCSendRPCSystem.RPCEvent(Teammates, EventEnum.AddTip, TipConfig.TipType.TriggerMechanism, InTriggeredPlayer, self.Mechanism:GetMechanismType()) end function BP_TriggerDevice:MechanismClosed() self.bTriggering = false self.TriggeredPlayerKey = -1 -- UnrealNetwork.CallUnrealRPC_Multicast(self, "DisableClientTriggerEffects") UGCSendRPCSystem.ActorRPCNotify(nil, self, "DisableClientTriggerEffects") end function BP_TriggerDevice:CheckTriggerCondition(InTriggeredPlayer) if self.bTriggering then UGCSendRPCSystem.RPCEvent(InTriggeredPlayer, EventEnum.AddTip, TipConfig.TipType.MechanismOccupied) return false end if not UE.IsValid(self.Mechanism) then UGCLogSystem.LogError("[BP_TriggerDevice_CheckTriggerCondition] 机关未设置或被销毁") return false end --- 需要判断玩家能量是否满足触发 local TriggeredPlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(InTriggeredPlayer) if TriggeredPlayerPawn == nil then UGCLogSystem.LogError("[BP_TriggerDevice_CheckTriggerCondition] Pawn is nil") end if TriggeredPlayerPawn:GetMechanismEnergy() < self.Mechanism:GetEnergyMinimumLimit() then UGCSendRPCSystem.RPCEvent(InTriggeredPlayer, EventEnum.AddTip, TipConfig.TipType.EnergyDeficiency) -- UGCLogSystem.Log("[BP_TriggerDevice_CheckTriggerCondition]玩家能量不满足触发条件") return end return true end function BP_TriggerDevice:UpdateMechanismEnergyInfo(InEnergyValue) self.EnergyValue = InEnergyValue if self.MaxEnergyValue < self.EnergyValue then self.MaxEnergyValue = self.Mechanism:GetMaxEnergyValue() end DOREPONCE(self, "EnergyValue") end function BP_TriggerDevice:Create3DWidget() UGCLogSystem.Log("[BP_TriggerDevice_Create3DWidget]") self.ShowInfoWidgetID = UGCWidgetManagerSystem.AddObjectPositionUI(self, self.ShowInfoWidgetPath, VectorHelper.ToLuaTable(self.WidgetOffset), true, true, true) if self.Mechanism:GetEnableTipPlayerInRange() or self.Mechanism:GetGlobalScope() then self.TipActivationWidgetID = UGCWidgetManagerSystem.AddObjectPositionUI(self, self.TipPlayerInRangeWidgetPath, VectorHelper.ToLuaTable(self.Device:GetRelativeTransform().Translation), true, true, false) end end function BP_TriggerDevice:GetShowInfoWidget() -- return self.ShowDeviceInfoWidget:GetUserWidgetObject() return UGCWidgetManagerSystem.GetObjectPositionUI(self, self.ShowInfoWidgetID) end function BP_TriggerDevice:GetTipActivationWidget() return UGCWidgetManagerSystem.GetObjectPositionUI(self, self.TipActivationWidgetID) end function BP_TriggerDevice:Update3DWidgetRedraw() -- self.ShowDeviceInfoWidget:RequestRedraw() end function BP_TriggerDevice:InitClientDeviceInfo() if UE.IsValid(self.Mechanism) then -- local MechanismName = MechanismConfig.MechanismTypeName[self.Mechanism:GetMechanismType()] self:GetShowInfoWidget():InitMechanismInfo(self.Mechanism:GetMaxEnergyValue(), self.Mechanism:GetEnergyMinimumLimit(), self.Mechanism:GetMechanismType()) self:Update3DWidgetRedraw() end end function BP_TriggerDevice:OnRep_EnergyValue() local WidgetObject = self:GetShowInfoWidget() if UE.IsValid(WidgetObject) then WidgetObject:UpdateEnergyInfo(self.EnergyValue, self.Mechanism:GetMaxEnergyValue()) self:Update3DWidgetRedraw() end end function BP_TriggerDevice:OnRep_TriggeredPlayerKey() --local WidgetObject = self:GetShowInfoWidget() --WidgetObject:UpdateTriggeredPlayerInfo(self.TriggeredPlayerKey) --self:Update3DWidgetRedraw() end --- 启用客户端效果 function BP_TriggerDevice:EnableClientTriggerEffects(InTriggeredPlayerKey) self.bTriggering = true local WidgetObject = self:GetShowInfoWidget() if UE.IsValid(WidgetObject) then WidgetObject:Trigger(InTriggeredPlayerKey, self.EnergyValue, self.Mechanism:GetMaxEnergyValue()) self:Update3DWidgetRedraw() end self.ParticleSystem:SetActive(true, true) self:SetDeviceEnable(true) if InTriggeredPlayerKey > 0 then local PlayerTeamID = UGCGameSystem.GameState:GetPlayerTeamIDByPlayerKey(InTriggeredPlayerKey) local LocalPlayerTeamID = UGCPlayerControllerSystem.GetTeamID(UGCSystemLibrary.GetLocalPlayerController()) local ShowTeamType = LocalPlayerTeamID == PlayerTeamID and TeamConfig.TeamType.CT or TeamConfig.TeamType.T local TeamColor = TeamConfig.TeamColor[ShowTeamType] if TeamColor then local VectorColor = KismetMathLibrary.Conv_LinearColorToVector(TeamColor) self.ParticleContact:SetVectorParameter("ContactColor", VectorHelper.MulNumber(VectorColor, 10)) else UGCLogSystem.LogError("[BP_TriggerDevice_EnableClientTriggerEffects] TeamColor is nil") end end end --- 关闭客户端效果 function BP_TriggerDevice:DisableClientTriggerEffects() self.bTriggering = false local WidgetObject = self:GetShowInfoWidget() if UE.IsValid(WidgetObject) then WidgetObject:MechanismClosed() self:Update3DWidgetRedraw() end self.ParticleSystem:SetActive(false, false) local VectorColor = VectorHelper.ColorToVector(self.DefaultParticleColor) self.ParticleContact:SetVectorParameter("ContactColor", VectorColor) self:SetDeviceEnable(false) end --- 显示核心是否启用 function BP_TriggerDevice:SetDeviceEnable(bEnable) if self.bInAir then self.P_TriggerDevicce:SetHiddenInGame(not bEnable) --self.DeviceMesh:SetHiddenInGame(not bEnable) self.P_TriggerDevicce_Disable:SetHiddenInGame(bEnable) else if bEnable then self.Mesh:PlayAnimation(self.ActiveAnim, true) else self.Mesh:Stop() end end end --- 获取队伍是否在范围内 function BP_TriggerDevice:GetTheTeamWithinTheActivationRange() local AllPlayerPawn = UGCGameSystem.GetAllPlayerPawn() local TempTeams = {} for i, TempPawn in pairs(AllPlayerPawn) do -- if TempPawn.PlayerKey and TempPawn:IsAlive() and self.Mechanism:CheckPlayerInRange(TempPawn) then if TempPawn.PlayerKey and TempPawn:IsAlive() and self.Mechanism:CheckPlayerInRange(TempPawn) then local PlayerTeamID = UGCPlayerStateSystem.GetTeamID(TempPawn.PlayerKey) if not table.hasValue(TempTeams, PlayerTeamID) then TempTeams[#TempTeams + 1] = PlayerTeamID end end end if not table.collectionsEqual(self.RangeTeams, TempTeams) then self.RangeTeams = TempTeams UGCSendRPCSystem.ActorRPCNotify(nil, self, "UpdateTempTeams", self.TempTeams) DOREPONCE(self, "RangeTeams") end end function BP_TriggerDevice:OnRep_RangeTeams() self:UpdateTempTeams(self.RangeTeams) end function BP_TriggerDevice:UpdateTempTeams(TempTeams) self.RangeTeams = TempTeams local TargetWidget = self:GetTipActivationWidget() if UE.IsValid(TargetWidget) then if self.Mechanism:GetGlobalScope() then TargetWidget:ShowWidget(true) elseif UGCGameSystem.GameState then local PlayerTeamID = UGCGameSystem.GameState:GetPlayerTeamIDByPlayerKey(UGCSystemLibrary.GetLocalPlayerKey()) local bShow = (#self.RangeTeams > 1 or (#self.RangeTeams == 1 and (not table.hasValue(self.RangeTeams, PlayerTeamID)))) TargetWidget:ShowWidget(bShow) UGCLogSystem.Log("[BP_TriggerDevice_UpdateTempTeams] Finish") end end end function BP_TriggerDevice:CheckCanActive() local LocalPawn = UGCSystemLibrary.GetLocalPlayerPawn() if LocalPawn then self:SetCanActive(LocalPawn:GetMechanismEnergy() >= self.Mechanism:GetEnergyMinimumLimit() and (not self.bTriggering) ) end end function BP_TriggerDevice:SetCanActive(bActive) if self:GetShowInfoWidget() then self:GetShowInfoWidget():CanActive(bActive) end if self:GetTipActivationWidget() then self:GetTipActivationWidget():CanActive(bActive) end end function BP_TriggerDevice:ReceiveTick(DeltaTime) self.SuperClass.ReceiveTick(self, DeltaTime); if UGCGameSystem.IsServer() then else -- UI朝向玩家 --local LocalPC = UGCSystemLibrary.GetLocalPlayerController() --if LocalPC then -- local CameraPos = LocalPC.PlayerCameraManager:K2_GetActorLocation() -- local Pos = self.FacingToPlayerComponent:K2_GetComponentLocation() -- local Dir = KismetMathLibrary.MakeRotFromX(VectorHelper.Sub(CameraPos, Pos)) -- self.FacingToPlayerComponent:K2_SetWorldRotation(Dir) --end -- 添加自转 --if self.bTriggering then -- self.Device:K2_AddLocalRotation({Roll = 0., Pitch = 0., Yaw = DeltaTime * self.RotationalSpeed}) --end end end function BP_TriggerDevice:ReceiveEndPlay() if self.TeamWithinTheActivationRangeHandle then UGCEventSystem.StopTimer(self.TeamWithinTheActivationRangeHandle) self.TeamWithinTheActivationRangeHandle = nil end if self.InitHandle then UGCEventSystem.StopTimer(self.InitHandle) self.InitHandle = nil end if UGCGameSystem.IsServer() then else UGCLogSystem.Log("[BP_TriggerDevice_ReceiveEndPlay] self.ShowInfoWidgetID:%s, self.TipActivationWidgetID:%s", tostring(self.ShowInfoWidgetID), tostring(self.TipActivationWidgetID)) if self.ShowInfoWidgetID then UGCWidgetManagerSystem.RemoveObjectPositionUI(self, self.ShowInfoWidgetID) end if self.TipActivationWidgetID then UGCWidgetManagerSystem.RemoveObjectPositionUI(self, self.TipActivationWidgetID) end end self.SuperClass.ReceiveEndPlay(self); end function BP_TriggerDevice:GetReplicatedProperties() return "bTriggering", "MaxEnergyValue", "EnergyValue", "TriggeredPlayerKey", "RangeTeams" end --[[ function BP_TriggerDevice:GetAvailableServerRPCs() return end --]] return BP_TriggerDevice;