Skip to content

Commit b6ac932

Browse files
markus-waclaude
andcommitted
feat(events): add InfernoFireOut and correct InfernoExpired doc
InfernoExpired is dispatched when the CInferno entity is destroyed (~20s lifetime / round end), not when the fire goes out, but its doc claimed the latter. Correct the doc and add InfernoFireOut, dispatched the first time an inferno's active fires (m_bFireIsBurning) transition to zero - the true flame-out moment (~5-7s), which no event previously exposed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent d8440de commit b6ac932

4 files changed

Lines changed: 48 additions & 1 deletion

File tree

‎pkg/demoinfocs/datatables.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,7 @@ func (p *parser) infernoExpired(inf *common.Inferno) {
10701070
})
10711071

10721072
delete(p.gameState.infernos, inf.Entity.ID())
1073+
delete(p.gameState.infernoFireStates, inf.Entity.ID())
10731074

10741075
p.gameEventHandler.deleteThrownGrenade(inf.Thrower(), common.EqIncendiary)
10751076
}

‎pkg/demoinfocs/events/events.go‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,18 @@ type InfernoStart struct {
642642
Inferno *common.Inferno
643643
}
644644

645-
// InfernoExpired signals that all fire from a incendiary or Molotov has extinguished.
645+
// InfernoFireOut signals that all fires of an inferno (incendiary/Molotov) have gone out, i.e.
646+
// Inferno.Fires().Active() first reached zero. Unlike InfernoExpired - which fires when the inferno
647+
// entity is destroyed, seconds later - this marks the actual flame-out / smoke-extinguish moment.
648+
type InfernoFireOut struct {
649+
Inferno *common.Inferno
650+
}
651+
652+
// InfernoExpired signals that the inferno (incendiary/Molotov) entity has been removed.
653+
//
654+
// Note: this fires when the CInferno entity is destroyed - roughly the entity's lifetime (~20s) or
655+
// round end - NOT when the fire actually goes out. For the true flame-out / smoke-extinguish moment
656+
// use InfernoFireOut instead.
646657
// This is different from the FireGrenadeExpire event because it's sent out when the inferno entity is destroyed instead of on the game-event.
647658
//
648659
// Mainly useful for getting the final area of an inferno.

‎pkg/demoinfocs/game_events.go‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,9 +1331,35 @@ func (p *parser) processFrameGameEvents() {
13311331
p.processRoundProgressEvents()
13321332
}
13331333

1334+
p.processInfernoFireOut()
1335+
13341336
for _, eventHandler := range p.delayedEventHandlers {
13351337
eventHandler()
13361338
}
13371339

13381340
p.delayedEventHandlers = p.delayedEventHandlers[:0]
13391341
}
1342+
1343+
// processInfernoFireOut dispatches events.InfernoFireOut the first time an inferno's active fires
1344+
// transition from burning to none. InfernoExpired only fires when the entity is destroyed (~20s),
1345+
// which is much later than the actual flame-out.
1346+
func (p *parser) processInfernoFireOut() {
1347+
for id, inf := range p.gameState.infernos {
1348+
state := p.gameState.infernoFireStates[id]
1349+
if state == nil {
1350+
state = &infernoFireState{}
1351+
p.gameState.infernoFireStates[id] = state
1352+
}
1353+
1354+
if state.firedOut {
1355+
continue
1356+
}
1357+
1358+
if len(inf.Fires().Active().List()) > 0 {
1359+
state.wasBurning = true
1360+
} else if state.wasBurning {
1361+
state.firedOut = true
1362+
p.eventDispatcher.Dispatch(events.InfernoFireOut{Inferno: inf})
1363+
}
1364+
}
1365+
}

‎pkg/demoinfocs/game_state.go‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type gameState struct {
2828
playerControllerEntities map[int]st.Entity
2929
grenadeProjectiles map[int]*common.GrenadeProjectile // Maps entity-IDs to active nade-projectiles. That's grenades that have been thrown, but have not yet detonated.
3030
infernos map[int]*common.Inferno // Maps entity-IDs to active infernos.
31+
infernoFireStates map[int]*infernoFireState // Maps inferno entity-IDs to their burning state, for InfernoFireOut.
3132
weapons map[int]*common.Equipment // Maps entity IDs to weapons. Used to remember what a weapon is (p250 / cz etc.)
3233
hostages map[int]*common.Hostage // Maps entity-IDs to hostages.
3334
entities map[int]st.Entity // Maps entity IDs to entities
@@ -78,6 +79,13 @@ type FlyingFlashbang struct {
7879
explodedFrame int
7980
}
8081

82+
// infernoFireState tracks an inferno's burning state so InfernoFireOut can be dispatched once, when
83+
// its active fires first transition from >0 to 0 (the true flame-out, distinct from InfernoExpired).
84+
type infernoFireState struct {
85+
wasBurning bool
86+
firedOut bool
87+
}
88+
8189
type lastFlash struct {
8290
player *common.Player
8391
projectileByPlayer map[*common.Player]*common.GrenadeProjectile
@@ -238,6 +246,7 @@ func newGameState(demoInfo demoInfoProvider) *gameState {
238246
playersBySteamID32: make(map[uint32]*common.Player),
239247
grenadeProjectiles: make(map[int]*common.GrenadeProjectile),
240248
infernos: make(map[int]*common.Inferno),
249+
infernoFireStates: make(map[int]*infernoFireState),
241250
weapons: make(map[int]*common.Equipment),
242251
hostages: make(map[int]*common.Hostage),
243252
entities: make(map[int]st.Entity),

0 commit comments

Comments
 (0)