DEADSOFTWARE

gl: implement load screen
[d2df-sdl.git] / src / game / g_weapons.pas
index a5114e15a613670dd90af85c54bd33668b9ce2c0..96c46c8d4fc0cad7a2d0e36eeaf88b431addbaf9 100644 (file)
@@ -20,7 +20,7 @@ interface
 
 uses
   SysUtils, Classes, mempool,
-  g_textures, g_basic, g_phys, xprofiler;
+  g_basic, g_phys, xprofiler;
 
 
 type
@@ -30,7 +30,7 @@ type
     SpawnerUID: Word;
     Triggers: DWArray;
     Obj: TObj;
-    Animation: TAnimationState;
+    time: LongWord;
     Timeout: DWORD;
     Stopped: Byte;
 
@@ -100,6 +100,7 @@ const
   WEAPON_BARON_FIRE     = 24;
   WEAPON_MANCUB_FIRE    = 25;
   WEAPON_SKEL_FIRE      = 26;
+  WEAPON_LAST           = WEAPON_SKEL_FIRE;
 
   WP_FIRST          = WEAPON_KASTET;
   WP_LAST           = WEAPON_FLAMETHROWER;
@@ -110,12 +111,22 @@ var
 
 implementation
 
-uses
-  Math, g_map, g_player, g_gfx, g_sound, g_panel,
-  g_console, g_options, g_game, r_textures, r_animations, r_gfx,
-  g_triggers, MAPDEF, e_log, g_monsters, g_saveload,
-  g_language, g_netmsg, g_grid,
-  geom, binheap, hashtable, utils, xstreams;
+  uses
+    {$IFDEF ENABLE_GFX}
+      g_gfx,
+    {$ENDIF}
+    {$IFDEF ENABLE_GIBS}
+      g_gibs,
+    {$ENDIF}
+    {$IFDEF ENABLE_CORPSES}
+      g_corpses,
+    {$ENDIF}
+    Math, g_map, g_player, g_sound, g_panel,
+    g_console, g_options, g_game,
+    g_triggers, MAPDEF, e_log, g_monsters, g_saveload,
+    g_language, g_netmsg, g_grid, g_window,
+    geom, binheap, hashtable, utils, xstreams
+  ;
 
 type
   TWaterPanel = record
@@ -513,21 +524,29 @@ var
 begin
   //g_Sound_PlayEx('SOUND_WEAPON_EXPLODEBFG', 255);
 
-  h := High(gCorpses);
-
-  if gAdvCorpses and (h <> -1) then
-    for i := 0 to h do
-      if (gCorpses[i] <> nil) and (gCorpses[i].State <> CORPSE_STATE_REMOVEME) then
-        with gCorpses[i] do
-          if (g_PatchLength(X, Y, Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2),
-                            Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)) <= SHOT_BFG_RADIUS) and
-              g_TraceVector(X, Y, Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2),
-                            Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)) then
+  {$IFDEF ENABLE_CORPSES}
+    h := High(gCorpses);
+    if gAdvCorpses and (h <> -1) then
+    begin
+      for i := 0 to h do
+      begin
+        if (gCorpses[i] <> nil) and (gCorpses[i].State <> CORPSE_STATE_REMOVEME) then
+        begin
+          with gCorpses[i] do
           begin
-            Damage(50, SpawnerUID, 0, 0);
-            g_Weapon_BFGHit(Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2),
-                            Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2));
+            if (g_PatchLength(X, Y, Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2),
+                              Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)) <= SHOT_BFG_RADIUS) and
+                g_TraceVector(X, Y, Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2),
+                              Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)) then
+            begin
+              Damage(50, SpawnerUID, 0, 0);
+              g_Weapon_BFGHit(Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2), Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2));
+            end;
           end;
+        end;
+      end;
+    end;
+  {$ENDIF}
 
   st := TEAM_NONE;
   pl := g_Player_Get(SpawnerUID);
@@ -570,6 +589,8 @@ begin
       SetLength(Shots, find_id + 64)
   end;
 
+  shots[find_id].time := gTime;
+
   case ShotType of
     WEAPON_ROCKETLAUNCHER:
     begin
@@ -580,7 +601,6 @@ begin
         Obj.Rect.Width := SHOT_ROCKETLAUNCHER_WIDTH;
         Obj.Rect.Height := SHOT_ROCKETLAUNCHER_HEIGHT;
 
-        Animation := nil;
         Triggers := nil;
         ShotType := WEAPON_ROCKETLAUNCHER;
       end;
@@ -597,7 +617,6 @@ begin
 
         Triggers := nil;
         ShotType := WEAPON_PLASMA;
