local Action_GameFight = { InitialWaitTime = 90.0, } function Action_GameFight:Execute(...) local GameState = UGCGameSystem.GameState GameState.GameStage = EGameStage.GameFight self.bEnableActionTick = false self.CurWaveRemainTime = 0.0 self.CurWaveElapseTime = 0.0 self.TimeScale = 1.0 self:SetupGameMultiplier() self:SendAllPlayerToTeleporters() self:InitAttackWave() self:InitChallengeMonsterTime() self:SetupBGMSoundConfigId(4) EventSystem:AddListener(EventType.OnIsInAttackWaveChanged, Action_GameFight.OnIsInAttackWaveChanged, self) EventSystem:AddListener(EventType.SendPlayersToExercise, Action_GameFight.SendAllPlayerToTeleporters, self) EventSystem:AddListener(EventType.OnSendGameEnd, Action_GameFight.OnReceiveGameEnd, self) EventSystem:AddListener(EventType.GM_TimeScale, Action_GameFight.UpdateTimeScale, self) UGCGameSystem.SendModeCustomEvent("ActivateHangUpRoom") return true end function Action_GameFight:SendAllPlayerToTeleporters() local AllTeleporters ={} local TeleporterClass = UE.LoadClass(BPClassPath.Teleporter) if UE.IsValid(TeleporterClass) then AllTeleporters = totable(GameplayStatics.GetAllActorsOfClass(self, TeleporterClass, {})) end if next(AllTeleporters) == nil then return end local AllPlayers = UGCGameSystem.GetAllPlayerPawn() for _, PlayerPawn in pairs(AllPlayers) do if PlayerPawn.IsInArena then local PlayerKey = UGCPawnAttrSystem.GetPlayerKeyInt64(PlayerPawn) local PC = UGCGameSystem.GetPlayerControllerByPlayerKey(PlayerKey) if PC and PC.HangUpRoomPlayerStart then local DestLoc = PC.HangUpRoomPlayerStart:K2_GetActorLocation() local DestRot = PC.HangUpRoomPlayerStart:K2_GetActorRotation() PlayerPawn.bShouldDumpCallstackWhenMovingfast = false PlayerPawn:SetClientLocationOrRotation(DestLoc, DestRot, true, false) PlayerPawn.bShouldDumpCallstackWhenMovingfast = true PlayerPawn.IsInArena = false end end end end function Action_GameFight:InitChallengeMonsterTime() local PlayerStates = UGCGameSystem.GetAllPlayerState(false); for i, v in pairs(PlayerStates) do v:InitChallengeMonsterTime(UGCGameSystem.GameState.GameDuration) end end function Action_GameFight:InitAttackWave() self.EnterStateTime = GameplayStatics.GetRealTimeSeconds(self) UE.Log("[Action_GameFight:InitAttackWave] EnterStateTime = %.2f", self.EnterStateTime) local GameState = UGCGameSystem.GameState local GameDifficulty = GameState.GameDifficulty self.AttackWaveConfig = {} local Table = Tables.GameFightStageConfig[GameDifficulty] if Table == nil then Table = Tables.GameFightStageConfig[4] end self.AttackWaveConfig = TableHelper.DeepCopyTable(Table) self.AttackWaveConfig[0] = { WaitTime = self.InitialWaitTime } local TotalWaitTime = self.EnterStateTime + 0.5 GameState.GameStartTimeStamp = TotalWaitTime for Index = 0, table.getCount(self.AttackWaveConfig) - 1 do local Config = self.AttackWaveConfig[Index] UE.Log("[Action_GameFight:Execute] Config: Index = %d, WaitTime = %.2f", Index, Config.WaitTime) end self.CurAttackWave = 0 self.AttackWaveMonsterConfig = nil self.bIsInLastWave = false EventSystem.SetTimer(GameState, function() self:DispatchEvent() self.bEnableActionTick = true end, 0.5) end function Action_GameFight:Update(DeltaSeconds) if self.bEnableActionTick == false then return end local RemainTime = self.CurWaveRemainTime - self.CurWaveElapseTime if RemainTime > 0.0 then self.CurWaveElapseTime = self.CurWaveElapseTime + DeltaSeconds * self.TimeScale else self:DispatchEvent() self:AttackWaveCheck() end local GameState = UGCGameSystem.GameState if GameState then GameState.GameDuration = math.floor(GameplayStatics.GetRealTimeSeconds(self) - GameState.GameStartTimeStamp) GameState.GameFightStageRemainTime = math.ceil(math.clamp(RemainTime, 0.0, RemainTime)) end end function Action_GameFight:DispatchEvent() if self.bIsInLastWave then UE.Log("[Action_GameFight:DispatchEvent] GameEnd This Time = %2.2f", GameplayStatics.GetRealTimeSeconds(self)) self:StopGameFightStage() return end local WaveConfig = self.AttackWaveConfig[self.CurAttackWave] if WaveConfig ~= nil then self.CurWaveRemainTime = WaveConfig.WaitTime self.CurWaveElapseTime = 0.0 self.AttackWaveMonsterConfig = WaveConfig.MonsterNum UGCGameSystem.GameState.CurAttackWave = self.CurAttackWave UE.Log("[Action_GameFight:DispatchEvent] Update GameState.CurAttackWave[%d]", UGCGameSystem.GameState.CurAttackWave) self:SpawnAttackMonsters() end self.CurAttackWave = self.CurAttackWave + 1 end function Action_GameFight:SpawnAttackMonsters() local LogStr = string.format("[Action_GameFight:SpawnAttackMonsters] CurWave = %d, ", self.CurAttackWave) local MonsterNum = self.AttackWaveMonsterConfig if MonsterNum ~= nil then local NormalMonsterNum = MonsterNum.Normal local BossMonsterNum = MonsterNum.Boss LogStr = LogStr..string.format("NormalNum = %d, BossNum = %d",NormalMonsterNum,BossMonsterNum) if BossMonsterNum > 0 then self:SetupBGMSoundConfigId(3) else self:SetupBGMSoundConfigId(4) end local AttackWaveSpawner = UGCGameSystem.GameState:GetAttackWaveSpawner() if UE.IsValid(AttackWaveSpawner) then AttackWaveSpawner:StartSpawnAttackWave(NormalMonsterNum, BossMonsterNum) end else LogStr = LogStr.."invalid config" end UE.Log(LogStr) end function Action_GameFight:AttackWaveCheck() if self.bIsInLastWave == false and self.CurAttackWave >= table.getCount(self.AttackWaveConfig) then self.bIsInLastWave = true self.AttackWaveConfig[self.CurAttackWave] = self.AttackWaveConfig[self.CurAttackWave - 1].WaitTime UE.Log("[Action_GameFight:AttackWaveCheck] Final Wave = %d", self.CurAttackWave - 1) end end function Action_GameFight:StopGameFightStage() EventSystem:SendEvent(EventType.OnSendGameEnd, "TimeOut") end function Action_GameFight:OnIsInAttackWaveChanged(bIsInAttackWave) if bIsInAttackWave == false then local CrystalBP = UGCGameSystem.GameState:GetCrystal() if UE.IsValid(CrystalBP) then CrystalBP.CurrentHp = CrystalBP.MaxHp CrystalBP:OnRep_CurrentHp() end end end function Action_GameFight:SetupGameMultiplier() local GameState = UGCGameSystem.GameState local AllPlayers = UGCGameSystem.GetAllPlayerPawn() local PlayerNum = #AllPlayers GameState.BossHealthMultiplier = GlobalConfigs.PlayerNumMultiplier[PlayerNum] local GameDifficulty = GameState.GameDifficulty GameState.MonsterHealthAndAttackValueMultiplier.Health = GlobalConfigs.DifficultyMultiplier["Health"][GameDifficulty] GameState.MonsterHealthAndAttackValueMultiplier.Attack = GlobalConfigs.DifficultyMultiplier["Attack"][GameDifficulty] end function Action_GameFight:SetupBGMSoundConfigId(Id) if self.CurFightSoundConfigId ~= Id then self.CurFightSoundConfigId = Id SoundManager.MulticastPlaySound2D(self.CurFightSoundConfigId) end end function Action_GameFight:OnReceiveGameEnd(EndReason) self.bEnableActionTick = false end function Action_GameFight:UpdateTimeScale(Scale) if Scale ~= self.TimeScale then self.TimeScale = Scale end end return Action_GameFight