DEADSOFTWARE

Medkits now always extinguish fire
[d2df-sdl.git] / src / game / g_player.pas
index 5d1f863faa686c667ec21470ffed524e700c4778..3549b11b2b5b56a036d448b2939bd7a01787b194 100644 (file)
@@ -102,6 +102,7 @@ const
 
 type
   TPlayerStat = record
+    Num: Integer;
     Ping: Word;
     Loss: Byte;
     Name: String;
@@ -262,8 +263,10 @@ type
     FClientID:  SmallInt;
     FPing:      Word;
     FLoss:      Byte;
+    FReady:     Boolean;
     FDummy:     Boolean;
     FFireTime:  Integer;
+    FHandicap:  Integer;
 
     // debug: viewport offset
     viewPortX, viewPortY, viewPortW, viewPortH: Integer;
@@ -592,8 +595,9 @@ procedure g_Player_DrawShells();
 procedure g_Player_RemoveAllCorpses();
 procedure g_Player_Corpses_SaveState (st: TStream);
 procedure g_Player_Corpses_LoadState (st: TStream);
-procedure g_Bot_Add(Team, Difficult: Byte);
-procedure g_Bot_AddList(Team: Byte; lname: ShortString; num: Integer = -1);
+procedure g_Player_ResetReady();
+procedure g_Bot_Add(Team, Difficult: Byte; Handicap: Integer = 100);
+procedure g_Bot_AddList(Team: Byte; lname: ShortString; num: Integer = -1; Handicap: Integer = 100);
 procedure g_Bot_MixNames();
 procedure g_Bot_RemoveAll();
 
@@ -882,6 +886,8 @@ begin
   if b = 1 then gPlayers[a].FDirection := TDirection.D_LEFT else gPlayers[a].FDirection := TDirection.D_RIGHT; // b = 2
   // Çäîðîâüå
   gPlayers[a].FHealth := utils.readLongInt(st);
+  // Ôîðà
+  gPlayers[a].FHandicap := utils.readLongInt(st);
   // Æèçíè
   gPlayers[a].FLives := utils.readByte(st);
   // Áðîíÿ
@@ -1003,7 +1009,7 @@ begin
       end;
 end;
 
-procedure g_Bot_Add(Team, Difficult: Byte);
+procedure g_Bot_Add(Team, Difficult: Byte; Handicap: Integer = 100);
 var
   m: SSArray;
   _name, _model: String;
@@ -1092,6 +1098,8 @@ begin
       //FDifficult.SafeWeaponPrior[a] := WEAPON_PRIOR3[a];
     end;
 
+    FHandicap := Handicap;
+
     g_Console_Add(Format(_lc[I_PLAYER_JOIN], [Name]), True);
 
     if g_Game_IsNet then MH_SEND_PlayerCreate(UID);
@@ -1100,7 +1108,7 @@ begin
   end;
 end;
 
-procedure g_Bot_AddList(Team: Byte; lName: ShortString; num: Integer = -1);
+procedure g_Bot_AddList(Team: Byte; lName: ShortString; num: Integer = -1; Handicap: Integer = 100);
 var
   m: SSArray;
   _name, _model: String;
@@ -1163,6 +1171,8 @@ begin
     FDifficult.Cover := BotList[num].cover;
     FDifficult.CloseJump := BotList[num].close_jump;
 
+    FHandicap := Handicap;
+
     for a := WP_FIRST to WP_LAST do
     begin
       FDifficult.WeaponPrior[a] := BotList[num].w_prior1[a];
@@ -1471,6 +1481,7 @@ begin
       SetLength(Result, Length(Result)+1);
       with Result[High(Result)] do
       begin
+        Num := a;
         Ping := gPlayers[a].FPing;
         Loss := gPlayers[a].FLoss;
         Name := gPlayers[a].FName;
@@ -1485,6 +1496,22 @@ begin
     end;
 end;
 
+procedure g_Player_ResetReady();
+var
+  a: Integer;
+begin
+  if not g_Game_IsServer then Exit;
+  if gPlayers = nil then Exit;
+
+  for a := 0 to High(gPlayers) do
+    if gPlayers[a] <> nil then
+    begin
+      gPlayers[a].FReady := False;
+      if g_Game_IsNet then
+        MH_SEND_GameEvent(NET_EV_INTER_READY, gPlayers[a].UID, 'N');
+    end;
+end;
+
 procedure g_Player_RememberAll;
 var
   i: Integer;
@@ -2132,6 +2159,7 @@ begin
   FFireTime := 0;
   FFirePainTime := 0;
   FFireAttacker := 0;
+  FHandicap := 100;
 
   FActualModelName := 'doomer';
 
@@ -2300,12 +2328,12 @@ var
 begin
   if FAlive then
     begin
