DEADSOFTWARE

render: use TPlayerModel for corpse drawing
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Sun, 16 Jan 2022 20:59:01 +0000 (23:59 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Sun, 16 Jan 2022 20:59:01 +0000 (23:59 +0300)
src/game/g_player.pas
src/game/g_playermodel.pas
src/game/g_textures.pas
src/game/opengl/r_player.pas

index 5478180bf23ed93ddf84d425087edbd16e20f605..e7f3fee964a6f24df74675de530d0b8d3255312b 100644 (file)
@@ -536,15 +536,12 @@ type
 
   TCorpse = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
   private
-    FModelName:     String;
     FMess:          Boolean;
     FState:         Byte;
     FDamage:        Byte;
-    FColor:         TRGB;
     FObj:           TObj;
     FPlayerUID:     Word;
-    FAnimation:     TAnimation;
-    FAnimationMask: TAnimation;
+    FModel:   TPlayerModel;
 
   public
     constructor Create(X, Y: Integer; ModelName: String; aMess: Boolean);
@@ -564,11 +561,7 @@ type
     property    Obj: TObj read FObj; // copies object
     property    State: Byte read FState;
     property    Mess: Boolean read FMess;
-
-    (* internal state *)
-    property    Color: TRGB read FColor;
-    property    Animation: TAnimation read FAnimation;
-    property    AnimationMask: TAnimation read FAnimationMask;
+    property    Model: TPlayerModel read FModel;
   end;
 
   TTeamStat = Array [TEAM_RED..TEAM_BLUE] of
@@ -618,7 +611,7 @@ function  g_Player_GetCount(): Byte;
 function  g_Player_GetStats(): TPlayerStatArray;
 function  g_Player_ValidName(Name: String): Boolean;
 function  g_Player_CreateCorpse(Player: TPlayer): Integer;
-procedure g_Player_CreateGibs(fX, fY: Integer; ModelName: String; fColor: TRGB);
+procedure g_Player_CreateGibs (fX, fY, mid: Integer; fColor: TRGB);
 procedure g_Player_CreateShell(fX, fY, dX, dY: Integer; T: Byte);
 procedure g_Player_UpdatePhysicalObjects();
 procedure g_Player_RemoveAllCorpses();
@@ -1570,7 +1563,7 @@ begin
           find_id := Random(Length(gCorpses));
 
         gCorpses[find_id] := TCorpse.Create(FObj.X, FObj.Y, FModel.GetName(), FHealth < -20);
-        gCorpses[find_id].FColor := FModel.Color;
+        gCorpses[find_id].FModel.Color := FModel.Color;
         gCorpses[find_id].FObj.Vel := FObj.Vel;
         gCorpses[find_id].FObj.Accel := FObj.Accel;
         gCorpses[find_id].FPlayerUID := FUID;
@@ -1578,9 +1571,7 @@ begin
         Result := find_id;
       end
     else
-      g_Player_CreateGibs(FObj.X + PLAYER_RECT_CX,
-                          FObj.Y + PLAYER_RECT_CY,
-                          FModel.GetName(), FModel.Color);
+      g_Player_CreateGibs(FObj.X + PLAYER_RECT_CX, FObj.Y + PLAYER_RECT_CY, FModel.id, FModel.Color);
   end;
 end;
 
@@ -1631,17 +1622,16 @@ begin
   end;
 end;
 
-procedure g_Player_CreateGibs(fX, fY: Integer; ModelName: string; fColor: TRGB);
+procedure g_Player_CreateGibs (fX, fY, mid: Integer; fColor: TRGB);
 var
-  a, mid: Integer;
+  a: Integer;
   GibsArray: TGibsArray;
   Blood: TModelBlood;
 begin
-  if (gGibs = nil) or (Length(gGibs) = 0) then
-    Exit;
-  mid := g_PlayerModel_GetIndex(ModelName);
   if mid = -1 then
     Exit;
+  if (gGibs = nil) or (Length(gGibs) = 0) then
+    Exit;
   if not g_PlayerModel_GetGibs(mid, GibsArray) then
     Exit;
   Blood := PlayerModelsArray[mid].Blood;
@@ -1876,7 +1866,7 @@ begin
     if gCorpses[i] <> nil then
     begin
       // Название модели
-      utils.writeStr(st, gCorpses[i].FModelName);
+      utils.writeStr(st, gCorpses[i].FModel.GetName());
       // Тип смерти
       utils.writeBool(st, gCorpses[i].Mess);
       // Сохраняем данные трупа:
@@ -5731,25 +5721,24 @@ begin
   FObj.X := X;
   FObj.Y := Y;
   FObj.Rect := PLAYER_CORPSERECT;
-  FModelName := ModelName;
   FMess := aMess;
+  FModel := g_PlayerModel_Get(ModelName);
 
   if FMess then
-    begin
-      FState := CORPSE_STATE_MESS;
-      g_PlayerModel_GetAnim(ModelName, A_DIE2, FAnimation, FAnimationMask);
-    end
+  begin
+    FState := CORPSE_STATE_MESS;
+    FModel.ChangeAnimation(A_DIE2);
+  end
   else
-    begin
-      FState := CORPSE_STATE_NORMAL;
-      g_PlayerModel_GetAnim(ModelName, A_DIE1, FAnimation, FAnimationMask);
-    end;
+  begin
+    FState := CORPSE_STATE_NORMAL;
+    FModel.ChangeAnimation(A_DIE1);
+  end;
 end;
 
 destructor TCorpse.Destroy();
 begin
-  FAnimation.Free();
-
+  FModel.Free;
   inherited;
 end;
 
@@ -5778,9 +5767,7 @@ end;
 
 
 procedure TCorpse.Damage(Value: Word; SpawnerUID: Word; vx, vy: Integer);
-var
-  pm: TPlayerModel;
-  Blood: TModelBlood;
+  var Blood: TModelBlood;
 begin
   if FState = CORPSE_STATE_REMOVEME then
     Exit;
@@ -5788,32 +5775,33 @@ begin
   FDamage := FDamage + Value;
 
   if FDamage > 150 then
+  begin
+    if FModel <> nil then
     begin
-      if FAnimation <> nil then
-      begin
-        FAnimation.Free();
-        FAnimation := nil;
-
-        FState := CORPSE_STATE_REMOVEME;
-
-        g_Player_CreateGibs(FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2),
-                            FObj.Y+FObj.Rect.Y+(FObj.Rect.Height div 2),
-                            FModelName, FColor);
-        // Звук мяса от трупа:
-        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, SpawnerUID);
-      end;
+      FState := CORPSE_STATE_REMOVEME;
+
+      g_Player_CreateGibs(
+        FObj.X + FObj.Rect.X + (FObj.Rect.Width div 2),
+        FObj.Y + FObj.Rect.Y + (FObj.Rect.Height div 2),
+        FModel.id,
+        FModel.Color
+      );
+
+      // Звук мяса от трупа:
+      FModel.PlaySound(MODELSOUND_DIE, 5, FObj.X, FObj.Y);
+
+      // Зловещий смех:
+      if (gBodyKillEvent <> -1) and gDelayedEvents[gBodyKillEvent].Pending then
+        gDelayedEvents[gBodyKillEvent].Pending := False;
+      gBodyKillEvent := g_Game_DelayEvent(DE_BODYKILL, 1050, SpawnerUID);
+
+      FModel.Free;
+      FModel := nil;
     end
