---@class BP_PlayerController_C:BP_UGCPlayerController_C --Edit Below-- UGCGameSystem.UGCRequire('Script.Common.ue_enum_custom') UGCGameSystem.UGCRequire('Script.Common.ue_struct_custom') UGCGameSystem.UGCRequire('Script.Global.Global') local BP_PlayerController = { IsRunOnServer = false, IsDead = false, IsDeadInArena = false, HasSelectedBaseAttribute = false, HasSelectedGameDifficulty = false, HasSelectedDefaultWeapon = false, CameraManager = nil, BackpackComp = nil, --背包组件 ---@type table> ActiveSkillNameList = {}, --技能映射表 ResourceGrade = 1, -- 资源等级 SealInfo = { -- 次数 Times = 1, -- 击杀数(该数据会依次增加,然后在50的时候如果没有点击封印,就一直是50,当点击封印的时候,该数值重置,死了之后也不会改变) KillCount = 0, -- 怪物是否存活,如果不存活说明没有挑战成功,需要继续挑战,即显示挑战按钮 IsMonsterAlive = false, }, -- 背包数据 ItemMap = { [0] = {}, --枪口 [1] = {}, --握把 [2] = {}, --弹夹 [3] = {}, --枪托 [4] = {}, --准镜 [5] = {}, --技能书 [6] = {}, --重铸石 [7] = {}, --置换石 }, ItemActorClass = nil, AutoPickIntervalTime = { Current = 0, LimitTime = 1, }; IsAutoRightNowPick = false; ------------- 拾取操作 ------------- -- 场景中的物品 AllItemActors = { [ETeleportType.InHangupRoom] = {}, [ETeleportType.InArena] = {}, }; -- 拾取距离 PickupDistance = 1000; --自动拾取距离 AutoPickupDistance = 200; -- 初始化的界面 InitialWidget = nil; }; function BP_PlayerController:GetReplicatedProperties() return "ActiveSkillNameList", "ResourceGrade", "ItemMap" end function BP_PlayerController:GetAvailableServerRPCs() return "ServerRPC_SelectGameDifficulty", --"ServerRPC_SelectBaseAttribute", --"ServerRPC_SelectDefaultWeapon", --"ServerRPC_AddWeapon", "ServerRPC_AddItemsByThisID", "ServerRPC_DiscardItems", -- "ClientRPC_ShowGeneralNoticeTips", -- "ClientRPC_ShowNoticeTips", -- "Client_MulticastRPC_PlayWeaponFireEffect", -- "ClientRPC_BuyTechSucceed", "ServerRPC_BuyTech", "ServerRPC_ChallengeSucceed", -- 背包 "ServerRPC_GenerateItem", "ServerRPC_SellItem", "ServerRPC_ResetItem", "ServerRPC_GenerateAllItem", "ServerRPC_OnBreach", -- "ClientRPC_ShowPickUpItems", --"ClientRPC_UpdateBackpackItemMap", --武器 "ServerRPC_AddFittingItem", "ServerRPC_ChangeCurrentWeaponId", "ServerRPC_ResetWeapon", -- 重铸 --释放技能 "ServerRPC_GiveSkill", "ServerRPC_OnCastSkill", -- "ClientRPC_SetupSkillButton", -- "ClientRPC_SetSkillCD", --突破 "ServerRPC_StartSpawnBreachMonster", -- "ClientRPC_SetBreachButtonVisible", -- 封印 "ServerRPC_StartSpawnSealMonster", "ServerRPC_ApplyRewards", -- "ClientRPC_SetSealRewards", -- "ClientRPC_SetSealButtonVisible", -- 传承 "ServerRPC_Inherit", -- "ClientRPC_UpdateInherit", -- 资源等级 "ServerRPC_SetResourceGrade", -- 背包 --"ClientRPC_ReplicatePawn", --新手引导 -- "ClientRPC_TriggerGuide", -- "ClientRPC_RemoveGuide", "ServerRPC_RecordForceGuideInfo", -- 生成练功房掉落物 "ServerRPC_AddExerciseItems", -- "ClientRPC_SpawnExerciseDropItem", -- "ClientRPC_ShowInitialPanel", -- "Client_UpdateArchiveData", "ServerRPC_CloseInitialNotice", -- GM命令 "ServerRPC_GM_AddItems", "ServerRPC_GM_AddCoinPoint", "ServerRPC_GM_AddTechPoint", "ServerRPC_GM_ChangeTimeScale" ; end function BP_PlayerController:ReceiveBeginPlay() BP_PlayerController.SuperClass.ReceiveBeginPlay(self) self.IsRunOnServer = UGCGameSystem.IsServer() -- 不要自动切换相机 self.bNeedResetCameraOnPossess = false self.ItemActorClass = UE.LoadClass(BPClassPath.PickupItemClass) if self.IsRunOnServer then self.OnCharacterDeadDelegate:Add(self.ServerOnCharacterDead, self) self.PlayerControllerRespawnedDelegate:Add(self.ServerOnRespawn, self) else self.PlayerControllerRespawnedDelegate:Add(self.ClientOnRespawn, self) self.OnCharacterDeadDelegate:Add(self.ClientOnCharacterDead, self) GameDataManager:SetLocalPlayerController(self) local CommandManager = require('Script.Manager.CommandQueneManager') CommandManager:AddInitCommand(self, self.Client_Init) end end function BP_PlayerController:ReceiveEndPlay() if self.IsRunOnServer then self.PlayerControllerRespawnedDelegate:Remove(self.ServerOnRespawn, self) self.OnCharacterDeadDelegate:Remove(self.ServerOnCharacterDead, self) else self.OnCharacterDeadDelegate:Remove(self.ClientOnCharacterDead, self) self.PlayerControllerRespawnedDelegate:Remove(self.ClientOnRespawn, self) end BP_PlayerController.SuperClass.ReceiveEndPlay(self) end --function BP_PlayerController:Possess(InPawn) -- -- 同步一下 Pawn -- self.SuperClass:Possess(InPawn) -- --UnrealNetwork.CallUnrealRPC(self, self, "ClientRPC_ReplicatePawn", InPawn) --end function BP_PlayerController:ReceiveTick(DeltaTime) if not self.IsRunOnServer then if self.bHasInitClient == nil and self.PlayerKey ~= 0 and self.IsDead == false then local CommandManager = require('Script.Manager.CommandQueneManager') CommandManager.bPlayerCtrlReady = true self.bHasInitClient = true UE.Log("[BP_PlayerController] *** UGCPlayerController Tick Init Ready PlayerKey:%s", self.PlayerKey) end end if self:HasAuthority() == false then -- 自动拾取 self.AutoPickIntervalTime.Current = self.AutoPickIntervalTime.Current + DeltaTime if self.AutoPickIntervalTime.Current > self.AutoPickIntervalTime.LimitTime then self.AutoPickIntervalTime.Current = self.AutoPickIntervalTime.Current - self.AutoPickIntervalTime.LimitTime self:RequestPickupNearbyItems(false) end end end function BP_PlayerController:Client_Init() UE.Log("[BP_PlayerController] Client_Init PlayerKey=%d", self.PlayerKey); GameDataManager:SetLocalPlayerController(self) GameDataManager:SetLocalPlayerState(self.PlayerState) -- 不要自动切换相机 self.bAutoManageActiveCameraTarget = false -- 初始化摄像机 self:SetupCamera(0.2) -- 初始化UI local UIManager = require('Script.Manager.UIManager') UIManager:Init() require('Script.Manager.NewPlayerGuideManager') NewPlayerGuideManager:Init() local GameStage = UGCGameSystem.GameState.GameStage if GameStage > EGameStage.WaitForPlayer then if self.InitialWidget then self.InitialWidget:SetVisibility(ESlateVisibility.Collapsed) end end if GameStage == EGameStage.GameReady then if UGCGameSystem.GameState.GameReadyStage >= 0 and UGCGameSystem.GameState.GameReadyStageRemainTime > 0 then for _, Config in pairs(Tables.GameReadyStageConfig) do if Config.Stage == UGCGameSystem.GameState.GameReadyStage then UIManager:ShowPanel(Config.TriggerUI) break end end end end self.CheckForceGuidePanelHandle = EventSystem.SetTimerLoop(self, function() local GameState = UGCGameSystem.GameState if GameState and GameState.GameDifficulty > 0 then local PS = GameDataManager.GetLocalPlayerState() if PS then if PS:GetNeedTriggerForceGuide() then if PS.ForceGuideInfo ~= nil and PS.ForceGuideInfo.CurStepIndex > 0 then local ForceGuidePanel = UIManager:GetPanel(EUIType.ForceGuide) if ForceGuidePanel and UE.IsValid(ForceGuidePanel) then ForceGuidePanel:InitByRecordedInfo(PS.ForceGuideInfo) end end end EventSystem.StopTimer(self.CheckForceGuidePanelHandle) end end end, 0.5) end function BP_PlayerController:ServerOnRespawn(InPlayerController) if InPlayerController == self then UE.Log("[BP_PlayerController:ServerOnRespawn] PlayerKey=%d", self.PlayerKey) local PlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) if PlayerPawn and UE.IsValid(PlayerPawn) and UE.IsValid(PlayerState) then UGCPawnSystem.SetIsInvincible(PlayerPawn, true) EventSystem.SetTimer(self, function() local PlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey) PlayerPawn:OnPlayerRespawned(PlayerState, self) UGCPawnSystem.SetIsInvincible(PlayerPawn, false) end, 1.0) end end end function BP_PlayerController:ClientOnRespawn(InPlayerController) if InPlayerController == self then UE.Log("[BP_PlayerController:ClientOnRespawn] PlayerKey=%d", self.PlayerKey) GameDataManager:SetLocalPlayerController(self) self.IsDead = false end end function BP_PlayerController:ServerOnCharacterDead(InCharacter) if InCharacter.PlayerKey == self.PlayerKey then UE.Log("[BP_PlayerController:ServerOnCharacterDead] PlayerKey=%d", self.PlayerKey) end end function BP_PlayerController:ClientOnCharacterDead(InCharacter) if InCharacter.PlayerKey == self.PlayerKey then UE.Log("[BP_PlayerController:ClientOnCharacterDead] PlayerKey=%d", self.PlayerKey) self.bHasInitClient = nil self.IsDead = true CommandQueneManager.bHasInit = false CommandQueneManager.bPlayerCtrlReady = false CommandQueneManager:RemoveInitCommand(InCharacter) ----记录强引导的当前步数 local PS = GameDataManager.GetLocalPlayerState() if PS and PS:GetNeedTriggerForceGuide() then local ForceGuidePanel = UIManager:GetPanel(EUIType.ForceGuide) if ForceGuidePanel and UE.IsValid(ForceGuidePanel) and ForceGuidePanel.CurStepIndex > 0 then UnrealNetwork.CallUnrealRPC(self, self, "ServerRPC_RecordForceGuideInfo", self.PlayerKey, ForceGuidePanel.CurStepIndex, ForceGuidePanel.CurValidStepIndex, ForceGuidePanel.bIsInStepProgress, ForceGuidePanel.StepPendingList) end end UIManager:DestroyAllPanel(true) UIManager:ShowNotice(ECustomNoticeType.RespawnNotice, 5) NewPlayerGuideManager:RemoveAllGuide() end end function BP_PlayerController:SetupCamera(DelayTime) local CameraManagerClass = require('Script.Manager.CameraManager') self.CameraManager = CameraManagerClass.New(self) EventSystem.SetTimer(self, function() self:GetCameraManager():SetupOverlookCamera() end, DelayTime) end function BP_PlayerController:GetCameraManager() return self.CameraManager end function BP_PlayerController:OnRep_ResourceGrade() if EventSystem and GameDataManager.GetLocalPlayerController() == self then EventSystem:SendEvent(EventType.OnResourceGradeChanged, self.ResourceGrade) end end function BP_PlayerController:ServerRPC_RecordForceGuideInfo(PlayerKey, CurStepIndex, ValidStepIndex, bIsInStepProgress, StepPendingList) if not self:HasAuthority() then return end local PS = UGCGameSystem.GetPlayerStateByPlayerKey(PlayerKey) if PS then PS.ForceGuideInfo = { CurStepIndex = CurStepIndex, ValidStepIndex = ValidStepIndex, bIsInStepProgress = bIsInStepProgress, StepPendingList = StepPendingList, } UnrealNetwork.RepLazyProperty(PS, "ForceGuideInfo") end end function BP_PlayerController:ServerRPC_SelectGameDifficulty(Index) if self.HasSelectedGameDifficulty then return end if self:HasAuthority() then UE.Log("[BP_PlayerController:ServerRPC_SelectGameDifficulty] Index = " .. tostring(Index)) if UGCGameSystem.GameState.PlayerDifficultySelection[Index] == nil then UGCGameSystem.GameState.PlayerDifficultySelection[Index] = 1 else UGCGameSystem.GameState.PlayerDifficultySelection[Index] = UGCGameSystem.GameState.PlayerDifficultySelection[Index] + 1 end self.HasSelectedGameDifficulty = true end end function BP_PlayerController:ServerRPC_SelectBaseAttribute(Index) if self.HasSelectedBaseAttribute then return end if self:HasAuthority() then local AttributeInfo = { PlayerKey = UGCPawnAttrSystem.GetPlayerKeyInt64(self:GetPlayerCharacterSafety()), AttributeIndex = Index, } table.insert(UGCGameSystem.GameState.PlayerAttributeSelection, AttributeInfo) self.HasSelectedBaseAttribute = true end end function BP_PlayerController:ServerRPC_SelectDefaultWeapon(ID) if self.HasSelectedDefaultWeapon then UE.LogError("[BP_PlayerController:ServerRPC_SelectDefaultWeapon] HasSelected") return end if self:HasAuthority() then UE.Log("[BP_PlayerController:ServerRPC_SelectDefaultWeapon] ID = " .. tostring(ID)) self:ServerRPC_AddWeapon(ID, self.PlayerKey) self.HasSelectedDefaultWeapon = true end end -- 添加武器唯一入口 function BP_PlayerController:ServerRPC_AddWeapon(ID, InPlayerKey) if self:HasAuthority() then if InPlayerKey ~= self.PlayerKey then return end print(string.format('[BP_PlayerController:ServerRPC_AddWeapon] 添加武器')) if InPlayerKey ~= nil then UE.Log("[BP_PlayerController:ServerRPC_AddWeapon] 开始添加武器, Id = %d, PlayerKey = %d", ID, InPlayerKey) end local ControlledCharacter = self:GetPlayerCharacterSafety() if not UE.IsValid(ControlledCharacter) then return end local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) local ControlledWeapon = ControlledCharacter.WeaponActor --新添加的武器 Id 将会被显示 if UE.IsValid(ControlledWeapon) then ControlledWeapon:SetWeaponID(ID) PlayerState:AddWeapon(ID) else -- 这说明武器里面啥都没有 AsyncLoadTools:LoadObject(BPClassPath.WeaponBaseActor, function(WeaponClass) if UE.IsValid(self) and UE.IsValid(WeaponClass) and UE.IsValid(PlayerState) then ControlledWeapon = UGCGameSystem.SpawnActor(self, WeaponClass, ControlledCharacter:K2_GetActorLocation(), ControlledCharacter:K2_GetActorRotation(), VectorHelper.ScaleOne(), nil) ControlledCharacter.WeaponActor = ControlledWeapon ControlledCharacter.OnWeaponSpawnedDelegate(ControlledCharacter) ControlledWeapon:SetWeaponID(ID) ControlledWeapon:SetOwnerCharacter(ControlledCharacter) PlayerState:AddWeapon(ID) end end) end end end --改变当前武器 function BP_PlayerController:ServerRPC_ChangeCurrentWeaponId(InWeaponId) UE.Log("[BP_PlayerController:ServerRPC_ChangeCurrentWeaponId] 开始执行改变当前武器操作") local ControlledCharacter = self:GetPlayerCharacterSafety() local WC = ControlledCharacter:GetWeaponComponent() if WC ~= nil then if WC:FindWeaponById(InWeaponId) ~= nil then WC:SetCurrentWeapon(InWeaponId) else UE.Log("[BP_PlayerController:ServerRPC_ChangeCurrentWeaponId] 找不到该武器,请检查一下") end end end function BP_PlayerController:ServerRPC_ResetWeapon(InWeaponId) UE.Log("[BP_PlayerController:ServerRPC_ResetWeapon] Weapon Id = %d", InWeaponId) -- 移除石头 local ItemData = { ItemID = 31000, ItemCount = -1 } local bSuccess = self:UpdateBackpackItem(ItemData) if not bSuccess then UE.Log("[BP_PlayerController:ServerRPC_ResetWeapon] 移除重铸石失败,请检查一下") return end -- 移除成功了,开始重铸玩家武器属性 local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) bSuccess = PlayerState:ResetWeapon(InWeaponId) if not bSuccess then local Item = { ItemID = 31000, ItemCount = 1 } bSuccess = self:UpdateBackpackItem(Item) if not bSuccess then UE.Log("[BP_PlayerController:ServerRPC_ResetWeapon] 添加重铸石失败,请检查原因") end end end function BP_PlayerController:ServerRPC_GenerateItem(InItemList) -- 先生成一个 self:GenerateItem(InItemList) end -- 添加物品的时候 function BP_PlayerController:ServerRPC_AddItemsByThisID(InThisIDList) if self:HasAuthority() then local GameState = UGCGameSystem.GameState if not UE.IsValid(GameState) then UE.Log("[ServerRPC_AddItemsByThisID] invalid gamestate") return end local ThisIDList = InThisIDList local HadItemIds = {} for i, v in pairs(GameState.GlobalDropItemActorList) do table.insert(HadItemIds, i) end log_tree('Common GlobalDropItemActorList = ', HadItemIds) log_tree('Common ThisIDList = ', ThisIDList) local Func = function(InGameState, InThisIdList) local PendingActorThisIDs = {} local AddItemIds = {} local LogStr = "[ServerRPC_AddItemsByThisID] Add: " for _, InThisID in pairs(InThisIdList) do local ItemActor = InGameState.GlobalDropItemActorList[InThisID] if UE.IsValid(ItemActor) and ItemActor.bIsPicking == false then local ItemID = ItemActor:GetItemID() local ItemCount = ItemActor:GetItemCount() ItemActor:SetIsPicking(true) -- 检查是否添加进去了 local AddCount = self:UpdateItemMap(ItemID, ItemCount) -- 当添加数量或者移除数量跟原先的一样的时候才会销毁 if AddCount == ItemActor:GetItemCount() then LogStr = LogStr .. string.format("{ItemID = %d, Count = %d},", ItemID, AddCount) table.insert(PendingActorThisIDs, InThisID) table.insert(AddItemIds, ItemID) end end end UE.Log(LogStr) return PendingActorThisIDs, AddItemIds end local PendingActorThisIDs, AddItemIds = Func(GameState, ThisIDList) UE.Log("[ServerRPC_AddItemsByThisID] PendingActorThisIDs Length = %d", #PendingActorThisIDs) for _, ThisID in pairs(PendingActorThisIDs) do local ThisActor = GameState.GlobalDropItemActorList[ThisID] if UE.IsValid(ThisActor) and ThisActor.bIsPicking then ThisActor:K2_DestroyActor() else print(string.format('[BP_PlayerController:ServerRPC_AddItemsByThisID] 无法找到 This ID = %d', ThisID)) end GameState.GlobalDropItemActorList[ThisID] = nil end UnrealNetwork.CallUnrealRPC(self, self, "ClientRPC_ShowPickUpItems", AddItemIds) end end -- 往武器上添加配件 function BP_PlayerController:ServerRPC_AddFittingItem(InWeaponId, InFittingItemId) UE.Log("[BP_PlayerController:ServerRPC_AddFittingItem] 添加配件") local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) PlayerState:AddWeaponFittingItem(InWeaponId, InFittingItemId) end function BP_PlayerController:ServerRPC_RemoveFittingItem(InFittingItemId) UE.Log("[BP_PlayerController:ServerRPC_RemoveFittingItem] 开始执行") local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) PlayerState:RemoveWeaponFittingItem(InFittingItemId) end -- Server 该生成仅生成在玩家周围 function BP_PlayerController:CreateItem(InPlayer, InItemData, IsFromDiscard) print(string.format('[BP_PlayerController:CreateItem] 执行')) if InPlayer == nil then InPlayer = self:GetPlayerCharacterSafety() end -- TODO local PlayerVec = VectorHelper.ToLuaTable(InPlayer:K2_GetActorLocation()) --local DropPos = VectorHelper.Sub(PlayerVec, { X = 0, Y = 0, Z = 0 }) local DropPos = PlayerVec log_tree("PlayerVec = ", PlayerVec) UE.Log("DiscardItemId: %d, DiscardCount = %d", InItemData.ItemID, InItemData.ItemCount) if self.Pawn.IsInArena then print(string.format('[BP_PlayerController:CreateItem] 在场景中丢弃')) EventSystem:SendEvent(EventType.SpawnDropItemByID, InItemData.ItemID, InItemData.ItemCount, DropPos, InPlayer:K2_GetActorRotation(), self.PlayerKey, IsFromDiscard) else -- 练功房通知生成一个 print(string.format('[BP_PlayerController:CreateItem] 在练功房丢弃')) local ItemData = { ItemID = InItemData.ItemID, Count = InItemData.ItemCount } self:RequestExerciseDropItem(self.PlayerKey, DropPos, VectorHelper.RotZero(), ItemData, false, IsFromDiscard) end end -- 丢弃物品 function BP_PlayerController:ServerRPC_DiscardItems(InDiscardItems) if self:HasAuthority() then print(string.format('[BP_PlayerController:ServerRPC_DiscardItems] 执行')) local GameState = UGCGameSystem.GameState if not UE.IsValid(GameState) then UE.Log("[ServerRPC_DiscardItems] invalid gamestate") return end local LogStr = "[ServerRPC_DiscardItems] Discard: " local DiscardItemIDs = {} for ItemID, Count in pairs(InDiscardItems) do -- 看一下此时的type local DiscardCount = self:UpdateItemMap(ItemID, Count) -- 检查一下 Discard UE.Log('[BP_PlayerController:ServerRPC_DiscardItems] Discard Count = %d', DiscardCount) if DiscardCount == Count then LogStr = LogStr .. string.format("{ItemID = %d, Count = %d},", ItemID, Count) if DiscardCount < 0 then DiscardCount = -DiscardCount end DiscardItemIDs[ItemID] = DiscardCount else print(string.format('[BP_PlayerController:ServerRPC_DiscardItems] 丢弃物品数量不对,本应该丢弃:%d,实际上丢弃:%d', Count, DiscardCount)) end end UE.Log(LogStr) for DiscardItemID, DiscardCount in pairs(DiscardItemIDs) do local ItemData = { ItemID = DiscardItemID, ItemCount = DiscardCount } self:CreateItem(self.Pawn, ItemData, true) end LogStr = "[ServerRPC_DiscardItems] Result ItemMap = " local CurItemMap = self:GetItemMap() for ItemType, ItemList in pairs(CurItemMap) do for i, v in pairs(ItemList) do LogStr = LogStr .. string.format("{ItemType = %d, ItemID = %d, Count = %d},", ItemType, i, v) end end UE.Log(LogStr) end end --function BP_PlayerController:ClientRPC_UpdateBackpackItemMap(InItemMap) -- if self:HasAuthority() then return end -- -- --此处需要知道死亡之后自己是谁,每次获取即可 -- self:ClientUpdateItemMap(InItemMap) --end function BP_PlayerController:ClientRPC_UpdateWeaponById(InWeaponType) end -- Server, 直接输入{ItemID, ±ItemCount},返回添加或者移除的是否是这些东西 function BP_PlayerController:UpdateBackpackItem(InData) local GameState = UGCGameSystem.GameState if not UE.IsValid(GameState) then return end local DiscardCount = self:UpdateItemMap(InData.ItemID, InData.ItemCount) local bSuccess = DiscardCount == InData.ItemCount return bSuccess end -- Server function BP_PlayerController:UpdateMoney(InDelta) local ControlledCharacter = self:GetPlayerCharacterSafety() if not UE.IsValid(ControlledCharacter) then return false end local PlayerKey = UGCPawnAttrSystem.GetPlayerKeyInt64(ControlledCharacter) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(PlayerKey) return PlayerState:UpdateCoinPoint(InDelta) end function BP_PlayerController:ServerRPC_SellItem(InData) if InData.ItemCount > 0 then InData.ItemCount = -InData.ItemCount end local bSuccess = self:UpdateBackpackItem(InData) --售卖东西 if bSuccess then local Money = math.abs(Tables.QualityInfo[GetItemQualityLevel(InData.ItemID)][2] * InData.ItemCount) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) bSuccess = PlayerState ~= nil and UE.IsValid(PlayerState) and PlayerState:AddCoinPointDirectly(Money) if bSuccess then UE.Log("[BP_PlayerController:ServerRPC_SellItem] 售卖 Item: Id = %d 成功", InData.ItemID) end else UE.Log("[BP_PlayerController:ServerRPC_SellItem] 售卖 Item: Id = %d 失败", InData.ItemID) end end --执行置换 function BP_PlayerController:ServerRPC_ResetItem(InData) --这是要移除的,说明开始转换了 UE.Log('[BP_PlayerController:ServerRPC_ResetItem] 开始 Rest Item') --if GetItemQualityLevel(InData.ItemID) >= EQualityType.Super then -- -- 再做一次限制 -- return --end --开始移除 local TheCount = InData.ItemCount InData.ItemCount = - TheCount local bSuccess = self:UpdateBackpackItem(InData) if bSuccess then -- 开始添加物品,如果添加不下了,就生成一个 if GetItemGrantTypeById(InData.ItemID) == EDropItemSet.SkillBooks then local SkillId = GetSkillIdByItemId(InData.ItemID) local Skills = {} for i = 9, 32 do if SkillId == i then else table.insert(Skills, i) end end local Skill = Skills[math.random(1, table.getCount(Skills))] Skill = 20000 + Skill * 100 + InData.ItemID % 100 local ItemData = { ItemID = Skill, ItemCount = TheCount } bSuccess = self:UpdateBackpackItem(ItemData) else local TempArr1 = { 1, 2, 3, 4, 5 } local TempArr2 = { 1, 2, 3, 4, 5, 6 } local CurrentItemType = GetItemTypeByItemId(InData.ItemID) + 1 local CurrentWeaponType = GetItemWeaponTypeByItemId(InData.ItemID) local RandomNum = math.random(1, 4) table.remove(TempArr1, CurrentItemType) InData.ItemID = InData.ItemID - CurrentItemType * 1000 + TempArr1[RandomNum] * 1000 table.remove(TempArr2, CurrentWeaponType) RandomNum = math.random(1, 5) InData.ItemID = InData.ItemID - CurrentWeaponType * 100 + TempArr2[RandomNum] * 100 InData.ItemCount = TheCount bSuccess = self:UpdateBackpackItem(InData) end if bSuccess then local ItemData = { ItemID = 32000, ItemCount = - TheCount } self:UpdateBackpackItem(ItemData) end end end function BP_PlayerController:ClientRPC_ShowGeneralNoticeTips(InText, ShowAlert, ShowTime) if self:HasAuthority() then return end UIManager:ShowGeneralNotice(InText, ShowAlert, ShowTime) end function BP_PlayerController:ClientRPC_ShowNoticeTips(InNoticeType, ...) if self:HasAuthority() then return end UIManager:ShowNotice(InNoticeType, ...) end function BP_PlayerController:Client_MulticastRPC_PlayWeaponFireEffect() if self:HasAuthority() then return end local ControlledCharacter = self:GetPlayerCharacterSafety() if UE.IsValid(ControlledCharacter) then local ControlledWeapon = ControlledCharacter.WeaponActor if ControlledWeapon then ControlledWeapon:PlayFireEffect() end end end --- 购买科技 function BP_PlayerController:ServerRPC_BuyTech(TechID) if self:HasAuthority() then local TargetPlayerState = self:GetCurPlayerState() if TargetPlayerState.TechBuyNum[TechID] ~= nil then if Tables.Tech[TechID].bLimit and Tables.Tech[TechID].LimitNum <= TargetPlayerState.TechBuyNum[TechID] then UE.Log("BP_PlayerController_Fun_" .. "ServerRPC_BuyTech_" .. "BugFailure") return end local NeedKillPoint = Tables.Tech[TechID].KillingPoints(TargetPlayerState.TechBuyNum[TechID] + 1) local Temp = 0 for i, v in pairs(TargetPlayerState.Attributes) do Temp = Temp + v.KillPoint_Cost end NeedKillPoint = NeedKillPoint * (1 + Temp) if TargetPlayerState.KillPoint.Current >= NeedKillPoint then TargetPlayerState.KillPoint.Current = TargetPlayerState.KillPoint.Current - NeedKillPoint TargetPlayerState.TechBuyNum[TechID] = TargetPlayerState.TechBuyNum[TechID] + 1 Tables.Tech[TechID].ChangeTechParam(self) UnrealNetwork.CallUnrealRPC(self, self, "ClientRPC_BuyTechSucceed", TechID, TargetPlayerState.TechBuyNum[TechID]) else NoticeTipsTools.ServerGeneralNoticeTips(self.PlayerKey, "科技点不足", true) end end end end function BP_PlayerController:ClientRPC_BuyTechSucceed(TechID, BuyNum) EventSystem:SendEvent(EventType.PlayerBuyTechSucceed, TechID, BuyNum) end function BP_PlayerController:ServerRPC_ChallengeSucceed(ChallengeInfoKey, PlayerKey, ChallengeMonsterType, MonsterLevel, bSkipCheckCD) --TODO:检测是否该挑战在CD中 if Tables.ChallengeInfo[ChallengeInfoKey] == nil then UE.Log("[BP_PlayerController:ServerRPC_ChallengeSucceed] [Error] invalid ChallengeInfoKey") return end local TargetPlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(PlayerKey) local NowTime = UGCGameSystem.GameState.GameDuration if not bSkipCheckCD then local LastChallengeTime = TargetPlayerState.ChallengeMonsterTime[ChallengeInfoKey].LastChallengeTime local CoolingTime = TargetPlayerState.ChallengeMonsterTime[ChallengeInfoKey].CoolingTime if NowTime - LastChallengeTime < CoolingTime then return end end TargetPlayerState.ChallengeMonsterTime[ChallengeInfoKey].LastChallengeTime = NowTime local TargetSpawner = UGCGameSystem.GameState:GetSpawnerByPlayerKey(PlayerKey) if UE.IsValid(TargetSpawner) then TargetSpawner:StartSpawnChallengeMonster(ChallengeMonsterType, MonsterLevel) NoticeTipsTools.ServerGeneralNoticeTips(PlayerKey, "挑战怪已生成在练功房,请尽快击败获取奖励!", true, 4.0) end end --------------------------------------------- 技能相关逻辑 ---------------------------------------------------- function BP_PlayerController:ServerRPC_GiveSkill(SkillName, SkillSlot, SkillLevel) UE.Log("[BP_PlayerController:ServerRPC_GiveSkill] [%s] [%s] GiveSkill:%d, Slot:%s, Level:%s", self.PlayerKey, self.PlayerName, SkillName, tostring(SkillSlot), tostring(SkillLevel)) --- OldSkillId == -1: 失败出错 --- OldSkillId == 0: 当前是空插槽 --- OldSkillId > 0: 当前是空插槽 local OldSkillId = self:GiveSkill(SkillName, SkillSlot, SkillLevel) if SkillLevel == nil then return end if OldSkillId == -1 then print(string.format('[BP_PlayerController:ServerRPC_GiveSkill] 添加错误')) elseif OldSkillId == 0 then -- 说明是空白插槽 if SkillLevel == nil then return end local InSkillId = 20000 + SkillName * 100 + SkillLevel * 10 local AddItemCount = self:UpdateItemMap(InSkillId, -1) if AddItemCount == -1 then print(string.format('[BP_PlayerController:ServerRPC_GiveSkill] 添加好啦')) else print(string.format('[BP_PlayerController:ServerRPC_GiveSkill] 添加失败')) end else -- 说明是替换技能 -- 塞回背包 local InSkillId = 20000 + SkillName * 100 + SkillLevel * 10 local AddItemCount = self:UpdateItemMap(InSkillId, -1) if AddItemCount == -1 then AddItemCount = self:UpdateItemMap(OldSkillId, 1) if AddItemCount == 1 then print(string.format('[BP_PlayerController:ServerRPC_GiveSkill] 成功啦~')) else -- 检查背包是否满了 if self:IsBackpackFull(EItemType.SkillBook) then -- 丢到地面上 self:CreateItem(nil, { ItemID = OldSkillId, ItemCount = 1 }) else print(string.format('[BP_PlayerController:ServerRPC_GiveSkill] 存在问题,请检查一下')) end print(string.format('[BP_PlayerController:ServerRPC_GiveSkill] 存在问题,请检查一下')) end else -- 检查背包是否满了 if self:IsBackpackFull(EItemType.SkillBook) then -- 丢到地面上 self:CreateItem(nil, { ItemID = OldSkillId, ItemCount = 1 }) else print(string.format('[BP_PlayerController:ServerRPC_GiveSkill] 存在问题,请检查一下')) end end end end function BP_PlayerController:ClientRPC_SetupSkillButton(SkillName, SkillSlot, SkillLevel) EventSystem:SendEvent(EventType.OnSetupSkillButton, SkillName, SkillSlot, SkillLevel) end function BP_PlayerController:GiveSkillList(SkillNameList) if (not (self.Pawn and UE.IsValid(self.Pawn))) then UE.LogError("[BP_PlayerController:GiveSkillList] self.Pawn == nil") return end if SkillNameList == nil then return end self.Pawn:GiveSkillWithSkillNameList(SkillNameList) end function BP_PlayerController:GiveSkill(SkillName, SkillSlot, SkillLevel) if (not (self.Pawn and UE.IsValid(self.Pawn))) then UE.LogError("[BP_PlayerController:GiveSkill] self.Pawn == nil") return -1 end if SkillName == nil or SkillName == ESkillName.Default then UE.LogError("[BP_PlayerController:GiveSkill] invalid SkillName") return -1 end for i, v in pairs(self.ActiveSkillNameList) do print(string.format('[BP_PlayerController:GiveSkill] Slot: %d, SkillName: %d, SkillLevel: %d', i, v.SkillName, v.SkillLevel)) end for Slot, SkillInfo in pairs(self.ActiveSkillNameList) do if SkillInfo.SkillName == SkillName and SkillInfo.SkillLevel == SkillLevel then UE.LogError("[BP_PlayerController:GiveSkill] Has Same Skill") return -1 end end return self.Pawn:GiveSkill(SkillName, SkillSlot, SkillLevel) end ---@param SkillSlot ESkillSlot function BP_PlayerController:ClientOnCastSkill(SkillSlot) UE.Log("[Skill] [%s] [%s] ClientOnCastSkill:%s", self.PlayerKey, self.PlayerName, SkillSlot) UnrealNetwork.CallUnrealRPC(self, self, "ServerRPC_OnCastSkill", SkillSlot) end function BP_PlayerController:ServerRPC_OnCastSkill(SkillSlot) UE.Log("[Skill] [%s] [%s] ServerRPC_OnCastSkill:%s", self.PlayerKey, self.PlayerName, SkillSlot) local Pawn = self:GetPlayerCharacterSafety() if UE.IsValid(Pawn) then Pawn:TryActiveSkillBySlot(SkillSlot) end end function BP_PlayerController:ClientRPC_SetSkillCD(Slot, CDDuration) -- 更改CD状态 UE.Log("[Skill] ClientRPC_SetSkillCD Slot:%s Duration:%f", Slot, CDDuration) EventSystem:SendEvent(EventType.PlayerSkillCDTriggered, Slot, CDDuration) end -- 获取空的机能插槽 function BP_PlayerController:GetEmptySlots() local Slots = { ESkillSlot.Slot1, ESkillSlot.Slot2, ESkillSlot.Slot3, } local NeedRemoveSlots = {} if table.getCount(self.ActiveSkillNameList) > 0 then for i, v in pairs(self.ActiveSkillNameList) do for j = 1, #Slots do if i == Slots[j] then table.insert(NeedRemoveSlots, j) end end end end if #NeedRemoveSlots > 0 then --for i = 1, #NeedRemoveSlots do -- print(string.format('[BP_PlayerController:GetEmptySlots] 移除的index = %d', NeedRemoveSlots[i])) --end for i = 1, #NeedRemoveSlots do table.remove(Slots, NeedRemoveSlots[#NeedRemoveSlots - i + 1]) end end return Slots end -- 获取主动技能 function BP_PlayerController:GetInitiativeSkillSlots() local Slots = {} for i, v in pairs(self.ActiveSkillNameList) do for j = 1, 3 do if i == j then table.insert(Slots, i) end end end return Slots end function BP_PlayerController:GetNearEmptySlot() local EmptySlots = self:GetEmptySlots() if #EmptySlots == 0 then return 0 end return EmptySlots[1] end function BP_PlayerController:IsFullInitiativeSkills() return self:GetEmptySlots() == 0 end --------------------------------------------- 新手引导相关 --------------------------------------------- function BP_PlayerController:ClientRPC_TriggerGuide(ConfigID) if NewPlayerGuideManager then NewPlayerGuideManager:TriggerGuide(ConfigID) end end function BP_PlayerController:ClientRPC_RemoveGuide(ConfigID) if NewPlayerGuideManager then NewPlayerGuideManager:RemoveGuide(ConfigID) end end --------------------------------------------- 突破相关逻辑 ---------------------------------------------------- function BP_PlayerController:ClientRPC_SetBreachButtonVisible(IsShow) EventSystem:SendEvent(EventType.ToggleBreachButton, IsShow) end function BP_PlayerController:ClientRPC_SetSealButtonVisible(IsShow) EventSystem:SendEvent(EventType.ShowSealButton, IsShow) end function BP_PlayerController:ServerRPC_StartSpawnBreachMonster(RewardWeaponID, InLevel) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) if UE.IsValid(PlayerState) == false or PlayerState:GetCanSpawnBreachMonster() == false then return end local TargetSpawner = UGCGameSystem.GameState:GetSpawnerByPlayerKey(self.PlayerKey) if UE.IsValid(TargetSpawner) == false then return end TargetSpawner:StartSpawnBreachMonster(RewardWeaponID, InLevel) end --------------------------------------------- 封印 --------------------------------------------- -- 增加封印击杀数 function BP_PlayerController:AddSealKillCount() -- 阉割版 --if self.SealInfo.KillCount + 1 >= SealTables.MultiCount then -- -- 执行显示封印按钮,如果当前有封引怪或者显示按钮,那么就不进行操作 -- if not self.SealInfo.IsMonsterAlive then -- UnrealNetwork.CallUnrealRPC(self, self, "ClientRPC_SetSealButtonVisible", true) -- end --else -- self.SealInfo.KillCount = self.SealInfo.KillCount + 1 --end end function BP_PlayerController:ServerRPC_StartSpawnSealMonster() local TargetSpawner = UGCGameSystem.GameState:GetSpawnerByPlayerKey(self.PlayerKey) if UE.IsValid(TargetSpawner) == false then return end TargetSpawner:StartSpawnSeal(self) NoticeTipsTools.ServerGeneralNoticeTips(self.PlayerKey, "封印怪已生成在练功房,请尽快击败获取奖励!", true, 4.0) end function BP_PlayerController:ClientRPC_SetSealRewards(InRewardsItems) -- 显示奖励界面 UIManager.AllPanel[EUIType.SealRewards]:SetRewards(InRewardsItems) UIManager:ShowPanel(EUIType.SealRewards) end function BP_PlayerController:ServerRPC_ApplyRewards(InData) print(string.format('[BP_PlayerController:ServerRPC_ApplyRewards] Type = %s', InData.Type)) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) local Type = InData.Type if Type == '配件' or Type == '技能书' then for _ = 1, InData.Value do local ItemData if Type == '配件' then ItemData = GenerateWeaponPartData() else ItemData = GenerateSkillBookData() end local ItemInfo = { ItemID = ItemData.ItemID, ItemCount = ItemData.Count } self:CreateItem(nil, ItemInfo) end elseif Type == '金币' then PlayerState:UpdateCoinPoint(InData.Value) elseif Type == '科技点' then PlayerState:AddKillPoint(InData.Value) else PlayerState:AddAttribute(Type, InData.Value, true) end end --------------------------------------------- 传承 --------------------------------------------- function BP_PlayerController:ServerRPC_Inherit(IsBreak, SelectText, InCurrId) print(string.format('[BP_PlayerController:ServerRPC_Inherit] 继承怪')) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) local OldNum = PlayerState.InheritItems[SelectText] local OldInfo = InheritTable.Items[OldNum] if InCurrId ~= OldNum then print(string.format('[BP_PlayerController:ServerRPC_Inherit] Current Id = %d', InCurrId)) print(string.format('[BP_PlayerController:ServerRPC_Inherit] Old Num = %d', OldNum)) UnrealNetwork.CallUnrealRPC(self, self, "ClientRPC_UpdateInherit", self.PlayerKey, 4) return end local NextId = InheritTable.GetNextId(OldNum) local NewInfo = InheritTable.Items[NextId] if IsBreak then -- 出个怪 local TargetSpawner = UGCGameSystem.GameState:GetSpawnerByPlayerKey(self.PlayerKey) if UE.IsValid(TargetSpawner) == false then UnrealNetwork.CallUnrealRPC(self, self, "ClientRPC_UpdateInherit", self.PlayerKey, 2) return end TargetSpawner:StartSpawnInherit(self, SelectText, OldNum) NoticeTipsTools.ServerGeneralNoticeTips(self.PlayerKey, "进阶怪已生成在练功房,请尽快击败获取奖励!", true, 4.0) else if PlayerState.CoinPoint.Current < OldInfo.Cost then UnrealNetwork.CallUnrealRPC(self, self, "ClientRPC_UpdateInherit", self.PlayerKey, 3) return else local IsSuccess = PlayerState:UpdateCoinPoint( - OldInfo.Cost) if IsSuccess then PlayerState.InheritItems[SelectText] = NextId --获得奖励 for i = 1, #NewInfo.Benefit do PlayerState:AddAttribute(OldInfo.Benefit[i].Type, OldInfo.Benefit[i].Value, true) end UnrealNetwork.CallUnrealRPC(self, self, "ClientRPC_UpdateInherit", self.PlayerKey, 1) else print(string.format('[BP_PlayerController:ServerRPC_Inherit] 没有添加成功')) end end end end -- IsSuccess: 0:击杀怪物;1:扣除金币成功;2:击杀失败;3:扣除失败;4:执行失败 function BP_PlayerController:ClientRPC_UpdateInherit(InPlayerKey, IsSuccess) if InPlayerKey ~= self.PlayerKey then return end UIManager.AllPanel[EUIType.Inherit]:UpdateInherit(IsSuccess) end function BP_PlayerController:ServerRPC_SetResourceGrade(ResourceGrade) if type(ResourceGrade) ~= 'number' or ResourceGrade < 1 or ResourceGrade > 4 then return end local GameState = UGCGameSystem.GameState if GameState == nil or UE.IsValid(GameState) == false then return end local Spawner = GameState:GetSpawnerByPlayerKey(self.PlayerKey) if Spawner == nil or UE.IsValid(Spawner) == false then return end self.ResourceGrade = ResourceGrade Spawner:UpdateHangupRoomMonsterLevel(ResourceGrade) end -- 一键合成 function BP_PlayerController:ServerRPC_GenerateAllItem(InType) local ItemMap = self:GetItemMapByItemType(InType) if ItemMap == nil then print(string.format('[BP_PlayerController:ServerRPC_GenerateAllItem] 当前背包中没有 %d', InType)) return end -- 首先,将背包中的物品放到各个数组中 local AllItems = {} -- 全部拆分开 for i, v in pairs(ItemMap) do local Quality = GetItemQualityLevel(i) if AllItems[Quality] == nil then AllItems[Quality] = {} end AllItems[Quality][i] = v end local SingleItems = {} -- 先根据AllItems[Quality] 进行判断 local TheType = EQualityType.Senior while TheType >= 0 do if AllItems[TheType] ~= nil then for i, v in pairs(AllItems[TheType]) do local NextStack = v // 3 if NextStack > 0 then for d = 1, NextStack do local ItemData = {i,i,i} self:GenerateItem(ItemData) end end -- 检查一下剩余的 local LastCount = v - NextStack * 3 if LastCount > 0 then if SingleItems[TheType] == nil then SingleItems[TheType] = {} end for c = 1, LastCount do table.insert(SingleItems[TheType], i) end end end if SingleItems[TheType] ~= nil then -- 计算数量 local Count = table.getCount(SingleItems[TheType]) local NextTypeCount = Count // 3 if NextTypeCount >= 1 then for i = 1, NextTypeCount do local ItemData = { SingleItems[TheType][3 * (i - 1) + 1], SingleItems[TheType][3 * (i - 1) + 2], SingleItems[TheType][3 * (i - 1) + 3], } self:GenerateItem(ItemData) end end end end TheType = TheType - 1 end end function BP_PlayerController:GenerateItem(InItemList) -- InData 中包含的是几个要合成的 Id for i = 1, #InItemList do local InData = InItemList[i] local RemoveCount = self:UpdateItemMap(InData, -1) UE.Log('移除的数量:%d,移除的 Id = %d', RemoveCount, InData) end -- 判断是不是技能书 local CreateId = self:GetCreateId(InItemList) CreateId = CreateId + 10 -- 抬升一个等级 -- 判断当前技能是否是超级 if GetItemQualityLevel(CreateId) == EQualityType.Super then self.PlayerState.ArchiveData.TotalSuperSkill = self.PlayerState.ArchiveData.TotalSuperSkill + 1 end UE.Log('要添加的物品的 Id:%d', CreateId) local AddItemCount = self:UpdateItemMap(CreateId, 1) if AddItemCount == 0 then local ItemData = { ItemID = CreateId, ItemCount = 1 } self:CreateItem(nil, ItemData) return end end function BP_PlayerController:GetCreateId(InItemList) --local ItemId = InItemList[1] --local Level = GetItemQualityLevel(ItemId) + 1 -- ----生成ID --local WeaponType = math.random(1, 6) -- ---- 判断是不是技能书 --local CreateId = 0 --if GetItemGrantTypeById(ItemId) == EDropItemSet.SkillBooks then -- local Val = math.random(9, 32) -- CreateId = 20000 + Val * 100 + (Level + 1) * 10 --else -- CreateId = ItemId // 1000 * 1000 + WeaponType * 100 + (Level + 1) * 10 --end -- --if ItemId == InItemList[2] and ItemId == InItemList[3] then -- CreateId = ItemId + 10 -- 抬升一个等级 --end return InItemList[math.random(1,3)] end -- 显示所有拾取的东西 function BP_PlayerController:ClientRPC_ShowPickUpItems(InAddItems) local ItemsMap = {} for i = 1, table.getCount(InAddItems) do local ItemId = InAddItems[i] if ItemsMap[ItemId] == nil then ItemsMap[ItemId] = 1 else ItemsMap[ItemId] = ItemsMap[ItemId] + 1 end end -- 找到对应物品 for i, v in pairs(ItemsMap) do local FittingItem = DropItemMap.FittingItemMap[i] local Item = nil if FittingItem ~= nil then Item = FittingItem["Quality"] .. FittingItem["WeaponType"] .. FittingItem["FittingType"] else FittingItem = DropItemMap.SkillItemMap[i] if FittingItem == nil then print(string.format('[BP_PlayerController:ClientRPC_ShowPickUpItems] 当前没有该元素:%s', tostring(i))) return end Item = FittingItem["Quality"] .. FittingItem["SkillName"] end local Params = { Text = Item, Color = Tables.ItemRarityColor[GetItemQualityLevel(i)].LinearColor, -- 16进制颜色 Num = v, } NoticeTipsTools.ClientNoticeTips(ECustomNoticeType.RollingNotice, Params, ERollingNoticeType.Gain) end end ------------------------------------ 背包相关逻辑 ------------------------------------ function BP_PlayerController:OnRep_ItemMap() -- 刷新一下背包界面 --log_tree("ItemMap - ", self.ItemMap) EventSystem:SendEvent(EventType.UpdateItemList, false) end function BP_PlayerController:GetItemTypeCountByType(InType) return table.getCount(self.ItemMap[InType]) end --- Server 添加/减少物品数量 ---@param InItemID number @目标物品ID ---@param InCount number @更改的数量(若为负数则视为丢弃) ---@return number @实际添加/减少的数量,当 数据 == -1000 的时候没有拾取或者丢弃 ---减少的时候数量不会超过该物品的总数,因此不需要判断具体减少数据会不会超过总数 function BP_PlayerController:UpdateItemMap(InItemID, InCount) local RetVal = 0 --石头 和 技能书 if InItemID > 20000 then --获取对应信息即可 local InType = nil if InItemID // 1000 == 31 then InType = EItemType.ScouringStone elseif InItemID // 1000 == 32 then InType = EItemType.SubstituteStone elseif InItemID // 10000 == 2 then InType = EItemType.SkillBook end RetVal = InCount print(string.format('当前玩家身上物品表的数量为:%d', self:GetItemTypeCountByType(InType))) local val = self.ItemMap[InType][InItemID] if self:GetItemTypeCountByType(InType) >= 24 then -- 判断当前是否有该物品,如果有,就执行操作,没有就返回0 if val == nil then return 0 end end if val == nil then if InCount <= 0 then RetVal = 0 else self.ItemMap[InType][InItemID] = InCount end else --表示由原先值并且打算移除 if val + InCount == 0 then table.removeKey(self.ItemMap[InType], InItemID) else self.ItemMap[InType][InItemID] = val + InCount end RetVal = InCount end return RetVal end -- 普通武器配件 local Type = GetItemTypeByItemId(InItemID) if self:GetItemTypeCountByType(Type) >= 24 then if InCount <= 0 then return 0 end end local CurCount = self.ItemMap[Type][InItemID] if InCount > 0 then if CurCount == nil then self.ItemMap[Type][InItemID] = InCount else -- 此处判断是否会超出数量 self.ItemMap[Type][InItemID] = CurCount + InCount end RetVal = InCount elseif InCount < 0 then if CurCount == nil then return 0 end print(string.format('开始移除')) if math.abs(InCount) == CurCount then table.removeKey(self.ItemMap[Type], InItemID) else self.ItemMap[Type][InItemID] = CurCount + InCount end RetVal = InCount else RetVal = 0 end return RetVal end -- 添加背包物品 function BP_PlayerController:AddBagItem(InItemData) local HadAddCount = self:UpdateItemMap(InItemData.ItemID, InItemData.ItemCount) --该数据只有 == 数量和 0 这两个值 if HadAddCount == InItemData.ItemCount then return end -- 生成出来 if InItemData.ItemCount < 0 then return end self:CreateItem(nil, InItemData) end function BP_PlayerController:GenerateItemList(InItemList) print(string.format("[BP_PlayerController:GenerateItemList] 当前要删除的数量为:%d", #InItemList)) local ItemList = {} for i = 1, #InItemList do table.insert(ItemList, InItemList[i]) end UnrealNetwork.CallUnrealRPC(self, self, "ServerRPC_GenerateItem", ItemList) end function BP_PlayerController:GetItemMap() return self.ItemMap end function BP_PlayerController:GetItemMapByItemType(InType) return self.ItemMap[InType] end function BP_PlayerController:FindItemCount( InType, InItemID ) if InItemID ~= nil then print('[BP_PlayerController:FindItemCount] ItemId = NIl') else print(string.format('[BP_PlayerController:FindItemCount] ItemId = %d, ItemMap Count = %d', InItemID, #self.ItemMap)) end local Count = self.ItemMap[InType][InItemID] if Count == nil then return 0 end return Count end -- 拾取操作 function BP_PlayerController:RequestPickupNearbyItems(IsPickAll) -- 首先判断玩家在哪部分 if self.Pawn.IsInArena then local Dis if IsPickAll then Dis = self.PickupDistance else Dis = self.AutoPickupDistance end if not table.isEmpty(self.AllItemActors[ETeleportType.InArena]) then local AddItemThisIDs = {} for i, v in pairs(self.AllItemActors[ETeleportType.InArena]) do if UE.IsValid(v) and v.bIsPicking == false then local bCanPick = true if IsPickAll == false then bCanPick = v:IsAutoPickupDisabled(self.PlayerKey) == false end local DisLen = VectorHelper.Length(VectorHelper.Sub(self.Pawn:K2_GetActorLocation(), v:K2_GetActorLocation())) if Dis >= DisLen and bCanPick then v:SetIsPicking(true) table.insert(AddItemThisIDs, v:GetThisID()) end end end -- 告知服务器进行拾取这些 UnrealNetwork.CallUnrealRPC(self, self, "ServerRPC_AddItemsByThisID", AddItemThisIDs) end else if not table.isEmpty(self.AllItemActors[ETeleportType.InHangupRoom]) then -- 拾取这里面的所有物品 -- i: 序号;v: 具体物体 local AddItems = {} for i, v in pairs(self.AllItemActors[ETeleportType.InHangupRoom]) do if UE.IsValid(v) and v.bIsPicking == false then -- 通知服务器进行添加 local bCanPick = false if not IsPickAll then local DisLen = VectorHelper.Length(VectorHelper.Sub(self.Pawn:K2_GetActorLocation(), v:K2_GetActorLocation())) bCanPick = v:IsAutoPickupDisabled(self.PlayerKey) == false and DisLen <= self.AutoPickupDistance end bCanPick = self:CanAddItemById(v:GetItemID()) and (IsPickAll or bCanPick) if bCanPick then v:SetIsPicking(true) local ItemData = { ItemID = v:GetItemID(), ItemCount = v:GetItemCount() } v:K2_DestroyActor() table.insert(AddItems, ItemData) end end end if not table.isEmpty(AddItems) then UnrealNetwork.CallUnrealRPC(self, self, "ServerRPC_AddExerciseItems", AddItems) end end end end function BP_PlayerController:ClientUpdateItemMap(ItemMap) self.ItemMap = TableHelper.DeepCopyTable(ItemMap) end function BP_PlayerController:IsBackpackFull(InItemType) return table.getCount(self.ItemMap[InItemType]) == 24 end function BP_PlayerController:FindQualityItemCount(InQuality, InGrantType) local Count = 0 if InGrantType == EDropItemSet.WeaponParts then for i, v in pairs(self.ItemMap) do if i < EItemType.SkillBook then for c, d in pairs(v) do if GetItemQualityLevel(c) == InQuality then Count = Count + d end end end end elseif InGrantType == EDropItemSet.SkillBooks then for i, v in pairs(self.ItemMap[EItemType.SkillBook]) do if GetItemQualityLevel(i) == InQuality then Count = Count + v end end end return Count end -- S / C: 是否可以添加新的物品 function BP_PlayerController:CanAddItemById(InItemId) -- 如果没满的话 local InType = GetItemTypeByItemId(InItemId) if self:IsBackpackFull(GetItemTypeByItemId(InItemId)) then -- 遍历查找是否有该东西 local Count = self:FindItemCount(InType, InItemId) return Count > 0 end return true end function BP_PlayerController:RequestExerciseDropItem(InPlayerKey, InLoc, InRot, InData, IsMonsterDrop, IsFromDiscard) print(string.format('[BP_PlayerController:RequestExerciseDropItem] '.. tostring(InPlayerKey))) InLoc = VectorHelper.ToLuaTable(InLoc) InRot = VectorHelper.RotToLuaTable(InRot) UnrealNetwork.CallUnrealRPC(self, self, "ClientRPC_SpawnExerciseDropItem", InPlayerKey, InLoc, InRot, InData, IsMonsterDrop, IsFromDiscard) end -- 客户端生成 function BP_PlayerController:ClientRPC_SpawnExerciseDropItem(InPlayerKey, InLoc, InRot, InData, IsMonsterDrop, IsFromDiscard) if self.PlayerKey ~= InPlayerKey then return; end print(string.format('[BP_PlayerController:ClientRPC_SpawnExerciseDropItem] 执行')) local Location = self.Pawn:K2_GetActorLocation() local ForwardLocation = VectorHelper.ToLuaTable(self.Pawn:GetActorForwardVector()) local Scalar = 1.5 ForwardLocation = { X = ForwardLocation.X * Scalar, Y = ForwardLocation.Y * Scalar, Z = ForwardLocation.Z - 0 } log_tree('ForwardLocation = ', ForwardLocation) Location = VectorHelper.Add(Location, ForwardLocation) --Location = VectorHelper.Add(Location, VectorHelper.MulScalar(ForwardLocation, 1.5)) Location = VectorHelper.ToLuaTable(Location) local Scale = VectorHelper.ScaleOne() --此处生成了一个具体的 Item local DropItemActor = nil if IsMonsterDrop then DropItemActor = UGCGameSystem.SpawnActor( self, self.ItemActorClass, InLoc, -- 阉割版 InRot, Scale, UGCGameSystem.GameState ) else DropItemActor = UGCGameSystem.SpawnActor( self, self.ItemActorClass, Location, -- 阉割版 InRot, Scale, UGCGameSystem.GameState ) end --DropItemActor:SetPickItemData(string.format("%d;%d", InData.ItemID, InData.Count)) -- 设置数据进去 DropItemActor:SetItemData(InData) -- 设置自动销毁时间 DropItemActor:SetLifeSpan(60 * 30) if IsFromDiscard then DropItemActor:SetAutoPickupDisabled(InPlayerKey) end table.insert(self.AllItemActors[ETeleportType.InHangupRoom], DropItemActor) end function BP_PlayerController:ServerRPC_AddExerciseItems(InItemList) local AddItems = {} print(string.format('[BP_PlayerController:ServerRPC_AddExerciseItems] 执行!'.. tostring(self.PlayerKey))) log_tree('InItemList = ', InItemList) log_tree('UGCGameSystem.GameState.DropItemList = ', UGCGameSystem.GameState.DropItemList) local AddItemIds = {} for i = 1, #InItemList do -- 检查保存在 GameState 中的数组 -- c: ItemId, v:ItemCount local SavedCount = UGCGameSystem.GameState.DropItemList[self.PlayerKey][InItemList[i].ItemID] if SavedCount ~= nil then if SavedCount < InItemList[i].ItemCount then print(string.format('[BP_PlayerController:ServerRPC_AddExerciseItems] 该元素:%d 作弊了', InItemList[i].ItemID)) else local ItemData = { ItemID = InItemList[i].ItemID, ItemCount = InItemList[i].ItemCount, } table.insert(AddItems, ItemData) table.insert(AddItemIds, InItemList[i].ItemID) local AddCount = self:UpdateItemMap(InItemList[i].ItemID, InItemList[i].ItemCount) if SavedCount == AddCount then table.removeKey(UGCGameSystem.GameState.DropItemList[self.PlayerKey], InItemList[i].ItemID) else UGCGameSystem.GameState.DropItemList[self.PlayerKey][InItemList[i].ItemID] = SavedCount - InItemList[i].ItemCount end end else print(string.format('[BP_PlayerController:ServerRPC_AddExerciseItems] 该元素:%d 作弊了', InItemList[i].ItemID)) end end UnrealNetwork.CallUnrealRPC(self, self, "ClientRPC_ShowPickUpItems", AddItemIds) end function BP_PlayerController:ServerRPC_GM_AddItems(InItemDataList) local AddItemIds = {} for _, ItemData in pairs(InItemDataList) do if self:UpdateItemMap(ItemData.ItemID, ItemData.ItemCount) > 0 then table.insert(AddItemIds, ItemData.ItemID) end end UnrealNetwork.CallUnrealRPC(self, self, "ClientRPC_ShowPickUpItems", AddItemIds) end function BP_PlayerController:ServerRPC_GM_AddCoinPoint(InDelta) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) if UE.IsValid(PlayerState) then PlayerState:AddCoinPointDirectly(InDelta) end end function BP_PlayerController:ServerRPC_GM_AddTechPoint(InDelta) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) if UE.IsValid(PlayerState) then PlayerState:AddTechPointDirectly(InDelta) end end function BP_PlayerController:ServerRPC_GM_ChangeTimeScale(Scale) EventSystem:SendEvent(EventType.GM_TimeScale, Scale) end function BP_PlayerController:ServerRPC_OnBreach(InPlayerKey) print(string.format('[BP_PlayerController:ServerRPC_OnBreach] 执行生成一个怪')) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(InPlayerKey) local Level = PlayerState.Level if Level % 10 ~= 0 then return end local LevelVal = Level / 10 -- 获取 BossId local BossList = UGCGameSystem.GameState.BossList if LevelVal > #BossList then LevelVal = #BossList end local BossId = BossList[LevelVal] print(string.format('[BP_PlayerController:ServerRPC_OnBreach] BossId = %d', BossId)) -- 找到要添加的枪 local NeedAddWeaponType = Tables.MonsterBaseConfig[BossId].WeaponType if NeedAddWeaponType == nil then print(string.format('[BP_PlayerController:ServerRPC_OnBreach] 找不到当前武器类型:%d', NeedAddWeaponType)) return end for i, v in pairs(Tables.DefaultWeaponId) do if v == NeedAddWeaponType then -- 要添加 i self:ServerRPC_StartSpawnBreachMonster(i, Level) break end end end function BP_PlayerController:ClientRPC_ShowInitialPanel(IsShow) print(string.format('[BP_PlayerController:ClientRPC_ShowInitialPanel] 执行')) if IsShow then self.InitialWidget = UserWidget.NewWidgetObjectBP(self, UE.LoadClass(UGCGameSystem.GetUGCResourcesFullPath('Asset/UI/Notice/WBP_InitialNotice_V2.WBP_InitialNotice_V2_C'))) self.InitialWidget:AddToViewport() self.InitialWidget:SetVisibility(ESlateVisibility.Visible) else if self.InitialWidget then self.InitialWidget:SetVisibility(ESlateVisibility.Collapsed) end end end function BP_PlayerController:ClientRPC_ShowPanel(UIType, ...) UIManager:ShowPanel(UIType, ...) end function BP_PlayerController:ServerRPC_CloseInitialNotice(IsShow) UGCGameSystem.GameState:SetInitialOver(IsShow) end function BP_PlayerController:Client_UpdateArchiveData(InArchiveData) log_tree("[BP_PlayerController:Client_UpdateArchiveData] InArchiveData = ", InArchiveData); self.PlayerState:SetGameEndArchiveData(InArchiveData); end return BP_PlayerController;