DEADSOFTWARE

Revert "no more delay between weapon switching: now player should release switching...
[d2df-sdl.git] / src / game / g_player.pas
index 6cc70f53c4a8c1fd232eb57d68721f364fae4214..980aec736c8905ea0c91ba5392caa2a70468aad8 100644 (file)
@@ -1512,11 +1512,20 @@ end;
 
 procedure g_Player_CreateCorpse(Player: TPlayer);
 var
+  i: Integer;
   find_id: DWORD;
   ok: Boolean;
 begin
   if Player.alive then
     Exit;
+
+// Ðàçðûâàåì ñâÿçü ñ ïðåæíèì òðóïîì:
+  if gCorpses <> nil then
+    for i := 0 to High(gCorpses) do
+      if gCorpses[i] <> nil then
+        if gCorpses[i].FPlayerUID = Player.FUID then
+          gCorpses[i].FPlayerUID := 0;
+
   if Player.FObj.Y >= gMapInfo.Height+128 then
     Exit;
 
@@ -1602,11 +1611,13 @@ procedure g_Player_CreateGibs(fX, fY: Integer; ModelName: string; fColor: TRGB);
 var
   a: Integer;
   GibsArray: TGibsArray;
+  Blood: TModelBlood;
 begin
   if (gGibs = nil) or (Length(gGibs) = 0) then
     Exit;
   if not g_PlayerModel_GetGibs(ModelName, GibsArray) then
     Exit;
+  Blood := g_PlayerModel_GetBlood(ModelName);
 
   for a := 0 to High(GibsArray) do
     with gGibs[CurrentGib] do
@@ -1625,7 +1636,7 @@ begin
 
       if gBloodCount > 0 then
         g_GFX_Blood(fX, fY, 16*gBloodCount+Random(5*gBloodCount), -16+Random(33), -16+Random(33),
-                    Random(48), Random(48), 150, 0, 0);
+                    Random(48), Random(48), Blood.R, Blood.G, Blood.B, Blood.Kind);
 
       if CurrentGib >= High(gGibs) then
         CurrentGib := 0
@@ -3509,11 +3520,11 @@ begin
   g_GFX_Blood(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)+8,
               FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2),
               Count div 2, 3, -1, 16, (PLAYER_RECT.Height*2 div 3),
-              150, 0, 0);
+              FModel.Blood.R, FModel.Blood.G, FModel.Blood.B, FModel.Blood.Kind);
   g_GFX_Blood(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-8,
               FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2),
               Count div 2, -3, -1, 16, (PLAYER_RECT.Height*2) div 3,
-              150, 0, 0);
+              FModel.Blood.R, FModel.Blood.G, FModel.Blood.B, FModel.Blood.Kind);
 end;
 
 procedure TPlayer.MakeBloodVector(Count: Word; VelX, VelY: Integer);
@@ -3521,7 +3532,7 @@ begin
   g_GFX_Blood(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2),
               FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2),
               Count, VelX, VelY, 16, (PLAYER_RECT.Height*2) div 3,
-              150, 0, 0);
+              FModel.Blood.R, FModel.Blood.G, FModel.Blood.B, FModel.Blood.Kind);
 end;
 
 procedure TPlayer.QueueWeaponSwitch(Weapon: Byte);
@@ -3542,8 +3553,8 @@ begin
   result := false;
   case weapon of
     WEAPON_KASTET, WEAPON_SAW: result := true;
-    WEAPON_SHOTGUN1, WEAPON_SHOTGUN2: result := (FAmmo[A_SHELLS] > 0);
-    WEAPON_PISTOL, WEAPON_CHAINGUN, WEAPON_SUPERPULEMET: result := (FAmmo[A_BULLETS] > 0);
+    WEAPON_SHOTGUN1, WEAPON_SHOTGUN2, WEAPON_SUPERPULEMET: result := (FAmmo[A_SHELLS] > 0);
+    WEAPON_PISTOL, WEAPON_CHAINGUN: 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);
@@ -3556,9 +3567,9 @@ function TPlayer.getNextWeaponIndex (): Byte;
 var
   i: Word;
   wantThisWeapon: array[0..64] of Boolean;
-  weaponOrder: array[0..64] of Integer; // value: index in `FWeapon`
-  wwc: Integer = 0; //HACK!
-  dir, cwi, rwidx, curlidx: Integer;
+  weaponOrder: array[0..16] of Integer; // value: index in `FWeapon`
+  wwc: Integer;
+  f, dir, cwi, rwidx, curlidx: Integer;
 
   function real2log (ridx: Integer): Integer;
   var
@@ -3566,7 +3577,7 @@ var
   begin
     if (ridx >= 0) then
     begin
-      for f := 0 to 10 do if (weaponOrder[f] = ridx) then begin result := f; exit; end;
+      for f := 0 to High(weaponOrder) do if (weaponOrder[f] = ridx) then begin result := f; exit; end;
     end;
     result := -1;
   end;
@@ -3581,22 +3592,39 @@ begin
     FNextWeapDelay := 0;
   end;
 