-        Animation := TAnimationState.Create(True, 5, 2); // !!! put values into table
       end;
     end;
 
@@ -612,7 +631,6 @@ begin
 
         Triggers := nil;
         ShotType := WEAPON_BFG;
-        Animation := TAnimationState.Create(True, 6, 2); // !!! put values into table
       end;
     end;
 
@@ -627,7 +645,6 @@ begin
 
         Triggers := nil;
         ShotType := WEAPON_FLAMETHROWER;
-        // Animation := TAnimationState.Create(True, 6, 0); // drawed as gfx
       end;
     end;
 
@@ -642,7 +659,6 @@ begin
 
         Triggers := nil;
         ShotType := WEAPON_IMP_FIRE;
-        Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
       end;
     end;
 
@@ -657,7 +673,6 @@ begin
 
         Triggers := nil;
         ShotType := WEAPON_CACO_FIRE;
-        Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
       end;
     end;
 
@@ -672,7 +687,6 @@ begin
 
         Triggers := nil;
         ShotType := WEAPON_MANCUB_FIRE;
-        Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
       end;
     end;
 
@@ -687,7 +701,6 @@ begin
 
         Triggers := nil;
         ShotType := WEAPON_BARON_FIRE;
-        Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
       end;
     end;
 
@@ -702,7 +715,6 @@ begin
 
         Triggers := nil;
         ShotType := WEAPON_BSP_FIRE;
-        Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
       end;
     end;
 
@@ -718,7 +730,6 @@ begin
         Triggers := nil;
         ShotType := WEAPON_SKEL_FIRE;
         target := TargetUID;
-        Animation := TAnimationState.Create(True, 5, 2); // !!! put values into table
       end;
     end;
   end;
@@ -771,8 +782,10 @@ begin
 end;
 
 function g_Weapon_Hit(obj: PObj; d: Integer; SpawnerUID: Word; t: Byte; HitCorpses: Boolean = True): Byte;
-var
-  i, h: Integer;
+  {$IFDEF ENABLE_CORPSES}
+    var i: Integer;
+  {$ENDIF}
+  var h: Integer;
 
   function PlayerHit(Team: Byte = 0): Boolean;
   var
@@ -851,21 +864,26 @@ var
 begin
   Result := 0;
 
-  if HitCorpses then
-  begin
-    h := High(gCorpses);
-
-    if gAdvCorpses and (h <> -1) then
-      for i := 0 to h do
-        if (gCorpses[i] <> nil) and (gCorpses[i].State <> CORPSE_STATE_REMOVEME) and
-           g_Obj_Collide(obj, @gCorpses[i].Obj) then
+  {$IFDEF ENABLE_CORPSES}
+    if HitCorpses then
+    begin
+      h := High(gCorpses);
+      if gAdvCorpses and (h <> -1) then
+      begin
+        for i := 0 to h do
         begin
-          // Ðàñïèëèâàåì òðóï:
-          gCorpses[i].Damage(d, SpawnerUID, (obj^.Vel.X+obj^.Accel.X) div 4,
-                                            (obj^.Vel.Y+obj^.Accel.Y) div 4);
-          Result := 1;
+          if (gCorpses[i] <> nil) and (gCorpses[i].State <> CORPSE_STATE_REMOVEME) and
+             g_Obj_Collide(obj, @gCorpses[i].Obj) then
+          begin
+            // Ðàñïèëèâàåì òðóï:
+            gCorpses[i].Damage(d, SpawnerUID, (obj^.Vel.X+obj^.Accel.X) div 4,
+                                              (obj^.Vel.Y+obj^.Accel.Y) div 4);
+            Result := 1;
+          end;
         end;
-  end;
+      end;
+    end;
+  {$ENDIF}
 
   case gGameSettings.GameMode of
     // Êàìïàíèÿ:
@@ -985,9 +1003,13 @@ var
     end;
   end;
 
-var
-  i, h, dx, dy, m, mm: Integer;
-  _angle: SmallInt;
+  var i, h, dx, dy, mm: Integer;
+  {$IFDEF ENABLE_GIBS}
+    var _angle: SmallInt;
+  {$ENDIF}
+  {$IF DEFINED(ENABLE_GIBS) OR DEFINED(ENABLE_CORPSES)}
+    var m: Integer;
+  {$ENDIF}
 begin
   result := false;
 
@@ -1024,55 +1046,56 @@ begin
   //g_Mons_ForEach(monsExCheck);
   g_Mons_ForEachAt(X-(rad+32), Y-(rad+32), (rad+32)*2, (rad+32)*2, monsExCheck);
 
