@@ -51,8 +51,10 @@ func (p *parser) handleGameEvent(ge *msg.CSVCMsg_GameEvent) {
5151}
5252
5353type gameEventHandler struct {
54- parser * parser
55- gameEventNameToHandler map [string ]gameEventHandlerFunc
54+ parser * parser
55+ gameEventNameToHandler map [string ]gameEventHandlerFunc
56+ userIDToFallDamageFrame map [int32 ]int
57+ frameToRoundEndReason map [int ]events.RoundEndReason
5658}
5759
5860func (geh gameEventHandler ) dispatch (event interface {}) {
@@ -75,7 +77,11 @@ type gameEventHandlerFunc func(map[string]*msg.CSVCMsg_GameEventKeyT)
7577
7678//nolint:funlen
7779func newGameEventHandler (parser * parser ) gameEventHandler {
78- geh := gameEventHandler {parser : parser }
80+ geh := gameEventHandler {
81+ parser : parser ,
82+ userIDToFallDamageFrame : make (map [int32 ]int ),
83+ frameToRoundEndReason : make (map [int ]events.RoundEndReason ),
84+ }
7985
8086 // some events need to be delayed until their data is available
8187 // some events can't be delayed because the required state is lost by the end of the tick
@@ -147,7 +153,7 @@ func newGameEventHandler(parser *parser) gameEventHandler {
147153 "player_connect_full" : nil , // Connecting finished
148154 "player_death" : delayIfNoPlayers (geh .playerDeath ), // Player died
149155 "player_disconnect" : geh .playerDisconnect , // Player disconnected (kicked, quit, timed out etc.)
150- "player_falldamage" : nil , // Falldamage
156+ "player_falldamage" : geh . playerFallDamage , // Falldamage
151157 "player_footstep" : delayIfNoPlayers (geh .playerFootstep ), // Footstep sound.- Delayed because otherwise Player might be nil
152158 "player_hurt" : geh .playerHurt , // Player got hurt
153159 "player_jump" : geh .playerJump , // Player jumped
@@ -216,9 +222,12 @@ func (geh gameEventHandler) roundEnd(data map[string]*msg.CSVCMsg_GameEventKeyT)
216222 loserState = winnerState .Opponent
217223 }
218224
225+ reason := events .RoundEndReason (data ["reason" ].GetValByte ())
226+ geh .frameToRoundEndReason [geh .parser .currentFrame ] = reason
227+
219228 geh .dispatch (events.RoundEnd {
220229 Message : data ["message" ].GetValString (),
221- Reason : events . RoundEndReason ( data [ " reason" ]. GetValByte ()) ,
230+ Reason : reason ,
222231 Winner : winner ,
223232 WinnerState : winnerState ,
224233 LoserState : loserState ,
@@ -313,6 +322,8 @@ func (geh gameEventHandler) weaponReload(data map[string]*msg.CSVCMsg_GameEventK
313322func (geh gameEventHandler ) playerDeath (data map [string ]* msg.CSVCMsg_GameEventKeyT ) {
314323 killer := geh .playerByUserID32 (data ["attacker" ].GetValShort ())
315324 wepType := common .MapEquipment (data ["weapon" ].GetValString ())
325+ victimUserID := data ["userid" ].GetValShort ()
326+ wepType = geh .attackerWeaponType (wepType , victimUserID )
316327
317328 geh .dispatch (events.Kill {
318329 Victim : geh .playerByUserID32 (data ["userid" ].GetValShort ()),
@@ -327,9 +338,11 @@ func (geh gameEventHandler) playerDeath(data map[string]*msg.CSVCMsg_GameEventKe
327338func (geh gameEventHandler ) playerHurt (data map [string ]* msg.CSVCMsg_GameEventKeyT ) {
328339 attacker := geh .playerByUserID32 (data ["attacker" ].GetValShort ())
329340 wepType := common .MapEquipment (data ["weapon" ].GetValString ())
341+ userID := data ["userid" ].GetValShort ()
342+ wepType = geh .attackerWeaponType (wepType , userID )
330343
331344 geh .dispatch (events.PlayerHurt {
332- Player : geh .playerByUserID32 (data [ "userid" ]. GetValShort () ),
345+ Player : geh .playerByUserID32 (userID ),
333346 Attacker : attacker ,
334347 Health : int (data ["health" ].GetValByte ()),
335348 Armor : int (data ["armor" ].GetValByte ()),
@@ -340,6 +353,10 @@ func (geh gameEventHandler) playerHurt(data map[string]*msg.CSVCMsg_GameEventKey
340353 })
341354}
342355
356+ func (geh gameEventHandler ) playerFallDamage (data map [string ]* msg.CSVCMsg_GameEventKeyT ) {
357+ geh .userIDToFallDamageFrame [data ["userid" ].GetValShort ()] = geh .parser .currentFrame
358+ }
359+
343360func (geh gameEventHandler ) playerBlind (data map [string ]* msg.CSVCMsg_GameEventKeyT ) {
344361 attacker := geh .gameState ().lastFlash .player
345362 projectile := geh .gameState ().lastFlash .projectileByPlayer [attacker ]
@@ -694,6 +711,28 @@ func (geh gameEventHandler) deleteThrownGrenade(p *common.Player, wepType common
694711 unassert .Samef (wepType , common .EqSmoke , "trying to delete non-existing grenade from gameState.thrownGrenades" )
695712}
696713
714+ func (geh gameEventHandler ) attackerWeaponType (wepType common.EquipmentType , victimUserID int32 ) common.EquipmentType {
715+ // if the player took falldamage in this frame we set the weapon type to world damage
716+ if wepType == common .EqUnknown && geh .userIDToFallDamageFrame [victimUserID ] == geh .parser .currentFrame {
717+ wepType = common .EqWorld
718+ }
719+
720+ // if the round ended in the current frame with reason 1 or 0 we assume it was bomb damage
721+ // unfortunately RoundEndReasonTargetBombed isn't enough and sometimes we need to check for 0 as well
722+ if wepType == common .EqUnknown {
723+ switch geh .frameToRoundEndReason [geh .parser .currentFrame ] {
724+ case 0 :
725+ fallthrough
726+ case events .RoundEndReasonTargetBombed :
727+ wepType = common .EqBomb
728+ }
729+ }
730+
731+ unassert .NotSame (wepType , common .EqUnknown )
732+
733+ return wepType
734+ }
735+
697736func (geh gameEventHandler ) getEquipmentInstance (player * common.Player , wepType common.EquipmentType ) * common.Equipment {
698737 isGrenade := wepType .Class () == common .EqClassGrenade
699738 if isGrenade {
0 commit comments