X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_player.pas;h=068c2b4124e41fe4d225a6dd4685666797c1300c;hb=b9615dc5473b0eadac9f3298714b440ff406d322;hp=d9dd8871a953815a003809dbeacb6d231539f1e7;hpb=6820eae460a9c99136ab5e679ffe2f6236c3540f;p=d2df-sdl.git diff --git a/src/game/g_player.pas b/src/game/g_player.pas index d9dd887..068c2b4 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -130,7 +130,7 @@ type MaxAmmo: Array [A_BULLETS..A_HIGH] of Word; Weapon: Array [WP_FIRST..WP_LAST] of Boolean; Rulez: Set of R_ITEM_BACKPACK..R_BERSERK; - WaitRecall: Boolean; + Used: Boolean; end; TKeyState = record @@ -176,7 +176,7 @@ type FFirePainTime: Integer; FFireAttacker: Word; - FSavedState: TPlayerSavedState; + FSavedStateNum: Integer; FModel: TPlayerModel; FPunchAnim: TAnimation; @@ -186,7 +186,9 @@ type FActionChanged: Boolean; FAngle: SmallInt; FFireAngle: SmallInt; + FIncCamOld: Integer; FIncCam: Integer; + FSlopeOld: Integer; FShellTimer: Integer; FShellType: Byte; FSawSound: TPlayableSound; @@ -325,6 +327,7 @@ type procedure DrawIndicator(Color: TRGB); procedure DrawBubble(); procedure DrawGUI(); + procedure PreUpdate(); procedure Update(); virtual; procedure RememberState(); procedure RecallState(); @@ -379,6 +382,8 @@ type property GameAccelX: Integer read FObj.Accel.X write FObj.Accel.X; property GameAccelY: Integer read FObj.Accel.Y write FObj.Accel.Y; property IncCam: Integer read FIncCam write FIncCam; + property IncCamOld: Integer read FIncCamOld write FIncCamOld; + property SlopeOld: Integer read FSlopeOld write FSlopeOld; property UID: Word read FUID write FUID; property JustTeleported: Boolean read FJustTeleported write FJustTeleported; property NetTime: LongWord read FNetTime write FNetTime; @@ -581,6 +586,7 @@ function g_Player_Create(ModelName: String; Color: TRGB; Team: Byte; Bot: Boole function g_Player_CreateFromState (st: TStream): Word; procedure g_Player_Remove(UID: Word); procedure g_Player_ResetTeams(); +procedure g_Player_PreUpdate(); procedure g_Player_UpdateAll(); procedure g_Player_DrawAll(); procedure g_Player_DrawDebug(p: TPlayer); @@ -703,6 +709,7 @@ var CurrentShell: Integer = 0; BotNames: Array of String; BotList: Array of TBotProfile; + SavedStates: Array of TPlayerSavedState; function Lerp(X, Y, Factor: Integer): Integer; @@ -1340,6 +1347,7 @@ begin end; config.Free(); + SetLength(SavedStates, 0); end; procedure g_Player_Free(); @@ -1363,6 +1371,17 @@ begin gPlayer1 := nil; gPlayer2 := nil; + SetLength(SavedStates, 0); +end; + +procedure g_Player_PreUpdate(); +var + i: Integer; +begin + if gPlayers = nil then Exit; + for i := 0 to High(gPlayers) do + if gPlayers[i] <> nil then + gPlayers[i].PreUpdate(); end; procedure g_Player_UpdateAll(); @@ -1710,6 +1729,9 @@ begin 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 @@ -1760,6 +1782,9 @@ begin if gShells[i].alive then with gShells[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 @@ -1848,7 +1873,7 @@ procedure TShell.positionChanged (); inline; begin end; procedure g_Player_DrawCorpses(); var - i: Integer; + i, fX, fY: Integer; a: TDFPoint; begin if gGibs <> nil then @@ -1859,13 +1884,15 @@ begin if not g_Obj_Collide(sX, sY, sWidth, sHeight, @Obj) then Continue; + Obj.lerp(gLerpFactor, fX, fY); + a.X := Obj.Rect.X+(Obj.Rect.Width div 2); a.y := Obj.Rect.Y+(Obj.Rect.Height div 2); - e_DrawAdv(ID, Obj.X, Obj.Y, 0, True, False, RAngle, @a, TMirrorType.None); + e_DrawAdv(ID, fX, fY, 0, True, False, RAngle, @a, TMirrorType.None); e_Colors := Color; - e_DrawAdv(MaskID, Obj.X, Obj.Y, 0, True, False, RAngle, @a, TMirrorType.None); + e_DrawAdv(MaskID, fX, fY, 0, True, False, RAngle, @a, TMirrorType.None); e_Colors.R := 255; e_Colors.G := 255; e_Colors.B := 255; @@ -1879,7 +1906,7 @@ end; procedure g_Player_DrawShells(); var - i: Integer; + i, fX, fY: Integer; a: TDFPoint; begin if gShells <> nil then @@ -1890,10 +1917,12 @@ begin if not g_Obj_Collide(sX, sY, sWidth, sHeight, @Obj) then Continue; + Obj.lerp(gLerpFactor, fX, fY); + a.X := CX; a.Y := CY; - e_DrawAdv(SpriteID, Obj.X, Obj.Y, 0, True, False, RAngle, @a, TMirrorType.None); + e_DrawAdv(SpriteID, fX, fY, 0, True, False, RAngle, @a, TMirrorType.None); end; end; @@ -2164,7 +2193,7 @@ begin FClientID := -1; FPing := 0; FLoss := 0; - FSavedState.WaitRecall := False; + FSavedStateNum := -1; FShellTimer := -1; FFireTime := 0; FFirePainTime := 0; @@ -2335,7 +2364,7 @@ end; procedure TPlayer.DrawIndicator(Color: TRGB); var - indX, indY: Integer; + indX, indY, fX, fY, fSlope: Integer; indW, indH: Word; indA: Single; a: TDFPoint; @@ -2344,6 +2373,10 @@ var c: TRGB; begin if FAlive then + begin + FObj.lerp(gLerpFactor, fX, fY); + fSlope := nlerp(FSlopeOld, FObj.slopeUpLeft, gLerpFactor); + case gPlayerIndicatorStyle of 0: begin @@ -2356,31 +2389,32 @@ begin if (FObj.X + FObj.Rect.X) < 0 then begin indA := 90; - indX := FObj.X + FObj.Rect.X + FObj.Rect.Width; - indY := FObj.Y + FObj.Rect.Y + (FObj.Rect.Height - indW) div 2; + indX := fX + FObj.Rect.X + FObj.Rect.Width; + indY := fY + FObj.Rect.Y + (FObj.Rect.Height - indW) div 2; end else if (FObj.X + FObj.Rect.X + FObj.Rect.Width) > Max(gMapInfo.Width, gPlayerScreenSize.X) then begin indA := 270; - indX := FObj.X + FObj.Rect.X - indH; - indY := FObj.Y + FObj.Rect.Y + (FObj.Rect.Height - indW) div 2; + indX := fX + FObj.Rect.X - indH; + indY := fY + FObj.Rect.Y + (FObj.Rect.Height - indW) div 2; end - else if (fObj.Y - indH) < 0 then + else if (FObj.Y - indH) < 0 then begin indA := 180; - indX := FObj.X + FObj.Rect.X + (FObj.Rect.Width - indW) div 2; - indY := FObj.Y + FObj.Rect.Y + FObj.Rect.Height; + indX := fX + FObj.Rect.X + (FObj.Rect.Width - indW) div 2; + indY := fY + FObj.Rect.Y + FObj.Rect.Height; end else begin indA := 0; - indX := FObj.X + FObj.Rect.X + (FObj.Rect.Width - indW) div 2; - indY := FObj.Y - indH; + indX := fX + FObj.Rect.X + (FObj.Rect.Width - indW) div 2; + indY := fY - indH; end; + indY := indY + fSlope; indX := EnsureRange(indX, 0, Max(gMapInfo.Width, gPlayerScreenSize.X) - indW); indY := EnsureRange(indY, 0, Max(gMapInfo.Height, gPlayerScreenSize.Y) - indH); @@ -2394,23 +2428,25 @@ begin 1: begin e_TextureFontGetSize(gStdFont, nW, nH); - indX := FObj.X + FObj.Rect.X + (FObj.Rect.Width - Length(FName) * nW) div 2; - indY := FObj.Y - nH; + indX := fX + FObj.Rect.X + (FObj.Rect.Width - Length(FName) * nW) div 2; + indY := fY - nH + fSlope; e_TextureFontPrintEx(indX, indY, FName, gStdFont, Color.R, Color.G, Color.B, 1.0, True); end; end; + end; end; procedure TPlayer.DrawBubble(); var - bubX, bubY: Integer; + bubX, bubY, fX, fY: Integer; ID: LongWord; Rb, Gb, Bb, Rw, Gw, Bw: SmallInt; Dot: Byte; begin - bubX := FObj.X+FObj.Rect.X + IfThen(FDirection = TDirection.D_LEFT, -4, 18); - bubY := FObj.Y+FObj.Rect.Y - 18; + FObj.lerp(gLerpFactor, fX, fY); + bubX := fX+FObj.Rect.X + IfThen(FDirection = TDirection.D_LEFT, -4, 18); + bubY := fY+FObj.Rect.Y - 18; Rb := 64; Gb := 64; Bb := 64; @@ -2420,8 +2456,8 @@ begin case gChatBubble of 1: // simple textual non-bubble begin - bubX := FObj.X+FObj.Rect.X - 11; - bubY := FObj.Y+FObj.Rect.Y - 17; + bubX := fX+FObj.Rect.X - 11; + bubY := fY+FObj.Rect.Y - 17; e_TextureFontPrint(bubX, bubY, '[...]', gStdFont); Exit; end; @@ -2488,7 +2524,11 @@ var w, h: Word; dr: Boolean; Mirror: TMirrorType; + fX, fY, fSlope: Integer; begin + FObj.lerp(gLerpFactor, fX, fY); + fSlope := nlerp(FSlopeOld, FObj.slopeUpLeft, gLerpFactor); + if FAlive then begin if Direction = TDirection.D_RIGHT then @@ -2498,8 +2538,8 @@ begin if FPunchAnim <> nil then begin - FPunchAnim.Draw(FObj.X+IfThen(Direction = TDirection.D_LEFT, 15-FObj.Rect.X, FObj.Rect.X-15), - FObj.Y+FObj.Rect.Y-11, Mirror); + FPunchAnim.Draw(fX+IfThen(Direction = TDirection.D_LEFT, 15-FObj.Rect.X, FObj.Rect.X-15), + fY+fSlope+FObj.Rect.Y-11, Mirror); if FPunchAnim.played then begin FPunchAnim.Free; @@ -2512,11 +2552,11 @@ begin begin e_GetTextureSize(ID, @w, @h); if FDirection = TDirection.D_LEFT then - e_Draw(ID, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2)-(w div 2)+4, - FObj.Y+FObj.Rect.Y+(FObj.Rect.Height div 2)-(h div 2)-7+FObj.slopeUpLeft, 0, True, False) + e_Draw(ID, fX+FObj.Rect.X+(FObj.Rect.Width div 2)-(w div 2)+4, + fY+FObj.Rect.Y+(FObj.Rect.Height div 2)-(h div 2)-7+fSlope, 0, True, False) else - e_Draw(ID, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2)-(w div 2)-2, - FObj.Y+FObj.Rect.Y+(FObj.Rect.Height div 2)-(h div 2)-7+FObj.slopeUpLeft, 0, True, False); + e_Draw(ID, fX+FObj.Rect.X+(FObj.Rect.Width div 2)-(w div 2)-2, + fY+FObj.Rect.Y+(FObj.Rect.Height div 2)-(h div 2)-7+fSlope, 0, True, False); end; if FMegaRulez[MR_INVIS] > gTime then @@ -2529,15 +2569,15 @@ begin else dr := True; if dr then - FModel.Draw(FObj.X, FObj.Y+FObj.slopeUpLeft, 200) + FModel.Draw(fX, fY+fSlope, 200) else - FModel.Draw(FObj.X, FObj.Y+FObj.slopeUpLeft); + FModel.Draw(fX, fY+fSlope); end else - FModel.Draw(FObj.X, FObj.Y+FObj.slopeUpLeft, 254); + FModel.Draw(fX, fY+fSlope, 254); end else - FModel.Draw(FObj.X, FObj.Y+FObj.slopeUpLeft); + FModel.Draw(fX, fY+fSlope); end; if g_debug_Frames then @@ -2766,7 +2806,7 @@ begin e_CharFont_PrintEx(gMenuSmallFont, X-16-tw, Y+32, s, _RGB(255, 0, 0)); end; - if gLMSRespawn = LMS_RESPAWN_WARMUP then + if gLMSRespawn > LMS_RESPAWN_NONE then begin s := _lc[I_GAME_WARMUP]; e_CharFont_GetSize(gMenuFont, s, tw, th); @@ -4393,6 +4433,8 @@ begin ReleaseKeys(); FDamageBuffer := 0; + FSlopeOld := 0; + FIncCamOld := 0; FIncCam := 0; FBFGFireCounter := -1; FShellTimer := -1; @@ -4561,6 +4603,8 @@ var Anim: TAnimation; ID: DWORD; begin + FSlopeOld := 0; + FIncCamOld := 0; FIncCam := 0; FBFGFireCounter := -1; FShellTimer := -1; @@ -4662,6 +4706,8 @@ begin // Óñòàíîâêà êîîðäèíàò è ñáðîñ âñåõ ïàðàìåòðîâ: FObj.X := RespawnPoint.X-PLAYER_RECT.X; FObj.Y := RespawnPoint.Y-PLAYER_RECT.Y; + FObj.oldX := FObj.X; // don't interpolate after respawn + FObj.oldY := FObj.Y; FObj.Vel.X := 0; FObj.Vel.Y := 0; FObj.Accel.X := 0; @@ -4919,6 +4965,8 @@ begin FObj.X := X-PLAYER_RECT.X; FObj.Y := Y-PLAYER_RECT.Y; + FObj.oldX := FObj.X; // don't interpolate after respawn + FObj.oldY := FObj.Y; if FAlive and FGhost then begin FXTo := FObj.X; @@ -5001,6 +5049,14 @@ begin end; end; +procedure TPlayer.PreUpdate(); +begin + FSlopeOld := FObj.slopeUpLeft; + FIncCamOld := FIncCam; + FObj.oldX := FObj.X; + FObj.oldY := FObj.Y; +end; + procedure TPlayer.Update(); var b: Byte; @@ -5013,11 +5069,8 @@ begin NetServer := g_Game_IsNet and g_Game_IsServer; AnyServer := g_Game_IsServer; - if g_Game_IsClient and (NetInterpLevel > 0) then - DoLerp(NetInterpLevel + 1) - else - if FGhost then - DoLerp(4); + if FGhost then + DoLerp(4); if NetServer then if FClientID >= 0 then @@ -5954,45 +6007,66 @@ end; procedure TPlayer.RememberState(); var i: Integer; -begin - FSavedState.Health := FHealth; - FSavedState.Armor := FArmor; - FSavedState.Air := FAir; - FSavedState.JetFuel := FJetFuel; - FSavedState.CurrWeap := FCurrWeap; - FSavedState.NextWeap := FNextWeap; - FSavedState.NextWeapDelay := FNextWeapDelay; - - for i := 0 to 3 do - FSavedState.Ammo[i] := FAmmo[i]; - for i := 0 to 3 do - FSavedState.MaxAmmo[i] := FMaxAmmo[i]; + SavedState: TPlayerSavedState; +begin + SavedState.Health := FHealth; + SavedState.Armor := FArmor; + SavedState.Air := FAir; + SavedState.JetFuel := FJetFuel; + SavedState.CurrWeap := FCurrWeap; + SavedState.NextWeap := FNextWeap; + SavedState.NextWeapDelay := FNextWeapDelay; + for i := Low(FWeapon) to High(FWeapon) do + SavedState.Weapon[i] := FWeapon[i]; + for i := Low(FAmmo) to High(FAmmo) do + SavedState.Ammo[i] := FAmmo[i]; + for i := Low(FMaxAmmo) to High(FMaxAmmo) do + SavedState.MaxAmmo[i] := FMaxAmmo[i]; + SavedState.Rulez := FRulez - [R_KEY_RED, R_KEY_GREEN, R_KEY_BLUE]; + + FSavedStateNum := -1; + for i := Low(SavedStates) to High(SavedStates) do + if not SavedStates[i].Used then + begin + FSavedStateNum := i; + break; + end; + if FSavedStateNum < 0 then + begin + SetLength(SavedStates, Length(SavedStates) + 1); + FSavedStateNum := High(SavedStates); + end; - FSavedState.Rulez := FRulez; - FSavedState.WaitRecall := True; + SavedState.Used := True; + SavedStates[FSavedStateNum] := SavedState; end; procedure TPlayer.RecallState(); var i: Integer; + SavedState: TPlayerSavedState; begin - if not FSavedState.WaitRecall then Exit; - - FHealth := FSavedState.Health; - FArmor := FSavedState.Armor; - FAir := FSavedState.Air; - FJetFuel := FSavedState.JetFuel; - FCurrWeap := FSavedState.CurrWeap; - FNextWeap := FSavedState.NextWeap; - FNextWeapDelay := FSavedState.NextWeapDelay; - - for i := 0 to 3 do - FAmmo[i] := FSavedState.Ammo[i]; - for i := 0 to 3 do - FMaxAmmo[i] := FSavedState.MaxAmmo[i]; + if(FSavedStateNum < 0) or (FSavedStateNum > High(SavedStates)) then + Exit; - FRulez := FSavedState.Rulez; - FSavedState.WaitRecall := False; + SavedState := SavedStates[FSavedStateNum]; + SavedStates[FSavedStateNum].Used := False; + FSavedStateNum := -1; + + FHealth := SavedState.Health; + FArmor := SavedState.Armor; + FAir := SavedState.Air; + FJetFuel := SavedState.JetFuel; + FCurrWeap := SavedState.CurrWeap; + FNextWeap := SavedState.NextWeap; + FNextWeapDelay := SavedState.NextWeapDelay; + for i := Low(FWeapon) to High(FWeapon) do + FWeapon[i] := SavedState.Weapon[i]; + for i := Low(FAmmo) to High(FAmmo) do + FAmmo[i] := SavedState.Ammo[i]; + for i := Low(FMaxAmmo) to High(FMaxAmmo) do + FMaxAmmo[i] := SavedState.MaxAmmo[i]; + FRulez := SavedState.Rulez; if gGameSettings.GameType = GT_SERVER then MH_SEND_PlayerStats(FUID); @@ -6562,17 +6636,21 @@ begin end; procedure TCorpse.Draw(); +var + fX, fY: Integer; begin if FState = CORPSE_STATE_REMOVEME then Exit; + FObj.lerp(gLerpFactor, fX, fY); + if FAnimation <> nil then - FAnimation.Draw(FObj.X, FObj.Y, TMirrorType.None); + FAnimation.Draw(fX, fY, TMirrorType.None); if FAnimationMask <> nil then begin e_Colors := FColor; - FAnimationMask.Draw(FObj.X, FObj.Y, TMirrorType.None); + FAnimationMask.Draw(fX, fY, TMirrorType.None); e_Colors.R := 255; e_Colors.G := 255; e_Colors.B := 255; @@ -6586,6 +6664,9 @@ begin if FState = CORPSE_STATE_REMOVEME then Exit; + FObj.oldX := FObj.X; + FObj.oldY := FObj.Y; + if gTime mod (GAME_TICK*2) <> 0 then begin g_Obj_Move(@FObj, True, True, True);