-  h := High(gCorpses);
-
-  if gAdvCorpses and (h <> -1) then
-    for i := 0 to h do
-      if (gCorpses[i] <> nil) and (gCorpses[i].State <> CORPSE_STATE_REMOVEME) then
-        with gCorpses[i] do
+  {$IFDEF ENABLE_CORPSES}
+    h := High(gCorpses);
+    if gAdvCorpses and (h <> -1) then
+    begin
+      for i := 0 to h do
+      begin
+        if (gCorpses[i] <> nil) and (gCorpses[i].State <> CORPSE_STATE_REMOVEME) then
         begin
-          dx := Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)-X;
-          dy := Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)-Y;
-
-          if dx > 1000 then dx := 1000;
-          if dy > 1000 then dy := 1000;
-
-          if dx*dx+dy*dy < r then
+          with gCorpses[i] do
           begin
-            m := PointToRect(X, Y, Obj.X+Obj.Rect.X, Obj.Y+Obj.Rect.Y,
-                             Obj.Rect.Width, Obj.Rect.Height);
-
-            mm := Max(abs(dx), abs(dy));
-            if mm = 0 then mm := 1;
-
-            Damage(Round(100*(rad-m)/rad), SpawnerUID, (dx*10) div mm, (dy*10) div mm);
+            dx := Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)-X;
+            dy := Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)-Y;
+            if dx > 1000 then dx := 1000;
+            if dy > 1000 then dy := 1000;
+            if dx*dx+dy*dy < r then
+            begin
+              m := PointToRect(X, Y, Obj.X+Obj.Rect.X, Obj.Y+Obj.Rect.Y, Obj.Rect.Width, Obj.Rect.Height);
+              mm := Max(abs(dx), abs(dy));
+              if mm = 0 then
+                mm := 1;
+              Damage(Round(100*(rad-m)/rad), SpawnerUID, (dx*10) div mm, (dy*10) div mm);
+            end;
           end;
         end;
+      end;
+    end;
+  {$ENDIF}
 
-  h := High(gGibs);
-
-  if gAdvGibs and (h <> -1) then
-    for i := 0 to h do
-      if gGibs[i].alive then
-        with gGibs[i] do
-        begin
-          dx := Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)-X;
-          dy := Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)-Y;
-
-          if dx > 1000 then dx := 1000;
-          if dy > 1000 then dy := 1000;
-
-          if dx*dx+dy*dy < r then
+  {$IFDEF ENABLE_GIBS}
+    h := High(gGibs);
+    if gAdvGibs and (h <> -1) then
+      for i := 0 to h do
+        if gGibs[i].alive then
+          with gGibs[i] do
           begin
-            m := PointToRect(X, Y, Obj.X+Obj.Rect.X, Obj.Y+Obj.Rect.Y,
-                             Obj.Rect.Width, Obj.Rect.Height);
-            _angle := GetAngle(Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2),
-                               Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2), X, Y);
-
-            g_Obj_PushA(@Obj, Round(15*(rad-m)/rad), _angle);
-            positionChanged(); // this updates spatial accelerators
+            dx := Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)-X;
+            dy := Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)-Y;
+            if dx > 1000 then dx := 1000;
+            if dy > 1000 then dy := 1000;
+            if dx*dx+dy*dy < r then
+            begin
+              m := PointToRect(X, Y, Obj.X+Obj.Rect.X, Obj.Y+Obj.Rect.Y,
+                               Obj.Rect.Width, Obj.Rect.Height);
+              _angle := GetAngle(Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2),
+                                 Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2), X, Y);
+              g_Obj_PushA(@Obj, Round(15*(rad-m)/rad), _angle);
+              positionChanged(); // this updates spatial accelerators
+            end;
           end;
-        end;
+  {$ENDIF}
 end;
 
 procedure g_Weapon_Init();
@@ -1081,24 +1104,15 @@ begin
 end;
 
 procedure g_Weapon_Free();
-var
-  i: Integer;
 begin
-  if Shots <> nil then
-  begin
-    for i := 0 to High(Shots) do
-      if Shots[i].ShotType <> 0 then
-        Shots[i].Animation.Free();
-
-    Shots := nil;
-  end;
-
+  Shots := nil;
   WaterMap := nil;
 end;
 
 procedure g_Weapon_LoadData();
 begin
   e_WriteLog('Loading weapons data...', TMsgType.Notify);
+  g_Game_SetLoadingText(_lc[I_LOAD_WEAPONS_DATA], 0, False);
 
   g_Sound_CreateWADEx('SOUND_WEAPON_HITPUNCH', GameWAD+':SOUNDS\HITPUNCH');
   g_Sound_CreateWADEx('SOUND_WEAPON_MISSPUNCH', GameWAD+':SOUNDS\MISSPUNCH');
