X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_player.pas;h=7dd22f870f497aec99735edd27f4caa7887e7a60;hb=ba177dd9743397cb43dad787fbe7748c8ea51cba;hp=d7f305e68757bfb287d836b28dab9d398497155b;hpb=28e48925d007c0ce77737293a2a8e87b7e8d9573;p=d2df-sdl.git diff --git a/src/game/g_player.pas b/src/game/g_player.pas index d7f305e..7dd22f8 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -116,7 +116,7 @@ type NextWeapDelay: 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; + Weapon: Array [WP_FIRST..WP_LAST] of Boolean; Rulez: Set of R_ITEM_BACKPACK..R_BERSERK; WaitRecall: Boolean; end; @@ -209,7 +209,6 @@ type procedure Jump(); procedure Use(); - procedure cycleWeapon (dir: Integer); function getNextWeaponIndex (): Byte; // return 255 for "no switch" procedure resetWeaponQueue (); function hasAmmoForWeapon (weapon: Byte): Boolean; @@ -219,11 +218,11 @@ type FAmmo: Array [A_BULLETS..A_CELLS] of Word; FMaxAmmo: Array [A_BULLETS..A_CELLS] of Word; - FWeapon: Array [WEAPON_KASTET..WEAPON_SUPERPULEMET] of Boolean; + 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; @@ -342,9 +341,9 @@ type 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 @@ -512,9 +511,9 @@ type 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 @@ -550,19 +549,19 @@ 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' @@ -829,10 +828,10 @@ begin for i := A_BULLETS to A_CELLS 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); @@ -998,7 +997,7 @@ begin 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]; @@ -1076,7 +1075,7 @@ begin 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]; @@ -1269,10 +1268,24 @@ var 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(); @@ -3070,7 +3083,7 @@ begin 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 @@ -3299,8 +3312,33 @@ var 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 + cwi := (cwi+length(FWeapon)+dir) mod length(FWeapon); + if FWeapon[cwi] then + begin + //e_WriteLog(Format(' SWITCH: cur=%d; new=%d', [FCurrWeap, cwi]), MSG_WARNING); + result := Byte(cwi); + FNextWeapDelay := 10; + exit; + end; + 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 @@ -3308,10 +3346,12 @@ begin // 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 @@ -3321,6 +3361,8 @@ begin begin // i found her! result := Byte(i); + resetWeaponQueue(); + FNextWeapDelay := 10; // anyway, 'cause why not exit; end; end; @@ -3329,18 +3371,44 @@ begin end; 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, nw: Byte; + nw: Byte; begin - nw := getNextWeaponIndex(); + //e_WriteLog(Format('***RealizeCurrentWeapon: FNextWeap=%x; FNextWeapDelay=%d', [FNextWeap, FNextWeapDelay]), MSG_WARNING); + //FNextWeap := FNextWeap and $1FFF; if FNextWeapDelay > 0 then Dec(FNextWeapDelay); // "alteration delay" - if nw = 255 then exit; // don't reset anything here - if nw > High(FWeapon) then begin resetWeaponQueue(); exit; end; // don't forget to reset queue here! - if FBFGFireCounter <> -1 then exit; - if FTime[T_SWITCH] > gTime then exit; + if not switchAllowed then + begin + //HACK for weapon cycling + if (FNextWeap and $7000) <> 0 then FNextWeap := 0; + exit; + end; - for i := WEAPON_KASTET to WEAPON_SUPERPULEMET do if FReloading[i] > 0 then exit; + 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 FWeapon[nw] then begin @@ -3350,40 +3418,18 @@ begin FModel.SetWeapon(FCurrWeap); if g_Game_IsNet then MH_SEND_PlayerStats(FUID); end; - // reset weapon queue; `getNextWeaponIndex()` guarantees to not select a weapon player don't have - resetWeaponQueue(); - FNextWeapDelay := 10; // anyway, 'cause why not -end; - -procedure TPlayer.cycleWeapon (dir: Integer); -var - i, cwi: Integer; -begin - if dir < 0 then dir := 1 else if dir > 0 then dir := 1 else exit; - cwi := FCurrWeap; - for i := 0 to High(FWeapon) do - begin - cwi := cwi+dir; - if cwi < 0 then cwi += length(FWeapon) - else if cwi > High(FWeapon) then cwi := cwi-length(FWeapon); - if FWeapon[cwi] then - begin - QueueWeaponSwitch(Byte(cwi)); - exit; - end; - end; end; procedure TPlayer.NextWeapon(); begin if g_Game_IsClient then Exit; - cycleWeapon(1); + FNextWeap := $8000; end; procedure TPlayer.PrevWeapon(); begin if g_Game_IsClient then Exit; - cycleWeapon(-1); + FNextWeap := $4000; end; procedure TPlayer.SetWeapon(W: Byte); @@ -4061,7 +4107,7 @@ begin 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; @@ -4453,6 +4499,10 @@ begin 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 @@ -4476,8 +4526,8 @@ begin // 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() @@ -4642,7 +4692,7 @@ begin 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 @@ -5348,10 +5398,10 @@ begin for i := A_BULLETS to A_CELLS 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 @@ -5488,10 +5538,10 @@ begin for i := A_BULLETS to A_CELLS 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); @@ -5554,7 +5604,7 @@ begin Exit; end; - for a := WEAPON_KASTET to WEAPON_SUPERPULEMET do FWeapon[a] := True; + for a := WP_FIRST to WP_LAST do FWeapon[a] := True; for a := A_BULLETS to A_CELLS do FAmmo[a] := 30000; FRulez := FRulez+[R_KEY_RED, R_KEY_GREEN, R_KEY_BLUE]; end; @@ -5964,7 +6014,7 @@ begin 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]; @@ -6525,6 +6575,10 @@ begin begin UpdateMove(); UpdateCombat(); + end + else + begin + RealizeCurrentWeapon(); end; end;