DEADSOFTWARE

Player: Code formatting only
[d2df-sdl.git] / src / game / g_player.pas
index 5f4692fc081d81b7aff0581eba151c96e73328bf..ef8b1af0da19cfd20e0ea61faa118bc8474f298f 100644 (file)
@@ -50,11 +50,12 @@ const
   A_SHELLS          = 1;
   A_ROCKETS         = 2;
   A_CELLS           = 3;
-  A_HIGH            = 3;
+  A_FUEL            = 4;
+  A_HIGH            = 4;
 
   AmmoLimits: Array [0..1] of Array [A_BULLETS..A_HIGH] of Word =
-  ((200,  50,  50, 300),
-   (400, 100, 100, 600));
+  ((200,  50,  50, 300, 100),
+   (400, 100, 100, 600, 200));
 
   K_SIMPLEKILL      = 0;
   K_HARDKILL        = 1;
@@ -166,6 +167,8 @@ type
     FObj:       TObj;
     FXTo, FYTo: Integer;
     FSpectatePlayer: Integer;
+    FFirePainTime:   Integer;
+    FFireAttacker:   Word;
 
     FSavedState: TPlayerSavedState;
 
@@ -200,6 +203,7 @@ type
     function    FullInLift(XInc, YInc: Integer): Integer;
     {procedure   CollideItem();}
     procedure   FlySmoke(Times: DWORD = 1);
+    procedure   OnFireFlame(Times: DWORD = 1);
     function    GetAmmoByWeapon(Weapon: Byte): Word;
     procedure   SetAction(Action: Byte; Force: Boolean = False);
     procedure   OnDamage(Angle: SmallInt); virtual;
@@ -243,6 +247,7 @@ type
     FPing:      Word;
     FLoss:      Byte;
     FDummy:     Boolean;
+    FFireTime:  Integer;
 
     constructor Create(); virtual;
     destructor  Destroy(); override;
@@ -304,6 +309,7 @@ type
     procedure   RealizeCurrentWeapon();
     procedure   JetpackOn;
     procedure   JetpackOff;
+    procedure   CatchFire(Attacker: Word);
 
     property    Name: String read FName write FName;
     property    Model: TPlayerModel read FModel;
@@ -547,27 +553,30 @@ const
                                                    (R:0; G:0; B:255));
   DIFFICULT_EASY: TDifficult = (DiagFire: 32; InvisFire: 32; DiagPrecision: 32;
                                 FlyPrecision: 32; Cover: 32; CloseJump: 32;
-                                WeaponPrior:(0,0,0,0,0,0,0,0,0,0); CloseWeaponPrior:(0,0,0,0,0,0,0,0,0,0));
+                                WeaponPrior:(0,0,0,0,0,0,0,0,0,0,0); CloseWeaponPrior:(0,0,0,0,0,0,0,0,0,0,0));
   DIFFICULT_MEDIUM: TDifficult = (DiagFire: 127; InvisFire: 127; DiagPrecision: 127;
                                   FlyPrecision: 127; Cover: 127; CloseJump: 127;
-                                WeaponPrior:(0,0,0,0,0,0,0,0,0,0); CloseWeaponPrior:(0,0,0,0,0,0,0,0,0,0));
+                                WeaponPrior:(0,0,0,0,0,0,0,0,0,0,0); CloseWeaponPrior:(0,0,0,0,0,0,0,0,0,0,0));
   DIFFICULT_HARD: TDifficult = (DiagFire: 255; InvisFire: 255; DiagPrecision: 255;
                                 FlyPrecision: 255; Cover: 255; CloseJump: 255;
-                                WeaponPrior:(0,0,0,0,0,0,0,0,0,0); CloseWeaponPrior:(0,0,0,0,0,0,0,0,0,0));
+                                WeaponPrior:(0,0,0,0,0,0,0,0,0,0,0); CloseWeaponPrior:(0,0,0,0,0,0,0,0,0,0,0));
   WEAPON_PRIOR1: Array [WP_FIRST..WP_LAST] of Byte =
