X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_player.pas;h=68bee9a40a786e8f1f3470eb74f072bcd6d38427;hb=16342bee09fa001d05697571124e48a93cd35f2c;hp=7c73eb7e5754a68adf1831829d273a22c7b04fba;hpb=f517a19e84dae6941cff317aaf6fbcc3a5c5bb6f;p=d2df-sdl.git diff --git a/src/game/g_player.pas b/src/game/g_player.pas index 7c73eb7..68bee9a 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -23,7 +23,7 @@ uses {$IFDEF USE_MEMPOOL}mempool,{$ENDIF} g_base, g_playermodel, g_basic, g_textures, g_weapons, g_phys, g_sound, g_saveload, MAPDEF, - g_panel, r_playermodel; + g_panel; const KEY_LEFT = 1; @@ -191,7 +191,7 @@ type FSavedStateNum: Integer; FModel: TPlayerModel; - FPunchAnim: TAnimation; + FPunchAnim: TAnimationState; FActionPrior: Byte; FActionAnim: Byte; FActionForce: Boolean; @@ -403,7 +403,7 @@ type property Berserk: Integer read FBerserk; property Pain: Integer read FPain; property Pickup: Integer read FPickup; - property PunchAnim: TAnimation read FPunchAnim write FPunchAnim; + property PunchAnim: TAnimationState read FPunchAnim write FPunchAnim; property SpawnInvul: Integer read FSpawnInvul; property Ghost: Boolean read FGhost; @@ -501,31 +501,12 @@ type procedure LoadState (st: TStream); override; end; - PGib = ^TGib; - TGib = record - alive: Boolean; - RAngle: Integer; - Color: TRGB; - Obj: TObj; - - ModelID: Integer; - GibID: Integer; - - procedure getMapBox (out x, y, w, h: Integer); inline; - procedure moveBy (dx, dy: Integer); inline; - - procedure positionChanged (); inline; //WARNING! call this after entity position was changed, or coldet will not work right! - end; - - PShell = ^TShell; TShell = record - SpriteID: DWORD; - alive: Boolean; + alive: Boolean; SType: Byte; RAngle: Integer; Timeout: Cardinal; - CX, CY: Integer; Obj: TObj; procedure getMapBox (out x, y, w, h: Integer); inline; @@ -536,15 +517,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 +542,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 @@ -579,7 +553,6 @@ type var gPlayers: Array of TPlayer; gCorpses: Array of TCorpse; - gGibs: Array of TGib; gShells: Array of TShell; gTeamStat: TTeamStat; gFly: Boolean = False; @@ -596,8 +569,6 @@ var function Lerp(X, Y, Factor: Integer): Integer; -procedure g_Gibs_SetMax(Count: Word); -function g_Gibs_GetMax(): Word; procedure g_Corpses_SetMax(Count: Word); function g_Corpses_GetMax(): Word; procedure g_Shells_SetMax(Count: Word); @@ -618,7 +589,6 @@ 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_CreateShell(fX, fY, dX, dY: Integer; T: Byte); procedure g_Player_UpdatePhysicalObjects(); procedure g_Player_RemoveAllCorpses(); @@ -633,11 +603,23 @@ procedure g_Bot_RemoveAll(); implementation uses -{$IFDEF ENABLE_HOLMES} - g_holmes, -{$ENDIF} - e_log, g_map, g_items, g_console, g_gfx, Math, r_textures, r_animations, r_gfx, - g_options, g_triggers, g_menu, g_game, g_grid, e_res, + {$IFDEF ENABLE_HOLMES} + g_holmes, + {$ENDIF} + {$IFDEF ENABLE_MENU} + g_menu, + {$ENDIF} + {$IFNDEF HEADLESS} + r_render, + {$ENDIF} + {$IFDEF ENABLE_GFX} + g_gfx, + {$ENDIF} + {$IFDEF ENABLE_GIBS} + g_gibs, + {$ENDIF} + e_log, g_map, g_items, g_console, Math, + g_options, g_triggers, g_game, g_grid, e_res, wadreader, g_monsters, CONFIG, g_language, g_net, g_netmsg, utils, xstreams; @@ -709,10 +691,8 @@ const BOTLIST_FILENAME = 'botlist.txt'; var - MaxGibs: Word = 150; MaxCorpses: Word = 20; MaxShells: Word = 300; - CurrentGib: Integer = 0; CurrentShell: Integer = 0; BotNames: Array of String; BotList: Array of TBotProfile; @@ -739,20 +719,6 @@ begin Result := g_Player_Get(UID1).FTeam = g_Player_Get(UID2).FTeam; end; -procedure g_Gibs_SetMax(Count: Word); -begin - MaxGibs := Count; - SetLength(gGibs, Count); - - if CurrentGib >= Count then - CurrentGib := 0; -end; - -function g_Gibs_GetMax(): Word; -begin - Result := MaxGibs; -end; - procedure g_Shells_SetMax(Count: Word); begin MaxShells := Count; @@ -1553,7 +1519,13 @@ begin with Player do begin - if (FHealth >= -50) or (gGibsCount = 0) then +{$IFDEF ENABLE_GIBS} + if (FHealth < -50) and (gGibsCount > 0) then + begin + g_Gibs_Create(FObj.X + PLAYER_RECT_CX, FObj.Y + PLAYER_RECT_CY, FModel.id, FModel.Color); + end + else +{$ENDIF} begin if (gCorpses = nil) or (Length(gCorpses) = 0) then Exit; @@ -1570,48 +1542,33 @@ 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; Result := find_id; end - else - g_Player_CreateGibs(FObj.X + PLAYER_RECT_CX, - FObj.Y + PLAYER_RECT_CY, - FModel.GetName(), FModel.Color); end; end; procedure g_Player_CreateShell(fX, fY, dX, dY: Integer; T: Byte); -var - SID: DWORD; begin if (gShells = nil) or (Length(gShells) = 0) then Exit; with gShells[CurrentShell] do begin - SpriteID := 0; g_Obj_Init(@Obj); Obj.Rect.X := 0; Obj.Rect.Y := 0; if T = SHELL_BULLET then begin - if g_Texture_Get('TEXTURE_SHELL_BULLET', SID) then - SpriteID := SID; - CX := 2; - CY := 1; Obj.Rect.Width := 4; Obj.Rect.Height := 2; end else begin - if g_Texture_Get('TEXTURE_SHELL_SHELL', SID) then - SpriteID := SID; - CX := 4; - CY := 2; Obj.Rect.Width := 7; Obj.Rect.Height := 3; end; @@ -1631,47 +1588,6 @@ begin end; end; -procedure g_Player_CreateGibs(fX, fY: Integer; ModelName: string; fColor: TRGB); -var - a, mid: 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 not g_PlayerModel_GetGibs(mid, GibsArray) then - Exit; - Blood := PlayerModelsArray[mid].Blood; - - for a := 0 to High(GibsArray) do - with gGibs[CurrentGib] do - begin - ModelID := mid; - GibID := GibsArray[a]; - Color := fColor; - alive := True; - g_Obj_Init(@Obj); - Obj.Rect := r_PlayerModel_GetGibRect(ModelID, GibID); - Obj.X := fX - Obj.Rect.X - (Obj.Rect.Width div 2); - Obj.Y := fY - Obj.Rect.Y - (Obj.Rect.Height div 2); - g_Obj_PushA(@Obj, 25 + Random(10), Random(361)); - positionChanged(); // this updates spatial accelerators - RAngle := Random(360); - - if gBloodCount > 0 then - g_GFX_Blood(fX, fY, 16*gBloodCount+Random(5*gBloodCount), -16+Random(33), -16+Random(33), - Random(48), Random(48), Blood.R, Blood.G, Blood.B, Blood.Kind); - - if CurrentGib >= High(gGibs) then - CurrentGib := 0 - else - Inc(CurrentGib); - end; -end; - procedure g_Player_UpdatePhysicalObjects(); var i: Integer; @@ -1690,47 +1606,6 @@ var end; begin -// Куски мяса: - if gGibs <> nil then - for i := 0 to High(gGibs) do - if gGibs[i].alive then - with gGibs[i] do - begin - Obj.oldX := Obj.X; - Obj.oldY := Obj.Y; - - vel := Obj.Vel; - mr := g_Obj_Move(@Obj, True, False, True); - positionChanged(); // this updates spatial accelerators - - if WordBool(mr and MOVE_FALLOUT) then - begin - alive := False; - Continue; - end; - - // Отлетает от удара о стену/потолок/пол: - if WordBool(mr and MOVE_HITWALL) then - Obj.Vel.X := -(vel.X div 2); - if WordBool(mr and (MOVE_HITCEIL or MOVE_HITLAND)) then - Obj.Vel.Y := -(vel.Y div 2); - - if (Obj.Vel.X >= 0) then - begin // Clockwise - RAngle := RAngle + Abs(Obj.Vel.X)*6 + Abs(Obj.Vel.Y); - if RAngle >= 360 then - RAngle := RAngle mod 360; - end else begin // Counter-clockwise - RAngle := RAngle - Abs(Obj.Vel.X)*6 - Abs(Obj.Vel.Y); - if RAngle < 0 then - RAngle := (360 - (Abs(RAngle) mod 360)) mod 360; - end; - - // Сопротивление воздуха для куска трупа: - if gTime mod (GAME_TICK*3) = 0 then - Obj.Vel.X := z_dec(Obj.Vel.X, 1); - end; - // Трупы: if gCorpses <> nil then for i := 0 to High(gCorpses) do @@ -1795,26 +1670,6 @@ begin end; end; - -procedure TGib.getMapBox (out x, y, w, h: Integer); inline; -begin - x := Obj.X+Obj.Rect.X; - y := Obj.Y+Obj.Rect.Y; - w := Obj.Rect.Width; - h := Obj.Rect.Height; -end; - -procedure TGib.moveBy (dx, dy: Integer); inline; -begin - if (dx <> 0) or (dy <> 0) then - begin - Obj.X += dx; - Obj.Y += dy; - positionChanged(); - end; -end; - - procedure TShell.getMapBox (out x, y, w, h: Integer); inline; begin x := Obj.X; @@ -1833,20 +1688,22 @@ begin end; end; - -procedure TGib.positionChanged (); inline; begin end; procedure TShell.positionChanged (); inline; begin end; procedure g_Player_RemoveAllCorpses(); -var - i: Integer; -begin - gGibs := nil; + var i: Integer; + {$IFDEF ENABLE_GIBS} + var maxgibs: Integer; + {$ENDIF} +begin + {$IFDEF ENABLE_GIBS} + maxgibs := g_Gibs_GetMax(); + g_Gibs_SetMax(0); + g_Gibs_SetMax(maxgibs); + {$ENDIF} gShells := nil; - SetLength(gGibs, MaxGibs); - SetLength(gShells, MaxGibs); - CurrentGib := 0; + SetLength(gShells, MaxShells); CurrentShell := 0; if gCorpses <> nil then @@ -1876,7 +1733,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); // Сохраняем данные трупа: @@ -2123,6 +1980,8 @@ begin FNetTime := 0; FWaitForFirstSpawn := false; + FPunchAnim := TAnimationState.Create(False, 1, 4); + FPunchAnim.Disable; resetWeaponQueue(); end; @@ -2206,9 +2065,13 @@ begin HIT_BFG, HIT_ROCKET, HIT_SOME: MakeBloodVector(c, vx, vy); end; - if t = HIT_WATER then - g_GFX_Bubbles(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2), - FObj.Y+PLAYER_RECT.Y-4, value div 2, 8, 4); + {$IFDEF ENABLE_GFX} + if t = HIT_WATER then + begin + g_GFX_Bubbles(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2), + FObj.Y+PLAYER_RECT.Y-4, value div 2, 8, 4); + end; + {$ENDIF} end; // Буфер урона: @@ -2269,31 +2132,15 @@ begin FJetSoundOn.Free(); FJetSoundOff.Free(); FModel.Free(); - if FPunchAnim <> nil then - FPunchAnim.Free(); + FPunchAnim.Free(); inherited; end; procedure TPlayer.DoPunch(); -var - id: DWORD; - st: String; begin - if FPunchAnim <> nil then begin - FPunchAnim.reset(); - FPunchAnim.Free; - FPunchAnim := nil; - end; - st := 'FRAMES_PUNCH'; - if R_BERSERK in FRulez then - st := st + '_BERSERK'; - if FKeys[KEY_UP].Pressed then - st := st + '_UP' - else if FKeys[KEY_DOWN].Pressed then - st := st + '_DN'; - g_Frames_Get(id, st); - FPunchAnim := TAnimation.Create(id, False, 1); + FPunchAnim.Reset; + FPunchAnim.Enable; end; procedure TPlayer.Fire(); @@ -3019,27 +2866,35 @@ begin end; procedure TPlayer.MakeBloodSimple(Count: Word); - var Blood: TModelBlood; -begin - Blood := SELF.FModel.GetBlood(); - 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), - Blood.R, Blood.G, Blood.B, 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, - Blood.R, Blood.G, Blood.B, Blood.Kind); + {$IFDEF ENABLE_GFX} + var Blood: TModelBlood; + {$ENDIF} +begin + {$IFDEF ENABLE_GFX} + Blood := SELF.FModel.GetBlood(); + 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), + Blood.R, Blood.G, Blood.B, 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, + Blood.R, Blood.G, Blood.B, Blood.Kind); + {$ENDIF} end; procedure TPlayer.MakeBloodVector(Count: Word; VelX, VelY: Integer); - var Blood: TModelBlood; + {$IFDEF ENABLE_GFX} + var Blood: TModelBlood; + {$ENDIF} begin - Blood := SELF.FModel.GetBlood(); - 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, - Blood.R, Blood.G, Blood.B, Blood.Kind); + {$IFDEF ENABLE_GFX} + Blood := SELF.FModel.GetBlood(); + 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, + Blood.R, Blood.G, Blood.B, Blood.Kind); + {$ENDIF} end; procedure TPlayer.QueueWeaponSwitch(Weapon: Byte); @@ -3944,13 +3799,17 @@ begin FFirePainTime := 0; FFireAttacker := 0; -// Анимация возрождения: - if (not gLoadGameMode) and (not Silent) then - r_GFX_OnceAnim( - R_GFX_TELEPORT_FAST, - FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-32, - FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2)-32 - ); + {$IFDEF ENABLE_GFX} + // Анимация возрождения: + if (not gLoadGameMode) and (not Silent) then + begin + g_GFX_QueueEffect( + R_GFX_TELEPORT_FAST, + FObj.X + PLAYER_RECT.X + (PLAYER_RECT.Width div 2) - 32, + FObj.Y + PLAYER_RECT.Y + (PLAYER_RECT.Height div 2) - 32 + ); + end; + {$ENDIF} FSpectator := False; FGhost := False; @@ -4030,8 +3889,9 @@ begin end; procedure TPlayer.Run(Direction: TDirection); -var - a, b: Integer; + {$IFDEF ENABLE_GIBS} + var a, b: Integer; + {$ENDIF} begin if MAX_RUNVEL > 8 then FlySmoke(); @@ -4046,30 +3906,32 @@ begin if FObj.Vel.X < MAX_RUNVEL then FObj.Vel.X := FObj.Vel.X + (MAX_RUNVEL shr 3); -// Возможно, пинаем куски: - if (FObj.Vel.X <> 0) and (gGibs <> nil) then - begin - b := Abs(FObj.Vel.X); - if b > 1 then b := b * (Random(8 div b) + 1); - for a := 0 to High(gGibs) do + {$IFDEF ENABLE_GIBS} + // Возможно, пинаем куски: + if (FObj.Vel.X <> 0) and (gGibs <> nil) then begin - if gGibs[a].alive and - g_Obj_Collide(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y+FObj.Rect.Height-4, - FObj.Rect.Width, 8, @gGibs[a].Obj) and (Random(3) = 0) then + b := Abs(FObj.Vel.X); + if b > 1 then b := b * (Random(8 div b) + 1); + for a := 0 to High(gGibs) do begin - // Пинаем куски - if FObj.Vel.X < 0 then + if gGibs[a].alive and + g_Obj_Collide(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y+FObj.Rect.Height-4, + FObj.Rect.Width, 8, @gGibs[a].Obj) and (Random(3) = 0) then begin - g_Obj_PushA(@gGibs[a].Obj, b, Random(61)+120) // налево - end - else - begin - g_Obj_PushA(@gGibs[a].Obj, b, Random(61)); // направо + // Пинаем куски + if FObj.Vel.X < 0 then + begin + g_Obj_PushA(@gGibs[a].Obj, b, Random(61)+120) // налево + end + else + begin + g_Obj_PushA(@gGibs[a].Obj, b, Random(61)); // направо + end; + gGibs[a].positionChanged(); // this updates spatial accelerators end; - gGibs[a].positionChanged(); // this updates spatial accelerators end; end; - end; + {$ENDIF} SetAction(A_WALK); end; @@ -4146,11 +4008,13 @@ begin if not silent then begin g_Sound_PlayExAt('SOUND_GAME_TELEPORT', FObj.X, FObj.Y); - r_GFX_OnceAnim( - R_GFX_TELEPORT_FAST, - FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-32, - FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2)-32 - ); + {$IFDEF ENABLE_GFX} + g_GFX_QueueEffect( + R_GFX_TELEPORT_FAST, + FObj.X + PLAYER_RECT.X + (PLAYER_RECT.Width div 2) - 32, + FObj.Y + PLAYER_RECT.Y + (PLAYER_RECT.Height div 2) - 32 + ); + {$ENDIF} if g_Game_IsServer and g_Game_IsNet then MH_SEND_Effect(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-32, FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2)-32, 1, @@ -4198,11 +4062,13 @@ begin if not silent then begin - r_GFX_OnceAnim( - R_GFX_TELEPORT_FAST, - FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-32, - FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2)-32 - ); + {$IFDEF ENABLE_GFX} + g_GFX_QueueEffect( + R_GFX_TELEPORT_FAST, + FObj.X + PLAYER_RECT.X + (PLAYER_RECT.Width div 2) - 32, + FObj.Y + PLAYER_RECT.Y + (PLAYER_RECT.Height div 2) - 32 + ); + {$ENDIF} if g_Game_IsServer and g_Game_IsNet then MH_SEND_Effect(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-32, FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2)-32, 0, @@ -4295,8 +4161,10 @@ begin FLoss := 0; end; - if FAlive and (FPunchAnim <> nil) then - FPunchAnim.Update(); + if FAlive then + FPunchAnim.Update; + if FPunchAnim.played then + FPunchAnim.Disable; if FAlive and (gFly or FJetpack) then FlySmoke(); @@ -4595,7 +4463,9 @@ begin end else if (FAir mod 31 = 0) and not blockmon then begin - g_GFX_Bubbles(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2), FObj.Y+PLAYER_RECT.Y-4, 5+Random(6), 8, 4); + {$IFDEF ENABLE_GFX} + g_GFX_Bubbles(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2), FObj.Y+PLAYER_RECT.Y-4, 5+Random(6), 8, 4); + {$ENDIF} if Random(2) = 0 then g_Sound_PlayExAt('SOUND_GAME_BUBBLE1', FObj.X, FObj.Y) else @@ -5686,8 +5556,10 @@ begin if BodyInLiquid(0, 0) then begin - g_GFX_Bubbles(Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)+Random(3)-1, - Obj.Y+Obj.Rect.Height+8, 1, 8, 4); + {$IFDEF ENABLE_GFX} + g_GFX_Bubbles(Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)+Random(3)-1, + Obj.Y+Obj.Rect.Height+8, 1, 8, 4); + {$ENDIF} if Random(2) = 0 then g_Sound_PlayExAt('SOUND_GAME_BUBBLE1', FObj.X, FObj.Y) else @@ -5697,11 +5569,13 @@ begin for i := 1 to Times do begin - r_GFX_OnceAnim( - R_GFX_SMOKE_TRANS, - Obj.X+Obj.Rect.X+Random(Obj.Rect.Width+Times*2)-(R_GFX_SMOKE_WIDTH div 2), - Obj.Y+Obj.Rect.Height-4+Random(8+Times*2) - ); + {$IFDEF ENABLE_GFX} + g_GFX_QueueEffect( + R_GFX_SMOKE_TRANS, + Obj.X+Obj.Rect.X+Random(Obj.Rect.Width+Times*2)-(R_GFX_SMOKE_WIDTH div 2), + Obj.Y+Obj.Rect.Height-4+Random(8+Times*2) + ); + {$ENDIF} end; end; @@ -5713,11 +5587,13 @@ begin for i := 1 to Times do begin - r_GFX_OnceAnim( - R_GFX_FLAME, - Obj.X+Obj.Rect.X+Random(Obj.Rect.Width+Times*2)-(R_GFX_FLAME_WIDTH div 2), - Obj.Y+8+Random(8+Times*2) - ); + {$IFDEF ENABLE_GFX} + g_GFX_QueueEffect( + R_GFX_FLAME, + Obj.X+Obj.Rect.X+Random(Obj.Rect.Width+Times*2)-(R_GFX_FLAME_WIDTH div 2), + Obj.Y+8+Random(8+Times*2) + ); + {$ENDIF} end; end; @@ -5743,25 +5619,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; @@ -5790,49 +5665,54 @@ end; procedure TCorpse.Damage(Value: Word; SpawnerUID: Word; vx, vy: Integer); -var - pm: TPlayerModel; - Blood: TModelBlood; + {$IFDEF ENABLE_GFX} + var Blood: TModelBlood; + {$ENDIF} begin if FState = CORPSE_STATE_REMOVEME then Exit; FDamage := FDamage + Value; +{$IFDEF ENABLE_GIBS} 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_Gibs_Create( + 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); - FObj.Vel.X := FObj.Vel.X + vx; - FObj.Vel.Y := FObj.Vel.Y + vy; +{$ENDIF} + begin + FObj.Vel.X := FObj.Vel.X + vx; + FObj.Vel.Y := FObj.Vel.Y + vy; + {$IFDEF ENABLE_GFX} + Blood := FModel.GetBlood(); 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, Blood.R, Blood.G, Blood.B, Blood.Kind); - end; + {$ENDIF} + end; end; procedure TCorpse.Update(); @@ -5864,16 +5744,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); @@ -5885,28 +5762,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, 0, False); + // 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, 0, False); end; procedure TCorpse.LoadState (st: TStream); -var - anim: Boolean; + var anim, blending: Boolean; r, g, b, alpha: Byte; stub: TAnimationState; begin assert(st <> nil); @@ -5918,28 +5792,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, alpha, blending); + 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, alpha, blending); + stub.Free; end; { T B o t : }