summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 49466dd)
raw | patch | inline | side by side (parent: 49466dd)
author | fgsfds <pvt.fgsfds@gmail.com> | |
Thu, 27 Feb 2020 17:44:52 +0000 (20:44 +0300) | ||
committer | fgsfds <pvt.fgsfds@gmail.com> | |
Thu, 27 Feb 2020 17:44:52 +0000 (20:44 +0300) |
* 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
* 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
diff --git a/src/game/g_game.pas b/src/game/g_game.pas
index 4a79f98ebfd67d496271b8ed577b844402f19b2c..94fe8831712df01b6c81f8e557b82f89ce691e2a 100644 (file)
--- a/src/game/g_game.pas
+++ b/src/game/g_game.pas
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
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;
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;
g_Net_Slist_ServerPlayerLeaves();
end else
begin
+ gSpectLatchPID1 := Pl.UID;
gPlayer1 := nil;
MC_SEND_CheatRequest(NET_CHEAT_SPECTATE);
end;
// 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
Exit;
end;
- gLMSRespawn := LMS_RESPAWN_NONE;
- gLMSRespawnTime := 0;
-
g_Player_Init();
NetState := NET_STATE_GAME;
MC_SEND_FullStateRequest;
NetTimeToUpdate := 1;
NetTimeToReliable := 0;
NetTimeToMaster := NetMasterRate;
- gLMSRespawn := LMS_RESPAWN_NONE;
- gLMSRespawnTime := 0;
+ gSpectLatchPID1 := 0;
+ gSpectLatchPID2 := 0;
gMissionFailed := False;
gNextMap := '';
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
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;
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;
index e17b4c2420bad2b24c77bc48966fa6c511f15353..5a24323de0c66ce0f989a100c9a60672d926c1eb 100644 (file)
--- a/src/game/g_language.pas
+++ b/src/game/g_language.pas
I_GAME_SECRETS,
I_GAME_MONSTERS_TOTAL,
I_GAME_SECRETS_TOTAL,
+ I_GAME_WARMUP,
I_GAME_CHEAT_GODMODE,
I_GAME_CHEAT_WEAPONS,
'Âñåãî ìîíñòðîâ óáèòî:'),
('GAME SECRETS TOTAL', 'Total secrets found:',
'Âñåãî ñåêðåòîâ íàéäåíî:'),
+ ('GAME WARMUP', 'Warmup',
+ 'Ïîäãîòîâêà'),
('GAME CHEAT GODMODE', 'MACLEOD',
'ÃÎÐÅÖ'),
index 878d00df54fd550ab129c634a91405857b5b6635..e7ee1d0eb784275870b6aa872acb8158049d3256 100644 (file)
--- a/src/game/g_monsters.pas
+++ b/src/game/g_monsters.pas
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;
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
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 d2bc5a2be06a30cf2111c7189d9e1ad0fed0e78e..6226f00f3d9cc23e084892717c30dd44b7cf3564 100644 (file)
--- a/src/game/g_net.pas
+++ b/src/game/g_net.pas
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 1fd6f7c5a8d3e7a6be8a0dad2ce9ea3980b2b78c..92c45168c620f9c1f450c3e5ffc650f1b20ad359 100644 (file)
--- a/src/game/g_netmsg.pas
+++ b/src/game/g_netmsg.pas
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;
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
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;
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;
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;
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;
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;
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;
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);
NET_EV_LMS_START:
begin
g_Player_RemoveAllCorpses;
+ gLMSRespawn := LMS_RESPAWN_NONE;
g_Game_Message(_lc[I_MESSAGE_LMS_START], 144);
end;
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);
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 94ca02efbd7372227be18b606ad975f94c2f0673..d9dd8871a953815a003809dbeacb6d231539f1e7 100644 (file)
--- a/src/game/g_player.pas
+++ b/src/game/g_player.pas
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;
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);
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;
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
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;