Skip to content

Commit 99e66a0

Browse files
committed
common: add Player.IsAirborne() utility function (#132)
1 parent 4903176 commit 99e66a0

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

common/player.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ import (
88
st "github.com/markus-wa/demoinfocs-golang/sendtables"
99
)
1010

11+
const (
12+
maxEdictBits = 11
13+
entityHandleSerialNumberBits = 10
14+
entityHandleBits = maxEdictBits + entityHandleSerialNumberBits
15+
invalidEntityHandle = (1 << entityHandleBits) - 1
16+
)
17+
1118
// Player contains mostly game-relevant player information.
1219
type Player struct {
1320
demoInfoProvider demoInfoProvider // provider for demo info such as tick-rate or current tick
@@ -66,6 +73,17 @@ func (p *Player) IsBlinded() bool {
6673
return p.FlashDurationTimeRemaining() > 0
6774
}
6875

76+
// IsAirborne returns true if the player is jumping or falling.
77+
func (p *Player) IsAirborne() bool {
78+
if p.Entity == nil {
79+
return false
80+
}
81+
82+
groundEntityHandle := p.Entity.FindPropertyI("m_hGroundEntity").Value().IntVal
83+
84+
return groundEntityHandle == invalidEntityHandle
85+
}
86+
6987
// FlashDurationTime returns the duration of the blinding effect as time.Duration instead of float32 in seconds.
7088
// Will return 0 if IsBlinded() returns false.
7189
func (p *Player) FlashDurationTime() time.Duration {

common/player_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,22 @@ func TestPlayer_IsScoped(t *testing.T) {
190190
assert.True(t, pl.IsScoped())
191191
}
192192

193+
func TestPlayer_IsAirborne_NilEntity(t *testing.T) {
194+
pl := new(Player)
195+
196+
assert.False(t, pl.IsAirborne())
197+
}
198+
199+
func TestPlayer_IsAirborne(t *testing.T) {
200+
pl := playerWithProperty("m_hGroundEntity", st.PropertyValue{IntVal: 0})
201+
202+
assert.False(t, pl.IsAirborne())
203+
204+
pl = playerWithProperty("m_hGroundEntity", st.PropertyValue{IntVal: 2097151})
205+
206+
assert.True(t, pl.IsAirborne())
207+
}
208+
193209
func newPlayer(tick int) *Player {
194210
return NewPlayer(mockDemoInfoProvider(128, tick))
195211
}

demoinfocs_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,14 @@ func TestDemoInfoCs(t *testing.T) {
115115
}
116116
})
117117

118+
// airborne checks
119+
// we don't check RoundStart or RoundFreezetimeEnd since players may spawn airborne
120+
p.RegisterEventHandler(func(plantBegin events.BombPlantBegin) {
121+
if plantBegin.Player.IsAirborne() {
122+
t.Error("Player is airborne during plant")
123+
}
124+
})
125+
118126
// Check some things at match start
119127
p.RegisterEventHandler(func(events.MatchStart) {
120128
participants := gs.Participants()

0 commit comments

Comments
 (0)