diff --git a/src/game/g_player.pas b/src/game/g_player.pas
index 362c2833ecbe9a7393caf11622c1ccb5bbfdb67e..ee0655c223c9c39231669ce7d1f39d75858e0d3f 100644 (file)
--- a/src/game/g_player.pas
+++ b/src/game/g_player.pas
KEY_UP = 3;
KEY_DOWN = 4;
KEY_FIRE = 5;
KEY_UP = 3;
KEY_DOWN = 4;
KEY_FIRE = 5;
- KEY_NEXTWEAPON = 6;
- KEY_PREVWEAPON = 7;
- KEY_OPEN = 8;
- KEY_JUMP = 9;
- KEY_CHAT = 10;
+ KEY_OPEN = 6;
+ KEY_JUMP = 7;
+ KEY_CHAT = 8;
+
+ WP_PREV = 0;
+ WP_NEXT = 1;
+ WP_FACT = WP_PREV;
+ WP_LACT = WP_NEXT;
R_ITEM_BACKPACK = 0;
R_KEY_RED = 1;
R_ITEM_BACKPACK = 0;
R_KEY_RED = 1;
Kills: Word;
Color: TRGB;
Spectator: Boolean;
Kills: Word;
Color: TRGB;
Spectator: Boolean;
+ UID: Word;
end;
TPlayerStatArray = Array of TPlayerStat;
end;
TPlayerStatArray = Array of TPlayerStat;
FLastSpawnerUID: Word;
FLastHit: Byte;
FObj: TObj;
FLastSpawnerUID: Word;
FLastHit: Byte;
FObj: TObj;
+ FXTo, FYTo: Integer;
FSpectatePlayer: Integer;
FFirePainTime: Integer;
FFireAttacker: Word;
FSpectatePlayer: Integer;
FFirePainTime: Integer;
FFireAttacker: Word;
procedure doDamage (v: Integer);
procedure doDamage (v: Integer);
- function followCorpse(): Boolean;
+ function refreshCorpse(): Boolean;
public
FDamageBuffer: Integer;
public
FDamageBuffer: Integer;
FSpawnInvul: Integer;
FHandicap: Integer;
FWaitForFirstSpawn: Boolean; // set to `true` in server, used to spawn a player on first full state request
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;
// debug: viewport offset
viewPortX, viewPortY, viewPortW, viewPortH: Integer;
procedure BFGHit();
function GetFlag(Flag: Byte): Boolean;
procedure SetFlag(Flag: Byte);
procedure BFGHit();
function GetFlag(Flag: Byte): Boolean;
procedure SetFlag(Flag: Byte);
- function DropFlag(Silent: Boolean = True): Boolean;
+ function DropFlag(Silent: Boolean = True; DoThrow: Boolean = False): Boolean;
+ function TryDropFlag(): Boolean;
procedure AllRulez(Health: Boolean);
procedure RestoreHealthArmor();
procedure FragCombo();
procedure AllRulez(Health: Boolean);
procedure RestoreHealthArmor();
procedure FragCombo();
procedure LoadState (st: TStream); virtual;
procedure PauseSounds(Enable: Boolean);
procedure NetFire(Wpn: Byte; X, Y, AX, AY: Integer; WID: Integer = -1);
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 ProcessWeaponAction(Action: Byte);
procedure QueueWeaponSwitch(Weapon: Byte);
procedure RealizeCurrentWeapon();
procedure FlamerOn;
procedure QueueWeaponSwitch(Weapon: Byte);
procedure RealizeCurrentWeapon();
procedure FlamerOn;
procedure getMapBox (out x, y, w, h: Integer); inline;
procedure moveBy (dx, dy: Integer); inline;
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;
public
property Vel: TPoint2i read FObj.Vel;
property Obj: TObj read FObj;
public
constructor Create(X, Y: Integer; ModelName: String; aMess: Boolean);
destructor Destroy(); override;
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);
procedure Update();
procedure Draw();
procedure SaveState (st: TStream);
function g_Player_GetCount(): Byte;
function g_Player_GetStats(): TPlayerStatArray;
function g_Player_ValidName(Name: String): Boolean;
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();
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();
end;
function g_Player_CreateFromState (st: TStream): Word;
end;
function g_Player_CreateFromState (st: TStream): Word;
-var
- a, i: Integer;
- ok, Bot: Boolean;
- b: Byte;
+ var a: Integer; ok, Bot: Boolean; pos: Int64;
begin
begin
- result := 0;
- if (st = nil) then exit; //???
+ assert(st <> nil);
- // Ñèãíàòóðà èãðîêà
+ // check signature and entity type
+ pos := st.Position;
if not utils.checkSign(st, 'PLYR') then raise XStreamError.Create('invalid player signature');
if (utils.readByte(st) <> PLR_SAVE_VERSION) then raise XStreamError.Create('invalid player version');
if not utils.checkSign(st, 'PLYR') then raise XStreamError.Create('invalid player signature');
if (utils.readByte(st) <> PLR_SAVE_VERSION) then raise XStreamError.Create('invalid player version');
-
- // Áîò èëè ÷åëîâåê:
Bot := utils.readBool(st);
Bot := utils.readBool(st);
+ st.Position := pos;
+ // find free player slot
ok := false;
ok := false;
- a := 0;
-
- // Åñòü ëè ìåñòî â gPlayers:
- for a := 0 to High(gPlayers) do if (gPlayers[a] = nil) then begin ok := true; break; end;
+ for a := 0 to High(gPlayers) do
+ if gPlayers[a] = nil then
+ begin
+ ok := true;
+ break;
+ end;
- // Íåò ìåñòà - ðàñøèðÿåì gPlayers
+ // allocate player slot
if not ok then
begin
SetLength(gPlayers, Length(gPlayers)+1);
a := High(gPlayers);
end;
if not ok then
begin
SetLength(gPlayers, Length(gPlayers)+1);
a := High(gPlayers);
end;
- // Ñîçäàåì îáúåêò èãðîêà
+ // create entity and load state
if Bot then
gPlayers[a] := TBot.Create()
else
gPlayers[a] := TPlayer.Create();
if Bot then
gPlayers[a] := TBot.Create()
else
gPlayers[a] := TPlayer.Create();
- gPlayers[a].FIamBot := Bot;
- gPlayers[a].FPhysics := True;
-
- // UID èãðîêà
- gPlayers[a].FUID := utils.readWord(st);
- // Èìÿ èãðîêà
- gPlayers[a].FName := utils.readStr(st);
- // Êîìàíäà
- gPlayers[a].FTeam := utils.readByte(st);
- gPlayers[a].FPreferredTeam := gPlayers[a].FTeam;
- // Æèâ ëè
- gPlayers[a].FAlive := utils.readBool(st);
- // Èçðàñõîäîâàë ëè âñå æèçíè
- gPlayers[a].FNoRespawn := utils.readBool(st);
- // Íàïðàâëåíèå
- b := utils.readByte(st);
- if b = 1 then gPlayers[a].FDirection := TDirection.D_LEFT else gPlayers[a].FDirection := TDirection.D_RIGHT; // b = 2
- // Çäîðîâüå
- gPlayers[a].FHealth := utils.readLongInt(st);
- // Ôîðà
- gPlayers[a].FHandicap := utils.readLongInt(st);
- // Æèçíè
- gPlayers[a].FLives := utils.readByte(st);
- // Áðîíÿ
- gPlayers[a].FArmor := utils.readLongInt(st);
- // Çàïàñ âîçäóõà
- gPlayers[a].FAir := utils.readLongInt(st);
- // Çàïàñ ãîðþ÷åãî
- gPlayers[a].FJetFuel := utils.readLongInt(st);
- // Áîëü
- gPlayers[a].FPain := utils.readLongInt(st);
- // Óáèë
- gPlayers[a].FKills := utils.readLongInt(st);
- // Óáèë ìîíñòðîâ
- gPlayers[a].FMonsterKills := utils.readLongInt(st);
- // Ôðàãîâ
- gPlayers[a].FFrags := utils.readLongInt(st);
- // Ôðàãîâ ïîäðÿä
- gPlayers[a].FFragCombo := utils.readByte(st);
- // Âðåìÿ ïîñëåäíåãî ôðàãà
- gPlayers[a].FLastFrag := utils.readLongWord(st);
- // Ñìåðòåé
- gPlayers[a].FDeath := utils.readLongInt(st);
- // Êàêîé ôëàã íåñåò
- gPlayers[a].FFlag := utils.readByte(st);
- // Íàøåë ñåêðåòîâ
- gPlayers[a].FSecrets := utils.readLongInt(st);
- // Òåêóùåå îðóæèå
- gPlayers[a].FCurrWeap := utils.readByte(st);
- // Ñëåäóþùåå æåëàåìîå îðóæèå
- gPlayers[a].FNextWeap := utils.readWord(st);
- // ...è ïàóçà
- gPlayers[a].FNextWeapDelay := utils.readByte(st);
- // Âðåìÿ çàðÿäêè BFG
- gPlayers[a].FBFGFireCounter := utils.readSmallInt(st);
- // Áóôåð óðîíà
- gPlayers[a].FDamageBuffer := utils.readLongInt(st);
- // Ïîñëåäíèé óäàðèâøèé
- gPlayers[a].FLastSpawnerUID := utils.readWord(st);
- // Òèï ïîñëåäíåãî ïîëó÷åííîãî óðîíà
- gPlayers[a].FLastHit := utils.readByte(st);
- // Îáúåêò èãðîêà:
- Obj_LoadState(@gPlayers[a].FObj, st);
- // Òåêóùåå êîëè÷åñòâî ïàòðîíîâ
- for i := A_BULLETS to A_HIGH do gPlayers[a].FAmmo[i] := utils.readWord(st);
- // Ìàêñèìàëüíîå êîëè÷åñòâî ïàòðîíîâ
- for i := A_BULLETS to A_HIGH do gPlayers[a].FMaxAmmo[i] := utils.readWord(st);
- // Íàëè÷èå îðóæèÿ
- for i := WP_FIRST to WP_LAST do gPlayers[a].FWeapon[i] := utils.readBool(st);
- // Âðåìÿ ïåðåçàðÿäêè îðóæèÿ
- for i := WP_FIRST to WP_LAST do gPlayers[a].FReloading[i] := utils.readWord(st);
- // Íàëè÷èå ðþêçàêà
- if utils.readBool(st) then Include(gPlayers[a].FRulez, R_ITEM_BACKPACK);
- // Íàëè÷èå êðàñíîãî êëþ÷à
- if utils.readBool(st) then Include(gPlayers[a].FRulez, R_KEY_RED);
- // Íàëè÷èå çåëåíîãî êëþ÷à
- if utils.readBool(st) then Include(gPlayers[a].FRulez, R_KEY_GREEN);
- // Íàëè÷èå ñèíåãî êëþ÷à
- if utils.readBool(st) then Include(gPlayers[a].FRulez, R_KEY_BLUE);
- // Íàëè÷èå áåðñåðêà
- if utils.readBool(st) then Include(gPlayers[a].FRulez, R_BERSERK);
- // Âðåìÿ äåéñòâèÿ ñïåöèàëüíûõ ïðåäìåòîâ
- for i := MR_SUIT to MR_MAX do gPlayers[a].FMegaRulez[i] := utils.readLongWord(st);
- // Âðåìÿ äî ïîâòîðíîãî ðåñïàóíà, ñìåíû îðóæèÿ, èñîëüçîâàíèÿ, çàõâàòà ôëàãà
- for i := T_RESPAWN to T_FLAGCAP do gPlayers[a].FTime[i] := utils.readLongWord(st);
-
- // Íàçâàíèå ìîäåëè:
- gPlayers[a].FActualModelName := utils.readStr(st);
- // Öâåò ìîäåëè
- gPlayers[a].FColor.R := utils.readByte(st);
- gPlayers[a].FColor.G := utils.readByte(st);
- gPlayers[a].FColor.B := utils.readByte(st);
- // Îáíîâëÿåì ìîäåëü èãðîêà
- gPlayers[a].SetModel(gPlayers[a].FActualModelName);
-
- // Íåò ìîäåëè - ñîçäàíèå íåâîçìîæíî
- if (gPlayers[a].FModel = nil) then
- begin
- gPlayers[a].Free();
- gPlayers[a] := nil;
- g_FatalError(Format(_lc[I_GAME_ERROR_MODEL], [gPlayers[a].FActualModelName]));
- exit;
- end;
-
- // Åñëè êîìàíäíàÿ èãðà - êðàñèì ìîäåëü â öâåò êîìàíäû
- if gGameSettings.GameMode in [GM_TDM, GM_CTF] then
- gPlayers[a].FModel.Color := TEAMCOLOR[gPlayers[a].FTeam]
- else
- gPlayers[a].FModel.Color := gPlayers[a].FColor;
+ gPlayers[a].FPhysics := True; // ???
+ gPlayers[a].LoadState(st);
result := gPlayers[a].FUID;
end;
result := gPlayers[a].FUID;
end;
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 * 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();
end;
procedure g_Player_DrawHealth();
Color := gPlayers[a].FModel.Color;
Lives := gPlayers[a].FLives;
Spectator := gPlayers[a].FSpectator;
Color := gPlayers[a].FModel.Color;
Lives := gPlayers[a].FLives;
Spectator := gPlayers[a].FSpectator;
+ UID := gPlayers[a].FUID;
end;
end;
end;
end;
end;
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
var
i: Integer;
find_id: DWORD;
ok: Boolean;
begin
+ Result := -1;
+
if Player.alive then
Exit;
// Ðàçðûâàåì ñâÿçü ñ ïðåæíèì òðóïîì:
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;
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;
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,
end
else
g_Player_CreateGibs(FObj.X + PLAYER_RECT_CX,
FFirePainTime := 0;
FFireAttacker := 0;
FHandicap := 100;
FFirePainTime := 0;
FFireAttacker := 0;
FHandicap := 100;
+ FCorpse := -1;
FActualModelName := 'doomer';
FActualModelName := 'doomer';
Rb, Gb, Bb,
Rw, Gw, Bw: SmallInt;
Dot: Byte;
Rb, Gb, Bb,
Rw, Gw, Bw: SmallInt;
Dot: Byte;
+ CObj: TObj;
begin
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;
bubX := fX+FObj.Rect.X + IfThen(FDirection = TDirection.D_LEFT, -4, 18);
bubY := fY+FObj.Rect.Y - 18;
Rb := 64;
DropFlag(KillType = K_FALLKILL);
end;
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
if Srv and (gGameSettings.MaxLives > 0) and FNoRespawn and
(gLMSRespawn = LMS_RESPAWN_NONE) then
FModel.Blood.R, FModel.Blood.G, FModel.Blood.B, FModel.Blood.Kind);
end;
FModel.Blood.R, FModel.Blood.G, FModel.Blood.B, FModel.Blood.Kind);
end;
+procedure TPlayer.ProcessWeaponAction(Action: Byte);
+begin
+ if g_Game_IsClient then Exit;
+ case Action of
+ WP_PREV: PrevWeapon();
+ WP_NEXT: NextWeapon();
+ end;
+end;
+
procedure TPlayer.QueueWeaponSwitch(Weapon: Byte);
begin
if g_Game_IsClient then Exit;
procedure TPlayer.QueueWeaponSwitch(Weapon: Byte);
begin
if g_Game_IsClient then Exit;
@@ -3952,6 +3877,8 @@ function TPlayer.PickItem(ItemType: Byte; arespawn: Boolean; var remove: Boolean
var
a: Boolean;
var
a: Boolean;
+ switchWeapon: Byte;
+ hadWeapon: Boolean;
begin
Result := False;
if g_Game_IsClient then Exit;
begin
Result := False;
if g_Game_IsClient then Exit;
// a = true - ìåñòî ñïàâíà ïðåäìåòà:
a := LongBool(gGameSettings.Options and GAME_OPTION_WEAPONSTAY) and arespawn;
remove := not a;
// a = true - ìåñòî ñïàâíà ïðåäìåòà:
a := LongBool(gGameSettings.Options and GAME_OPTION_WEAPONSTAY) and arespawn;
remove := not a;
-
case ItemType of
ITEM_MEDKIT_SMALL:
if (FHealth < PLAYER_HP_SOFT) or (FFireTime > 0) then
case ItemType of
ITEM_MEDKIT_SMALL:
if (FHealth < PLAYER_HP_SOFT) or (FFireTime > 0) then
ITEM_WEAPON_SAW:
if (not FWeapon[WEAPON_SAW]) or ((not arespawn) and (gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF])) then
begin
ITEM_WEAPON_SAW:
if (not FWeapon[WEAPON_SAW]) or ((not arespawn) and (gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF])) then
begin
+ hadWeapon := FWeapon[WEAPON_SAW];
+ switchWeapon := WEAPON_SAW;
FWeapon[WEAPON_SAW] := True;
Result := True;
if gFlash = 2 then Inc(FPickup, 5);
FWeapon[WEAPON_SAW] := True;
Result := True;
if gFlash = 2 then Inc(FPickup, 5);
begin
// Íóæíî, ÷òîáû íå âçÿòü âñå ïóëè ñðàçó:
if a and FWeapon[WEAPON_SHOTGUN1] then Exit;
begin
// Íóæíî, ÷òîáû íå âçÿòü âñå ïóëè ñðàçó:
if a and FWeapon[WEAPON_SHOTGUN1] then Exit;
-
+ hadWeapon := FWeapon[WEAPON_SHOTGUN1];
+ switchWeapon := WEAPON_SHOTGUN1;
IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
FWeapon[WEAPON_SHOTGUN1] := True;
Result := True;
IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
FWeapon[WEAPON_SHOTGUN1] := True;
Result := True;
if (FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS]) or not FWeapon[WEAPON_SHOTGUN2] then
begin
if a and FWeapon[WEAPON_SHOTGUN2] then Exit;
if (FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS]) or not FWeapon[WEAPON_SHOTGUN2] then
begin
if a and FWeapon[WEAPON_SHOTGUN2] then Exit;
-
+ hadWeapon := FWeapon[WEAPON_SHOTGUN2];
+ switchWeapon := WEAPON_SHOTGUN2;
IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
FWeapon[WEAPON_SHOTGUN2] := True;
Result := True;
IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
FWeapon[WEAPON_SHOTGUN2] := True;
Result := True;
if (FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS]) or not FWeapon[WEAPON_CHAINGUN] then
begin
if a and FWeapon[WEAPON_CHAINGUN] then Exit;
if (FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS]) or not FWeapon[WEAPON_CHAINGUN] then
begin
if a and FWeapon[WEAPON_CHAINGUN] then Exit;
-
+ hadWeapon := FWeapon[WEAPON_CHAINGUN];
+ switchWeapon := WEAPON_CHAINGUN;
IncMax(FAmmo[A_BULLETS], 50, FMaxAmmo[A_BULLETS]);
FWeapon[WEAPON_CHAINGUN] := True;
Result := True;
IncMax(FAmmo[A_BULLETS], 50, FMaxAmmo[A_BULLETS]);
FWeapon[WEAPON_CHAINGUN] := True;
Result := True;
if (FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS]) or not FWeapon[WEAPON_ROCKETLAUNCHER] then
begin
if a and FWeapon[WEAPON_ROCKETLAUNCHER] then Exit;
if (FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS]) or not FWeapon[WEAPON_ROCKETLAUNCHER] then
begin
if a and FWeapon[WEAPON_ROCKETLAUNCHER] then Exit;
-
+ switchWeapon := WEAPON_ROCKETLAUNCHER;
+ hadWeapon := FWeapon[WEAPON_ROCKETLAUNCHER];
IncMax(FAmmo[A_ROCKETS], 2, FMaxAmmo[A_ROCKETS]);
FWeapon[WEAPON_ROCKETLAUNCHER] := True;
Result := True;
IncMax(FAmmo[A_ROCKETS], 2, FMaxAmmo[A_ROCKETS]);
FWeapon[WEAPON_ROCKETLAUNCHER] := True;
Result := True;
if (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) or not FWeapon[WEAPON_PLASMA] then
begin
if a and FWeapon[WEAPON_PLASMA] then Exit;
if (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) or not FWeapon[WEAPON_PLASMA] then
begin
if a and FWeapon[WEAPON_PLASMA] then Exit;
-
+ switchWeapon := WEAPON_PLASMA;
+ hadWeapon := FWeapon[WEAPON_PLASMA];
IncMax(FAmmo[A_CELLS], 40, FMaxAmmo[A_CELLS]);
FWeapon[WEAPON_PLASMA] := True;
Result := True;
IncMax(FAmmo[A_CELLS], 40, FMaxAmmo[A_CELLS]);
FWeapon[WEAPON_PLASMA] := True;
Result := True;
if (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) or not FWeapon[WEAPON_BFG] then
begin
if a and FWeapon[WEAPON_BFG] then Exit;
if (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) or not FWeapon[WEAPON_BFG] then
begin
if a and FWeapon[WEAPON_BFG] then Exit;
-
+ switchWeapon := WEAPON_BFG;
+ hadWeapon := FWeapon[WEAPON_BFG];
IncMax(FAmmo[A_CELLS], 40, FMaxAmmo[A_CELLS]);
FWeapon[WEAPON_BFG] := True;
Result := True;
IncMax(FAmmo[A_CELLS], 40, FMaxAmmo[A_CELLS]);
FWeapon[WEAPON_BFG] := True;
Result := True;
if (FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS]) or not FWeapon[WEAPON_SUPERPULEMET] then
begin
if a and FWeapon[WEAPON_SUPERPULEMET] then Exit;
if (FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS]) or not FWeapon[WEAPON_SUPERPULEMET] then
begin
if a and FWeapon[WEAPON_SUPERPULEMET] then Exit;
-
+ switchWeapon := WEAPON_SUPERPULEMET;
+ hadWeapon := FWeapon[WEAPON_SUPERPULEMET];
IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
FWeapon[WEAPON_SUPERPULEMET] := True;
Result := True;
IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
FWeapon[WEAPON_SUPERPULEMET] := True;
Result := True;
if (FAmmo[A_FUEL] < FMaxAmmo[A_FUEL]) or not FWeapon[WEAPON_FLAMETHROWER] then
begin
if a and FWeapon[WEAPON_FLAMETHROWER] then Exit;
if (FAmmo[A_FUEL] < FMaxAmmo[A_FUEL]) or not FWeapon[WEAPON_FLAMETHROWER] then
begin
if a and FWeapon[WEAPON_FLAMETHROWER] then Exit;
-
+ switchWeapon := WEAPON_FLAMETHROWER;
+ hadWeapon := FWeapon[WEAPON_FLAMETHROWER];
IncMax(FAmmo[A_FUEL], 100, FMaxAmmo[A_FUEL]);
FWeapon[WEAPON_FLAMETHROWER] := True;
Result := True;
IncMax(FAmmo[A_FUEL], 100, FMaxAmmo[A_FUEL]);
FWeapon[WEAPON_FLAMETHROWER] := True;
Result := True;
if not (R_BERSERK in FRulez) then
begin
Include(FRulez, R_BERSERK);
if not (R_BERSERK in FRulez) then
begin
Include(FRulez, R_BERSERK);
+ (*
if allowBerserkSwitching then
begin
FCurrWeap := WEAPON_KASTET;
resetWeaponQueue();
FModel.SetWeapon(WEAPON_KASTET);
if allowBerserkSwitching then
begin
FCurrWeap := WEAPON_KASTET;
resetWeaponQueue();
FModel.SetWeapon(WEAPON_KASTET);
+ end; *)
+ if ( (g_Game_IsNet = False) or (NetMode = NET_SERVER) ) and ( ( (Self = gPlayer1) and (gPlayer1Settings.WeaponSwitch <> 0) ) or ( (gPlayer2 <> nil) and (Self = gPlayer2) and (gPlayer2Settings.WeaponSwitch <> 0) )) then
+ begin
+ if (Self = gPlayer1) then
+ begin
+ if (gPlayer1Settings.WeaponSwitch = 1) or ( (gPlayer1Settings.WeaponSwitch = 2) and (gPlayer1Settings.WeaponPreferences[WP_LAST+1] > gPlayer1Settings.WeaponPreferences[FCurrWeap]) ) then
+ begin
+ FCurrWeap := WEAPON_KASTET;
+ resetWeaponQueue();
+ FModel.SetWeapon(WEAPON_KASTET);
+ end;
+ end
+ else
+ begin
+ if (gPlayer2Settings.WeaponSwitch = 1) or ( (gPlayer2Settings.WeaponSwitch = 2) and (gPlayer2Settings.WeaponPreferences[WP_LAST+1] > gPlayer2Settings.WeaponPreferences[FCurrWeap]) ) then
+ begin
+ FCurrWeap := WEAPON_KASTET;
+ resetWeaponQueue();
+ FModel.SetWeapon(WEAPON_KASTET);
+ end;
+ end;
end;
if gFlash <> 0 then
begin
end;
if gFlash <> 0 then
begin
if gFlash = 2 then Inc(FPickup, 5);
end;
end;
if gFlash = 2 then Inc(FPickup, 5);
end;
end;
+ if ( (g_Game_IsNet = False) or (NetMode = NET_SERVER) ) and ( ( (Self = gPlayer1) and (gPlayer1Settings.WeaponSwitch <> 0) ) or ( (gPlayer2 <> nil) and (Self = gPlayer2) and (gPlayer2Settings.WeaponSwitch <> 0) )) then
+ begin
+ if (hadWeapon = False) then
+ begin
+ if (Self = gPlayer1) and ( (gPlayer1Settings.WeaponSwitch = 1) or ( (gPlayer1Settings.WeaponSwitch = 2)
+ and (gPlayer1Settings.WeaponPreferences[switchWeapon] > gPlayer1Settings.WeaponPreferences[FCurrWeap]) ) ) then
+ begin
+ FCurrWeap := switchWeapon;
+ resetWeaponQueue();
+ FModel.SetWeapon(switchWeapon);
+ end
+ else if (Self = gPlayer2) and ( (gPlayer2Settings.WeaponSwitch = 1) or ( (gPlayer2Settings.WeaponSwitch = 2)
+ and (gPlayer2Settings.WeaponPreferences[switchWeapon] > gPlayer2Settings.WeaponPreferences[FCurrWeap]) ) ) then
+ begin
+ FCurrWeap := switchWeapon;
+ resetWeaponQueue();
+ FModel.SetWeapon(switchWeapon);
+ end;
+ end;
+ end;
end;
procedure TPlayer.Touch();
end;
procedure TPlayer.Touch();
FDeath := 0;
FSecrets := 0;
FSpawnInvul := 0;
FDeath := 0;
FSecrets := 0;
FSpawnInvul := 0;
+ FCorpse := -1;
FReady := False;
if FNoRespawn then
begin
FReady := False;
if FNoRespawn then
begin
// Îäèíî÷íàÿ èãðà/êîîïåðàòèâ
if gGameSettings.GameMode in [GM_COOP, GM_SINGLE] then
begin
// Îäèíî÷íàÿ èãðà/êîîïåðàòèâ
if gGameSettings.GameMode in [GM_COOP, GM_SINGLE] then
begin
- if (Self = gPlayer1) or (Self = gPlayer2) then
+ if Self = gPlayer1 then
begin
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
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
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
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
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
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_DM;
if FTeam = TEAM_RED then
+ c := RESPAWNPOINT_RED
+ else if FTeam = TEAM_BLUE then
c := RESPAWNPOINT_BLUE;
c := RESPAWNPOINT_BLUE;
- if FTeam = TEAM_BLUE then
- c := RESPAWNPOINT_RED;
if g_Map_GetPointCount(c) > 0 then
if g_Map_GetPointCount(c) > 0 then
- begin
- Result := c;
- Exit;
- end;
+ Exit(c);
end;
end;
+
+ // still haven't found a spawnpoint, try random shit
+ Result := g_Map_GetRandomPointType();
end;
procedure TPlayer.Respawn(Silent: Boolean; Force: Boolean = False);
end;
procedure TPlayer.Respawn(Silent: Boolean; Force: Boolean = False);
FPain := 0;
FLastHit := 0;
FSpawnInvul := 0;
FPain := 0;
FLastHit := 0;
FSpawnInvul := 0;
+ FCorpse := -1;
if not g_Game_IsServer then
Exit;
if not g_Game_IsServer then
Exit;
GameX := gMapInfo.Width div 2;
GameY := gMapInfo.Height div 2;
end;
GameX := gMapInfo.Width div 2;
GameY := gMapInfo.Height div 2;
end;
+ FXTo := GameX;
+ FYTo := GameY;
FAlive := False;
FSpectator := True;
FAlive := False;
FSpectator := True;
FPhysics := False;
FWantsInGame := False;
FSpawned := False;
FPhysics := False;
FWantsInGame := False;
FSpawned := False;
+ FCorpse := -1;
if FNoRespawn then
begin
if FNoRespawn then
begin
Exit;
FGhost := not FGhost;
FPhysics := not FGhost;
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;
begin
FObj.Accel.X := 0;
FObj.Accel.Y := 0;
FObj.Y := Y-PLAYER_RECT.Y;
FObj.oldX := FObj.X; // don't interpolate after respawn
FObj.oldY := FObj.Y;
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
if not g_Game_IsNet then
begin
Result := 1;
end;
Result := 1;
end;
-function TPlayer.followCorpse(): Boolean;
+function TPlayer.refreshCorpse(): Boolean;
var
i: Integer;
begin
Result := False;
var
i: Integer;
begin
Result := False;
+ FCorpse := -1;
if FAlive or FSpectator then
Exit;
if (gCorpses = nil) or (Length(gCorpses) = 0) then
if FAlive or FSpectator then
Exit;
if (gCorpses = nil) or (Length(gCorpses) = 0) then
if gCorpses[i].FPlayerUID = FUID then
begin
Result := True;
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;
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;
procedure TPlayer.PreUpdate();
begin
FSlopeOld := FObj.slopeUpLeft;
NetServer := g_Game_IsNet and g_Game_IsServer;
AnyServer := g_Game_IsServer;
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 NetServer then
- if FClientID >= 0 then
+ if (FClientID >= 0) and (NetClients[FClientID].Peer <> nil) then
begin
FPing := NetClients[FClientID].Peer^.lastRoundTripTime;
if NetClients[FClientID].Peer^.packetsSent > 0 then
begin
FPing := NetClients[FClientID].Peer^.lastRoundTripTime;
if NetClients[FClientID].Peer^.packetsSent > 0 then
FIncCam := FIncCam*i;
end;
FIncCam := FIncCam*i;
end;
- // no need to do that each second frame, weapon queue will take care of it
- if FAlive and FKeys[KEY_NEXTWEAPON].Pressed and AnyServer then NextWeapon();
- if FAlive and FKeys[KEY_PREVWEAPON].Pressed and AnyServer then PrevWeapon();
-
if gTime mod (GAME_TICK*2) <> 0 then
begin
if (FObj.Vel.X = 0) and FAlive then
if gTime mod (GAME_TICK*2) <> 0 then
begin
if (FObj.Vel.X = 0) and FAlive then
if FPhysics then
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;
positionChanged(); // this updates spatial accelerators
end;
// Let alive player do some actions
if FKeys[KEY_LEFT].Pressed then Run(TDirection.D_LEFT);
if FKeys[KEY_RIGHT].Pressed then Run(TDirection.D_RIGHT);
// Let alive player do some actions
if FKeys[KEY_LEFT].Pressed then Run(TDirection.D_LEFT);
if FKeys[KEY_RIGHT].Pressed then Run(TDirection.D_RIGHT);
- //if FKeys[KEY_NEXTWEAPON].Pressed and AnyServer then NextWeapon();
- //if FKeys[KEY_PREVWEAPON].Pressed and AnyServer then PrevWeapon();
if FKeys[KEY_FIRE].Pressed and AnyServer then Fire()
else
begin
if FKeys[KEY_FIRE].Pressed and AnyServer then Fire()
else
begin
begin
if FKeys[KEY_UP].Pressed or FKeys[KEY_JUMP].Pressed then
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
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
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
FSpectatePlayer := -1;
end;
if FKeys[KEY_RIGHT].Pressed then
begin
- FObj.X := FObj.X + 32;
+ FXTo := FObj.X + 32;
FSpectatePlayer := -1;
end;
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
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
positionChanged(); // this updates spatial accelerators
end
else
if gPlayers[FSpectatePlayer] <> nil then
if gPlayers[FSpectatePlayer].alive then
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;
end;
end;
else if (FAngle = ANGLE_LEFTUP) or (FAngle = ANGLE_RIGHTUP) then SetAction(A_ATTACKUP);
end;
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 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
+ 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,
function TPlayer.FullInLift(XInc, YInc: Integer): Integer;
begin
if g_Map_CollidePanel(FObj.X+PLAYER_RECT.X+XInc, FObj.Y+PLAYER_RECT.Y+YInc,
FModel.SetFlag(FFlag);
end;
FModel.SetFlag(FFlag);
end;
-function TPlayer.DropFlag(Silent: Boolean = True): Boolean;
+function TPlayer.TryDropFlag(): Boolean;
+begin
+ if LongBool(gGameSettings.Options and GAME_OPTION_ALLOWDROPFLAG) then
+ Result := DropFlag(False, LongBool(gGameSettings.Options and GAME_OPTION_THROWFLAG))
+ else
+ Result := False;
+end;
+
+function TPlayer.DropFlag(Silent: Boolean = True; DoThrow: Boolean = False): Boolean;
var
s: String;
a: Byte;
var
s: String;
a: Byte;
+ xv, yv: Integer;
begin
Result := False;
if (not g_Game_IsServer) or (FFlag = FLAG_NONE) then
begin
Result := False;
if (not g_Game_IsServer) or (FFlag = FLAG_NONE) then
Direction := FDirection;
State := FLAG_STATE_DROPPED;
Count := FLAG_TIME;
Direction := FDirection;
State := FLAG_STATE_DROPPED;
Count := FLAG_TIME;
- g_Obj_Push(@Obj, (FObj.Vel.X div 2)-2+Random(5),
- (FObj.Vel.Y div 2)-2+Random(5));
+ if DoThrow then
+ begin
+ xv := FObj.Vel.X + IfThen(Direction = TDirection.D_RIGHT, 10, -10);
+ yv := FObj.Vel.Y - 2;
+ end
+ else
+ begin
+ xv := (FObj.Vel.X div 2);
+ yv := (FObj.Vel.Y div 2) - 2;
+ end;
+ g_Obj_Push(@Obj, xv, yv);
+
positionChanged(); // this updates spatial accelerators
if FFlag = FLAG_RED then
positionChanged(); // this updates spatial accelerators
if FFlag = FLAG_RED then
end;
end;
-procedure TCorpse.Damage(Value: Word; vx, vy: Integer);
+procedure TCorpse.Damage(Value: Word; SpawnerUID: Word; vx, vy: Integer);
var
pm: TPlayerModel;
Blood: TModelBlood;
var
pm: TPlayerModel;
Blood: TModelBlood;
if (gBodyKillEvent <> -1)
and gDelayedEvents[gBodyKillEvent].Pending then
gDelayedEvents[gBodyKillEvent].Pending := False;
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;
end
else