Skip to content

Commit 4d7029c

Browse files
committed
datatables cs2: rewrite player equipment tracking
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!
1 parent ea35647 commit 4d7029c

File tree

1 file changed

+51
-29
lines changed

1 file changed

+51
-29
lines changed

pkg/demoinfocs/datatables.go

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -688,44 +688,66 @@ func (p *parser) bindPlayerWeapons(playerEntity st.Entity, pl *common.Player) {
688688
}
689689

690690
func (p *parser) bindPlayerWeaponsS2(pawnEntity st.Entity, pl *common.Player) {
691-
var cache [maxWeapons]uint64
692-
for i := range cache {
693-
i2 := i // Copy for passing to handler
691+
const inventoryCapacity = 64
692+
var inventorySize uint64 = 64
693+
playerInventory := make(map[int]*common.Equipment)
694+
695+
getWep := func(wepSlotPropertyValue st.PropertyValue) (uint64, *common.Equipment) {
696+
entityID := wepSlotPropertyValue.S2UInt64() & constants.EntityHandleIndexMaskSource2
697+
wep := p.gameState.weapons[int(entityID)]
698+
if wep == nil {
699+
// sometimes a weapon is assigned to a player before the weapon entity is created
700+
wep = common.NewEquipment(common.EqUnknown)
701+
p.gameState.weapons[int(entityID)] = wep
702+
}
703+
704+
return entityID, wep
705+
}
706+
707+
setPlayerInventory := func() {
708+
inventory := make(map[int]*common.Equipment, inventorySize)
709+
for i := uint64(0); i < inventorySize; i++ {
710+
val := pawnEntity.Property(playerWeaponPrefixS2 + fmt.Sprintf("%04d", i)).Value()
711+
if val.Any == nil {
712+
continue
713+
}
714+
715+
entityID, wep := getWep(val)
716+
inventory[int(entityID)] = wep
717+
}
718+
pl.Inventory = inventory
719+
}
720+
721+
pawnEntity.Property("m_pWeaponServices.m_hMyWeapons").OnUpdate(func(pv st.PropertyValue) {
722+
inventorySize = pv.S2UInt64()
723+
setPlayerInventory()
724+
})
725+
726+
for i := 0; i < inventoryCapacity; i++ {
727+
i := i
694728
updateWeapon := func(val st.PropertyValue) {
695729
if val.Any == nil {
696730
return
697731
}
698-
entityID := val.S2UInt64() & constants.EntityHandleIndexMaskSource2
699-
if entityID != constants.EntityHandleIndexMaskSource2 {
700-
if cache[i2] != 0 {
701-
// Player already has a weapon in this slot.
702-
delete(pl.Inventory, int(cache[i2]))
703-
}
704-
cache[i2] = entityID
705-
706-
wep := p.gameState.weapons[int(entityID)]
707732

708-
if wep == nil {
709-
// sometimes a weapon is assigned to a player before the weapon entity is created
710-
wep = common.NewEquipment(common.EqUnknown)
711-
p.gameState.weapons[int(entityID)] = wep
712-
}
733+
entityID, wep := getWep(val)
734+
wep.Owner = pl
713735

714-
// Clear previous owner
715-
if wep.Owner != nil && wep.Entity != nil {
716-
delete(wep.Owner.Inventory, wep.Entity.ID())
717-
}
736+
entityWasCreated := entityID != constants.EntityHandleIndexMaskSource2
718737

719-
// Attribute weapon to player
720-
wep.Owner = pl
721-
pl.Inventory[int(entityID)] = wep
722-
} else {
723-
if cache[i2] != 0 && pl.Inventory[int(cache[i2])] != nil {
724-
pl.Inventory[int(cache[i2])].Owner = nil
738+
if uint64(i) < inventorySize {
739+
if entityWasCreated {
740+
existingWeapon, exists := playerInventory[i]
741+
if exists {
742+
delete(pl.Inventory, existingWeapon.Entity.ID())
743+
}
744+
pl.Inventory[int(entityID)] = wep
745+
playerInventory[i] = wep
746+
} else {
747+
delete(pl.Inventory, int(entityID))
725748
}
726-
delete(pl.Inventory, int(cache[i2]))
727749

728-
cache[i2] = 0
750+
setPlayerInventory()
729751
}
730752
}
731753
property := pawnEntity.Property(playerWeaponPrefixS2 + fmt.Sprintf("%04d", i))

0 commit comments

Comments
 (0)