-                                (WEAPON_SUPERPULEMET, WEAPON_SHOTGUN2, WEAPON_SHOTGUN1,
+                                (WEAPON_FLAMETHROWER, WEAPON_SUPERPULEMET,
+                                 WEAPON_SHOTGUN2, WEAPON_SHOTGUN1,
                                  WEAPON_CHAINGUN, WEAPON_PLASMA, WEAPON_ROCKETLAUNCHER,
                                  WEAPON_BFG, WEAPON_PISTOL, WEAPON_SAW, WEAPON_KASTET);
   WEAPON_PRIOR2: Array [WP_FIRST..WP_LAST] of Byte =
-                                (WEAPON_SUPERPULEMET, WEAPON_BFG, WEAPON_ROCKETLAUNCHER,
+                                (WEAPON_FLAMETHROWER, WEAPON_SUPERPULEMET,
+                                 WEAPON_BFG, WEAPON_ROCKETLAUNCHER,
                                  WEAPON_SHOTGUN2, WEAPON_PLASMA, WEAPON_SHOTGUN1,
                                  WEAPON_CHAINGUN, WEAPON_PISTOL, WEAPON_SAW, WEAPON_KASTET);
   //WEAPON_PRIOR3: Array [WP_FIRST..WP_LAST] of Byte =
-  //                              (WEAPON_SUPERPULEMET, WEAPON_BFG, WEAPON_PLASMA,
-  //                               WEAPON_SHOTGUN2, WEAPON_CHAINGUN, WEAPON_SHOTGUN1,
-  //                               WEAPON_SAW, WEAPON_ROCKETLAUNCHER, WEAPON_PISTOL, WEAPON_KASTET);
+  //                              (WEAPON_FLAMETHROWER, WEAPON_SUPERPULEMET,
+  //                               WEAPON_BFG, WEAPON_PLASMA, WEAPON_SHOTGUN2,
+  //                               WEAPON_CHAINGUN, WEAPON_SHOTGUN1, WEAPON_SAW,
+  //                               WEAPON_ROCKETLAUNCHER, WEAPON_PISTOL, WEAPON_KASTET);
   WEAPON_RELOAD: Array [WP_FIRST..WP_LAST] of Byte =
-                                (5, 2, 6, 18, 36, 2, 12, 2, 14, 2);
+                                (5, 2, 6, 18, 36, 2, 12, 2, 14, 2, 2);
 
   PLAYER_SIGNATURE = $52594C50; // 'PLYR'
   CORPSE_SIGNATURE = $50524F43; // 'CORP'
@@ -1983,6 +1992,9 @@ begin
   FLoss := 0;
   FSavedState.WaitRecall := False;
   FShellTimer := -1;
+  FFireTime := 0;
+  FFirePainTime := 0;
+  FFireAttacker := 0;
 
   FActualModelName := 'doomer';
 
@@ -2492,6 +2504,7 @@ begin
     WEAPON_ROCKETLAUNCHER: ID := gItemsTexturesID[ITEM_WEAPON_ROCKETLAUNCHER];
     WEAPON_PLASMA: ID := gItemsTexturesID[ITEM_WEAPON_PLASMA];
     WEAPON_BFG: ID := gItemsTexturesID[ITEM_WEAPON_BFG];
+    WEAPON_FLAMETHROWER: ID := gItemsTexturesID[ITEM_WEAPON_FLAMETHROWER];
   end;
 
   e_CharFont_GetSize(gMenuFont, s, tw, th);
@@ -2799,6 +2812,17 @@ begin
         g_Player_CreateShell(GameX+PLAYER_RECT_CX, GameY+PLAYER_RECT_CX,
                              GameVelX, GameVelY-2, SHELL_SHELL);
       end;
+
+    WEAPON_FLAMETHROWER:
+      if FAmmo[A_FUEL] > 0 then
+      begin
+        g_Weapon_flame(wx, wy, xd, yd, FUID);
+        FReloading[FCurrWeap] := WEAPON_RELOAD[FCurrWeap];
+        Dec(FAmmo[A_FUEL]);
+        FFireAngle := FAngle;
+        f := True;
+        DidFire := True;
+      end;
   end;
 
   if g_Game_IsNet then
@@ -2829,6 +2853,7 @@ begin
     WEAPON_SHOTGUN1, WEAPON_SHOTGUN2, WEAPON_SUPERPULEMET: Result := FAmmo[A_SHELLS];
     WEAPON_ROCKETLAUNCHER: Result := FAmmo[A_ROCKETS];
     WEAPON_PLASMA, WEAPON_BFG: Result := FAmmo[A_CELLS];
+    WEAPON_FLAMETHROWER: Result := FAmmo[A_FUEL];
     else Result := 0;
   end;
 end;
@@ -2857,6 +2882,14 @@ begin
   FJetSoundOff.PlayAt(FObj.X, FObj.Y);
 end;
 
+procedure TPlayer.CatchFire(Attacker: Word);
+begin
+  FFireTime := 100;
+  FFireAttacker := Attacker;
+  if g_Game_IsNet and g_Game_IsServer then
+    MH_SEND_PlayerStats(FUID);
+end;
+
 procedure TPlayer.Jump();
 begin
   if gFly or FJetpack then
@@ -3100,6 +3133,7 @@ begin
           WEAPON_PLASMA: i := ITEM_WEAPON_PLASMA;
           WEAPON_BFG: i := ITEM_WEAPON_BFG;
           WEAPON_SUPERPULEMET: i := ITEM_WEAPON_SUPERPULEMET;
+          WEAPON_FLAMETHROWER: i := ITEM_WEAPON_FLAMETHROWER;
           else i := 0;
         end;
 
@@ -3307,6 +3341,7 @@ begin
     WEAPON_PISTOL, WEAPON_CHAINGUN, WEAPON_SUPERPULEMET: result := (FAmmo[A_BULLETS] > 0);
     WEAPON_ROCKETLAUNCHER: result := (FAmmo[A_ROCKETS] > 0);
     WEAPON_PLASMA, WEAPON_BFG: result := (FAmmo[A_CELLS] > 0);
+    WEAPON_FLAMETHROWER: result := (FAmmo[A_FUEL] > 0);
     else result := (weapon < length(FWeapon));
   end;
 end;
@@ -3321,13 +3356,21 @@ var
 begin
   result := 255; // default result: "no switch"
   // had weapon cycling on previous frame? remove that flag
-  if (FNextWeap and $2000) <> 0 then begin FNextWeap := FNextWeap and $1FFF; FNextWeapDelay := 0; end;
+  if (FNextWeap and $2000) <> 0 then
+  begin
+    FNextWeap := FNextWeap and $1FFF;
+    FNextWeapDelay := 0;
+  end;
   // cycling has priority
   if (FNextWeap and $C000) <> 0 then
   begin
-    if (FNextWeap and $8000) <> 0 then dir := 1 else dir := -1;
+    if (FNextWeap and $8000) <> 0 then
+      dir := 1
+    else
+      dir := -1;
     FNextWeap := FNextWeap or $2000; // we need this
-    if FNextWeapDelay > 0 then exit; // cooldown time
+    if FNextWeapDelay > 0 then
+      exit; // cooldown time
     cwi := FCurrWeap;
     for i := 0 to High(FWeapon) do
     begin
@@ -3344,8 +3387,14 @@ begin
     exit;
   end;
   // no cycling
-  for i := 0 to High(wantThisWeapon) do wantThisWeapon[i] := false;
-  for i := 0 to High(FWeapon) do if (FNextWeap and (1 shl i)) <> 0 then begin wantThisWeapon[i] := true; Inc(wwc); end;
+  for i := 0 to High(wantThisWeapon) do
+    wantThisWeapon[i] := false;
+  for i := 0 to High(FWeapon) do
+    if (FNextWeap and (1 shl i)) <> 0 then
+    begin
+      wantThisWeapon[i] := true;
+      Inc(wwc);
+    end;
   // exclude currently selected weapon from the set
   wantThisWeapon[FCurrWeap] := false;
   // slow down alterations a little
@@ -3353,11 +3402,19 @@ begin
   begin
     //e_WriteLog(Format(' FNextWeap=%x; delay=%d', [FNextWeap, FNextWeapDelay]), MSG_WARNING);
     // more than one weapon requested, assume "alteration" and check alteration delay
-    if FNextWeapDelay > 0 then begin FNextWeap := 0; exit; end; // yeah
+    if FNextWeapDelay > 0 then
+    begin
+      FNextWeap := 0;
+      exit;
+    end; // yeah
   end;
   // do not reset weapon queue, it will be done in `RealizeCurrentWeapon()`
   // but clear all counters if no weapon should be switched
-  if wwc < 1 then begin resetWeaponQueue(); exit; end;
+  if wwc < 1 then
+  begin
+    resetWeaponQueue();
+    exit;
+  end;
   //e_WriteLog(Format('wwc=%d', [wwc]), MSG_WARNING);
   // try weapons in descending order
   for i := High(FWeapon) downto 0 do
@@ -3466,6 +3523,7 @@ begin
         IncMax(FHealth, 10, PLAYER_HP_SOFT);
         Result := True;
         remove := True;
+        FFireTime := 0;
         if gFlash = 2 then Inc(FPickup, 5);
       end;
 
@@ -3475,6 +3533,7 @@ begin
         IncMax(FHealth, 25, PLAYER_HP_SOFT);
         Result := True;
         remove := True;
+        FFireTime := 0;
         if gFlash = 2 then Inc(FPickup, 5);
       end;
 
@@ -3502,6 +3561,7 @@ begin
         IncMax(FHealth, 100, PLAYER_HP_LIMIT);
         Result := True;
         remove := True;
+        FFireTime := 0;
         if gFlash = 2 then Inc(FPickup, 5);
       end;
 
@@ -3514,6 +3574,7 @@ begin
           FArmor := PLAYER_AP_LIMIT;
         Result := True;
         remove := True;
+        FFireTime := 0;
         if gFlash = 2 then Inc(FPickup, 5);
       end;
 
@@ -3611,6 +3672,18 @@ begin
         if a and g_Game_IsNet then MH_SEND_Sound(GameX, GameY, 'SOUND_ITEM_GETWEAPON');
       end;
 
+    ITEM_WEAPON_FLAMETHROWER:
+      if (FAmmo[A_FUEL] < FMaxAmmo[A_FUEL]) or not FWeapon[WEAPON_FLAMETHROWER] then
+      begin
+        if a and FWeapon[WEAPON_FLAMETHROWER] then Exit;
+
+        IncMax(FAmmo[A_FUEL], 100, FMaxAmmo[A_FUEL]);
+        FWeapon[WEAPON_FLAMETHROWER] := True;
+        Result := True;
+        if gFlash = 2 then Inc(FPickup, 5);
+        if a and g_Game_IsNet then MH_SEND_Sound(GameX, GameY, 'SOUND_ITEM_GETWEAPON');
+      end;
+
     ITEM_AMMO_BULLETS:
       if FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS] then
       begin
@@ -3683,17 +3756,28 @@ begin
         if gFlash = 2 then Inc(FPickup, 5);
       end;
 
+    ITEM_AMMO_FUELCAN:
+      if FAmmo[A_FUEL] < FMaxAmmo[A_FUEL] then
+      begin
+        IncMax(FAmmo[A_FUEL], 100, FMaxAmmo[A_FUEL]);
+        Result := True;
+        remove := True;
+        if gFlash = 2 then Inc(FPickup, 5);
+      end;
+
     ITEM_AMMO_BACKPACK:
       if not(R_ITEM_BACKPACK in FRulez) or
             (FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS]) or
             (FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS]) or
             (FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS]) or
