Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ internal static class SkillShotCatalog
Kill("untouchable", "Untouchable", "Three kills in one life without taking damage", Rarity.Rare, Any, (e, _) => e.KillsUnhurt == 3),
Kill("killstreak_10", "10-kill streak", "Ten kills in one life", Rarity.Rare, Any, (e, _) => e.LifeKills == 10),
Kill("killstreak_20", "20-kill streak", "Twenty kills in one life", Rarity.Epic, Any, (e, _) => e.LifeKills == 20),
Kill("collateral", "Collateral", "Kill two players with one bullet", Rarity.Epic, Gun, (e, _) => e.KillsWithThisBullet >= 2),
Kill("collateral", "Collateral", "Kill two players with one bullet", Rarity.Epic, GunNotShotgun, (e, _) => e.KillsWithThisBullet >= 2),
Kill("opening_kill", "Opening kill", "Get the first kill of the round", Rarity.Common, Any, (e, _) => e.IsOpeningKill),
Kill("trade", "Trade", "Kill a teammate's killer right away", Rarity.Common, Any, (e, _) => e.IsTrade),
Kill("revenge", "Revenge", "Kill a player who was dominating you", Rarity.Common, Any, (e, _) => e.IsRevenge),
Expand Down
15 changes: 11 additions & 4 deletions CounterStrikeProgression.Core/Tracking/RoundTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace ktsu.CounterStrikeProgression.Core.Tracking;
/// </summary>
/// <param name="IsOpeningKill">Whether it's the round's first kill.</param>
/// <param name="ChainedKills">The attacker's kills in the current chain, counting this one.</param>
/// <param name="KillsWithThisBullet">The attacker's kills on this tick, counting this one.</param>
/// <param name="KillsWithThisBullet">The attacker's kills with this weapon on this tick, counting this one.</param>
/// <param name="IsTrade">Whether the victim had just killed one of the attacker's teammates.</param>
internal readonly record struct KillContext(bool IsOpeningKill, int ChainedKills, int KillsWithThisBullet, bool IsTrade);

Expand Down Expand Up @@ -48,9 +48,13 @@ public void StartRound()
/// <param name="victim">The victim's id.</param>
/// <param name="victimTeam">The victim's side.</param>
/// <param name="time">The game time in seconds.</param>
/// <param name="tick">The server tick, which identifies kills made with one bullet.</param>
/// <param name="tick">The server tick, which with the weapon identifies kills made with one bullet.</param>
/// <param name="weapon">
/// The weapon's key. Kills on one tick count as one bullet only when they're with the same weapon, so a molotov
/// finishing one enemy as a rifle kills another isn't a collateral.
/// </param>
/// <returns>The round context for the kill.</returns>
public KillContext RegisterKill(int attacker, int attackerTeam, int victim, int victimTeam, double time, int tick)
public KillContext RegisterKill(int attacker, int attackerTeam, int victim, int victimTeam, double time, int tick, string? weapon = null)
{
bool opening = !anyKill;
anyKill = true;
Expand All @@ -63,8 +67,9 @@ public KillContext RegisterKill(int attacker, int attackerTeam, int victim, int

chain.Count++;
chain.LastKillTime = time;
chain.KillsThisTick = chain.LastTick == tick ? chain.KillsThisTick + 1 : 1;
chain.KillsThisTick = (chain.LastTick == tick) && string.Equals(chain.LastWeapon, weapon, StringComparison.Ordinal) ? chain.KillsThisTick + 1 : 1;
chain.LastTick = tick;
chain.LastWeapon = weapon;

bool trade = false;
if (recentKillsBy.TryGetValue(victim, out List<KillRecord>? victimsKills))
Expand Down Expand Up @@ -115,6 +120,8 @@ private sealed class KillChain
public int LastTick { get; set; } = -1;

public int KillsThisTick { get; set; }

public string? LastWeapon { get; set; }
}

private sealed record KillRecord(int Victim, int VictimTeam, double Time);
Expand Down
2 changes: 2 additions & 0 deletions CounterStrikeProgression.Test/SkillShotTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ public void SituationalKills()
Assert.Contains("triple_kill", Earned(TestHelpers.Kill("ak47") with { ChainedKills = 3 }));
Assert.Contains("rampage", Earned(TestHelpers.Kill("ak47") with { ChainedKills = 6 }));
Assert.Contains("collateral", Earned(TestHelpers.Kill("awp") with { KillsWithThisBullet = 2 }));
Assert.Contains("collateral", Earned(TestHelpers.Kill("ak47") with { KillsWithThisBullet = 2 }));
Assert.DoesNotContain("collateral", Earned(TestHelpers.Kill("nova") with { KillsWithThisBullet = 2 }), "One shotgun shell is many pellets, not one bullet.");
Assert.Contains("opening_kill", Earned(TestHelpers.Kill("ak47") with { IsOpeningKill = true }));
Assert.Contains("trade", Earned(TestHelpers.Kill("ak47") with { IsTrade = true }));
Assert.Contains("revenge", Earned(TestHelpers.Kill("ak47") with { IsRevenge = true }));
Expand Down
11 changes: 11 additions & 0 deletions CounterStrikeProgression.Test/TrackerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ public void KillsOnTheSameTickAreACollateral()
Assert.AreEqual(1, round.RegisterKill(1, TeamA, 12, TeamB, 1.1, 70).KillsWithThisBullet);
}

