@@ -238,6 +238,9 @@ func (geh gameEventHandler) roundOfficiallyEnded(data map[string]*msg.CSVCMsg_Ga
238238 geh .parser .infernoExpired (inf )
239239 }
240240
241+ // Thrown grenades could not be deleted at the end of the round (if they are thrown at the very end, they never get destroyed)
242+ geh .gameState ().thrownGrenades = make (map [* common.Player ][]* common.Equipment )
243+
241244 geh .dispatch (events.RoundEndOfficial {})
242245}
243246
@@ -307,7 +310,7 @@ func (geh gameEventHandler) playerDeath(data map[string]*msg.CSVCMsg_GameEventKe
307310 Assister : geh .playerByUserID32 (data ["assister" ].GetValShort ()),
308311 IsHeadshot : data ["headshot" ].GetValBool (),
309312 PenetratedObjects : int (data ["penetrated" ].GetValShort ()),
310- Weapon : getPlayerWeapon (killer , wepType ),
313+ Weapon : geh . getEquipmentInstance (killer , wepType ),
311314 })
312315}
313316
@@ -323,7 +326,7 @@ func (geh gameEventHandler) playerHurt(data map[string]*msg.CSVCMsg_GameEventKey
323326 HealthDamage : int (data ["dmg_health" ].GetValShort ()),
324327 ArmorDamage : int (data ["dmg_armor" ].GetValByte ()),
325328 HitGroup : events .HitGroup (data ["hitgroup" ].GetValByte ()),
326- Weapon : getPlayerWeapon (attacker , wepType ),
329+ Weapon : geh . getEquipmentInstance (attacker , wepType ),
327330 })
328331}
329332
@@ -366,9 +369,12 @@ func (geh gameEventHandler) decoyStarted(data map[string]*msg.CSVCMsg_GameEventK
366369}
367370
368371func (geh gameEventHandler ) decoyDetonate (data map [string ]* msg.CSVCMsg_GameEventKeyT ) {
372+ event := geh .nadeEvent (data , common .EqDecoy )
369373 geh .dispatch (events.DecoyExpired {
370- GrenadeEvent : geh . nadeEvent ( data , common . EqDecoy ) ,
374+ GrenadeEvent : event ,
371375 })
376+
377+ geh .deleteThrownGrenade (event .Thrower , common .EqDecoy )
372378}
373379
374380func (geh gameEventHandler ) smokeGrenadeDetonate (data map [string ]* msg.CSVCMsg_GameEventKeyT ) {
@@ -378,9 +384,12 @@ func (geh gameEventHandler) smokeGrenadeDetonate(data map[string]*msg.CSVCMsg_Ga
378384}
379385
380386func (geh gameEventHandler ) smokeGrenadeExpired (data map [string ]* msg.CSVCMsg_GameEventKeyT ) {
387+ event := geh .nadeEvent (data , common .EqSmoke )
381388 geh .dispatch (events.SmokeExpired {
382- GrenadeEvent : geh . nadeEvent ( data , common . EqSmoke ) ,
389+ GrenadeEvent : event ,
383390 })
391+
392+ geh .deleteThrownGrenade (event .Thrower , common .EqSmoke )
384393}
385394
386395func (geh gameEventHandler ) infernoStartBurn (data map [string ]* msg.CSVCMsg_GameEventKeyT ) {
@@ -583,18 +592,80 @@ func (geh gameEventHandler) nadeEvent(data map[string]*msg.CSVCMsg_GameEventKeyT
583592
584593 return events.GrenadeEvent {
585594 GrenadeType : nadeType ,
595+ Grenade : geh .getThrownGrenade (thrower , nadeType ),
586596 Thrower : thrower ,
587597 Position : position ,
588598 GrenadeEntityID : nadeEntityID ,
589599 }
590600}
591601
592- func mapGameEventData ( d * msg. CSVCMsg_GameEventListDescriptorT , e * msg. CSVCMsg_GameEvent ) map [ string ] * msg. CSVCMsg_GameEventKeyT {
593- data := make ( map [ string ] * msg. CSVCMsg_GameEventKeyT )
594- for i , k := range d . Keys {
595- data [ k . Name ] = e . Keys [ i ]
602+ func ( geh gameEventHandler ) addThrownGrenade ( p * common. Player , wep * common. Equipment ) {
603+ if p == nil {
604+ // can happen for "unknown" players (see #162)
605+ return
596606 }
597- return data
607+
608+ gameState := geh .gameState ()
609+ gameState .thrownGrenades [p ] = append (gameState .thrownGrenades [p ], wep )
610+ }
611+
612+ func (geh gameEventHandler ) getThrownGrenade (p * common.Player , wepType common.EquipmentElement ) * common.Equipment {
613+ if p == nil {
614+ // can happen for incendiaries or "unknown" players (see #162)
615+ return nil
616+ }
617+
618+ // Get the first weapon we found for this player with this weapon type
619+ for _ , thrownGrenade := range geh .gameState ().thrownGrenades [p ] {
620+ if isSameEquipmentElement (thrownGrenade .Weapon , wepType ) {
621+ return thrownGrenade
622+ }
623+ }
624+
625+ // smokes might have duplicate smokegrenade_expired events, so it could have already been deleted.
626+ // if it's not a smoke this should never be reached
627+ unassert .Samef (wepType , common .EqSmoke , "tried to get non-existing grenade from gameState.thrownGrenades" )
628+
629+ return nil
630+ }
631+
632+ func (geh gameEventHandler ) deleteThrownGrenade (p * common.Player , wepType common.EquipmentElement ) {
633+ if p == nil {
634+ // can happen for incendiaries or "unknown" players (see #162)
635+ return
636+ }
637+
638+ gameState := geh .gameState ()
639+
640+ // Delete the first weapon we found with this weapon type
641+ for i , weapon := range gameState .thrownGrenades [p ] {
642+ // If same weapon type
643+ // OR if it's an EqIncendiary we must check for EqMolotov too because of geh.infernoExpire() handling ?
644+ if isSameEquipmentElement (wepType , weapon .Weapon ) {
645+ gameState .thrownGrenades [p ] = append (gameState .thrownGrenades [p ][:i ], gameState .thrownGrenades [p ][i + 1 :]... )
646+ return
647+ }
648+ }
649+
650+ // smokes might have duplicate smokegrenade_expired events, so it might already be deleted.
651+ // besides that this code should never be reached
652+ unassert .Samef (wepType , common .EqSmoke , "trying to delete non-existing grenade from gameState.thrownGrenades" )
653+ }
654+
655+ func (geh gameEventHandler ) getEquipmentInstance (player * common.Player , wepType common.EquipmentElement ) * common.Equipment {
656+ isGrenade := wepType .Class () == common .EqClassGrenade
657+ if isGrenade {
658+ return geh .getThrownGrenade (player , wepType )
659+ }
660+
661+ return getPlayerWeapon (player , wepType )
662+ }
663+
664+ // checks if two EquipmentElements are the same, considering that incendiary and molotov should be treated as identical
665+ func isSameEquipmentElement (a common.EquipmentElement , b common.EquipmentElement ) bool {
666+ return a == b ||
667+ (a == common .EqIncendiary && b == common .EqMolotov ) ||
668+ (b == common .EqIncendiary && a == common .EqMolotov )
598669}
599670
600671// Returns the players instance of the weapon if applicable or a new instance otherwise.
@@ -612,6 +683,15 @@ func getPlayerWeapon(player *common.Player, wepType common.EquipmentElement) *co
612683 return & wep
613684}
614685
686+ func mapGameEventData (d * msg.CSVCMsg_GameEventListDescriptorT , e * msg.CSVCMsg_GameEvent ) map [string ]* msg.CSVCMsg_GameEventKeyT {
687+ data := make (map [string ]* msg.CSVCMsg_GameEventKeyT )
688+ for i , k := range d .Keys {
689+ data [k .Name ] = e .Keys [i ]
690+ }
691+
692+ return data
693+ }
694+
615695// We're all better off not asking questions
616696const valveMagicNumber = 76561197960265728
617697
0 commit comments