-      indX := FObj.X+FObj.Rect.X;
-      indY := FObj.Y;
       if g_Texture_Get('TEXTURE_PLAYER_INDICATOR', ID) then
         begin
           e_GetTextureSize(ID, @indW, @indH);
-          e_Draw(ID, indX + indW div 2, indY - indH, 0, True, False);
+          indX := FObj.X + FObj.Rect.X + (FObj.Rect.Width - indW) div 2;
+          indY := FObj.Y;
+          e_Draw(ID, indX, indY - indH, 0, True, False);
         end;
     end;
   //e_TextureFontPrint(indX, indY, FName, gStdFont); // Shows player name overhead
@@ -3163,7 +3191,11 @@ end;
 
 procedure TPlayer.CatchFire(Attacker: Word);
 begin
-  FFireTime := 100;
+  if (FMegaRulez[MR_SUIT] > gTime) or (FMegaRulez[MR_INVUL] > gTime) then
+    exit; // Íå çàãîðàåìñÿ êîãäà åñòü çàùèòà
+  if FFireTime <= 0 then
+    g_Sound_PlayExAt('SOUND_IGNITE', FObj.X, FObj.Y);
+  FFireTime := 110;
   FFireAttacker := Attacker;
   if g_Game_IsNet and g_Game_IsServer then
     MH_SEND_PlayerStats(FUID);
@@ -3715,7 +3747,7 @@ begin
       // i found her!
       result := Byte(i);
       resetWeaponQueue();
-      FNextWeapDelay := WEAPON_DELAY; // anyway, 'cause why not
+      FNextWeapDelay := WEAPON_DELAY * 2; // anyway, 'cause why not
       exit;
     end;
   end;
@@ -3819,9 +3851,9 @@ begin
 
   case ItemType of
     ITEM_MEDKIT_SMALL:
-      if FHealth < PLAYER_HP_SOFT then
+      if (FHealth < PLAYER_HP_SOFT) or (FFireTime > 0) then
       begin
-        IncMax(FHealth, 10, PLAYER_HP_SOFT);
+        if FHealth < PLAYER_HP_SOFT then IncMax(FHealth, 10, PLAYER_HP_SOFT);
         Result := True;
         remove := True;
         FFireTime := 0;
@@ -3829,9 +3861,9 @@ begin
       end;
 
     ITEM_MEDKIT_LARGE:
-      if FHealth < PLAYER_HP_SOFT then
+      if (FHealth < PLAYER_HP_SOFT) or (FFireTime > 0) then
       begin
-        IncMax(FHealth, 25, PLAYER_HP_SOFT);
+        if FHealth < PLAYER_HP_SOFT then IncMax(FHealth, 25, PLAYER_HP_SOFT);
         Result := True;
         remove := True;
         FFireTime := 0;
@@ -3857,9 +3889,9 @@ begin
       end;
 
     ITEM_SPHERE_BLUE:
-      if FHealth < PLAYER_HP_LIMIT then
+      if (FHealth < PLAYER_HP_LIMIT) or (FFireTime > 0) then
       begin
-        IncMax(FHealth, 100, PLAYER_HP_LIMIT);
+        if FHealth < PLAYER_HP_LIMIT then IncMax(FHealth, 100, PLAYER_HP_LIMIT);
         Result := True;
         remove := True;
         FFireTime := 0;
@@ -3867,7 +3899,7 @@ begin
       end;
 
     ITEM_SPHERE_WHITE:
-      if (FHealth < PLAYER_HP_LIMIT) or (FArmor < PLAYER_AP_LIMIT) then
+      if (FHealth < PLAYER_HP_LIMIT) or (FArmor < PLAYER_AP_LIMIT) or (FFireTime > 0) then
       begin
         if FHealth < PLAYER_HP_LIMIT then
           FHealth := PLAYER_HP_LIMIT;
@@ -4072,7 +4104,7 @@ begin
             (FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS]) or
             (FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS]) or
             (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) or
-            (FMaxAmmo[A_FUEL] < AmmoLimits[1, A_FUEL]) then
+            (FAmmo[A_FUEL] < FMaxAmmo[A_FUEL]) then
       begin
         FMaxAmmo[A_BULLETS] := AmmoLimits[1, A_BULLETS];
         FMaxAmmo[A_SHELLS] := AmmoLimits[1, A_SHELLS];
@@ -4088,6 +4120,8 @@ begin
           IncMax(FAmmo[A_ROCKETS], 1, FMaxAmmo[A_ROCKETS]);
         if FAmmo[A_CELLS] < FMaxAmmo[A_CELLS] then
           IncMax(FAmmo[A_CELLS], 40, FMaxAmmo[A_CELLS]);
