Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preferred Weapon Allocation #40

Merged
merged 14 commits into from
Jan 15, 2024
16 changes: 9 additions & 7 deletions RetakesAllocator/Menus/WeaponsMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private void OpenTPrimaryMenu(CCSPlayerController player)
{
var menu = new ChatMenu($"{MessagePrefix} Select a T Primary Weapon");

foreach (var weapon in WeaponHelpers.GetPossibleWeaponsForRoundType(RoundType.FullBuy, CsTeam.Terrorist))
foreach (var weapon in WeaponHelpers.GetPossibleWeaponsForAllocationType(WeaponAllocationType.FullBuyPrimary, CsTeam.Terrorist))
{
menu.AddMenuOption(weapon.ToString(), OnTPrimarySelect);
}
Expand Down Expand Up @@ -92,7 +92,7 @@ private void OpenTSecondaryMenu(CCSPlayerController player)
{
var menu = new ChatMenu($"{MessagePrefix} Select a T Secondary Weapon");

foreach (var weapon in WeaponHelpers.GetPossibleWeaponsForRoundType(RoundType.Pistol, CsTeam.Terrorist))
foreach (var weapon in WeaponHelpers.GetPossibleWeaponsForAllocationType(WeaponAllocationType.Secondary, CsTeam.Terrorist))
{
menu.AddMenuOption(weapon.ToString(), OnTSecondarySelect);
}
Expand All @@ -112,7 +112,6 @@ private void OnTSecondarySelect(CCSPlayerController player, ChatMenuOption optio

var weaponName = option.Text;

// TODO: Separate allocation for CT pistol and T pistol
player.PrintToChat($"{MessagePrefix} You selected {weaponName} as T Secondary!");
HandlePreferenceSelection(player, CsTeam.Terrorist, weaponName);

Expand All @@ -123,7 +122,7 @@ private void OpenCtPrimaryMenu(CCSPlayerController player)
{
var menu = new ChatMenu($"{MessagePrefix} Select a CT Primary Weapon");

foreach (var weapon in WeaponHelpers.GetPossibleWeaponsForRoundType(RoundType.FullBuy, CsTeam.CounterTerrorist))
foreach (var weapon in WeaponHelpers.GetPossibleWeaponsForAllocationType(WeaponAllocationType.FullBuyPrimary, CsTeam.CounterTerrorist))
{
menu.AddMenuOption(weapon.ToString(), OnCTPrimarySelect);
}
Expand Down Expand Up @@ -153,7 +152,7 @@ private void OpenCtSecondaryMenu(CCSPlayerController player)
{
var menu = new ChatMenu($"{MessagePrefix} Select a CT Secondary Weapon");

foreach (var weapon in WeaponHelpers.GetPossibleWeaponsForRoundType(RoundType.Pistol, CsTeam.Terrorist))
foreach (var weapon in WeaponHelpers.GetPossibleWeaponsForAllocationType(WeaponAllocationType.Secondary, CsTeam.CounterTerrorist))
{
menu.AddMenuOption(weapon.ToString(), OnCTSecondarySelect);
}
Expand All @@ -173,13 +172,14 @@ private void OnCTSecondarySelect(CCSPlayerController player, ChatMenuOption opti

var weaponName = option.Text;

// TODO: Separate allocation for CT pistol and T pistol
player.PrintToChat($"{MessagePrefix} You selected {weaponName} as CT Secondary!");
HandlePreferenceSelection(player, CsTeam.CounterTerrorist, weaponName);

// OpenGiveAwpMenu(player);
OnMenuComplete(player);
}

// TODO: Add menu to select pistol round weapon

// private void OpenGiveAwpMenu(CCSPlayerController player)
// {
Expand Down Expand Up @@ -224,12 +224,14 @@ private void OnCTSecondarySelect(CCSPlayerController player, ChatMenuOption opti

private static void HandlePreferenceSelection(CCSPlayerController player, CsTeam team, string weapon)
{
OnWeaponCommandHelper.Handle(
var message = OnWeaponCommandHelper.Handle(
new List<string>{weapon},
player.AuthorizedSteamID?.SteamId64 ?? 0,
null,
team,
false,
out _
);
// Log.Write(message);
}
}
113 changes: 81 additions & 32 deletions RetakesAllocator/RetakesAllocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,12 @@ public override void Load(bool hotReload)

RegisterListener<Listeners.OnMapStart>(mapName => { ResetState(); });
AddCommandListener("say", OnPlayerChat, HookMode.Post);

if (Configs.GetConfigData().MigrateOnStartup)
{
Queries.Migrate();
}


if (hotReload)
{
HandleHotReload();
Expand Down Expand Up @@ -71,6 +70,7 @@ public override void Unload(bool hotReload)
#endregion

#region Commands

private HookResult OnPlayerChat(CCSPlayerController? player, CommandInfo info)
{
if (!Helpers.PlayerIsValid(player))
Expand All @@ -89,14 +89,14 @@ private HookResult OnPlayerChat(CCSPlayerController? player, CommandInfo info)

return HookResult.Continue;
}

[ConsoleCommand("css_guns")]
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
public void OnGunsCommand(CCSPlayerController? player, CommandInfo commandInfo)
{
HandleGunsCommand(player, commandInfo);
}

private void HandleGunsCommand(CCSPlayerController? player, CommandInfo commandInfo)
{
if (!Helpers.PlayerIsValid(player))
Expand Down Expand Up @@ -135,25 +135,33 @@ private void HandleWeaponCommand(CCSPlayerController? player, CommandInfo comman
var result = OnWeaponCommandHelper.Handle(
Helpers.CommandInfoToArgList(commandInfo),
playerId,
_currentRoundType,
currentTeam,
false,
out var selectedWeapon
);
if (result is not null)
{
commandInfo.ReplyToCommand($"{MessagePrefix}{result}");
}
commandInfo.ReplyToCommand($"{MessagePrefix}{result}");

if (Helpers.IsWeaponAllocationAllowed() && selectedWeapon is not null)
{
var selectedWeaponRoundType = WeaponHelpers.GetRoundTypeForWeapon(selectedWeapon.Value);
if (selectedWeaponRoundType == RoundType.Pistol || selectedWeaponRoundType == _currentRoundType)
var selectedWeaponAllocationType =
WeaponHelpers.GetWeaponAllocationTypeForWeaponAndRound(_currentRoundType, currentTeam, selectedWeapon.Value);
if (selectedWeaponAllocationType is not null)
{
Helpers.RemoveWeapons(
player,
item => WeaponHelpers.GetRoundTypeForWeapon(item) == selectedWeaponRoundType
item => WeaponHelpers.GetWeaponAllocationTypeForWeaponAndRound(_currentRoundType, currentTeam, item) ==
selectedWeaponAllocationType
);
var slot = selectedWeaponRoundType == RoundType.Pistol ? "slot2" : "slot1";
var slot = selectedWeaponAllocationType.Value switch
{
WeaponAllocationType.FullBuyPrimary => "slot1",
WeaponAllocationType.HalfBuyPrimary => "slot1",
WeaponAllocationType.Secondary => "slot2",
WeaponAllocationType.PistolRound => "slot2",
WeaponAllocationType.Preferred => "slot1",
_ => throw new ArgumentOutOfRangeException()
};
AllocateItemsForPlayer(player, new List<CsItem> {selectedWeapon.Value}, slot);
}
}
Expand All @@ -174,14 +182,12 @@ public void OnRemoveWeaponCommand(CCSPlayerController? player, CommandInfo comma
var result = OnWeaponCommandHelper.Handle(
Helpers.CommandInfoToArgList(commandInfo),
playerId,
_currentRoundType,
currentTeam,
true,
out _
);
if (result is not null)
{
commandInfo.ReplyToCommand($"{MessagePrefix}{result}");
}
commandInfo.ReplyToCommand($"{MessagePrefix}{result}");
}

[ConsoleCommand("css_nextround", "Sets the next round type.")]
Expand Down Expand Up @@ -226,21 +232,33 @@ public HookResult OnPostItemPurchase(EventItemPurchase @event, GameEventInfo inf
var item = Utils.ToEnum<CsItem>(@event.Weapon);
var team = (CsTeam) player.TeamNum;
var playerId = Helpers.GetSteamId(player);
var weaponRoundType = WeaponHelpers.GetRoundTypeForWeapon(item);
var isPreferred = WeaponHelpers.IsPreferred(team, item);

var purchasedAllocationType = _currentRoundType is not null
? WeaponHelpers.GetWeaponAllocationTypeForWeaponAndRound(
_currentRoundType.Value, team, item
)
: null;

var isValidAllocation = WeaponHelpers.IsAllocationTypeValidForRound(purchasedAllocationType, _currentRoundType);

// Log.Write($"item {item} team {team} player {playerId}");
// Log.Write($"curRound {_currentRoundType} weapon Round {weaponRoundType}");
// Log.Write($"curRound {_currentRoundType} weapon alloc {purchasedAllocationType} valid? {isValidAllocation}");
// Log.Write($"Preferred? {isPreferred}");

if (
Helpers.IsWeaponAllocationAllowed() &&
weaponRoundType is not null &&
(weaponRoundType == _currentRoundType || weaponRoundType == RoundType.Pistol)
// Preferred weapons are treated like un-buy-able weapons, but at the end we'll set the user preference
!isPreferred &&
isValidAllocation &&
// redundant, just for null checker
purchasedAllocationType is not null
)
{
Queries.SetWeaponPreferenceForUser(
playerId,
team,
weaponRoundType.Value,
purchasedAllocationType.Value,
item
);
}
Expand All @@ -254,25 +272,38 @@ weaponRoundType is not null &&
return i == item;
}

// Some weapons identify as other weapons, so we just remove them all
return WeaponHelpers.GetRoundTypeForWeapon(i) == weaponRoundType;
if (_currentRoundType is null)
{
return true;
}

var at = WeaponHelpers.GetWeaponAllocationTypeForWeaponAndRound(_currentRoundType.Value, team, i);
// Log.Write($"at: {at}");
return at is null || at == purchasedAllocationType;
});
// Log.Write($"Removed {item}? {removedAnyWeapons}");
Log.Write($"Removed {item}? {removedAnyWeapons}");

var replacedWeapon = false;
var slotToSelect = _currentRoundType == RoundType.Pistol ? "slot2" : "slot1";
if (removedAnyWeapons && _currentRoundType is not null && WeaponHelpers.IsWeapon(item))
{
var replacementItem = WeaponHelpers.GetWeaponForRoundType(_currentRoundType.Value, team,
Queries.GetUserSettings(playerId));
// Log.Write($"Replacement item: {replacementItem}");
if (replacementItem is not null)
var replacementAllocationType =
WeaponHelpers.GetReplacementWeaponAllocationTypeForWeapon(_currentRoundType.Value);
// Log.Write($"Replacement allocation type {replacementAllocationType}");
if (replacementAllocationType is not null)
{
replacedWeapon = true;
AllocateItemsForPlayer(player, new List<CsItem>
var replacementItem = WeaponHelpers.GetWeaponForAllocationType(replacementAllocationType.Value,
team,
Queries.GetUserSettings(playerId));
// Log.Write($"Replacement item: {replacementItem}");
if (replacementItem is not null)
{
replacementItem.Value
}, slotToSelect);
replacedWeapon = true;
AllocateItemsForPlayer(player, new List<CsItem>
{
replacementItem.Value
}, slotToSelect);
}
}
}

Expand Down Expand Up @@ -312,12 +343,30 @@ p.AbsOrigin is null
{
if (p.IsValid && !p.OwnerEntity.IsValid)
{
// Log.Write($"Removing {p.DesignerName}");
p.Remove();
}
});
}
}

if (isPreferred)
{
var itemName = Enum.GetName(item);
if (itemName is not null)
{
var message = OnWeaponCommandHelper.Handle(
new List<string> {itemName},
Helpers.GetSteamId(player),
_currentRoundType,
team,
false,
out _
);
player.PrintToChat(message);
}
}

return HookResult.Continue;
}

Expand Down
5 changes: 5 additions & 0 deletions RetakesAllocatorCore/Config/Configs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public static class Configs
ReadCommentHandling = JsonCommentHandling.Skip,
};

public static bool IsLoaded()
{
return _configData is not null;
}

public static ConfigData GetConfigData()
{
if (_configData is null)
Expand Down
26 changes: 16 additions & 10 deletions RetakesAllocatorCore/Db/Db.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@

namespace RetakesAllocatorCore.Db;

using WeaponPreferencesType = Dictionary<
CsTeam,
Dictionary<RoundType, CsItem>
>;

public class Db : DbContext
{
public DbSet<UserSetting> UserSettings { get; set; }
Expand All @@ -32,9 +27,11 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
optionsBuilder
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);

var databaseConnectionString = Configs.GetConfigData().DatabaseConnectionString;

switch (Configs.GetConfigData().DatabaseProvider)
// TODO This whole thing needs to be fixed per
// https://jasonwatmore.com/post/2020/01/03/aspnet-core-ef-core-migrations-for-multiple-databases-sqlite-and-sql-server
var configData = Configs.IsLoaded() ? Configs.GetConfigData() : new ConfigData();
var databaseConnectionString = configData.DatabaseConnectionString;
switch (configData.DatabaseProvider)
{
case DatabaseProvider.Sqlite:
optionsBuilder.UseSqlite(databaseConnectionString);
Expand All @@ -48,10 +45,19 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
}
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<UserSetting>()
.Property(e => e.WeaponPreferences)
.IsRequired(false);
base.OnModelCreating(modelBuilder);
}

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
UserSetting.Configure(configurationBuilder);
configurationBuilder
.Properties<WeaponPreferencesType>()
.HaveConversion<WeaponPreferencesConverter, WeaponPreferencesComparer>();
.Properties<CsItem>()
.HaveConversion<CsItemConverter>();
}
}
Loading