From 4204edd3c7df01198a2289af4896be0575fff15c Mon Sep 17 00:00:00 2001 From: Dmitry Lyashuk Date: Sat, 26 Mar 2022 17:20:22 +0300 Subject: [PATCH] Make autoswitch server-side. Add option to skip empty weapons by travi$ --- src/game/g_console.pas | 14 +++-- src/game/g_game.pas | 40 +++++++++++++ src/game/g_language.pas | 12 ++++ src/game/g_menu.pas | 32 +++++++++-- src/game/g_net.pas | 2 +- src/game/g_netmsg.pas | 89 ++++++++++++++--------------- src/game/g_player.pas | 121 +++++++++++++++++++++++----------------- 7 files changed, 203 insertions(+), 107 deletions(-) diff --git a/src/game/g_console.pas b/src/game/g_console.pas index 8c0c41e..b4b67ff 100644 --- a/src/game/g_console.pas +++ b/src/game/g_console.pas @@ -1037,9 +1037,11 @@ begin AddCommand('p1_team', PlayerSettingsCVars); AddCommand('p2_team', PlayerSettingsCVars); AddCommand('p1_autoswitch', PlayerSettingsCVars); - AddCommand('p2_autoswitch', PlayerSettingsCVars); + AddCommand('p2_autoswitch', PlayerSettingsCVars); + AddCommand('p1_switch_empty', PlayerSettingsCVars); + AddCommand('p2_switch_empty', PlayerSettingsCVars); AddCommand('p1_priority_kastet', PlayerSettingsCVars); - AddCommand('p2_priority_kastet', PlayerSettingsCVars); + AddCommand('p2_priority_kastet', PlayerSettingsCVars); AddCommand('p1_priority_saw', PlayerSettingsCVars); AddCommand('p2_priority_saw', PlayerSettingsCVars); AddCommand('p1_priority_pistol', PlayerSettingsCVars); @@ -2205,9 +2207,10 @@ begin WriteLn(f, 'p1_model ', QuoteStr(Model)); WriteLn(f, 'p1_team ', FormatTeam(Team)); WriteLn(f, 'p1_autoswitch ', WeaponSwitch); - WriteLn(f, 'p1_priority_kastet ', Max(0, WeaponPreferences[WEAPON_KASTET])); + WriteLn(f, 'p1_switch_empty ', SwitchToEmpty); + WriteLn(f, 'p1_priority_kastet ', Max(0, WeaponPreferences[WEAPON_KASTET])); WriteLn(f, 'p1_priority_saw ', Max(0, WeaponPreferences[WEAPON_SAW])); - WriteLn(f, 'p1_priority_pistol ', Max(0, WeaponPreferences[WEAPON_PISTOL])); + WriteLn(f, 'p1_priority_pistol ', Max(0, WeaponPreferences[WEAPON_PISTOL])); WriteLn(f, 'p1_priority_shotgun1 ', Max(0, WeaponPreferences[WEAPON_SHOTGUN1])); WriteLn(f, 'p1_priority_shotgun2 ', Max(0, WeaponPreferences[WEAPON_SHOTGUN2] )); WriteLn(f, 'p1_priority_chaingun ', Max(0, WeaponPreferences[WEAPON_CHAINGUN])); @@ -2226,7 +2229,8 @@ begin WriteLn(f, 'p2_model ', QuoteStr(Model)); WriteLn(f, 'p2_team ', FormatTeam(Team)); WriteLn(f, 'p2_autoswitch ', WeaponSwitch); - WriteLn(f, 'p2_priority_kastet ', Max(0, WeaponPreferences[WEAPON_KASTET])); + WriteLn(f, 'p2_switch_empty ', SwitchToEmpty); + WriteLn(f, 'p2_priority_kastet ', Max(0, WeaponPreferences[WEAPON_KASTET])); WriteLn(f, 'p2_priority_saw ', Max(0, WeaponPreferences[WEAPON_SAW])); WriteLn(f, 'p2_priority_pistol ', Max(0, WeaponPreferences[WEAPON_PISTOL])); WriteLn(f, 'p2_priority_shotgun1 ', Max(0, WeaponPreferences[WEAPON_SHOTGUN1])); diff --git a/src/game/g_game.pas b/src/game/g_game.pas index 7674db9..f85024b 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -62,8 +62,11 @@ type Model: String; Color: TRGB; Team: Byte; + // ones below are sent only to the server WeaponSwitch: Byte; WeaponPreferences: Array[WP_FIRST..WP_LAST+1] of Byte; + SwitchToEmpty: Byte; + SwitchToFist: Byte; end; TMegaWADInfo = record @@ -4348,6 +4351,9 @@ begin else begin gPlayer1.Name := gPlayer1Settings.Name; + gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch; + gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences); + gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty; g_Console_Add(Format(_lc[I_PLAYER_JOIN], [gPlayer1.Name]), True); if g_Game_IsServer and g_Game_IsNet then MH_SEND_PlayerCreate(gPlayer1.UID); @@ -4378,6 +4384,9 @@ begin else begin gPlayer2.Name := gPlayer2Settings.Name; + gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch; + gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences); + gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty; g_Console_Add(Format(_lc[I_PLAYER_JOIN], [gPlayer2.Name]), True); if g_Game_IsServer and g_Game_IsNet then MH_SEND_PlayerCreate(gPlayer2.UID); @@ -4493,6 +4502,9 @@ begin end; gPlayer1.Name := gPlayer1Settings.Name; + gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch; + gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences); + gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty; nPl := 1; // Ñîçäàíèå âòîðîãî èãðîêà, åñëè åñòü: @@ -4508,6 +4520,9 @@ begin end; gPlayer2.Name := gPlayer2Settings.Name; + gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch; + gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences); + gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty; Inc(nPl); end; @@ -4587,6 +4602,9 @@ begin end; gPlayer1.Name := gPlayer1Settings.Name; + gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch; + gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences); + gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty; Inc(nPl); end; @@ -4603,6 +4621,9 @@ begin end; gPlayer2.Name := gPlayer2Settings.Name; + gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch; + gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences); + gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty; Inc(nPl); end; @@ -4690,6 +4711,9 @@ begin end; gPlayer1.Name := gPlayer1Settings.Name; + gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch; + gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences); + gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty; end; if nPlayers >= 2 then @@ -4705,6 +4729,9 @@ begin end; gPlayer2.Name := gPlayer2Settings.Name; + gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch; + gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences); + gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty; end; g_Game_SetLoadingText(_lc[I_LOAD_HOST], 0, False); @@ -4883,6 +4910,9 @@ begin end; gPlayer1.Name := gPlayer1Settings.Name; + gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch; + gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences); + gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty; gPlayer1.UID := NetPlrUID1; gPlayer1.Reset(True); @@ -5929,6 +5959,16 @@ begin if (Length(P) = 2) then gPlayer2Settings.WeaponSwitch := EnsureRange(StrTointDef(P[1], 0), 0, 2); end; + 'p1_switch_empty': + begin + if (Length(P) = 2) then + gPlayer1Settings.SwitchToEmpty := EnsureRange(StrTointDef(P[1], 0), 0, 1); + end; + 'p2_switch_empty': + begin + if (Length(P) = 2) then + gPlayer2Settings.SwitchToEmpty := EnsureRange(StrTointDef(P[1], 0), 0, 1); + end; 'p1_priority_kastet': begin if (Length(P) = 2) then diff --git a/src/game/g_language.pas b/src/game/g_language.pas index 900ae42..131bd61 100644 --- a/src/game/g_language.pas +++ b/src/game/g_language.pas @@ -323,6 +323,10 @@ type I_MENU_WEAPON_SWITCH_LINEAR, I_MENU_WEAPON_SWITCH_PREFERENCE, I_MENU_WEAPON_SWITCH_PRIORITY, + I_MENU_WEAPON_ALLOW_EMPTY, + I_MENU_KASTET_ALLOW, + I_MENU_KASTET_ALLOW_BERSERK, + I_MENU_KASTET_ALLOW_ALWAYS, I_MENU_WEAPON_PRIORITY_PLAYER_1, I_MENU_WEAPON_PRIORITY_PLAYER_2, @@ -1263,6 +1267,14 @@ const 'Ïî ïðèîðèòåòó'), ('MENU WEAPON SWITCH PRIORITY', 'Weapon priority', 'Ïðèîðèòåòíîñòü îðóæèÿ'), + ('MENU WEAPON ALLOW EMPTY', 'Skip empty weapons', + 'Ïðîïóñêàòü ïóñòîå îðóæèå'), + ('MENU KASTET ALLOW', 'Switch to fist', + 'Âûáèðàòü êàñòåò'), + ('MENU KASTET ALLOW BERSERK', 'Only with berserk', + 'Åñòü áåðñåðê'), + ('MENU KASTET ALLOW ALWAYS', 'Always', + 'Âñåãäà'), ('MENU WEAPON PRIORITY PLAYER 1', 'Player 1 Priority', 'Ïðèîðèòåò îðóæèÿ (1)'), ('MENU WEAPON PRIORITY PLAYER 2', 'Player 2 Priority', diff --git a/src/game/g_menu.pas b/src/game/g_menu.pas index 2f6ce09..69cd445 100644 --- a/src/game/g_menu.pas +++ b/src/game/g_menu.pas @@ -355,7 +355,9 @@ begin end; menu := TGUIMenu(g_GUI_GetWindow('OptionsPlayersP1WeaponMenu').GetControl('mOptionsPlayersP1WeaponMenu')); - gPlayer1Settings.WeaponSwitch := TGUISwitch(menu.GetControl('swWeaponAutoswitch')).ItemIndex; + gPlayer1Settings.WeaponSwitch := TGUISwitch(menu.GetControl('swWeaponAutoswitch')).ItemIndex; + gPlayer1Settings.SwitchToEmpty := TGUISwitch(menu.GetControl('swWeaponAllowEmpty')).ItemIndex; + menu := TGUIMenu(g_GUI_GetWindow('OptionsPreferencesP1WeaponMenu').GetControl('mOptionsPreferencesP1WeaponMenu')); with menu do @@ -367,8 +369,8 @@ begin end; menu := TGUIMenu(g_GUI_GetWindow('OptionsPlayersP2WeaponMenu').GetControl('mOptionsPlayersP2WeaponMenu')); - gPlayer2Settings.WeaponSwitch := TGUISwitch(menu.GetControl('swWeaponAutoswitch')).ItemIndex; - + gPlayer2Settings.WeaponSwitch := TGUISwitch(menu.GetControl('swWeaponAutoswitch')).ItemIndex; + gPlayer2Settings.SwitchToEmpty := TGUISwitch(menu.GetControl('swWeaponAllowEmpty')).ItemIndex; menu := TGUIMenu(g_GUI_GetWindow('OptionsPreferencesP2WeaponMenu').GetControl('mOptionsPreferencesP2WeaponMenu')); with menu do begin @@ -403,7 +405,10 @@ begin else if gPlayer1.Team <> gPlayer1Settings.Team then gPlayer1.SwitchTeam; - + gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch; + if (gPlayer1.WeapSwitchMode = 2) then + gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences); + gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty; if g_Game_IsNet then MH_SEND_PlayerSettings(gPlayer1.UID); end; @@ -416,6 +421,10 @@ begin else if gPlayer2.Team <> gPlayer2Settings.Team then gPlayer2.SwitchTeam; + gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch; + if (gPlayer2.WeapSwitchMode = 2) then + gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences); + gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty; end; end; @@ -646,6 +655,7 @@ begin menu := TGUIMenu(g_GUI_GetWindow('OptionsPlayersP1WeaponMenu').GetControl('mOptionsPlayersP1WeaponMenu')); TGUISwitch(menu.GetControl('swWeaponAutoswitch')).ItemIndex := gPlayer1Settings.WeaponSwitch; + TGUISwitch(menu.GetControl('swWeaponAllowEmpty')).ItemIndex := gPlayer1Settings.SwitchToEmpty; menu := TGUIMenu(g_GUI_GetWindow('OptionsPreferencesP1WeaponMenu').GetControl('mOptionsPreferencesP1WeaponMenu')); for i := WP_FIRST to WP_LAST+1 do @@ -656,7 +666,7 @@ begin menu := TGUIMenu(g_GUI_GetWindow('OptionsPlayersP2WeaponMenu').GetControl('mOptionsPlayersP2WeaponMenu')); TGUISwitch(menu.GetControl('swWeaponAutoswitch')).ItemIndex := gPlayer2Settings.WeaponSwitch; - + TGUISwitch(menu.GetControl('swWeaponAllowEmpty')).ItemIndex := gPlayer2Settings.SwitchToEmpty; menu := TGUIMenu(g_GUI_GetWindow('OptionsPreferencesP2WeaponMenu').GetControl('mOptionsPreferencesP2WeaponMenu')); for i := WP_FIRST to WP_LAST+1 do begin @@ -3272,6 +3282,12 @@ begin AddItem(_lc[I_MENU_WEAPON_SWITCH_LINEAR]); AddItem(_lc[I_MENU_WEAPON_SWITCH_PREFERENCE]); end; + with AddSwitch(_lc[I_MENU_WEAPON_ALLOW_EMPTY]) do + begin + Name := 'swWeaponAllowEmpty'; + AddItem(_lc[I_MENU_YES]); + AddItem(_lc[I_MENU_NO]); + end; AddButton(@ProcOptionsPlayerP1WeaponPreferencesMenu, _lc[I_MENU_WEAPON_SWITCH_PRIORITY]); ReAlign(); end; @@ -3319,6 +3335,12 @@ begin AddItem(_lc[I_MENU_WEAPON_SWITCH_LINEAR]); AddItem(_lc[I_MENU_WEAPON_SWITCH_PREFERENCE]); end; + with AddSwitch(_lc[I_MENU_WEAPON_ALLOW_EMPTY]) do + begin + Name := 'swWeaponAllowEmpty'; + AddItem(_lc[I_MENU_YES]); + AddItem(_lc[I_MENU_NO]); + end; AddButton(@ProcOptionsPlayerP2WeaponPreferencesMenu, _lc[I_MENU_WEAPON_SWITCH_PRIORITY]); ReAlign(); end; diff --git a/src/game/g_net.pas b/src/game/g_net.pas index 27825c2..edd6024 100644 --- a/src/game/g_net.pas +++ b/src/game/g_net.pas @@ -21,7 +21,7 @@ uses e_log, e_msg, utils, ENet, Classes, md5, MAPDEF{$IFDEF USE_MINIUPNPC}, miniupnpc;{$ELSE};{$ENDIF} const - NET_PROTOCOL_VER = 187; + NET_PROTOCOL_VER = 188; NET_MAXCLIENTS = 24; NET_CHANS = 12; diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index b7a0fdd..55b99b3 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -380,6 +380,9 @@ procedure MH_RECV_Info(C: pTNetClient; var M: TMsg); var Ver, PName, Model, Pw: string; R, G, B, T: Byte; + WeapSwitch: Byte; + TmpPrefArray: Array [WP_FIRST .. WP_LAST + 1] of Byte; + SwitchEmpty: Byte; PID: Word; Color: TRGB; I: Integer; @@ -395,6 +398,11 @@ begin G := M.ReadByte(); B := M.ReadByte(); T := M.ReadByte(); + WeapSwitch := M.ReadByte(); + if (WeapSwitch = 2) then + for I := WP_FIRST to WP_LAST + 1 do + TmpPrefArray[I] := M.ReadByte(); + SwitchEmpty := M.ReadByte(); except Err := True; end; @@ -450,6 +458,10 @@ begin with g_Player_Get(PID) do begin Name := PName; + WeapSwitchMode := WeapSwitch; + if (WeapSwitch = 2) then + SetWeaponPrefs(TmpPrefArray); + SwitchToEmpty := SwitchEmpty; Reset(True); end; @@ -700,6 +712,10 @@ var TmpModel: string; TmpColor: TRGB; TmpTeam: Byte; + TmpWeapSwitch: Byte; + TmpPrefArray: Array [WP_FIRST .. WP_LAST + 1] of Byte; + TmpSwEmpty: Byte; + I: Integer; Pl: TPlayer; Err: Boolean; begin @@ -711,6 +727,11 @@ begin TmpColor.G := M.ReadByte(); TmpColor.B := M.ReadByte(); TmpTeam := M.ReadByte(); + TmpWeapSwitch := M.ReadByte(); + if (TmpWeapSwitch = 2) then + for I := WP_FIRST to WP_LAST + 1 do + TmpPrefArray[I] := M.ReadByte(); + TmpSwEmpty := M.ReadByte(); except Err := True; end; @@ -734,6 +755,14 @@ begin if TmpModel <> Pl.Model.Name then Pl.SetModel(TmpModel); + if (TmpWeapSwitch <> Pl.WeapSwitchMode) then + Pl.WeapSwitchMode := TmpWeapSwitch; + + if (TmpWeapSwitch = 2) then + Pl.SetWeaponPrefs(TmpPrefArray); + + if (TmpSwEmpty <> Pl.SwitchToEmpty) then + Pl.SwitchToEmpty := TmpSwEmpty; MH_SEND_PlayerSettings(Pl.UID, TmpModel); end; @@ -2447,7 +2476,6 @@ var PID: Word; Pl: TPlayer; I, OldFire: Integer; - checkWeapon: Boolean; OldJet, Flam: Boolean; NewTeam: Byte; begin @@ -2469,28 +2497,8 @@ begin NewTeam := M.ReadByte(); for I := WP_FIRST to WP_LAST do - begin - checkWeapon := (M.ReadByte() <> 0); - if ( (gPlayer1Settings.WeaponSwitch = 0) and (gPlayer2Settings.WeaponSwitch = 0) ) or ( (I = WEAPON_KASTET) or (I = WEAPON_PISTOL) or (checkWeapon = False) or (FWeapon[I] = True) ) then - FWeapon[I] := checkWeapon - else - begin - if ((PID = gPlayer1.UID) and (gPlayer1Settings.WeaponSwitch <> 0)) or ( (gPlayer2 <> nil) and (PID = gPlayer2.UID) and (gPlayer2Settings.WeaponSwitch <> 0) ) then - begin - FWeapon[I] := True; - if (PID = gPlayer1.UID) then - if (gPlayer1Settings.WeaponSwitch = 1) or ( (gPlayer1Settings.WeaponSwitch = 2) and (gPlayer1Settings.WeaponPreferences[I] > gPlayer1Settings.WeaponPreferences[CurrWeap]) ) then - begin - gSelectWeapon[0, I] := True; - end - else - if (gPlayer2Settings.WeaponSwitch = 1) or ( (gPlayer2Settings.WeaponSwitch = 2) and (gPlayer2Settings.WeaponPreferences[I] > gPlayer2Settings.WeaponPreferences[CurrWeap]) ) then - gSelectWeapon[1, I] := True; - end - else - FWeapon[I] := checkWeapon; - end; - end; + FWeapon[I] := (M.ReadByte() <> 0); + for I := A_BULLETS to A_HIGH do FAmmo[I] := M.ReadWord(); @@ -2509,28 +2517,8 @@ begin FRulez := FRulez + [R_KEY_GREEN]; if (M.ReadByte() <> 0) then FRulez := FRulez + [R_KEY_BLUE]; - checkWeapon := M.ReadByte() <> 0; - if (checkWeapon) then - begin + if (M.ReadByte() <> 0) then FRulez := FRulez + [R_BERSERK]; - if ((gPlayer2Settings.WeaponSwitch <> 0) and (gPlayer2Settings.WeaponSwitch <> 0)) and ((PID = gPlayer1.UID) or ( (gPlayer2 <> nil) and (PID = gPlayer2.UID) )) then - begin - if (PID = gPlayer1.UID) then - begin - if (gPlayer1Settings.WeaponSwitch = 1) or ( (gPlayer1Settings.WeaponSwitch = 2) and (gPlayer1Settings.WeaponPreferences[WP_LAST+1] > gPlayer1Settings.WeaponPreferences[CurrWeap]) ) then - begin - gSelectWeapon[0, WEAPON_KASTET] := True; - end; - end - else - begin - if (gPlayer2Settings.WeaponSwitch = 1) or ( (gPlayer2Settings.WeaponSwitch = 2) and (gPlayer2Settings.WeaponPreferences[WP_LAST+1] > gPlayer2Settings.WeaponPreferences[CurrWeap]) ) then - begin - gSelectWeapon[0, WEAPON_KASTET] := True; - end; - end; - end; - end; Frags := M.ReadLongInt(); Death := M.ReadLongInt(); @@ -2688,6 +2676,7 @@ var TmpModel: string; TmpColor: TRGB; TmpTeam: Byte; + i: Integer; Pl: TPlayer; PID: Word; begin @@ -3152,6 +3141,7 @@ end; // CLIENT SEND procedure MC_SEND_Info(Password: string); +var i: Integer; begin NetOut.Clear(); @@ -3164,6 +3154,11 @@ begin NetOut.Write(gPlayer1Settings.Color.G); NetOut.Write(gPlayer1Settings.Color.B); NetOut.Write(gPlayer1Settings.Team); + NetOut.Write(gPlayer1Settings.WeaponSwitch); + if (gPlayer1Settings.WeaponSwitch = 2) then + for i := WP_FIRST to WP_LAST + 1 do + NetOut.Write(gPlayer1Settings.WeaponPreferences[i]); + NetOut.Write(gPlayer1Settings.SwitchToEmpty); g_Net_Client_Send(True, NET_CHAN_SERVICE); end; @@ -3303,6 +3298,7 @@ begin end; procedure MC_SEND_PlayerSettings(); +var i: Integer; begin NetOut.Write(Byte(NET_MSG_PLRSET)); NetOut.Write(gPlayer1Settings.Name); @@ -3311,6 +3307,11 @@ begin NetOut.Write(gPlayer1Settings.Color.G); NetOut.Write(gPlayer1Settings.Color.B); NetOut.Write(gPlayer1Settings.Team); + NetOut.Write(gPlayer1Settings.WeaponSwitch); + if (gPlayer1Settings.WeaponSwitch = 2) then + for i := WP_FIRST to WP_LAST + 1 do + NetOut.Write(gPlayer1Settings.WeaponPreferences[i]); + NetOut.Write(gPlayer1Settings.SwitchToEmpty); g_Net_Client_Send(True, NET_CHAN_IMPORTANT); end; diff --git a/src/game/g_player.pas b/src/game/g_player.pas index b04cdc2..fbbd09a 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -240,6 +240,7 @@ type function getNextWeaponIndex (): Byte; // return 255 for "no switch" procedure resetWeaponQueue (); function hasAmmoForWeapon (weapon: Byte): Boolean; + function shouldSwitch (weapon: Byte; hadWeapon: Boolean) : Boolean; procedure doDamage (v: Integer); @@ -257,6 +258,9 @@ type FReloading: Array [WP_FIRST..WP_LAST] of Word; FTime: Array [T_RESPAWN..T_FLAGCAP] of DWORD; FKeys: Array [KEY_LEFT..KEY_CHAT] of TKeyState; + FWeapSwitchMode: Byte; + FWeapPreferences: Array [WP_FIRST .. WP_LAST+1] of Byte; + FSwitchToEmpty: Byte; FColor: TRGB; FPreferredTeam: Byte; FSpectator: Boolean; @@ -296,6 +300,9 @@ type function IsKeyPressed(K: Byte): Boolean; function GetKeys(): Byte; function PickItem(ItemType: Byte; arespawn: Boolean; var remove: Boolean): Boolean; virtual; + procedure SetWeaponPrefs(Prefs: Array of Byte); + procedure SetWeaponPref(Weapon, Pref: Byte); + function GetWeaponPref(Weapon: Byte) : Byte; function Collide(X, Y: Integer; Width, Height: Word): Boolean; overload; function Collide(Panel: TPanel): Boolean; overload; function Collide(X, Y: Integer): Boolean; overload; @@ -375,6 +382,8 @@ type property Death: Integer read FDeath write FDeath; property Kills: Integer read FKills write FKills; property CurrWeap: Byte read FCurrWeap write FCurrWeap; + property WeapSwitchMode: Byte read FWeapSwitchMode write FWeapSwitchMode; + property SwitchToEmpty: Byte read FSwitchToEmpty write FSwitchToEmpty; property MonsterKills: Integer read FMonsterKills write FMonsterKills; property Secrets: Integer read FSecrets; property GodMode: Boolean read FGodMode write FGodMode; @@ -1976,11 +1985,44 @@ begin if FModel <> nil then FModel.Color := Color; end; + + function TPlayer.GetColor(): TRGB; begin result := FModel.Color; end; +procedure TPlayer.SetWeaponPrefs(Prefs: Array of Byte); +var i: Integer; +begin + for i := WP_FIRST to WP_LAST + 1 do + begin + if (Prefs[i] < 0) or (Prefs[i] > WP_LAST + 1) then + FWeapPreferences[i] := 0 + else FWeapPreferences[i] := Prefs[i]; + end; +end; + +procedure TPlayer.SetWeaponPref(Weapon, Pref: Byte); +begin + if (Weapon < 0) or (Weapon > WP_LAST + 1) then + exit + else if (Pref >= 0) and (Pref <= WP_LAST + 1) and (Weapon >= 0) and (Weapon <= WP_LAST + 1) then + FWeapPreferences[Weapon] := Pref + else if (Weapon >= 0) and (Weapon <= WP_LAST + 1) and ((Pref < 0) or (Pref > WP_LAST + 1)) then + FWeapPreferences[Weapon] := 0; +end; + +function TPlayer.GetWeaponPref(Weapon: Byte) : Byte; +begin + if (Weapon < 0) or (Weapon > WP_LAST + 1) then + result := 0 + else if (FWeapPreferences[Weapon] < 0) or (FWeapPreferences[Weapon] > WP_LAST + 1) then + result := 0 + else + result := FWeapPreferences[Weapon]; +end; + procedure TPlayer.SwitchTeam; begin if g_Game_IsClient then @@ -3710,6 +3752,20 @@ begin end; end; +function TPlayer.shouldSwitch (weapon: Byte; hadWeapon: Boolean): Boolean; +begin + result := false; + if (weapon < 0) or (weapon > WP_LAST + 1) then + begin + result := false; + exit; + end; + if (FWeapSwitchMode = 1) and not hadWeapon then + result := true + else if (FWeapSwitchMode = 2) then + result := (FWeapPreferences[weapon] > FWeapPreferences[FCurrWeap]); +end; + // return 255 for "no switch" function TPlayer.getNextWeaponIndex (): Byte; var @@ -3719,6 +3775,7 @@ var dir, cwi: Integer; begin result := 255; // default result: "no switch" + //e_LogWriteFln('FSWITCHTOEMPTY: %s', [FSwitchToEmpty], TMsgType.Notify); // had weapon cycling on previous frame? remove that flag if (FNextWeap and $2000) <> 0 then begin @@ -3739,9 +3796,9 @@ begin for i := 0 to High(FWeapon) do begin cwi := (cwi+length(FWeapon)+dir) mod length(FWeapon); - if FWeapon[cwi] then + if FWeapon[cwi] and ((FSwitchToEmpty = 1) or hasAmmoForWeapon(cwi)) then begin - //e_WriteLog(Format(' SWITCH: cur=%d; new=%d', [FCurrWeap, cwi]), MSG_WARNING); + //e_LogWriteFln(' SWITCH: cur=%d; new=%d %s %s', [FCurrWeap, cwi, FSwitchToEmpty, hasAmmoForWeapon(cwi)], TMsgType.Notify); result := Byte(cwi); FNextWeapDelay := WEAPON_DELAY; exit; @@ -3759,6 +3816,7 @@ begin wantThisWeapon[i] := true; Inc(wwc); end; + // exclude currently selected weapon from the set wantThisWeapon[FCurrWeap] := false; // slow down alterations a little @@ -3789,6 +3847,7 @@ begin result := Byte(i); resetWeaponQueue(); FNextWeapDelay := WEAPON_DELAY * 2; // anyway, 'cause why not + //e_LogWriteFln('FOUND %s %s %s', [result, FSwitchToEmpty, hasAmmoForWeapon(i)], TMsgType.Notify); exit; end; end; @@ -3827,6 +3886,7 @@ begin end; nw := getNextWeaponIndex(); + // if nw = 255 then exit; // don't reset anything here if nw > High(FWeapon) then begin @@ -3882,8 +3942,8 @@ function TPlayer.PickItem(ItemType: Byte; arespawn: Boolean; var remove: Boolean var a: Boolean; - switchWeapon: Byte; - hadWeapon: Boolean; + switchWeapon: Byte = -1; + hadWeapon: Boolean = False; begin Result := False; if g_Game_IsClient then Exit; @@ -4235,34 +4295,8 @@ begin if not (R_BERSERK in FRulez) then begin Include(FRulez, R_BERSERK); - (* - 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 (shouldSwitch(WP_LAST + 1, false)) then + QueueWeaponSwitch(WEAPON_KASTET); if gFlash <> 0 then begin Inc(FPain, 100); @@ -4330,26 +4364,9 @@ begin 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; + + if (shouldSwitch(switchWeapon, hadWeapon)) then + QueueWeaponSwitch(switchWeapon); end; procedure TPlayer.Touch(); -- 2.29.2