@@ -1137,9 +1151,6 @@ begin
   g_Sound_CreateWADEx('SOUND_PLAYER_SHELL1', GameWAD+':SOUNDS\SHELL1');
   g_Sound_CreateWADEx('SOUND_PLAYER_SHELL2', GameWAD+':SOUNDS\SHELL2');
 
-  g_Texture_CreateWADEx('TEXTURE_SHELL_BULLET', GameWAD+':TEXTURES\EBULLET');
-  g_Texture_CreateWADEx('TEXTURE_SHELL_SHELL', GameWAD+':TEXTURES\ESHELL');
-
   //wgunMonHash := hashNewIntInt();
   wgunHitHeap := TBinaryHeapHitTimes.Create();
 end;
@@ -1548,7 +1559,9 @@ begin
     stt := getTimeMicro()-stt;
     e_WriteLog(Format('*** new trace time: %u microseconds', [LongWord(stt)]), TMsgType.Notify);
     {$ENDIF}
-    g_GFX_Spark(wallHitX, wallHitY, 2+Random(2), 180+a, 0, 0);
+    {$IFDEF ENABLE_GFX}
+      g_GFX_Spark(wallHitX, wallHitY, 2+Random(2), 180+a, 0, 0);
+    {$ENDIF}
     if g_Game_IsServer and g_Game_IsNet then MH_SEND_Effect(wallHitX, wallHitY, 180+a, NET_GFX_SPARK);
   end
   else
@@ -1633,8 +1646,8 @@ begin
     ShotType := WEAPON_ROCKETLAUNCHER;
     throw(find_id, x+dx, y+dy, xd+dx, yd+dy, 12);
 
-    Animation := nil;
     triggers := nil;
+    time := gTime;
   end;
 
   Shots[find_id].SpawnerUID := SpawnerUID;
@@ -1673,7 +1686,7 @@ begin
 
     triggers := nil;
     target := TargetUID;
-    Animation := TAnimationState.Create(True, 5, 2); // !!! put values into table
+    time := gTime;
   end;
 
   Shots[find_id].SpawnerUID := SpawnerUID;
@@ -1714,7 +1727,7 @@ begin
     throw(find_id, x+dx, y+dy, xd+dx, yd+dy, 16);
 
     triggers := nil;
-    Animation := TAnimationState.Create(True, 5, 2); // !!! put values into table
+    time := gTime;
   end;
 
   Shots[find_id].SpawnerUID := SpawnerUID;
@@ -1755,7 +1768,7 @@ begin
     throw(find_id, x+dx, y+dy, xd+dx, yd+dy, 16);
 
     triggers := nil;
-    Animation := nil;
+    time := gTime;
   end;
 
   Shots[find_id].SpawnerUID := SpawnerUID;
@@ -1796,7 +1809,7 @@ begin
     throw(find_id, x+dx, y+dy, xd+dx, yd+dy, 16);
 
     triggers := nil;
-    Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
+    time := gTime;
   end;
 
   Shots[find_id].SpawnerUID := SpawnerUID;
@@ -1837,7 +1850,7 @@ begin
     throw(find_id, x+dx, y+dy, xd+dx, yd+dy, 16);
 
     triggers := nil;
-    Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
+    time := gTime;
   end;
 
   Shots[find_id].SpawnerUID := SpawnerUID;
@@ -1878,7 +1891,7 @@ begin
     throw(find_id, x+dx, y+dy, xd+dx, yd+dy, 16);
 
     triggers := nil;
-    Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
+    time := gTime;
   end;
 
   Shots[find_id].SpawnerUID := SpawnerUID;
@@ -1890,7 +1903,7 @@ end;
 procedure g_Weapon_aplasma(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
   Silent: Boolean = False; compat: Boolean = true);
 var
-  find_id, FramesID: DWORD;
+  find_id: DWORD;
   dx, dy: Integer;
 begin
   if WID < 0 then
@@ -1919,8 +1932,7 @@ begin
     throw(find_id, x+dx, y+dy, xd+dx, yd+dy, 16);
 
     triggers := nil;
-
-    Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
+    time := gTime;
   end;
 
   Shots[find_id].SpawnerUID := SpawnerUID;
@@ -1961,8 +1973,7 @@ begin
     throw(find_id, x+dx, y+dy, xd+dx, yd+dy, 16);
 
     triggers := nil;
-
-    Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
+    time := gTime;
   end;
 
   Shots[find_id].SpawnerUID := SpawnerUID;
@@ -2003,7 +2014,7 @@ begin
     throw(find_id, x+dx, y+dy, xd+dx, yd+dy, 16);
 
     triggers := nil;
