diff --git a/src/game/g_player.pas b/src/game/g_player.pas
index caddc0d9e7612dfa230b9676b010a95373bb6cbb..1ec0ccd237bc56c85df03b3d26c9d286fe1131d5 100644 (file)
--- a/src/game/g_player.pas
+++ b/src/game/g_player.pas
A_SHELLS = 1;
A_ROCKETS = 2;
A_CELLS = 3;
+ A_HIGH = 3;
K_SIMPLEKILL = 0;
K_HARDKILL = 1;
Air: Integer;
JetFuel: Integer;
CurrWeap: Byte;
- Ammo: Array [A_BULLETS..A_CELLS] of Word;
- MaxAmmo: Array [A_BULLETS..A_CELLS] of Word;
- Weapon: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Boolean;
+ NextWeap: WORD;
+ NextWeapDelay: Byte;
+ Ammo: Array [A_BULLETS..A_HIGH] of Word;
+ 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;
end;
FFlag: Byte;
FSecrets: Integer;
FCurrWeap: Byte;
+ FNextWeap: WORD;
+ FNextWeapDelay: Byte; // frames
FBFGFireCounter: SmallInt;
FLastSpawnerUID: Word;
FLastHit: Byte;
procedure Jump();
procedure Use();
+ function getNextWeaponIndex (): Byte; // return 255 for "no switch"
+ procedure resetWeaponQueue ();
+ function hasAmmoForWeapon (weapon: Byte): Boolean;
+
public
FDamageBuffer: Integer;
- FAmmo: Array [A_BULLETS..A_CELLS] of Word;
- FMaxAmmo: Array [A_BULLETS..A_CELLS] of Word;
- FWeapon: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Boolean;
+ FAmmo: Array [A_BULLETS..A_HIGH] of Word;
+ FMaxAmmo: Array [A_BULLETS..A_HIGH] of Word;
+ FWeapon: Array [WP_FIRST..WP_LAST] of Boolean;
FRulez: Set of R_ITEM_BACKPACK..R_BERSERK;
FBerserk: Integer;
FMegaRulez: Array [MR_SUIT..MR_MAX] of DWORD;
- FReloading: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Word;
+ FReloading: Array [WP_FIRST..WP_LAST] of Word;
FTime: Array [T_RESPAWN..T_FLAGCAP] of DWORD;
FKeys: Array [KEY_LEFT..KEY_CHAT] of TKeyState;
FColor: TRGB;
procedure NetFire(Wpn: Byte; X, Y, AX, AY: Integer; WID: Integer = -1);
procedure DoLerp(Level: Integer = 2);
procedure SetLerp(XTo, YTo: Integer);
- procedure ForceWeapon(Weapon: Byte);
+ procedure QueueWeaponSwitch(Weapon: Byte);
+ procedure RealizeCurrentWeapon();
procedure JetpackOn;
procedure JetpackOff;
FlyPrecision: Byte;
Cover: Byte;
CloseJump: Byte;
- WeaponPrior: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Byte;
- CloseWeaponPrior: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Byte;
- //SafeWeaponPrior: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Byte;
+ WeaponPrior: Array [WP_FIRST..WP_LAST] of Byte;
+ CloseWeaponPrior: Array [WP_FIRST..WP_LAST] of Byte;
+ //SafeWeaponPrior: Array [WP_FIRST..WP_LAST] of Byte;
end;
TAIFlag = record
fly_precision: Byte;
cover: Byte;
close_jump: Byte;
- w_prior1: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Byte;
- w_prior2: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Byte;
- w_prior3: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Byte;
+ w_prior1: Array [WP_FIRST..WP_LAST] of Byte;
+ w_prior2: Array [WP_FIRST..WP_LAST] of Byte;
+ w_prior3: Array [WP_FIRST..WP_LAST] of Byte;
end;
const
DIFFICULT_HARD: TDifficult = (DiagFire: 255; InvisFire: 255; DiagPrecision: 255;
FlyPrecision: 255; Cover: 255; CloseJump: 255;
WeaponPrior:(0,0,0,0,0,0,0,0,0,0); CloseWeaponPrior:(0,0,0,0,0,0,0,0,0,0));
- WEAPON_PRIOR1: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Byte =
+ WEAPON_PRIOR1: Array [WP_FIRST..WP_LAST] of Byte =
(WEAPON_SUPERPULEMET, WEAPON_SHOTGUN2, WEAPON_SHOTGUN1,
WEAPON_CHAINGUN, WEAPON_PLASMA, WEAPON_ROCKETLAUNCHER,
WEAPON_BFG, WEAPON_PISTOL, WEAPON_SAW, WEAPON_KASTET);
- WEAPON_PRIOR2: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Byte =
+ WEAPON_PRIOR2: Array [WP_FIRST..WP_LAST] of Byte =
(WEAPON_SUPERPULEMET, WEAPON_BFG, WEAPON_ROCKETLAUNCHER,
WEAPON_SHOTGUN2, WEAPON_PLASMA, WEAPON_SHOTGUN1,
WEAPON_CHAINGUN, WEAPON_PISTOL, WEAPON_SAW, WEAPON_KASTET);
- //WEAPON_PRIOR3: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Byte =
+ //WEAPON_PRIOR3: Array [WP_FIRST..WP_LAST] of Byte =
// (WEAPON_SUPERPULEMET, WEAPON_BFG, WEAPON_PLASMA,
// WEAPON_SHOTGUN2, WEAPON_CHAINGUN, WEAPON_SHOTGUN1,
// WEAPON_SAW, WEAPON_ROCKETLAUNCHER, WEAPON_PISTOL, WEAPON_KASTET);
- WEAPON_RELOAD: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Byte =
+ WEAPON_RELOAD: Array [WP_FIRST..WP_LAST] of Byte =
(5, 2, 6, 18, 36, 2, 12, 2, 14, 2);
PLAYER_SIGNATURE = $52594C50; // 'PLYR'
Mem.ReadInt(gPlayers[a].FSecrets);
// Òåêóùåå îðóæèå:
Mem.ReadByte(gPlayers[a].FCurrWeap);
+// Ñëåäóþùåå æåëàåìîå îðóæèå:
+ Mem.ReadWord(gPlayers[a].FNextWeap);
+// ...è ïàóçà:
+ Mem.ReadByte(gPlayers[a].FNextWeapDelay);
// Âðåìÿ çàðÿäêè BFG:
Mem.ReadSmallInt(gPlayers[a].FBFGFireCounter);
// Áóôåð óðîíà:
// Îáúåêò èãðîêà:
Obj_LoadState(@gPlayers[a].FObj, Mem);
// Òåêóùåå êîëè÷åñòâî ïàòðîíîâ:
- for i := A_BULLETS to A_CELLS do
+ for i := A_BULLETS to A_HIGH do
Mem.ReadWord(gPlayers[a].FAmmo[i]);
// Ìàêñèìàëüíîå êîëè÷åñòâî ïàòðîíîâ:
- for i := A_BULLETS to A_CELLS do
+ for i := A_BULLETS to A_HIGH do
Mem.ReadWord(gPlayers[a].FMaxAmmo[i]);
// Íàëè÷èå îðóæèÿ:
- for i := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for i := WP_FIRST to WP_LAST do
Mem.ReadBoolean(gPlayers[a].FWeapon[i]);
// Âðåìÿ ïåðåçàðÿäêè îðóæèÿ:
- for i := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for i := WP_FIRST to WP_LAST do
Mem.ReadWord(gPlayers[a].FReloading[i]);
// Íàëè÷èå ðþêçàêà:
Mem.ReadByte(b);
else FDifficult := DIFFICULT_HARD;
end;
- for a := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for a := WP_FIRST to WP_LAST do
begin
FDifficult.WeaponPrior[a] := WEAPON_PRIOR1[a];
FDifficult.CloseWeaponPrior[a] := WEAPON_PRIOR2[a];
FDifficult.Cover := BotList[num].cover;
FDifficult.CloseJump := BotList[num].close_jump;
- for a := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for a := WP_FIRST to WP_LAST do
begin
FDifficult.WeaponPrior[a] := BotList[num].w_prior1[a];
FDifficult.CloseWeaponPrior[a] := BotList[num].w_prior2[a];
begin
if gPlayers = nil then Exit;
+ //e_WriteLog('***g_Player_UpdateAll: ENTER', MSG_WARNING);
for i := 0 to High(gPlayers) do
+ begin
if gPlayers[i] <> nil then
- if gPlayers[i] is TPlayer then gPlayers[i].Update()
- else TBot(gPlayers[i]).Update();
+ begin
+ if gPlayers[i] is TPlayer then
+ begin
+ gPlayers[i].Update();
+ gPlayers[i].RealizeCurrentWeapon(); // WARNING! DO NOT MOVE THIS INTO `Update()`!
+ end
+ else
+ begin
+ // bot updates weapons in `UpdateCombat()`
+ TBot(gPlayers[i]).Update();
+ end;
+ end;
+ end;
+ //e_WriteLog('***g_Player_UpdateAll: EXIT', MSG_WARNING);
end;
procedure g_Player_DrawAll();
FBFGFireCounter := -1;
FJustTeleported := False;
FNetTime := 0;
+
+ resetWeaponQueue();
end;
procedure TPlayer.Damage(value: Word; SpawnerUID: Word; vx, vy: Integer; t: Byte);
if Srv then
begin
// Âûáðîñ îðóæèÿ:
- for a := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for a := WP_FIRST to WP_LAST do
if FWeapon[a] then
begin
case a of
150, 0, 0);
end;
-procedure TPlayer.ForceWeapon(Weapon: Byte);
-var
- i: Byte;
+procedure TPlayer.QueueWeaponSwitch(Weapon: Byte);
begin
if g_Game_IsClient then Exit;
if Weapon > High(FWeapon) then Exit;
- if FBFGFireCounter <> -1 then Exit;
-
- if FTime[T_SWITCH] > gTime then Exit;
+ FNextWeap := FNextWeap or (1 shl Weapon);
+end;
- for i := WEAPON_KASTET to WEAPON_SUPERPULEMET do
- if FReloading[i] > 0 then Exit;
+procedure TPlayer.resetWeaponQueue ();
+begin
+ FNextWeap := 0;
+ FNextWeapDelay := 0;
+end;
- if FWeapon[Weapon] then
- begin
- FCurrWeap := Weapon;
- FTime[T_SWITCH] := gTime+156;
- if FCurrWeap = WEAPON_SAW then
- FSawSoundSelect.PlayAt(FObj.X, FObj.Y);
- FModel.SetWeapon(FCurrWeap);
- if g_Game_IsNet then MH_SEND_PlayerStats(FUID);
+function TPlayer.hasAmmoForWeapon (weapon: Byte): Boolean;
+begin
+ result := false;
+ case weapon of
+ WEAPON_KASTET, WEAPON_SAW: result := true;
+ WEAPON_SHOTGUN1, WEAPON_SHOTGUN2: result := (FAmmo[A_SHELLS] > 0);
+ WEAPON_PISTOL, WEAPON_CHAINGUN, WEAPON_SUPERPULEMET: result := (FAmmo[A_BULLETS] > 0);
+ WEAPON_ROCKETLAUNCHER: result := (FAmmo[A_ROCKETS] > 0);
+ WEAPON_PLASMA, WEAPON_BFG: result := (FAmmo[A_CELLS] > 0);
+ else result := (weapon < length(FWeapon));
end;
end;
-procedure TPlayer.NextWeapon();
+// return 255 for "no switch"
+function TPlayer.getNextWeaponIndex (): Byte;
var
- i: Byte;
- ok: Boolean;
-begin
- if g_Game_IsClient then Exit;
- if FBFGFireCounter <> -1 then Exit;
-
- if FTime[T_SWITCH] > gTime then Exit;
-
- for i := WEAPON_KASTET to WEAPON_SUPERPULEMET do
- if FReloading[i] > 0 then Exit;
-
- ok := False;
-
- for i := FCurrWeap+1 to WEAPON_SUPERPULEMET do
- if FWeapon[i] then
+ i: Word;
+ wantThisWeapon: array[0..64] of Boolean;
+ wwc: Integer = 0; //HACK!
+ dir, cwi: Integer;
+begin
+ result := 255; // default result: "no switch"
+ // had weapon cycling on previous frame? remove that flag
+ if (FNextWeap and $2000) <> 0 then begin FNextWeap := FNextWeap and $1FFF; FNextWeapDelay := 0; end;
+ // cycling has priority
+ if (FNextWeap and $C000) <> 0 then
+ begin
+ if (FNextWeap and $8000) <> 0 then dir := 1 else dir := -1;
+ FNextWeap := FNextWeap or $2000; // we need this
+ if FNextWeapDelay > 0 then exit; // cooldown time
+ cwi := FCurrWeap;
+ for i := 0 to High(FWeapon) do
begin
- FCurrWeap := i;
- ok := True;
- Break;
- end;
-
- if not ok then
- for i := WEAPON_KASTET to FCurrWeap-1 do
- if FWeapon[i] then
+ cwi := (cwi+length(FWeapon)+dir) mod length(FWeapon);
+ if FWeapon[cwi] then
begin
- FCurrWeap := i;
- Break;
+ //e_WriteLog(Format(' SWITCH: cur=%d; new=%d', [FCurrWeap, cwi]), MSG_WARNING);
+ result := Byte(cwi);
+ FNextWeapDelay := 10;
+ exit;
end;
-
- FTime[T_SWITCH] := gTime+156;
-
- if FCurrWeap = WEAPON_SAW then
- FSawSoundSelect.PlayAt(FObj.X, FObj.Y);
-
- FModel.SetWeapon(FCurrWeap);
-
- if g_Game_IsNet then MH_SEND_PlayerStats(FUID);
+ end;
+ resetWeaponQueue();
+ exit;
+ end;
+ // no cycling
+ for i := 0 to High(wantThisWeapon) do wantThisWeapon[i] := false;
+ for i := 0 to High(FWeapon) do if (FNextWeap and (1 shl i)) <> 0 then begin wantThisWeapon[i] := true; Inc(wwc); end;
+ // exclude currently selected weapon from the set
+ wantThisWeapon[FCurrWeap] := false;
+ // slow down alterations a little
+ if wwc > 1 then
+ begin
+ //e_WriteLog(Format(' FNextWeap=%x; delay=%d', [FNextWeap, FNextWeapDelay]), MSG_WARNING);
+ // more than one weapon requested, assume "alteration" and check alteration delay
+ if FNextWeapDelay > 0 then begin FNextWeap := 0; exit; end; // yeah
+ end;
+ // do not reset weapon queue, it will be done in `RealizeCurrentWeapon()`
+ // but clear all counters if no weapon should be switched
+ if wwc < 1 then begin resetWeaponQueue(); exit; end;
+ //e_WriteLog(Format('wwc=%d', [wwc]), MSG_WARNING);
+ // try weapons in descending order
+ for i := High(FWeapon) downto 0 do
+ begin
+ if wantThisWeapon[i] and FWeapon[i] and ((wwc = 1) or hasAmmoForWeapon(i)) then
+ begin
+ // i found her!
+ result := Byte(i);
+ resetWeaponQueue();
+ FNextWeapDelay := 10; // anyway, 'cause why not
+ exit;
+ end;
+ end;
+ // no suitable weapon found, so reset the queue, to avoid accidental "queuing" of weapon w/o ammo
+ resetWeaponQueue();
end;
-procedure TPlayer.PrevWeapon();
+procedure TPlayer.RealizeCurrentWeapon();
+ function switchAllowed (): Boolean;
+ var
+ i: Byte;
+ begin
+ result := false;
+ if FBFGFireCounter <> -1 then
+ exit;
+ if FTime[T_SWITCH] > gTime then
+ exit;
+ for i := WP_FIRST to WP_LAST do
+ if FReloading[i] > 0 then
+ exit;
+ result := true;
+ end;
+
var
- i: Byte;
- ok: Boolean;
+ nw: Byte;
begin
- if g_Game_IsClient then Exit;
- if FBFGFireCounter <> -1 then Exit;
-
- if FTime[T_SWITCH] > gTime then Exit;
-
- for i := WEAPON_KASTET to WEAPON_SUPERPULEMET do
- if FReloading[i] > 0 then Exit;
+ //e_WriteLog(Format('***RealizeCurrentWeapon: FNextWeap=%x; FNextWeapDelay=%d', [FNextWeap, FNextWeapDelay]), MSG_WARNING);
+ //FNextWeap := FNextWeap and $1FFF;
+ if FNextWeapDelay > 0 then Dec(FNextWeapDelay); // "alteration delay"
- ok := False;
-
- if FCurrWeap > 0 then
- for i := FCurrWeap-1 downto WEAPON_KASTET do
- if FWeapon[i] then
- begin
- FCurrWeap := i;
- ok := True;
- Break;
- end;
-
- if not ok then
- for i := WEAPON_SUPERPULEMET downto FCurrWeap+1 do
- if FWeapon[i] then
- begin
- FCurrWeap := i;
- Break;
- end;
+ if not switchAllowed then
+ begin
+ //HACK for weapon cycling
+ if (FNextWeap and $7000) <> 0 then FNextWeap := 0;
+ exit;
+ end;
- FTime[T_SWITCH] := gTime+156;
+ nw := getNextWeaponIndex();
+ if nw = 255 then exit; // don't reset anything here
+ if nw > High(FWeapon) then
+ begin
+ // don't forget to reset queue here!
+ //e_WriteLog(' RealizeCurrentWeapon: WUTAFUUUU', MSG_WARNING);
+ resetWeaponQueue();
+ exit;
+ end;
- if FCurrWeap = WEAPON_SAW then
- FSawSoundSelect.PlayAt(FObj.X, FObj.Y);
+ if FWeapon[nw] then
+ begin
+ FCurrWeap := nw;
+ FTime[T_SWITCH] := gTime+156;
+ if FCurrWeap = WEAPON_SAW then FSawSoundSelect.PlayAt(FObj.X, FObj.Y);
+ FModel.SetWeapon(FCurrWeap);
+ if g_Game_IsNet then MH_SEND_PlayerStats(FUID);
+ end;
+end;
- FModel.SetWeapon(FCurrWeap);
+procedure TPlayer.NextWeapon();
+begin
+ if g_Game_IsClient then Exit;
+ FNextWeap := $8000;
+end;
- if g_Game_IsNet then MH_SEND_PlayerStats(FUID);
+procedure TPlayer.PrevWeapon();
+begin
+ if g_Game_IsClient then Exit;
+ FNextWeap := $4000;
end;
procedure TPlayer.SetWeapon(W: Byte);
FCurrWeap := W;
FModel.SetWeapon(CurrWeap);
+ resetWeaponQueue();
end;
function TPlayer.PickItem(ItemType: Byte; respawn: Boolean; var remove: Boolean): Boolean;
if FBFGFireCounter = -1 then
begin
FCurrWeap := WEAPON_KASTET;
+ resetWeaponQueue();
FModel.SetWeapon(WEAPON_KASTET);
end;
if gFlash <> 0 then
FAir := AIR_DEF;
FJetFuel := 0;
- for a := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for a := WP_FIRST to WP_LAST do
begin
FWeapon[a] := False;
FReloading[a] := 0;
FWeapon[WEAPON_PISTOL] := True;
FWeapon[WEAPON_KASTET] := True;
FCurrWeap := WEAPON_PISTOL;
+ resetWeaponQueue();
FModel.SetWeapon(FCurrWeap);
- for b := A_BULLETS to A_CELLS do
+ for b := A_BULLETS to A_HIGH do
FAmmo[b] := 0;
FAmmo[A_BULLETS] := 50;
FIncCam := FIncCam*i;
end;
+ // no need to do that each second frame, weapon queue will take care of it
+ if FLive and FKeys[KEY_NEXTWEAPON].Pressed and AnyServer then NextWeapon();
+ if FLive and FKeys[KEY_PREVWEAPON].Pressed and AnyServer then PrevWeapon();
+
if gTime mod (GAME_TICK*2) <> 0 then
begin
if (FObj.Vel.X = 0) and FLive then
// Let alive player do some actions
if FKeys[KEY_LEFT].Pressed then Run(D_LEFT);
if FKeys[KEY_RIGHT].Pressed then Run(D_RIGHT);
- if FKeys[KEY_NEXTWEAPON].Pressed and AnyServer then NextWeapon();
- if FKeys[KEY_PREVWEAPON].Pressed and AnyServer then PrevWeapon();
+ //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();
if FKeys[KEY_OPEN].Pressed and AnyServer then Use();
if FKeys[KEY_JUMP].Pressed then Jump()
FJetSoundFly.PlayAt(FObj.X, FObj.Y);
end;
- for b := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for b := WP_FIRST to WP_LAST do
if FReloading[b] > 0 then
if FNoReload then
FReloading[b] := 0
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];
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];
Mem.WriteInt(FSecrets);
// Òåêóùåå îðóæèå:
Mem.WriteByte(FCurrWeap);
+// Æåëàåìîå îðóæèå:
+ Mem.WriteWord(FNextWeap);
+// ...è ïàóçà
+ Mem.WriteByte(FNextWeapDelay);
// Âðåìÿ çàðÿäêè BFG:
Mem.WriteSmallInt(FBFGFireCounter);
// Áóôåð óðîíà:
// Îáúåêò èãðîêà:
Obj_SaveState(@FObj, Mem);
// Òåêóùåå êîëè÷åñòâî ïàòðîíîâ:
- for i := A_BULLETS to A_CELLS do
+ for i := A_BULLETS to A_HIGH do
Mem.WriteWord(FAmmo[i]);
// Ìàêñèìàëüíîå êîëè÷åñòâî ïàòðîíîâ:
- for i := A_BULLETS to A_CELLS do
+ for i := A_BULLETS to A_HIGH do
Mem.WriteWord(FMaxAmmo[i]);
// Íàëè÷èå îðóæèÿ:
- for i := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for i := WP_FIRST to WP_LAST do
Mem.WriteBoolean(FWeapon[i]);
// Âðåìÿ ïåðåçàðÿäêè îðóæèÿ:
- for i := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for i := WP_FIRST to WP_LAST do
Mem.WriteWord(FReloading[i]);
// Íàëè÷èå ðþêçàêà:
if R_ITEM_BACKPACK in FRulez then
Mem.ReadInt(FSecrets);
// Òåêóùåå îðóæèå:
Mem.ReadByte(FCurrWeap);
+// Æåëàåìîå îðóæèå:
+ Mem.ReadWord(FNextWeap);
+// ...è ïàóçà
+ Mem.ReadByte(FNextWeapDelay);
// Âðåìÿ çàðÿäêè BFG:
Mem.ReadSmallInt(FBFGFireCounter);
// Áóôåð óðîíà:
// Îáúåêò èãðîêà:
Obj_LoadState(@FObj, Mem);
// Òåêóùåå êîëè÷åñòâî ïàòðîíîâ:
- for i := A_BULLETS to A_CELLS do
+ for i := A_BULLETS to A_HIGH do
Mem.ReadWord(FAmmo[i]);
// Ìàêñèìàëüíîå êîëè÷åñòâî ïàòðîíîâ:
- for i := A_BULLETS to A_CELLS do
+ for i := A_BULLETS to A_HIGH do
Mem.ReadWord(FMaxAmmo[i]);
// Íàëè÷èå îðóæèÿ:
- for i := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for i := WP_FIRST to WP_LAST do
Mem.ReadBoolean(FWeapon[i]);
// Âðåìÿ ïåðåçàðÿäêè îðóæèÿ:
- for i := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for i := WP_FIRST to WP_LAST do
Mem.ReadWord(FReloading[i]);
// Íàëè÷èå ðþêçàêà:
Mem.ReadByte(b);
Exit;
end;
- for a := WEAPON_KASTET to WEAPON_SUPERPULEMET do FWeapon[a] := True;
- for a := A_BULLETS to A_CELLS do FAmmo[a] := 30000;
+ for a := WP_FIRST to WP_LAST do FWeapon[a] := True;
+ for a := A_BULLETS to A_HIGH do FAmmo[a] := 30000;
FRulez := FRulez+[R_KEY_RED, R_KEY_GREEN, R_KEY_BLUE];
end;
if FBFGFireCounter < 1 then
begin
FCurrWeap := WEAPON_KASTET;
+ resetWeaponQueue();
FModel.SetWeapon(WEAPON_KASTET);
end;
if gFlash <> 0 then
FJetFuel := JET_MAX;
end;
+ ITEM_MEDKIT_SMALL: if FHealth < PLAYER_HP_SOFT then IncMax(FHealth, 10, PLAYER_HP_SOFT);
+ ITEM_MEDKIT_LARGE: if FHealth < PLAYER_HP_SOFT then IncMax(FHealth, 25, PLAYER_HP_SOFT);
+
+ ITEM_ARMOR_GREEN: if FArmor < PLAYER_AP_SOFT then FArmor := PLAYER_AP_SOFT;
+ ITEM_ARMOR_BLUE: if FArmor < PLAYER_AP_LIMIT then FArmor := PLAYER_AP_LIMIT;
+
+ ITEM_SPHERE_BLUE: if FHealth < PLAYER_HP_LIMIT then IncMax(FHealth, 100, PLAYER_HP_LIMIT);
+ ITEM_SPHERE_WHITE:
+ if (FHealth < PLAYER_HP_LIMIT) or (FArmor < PLAYER_AP_LIMIT) then
+ begin
+ if FHealth < PLAYER_HP_LIMIT then FHealth := PLAYER_HP_LIMIT;
+ if FArmor < PLAYER_AP_LIMIT then FArmor := PLAYER_AP_LIMIT;
+ end;
+
+ ITEM_WEAPON_SAW: FWeapon[WEAPON_SAW] := True;
+ ITEM_WEAPON_SHOTGUN1: FWeapon[WEAPON_SHOTGUN1] := True;
+ ITEM_WEAPON_SHOTGUN2: FWeapon[WEAPON_SHOTGUN2] := True;
+ ITEM_WEAPON_CHAINGUN: FWeapon[WEAPON_CHAINGUN] := True;
+ ITEM_WEAPON_ROCKETLAUNCHER: FWeapon[WEAPON_ROCKETLAUNCHER] := True;
+ ITEM_WEAPON_PLASMA: FWeapon[WEAPON_PLASMA] := True;
+ ITEM_WEAPON_BFG: FWeapon[WEAPON_BFG] := True;
+ ITEM_WEAPON_SUPERPULEMET: FWeapon[WEAPON_SUPERPULEMET] := True;
+
+ ITEM_AMMO_BULLETS: if FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS] then IncMax(FAmmo[A_BULLETS], 10, FMaxAmmo[A_BULLETS]);
+ ITEM_AMMO_BULLETS_BOX: if FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS] then IncMax(FAmmo[A_BULLETS], 50, FMaxAmmo[A_BULLETS]);
+ ITEM_AMMO_SHELLS: if FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS] then IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
+ ITEM_AMMO_SHELLS_BOX: if FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS] then IncMax(FAmmo[A_SHELLS], 25, FMaxAmmo[A_SHELLS]);
+ ITEM_AMMO_ROCKET: if FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS] then IncMax(FAmmo[A_ROCKETS], 1, FMaxAmmo[A_ROCKETS]);
+ ITEM_AMMO_ROCKET_BOX: if FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS] then IncMax(FAmmo[A_ROCKETS], 5, FMaxAmmo[A_ROCKETS]);
+ ITEM_AMMO_CELL: if FAmmo[A_CELLS] < FMaxAmmo[A_CELLS] then IncMax(FAmmo[A_CELLS], 40, FMaxAmmo[A_CELLS]);
+ ITEM_AMMO_CELL_BIG: if FAmmo[A_CELLS] < FMaxAmmo[A_CELLS] then IncMax(FAmmo[A_CELLS], 100, FMaxAmmo[A_CELLS]);
+
+ ITEM_AMMO_BACKPACK:
+ if (FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS]) or
+ (FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS]) or
+ (FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS]) or
+ (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) then
+ begin
+ FMaxAmmo[A_BULLETS] := 400;
+ FMaxAmmo[A_SHELLS] := 100;
+ FMaxAmmo[A_ROCKETS] := 100;
+ FMaxAmmo[A_CELLS] := 600;
+
+ if FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS] then IncMax(FAmmo[A_BULLETS], 10, FMaxAmmo[A_BULLETS]);
+ if FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS] then IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
+ if FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS] then IncMax(FAmmo[A_ROCKETS], 1, FMaxAmmo[A_ROCKETS]);
+ if FAmmo[A_CELLS] < FMaxAmmo[A_CELLS] then IncMax(FAmmo[A_CELLS], 40, FMaxAmmo[A_CELLS]);
+
+ FRulez := FRulez + [R_ITEM_BACKPACK];
+ end;
+
+ ITEM_KEY_RED: if not (R_KEY_RED in FRulez) then Include(FRulez, R_KEY_RED);
+ ITEM_KEY_GREEN: if not (R_KEY_GREEN in FRulez) then Include(FRulez, R_KEY_GREEN);
+ ITEM_KEY_BLUE: if not (R_KEY_BLUE in FRulez) then Include(FRulez, R_KEY_BLUE);
+
+ ITEM_BOTTLE: if FHealth < PLAYER_HP_LIMIT then IncMax(FHealth, 4, PLAYER_HP_LIMIT);
+ ITEM_HELMET: if FArmor < PLAYER_AP_LIMIT then IncMax(FArmor, 5, PLAYER_AP_LIMIT);
+
else
Exit;
end;
Inc(gNumBots);
- for a := WEAPON_KASTET to WEAPON_SUPERPULEMET do
+ for a := WP_FIRST to WP_LAST do
begin
FDifficult.WeaponPrior[a] := WEAPON_PRIOR1[a];
FDifficult.CloseWeaponPrior[a] := WEAPON_PRIOR2[a];
FAIFlags := nil;
FSelectedWeapon := FCurrWeap;
+ resetWeaponQueue();
FTargetUID := 0;
end;
end;
end;
+ //HACK! (does it belongs there?)
+ RealizeCurrentWeapon();
+
// Åñëè åñòü âîçìîæíûå öåëè:
// (Ñòðåëÿåì ïî íàïðàâëåíèþ ê öåëÿì)
if (targets <> nil) and (GetAIFlag('NEEDFIRE') <> '') then
begin
UpdateMove();
UpdateCombat();
+ end
+ else
+ begin
+ RealizeCurrentWeapon();
end;
end;