+  end
   else
     begin
-      Blood := g_PlayerModel_GetBlood(FModelName);
+      Blood := FModel.GetBlood();
       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),
@@ -5852,16 +5840,13 @@ begin
     Exit;
   end;
 
-  if FAnimation <> nil then
-    FAnimation.Update();
-  if FAnimationMask <> nil then
-    FAnimationMask.Update();
+  if FModel <> nil then
+    FModel.Update;
 end;
 
 
 procedure TCorpse.SaveState (st: TStream);
-var
-  anim: Boolean;
+  var anim: Boolean;
 begin
   assert(st <> nil);
 
@@ -5873,28 +5858,25 @@ begin
   // Накопленный урон
   utils.writeInt(st, Byte(FDamage));
   // Цвет
-  utils.writeInt(st, Byte(FColor.R));
-  utils.writeInt(st, Byte(FColor.G));
-  utils.writeInt(st, Byte(FColor.B));
+  utils.writeInt(st, Byte(FModel.Color.R));
+  utils.writeInt(st, Byte(FModel.Color.G));
+  utils.writeInt(st, Byte(FModel.Color.B));
   // Объект трупа
   Obj_SaveState(st, @FObj);
   utils.writeInt(st, Word(FPlayerUID));
-  // Есть ли анимация
-  anim := (FAnimation <> nil);
+  // animation
+  anim := (FModel <> nil);
   utils.writeBool(st, anim);