-    Animation := TAnimationState.Create(True, 6, 2); // !!! put values into table
+    time := gTime;
   end;
 
   Shots[find_id].SpawnerUID := SpawnerUID;
@@ -2014,7 +2025,9 @@ end;
 
 procedure g_Weapon_bfghit(x, y: Integer);
 begin
-  r_GFX_OnceAnim(R_GFX_BFG_HIT, x - 32, y - 32);
+  {$IFDEF ENABLE_GFX}
+    g_GFX_QueueEffect(R_GFX_BFG_HIT, x - 32, y - 32);
+  {$ENDIF}
 end;
 
 procedure g_Weapon_pistol(x, y, xd, yd: Integer; SpawnerUID: Word;
@@ -2116,7 +2129,9 @@ var
   o: TObj;
   spl: Boolean;
   Loud: Boolean;
-  tcx, tcy: Integer;
+  {$IFDEF ENABLE_GFX}
+    var tcx, tcy: Integer;
+  {$ENDIF}
 begin
   if Shots = nil then
     Exit;
@@ -2158,10 +2173,6 @@ begin
           end;
       end;
 
-    // Àíèìàöèÿ ñíàðÿäà:
-      if Animation <> nil then
-        Animation.Update();
-
     // Äâèæåíèå:
       spl := (ShotType <> WEAPON_PLASMA) and
              (ShotType <> WEAPON_BFG) and
@@ -2183,7 +2194,7 @@ begin
       begin
         // Íà êëèåíòå ñêîðåå âñåãî è òàê óæå âûïàë.
         ShotType := 0;
-        Animation.Free();
+        time := 0;
         Continue;
       end;
 
@@ -2200,14 +2211,18 @@ begin
           // Â âîäå øëåéô - ïóçûðè, â âîçäóõå øëåéô - äûì:
             if WordBool(st and MOVE_INWATER) then
             begin
-              g_GFX_Bubbles(cx, cy, 1+Random(3), 16, 16);
+              {$IFDEF ENABLE_GFX}
+                g_GFX_Bubbles(cx, cy, 1+Random(3), 16, 16);
+              {$ENDIF}
               if Random(2) = 0
                 then g_Sound_PlayExAt('SOUND_GAME_BUBBLE1', cx, cy)
                 else g_Sound_PlayExAt('SOUND_GAME_BUBBLE2', cx, cy);
             end
             else
             begin
-              r_GFX_OnceAnim(R_GFX_SMOKE_TRANS, Obj.X-14+Random(9), cy-20+Random(9));
+              {$IFDEF ENABLE_GFX}
+                g_GFX_QueueEffect(R_GFX_SMOKE_TRANS, Obj.X-14+Random(9), cy-20+Random(9));
+              {$ENDIF}
             end;
 
           // Ïîïàëè â êîãî-òî èëè â ñòåíó:
@@ -2221,15 +2236,19 @@ begin
               g_Weapon_Explode(cx, cy, 60, SpawnerUID);
 
               if ShotType = WEAPON_SKEL_FIRE then
-                begin // Âçðûâ ñíàðÿäà Ñêåëåòà
-                  r_GFX_OnceAnim(R_GFX_EXPLODE_SKELFIRE, Obj.X + 32 - 58, Obj.Y + 8 - 36);
+              begin // Âçðûâ ñíàðÿäà Ñêåëåòà
+                {$IFDEF ENABLE_GFX}
+                  g_GFX_QueueEffect(R_GFX_EXPLODE_SKELFIRE, Obj.X + 32 - 58, Obj.Y + 8 - 36);
                   g_DynLightExplosion((Obj.X+32), (Obj.Y+8), 64, 1, 0, 0);
-                end
+                {$ENDIF}
+              end
               else
-                begin // Âçðûâ Ðàêåòû
-                  r_GFX_OnceAnim(R_GFX_EXPLODE_ROCKET, cx - 64, cy - 64);
+              begin // Âçðûâ Ðàêåòû
+                {$IFDEF ENABLE_GFX}
+                  g_GFX_QueueEffect(R_GFX_EXPLODE_ROCKET, cx - 64, cy - 64);
                   g_DynLightExplosion(cx, cy, 64, 1, 0, 0);
-                end;
+                {$ENDIF}
+              end;
 
               g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEROCKET', Obj.X, Obj.Y);
 
@@ -2272,11 +2291,13 @@ begin
                (g_Weapon_Hit(@Obj, a, SpawnerUID, HIT_SOME, False) <> 0) or
                (Timeout < 1) then
             begin
-              if ShotType = WEAPON_PLASMA then
-                r_GFX_OnceAnim(R_GFX_EXPLODE_PLASMA, cx - 16, cy - 16)
-              else
-                r_GFX_OnceAnim(R_GFX_EXPLODE_BSPFIRE, cx - 16, cy - 16);
-              g_DynLightExplosion(cx, cy, 32, 0, 0.5, 0.5);
+              {$IFDEF ENABLE_GFX}
+                if ShotType = WEAPON_PLASMA then
+                  g_GFX_QueueEffect(R_GFX_EXPLODE_PLASMA, cx - 16, cy - 16)
+                else
+                  g_GFX_QueueEffect(R_GFX_EXPLODE_BSPFIRE, cx - 16, cy - 16);
+                g_DynLightExplosion(cx, cy, 32, 0, 0.5, 0.5);
+              {$ENDIF}
               g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEPLASMA', Obj.X, Obj.Y);
               ShotType := 0;
             end;
@@ -2295,13 +2316,17 @@ begin
             begin
               if WordBool(st and MOVE_HITWATER) then
               begin
-                tcx := Random(8);
-                tcy := Random(8);
-                r_GFX_OnceAnim(R_GFX_SMOKE, cx-4+tcx-(R_GFX_SMOKE_WIDTH div 2), cy-4+tcy-(R_GFX_SMOKE_HEIGHT div 2));
+                {$IFDEF ENABLE_GFX}
+                  tcx := Random(8);
+                  tcy := Random(8);
+                  g_GFX_QueueEffect(R_GFX_SMOKE, cx-4+tcx-(R_GFX_SMOKE_WIDTH div 2), cy-4+tcy-(R_GFX_SMOKE_HEIGHT div 2));
+                {$ENDIF}
               end
               else
               begin
-                g_GFX_Bubbles(cx, cy, 1+Random(3), 16, 16);
+                {$IFDEF ENABLE_GFX}
+                  g_GFX_Bubbles(cx, cy, 1+Random(3), 16, 16);
+                {$ENDIF}
                 if Random(2) = 0
                   then g_Sound_PlayExAt('SOUND_GAME_BUBBLE1', cx, cy)
                   else g_Sound_PlayExAt('SOUND_GAME_BUBBLE2', cx, cy);
@@ -2345,14 +2370,16 @@ begin
 
             if (gTime mod LongWord(tf) = 0) then
             begin
-              case Stopped of
-                MOVE_HITWALL: begin tcx := cx-4+Random(8); tcy := cy-12+Random(24); end;
-                MOVE_HITLAND: begin tcx := cx-12+Random(24); tcy := cy-10+Random(8); end;
-                MOVE_HITCEIL: begin tcx := cx-12+Random(24); tcy := cy+6+Random(8); end;
-                else begin tcx := cx-4+Random(8); tcy := cy-4+Random(8); end;
-              end;
-              r_GFX_OnceAnim(R_GFX_FLAME_RAND, tcx - (R_GFX_FLAME_WIDTH div 2), tcy - (R_GFX_FLAME_HEIGHT div 2));
-              //g_DynLightExplosion(tcx, tcy, 1, 1, 0.8, 0.3);
+              {$IFDEF ENABLE_GFX}
+                case Stopped of
+                  MOVE_HITWALL: begin tcx := cx-4+Random(8); tcy := cy-12+Random(24); end;
+                  MOVE_HITLAND: begin tcx := cx-12+Random(24); tcy := cy-10+Random(8); end;
+                  MOVE_HITCEIL: begin tcx := cx-12+Random(24); tcy := cy+6+Random(8); end;
+                  else begin tcx := cx-4+Random(8); tcy := cy-4+Random(8); end;
+                end;
+                g_GFX_QueueEffect(R_GFX_FLAME_RAND, tcx - (R_GFX_FLAME_WIDTH div 2), tcy - (R_GFX_FLAME_HEIGHT div 2));
+                //g_DynLightExplosion(tcx, tcy, 1, 1, 0.8, 0.3);
+              {$ENDIF}
             end;
           end;
 
@@ -2374,8 +2401,10 @@ begin
             begin
             // Ëó÷è BFG:
               if g_Game_IsServer then g_Weapon_BFG9000(cx, cy, SpawnerUID);
-              r_GFX_OnceAnim(R_GFX_EXPLODE_BFG, cx - 64, cy - 64);
-              g_DynLightExplosion(cx, cy, 96, 0, 1, 0);
+              {$IFDEF ENABLE_GFX}
+                g_GFX_QueueEffect(R_GFX_EXPLODE_BFG, cx - 64, cy - 64);
+                g_DynLightExplosion(cx, cy, 96, 0, 1, 0);
+              {$ENDIF}
               g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBFG', Obj.X, Obj.Y);
               ShotType := 0;
             end;
@@ -2401,11 +2430,13 @@ begin
                (g_Weapon_Hit(@Obj, a, SpawnerUID, HIT_SOME) <> 0) or
                (Timeout < 1) then
             begin
-              case ShotType of
-                WEAPON_IMP_FIRE: r_GFX_OnceAnim(R_GFX_EXPLODE_IMPFIRE, cx - 32, cy - 32);
-                WEAPON_CACO_FIRE: r_GFX_OnceAnim(R_GFX_EXPLODE_CACOFIRE, cx - 32, cy - 32);
-                WEAPON_BARON_FIRE: r_GFX_OnceAnim(R_GFX_EXPLODE_BARONFIRE, cx - 32, cy - 32);
-              end;
+              {$IFDEF ENABLE_GFX}
+                case ShotType of
+                  WEAPON_IMP_FIRE: g_GFX_QueueEffect(R_GFX_EXPLODE_IMPFIRE, cx - 32, cy - 32);
+                  WEAPON_CACO_FIRE: g_GFX_QueueEffect(R_GFX_EXPLODE_CACOFIRE, cx - 32, cy - 32);
+                  WEAPON_BARON_FIRE: g_GFX_QueueEffect(R_GFX_EXPLODE_BARONFIRE, cx - 32, cy - 32);
+                end;
+              {$ENDIF}
               g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBALL', Obj.X, Obj.Y);
               ShotType := 0;
             end;
@@ -2422,8 +2453,10 @@ begin
                (g_Weapon_Hit(@Obj, 40, SpawnerUID, HIT_SOME, False) <> 0) or
                (Timeout < 1) then
             begin
-            // Âçðûâ:
-              r_GFX_OnceAnim(R_GFX_EXPLODE_ROCKET, cx - 64, cy - 64);
+              // Âçðûâ:
+              {$IFDEF ENABLE_GFX}
+                g_GFX_QueueEffect(R_GFX_EXPLODE_ROCKET, cx - 64, cy - 64);
+              {$ENDIF}
               g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBALL', Obj.X, Obj.Y);
               ShotType := 0;
             end;
@@ -2435,11 +2468,7 @@ begin
       begin
         if gGameSettings.GameType = GT_SERVER then
           MH_SEND_DeleteShot(i, Obj.X, Obj.Y, Loud);
-        if Animation <> nil then
-        begin
-          Animation.Free();
-          Animation := nil;
-        end;
+        time := 0;
       end
       else if (ShotType <> WEAPON_FLAMETHROWER) and ((oldvx <> Obj.Vel.X) or (oldvy <> Obj.Vel.Y)) then
         if gGameSettings.GameType = GT_SERVER then
@@ -2545,47 +2574,14 @@ begin
     // Êîñòûëèíà åáàíàÿ
     Shots[i].Stopped := utils.readByte(st);
 
-    // Óñòàíîâêà òåêñòóðû èëè àíèìàöèè
-    Shots[i].Animation := nil;
-
-    case Shots[i].ShotType of
-      WEAPON_ROCKETLAUNCHER, WEAPON_SKEL_FIRE:
-        begin
-        end;
-      WEAPON_PLASMA:
-        begin
-          Shots[i].Animation := TAnimationState.Create(True, 5, 2); // !!! put values into table
-        end;
-      WEAPON_BFG:
-        begin
-          Shots[i].Animation := TAnimationState.Create(True, 6, 2); // !!! put values into table
-        end;
-      WEAPON_IMP_FIRE:
-        begin
-          Shots[i].Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
-        end;
-      WEAPON_BSP_FIRE:
-        begin
-          Shots[i].Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
-        end;
-      WEAPON_CACO_FIRE:
-        begin
-          Shots[i].Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
-        end;
-      WEAPON_BARON_FIRE:
-        begin
-          Shots[i].Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
-        end;
-      WEAPON_MANCUB_FIRE:
-        begin
-          Shots[i].Animation := TAnimationState.Create(True, 4, 2); // !!! put values into table
-        end;
-    end;
+    Shots[i].time := gTime; // TODO save time?
   end;
 end;
 
 procedure g_Weapon_DestroyShot(I: Integer; X, Y: Integer; Loud: Boolean = True);
-  var cx, cy: Integer;
+  {$IFDEF ENABLE_GFX}
+    var cx, cy: Integer;
+  {$ENDIF}
 begin
   if Shots = nil then
     Exit;
@@ -2596,18 +2592,22 @@ begin
     if ShotType = 0 then Exit;
     Obj.X := X;
     Obj.Y := Y;
-    cx := Obj.X + (Obj.Rect.Width div 2);
-    cy := Obj.Y + (Obj.Rect.Height div 2);
+    {$IFDEF ENABLE_GFX}
+      cx := Obj.X + (Obj.Rect.Width div 2);
+      cy := Obj.Y + (Obj.Rect.Height div 2);
+    {$ENDIF}
 
     case ShotType of
       WEAPON_ROCKETLAUNCHER, WEAPON_SKEL_FIRE: // Ðàêåòû è ñíàðÿäû Ñêåëåòà
       begin
         if Loud then
         begin
-          if ShotType = WEAPON_SKEL_FIRE then
-            r_GFX_OnceAnim(R_GFX_EXPLODE_SKELFIRE, (Obj.X + 32) - 32, (Obj.Y + 8) - 32)
-          else
-            r_GFX_OnceAnim(R_GFX_EXPLODE_ROCKET, cx - 64, cy - 64);
+          {$IFDEF ENABLE_GFX}
+            if ShotType = WEAPON_SKEL_FIRE then
+              g_GFX_QueueEffect(R_GFX_EXPLODE_SKELFIRE, (Obj.X + 32) - 32, (Obj.Y + 8) - 32)
+            else
+              g_GFX_QueueEffect(R_GFX_EXPLODE_ROCKET, cx - 64, cy - 64);
+          {$ENDIF}
           g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEROCKET', Obj.X, Obj.Y);
         end;
       end;
@@ -2616,17 +2616,21 @@ begin
       begin
         if loud then
         begin
-          if ShotType = WEAPON_PLASMA then
-            r_GFX_OnceAnim(R_GFX_EXPLODE_PLASMA, cx - 16, cy - 16)
-          else
-            r_GFX_OnceAnim(R_GFX_EXPLODE_BSPFIRE, cx - 16, cy - 16);
+          {$IFDEF ENABLE_GFX}
+            if ShotType = WEAPON_PLASMA then
+              g_GFX_QueueEffect(R_GFX_EXPLODE_PLASMA, cx - 16, cy - 16)
+            else
+              g_GFX_QueueEffect(R_GFX_EXPLODE_BSPFIRE, cx - 16, cy - 16);
+          {$ENDIF}
           g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEPLASMA', Obj.X, Obj.Y);
         end;
       end;
 
       WEAPON_BFG: // BFG
       begin
-        r_GFX_OnceAnim(R_GFX_EXPLODE_BFG, cx - 64, cy - 64);
+        {$IFDEF ENABLE_GFX}
+          g_GFX_QueueEffect(R_GFX_EXPLODE_BFG, cx - 64, cy - 64);
+        {$ENDIF}
         g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBFG', Obj.X, Obj.Y);
       end;
 
@@ -2634,24 +2638,27 @@ begin
       begin
         if loud then
         begin
-          case ShotType of
-            WEAPON_IMP_FIRE: r_GFX_OnceAnim(R_GFX_EXPLODE_IMPFIRE, cx - 32, cy - 32);
-            WEAPON_CACO_FIRE: r_GFX_OnceAnim(R_GFX_EXPLODE_CACOFIRE, cx - 32, cy - 32);
-            WEAPON_BARON_FIRE: r_GFX_OnceAnim(R_GFX_EXPLODE_BARONFIRE, cx - 32, cy - 32);
-          end;
+          {$IFDEF ENABLE_GFX}
+            case ShotType of
+              WEAPON_IMP_FIRE: g_GFX_QueueEffect(R_GFX_EXPLODE_IMPFIRE, cx - 32, cy - 32);
+              WEAPON_CACO_FIRE: g_GFX_QueueEffect(R_GFX_EXPLODE_CACOFIRE, cx - 32, cy - 32);
+              WEAPON_BARON_FIRE: g_GFX_QueueEffect(R_GFX_EXPLODE_BARONFIRE, cx - 32, cy - 32);
+            end;
+          {$ENDIF}
           g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBALL', Obj.X, Obj.Y);
         end;
       end;
 
       WEAPON_MANCUB_FIRE: // Âûñòðåë Ìàíêóáóñà
       begin
-        r_GFX_OnceAnim(R_GFX_EXPLODE_ROCKET, cx - 64, cy - 64);
+        {$IFDEF ENABLE_GFX}
+          g_GFX_QueueEffect(R_GFX_EXPLODE_ROCKET, cx - 64, cy - 64);
+        {$ENDIF}
         g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBALL', Obj.X, Obj.Y);
       end;
     end; // case ShotType of...
 
     ShotType := 0;
-    Animation.Free();
   end;
 end;