-            (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) then
+            (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) or
+            (FMaxAmmo[A_FUEL] < AmmoLimits[1, A_FUEL]) then
       begin
         FMaxAmmo[A_BULLETS] := AmmoLimits[1, A_BULLETS];
         FMaxAmmo[A_SHELLS] := AmmoLimits[1, A_SHELLS];
         FMaxAmmo[A_ROCKETS] := AmmoLimits[1, A_ROCKETS];
         FMaxAmmo[A_CELLS] := AmmoLimits[1, A_CELLS];
+        FMaxAmmo[A_FUEL] := AmmoLimits[1, A_FUEL];
 
         if FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS] then
           IncMax(FAmmo[A_BULLETS], 10, FMaxAmmo[A_BULLETS]);
@@ -3746,6 +3830,7 @@ begin
         FMegaRulez[MR_SUIT] := gTime+PLAYER_SUIT_TIME;
         Result := True;
         remove := True;
+        FFireTime := 0;
         if gFlash = 2 then Inc(FPickup, 5);
       end;
 
@@ -3775,6 +3860,7 @@ begin
           FBerserk := gTime+30000;
           Result := True;
           remove := True;
+          FFireTime := 0;
         end;
         if FHealth < PLAYER_HP_SOFT then
         begin
@@ -3782,6 +3868,7 @@ begin
           FBerserk := gTime+30000;
           Result := True;
           remove := True;
