@@ -469,6 +469,10 @@ func (geh gameEventHandler) playerDeath(data map[string]*msg.CSVCMsg_GameEventKe
469469 wepType := common .MapEquipment (data ["weapon" ].GetValString ())
470470 victimUserID := data ["userid" ].GetValShort ()
471471 wepType = geh .attackerWeaponType (wepType , victimUserID )
472+ if killer == nil && data ["attacker_pawn" ] != nil {
473+ // CS2 only, fallback to pawn handle if the killer was not found by its user ID
474+ killer = geh .parser .gameState .Participants ().FindByPawnHandle (uint64 (data ["attacker_pawn" ].GetValLong ()))
475+ }
472476
473477 geh .dispatch (events.Kill {
474478 Victim : geh .playerByUserID32 (data ["userid" ].GetValShort ()),
@@ -997,7 +1001,18 @@ func (geh gameEventHandler) bombPickup(data map[string]*msg.CSVCMsg_GameEventKey
9971001
9981002// Just so we can nicely create GrenadeEvents in one line
9991003func (geh gameEventHandler ) nadeEvent (data map [string ]* msg.CSVCMsg_GameEventKeyT , nadeType common.EquipmentType ) events.GrenadeEvent {
1000- thrower := geh .playerByUserID32 (data ["userid" ].GetValShort ())
1004+ var thrower * common.Player
1005+ // Sometimes only the position and the entityid are present.
1006+ // Since GetValShort() returns 0 for nil values, the thrower would be the player with UserID 0, so we need to check for the existence of the key.
1007+ if data ["userid" ] != nil {
1008+ thrower = geh .playerByUserID32 (data ["userid" ].GetValShort ())
1009+ }
1010+
1011+ // CS2 only - userid may be missing, but userid_pawn present.
1012+ if thrower == nil && data ["userid_pawn" ] != nil {
1013+ thrower = geh .gameState ().Participants ().FindByPawnHandle (uint64 (data ["userid_pawn" ].GetValLong ()))
1014+ }
1015+
10011016 position := r3.Vector {
10021017 X : float64 (data ["x" ].GetValFloat ()),
10031018 Y : float64 (data ["y" ].GetValFloat ()),
0 commit comments