DEADSOFTWARE

nuke doom2df.cfg; refactor some cvar-related stuff
authorfgsfds <pvt.fgsfds@gmail.com>
Mon, 24 Feb 2020 21:12:38 +0000 (00:12 +0300)
committerfgsfds <pvt.fgsfds@gmail.com>
Mon, 24 Feb 2020 21:12:38 +0000 (00:12 +0300)
src/game/g_console.pas
src/game/g_game.pas
src/game/g_items.pas
src/game/g_language.pas
src/game/g_main.pas
src/game/g_menu.pas
src/game/g_net.pas
src/game/g_netmaster.pas
src/game/g_options.pas

index cbfcf5faaabf1134618ca6942c99485d89bb364d..806c73f098e08e38746a65891a0b8c9c717a1128 100644 (file)
@@ -64,6 +64,8 @@ procedure conwritefln (const s: AnsiString; args: array of const; show: Boolean=
 procedure conRegVar (const conname: AnsiString; pvar: PBoolean; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload;
 procedure conRegVar (const conname: AnsiString; pvar: PSingle; amin, amax: Single; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload;
 procedure conRegVar (const conname: AnsiString; pvar: PInteger; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload;
+procedure conRegVar (const conname: AnsiString; pvar: PWord; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload;
+procedure conRegVar (const conname: AnsiString; pvar: PCardinal; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload;
 procedure conRegVar (const conname: AnsiString; pvar: PAnsiString; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload;
 
 // <0: no arg; 0/1: true/false
@@ -72,6 +74,8 @@ function conGetBoolArg (p: SSArray; idx: Integer): Integer;
 // poor man's floating literal parser; i'm sorry, but `StrToFloat()` sux cocks
 function conParseFloat (var res: Single; const s: AnsiString): Boolean;
 
+const
+  defaultConfigScript = 'dfconfig.cfg';
 
 var
   gConsoleShow: Boolean = false; // True - êîíñîëü îòêðûòà èëè îòêðûâàåòñÿ
@@ -81,6 +85,7 @@ var
   gJustChatted: Boolean = false; // ÷òîáû àäìèí â èíòåðå ÷àòÿñü íå ïðîìàòûâàë ñòàòèñòèêó
   gParsingBinds: Boolean = true; // íå ïåðåñîõðàíÿòü êîíôèã âî âðåìÿ ïàðñèíãà
   gPlayerAction: Array [0..1, 0..LAST_ACTION] of Boolean; // [player, action]
+  gConfigScript: string = defaultConfigScript;
 
 implementation
 
@@ -90,7 +95,6 @@ uses
   g_menu, g_gui, g_language, g_net, g_netmsg, e_log, conbuf;
 
 const
-  configScript = 'dfconfig.cfg';
   autoexecScript = 'autoexec.cfg';
   configComment = 'generated by doom2d, do not modify';
 
@@ -287,6 +291,50 @@ begin
 end;
 
 
+procedure wordVarHandler (me: PCommand; p: SSArray);
+var
+  old: Integer;
+begin
+  if (Length(p) <> 2) then
+  begin
+    conwritefln('%s %d', [me.cmd, PInteger(me.ptr)^]);
+  end
+  else
+  begin
+    try
+      old := PWord(me.ptr)^;
+      PWord(me.ptr)^ := min($FFFF, StrToDWord(p[1]));
+      if PWord(me.ptr)^ <> old then
+        g_Console_WriteGameConfig();
+    except
+      conwritefln('invalid word value: "%s"', [p[1]]);
+    end;
+  end;
+end;
+
+
+procedure dwordVarHandler (me: PCommand; p: SSArray);
+var
+  old: Integer;
+begin
+  if (Length(p) <> 2) then
+  begin
+    conwritefln('%s %d', [me.cmd, PInteger(me.ptr)^]);
+  end
+  else
+  begin
+    try
+      old := PCardinal(me.ptr)^;
+      PCardinal(me.ptr)^ := StrToDWord(p[1]);
+      if PCardinal(me.ptr)^ <> old then
+        g_Console_WriteGameConfig();
+    except
+      conwritefln('invalid dword value: "%s"', [p[1]]);
+    end;
+  end;
+end;
+
+
 procedure strVarHandler (me: PCommand; p: SSArray);
 var
   old: AnsiString;
@@ -347,6 +395,48 @@ begin
 end;
 
 
+procedure conRegVar (const conname: AnsiString; pvar: PWord; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload;
+var
+  f: Integer;
+  cp: PCommand;
+begin
+  f := Length(commands);
+  SetLength(commands, f+1);
+  cp := @commands[f];
+  cp.cmd := LowerCase(conname);
+  cp.proc := nil;
+  cp.procEx := wordVarHandler;
+  cp.help := ahelp;
+  cp.hidden := ahidden;
+  cp.ptr := pvar;
+  cp.msg := amsg;
+  cp.cheat := acheat;
+  cp.action := -1;
+  cp.player := -1;
+end;
+
+
+procedure conRegVar (const conname: AnsiString; pvar: PCardinal; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload;
+var
+  f: Integer;
+  cp: PCommand;
+begin
+  f := Length(commands);
+  SetLength(commands, f+1);
+  cp := @commands[f];
+  cp.cmd := LowerCase(conname);
+  cp.proc := nil;
+  cp.procEx := dwordVarHandler;
+  cp.help := ahelp;
+  cp.hidden := ahidden;
+  cp.ptr := pvar;
+  cp.msg := amsg;
+  cp.cheat := acheat;
+  cp.action := -1;
+  cp.player := -1;
+end;
+
+
 procedure conRegVar (const conname: AnsiString; pvar: PAnsiString; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload;
 var
   f: Integer;
@@ -860,13 +950,10 @@ begin
 
   AddCommand('segfault', segfault, 'make segfault');
 
-  AddCommand('r_reset', g_Options_Commands);
-  AddCommand('g_language', g_Options_Commands);
-  AddCommand('g_max_particles', g_Options_Commands);
-  AddCommand('g_max_shells', g_Options_Commands);
-  AddCommand('g_max_gibs', g_Options_Commands);
-  AddCommand('g_max_corpses', g_Options_Commands);
-  AddCommand('g_item_respawn_time', g_Options_Commands);
+  AddCommand('quit', SystemCommands);
+  AddCommand('exit', SystemCommands);
+  AddCommand('r_reset', SystemCommands);
+  AddCommand('g_language', SystemCommands);
 
   AddCommand('bind', BindCommands);
   AddCommand('bindlist', BindCommands);
@@ -913,12 +1000,10 @@ begin
   AddCommand('p1_model', PlayerSettingsCVars);
   AddCommand('p2_model', PlayerSettingsCVars);
 
-  AddCommand('r_showscore', GameCVars);
-  AddCommand('r_showlives', GameCVars);
-  AddCommand('r_showstat', GameCVars);
-  AddCommand('r_showkillmsg', GameCVars);
-  AddCommand('r_showspect', GameCVars);
-  AddCommand('r_showping', GameCVars);
+  AddCommand('g_max_particles', GameCVars);
+  AddCommand('g_max_shells', GameCVars);
+  AddCommand('g_max_gibs', GameCVars);
+  AddCommand('g_max_corpses', GameCVars);
   AddCommand('g_gamemode', GameCVars);
   AddCommand('g_friendlyfire', GameCVars);
   AddCommand('g_weaponstay', GameCVars);
@@ -930,17 +1015,17 @@ begin
   AddCommand('g_scorelimit', GameCVars);
   AddCommand('g_timelimit', GameCVars);
   AddCommand('g_maxlives', GameCVars);
-  AddCommand('g_warmuptime', GameCVars);
+  AddCommand('g_warmup_time', GameCVars);
   AddCommand('g_spawn_invul', GameCVars);
+  AddCommand('g_item_respawn_time', GameCVars);
   AddCommand('sv_intertime', GameCVars);
 
   AddCommand('sv_name', NetServerCVars);
   AddCommand('sv_passwd', NetServerCVars);
   AddCommand('sv_maxplrs', NetServerCVars);
   AddCommand('sv_public', NetServerCVars);
+  AddCommand('sv_port', NetServerCVars);
 
-  AddCommand('quit', GameCommands);
-  AddCommand('exit', GameCommands);
   AddCommand('pause', GameCommands);
   AddCommand('endgame', GameCommands);
   AddCommand('restart', GameCommands);
@@ -1037,10 +1122,11 @@ begin
   WhitelistCommand('g_timelimit');
   WhitelistCommand('g_dm_keys');
   WhitelistCommand('g_spawn_invul');
-  WhitelistCommand('g_warmuptime');
+  WhitelistCommand('g_item_respawn_time');
+  WhitelistCommand('g_warmup_time');
 
   g_Console_ResetBinds;
-  g_Console_ReadConfig(configScript);
+  g_Console_ReadConfig(gConfigScript);
   g_Console_ReadConfig(autoexecScript);
   gParsingBinds := False;
 end;
@@ -1932,10 +2018,18 @@ end;
 
 procedure g_Console_WriteConfig (filename: String);
   var f: TextFile; i, j: Integer;
+
+  procedure WriteFlag(name: string; flag: LongWord);
+  begin
+    WriteLn(f, name, IfThen(LongBool(gsGameFlags and flag), 1, 0));
+  end;
+
 begin
   AssignFile(f, filename);
   Rewrite(f);
   WriteLn(f, '// ' + configComment);
+
+  // binds
   WriteLn(f, 'unbindall');
   for i := 0 to e_MaxInputKeys - 1 do
     if (Length(gInputBinds[i].down) > 0) or (Length(gInputBinds[i].up) > 0) then
@@ -1947,25 +2041,58 @@ begin
         Write(f, ' ', QuoteStr(GetCommandString(gInputBinds[i].up)));
       WriteLn(f, '');
     end;
+
+  // lang
   if gAskLanguage then
     WriteLn(f, 'g_language ask')
   else
     WriteLn(f, 'g_language ', gLanguage);
+
+  // net server
+  WriteLn(f, 'sv_name ', QuoteStr(NetServerName));
+  WriteLn(f, 'sv_passwd ', QuoteStr(NetPassword));
+  WriteLn(f, 'sv_maxplrs ', NetMaxClients);
+  WriteLn(f, 'sv_port ', NetPort);
+
+  // game settings
   WriteLn(f, 'g_max_particles ', g_GFX_GetMax());
   WriteLn(f, 'g_max_shells ', g_Shells_GetMax());
   WriteLn(f, 'g_max_gibs ', g_Gibs_GetMax());
   WriteLn(f, 'g_max_corpses ', g_Corpses_GetMax());
-  WriteLn(f, 'g_item_respawn_time ', ITEM_RESPAWNTIME div 36);
+  WriteLn(f, 'sv_intertime ', gDefInterTime);
+
+  // gameplay settings
+  WriteLn(f, 'g_gamemode ', gsGameMode);
+  WriteLn(f, 'g_scorelimit ', gsGoalLimit);
+  WriteLn(f, 'g_timelimit ', gsTimeLimit);
+  WriteLn(f, 'g_maxlives ', gsMaxLives);
+  WriteLn(f, 'g_item_respawn_time ', gsItemRespawnTime);
+  WriteLn(f, 'g_spawn_invul ', gsSpawnInvul);
+  WriteLn(f, 'g_warmup_time ', gsWarmupTime);
+
+  WriteFlag('g_friendlyfire ', GAME_OPTION_TEAMDAMAGE);
+  WriteFlag('g_allow_exit ', GAME_OPTION_ALLOWEXIT);
+  WriteFlag('g_allow_monsters ', GAME_OPTION_MONSTERS);
+  WriteFlag('g_dm_keys ', GAME_OPTION_DMKEYS);
+  WriteFlag('g_weaponstay ', GAME_OPTION_WEAPONSTAY);
+  WriteFlag('g_bot_vsmonsters ', GAME_OPTION_BOTVSMONSTER);
+  WriteFlag('g_bot_vsplayers ', GAME_OPTION_BOTVSPLAYER);
+
+  // players
   with gPlayer1Settings do
   begin
     WriteLn(f, 'p1_name ', QuoteStr(Name));
     WriteLn(f, 'p1_color ', Color.R, ' ', Color.G, ' ', Color.B);
+    WriteLn(f, 'p1_model ', QuoteStr(Model));
   end;
   with gPlayer2Settings do
   begin
     WriteLn(f, 'p2_name ', QuoteStr(Name));
     WriteLn(f, 'p2_color ', Color.R, ' ', Color.G, ' ', Color.B);
+    WriteLn(f, 'p2_model ', QuoteStr(Model));
   end;
+
+  // all cvars
   for i := 0 to High(commands) do
   begin
     if not commands[i].cheat then
@@ -1979,6 +2106,14 @@ begin
       begin
         WriteLn(f, commands[i].cmd, ' ', PInteger(commands[i].ptr)^)
       end
+      else if @commands[i].procEx = @wordVarHandler then
+      begin
+        WriteLn(f, commands[i].cmd, ' ', PWord(commands[i].ptr)^)
+      end
+      else if @commands[i].procEx = @dwordVarHandler then
+      begin
+        WriteLn(f, commands[i].cmd, ' ', PCardinal(commands[i].ptr)^)
+      end
       else if @commands[i].procEx = @singleVarHandler then
       begin
         WriteLn(f, commands[i].cmd, ' ', PVarSingle(commands[i].ptr).val^:0:6)
@@ -1992,6 +2127,7 @@ begin
       end
     end
   end;
+
   WriteLn(f, 'r_reset');
   CloseFile(f)
 end;
@@ -2002,7 +2138,7 @@ begin
   if gParsingBinds = false then
   begin
     s := e_GetWriteableDir(ConfigDirs);
-    g_Console_WriteConfig(e_CatPath(s, configScript))
+    g_Console_WriteConfig(e_CatPath(s, gConfigScript))
   end
 end;
 
index 61fed94c851f31560c9bc6bdfb6d45bc2437e90e..4a79f98ebfd67d496271b8ed577b844402f19b2c 100644 (file)
@@ -32,6 +32,7 @@ type
     GoalLimit: Word;
     WarmupTime: Word;
     SpawnInvul: Word;
+    ItemRespawnTime: Word;
     MaxLives: Byte;
     Options: LongWord;
     WAD: String;
@@ -133,6 +134,7 @@ function  g_Game_IsTestMap(): Boolean;
 procedure g_Game_DeleteTestMap();
 procedure GameCVars(P: SSArray);
 procedure PlayerSettingsCVars(P: SSArray);
+procedure SystemCommands(P: SSArray);
 procedure GameCommands(P: SSArray);
 procedure GameCheats(P: SSArray);
 procedure DebugCommands(P: SSArray);
@@ -4625,7 +4627,7 @@ begin
     Exit;
   end;
 
-  g_Net_Slist_Set(NetSlistIP, NetSlistPort, NetSlistList);
+  g_Net_Slist_Set(NetMasterList);
 
   g_Net_Slist_ServerStarted();
 
@@ -5383,64 +5385,61 @@ var
   a, b: Integer;
   stat: TPlayerStatArray;
   cmd: string;
-begin
-  stat := nil;
-  cmd := LowerCase(P[0]);
-  if (cmd = 'g_friendlyfire') and not g_Game_IsClient then
+
+  procedure ParseGameFlag(Flag: LongWord; OffMsg, OnMsg: TStrings_Locale; OnMapChange: Boolean = False);
+  var
+    x: Boolean;
   begin
-    with gGameSettings do
+    if Length(P) > 1 then
     begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
-      begin
-        if (P[1][1] = '1') then
-          Options := Options or GAME_OPTION_TEAMDAMAGE
-        else
-          Options := Options and (not GAME_OPTION_TEAMDAMAGE);
-      end;
+      x := P[1] = '1';
 
-      if (LongBool(Options and GAME_OPTION_TEAMDAMAGE)) then
-        g_Console_Add(_lc[I_MSG_FRIENDLY_FIRE_ON])
+      if x then
+        gsGameFlags := gsGameFlags or Flag
       else
-        g_Console_Add(_lc[I_MSG_FRIENDLY_FIRE_OFF]);
+        gsGameFlags := gsGameFlags and (not Flag);
 
-      if g_Game_IsNet then MH_SEND_GameSettings;
-    end;
-  end
-  else if (cmd = 'g_weaponstay') and not g_Game_IsClient then
-  begin
-    with gGameSettings do
-    begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
+      if g_Game_IsServer then
       begin
-        if (P[1][1] = '1') then
-          Options := Options or GAME_OPTION_WEAPONSTAY
+        if x then
+          gGameSettings.Options := gGameSettings.Options or Flag
         else
-          Options := Options and (not GAME_OPTION_WEAPONSTAY);
+          gGameSettings.Options := gGameSettings.Options and (not Flag);
+        if g_Game_IsNet then MH_SEND_GameSettings;
       end;
+    end;
 
-      if (LongBool(Options and GAME_OPTION_WEAPONSTAY)) then
-        g_Console_Add(_lc[I_MSG_WEAPONSTAY_ON])
-      else
-        g_Console_Add(_lc[I_MSG_WEAPONSTAY_OFF]);
+    if LongBool(gsGameFlags and Flag) then
+      g_Console_Add(_lc[OnMsg])
+    else
+      g_Console_Add(_lc[OffMsg]);
 
-      if g_Game_IsNet then MH_SEND_GameSettings;
-    end;
-  end
-  else if cmd = 'g_gamemode' then
+    if OnMapChange and g_Game_IsServer then
+      g_Console_Add(_lc[I_MSG_ONMAPCHANGE]);
+  end;
+
+begin
+  stat := nil;
+  cmd := LowerCase(P[0]);
+
+  if cmd = 'g_gamemode' then
   begin
-    a := g_Game_TextToMode(P[1]);
-    if a = GM_SINGLE then a := GM_COOP;
-    if (Length(P) > 1) and (a <> GM_NONE) and (not g_Game_IsClient) then
+    if (Length(P) > 1) then
     begin
-      gSwitchGameMode := a;
-      if (gGameOn and (gGameSettings.GameMode = GM_SINGLE)) or
-         (gState = STATE_INTERSINGLE) then
-        gSwitchGameMode := GM_SINGLE;
-      if not gGameOn then
-        gGameSettings.GameMode := gSwitchGameMode;
+      a := g_Game_TextToMode(P[1]);
+      if a = GM_SINGLE then a := GM_COOP;
+      gsGameMode := g_Game_ModeToText(a);
+      if g_Game_IsServer then
+      begin
+        gSwitchGameMode := a;
+        if (gGameOn and (gGameSettings.GameMode = GM_SINGLE)) or
+           (gState = STATE_INTERSINGLE) then
+          gSwitchGameMode := GM_SINGLE;
+        if not gGameOn then
+          gGameSettings.GameMode := gSwitchGameMode;
+      end;
     end;
+
     if gSwitchGameMode = gGameSettings.GameMode then
       g_Console_Add(Format(_lc[I_MSG_GAMEMODE_CURRENT],
                           [g_Game_ModeToText(gGameSettings.GameMode)]))
@@ -5449,140 +5448,91 @@ begin
                           [g_Game_ModeToText(gGameSettings.GameMode),
                            g_Game_ModeToText(gSwitchGameMode)]));
   end
-  else if (cmd = 'g_allow_exit') and not g_Game_IsClient then
+  else if cmd = 'g_friendlyfire' then
   begin
-    with gGameSettings do
-    begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
-      begin
-        if (P[1][1] = '1') then
-          Options := Options or GAME_OPTION_ALLOWEXIT
-        else
-          Options := Options and (not GAME_OPTION_ALLOWEXIT);
-      end;
-
-      if (LongBool(Options and GAME_OPTION_ALLOWEXIT)) then
-        g_Console_Add(_lc[I_MSG_ALLOWEXIT_ON])
-      else
-        g_Console_Add(_lc[I_MSG_ALLOWEXIT_OFF]);
-      g_Console_Add(_lc[I_MSG_ONMAPCHANGE]);
-
-      if g_Game_IsNet then MH_SEND_GameSettings;
-    end;
+    ParseGameFlag(GAME_OPTION_TEAMDAMAGE, I_MSG_FRIENDLY_FIRE_OFF, I_MSG_FRIENDLY_FIRE_ON);
   end
-  else if (cmd = 'g_allow_monsters') and not g_Game_IsClient then
+  else if cmd = 'g_weaponstay' then
   begin
-    with gGameSettings do
-    begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
-      begin
-        if (P[1][1] = '1') then
-          Options := Options or GAME_OPTION_MONSTERS
-        else
-          Options := Options and (not GAME_OPTION_MONSTERS);
-      end;
-
-      if (LongBool(Options and GAME_OPTION_MONSTERS)) then
-        g_Console_Add(_lc[I_MSG_ALLOWMON_ON])
-      else
-        g_Console_Add(_lc[I_MSG_ALLOWMON_OFF]);
-      g_Console_Add(_lc[I_MSG_ONMAPCHANGE]);
-
-      if g_Game_IsNet then MH_SEND_GameSettings;
-    end;
+    ParseGameFlag(GAME_OPTION_WEAPONSTAY, I_MSG_WEAPONSTAY_OFF, I_MSG_WEAPONSTAY_ON);
   end
-  else if (cmd = 'g_bot_vsplayers') and not g_Game_IsClient then
+  else if cmd = 'g_allow_exit' then
   begin
-    with gGameSettings do
-    begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
-      begin
-        if (P[1][1] = '1') then
-          Options := Options or GAME_OPTION_BOTVSPLAYER
-        else
-          Options := Options and (not GAME_OPTION_BOTVSPLAYER);
-      end;
-
-      if (LongBool(Options and GAME_OPTION_BOTVSPLAYER)) then
-        g_Console_Add(_lc[I_MSG_BOTSVSPLAYERS_ON])
-      else
-        g_Console_Add(_lc[I_MSG_BOTSVSPLAYERS_OFF]);
-
-      if g_Game_IsNet then MH_SEND_GameSettings;
-    end;
+    ParseGameFlag(GAME_OPTION_ALLOWEXIT, I_MSG_ALLOWEXIT_OFF, I_MSG_ALLOWEXIT_ON, True);
+  end
+  else if cmd = 'g_allow_monsters' then
+  begin
+    ParseGameFlag(GAME_OPTION_MONSTERS, I_MSG_ALLOWMON_OFF, I_MSG_ALLOWMON_ON, True);
   end
-  else if (cmd = 'g_bot_vsmonsters') and not g_Game_IsClient then
+  else if cmd = 'g_bot_vsplayers' then
   begin
-    with gGameSettings do
+    ParseGameFlag(GAME_OPTION_BOTVSPLAYER, I_MSG_BOTSVSPLAYERS_OFF, I_MSG_BOTSVSPLAYERS_ON);
+  end
+  else if cmd = 'g_bot_vsmonsters' then
+  begin
+    ParseGameFlag(GAME_OPTION_BOTVSMONSTER, I_MSG_BOTSVSMONSTERS_OFF, I_MSG_BOTSVSMONSTERS_ON);
+  end
+  else if cmd = 'g_dm_keys' then
+  begin
+    ParseGameFlag(GAME_OPTION_DMKEYS, I_MSG_DMKEYS_OFF, I_MSG_DMKEYS_ON, True);
+  end
+  else if cmd = 'g_gameflags' then
+  begin
+    if Length(P) > 1 then
     begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
+      gsGameFlags := StrToDWordDef(P[1], gsGameFlags);
+      if g_Game_IsServer then
       begin
-        if (P[1][1] = '1') then
-          Options := Options or GAME_OPTION_BOTVSMONSTER
-        else
-          Options := Options and (not GAME_OPTION_BOTVSMONSTER);
+        gGameSettings.Options := gsGameFlags;
+        if g_Game_IsNet then MH_SEND_GameSettings;
       end;
-
-      if (LongBool(Options and GAME_OPTION_BOTVSMONSTER)) then
-        g_Console_Add(_lc[I_MSG_BOTSVSMONSTERS_ON])
-      else
-        g_Console_Add(_lc[I_MSG_BOTSVSMONSTERS_OFF]);
-
-      if g_Game_IsNet then MH_SEND_GameSettings;
     end;
+
+    g_Console_Add(Format('%s %u', [cmd, gsGameFlags]));
   end
-  else if (cmd = 'g_dm_keys') and not g_Game_IsClient then
+  else if cmd = 'g_warmup_time' then
   begin
-    with gGameSettings do
+    if Length(P) > 1 then
     begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
+      gsWarmupTime := nclamp(StrToIntDef(P[1], gsWarmupTime), 0, $FFFF);
+      if g_Game_IsServer then
       begin
-        if (P[1][1] = '1') then
-          Options := Options or GAME_OPTION_DMKEYS
-        else
-          Options := Options and (not GAME_OPTION_DMKEYS);
+        gGameSettings.WarmupTime := gsWarmupTime;
+        if g_Game_IsNet then MH_SEND_GameSettings;
       end;
-
-      if (LongBool(Options and GAME_OPTION_DMKEYS)) then
-        g_Console_Add(_lc[I_MSG_DMKEYS_ON])
-      else
-        g_Console_Add(_lc[I_MSG_DMKEYS_OFF]);
-
-      if g_Game_IsNet then MH_SEND_GameSettings;
     end;
+
+    g_Console_Add(Format(_lc[I_MSG_WARMUP], [Integer(gsWarmupTime)]));
+    if g_Game_IsServer then g_Console_Add(_lc[I_MSG_ONMAPCHANGE]);
   end
-  else if (cmd = 'g_warmuptime') and not g_Game_IsClient then
+  else if cmd = 'g_spawn_invul' then
   begin
     if Length(P) > 1 then
     begin
-      if StrToIntDef(P[1], gGameSettings.WarmupTime) = 0 then
-        gGameSettings.WarmupTime := 30
-      else
-        gGameSettings.WarmupTime := StrToIntDef(P[1], gGameSettings.WarmupTime);
+      gsSpawnInvul := nclamp(StrToIntDef(P[1], gsSpawnInvul), 0, $FFFF);
+      if g_Game_IsServer then
+      begin
+        gGameSettings.SpawnInvul := gsSpawnInvul;
+        if g_Game_IsNet then MH_SEND_GameSettings;
+      end;
     end;
 
-    g_Console_Add(Format(_lc[I_MSG_WARMUP],
-                 [gGameSettings.WarmupTime]));
-    g_Console_Add(_lc[I_MSG_ONMAPCHANGE]);
+    g_Console_Add(Format('%s %d', [cmd, Integer(gsSpawnInvul)]));
   end
-  else if (cmd = 'g_spawn_invul') and not g_Game_IsClient then
+  else if cmd = 'g_item_respawn_time' then
   begin
     if Length(P) > 1 then
     begin
-      if StrToIntDef(P[1], gGameSettings.SpawnInvul) = 0 then
-        gGameSettings.SpawnInvul := 0
-      else
-        gGameSettings.SpawnInvul := StrToIntDef(P[1], gGameSettings.SpawnInvul);
+      gsItemRespawnTime := nclamp(StrToIntDef(P[1], gsItemRespawnTime), 0, $FFFF);
+      if g_Game_IsServer then
+      begin
+        gGameSettings.ItemRespawnTime := gsItemRespawnTime;
+        if g_Game_IsNet then MH_SEND_GameSettings;
+      end;
     end;
 
-    g_Console_Add(Format(_lc[I_MSG_SPAWNINVUL],
-                 [gGameSettings.SpawnInvul]));
-    g_Console_Add(_lc[I_MSG_ONMAPCHANGE]);
+    g_Console_Add(Format('%s %d', [cmd, Integer(gsItemRespawnTime)]));
+    if g_Game_IsServer then g_Console_Add(_lc[I_MSG_ONMAPCHANGE]);
   end
   else if cmd = 'sv_intertime' then
   begin
@@ -5591,134 +5541,129 @@ begin
 
     g_Console_Add(cmd + ' = ' + IntToStr(gDefInterTime));
   end
-  else if cmd = 'r_showscore' then
-  begin
-    if (Length(P) > 1) and
-       ((P[1] = '1') or (P[1] = '0')) then
-      gShowGoals := (P[1][1] = '1');
-
-    if gShowGoals then
-      g_Console_Add(_lc[I_MSG_SCORE_ON])
-    else
-      g_Console_Add(_lc[I_MSG_SCORE_OFF]);
-  end
-  else if cmd = 'r_showstat' then
-  begin
-    if (Length(P) > 1) and
-       ((P[1] = '1') or (P[1] = '0')) then
-      gShowStat := (P[1][1] = '1');
-
-    if gShowStat then
-      g_Console_Add(_lc[I_MSG_STATS_ON])
-    else
-      g_Console_Add(_lc[I_MSG_STATS_OFF]);
-  end
-  else if cmd = 'r_showkillmsg' then
+  else if cmd = 'g_max_particles' then
   begin
-    if (Length(P) > 1) and
-       ((P[1] = '1') or (P[1] = '0')) then
-      gShowKillMsg := (P[1][1] = '1');
-
-    if gShowKillMsg then
-      g_Console_Add(_lc[I_MSG_KILL_MSGS_ON])
+    if Length(p) = 2 then
+    begin
+      a := Max(0, StrToInt(p[1]));
+      g_GFX_SetMax(a)
+    end
+    else if Length(p) = 1 then
+    begin
+      e_LogWritefln('%s', [g_GFX_GetMax()])
+    end
     else
-      g_Console_Add(_lc[I_MSG_KILL_MSGS_OFF]);
+    begin
+      e_LogWritefln('usage: %s <n>', [cmd])
+    end
   end
-  else if cmd = 'r_showlives' then
+  else if cmd = 'g_max_shells' then
   begin
-    if (Length(P) > 1) and
-       ((P[1] = '1') or (P[1] = '0')) then
-      gShowLives := (P[1][1] = '1');
-
-    if gShowLives then
-      g_Console_Add(_lc[I_MSG_LIVES_ON])
+    if Length(p) = 2 then
+    begin
+      a := Max(0, StrToInt(p[1]));
+      g_Shells_SetMax(a)
+    end
+    else if Length(p) = 1 then
+    begin
+      e_LogWritefln('%s', [g_Shells_GetMax()])
+    end
     else
-      g_Console_Add(_lc[I_MSG_LIVES_OFF]);
+    begin
+      e_LogWritefln('usage: %s <n>', [cmd])
+    end
   end
-  else if cmd = 'r_showspect' then
+  else if cmd = 'g_max_gibs' then
   begin
-    if (Length(P) > 1) and
-       ((P[1] = '1') or (P[1] = '0')) then
-      gSpectHUD := (P[1][1] = '1');
-
-    if gSpectHUD then
-      g_Console_Add(_lc[I_MSG_SPECT_HUD_ON])
+    if Length(p) = 2 then
+    begin
+      a := Max(0, StrToInt(p[1]));
+      g_Gibs_SetMax(a)
+    end
+    else if Length(p) = 1 then
+    begin
+      e_LogWritefln('%s', [g_Gibs_GetMax()])
+    end
     else
-      g_Console_Add(_lc[I_MSG_SPECT_HUD_OFF]);
+    begin
+      e_LogWritefln('usage: %s <n>', [cmd])
+    end
   end
-  else if cmd = 'r_showping' then
+  else if cmd = 'g_max_corpses' then
   begin
-    if (Length(P) > 1) and
-       ((P[1] = '1') or (P[1] = '0')) then
-      gShowPing := (P[1][1] = '1');
-
-    if gShowPing then
-      g_Console_Add(_lc[I_MSG_PING_ON])
+    if Length(p) = 2 then
+    begin
+      a := Max(0, StrToInt(p[1]));
+      g_Corpses_SetMax(a)
+    end
+    else if Length(p) = 1 then
+    begin
+      e_LogWritefln('%s', [g_Corpses_GetMax()])
+    end
     else
-      g_Console_Add(_lc[I_MSG_PING_OFF]);
+    begin
+      e_LogWritefln('usage: %s <n>', [cmd])
+    end
   end
-  else if (cmd = 'g_scorelimit') and not g_Game_IsClient then
+  else if cmd = 'g_scorelimit' then
   begin
     if Length(P) > 1 then
     begin
-      if StrToIntDef(P[1], gGameSettings.GoalLimit) = 0 then
-        gGameSettings.GoalLimit := 0
-      else
-        begin
-          b := 0;
-
-          if gGameSettings.GameMode = GM_DM then
-            begin // DM
-              stat := g_Player_GetStats();
-              if stat <> nil then
-                for a := 0 to High(stat) do
-                  if stat[a].Frags > b then
-                    b := stat[a].Frags;
-            end
-          else // TDM/CTF
-            b := Max(gTeamStat[TEAM_RED].Goals, gTeamStat[TEAM_BLUE].Goals);
+      gsGoalLimit := nclamp(StrToIntDef(P[1], gsGoalLimit), 0, $FFFF);
 
-          gGameSettings.GoalLimit := Max(StrToIntDef(P[1], gGameSettings.GoalLimit), b);
-        end;
-
-      if g_Game_IsNet then MH_SEND_GameSettings;
+      if g_Game_IsServer then
+      begin
+        b := 0;
+        if gGameSettings.GameMode = GM_DM then
+        begin // DM
+          stat := g_Player_GetStats();
+          if stat <> nil then
+            for a := 0 to High(stat) do
+              if stat[a].Frags > b then
+                b := stat[a].Frags;
+        end
+        else // TDM/CTF
+          b := Max(gTeamStat[TEAM_RED].Goals, gTeamStat[TEAM_BLUE].Goals);
+
+        // if someone has a higher score, set it to that instead
+        gsGoalLimit := max(gsGoalLimit, b);
+        gGameSettings.GoalLimit := gsGoalLimit;
+        if g_Game_IsNet then MH_SEND_GameSettings;
+      end;
     end;
 
-    g_Console_Add(Format(_lc[I_MSG_SCORE_LIMIT], [gGameSettings.GoalLimit]));
+    g_Console_Add(Format(_lc[I_MSG_SCORE_LIMIT], [Integer(gsGoalLimit)]));
   end
-  else if (cmd = 'g_timelimit') and not g_Game_IsClient then
+  else if cmd = 'g_timelimit' then
   begin
-    if (Length(P) > 1) and (StrToIntDef(P[1], -1) >= 0) then
-      gGameSettings.TimeLimit := StrToIntDef(P[1], -1);
-
+    if Length(P) > 1 then
+    begin
+      gsTimeLimit := nclamp(StrToIntDef(P[1], gsTimeLimit), 0, $FFFF);
+      if g_Game_IsServer then
+      begin
+        gGameSettings.TimeLimit := gsTimeLimit;
+        if g_Game_IsNet then MH_SEND_GameSettings;
+      end;
+    end;
     g_Console_Add(Format(_lc[I_MSG_TIME_LIMIT],
-                         [gGameSettings.TimeLimit div 3600,
-                         (gGameSettings.TimeLimit div 60) mod 60,
-                          gGameSettings.TimeLimit mod 60]));
-    if g_Game_IsNet then MH_SEND_GameSettings;
+                         [gsTimeLimit div 3600,
+                         (gsTimeLimit div 60) mod 60,
+                          gsTimeLimit mod 60]));
   end
-  else if (cmd = 'g_maxlives') and not g_Game_IsClient then
+  else if cmd = 'g_maxlives' then
   begin
     if Length(P) > 1 then
     begin
-      if StrToIntDef(P[1], gGameSettings.MaxLives) = 0 then
-        gGameSettings.MaxLives := 0
-      else
+      gsMaxLives := nclamp(StrToIntDef(P[1], gsMaxLives), 0, $FFFF);
+      if g_Game_IsServer then
       begin
-        b := 0;
-        stat := g_Player_GetStats();
-        if stat <> nil then
-          for a := 0 to High(stat) do
-            if stat[a].Lives > b then
-              b := stat[a].Lives;
-        gGameSettings.MaxLives :=
-          Max(StrToIntDef(P[1], gGameSettings.MaxLives), b);
+        gGameSettings.MaxLives := gsMaxLives;
+        if g_Game_IsNet then MH_SEND_GameSettings;
       end;
     end;
 
-    g_Console_Add(Format(_lc[I_MSG_LIVES],
-                         [gGameSettings.MaxLives]));
-    if g_Game_IsNet then MH_SEND_GameSettings;
+    g_Console_Add(Format(_lc[I_MSG_LIVES], [Integer(gsMaxLives)]));
   end;
 end;
 
@@ -6194,14 +6139,7 @@ begin
 // Îáùèå êîìàíäû:
   cmd := LowerCase(P[0]);
   chstr := '';
-  if (cmd = 'quit') or
-     (cmd = 'exit') then
-  begin
-    g_Game_Free();
-    g_Game_Quit();
-    Exit;
-  end
-  else if cmd = 'pause' then
+  if cmd = 'pause' then
   begin
     if (g_ActiveWindow = nil) then
       g_Game_Pause(not gPauseMain);
@@ -6620,7 +6558,7 @@ begin
         g_Game_Free();
         with gGameSettings do
         begin
-          GameMode := g_Game_TextToMode(gcGameMode);
+          GameMode := g_Game_TextToMode(gsGameMode);
           if gSwitchGameMode <> GM_NONE then
             GameMode := gSwitchGameMode;
           if GameMode = GM_NONE then GameMode := GM_DM;
@@ -6674,7 +6612,7 @@ begin
         g_Game_Free();
         with gGameSettings do
         begin
-          GameMode := g_Game_TextToMode(gcGameMode);
+          GameMode := g_Game_TextToMode(gsGameMode);
           if gSwitchGameMode <> GM_NONE then GameMode := gSwitchGameMode;
           if GameMode = GM_NONE then GameMode := GM_DM;
           if GameMode = GM_SINGLE then GameMode := GM_COOP;
@@ -7251,6 +7189,61 @@ begin
   end;
 end;
 
+procedure SystemCommands(P: SSArray);
+var
+  cmd: string;
+begin
+  cmd := LowerCase(P[0]);
+  case cmd of
+    'exit', 'quit':
+      begin
+        g_Game_Free();
+        g_Game_Quit();
+      end;
+    'r_reset':
+      begin
+        sys_EnableVSync(gVSync);
+        gRC_Width := Max(1, gRC_Width);
+        gRC_Height := Max(1, gRC_Height);
+        gBPP := Max(1, gBPP);
+        if sys_SetDisplayMode(gRC_Width, gRC_Height, gBPP, gRC_FullScreen, gRC_Maximized) = True then
+          e_LogWriteln('resolution changed')
+        else
+          e_LogWriteln('resolution not changed');
+      end;
+    'g_language':
+      begin
+        if Length(p) = 2 then
+        begin
+          gAskLanguage := true;
+          gLanguage := LANGUAGE_ENGLISH;
+          case LowerCase(p[1]) of
+            'english':
+               begin
+                 gAskLanguage := false;
+                 gLanguage := LANGUAGE_ENGLISH;
+               end;
+            'russian':
+               begin
+                 gAskLanguage := false;
+                 gLanguage := LANGUAGE_RUSSIAN;
+               end;
+            'ask':
+               begin
+                 gAskLanguage := true;
+                 gLanguage := LANGUAGE_ENGLISH;
+               end;
+          end;
+          g_Language_Set(gLanguage);
+        end
+        else
+        begin
+          e_LogWritefln('usage: %s <English|Russian|Ask>', [cmd]);
+        end
+      end;
+  end;
+end;
+
 procedure g_TakeScreenShot(Filename: string = '');
   var s: TStream; t: TDateTime; dir, date, name: String;
 begin
@@ -7941,11 +7934,10 @@ begin
   // Options:
     s := Find_Param_Value(pars, '-opt');
     if (s = '') then
-      Opt := GAME_OPTION_ALLOWEXIT or GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER
+      Opt := GAME_OPTION_ALLOWEXIT or GAME_OPTION_BOTVSPLAYER or
+        GAME_OPTION_BOTVSMONSTER or GAME_OPTION_DMKEYS
     else
       Opt := StrToIntDef(s, 0);
-    if Opt = 0 then
-      Opt := GAME_OPTION_ALLOWEXIT or GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER;
 
   // Close after map:
     s := Find_Param_Value(pars, '--close');
@@ -8068,4 +8060,10 @@ begin
 
   conRegVar('r_showfps', @gShowFPS, 'draw fps counter', 'draw fps counter');
   conRegVar('r_showtime', @gShowTime, 'show game time', 'show game time');
+  conRegVar('r_showping', @gShowPing, 'show ping', 'show ping');
+  conRegVar('r_showscore', @gShowGoals, 'show score', 'show score');
+  conRegVar('r_showkillmsg', @gShowKillMsg, 'show kill log', 'show kill log');
+  conRegVar('r_showlives', @gShowLives, 'show lives', 'show lives');
+  conRegVar('r_showspect', @gSpectHUD, 'show spectator hud', 'show spectator hud');
+  conRegVar('r_showstat', @gShowStat, 'show stats', 'show stats');
 end.
index 9693ad07f31270f0d4e691a33ebcd66de8cbe04d..200ebdd96cf725a2bc486d043e66bfce96ce46e4 100644 (file)
@@ -83,7 +83,6 @@ function g_Items_ForEachAlive (cb: TItemEachAliveCB; backwards: Boolean=false):
 var
   gItemsTexturesID: Array [1..ITEM_MAX] of DWORD;
   gMaxDist: Integer = 1; // for sounds
-  ITEM_RESPAWNTIME: Integer = 60 * 36;
 
 implementation
 
@@ -576,7 +575,7 @@ begin
               // Íàäî óáðàòü ñ êàðòû, åñëè ýòî íå êëþ÷, êîòîðûì íóæíî ïîäåëèòüñÿ ñ äðóãèì èãðîêîì
               if r then
               begin
-                if not (Respawnable and (ITEM_RESPAWNTIME > 0)) then
+                if not (Respawnable and (gGameSettings.ItemRespawnTime > 0)) then
                   g_Items_Remove(i)
                 else 
                   g_Items_Pick(i);
@@ -692,7 +691,7 @@ begin
   if (ID < Length(ggItems)) then
   begin
     ggItems[ID].alive := false;
-    ggItems[ID].RespawnTime := ITEM_RESPAWNTIME;
+    ggItems[ID].RespawnTime := gGameSettings.ItemRespawnTime * 36;
   end;
 end;
 
index 8d5ea098ae9488b74e9b9737620127b330bf391a..e17b4c2420bad2b24c77bc48966fa6c511f15353 100644 (file)
@@ -611,6 +611,7 @@ type
     I_MSG_NOT_DEBUG,
     I_MSG_GM_UNAVAIL,
     I_MSG_SERVERONLY,
+    I_MSG_NOT_NETGAME,
     I_MSG_NOCLIENTS,
     I_MSG_UNBAN_OK,
     I_MSG_UNBAN_FAIL,
@@ -1773,14 +1774,16 @@ const
                                        'Ñëåäóþùàÿ êàðòà íå çàäàíà.'),
     ('MSG ONMAPCHANGE',                '* Changes to this variable will be applied upon next map change',
                                        '* Èçìåíåíèÿ âñòóïÿò â ñèëó ïîñëå ñëåäóþùåé ñìåíû êàðòû'),
-    ('MSG NOT GAME',                   'Command can be accepted in a game only.',
+    ('MSG NOT GAME',                   'This command is only available in-game.',
                                        'Êîìàíäà ïðèìåíèìà òîëüêî â èãðå.'),
-    ('MSG NOT DEBUG',                  'Command can be accepted in debug mode only.',
+    ('MSG NOT DEBUG',                  'This command is only available in debug mode.',
                                        'Êîìàíäà ïðèìåíèìà òîëüêî â ðåæèìå îòëàäêè.'),
     ('MSG GM UNAVAIL',                 'This command is unavailable in the current game mode.',
-                                       'Ýòà êîìàíäà íåäîñòóïíà â òåêóùåì ðåæèìå èãðû.'),
-    ('MSG SERVERONLY',                 'This command is for server only.',
-                                       'Ýòà êîìàíäà äîñòóïíà òîëüêî â ðåæèìå ñåðâåðà.'),
+                                       'Êîìàíäà íåäîñòóïíà â òåêóùåì ðåæèìå èãðû.'),
+    ('MSG SERVERONLY',                 'This command is only available to servers.',
+                                       'Êîìàíäà äîñòóïíà òîëüêî â ðåæèìå ñåðâåðà.'),
+    ('MSG NOT NETGAME',                'This command is unavailable during a net game.',
+                                       'Êîìàíäà íåäîñòóïíà âî âðåìÿ ñåòåâîé èãðû.'),
     ('MSG NOCLIENTS',                  'No clients connected.',
                                        'Íåò ïîäêëþ÷¸ííûõ êëèåíòîâ.'),
     ('MSG UNBAN OK',                   'Client %s was unbanned.',
index ab6e1d8498b9de28c655539f2bf4c985c8a1a8c7..20419ecc0299fcfc9ae8b4fc982f8f77ff58bcf1 100644 (file)
@@ -372,6 +372,11 @@ begin
         Inc(i);
         GameWADName := ParamStr(i);
       end;
+    '--config':
+      begin
+        Inc(i);
+        gConfigScript := ParamStr(i);
+      end;
     end;
     Inc(i)
   end;
@@ -502,7 +507,6 @@ procedure Main();
 {$IFDEF ENABLE_HOLMES}
   var flexloaded: Boolean;
 {$ENDIF}
-  var s: AnsiString;
 begin
   InitPath;
   InitPrep;
@@ -511,9 +515,6 @@ begin
 
   g_Options_SetDefault;
   g_Options_SetDefaultVideo;
-  s := CONFIG_FILENAME;
-  if e_FindResource(ConfigDirs, s) = true then
-    g_Options_Read(s);
   g_Console_SysInit;
   if sys_SetDisplayMode(gRC_Width, gRC_Height, gBPP, gRC_FullScreen, gRC_Maximized) = False then
     raise Exception.Create('Failed to set videomode on startup.');
index 9f7aaaa4c53ea09180d2972a0f3c4428dba66fa5..b29a5137c4ff173c7e67b41bac7359d980736c76 100644 (file)
@@ -109,7 +109,6 @@ var
   menu: TGUIMenu;
   i: Integer;
   ovs: Boolean;
-  s: AnsiString;
 begin
   menu := TGUIMenu(g_GUI_GetWindow('OptionsVideoMenu').GetControl('mOptionsVideoMenu'));
 
@@ -376,9 +375,6 @@ begin
 
   if g_Game_IsClient then MC_SEND_PlayerSettings;
 
-  s := e_GetWriteableDir(ConfigDirs);
-  if s <> '' then
-    g_Options_Write(s + '/' + CONFIG_FILENAME);
   g_Console_WriteGameConfig;
 end;
 
@@ -646,14 +642,13 @@ begin
     }
 end;
 
-procedure ProcStartCustomGame();
+function LatchGameOptions(const MenuName: string): Byte;
 var
-  Map: String;
-  GameMode: Byte;
-  Options: LongWord;
-  s: AnsiString;
+  Map: string;
 begin
-  with TGUIMenu(g_ActiveWindow.GetControl('mCustomGameMenu')) do
+  Result := GM_NONE;
+
+  with TGUIMenu(g_ActiveWindow.GetControl(MenuName)) do
   begin
     Map := TGUILabel(GetControl('lbMap')).Text;
     if Map = '' then
@@ -661,113 +656,60 @@ begin
     if not isWadPath(Map) then
       Exit;
 
-    GameMode := TGUISwitch(GetControl('swGameMode')).ItemIndex+1;
-    gcGameMode := TGUISwitch(GetControl('swGameMode')).GetText;
-    gcTimeLimit := StrToIntDef(TGUIEdit(GetControl('edTimeLimit')).Text, 0);
-    gcGoalLimit := StrToIntDef(TGUIEdit(GetControl('edGoalLimit')).Text, 0);
-    gcMaxLives := StrToIntDef(TGUIEdit(GetControl('edMaxLives')).Text, 0);
-
-    gcTeamDamage := TGUISwitch(GetControl('swTeamDamage')).ItemIndex = 0;
-    gcDeathmatchKeys := TGUISwitch(GetControl('swDeathmatchKeys')).ItemIndex = 0;
-    gcAllowExit := TGUISwitch(GetControl('swEnableExits')).ItemIndex = 0;
-    gcWeaponStay := TGUISwitch(GetControl('swWeaponStay')).ItemIndex = 0;
-    gcMonsters := TGUISwitch(GetControl('swMonsters')).ItemIndex = 0;
-    Options := 0;
-    if gcTeamDamage then
-      Options := Options or GAME_OPTION_TEAMDAMAGE;
-    if gcDeathmatchKeys then
-      Options := Options or GAME_OPTION_DMKEYS;
-    if gcAllowExit then
-      Options := Options or GAME_OPTION_ALLOWEXIT;
-    if gcWeaponStay then
-      Options := Options or GAME_OPTION_WEAPONSTAY;
-    if gcMonsters then
-      Options := Options or GAME_OPTION_MONSTERS;
-    gcPlayers := TGUISwitch(GetControl('swPlayers')).ItemIndex;
+    Result := TGUISwitch(GetControl('swGameMode')).ItemIndex+1;
+    gsGameMode := TGUISwitch(GetControl('swGameMode')).GetText;
+    gsTimeLimit := StrToIntDef(TGUIEdit(GetControl('edTimeLimit')).Text, 0);
+    gsGoalLimit := StrToIntDef(TGUIEdit(GetControl('edGoalLimit')).Text, 0);
+    gsMaxLives := StrToIntDef(TGUIEdit(GetControl('edMaxLives')).Text, 0);
+    gsItemRespawnTime := StrToIntDef(TGUIEdit(GetControl('edItemRespawnTime')).Text, 0);
+    gsPlayers := TGUISwitch(GetControl('swPlayers')).ItemIndex;
+    gsMap := Map;
+
+    gsGameFlags := 0;
+    if TGUISwitch(GetControl('swTeamDamage')).ItemIndex = 0 then
+      gsGameFlags := gsGameFlags or GAME_OPTION_TEAMDAMAGE;
+    if TGUISwitch(GetControl('swDeathmatchKeys')).ItemIndex = 0 then
+      gsGameFlags := gsGameFlags or GAME_OPTION_DMKEYS;
+    if TGUISwitch(GetControl('swEnableExits')).ItemIndex = 0 then
+      gsGameFlags := gsGameFlags or GAME_OPTION_ALLOWEXIT;
+    if TGUISwitch(GetControl('swWeaponStay')).ItemIndex = 0 then
+      gsGameFlags := gsGameFlags or GAME_OPTION_WEAPONSTAY;
+    if TGUISwitch(GetControl('swMonsters')).ItemIndex = 0 then
+      gsGameFlags := gsGameFlags or GAME_OPTION_MONSTERS;
 
     case TGUISwitch(GetControl('swBotsVS')).ItemIndex of
-      1: begin
-        Options := Options or GAME_OPTION_BOTVSMONSTER;
-        gcBotsVS := 'Monsters';
-      end;
-      2: begin
-        Options := Options or GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER;
-        gcBotsVS := 'Everybody';
-      end;
-      else begin
-        Options := Options or GAME_OPTION_BOTVSPLAYER;
-        gcBotsVS := 'Players';
-      end;
+      1: gsGameFlags := gsGameFlags or GAME_OPTION_BOTVSMONSTER;
+      2: gsGameFlags := gsGameFlags or GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER;
+      else gsGameFlags := gsGameFlags or GAME_OPTION_BOTVSPLAYER;
     end;
 
-    gcMap := Map;
+    gGameSettings.ItemRespawnTime := gsItemRespawnTime; // TODO: get this crap out of here
   end;
+end;
 
-  s := e_GetWriteableDir(ConfigDirs);
-  if s <> '' then
-    g_Options_Write_Gameplay_Custom(s + '/' + CONFIG_FILENAME);
+procedure ProcStartCustomGame();
+var
+  GameMode: Byte;
+begin
+  GameMode := LatchGameOptions('mCustomGameMenu');
+  if GameMode = GM_NONE then Exit;
 
-  g_Game_StartCustom(Map, GameMode, gcTimeLimit, gcGoalLimit,
-                     gcMaxLives, Options, gcPlayers);
+  g_Console_WriteGameConfig;
+  g_Game_StartCustom(gsMap, GameMode, gsTimeLimit, gsGoalLimit,
+                     gsMaxLives, gsGameFlags, gsPlayers);
 end;
 
 
 procedure ProcStartNetGame();
 var
-  Map: String;
   GameMode: Byte;
-  Options: LongWord;
-  s: AnsiString;
 begin
+  GameMode := LatchGameOptions('mNetServerMenu');
+  if GameMode = GM_NONE then Exit;
+
   with TGUIMenu(g_ActiveWindow.GetControl('mNetServerMenu')) do
   begin
-    Map := TGUILabel(GetControl('lbMap')).Text;
-    if Map = '' then
-      Exit;
-    if not isWadPath(Map) then
-      Exit;
-
-    GameMode := TGUISwitch(GetControl('swGameMode')).ItemIndex+1;
-    gnGameMode := TGUISwitch(GetControl('swGameMode')).GetText;
-    gnTimeLimit := StrToIntDef(TGUIEdit(GetControl('edTimeLimit')).Text, 0);
-    gnGoalLimit := StrToIntDef(TGUIEdit(GetControl('edGoalLimit')).Text, 0);
-    gnMaxLives := StrToIntDef(TGUIEdit(GetControl('edMaxLives')).Text, 0);
     NetPort := StrToIntDef(TGUIEdit(GetControl('edPort')).Text, 0);
-
-    gnTeamDamage := TGUISwitch(GetControl('swTeamDamage')).ItemIndex = 0;
-    gnDeathmatchKeys := TGUISwitch(GetControl('swDeathmatchKeys')).ItemIndex = 0;
-    gnAllowExit := TGUISwitch(GetControl('swEnableExits')).ItemIndex = 0;
-    gnWeaponStay := TGUISwitch(GetControl('swWeaponStay')).ItemIndex = 0;
-    gnMonsters := TGUISwitch(GetControl('swMonsters')).ItemIndex = 0;
-    Options := 0;
-    if gnTeamDamage then
-      Options := Options or GAME_OPTION_TEAMDAMAGE;
-    if gnDeathmatchKeys then
-      Options := Options or GAME_OPTION_DMKEYS;
-    if gnAllowExit then
-      Options := Options or GAME_OPTION_ALLOWEXIT;
-    if gnWeaponStay then
-      Options := Options or GAME_OPTION_WEAPONSTAY;
-    if gnMonsters then
-      Options := Options or GAME_OPTION_MONSTERS;
-    gnPlayers := TGUISwitch(GetControl('swPlayers')).ItemIndex;
-
-    case TGUISwitch(GetControl('swBotsVS')).ItemIndex of
-      1: begin
-        Options := Options or GAME_OPTION_BOTVSMONSTER;
-        gnBotsVS := 'Monsters';
-      end;
-      2: begin
-        Options := Options or GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER;
-        gnBotsVS := 'Everybody';
-      end;
-      else begin
-        Options := Options or GAME_OPTION_BOTVSPLAYER;
-        gnBotsVS := 'Players';
-      end;
-    end;
-
-    gnMap := Map;
     NetServerName := TGUIEdit(GetControl('edSrvName')).Text;
     NetMaxClients := Max(1, StrToIntDef(TGUIEdit(GetControl('edMaxPlayers')).Text, 1));
     NetMaxClients := Min(NET_MAXCLIENTS, NetMaxClients);
@@ -775,21 +717,14 @@ begin
     NetUseMaster := TGUISwitch(GetControl('swUseMaster')).ItemIndex = 0;
   end;
 
-  s := e_GetWriteableDir(ConfigDirs);
-  if s <> '' then
-  begin
-    g_Options_Write_Net_Server(s + '/' + CONFIG_FILENAME);
-    g_Options_Write_Gameplay_Net(s + '/' + CONFIG_FILENAME)
-  end;
-
-  g_Game_StartServer(Map, GameMode, gnTimeLimit, gnGoalLimit, gnMaxLives,
-                     Options, gnPlayers, 0, NetPort);
+  g_Console_WriteGameConfig;
+  g_Game_StartServer(gsMap, GameMode, gsTimeLimit, gsGoalLimit, gsMaxLives,
+                     gsGameFlags, gsPlayers, 0, NetPort);
 end;
 
 procedure ProcConnectNetGame();
 var
   PW: String;
-  s: AnsiString;
 begin
   with TGUIMenu(g_ActiveWindow.GetControl('mNetClientMenu')) do
   begin
@@ -798,16 +733,13 @@ begin
     PW := TGUIEdit(GetControl('edPW')).Text;
   end;
 
-  s := e_GetWriteableDir(ConfigDirs);
-  if s <> '' then
-    g_Options_Write_Net_Client(s + '/' + CONFIG_FILENAME);
+  g_Console_WriteGameConfig;
   g_Game_StartClient(NetClientIP, NetClientPort, PW);
 end;
 
 procedure ProcEnterPassword();
 var
   PW: string;
-  s: AnsiString;
 begin
   with TGUIMenu(g_ActiveWindow.GetControl('mClientPasswordMenu')) do
   begin
@@ -816,9 +748,7 @@ begin
     PW := TGUIEdit(GetControl('edPW')).Text;
   end;
 
-  s := e_GetWriteableDir(ConfigDirs);
-  if s <> '' then
-    g_Options_Write_Net_Client(s + '/' + CONFIG_FILENAME);
+  g_Console_WriteGameConfig;
   g_Game_StartClient(NetClientIP, NetClientPort, PW);
 end;
 
@@ -835,7 +765,7 @@ begin
       NetInitDone := True;
   end;
 
-  g_Net_Slist_Set(NetSlistIP, NetSlistPort, NetSlistList);
+  g_Net_Slist_Set(NetMasterList);
 
   gState := STATE_SLIST;
   g_ActiveWindow := nil;
@@ -1873,6 +1803,12 @@ begin
           end;
       end;
     end;
+
+    // don't forget to latch this shit
+    gsGameFlags := Options;
+    gsMaxLives := MaxLives;
+    gsGoalLimit := GoalLimit;
+    gsTimeLimit := TimeLimit;
   end;
 
   if g_Game_IsNet then MH_SEND_GameSettings;
@@ -2174,7 +2110,7 @@ begin
     begin
       Name := 'lbMap';
       FixedLength := 16;
-      Text := gnMap;
+      Text := gsMap;
       OnClick := @ProcSelectMapMenu;
     end;
     with AddSwitch(_lc[I_MENU_GAME_TYPE]) do
@@ -2184,7 +2120,7 @@ begin
       AddItem(_lc[I_MENU_GAME_TYPE_TDM]);
       AddItem(_lc[I_MENU_GAME_TYPE_CTF]);
       AddItem(_lc[I_MENU_GAME_TYPE_COOP]);
-      case g_Game_TextToMode(gnGameMode) of
+      case g_Game_TextToMode(gsGameMode) of
         GM_NONE,
         GM_DM:   ItemIndex := 0;
         GM_TDM:  ItemIndex := 1;
@@ -2192,7 +2128,7 @@ begin
         GM_SINGLE,
         GM_COOP: ItemIndex := 3;
       end;
-      OnChange := ProcSwitchMonstersNet;
+      OnChange := ProcSwitchMonstersCustom;
     end;
     with AddEdit(_lc[I_MENU_TIME_LIMIT]) do
     begin
@@ -2200,8 +2136,8 @@ begin
       OnlyDigits := True;
       Width := 4;
       MaxLength := 5;
-      if gnTimeLimit > 0 then
-        Text := IntToStr(gnTimeLimit);
+      if gsTimeLimit > 0 then
+        Text := IntToStr(gsTimeLimit);
     end;
     with AddEdit(_lc[I_MENU_GOAL_LIMIT]) do
     begin
@@ -2209,32 +2145,41 @@ begin
       OnlyDigits := True;
       Width := 4;
       MaxLength := 5;
-      if gnGoalLimit > 0 then
-        Text := IntToStr(gnGoalLimit);
+      if gsGoalLimit > 0 then
+        Text := IntToStr(gsGoalLimit);
     end;
     with AddEdit(_lc[I_MENU_MAX_LIVES]) do
     begin
       Name := 'edMaxLives';
       OnlyDigits := True;
       Width := 4;
-      MaxLength := 3;
-      if gnMaxLives > 0 then
-        Text := IntToStr(gnMaxLives);
+      MaxLength := 5;
+      if gsMaxLives > 0 then
+        Text := IntToStr(gsMaxLives);
+    end;
+    with AddEdit(_lc[I_MENU_ITEM_RESPAWN_TIME]) do
+    begin
+      Name := 'edItemRespawnTime';
+      OnlyDigits := True;
+      Width := 4;
+      MaxLength := 5;
+      if gsItemRespawnTime > 0 then
+        Text := IntToStr(gsItemRespawnTime);
     end;
-    with AddSwitch(_lc[I_MENU_SERVER_PLAYERS]) do
+    with AddSwitch(_lc[I_MENU_PLAYERS]) do
     begin
       Name := 'swPlayers';
       AddItem(_lc[I_MENU_COUNT_NONE]);
       AddItem(_lc[I_MENU_PLAYERS_ONE]);
       AddItem(_lc[I_MENU_PLAYERS_TWO]);
-      ItemIndex := gnPlayers;
+      ItemIndex := gsPlayers;
     end;
     with AddSwitch(_lc[I_MENU_TEAM_DAMAGE]) do
     begin
       Name := 'swTeamDamage';
       AddItem(_lc[I_MENU_YES]);
       AddItem(_lc[I_MENU_NO]);
-      if gnTeamDamage then
+      if LongBool(gsGameFlags and GAME_OPTION_TEAMDAMAGE) then
         ItemIndex := 0
       else
         ItemIndex := 1;
@@ -2244,7 +2189,7 @@ begin
       Name := 'swDeathmatchKeys';
       AddItem(_lc[I_MENU_YES]);
       AddItem(_lc[I_MENU_NO]);
-      if gnDeathmatchKeys then
+      if LongBool(gsGameFlags and GAME_OPTION_DMKEYS) then
         ItemIndex := 0
       else
         ItemIndex := 1;
@@ -2254,7 +2199,7 @@ begin
       Name := 'swEnableExits';
       AddItem(_lc[I_MENU_YES]);
       AddItem(_lc[I_MENU_NO]);
-      if gnAllowExit then
+      if LongBool(gsGameFlags and GAME_OPTION_ALLOWEXIT) then
         ItemIndex := 0
       else
         ItemIndex := 1;
@@ -2264,7 +2209,7 @@ begin
       Name := 'swWeaponStay';
       AddItem(_lc[I_MENU_YES]);
       AddItem(_lc[I_MENU_NO]);
-      if gnWeaponStay then
+      if LongBool(gsGameFlags and GAME_OPTION_WEAPONSTAY) then
         ItemIndex := 0
       else
         ItemIndex := 1;
@@ -2274,7 +2219,7 @@ begin
       Name := 'swMonsters';
       AddItem(_lc[I_MENU_YES]);
       AddItem(_lc[I_MENU_NO]);
-      if gnMonsters then
+      if LongBool(gsGameFlags and GAME_OPTION_MONSTERS) then
         ItemIndex := 0
       else
         ItemIndex := 1;
@@ -2286,9 +2231,9 @@ begin
       AddItem(_lc[I_MENU_BOTS_VS_MONSTERS]);
       AddItem(_lc[I_MENU_BOTS_VS_ALL]);
       ItemIndex := 2;
-      if gnBotsVS = 'Players' then
+      if not LongBool(gsGameFlags and GAME_OPTION_BOTVSMONSTER) then
         ItemIndex := 0;
-      if gnBotsVS = 'Monsters' then
+      if not LongBool(gsGameFlags and GAME_OPTION_BOTVSPLAYER) then
         ItemIndex := 1;
     end;
     AddSpace();
@@ -2384,7 +2329,7 @@ begin
     begin
       Name := 'lbMap';
       FixedLength := 16;
-      Text := gcMap;
+      Text := gsMap;
       OnClick := @ProcSelectMapMenu;
     end;
     with AddSwitch(_lc[I_MENU_GAME_TYPE]) do
@@ -2394,7 +2339,7 @@ begin
       AddItem(_lc[I_MENU_GAME_TYPE_TDM]);
       AddItem(_lc[I_MENU_GAME_TYPE_CTF]);
       AddItem(_lc[I_MENU_GAME_TYPE_COOP]);
-      case g_Game_TextToMode(gcGameMode) of
+      case g_Game_TextToMode(gsGameMode) of
         GM_NONE,
         GM_DM:   ItemIndex := 0;
         GM_TDM:  ItemIndex := 1;
@@ -2410,8 +2355,8 @@ begin
       OnlyDigits := True;
       Width := 4;
       MaxLength := 5;
-      if gcTimeLimit > 0 then
-        Text := IntToStr(gcTimeLimit);
+      if gsTimeLimit > 0 then
+        Text := IntToStr(gsTimeLimit);
     end;
     with AddEdit(_lc[I_MENU_GOAL_LIMIT]) do
     begin
@@ -2419,8 +2364,8 @@ begin
       OnlyDigits := True;
       Width := 4;
       MaxLength := 5;
-      if gcGoalLimit > 0 then
-        Text := IntToStr(gcGoalLimit);
+      if gsGoalLimit > 0 then
+        Text := IntToStr(gsGoalLimit);
     end;
     with AddEdit(_lc[I_MENU_MAX_LIVES]) do
     begin
@@ -2428,8 +2373,17 @@ begin
       OnlyDigits := True;
       Width := 4;
       MaxLength := 5;
-      if gcMaxLives > 0 then
-        Text := IntToStr(gcMaxLives);
+      if gsMaxLives > 0 then
+        Text := IntToStr(gsMaxLives);
+    end;
+    with AddEdit(_lc[I_MENU_ITEM_RESPAWN_TIME]) do
+    begin
+      Name := 'edItemRespawnTime';
+      OnlyDigits := True;
+      Width := 4;
+      MaxLength := 5;
+      if gsItemRespawnTime > 0 then
+        Text := IntToStr(gsItemRespawnTime);
     end;
     with AddSwitch(_lc[I_MENU_PLAYERS]) do
     begin
@@ -2437,14 +2391,14 @@ begin
       AddItem(_lc[I_MENU_COUNT_NONE]);
       AddItem(_lc[I_MENU_PLAYERS_ONE]);
       AddItem(_lc[I_MENU_PLAYERS_TWO]);
-      ItemIndex := gcPlayers;
+      ItemIndex := gsPlayers;
     end;
     with AddSwitch(_lc[I_MENU_TEAM_DAMAGE]) do
     begin
       Name := 'swTeamDamage';
       AddItem(_lc[I_MENU_YES]);
       AddItem(_lc[I_MENU_NO]);
-      if gcTeamDamage then
+      if LongBool(gsGameFlags and GAME_OPTION_TEAMDAMAGE) then
         ItemIndex := 0
       else
         ItemIndex := 1;
@@ -2454,7 +2408,7 @@ begin
       Name := 'swDeathmatchKeys';
       AddItem(_lc[I_MENU_YES]);
       AddItem(_lc[I_MENU_NO]);
-      if gcDeathmatchKeys then
+      if LongBool(gsGameFlags and GAME_OPTION_DMKEYS) then
         ItemIndex := 0
       else
         ItemIndex := 1;
@@ -2464,7 +2418,7 @@ begin
       Name := 'swEnableExits';
       AddItem(_lc[I_MENU_YES]);
       AddItem(_lc[I_MENU_NO]);
-      if gcAllowExit then
+      if LongBool(gsGameFlags and GAME_OPTION_ALLOWEXIT) then
         ItemIndex := 0
       else
         ItemIndex := 1;
@@ -2474,7 +2428,7 @@ begin
       Name := 'swWeaponStay';
       AddItem(_lc[I_MENU_YES]);
       AddItem(_lc[I_MENU_NO]);
-      if gcWeaponStay then
+      if LongBool(gsGameFlags and GAME_OPTION_WEAPONSTAY) then
         ItemIndex := 0
       else
         ItemIndex := 1;
@@ -2484,7 +2438,7 @@ begin
       Name := 'swMonsters';
       AddItem(_lc[I_MENU_YES]);
       AddItem(_lc[I_MENU_NO]);
-      if gcMonsters then
+      if LongBool(gsGameFlags and GAME_OPTION_MONSTERS) then
         ItemIndex := 0
       else
         ItemIndex := 1;
@@ -2496,9 +2450,9 @@ begin
       AddItem(_lc[I_MENU_BOTS_VS_MONSTERS]);
       AddItem(_lc[I_MENU_BOTS_VS_ALL]);
       ItemIndex := 2;
-      if gcBotsVS = 'Players' then
+      if not LongBool(gsGameFlags and GAME_OPTION_BOTVSMONSTER) then
         ItemIndex := 0;
-      if gcBotsVS = 'Monsters' then
+      if not LongBool(gsGameFlags and GAME_OPTION_BOTVSPLAYER) then
         ItemIndex := 1;
     end;
     AddSpace();
index 0c01dd925fffd40aac9d0e98aeae874916ce294b..d2bc5a2be06a30cf2111c7189d9e1ad0fed0e78e 100644 (file)
@@ -147,9 +147,7 @@ var
   NetPongSock:   ENetSocket = ENET_SOCKET_NULL;
 
   NetUseMaster: Boolean = True;
-  NetSlistIP:   string = 'mpms.doom2d.org';
-  NetSlistPort: Word = 25665;
-  NetSlistList: string = 'deadsoftware.ru:25665';
+  NetMasterList: string = 'mpms.doom2d.org:25665,deadsoftware.ru:25665';
 
   NetClientIP:   string = '127.0.0.1';
   NetClientPort: Word   = 25666;
@@ -2374,7 +2372,7 @@ begin
             SetLength(NetServerName, 64);
           g_Net_Slist_ServerRenamed();
         end;
-        g_Console_Add(cmd + ' "' + NetServerName + '"');
+        g_Console_Add(cmd + ' "' + NetServerName + '"');
       end;
     'sv_passwd':
       begin
@@ -2385,7 +2383,7 @@ begin
             SetLength(NetPassword, 24);
           g_Net_Slist_ServerRenamed();
         end;
-        g_Console_Add(cmd + ' "' + AnsiLowerCase(NetPassword) + '"');
+        g_Console_Add(cmd + ' "' + AnsiLowerCase(NetPassword) + '"');
       end;
     'sv_maxplrs':
       begin
@@ -2412,16 +2410,27 @@ begin
             g_Net_Slist_ServerRenamed();
           end;
         end;
-        g_Console_Add(cmd + ' ' + IntToStr(NetMaxClients));
+        g_Console_Add(cmd + ' ' + IntToStr(NetMaxClients));
       end;
     'sv_public':
       begin
         if (Length(P) > 1) then
         begin
-          NetUseMaster := StrToIntDef(P[1], Byte(NetUseMaster)) > 0;
+          NetUseMaster := StrToIntDef(P[1], Byte(NetUseMaster)) <> 0;
           if NetUseMaster then g_Net_Slist_Public() else g_Net_Slist_Private();
         end;
-        g_Console_Add(cmd + ' = ' + IntToStr(Byte(NetUseMaster)));
+        g_Console_Add(cmd + ' ' + IntToStr(Byte(NetUseMaster)));
+      end;
+    'sv_port':
+      begin
+        if (Length(P) > 1) then
+        begin
+          if not g_Game_IsNet then
+            NetPort := nclamp(StrToIntDef(P[1], NetPort), 0, $FFFF)
+          else
+            g_Console_Add(_lc[I_MSG_NOT_NETGAME]);
+        end;
+        g_Console_Add(cmd + ' ' + IntToStr(Ord(NetUseMaster)));
       end;
   end;
 end;
@@ -2431,7 +2440,18 @@ initialization
   conRegVar('cl_predictself', @NetPredictSelf, '', 'predict local player');
   conRegVar('cl_forceplayerupdate', @NetForcePlayerUpdate, '', 'update net players on NET_MSG_PLRPOS');
   conRegVar('cl_interp', @NetInterpLevel, '', 'net player interpolation steps');
+  conRegVar('cl_last_ip', @NetClientIP, '', 'address of the last you have connected to');
+  conRegVar('cl_last_port', @NetClientPort, '', 'port of the last server you have connected to');
+
   conRegVar('sv_forwardports', @NetForwardPorts, '', 'forward server port using miniupnpc (requires server restart)');
+  conRegVar('sv_rcon', @NetAllowRCON, '', 'enable remote console');
+  conRegVar('sv_rcon_password', @NetRCONPassword, '', 'remote console password');
+  conRegVar('sv_update_interval', @NetUpdateRate, '', 'unreliable update interval');
+  conRegVar('sv_reliable_interval', @NetRelupdRate, '', 'reliable update interval');
+  conRegVar('sv_master_interval', @NetMasterRate, '', 'master server update interval');
+
+  conRegVar('net_master_list', @NetMasterList, '', 'list of master servers');
+
   SetLength(NetClients, 0);
   g_Net_DownloadTimeout := 60;
   NetIn.Alloc(NET_BUFSIZE);
index 67747595d085f70169932a4cc1c984982c3fbbb3..fa3d1904c29be532f66056f96f9c38c6c9e11961 100644 (file)
@@ -133,7 +133,7 @@ var
   NMASTER_FORCE_UPDATE_TIMEOUT: Integer = 0; // fuck you, fpc, and your idiotic "diagnostics"
 
 
-procedure g_Net_Slist_Set (IP: AnsiString; Port: Word; list: AnsiString='');
+procedure g_Net_Slist_Set (list: AnsiString);
 function g_Net_Slist_Fetch (var SL: TNetServerList): Boolean;
 
 // make this server private
@@ -1053,7 +1053,7 @@ end;
 //  g_Net_Slist_Set
 //
 //==========================================================================
-procedure g_Net_Slist_Set (IP: AnsiString; Port: Word; list: AnsiString='');
+procedure g_Net_Slist_Set (list: AnsiString);
 var
   f, dest: Integer;
   sa: AnsiString;
@@ -1064,13 +1064,6 @@ begin
 
   for f := 0 to High(mlist) do mlist[f].justAdded := false;
 
-  IP := Trim(IP);
-  if (length(IP) > 0) and (Port > 0) then
-  begin
-    sa := IP+':'+IntToStr(Port);
-    if parseAddressPort(ea, sa) then addMasterRecord(ea, sa);
-  end;
-
   list := Trim(list);
   //writeln('list=[', list, ']');
   while (length(list) > 0) do
index 23ddc36a259a6a5d04531e64b3ff5243253b8e5a..091935cb80b2b0eab96233a1680de41741e381a2 100644 (file)
@@ -24,13 +24,7 @@ function GenPlayerName (n: Integer): String;
 
 procedure g_Options_SetDefault;
 procedure g_Options_SetDefaultVideo;
-procedure g_Options_Read(FileName: String);
-procedure g_Options_Write(FileName: String);
-procedure g_Options_Write_Gameplay_Custom(FileName: String);
-procedure g_Options_Write_Gameplay_Net(FileName: String);
-procedure g_Options_Write_Net_Server(FileName: String);
-procedure g_Options_Write_Net_Client(FileName: String);
-procedure g_Options_Commands (p: SSArray);
+procedure g_Options_ApplyGameSettings;
 
 const DF_Default_Megawad_Start = 'megawads/DOOM2D.WAD:\MAP01';
 
@@ -62,38 +56,24 @@ var
   gAskLanguage: Boolean;
   gSaveStats: Boolean = False;
   gScreenshotStats: Boolean = False;
-  gcMap: String;
-  gcGameMode: String;
-  gcTimeLimit: Word;
-  gcGoalLimit: Word;
-  gcMaxLives: Byte;
-  gcPlayers: Byte;
-  gcTeamDamage: Boolean;
-  gcAllowExit: Boolean;
-  gcWeaponStay: Boolean;
-  gcMonsters: Boolean;
-  gcBotsVS: String;
-  gcDeathmatchKeys: Boolean = True;
-  gcSpawnInvul: Integer = 0;
-  gnMap: String;
-  gnGameMode: String;
-  gnTimeLimit: Word;
-  gnGoalLimit: Word;
-  gnMaxLives: Byte;
-  gnPlayers: Byte;
-  gnTeamDamage: Boolean;
-  gnAllowExit: Boolean;
-  gnWeaponStay: Boolean;
-  gnMonsters: Boolean;
-  gnBotsVS: String;
-  gnDeathmatchKeys: Boolean = True;
-  gnSpawnInvul: Integer = 0;
   gsSDLSampleRate: Integer;
   gsSDLBufferSize: Integer;
   gDefaultMegawadStart: AnsiString;
   gBerserkAutoswitch: Boolean;
   glNPOTOverride: Boolean = false;
 
+  (* Latched game settings *)
+  gsMap: String;
+  gsGameMode: String;
+  gsTimeLimit: Word;
+  gsGoalLimit: Word;
+  gsMaxLives: Byte;
+  gsPlayers: Byte;
+  gsGameFlags: LongWord;
+  gsSpawnInvul: Integer = 0;
+  gsItemRespawnTime: Word = 60;
+  gsWarmupTime: Word = 30;
+
 implementation
 
 uses
@@ -258,7 +238,6 @@ begin
   g_Gibs_SetMax(150);
   g_Corpses_SetMax(20);
   gGibsCount := 32;
-  ITEM_RESPAWNTIME := 60 * 36;
   gBloodCount := 4;
   gAdvBlood := True;
   gAdvCorpses := True;
@@ -279,40 +258,21 @@ begin
   gAskLanguage := True;
   gLanguage := LANGUAGE_ENGLISH;
 
-  (* section GameplayCustom *)
-  gcMap := '';
-  gcGameMode := _lc[I_MENU_GAME_TYPE_DM];
-  gcTimeLimit := 0;
-  gcGoalLimit := 0;
-  gcMaxLives := 0;
-  gcPlayers := 1;
-  gcTeamDamage := False;
-  gcAllowExit := True;
-  gcWeaponStay := False;
-  gcMonsters := False;
-  gcBotsVS := 'Everybody';
-  gcDeathmatchKeys := True;
-  gcSpawnInvul := 0;
-
-  (* section GameplayNetwork *)
-  gnMap := '';
-  gnGameMode := _lc[I_MENU_GAME_TYPE_DM];
-  gnTimeLimit := 0;
-  gnGoalLimit := 0;
-  gnMaxLives := 0;
-  gnPlayers := 1;
-  gnTeamDamage := False;
-  gnAllowExit := True;
-  gnWeaponStay := False;
-  gnMonsters := False;
-  gnBotsVS := 'Everybody';
-  gnDeathmatchKeys := True;
-  gnSpawnInvul := 0;
+  gsMap := '';
+  gsGameMode := _lc[I_MENU_GAME_TYPE_DM];
+  gsTimeLimit := 0;
+  gsGoalLimit := 0;
+  gsMaxLives := 0;
+  gsPlayers := 1;
+  gsSpawnInvul := 0;
+  gsItemRespawnTime := 60;
+  gsGameFlags := GAME_OPTION_ALLOWEXIT or GAME_OPTION_DMKEYS or
+    GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER;
+  gsPlayers := 1;
 
   (* section MasterServer *)
-  NetSlistIP := 'mpms.doom2d.org';
-  NetSlistPort := 25665;
-  g_Net_Slist_Set(NetSlistIP, NetSlistPort, NetSlistList);
+  NetMasterList := 'mpms.doom2d.org:25665,deadsoftware.ru:25665';
+  g_Net_Slist_Set(NetMasterList);
 
   (* section Server *)
   NetServerName := 'Unnamed Server';
@@ -335,458 +295,22 @@ begin
   NetClientPort := NetPort;
 end;
 
-procedure g_Options_Read(FileName: String);
-var
-  config: TConfig;
-  section: String;
-  
-  procedure ReadInteger (VAR v: Integer; param: String; minv: Integer = Low(Integer); maxv: Integer = High(Integer));
-  begin
-    v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
-  end;
-
-  procedure ReadInteger (VAR v: LongWord; param: String; minv: LongWord = Low(LongWord); maxv: LongWord = High(LongWord)); overload;
-  begin
-    v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
-  end;
-
-  procedure ReadInteger (VAR v: Word; param: String; minv: Word = Low(Word); maxv: Word = High(Word)); overload;
-  begin
-    v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
-  end;
-
-  procedure ReadInteger (VAR v: Byte; param: String; minv: Byte = Low(Byte); maxv: Byte = High(Byte)); overload;
-  begin
-    v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
-  end;
-
-  procedure ReadBoolean (VAR v: Boolean; param: String);
-  begin
-    v := config.ReadBool(section, param, v)
-  end;
-
-  procedure ReadString (VAR v: String; param: String);
-  begin
-    v := config.ReadStr(section, param, v)
-  end;
-
+procedure g_Options_ApplyGameSettings;
 begin
-  gAskLanguage := True;
-  e_WriteLog('Reading config', TMsgType.Notify);
-  g_Options_SetDefault;
-
-  if FileExists(FileName) = False then
-  begin
-    e_WriteLog('Config file '+FileName+' not found', TMsgType.Warning);
-    g_Options_SetDefaultVideo;
-    Exit
-  end;
-
-  config := TConfig.CreateFile(FileName);
-
-  section := 'Player1';
-  with gPlayer1Settings do
-  begin
-    ReadString(Name, 'name');
-    ReadString(Model, 'model');
-    ReadInteger(Color.R, 'red', 0, 255);
-    ReadInteger(Color.G, 'green', 0, 255);
-    ReadInteger(Color.B, 'blue', 0, 255);
-    ReadInteger(Team, 'team');
-    if (Team < TEAM_RED) or (Team > TEAM_BLUE) then
-      Team := TEAM_RED;
-  end;
-
-  section := 'Player2';
-  with gPlayer2Settings do
-  begin
-    ReadString(Name, 'name');
-    ReadString(Model, 'model');
-    ReadInteger(Color.R, 'red', 0, 255);
-    ReadInteger(Color.G, 'green', 0, 255);
-    ReadInteger(Color.B, 'blue', 0, 255);
-    ReadInteger(Team, 'team');
-    if (Team < TEAM_RED) or (Team > TEAM_BLUE) then
-      Team := TEAM_RED;
-  end;
-
-  section := 'GameplayCustom';
-  ReadString(gcMap, 'Map');
-  ReadString(gcGameMode, 'GameMode');
-  ReadInteger(gcTimeLimit, 'TimeLimit', 0, 65535);
-  ReadInteger(gcGoalLimit, 'GoalLimit', 0, 65535);
-  ReadInteger(gcMaxLives, 'MaxLives', 0, 255);
-  ReadInteger(gcPlayers, 'Players', 0, 2);
-  ReadBoolean(gcTeamDamage, 'TeamDamage');
-  ReadBoolean(gcAllowExit, 'AllowExit');
-  ReadBoolean(gcWeaponStay, 'WeaponStay');
-  ReadBoolean(gcMonsters, 'Monsters');
-  ReadString(gcBotsVS, 'BotsVS');
-  ReadBoolean(gcDeathmatchKeys, 'DeathmatchKeys');
-  ReadInteger(gcSpawnInvul, 'SpawnInvul');
-
   with gGameSettings do
   begin
-    GameMode := g_Game_TextToMode(gcGameMode);
+    GameMode := g_Game_TextToMode(gsGameMode);
     if GameMode = GM_NONE then
       GameMode := GM_DM;
     if GameMode = GM_SINGLE then
       GameMode := GM_COOP;
-    TimeLimit := gcTimeLimit;
-    GoalLimit := gcGoalLimit;
-    MaxLives := gcMaxLives;
-
-    Options := 0;
-    if gcTeamDamage then
-      Options := Options or GAME_OPTION_TEAMDAMAGE;
-    if gcAllowExit then
-      Options := Options or GAME_OPTION_ALLOWEXIT;
-    if gcWeaponStay then
-      Options := Options or GAME_OPTION_WEAPONSTAY;
-    if gcMonsters then
-      Options := Options or GAME_OPTION_MONSTERS;
-    if gcBotsVS = 'Everybody' then
-      Options := Options or GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER;
-    if gcBotsVS = 'Players' then
-      Options := Options or GAME_OPTION_BOTVSPLAYER;
-    if gcBotsVS = 'Monsters' then
-      Options := Options or GAME_OPTION_BOTVSMONSTER;
-    if gcDeathmatchKeys then
-      Options := Options or GAME_OPTION_DMKEYS;
-  end;
-
-  section := 'GameplayNetwork';
-  ReadString(gnMap, 'Map');
-  ReadString(gnGameMode, 'GameMode');
-  ReadInteger(gnTimeLimit, 'TimeLimit', 0, 65535);
-  ReadInteger(gnGoalLimit, 'GoalLimit', 0, 65535);
-  ReadInteger(gnMaxLives, 'MaxLives', 0, 255);
-  ReadInteger(gnPlayers, 'Players', 0, 2);
-  ReadBoolean(gnTeamDamage, 'TeamDamage');
-  ReadBoolean(gnAllowExit, 'AllowExit');
-  ReadBoolean(gnWeaponStay, 'WeaponStay');
-  ReadBoolean(gnMonsters, 'Monsters');
-  ReadString(gnBotsVS, 'BotsVS');
-  ReadBoolean(gnDeathmatchKeys, 'DeathmatchKeys');
-  ReadInteger(gnSpawnInvul, 'SpawnInvul');
-
-  section := 'MasterServer';
-  ReadString(NetSlistIP, 'IP');
-  ReadInteger(NetSlistPort, 'Port', 0, 65535);
-  ReadString(NetSlistList, 'List');
-  g_Net_Slist_Set(NetSlistIP, NetSlistPort, NetSlistList);
-
-  section := 'Server';
-  ReadString(NetServerName, 'Name');
-  ReadString(NetPassword, 'Password');
-  ReadInteger(NetPort, 'Port', 0, 65535);
-  ReadInteger(NetMaxClients, 'MaxClients', 0, NET_MAXCLIENTS);
-  ReadBoolean(NetAllowRCON, 'RCON');
-  ReadString(NetRCONPassword, 'RCONPassword');
-  ReadBoolean(NetUseMaster, 'SyncWithMaster');
-  ReadInteger(NetUpdateRate, 'UpdateInterval', 0);
-  ReadInteger(NetRelupdRate, 'ReliableUpdateInterval', 0);
-  ReadInteger(NetMasterRate, 'MasterSyncInterval', 1);
-  ReadBoolean(NetForwardPorts, 'ForwardPorts');
-
-  section := 'Client';
-  ReadInteger(NetInterpLevel, 'InterpolationSteps', 0);
-  ReadBoolean(NetForcePlayerUpdate, 'ForcePlayerUpdate');
-  ReadBoolean(NetPredictSelf, 'PredictSelf');
-  ReadString(NetClientIP, 'LastIP');
-  ReadInteger(NetClientPort, 'LastPort', 0, 65535);
-
-  config.Free();
-
-  //if gTextureFilter then TEXTUREFILTER := GL_LINEAR else TEXTUREFILTER := GL_NEAREST;
-end;
-
-procedure g_Options_Write(FileName: String);
-  var config: TConfig;
-begin
-  e_WriteLog('Writing config', TMsgType.Notify);
-
-  config := TConfig.CreateFile(FileName);
-
-  with config, gPlayer1Settings do
-  begin
-    WriteStr('Player1', 'Name', Name);
-    WriteStr('Player1', 'model', Model);
-    WriteInt('Player1', 'red', Color.R);
-    WriteInt('Player1', 'green', Color.G);
-    WriteInt('Player1', 'blue', Color.B);
-    WriteInt('Player1', 'team', Team);
-  end;
-
-  with config, gPlayer2Settings do
-  begin
-    WriteStr('Player2', 'Name', Name);
-    WriteStr('Player2', 'model', Model);
-    WriteInt('Player2', 'red', Color.R);
-    WriteInt('Player2', 'green', Color.G);
-    WriteInt('Player2', 'blue', Color.B);
-    WriteInt('Player2', 'team', Team);
-  end;
-
-  config.WriteStr ('GameplayCustom', 'Map', gcMap);
-  config.WriteStr ('GameplayCustom', 'GameMode', gcGameMode);
-  config.WriteInt ('GameplayCustom', 'TimeLimit', gcTimeLimit);
-  config.WriteInt ('GameplayCustom', 'GoalLimit', gcGoalLimit);
-  config.WriteInt ('GameplayCustom', 'MaxLives', gcMaxLives);
-  config.WriteInt ('GameplayCustom', 'Players', gcPlayers);
-  config.WriteBool('GameplayCustom', 'TeamDamage', gcTeamDamage);
-  config.WriteBool('GameplayCustom', 'AllowExit', gcAllowExit);
-  config.WriteBool('GameplayCustom', 'WeaponStay', gcWeaponStay);
-  config.WriteBool('GameplayCustom', 'Monsters', gcMonsters);
-  config.WriteStr ('GameplayCustom', 'BotsVS', gcBotsVS);
-  config.WriteBool('GameplayCustom', 'DeathmatchKeys', gcDeathmatchKeys);
-  config.WriteInt ('GameplayCustom', 'SpawnInvul', gcSpawnInvul);
-
-  config.WriteStr ('GameplayNetwork', 'Map', gnMap);
-  config.WriteStr ('GameplayNetwork', 'GameMode', gnGameMode);
-  config.WriteInt ('GameplayNetwork', 'TimeLimit', gnTimeLimit);
-  config.WriteInt ('GameplayNetwork', 'GoalLimit', gnGoalLimit);
-  config.WriteInt ('GameplayNetwork', 'MaxLives', gnMaxLives);
-  config.WriteInt ('GameplayNetwork', 'Players', gnPlayers);
-  config.WriteBool('GameplayNetwork', 'TeamDamage', gnTeamDamage);
-  config.WriteBool('GameplayNetwork', 'AllowExit', gnAllowExit);
-  config.WriteBool('GameplayNetwork', 'WeaponStay', gnWeaponStay);
-  config.WriteBool('GameplayNetwork', 'Monsters', gnMonsters);
-  config.WriteStr ('GameplayNetwork', 'BotsVS', gnBotsVS);
-  config.WriteBool('GameplayNetwork', 'DeathmatchKeys', gnDeathmatchKeys);
-  config.WriteInt ('GameplayNetwork', 'SpawnInvul', gnSpawnInvul);
-
-  config.WriteStr('MasterServer', 'IP', NetSlistIP);
-  config.WriteInt('MasterServer', 'Port', NetSlistPort);
-  config.WriteStr('MasterServer', 'List', NetSlistList);
-
-  config.WriteStr ('Server', 'Name', NetServerName);
-  config.WriteStr ('Server', 'Password', NetPassword);
-  config.WriteInt ('Server', 'Port', NetPort);
-  config.WriteInt ('Server', 'MaxClients', NetMaxClients);
-  config.WriteBool('Server', 'RCON', NetAllowRCON);
-  config.WriteStr ('Server', 'RCONPassword', NetRCONPassword);
-  config.WriteBool('Server', 'SyncWithMaster', NetUseMaster);
-  config.WriteBool('Server', 'ForwardPorts', NetForwardPorts);
-  config.WriteInt ('Server', 'UpdateInterval', NetUpdateRate);
-  config.WriteInt ('Server', 'ReliableUpdateInterval', NetRelupdRate);
-  config.WriteInt ('Server', 'MasterSyncInterval', NetMasterRate);
-
-  config.WriteInt  ('Client', 'InterpolationSteps', NetInterpLevel);
-  config.WriteBool ('Client', 'ForcePlayerUpdate', NetForcePlayerUpdate);
-  config.WriteBool ('Client', 'PredictSelf', NetPredictSelf);
-  config.WriteStr  ('Client', 'LastIP', NetClientIP);
-  config.WriteInt  ('Client', 'LastPort', NetClientPort);
-
-  config.SaveFile(FileName);
-  config.Free();
-end;
-
-procedure g_Options_Write_Gameplay_Custom(FileName: String);
-var
-  config: TConfig;
-begin
-  e_WriteLog('Writing custom gameplay config', TMsgType.Notify);
-
-  config := TConfig.CreateFile(FileName);
-
-  config.WriteStr ('GameplayCustom', 'Map', gcMap);
-  config.WriteStr ('GameplayCustom', 'GameMode', gcGameMode);
-  config.WriteInt ('GameplayCustom', 'TimeLimit', gcTimeLimit);
-  config.WriteInt ('GameplayCustom', 'GoalLimit', gcGoalLimit);
-  config.WriteInt ('GameplayCustom', 'MaxLives', gcMaxLives);
-  config.WriteInt ('GameplayCustom', 'Players', gcPlayers);
-  config.WriteBool('GameplayCustom', 'TeamDamage', gcTeamDamage);
-  config.WriteBool('GameplayCustom', 'AllowExit', gcAllowExit);
-  config.WriteBool('GameplayCustom', 'WeaponStay', gcWeaponStay);
-  config.WriteBool('GameplayCustom', 'Monsters', gcMonsters);
-  config.WriteStr ('GameplayCustom', 'BotsVS', gcBotsVS);
-  config.WriteBool('GameplayCustom', 'DeathmatchKeys', gcDeathmatchKeys);
-  config.WriteInt ('GameplayCustom', 'SpawnInvul', gcSpawnInvul);
-
-  config.SaveFile(FileName);
-  config.Free();
-end;
-
-procedure g_Options_Write_Gameplay_Net(FileName: String);
-var
-  config: TConfig;
-begin
-  e_WriteLog('Writing network gameplay config', TMsgType.Notify);
-
-  config := TConfig.CreateFile(FileName);
-
-  config.WriteStr ('GameplayNetwork', 'Map', gnMap);
-  config.WriteStr ('GameplayNetwork', 'GameMode', gnGameMode);
-  config.WriteInt ('GameplayNetwork', 'TimeLimit', gnTimeLimit);
-  config.WriteInt ('GameplayNetwork', 'GoalLimit', gnGoalLimit);
-  config.WriteInt ('GameplayNetwork', 'MaxLives', gnMaxLives);
-  config.WriteInt ('GameplayNetwork', 'Players', gnPlayers);
-  config.WriteBool('GameplayNetwork', 'TeamDamage', gnTeamDamage);
-  config.WriteBool('GameplayNetwork', 'AllowExit', gnAllowExit);
-  config.WriteBool('GameplayNetwork', 'WeaponStay', gnWeaponStay);
-  config.WriteBool('GameplayNetwork', 'Monsters', gnMonsters);
-  config.WriteStr ('GameplayNetwork', 'BotsVS', gnBotsVS);
-  config.WriteBool('GameplayNetwork', 'DeathmatchKeys', gnDeathmatchKeys);
-  config.WriteInt ('GameplayNetwork', 'SpawnInvul', gnSpawnInvul);
-
-  config.SaveFile(FileName);
-  config.Free();
-end;
-
-procedure g_Options_Write_Net_Server(FileName: String);
-var
-  config: TConfig;
-begin
-  e_WriteLog('Writing server config', TMsgType.Notify);
-
-  config := TConfig.CreateFile(FileName);
-
-  config.WriteStr ('Server', 'Name', NetServerName);
-  config.WriteStr ('Server', 'Password', NetPassword);
-  config.WriteInt ('Server', 'Port', NetPort);
-  config.WriteInt ('Server', 'MaxClients', NetMaxClients);
-  config.WriteBool('Server', 'SyncWithMaster', NetUseMaster);
-  config.WriteBool('Server', 'ForwardPorts', NetForwardPorts);
-
-  config.SaveFile(FileName);
-  config.Free();
-end;
-
-procedure g_Options_Write_Net_Client(FileName: String);
-var
-  config: TConfig;
-begin
-  e_WriteLog('Writing client config', TMsgType.Notify);
-
-  config := TConfig.CreateFile(FileName);
-
-  config.WriteStr('Client', 'LastIP', NetClientIP);
-  config.WriteInt('Client', 'LastPort', NetClientPort);
-
-  config.SaveFile(FileName);
-  config.Free();
-end;
-
-procedure g_Options_Commands (p: SSArray);
-  var cmd: AnsiString; i: Integer;
-begin
-  cmd := LowerCase(p[0]);
-  case cmd of
-    'r_reset':
-      begin
-        sys_EnableVSync(gVSync);
-        gRC_Width := Max(1, gRC_Width);
-        gRC_Height := Max(1, gRC_Height);
-        gBPP := Max(1, gBPP);
-        if sys_SetDisplayMode(gRC_Width, gRC_Height, gBPP, gRC_FullScreen, gRC_Maximized) = True then
-          e_LogWriteln('resolution changed')
-        else
-          e_LogWriteln('resolution not changed')
-      end;
-    'g_language':
-      begin
-        if Length(p) = 2 then
-        begin
-          gAskLanguage := true;
-          gLanguage := LANGUAGE_ENGLISH;
-          case LowerCase(p[1]) of
-            'english':
-               begin
-                 gAskLanguage := false;
-                 gLanguage := LANGUAGE_ENGLISH;
-               end;
-            'russian':
-               begin
-                 gAskLanguage := false;
-                 gLanguage := LANGUAGE_RUSSIAN;
-               end;
-            'ask':
-               begin
-                 gAskLanguage := true;
-                 gLanguage := LANGUAGE_ENGLISH;
-               end;
-          end;
-          g_Language_Set(gLanguage)
-        end
-        else
-        begin
-          e_LogWritefln('usage: %s <English|Russian|Ask>', [cmd])
-        end
-      end;
-    'g_max_particles':
-      begin
-        if Length(p) = 2 then
-        begin
-          i := Max(0, StrToInt(p[1]));
-          g_GFX_SetMax(i)
-        end
-        else if Length(p) = 1 then
-        begin
-          e_LogWritefln('%s', [g_GFX_GetMax()])
-        end
-        else
-        begin
-          e_LogWritefln('usage: %s <n>', [cmd])
-        end
-      end;
-    'g_max_shells':
-      begin
-        if Length(p) = 2 then
-        begin
-          i := Max(0, StrToInt(p[1]));
-          g_Shells_SetMax(i)
-        end
-        else if Length(p) = 1 then
-        begin
-          e_LogWritefln('%s', [g_Shells_GetMax()])
-        end
-        else
-        begin
-          e_LogWritefln('usage: %s <n>', [cmd])
-        end
-      end;
-    'g_max_gibs':
-      begin
-        if Length(p) = 2 then
-        begin
-          i := Max(0, StrToInt(p[1]));
-          g_Gibs_SetMax(i)
-        end
-        else if Length(p) = 1 then
-        begin
-          e_LogWritefln('%s', [g_Gibs_GetMax()])
-        end
-        else
-        begin
-          e_LogWritefln('usage: %s <n>', [cmd])
-        end
-      end;
-    'g_max_corpses':
-      begin
-        if Length(p) = 2 then
-        begin
-          i := Max(0, StrToInt(p[1]));
-          g_Corpses_SetMax(i)
-        end
-        else if Length(p) = 1 then
-        begin
-          e_LogWritefln('%s', [g_Corpses_GetMax()])
-        end
-        else
-        begin
-          e_LogWritefln('usage: %s <n>', [cmd])
-        end
-      end;
-    'g_item_respawn_time':
-      begin
-        if Length(p) = 2 then
-          ITEM_RESPAWNTIME := Max(0, StrToInt(p[1])) * 36
-        else if Length(p) = 1 then
-          e_LogWritefln('%s', [ITEM_RESPAWNTIME div 36])
-        else
-          e_LogWritefln('usage: %s <n>', [cmd])
-      end;
+    TimeLimit := gsTimeLimit;
+    GoalLimit := gsGoalLimit;
+    MaxLives := gsMaxLives;
+    SpawnInvul := gsSpawnInvul;
+    ItemRespawnTime := gsItemRespawnTime;
+    WarmupTime := gsWarmupTime;
+    Options := gsGameFlags;
   end;
 end;
 
@@ -835,4 +359,5 @@ initialization
   conRegVar('g_default_megawad', @gDefaultMegawadStart, '', '');
   conRegVar('g_save_stats', @gSaveStats, '', '');
   conRegVar('g_screenshot_stats', @gScreenshotStats, '', '');
+  conRegVar('g_lastmap', @gsMap, '', '');
 end.