+          FFireTime := 0;
         end;
       end;
 
@@ -3800,6 +3887,7 @@ begin
         IncMax(FHealth, 4, PLAYER_HP_LIMIT);
         Result := True;
         remove := True;
+        FFireTime := 0;
         if gFlash = 2 then Inc(FPickup, 5);
       end;
 
@@ -4134,6 +4222,7 @@ begin
     FMaxAmmo[A_SHELLS] := AmmoLimits[0, A_SHELLS];
     FMaxAmmo[A_ROCKETS] := AmmoLimits[0, A_SHELLS];
     FMaxAmmo[A_CELLS] := AmmoLimits[0, A_CELLS];
+    FMaxAmmo[A_FUEL] := AmmoLimits[0, A_FUEL];
 
     if gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF] then
       FRulez := [R_KEY_RED, R_KEY_GREEN, R_KEY_BLUE]
@@ -4180,6 +4269,9 @@ begin
   FDamageBuffer := 0;
   FJetpack := False;
   FCanJetpack := False;
+  FFireTime := 0;
+  FFirePainTime := 0;
+  FFireAttacker := 0;
 
 // Àíèìàöèÿ âîçðîæäåíèÿ:
   if (not gLoadGameMode) and (not Silent) then
@@ -4771,6 +4863,35 @@ begin
     end else if FAir < AIR_DEF then
       FAir := AIR_DEF;
 
