Skip to content

Commit ccdcfec

Browse files
committed
add Player bot utility functions (#164)
- Player.IsControllingBot() - Player.ControlledBot()
1 parent 59fbe07 commit ccdcfec

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

common/player.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ type Player struct {
4343
FlashTick int // In-game tick at which the player was last flashed
4444
TeamState *TeamState // When keeping the reference make sure you notice when the player changes teams
4545
Team Team
46-
IsBot bool
46+
IsBot bool // True if this is a bot-entity. See also IsControllingBot and ControlledBot().
4747
IsConnected bool
4848
IsDucking bool
4949
IsDefusing bool
@@ -204,6 +204,28 @@ func (p *Player) CashSpentTotal() int {
204204
return p.AdditionalPlayerInformation.TotalCashSpent
205205
}
206206

207+
// IsControllingBot returns true if the player is currently controlling a bot.
208+
// See also ControlledBot().
209+
func (p *Player) IsControllingBot() bool {
210+
if p.Entity == nil {
211+
return false
212+
}
213+
214+
return p.Entity.FindPropertyI("m_bIsControllingBot").Value().IntVal != 0
215+
}
216+
217+
// ControlledBot returns the player instance of the bot that the player is controlling, if any.
218+
// Returns nil if the player is not controlling a bot.
219+
func (p *Player) ControlledBot() *Player {
220+
if p.Entity == nil {
221+
return nil
222+
}
223+
224+
botHandle := p.Entity.FindPropertyI("m_iControlledBotEntIndex").Value().IntVal
225+
226+
return p.demoInfoProvider.FindPlayerByHandle(botHandle)
227+
}
228+
207229
// AdditionalPlayerInformation contains mostly scoreboard information.
208230
type AdditionalPlayerInformation struct {
209231
Kills int

common/player_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,50 @@ func TestPlayer_IsAirborne(t *testing.T) {
206206
assert.True(t, pl.IsAirborne())
207207
}
208208

209+
func TestPlayer_IsControllingBot_NilEntity(t *testing.T) {
210+
pl := new(Player)
211+
212+
assert.False(t, pl.IsControllingBot())
213+
}
214+
215+
func TestPlayer_IsControllingBot(t *testing.T) {
216+
pl := playerWithProperty("m_bIsControllingBot", st.PropertyValue{IntVal: 0})
217+
218+
assert.False(t, pl.IsControllingBot())
219+
220+
pl = playerWithProperty("m_bIsControllingBot", st.PropertyValue{IntVal: 1})
221+
222+
assert.True(t, pl.IsControllingBot())
223+
}
224+
225+
func TestPlayer_ControlledBot_NilEntity(t *testing.T) {
226+
pl := new(Player)
227+
228+
assert.Nil(t, pl.ControlledBot())
229+
}
230+
231+
func TestPlayer_ControlledBot(t *testing.T) {
232+
dave := &Player{
233+
Name: "Dave",
234+
IsBot: true,
235+
}
236+
demoInfoProvider := &demoInfoProviderMock{
237+
playersByHandle: map[int]*Player{
238+
12: dave,
239+
},
240+
}
241+
242+
pl := playerWithProperty("m_iControlledBotEntIndex", st.PropertyValue{IntVal: 0})
243+
pl.demoInfoProvider = demoInfoProvider
244+
245+
assert.Nil(t, pl.ControlledBot())
246+
247+
pl = playerWithProperty("m_iControlledBotEntIndex", st.PropertyValue{IntVal: 12})
248+
pl.demoInfoProvider = demoInfoProvider
249+
250+
assert.Same(t, dave, pl.ControlledBot())
251+
}
252+
209253
func newPlayer(tick int) *Player {
210254
return NewPlayer(mockDemoInfoProvider(128, tick))
211255
}

0 commit comments

Comments
 (0)