Compare commits

...

3 Commits

Author SHA1 Message Date
Isaac
dd6b8c00fe Update TTT/CS2/Utils/DamageDealingHelper.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Isaac <git@msws.xyz>
2025-10-17 22:00:38 -07:00
MSWS
d9ad08aa27 Improve alive checks 2025-10-17 21:55:36 -07:00
MSWS
35191f23e1 refactor: Refactor data structures for kill tracking +semver:patch
- Change `killedWithStation` data structure to `Dictionary` for enhanced player interaction tracking in `DamageStation.cs`
- Update `PoisonShotsListener.cs` to use `Dictionary` for poison kill tracking and adjust related logic
- Specify priority levels for event handlers in `GlovesListener.cs` to optimize execution order
2025-10-17 21:45:25 -07:00
7 changed files with 30 additions and 37 deletions

View File

@@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection;
using TTT.API.Events;
using TTT.API.Game;
using TTT.API.Player;
using TTT.CS2.Extensions;
using TTT.Game.Events.Game;
using TTT.Game.Events.Player;
using TTT.Game.Listeners;
@@ -36,8 +37,8 @@ public class LateSpawnListener(IServiceProvider provider)
Server.NextWorldUpdate(() => {
foreach (var player in Utilities.GetPlayers()
.Where(p => p.LifeState != (int)LifeState_t.LIFE_ALIVE
&& p.Team != CsTeam.Spectator && p.Team != CsTeam.None))
.Where(p => p.GetHealth() <= 0 && p.Team != CsTeam.Spectator
&& p.Team != CsTeam.None))
player.Respawn();
});
}

View File

@@ -9,6 +9,7 @@ using TTT.API;
using TTT.API.Events;
using TTT.API.Game;
using TTT.API.Player;
using TTT.CS2.Extensions;
using TTT.Game.Events.Player;
namespace TTT.CS2.GameHandlers;
@@ -44,7 +45,7 @@ public class TeamChangeHandler(IServiceProvider provider) : IPluginModule {
};
if (games.ActiveGame is not { State: State.IN_PROGRESS }) {
if (player != null && player.LifeState != (int)LifeState_t.LIFE_ALIVE)
if (player != null && player.GetHealth() <= 0)
Server.NextWorldUpdate(player.Respawn);
return HookResult.Continue;
}
@@ -65,8 +66,10 @@ public class TeamChangeHandler(IServiceProvider provider) : IPluginModule {
return HookResult.Continue;
var apiPlayer = converter.GetPlayer(ev.Userid);
var playerDeath = new PlayerDeathEvent(apiPlayer);
bus.Dispatch(playerDeath);
Server.NextWorldUpdate(() => {
var playerDeath = new PlayerDeathEvent(apiPlayer);
bus.Dispatch(playerDeath);
});
return HookResult.Continue;
}
}

View File