+    if FFireTime > 0 then
+    begin
+      if BodyInLiquid(0, 0) then
+      begin
+        FFireTime := 0;
+        FFirePainTime := 0;
+      end
+      else if FMegaRulez[MR_SUIT] >= gTime then
+      begin
+        if FMegaRulez[MR_SUIT] = gTime then
+          FFireTime := 1;
+        FFirePainTime := 0;
+      end
+      else
+      begin
+        OnFireFlame(1);
+        if FFirePainTime <= 0 then
+        begin
+          if g_Game_IsServer then
+            Damage(5, FFireAttacker, 0, 0, HIT_FLAME);
+          FFirePainTime := 18;
+        end;
+        FFirePainTime := FFirePainTime - 1;
+        FFireTime := FFireTime - 1;
+        if (FFireTime = 0) and g_Game_IsNet and g_Game_IsServer then
+          MH_SEND_PlayerStats(FUID);
+      end;
+    end;
+
     if FDamageBuffer > 0 then
     begin
       if FDamageBuffer >= 9 then
@@ -5042,6 +5163,13 @@ begin
       g_Player_CreateShell(GameX+PLAYER_RECT_CX, GameY+PLAYER_RECT_CX,
                              GameVelX, GameVelY-2, SHELL_SHELL);
     end;
+
+    WEAPON_FLAMETHROWER:
+    begin
+      g_Weapon_flame(wx, wy, xd, yd, FUID, WID);
+      FFireAngle := FAngle;
+      f := True;
+    end;
   end;
 
   if not f then Exit;
@@ -5726,6 +5854,7 @@ begin
     ITEM_WEAPON_PLASMA: FWeapon[WEAPON_PLASMA] := True;
     ITEM_WEAPON_BFG: FWeapon[WEAPON_BFG] := True;
     ITEM_WEAPON_SUPERPULEMET: FWeapon[WEAPON_SUPERPULEMET] := True;
+    ITEM_WEAPON_FLAMETHROWER: FWeapon[WEAPON_FLAMETHROWER] := True;
 
     ITEM_AMMO_BULLETS: if FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS] then IncMax(FAmmo[A_BULLETS], 10, FMaxAmmo[A_BULLETS]);
     ITEM_AMMO_BULLETS_BOX: if FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS] then IncMax(FAmmo[A_BULLETS], 50, FMaxAmmo[A_BULLETS]);
@@ -5735,17 +5864,20 @@ begin
     ITEM_AMMO_ROCKET_BOX: if FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS] then IncMax(FAmmo[A_ROCKETS], 5, FMaxAmmo[A_ROCKETS]);
     ITEM_AMMO_CELL: if FAmmo[A_CELLS] < FMaxAmmo[A_CELLS] then IncMax(FAmmo[A_CELLS], 40, FMaxAmmo[A_CELLS]);
     ITEM_AMMO_CELL_BIG: if FAmmo[A_CELLS] < FMaxAmmo[A_CELLS] then IncMax(FAmmo[A_CELLS], 100, FMaxAmmo[A_CELLS]);
