---@class BP_JigsawManager_C:AActor ---@field StaticMesh8 UStaticMeshComponent ---@field StaticMesh7 UStaticMeshComponent ---@field StaticMesh6 UStaticMeshComponent ---@field StaticMesh5 UStaticMeshComponent ---@field StaticMesh4 UStaticMeshComponent ---@field StaticMesh3 UStaticMeshComponent ---@field StaticMesh2 UStaticMeshComponent ---@field StaticMesh1 UStaticMeshComponent ---@field StaticMesh UStaticMeshComponent ---@field Cube UStaticMeshComponent ---@field Scene USceneComponent ---@field DefaultSceneRoot USceneComponent ---@field Row int32 ---@field Col int32 ---@field TipPicClass UClass ---@field JigsawClass UClass ---@field PlayerPickUpRange float ---@field SideLength float ---@field TexIndex int32 ---@field RandomTex TArray --Edit Below-- local BP_JigsawManager = { -- playerkey: JigsawID PlayerHasJigsaw = {}; -- JigsawID = MinPos2D JigsawRelativeRange = {}; AllJigsaws = {}; PlacedNum = 0; -- 玩家禁止拾取到的时间 PlayerProhibitPickupEndTime = {}; }; function BP_JigsawManager:ReceiveBeginPlay() self.SuperClass.ReceiveBeginPlay(self); self:InitParam() if UGCGameSystem.IsServer() then UGCEventSystem.AddListener(EventEnum.PlayerPickUpOrPutDownJigsaw, self.PlayerPickUpOrPutDown, self) UGCEventSystem.AddListener(EventEnum.PlayerExit, self.ResetPlayerJigsaw, self) self.CheckPlayerAliveHandle = UGCEventSystem.SetTimerLoop(self, self.CheckPlayerAlive, 2) else UGCLogSystem.Log("[BP_JigsawManager_ReceiveBeginPlay]") self:OnRep_TexIndex() end end function BP_JigsawManager:InitParam() -- 设置每个区间左上角的点位 for i = 1, self.Row do for j = 1, self.Col do local Y = self.SideLength * (- self.Row / 2 + i - 1) local X = self.SideLength * (- self.Col / 2 + j - 1) self.JigsawRelativeRange[(i - 1) * self.Col + j] = {X = X, Y = Y} end end UGCLogSystem.LogTree("[BP_JigsawManager_InitParam] JigsawRelativeRange:", self.JigsawRelativeRange) if UGCGameSystem.IsServer() then -- 获取随机的拼图 self.TexIndex = math.random(1, self.RandomTex:Num()) UGCLogSystem.LogTree("[BP_JigsawManager_InitParam] TexIndex", self.TexIndex) -- 初始化拼图 local TempAllJigsaws = GameplayStatics.GetAllActorsOfClass(self, self.JigsawClass); for i, v in pairs(TempAllJigsaws) do self.AllJigsaws[#self.AllJigsaws + 1] = v end table.Shuffle(self.AllJigsaws) for i, v in pairs(self.AllJigsaws) do v:SetFrameValue(i) end end end --[[ function BP_JigsawManager:ReceiveTick(DeltaTime) self.SuperClass.ReceiveTick(self, DeltaTime); end --]] function BP_JigsawManager:GetTargetTex() return self.RandomTex[self.TexIndex] end function BP_JigsawManager:ClientUpdateTexIndex() local TargetTex = self:GetTargetTex() if self.TargetTipActor == nil then self.TargetTipActor = UGCSystemLibrary.GetUniqueInstanceFromClass(self.TipPicClass) end self.TargetTipActor:UpdateTex(TargetTex) for i, v in pairs(self.AllJigsaws) do v:UpdateTex(TargetTex) end end function BP_JigsawManager:OnRep_TexIndex() if UE.IsValid(self) then self:ClientUpdateTexIndex() end end function BP_JigsawManager:PlayerThrowOut(PlayerKey) local Jigsaw = self.AllJigsaws[self.PlayerHasJigsaw[PlayerKey]] local TargetPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(PlayerKey) if Jigsaw then self.PlayerHasJigsaw[PlayerKey] = nil local Pos if TargetPawn then Pos = TargetPawn:K2_GetActorLocation() else Pos = Jigsaw:K2_GetActorLocation() end Jigsaw:DetachAndSetTargetPos(VectorHelper.ToLuaTable(Pos)) end end function BP_JigsawManager:PlayerPickUpOrPutDown(PlayerKey) local TargetPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(PlayerKey) if UE.IsValid(TargetPawn) then if self.PlayerHasJigsaw[PlayerKey] then self:PlayerPutDown(TargetPawn, self.PlayerHasJigsaw[PlayerKey]) self.PlayerHasJigsaw[PlayerKey] = nil else if self:CheckPlayerCanPickUp(PlayerKey) then self:PlayerPickUp(TargetPawn) end end end end function BP_JigsawManager:ProhibitPickupTime(PlayerKey, Time) self.PlayerProhibitPickupEndTime[PlayerKey] = UGCSystemLibrary.GetGameTime() + Time self:PlayerThrowOut(PlayerKey) end function BP_JigsawManager:CheckPlayerCanPickUp(PlayerKey) local EndTime = self.PlayerProhibitPickupEndTime[PlayerKey] if EndTime then return EndTime < UGCSystemLibrary.GetGameTime() end return true end function BP_JigsawManager:PlayerPickUp(TargetPawn) local PawnPos = TargetPawn:K2_GetActorLocation() local TargetJigsaw = nil local TargetDis = -1 for i, v in pairs(self.AllJigsaws) do if not v:GetPlaced() and not v:GetPicked() then local Dis = VectorHelper.GetDistance2D(PawnPos, v:K2_GetActorLocation()) if Dis <= self.PlayerPickUpRange then if TargetJigsaw == nil or Dis < TargetDis then TargetJigsaw = v TargetDis = Dis end end end end if TargetJigsaw then self.PlayerHasJigsaw[TargetPawn.PlayerKey] = TargetJigsaw:GetFrame() TargetJigsaw:AttachPlayer(TargetPawn) end end function BP_JigsawManager:PlayerPutDown(TargetPawn, JigsawID) local PlayerPos = TargetPawn:K2_GetActorLocation() local PlayerKey = TargetPawn.PlayerKey local RelativePos = KismetMathLibrary.GreaterGreater_VectorRotator(VectorHelper.Sub(PlayerPos, self:K2_GetActorLocation()), self:K2_GetActorRotation()) UGCLogSystem.Log("[BP_JigsawManager_PlayerPutDown]JigsawID:%s", tostring(JigsawID)) local bPlaced = false for i, v in pairs(self.JigsawRelativeRange) do if v.X < RelativePos.X and v.X + self.SideLength > RelativePos.X and v.Y < RelativePos.Y and v.Y + self.SideLength > RelativePos.Y then UGCLogSystem.Log("[BP_JigsawManager_PlayerPutDown]DownID:%s",tostring(i)) if i == JigsawID then -- 放置正确 self:PlacedJigsaw(i) -- UGCEventSystem.SendEvent(EventEnum.AddMiniGameScore, PlayerKey, 1) UGCGameSystem.GameState:PlayerAddMiniGameScore(PlayerKey, 1) UGCSendRPCSystem.ActorRPCNotify(PlayerKey, self, "PlacedEffect", true) self.PlacedNum = self.PlacedNum + 1 if self.PlacedNum >= self.Row * self.Col then UGCEventSystem.SendEvent(EventEnum.MiniGameEndNotify) end MiniGameConfig.CheckPlayerTask(PlayerKey, MiniGameConfig.MiniGameType.Jigsaw, UGCGameSystem.GameState:GetPlayerMiniGameScore(PlayerKey), false) else -- 放置错误 self.AllJigsaws[JigsawID]:ResetJigsaw() UGCSendRPCSystem.ActorRPCNotify(PlayerKey, self, "PlacedEffect", false) end bPlaced = true break end end if not bPlaced then self.AllJigsaws[JigsawID]:ResetJigsaw() end end function BP_JigsawManager:PlacedJigsaw(JigsawID) local Jigsaw = self.AllJigsaws[JigsawID] if UGCGameSystem.IsServer() then Jigsaw:SetPlaced(true) UGCSendRPCSystem.ActorRPCNotify(nil, self, "PlacedJigsaw", JigsawID) else local ID = Jigsaw:GetFrame() Jigsaw:K2_AttachToActor(self, EAttachmentRule.KeepRelative, EAttachmentRule.SnapToTarget, EAttachmentRule.SnapToTarget) local RelativePos = {X = self.JigsawRelativeRange[ID].X + self.SideLength/ 2, Y = self.JigsawRelativeRange[ID].Y + self.SideLength/ 2, Z = 0} UGCLogSystem.Log("[BP_JigsawManager_PlacedJigsaw] RelativePos:%s", VectorHelper.ToString(RelativePos)) Jigsaw:K2_SetActorRelativeLocation(RelativePos) end end function BP_JigsawManager:PlacedEffect(IsTrue) if IsTrue then SoundSystem.PlaySound(SoundSystem.ESound.Right) else SoundSystem.PlaySound(SoundSystem.ESound.Error) end end function BP_JigsawManager:ResetPlayerJigsaw(Pawn, PlayerKey) local JigsawID = self.PlayerHasJigsaw[PlayerKey] UGCLogSystem.Log("[BP_JigsawManager_ResetPlayerJigsaw] PlayerKey:%s, JigsawID:%s", tostring(PlayerKey), tostring(JigsawID)) if JigsawID then if self.AllJigsaws[JigsawID] then self.AllJigsaws[JigsawID]:ResetJigsaw() end end self.PlayerHasJigsaw[PlayerKey] = nil end function BP_JigsawManager:CheckPlayerAlive() for PlayerKey, v in pairs(self.PlayerHasJigsaw) do if not UE.IsValid(UGCGameSystem.GetPlayerPawnByPlayerKey(PlayerKey)) then self:ResetPlayerJigsaw(nil, PlayerKey) end end end function BP_JigsawManager:ReceiveEndPlay() if UGCGameSystem.IsServer() then UGCEventSystem.RemoveListener(EventEnum.PlayerPickUpOrPutDownJigsaw, self.PlayerPickUpOrPutDown, self) UGCEventSystem.RemoveListener(EventEnum.PlayerExit, self.ResetPlayerJigsaw, self) if self.CheckPlayerAliveHandle then UGCEventSystem.StopTimer(self.CheckPlayerAliveHandle) self.CheckPlayerAliveHandle = nil end else end self.SuperClass.ReceiveEndPlay(self); end function BP_JigsawManager:GetReplicatedProperties() return "AllJigsaws" end --[[ function BP_JigsawManager:GetAvailableServerRPCs() return end --]] return BP_JigsawManager;