@@ -42,7 +42,8 @@ public class PoisonShotsListener(IServiceProvider provider)
private readonly IShop shop = provider.GetRequiredService<IShop>();
private readonly ISet<string> killedWithPoison = new HashSet<string>();
// private readonly ISet<string> killedWithPoison = new HashSet<string>();
private readonly Dictionary<string, IPlayer> killedWithPoison = new();
public override void Dispose() {
base.Dispose();
@@ -118,7 +119,7 @@ public class PoisonShotsListener(IServiceProvider provider)
if (dmgEvent.IsCanceled) return true;
if (online.Health - config.PoisonConfig.DamagePerTick <= 0) {
killedWithPoison.Add(online.Id);
killedWithPoison[online.Id] = effect.Shooter;
var deathEvent = new PlayerDeathEvent(online)
.WithKiller(effect.Shooter as IOnlinePlayer)
.WithWeapon($"[{Locale[PoisonShotMsgs.SHOP_ITEM_POISON_SHOTS]}]");
@@ -167,8 +168,10 @@ public class PoisonShotsListener(IServiceProvider provider)
[UsedImplicitly]
[EventHandler]
public void OnRagdollSpawn(BodyCreateEvent ev) {
if (!killedWithPoison.Contains(ev.Body.OfPlayer.Id)) return;
if (ev.Body.Killer == null || ev.Body.Killer.Id == ev.Body.OfPlayer.Id)
ev.IsCanceled = true;
if (!killedWithPoison.TryGetValue(ev.Body.OfPlayer.Id, out var shooter))
return;
if (ev.Body.Killer != null && ev.Body.Killer.Id != ev.Body.OfPlayer.Id)
return;
ev.Body.Killer = shooter as IOnlinePlayer;
}
}

View File

@@ -46,7 +46,9 @@ public class DamageStation(IServiceProvider provider)
public override string Description
=> Locale[StationMsgs.SHOP_ITEM_STATION_HURT_DESC];
private readonly ISet<string> killedWithStation = new HashSet<string>();
// private readonly ISet<string> killedWithStation = new HashSet<string>();
private Dictionary<string, StationInfo> killedWithStation =
new Dictionary<string, StationInfo>();
override protected void onInterval() {
var players = finder.GetOnline();
@@ -88,7 +90,7 @@ public class DamageStation(IServiceProvider provider)
damageAmount = -dmgEvent.DmgDealt;
if (player.Health + damageAmount <= 0) {
killedWithStation.Add(player.Id);
killedWithStation[player.Id] = info;
var playerDeath = new PlayerDeathEvent(player)
.WithKiller(info.Owner as IOnlinePlayer)
.WithWeapon($"[{Name}]");
@@ -116,8 +118,11 @@ public class DamageStation(IServiceProvider provider)
[UsedImplicitly]
[EventHandler]
public void OnRagdollSpawn(BodyCreateEvent ev) {
if (!killedWithStation.Contains(ev.Body.OfPlayer.Id)) return;
if (ev.Body.Killer == null || ev.Body.Killer.Id == ev.Body.OfPlayer.Id)
ev.IsCanceled = true;
if (!killedWithStation.TryGetValue(ev.Body.OfPlayer.Id,
out var stationInfo))
return;
if (ev.Body.Killer != null && ev.Body.Killer.Id != ev.Body.OfPlayer.Id)
return;
ev.Body.Killer = stationInfo.Owner as IOnlinePlayer;
}
}

View File

@@ -45,7 +45,7 @@ public class RoundTimerListener(IServiceProvider provider)
.TotalSeconds);
Server.ExecuteCommand("mp_ignore_round_win_conditions 1");
foreach (var player in Utilities.GetPlayers()
.Where(p => p.LifeState != (int)LifeState_t.LIFE_ALIVE && p is {
.Where(p => p.GetHealth() <= 0 && p is {
Team: CsTeam.CounterTerrorist or CsTeam.Terrorist
}))
player.Respawn();
@@ -60,7 +60,7 @@ public class RoundTimerListener(IServiceProvider provider)
if (ev.NewState == State.IN_PROGRESS)
Server.NextWorldUpdate(() => {
foreach (var player in Utilities.GetPlayers()
.Where(p => p.LifeState != (int)LifeState_t.LIFE_ALIVE && p is {
.Where(p => p.GetHealth() <= 0 && p is {
Team: CsTeam.CounterTerrorist or CsTeam.Terrorist
}))
player.Respawn();

View File

@@ -21,25 +21,6 @@ public class DamageDealingHelper {
var damageInfo = new CTakeDamageInfo(infoPtr);
// var attackerInfo = new CAttackerInfo() {
// AttackerUserId =
// attacker != null && attacker.UserId != null ?
// (ushort)attacker.UserId :
// unchecked((ushort)(-1)),
// AttackerPawn = attacker != null ? attacker.Pawn.Raw : 0,
// NeedInit = false,
// TeamNum =
// attacker != null && attacker.Pawn.Value != null ?
// attacker.Pawn.Value.TeamNum :
// 0,
// TeamChecked = 0,
// IsWorld = attacker == null,
// IsPawn = attacker != null,
// };
// Marshal.StructureToPtr(attackerInfo, new IntPtr(infoPtr.ToInt64() + 0x80),
// false);
Schema.SetSchemaValue(damageInfo.Handle, "CTakeDamageInfo", "m_hInflictor",
attacker != null ? attacker.Pawn.Raw : 0);
Schema.SetSchemaValue(damageInfo.Handle, "CTakeDamageInfo", "m_hAttacker",

View File

@@ -24,7 +24,7 @@ public class GlovesListener(IServiceProvider provider)
private readonly Dictionary<IPlayer, int> uses = new();
[UsedImplicitly]
[EventHandler]
[EventHandler(Priority = Priority.LOW)]
public void BodyCreate(BodyCreateEvent ev) {
if (ev.Body.Killer == null || !useGloves(ev.Body.Killer)) return;
if (ev.Body.Killer is not IOnlinePlayer online) return;