+    ITEM_AMMO_FUELCAN: if FAmmo[A_FUEL] < FMaxAmmo[A_FUEL] then IncMax(FAmmo[A_FUEL], 100, FMaxAmmo[A_FUEL]);
 
     ITEM_AMMO_BACKPACK:
       if (FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS]) or
          (FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS]) or
          (FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS]) or
-         (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) then
+         (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) or
+         (FMaxAmmo[A_FUEL] < AmmoLimits[1, A_FUEL]) then
       begin
         FMaxAmmo[A_BULLETS] := AmmoLimits[1, A_BULLETS];
         FMaxAmmo[A_SHELLS] := AmmoLimits[1, A_SHELLS];
         FMaxAmmo[A_ROCKETS] := AmmoLimits[1, A_ROCKETS];
         FMaxAmmo[A_CELLS] := AmmoLimits[1, A_CELLS];
+        FMaxAmmo[A_FUEL] := AmmoLimits[1, A_FUEL];
 
         if FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS] then IncMax(FAmmo[A_BULLETS], 10, FMaxAmmo[A_BULLETS]);
         if FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS] then IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
@@ -5801,6 +5933,27 @@ begin
   end;
 end;
 
+procedure TPlayer.OnFireFlame(Times: DWORD = 1);
+var
+  id, i: DWORD;
+  Anim: TAnimation;
+begin
+  if (Random(10) = 1) and (Times = 1) then
+    Exit;
+
+  if g_Frames_Get(id, 'FRAMES_FLAME') then
+  begin
+    for i := 1 to Times do
+    begin
+      Anim := TAnimation.Create(id, False, 3);
+      Anim.Alpha := 0;
+      g_GFX_OnceAnim(Obj.X+Obj.Rect.X+Random(Obj.Rect.Width+Times*2)-(Anim.Width div 2),
+                   Obj.Y+8+Random(8+Times*2), Anim, ONCEANIM_SMOKE);
+      Anim.Free();
+    end;
+  end;
+end;
+
 procedure TPlayer.PauseSounds(Enable: Boolean);
 begin
   FSawSound.Pause(Enable);
@@ -6093,7 +6246,7 @@ var
   firew, fireh: Integer;
   angle: SmallInt;
   mon: TMonster;
-  pla: TPlayer;
+  pla, tpla: TPlayer;
   vsPlayer, vsMonster, ok: Boolean;
 begin
   vsPlayer := LongBool(gGameSettings.Options and GAME_OPTION_BOTVSPLAYER);
@@ -6110,7 +6263,7 @@ begin
 
       case FCurrWeap of
         WEAPON_PLASMA, WEAPON_SUPERPULEMET, WEAPON_CHAINGUN: PressKey(KEY_FIRE, 20);
-        WEAPON_SAW, WEAPON_KASTET, WEAPON_MEGAKASTET: PressKey(KEY_FIRE, 40);
+        WEAPON_SAW, WEAPON_KASTET, WEAPON_FLAMETHROWER: PressKey(KEY_FIRE, 40);
         else PressKey(KEY_FIRE);
       end;
     end;
@@ -6127,14 +6280,16 @@ begin
       if (g_GetUIDType(Target.UID) = UID_PLAYER) and
           vsPlayer then
         begin // Èãðîê
-          with g_Player_Get(Target.UID) do
-            begin
-              if (@FObj) <> nil then
+          tpla := g_Player_Get(Target.UID);
+          if tpla <> nil then
+            with tpla do
               begin
-                Target.X := FObj.X;
-                Target.Y := FObj.Y;
+                if (@FObj) <> nil then
+                begin
+                  Target.X := FObj.X;
+                  Target.Y := FObj.Y;
+                end;
               end;
-            end;
 
           Target.cX := Target.X + PLAYER_RECT_CX;
           Target.cY := Target.Y + PLAYER_RECT_CY;
@@ -7082,6 +7237,7 @@ var
       WEAPON_PLASMA: Result := FAmmo[A_CELLS] >= 10;
       WEAPON_BFG: Result := FAmmo[A_CELLS] >= 40;
       WEAPON_SUPERPULEMET: Result := FAmmo[A_SHELLS] >= 1;
+      WEAPON_FLAMETHROWER: Result := FAmmo[A_FUEL] >= 1;
       else Result := True;
     end;
   end;