-  // Если есть - сохраняем
-  if anim then FAnimation.SaveState(st);
-  // Есть ли маска анимации
-  anim := (FAnimationMask <> nil);
+  if anim then FModel.AnimState.SaveState(st);
+  // animation for mask (same as animation, compat with older saves)
+  anim := (FModel <> nil);
   utils.writeBool(st, anim);
-  // Если есть - сохраняем
-  if anim then FAnimationMask.SaveState(st);
+  if anim then FModel.AnimState.SaveState(st);
 end;
 
 
 procedure TCorpse.LoadState (st: TStream);
-var
-  anim: Boolean;
+  var anim: Boolean; r, g, b: Byte; stub: TAnimationState;
 begin
   assert(st <> nil);
 
@@ -5906,28 +5888,30 @@ begin
   // Накопленный урон
   FDamage := utils.readByte(st);
   // Цвет
-  FColor.R := utils.readByte(st);
-  FColor.G := utils.readByte(st);
-  FColor.B := utils.readByte(st);
+  r := utils.readByte(st);
+  g := utils.readByte(st);
+  b := utils.readByte(st);
+  FModel.SetColor(r, g, b);
   // Объект трупа
   Obj_LoadState(@FObj, st);
   FPlayerUID := utils.readWord(st);
-  // Есть ли анимация
+  // animation
+  stub := TAnimationState.Create(False, 0, 0);
   anim := utils.readBool(st);
-  // Если есть - загружаем
   if anim then
   begin
-    Assert(FAnimation <> nil, 'TCorpse.LoadState: no FAnimation');
-    FAnimation.LoadState(st);
-  end;
-  // Есть ли маска анимации
-  anim := utils.readBool(st);
-  // Если есть - загружаем
-  if anim then
+    stub.LoadState(st);
+    FModel.AnimState.CurrentFrame := Min(stub.CurrentFrame, FModel.AnimState.Length);
+  end
+  else
   begin
-    Assert(FAnimationMask <> nil, 'TCorpse.LoadState: no FAnimationMask');
-    FAnimationMask.LoadState(st);
+    FModel.Free;
+    FModel := nil
   end;
+  // animation for mask (same as animation, compat with older saves)
+  anim := utils.readBool(st);
+  if anim then stub.LoadState(st);
+  stub.Free;
 end;
 
 { T B o t : }
index 820c7c5c52ad72bcfa0e5a49dfef8afb19e2381b..e2db8d47acabb897be51d738f0ef854794355c55 100644 (file)
@@ -134,7 +134,6 @@ function  g_PlayerModel_Load(FileName: String): Boolean;
 function  g_PlayerModel_GetNames(): SSArray;
 function  g_PlayerModel_GetBlood(ModelName: String): TModelBlood;
 function  g_PlayerModel_Get(ModelName: String): TPlayerModel;
-function  g_PlayerModel_GetAnim(ModelName: String; AnimTyp: Byte; var _Anim, _Mask: TAnimation): Boolean;
 function  g_PlayerModel_GetGibs (ModelID: Integer; var Gibs: TGibsArray): Boolean;
 function  g_PlayerModel_GetIndex (ModelName: String): Integer;
 