[TestMethod]
public void KillsOnTheSameTickWithDifferentWeaponsAreNotOneBullet()
{
RoundTracker round = new(new ProgressionSettings());
round.StartRound();

Assert.AreEqual(1, round.RegisterKill(1, TeamA, 10, TeamB, 1.0, 64, "molotov").KillsWithThisBullet);
Assert.AreEqual(1, round.RegisterKill(1, TeamA, 11, TeamB, 1.0, 64, "ak47").KillsWithThisBullet, "A molotov kill and a rifle kill on one tick counted as one bullet.");
Assert.AreEqual(2, round.RegisterKill(1, TeamA, 12, TeamB, 1.0, 64, "ak47").KillsWithThisBullet, "Two rifle kills on one tick are one bullet.");
}

[TestMethod]
public void KillingATeammatesKillerQuicklyIsATrade()
{
Expand Down
7 changes: 4 additions & 3 deletions CounterStrikeProgression/CombatHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,22 +256,23 @@ private HookResult OnPlayerDeath(EventPlayerDeath @event, GameEventInfo info)

private void CreditKill(EventPlayerDeath @event, CCSPlayerController attacker, CCSPlayerController victim, bool teammatesAreEnemies)
{
CCSPlayerPawn? attackerPawn = GameState.PawnOf(attacker);
WeaponInfo? weapon = GameState.ResolveWeapon(@event.Weapon, attackerPawn);
KillContext context = services.Round.RegisterKill(
attacker.Slot,
GameState.SideOf(attacker, teammatesAreEnemies),
victim.Slot,
GameState.SideOf(victim, teammatesAreEnemies),
Server.CurrentTime,
Server.TickCount);
Server.TickCount,
weapon?.Key.WeakString ?? @event.Weapon);

CreditAssist(@event, victim);
if (!ProgressionServices.IsTeammate(attacker, victim) && (Sessions.Get(attacker) is { Progress: not null } lifeSession))
{
lifeSession.Life.Kill(victim.IsBot);
}

CCSPlayerPawn? attackerPawn = GameState.PawnOf(attacker);
WeaponInfo? weapon = GameState.ResolveWeapon(@event.Weapon, attackerPawn);
if ((weapon is not null) && !ProgressionServices.IsTeammate(attacker, victim) && ((services.KillMaps is not null) || (services.Site is not null))
&& (KillMapRecorder.PointOf(Server.MapName ?? string.Empty, attacker, Sessions.Get(attacker)?.SteamId ?? 0, victim, Sessions.Get(victim)?.SteamId ?? 0, weapon, @event.Headshot) is { } point))
{
Expand Down
Loading