2025-01-04 23:00:19 +08:00

437 lines
18 KiB
Lua

---@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)
--- 触发机关
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;