DEADSOFTWARE

Added new blood types for player's models
[d2df-sdl.git] / src / game / g_playermodel.pas
index c3bfdac266dcd9090cf9df3b418b988364357a22..e2148e8ec204f35ae225ab656751a550235bd2b0 100644 (file)
@@ -21,7 +21,8 @@ interface
 
 uses
   {$IFDEF USE_MEMPOOL}mempool,{$ENDIF}
-  MAPDEF, g_textures, g_basic, g_weapons, e_graphics, utils;
+  MAPDEF, g_textures, g_basic, g_weapons, e_graphics, utils, g_gfx,
+  ImagingTypes, Imaging, ImagingUtility;
 
 const
   A_STAND      = 0;
@@ -64,6 +65,10 @@ type
     HaveWeapon:  Boolean;
   end;
 
+  TModelBlood = record
+    R, G, B, Kind: Byte;
+  end;
+
   TModelSound = record
     ID:    DWORD;
     Level: Byte;
@@ -87,6 +92,7 @@ type
     FName:             String;
     FDirection:        TDirection;
     FColor:            TRGB;
+    FBlood:            TModelBlood;
     FCurrentAnimation: Byte;
     FAnim:             Array [TDirection.D_LEFT..TDirection.D_RIGHT] of Array [A_STAND..A_LAST] of TAnimation;
     FMaskAnim:         Array [TDirection.D_LEFT..TDirection.D_RIGHT] of Array [A_STAND..A_LAST] of TAnimation;
@@ -125,6 +131,7 @@ type
 
   public
     property    Color: TRGB read FColor write FColor;
+    property    Blood: TModelBlood read FBlood;
   end;
 
 procedure g_PlayerModel_LoadData();
@@ -132,6 +139,7 @@ procedure g_PlayerModel_FreeData();
 function  g_PlayerModel_Load(FileName: String): Boolean;
 function  g_PlayerModel_GetNames(): SSArray;
 function  g_PlayerModel_GetInfo(ModelName: String): TModelInfo;
+function  g_PlayerModel_GetBlood(ModelName: String): TModelBlood;
 function  g_PlayerModel_Get(ModelName: String): TPlayerModel;
 function  g_PlayerModel_GetAnim(ModelName: String; Anim: Byte; var _Anim, _Mask: TAnimation): Boolean;
 function  g_PlayerModel_GetGibs(ModelName: String; var Gibs: TGibsArray): Boolean;
@@ -140,11 +148,7 @@ function  g_PlayerModel_GetGibs(ModelName: String; var Gibs: TGibsArray): Boolea
 implementation
 
 uses
-{$IFDEF USE_NANOGL}
-  nanoGL,
-{$ELSE}
-  GL, GLExt,
-{$ENDIF}
+  {$INCLUDE ../nogl/noGLuses.inc}
   g_main, g_sound, g_console, SysUtils, g_player, CONFIG,
   e_sound, g_options, g_map, Math, e_log, wadreader;
 
@@ -159,6 +163,7 @@ type
     PainSounds:   TModelSoundArray;
     DieSounds:    TModelSoundArray;
     SlopSound:    Byte;
+    Blood:        TModelBlood;
   end;
 
 const
@@ -322,6 +327,65 @@ begin
   end;
 end;
 