+        if FAmmo[A_FUEL] < FMaxAmmo[A_FUEL] then
+          IncMax(FAmmo[A_FUEL], 50, FMaxAmmo[A_FUEL]);
 
         FRulez := FRulez + [R_ITEM_BACKPACK];
         Result := True;
@@ -4165,9 +4199,9 @@ begin
           remove := True;
           FFireTime := 0;
         end;
-        if FHealth < PLAYER_HP_SOFT then
+        if (FHealth < PLAYER_HP_SOFT) or (FFireTime > 0) then
         begin
-          FHealth := PLAYER_HP_SOFT;
+          if FHealth < PLAYER_HP_SOFT then FHealth := PLAYER_HP_SOFT;
           FBerserk := gTime+30000;
           Result := True;
           remove := True;
@@ -4185,9 +4219,9 @@ begin
       end;
 
     ITEM_BOTTLE:
-      if FHealth < PLAYER_HP_LIMIT then
+      if (FHealth < PLAYER_HP_LIMIT) or (FFireTime > 0) then
       begin
-        IncMax(FHealth, 4, PLAYER_HP_LIMIT);
+        if FHealth < PLAYER_HP_LIMIT then IncMax(FHealth, 4, PLAYER_HP_LIMIT);
         Result := True;
         remove := True;
         FFireTime := 0;
@@ -4264,6 +4298,7 @@ begin
   FMonsterKills := 0;
   FDeath := 0;
   FSecrets := 0;
+  FReady := False;
   if FNoRespawn then
   begin
     FSpectator := False;
@@ -4503,7 +4538,7 @@ begin
 // Âîñêðåøåíèå áåç îðóæèÿ:
   if not FAlive then
   begin
-    FHealth := PLAYER_HP_SOFT;
+    FHealth := Round(PLAYER_HP_SOFT * (FHandicap / 100));
     FArmor := 0;
     FAlive := True;
     FAir := AIR_DEF;
@@ -5243,11 +5278,13 @@ begin
         if FFirePainTime <= 0 then
         begin
           if g_Game_IsServer then
-            Damage(5, FFireAttacker, 0, 0, HIT_FLAME);
-          FFirePainTime := 18;
+            Damage(2, FFireAttacker, 0, 0, HIT_FLAME);
+          FFirePainTime := 12 - FFireTime div 12;
         end;
         FFirePainTime := FFirePainTime - 1;
         FFireTime := FFireTime - 1;
+        if ((FFireTime mod 33) = 0) and (FMegaRulez[MR_INVUL] < gTime) then
+          FModel.PlaySound(MODELSOUND_PAIN, 1, FObj.X, FObj.Y);
         if (FFireTime = 0) and g_Game_IsNet and g_Game_IsServer then
           MH_SEND_PlayerStats(FUID);
       end;
@@ -5279,7 +5316,7 @@ begin
             else if FHealth > -50 then Kill(K_HARDKILL, FLastSpawnerUID, FLastHit)
               else Kill(K_EXTRAHARDKILL, FLastSpawnerUID, FLastHit);
 
-      if FAlive then
+      if FAlive and ((FLastHit <> HIT_FLAME) or (FFireTime <= 0)) then
       begin
         if FDamageBuffer <= 20 then FModel.PlaySound(MODELSOUND_PAIN, 1, FObj.X, FObj.Y)
           else if FDamageBuffer <= 55 then FModel.PlaySound(MODELSOUND_PAIN, 2, FObj.X, FObj.Y)
@@ -5786,6 +5823,11 @@ end;
 
 procedure TPlayer.GetSecret();
 begin
+  if (self = gPlayer1) or (self = gPlayer2) then
+  begin
+    g_Console_Add(Format(_lc[I_PLAYER_SECRET], [FName]), True);
+    g_Sound_PlayEx('SOUND_GAME_SECRET');
+  end;
   Inc(FSecrets);
 end;
 
@@ -5896,6 +5938,8 @@ begin
   utils.writeInt(st, Byte(b));
   // Çäîðîâüå
   utils.writeInt(st, LongInt(FHealth));
+  // Êîýôôèöèåíò èíâàëèäíîñòè
+  utils.writeInt(st, LongInt(FHandicap));
   // Æèçíè
   utils.writeInt(st, Byte(FLives));
   // Áðîíÿ
@@ -5998,6 +6042,8 @@ begin
   if b = 1 then FDirection := TDirection.D_LEFT else FDirection := TDirection.D_RIGHT; // b = 2
   // Çäîðîâüå
   FHealth := utils.readLongInt(st);
+  // Êîýôôèöèåíò èíâàëèäíîñòè
+  FHandicap := utils.readLongInt(st);
   // Æèçíè
   FLives := utils.readByte(st);
   // Áðîíÿ