DEADSOFTWARE

center player when the game is scaled (lighting is not working correctly yet, tho)
[d2df-sdl.git] / src / game / g_game.pas
index a377122e143a16bf6b443b54e6fc381cb8ea9e07..467c13f1dcef4fabbfc06d6ddf07acaf08e23fd9 100644 (file)
@@ -794,7 +794,7 @@ begin
 
   {$IF DEFINED(D2F_DEBUG)}
   if gPlayer1 <> nil then gPlayer1.NoTarget := True;
-  gAimLine := true;
+  gAimLine := g_dbg_aimline_on;
   {$ENDIF}
 end;
 
@@ -1487,20 +1487,30 @@ var
   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();
 // Ïîðà âûêëþ÷àòü èãðó:
@@ -1844,13 +1854,16 @@ begin
     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
@@ -1858,49 +1871,65 @@ 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 ...
 
 // Àêòèâíî îêíî èíòåðôåéñà - ïåðåäàåì êëàâèøè åìó:
@@ -2751,9 +2780,29 @@ begin
 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 ();
 
@@ -2796,14 +2845,7 @@ begin
   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();
 
@@ -2814,7 +2856,7 @@ begin
   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);
@@ -2860,7 +2902,8 @@ begin
   sWidth := w;
   sHeight := h;
 
-  renderMapInternal(-bx, -by, -x, -y, true);
+  fixViewportForScale();
+  renderMapInternal(-bx, -by, true);
 
   glPopMatrix();
 end;
@@ -2889,24 +2932,33 @@ begin
   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
@@ -2953,17 +3005,17 @@ begin
 
   //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,
@@ -4077,7 +4129,7 @@ begin
 
   g_Player_ResetTeams();
 
-  if Pos(':\', Map) > 0 then
+  if isWadPath(Map) then
   begin
     NewWAD := g_ExtractWadName(Map);
     ResName := g_ExtractFileName(Map);
@@ -4452,7 +4504,8 @@ var
   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;
 
@@ -5106,12 +5159,12 @@ 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]]))
@@ -5202,7 +5255,7 @@ begin
               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].trigData.trigMap);
               break;
             end;
           end;
@@ -6072,14 +6125,14 @@ begin
             begin
               gExitByTrigger := True;
               //gNextMap := gTriggers[a].Data.MapName;
-              gNextMap := gTriggers[a].trigData.trigMapName;
+              gNextMap := gTriggers[a].trigData.trigMap;
               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;
@@ -6125,6 +6178,21 @@ begin
         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
@@ -6142,21 +6210,6 @@ 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
@@ -6980,7 +7033,7 @@ begin
   s := Find_Param_Value(pars, '-exec');
   if s <> '' then
   begin
-    if Pos(':\', s) = 0 then
+    if not isWadPath(s) then
       s := GameDir + '/' + s;
 
     {$I-}