X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_player.pas;h=92afc636f73aa29a5a0922fbc8493cb8b8b7bf28;hb=abda6900c041e39944de6a49aa088a60c170715e;hp=7499754329dac902458811598b024c4a3ebf2aef;hpb=b89a73ac1981feb1c63f4760d696f1b31a6b9349;p=d2df-sdl.git diff --git a/src/game/g_player.pas b/src/game/g_player.pas index 7499754..92afc63 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -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; @@ -504,12 +504,13 @@ type PGib = ^TGib; TGib = record alive: Boolean; - ID: DWORD; - MaskID: DWORD; 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; @@ -519,12 +520,10 @@ type 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; @@ -535,15 +534,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); @@ -563,11 +559,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 @@ -617,7 +609,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(); @@ -635,7 +627,7 @@ uses {$IFDEF ENABLE_HOLMES} g_holmes, {$ENDIF} - e_log, g_map, g_items, g_console, g_gfx, Math, r_textures, r_animations, r_gfx, + e_log, g_map, g_items, g_console, g_gfx, Math, r_playermodel, r_gfx, g_options, g_triggers, g_menu, g_game, g_grid, e_res, wadreader, g_monsters, CONFIG, g_language, g_net, g_netmsg, @@ -1568,8 +1560,8 @@ begin if not ok then find_id := Random(Length(gCorpses)); - gCorpses[find_id] := TCorpse.Create(FObj.X, FObj.Y, FModel.Name, FHealth < -20); - gCorpses[find_id].FColor := FModel.Color; + gCorpses[find_id] := TCorpse.Create(FObj.X, FObj.Y, FModel.GetName(), FHealth < -20); + 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; @@ -1577,40 +1569,27 @@ begin Result := find_id; end else - g_Player_CreateGibs(FObj.X + PLAYER_RECT_CX, - FObj.Y + PLAYER_RECT_CY, - FModel.Name, FModel.Color); + g_Player_CreateGibs(FObj.X + PLAYER_RECT_CX, FObj.Y + PLAYER_RECT_CY, FModel.id, 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; @@ -1630,29 +1609,31 @@ 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: Integer; GibsArray: TGibsArray; Blood: TModelBlood; begin + if mid = -1 then + Exit; if (gGibs = nil) or (Length(gGibs) = 0) then Exit; - if not g_PlayerModel_GetGibs(ModelName, GibsArray) then + if not g_PlayerModel_GetGibs(mid, GibsArray) then Exit; - Blood := g_PlayerModel_GetBlood(ModelName); + Blood := PlayerModelsArray[mid].Blood; for a := 0 to High(GibsArray) do with gGibs[CurrentGib] do begin + ModelID := mid; + GibID := GibsArray[a]; Color := fColor; - ID := GibsArray[a].ID; - MaskID := GibsArray[a].MaskID; alive := True; g_Obj_Init(@Obj); - Obj.Rect := GibsArray[a].Rect; - Obj.X := fX-GibsArray[a].Rect.X-(GibsArray[a].Rect.Width div 2); - Obj.Y := fY-GibsArray[a].Rect.Y-(GibsArray[a].Rect.Height div 2); + 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); @@ -1872,7 +1853,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); // Сохраняем данные трупа: @@ -2119,6 +2100,8 @@ begin FNetTime := 0; FWaitForFirstSpawn := false; + FPunchAnim := TAnimationState.Create(False, 1, 4); + FPunchAnim.Disable; resetWeaponQueue(); end; @@ -2265,31 +2248,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(); @@ -3015,23 +2982,27 @@ 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), - FModel.Blood.R, FModel.Blood.G, FModel.Blood.B, FModel.Blood.Kind); + 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, - FModel.Blood.R, FModel.Blood.G, FModel.Blood.B, FModel.Blood.Kind); + Blood.R, Blood.G, Blood.B, Blood.Kind); end; procedure TPlayer.MakeBloodVector(Count: Word; VelX, VelY: Integer); + var Blood: TModelBlood; 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, - FModel.Blood.R, FModel.Blood.G, FModel.Blood.B, FModel.Blood.Kind); + Blood.R, Blood.G, Blood.B, Blood.Kind); end; procedure TPlayer.QueueWeaponSwitch(Weapon: Byte); @@ -4287,8 +4258,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(); @@ -4670,14 +4643,13 @@ begin if (FActionAnim = A_PAIN) and (FModel.Animation <> A_PAIN) then begin FModel.ChangeAnimation(FActionAnim, FActionForce); - FModel.GetCurrentAnimation.MinLength := i; - FModel.GetCurrentAnimationMask.MinLength := i; + FModel.AnimState.MinLength := i; end else FModel.ChangeAnimation(FActionAnim, FActionForce and (FModel.Animation <> A_STAND)); - if (FModel.GetCurrentAnimation.Played or ((not FActionChanged) and (FModel.Animation = A_WALK))) + if (FModel.AnimState.Played or ((not FActionChanged) and (FModel.Animation = A_WALK))) then SetAction(A_STAND, True); - if not ((FModel.Animation = A_WALK) and (Abs(FObj.Vel.X) < 4) and not FModel.Fire) then FModel.Update; + if not ((FModel.Animation = A_WALK) and (Abs(FObj.Vel.X) < 4) and not FModel.GetFire()) then FModel.Update; for b := Low(FKeys) to High(FKeys) do if FKeys[b].Time = 0 then FKeys[b].Pressed := False else Dec(FKeys[b].Time); @@ -5367,7 +5339,7 @@ begin // Время до повторного респауна, смены оружия, исользования, захвата флага for i := T_RESPAWN to T_FLAGCAP do utils.writeInt(st, LongWord(FTime[i])); // Название модели - utils.writeStr(st, FModel.Name); + utils.writeStr(st, FModel.GetName()); // Цвет модели utils.writeInt(st, Byte(FColor.R)); utils.writeInt(st, Byte(FColor.G)); @@ -5736,25 +5708,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; @@ -5783,9 +5754,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; @@ -5793,32 +5762,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), @@ -5857,16 +5827,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); @@ -5878,28 +5845,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); @@ -5911,28 +5875,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 : }