From 6820eae460a9c99136ab5e679ffe2f6236c3540f Mon Sep 17 00:00:00 2001 From: fgsfds Date: Thu, 27 Feb 2020 20:44:52 +0300 Subject: [PATCH] survival/lms fixes * people joining mid game do not spawn * warmup time is displayed on both clients and server * monsters are now intangible during warmup * clients use the proper spectator mode when dead in survival * raised protocol version to 185 --- src/game/g_game.pas | 64 ++++++++++------------ src/game/g_language.pas | 3 + src/game/g_monsters.pas | 10 ++++ src/game/g_net.pas | 2 +- src/game/g_netmsg.pas | 118 ++++++++++++++++++++++++---------------- src/game/g_player.pas | 27 +++++---- 6 files changed, 133 insertions(+), 91 deletions(-) diff --git a/src/game/g_game.pas b/src/game/g_game.pas index 4a79f98..94fe883 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -3769,10 +3769,6 @@ begin else gPlayers[i].DrawIndicator(gPlayers[i].GetColor); end; - if p.FSpectator then - e_TextureFontPrintEx(p.GameX + PLAYER_RECT_CX - 4, - p.GameY + PLAYER_RECT_CY - 4, - 'X', gStdFont, 255, 255, 255, 1, True); { for a := 0 to High(gCollideMap) do for b := 0 to High(gCollideMap[a]) do @@ -4260,10 +4256,7 @@ begin if g_Game_IsClient then begin if NetPlrUID1 > -1 then - begin MC_SEND_CheatRequest(NET_CHEAT_SPECTATE); - gPlayer1 := g_Player_Get(NetPlrUID1); - end; Exit; end; @@ -4337,8 +4330,12 @@ begin g_Console_Add(Format(_lc[I_PLAYER_LEAVE], [Pl.Name]), True); g_Player_Remove(Pl.UID); g_Net_Slist_ServerPlayerLeaves(); - end else + end + else + begin + gSpectLatchPID2 := Pl.UID; gPlayer2 := nil; + end; Exit; end; Pl := gPlayer1; @@ -4353,6 +4350,7 @@ begin g_Net_Slist_ServerPlayerLeaves(); end else begin + gSpectLatchPID1 := Pl.UID; gPlayer1 := nil; MC_SEND_CheatRequest(NET_CHEAT_SPECTATE); end; @@ -4700,6 +4698,11 @@ begin // create (or update) map/resource databases g_Res_CreateDatabases(true); + gLMSRespawn := LMS_RESPAWN_NONE; + gLMSRespawnTime := 0; + gSpectLatchPID1 := 0; + gSpectLatchPID2 := 0; + // Ñòàðòóåì êëèåíò if not g_Net_Connect(Addr, Port) then begin @@ -4839,9 +4842,6 @@ begin Exit; end; - gLMSRespawn := LMS_RESPAWN_NONE; - gLMSRespawnTime := 0; - g_Player_Init(); NetState := NET_STATE_GAME; MC_SEND_FullStateRequest; @@ -4992,8 +4992,8 @@ begin NetTimeToUpdate := 1; NetTimeToReliable := 0; NetTimeToMaster := NetMasterRate; - gLMSRespawn := LMS_RESPAWN_NONE; - gLMSRespawnTime := 0; + gSpectLatchPID1 := 0; + gSpectLatchPID2 := 0; gMissionFailed := False; gNextMap := ''; @@ -5011,15 +5011,21 @@ begin g_Game_SpectateCenterView(); - if (gGameSettings.MaxLives > 0) and (gGameSettings.WarmupTime > 0) then + if g_Game_IsServer then begin - gLMSRespawn := LMS_RESPAWN_WARMUP; - gLMSRespawnTime := gTime + gGameSettings.WarmupTime*1000; - gLMSSoftSpawn := True; - if NetMode = NET_SERVER then - MH_SEND_GameEvent(NET_EV_LMS_WARMUP, (gLMSRespawnTime - gTime) div 1000) + if (gGameSettings.MaxLives > 0) and (gGameSettings.WarmupTime > 0) then + begin + gLMSRespawn := LMS_RESPAWN_WARMUP; + gLMSRespawnTime := gTime + gGameSettings.WarmupTime*1000; + gLMSSoftSpawn := True; + if g_Game_IsNet then + MH_SEND_GameEvent(NET_EV_LMS_WARMUP, gLMSRespawnTime - gTime); + end else - g_Console_Add(Format(_lc[I_MSG_WARMUP_START], [(gLMSRespawnTime - gTime) div 1000]), True); + begin + gLMSRespawn := LMS_RESPAWN_NONE; + gLMSRespawnTime := 0; + end; end; if NetMode = NET_SERVER then @@ -5168,13 +5174,6 @@ end; procedure g_Game_RestartRound(NoMapRestart: Boolean = False); var i, n, nb, nr: Integer; - - function monRespawn (mon: TMonster): Boolean; - begin - result := false; // don't stop - if not mon.FNoRespawn then mon.Respawn(); - end; - begin if not g_Game_IsServer then Exit; if gLMSRespawn = LMS_RESPAWN_NONE then Exit; @@ -5235,17 +5234,14 @@ begin gPlayers[i].Frags := 0; gPlayers[i].RecallState; end; - if (gPlayer1 = nil) and (gLMSPID1 > 0) then - gPlayer1 := g_Player_Get(gLMSPID1); - if (gPlayer2 = nil) and (gLMSPID2 > 0) then - gPlayer2 := g_Player_Get(gLMSPID2); + if (gPlayer1 = nil) and (gSpectLatchPID1 > 0) then + gPlayer1 := g_Player_Get(gSpectLatchPID1); + if (gPlayer2 = nil) and (gSpectLatchPID2 > 0) then + gPlayer2 := g_Player_Get(gSpectLatchPID2); end; g_Items_RestartRound(); - - g_Mons_ForEach(monRespawn); - gLMSSoftSpawn := False; end; diff --git a/src/game/g_language.pas b/src/game/g_language.pas index e17b4c2..5a24323 100644 --- a/src/game/g_language.pas +++ b/src/game/g_language.pas @@ -80,6 +80,7 @@ type I_GAME_SECRETS, I_GAME_MONSTERS_TOTAL, I_GAME_SECRETS_TOTAL, + I_GAME_WARMUP, I_GAME_CHEAT_GODMODE, I_GAME_CHEAT_WEAPONS, @@ -764,6 +765,8 @@ const 'Âñåãî ìîíñòðîâ óáèòî:'), ('GAME SECRETS TOTAL', 'Total secrets found:', 'Âñåãî ñåêðåòîâ íàéäåíî:'), + ('GAME WARMUP', 'Warmup', + 'Ïîäãîòîâêà'), ('GAME CHEAT GODMODE', 'MACLEOD', 'ÃÎÐÅÖ'), diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index 878d00d..e7ee1d0 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -1993,6 +1993,9 @@ var begin Result := False; +// Ìîíñòð ñòàòè÷åí ïîêà èäåò warmup + if (gLMSRespawn = LMS_RESPAWN_WARMUP) then exit; + // Óìèðàåò, óìåð èëè âîñêðåøàåòñÿ => óðîí äåëàòü íåêîìó: if (FState = MONSTATE_DEAD) or (FState = MONSTATE_DIE) or (FState = MONSTATE_REVIVE) then Exit; @@ -2450,6 +2453,9 @@ label begin fall := True; +// Ìîíñòð ñòàòè÷åí ïîêà èäåò warmup + if (gLMSRespawn = LMS_RESPAWN_WARMUP) then exit; + // Ðûáû "ëåòàþò" òîëüêî â âîäå: if FMonsterType = MONSTER_FISH then if g_Obj_CollidePanel(@FObj, 0, 0, PANEL_WATER or PANEL_ACID1 or PANEL_ACID2) then @@ -3439,6 +3445,10 @@ begin sx := 0; // SHUT UP COMPILER sy := 0; fall := True; + +// Ìîíñòð ñòàòè÷åí ïîêà èäåò warmup + if (gLMSRespawn = LMS_RESPAWN_WARMUP) then exit; + // Ðûáû "ëåòàþò" òîëüêî â âîäå: if FMonsterType = MONSTER_FISH then if g_Obj_CollidePanel(@FObj, 0, 0, PANEL_WATER or PANEL_ACID1 or PANEL_ACID2) then diff --git a/src/game/g_net.pas b/src/game/g_net.pas index d2bc5a2..6226f00 100644 --- a/src/game/g_net.pas +++ b/src/game/g_net.pas @@ -21,7 +21,7 @@ uses e_log, e_msg, utils, ENet, Classes, md5, MAPDEF{$IFDEF USE_MINIUPNPC}, miniupnpc;{$ELSE};{$ENDIF} const - NET_PROTOCOL_VER = 184; + NET_PROTOCOL_VER = 185; NET_MAXCLIENTS = 24; NET_CHANS = 12; diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index 1fd6f7c..92c4516 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -112,6 +112,7 @@ const NET_EV_PLAYER_TOUCH = 18; NET_EV_SECRET = 19; NET_EV_INTER_READY = 20; + NET_EV_LMS_NOSPAWN = 21; NET_VE_STARTED = 1; NET_VE_PASSED = 2; @@ -429,37 +430,26 @@ begin Name := PName; FClientID := C^.ID; // round in progress, don't spawn - if (gGameSettings.MaxLives > 0) and (gLMSRespawn = LMS_RESPAWN_NONE) then - begin - Lives := 0; - FNoRespawn := True; - Spectate; - FWantsInGame := True; // TODO: look into this later - C^.WaitForFirstSpawn := true; - end - else - begin - e_LogWritefln('*** client #%u (cid #%u) authenticated...', [C.ID, C.Player]); - //e_LogWritefln('spawning player with pid #%u...', [PID]); - //Respawn(gGameSettings.GameType = GT_SINGLE); - //k8: no, do not spawn a player yet, wait for "request full state" packet - Lives := 0; - Spectate; - FNoRespawn := True; - // `FWantsInGame` seems to mean "spawn the player on the next occasion". - // that is, if we'll set it to `true`, the player can be spawned after - // warmup time ran out, for example, regardless of the real player state. - // also, this seems to work only for the initial connection. further - // map changes could initiate resource downloading, but the player will - // be spawned immediately. - // the proper solution will require another player state, "ephemeral". - // the player should start any map in "ephemeral" state, and turned into - // real mobj only when they sent a special "i am ready" packet. this packet - // must be sent after receiving the full state, so the player will get a full - // map view before going into game. - FWantsInGame := false; - C^.WaitForFirstSpawn := true; - end; + e_LogWritefln('*** client #%u (cid #%u) authenticated...', [C.ID, C.Player]); + //e_LogWritefln('spawning player with pid #%u...', [PID]); + //Respawn(gGameSettings.GameType = GT_SINGLE); + //k8: no, do not spawn a player yet, wait for "request full state" packet + Lives := 0; + Spectate; + FNoRespawn := True; + // `FWantsInGame` seems to mean "spawn the player on the next occasion". + // that is, if we'll set it to `true`, the player can be spawned after + // warmup time ran out, for example, regardless of the real player state. + // also, this seems to work only for the initial connection. further + // map changes could initiate resource downloading, but the player will + // be spawned immediately. + // the proper solution will require another player state, "ephemeral". + // the player should start any map in "ephemeral" state, and turned into + // real mobj only when they sent a special "i am ready" packet. this packet + // must be sent after receiving the full state, so the player will get a full + // map view before going into game. + FWantsInGame := false; + C^.WaitForFirstSpawn := true; end; //if not C^.WaitForFirstSpawn then @@ -496,7 +486,18 @@ begin C.WaitForFirstSpawn := false; plr.FNoRespawn := false; plr.FWantsInGame := true; // TODO: look into this later - plr.Respawn(False); + + if (gGameSettings.MaxLives > 0) and (gLMSRespawn = LMS_RESPAWN_NONE) then + begin + plr.Spectate; + MH_SEND_GameEvent(NET_EV_LMS_NOSPAWN, 0, 'N', C.ID); + end + else + begin + plr.Respawn(False); + if gLMSRespawn = LMS_RESPAWN_WARMUP then + MH_SEND_GameEvent(NET_EV_LMS_WARMUP, gLMSRespawnTime - gTime, 'N', C.ID); + end; end; @@ -593,7 +594,12 @@ begin NET_CHEAT_SPECTATE: begin if Pl.FSpectator then - Pl.Respawn(False) + begin + if (gGameSettings.MaxLives = 0) or (gLMSRespawn = LMS_RESPAWN_WARMUP) then + Pl.Respawn(False) + else + MH_SEND_GameEvent(NET_EV_LMS_NOSPAWN, Pl.UID); + end else Pl.Spectate; end; @@ -815,12 +821,6 @@ begin if CreatePlayers and (ID >= 0) then NetClients[ID].State := NET_STATE_GAME; - if gLMSRespawn > LMS_RESPAWN_NONE then - begin - e_LogWritefln('*** client #%u (cid #%u) WARMUP', [ID, NetClients[ID].Player]); - MH_SEND_GameEvent(NET_EV_LMS_WARMUP, (gLMSRespawnTime - gTime) div 1000, 'N', ID); - end; - g_Net_Flush(); end; @@ -1768,6 +1768,8 @@ begin gTime := EvTime; + e_LogWritefln('EVENT %d %d', [EvType, EvNum]); + if (g_Res_received_map_start <> 0) then begin if (g_Res_received_map_start < 0) then exit; @@ -1777,6 +1779,7 @@ begin NET_EV_MAPEND: goodCmd := true; NET_EV_PLAYER_KICK: goodCmd := true; NET_EV_PLAYER_BAN: goodCmd := true; + NET_EV_LMS_WARMUP: goodCmd := true; end; if not goodCmd then exit; end; @@ -1813,6 +1816,8 @@ begin NET_EV_MAPEND: begin + gLMSRespawn := LMS_RESPAWN_NONE; + gLMSRespawnTime := 0; if (g_Res_received_map_start <> 0) then begin g_Res_received_map_start := -1; @@ -1857,7 +1862,18 @@ begin end; NET_EV_LMS_WARMUP: - g_Console_Add(Format(_lc[I_MSG_WARMUP_START], [EvNum]), True); + begin + if EvNum > 0 then + begin + gLMSRespawn := LMS_RESPAWN_WARMUP; + gLMSRespawnTime := gTime + EvNum; + g_Console_Add(Format(_lc[I_MSG_WARMUP_START], [EvNum div 1000]), True); + end + else if gPlayer1 = nil then + begin + g_Console_Add(_lc[I_PLAYER_SPECT4], True); + end; + end; NET_EV_LMS_SURVIVOR: g_Console_Add('*** ' + _lc[I_MESSAGE_LMS_SURVIVOR] + ' ***', True); @@ -1943,6 +1959,7 @@ begin NET_EV_LMS_START: begin g_Player_RemoveAllCorpses; + gLMSRespawn := LMS_RESPAWN_NONE; g_Game_Message(_lc[I_MESSAGE_LMS_START], 144); end; @@ -1963,6 +1980,9 @@ begin NET_EV_LMS_DRAW: g_Game_Message(_lc[I_GAME_WIN_DRAW], 144); + NET_EV_LMS_NOSPAWN: + g_Console_Add(_lc[I_PLAYER_SPECT4], True); + NET_EV_KILLCOMBO: g_Game_Announce_KillCombo(EvNum); @@ -2328,21 +2348,27 @@ begin begin if Pl = gPlayer1 then begin - gLMSPID1 := UID; + gSpectLatchPID1 := UID; gPlayer1 := nil; end; if Pl = gPlayer2 then begin - gLMSPID2 := UID; + gSpectLatchPID2 := UID; gPlayer2 := nil; end; end else begin - if (gPlayer1 = nil) and (gLMSPID1 > 0) then - gPlayer1 := g_Player_Get(gLMSPID1); - if (gPlayer2 = nil) and (gLMSPID2 > 0) then - gPlayer2 := g_Player_Get(gLMSPID2); + if (gPlayer1 = nil) and (gSpectLatchPID1 > 0) and (UID = gSpectLatchPID1) then + begin + gPlayer1 := Pl; + gSpectLatchPID1 := 0; + end; + if (gPlayer2 = nil) and (gSpectLatchPID2 > 0) and (UID = gSpectLatchPID2) then + begin + gPlayer2 := Pl; + gSpectLatchPID2 := 0; + end; end; FGhost := M.ReadByte() <> 0; FPhysics := M.ReadByte() <> 0; diff --git a/src/game/g_player.pas b/src/game/g_player.pas index 94ca02e..d9dd887 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -560,8 +560,8 @@ var gPlayerIndicator: Integer = 1; gPlayerIndicatorStyle: Integer = 0; gNumBots: Word = 0; - gLMSPID1: Word = 0; - gLMSPID2: Word = 0; + gSpectLatchPID1: Word = 0; + gSpectLatchPID2: Word = 0; MAX_RUNVEL: Integer = 8; VEL_JUMP: Integer = 10; SHELL_TIMEOUT: Cardinal = 60000; @@ -2766,7 +2766,14 @@ begin e_CharFont_PrintEx(gMenuSmallFont, X-16-tw, Y+32, s, _RGB(255, 0, 0)); end; - if gShowLives and (gGameSettings.MaxLives > 0) then + if gLMSRespawn = LMS_RESPAWN_WARMUP then + begin + s := _lc[I_GAME_WARMUP]; + e_CharFont_GetSize(gMenuFont, s, tw, th); + s := s + ': ' + IntToStr((gLMSRespawnTime - gTime) div 1000); + e_CharFont_PrintEx(gMenuFont, X-64-tw, SY-32, s, _RGB(0, 255, 0)); + end + else if gShowLives and (gGameSettings.MaxLives > 0) then begin s := IntToStr(Lives); e_CharFont_GetSize(gMenuFont, s, tw, th); @@ -3660,7 +3667,7 @@ begin if srv and (OldLR = LMS_RESPAWN_NONE) and (gLMSRespawn > LMS_RESPAWN_NONE) then begin if NetMode = NET_SERVER then - MH_SEND_GameEvent(NET_EV_LMS_WARMUP, (gLMSRespawnTime - gTime) div 1000) + MH_SEND_GameEvent(NET_EV_LMS_WARMUP, gLMSRespawnTime - gTime) else g_Console_Add(Format(_lc[I_MSG_WARMUP_START], [(gLMSRespawnTime - gTime) div 1000]), True); end; @@ -4706,9 +4713,9 @@ begin FSpectatePlayer := -1; FSpawned := True; - if (gPlayer1 = nil) and (gLMSPID1 = FUID) then + if (gPlayer1 = nil) and (gSpectLatchPID1 = FUID) then gPlayer1 := self; - if (gPlayer2 = nil) and (gLMSPID2 = FUID) then + if (gPlayer2 = nil) and (gSpectLatchPID2 = FUID) then gPlayer2 := self; if g_Game_IsNet then @@ -4745,12 +4752,12 @@ begin begin if Self = gPlayer1 then begin - gLMSPID1 := FUID; + gSpectLatchPID1 := FUID; gPlayer1 := nil; - end; - if Self = gPlayer2 then + end + else if Self = gPlayer2 then begin - gLMSPID2 := FUID; + gSpectLatchPID2 := FUID; gPlayer2 := nil; end; end; -- 2.29.2