DEADSOFTWARE

don't hit monsters on the client when it's warmup time
[d2df-sdl.git] / src / game / g_weapons.pas
index 311b18cbc344dbb78b83a7ad0d4c3053a858c9d9..498487da73d4acd8862ebf74841bb33479940ad3 100644 (file)
@@ -1,9 +1,8 @@
-(* 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation, version 3 of the License ONLY.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,7 +19,7 @@ unit g_weapons;
 interface
 
 uses
-  SysUtils, Classes,
+  SysUtils, Classes, mempool,
   g_textures, g_basic, e_graphics, g_phys, xprofiler;
 
 
@@ -118,7 +117,7 @@ uses
   g_console, g_options, g_game,
   g_triggers, MAPDEF, e_log, g_monsters, g_saveload,
   g_language, g_netmsg, g_grid,
-  binheap, hashtable, utils, xstreams;
+  geom, binheap, hashtable, utils, xstreams;
 
 type
   TWaterPanel = record
@@ -157,8 +156,13 @@ type
     x, y: Integer;
   end;
 
+  TBinHeapKeyHitTime = class
+  public
+    class function less (const a, b: Integer): Boolean; inline;
+  end;
+
   // indicies in `wgunHitTime` array
-  TBinaryHeapHitTimes = specialize TBinaryHeapBase<Integer>;
+  TBinaryHeapHitTimes = specialize TBinaryHeapBase<Integer, TBinHeapKeyHitTime>;
 
 var
   WaterMap: array of array of DWORD = nil;
@@ -168,7 +172,7 @@ var
   wgunHitTimeUsed: Integer = 0;
 
 
-function hitTimeLess (a, b: Integer): Boolean;
+class function TBinHeapKeyHitTime.less (const a, b: Integer): Boolean;
 var
   hta, htb: PHitTime;
 begin
@@ -457,12 +461,12 @@ begin
     if (t <> HIT_FLAME) or (m.FFireTime = 0) or (vx <> 0) or (vy <> 0) then
       Result := m.Damage(d, vx, vy, SpawnerUID, t)
     else
-      Result := True;
+      Result := (gLMSRespawn <> LMS_RESPAWN_WARMUP); // don't hit monsters when it's warmup time
     if t = HIT_FLAME then
       m.CatchFire(SpawnerUID);
   end
   else
-    Result := True;
+    Result := (gLMSRespawn <> LMS_RESPAWN_WARMUP); // don't hit monsters when it's warmup time
 end;
 
 
@@ -1112,6 +1116,7 @@ begin
   g_Sound_CreateWADEx('SOUND_WEAPON_FIRECGUN', GameWAD+':SOUNDS\FIRECGUN');
   g_Sound_CreateWADEx('SOUND_WEAPON_FIREBFG', GameWAD+':SOUNDS\FIREBFG');
   g_Sound_CreateWADEx('SOUND_FIRE', GameWAD+':SOUNDS\FIRE');
+  g_Sound_CreateWADEx('SOUND_IGNITE', GameWAD+':SOUNDS\IGNITE');
   g_Sound_CreateWADEx('SOUND_WEAPON_STARTFIREBFG', GameWAD+':SOUNDS\STARTFIREBFG');
   g_Sound_CreateWADEx('SOUND_WEAPON_EXPLODEROCKET', GameWAD+':SOUNDS\EXPLODEROCKET');
   g_Sound_CreateWADEx('SOUND_WEAPON_EXPLODEBFG', GameWAD+':SOUNDS\EXPLODEBFG');
@@ -1121,6 +1126,9 @@ begin
   g_Sound_CreateWADEx('SOUND_WEAPON_FIREBALL', GameWAD+':SOUNDS\FIREBALL');
   g_Sound_CreateWADEx('SOUND_WEAPON_EXPLODEBALL', GameWAD+':SOUNDS\EXPLODEBALL');
   g_Sound_CreateWADEx('SOUND_WEAPON_FIREREV', GameWAD+':SOUNDS\FIREREV');
+  g_Sound_CreateWADEx('SOUND_WEAPON_FLAMEON', GameWAD+':SOUNDS\STARTFLM');
+  g_Sound_CreateWADEx('SOUND_WEAPON_FLAMEOFF', GameWAD+':SOUNDS\STOPFLM');
+  g_Sound_CreateWADEx('SOUND_WEAPON_FLAMEWORK', GameWAD+':SOUNDS\WORKFLM');
   g_Sound_CreateWADEx('SOUND_PLAYER_JETFLY', GameWAD+':SOUNDS\WORKJETPACK');
   g_Sound_CreateWADEx('SOUND_PLAYER_JETON', GameWAD+':SOUNDS\STARTJETPACK');
   g_Sound_CreateWADEx('SOUND_PLAYER_JETOFF', GameWAD+':SOUNDS\STOPJETPACK');
@@ -1155,7 +1163,7 @@ begin
   g_Texture_CreateWADEx('TEXTURE_SHELL_SHELL', GameWAD+':TEXTURES\ESHELL');
 
   //wgunMonHash := hashNewIntInt();
-  wgunHitHeap := TBinaryHeapHitTimes.Create(hitTimeLess);
+  wgunHitHeap := TBinaryHeapHitTimes.Create();
 end;
 
 procedure g_Weapon_FreeData();
@@ -1178,6 +1186,7 @@ begin
   g_Sound_Delete('SOUND_WEAPON_FIRECGUN');
   g_Sound_Delete('SOUND_WEAPON_FIREBFG');
   g_Sound_Delete('SOUND_FIRE');
+  g_Sound_Delete('SOUND_IGNITE');
   g_Sound_Delete('SOUND_WEAPON_STARTFIREBFG');
   g_Sound_Delete('SOUND_WEAPON_EXPLODEROCKET');
   g_Sound_Delete('SOUND_WEAPON_EXPLODEBFG');
@@ -1187,6 +1196,9 @@ begin
   g_Sound_Delete('SOUND_WEAPON_FIREBALL');
   g_Sound_Delete('SOUND_WEAPON_EXPLODEBALL');
   g_Sound_Delete('SOUND_WEAPON_FIREREV');
+  g_Sound_Delete('SOUND_WEAPON_FLAMEON');
+  g_Sound_Delete('SOUND_WEAPON_FLAMEOFF');
+  g_Sound_Delete('SOUND_WEAPON_FLAMEWORK');
   g_Sound_Delete('SOUND_PLAYER_JETFLY');
   g_Sound_Delete('SOUND_PLAYER_JETON');
   g_Sound_Delete('SOUND_PLAYER_JETOFF');
@@ -1435,13 +1447,12 @@ var
     end;
   end;
 
-  function sqchecker (mon: TMonster; tag: Integer): Boolean;
+  procedure sqchecker (mon: TMonster);
   var
     mx, my, mw, mh: Integer;
     inx, iny: Integer;
     distSq: Integer;
   begin
-    result := false; // don't stop
     mon.getMapBox(mx, my, mw, mh);
     if lineAABBIntersects(x0, y0, x2, y2, mx, my, mw, mh, inx, iny) then
     begin
@@ -1463,6 +1474,8 @@ var
   {$IF DEFINED(D2F_DEBUG)}
   stt: UInt64;
   {$ENDIF}
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
   (*
   if not gwep_debug_fast_trace then
@@ -1517,7 +1530,11 @@ begin
   if playerPossibleHit() then exit; // instant hit
 
   // collect monsters
-  g_Mons_AlongLine(x, y, x2, y2, sqchecker);
+  //g_Mons_AlongLine(x, y, x2, y2, sqchecker);
+
+  it := monsGrid.forEachAlongLine(x, y, x2, y2, -1);
+  for mit in it do sqchecker(mit^);
+  it.release();
 
   // here, we collected all monsters and players in `wgunHitHeap` and `wgunHitTime`
   // also, if `wallWasHit` is `true`, then `wallHitX` and `wallHitY` contains spark coords
@@ -2141,7 +2158,7 @@ begin
 
       if Stopped = 0 then
       begin
-        st := g_Obj_Move(@Obj, False, spl);
+        st := g_Obj_Move_Projectile(@Obj, False, spl);
       end
       else
       begin
@@ -2328,7 +2345,7 @@ begin
                 Stopped := MOVE_HITCEIL;
             end;
 
-            a := IfThen(Stopped = 0, 3, 1);
+            a := IfThen(Stopped = 0, 10, 1);
           // Åñëè â êîãî-òî ïîïàëè
             if g_Weapon_Hit(@Obj, a, SpawnerUID, HIT_FLAME, False) <> 0 then
             begin