diff --git a/src/game/g_game.pas b/src/game/g_game.pas
index acb2a76373fb576c878e081c77be75b60b4b98b5..d7b9b2d020e1d2a2d12e4550da90fa192526ea12 100644 (file)
--- a/src/game/g_game.pas
+++ b/src/game/g_game.pas
- (* Copyright (C) Doom 2D: Forever Developers
+(* Copyright (C) Doom 2D: Forever Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
procedure g_Game_Announce_BodyKill(SpawnerUID: Word);
procedure g_Game_StartVote(Command, Initiator: string);
procedure g_Game_CheckVote;
-{$IFDEF ENABLE_RENDER}
- procedure g_TakeScreenShot(Filename: string = '');
-{$ENDIF}
procedure g_FatalError(Text: String);
procedure g_SimpleError(Text: String);
function g_Game_IsTestMap(): Boolean;
procedure GameCheats(P: SSArray);
procedure DebugCommands(P: SSArray);
procedure g_Game_Process_Params;
-procedure g_Game_SetLoadingText(Text: String; Max: Integer; reWrite: Boolean);
-procedure g_Game_StepLoading(Value: Integer = -1);
-procedure g_Game_ClearLoading();
procedure g_Game_SetDebugMode();
function IsActivePlayer(p: TPlayer): Boolean;
const
GAME_TICK = 28;
- LOADING_SHOW_STEP = 100;
- LOADING_INTERLINE = 20;
-
GT_NONE = 0;
GT_SINGLE = 1;
GT_CUSTOM = 2;
gPlayer2Settings: TPlayerSettings;
gGameOn: Boolean;
gPlayerScreenSize: TDFPoint;
- gPlayer1ScreenCoord: TDFPoint;
- gPlayer2ScreenCoord: TDFPoint;
gPlayer1: TPlayer = nil;
gPlayer2: TPlayer = nil;
- gPlayerDrawn: TPlayer = nil;
gTime: LongWord;
gLerpFactor: Single = 1.0;
gSwitchGameMode: Byte = GM_DM;
gHearPoint1, gHearPoint2: THearPoint;
+ gMaxDist: Integer = 1; // for sound
gSoundEffectsDF: Boolean = False;
gSoundTriggerTime: Word = 0;
gAnnouncer: Integer = ANNOUNCE_NONE;
gRC_FullScreen, gRC_Maximized: Boolean;
gLanguageChange: Boolean = False;
gDebugMode: Boolean = False;
- g_debug_Sounds: Boolean = False;
- g_debug_Frames: Boolean = False;
g_debug_WinMsgs: Boolean = False;
g_debug_MonsterOff: Boolean = False;
g_debug_BotAIOff: Byte = 0;
- g_debug_HealthBar: Boolean = False;
g_Debug_Player: Boolean = False;
gCoopMonstersKilled: Word = 0;
gCoopSecretsFound: Word = 0;
TotalSecrets: Integer;
end;
- TLoadingStat = record
- CurValue: Integer;
- MaxValue: Integer;
- ShowCount: Integer;
- Msgs: Array of String;
- NextMsg: Word;
- PBarWasHere: Boolean; // did we draw a progress bar for this message?
- end;
-
TDynLight = record
x, y, radius: Integer;
r, g, b, a: Single;
StatShotDone: Boolean;
StatFilename: string = ''; // used by stat screenshot to save with the same name as the csv
SingleStat: TEndSingleGameStat;
- LoadingStat: TLoadingStat;
MessageText: String;
IsDrawStat: Boolean;
EndingGameCounter: Byte;
procedure ClearDebugCvars();
begin
- g_debug_Sounds := False;
- g_debug_Frames := False;
g_debug_WinMsgs := False;
g_debug_MonsterOff := False;
g_debug_BotAIOff := 0;
- g_debug_HealthBar := False;
g_Debug_Player := False;
end;
sfsGCDisable(); // temporary disable removing of temporary volumes
try
- g_Game_ClearLoading();
- g_Game_SetLoadingText(Format('Doom 2D: Forever %s', [GAME_VERSION]), 0, False);
- g_Game_SetLoadingText('', 0, False);
-
-// g_Game_SetLoadingText(_lc[I_LOAD_MODELS], 0, False);
-
gGameOn := false;
gPauseMain := false;
gPauseHolmes := false;
{e_MouseInfo.Accel := 1.0;}
- g_Game_SetLoadingText(_lc[I_LOAD_GAME_DATA], 0, False);
g_Game_LoadData();
g_Game_SetLoadingText(_lc[I_LOAD_MUSIC], 0, False);
{$IFDEF ENABLE_GIBS}
g_Gibs_RemoveAll;
{$ENDIF}
- {$IFDEF ENALBE_SHELLS}
+ {$IFDEF ENABLE_SHELLS}
g_Shells_RemoveAll;
{$ENDIF}
{$IFDEF ENABLE_CORPSES}
g_Weapon_PreUpdate();
end;
+ procedure g_Game_SetupHearPoints;
+ var p1, p2: TPlayer; a, b: Integer;
+ begin
+ p1 := nil;
+ p2 := nil;
+ gHearPoint1.Active := false;
+ gHearPoint2.Active := false;
+ if gSpectMode = SPECT_MAPVIEW then
+ begin
+ // TODO something better (render dependency)
+ gHearPoint1.Active := true;
+ gHearPoint1.Coords.X := gSpectX + gScreenWidth div 2;
+ gHearPoint1.Coords.Y := gSpectY + gScreenHeight div 2;
+ end
+ else if gSpectMode = SPECT_PLAYERS then
+ begin
+ p1 := g_Player_Get(gSpectPID1);
+ if gSpectViewTwo then
+ p2 := g_Player_Get(gSpectPID2);
+ end
+ else if gSpectMode = SPECT_NONE then
+ begin
+ p1 := gPlayer1;
+ p2 := gPlayer2;
+ end;
+ if p1 <> nil then
+ begin
+ gHearPoint1.Active := true;
+ gHearPoint1.Coords.X := p1.obj.x + p1.obj.rect.width div 2;
+ gHearPoint1.Coords.Y := p1.obj.y + p1.obj.rect.height div 2;
+ end;
+ if (p2 <> nil) and (p1 <> p2) then
+ begin
+ gHearPoint2.Active := true;
+ gHearPoint2.Coords.X := p2.obj.x + p2.obj.rect.width div 2;
+ gHearPoint2.Coords.Y := p2.obj.y + p2.obj.rect.height div 2;
+ end;
+ // TODO something better (render dependency)
+ if (p1 <> nil) and (p2 <> nil) then
+ begin
+ gPlayerScreenSize.X := gScreenWidth - 196;
+ gPlayerScreenSize.Y := gScreenHeight div 2;
+ end
+ else
+ begin
+ gPlayerScreenSize.X := gScreenWidth - 196;
+ gPlayerScreenSize.Y := gScreenHeight;
+ end;
+ // sound distance
+ if gMapInfo.Height > gPlayerScreenSize.Y then a := gMapInfo.Height - gPlayerScreenSize.Y else a := gMapInfo.Height;
+ if gMapInfo.Width > gPlayerScreenSize.X then b := gMapInfo.Width - gPlayerScreenSize.X else b := gMapInfo.Width;
+ gMaxDist := Trunc(Hypot(a, b));
+ end;
+
procedure g_Game_Update();
var
{$IFDEF ENABLE_MENU}
var
reliableUpdate: Boolean;
+ rSpectX0, rSpectY0: Integer;
+ rSpectX1, rSpectY1: Integer;
begin
g_ResetDynlights();
framePool.reset();
// process weapon switch queue
end; // if server
- // Наблюдатель
+ // Spectator
+
+ {$IFDEF ENABLE_RENDER}
+ r_Render_GetSpectatorLimits(rSpectX0, rSpectY0, rSpectX1, rSpectY1);
+ {$ELSE}
+ rSpectX0 := 0; rSpectY0 := 0;
+ rSpectX1 := gMapInfo.Width - 1; rSpectY1 := gMapInfo.Height - 1;
+ {$ENDIF}
+
if (gPlayer1 = nil) and (gPlayer2 = nil)
and (not gConsoleShow) and (not gChatShow)
{$IFDEF ENABLE_MENU}
if (gSpectMode = SPECT_MAPVIEW)
and (not gSpectAuto) then
begin
- if gPlayerAction[0, ACTION_MOVELEFT] then
- gSpectX := Max(gSpectX - gSpectStep, 0);
- if gPlayerAction[0, ACTION_MOVERIGHT] then
- gSpectX := Min(gSpectX + gSpectStep, gMapInfo.Width - gScreenWidth);
- if gPlayerAction[0, ACTION_LOOKUP] then
- gSpectY := Max(gSpectY - gSpectStep, 0);
- if gPlayerAction[0, ACTION_LOOKDOWN] then
- gSpectY := Min(gSpectY + gSpectStep, gMapInfo.Height - gScreenHeight);
+ if gPlayerAction[0, ACTION_MOVELEFT] then gSpectX := gSpectX - gSpectStep;
+ if gPlayerAction[0, ACTION_MOVERIGHT] then gSpectX := gSpectX + gSpectStep;
+ if gPlayerAction[0, ACTION_LOOKUP] then gSpectY := gSpectY - gSpectStep;
+ if gPlayerAction[0, ACTION_LOOKDOWN] then gSpectY := gSpectY + gSpectStep;
if gWeaponAction[0, WP_PREV] then
begin
// decrease step
begin
if gSpectMode = SPECT_MAPVIEW then
begin
- i := Min(Max(gSpectX + gSpectAutoStepX, 0), gMapInfo.Width - gScreenWidth);
+ i := Min(Max(gSpectX + gSpectAutoStepX, rSpectX0), rSpectX1);
if i = gSpectX then
gSpectAutoNext := gTime
else
gSpectX := i;
- i := Min(Max(gSpectY + gSpectAutoStepY, 0), gMapInfo.Height - gScreenHeight);
+ i := Min(Max(gSpectY + gSpectAutoStepY, rSpectY0), rSpectY1);
if i = gSpectY then
gSpectAutoNext := gTime
else
case gSpectMode of
SPECT_MAPVIEW:
begin
- gSpectX := Random(gMapInfo.Width - gScreenWidth);
- gSpectY := Random(gMapInfo.Height - gScreenHeight);
+ gSpectX := rSpectX0 + Random(rSpectX1 - rSpectX0);
+ gSpectY := rSpectY0 + Random(rSpectY1 - rSpectY0);
gSpectAutoStepX := Random(9) - 4;
gSpectAutoStepY := Random(9) - 4;
- if ((gSpectX < 800) and (gSpectAutoStepX < 0)) or
- ((gSpectX > gMapInfo.Width - gScreenWidth - 800) and (gSpectAutoStepX > 0)) then
+ if ((gSpectX < rSpectX0) and (gSpectAutoStepX < 0)) or
+ ((gSpectX > rSpectX1) and (gSpectAutoStepX > 0)) then
gSpectAutoStepX := gSpectAutoStepX * -1;
- if ((gSpectY < 800) and (gSpectAutoStepY < 0)) or
- ((gSpectY > gMapInfo.Height - gScreenHeight - 800) and (gSpectAutoStepY > 0)) then
+ if ((gSpectY < rSpectY0) and (gSpectAutoStepY < 0)) or
+ ((gSpectY > rSpectY1) and (gSpectAutoStepY > 0)) then
gSpectAutoStepY := gSpectAutoStepY * -1;
end;
SPECT_PLAYERS:
end;
end;
end;
+
+ if gSpectMode = SPECT_MAPVIEW then
+ begin
+ gSpectX := Max(gSpectX, rSpectX0);
+ gSpectX := Min(gSpectX, rSpectX1);
+ gSpectY := Max(gSpectY, rSpectY0);
+ gSpectY := Min(gSpectY, rSpectY1);
+ end;
end;
(* spectator state check from render *)
- if (gPlayer1 = nil) and (gPlayer2 = nil) and (gSpectMode = SPECT_NONE) then
- gSpectMode := SPECT_STATS;
+ if (gPlayer1 = nil) and (gPlayer2 = nil) then
+ begin
+ (* no local players -> automatically enable to spectator mode *)
+ if gSpectMode = SPECT_NONE then gSpectMode := SPECT_STATS;
+ end
+ else
+ begin
+ (* at least one local player -> automatically disable spectator mode *)
+ gSpectMode := SPECT_NONE;
+ end;
if IsActivePlayer(g_Player_Get(gSpectPID1)) = false then
gSpectPID1 := GetActivePlayerID_Next();
if IsActivePlayer(g_Player_Get(gSpectPID2)) = false then
gSpectPID2 := GetActivePlayerID_Next();
+ g_Game_SetupHearPoints;
+
// Обновляем все остальное:
g_Map_Update();
g_Items_Update();
if DataLoaded then Exit;
e_WriteLog('Loading game data...', TMsgType.Notify);
+ g_Game_SetLoadingText(_lc[I_LOAD_GAME_DATA], 0, False);
g_Sound_CreateWADEx('SOUND_GAME_TELEPORT', GameWAD+':SOUNDS\TELEPORT');
g_Sound_CreateWADEx('SOUND_GAME_NOTELEPORT', GameWAD+':SOUNDS\NOTELEPORT');
g_Game_LoadChatSounds(GameWAD+':CHATSND\SNDCFG');
- g_Game_SetLoadingText(_lc[I_LOAD_ITEMS_DATA], 0, False);
g_Items_LoadData();
- g_Game_SetLoadingText(_lc[I_LOAD_WEAPONS_DATA], 0, False);
g_Weapon_LoadData();
g_Monsters_LoadData();
{$IFDEF ENABLE_GIBS}
g_Gibs_RemoveAll;
{$ENDIF}
- {$IFDEF ENALBE_SHELLS}
+ {$IFDEF ENABLE_SHELLS}
g_Shells_RemoveAll;
{$ENDIF}
{$IFDEF ENABLE_CORPSES}
begin
//result := g_Map_Load(gGameSettings.WAD + ':\' + ResName);
result := g_Map_Load(NewWAD+':\'+ResName);
- {$IFDEF ENABLE_RENDER}
- r_Render_LoadTextures;
- {$ENDIF}
end;
if Result then
begin
+ {$IFDEF ENABLE_RENDER}
+ r_Render_LoadTextures;
+ r_Render_Reset;
+ {$ENDIF}
g_Player_ResetAll(Force or gLastMap, gGameSettings.GameType = GT_SINGLE);
gState := STATE_NONE;
{$IFDEF ENABLE_GIBS}
g_Gibs_RemoveAll;
{$ENDIF}
- {$IFDEF ENALBE_SHELLS}
+ {$IFDEF ENABLE_SHELLS}
g_Shells_RemoveAll;
{$ENDIF}
{$IFDEF ENABLE_CORPSES}
g_Console_Add(Format('gScreenWidth = %d, gScreenHeight = %d', [gScreenWidth, gScreenHeight]));
g_Console_Add(Format('gScreenWidth = %d, gScreenHeight = %d', [gScreenWidth, gScreenHeight]));
end
- else if cmd = 'd_sounds' then
- begin
- if (Length(P) > 1) and
- ((P[1] = '1') or (P[1] = '0')) then
- g_Debug_Sounds := (P[1][1] = '1');
-
- g_Console_Add(Format('d_sounds is %d', [Byte(g_Debug_Sounds)]));
- end
- else if cmd = 'd_frames' then
- begin
- if (Length(P) > 1) and
- ((P[1] = '1') or (P[1] = '0')) then
- g_Debug_Frames := (P[1][1] = '1');
-
- g_Console_Add(Format('d_frames is %d', [Byte(g_Debug_Frames)]));
- end
else if cmd = 'd_winmsg' then
begin
if (Length(P) > 1) and
end;
end;
end
- else if (cmd = 'd_health') then
- begin
- if (Length(P) > 1) and
- ((P[1] = '1') or (P[1] = '0')) then
- g_debug_HealthBar := (P[1][1] = '1');
-
- g_Console_Add(Format('d_health is %d', [Byte(g_debug_HealthBar)]));
- end
else if (cmd = 'd_player') then
begin
if (Length(P) > 1) and
else if cmd = 'screenshot' then
begin
{$IFDEF ENABLE_RENDER}
- g_TakeScreenShot;
+ r_Render_RequestScreenShot;
{$ENDIF}
end
else if (cmd = 'weapnext') or (cmd = 'weapprev') then
end;
end;
-{$IFDEF ENABLE_RENDER}
-procedure g_TakeScreenShot(Filename: string = '');
- var t: TDateTime; dir, date, name: String;
-begin
- if e_NoGraphics then
- Exit;
-
- 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');
- if r_Render_WriteScreenShot(name) then
- g_Console_Add(Format(_lc[I_CONSOLE_SCREENSHOT], [name]))
- else
- g_Console_Add(Format(_lc[I_CONSOLE_ERROR_WRITE], [name]));
-end;
-{$ENDIF}
-
{$IFDEF ENABLE_MENU}
procedure g_Game_InGameMenu(Show: Boolean);
begin
gCheats := True;
end;
-procedure g_Game_SetLoadingText(Text: String; Max: Integer; reWrite: Boolean);
-var
- i: Word;
-begin
- if Length(LoadingStat.Msgs) = 0 then
- Exit;
-
- with LoadingStat do
- begin
- if not reWrite then
- begin // Переходим на следующую строку или скроллируем:
- if NextMsg = Length(Msgs) then
- begin // scroll
- for i := 0 to High(Msgs)-1 do
- Msgs[i] := Msgs[i+1];
- end
- else
- Inc(NextMsg);
- end else
- if NextMsg = 0 then
- Inc(NextMsg);
-
- Msgs[NextMsg-1] := Text;
- CurValue := 0;
- MaxValue := Max;
- ShowCount := 0;
- PBarWasHere := false;
- end;
-
- {$IFDEF ENABLE_MENU}
- g_ActiveWindow := nil;
- {$ENDIF}
-
- ProcessLoading(true);
-end;
-
-procedure g_Game_StepLoading(Value: Integer = -1);
-begin
- with LoadingStat do
- begin
- if Value = -1 then
- begin
- Inc(CurValue);
- Inc(ShowCount);
- end
- else
- CurValue := Value;
-
- if (ShowCount > LOADING_SHOW_STEP) or (Value > -1) then
- begin
- ShowCount := 0;
- ProcessLoading(False);
- end;
- end;
-end;
-
-procedure g_Game_ClearLoading();
-var
- len: Word;
-begin
- with LoadingStat do
- begin
- CurValue := 0;
- MaxValue := 0;
- ShowCount := 0;
- len := ((gScreenHeight div 3)*2 - 50) div LOADING_INTERLINE;
- if len < 1 then len := 1;
- SetLength(Msgs, len);
- for len := Low(Msgs) to High(Msgs) do
- Msgs[len] := '';
- NextMsg := 0;
- PBarWasHere := false;
- end;
-end;
-
procedure Parse_Params(var pars: TParamStrValues);
var
i: Integer;
conRegVar('pf_coldet', @g_profile_collision, 'draw collision detection profiles', 'coldet profiles');
conRegVar('pf_los', @g_profile_los, 'draw monster LOS profiles', 'monster LOS profiles');
- conRegVar('r_sq_draw', @gdbg_map_use_accel_render, 'accelerated spatial queries in rendering', 'accelerated rendering');
conRegVar('cd_sq_enabled', @gdbg_map_use_accel_coldet, 'accelerated spatial queries in map coldet', 'accelerated map coldet');
conRegVar('mon_sq_enabled', @gmon_debug_use_sqaccel, 'accelerated spatial queries for monsters', 'accelerated monster coldet');
conRegVar('wtrace_sq_enabled', @gwep_debug_fast_trace, 'accelerated spatial queries for weapon hitscan trace', 'accelerated weapon hitscan');