DEADSOFTWARE

mapdef cleanup; renamed some fields; mapdef.txt is RC0 now
[d2df-sdl.git] / src / game / g_game.pas
index 302b952af4b10f88b81c89e2537faf706921b2b9..7f77a41a3194d89279f537bdd2d656cc92030b85 100644 (file)
@@ -70,7 +70,7 @@ function  g_Game_IsNet(): Boolean;
 function  g_Game_IsServer(): Boolean;
 function  g_Game_IsClient(): Boolean;
 procedure g_Game_Init();
-procedure g_Game_Free();
+procedure g_Game_Free (freeTextures: Boolean=true);
 procedure g_Game_LoadData();
 procedure g_Game_FreeData();
 procedure g_Game_Update();
@@ -95,7 +95,7 @@ procedure g_Game_RestartLevel();
 procedure g_Game_RestartRound(NoMapRestart: Boolean = False);
 procedure g_Game_ClientWAD(NewWAD: String; WHash: TMD5Digest);
 procedure g_Game_SaveOptions();
-function  g_Game_StartMap(Map: String; Force: Boolean = False): Boolean;
+function  g_Game_StartMap(Map: String; Force: Boolean = False; const oldMapPath: AnsiString=''): Boolean;
 procedure g_Game_ChangeMap(MapPath: String);
 procedure g_Game_ExitLevel(Map: Char16);
 function  g_Game_GetFirstMap(WAD: String): String;
@@ -324,7 +324,7 @@ var
   g_rlayer_water: Boolean = true;
   g_rlayer_fore: Boolean = true;
 
-  g_dbg_scale_05: Boolean = false;
+  g_dbg_scale: Single = 1.0;
 
 
 procedure g_ResetDynlights ();
@@ -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;
 
@@ -1299,12 +1299,12 @@ begin
   end;
 end;
 
-procedure g_Game_Free();
+procedure g_Game_Free(freeTextures: Boolean=true);
 begin
   if NetMode = NET_CLIENT then g_Net_Disconnect();
   if NetMode = NET_SERVER then g_Net_Host_Die();
 
-  g_Map_Free();
+  g_Map_Free(freeTextures);
   g_Player_Free();
   g_Player_RemoveAllCorpses();
 
@@ -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 ...
 
 // Àêòèâíî îêíî èíòåðôåéñà - ïåðåäàåì êëàâèøè åìó:
@@ -2495,7 +2524,7 @@ var
     result := false; // don't stop
     with mon do
     begin
-      if Live then
+      if alive then
       begin
         // Ëåâûé âåðõíèé óãîë
         aX := Obj.X div ScaleSz + 1;
@@ -2658,7 +2687,7 @@ begin
     // Ðèñóåì èãðîêîâ:
       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;
@@ -2796,9 +2825,9 @@ begin
   profileFrameDraw.sectionBegin('collect');
   if gdbg_map_use_accel_render then
   begin
-    if g_dbg_scale_05 then
+    if (g_dbg_scale <> 1.0) then
     begin
-      g_Map_CollectDrawPanels(sX, sY, sWidth*2, sHeight*2);
+      g_Map_CollectDrawPanels(sX, sY, round(sWidth/g_dbg_scale)+1, round(sHeight/g_dbg_scale)+1);
     end
     else
     begin
@@ -2811,17 +2840,10 @@ begin
   g_Map_DrawBack(backXOfs, backYOfs);
   profileFrameDraw.sectionEnd();
 
-  if (setTransMatrix) then
+  if setTransMatrix then
   begin
-    if g_dbg_scale_05 then
-    begin
-      glScalef(0.5, 0.5, 1.0);
-      glTranslatef(transX, transY, 0);
-    end
-    else
-    begin
-      glTranslatef(transX, transY, 0);
-    end;
+    glScalef(g_dbg_scale, g_dbg_scale, 1.0);
+    glTranslatef(transX, transY, 0);
   end;
 
   drawPanelType('*back', PANEL_BACK, g_rlayer_back);
