X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_player.pas;h=dd5378b5162ce6e2fbbf3f67bf5eee90cda9efbb;hb=fd8f6c935e5b65101768e08007d5751e8e5e9ba8;hp=362c2833ecbe9a7393caf11622c1ccb5bbfdb67e;hpb=cb61300b61ba18d486d19edf315f05b5b494fac3;p=d2df-sdl.git diff --git a/src/game/g_player.pas b/src/game/g_player.pas index 362c283..dd5378b 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -171,6 +171,7 @@ type FLastSpawnerUID: Word; FLastHit: Byte; FObj: TObj; + FXTo, FYTo: Integer; FSpectatePlayer: Integer; FFirePainTime: Integer; FFireAttacker: Word; @@ -238,7 +239,7 @@ type procedure doDamage (v: Integer); - function followCorpse(): Boolean; + function refreshCorpse(): Boolean; public FDamageBuffer: Integer; @@ -271,6 +272,7 @@ type FSpawnInvul: Integer; FHandicap: Integer; FWaitForFirstSpawn: Boolean; // set to `true` in server, used to spawn a player on first full state request + FCorpse: Integer; // debug: viewport offset viewPortX, viewPortY, viewPortW, viewPortH: Integer; @@ -334,6 +336,8 @@ type procedure LoadState (st: TStream); virtual; procedure PauseSounds(Enable: Boolean); procedure NetFire(Wpn: Byte; X, Y, AX, AY: Integer; WID: Integer = -1); + procedure DoLerp(Level: Integer = 2); + procedure SetLerp(XTo, YTo: Integer); procedure QueueWeaponSwitch(Weapon: Byte); procedure RealizeCurrentWeapon(); procedure FlamerOn; @@ -348,6 +352,8 @@ type procedure getMapBox (out x, y, w, h: Integer); inline; procedure moveBy (dx, dy: Integer); inline; + function getCameraObj(): TObj; + public property Vel: TPoint2i read FObj.Vel; property Obj: TObj read FObj; @@ -594,7 +600,7 @@ function g_Player_Get(UID: Word): TPlayer; function g_Player_GetCount(): Byte; function g_Player_GetStats(): TPlayerStatArray; function g_Player_ValidName(Name: String): Boolean; -procedure g_Player_CreateCorpse(Player: TPlayer); +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(); @@ -1434,6 +1440,8 @@ begin e_TextureFontPrint(0, fH * 3, 'Vel Y: ' + IntToStr(p.FObj.Vel.Y), gStdFont); e_TextureFontPrint(0, fH * 4, 'Acc X: ' + IntToStr(p.FObj.Accel.X), gStdFont); e_TextureFontPrint(0, fH * 5, 'Acc Y: ' + IntToStr(p.FObj.Accel.Y), gStdFont); + e_TextureFontPrint(0, fH * 6, 'Old X: ' + IntToStr(p.FObj.oldX), gStdFont); + e_TextureFontPrint(0, fH * 7, 'Old Y: ' + IntToStr(p.FObj.oldY), gStdFont); end; procedure g_Player_DrawHealth(); @@ -1567,21 +1575,24 @@ begin end; end; -procedure g_Player_CreateCorpse(Player: TPlayer); +function g_Player_CreateCorpse(Player: TPlayer): Integer; var i: Integer; find_id: DWORD; ok: Boolean; begin + Result := -1; + if Player.alive then Exit; // Ðàçðûâàåì ñâÿçü ñ ïðåæíèì òðóïîì: - if gCorpses <> nil then - for i := 0 to High(gCorpses) do - if gCorpses[i] <> nil then - if gCorpses[i].FPlayerUID = Player.FUID then - gCorpses[i].FPlayerUID := 0; + i := Player.FCorpse; + if (i >= 0) and (i < Length(gCorpses)) then + begin + if (gCorpses[i] <> nil) and (gCorpses[i].FPlayerUID = Player.FUID) then + gCorpses[i].FPlayerUID := 0; + end; if Player.FObj.Y >= gMapInfo.Height+128 then Exit; @@ -1609,6 +1620,8 @@ begin 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, @@ -2196,6 +2209,7 @@ begin FFirePainTime := 0; FFireAttacker := 0; FHandicap := 100; + FCorpse := -1; FActualModelName := 'doomer'; @@ -2440,8 +2454,11 @@ var Rb, Gb, Bb, Rw, Gw, Bw: SmallInt; Dot: Byte; + CObj: TObj; begin - FObj.lerp(gLerpFactor, fX, fY); + CObj := getCameraObj(); + CObj.lerp(gLerpFactor, fX, fY); + // NB: _F_Obj.Rect is used to keep the bubble higher; this is not a mistake bubX := fX+FObj.Rect.X + IfThen(FDirection = TDirection.D_LEFT, -4, 18); bubY := fY+FObj.Rect.Y - 18; Rb := 64; @@ -3600,7 +3617,7 @@ begin DropFlag(KillType = K_FALLKILL); end; - g_Player_CreateCorpse(Self); + FCorpse := g_Player_CreateCorpse(Self); if Srv and (gGameSettings.MaxLives > 0) and FNoRespawn and (gLMSRespawn = LMS_RESPAWN_NONE) then @@ -4411,6 +4428,7 @@ begin FDeath := 0; FSecrets := 0; FSpawnInvul := 0; + FCorpse := -1; FReady := False; if FNoRespawn then begin @@ -4608,6 +4626,7 @@ begin FPain := 0; FLastHit := 0; FSpawnInvul := 0; + FCorpse := -1; if not g_Game_IsServer then Exit; @@ -4781,6 +4800,8 @@ begin GameX := gMapInfo.Width div 2; GameY := gMapInfo.Height div 2; end; + FXTo := GameX; + FYTo := GameY; FAlive := False; FSpectator := True; @@ -4788,6 +4809,7 @@ begin FPhysics := False; FWantsInGame := False; FSpawned := False; + FCorpse := -1; if FNoRespawn then begin @@ -4813,7 +4835,11 @@ begin Exit; FGhost := not FGhost; FPhysics := not FGhost; - if not FGhost then + if FGhost then + begin + FXTo := FObj.X; + FYTo := FObj.Y; + end else begin FObj.Accel.X := 0; FObj.Accel.Y := 0; @@ -4958,6 +4984,11 @@ begin 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; + FYTo := FObj.Y; + end; if not g_Game_IsNet then begin @@ -5011,11 +5042,12 @@ begin Result := 1; end; -function TPlayer.followCorpse(): Boolean; +function TPlayer.refreshCorpse(): Boolean; var i: Integer; begin Result := False; + FCorpse := -1; if FAlive or FSpectator then Exit; if (gCorpses = nil) or (Length(gCorpses) = 0) then @@ -5025,16 +5057,26 @@ begin if gCorpses[i].FPlayerUID = FUID then begin Result := True; - FObj.X := gCorpses[i].FObj.X; - FObj.Y := gCorpses[i].FObj.Y; - FObj.Vel.X := gCorpses[i].FObj.Vel.X; - FObj.Vel.Y := gCorpses[i].FObj.Vel.Y; - FObj.Accel.X := gCorpses[i].FObj.Accel.X; - FObj.Accel.Y := gCorpses[i].FObj.Accel.Y; + FCorpse := i; break; end; end; +function TPlayer.getCameraObj(): TObj; +begin + if (not FAlive) and (not FSpectator) and + (FCorpse >= 0) and (FCorpse < Length(gCorpses)) and + (gCorpses[FCorpse] <> nil) and (gCorpses[FCorpse].FPlayerUID = FUID) then + begin + gCorpses[FCorpse].FObj.slopeUpLeft := FObj.slopeUpLeft; + Result := gCorpses[FCorpse].FObj; + end + else + begin + Result := FObj; + end; +end; + procedure TPlayer.PreUpdate(); begin FSlopeOld := FObj.slopeUpLeft; @@ -5055,6 +5097,12 @@ 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 NetServer then if FClientID >= 0 then begin @@ -5113,8 +5161,7 @@ begin if FPhysics then begin - if not followCorpse() then - g_Obj_Move(@FObj, True, True, True); + g_Obj_Move(@FObj, True, True, True); positionChanged(); // this updates spatial accelerators end; @@ -5217,39 +5264,38 @@ begin begin if FKeys[KEY_UP].Pressed or FKeys[KEY_JUMP].Pressed then begin - FObj.Y := FObj.Y - 32; + FYTo := FObj.Y - 32; FSpectatePlayer := -1; end; if FKeys[KEY_DOWN].Pressed then begin - FObj.Y := FObj.Y + 32; + FYTo := FObj.Y + 32; FSpectatePlayer := -1; end; if FKeys[KEY_LEFT].Pressed then begin - FObj.X := FObj.X - 32; + FXTo := FObj.X - 32; FSpectatePlayer := -1; end; if FKeys[KEY_RIGHT].Pressed then begin - FObj.X := FObj.X + 32; + FXTo := FObj.X + 32; FSpectatePlayer := -1; end; - if (FObj.X < -64) then - FObj.X := -64 - else if (FObj.X > gMapInfo.Width + 32) then - FObj.X := gMapInfo.Width + 32; - if (FObj.Y < -72) then - FObj.Y := -72 - else if (FObj.Y > gMapInfo.Height + 32) then - FObj.Y := gMapInfo.Height + 32; + if (FXTo < -64) then + FXTo := -64 + else if (FXTo > gMapInfo.Width + 32) then + FXTo := gMapInfo.Width + 32; + if (FYTo < -72) then + FYTo := -72 + else if (FYTo > gMapInfo.Height + 32) then + FYTo := gMapInfo.Height + 32; end; if FPhysics then begin - if not followCorpse() then - g_Obj_Move(@FObj, True, True, True); + g_Obj_Move(@FObj, True, True, True); positionChanged(); // this updates spatial accelerators end else @@ -5261,8 +5307,8 @@ begin if gPlayers[FSpectatePlayer] <> nil then if gPlayers[FSpectatePlayer].alive then begin - FObj.X := gPlayers[FSpectatePlayer].GameX; - FObj.Y := gPlayers[FSpectatePlayer].GameY; + FXTo := gPlayers[FSpectatePlayer].GameX; + FYTo := gPlayers[FSpectatePlayer].GameY; end; end; @@ -5721,6 +5767,34 @@ begin else if (FAngle = ANGLE_LEFTUP) or (FAngle = ANGLE_RIGHTUP) then SetAction(A_ATTACKUP); end; +procedure TPlayer.DoLerp(Level: Integer = 2); +begin + if FObj.X <> FXTo then FObj.X := Lerp(FObj.X, FXTo, Level); + if FObj.Y <> FYTo then FObj.Y := Lerp(FObj.Y, FYTo, Level); +end; + +procedure TPlayer.SetLerp(XTo, YTo: Integer); +var + AX, AY: Integer; +begin + FXTo := XTo; + FYTo := YTo; + if NetInterpLevel < 1 then + begin + FObj.X := XTo; + FObj.Y := YTo; + end + else + begin + AX := Abs(FXTo - FObj.X); + AY := Abs(FYTo - FObj.Y); + if (AX > 32) or (AX <= NetInterpLevel) then + FObj.X := FXTo; + if (AY > 32) or (AY <= NetInterpLevel) then + FObj.Y := FYTo; + end; +end; + function TPlayer.FullInLift(XInc, YInc: Integer): Integer; begin if g_Map_CollidePanel(FObj.X+PLAYER_RECT.X+XInc, FObj.Y+PLAYER_RECT.Y+YInc,