diff --git a/src/game/g_player.pas b/src/game/g_player.pas
index 90588ba10e31d4be1d60592fad315687274c8aff..28032e95d4ea5c2b767c165ff8b6993915e5af21 100644 (file)
--- a/src/game/g_player.pas
+++ b/src/game/g_player.pas
Kills: Word;
Color: TRGB;
Spectator: Boolean;
+ UID: Word;
end;
TPlayerStatArray = Array of TPlayerStat;
FActionChanged: Boolean;
FAngle: SmallInt;
FFireAngle: SmallInt;
+ FIncCamOld: Integer;
FIncCam: Integer;
+ FSlopeOld: Integer;
FShellTimer: Integer;
FShellType: Byte;
FSawSound: TPlayableSound;
procedure doDamage (v: Integer);
- function followCorpse(): Boolean;
+ function refreshCorpse(): Boolean;
public
FDamageBuffer: Integer;
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;
procedure DrawIndicator(Color: TRGB);
procedure DrawBubble();
procedure DrawGUI();
+ procedure PreUpdate();
procedure Update(); virtual;
procedure RememberState();
procedure RecallState();
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;
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;
public
constructor Create(X, Y: Integer; ModelName: String; aMess: Boolean);
destructor Destroy(); override;
- procedure Damage(Value: Word; vx, vy: Integer);
+ procedure Damage(Value: Word; SpawnerUID: Word; vx, vy: Integer);
procedure Update();
procedure Draw();
procedure SaveState (st: TStream);
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);
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();
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();
var
i: Integer;
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();
Color := gPlayers[a].FModel.Color;
Lives := gPlayers[a].FLives;
Spectator := gPlayers[a].FSpectator;
+ UID := gPlayers[a].FUID;
end;
end;
end;
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;
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,
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 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
procedure g_Player_DrawCorpses();
var
- i: Integer;
+ i, fX, fY: Integer;
a: TDFPoint;
begin
if gGibs <> nil then
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;
procedure g_Player_DrawShells();
var
- i: Integer;
+ i, fX, fY: Integer;
a: TDFPoint;
begin
if gShells <> nil then
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;
FFirePainTime := 0;
FFireAttacker := 0;
FHandicap := 100;
+ FCorpse := -1;
FActualModelName := 'doomer';
procedure TPlayer.DrawIndicator(Color: TRGB);
var
- indX, indY: Integer;
+ indX, indY, fX, fY, fSlope: Integer;
indW, indH: Word;
indA: Single;
a: TDFPoint;
c: TRGB;
begin
if FAlive then
+ begin
+ FObj.lerp(gLerpFactor, fX, fY);
+ fSlope := nlerp(FSlopeOld, FObj.slopeUpLeft, gLerpFactor);
+
case gPlayerIndicatorStyle of
0:
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);
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;
+ CObj: TObj;
begin
- bubX := FObj.X+FObj.Rect.X + IfThen(FDirection = TDirection.D_LEFT, -4, 18);
- bubY := FObj.Y+FObj.Rect.Y - 18;
+ 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;
Gb := 64;
Bb := 64;
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;
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
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;
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
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
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
FDeath := 0;
FSecrets := 0;
FSpawnInvul := 0;
+ FCorpse := -1;
FReady := False;
if FNoRespawn then
begin
ReleaseKeys();
FDamageBuffer := 0;
+ FSlopeOld := 0;
+ FIncCamOld := 0;
FIncCam := 0;
FBFGFireCounter := -1;
FShellTimer := -1;
// Îäèíî÷íàÿ èãðà/êîîïåðàòèâ
if gGameSettings.GameMode in [GM_COOP, GM_SINGLE] then
begin
- if (Self = gPlayer1) or (Self = gPlayer2) then
+ if Self = gPlayer1 then
begin
- // Òî÷êà ïîÿâëåíèÿ ñâîåãî èãðîêà
- if Self = gPlayer1 then
- c := RESPAWNPOINT_PLAYER1
- else
- c := RESPAWNPOINT_PLAYER2;
- if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
-
- // Òî÷êà ïîÿâëåíèÿ äðóãîãî èãðîêà
- if Self = gPlayer1 then
- c := RESPAWNPOINT_PLAYER2
- else
- c := RESPAWNPOINT_PLAYER1;
- if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
- end else
+ // player 1 should try to spawn on the player 1 point
+ if g_Map_GetPointCount(RESPAWNPOINT_PLAYER1) > 0 then
+ Exit(RESPAWNPOINT_PLAYER1)
+ else if g_Map_GetPointCount(RESPAWNPOINT_PLAYER2) > 0 then
+ Exit(RESPAWNPOINT_PLAYER2);
+ end
+ else if Self = gPlayer2 then
begin
- // Òî÷êà ïîÿâëåíèÿ ëþáîãî èãðîêà (áîòà)
- if Random(2) = 0 then
- c := RESPAWNPOINT_PLAYER1
- else
- c := RESPAWNPOINT_PLAYER2;
- if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
- end;
-
- // Òî÷êà ëþáîé èç êîìàíä
- if Random(2) = 0 then
- c := RESPAWNPOINT_RED
+ // player 2 should try to spawn on the player 2 point
+ if g_Map_GetPointCount(RESPAWNPOINT_PLAYER2) > 0 then
+ Exit(RESPAWNPOINT_PLAYER2)
+ else if g_Map_GetPointCount(RESPAWNPOINT_PLAYER1) > 0 then
+ Exit(RESPAWNPOINT_PLAYER1);
+ end
else
- c := RESPAWNPOINT_BLUE;
- if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
-
- // Òî÷êà DM
- c := RESPAWNPOINT_DM;
- if g_Map_GetPointCount(c) > 0 then
begin
- Result := c;
- Exit;
+ // other players randomly pick either the first or the second point
+ c := IfThen((Random(2) = 0), RESPAWNPOINT_PLAYER1, RESPAWNPOINT_PLAYER2);
+ if g_Map_GetPointCount(c) > 0 then
+ Exit(c);
+ // try the other one
+ c := IfThen((c = RESPAWNPOINT_PLAYER1), RESPAWNPOINT_PLAYER2, RESPAWNPOINT_PLAYER1);
+ if g_Map_GetPointCount(c) > 0 then
+ Exit(c);
end;
end;
// Ìÿñîïîâàë
if gGameSettings.GameMode = GM_DM then
begin
- // Òî÷êà DM
- c := RESPAWNPOINT_DM;
- if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
-
- // Òî÷êà ïîÿâëåíèÿ ëþáîãî èãðîêà
- if Random(2) = 0 then
- c := RESPAWNPOINT_PLAYER1
- else
- c := RESPAWNPOINT_PLAYER2;
- if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
-
- // Òî÷êà ëþáîé èç êîìàíä
- if Random(2) = 0 then
- c := RESPAWNPOINT_RED
- else
- c := RESPAWNPOINT_BLUE;
- if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
+ // try DM points first
+ if g_Map_GetPointCount(RESPAWNPOINT_DM) > 0 then
+ Exit(RESPAWNPOINT_DM);
end;
// Êîìàíäíûå
if gGameSettings.GameMode in [GM_TDM, GM_CTF] then
begin
- // Òî÷êà ñâîåé êîìàíäû
- c := RESPAWNPOINT_DM;
- if FTeam = TEAM_RED then
- c := RESPAWNPOINT_RED;
- if FTeam = TEAM_BLUE then
- c := RESPAWNPOINT_BLUE;
- if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
-
- // Òî÷êà DM
- c := RESPAWNPOINT_DM;
- if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
-
- // Òî÷êà ïîÿâëåíèÿ ëþáîãî èãðîêà
- if Random(2) = 0 then
- c := RESPAWNPOINT_PLAYER1
- else
- c := RESPAWNPOINT_PLAYER2;
- if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
-
- // Òî÷êà äðóãîé êîìàíäû
+ // try team points first
c := RESPAWNPOINT_DM;
if FTeam = TEAM_RED then
+ c := RESPAWNPOINT_RED
+ else if FTeam = TEAM_BLUE then
c := RESPAWNPOINT_BLUE;
- if FTeam = TEAM_BLUE then
- c := RESPAWNPOINT_RED;
if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
+ Exit(c);
end;
+
+ // still haven't found a spawnpoint, try random shit
+ Result := g_Map_GetRandomPointType();
end;
procedure TPlayer.Respawn(Silent: Boolean; Force: Boolean = False);
Anim: TAnimation;
ID: DWORD;
begin
+ FSlopeOld := 0;
+ FIncCamOld := 0;
FIncCam := 0;
FBFGFireCounter := -1;
FShellTimer := -1;
FPain := 0;
FLastHit := 0;
FSpawnInvul := 0;
+ FCorpse := -1;
if not g_Game_IsServer then
Exit;
// Óñòàíîâêà êîîðäèíàò è ñáðîñ âñåõ ïàðàìåòðîâ:
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;
FPhysics := False;
FWantsInGame := False;
FSpawned := False;
+ FCorpse := -1;
if FNoRespawn then
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;
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
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;
+ FIncCamOld := FIncCam;
+ FObj.oldX := FObj.X;
+ FObj.oldY := FObj.Y;
+end;
+
procedure TPlayer.Update();
var
b: Byte;
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;
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
var
AX, AY: Integer;
begin
- if NetInterpLevel < 1 then
+ FXTo := XTo;
+ FYTo := YTo;
+ if FJustTeleported or (NetInterpLevel < 1) then
begin
FObj.X := XTo;
FObj.Y := YTo;
+ if FJustTeleported then
+ begin
+ FObj.oldX := FObj.X;
+ FObj.oldY := FObj.Y;
+ end;
end
else
begin
- FXTo := XTo;
- FYTo := YTo;
-
AX := Abs(FXTo - FObj.X);
AY := Abs(FYTo - FObj.Y);
if (AX > 32) or (AX <= NetInterpLevel) then
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
end;
SavedState.Used := True;
- SavedStates[i] := SavedState;
+ SavedStates[FSavedStateNum] := SavedState;
end;
procedure TPlayer.RecallState();
end;
-procedure TCorpse.Damage(Value: Word; vx, vy: Integer);
+procedure TCorpse.Damage(Value: Word; SpawnerUID: Word; vx, vy: Integer);
var
pm: TPlayerModel;
Blood: TModelBlood;
if (gBodyKillEvent <> -1)
and gDelayedEvents[gBodyKillEvent].Pending then
gDelayedEvents[gBodyKillEvent].Pending := False;
- gBodyKillEvent := g_Game_DelayEvent(DE_BODYKILL, 1050, 0);
+ gBodyKillEvent := g_Game_DelayEvent(DE_BODYKILL, 1050, SpawnerUID);
end;
end
else
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;
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);