Skip to content

Commit

Permalink
datatables cs2: rewrite player equipment tracking
Browse files Browse the repository at this point in the history
NOTE: this is not 100% accurate yet, but it's a big step in the right
direction.

Thanks to esbengc for describing the required logic!
  • Loading branch information
micvbang committed Nov 20, 2023
1 parent ea35647 commit 4d7029c
Showing 1 changed file with 51 additions and 29 deletions.
80 changes: 51 additions & 29 deletions pkg/demoinfocs/datatables.go
Original file line number Diff line number Diff line change
Expand Up @@ -688,44 +688,66 @@ func (p *parser) bindPlayerWeapons(playerEntity st.Entity, pl *common.Player) {
}

func (p *parser) bindPlayerWeaponsS2(pawnEntity st.Entity, pl *common.Player) {
var cache [maxWeapons]uint64
for i := range cache {
i2 := i // Copy for passing to handler
const inventoryCapacity = 64
var inventorySize uint64 = 64

Check failure on line 692 in pkg/demoinfocs/datatables.go

View workflow job for this annotation

GitHub Actions / ci

[golangci-lint] reported by reviewdog 🐶 declarations should never be cuddled (wsl) Raw Output: pkg/demoinfocs/datatables.go:692:2: declarations should never be cuddled (wsl) var inventorySize uint64 = 64 ^
playerInventory := make(map[int]*common.Equipment)

Check failure on line 693 in pkg/demoinfocs/datatables.go

View workflow job for this annotation

GitHub Actions / ci

[golangci-lint] reported by reviewdog 🐶 assignments should only be cuddled with other assignments (wsl) Raw Output: pkg/demoinfocs/datatables.go:693:2: assignments should only be cuddled with other assignments (wsl) playerInventory := make(map[int]*common.Equipment) ^

getWep := func(wepSlotPropertyValue st.PropertyValue) (uint64, *common.Equipment) {
entityID := wepSlotPropertyValue.S2UInt64() & constants.EntityHandleIndexMaskSource2
wep := p.gameState.weapons[int(entityID)]
if wep == nil {

Check failure on line 698 in pkg/demoinfocs/datatables.go

View workflow job for this annotation

GitHub Actions / ci

[golangci-lint] reported by reviewdog 🐶 only one cuddle assignment allowed before if statement (wsl) Raw Output: pkg/demoinfocs/datatables.go:698:3: only one cuddle assignment allowed before if statement (wsl) if wep == nil { ^
// sometimes a weapon is assigned to a player before the weapon entity is created
wep = common.NewEquipment(common.EqUnknown)
p.gameState.weapons[int(entityID)] = wep
}

return entityID, wep
}

setPlayerInventory := func() {
inventory := make(map[int]*common.Equipment, inventorySize)
for i := uint64(0); i < inventorySize; i++ {

Check failure on line 709 in pkg/demoinfocs/datatables.go

View workflow job for this annotation

GitHub Actions / ci

[golangci-lint] reported by reviewdog 🐶 for statements should only be cuddled with assignments used in the iteration (wsl) Raw Output: pkg/demoinfocs/datatables.go:709:3: for statements should only be cuddled with assignments used in the iteration (wsl) for i := uint64(0); i < inventorySize; i++ { ^
val := pawnEntity.Property(playerWeaponPrefixS2 + fmt.Sprintf("%04d", i)).Value()
if val.Any == nil {
continue
}

entityID, wep := getWep(val)
inventory[int(entityID)] = wep
}
pl.Inventory = inventory

Check failure on line 718 in pkg/demoinfocs/datatables.go

View workflow job for this annotation

GitHub Actions / ci

[golangci-lint] reported by reviewdog 🐶 assignments should only be cuddled with other assignments (wsl) Raw Output: pkg/demoinfocs/datatables.go:718:3: assignments should only be cuddled with other assignments (wsl) pl.Inventory = inventory ^
}

pawnEntity.Property("m_pWeaponServices.m_hMyWeapons").OnUpdate(func(pv st.PropertyValue) {
inventorySize = pv.S2UInt64()
setPlayerInventory()
})

for i := 0; i < inventoryCapacity; i++ {
i := i
updateWeapon := func(val st.PropertyValue) {
if val.Any == nil {
return
}
entityID := val.S2UInt64() & constants.EntityHandleIndexMaskSource2
if entityID != constants.EntityHandleIndexMaskSource2 {
if cache[i2] != 0 {
// Player already has a weapon in this slot.
delete(pl.Inventory, int(cache[i2]))
}
cache[i2] = entityID

wep := p.gameState.weapons[int(entityID)]

if wep == nil {
// sometimes a weapon is assigned to a player before the weapon entity is created
wep = common.NewEquipment(common.EqUnknown)
p.gameState.weapons[int(entityID)] = wep
}
entityID, wep := getWep(val)
wep.Owner = pl

// Clear previous owner
if wep.Owner != nil && wep.Entity != nil {
delete(wep.Owner.Inventory, wep.Entity.ID())
}
entityWasCreated := entityID != constants.EntityHandleIndexMaskSource2

// Attribute weapon to player
wep.Owner = pl
pl.Inventory[int(entityID)] = wep
} else {
if cache[i2] != 0 && pl.Inventory[int(cache[i2])] != nil {
pl.Inventory[int(cache[i2])].Owner = nil
if uint64(i) < inventorySize {
if entityWasCreated {
existingWeapon, exists := playerInventory[i]
if exists {
delete(pl.Inventory, existingWeapon.Entity.ID())
}
pl.Inventory[int(entityID)] = wep

Check failure on line 744 in pkg/demoinfocs/datatables.go

View workflow job for this annotation

GitHub Actions / ci

[golangci-lint] reported by reviewdog 🐶 assignments should only be cuddled with other assignments (wsl) Raw Output: pkg/demoinfocs/datatables.go:744:6: assignments should only be cuddled with other assignments (wsl) pl.Inventory[int(entityID)] = wep ^
playerInventory[i] = wep
} else {
delete(pl.Inventory, int(entityID))
}
delete(pl.Inventory, int(cache[i2]))

cache[i2] = 0
setPlayerInventory()
}
}
property := pawnEntity.Property(playerWeaponPrefixS2 + fmt.Sprintf("%04d", i))
Expand Down

0 comments on commit 4d7029c

Please sign in to comment.