diff --git a/src/game/g_game.pas b/src/game/g_game.pas
index 9ec96396134f776058e72cb7616103bd7a116501..73c8ddf3a8c60127b66c8c7a37349a50b52abad2 100644 (file)
--- a/src/game/g_game.pas
+++ b/src/game/g_game.pas
{$IF DEFINED(D2F_DEBUG)}
if gPlayer1 <> nil then gPlayer1.NoTarget := True;
- gAimLine := true;
+ gAimLine := g_dbg_aimline_on;
{$ENDIF}
end;
function sendMonsPos (mon: TMonster): Boolean;
begin
result := false; // don't stop
- if (mon.MonsterType = MONSTER_BARREL) then
+ // this will also reset "need-send" flag
+ if mon.gncNeedSend then
+ begin
+ MH_SEND_MonsterPos(mon.UID);
+ end
+ else if (mon.MonsterType = MONSTER_BARREL) then
begin
if (mon.GameVelX <> 0) or (mon.GameVelY <> 0) then MH_SEND_MonsterPos(mon.UID);
end
- else
- if (mon.MonsterState <> MONSTATE_SLEEP) then
- begin
- if (mon.MonsterState <> MONSTATE_DEAD) or (mon.GameVelX <> 0) or (mon.GameVelY <> 0) then
- begin
- MH_SEND_MonsterPos(mon.UID);
- end;
- end;
+ else if (mon.MonsterState <> MONSTATE_SLEEP) then
+ begin
+ if (mon.MonsterState <> MONSTATE_DEAD) or (mon.GameVelX <> 0) or (mon.GameVelY <> 0) then MH_SEND_MonsterPos(mon.UID);
+ end;
+ end;
+
+ function sendMonsPosUnexpected (mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ // this will also reset "need-send" flag
+ if mon.gncNeedSend then MH_SEND_MonsterPos(mon.UID);
end;
+var
+ reliableUpdate: Boolean;
begin
g_ResetDynlights();
// Ïîðà âûêëþ÷àòü èãðó:
g_GFX_Update();
g_Player_UpdateAll();
g_Player_UpdatePhysicalObjects();
- if gGameSettings.GameType = GT_SERVER then
- if Length(gMonstersSpawned) > 0 then
+
+ // server: send newly spawned monsters unconditionally
+ if (gGameSettings.GameType = GT_SERVER) then
+ begin
+ if (Length(gMonstersSpawned) > 0) then
begin
- for I := 0 to High(gMonstersSpawned) do
- MH_SEND_MonsterSpawn(gMonstersSpawned[I]);
+ for I := 0 to High(gMonstersSpawned) do MH_SEND_MonsterSpawn(gMonstersSpawned[I]);
SetLength(gMonstersSpawned, 0);
end;
+ end;
if (gSoundTriggerTime > 8) then
begin
gSoundTriggerTime := 0;
end
else
+ begin
Inc(gSoundTriggerTime);
+ end;
if (NetMode = NET_SERVER) then
begin
Inc(NetTimeToUpdate);
Inc(NetTimeToReliable);
- if NetTimeToReliable >= NetRelupdRate then
+
+ // send monster updates
+ if (NetTimeToReliable >= NetRelupdRate) or (NetTimeToUpdate >= NetUpdateRate) then
begin
+ // send all monsters (periodic sync)
+ reliableUpdate := (NetTimeToReliable >= NetRelupdRate);
+
for I := 0 to High(gPlayers) do
- if gPlayers[I] <> nil then
- MH_SEND_PlayerPos(True, gPlayers[I].UID);
+ begin
+ if (gPlayers[I] <> nil) then MH_SEND_PlayerPos(reliableUpdate, gPlayers[I].UID);
+ end;
g_Mons_ForEach(sendMonsPos);
- NetTimeToReliable := 0;
- NetTimeToUpdate := NetUpdateRate;
+ if reliableUpdate then
+ begin
+ NetTimeToReliable := 0;
+ NetTimeToUpdate := NetUpdateRate;
+ end
+ else
+ begin
+ NetTimeToUpdate := 0;
+ end;
end
- else if NetTimeToUpdate >= NetUpdateRate then
+ else
begin
- if gPlayers <> nil then
- for I := 0 to High(gPlayers) do
- if gPlayers[I] <> nil then
- MH_SEND_PlayerPos(False, gPlayers[I].UID);
-
- g_Mons_ForEach(sendMonsPos);
-
- NetTimeToUpdate := 0;
+ // send only mosters with some unexpected changes
+ g_Mons_ForEach(sendMonsPosUnexpected);
end;
+ // send unexpected platform changes
+ g_Map_NetSendInterestingPanels();
+
if NetUseMaster then
+ begin
if gTime >= NetTimeToMaster then
begin
if (NetMHost = nil) or (NetMPeer = nil) then
- if not g_Net_Slist_Connect then
- g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR]);
+ begin
+ if not g_Net_Slist_Connect then g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR]);
+ end;
g_Net_Slist_Update;
NetTimeToMaster := gTime + NetMasterRate;
end;
+ end;
end
- else
- if NetMode = NET_CLIENT then
- MC_SEND_PlayerPos();
+ else if (NetMode = NET_CLIENT) then
+ begin
+ MC_SEND_PlayerPos();
+ end;
end; // if gameOn ...
// Àêòèâíî îêíî èíòåðôåéñà - ïåðåäàåì êëàâèøè åìó:
result := false; // don't stop
with mon do
begin
- if Live then
+ if alive then
begin
// Ëåâûé âåðõíèé óãîë
aX := Obj.X div ScaleSz + 1;
// Ðèñóåì èãðîêîâ:
for a := 0 to High(gPlayers) do
if gPlayers[a] <> nil then with gPlayers[a] do
- if Live then begin
+ if alive then begin
// Ëåâûé âåðõíèé óãîë:
aX := Obj.X div ScaleSz + 1;
aY := Obj.Y div ScaleSz + 1;
end;
+function fixViewportForScale (): Boolean;
+var
+ nx0, ny0, nw, nh: Integer;
+begin
+ result := false;
+ if (g_dbg_scale <> 1.0) then
+ begin
+ result := true;
+ nx0 := round(sX-(gPlayerScreenSize.X-(sWidth*g_dbg_scale))/2/g_dbg_scale);
+ ny0 := round(sY-(gPlayerScreenSize.Y-(sHeight*g_dbg_scale))/2/g_dbg_scale);
+ nw := round(sWidth/g_dbg_scale);
+ nh := round(sHeight/g_dbg_scale);
+ sX := nx0;
+ sY := ny0;
+ sWidth := nw;
+ sHeight := nh;
+ end;
+end;
+
+
// setup sX, sY, sWidth, sHeight, and transformation matrix before calling this!
// WARNING! this WILL CALL `glTranslatef()`, but won't restore matrices!
-procedure renderMapInternal (backXOfs, backYOfs: Integer; transX, transY: Integer; setTransMatrix: Boolean);
+procedure renderMapInternal (backXOfs, backYOfs: Integer; setTransMatrix: Boolean);
type
TDrawCB = procedure ();
profileFrameDraw.sectionBegin('collect');
if gdbg_map_use_accel_render then
begin
- if (g_dbg_scale <> 1.0) then
- begin
- g_Map_CollectDrawPanels(sX, sY, round(sWidth/g_dbg_scale)+1, round(sHeight/g_dbg_scale)+1);
- end
- else
- begin
- g_Map_CollectDrawPanels(sX, sY, sWidth, sHeight);
- end;
+ g_Map_CollectDrawPanels(sX, sY, sWidth, sHeight);
end;
profileFrameDraw.sectionEnd();
if setTransMatrix then
begin
glScalef(g_dbg_scale, g_dbg_scale, 1.0);
- glTranslatef(transX, transY, 0);
+ glTranslatef(-sX, -sY, 0);
end;
drawPanelType('*back', PANEL_BACK, g_rlayer_back);
sWidth := w;
sHeight := h;
- renderMapInternal(-bx, -by, -x, -y, true);
+ fixViewportForScale();
+ renderMapInternal(-bx, -by, true);
glPopMatrix();
end;
px := p.GameX + PLAYER_RECT_CX;
py := p.GameY + PLAYER_RECT_CY+p.Obj.slopeUpLeft;
- if px > (gPlayerScreenSize.X div 2) then a := -px+(gPlayerScreenSize.X div 2) else a := 0;
- if py > (gPlayerScreenSize.Y div 2) then b := -py+(gPlayerScreenSize.Y div 2) else b := 0;
+ if (g_dbg_scale = 1.0) then
+ begin
+ if (px > (gPlayerScreenSize.X div 2)) then a := -px+(gPlayerScreenSize.X div 2) else a := 0;
+ if (py > (gPlayerScreenSize.Y div 2)) then b := -py+(gPlayerScreenSize.Y div 2) else b := 0;
- if px > gMapInfo.Width-(gPlayerScreenSize.X div 2) then a := -gMapInfo.Width+gPlayerScreenSize.X;
- if py > gMapInfo.Height-(gPlayerScreenSize.Y div 2) then b := -gMapInfo.Height+gPlayerScreenSize.Y;
+ if (px > gMapInfo.Width-(gPlayerScreenSize.X div 2)) then a := -gMapInfo.Width+gPlayerScreenSize.X;
+ if (py > gMapInfo.Height-(gPlayerScreenSize.Y div 2)) then b := -gMapInfo.Height+gPlayerScreenSize.Y;
- if (gMapInfo.Width = gPlayerScreenSize.X) then a := 0
- else if (gMapInfo.Width < gPlayerScreenSize.X) then
- begin
- // hcenter
- a := (gPlayerScreenSize.X-gMapInfo.Width) div 2;
- end;
+ if (gMapInfo.Width = gPlayerScreenSize.X) then a := 0
+ else if (gMapInfo.Width < gPlayerScreenSize.X) then
+ begin
+ // hcenter
+ a := (gPlayerScreenSize.X-gMapInfo.Width) div 2;
+ end;
- if (gMapInfo.Height = gPlayerScreenSize.Y) then b := 0
- else if (gMapInfo.Height < gPlayerScreenSize.Y) then
+ if (gMapInfo.Height = gPlayerScreenSize.Y) then b := 0
+ else if (gMapInfo.Height < gPlayerScreenSize.Y) then
+ begin
+ // vcenter
+ b := (gPlayerScreenSize.Y-gMapInfo.Height) div 2;
+ end;
+ end
+ else
begin
- // vcenter
- b := (gPlayerScreenSize.Y-gMapInfo.Height) div 2;
+ // scaled, ignore level bounds
+ a := -px+(gPlayerScreenSize.X div 2);
+ b := -py+(gPlayerScreenSize.Y div 2);
end;
if p.IncCam <> 0 then
//glTranslatef(a, b+p.IncCam, 0);
+ if (p = gPlayer1) then g_Holmes_plrViewSize(sWidth, sHeight);
+
+ fixViewportForScale();
p.viewPortX := sX;
p.viewPortY := sY;
p.viewPortW := sWidth;
p.viewPortH := sHeight;
- if (p = gPlayer1) then
- begin
- g_Holmes_plrView(p.viewPortX, p.viewPortY, p.viewPortW, p.viewPortH);
- end;
+ if (p = gPlayer1) then g_Holmes_plrViewPos(sX, sY);
- renderMapInternal(-c, -d, a, b+p.IncCam, true);
+ renderMapInternal(-c, -d, true);
if p.FSpectator then
e_TextureFontPrintEx(p.GameX + PLAYER_RECT_CX - 4,
g_Player_ResetTeams();
- if Pos(':\', Map) > 0 then
+ if isWadPath(Map) then
begin
NewWAD := g_ExtractWadName(Map);
ResName := g_ExtractFileName(Map);
time: Integer;
}
begin
- a := Pos('.wad:\', gMapToDelete);
+ a := Pos('.wad:\', toLowerCase1251(gMapToDelete));
+ if (a = 0) then a := Pos('.wad:/', toLowerCase1251(gMapToDelete));
if a = 0 then
Exit;
end
else if cmd = 'd_monster' then
begin
- if gGameOn and (gPlayer1 <> nil) and (gPlayer1.Live) and (not g_Game_IsNet) then
+ if gGameOn and (gPlayer1 <> nil) and (gPlayer1.alive) and (not g_Game_IsNet) then
if Length(P) < 2 then
begin
g_Console_Add(cmd + ' [ID | Name] [behaviour]');
g_Console_Add('ID | Name');
for b := MONSTER_DEMON to MONSTER_MAN do
- g_Console_Add(Format('%2d | %s', [b, g_Monsters_GetNameByID(b)]));
+ g_Console_Add(Format('%2d | %s', [b, g_Mons_NameByTypeId(b)]));
end else
begin
a := StrToIntDef(P[1], 0);
if (a < MONSTER_DEMON) or (a > MONSTER_MAN) then
- a := g_Monsters_GetIDByName(P[1]);
+ a := g_Mons_TypeIdByName(P[1]);
if (a < MONSTER_DEMON) or (a > MONSTER_MAN) then
g_Console_Add(Format(_lc[I_MSG_NO_MONSTER], [P[1]]))
g_Console_Add('player left the map');
gExitByTrigger := True;
//g_Game_ExitLevel(gTriggers[a].Data.MapName);
- g_Game_ExitLevel(gTriggers[a].trigData.trigMapName);
+ g_Game_ExitLevel(gTriggers[a].tgcMap);
break;
end;
end;
begin
gExitByTrigger := True;
//gNextMap := gTriggers[a].Data.MapName;
- gNextMap := gTriggers[a].trigData.trigMapName;
+ gNextMap := gTriggers[a].tgcMap;
Break;
end;
// Èùåì ñëåäóþùóþ êàðòó â WAD ôàéëå
if gNextMap = '' then
gNextMap := g_Game_GetNextMap();
// Ïðîâåðÿåì, íå çàäàí ëè WAD ôàéë ðåñóðñíîé ñòðîêîé
- if Pos(':\', gNextMap) = 0 then
+ if not isWadPath(gNextMap) then
s := gGameSettings.WAD + ':\' + gNextMap
else
s := gNextMap;
Exit;
end;
end
+ else if cmd = 'suicide' then
+ begin
+ if gGameOn then
+ begin
+ if g_Game_IsClient then
+ MC_SEND_CheatRequest(NET_CHEAT_SUICIDE)
+ else
+ begin
+ if gPlayer1 <> nil then
+ gPlayer1.Damage(SUICIDE_DAMAGE, gPlayer1.UID, 0, 0, HIT_SELF);
+ if gPlayer2 <> nil then
+ gPlayer2.Damage(SUICIDE_DAMAGE, gPlayer2.UID, 0, 0, HIT_SELF);
+ end;
+ end;
+ end
// Êîìàíäû Ñâîåé èãðû:
else if gGameSettings.GameType in [GT_CUSTOM, GT_SERVER, GT_CLIENT] then
begin
else
g_Bot_Add(TEAM_BLUE, 2);
end
- else if cmd = 'suicide' then
- begin
- if gGameOn then
- begin
- if g_Game_IsClient then
- MC_SEND_CheatRequest(NET_CHEAT_SUICIDE)
- else
- begin
- if gPlayer1 <> nil then
- gPlayer1.Damage(SUICIDE_DAMAGE, gPlayer1.UID, 0, 0, HIT_SELF);
- if gPlayer2 <> nil then
- gPlayer2.Damage(SUICIDE_DAMAGE, gPlayer2.UID, 0, 0, HIT_SELF);
- end;
- end;
- end
else if cmd = 'spectate' then
begin
if not gGameOn then
with gTriggers[i] do
if (TriggerType = TRIGGER_SOUND) and
(Sound <> nil) and
- (trigData.trigLocal) and
+ (tgcLocal) and
Sound.IsPlaying() then
begin
if ((gPlayer1 <> nil) and g_CollidePoint(gPlayer1.GameX, gPlayer1.GameY, X, Y, Width, Height)) or
((gPlayer2 <> nil) and g_CollidePoint(gPlayer2.GameX, gPlayer2.GameY, X, Y, Width, Height)) then
begin
- Sound.SetPan(0.5 - trigData.trigPan/255.0);
- Sound.SetVolume(trigData.trigVolume/255.0);
+ Sound.SetPan(0.5 - tgcPan/255.0);
+ Sound.SetVolume(tgcVolume/255.0);
end
else
- Sound.SetCoords(X+(Width div 2), Y+(Height div 2), trigData.trigVolume/255.0);
+ Sound.SetCoords(X+(Width div 2), Y+(Height div 2), tgcVolume/255.0);
end;
end;
s := Find_Param_Value(pars, '-exec');
if s <> '' then
begin
- if Pos(':\', s) = 0 then
+ if not isWadPath(s) then
s := GameDir + '/' + s;
{$I-}