-
Notifications
You must be signed in to change notification settings - Fork 115
Description
Describe the bug
The m_Attributes property on gun entities, used to represent skin details, float value, StatTrak status, etc. - is sometimes populated with values that do not belong to the actual weapon entity. In several cases, items incorrectly appear to have attributes like StatTrak, or stickers that shouldn't be there.
This isn't a general thing as some guns are correctly marked, but the ones it gets wrong is consistent.
To Reproduce
Run this with map 1 from here - HLTV Match
go run bug.go -demo ence-vs-ecstatic-m1-dust2.dem
Code:
package main import ( "flag" "fmt" "log" "os" "strings" dem "github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs" events "github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs/events" sendtables "github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs/sendtables" ) func main() { fl := new(flag.FlagSet) urlPtr := fl.String("demo", "", "Filepath to Demo file") err := fl.Parse(os.Args[1:]) if err != nil { panic(err) } url := *urlPtr if url == "" { fmt.Println("Please provide a Demo file path via -demo") return } f, err := os.Open(url) if err != nil { log.Panic("failed to open demo file: ", err) } defer f.Close() p := dem.NewParser(f) defer p.Close() p.RegisterEventHandler(func(e events.DataTablesParsed) { // This event fires at the beginning of parsing, but we'll use it to initialize fmt.Println("Demo parsing started, weapon tracking initialized...") for _, serverclass := range p.ServerClasses().All() { if strings.Contains(serverclass.Name(), "CWeapon") { serverclass.OnEntityCreated(func(entity sendtables.Entity) { entity.Property("m_Attributes").OnUpdate(func(pv sendtables.PropertyValue) { itemId := fetchItemID(entity) if itemId == 22389739547 { //Specific SSG i found to replicate the bug fmt.Printf("Update for entity %d: itemId=%v\n", entity.ID(), itemId) if len(pv.S2Array()) > 0 { for _, attr := range pv.S2Array() { fmt.Printf("Attribute for entity %d: %v\n", entity.ID(), attr) } } else { fmt.Printf("No attributes found for entity %d\n", entity.ID()) } } }) }) } } }) // Parse demo err = p.ParseToEnd() if err != nil { log.Panic("failed to parse demo: ", err) } } // Helper function to get item ID func fetchItemID(w sendtables.Entity) uint64 { if w == nil { return 0 } var itemID uint64 = 0 itemHigh, itemHighFound := w.PropertyValue("m_iItemIDHigh") itemLow, itemLowFound := w.PropertyValue("m_iItemIDLow") if itemHighFound && itemLowFound { var itemIDHigh, itemIDLow uint32 // Convert high value switch v := itemHigh.Any.(type) { case uint32: itemIDHigh = v case uint64: itemIDHigh = uint32(v) case int: itemIDHigh = uint32(v) case int32: itemIDHigh = uint32(v) case int64: itemIDHigh = uint32(v) case float32: itemIDHigh = uint32(v) case float64: itemIDHigh = uint32(v) default: itemIDHigh = 0 } // Convert low value switch v := itemLow.Any.(type) { case uint32: itemIDLow = v case uint64: itemIDLow = uint32(v) case int: itemIDLow = uint32(v) case int32: itemIDLow = uint32(v) case int64: itemIDLow = uint32(v) case float32: itemIDLow = uint32(v) case float64: itemIDLow = uint32(v) default: itemIDLow = 0 } // Combine high and low into full item ID itemID = (uint64(itemIDHigh) << 32) | uint64(itemIDLow) } return itemID }
Expected behavior
The test above fetches this gun from the demo, and logs the attributes everytime it's updated. (seems like it's only once when it's created?)
It should have 6 - 7 - 8 - 75
Thinking this was a mistake in the demo itself i cross checked it using Clarity, and that correctly only shows 4 entries in the array. (notice how the last m_attributes is index 75)
The code above should only output:
Update for entity 89: itemId=22389739547
Attribute for entity 89: &{[6 624 624 0 false <nil> <nil> <nil>]}
Attribute for entity 89: &{[7 948.8936 948.8936 0 false <nil> <nil> <nil>]}
Attribute for entity 89: &{[8 0.069185875 0.069185875 0 false <nil> <nil> <nil>]}
Attribute for entity 89: &{[75 4.9426443e+19 4.9426443e+19 0 false <nil> <nil> <nil>]}
(Last entry is index 75)
And NOT
Update for entity 89: itemId=22389739547
Attribute for entity 89: &{[6 624 624 0 false <nil> <nil> <nil>]}
Attribute for entity 89: &{[7 948.8936 948.8936 0 false <nil> <nil> <nil>]}
Attribute for entity 89: &{[8 0.069185875 0.069185875 0 false <nil> <nil> <nil>]}
Attribute for entity 89: &{[75 4.9426443e+19 4.9426443e+19 0 false <nil> <nil> <nil>]}
Attribute for entity 89: &{[80 6.28e-43 6.28e-43 0 false <nil> <nil> <nil>]} //Related to stattrak, and the gun isn't stattrak
Attribute for entity 89: &{[81 0 0 0 false <nil> <nil> <nil>]} //Related to stattrak, and the gun isn't stattrak
Attribute for entity 89: &{[113 9.675e-42 9.675e-42 0 false <nil> <nil> <nil>]} //Related to Stickers, and gun doesn't have any
Attribute for entity 89: &{[121 9.916e-42 9.916e-42 0 false <nil> <nil> <nil>]} //Related to Stickers, and gun doesn't have any
I tried accessing the entities in a lot of different ways, player inventory etc. - they all have "wrong" m_Attributes for the affected guns.
This isn't to say m_Attributes is always wrong. A lot of guns does get correct values, somehow it just hallucinates other values into some guns.
Library version
Tested with V5 and V4