diff --git a/src/game/g_game.pas b/src/game/g_game.pas
index e371e0b3efe1bb221b8f7750ac35db1f637ca82d..47251204f2b021a78262a60f265d830d63308bda 100644 (file)
--- a/src/game/g_game.pas
+++ b/src/game/g_game.pas
TimeLimit: Word;
GoalLimit: Word;
WarmupTime: Word;
+ SpawnInvul: Word;
+ ItemRespawnTime: Word;
MaxLives: Byte;
Options: LongWord;
WAD: String;
Model: String;
Color: TRGB;
Team: Byte;
+ // ones below are sent only to the server
+ WeaponSwitch: Byte;
+ WeaponPreferences: Array[WP_FIRST..WP_LAST+1] of Byte;
+ SwitchToEmpty: Byte;
+ SkipFist: Byte;
end;
TMegaWADInfo = record
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();
procedure g_Game_RestartLevel();
procedure g_Game_RestartRound(NoMapRestart: Boolean = False);
function g_Game_ClientWAD (NewWAD: String; const WHash: TMD5Digest): AnsiString;
-procedure g_Game_SaveOptions();
-function g_Game_StartMap(Map: String; Force: Boolean = False; const oldMapPath: AnsiString=''): Boolean;
+function g_Game_StartMap(asMegawad: Boolean; Map: String; Force: Boolean = False; const oldMapPath: AnsiString=''): Boolean;
procedure g_Game_ChangeMap(const MapPath: String);
procedure g_Game_ExitLevel(const Map: AnsiString);
function g_Game_GetFirstMap(WAD: String): String;
procedure g_Game_Announce_BodyKill(SpawnerUID: Word);
procedure g_Game_StartVote(Command, Initiator: string);
procedure g_Game_CheckVote;
-procedure g_TakeScreenShot();
+procedure g_TakeScreenShot(Filename: string = '');
procedure g_FatalError(Text: String);
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);
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_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;
+ GAME_OPTION_ALLOWDROPFLAG = 2048;
+ GAME_OPTION_THROWFLAG = 4096;
STATE_NONE = 0;
STATE_MENU = 1;
DEFAULT_PLAYERS = 1;
{$ENDIF}
+ STATFILE_VERSION = $03;
+
var
gStdFont: DWORD;
gGameSettings: TGameSettings;
gPlayer2: TPlayer = nil;
gPlayerDrawn: TPlayer = nil;
gTime: LongWord;
+ gLerpFactor: Single = 1.0;
gSwitchGameMode: Byte = GM_DM;
gHearPoint1, gHearPoint2: THearPoint;
gSoundEffectsDF: Boolean = False;
gSoundTriggerTime: Word = 0;
- gAnnouncer: Byte = ANNOUNCE_NONE;
+ gAnnouncer: Integer = ANNOUNCE_NONE;
goodsnd: array[0..3] of TPlayableSound;
killsnd: array[0..3] of TPlayableSound;
hahasnd: array[0..2] of TPlayableSound;
gShowFPS: Boolean = False;
gShowGoals: Boolean = True;
gShowStat: Boolean = True;
+ gShowPIDs: Boolean = False;
gShowKillMsg: Boolean = True;
gShowLives: Boolean = True;
gShowPing: Boolean = False;
gMapToDelete: String;
gTempDelete: Boolean = False;
gLastMap: Boolean = False;
- gWinPosX, gWinPosY: Integer;
- gWinSizeX, gWinSizeY: Integer;
- gWinFrameX, gWinFrameY, gWinCaption: Integer;
- gWinActive: Boolean = True; // by default window is active, lol
+ gScreenWidth: Word;
+ gScreenHeight: Word;
gResolutionChange: Boolean = False;
- gRC_Width, gRC_Height: Word;
+ gRC_Width, gRC_Height: Integer;
gRC_FullScreen, gRC_Maximized: Boolean;
gLanguageChange: Boolean = False;
gDebugMode: Boolean = False;
gDelayedEvents: Array of TDelayedEvent;
gUseChatSounds: Boolean = True;
gChatSounds: Array of TChatSound;
+ gWeaponAction: Array [0..1, WP_FACT..WP_LACT] of Boolean; // [player, weapon_action]
gSelectWeapon: Array [0..1, WP_FIRST..WP_LAST] of Boolean; // [player, weapon]
gInterReadyCount: Integer = 0;
+ gMaxBots: Integer = 127;
g_dbg_ignore_bounds: Boolean = false;
r_smallmap_h: Integer = 0; // 0: left; 1: center; 2: right
{$IFDEF ENABLE_HOLMES}
g_holmes,
{$ENDIF}
- e_texture, e_res, g_textures, g_main, g_window, g_menu,
+ e_texture, e_res, g_textures, g_window, g_menu,
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_language, g_net, g_main, g_phys,
ENet, e_msg, g_netmsg, g_netmaster,
sfs, wadreader, g_system;
MapList: SSArray = nil;
MapIndex: Integer = -1;
InterReadyTime: Integer = -1;
+ StatShotDone: Boolean = False;
+ StatFilename: string = ''; // used by stat screenshot to save with the same name as the csv
+ StatDate: string = '';
MegaWAD: record
info: TMegaWADInfo;
endpic: String;
end;
end;
+// saves a shitty CSV containing the game stats passed to it
+procedure SaveGameStat(Stat: TEndCustomGameStat; Path: string);
+var
+ s: TextFile;
+ dir, fname, map, mode, etime: String;
+ I: Integer;
+begin
+ try
+ dir := e_GetWriteableDir(StatsDirs);
+ // stats are placed in stats/yy/mm/dd/*.csv
+ fname := e_CatPath(dir, Path);
+ ForceDirectories(fname); // ensure yy/mm/dd exists within the stats dir
+ fname := e_CatPath(fname, StatFilename + '.csv');
+ AssignFile(s, fname);
+ try
+ Rewrite(s);
+ // line 1: stats ver, datetime, server name, map name, game mode, time limit, score limit, dmflags, game time, num players
+ if g_Game_IsNet then fname := NetServerName else fname := '';
+ map := g_ExtractWadNameNoPath(gMapInfo.Map) + ':/' + g_ExtractFileName(gMapInfo.Map);
+ mode := g_Game_ModeToText(Stat.GameMode);
+ etime := Format('%d:%.2d:%.2d', [
+ Stat.GameTime div 1000 div 3600,
+ (Stat.GameTime div 1000 div 60) mod 60,
+ Stat.GameTime div 1000 mod 60
+ ]);
+ WriteLn(s, 'stats_ver,datetime,server,map,mode,timelimit,scorelimit,dmflags,time,num_players');
+ WriteLn(s, Format('%d,%s,%s,%s,%s,%u,%u,%u,%s,%d', [
+ STATFILE_VERSION,
+ StatDate,
+ dquoteStr(fname),
+ dquoteStr(map),
+ mode,
+ gGameSettings.TimeLimit,
+ gGameSettings.GoalLimit,
+ gGameSettings.Options,
+ etime,
+ Length(Stat.PlayerStat)
+ ]));
+ // line 2: game specific shit
+ // if it's a team game: red score, blue score
+ // if it's a coop game: monsters killed, monsters total, secrets found, secrets total
+ // otherwise nothing
+ if Stat.GameMode in [GM_TDM, GM_CTF] then
+ WriteLn(s,
+ Format('red_score,blue_score' + LineEnding + '%d,%d', [Stat.TeamStat[TEAM_RED].Goals, Stat.TeamStat[TEAM_BLUE].Goals]))
+ else if Stat.GameMode in [GM_COOP, GM_SINGLE] then
+ WriteLn(s,
+ Format('mon_killed,mon_total,secrets_found,secrets_total' + LineEnding + '%d,%d,%d,%d',[gCoopMonstersKilled, gTotalMonsters, gCoopSecretsFound, gSecretsCount]));
+ // lines 3-...: team, player name, frags, deaths
+ WriteLn(s, 'team,name,frags,deaths');
+ for I := Low(Stat.PlayerStat) to High(Stat.PlayerStat) do
+ with Stat.PlayerStat[I] do
+ WriteLn(s, Format('%d,%s,%d,%d', [Team, dquoteStr(Name), Frags, Deaths]));
+ except
+ g_Console_Add(Format(_lc[I_CONSOLE_ERROR_WRITE], [fname]));
+ end;
+ except
+ g_Console_Add('could not create gamestats file "' + fname + '"');
+ end;
+ CloseFile(s);
+end;
+
function g_Game_ModeToText(Mode: Byte): string;
begin
Result := '';
var
a: Integer;
FileName: string;
+ t: TDateTime;
begin
if g_Game_IsNet and g_Game_IsServer then
MH_SEND_GameEvent(NET_EV_MAPEND, Byte(gMissionFailed));
end;
SortGameStat(CustomStat.PlayerStat);
+
+ if (gSaveStats or gScreenshotStats) and (Length(CustomStat.PlayerStat) > 1) then
+ begin
+ t := Now;
+ if g_Game_IsNet then StatFilename := NetServerName else StatFilename := 'local';
+ StatDate := FormatDateTime('yymmdd_hhnnss', t);
+ StatFilename := StatFilename + '_' + CustomStat.Map + '_' + g_Game_ModeToText(CustomStat.GameMode);
+ StatFilename := sanitizeFilename(StatFilename) + '_' + StatDate;
+ if gSaveStats then
+ SaveGameStat(CustomStat, FormatDateTime('yyyy"/"mm"/"dd', t));
+ end;
+
+ StatShotDone := False;
end;
g_Game_ExecuteEvent('onmapend');
stat: TPlayerStatArray;
wad, map: string;
mapstr: string;
+ namestr: string;
begin
s1 := '';
s2 := '';
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);
// Ôðàãè
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);
// Ôðàãè
if gPlayerAction[p, ACTION_LOOKUP] then plr.PressKey(KEY_UP, time);
if gPlayerAction[p, ACTION_LOOKDOWN] then plr.PressKey(KEY_DOWN, time);
if gPlayerAction[p, ACTION_ATTACK] then plr.PressKey(KEY_FIRE);
- if gPlayerAction[p, ACTION_WEAPNEXT] then plr.PressKey(KEY_NEXTWEAPON);
- if gPlayerAction[p, ACTION_WEAPPREV] then plr.PressKey(KEY_PREVWEAPON);
if gPlayerAction[p, ACTION_ACTIVATE] then plr.PressKey(KEY_OPEN);
- gPlayerAction[p, ACTION_WEAPNEXT] := False; // HACK, remove after readyweaon&pendinweapon implementation
- gPlayerAction[p, ACTION_WEAPPREV] := False; // HACK, remove after readyweaon&pendinweapon implementation
+ for i := WP_FACT to WP_LACT do
+ begin
+ if gWeaponAction[p, i] then
+ begin
+ plr.ProcessWeaponAction(i);
+ gWeaponAction[p, i] := False
+ end
+ end;
for i := WP_FIRST to WP_LAST do
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;
if mon.gncNeedSend then MH_SEND_MonsterPos(mon.UID);
end;
+ function sendItemPos (it: PItem): Boolean;
+ begin
+ result := false; // don't stop
+ if it.needSend then
+ begin
+ MH_SEND_ItemPos(it.myId);
+ it.needSend := False;
+ end;
+ end;
+
var
reliableUpdate: Boolean;
begin
and (not gJustChatted) and (not gConsoleShow) and (not gChatShow)
and (g_ActiveWindow = nil)
)
- or (g_Game_IsNet and ((gInterTime > gInterEndTime) or (gInterReadyCount >= NetClientCount)))
+ or (g_Game_IsNet and ((gInterTime > gInterEndTime) or ((gInterReadyCount >= NetClientCount) and (NetClientCount > 0))))
)
then
begin // Íàæàëè <Enter>/<Ïðîáåë> èëè ïðîøëî äîñòàòî÷íî âðåìåíè:
// Çàêîí÷èëñÿ óðîâåíü â Ñâîåé èãðå:
if gGameSettings.GameType in [GT_CUSTOM, GT_SERVER, GT_CLIENT] then
begin
+ gState := STATE_INTERCUSTOM;
InterReadyTime := -1;
if gLastMap and (gGameSettings.GameMode = GM_COOP) then
begin
end
else
gMusic.SetByName('MUSIC_ROUNDMUS');
-
gMusic.Play();
- gState := STATE_INTERCUSTOM;
e_UnpressAllKeys();
end
else // Çàêîí÷èëàñü ïîñëåäíÿÿ êàðòà â Îäèíî÷íîé èãðå
gSpectY := Max(gSpectY - gSpectStep, 0);
if gPlayerAction[0, ACTION_LOOKDOWN] then
gSpectY := Min(gSpectY + gSpectStep, gMapInfo.Height - gScreenHeight);
- if gPlayerAction[0, ACTION_WEAPPREV] then
+ if gWeaponAction[0, WP_PREV] then
begin
// decrease step
if gSpectStep > 4 then gSpectStep := gSpectStep shr 1;
- gSpectKeyPress := True;
+ gWeaponAction[0, WP_PREV] := False;
end;
- if gPlayerAction[0, ACTION_WEAPNEXT] then
+ if gWeaponAction[0, WP_NEXT] then
begin
// increase step
if gSpectStep < 64 then gSpectStep := gSpectStep shl 1;
- gSpectKeyPress := True;
+ gWeaponAction[0, WP_NEXT] := False;
end;
end;
if (gSpectMode = SPECT_PLAYERS)
gSpectPID1 := GetActivePlayerID_Next(gSpectPID1);
gSpectKeyPress := True;
end;
- if gPlayerAction[0, ACTION_WEAPPREV] then
+ if gWeaponAction[0, WP_PREV] then
begin
// prev player (view 2)
gSpectPID2 := GetActivePlayerID_Prev(gSpectPID2);
- gSpectKeyPress := True;
+ gWeaponAction[0, WP_PREV] := False;
end;
- if gPlayerAction[0, ACTION_WEAPNEXT] then
+ if gWeaponAction[0, WP_NEXT] then
begin
// next player (view 2)
gSpectPID2 := GetActivePlayerID_Next(gSpectPID2);
- gSpectKeyPress := True;
+ gWeaponAction[0, WP_NEXT] := False;
end;
end;
if gPlayerAction[0, ACTION_ATTACK] then
(not gPlayerAction[0, ACTION_MOVELEFT]) and
(not gPlayerAction[0, ACTION_MOVERIGHT]) and
(not gPlayerAction[0, ACTION_LOOKUP]) and
- (not gPlayerAction[0, ACTION_LOOKDOWN]) and
- (not gPlayerAction[0, ACTION_WEAPPREV]) and
- (not gPlayerAction[0, ACTION_WEAPNEXT]) then
+ (not gPlayerAction[0, ACTION_LOOKDOWN]) then
gSpectKeyPress := False;
if gSpectAuto then
g_Mons_ForEach(sendMonsPos);
+ // update flags that aren't stationary
+ if gGameSettings.GameMode = GM_CTF then
+ for I := FLAG_RED to FLAG_BLUE do
+ if gFlags[I].NeedSend then
+ begin
+ gFlags[I].NeedSend := False;
+ MH_SEND_FlagPos(I);
+ end;
+
+ // update items that aren't stationary
+ g_Items_ForEachAlive(sendItemPos);
+
if reliableUpdate then
begin
NetTimeToReliable := 0;
_y := _y+24;
end;
end;
+
+ // HACK: take stats screenshot immediately after the first frame of the stats showing
+ if gScreenshotStats and (not StatShotDone) and (Length(CustomStat.PlayerStat) > 1) then
+ begin
+ g_TakeScreenShot('stats/' + StatFilename);
+ StatShotDone := True;
+ end;
end;
procedure DrawSingleStat();
end
else
begin
- glScissor(0, 0, gWinSizeX, gWinSizeY);
+ glScissor(0, 0, gScreenWidth, gScreenHeight);
end;
// no need to clear stencil buffer, light blitting will do it for us... but only for normal scale
if (g_dbg_scale <> 1.0) then glClear(GL_STENCIL_BUFFER_BIT);
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
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
b := -py+(gPlayerScreenSize.Y div 2);
end;
- if p.IncCam <> 0 then
- begin
- if py > gMapInfo.Height-(gPlayerScreenSize.Y div 2) then
- begin
- if p.IncCam > 120-(py-(gMapInfo.Height-(gPlayerScreenSize.Y div 2))) then
- begin
- p.IncCam := 120-(py-(gMapInfo.Height-(gPlayerScreenSize.Y div 2)));
- end;
- end;
-
- if py < gPlayerScreenSize.Y div 2 then
- begin
- if p.IncCam < -120+((gPlayerScreenSize.Y div 2)-py) then
- begin
- p.IncCam := -120+((gPlayerScreenSize.Y div 2)-py);
- end;
- end;
-
- if p.IncCam < 0 then
- begin
- while (py+(gPlayerScreenSize.Y div 2)-p.IncCam > gMapInfo.Height) and (p.IncCam < 0) do p.IncCam := p.IncCam+1; //Inc(p.IncCam);
- end;
-
- if p.IncCam > 0 then
- begin
- while (py-(gPlayerScreenSize.Y div 2)-p.IncCam < 0) and (p.IncCam > 0) do p.IncCam := p.IncCam-1; //Dec(p.IncCam);
- end;
- end;
-
- if (px < gPlayerScreenSize.X div 2) or (gMapInfo.Width-gPlayerScreenSize.X <= 256) then c := 0
- else if (px > gMapInfo.Width-(gPlayerScreenSize.X div 2)) then c := gBackSize.X-gPlayerScreenSize.X
- else c := round((px-(gPlayerScreenSize.X div 2))/(gMapInfo.Width-gPlayerScreenSize.X)*(gBackSize.X-gPlayerScreenSize.X));
-
- if (py-p.IncCam <= gPlayerScreenSize.Y div 2) or (gMapInfo.Height-gPlayerScreenSize.Y <= 256) then d := 0
- else if (py-p.IncCam >= gMapInfo.Height-(gPlayerScreenSize.Y div 2)) then d := gBackSize.Y-gPlayerScreenSize.Y
- else d := round((py-p.IncCam-(gPlayerScreenSize.Y div 2))/(gMapInfo.Height-gPlayerScreenSize.Y)*(gBackSize.Y-gPlayerScreenSize.Y));
-
sX := -a;
- sY := -(b+p.IncCam);
+ sY := -b;
sWidth := gPlayerScreenSize.X;
sHeight := gPlayerScreenSize.Y;
+ fixViewportForScale();
- //glTranslatef(a, b+p.IncCam, 0);
-
- //if (p = gPlayer1) and (g_dbg_scale >= 1.0) then g_Holmes_plrViewSize(sWidth, sHeight);
+ i := py - (sY + sHeight div 2);
+ if (p.IncCam > 0) then
+ begin
+ // clamp to level bounds
+ if (sY - p.IncCam < 0) then
+ p.IncCam := nclamp(sY, 0, 120);
+ // clamp around player position
+ if (i > 0) then
+ p.IncCam := nclamp(p.IncCam, 0, max(0, 120 - i));
+ end
+ else if (p.IncCam < 0) then
+ begin
+ // clamp to level bounds
+ if (sY + sHeight - p.IncCam > gMapInfo.Height) then
+ p.IncCam := nclamp(sY + sHeight - gMapInfo.Height, -120, 0);
+ // clamp around player position
+ if (i < 0) then
+ p.IncCam := nclamp(p.IncCam, min(0, -120 - i), 0);
+ end;
- //conwritefln('OLD: (%s,%s)-(%s,%s)', [sX, sY, sWidth, sHeight]);
- fixViewportForScale();
- //conwritefln(' (%s,%s)-(%s,%s)', [sX, sY, sWidth, sHeight]);
+ sY := sY - nlerp(p.IncCamOld, p.IncCam, gLerpFactor);
- if (g_dbg_scale <> 1.0) and (not g_dbg_ignore_bounds) then
+ if (not g_dbg_ignore_bounds) then
begin
if (sX+sWidth > gMapInfo.Width) then sX := gMapInfo.Width-sWidth;
if (sY+sHeight > gMapInfo.Height) then sY := gMapInfo.Height-sHeight;
if (sX < 0) then sX := 0;
if (sY < 0) then sY := 0;
-
- if (gBackSize.X <= gPlayerScreenSize.X) or (gMapInfo.Width <= sWidth) then c := 0 else c := trunc((gBackSize.X-gPlayerScreenSize.X)*sX/(gMapInfo.Width-sWidth));
- if (gBackSize.Y <= gPlayerScreenSize.Y) or (gMapInfo.Height <= sHeight) then d := 0 else d := trunc((gBackSize.Y-gPlayerScreenSize.Y)*sY/(gMapInfo.Height-sHeight));
end;
+ if (gBackSize.X <= gPlayerScreenSize.X) or (gMapInfo.Width <= sWidth) then c := 0 else c := trunc((gBackSize.X-gPlayerScreenSize.X)*sX/(gMapInfo.Width-sWidth));
+ if (gBackSize.Y <= gPlayerScreenSize.Y) or (gMapInfo.Height <= sHeight) then d := 0 else d := trunc((gBackSize.Y-gPlayerScreenSize.Y)*sY/(gMapInfo.Height-sHeight));
+
//r_smallmap_h: 0: left; 1: center; 2: right
//r_smallmap_v: 0: top; 1: center; 2: bottom
// horiz small map?
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
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
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
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;
begin
g_Game_StopAllSounds(True);
gMusic.Free();
- g_Game_SaveOptions();
g_Game_FreeData();
g_PlayerModel_FreeData();
g_Texture_DeleteAll();
e_WriteLog(Format(_lc[I_FATAL_ERROR], [Text]), TMsgType.Warning);
gExit := EXIT_SIMPLE;
+ if gGameOn then EndGame;
end;
procedure g_SimpleError(Text: String);
procedure g_Game_ChangeResolution(newWidth, newHeight: Word; nowFull, nowMax: Boolean);
begin
- sys_SetDisplayMode(newWidth, newHeight, gBPP, nowFull);
+ sys_SetDisplayMode(newWidth, newHeight, gBPP, nowFull, nowMax);
end;
procedure g_Game_AddPlayer(Team: Byte = TEAM_NONE);
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;
else
begin
gPlayer1.Name := gPlayer1Settings.Name;
+ gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch;
+ gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences);
+ gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty;
+ gPlayer1.SkipFist := gPlayer1Settings.SkipFist;
g_Console_Add(Format(_lc[I_PLAYER_JOIN], [gPlayer1.Name]), True);
if g_Game_IsServer and g_Game_IsNet then
MH_SEND_PlayerCreate(gPlayer1.UID);
else
begin
gPlayer2.Name := gPlayer2Settings.Name;
+ gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch;
+ gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences);
+ gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty;
+ gPlayer2.SkipFist := gPlayer2Settings.SkipFist;
g_Console_Add(Format(_lc[I_PLAYER_JOIN], [gPlayer2.Name]), True);
if g_Game_IsServer and g_Game_IsNet then
MH_SEND_PlayerCreate(gPlayer2.UID);
g_Console_Add(Format(_lc[I_PLAYER_LEAVE], [Pl.Name]), True);
g_Player_Remove(Pl.UID);
g_Net_Slist_ServerPlayerLeaves();
- end else
+ end
+ else
+ begin
+ gSpectLatchPID2 := Pl.UID;
gPlayer2 := nil;
+ end;
Exit;
end;
Pl := gPlayer1;
g_Net_Slist_ServerPlayerLeaves();
end else
begin
+ gSpectLatchPID1 := Pl.UID;
gPlayer1 := nil;
MC_SEND_CheatRequest(NET_CHEAT_SPECTATE);
end;
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');
// Óñòàíîâêà ðàçìåðîâ îêîí èãðîêîâ:
end;
gPlayer1.Name := gPlayer1Settings.Name;
+ gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch;
+ gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences);
+ gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty;
+ gPlayer1.SkipFist := gPlayer1Settings.SkipFist;
nPl := 1;
// Ñîçäàíèå âòîðîãî èãðîêà, åñëè åñòü:
end;
gPlayer2.Name := gPlayer2Settings.Name;
+ gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch;
+ gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences);
+ gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty;
+ gPlayer2.SkipFist := gPlayer2Settings.SkipFist;
Inc(nPl);
end;
// Çàãðóçêà è çàïóñê êàðòû:
- if not g_Game_StartMap(MAP, True) then
+ if not g_Game_StartMap(false{asMegawad}, MAP, True) then
begin
if (Pos(':\', Map) > 0) or (Pos(':/', Map) > 0) then tmps := Map else tmps := gGameSettings.WAD + ':\' + MAP;
g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [tmps]));
gAimLine := False;
gShowMap := False;
+ gLMSRespawn := LMS_RESPAWN_NONE;
+ gLMSRespawnTime := 0;
+ gSpectLatchPID1 := 0;
+ gSpectLatchPID2 := 0;
+
g_Game_ExecuteEvent('ongamestart');
// Óñòàíîâêà ðàçìåðîâ îêîí èãðîêîâ:
end;
gPlayer1.Name := gPlayer1Settings.Name;
+ gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch;
+ gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences);
+ gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty;
+ gPlayer1.SkipFist := gPlayer1Settings.SkipFist;
Inc(nPl);
end;
end;
gPlayer2.Name := gPlayer2Settings.Name;
+ gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch;
+ gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences);
+ gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty;
+ gPlayer2.SkipFist := gPlayer2Settings.SkipFist;
Inc(nPl);
end;
// Çàãðóçêà è çàïóñê êàðòû:
- if not g_Game_StartMap(Map, True) then
+ if not g_Game_StartMap(true{asMegawad}, Map, True) then
begin
g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Map]));
Exit;
gAimLine := False;
gShowMap := False;
+ gLMSRespawn := LMS_RESPAWN_NONE;
+ gLMSRespawnTime := 0;
+ gSpectLatchPID1 := 0;
+ gSpectLatchPID2 := 0;
+
g_Game_ExecuteEvent('ongamestart');
// Óñòàíîâêà ðàçìåðîâ îêíà èãðîêà
end;
gPlayer1.Name := gPlayer1Settings.Name;
+ gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch;
+ gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences);
+ gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty;
+ gPlayer1.SkipFist := gPlayer1Settings.SkipFist;
end;
if nPlayers >= 2 then
end;
gPlayer2.Name := gPlayer2Settings.Name;
+ gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch;
+ gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences);
+ gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty;
+ gPlayer2.SkipFist := gPlayer2Settings.SkipFist;
end;
g_Game_SetLoadingText(_lc[I_LOAD_HOST], 0, False);
// Ñòàðòóåì ñåðâåð
if not g_Net_Host(IPAddr, Port, NetMaxClients) then
begin
- g_FatalError(_lc[I_NET_MSG] + _lc[I_NET_ERR_HOST]);
+ g_FatalError(_lc[I_NET_MSG] + Format(_lc[I_NET_ERR_HOST], [Port]));
Exit;
end;
- g_Net_Slist_Set(NetSlistIP, NetSlistPort, NetSlistList);
+ g_Net_Slist_Set(NetMasterList);
g_Net_Slist_ServerStarted();
// Çàãðóçêà è çàïóñê êàðòû:
- if not g_Game_StartMap(Map, True) then
+ if not g_Game_StartMap(false{asMegawad}, Map, True) then
begin
g_Net_Slist_ServerClosed();
g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Map]));
// 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
//if newResPath = '' then
begin
//g_Game_SetLoadingText(_lc[I_LOAD_DL_RES], 0, False);
- newResPath := g_Res_DownloadMapWAD(WadName, gWADHash);
+ newResPath := g_Res_DownloadMapWAD(ExtractFileName(WadName), gWADHash);
if newResPath = '' then
begin
g_FatalError(_lc[I_NET_ERR_HASH]);
end;
gPlayer1.Name := gPlayer1Settings.Name;
+ gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch;
+ gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences);
+ gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty;
+ gPlayer1.SkipFist := gPlayer1Settings.SkipFist;
gPlayer1.UID := NetPlrUID1;
gPlayer1.Reset(True);
- if not g_Game_StartMap(newResPath + ':\' + Map, True) then
+ if not g_Game_StartMap(false{asMegawad}, newResPath + ':\' + Map, True) then
begin
g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [WadName + ':\' + Map]));
Exit;
end;
- gLMSRespawn := LMS_RESPAWN_NONE;
- gLMSRespawnTime := 0;
-
g_Player_Init();
NetState := NET_STATE_GAME;
MC_SEND_FullStateRequest;
e_WriteLog('NET: Connection successful.', TMsgType.Notify);
end;
-procedure g_Game_SaveOptions;
- var s: AnsiString;
-begin
- s := e_GetWriteableDir(ConfigDirs);
- if s <> '' then
- g_Options_Write_Video(s + '/' + CONFIG_FILENAME)
- else
- e_LogWritefln('unable to find or create directory for configs', []);
-end;
+var
+ lastAsMegaWad: Boolean = false;
procedure g_Game_ChangeMap(const MapPath: String);
var
Force := False;
gExitByTrigger := False;
end;
- if not g_Game_StartMap(MapPath, Force) then
+ if not g_Game_StartMap(lastAsMegaWad, MapPath, Force) then
g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [MapPath]));
end;
MessageTime := 0;
gGameOn := False;
g_Game_ClearLoading();
- g_Game_StartMap(Map, True, gCurrentMapFileName);
+ g_Game_StartMap(lastAsMegaWad, Map, True, gCurrentMapFileName);
end;
-function g_Game_StartMap(Map: String; Force: Boolean = False; const oldMapPath: AnsiString=''): Boolean;
+function g_Game_StartMap (asMegawad: Boolean; Map: String; Force: Boolean = False; const oldMapPath: AnsiString=''): Boolean;
var
NewWAD, ResName: String;
I: Integer;
g_Player_ResetTeams();
+ lastAsMegaWad := asMegawad;
if isWadPath(Map) then
begin
NewWAD := g_ExtractWadName(Map);
begin
nws := findDiskWad(NewWAD);
//writeln('000: Map=[', Map, ']; nws=[', nws, ']; NewWAD=[', NewWAD, ']');
- if (length(nws) = 0) then nws := e_FindWad(MapDirs, NewWAD);
+ if (asMegawad) then
+ begin
+ if (length(nws) = 0) then nws := e_FindWad(MegawadDirs, NewWAD);
+ if (length(nws) = 0) then nws := e_FindWad(MapDirs, NewWAD);
+ end
+ else
+ begin
+ if (length(nws) = 0) then nws := e_FindWad(MapDirs, NewWAD);
+ if (length(nws) = 0) then nws := e_FindWad(MegawadDirs, NewWAD);
+ end;
+ //if (length(nws) = 0) then nws := e_FindWad(MapDownloadDirs, NewWAD);
//writeln('001: Map=[', Map, ']; nws=[', nws, ']; NewWAD=[', NewWAD, ']');
//nws := NewWAD;
if (length(nws) = 0) then
ResName := Map;
end;
+ gTime := 0;
+
//writeln('********: gsw=', gGameSettings.WAD, '; rn=', ResName);
result := false;
if (ResName <> '') and (NewWAD <> '') then
gExit := 0;
gPauseMain := false;
gPauseHolmes := false;
- gTime := 0;
NetTimeToUpdate := 1;
NetTimeToReliable := 0;
NetTimeToMaster := NetMasterRate;
- gLMSRespawn := LMS_RESPAWN_NONE;
- gLMSRespawnTime := 0;
+ gSpectLatchPID1 := 0;
+ gSpectLatchPID2 := 0;
gMissionFailed := False;
gNextMap := '';
g_Game_SpectateCenterView();
- if (gGameSettings.MaxLives > 0) and (gGameSettings.WarmupTime > 0) then
+ if g_Game_IsServer then
begin
- gLMSRespawn := LMS_RESPAWN_WARMUP;
- gLMSRespawnTime := gTime + gGameSettings.WarmupTime*1000;
- gLMSSoftSpawn := True;
- if NetMode = NET_SERVER then
- MH_SEND_GameEvent(NET_EV_LMS_WARMUP, (gLMSRespawnTime - gTime) div 1000)
+ if (gGameSettings.MaxLives > 0) and (gGameSettings.WarmupTime > 0) then
+ begin
+ gLMSRespawn := LMS_RESPAWN_WARMUP;
+ gLMSRespawnTime := gTime + gGameSettings.WarmupTime*1000;
+ gLMSSoftSpawn := True;
+ if g_Game_IsNet then
+ MH_SEND_GameEvent(NET_EV_LMS_WARMUP, gLMSRespawnTime - gTime);
+ end
else
- g_Console_Add(Format(_lc[I_MSG_WARMUP_START], [(gLMSRespawnTime - gTime) div 1000]), True);
+ begin
+ gLMSRespawn := LMS_RESPAWN_NONE;
+ gLMSRespawnTime := 0;
+ end;
end;
if NetMode = NET_SERVER then
Exit;
end;
-(*
- xwad := ExtractRelativePath(MapsDir, gWAD);
- e_LogWritefln('using downloaded client map wad [%s] for [%s]`', [xwad, NewWAD], TMsgType.Notify);
- NewWAD := xwad;
- g_Game_LoadWAD(NewWAD);
-*)
+ e_LogWritefln('using downloaded client map wad [%s] for [%s]', [gWAD, NewWAD], TMsgType.Notify);
+ NewWAD := gWAD;
- e_LogWritefln('using downloaded client map wad [%s]`', [NewWAD], TMsgType.Notify);
g_Game_LoadWAD(NewWAD);
result := NewWAD;
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;
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;
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;
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)]))
[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_friendly_absorb_damage' then
+ begin
+ ParseGameFlag(GAME_OPTION_TEAMABSORBDAMAGE, I_MSG_FRIENDLY_ABSORB_DAMAGE_OFF, I_MSG_FRIENDLY_ABSORB_DAMAGE_ON);
+ end
+ else if cmd = 'g_friendly_hit_trace' then
+ begin
+ ParseGameFlag(GAME_OPTION_TEAMHITTRACE, I_MSG_FRIENDLY_HIT_TRACE_OFF, I_MSG_FRIENDLY_HIT_TRACE_ON);
+ end
+ else if cmd = 'g_friendly_hit_projectile' then
+ begin
+ ParseGameFlag(GAME_OPTION_TEAMHITPROJECTILE, I_MSG_FRIENDLY_PROJECT_TRACE_OFF, I_MSG_FRIENDLY_PROJECT_TRACE_ON);
+ end
+ else if cmd = 'g_weaponstay' then
+ begin
+ ParseGameFlag(GAME_OPTION_WEAPONSTAY, I_MSG_WEAPONSTAY_OFF, I_MSG_WEAPONSTAY_ON);
+ end
+ else if cmd = 'g_allow_exit' then
+ begin
+ 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_allow_dropflag' then
+ begin
+ ParseGameFlag(GAME_OPTION_ALLOWDROPFLAG, I_MSG_ALLOWDROPFLAG_OFF, I_MSG_ALLOWDROPFLAG_ON);
+ end
+ else if cmd = 'g_throw_flag' then
+ begin
+ ParseGameFlag(GAME_OPTION_THROWFLAG, I_MSG_THROWFLAG_OFF, I_MSG_THROWFLAG_ON);
+ end
+ else if cmd = 'g_bot_vsplayers' then
+ begin
+ 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_allow_monsters') and not g_Game_IsClient then
+ else if cmd = 'g_gameflags' then
begin
- with gGameSettings do
+ 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_MONSTERS
- else
- Options := Options and (not GAME_OPTION_MONSTERS);
+ gGameSettings.Options := gsGameFlags;
+ if g_Game_IsNet then MH_SEND_GameSettings;
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;
+
+ g_Console_Add(Format('%s %u', [cmd, gsGameFlags]));
end
- else if (cmd = 'g_bot_vsplayers') 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_BOTVSPLAYER
- else
- Options := Options and (not GAME_OPTION_BOTVSPLAYER);
+ 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;
-
- 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;
+
+ 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_bot_vsmonsters') and not g_Game_IsClient then
+ else if cmd = 'g_spawn_invul' then
begin
- with gGameSettings do
+ if Length(P) > 1 then
begin
- if (Length(P) > 1) and
- ((P[1] = '1') or (P[1] = '0')) then
+ gsSpawnInvul := nclamp(StrToIntDef(P[1], gsSpawnInvul), 0, $FFFF);
+ 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.SpawnInvul := gsSpawnInvul;
+ 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 %d', [cmd, Integer(gsSpawnInvul)]));
end
- else if (cmd = 'g_warmuptime') 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.WarmupTime) = 0 then
- gGameSettings.WarmupTime := 30
- else
- gGameSettings.WarmupTime := StrToIntDef(P[1], gGameSettings.WarmupTime);
+ 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_WARMUP],
- [gGameSettings.WarmupTime]));
- 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 = 'net_interp' then
+ else if cmd = 'sv_intertime' 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
+ gDefInterTime := Min(Max(StrToIntDef(P[1], gDefInterTime), -1), 120);
+
+ g_Console_Add(cmd + ' = ' + IntToStr(gDefInterTime));
end
- else if cmd = 'net_forceplayerupdate' then
+ else if cmd = 'g_max_particles' 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
+ if Length(p) = 2 then
begin
- config := TConfig.CreateFile(s + '/' + CONFIG_FILENAME);
- config.WriteBool('Client', 'ForcePlayerUpdate', NetForcePlayerUpdate);
- config.SaveFile(s + '/' + CONFIG_FILENAME);
- config.Free
+ a := Max(0, StrToIntDef(p[1], 0));
+ g_GFX_SetMax(a)
+ end
+ else if Length(p) = 1 then
+ begin
+ e_LogWritefln('%s', [g_GFX_GetMax()])
end
- end
- else if cmd = 'net_predictself' 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
+ e_LogWritefln('usage: %s <n>', [cmd])
end
end
- else if cmd = 'sv_name' then
+ else if cmd = 'g_max_shells' then
begin
- if (Length(P) > 1) and (Length(P[1]) > 0) then
+ if Length(p) = 2 then
begin
- NetServerName := P[1];
- if Length(NetServerName) > 64 then
- SetLength(NetServerName, 64);
- g_Net_Slist_ServerRenamed();
- end;
-
- g_Console_Add(cmd + ' = "' + NetServerName + '"');
+ a := Max(0, StrToIntDef(p[1], 0));
+ 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 <n>', [cmd])
+ end
end
- else if cmd = 'sv_passwd' then
+ else if cmd = 'g_max_gibs' then
begin
- if (Length(P) > 1) and (Length(P[1]) > 0) then
+ if Length(p) = 2 then
begin
- NetPassword := P[1];
- if Length(NetPassword) > 24 then
- SetLength(NetPassword, 24);
- g_Net_Slist_ServerRenamed();
- end;
-
- g_Console_Add(cmd + ' = "' + AnsiLowerCase(NetPassword) + '"');
+ a := Max(0, StrToIntDef(p[1], 0));
+ 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 <n>', [cmd])
+ end
end
- else if cmd = 'sv_maxplrs' then
+ else if cmd = 'g_max_corpses' then
begin
- if (Length(P) > 1) then
+ if Length(p) = 2 then
begin
- NetMaxClients := Min(Max(StrToIntDef(P[1], NetMaxClients), 1), NET_MAXCLIENTS);
- if g_Game_IsServer and g_Game_IsNet then
+ a := Max(0, StrToIntDef(p[1], 0));
+ 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 <n>', [cmd])
+ end
+ end
+ else if cmd = 'g_scorelimit' then
+ begin
+ if Length(P) > 1 then
+ begin
+ gsGoalLimit := nclamp(StrToIntDef(P[1], gsGoalLimit), 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();
+ 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(cmd + ' = ' + IntToStr(NetMaxClients));
+ g_Console_Add(Format(_lc[I_MSG_SCORE_LIMIT], [Integer(gsGoalLimit)]));
end
- else if cmd = 'sv_public' then
+ else if cmd = 'g_timelimit' 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();
+ 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(cmd + ' = ' + IntToStr(Byte(NetUseMaster)));
+ g_Console_Add(Format(_lc[I_MSG_TIME_LIMIT],
+ [gsTimeLimit div 3600,
+ (gsTimeLimit div 60) mod 60,
+ gsTimeLimit mod 60]));
end
- else if cmd = 'sv_intertime' then
+ else if cmd = 'g_max_bots' then
begin
- if (Length(P) > 1) then
- gDefInterTime := Min(Max(StrToIntDef(P[1], gDefInterTime), -1), 120);
-
- g_Console_Add(cmd + ' = ' + IntToStr(gDefInterTime));
+ if Length(P) > 1 then
+ gMaxBots := nclamp(StrToIntDef(P[1], gMaxBots), 0, 127);
+ g_Console_Add('g_max_bots = ' + IntToStr(gMaxBots));
end
- else if cmd = 'p1_name' then
+ else if cmd = 'g_maxlives' then
begin
- if (Length(P) > 1) and gGameOn then
+ if Length(P) > 1 then
begin
- if g_Game_IsClient then
+ gsMaxLives := nclamp(StrToIntDef(P[1], gsMaxLives), 0, $FFFF);
+ if g_Game_IsServer then
begin
- gPlayer1Settings.Name := b_Text_Unformat(P[1]);
- MC_SEND_PlayerSettings;
- end
- else
- if gPlayer1 <> nil then
- begin
- gPlayer1.Name := b_Text_Unformat(P[1]);
- if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer1.UID);
- end
- else
- gPlayer1Settings.Name := b_Text_Unformat(P[1]);
+ gGameSettings.MaxLives := gsMaxLives;
+ if g_Game_IsNet then MH_SEND_GameSettings;
+ end;
end;
- end
- else if cmd = 'p2_name' then
+
+ g_Console_Add(Format(_lc[I_MSG_LIVES], [Integer(gsMaxLives)]));
+ end;
+end;
+
+procedure PlayerSettingsCVars(P: SSArray);
+var
+ cmd: string;
+ team: Byte;
+
+ function ParseTeam(s: string): Byte;
begin
- if (Length(P) > 1) and gGameOn then
- begin
- if g_Game_IsClient then
+ 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
- gPlayer2Settings.Name := b_Text_Unformat(P[1]);
- MC_SEND_PlayerSettings;
- end
- else
- if gPlayer2 <> nil then
+ 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
+ gPlayer1.Name := b_Text_Unformat(P[1]);
+ if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer1.UID);
+ end;
+ end;
+ end;
+ 'p2_name':
+ begin
+ if (Length(P) > 1) then
begin
- gPlayer2.Name := b_Text_Unformat(P[1]);
- if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer2.UID);
- end
- else
gPlayer2Settings.Name := b_Text_Unformat(P[1]);
- end;
- end
- else if cmd = 'p1_color' then
- begin
- if Length(P) > 3 then
- if g_Game_IsClient then
+ 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
- gPlayer1Settings.Color := _RGB(EnsureRange(StrToIntDef(P[1], 0), 0, 255),
- EnsureRange(StrToIntDef(P[2], 0), 0, 255),
- EnsureRange(StrToIntDef(P[3], 0), 0, 255));
- MC_SEND_PlayerSettings;
- end
- else
- if gPlayer1 <> nil then
+ if Length(P) > 3 then
begin
- gPlayer1.Model.SetColor(EnsureRange(StrToIntDef(P[1], 0), 0, 255),
- EnsureRange(StrToIntDef(P[2], 0), 0, 255),
- EnsureRange(StrToIntDef(P[3], 0), 0, 255));
- if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer1.UID);
- end
- else
gPlayer1Settings.Color := _RGB(EnsureRange(StrToIntDef(P[1], 0), 0, 255),
EnsureRange(StrToIntDef(P[2], 0), 0, 255),
EnsureRange(StrToIntDef(P[3], 0), 0, 255));
- end
- else if (cmd = 'p2_color') and not g_Game_IsNet then
- begin
- if Length(P) > 3 then
- if g_Game_IsClient then
+ 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
- gPlayer2Settings.Color := _RGB(EnsureRange(StrToIntDef(P[1], 0), 0, 255),
- EnsureRange(StrToIntDef(P[2], 0), 0, 255),
- EnsureRange(StrToIntDef(P[3], 0), 0, 255));
- MC_SEND_PlayerSettings;
- end
- else
- if gPlayer2 <> nil then
+ if Length(P) > 3 then
begin
- gPlayer2.Model.SetColor(EnsureRange(StrToIntDef(P[1], 0), 0, 255),
- EnsureRange(StrToIntDef(P[2], 0), 0, 255),
- EnsureRange(StrToIntDef(P[3], 0), 0, 255));
- if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer2.UID);
- end
- else
gPlayer2Settings.Color := _RGB(EnsureRange(StrToIntDef(P[1], 0), 0, 255),
EnsureRange(StrToIntDef(P[2], 0), 0, 255),
EnsureRange(StrToIntDef(P[3], 0), 0, 255));
- end
- else if gGameSettings.GameType in [GT_CUSTOM, GT_SERVER, GT_CLIENT] 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
- 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])
- 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');
-
- 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');
-
- 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
+ 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 StrToIntDef(P[1], gGameSettings.GoalLimit) = 0 then
- gGameSettings.GoalLimit := 0
- else
+ 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
- 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.FActualModelName := gPlayer1Settings.Model;
+ gPlayer1.SetModel(gPlayer1Settings.Model);
+ 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_model':
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.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;
-
- g_Console_Add(Format(_lc[I_MSG_LIVES],
- [gGameSettings.MaxLives]));
- if g_Game_IsNet then MH_SEND_GameSettings;
- 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;
+ 'p1_autoswitch':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponSwitch := EnsureRange(StrTointDef(P[1], 0), 0, 2);
+ end;
+ 'p2_autoswitch':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponSwitch := EnsureRange(StrTointDef(P[1], 0), 0, 2);
+ end;
+ 'p1_switch_empty':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.SwitchToEmpty := EnsureRange(StrTointDef(P[1], 0), 0, 1);
+ end;
+ 'p2_switch_empty':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.SwitchToEmpty := EnsureRange(StrTointDef(P[1], 0), 0, 1);
+ end;
+ 'p1_skip_fist':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.SkipFist := EnsureRange(StrTointDef(P[1], 0), 0, 1);
+ end;
+ 'p2_skip_fist':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.SkipFist := EnsureRange(StrTointDef(P[1], 0), 0, 1);
+ end;
+ 'p1_priority_kastet':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WEAPON_KASTET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_kastet':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WEAPON_KASTET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p1_priority_saw':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WEAPON_SAW] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_saw':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WEAPON_SAW] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p1_priority_pistol':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WEAPON_KASTET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_pistol':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WEAPON_KASTET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p1_priority_shotgun1':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WEAPON_SHOTGUN1] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_shotgun1':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WEAPON_SHOTGUN1] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p1_priority_shotgun2':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WEAPON_SHOTGUN2] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_shotgun2':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WEAPON_SHOTGUN2] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p1_priority_chaingun':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WEAPON_CHAINGUN] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_chaingun':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WEAPON_CHAINGUN] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p1_priority_rocketlauncher':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WEAPON_ROCKETLAUNCHER] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_rocketlauncher':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WEAPON_ROCKETLAUNCHER] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p1_priority_plasma':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WEAPON_PLASMA] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_plasma':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WEAPON_PLASMA] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p1_priority_bfg':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WEAPON_BFG] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_bfg':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WEAPON_BFG] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p1_priority_super':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WEAPON_SUPERPULEMET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_super':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WEAPON_SUPERPULEMET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p1_priority_flamethrower':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WEAPON_FLAMETHROWER] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_flamethrower':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WEAPON_FLAMETHROWER] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p1_priority_berserk':
+ begin
+ if (Length(P) = 2) then
+ gPlayer1Settings.WeaponPreferences[WP_LAST+1] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
+ 'p2_priority_berserk':
+ begin
+ if (Length(P) = 2) then
+ gPlayer2Settings.WeaponPreferences[WP_LAST+1] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+ end;
end;
end;
cmd := LowerCase(P[0]);
if cmd = 'd_window' then
begin
- g_Console_Add(Format('gWinPosX = %d, gWinPosY %d', [gWinPosX, gWinPosY]));
- g_Console_Add(Format('gWinRealPosX = %d, gWinRealPosY %d', [gWinRealPosX, gWinRealPosY]));
g_Console_Add(Format('gScreenWidth = %d, gScreenHeight = %d', [gScreenWidth, gScreenHeight]));
- g_Console_Add(Format('gWinSizeX = %d, gWinSizeY = %d', [gWinSizeX, gWinSizeY]));
- g_Console_Add(Format('Frame X = %d, Y = %d, Caption Y = %d', [gWinFrameX, gWinFrameY, gWinCaption]));
+ g_Console_Add(Format('gScreenWidth = %d, gScreenHeight = %d', [gScreenWidth, gScreenHeight]));
end
else if cmd = 'd_sounds' then
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);
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 <player ID>');
+ Exit;
+ end;
+ if P[1] = '' then
+ begin
+ g_Console_Add('kick_pid <player ID>');
+ 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
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 <player ID>');
+ Exit;
+ end;
+ if P[1] = '' then
+ begin
+ g_Console_Add('ban_pid <player ID>');
+ 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
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 <player ID>');
+ Exit;
+ end;
+ if P[1] = '' then
+ begin
+ g_Console_Add('permban_pid <player ID>');
+ 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 <IP address>');
+ Exit;
+ end;
+ if P[1] = '' then
+ begin
+ g_Console_Add('permban_ip <IP address>');
+ 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
end else
g_Console_Add(_lc[I_MSG_GM_UNAVAIL]);
end
+ else if (cmd = 'an') or (cmd = 'announce') then
+ begin
+ if g_Game_IsNet then
+ begin
+ if Length(P) > 1 then
+ begin
+ for a := 1 to High(P) do
+ chstr := chstr + P[a] + ' ';
+
+ if Length(chstr) > 200 then SetLength(chstr, 200);
+
+ if Length(chstr) < 1 then
+ begin
+ g_Console_Add('announce <text>');
+ Exit;
+ end;
+
+ chstr := 'centerprint 100 ' + b_Text_Format(chstr);
+ if g_Game_IsClient then
+ MC_SEND_RCONCommand(chstr)
+ else
+ g_Console_Process(chstr, True);
+ end
+ else
+ g_Console_Add('announce <text>');
+ end else
+ g_Console_Add(_lc[I_MSG_GM_UNAVAIL]);
+ end
else if cmd = 'game' then
begin
if gGameSettings.GameType <> GT_NONE then
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;
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;
if found then
begin
// no such map, found wad
+ pw := P[1];
SetLength(P, 3);
P[1] := ExpandFileName(pw);
P[2] := g_Game_GetFirstMap(P[1]);
begin
g_TakeScreenShot()
end
+ else if (cmd = 'weapnext') or (cmd = 'weapprev') then
+ begin
+ a := 1 - (ord(cmd[5]) - ord('n'));
+ if a = -1 then
+ gWeaponAction[0, WP_PREV] := True;
+ if a = 1 then
+ gWeaponAction[0, WP_NEXT] := True;
+ end
else if cmd = 'weapon' then
begin
if Length(p) = 2 then
begin
- a := WP_FIRST + StrToInt(p[1]) - 1;
+ a := WP_FIRST + StrToIntDef(p[1], 0) - 1;
if (a >= WP_FIRST) and (a <= WP_LAST) then
gSelectWeapon[0, a] := True
end
end
+ else if (cmd = 'p1_weapnext') or (cmd = 'p1_weapprev')
+ or (cmd = 'p2_weapnext') or (cmd = 'p2_weapprev') then
+ begin
+ a := 1 - (ord(cmd[8]) - ord('n'));
+ b := ord(cmd[2]) - ord('1');
+ if a = -1 then
+ gWeaponAction[b, WP_PREV] := True;
+ if a = 1 then
+ gWeaponAction[b, WP_NEXT] := True;
+ end
else if (cmd = 'p1_weapon') or (cmd = 'p2_weapon') then
begin
if Length(p) = 2 then
begin
- a := WP_FIRST + StrToInt(p[1]) - 1;
+ a := WP_FIRST + StrToIntDef(p[1], 0) - 1;
b := ord(cmd[2]) - ord('1');
if (a >= WP_FIRST) and (a <= WP_LAST) then
gSelectWeapon[b, a] := True
end
end
+ else if (cmd = 'p1_weapbest') or (cmd = 'p2_weapbest') then
+ begin
+ b := ord(cmd[2]) - ord('1');
+ if b = 0 then
+ gSelectWeapon[b, gPlayer1.GetMorePrefered()] := True
+ else
+ gSelectWeapon[b, gPlayer2.GetMorePrefered()] := True;
+ end
+ else if (cmd = 'dropflag') then
+ begin
+ if g_Game_IsServer then
+ begin
+ if gPlayer2 <> nil then gPlayer2.TryDropFlag();
+ if gPlayer1 <> nil then gPlayer1.TryDropFlag();
+ end
+ else
+ MC_SEND_CheatRequest(NET_CHEAT_DROPFLAG);
+ end
+ else if (cmd = 'p1_dropflag') or (cmd = 'p2_dropflag') then
+ begin
+ b := ord(cmd[2]) - ord('1');
+ if g_Game_IsServer then
+ begin
+ if (b = 1) and (gPlayer2 <> nil) then gPlayer2.TryDropFlag()
+ else if (b = 0) and (gPlayer1 <> nil) then gPlayer1.TryDropFlag();
+ end
+ else
+ MC_SEND_CheatRequest(NET_CHEAT_DROPFLAG);
+ end
// Êîìàíäû Ñâîåé èãðû:
else if gGameSettings.GameType in [GT_CUSTOM, GT_SERVER, GT_CLIENT] then
begin
end else
g_Console_Add(_lc[I_MSG_SERVERONLY]);
end
+ else if cmd = 'centerprint' then
+ begin
+ if (Length(P) > 2) and (P[1] <> '') then
+ begin
+ chstr := '';
+ for a := 2 to High(P) do
+ chstr := chstr + P[a] + ' ';
+
+ if Length(chstr) > 200 then SetLength(chstr, 200);
+
+ if Length(chstr) < 1 then
+ begin
+ g_Console_Add('centerprint <timeout> <text>');
+ Exit;
+ end;
+
+ a := StrToIntDef(P[1], 100);
+ chstr := b_Text_Format(chstr);
+ g_Game_Message(chstr, a);
+ if g_Game_IsNet and g_Game_IsServer then
+ MH_SEND_GameEvent(NET_EV_BIGTEXT, a, chstr);
+ end
+ else g_Console_Add('centerprint <timeout> <text>');
+ end
else if (cmd = 'overtime') and not g_Game_IsClient then
begin
if (Length(P) = 1) or (StrToIntDef(P[1], -1) <= 0) then
end;
end;
-procedure g_TakeScreenShot;
- var s: TStream; t: TDateTime; date, name: String;
+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 <English|Russian|Ask>', [cmd]);
+ end
+ end;
+ end;
+end;
+
+procedure g_TakeScreenShot(Filename: string = '');
+ var s: TStream; t: TDateTime; dir, date, name: String;
begin
if e_NoGraphics then Exit;
- t := Now;
- DateTimeToString(date, 'yyyy-mm-dd-hh-nn-ss', t);
- name := 'screenshot-' + date + '.png';
try
- s := e_CreateResource(ScreenshotDirs, name);
- e_MakeScreenshot(s, gScreenWidth, gScreenHeight);
- g_Console_Add(Format(_lc[I_CONSOLE_SCREENSHOT], [name]))
+ dir := e_GetWriteableDir(ScreenshotDirs);
+
+ if Filename = '' then
+ begin
+ t := Now;
+ DateTimeToString(date, 'yyyy-mm-dd-hh-nn-ss', t);
+ Filename := 'screenshot-' + date;
+ end;
+
+ name := e_CatPath(dir, Filename + '.png');
+ s := createDiskFile(name);
+ try
+ e_MakeScreenshot(s, gWinSizeX, gWinSizeY);
+ s.Free;
+ g_Console_Add(Format(_lc[I_CONSOLE_SCREENSHOT], [name]))
+ except
+ g_Console_Add(Format(_lc[I_CONSOLE_ERROR_WRITE], [name]));
+ s.Free;
+ DeleteFile(name)
+ end
except
g_Console_Add('oh shit, i can''t create screenshot!')
end
case gAnnouncer of
ANNOUNCE_NONE:
Exit;
- ANNOUNCE_ME,
- ANNOUNCE_MEPLUS:
+ ANNOUNCE_ME:
if not g_Game_IsWatchedPlayer(SpawnerUID) then
Exit;
end;
while i <= ParamCount do
begin
s := ParamStr(i);
- if (s[1] = '-') and (Length(s) > 1) then
+ if (Length(s) > 1) and (s[1] = '-') then
begin
- if (s[2] = '-') and (Length(s) > 2) then
+ if (Length(s) > 2) and (s[2] = '-') then
begin // Îäèíî÷íûé ïàðàìåòð
SetLength(pars, Length(pars) + 1);
with pars[High(pars)] do
// 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');
conRegVar('dbg_ignore_level_bounds', @g_dbg_ignore_bounds, 'ignore level bounds', '', false);
conRegVar('r_scale', @g_dbg_scale, 0.01, 100.0, 'render scale', '', false);
+ conRegVar('r_resolution_scale', @r_pixel_scale, 0.01, 100.0, 'upscale factor', '', false);
conRegVar('light_enabled', @gwin_k8_enable_light_experiments, 'enable/disable dynamic lighting', 'lighting');
conRegVar('light_player_halo', @g_playerLight, 'enable/disable player halo', 'player light halo');
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.