X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_player.pas;h=0990c0e5ce43a17ff51a0ff1ff2c6cfe96bdb366;hb=48b4e4111d5f86af9a0f968f5ef7cf76b3ce538b;hp=9aa72a832c3c6d2cf52adfdb1ac70adcee3565cf;hpb=ee1df96f7123dcf3cdf0b0527cf7a790ec9d8d64;p=d2df-sdl.git diff --git a/src/game/g_player.pas b/src/game/g_player.pas index 9aa72a8..0990c0e 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -240,6 +240,8 @@ type function getNextWeaponIndex (): Byte; // return 255 for "no switch" procedure resetWeaponQueue (); function hasAmmoForWeapon (weapon: Byte): Boolean; + function hasAmmoForShooting (weapon: Byte): Boolean; + function shouldSwitch (weapon: Byte; hadWeapon: Boolean) : Boolean; procedure doDamage (v: Integer); @@ -257,6 +259,10 @@ 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; + FSkipFist: Byte; FColor: TRGB; FPreferredTeam: Byte; FSpectator: Boolean; @@ -296,6 +302,11 @@ 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 GetMorePrefered() : Byte; + function MaySwitch(Weapon: Byte) : Boolean; 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 +386,9 @@ 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 SkipFist: Byte read FSkipFist write FSkipFist; property MonsterKills: Integer read FMonsterKills write FMonsterKills; property Secrets: Integer read FSecrets; property GodMode: Boolean read FGodMode write FGodMode; @@ -559,7 +573,7 @@ type TTeamStat = Array [TEAM_RED..TEAM_BLUE] of record - Goals: SmallInt; + Score: SmallInt; end; var @@ -586,6 +600,10 @@ procedure g_Gibs_SetMax(Count: Word); function g_Gibs_GetMax(): Word; procedure g_Corpses_SetMax(Count: Word); function g_Corpses_GetMax(): Word; +procedure g_Force_Model_Set(Mode: Word); +function g_Force_Model_Get(): Word; +procedure g_Forced_Model_SetName(Model: String); +function g_Forced_Model_GetName(): String; procedure g_Shells_SetMax(Count: Word); function g_Shells_GetMax(): Word; @@ -605,7 +623,7 @@ procedure g_Player_ResetAll(Force, Silent: Boolean); function g_Player_Get(UID: Word): TPlayer; function g_Player_GetCount(): Byte; function g_Player_GetStats(): TPlayerStatArray; -function g_Player_ValidName(Name: String): Boolean; +function g_Player_ExistingName(Name: String): Boolean; 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); @@ -620,6 +638,7 @@ procedure g_Bot_Add(Team, Difficult: Byte; Handicap: Integer = 100); procedure g_Bot_AddList(Team: Byte; lname: ShortString; num: Integer = -1; Handicap: Integer = 100); procedure g_Bot_MixNames(); procedure g_Bot_RemoveAll(); +function g_Bot_GetCount(): Integer; implementation @@ -714,6 +733,8 @@ var MaxGibs: Word = 150; MaxCorpses: Word = 20; MaxShells: Word = 300; + ForceModel: Word = 0; + ForcedModelName: String = STD_PLAYER_MODEL; CurrentGib: Integer = 0; CurrentShell: Integer = 0; BotNames: Array of String; @@ -781,6 +802,26 @@ begin Result := MaxCorpses; end; +procedure g_Force_Model_Set(Mode: Word); +begin + ForceModel := Mode; +end; + +function g_Force_Model_Get(): Word; +begin + Result := ForceModel; +end; + +procedure g_Forced_Model_SetName(Model: String); +begin + ForcedModelName := Model; +end; + +function g_Forced_Model_GetName(): String; +begin + Result := ForcedModelName; +end; + function g_Player_Create(ModelName: String; Color: TRGB; Team: Byte; Bot: Boolean): Word; var a: Integer; @@ -816,6 +857,8 @@ begin gPlayers[a].FActualModelName := ModelName; gPlayers[a].SetModel(ModelName); + if Bot and (g_Force_Model_Get() <> 0) then + gPlayers[a].SetModel(g_Forced_Model_GetName()); // Íåò ìîäåëè - ñîçäàíèå íå âîçìîæíî: if gPlayers[a].FModel = nil then @@ -884,7 +927,11 @@ begin // create entity and load state if Bot then - gPlayers[a] := TBot.Create() + begin + gPlayers[a] := TBot.Create(); + if (g_Force_Model_Get() <> 0) then + gPlayers[a].SetModel(g_Forced_Model_GetName()); + end else gPlayers[a] := TPlayer.Create(); gPlayers[a].FPhysics := True; // ??? @@ -930,6 +977,9 @@ var begin if not g_Game_IsServer then Exit; +// Íå äîáàâëÿåì áîòîâ åñëè ëèìèò óæå äîñòèãíóò + if (g_Bot_GetCount() >= gMaxBots) then Exit; + // Ñïèñîê íàçâàíèé ìîäåëåé: m := g_PlayerModel_GetNames(); if m = nil then @@ -974,7 +1024,7 @@ begin _name := ''; if BotNames <> nil then for a := 0 to High(BotNames) do - if g_Player_ValidName(BotNames[a]) then + if g_Player_ExistingName(BotNames[a]) then begin _name := BotNames[a]; Break; @@ -1027,6 +1077,9 @@ var begin if not g_Game_IsServer then Exit; +// Íå äîáàâëÿåì áîòîâ åñëè ëèìèò óæå äîñòèãíóò + if (g_Bot_GetCount() >= gMaxBots) then Exit; + // Ñïèñîê íàçâàíèé ìîäåëåé: m := g_PlayerModel_GetNames(); if m = nil then @@ -1043,26 +1096,33 @@ begin Team := BotList[num].team; // CTF / TDM // Âûáèðàåì íàñòðîéêè áîòà èç ñïèñêà ïî íîìåðó èëè èìåíè: - lName := AnsiLowerCase(lName); - if (num < 0) or (num > Length(BotList)-1) then - num := -1; - if (num = -1) and (lName <> '') and (BotList <> nil) then - for a := 0 to High(BotList) do - if AnsiLowerCase(BotList[a].name) = lName then - begin - num := a; - Break; - end; - if num = -1 then - Exit; + if lName = '' then + num := Random(Length(BotList)) + else + begin + if (num < 0) or (num > Length(BotList)-1) then + num := -1; + if (num = -1) and (BotList <> nil) then + lName := AnsiLowerCase(lName); + for a := 0 to High(BotList) do + if AnsiLowerCase(BotList[a].name) = lName then + begin + num := a; + Break; + end; + if num = -1 then + Exit; + end; // Èìÿ áîòà: _name := BotList[num].name; -// Çàíÿòî - âûáèðàåì ñëó÷àéíîå: - if not g_Player_ValidName(_name) then - repeat - _name := Format('DFBOT%.2d', [Random(100)]); - until g_Player_ValidName(_name); + if (_name = '') and (BotNames <> nil) then + for a := 0 to High(BotNames) do + if g_Player_ExistingName(BotNames[a]) then + begin + _name := BotNames[a]; + Break; + end; // Ìîäåëü: _model := BotList[num].model; @@ -1073,7 +1133,10 @@ begin // Ñîçäàåì áîòà: with g_Player_Get(g_Player_Create(_model, BotList[num].color, Team, True)) as TBot do begin - Name := _name; + // Åñëè èìåíè íåò, äåëàåì åãî èç UID áîòà + if _name = '' + then Name := Format('DFBOT%.5d', [UID]) + else Name := _name; FDifficult.DiagFire := BotList[num].diag_fire; FDifficult.InvisFire := BotList[num].invis_fire; @@ -1164,90 +1227,91 @@ var path: AnsiString; begin BotNames := nil; + BotList := nil; path := BOTNAMES_FILENAME; - if e_FindResource(DataDirs, path) = false then - Exit; - -// ×èòàåì âîçìîæíûå èìåíà áîòîâ èç ôàéëà: - AssignFile(F, path); - Reset(F); - - while not EOF(F) do + if e_FindResource(DataDirs, path) then begin - ReadLn(F, s); + // ×èòàåì âîçìîæíûå èìåíà áîòîâ èç ôàéëà: + AssignFile(F, path); + Reset(F); - s := Trim(s); - if s = '' then - Continue; + while not EOF(F) do + begin + ReadLn(F, s); - SetLength(BotNames, Length(BotNames)+1); - BotNames[High(BotNames)] := s; - end; + s := Trim(s); + if s = '' then + Continue; - CloseFile(F); + SetLength(BotNames, Length(BotNames)+1); + BotNames[High(BotNames)] := s; + end; -// Ïåðåìåøèâàåì èõ: - g_Bot_MixNames(); + CloseFile(F); -// ×èòàåì ôàéë ñ ïàðàìåòðàìè áîòîâ: - config := TConfig.CreateFile(path); - BotList := nil; - a := 0; + // Ïåðåìåøèâàåì èõ: + g_Bot_MixNames(); + end; - while config.SectionExists(IntToStr(a)) do + path := BOTLIST_FILENAME; + if e_FindResource(DataDirs, path) then begin - SetLength(BotList, Length(BotList)+1); + // ×èòàåì ôàéë ñ ïàðàìåòðàìè áîòîâ: + config := TConfig.CreateFile(path); + a := 0; - with BotList[High(BotList)] do + while config.SectionExists(IntToStr(a)) do begin - // Èìÿ áîòà: - name := config.ReadStr(IntToStr(a), 'name', ''); - // Ìîäåëü: - model := config.ReadStr(IntToStr(a), 'model', ''); - // Êîìàíäà: - if config.ReadStr(IntToStr(a), 'team', 'red') = 'red' then - team := TEAM_RED - else - team := TEAM_BLUE; - // Öâåò ìîäåëè: - sa := parse(config.ReadStr(IntToStr(a), 'color', '')); - color.R := StrToIntDef(sa[0], 0); - color.G := StrToIntDef(sa[1], 0); - color.B := StrToIntDef(sa[2], 0); - // Âåðîÿòíîñòü ñòðåëüáû ïîä óãëîì: - diag_fire := config.ReadInt(IntToStr(a), 'diag_fire', 0); - // Âåðîÿòíîñòü îòâåòíîãî îãíÿ ïî íåâèäèìîìó ñîïåðíèêó: - invis_fire := config.ReadInt(IntToStr(a), 'invis_fire', 0); - // Òî÷íîñòü ñòðåëüáû ïîä óãëîì: - diag_precision := config.ReadInt(IntToStr(a), 'diag_precision', 0); - // Òî÷íîñòü ñòðåëüáû â ïîëåòå: - fly_precision := config.ReadInt(IntToStr(a), 'fly_precision', 0); - // Òî÷íîñòü óêëîíåíèÿ îò ñíàðÿäîâ: - cover := config.ReadInt(IntToStr(a), 'cover', 0); - // Âåðîÿòíîñòü ïðûæêà ïðè ïðèáëèæåíèè ñîïåðíèêà: - close_jump := config.ReadInt(IntToStr(a), 'close_jump', 0); - // Ïðèîðèòåòû îðóæèÿ äëÿ äàëüíåãî áîÿ: - sa := parse(config.ReadStr(IntToStr(a), 'w_prior1', '')); - if Length(sa) = 10 then - for b := 0 to 9 do - w_prior1[b] := EnsureRange(StrToInt(sa[b]), 0, 9); - // Ïðèîðèòåòû îðóæèÿ äëÿ áëèæíåãî áîÿ: - sa := parse(config.ReadStr(IntToStr(a), 'w_prior2', '')); - if Length(sa) = 10 then - for b := 0 to 9 do - w_prior2[b] := EnsureRange(StrToInt(sa[b]), 0, 9); - - {sa := parse(config.ReadStr(IntToStr(a), 'w_prior3', '')); - if Length(sa) = 10 then - for b := 0 to 9 do - w_prior3[b] := EnsureRange(StrToInt(sa[b]), 0, 9);} + SetLength(BotList, Length(BotList)+1); + + with BotList[High(BotList)] do + begin + name := config.ReadStr(IntToStr(a), 'name', ''); // Èìÿ áîòà + model := config.ReadStr(IntToStr(a), 'model', ''); // Ìîäåëü + + // Êîìàíäà + if config.ReadStr(IntToStr(a), 'team', 'red') = 'red' + then team := TEAM_RED + else team := TEAM_BLUE; + + // Öâåò ìîäåëè + sa := parse(config.ReadStr(IntToStr(a), 'color', '')); + color.R := StrToIntDef(sa[0], 0); + color.G := StrToIntDef(sa[1], 0); + color.B := StrToIntDef(sa[2], 0); + + diag_fire := config.ReadInt(IntToStr(a), 'diag_fire', 0); // Âåðîÿòíîñòü ñòðåëüáû ïîä óãëîì + invis_fire := config.ReadInt(IntToStr(a), 'invis_fire', 0); // Âåðîÿòíîñòü îòâåòíîãî îãíÿ ïî íåâèäèìîìó ñîïåðíèêó + diag_precision := config.ReadInt(IntToStr(a), 'diag_precision', 0); // Òî÷íîñòü ñòðåëüáû ïîä óãëîì + fly_precision := config.ReadInt(IntToStr(a), 'fly_precision', 0); // Òî÷íîñòü ñòðåëüáû â ïîëåòå + cover := config.ReadInt(IntToStr(a), 'cover', 0); // Òî÷íîñòü óêëîíåíèÿ îò ñíàðÿäîâ + close_jump := config.ReadInt(IntToStr(a), 'close_jump', 0); // Âåðîÿòíîñòü ïðûæêà ïðè ïðèáëèæåíèè ñîïåðíèêà + + // Ïðèîðèòåòû îðóæèÿ äëÿ äàëüíåãî áîÿ + sa := parse(config.ReadStr(IntToStr(a), 'w_prior1', '')); + if Length(sa) = 10 then + for b := 0 to 9 do + w_prior1[b] := EnsureRange(StrToInt(sa[b]), 0, 9); + + // Ïðèîðèòåòû îðóæèÿ äëÿ áëèæíåãî áîÿ + sa := parse(config.ReadStr(IntToStr(a), 'w_prior2', '')); + if Length(sa) = 10 then + for b := 0 to 9 do + w_prior2[b] := EnsureRange(StrToInt(sa[b]), 0, 9); + + {sa := parse(config.ReadStr(IntToStr(a), 'w_prior3', '')); + if Length(sa) = 10 then + for b := 0 to 9 do + w_prior3[b] := EnsureRange(StrToInt(sa[b]), 0, 9);} + end; + + a += 1; end; - a := a + 1; + config.Free(); end; - config.Free(); SetLength(SavedStates, 0); end; @@ -1394,6 +1458,20 @@ begin Result := Result + 1; end; +function g_Bot_GetCount(): Integer; +var + a: Integer; +begin + Result := 0; + + if gPlayers = nil then + Exit; + + for a := 0 to High(gPlayers) do + if (gPlayers[a] <> nil) and (gPlayers[a] is TBot) then + Result := Result + 1; +end; + function g_Player_GetStats(): TPlayerStatArray; var a: Integer; @@ -1453,8 +1531,8 @@ procedure g_Player_ResetAll(Force, Silent: Boolean); var i: Integer; begin - gTeamStat[TEAM_RED].Goals := 0; - gTeamStat[TEAM_BLUE].Goals := 0; + gTeamStat[TEAM_RED].Score := 0; + gTeamStat[TEAM_BLUE].Score := 0; if gPlayers <> nil then for i := 0 to High(gPlayers) do @@ -1976,11 +2054,71 @@ 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] > WP_LAST + 1) then + FWeapPreferences[i] := 0 + else + FWeapPreferences[i] := Prefs[i]; + end; +end; + +procedure TPlayer.SetWeaponPref(Weapon, Pref: Byte); +begin + if (Weapon > WP_LAST + 1) then + exit + else if (Pref <= WP_LAST + 1) and (Weapon <= WP_LAST + 1) then + FWeapPreferences[Weapon] := Pref + else if (Weapon <= WP_LAST + 1) and (Pref > WP_LAST + 1) then + FWeapPreferences[Weapon] := 0; +end; + +function TPlayer.GetWeaponPref(Weapon: Byte) : Byte; +begin + if (Weapon > WP_LAST + 1) then + result := 0 + else if (FWeapPreferences[Weapon] > WP_LAST + 1) then + result := 0 + else + result := FWeapPreferences[Weapon]; +end; + +function TPlayer.GetMorePrefered() : Byte; +var + testedWeap, i: Byte; +begin + testedWeap := FCurrWeap; + for i := WP_FIRST to WP_LAST do + if FWeapon[i] and maySwitch(i) and (FWeapPreferences[i] > FWeapPreferences[testedWeap]) then + testedWeap := i; + if (R_BERSERK in FRulez) and (FWeapPreferences[WP_LAST + 1] > FWeapPreferences[testedWeap]) then + testedWeap := WEAPON_KASTET; + result := testedWeap; +end; + +function TPlayer.maySwitch(Weapon: Byte) : Boolean; +begin + result := true; + if (Weapon = WEAPON_KASTET) and (FSkipFist <> 0) then + begin + if (FSkipFist = 1) and (not (R_BERSERK in FRulez)) then + result := false; + end + else if (FSwitchToEmpty = 0) and (not hasAmmoForShooting(Weapon)) then + result := false; +end; + procedure TPlayer.SwitchTeam; begin if g_Game_IsClient then @@ -2204,8 +2342,13 @@ begin end; if t = HIT_WATER then + begin g_GFX_Bubbles(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2), FObj.Y+PLAYER_RECT.Y-4, value div 2, 8, 4); + if Random(2) = 0 + then g_Sound_PlayExAt('SOUND_GAME_BUBBLE1', FObj.X, FObj.Y) + else g_Sound_PlayExAt('SOUND_GAME_BUBBLE2', FObj.X, FObj.Y); + end; end; // Áóôåð óðîíà: @@ -2643,7 +2786,7 @@ begin SY := gPlayerScreenSize.Y; Y := 0; - if gShowGoals and (gGameSettings.GameMode in [GM_TDM, GM_CTF]) then + if gShowScore and (gGameSettings.GameMode in [GM_TDM, GM_CTF]) then begin if gGameSettings.GameMode = GM_CTF then a := 32 + 8 @@ -2660,7 +2803,7 @@ begin e_Draw(ID, X-16-32, 240-72-4, 0, True, False); end; - s := IntToStr(gTeamStat[TEAM_RED].Goals); + s := IntToStr(gTeamStat[TEAM_RED].Score); e_CharFont_GetSize(gMenuFont, s, tw, th); e_CharFont_PrintEx(gMenuFont, X-16-a-tw, 240-72-4, s, TEAMCOLOR[TEAM_RED]); @@ -2675,7 +2818,7 @@ begin e_Draw(ID, X-16-32, 240-32-4, 0, True, False); end; - s := IntToStr(gTeamStat[TEAM_BLUE].Goals); + s := IntToStr(gTeamStat[TEAM_BLUE].Score); e_CharFont_GetSize(gMenuFont, s, tw, th); e_CharFont_PrintEx(gMenuFont, X-16-a-tw, 240-32-4, s, TEAMCOLOR[TEAM_BLUE]); end; @@ -3381,11 +3524,15 @@ begin if SpawnerUID = FUID then begin // Ñàìîóáèëñÿ - if Srv and (gGameSettings.GameMode = GM_TDM) then - Dec(gTeamStat[FTeam].Goals); + if Srv then begin - Dec(FFrags); - FLastFrag := 0; + if gGameSettings.GameMode = GM_TDM then + Dec(gTeamStat[FTeam].Score); + if DoFrags or (gGameSettings.GameMode = GM_TDM) then + begin + Dec(FFrags); + FLastFrag := 0; + end; end; g_Console_Add(Format(_lc[I_PLAYER_KILL_SELF], [FName]), True); end @@ -3407,7 +3554,7 @@ begin end; if (gGameSettings.GameMode = GM_TDM) and DoFrags then - Inc(gTeamStat[KP.Team].Goals, + Inc(gTeamStat[KP.Team].Score, IfThen(SameTeam(FUID, SpawnerUID), -1, 1)); if netsrv then MH_SEND_PlayerStats(SpawnerUID); @@ -3568,7 +3715,7 @@ begin g_Game_Message(Format(_lc[I_MESSAGE_TLMS_WIN], [AnsiUpperCase(_lc[I_GAME_TEAM_RED])]), 144); if Netsrv then MH_SEND_GameEvent(NET_EV_TLMS_WIN, TEAM_RED); - Inc(gTeamStat[TEAM_RED].Goals); + Inc(gTeamStat[TEAM_RED].Score); gLMSRespawn := LMS_RESPAWN_FINAL; gLMSRespawnTime := gTime + 5000; end @@ -3578,7 +3725,7 @@ begin g_Game_Message(Format(_lc[I_MESSAGE_TLMS_WIN], [AnsiUpperCase(_lc[I_GAME_TEAM_BLUE])]), 144); if Netsrv then MH_SEND_GameEvent(NET_EV_TLMS_WIN, TEAM_BLUE); - Inc(gTeamStat[TEAM_BLUE].Goals); + Inc(gTeamStat[TEAM_BLUE].Score); gLMSRespawn := LMS_RESPAWN_FINAL; gLMSRespawnTime := gTime + 5000; end @@ -3706,6 +3853,36 @@ begin end; end; +function TPlayer.hasAmmoForShooting (weapon: Byte): Boolean; +begin + result := false; + case weapon of + WEAPON_KASTET, WEAPON_SAW: result := true; + WEAPON_SHOTGUN1, WEAPON_SUPERPULEMET: result := (FAmmo[A_SHELLS] > 0); + WEAPON_SHOTGUN2: result := (FAmmo[A_SHELLS] > 1); + WEAPON_PISTOL, WEAPON_CHAINGUN: result := (FAmmo[A_BULLETS] > 0); + WEAPON_ROCKETLAUNCHER: result := (FAmmo[A_ROCKETS] > 0); + WEAPON_PLASMA: result := (FAmmo[A_CELLS] > 0); + WEAPON_BFG: result := (FAmmo[A_CELLS] >= 40); + WEAPON_FLAMETHROWER: result := (FAmmo[A_FUEL] > 0); + else result := (weapon < length(FWeapon)); + end; +end; + +function TPlayer.shouldSwitch (weapon: Byte; hadWeapon: Boolean): Boolean; +begin + result := false; + if (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 @@ -3715,6 +3892,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 @@ -3735,9 +3913,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 maySwitch(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; @@ -3755,6 +3933,7 @@ begin wantThisWeapon[i] := true; Inc(wwc); end; + // exclude currently selected weapon from the set wantThisWeapon[FCurrWeap] := false; // slow down alterations a little @@ -3785,6 +3964,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; @@ -3823,6 +4003,7 @@ begin end; nw := getNextWeaponIndex(); + // if nw = 255 then exit; // don't reset anything here if nw > High(FWeapon) then begin @@ -3866,20 +4047,10 @@ begin end; function TPlayer.PickItem(ItemType: Byte; arespawn: Boolean; var remove: Boolean): Boolean; - - function allowBerserkSwitching (): Boolean; - begin - if (FBFGFireCounter <> -1) then begin result := false; exit; end; - result := true; - if gBerserkAutoswitch then exit; - if not conIsCheatsEnabled then exit; - result := false; - end; - var a: Boolean; - switchWeapon: Byte; - hadWeapon: Boolean; + switchWeapon: Byte = 255; + hadWeapon: Boolean = False; begin Result := False; if g_Game_IsClient then Exit; @@ -4231,33 +4402,11 @@ begin if not (R_BERSERK in FRulez) then begin Include(FRulez, R_BERSERK); - (* - if allowBerserkSwitching then + if (FBFGFireCounter = -1) 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 @@ -4326,26 +4475,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(); @@ -5289,10 +5421,9 @@ begin else if (FAir mod 31 = 0) and not blockmon then begin g_GFX_Bubbles(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2), FObj.Y+PLAYER_RECT.Y-4, 5+Random(6), 8, 4); - if Random(2) = 0 then - g_Sound_PlayExAt('SOUND_GAME_BUBBLE1', FObj.X, FObj.Y) - else - g_Sound_PlayExAt('SOUND_GAME_BUBBLE2', FObj.X, FObj.Y); + if Random(2) = 0 + then g_Sound_PlayExAt('SOUND_GAME_BUBBLE1', FObj.X, FObj.Y) + else g_Sound_PlayExAt('SOUND_GAME_BUBBLE2', FObj.X, FObj.Y); end; end else if FAir < AIR_DEF then FAir := AIR_DEF; @@ -5433,7 +5564,7 @@ begin (y >= 0) and (y <= PLAYER_RECT.Height); end; -function g_Player_ValidName(Name: string): Boolean; +function g_Player_ExistingName(Name: string): Boolean; var a: Integer; begin @@ -5500,10 +5631,9 @@ end; procedure TPlayer.NetFire(Wpn: Byte; X, Y, AX, AY: Integer; WID: Integer = -1); var locObj: TObj; - F: Boolean; + visible: Boolean = True; WX, WY, XD, YD: Integer; begin - F := False; WX := X; WY := Y; XD := AX; @@ -5512,6 +5642,7 @@ begin case FCurrWeap of WEAPON_KASTET: begin + visible := False; DoPunch(); if R_BERSERK in FRulez then begin @@ -5553,14 +5684,12 @@ begin FSawSoundSelect.Stop(); FSawSound.PlayAt(FObj.X, FObj.Y); end; - f := True; end; WEAPON_PISTOL: begin g_Sound_PlayExAt('SOUND_WEAPON_FIREPISTOL', GameX, Gamey); FFireAngle := FAngle; - f := True; g_Player_CreateShell(GameX+PLAYER_RECT_CX, GameY+PLAYER_RECT_CX, GameVelX, GameVelY-2, SHELL_BULLET); end; @@ -5569,7 +5698,6 @@ begin begin g_Sound_PlayExAt('SOUND_WEAPON_FIRESHOTGUN', Gamex, Gamey); FFireAngle := FAngle; - f := True; FShellTimer := 10; FShellType := SHELL_SHELL; end; @@ -5578,7 +5706,6 @@ begin begin g_Sound_PlayExAt('SOUND_WEAPON_FIRESHOTGUN2', Gamex, Gamey); FFireAngle := FAngle; - f := True; FShellTimer := 13; FShellType := SHELL_DBLSHELL; end; @@ -5587,7 +5714,6 @@ begin begin g_Sound_PlayExAt('SOUND_WEAPON_FIRECGUN', Gamex, Gamey); FFireAngle := FAngle; - f := True; g_Player_CreateShell(GameX+PLAYER_RECT_CX, GameY+PLAYER_RECT_CX, GameVelX, GameVelY-2, SHELL_BULLET); end; @@ -5596,28 +5722,24 @@ begin begin g_Weapon_Rocket(wx, wy, xd, yd, FUID, WID); FFireAngle := FAngle; - f := True; end; WEAPON_PLASMA: begin g_Weapon_Plasma(wx, wy, xd, yd, FUID, WID); FFireAngle := FAngle; - f := True; end; WEAPON_BFG: begin g_Weapon_BFGShot(wx, wy, xd, yd, FUID, WID); FFireAngle := FAngle; - f := True; end; WEAPON_SUPERPULEMET: begin g_Sound_PlayExAt('SOUND_WEAPON_FIRESHOTGUN', Gamex, Gamey); FFireAngle := FAngle; - f := True; g_Player_CreateShell(GameX+PLAYER_RECT_CX, GameY+PLAYER_RECT_CX, GameVelX, GameVelY-2, SHELL_SHELL); end; @@ -5627,11 +5749,10 @@ begin g_Weapon_flame(wx, wy, xd, yd, FUID, WID); FlamerOn; FFireAngle := FAngle; - f := True; end; end; - if not f then Exit; + if not visible then Exit; if (FAngle = 0) or (FAngle = 180) then SetAction(A_ATTACK) else if (FAngle = ANGLE_LEFTDOWN) or (FAngle = ANGLE_RIGHTDOWN) then SetAction(A_ATTACKDOWN) @@ -5724,7 +5845,7 @@ begin if not sound_cap_flag[a].IsPlaying() then sound_cap_flag[a].Play(); - gTeamStat[FTeam].Goals := gTeamStat[FTeam].Goals + 1; + gTeamStat[FTeam].Score += 1; Result := True; if g_Game_IsNet then @@ -6403,10 +6524,9 @@ begin begin g_GFX_Bubbles(Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)+Random(3)-1, Obj.Y+Obj.Rect.Height+8, 1, 8, 4); - if Random(2) = 0 then - g_Sound_PlayExAt('SOUND_GAME_BUBBLE1', FObj.X, FObj.Y) - else - g_Sound_PlayExAt('SOUND_GAME_BUBBLE2', FObj.X, FObj.Y); + if Random(2) = 0 + then g_Sound_PlayExAt('SOUND_GAME_BUBBLE1', FObj.X, FObj.Y) + else g_Sound_PlayExAt('SOUND_GAME_BUBBLE2', FObj.X, FObj.Y); Exit; end; @@ -7971,7 +8091,6 @@ end; begin - conRegVar('cheat_berserk_autoswitch', @gBerserkAutoswitch, 'autoswitch to fist when berserk pack taken', '', true, true); conRegVar('player_indicator', @gPlayerIndicator, 'Draw indicator only for current player, also for teammates, or not at all', 'Draw indicator only for current player, also for teammates, or not at all'); conRegVar('player_indicator_style', @gPlayerIndicatorStyle, 'Visual appearance of indicator', 'Visual appearance of indicator'); end.