@@ -470,6 +470,11 @@ func (geh gameEventHandler) playerDeath(data map[string]*msg.CSVCMsg_GameEventKe
470470 victimUserID := data ["userid" ].GetValShort ()
471471 wepType = geh .attackerWeaponType (wepType , victimUserID )
472472
473+ if killer == nil && data ["attacker_pawn" ] != nil {
474+ // CS2 only, fallback to pawn handle if the killer was not found by its user ID
475+ killer = geh .parser .gameState .Participants ().FindByPawnHandle (uint64 (data ["attacker_pawn" ].GetValLong ()))
476+ }
477+
473478 geh .dispatch (events.Kill {
474479 Victim : geh .playerByUserID32 (data ["userid" ].GetValShort ()),
475480 Killer : killer ,
@@ -997,7 +1002,18 @@ func (geh gameEventHandler) bombPickup(data map[string]*msg.CSVCMsg_GameEventKey
9971002
9981003// Just so we can nicely create GrenadeEvents in one line
9991004func (geh gameEventHandler ) nadeEvent (data map [string ]* msg.CSVCMsg_GameEventKeyT , nadeType common.EquipmentType ) events.GrenadeEvent {
1000- thrower := geh .playerByUserID32 (data ["userid" ].GetValShort ())
1005+ var thrower * common.Player
1006+ // Sometimes only the position and the entityid are present.
1007+ // 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.
1008+ if data ["userid" ] != nil {
1009+ thrower = geh .playerByUserID32 (data ["userid" ].GetValShort ())
1010+ }
1011+
1012+ // CS2 only - userid may be missing, but userid_pawn present.
1013+ if thrower == nil && data ["userid_pawn" ] != nil {
1014+ thrower = geh .gameState ().Participants ().FindByPawnHandle (uint64 (data ["userid_pawn" ].GetValLong ()))
1015+ }
1016+
10011017 position := r3.Vector {
10021018 X : float64 (data ["x" ].GetValFloat ()),
10031019 Y : float64 (data ["y" ].GetValFloat ()),
0 commit comments