X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_game.pas;h=2c8ae0fb8dcdc8507c2184aaccc0ca4a660b3183;hb=a1338c3de8d2613ba82d89921630df1ae7b183d0;hp=8453f05fd1d87ca28799b7f40c2f4e4f1dfef560;hpb=3d9a4caf6b9c79640ea51cd8b5cdf602c5ed19a2;p=d2df-sdl.git diff --git a/src/game/g_game.pas b/src/game/g_game.pas index 8453f05..2c8ae0f 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -32,6 +32,7 @@ type GoalLimit: Word; WarmupTime: Word; SpawnInvul: Word; + ItemRespawnTime: Word; MaxLives: Byte; Options: LongWord; WAD: String; @@ -83,6 +84,7 @@ procedure g_Game_Free (freeTextures: Boolean=true); procedure g_Game_LoadData(); procedure g_Game_FreeData(); procedure g_Game_Update(); +procedure g_Game_PreUpdate(); procedure g_Game_Draw(); procedure g_Game_Quit(); procedure g_Game_SetupScreenSize(); @@ -132,6 +134,8 @@ procedure g_SimpleError(Text: String); 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); @@ -172,14 +176,17 @@ const EXIT_ENDLEVELSINGLE = 4; EXIT_ENDLEVELCUSTOM = 5; - GAME_OPTION_RESERVED = 1; - GAME_OPTION_TEAMDAMAGE = 2; - GAME_OPTION_ALLOWEXIT = 4; - GAME_OPTION_WEAPONSTAY = 8; - GAME_OPTION_MONSTERS = 16; - GAME_OPTION_BOTVSPLAYER = 32; - GAME_OPTION_BOTVSMONSTER = 64; - GAME_OPTION_DMKEYS = 128; + GAME_OPTION_RESERVED = 1; + GAME_OPTION_TEAMDAMAGE = 2; + GAME_OPTION_ALLOWEXIT = 4; + GAME_OPTION_WEAPONSTAY = 8; + GAME_OPTION_MONSTERS = 16; + GAME_OPTION_BOTVSPLAYER = 32; + GAME_OPTION_BOTVSMONSTER = 64; + GAME_OPTION_DMKEYS = 128; + GAME_OPTION_TEAMHITTRACE = 256; + GAME_OPTION_TEAMHITPROJECTILE = 512; + GAME_OPTION_TEAMABSORBDAMAGE = 1024; STATE_NONE = 0; STATE_MENU = 1; @@ -237,6 +244,7 @@ var gPlayer2: TPlayer = nil; gPlayerDrawn: TPlayer = nil; gTime: LongWord; + gLerpFactor: Single = 1.0; gSwitchGameMode: Byte = GM_DM; gHearPoint1, gHearPoint2: THearPoint; gSoundEffectsDF: Boolean = False; @@ -262,6 +270,7 @@ var gShowFPS: Boolean = False; gShowGoals: Boolean = True; gShowStat: Boolean = True; + gShowPIDs: Boolean = False; gShowKillMsg: Boolean = True; gShowLives: Boolean = True; gShowPing: Boolean = False; @@ -382,7 +391,7 @@ uses e_input, e_log, g_console, g_items, g_map, g_panel, g_playermodel, g_gfx, g_options, Math, g_triggers, g_monsters, e_sound, CONFIG, - g_language, g_net, g_main, + g_language, g_net, g_main, g_phys, ENet, e_msg, g_netmsg, g_netmaster, sfs, wadreader, g_system; @@ -1157,6 +1166,7 @@ var stat: TPlayerStatArray; wad, map: string; mapstr: string; + namestr: string; begin s1 := ''; s2 := ''; @@ -1298,8 +1308,12 @@ begin gg := g; bb := b; end; + if gShowPIDs then + namestr := Format('[%5d] %s', [UID, Name]) + else + namestr := Name; // Èìÿ - e_TextureFontPrintEx(x+16, _y, Name, gStdFont, rr, gg, bb, 1); + e_TextureFontPrintEx(x+16, _y, namestr, gStdFont, rr, gg, bb, 1); // Ïèíã/ïîòåðè e_TextureFontPrintEx(x+w1+16, _y, Format(_lc[I_GAME_PING_MS], [Ping, Loss]), gStdFont, rr, gg, bb, 1); // Ôðàãè @@ -1334,11 +1348,15 @@ begin r := 255; g := 127; end; + if gShowPIDs then + namestr := Format('[%5d] %s', [UID, Name]) + else + namestr := Name; // Öâåò èãðîêà e_DrawFillQuad(x+16, _y+4, x+32-1, _y+16+4-1, Color.R, Color.G, Color.B, 0); e_DrawQuad(x+16, _y+4, x+32-1, _y+16+4-1, 192, 192, 192); // Èìÿ - e_TextureFontPrintEx(x+16+16+8, _y+4, Name, gStdFont, r, g, 0, 1); + e_TextureFontPrintEx(x+16+16+8, _y+4, namestr, gStdFont, r, g, 0, 1); // Ïèíã/ïîòåðè e_TextureFontPrintEx(x+w1+16, _y+4, Format(_lc[I_GAME_PING_MS], [Ping, Loss]), gStdFont, r, g, 0, 1); // Ôðàãè @@ -1712,6 +1730,17 @@ begin MC_SEND_CheatRequest(NET_CHEAT_READY); end; +procedure g_Game_PreUpdate(); +begin + // these are in separate PreUpdate functions because they can interact during Update() + // and are synced over the net + // we don't care that much about corpses and gibs + g_Player_PreUpdate(); + g_Monsters_PreUpdate(); + g_Items_PreUpdate(); + g_Weapon_PreUpdate(); +end; + procedure g_Game_Update(); var Msg: g_gui.TMessage; @@ -3618,7 +3647,8 @@ end; procedure DrawPlayer(p: TPlayer); var - px, py, a, b, c, d, i: Integer; + px, py, a, b, c, d, i, fX, fY: Integer; + camObj: TObj; //R: TRect; begin if (p = nil) or (p.FDummy) then @@ -3636,8 +3666,10 @@ begin glPushMatrix(); - px := p.GameX + PLAYER_RECT_CX; - py := p.GameY + PLAYER_RECT_CY+p.Obj.slopeUpLeft; + camObj := p.getCameraObj(); + camObj.lerp(gLerpFactor, fX, fY); + px := fX + PLAYER_RECT_CX; + py := fY + PLAYER_RECT_CY+nlerp(p.SlopeOld, camObj.slopeUpLeft, gLerpFactor); if (g_dbg_scale = 1.0) and (not g_dbg_ignore_bounds) then begin @@ -3694,7 +3726,7 @@ begin p.IncCam := nclamp(p.IncCam, min(0, -120 - i), 0); end; - sY := sY - p.IncCam; + sY := sY - nlerp(p.IncCamOld, p.IncCam, gLerpFactor); if (not g_dbg_ignore_bounds) then begin @@ -3766,10 +3798,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 @@ -3830,6 +3858,9 @@ begin FPSTime := Time; end; + e_SetRendertarget(True); + e_SetViewPort(0, 0, gScreenWidth, gScreenHeight); + if gGameOn or (gState = STATE_FOLD) then begin if (gPlayer1 <> nil) and (gPlayer2 <> nil) then @@ -3970,7 +4001,8 @@ begin Round(gScreenHeight / 2.75)-(h div 2), MessageText); end; - if IsDrawStat or (gSpectMode = 1) then DrawStat(); + if IsDrawStat or (gSpectMode = SPECT_STATS) then + DrawStat(); if gSpectHUD and (not gChatShow) and (gSpectMode <> SPECT_NONE) and (not gSpectAuto) then begin @@ -4160,10 +4192,20 @@ begin if gGameOn then drawProfilers(); + // TODO: draw this after the FBO and remap mouse click coordinates + {$IFDEF ENABLE_HOLMES} g_Holmes_DrawUI(); {$ENDIF} + // blit framebuffer to screen + + e_SetRendertarget(False); + e_SetViewPort(0, 0, gWinSizeX, gWinSizeY); + e_BlitFramebuffer(gWinSizeX, gWinSizeY); + + // draw the overlay stuff on top of it + g_Touch_Draw; end; @@ -4195,6 +4237,7 @@ begin e_WriteLog(Format(_lc[I_FATAL_ERROR], [Text]), TMsgType.Warning); gExit := EXIT_SIMPLE; + if gGameOn then EndGame; end; procedure g_SimpleError(Text: String); @@ -4252,15 +4295,16 @@ begin if ((not gGameOn) and (gState <> STATE_INTERCUSTOM)) or (not (gGameSettings.GameType in [GT_CUSTOM, GT_SERVER, GT_CLIENT])) then Exit; + + if (gGameSettings.MaxLives > 0) and (gLMSRespawn = LMS_RESPAWN_NONE) then + Exit; + if gPlayer1 = nil then 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; @@ -4334,8 +4378,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; @@ -4350,6 +4398,7 @@ begin g_Net_Slist_ServerPlayerLeaves(); end else begin + gSpectLatchPID1 := Pl.UID; gPlayer1 := nil; MC_SEND_CheatRequest(NET_CHEAT_SPECTATE); end; @@ -4391,8 +4440,15 @@ begin gGameSettings.Options := gGameSettings.Options + GAME_OPTION_ALLOWEXIT; gGameSettings.Options := gGameSettings.Options + GAME_OPTION_MONSTERS; gGameSettings.Options := gGameSettings.Options + GAME_OPTION_BOTVSMONSTER; + gGameSettings.Options := gGameSettings.Options + GAME_OPTION_TEAMHITPROJECTILE; + gGameSettings.Options := gGameSettings.Options + GAME_OPTION_TEAMHITTRACE; gSwitchGameMode := GM_SINGLE; + gLMSRespawn := LMS_RESPAWN_NONE; + gLMSRespawnTime := 0; + gSpectLatchPID1 := 0; + gSpectLatchPID2 := 0; + g_Game_ExecuteEvent('ongamestart'); // Óñòàíîâêà ðàçìåðîâ îêîí èãðîêîâ: @@ -4472,6 +4528,11 @@ begin gAimLine := False; gShowMap := False; + gLMSRespawn := LMS_RESPAWN_NONE; + gLMSRespawnTime := 0; + gSpectLatchPID1 := 0; + gSpectLatchPID2 := 0; + g_Game_ExecuteEvent('ongamestart'); // Óñòàíîâêà ðàçìåðîâ îêîí èãðîêîâ: @@ -4571,6 +4632,11 @@ begin gAimLine := False; gShowMap := False; + gLMSRespawn := LMS_RESPAWN_NONE; + gLMSRespawnTime := 0; + gSpectLatchPID1 := 0; + gSpectLatchPID2 := 0; + g_Game_ExecuteEvent('ongamestart'); // Óñòàíîâêà ðàçìåðîâ îêíà èãðîêà @@ -4624,7 +4690,7 @@ begin Exit; end; - g_Net_Slist_Set(NetSlistIP, NetSlistPort, NetSlistList); + g_Net_Slist_Set(NetMasterList); g_Net_Slist_ServerStarted(); @@ -4697,6 +4763,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 @@ -4836,9 +4907,6 @@ begin Exit; end; - gLMSRespawn := LMS_RESPAWN_NONE; - gLMSRespawnTime := 0; - g_Player_Init(); NetState := NET_STATE_GAME; MC_SEND_FullStateRequest; @@ -4989,8 +5057,8 @@ begin NetTimeToUpdate := 1; NetTimeToReliable := 0; NetTimeToMaster := NetMasterRate; - gLMSRespawn := LMS_RESPAWN_NONE; - gLMSRespawnTime := 0; + gSpectLatchPID1 := 0; + gSpectLatchPID2 := 0; gMissionFailed := False; gNextMap := ''; @@ -5008,15 +5076,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 @@ -5165,13 +5239,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; @@ -5197,12 +5264,14 @@ begin else if gPlayers[i].Team = TEAM_BLUE then Inc(nb) end; - if (n < 2) or ((gGameSettings.GameMode = GM_TDM) and ((nr = 0) or (nb = 0))) then + if (n < 1) or ((gGameSettings.GameMode = GM_TDM) and ((nr = 0) or (nb = 0))) then begin // wait a second until the fuckers finally decide to join gLMSRespawn := LMS_RESPAWN_WARMUP; - gLMSRespawnTime := gTime + 1000; + gLMSRespawnTime := gTime + gGameSettings.WarmupTime*1000; gLMSSoftSpawn := NoMapRestart; + if g_Game_IsNet then + MH_SEND_GameEvent(NET_EV_LMS_WARMUP, gLMSRespawnTime - gTime); Exit; end; @@ -5232,17 +5301,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; @@ -5381,66 +5447,62 @@ procedure GameCVars(P: SSArray); var a, b: Integer; stat: TPlayerStatArray; - cmd, s: string; - config: TConfig; -begin - stat := nil; - cmd := LowerCase(P[0]); - if (cmd = 'g_friendlyfire') and not g_Game_IsClient then + cmd: string; + + 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,255 +5511,109 @@ 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_friendly_absorb_damage' 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_TEAMABSORBDAMAGE, I_MSG_FRIENDLY_ABSORB_DAMAGE_OFF, I_MSG_FRIENDLY_ABSORB_DAMAGE_ON); end - else if (cmd = 'g_bot_vsplayers') and not g_Game_IsClient then + else if cmd = 'g_friendly_hit_trace' 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_TEAMHITTRACE, I_MSG_FRIENDLY_HIT_TRACE_OFF, I_MSG_FRIENDLY_HIT_TRACE_ON); end - else if (cmd = 'g_bot_vsmonsters') and not g_Game_IsClient then + else if cmd = 'g_friendly_hit_projectile' 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_BOTVSMONSTER - else - Options := Options and (not GAME_OPTION_BOTVSMONSTER); - 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; + ParseGameFlag(GAME_OPTION_TEAMHITPROJECTILE, I_MSG_FRIENDLY_PROJECT_TRACE_OFF, I_MSG_FRIENDLY_PROJECT_TRACE_ON); end - else if (cmd = 'g_dm_keys') 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_DMKEYS - else - Options := Options and (not GAME_OPTION_DMKEYS); - 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; + ParseGameFlag(GAME_OPTION_WEAPONSTAY, I_MSG_WEAPONSTAY_OFF, I_MSG_WEAPONSTAY_ON); end - else if (cmd = 'g_warmuptime') and not g_Game_IsClient then + else if cmd = 'g_allow_exit' 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); - end; - - g_Console_Add(Format(_lc[I_MSG_WARMUP], - [gGameSettings.WarmupTime])); - g_Console_Add(_lc[I_MSG_ONMAPCHANGE]); + ParseGameFlag(GAME_OPTION_ALLOWEXIT, I_MSG_ALLOWEXIT_OFF, I_MSG_ALLOWEXIT_ON, True); end - else if (cmd = 'g_spawn_invul') and not g_Game_IsClient then + else if cmd = 'g_allow_monsters' 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); - end; - - g_Console_Add(Format(_lc[I_MSG_SPAWNINVUL], - [gGameSettings.SpawnInvul])); - g_Console_Add(_lc[I_MSG_ONMAPCHANGE]); + ParseGameFlag(GAME_OPTION_MONSTERS, I_MSG_ALLOWMON_OFF, I_MSG_ALLOWMON_ON, True); end - else if cmd = 'net_interp' then + else if cmd = 'g_bot_vsplayers' then begin - if (Length(P) > 1) then - NetInterpLevel := StrToIntDef(P[1], NetInterpLevel); - g_Console_Add('net_interp = ' + IntToStr(NetInterpLevel)); - s := e_GetWriteableDir(ConfigDirs); - if s <> '' then - begin - config := TConfig.CreateFile(s + '/' + CONFIG_FILENAME); - config.WriteInt('Client', 'InterpolationSteps', NetInterpLevel); - config.SaveFile(s + '/' + CONFIG_FILENAME); - config.Free - end + ParseGameFlag(GAME_OPTION_BOTVSPLAYER, I_MSG_BOTSVSPLAYERS_OFF, I_MSG_BOTSVSPLAYERS_ON); end - else if cmd = 'net_forceplayerupdate' then + else if cmd = 'g_bot_vsmonsters' then begin - if (Length(P) > 1) and ((P[1] = '1') or (P[1] = '0')) then - NetForcePlayerUpdate := (P[1][1] = '1'); - - if NetForcePlayerUpdate then - g_Console_Add('net_forceplayerupdate = 1') - else - g_Console_Add('net_forceplayerupdate = 0'); - - s := e_GetWriteableDir(ConfigDirs); - if s <> '' then - begin - config := TConfig.CreateFile(s + '/' + CONFIG_FILENAME); - config.WriteBool('Client', 'ForcePlayerUpdate', NetForcePlayerUpdate); - config.SaveFile(s + '/' + CONFIG_FILENAME); - config.Free - end + ParseGameFlag(GAME_OPTION_BOTVSMONSTER, I_MSG_BOTSVSMONSTERS_OFF, I_MSG_BOTSVSMONSTERS_ON); end - else if cmd = 'net_predictself' then + else if cmd = 'g_dm_keys' then begin - if (Length(P) > 1) and - ((P[1] = '1') or (P[1] = '0')) then - NetPredictSelf := (P[1][1] = '1'); - - if NetPredictSelf then - g_Console_Add('net_predictself = 1') - else - g_Console_Add('net_predictself = 0'); - - s := e_GetWriteableDir(ConfigDirs); - if s <> '' then - begin - config := TConfig.CreateFile(s + '/' + CONFIG_FILENAME); - config.WriteBool('Client', 'PredictSelf', NetPredictSelf); - config.SaveFile(s + '/' + CONFIG_FILENAME); - config.Free - end + ParseGameFlag(GAME_OPTION_DMKEYS, I_MSG_DMKEYS_OFF, I_MSG_DMKEYS_ON, True); end - else if cmd = 'sv_name' then + else if cmd = 'g_gameflags' then begin - if (Length(P) > 1) and (Length(P[1]) > 0) then + if Length(P) > 1 then begin - NetServerName := P[1]; - if Length(NetServerName) > 64 then - SetLength(NetServerName, 64); - g_Net_Slist_ServerRenamed(); + gsGameFlags := StrToDWordDef(P[1], gsGameFlags); + if g_Game_IsServer then + begin + gGameSettings.Options := gsGameFlags; + if g_Game_IsNet then MH_SEND_GameSettings; + end; end; - g_Console_Add(cmd + ' = "' + NetServerName + '"'); + g_Console_Add(Format('%s %u', [cmd, gsGameFlags])); end - else if cmd = 'sv_passwd' then + else if cmd = 'g_warmup_time' then begin - if (Length(P) > 1) and (Length(P[1]) > 0) then + if Length(P) > 1 then begin - NetPassword := P[1]; - if Length(NetPassword) > 24 then - SetLength(NetPassword, 24); - g_Net_Slist_ServerRenamed(); + gsWarmupTime := nclamp(StrToIntDef(P[1], gsWarmupTime), 0, $FFFF); + if g_Game_IsServer then + begin + gGameSettings.WarmupTime := gsWarmupTime; + // extend warmup if it's already going + if gLMSRespawn = LMS_RESPAWN_WARMUP then + begin + gLMSRespawnTime := gTime + gsWarmupTime * 1000; + if g_Game_IsNet then MH_SEND_GameEvent(NET_EV_LMS_WARMUP, gLMSRespawnTime - gTime); + end; + if g_Game_IsNet then MH_SEND_GameSettings; + end; end; - g_Console_Add(cmd + ' = "' + AnsiLowerCase(NetPassword) + '"'); + 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 = 'sv_maxplrs' then + else if cmd = 'g_spawn_invul' then begin - if (Length(P) > 1) then + if Length(P) > 1 then begin - NetMaxClients := Min(Max(StrToIntDef(P[1], NetMaxClients), 1), NET_MAXCLIENTS); - if g_Game_IsServer and g_Game_IsNet then + gsSpawnInvul := nclamp(StrToIntDef(P[1], gsSpawnInvul), 0, $FFFF); + if g_Game_IsServer then begin - b := 0; - for a := 0 to High(NetClients) do - begin - if NetClients[a].Used then - begin - Inc(b); - if b > NetMaxClients then - begin - s := g_Player_Get(NetClients[a].Player).Name; - enet_peer_disconnect(NetClients[a].Peer, NET_DISC_FULL); - g_Console_Add(Format(_lc[I_PLAYER_KICK], [s])); - MH_SEND_GameEvent(NET_EV_PLAYER_KICK, 0, s); - end; - end; - end; - g_Net_Slist_ServerRenamed(); + gGameSettings.SpawnInvul := gsSpawnInvul; + if g_Game_IsNet then MH_SEND_GameSettings; end; end; - g_Console_Add(cmd + ' = ' + IntToStr(NetMaxClients)); + g_Console_Add(Format('%s %d', [cmd, Integer(gsSpawnInvul)])); end - else if cmd = 'sv_public' then + else if cmd = 'g_item_respawn_time' then begin - if (Length(P) > 1) then + if Length(P) > 1 then begin - NetUseMaster := StrToIntDef(P[1], Byte(NetUseMaster)) > 0; - if NetUseMaster then g_Net_Slist_Public() else g_Net_Slist_Private(); + 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(cmd + ' = ' + IntToStr(Byte(NetUseMaster))); + 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 @@ -5706,227 +5622,267 @@ begin g_Console_Add(cmd + ' = ' + IntToStr(gDefInterTime)); end - else if cmd = 'p1_name' then + else if cmd = 'g_max_particles' then begin - if (Length(P) > 1) then + if Length(p) = 2 then begin - gPlayer1Settings.Name := b_Text_Unformat(P[1]); - if g_Game_IsClient then - MC_SEND_PlayerSettings - else if gGameOn and (gPlayer1 <> nil) then - begin - gPlayer1.Name := b_Text_Unformat(P[1]); - if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer1.UID); - end; - end; + 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 + begin + e_LogWritefln('usage: %s ', [cmd]) + end end - else if cmd = 'p2_name' then + else if cmd = 'g_max_shells' then begin - if (Length(P) > 1) then + if Length(p) = 2 then begin - gPlayer2Settings.Name := b_Text_Unformat(P[1]); - if g_Game_IsClient then - MC_SEND_PlayerSettings - else if gGameOn and (gPlayer2 <> nil) then - begin - gPlayer2.Name := b_Text_Unformat(P[1]); - if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer2.UID); - end; - end; + 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 + begin + e_LogWritefln('usage: %s ', [cmd]) + end end - else if cmd = 'p1_color' then + else if cmd = 'g_max_gibs' then begin - if Length(P) > 3 then + if Length(p) = 2 then begin - gPlayer1Settings.Color := _RGB(EnsureRange(StrToIntDef(P[1], 0), 0, 255), - EnsureRange(StrToIntDef(P[2], 0), 0, 255), - EnsureRange(StrToIntDef(P[3], 0), 0, 255)); - if g_Game_IsClient then - MC_SEND_PlayerSettings - else if gGameOn and (gPlayer1 <> nil) then - begin - gPlayer1.SetColor(gPlayer1Settings.Color); - if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer1.UID); - end; - end; + 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 + begin + e_LogWritefln('usage: %s ', [cmd]) + end end - else if cmd = 'p2_color' then + else if cmd = 'g_max_corpses' then begin - if Length(P) > 3 then + if Length(p) = 2 then begin - gPlayer2Settings.Color := _RGB(EnsureRange(StrToIntDef(P[1], 0), 0, 255), - EnsureRange(StrToIntDef(P[2], 0), 0, 255), - EnsureRange(StrToIntDef(P[3], 0), 0, 255)); - if g_Game_IsClient then - MC_SEND_PlayerSettings - else if gGameOn and (gPlayer2 <> nil) then - begin - gPlayer2.SetColor(gPlayer2Settings.Color); - if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer2.UID); - end; - end; + 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 + begin + e_LogWritefln('usage: %s ', [cmd]) + end end - else if cmd = 'p1_model' then + else if cmd = 'g_scorelimit' then begin - if (Length(P) > 1) then + if Length(P) > 1 then begin - gPlayer1Settings.Model := P[1]; - if g_Game_IsClient then - MC_SEND_PlayerSettings - else if gGameOn and (gPlayer1 <> nil) then + gsGoalLimit := nclamp(StrToIntDef(P[1], gsGoalLimit), 0, $FFFF); + + if g_Game_IsServer then begin - gPlayer1.FActualModelName := gPlayer1Settings.Model; - gPlayer1.SetModel(gPlayer1Settings.Model); - if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer1.UID); + 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], [Integer(gsGoalLimit)])); end - else if cmd = 'p2_model' then + else if cmd = 'g_timelimit' then begin - if (Length(P) > 1) then + if Length(P) > 1 then begin - gPlayer2Settings.Model := P[1]; - if g_Game_IsClient then - MC_SEND_PlayerSettings - else if gGameOn and (gPlayer2 <> nil) then + gsTimeLimit := nclamp(StrToIntDef(P[1], gsTimeLimit), 0, $FFFF); + if g_Game_IsServer then begin - gPlayer2.FActualModelName := gPlayer2Settings.Model; - gPlayer2.SetModel(gPlayer2Settings.Model); - if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer2.UID); + gGameSettings.TimeLimit := gsTimeLimit; + if g_Game_IsNet then MH_SEND_GameSettings; end; end; + g_Console_Add(Format(_lc[I_MSG_TIME_LIMIT], + [gsTimeLimit div 3600, + (gsTimeLimit div 60) mod 60, + gsTimeLimit mod 60])); end - else if gGameSettings.GameType in [GT_CUSTOM, GT_SERVER, GT_CLIENT] then + else if cmd = 'g_maxlives' then begin - 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 - 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]) - else - g_Console_Add(_lc[I_MSG_KILL_MSGS_OFF]); - end - else if cmd = 'r_showlives' then + if Length(P) > 1 then begin - if (Length(P) > 1) and - ((P[1] = '1') or (P[1] = '0')) then - gShowLives := (P[1][1] = '1'); + gsMaxLives := nclamp(StrToIntDef(P[1], gsMaxLives), 0, $FFFF); + if g_Game_IsServer then + begin + gGameSettings.MaxLives := gsMaxLives; + if g_Game_IsNet then MH_SEND_GameSettings; + end; + end; - if gShowLives then - g_Console_Add(_lc[I_MSG_LIVES_ON]) - else - g_Console_Add(_lc[I_MSG_LIVES_OFF]); - end - else if cmd = 'r_showspect' then - begin - if (Length(P) > 1) and - ((P[1] = '1') or (P[1] = '0')) then - gSpectHUD := (P[1][1] = '1'); + g_Console_Add(Format(_lc[I_MSG_LIVES], [Integer(gsMaxLives)])); + end; +end; - if gSpectHUD then - g_Console_Add(_lc[I_MSG_SPECT_HUD_ON]) - else - g_Console_Add(_lc[I_MSG_SPECT_HUD_OFF]); - end - else if cmd = 'r_showping' then - begin - if (Length(P) > 1) and - ((P[1] = '1') or (P[1] = '0')) then - gShowPing := (P[1][1] = '1'); +procedure PlayerSettingsCVars(P: SSArray); +var + cmd: string; + team: Byte; - if gShowPing then - g_Console_Add(_lc[I_MSG_PING_ON]) - else - g_Console_Add(_lc[I_MSG_PING_OFF]); - end - else if (cmd = 'g_scorelimit') and not g_Game_IsClient then - begin - if Length(P) > 1 then + function ParseTeam(s: string): Byte; + begin + result := 0; + case s of + 'red', '1': result := TEAM_RED; + 'blue', '2': result := TEAM_BLUE; + else result := TEAM_NONE; + end; + end; +begin + cmd := LowerCase(P[0]); + case cmd of + 'p1_name': begin - if StrToIntDef(P[1], gGameSettings.GoalLimit) = 0 then - gGameSettings.GoalLimit := 0 - else + if (Length(P) > 1) then + begin + gPlayer1Settings.Name := b_Text_Unformat(P[1]); + if g_Game_IsClient then + MC_SEND_PlayerSettings + else if gGameOn and (gPlayer1 <> nil) 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); - - gGameSettings.GoalLimit := Max(StrToIntDef(P[1], gGameSettings.GoalLimit), b); + gPlayer1.Name := b_Text_Unformat(P[1]); + if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer1.UID); end; - - if g_Game_IsNet then MH_SEND_GameSettings; + end; end; - - g_Console_Add(Format(_lc[I_MSG_SCORE_LIMIT], [gGameSettings.GoalLimit])); - end - else if (cmd = 'g_timelimit') and not g_Game_IsClient then - begin - if (Length(P) > 1) and (StrToIntDef(P[1], -1) >= 0) then - gGameSettings.TimeLimit := StrToIntDef(P[1], -1); - - 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; - end - else if (cmd = 'g_maxlives') and not g_Game_IsClient then - begin - if Length(P) > 1 then + 'p2_name': begin - if StrToIntDef(P[1], gGameSettings.MaxLives) = 0 then - gGameSettings.MaxLives := 0 - else + if (Length(P) > 1) 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); + gPlayer2Settings.Name := b_Text_Unformat(P[1]); + if g_Game_IsClient then + MC_SEND_PlayerSettings + else if gGameOn and (gPlayer2 <> nil) then + begin + gPlayer2.Name := b_Text_Unformat(P[1]); + if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer2.UID); + end; + end; + end; + 'p1_color': + begin + if Length(P) > 3 then + begin + gPlayer1Settings.Color := _RGB(EnsureRange(StrToIntDef(P[1], 0), 0, 255), + EnsureRange(StrToIntDef(P[2], 0), 0, 255), + EnsureRange(StrToIntDef(P[3], 0), 0, 255)); + if g_Game_IsClient then + MC_SEND_PlayerSettings + else if gGameOn and (gPlayer1 <> nil) then + begin + gPlayer1.SetColor(gPlayer1Settings.Color); + if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer1.UID); + end; + end; + end; + 'p2_color': + begin + if Length(P) > 3 then + begin + gPlayer2Settings.Color := _RGB(EnsureRange(StrToIntDef(P[1], 0), 0, 255), + EnsureRange(StrToIntDef(P[2], 0), 0, 255), + EnsureRange(StrToIntDef(P[3], 0), 0, 255)); + if g_Game_IsClient then + MC_SEND_PlayerSettings + else if gGameOn and (gPlayer2 <> nil) then + begin + gPlayer2.SetColor(gPlayer2Settings.Color); + if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer2.UID); + end; + end; + end; + 'p1_model': + begin + if (Length(P) > 1) then + begin + gPlayer1Settings.Model := P[1]; + if g_Game_IsClient then + MC_SEND_PlayerSettings + else if gGameOn and (gPlayer1 <> nil) then + begin + gPlayer1.FActualModelName := gPlayer1Settings.Model; + gPlayer1.SetModel(gPlayer1Settings.Model); + if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer1.UID); + end; + end; + end; + 'p2_model': + begin + if (Length(P) > 1) then + begin + gPlayer2Settings.Model := P[1]; + if g_Game_IsClient then + MC_SEND_PlayerSettings + else if gGameOn and (gPlayer2 <> nil) then + begin + gPlayer2.FActualModelName := gPlayer2Settings.Model; + gPlayer2.SetModel(gPlayer2Settings.Model); + if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer2.UID); + end; + end; + end; + 'p1_team': + begin + // TODO: switch teams if in game or store this separately + if (Length(P) > 1) then + begin + team := ParseTeam(P[1]); + if team = TEAM_NONE then + g_Console_Add('expected ''red'', ''blue'', 1 or 2') + else if not gGameOn and not g_Game_IsNet then + gPlayer1Settings.Team := team + else + g_Console_Add(_lc[I_MSG_ONMAPCHANGE]); + end; + end; + 'p2_team': + begin + // TODO: switch teams if in game or store this separately + if (Length(P) > 1) then + begin + team := ParseTeam(P[1]); + if team = TEAM_NONE then + g_Console_Add('expected ''red'', ''blue'', 1 or 2') + else if not gGameOn and not g_Game_IsNet then + gPlayer2Settings.Team := team + else + g_Console_Add(_lc[I_MSG_ONMAPCHANGE]); end; end; - - g_Console_Add(Format(_lc[I_MSG_LIVES], - [gGameSettings.MaxLives])); - if g_Game_IsNet then MH_SEND_GameSettings; - end; end; end; @@ -6303,14 +6259,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); @@ -6403,6 +6352,34 @@ begin end else g_Console_Add(_lc[I_MSG_SERVERONLY]); end + else if cmd = 'kick_pid' then + begin + if g_Game_IsServer and g_Game_IsNet then + begin + if Length(P) < 2 then + begin + g_Console_Add('kick_pid '); + Exit; + end; + if P[1] = '' then + begin + g_Console_Add('kick_pid '); + Exit; + end; + + a := StrToIntDef(P[1], 0); + pl := g_Net_Client_ByPlayer(a); + if (pl <> nil) and pl^.Used and (pl^.Peer <> nil) then + begin + s := g_Net_ClientName_ByID(pl^.ID); + enet_peer_disconnect(pl^.Peer, NET_DISC_KICK); + g_Console_Add(Format(_lc[I_PLAYER_KICK], [s])); + MH_SEND_GameEvent(NET_EV_PLAYER_KICK, 0, s); + g_Net_Slist_ServerPlayerLeaves(); + end; + end else + g_Console_Add(_lc[I_MSG_SERVERONLY]); + end else if cmd = 'ban' then begin if g_Game_IsServer and g_Game_IsNet then @@ -6461,6 +6438,35 @@ begin end else g_Console_Add(_lc[I_MSG_SERVERONLY]); end + else if cmd = 'ban_pid' then + begin + if g_Game_IsServer and g_Game_IsNet then + begin + if Length(P) < 2 then + begin + g_Console_Add('ban_pid '); + Exit; + end; + if P[1] = '' then + begin + g_Console_Add('ban_pid '); + Exit; + end; + + a := StrToIntDef(P[1], 0); + pl := g_Net_Client_ByPlayer(a); + if (pl <> nil) and pl^.Used and (pl^.Peer <> nil) then + begin + s := g_Net_ClientName_ByID(pl^.ID); + g_Net_BanHost(pl^.Peer^.address.host, False); + enet_peer_disconnect(pl^.Peer, NET_DISC_TEMPBAN); + g_Console_Add(Format(_lc[I_PLAYER_BAN], [s])); + MH_SEND_GameEvent(NET_EV_PLAYER_BAN, 0, s); + g_Net_Slist_ServerPlayerLeaves(); + end; + end else + g_Console_Add(_lc[I_MSG_SERVERONLY]); + end else if cmd = 'permban' then begin if g_Game_IsServer and g_Game_IsNet then @@ -6521,6 +6527,57 @@ begin end else g_Console_Add(_lc[I_MSG_SERVERONLY]); end + else if cmd = 'permban_pid' then + begin + if g_Game_IsServer and g_Game_IsNet then + begin + if Length(P) < 2 then + begin + g_Console_Add('permban_pid '); + Exit; + end; + if P[1] = '' then + begin + g_Console_Add('permban_pid '); + Exit; + end; + + a := StrToIntDef(P[1], 0); + pl := g_Net_Client_ByPlayer(a); + if (pl <> nil) and pl^.Used and (pl^.Peer <> nil) then + begin + s := g_Net_ClientName_ByID(pl^.ID); + g_Net_BanHost(pl^.Peer^.address.host); + enet_peer_disconnect(pl^.Peer, NET_DISC_BAN); + g_Net_SaveBanList(); + g_Console_Add(Format(_lc[I_PLAYER_BAN], [s])); + MH_SEND_GameEvent(NET_EV_PLAYER_BAN, 0, s); + g_Net_Slist_ServerPlayerLeaves(); + end; + end else + g_Console_Add(_lc[I_MSG_SERVERONLY]); + end + else if cmd = 'permban_ip' then + begin + if g_Game_IsServer and g_Game_IsNet then + begin + if Length(P) < 2 then + begin + g_Console_Add('permban_ip '); + Exit; + end; + if P[1] = '' then + begin + g_Console_Add('permban_ip '); + Exit; + end; + + g_Net_BanHost(P[1]); + g_Net_SaveBanList(); + g_Console_Add(Format(_lc[I_PLAYER_BAN], [P[1]])); + end else + g_Console_Add(_lc[I_MSG_SERVERONLY]); + end else if cmd = 'unban' then begin if g_Game_IsServer and g_Game_IsNet then @@ -6729,7 +6786,8 @@ begin g_Game_Free(); with gGameSettings do begin - GameMode := g_Game_TextToMode(gcGameMode); + Options := gsGameFlags; + GameMode := g_Game_TextToMode(gsGameMode); if gSwitchGameMode <> GM_NONE then GameMode := gSwitchGameMode; if GameMode = GM_NONE then GameMode := GM_DM; @@ -6783,7 +6841,8 @@ begin g_Game_Free(); with gGameSettings do begin - GameMode := g_Game_TextToMode(gcGameMode); + Options := gsGameFlags; + 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; @@ -7360,6 +7419,73 @@ 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 + 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'); + sys_EnableVSync(gVSync); + end; + 'r_maxfps': + begin + if Length(p) = 2 then + begin + gMaxFPS := StrToIntDef(p[1], gMaxFPS); + if gMaxFPS > 0 then + gFrameTime := 1000 div gMaxFPS + else + gFrameTime := 0; + end; + e_LogWritefln('r_maxfps %d', [gMaxFPS]); + 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 ', [cmd]); + end + end; + end; +end; + procedure g_TakeScreenShot(Filename: string = ''); var s: TStream; t: TDateTime; dir, date, name: String; begin @@ -7714,8 +7840,7 @@ begin case gAnnouncer of ANNOUNCE_NONE: Exit; - ANNOUNCE_ME, - ANNOUNCE_MEPLUS: + ANNOUNCE_ME: if not g_Game_IsWatchedPlayer(SpawnerUID) then Exit; end; @@ -8050,11 +8175,9 @@ begin // Options: s := Find_Param_Value(pars, '-opt'); if (s = '') then - Opt := GAME_OPTION_ALLOWEXIT or GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER + Opt := gsGameFlags 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'); @@ -8177,4 +8300,11 @@ 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'); + conRegVar('r_showpids', @gShowPIDs, 'show PIDs', 'show PIDs'); end.