@@ -3230,16 +3252,26 @@ begin
   begin
     if (gState = STATE_MENU) then
     begin
-      if  ((g_ActiveWindow = nil) or (g_ActiveWindow.BackTexture = '')) then
+      if (g_ActiveWindow = nil) or (g_ActiveWindow.BackTexture = '') then
       begin
-        if g_Texture_Get('MENU_BACKGROUND', ID) then
-          e_DrawSize(ID, 0, 0, 0, False, False, gScreenWidth, gScreenHeight)
+        if g_Texture_Get('MENU_BACKGROUND', ID) then e_DrawSize(ID, 0, 0, 0, False, False, gScreenWidth, gScreenHeight)
         else e_Clear(GL_COLOR_BUFFER_BIT, 0, 0, 0);
       end;
-      if g_ActiveWindow <> nil then
+      // F3 at menu will show game loading dialog
+      if e_KeyPressed(IK_F3) then g_Menu_Show_LoadMenu(true);
+      if (g_ActiveWindow <> nil) then
       begin
         //e_DrawFillQuad(0, 0, gScreenWidth-1, gScreenHeight-1, 48, 48, 48, 180);
         e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150);
+      end
+      else
+      begin
+        // F3 at titlepic will show game loading dialog
+        if e_KeyPressed(IK_F3) then
+        begin
+          g_Menu_Show_LoadMenu(true);
+          if (g_ActiveWindow <> nil) then e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150);
+        end;
       end;
     end;
 
@@ -3990,7 +4022,7 @@ begin
         end;
     end;
 
-    ProcessLoading();
+    ProcessLoading(true);
 
     e_PollInput();
 
@@ -4050,15 +4082,15 @@ begin
   MessageTime := 0;
   gGameOn := False;
   g_Game_ClearLoading();
-  g_Game_StartMap(Map, True);
+  g_Game_StartMap(Map, True, gCurrentMapFileName);
 end;
 
-function g_Game_StartMap(Map: String; Force: Boolean = False): Boolean;
+function g_Game_StartMap(Map: String; Force: Boolean = False; const oldMapPath: AnsiString=''): Boolean;
 var
   NewWAD, ResName: String;
   I: Integer;
 begin
-  g_Map_Free();
+  g_Map_Free((Map <> gCurrentMapFileName) and (oldMapPath <> gCurrentMapFileName));
   g_Player_RemoveAllCorpses();
 
   if (not g_Game_IsClient) and
@@ -5097,18 +5129,18 @@ begin
     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]]))
@@ -5199,7 +5231,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;
@@ -6069,7 +6101,7 @@ begin
             begin
               gExitByTrigger := True;
               //gNextMap := gTriggers[a].Data.MapName;
-              gNextMap := gTriggers[a].trigData.trigMapName;
+              gNextMap := gTriggers[a].trigData.trigMap;
               Break;
             end;
         // Èùåì ñëåäóþùóþ êàðòó â WAD ôàéëå
@@ -6122,6 +6154,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
@@ -6139,21 +6186,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
@@ -6758,7 +6790,7 @@ begin
 
   g_ActiveWindow := nil;
 
-  ProcessLoading;
+  ProcessLoading(true);
 end;
 
 procedure g_Game_StepLoading();
@@ -6770,7 +6802,7 @@ begin
     if (ShowCount > LOADING_SHOW_STEP) then
     begin
       ShowCount := 0;
-      ProcessLoading;
+      ProcessLoading();
     end;
   end;
 end;
@@ -7033,5 +7065,5 @@ begin
 
   conRegVar('dbg_holmes', @g_holmes_enabled, 'enable/disable Holmes', 'Holmes', true);
 
-  conRegVar('dbg_scale_half', @g_dbg_scale_05, 'experimental deBUG scale*0.5 mode', 'Scale0.5', true);
+  conRegVar('dbg_scale', @g_dbg_scale, 0.01, 5.0, 'experimental deBUG scale mode', '',  true);
 end.