@@ -631,40 +630,6 @@ begin
   end;
 end;
 
-function g_PlayerModel_GetAnim(ModelName: string; AnimTyp: Byte; var _Anim, _Mask: TAnimation): Boolean;
-var
-  a: Integer;
-  c: Boolean;
-  ID: DWORD;
-begin
-  Result := False;
-
-  if PlayerModelsArray = nil then Exit;
-  for a := 0 to High(PlayerModelsArray) do
-    if PlayerModelsArray[a].Name = ModelName then
-      with PlayerModelsArray[a] do
-      begin
-        if AnimTyp in [A_STAND, A_WALK] then c := True else c := False;
-
-        if not g_Frames_Get(ID, Name + '_RIGHTANIM' + IntToStr(AnimTyp)) then
-          if not g_Frames_Get(ID, Name + '_LEFTANIM' + IntToStr(AnimTyp)) then Exit;
-
-        _Anim := TAnimation.Create(ID, c, ModelSpeed[AnimTyp]);
-        _Anim.Speed := ModelSpeed[AnimTyp];
-
-        if not g_Frames_Get(ID, Name + '_RIGHTANIM' + IntToStr(AnimTyp) + '_MASK') then
-          if not g_Frames_Get(ID, Name + '_LEFTANIM' + IntToStr(AnimTyp) + '_MASK') then
-            Exit;
-
-        _Mask := TAnimation.Create(ID, c, ModelSpeed[AnimTyp]);
-        _Mask.Speed := ModelSpeed[AnimTyp];
-
-        Break;
-      end;
-
-  Result := True;
-end;
-
   function g_PlayerModel_GetGibs (ModelID: Integer; var Gibs: TGibsArray): Boolean;
     var i, b: Integer; c: Boolean;
   begin
index 02fe5aad01a60530c126232a0679d05d4d87b173..727e94ac7632e0b1e5b6e88e6f6a13f8876bfeb1 100644 (file)
@@ -73,6 +73,7 @@ type
     property counter: Byte read mCounter;
     property blending: Boolean read mBlending write mBlending;
     property alpha: Byte read mAlpha write mAlpha;
+    property length: Integer read mLength;
   end;
 
   TAnimation = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
index 8b25eb491187301e6dd06a2972bb58a39b0cb9bc..78931208c9e33acff7d102f83d61ceeb523d18ab 100644 (file)
@@ -38,8 +38,6 @@ interface
   procedure r_Player_DrawPain (p: TPlayer);
   procedure r_Player_DrawPickup (p: TPlayer);
 
-  procedure r_Player_DrawCorpse (p: TCorpse);
-
 implementation
 
   uses
@@ -123,6 +121,16 @@ begin
     end;
 end;
 
+  procedure r_Player_DrawCorpse (p: TCorpse);
+    var fX, fY: Integer;
+  begin
+    if (p.State <> CORPSE_STATE_REMOVEME) and (p.Model <> nil) then
+    begin
+      p.Obj.lerp(gLerpFactor, fX, fY);
+      r_PlayerModel_Draw(p.Model, fX, fY)
+    end
+  end;
+
   procedure r_Player_DrawCorpses;
     var i: Integer;
   begin
@@ -785,26 +793,4 @@ begin
   e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1, 150, 200, 150, 255-h*50);
 end;
 
-procedure r_Player_DrawCorpse (p: TCorpse);
-var
-  fX, fY: Integer;
-begin
-  if p.State = CORPSE_STATE_REMOVEME then
-    Exit;
-
-  p.Obj.lerp(gLerpFactor, fX, fY);
-
-  if p.Animation <> nil then
-    r_Animation_Draw(p.Animation, fX, fY, TMirrorType.None);
-
-  if p.AnimationMask <> nil then
-  begin
-    e_Colors := p.Color;
-    r_Animation_Draw(p.AnimationMask, fX, fY, TMirrorType.None);
-    e_Colors.R := 255;
-    e_Colors.G := 255;
-    e_Colors.B := 255;
-  end;
-end;
-
 end.