+  for f := 0 to High(weaponOrder) do weaponOrder[f] := -1;
+
   // build weapon order (k8: i know, i know, learn how to do constants and such... gtfo, please!)
+  // two knuckles are for "normal" and "berserk" (see `if` below -- it removes the one that is not needed)
   // priorities:
-  //   bfg, plasma, flamethrower, ssg, minigun, sg, pistol, berserk, chainsaw, fist
-  weaponOrder[0] := WEAPON_BFG;
-  weaponOrder[1] := WEAPON_PLASMA;
-  weaponOrder[2] := WEAPON_FLAMETHROWER;
-  weaponOrder[3] := WEAPON_SHOTGUN2;
-  weaponOrder[4] := WEAPON_CHAINGUN;
-  weaponOrder[5] := WEAPON_SHOTGUN1;
-  weaponOrder[6] := WEAPON_PISTOL;
-  weaponOrder[7] := WEAPON_KASTET;
-  weaponOrder[8] := WEAPON_SAW;
-  weaponOrder[9] := WEAPON_KASTET;
-  weaponOrder[10] := WEAPON_SUPERPULEMET;
-
-  if (R_BERSERK in FRulez) then weaponOrder[9] := -1 else weaponOrder[7] := -1;
+  //   bfg, launcher, plasma, flamethrower, ssg, minigun, sg, pistol, berserk, chainsaw, fist
+  weaponOrder[0] := WEAPON_SUPERPULEMET;
+  weaponOrder[1] := WEAPON_BFG;
+  weaponOrder[2] := WEAPON_ROCKETLAUNCHER;
+  weaponOrder[3] := WEAPON_PLASMA;
+  weaponOrder[4] := WEAPON_FLAMETHROWER;
+  weaponOrder[5] := WEAPON_SHOTGUN2;
+  weaponOrder[6] := WEAPON_CHAINGUN;
+  weaponOrder[7] := WEAPON_SHOTGUN1;
+  weaponOrder[8] := WEAPON_PISTOL;
+  weaponOrder[9] := WEAPON_KASTET+666; // berserk fist
+  weaponOrder[10] := WEAPON_SAW;
+  weaponOrder[11] := WEAPON_KASTET; // normal fist
+
+  for f := 0 to High(weaponOrder) do
+  begin
+    if (weaponOrder[f] = WEAPON_KASTET) then
+    begin
+      // normal fist: remove if we have a berserk pack
+      if (R_BERSERK in FRulez) then weaponOrder[f] := -1;
+    end
+    else
+    if (weaponOrder[f] = WEAPON_KASTET+666) then
+    begin
+      // berserk fist: remove if we don't have a berserk pack
+      if (R_BERSERK in FRulez) then weaponOrder[f] := WEAPON_KASTET else weaponOrder[f] := -1;
+    end;
+  end;
 
   (*
   WEAPON_KASTET         = 0;
@@ -3641,23 +3669,32 @@ begin
 
   // no cycling
   for i := 0 to High(wantThisWeapon) do wantThisWeapon[i] := false;
+  wwc := 0;
+
+  curlidx := -1; // start from a weapon with a highest priority (-1, 'cause loop will immediately increment this index)
+
   for i := 0 to High(FWeapon) do
   begin
     if (FNextWeap and (1 shl i)) <> 0 then
     begin
       cwi := real2log(i);
-      if (cwi >= 0) then wantThisWeapon[cwi] := true;
-      Inc(wwc);
+      if (cwi >= 0) then
+      begin
+        wantThisWeapon[cwi] := true;
+        Inc(wwc);
+        // if we hit currently selected weapon, start seachring from it, so we'll get "next weaker" weapon
+        if (i = FCurrWeap) then curlidx := cwi; // compare real, start from logical
+      end;
     end;
   end;
 
   // slow down alterations a little
   if (wwc > 1) then
   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
+      //e_WriteLog(Format(' FNextWeap=%x; delay=%d', [FNextWeap, FNextWeapDelay]), TMsgType.Warning);
       FNextWeap := 0;
       exit;
     end; // yeah
@@ -3670,26 +3707,22 @@ begin
     resetWeaponQueue();
     exit;
   end;
-  //e_WriteLog(Format('wwc=%d', [wwc]), TMsgType.Warning);
 
-  // exclude currently selected weapon from the set
-  curlidx := real2log(FCurrWeap);
-  //e_WriteLog(Format('FCurrWeap=%d; curlidx=%d', [FCurrWeap, curlidx]), TMsgType.Warning);
-  //if (curlidx >= 0) then wantThisWeapon[curlidx] := false;
-  //if (wwc = 2) then begin Dec(wwc); end; // easy case: switch between two weapons
+  //e_WriteLog(Format('*** wwc=%d; currweap=%d; logweap=%d', [wwc, FCurrWeap, curlidx]), TMsgType.Warning);
 
   // find next weapon to switch onto
   cwi := curlidx;
-  for i := 0 to High(FWeapon) do
+  for i := 0 to High(weaponOrder) do
   begin
-    cwi := (cwi+length(FWeapon)+1) mod length(FWeapon);
+    cwi := (cwi+length(weaponOrder)+1) mod length(weaponOrder);
     if (cwi = curlidx) then continue; // skip current weapon
     if not wantThisWeapon[cwi] then continue;
     rwidx := weaponOrder[cwi];
     if (rwidx < 0) then continue;
-    //e_WriteLog(Format('  trying logical %d (real %d)', [cwi, rwidx]), TMsgType.Warning);
-    if FWeapon[cwi] and ((wwc = 1) or hasAmmoForWeapon(cwi)) then
+    //e_WriteLog(Format('  trying logical %d (real %d); has=%d, hasammo=%d', [cwi, rwidx, Integer(FWeapon[rwidx]), Integer(hasAmmoForWeapon(rwidx))]), TMsgType.Warning);
+    if FWeapon[rwidx] and ((wwc = 1) or hasAmmoForWeapon(rwidx)) then
     begin
+      //e_WriteLog('    I FOUND HER!', TMsgType.Warning);
       // i found her!
       result := Byte(rwidx);
       resetWeaponQueue();
@@ -3737,7 +3770,7 @@ begin
   if nw > High(FWeapon) then
   begin
     // don't forget to reset queue here!
-    //e_WriteLog(' RealizeCurrentWeapon: WUTAFUUUU', MSG_WARNING);
+    //e_WriteLog(Format(' RealizeCurrentWeapon: WUTAFUUUU?! (%d)', [nw]), TMsgType.Warning);
     resetWeaponQueue();
     exit;
   end;
@@ -4143,6 +4176,7 @@ begin
           Result := True;
           remove := True;
           FFireTime := 0;
+          //k8:do we need it? if g_Game_IsNet and g_Game_IsServer then MH_SEND_PlayerStats(FUID);
         end;
         if FHealth < PLAYER_HP_SOFT then
         begin
@@ -4844,20 +4878,19 @@ begin
     Exit;
   if (gCorpses = nil) or (Length(gCorpses) = 0) then
     Exit;
-  if gCorpses <> nil then
-    for i := 0 to High(gCorpses) do
-      if gCorpses[i] <> nil then
-        if gCorpses[i].FPlayerUID = FUID then
-        begin
-          Result := True;
-          FObj.X := gCorpses[i].FObj.X;
-          FObj.Y := gCorpses[i].FObj.Y;
-          FObj.Vel.X := gCorpses[i].FObj.Vel.X;
-          FObj.Vel.Y := gCorpses[i].FObj.Vel.Y;
-          FObj.Accel.X := gCorpses[i].FObj.Accel.X;
-          FObj.Accel.Y := gCorpses[i].FObj.Accel.Y;
-          break;
-        end;
+  for i := 0 to High(gCorpses) do
+    if gCorpses[i] <> nil then
+      if gCorpses[i].FPlayerUID = FUID then
+      begin
+        Result := True;
+        FObj.X := gCorpses[i].FObj.X;
+        FObj.Y := gCorpses[i].FObj.Y;
+        FObj.Vel.X := gCorpses[i].FObj.Vel.X;
+        FObj.Vel.Y := gCorpses[i].FObj.Vel.Y;
+        FObj.Accel.X := gCorpses[i].FObj.Accel.X;
+        FObj.Accel.Y := gCorpses[i].FObj.Accel.Y;
+        break;
+      end;
 end;
 
 procedure TPlayer.Update();
@@ -6309,6 +6342,7 @@ end;
 procedure TCorpse.Damage(Value: Word; vx, vy: Integer);
 var
   pm: TPlayerModel;
+  Blood: TModelBlood;
 begin
   if FState = CORPSE_STATE_REMOVEME then
     Exit;
@@ -6331,16 +6365,23 @@ begin
         pm := g_PlayerModel_Get(FModelName);
         pm.PlaySound(MODELSOUND_DIE, 5, FObj.X, FObj.Y);
         pm.Free;
+
+        // Çëîâåùèé ñìåõ:
+        if (gBodyKillEvent <> -1)
+        and gDelayedEvents[gBodyKillEvent].Pending then
+          gDelayedEvents[gBodyKillEvent].Pending := False;
+        gBodyKillEvent := g_Game_DelayEvent(DE_BODYKILL, 1050, 0);
       end;
     end
   else
     begin
+      Blood := g_PlayerModel_GetBlood(FModelName);
       FObj.Vel.X := FObj.Vel.X + vx;
       FObj.Vel.Y := FObj.Vel.Y + vy;
       g_GFX_Blood(FObj.X+PLAYER_CORPSERECT.X+(PLAYER_CORPSERECT.Width div 2),
                   FObj.Y+PLAYER_CORPSERECT.Y+(PLAYER_CORPSERECT.Height div 2),
                   Value, vx, vy, 16, (PLAYER_CORPSERECT.Height*2) div 3,
-                  150, 0, 0);
+                  Blood.R, Blood.G, Blood.B, Blood.Kind);
     end;
 end;