+function g_PlayerModel_CalcGibSize (pData: Pointer; dataSize, x, y, w, h: Integer): TRectWH;
+  var i, j: Integer; done: Boolean; img: TImageData;
+
+  function IsVoid (i, j: Integer): Boolean;
+  begin
+    result := Byte((PByte(img.bits) + (y+j)*img.width*4 + (x+i)*4 + 3)^) = 0
+  end;
+
+begin
+  InitImage(img);
+  assert(LoadImageFromMemory(pData, dataSize, img));
+
+  (* trace x from right to left *)
+  done := false; i := 0;
+  while not done and (i < w) do
+  begin
+    j := 0;
+    while (j < h) and IsVoid(i, j) do inc(j);
+    done := (j < h) and (IsVoid(i, j) = false);
+    result.x := i;
+    inc(i);
+  end;
+
+  (* trace y from up to down *)
+  done := false; j := 0;
+  while not done and (j < h) do
+  begin
+    i := 0;
+    while (i < w) and IsVoid(i, j) do inc(i);
+    done := (i < w) and (IsVoid(i, j) = false);
+    result.y := j;
+    inc(j);
+  end;
+  
+  (* trace x from right to left *)
+  done := false; i := w - 1;
+  while not done and (i >= 0) do
+  begin
+    j := 0;
+    while (j < h) and IsVoid(i, j) do inc(j);
+    done := (j < h) and (IsVoid(i, j) = false);
+    result.width := i - result.x + 1;
+    dec(i);
+  end;
+
+  (* trace y from down to up *)
+  done := false; j := h - 1;
+  while not done and (j >= 0) do
+  begin
+    i := 0;
+    while (i < w) and IsVoid(i, j) do inc(i);
+    done := (i < w) and (IsVoid(i, j) = false);
+    result.height := j - result.y + 1;
+    dec(j);
+  end;
+
+  FreeImage(img);
+end;
+
 function g_PlayerModel_Load(FileName: string): Boolean;
 var
   ID: DWORD;
@@ -376,6 +440,20 @@ begin
     Description := config.ReadStr('Model', 'description', '');
   end;
 
+  with PlayerModelsArray[ID] do
+  begin
+    Blood.R := MAX(0, MIN(255, config.ReadInt('Blood', 'R', 150)));
+    Blood.G := MAX(0, MIN(255, config.ReadInt('Blood', 'G', 0)));
+    Blood.B := MAX(0, MIN(255, config.ReadInt('Blood', 'B', 0)));
+    case config.ReadStr('Blood', 'Kind', 'NORMAL') of
+      'NORMAL': Blood.Kind := BLOOD_NORMAL;
+      'SPARKS': Blood.Kind := BLOOD_CSPARKS;
+      'COMBINE': Blood.Kind := BLOOD_COMBINE;
+    else
+      Blood.Kind := BLOOD_NORMAL
+    end
+  end;
+
   for b := A_STAND to A_LAST do
   begin
     aname := s+'_RIGHTANIM'+IntToStr(b);
@@ -470,7 +548,8 @@ begin
         if e_CreateTextureMemEx(pData, lenpd, Gibs[a].ID, a*32, 0, 32, 32) and
           e_CreateTextureMemEx(pData2, lenpd2, Gibs[a].MaskID, a*32, 0, 32, 32) then
         begin
-          Gibs[a].Rect := e_GetTextureSize2(Gibs[a].ID);
+          //Gibs[a].Rect := e_GetTextureSize2(Gibs[a].ID);
+          Gibs[a].Rect := g_PlayerModel_CalcGibSize(pData, lenpd, a*32, 0, 32, 32);
           with Gibs[a].Rect do
             if Height > 3 then Height := Height-1-Random(2);
           Gibs[a].OnlyOne := config.ReadInt('Gibs', 'once', -1) = a+1;
@@ -586,6 +665,7 @@ begin
       with PlayerModelsArray[a] do
       begin
         Result.FName := Info.Name;
+        Result.FBlood := Blood;
 
         for b := A_STAND to A_LAST do
         begin
@@ -728,6 +808,24 @@ begin
     end;
 end;
 
+function g_PlayerModel_GetBlood(ModelName: string): TModelBlood;
+var
+  a: Integer;
+begin
+  Result.R := 150;
+  Result.G := 0;
+  Result.B := 0;
+  Result.Kind := BLOOD_NORMAL;
+  if PlayerModelsArray = nil then Exit;
+
+  for a := 0 to High(PlayerModelsArray) do
+    if PlayerModelsArray[a].Info.Name = ModelName then
+    begin
+      Result := PlayerModelsArray[a].Blood;
+      Break;
+    end;
+end;
+
 procedure g_PlayerModel_FreeData();
 var
   i: DWORD;