Make substructs implicit in arrays
This commit is contained in:
parent
3f9aae51cb
commit
b2a2e9366b
@ -82,12 +82,6 @@ Fast XML-like parser for binary packet structures with versioning and conditiona
|
|||||||
Organize related fields with automatic prefixing:
|
Organize related fields with automatic prefixing:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<group>
|
|
||||||
<i32 name="player_id">
|
|
||||||
<str16 name="player_name">
|
|
||||||
</group>
|
|
||||||
<!-- Creates: player_id, player_name (no prefix added) -->
|
|
||||||
|
|
||||||
<group name="appearance">
|
<group name="appearance">
|
||||||
<color name="skin_color,hair_color,eye_color">
|
<color name="skin_color,hair_color,eye_color">
|
||||||
<str16 name="face_file,hair_file">
|
<str16 name="face_file,hair_file">
|
||||||
@ -101,10 +95,8 @@ Organize related fields with automatic prefixing:
|
|||||||
```xml
|
```xml
|
||||||
<i8 name="item_count">
|
<i8 name="item_count">
|
||||||
<array name="items" count="var:item_count" max_size="100">
|
<array name="items" count="var:item_count" max_size="100">
|
||||||
<substruct>
|
<i32 name="item_id">
|
||||||
<i32 name="item_id">
|
<str16 name="item_name">
|
||||||
<str16 name="item_name">
|
|
||||||
</substruct>
|
|
||||||
</array>
|
</array>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -207,13 +207,13 @@ func (ctx *ParseContext) evaluateCondition(condition string) bool {
|
|||||||
return (ctx.flags & ctx.getFlagValue(flagName)) == 0
|
return (ctx.flags & ctx.getFlagValue(flagName)) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variable conditions: var:name or !var:name
|
// Variable conditions: var:name or !var:name (with %i support)
|
||||||
if strings.HasPrefix(condition, "var:") {
|
if strings.HasPrefix(condition, "var:") {
|
||||||
varName := condition[4:]
|
varName := ctx.resolveVariableName(condition[4:])
|
||||||
return ctx.hasVar(varName)
|
return ctx.hasVar(varName)
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(condition, "!var:") {
|
if strings.HasPrefix(condition, "!var:") {
|
||||||
varName := condition[5:]
|
varName := ctx.resolveVariableName(condition[5:])
|
||||||
return !ctx.hasVar(varName)
|
return !ctx.hasVar(varName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,27 +222,36 @@ func (ctx *ParseContext) evaluateCondition(condition string) bool {
|
|||||||
return ctx.evaluateVersionCondition(condition)
|
return ctx.evaluateVersionCondition(condition)
|
||||||
}
|
}
|
||||||
|
|
||||||
// String length operators: name!>5, name!<=10
|
// Bitwise AND: header_flag&0x01 (with %i support)
|
||||||
|
if strings.Contains(condition, "&0x") {
|
||||||
|
parts := strings.SplitN(condition, "&", 2)
|
||||||
|
varName := ctx.resolveVariableName(parts[0])
|
||||||
|
hexValue, _ := strconv.ParseUint(parts[1], 0, 64)
|
||||||
|
varValue := ctx.getVarValue(varName)
|
||||||
|
return (varValue & hexValue) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// String length operators: name!>5, name!<=10 (with %i support)
|
||||||
stringOps := []string{"!>=", "!<=", "!>", "!<", "!="}
|
stringOps := []string{"!>=", "!<=", "!>", "!<", "!="}
|
||||||
for _, op := range stringOps {
|
for _, op := range stringOps {
|
||||||
if idx := strings.Index(condition, op); idx > 0 {
|
if idx := strings.Index(condition, op); idx > 0 {
|
||||||
varName := condition[:idx]
|
varName := ctx.resolveVariableName(condition[:idx])
|
||||||
valueStr := condition[idx+len(op):]
|
valueStr := condition[idx+len(op):]
|
||||||
return ctx.evaluateStringLength(varName, valueStr, op)
|
return ctx.evaluateStringLength(varName, valueStr, op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparison operators: >=, <=, >, <, ==, !=
|
// Comparison operators: >=, <=, >, <, ==, != (with %i support)
|
||||||
compOps := []string{">=", "<=", ">", "<", "==", "!="}
|
compOps := []string{">=", "<=", ">", "<", "==", "!="}
|
||||||
for _, op := range compOps {
|
for _, op := range compOps {
|
||||||
if idx := strings.Index(condition, op); idx > 0 {
|
if idx := strings.Index(condition, op); idx > 0 {
|
||||||
varName := condition[:idx]
|
varName := ctx.resolveVariableName(condition[:idx])
|
||||||
valueStr := condition[idx+len(op):]
|
valueStr := condition[idx+len(op):]
|
||||||
return ctx.evaluateComparison(varName, valueStr, op)
|
return ctx.evaluateComparison(varName, valueStr, op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple variable existence
|
// Simple variable existence (with %i support)
|
||||||
resolvedName := ctx.resolveVariableName(condition)
|
resolvedName := ctx.resolveVariableName(condition)
|
||||||
return ctx.hasVar(resolvedName)
|
return ctx.hasVar(resolvedName)
|
||||||
}
|
}
|
||||||
@ -394,3 +403,15 @@ func (ctx *ParseContext) resolveVariableName(name string) string {
|
|||||||
}
|
}
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx *ParseContext) setVarWithArrayIndex(name string, value any) {
|
||||||
|
// Always set the base variable name
|
||||||
|
ctx.vars[name] = value
|
||||||
|
|
||||||
|
// If we're in an array context, also set the indexed variable
|
||||||
|
if len(ctx.arrayStack) > 0 {
|
||||||
|
currentIndex := ctx.arrayStack[len(ctx.arrayStack)-1]
|
||||||
|
indexedName := name + "_" + strconv.Itoa(currentIndex)
|
||||||
|
ctx.vars[indexedName] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -520,7 +520,7 @@ func (p *Parser) parseGroup(packetDef *PacketDef, fieldOrder *[]string, prefix s
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles array elements
|
// Handles array elements - FIXED: Remove redundant substruct wrapper
|
||||||
func (p *Parser) parseArray(packetDef *PacketDef, fieldOrder *[]string, prefix string) error {
|
func (p *Parser) parseArray(packetDef *PacketDef, fieldOrder *[]string, prefix string) error {
|
||||||
attrs := p.current.Attributes
|
attrs := p.current.Attributes
|
||||||
|
|
||||||
@ -565,7 +565,8 @@ func (p *Parser) parseArray(packetDef *PacketDef, fieldOrder *[]string, prefix s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.current.Type == TokenSelfCloseTag {
|
// Arrays with substruct references or explicit self-closing syntax are self-closing
|
||||||
|
if p.current.Type == TokenSelfCloseTag || fieldDesc.SubDef != nil {
|
||||||
p.advance()
|
p.advance()
|
||||||
packetDef.Fields[arrayName] = fieldDesc
|
packetDef.Fields[arrayName] = fieldDesc
|
||||||
*fieldOrder = append(*fieldOrder, arrayName)
|
*fieldOrder = append(*fieldOrder, arrayName)
|
||||||
@ -575,30 +576,9 @@ func (p *Parser) parseArray(packetDef *PacketDef, fieldOrder *[]string, prefix s
|
|||||||
p.pushTag("array")
|
p.pushTag("array")
|
||||||
p.advance()
|
p.advance()
|
||||||
|
|
||||||
// If we have a substruct reference and no inline content
|
// Handle direct child elements as substruct fields (no wrapper needed)
|
||||||
if fieldDesc.SubDef != nil && (p.current.Type == TokenCloseTag ||
|
if fieldDesc.SubDef == nil {
|
||||||
(p.current.Type == TokenOpenTag && p.current.Tag(p.input) != "substruct")) {
|
|
||||||
|
|
||||||
if p.current.Type == TokenCloseTag && p.current.Tag(p.input) == "array" {
|
|
||||||
if err := p.popTag("array"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.advance()
|
|
||||||
} else {
|
|
||||||
p.tagStack = p.tagStack[:len(p.tagStack)-1]
|
|
||||||
}
|
|
||||||
packetDef.Fields[arrayName] = fieldDesc
|
|
||||||
*fieldOrder = append(*fieldOrder, arrayName)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle inline substruct
|
|
||||||
if fieldDesc.SubDef == nil && p.current.Type == TokenOpenTag && p.current.Tag(p.input) == "substruct" {
|
|
||||||
subDef := NewPacketDef(16)
|
subDef := NewPacketDef(16)
|
||||||
|
|
||||||
p.pushTag("substruct")
|
|
||||||
p.advance()
|
|
||||||
|
|
||||||
subOrder := fieldOrderPool.Get().(*[]string)
|
subOrder := fieldOrderPool.Get().(*[]string)
|
||||||
*subOrder = (*subOrder)[:0]
|
*subOrder = (*subOrder)[:0]
|
||||||
defer fieldOrderPool.Put(subOrder)
|
defer fieldOrderPool.Put(subOrder)
|
||||||
@ -608,18 +588,12 @@ func (p *Parser) parseArray(packetDef *PacketDef, fieldOrder *[]string, prefix s
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.current.Type == TokenCloseTag && p.current.Tag(p.input) == "substruct" {
|
// Only create substruct if we actually have fields
|
||||||
if err := p.popTag("substruct"); err != nil {
|
if len(*subOrder) > 0 {
|
||||||
return err
|
subDef.Orders[1] = make([]string, len(*subOrder))
|
||||||
}
|
copy(subDef.Orders[1], *subOrder)
|
||||||
p.advance()
|
fieldDesc.SubDef = subDef
|
||||||
} else {
|
|
||||||
return fmt.Errorf("expected closing tag for substruct at line %d", p.current.Line)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subDef.Orders[1] = make([]string, len(*subOrder))
|
|
||||||
copy(subDef.Orders[1], *subOrder)
|
|
||||||
fieldDesc.SubDef = subDef
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.current.Type == TokenCloseTag && p.current.Tag(p.input) == "array" {
|
if p.current.Type == TokenCloseTag && p.current.Tag(p.input) == "array" {
|
||||||
|
@ -182,9 +182,7 @@ func TestArrayMaxSize(t *testing.T) {
|
|||||||
<version number="1">
|
<version number="1">
|
||||||
<i8 name="item_count">
|
<i8 name="item_count">
|
||||||
<array name="items" count="var:item_count" max_size="100">
|
<array name="items" count="var:item_count" max_size="100">
|
||||||
<substruct>
|
<i32 name="item_id">
|
||||||
<i32 name="item_id">
|
|
||||||
</substruct>
|
|
||||||
</array>
|
</array>
|
||||||
</version>
|
</version>
|
||||||
</packet>`
|
</packet>`
|
||||||
@ -207,9 +205,7 @@ func TestArrayOptionalAttributes(t *testing.T) {
|
|||||||
<version number="1">
|
<version number="1">
|
||||||
<i8 name="count">
|
<i8 name="count">
|
||||||
<array name="optional_items" count="var:count" optional="true" add_to_struct="false">
|
<array name="optional_items" count="var:count" optional="true" add_to_struct="false">
|
||||||
<substruct>
|
<i32 name="id">
|
||||||
<i32 name="id">
|
|
||||||
</substruct>
|
|
||||||
</array>
|
</array>
|
||||||
</version>
|
</version>
|
||||||
</packet>`
|
</packet>`
|
||||||
@ -275,10 +271,8 @@ func TestArrayParsing(t *testing.T) {
|
|||||||
<version number="1">
|
<version number="1">
|
||||||
<i8 name="item_count">
|
<i8 name="item_count">
|
||||||
<array name="items" count="var:item_count">
|
<array name="items" count="var:item_count">
|
||||||
<substruct>
|
<i32 name="item_id">
|
||||||
<i32 name="item_id">
|
<str16 name="item_name">
|
||||||
<str16 name="item_name">
|
|
||||||
</substruct>
|
|
||||||
</array>
|
</array>
|
||||||
</version>
|
</version>
|
||||||
</packet>`
|
</packet>`
|
||||||
@ -541,9 +535,7 @@ func TestBinaryParsingArrayMaxSize(t *testing.T) {
|
|||||||
<version number="1">
|
<version number="1">
|
||||||
<i8 name="item_count">
|
<i8 name="item_count">
|
||||||
<array name="items" count="var:item_count" max_size="2">
|
<array name="items" count="var:item_count" max_size="2">
|
||||||
<substruct>
|
<i16 name="item_id">
|
||||||
<i16 name="item_id">
|
|
||||||
</substruct>
|
|
||||||
</array>
|
</array>
|
||||||
</version>
|
</version>
|
||||||
</packet>`
|
</packet>`
|
||||||
@ -567,6 +559,146 @@ func TestBinaryParsingArrayMaxSize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestArrayIndexConditions(t *testing.T) {
|
||||||
|
// Test array index substitution in conditions
|
||||||
|
pml := `<packet name="ArrayConditionTest">
|
||||||
|
<version number="1">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stats" count="var:stat_count">
|
||||||
|
<i8 name="stat_type">
|
||||||
|
<i32 name="base_value">
|
||||||
|
<i32 name="modified_value" if="stat_type_%i>=1&stat_type_%i<=5">
|
||||||
|
<f32 name="percentage" if="stat_type_%i==6">
|
||||||
|
<str16 name="description" if="!var:stat_type_%i">
|
||||||
|
</array>
|
||||||
|
</version>
|
||||||
|
</packet>`
|
||||||
|
|
||||||
|
packets, err := Parse(pml)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
packet := packets["ArrayConditionTest"]
|
||||||
|
|
||||||
|
// Verify fields were parsed correctly
|
||||||
|
statsField := packet.Fields["stats"]
|
||||||
|
if statsField.Type != common.TypeArray {
|
||||||
|
t.Error("stats should be TypeArray")
|
||||||
|
}
|
||||||
|
|
||||||
|
if statsField.SubDef == nil {
|
||||||
|
t.Fatal("SubDef should not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that conditions were preserved
|
||||||
|
modifiedValue := statsField.SubDef.Fields["modified_value"]
|
||||||
|
if modifiedValue.Condition != "stat_type_%i>=1&stat_type_%i<=5" {
|
||||||
|
t.Errorf("Expected 'stat_type_%%i>=1&stat_type_%%i<=5', got '%s'", modifiedValue.Condition)
|
||||||
|
}
|
||||||
|
|
||||||
|
percentage := statsField.SubDef.Fields["percentage"]
|
||||||
|
if percentage.Condition != "stat_type_%i==6" {
|
||||||
|
t.Errorf("Expected 'stat_type_%%i==6', got '%s'", percentage.Condition)
|
||||||
|
}
|
||||||
|
|
||||||
|
description := statsField.SubDef.Fields["description"]
|
||||||
|
if description.Condition != "!var:stat_type_%i" {
|
||||||
|
t.Errorf("Expected '!var:stat_type_%%i', got '%s'", description.Condition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestArrayIndexBinaryParsing(t *testing.T) {
|
||||||
|
// Test that array index conditions work during binary parsing
|
||||||
|
pml := `<packet name="ArrayConditionBinary">
|
||||||
|
<version number="1">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stats" count="var:stat_count">
|
||||||
|
<i8 name="stat_type">
|
||||||
|
<i32 name="base_value">
|
||||||
|
<f32 name="percentage" if="stat_type_%i==6">
|
||||||
|
</array>
|
||||||
|
</version>
|
||||||
|
</packet>`
|
||||||
|
|
||||||
|
packets, err := Parse(pml)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test data: 2 stats, first with type=5, second with type=6
|
||||||
|
// stat_count=2, stat1: type=5, base=100, stat2: type=6, base=200, percentage=1.5
|
||||||
|
testData := []byte{
|
||||||
|
0x02, // stat_count = 2
|
||||||
|
0x05, 0x64, 0x00, 0x00, 0x00, // stat 1: type=5, base=100 (no percentage)
|
||||||
|
0x06, 0xC8, 0x00, 0x00, 0x00, // stat 2: type=6, base=200
|
||||||
|
0x00, 0x00, 0xC0, 0x3F, // percentage=1.5 (float32)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := packets["ArrayConditionBinary"].Parse(testData, 1, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Binary parse failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stats := result["stats"].([]map[string]any)
|
||||||
|
if len(stats) != 2 {
|
||||||
|
t.Fatalf("Expected 2 stats, got %d", len(stats))
|
||||||
|
}
|
||||||
|
|
||||||
|
// First stat (type=5) should not have percentage field
|
||||||
|
stat1 := stats[0]
|
||||||
|
if stat1["stat_type"].(uint8) != 5 {
|
||||||
|
t.Errorf("Expected stat_type 5, got %d", stat1["stat_type"])
|
||||||
|
}
|
||||||
|
if _, hasPercentage := stat1["percentage"]; hasPercentage {
|
||||||
|
t.Error("Stat type 5 should not have percentage field")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second stat (type=6) should have percentage field
|
||||||
|
stat2 := stats[1]
|
||||||
|
if stat2["stat_type"].(uint8) != 6 {
|
||||||
|
t.Errorf("Expected stat_type 6, got %d", stat2["stat_type"])
|
||||||
|
}
|
||||||
|
if percentage, hasPercentage := stat2["percentage"]; !hasPercentage {
|
||||||
|
t.Error("Stat type 6 should have percentage field")
|
||||||
|
} else if percentage.(float32) < 1.4 || percentage.(float32) > 1.6 {
|
||||||
|
t.Errorf("Expected percentage around 1.5, got %f", percentage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComplexArrayConditions(t *testing.T) {
|
||||||
|
// Test complex conditions with array indices
|
||||||
|
pml := `<packet name="ComplexArrayTest">
|
||||||
|
<version number="1">
|
||||||
|
<i8 name="item_count">
|
||||||
|
<array name="items" count="var:item_count">
|
||||||
|
<i16 name="item_type">
|
||||||
|
<i32 name="item_flags">
|
||||||
|
<i8 name="enhancement" if="item_type_%i!=0&item_flags_%i&0x01">
|
||||||
|
<color name="special_color" if="item_type_%i>=100,item_flags_%i&0x02">
|
||||||
|
</array>
|
||||||
|
</version>
|
||||||
|
</packet>`
|
||||||
|
|
||||||
|
packets, err := Parse(pml)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
packet := packets["ComplexArrayTest"]
|
||||||
|
itemsField := packet.Fields["items"]
|
||||||
|
|
||||||
|
enhancement := itemsField.SubDef.Fields["enhancement"]
|
||||||
|
if enhancement.Condition != "item_type_%i!=0&item_flags_%i&0x01" {
|
||||||
|
t.Errorf("Enhancement condition wrong: %s", enhancement.Condition)
|
||||||
|
}
|
||||||
|
|
||||||
|
specialColor := itemsField.SubDef.Fields["special_color"]
|
||||||
|
if specialColor.Condition != "item_type_%i>=100,item_flags_%i&0x02" {
|
||||||
|
t.Errorf("Special color condition wrong: %s", specialColor.Condition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestErrorHandling(t *testing.T) {
|
func TestErrorHandling(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -616,21 +748,17 @@ func BenchmarkComplexPacketWithNewFeatures(b *testing.B) {
|
|||||||
<i32 name="guild_id" if="flag:has_guild">
|
<i32 name="guild_id" if="flag:has_guild">
|
||||||
<i8 name="equipment_count">
|
<i8 name="equipment_count">
|
||||||
<array name="equipment" count="var:equipment_count" max_size="50">
|
<array name="equipment" count="var:equipment_count" max_size="50">
|
||||||
<substruct>
|
<i16 name="slot_id,item_type">
|
||||||
<i16 name="slot_id,item_type">
|
<color name="primary_color,secondary_color">
|
||||||
<color name="primary_color,secondary_color">
|
<i8 name="enhancement_level" if="item_type!=0">
|
||||||
<i8 name="enhancement_level" if="item_type!=0">
|
<i32 name="stat_value" type2="f32" type2_if="item_type==6" oversized="255">
|
||||||
<i32 name="stat_value" type2="f32" type2_if="item_type==6" oversized="255">
|
|
||||||
</substruct>
|
|
||||||
</array>
|
</array>
|
||||||
<i8 name="stat_count">
|
<i8 name="stat_count">
|
||||||
<array name="stats" count="var:stat_count" optional="true">
|
<array name="stats" count="var:stat_count" optional="true">
|
||||||
<substruct>
|
<i8 name="stat_type">
|
||||||
<i8 name="stat_type">
|
<i32 name="base_value">
|
||||||
<i32 name="base_value">
|
<i32 name="modified_value" if="stat_type>=1&stat_type<=5">
|
||||||
<i32 name="modified_value" if="stat_type>=1&stat_type<=5">
|
<f64 name="percentage" if="stat_type==6">
|
||||||
<f64 name="percentage" if="stat_type==6">
|
|
||||||
</substruct>
|
|
||||||
</array>
|
</array>
|
||||||
</version>
|
</version>
|
||||||
</packet>`
|
</packet>`
|
||||||
|
@ -31,7 +31,7 @@ func (def *PacketDef) parseStruct(ctx *ParseContext) (map[string]any, error) {
|
|||||||
|
|
||||||
value := def.parseField(ctx, field, fieldType, fieldName)
|
value := def.parseField(ctx, field, fieldType, fieldName)
|
||||||
result[fieldName] = value
|
result[fieldName] = value
|
||||||
ctx.setVar(fieldName, value)
|
ctx.setVarWithArrayIndex(fieldName, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
39
internal/packets/substructs/AASpellInfo.xml
Normal file
39
internal/packets/substructs/AASpellInfo.xml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<substruct name="AASpellInfo">
|
||||||
|
<version number="1193">
|
||||||
|
<i32 name="id">
|
||||||
|
<i16 name="icon,icon2,icontype,version,sub_version">
|
||||||
|
<i8 name="type">
|
||||||
|
<i32 name="class_skill,mastery_skill">
|
||||||
|
<i16 name="min_class_skill_req" oversized="127">
|
||||||
|
<i32 name="spell_text_color">
|
||||||
|
<i8 name="unknown_605_MJ_3,tier">
|
||||||
|
<i16 name="health_req,health_upkeep,power_req,power_upkeep" oversized="127">
|
||||||
|
<i16 name="req_concentration,unknown">
|
||||||
|
<i16 name="cast_time,recovery" oversized="127">
|
||||||
|
<f32 name="recast,radius">
|
||||||
|
<i16 name="max_aoe_targets">
|
||||||
|
<i8 name="friendly_spell,num_reagents">
|
||||||
|
<array name="reagent_array" count="var:num_reagents">
|
||||||
|
<str8 name="reagent">
|
||||||
|
<i8 name="consumed">
|
||||||
|
<i32 name="qty_required">
|
||||||
|
</array>
|
||||||
|
<i8 name="num_effects">
|
||||||
|
<array name="effect_array" count="var:num_effects">
|
||||||
|
<i8 name="subbulletflag">
|
||||||
|
<str16 name="effect">
|
||||||
|
<i8 name="percentage">
|
||||||
|
</array>
|
||||||
|
<i8 name="display_spell_tier,unknown1">
|
||||||
|
<f32 name="minimum_range,range">
|
||||||
|
<i32 name="duration1,duration2">
|
||||||
|
<i8 name="unknown9,duration_flag,target,can_effect_raid,affect_only_group_members,group_spell">
|
||||||
|
<f32 name="resistibility">
|
||||||
|
<i8 name="unknown11" size="7">
|
||||||
|
<f32 name="hit_bonus">
|
||||||
|
<i8 name="unknown12">
|
||||||
|
<str8 name="name">
|
||||||
|
<str16 name="description">
|
||||||
|
<i8 name="unknown_605_MJ_6">
|
||||||
|
</version>
|
||||||
|
</substruct>
|
484
internal/packets/substructs/BaseItemDescription.xml
Normal file
484
internal/packets/substructs/BaseItemDescription.xml
Normal file
@ -0,0 +1,484 @@
|
|||||||
|
<substruct name="BaseItemDescription">
|
||||||
|
<version number="1">
|
||||||
|
<i8 name="creator_flag">
|
||||||
|
<str16 name="creator">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i16 name="icon">
|
||||||
|
<str8 name="flag_names">
|
||||||
|
<i8 name="unknown8_1" size="17">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i16 name="stat_type" oversized="127">
|
||||||
|
<si16 name="stat_subtype" oversized="127">
|
||||||
|
<si16 name="value" oversized="127">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
</array>
|
||||||
|
<i8 name="stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
<i8 name="adornment_flag">
|
||||||
|
<array name="adornment_array" count="var:adornment_flag">
|
||||||
|
<i8 name="adornment_unknown">
|
||||||
|
</array>
|
||||||
|
<str16 name="stat_description">
|
||||||
|
</array>
|
||||||
|
<i8 name="condition">
|
||||||
|
<i16 name="weight" oversized="127">
|
||||||
|
<i32 name="skill_req1">
|
||||||
|
<i16 name="skill_min,skill_recommended" oversized="127">
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version number="373">
|
||||||
|
<i8 name="creator_flag">
|
||||||
|
<str16 name="creator">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i16 name="icon">
|
||||||
|
<i8 name="tier">
|
||||||
|
<str8 name="flag_names">
|
||||||
|
<i8 name="unknown8_1" size="17">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i16 name="stat_type" oversized="127">
|
||||||
|
<si16 name="stat_subtype" oversized="127">
|
||||||
|
<si16 name="value" oversized="127">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
</array>
|
||||||
|
<i8 name="stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
<i8 name="adornment_flag">
|
||||||
|
<array name="adornment_array" count="var:adornment_flag">
|
||||||
|
<i8 name="adornment_unknown">
|
||||||
|
</array>
|
||||||
|
<str16 name="stat_description">
|
||||||
|
</array>
|
||||||
|
<i8 name="condition">
|
||||||
|
<i16 name="weight" oversized="127">
|
||||||
|
<i32 name="skill_req1,skill_req2">
|
||||||
|
<i16 name="skill_min,skill_recommended" oversized="127">
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version number="546">
|
||||||
|
<str8 name="creator">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i64 name="broker_item_id">
|
||||||
|
<i16 name="icon">
|
||||||
|
<i8 name="tier">
|
||||||
|
<i32 name="flags">
|
||||||
|
<i8 name="unknown8_1" size="15">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i8 name="stat_type">
|
||||||
|
<si16 name="stat_subtype" oversized="127">
|
||||||
|
<si16 name="value" oversized="127">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
</array>
|
||||||
|
<i8 name="stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
</array>
|
||||||
|
<i8 name="condition">
|
||||||
|
<i16 name="weight" oversized="127">
|
||||||
|
<i32 name="skill_req1,skill_req2">
|
||||||
|
<i16 name="skill_min">
|
||||||
|
<i8 name="class_count">
|
||||||
|
<array name="class_array" count="var:class_count">
|
||||||
|
<i8 name="adventure_class,tradeskill_class">
|
||||||
|
<i16 name="level">
|
||||||
|
</array>
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
<i32 name="footer_type">
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version number="562">
|
||||||
|
<i8 name="creator_flag">
|
||||||
|
<str8 name="creator">
|
||||||
|
<str16 name="adornment">
|
||||||
|
<i32 name="adornment_id,unknown3">
|
||||||
|
<str16 name="first_desc">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i64 name="broker_item_id">
|
||||||
|
<si32 name="item_id">
|
||||||
|
<i16 name="icon">
|
||||||
|
<i8 name="tier">
|
||||||
|
<i32 name="flags">
|
||||||
|
<i8 name="unknown8_1" size="17">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i16 name="stat_type" oversized="127">
|
||||||
|
<si16 name="stat_subtype" oversized="127">
|
||||||
|
<si16 name="value" oversized="127">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
</array>
|
||||||
|
<i8 name="stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
<i8 name="adornment_flag">
|
||||||
|
<array name="adornment_array" count="var:adornment_flag">
|
||||||
|
<i8 name="adornment_unknown">
|
||||||
|
</array>
|
||||||
|
<str16 name="stat_description">
|
||||||
|
</array>
|
||||||
|
<i8 name="condition">
|
||||||
|
<i32 name="weight">
|
||||||
|
<i32 name="skill_req1,skill_req2">
|
||||||
|
<i16 name="skill_min" oversized="127">
|
||||||
|
<i8 name="class_count">
|
||||||
|
<array name="class_array" count="var:class_count">
|
||||||
|
<i8 name="adventure_class,tradeskill_class">
|
||||||
|
<i16 name="level">
|
||||||
|
</array>
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
<i32 name="footer_type">
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version number="860">
|
||||||
|
<i8 name="creator_flag">
|
||||||
|
<str8 name="creator">
|
||||||
|
<str16 name="adornment">
|
||||||
|
<i32 name="adornment_id,unknown3">
|
||||||
|
<str16 name="adornment_desc,unknown_desc,first_desc">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i64 name="broker_item_id">
|
||||||
|
<si32 name="item_id">
|
||||||
|
<i16 name="icon">
|
||||||
|
<i8 name="tier">
|
||||||
|
<i32 name="flags">
|
||||||
|
<i8 name="unknown8_860" size="17">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i16 name="stat_type" oversized="127">
|
||||||
|
<si16 name="stat_subtype" oversized="127">
|
||||||
|
<si16 name="value" oversized="127">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
</array>
|
||||||
|
<i8 name="stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
<i8 name="adornment_flag">
|
||||||
|
<array name="adornment_array" count="var:adornment_flag">
|
||||||
|
<i8 name="adornment_unknown">
|
||||||
|
</array>
|
||||||
|
<str16 name="stat_description">
|
||||||
|
</array>
|
||||||
|
<i8 name="condition">
|
||||||
|
<i32 name="weight,skill_req1,skill_req2">
|
||||||
|
<i16 name="skill_min" oversized="127">
|
||||||
|
<i8 name="class_count">
|
||||||
|
<array name="class_array" count="var:class_count">
|
||||||
|
<i8 name="adventure_class,tradeskill_class">
|
||||||
|
<i16 name="level">
|
||||||
|
</array>
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
<i32 name="footer_type">
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version number="1096">
|
||||||
|
<i8 name="creator_flag">
|
||||||
|
<str8 name="creator">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i64 name="broker_item_id">
|
||||||
|
<si32 name="item_id,item_crc">
|
||||||
|
<i16 name="icon">
|
||||||
|
<i8 name="tier">
|
||||||
|
<i16 name="flags,flags2">
|
||||||
|
<i8 name="unknown8_BID_1096" size="17">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i16 name="stat_type" oversized="127">
|
||||||
|
<si16 name="stat_subtype" oversized="127">
|
||||||
|
<f32 name="value" type2="si16" type2_if="stat_type!=6" oversized="127">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
</array>
|
||||||
|
<i8 name="stat_unknown,stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
<str16 name="stat_description">
|
||||||
|
<i8 name="stat_string_unknown">
|
||||||
|
</array>
|
||||||
|
<i16 name="unknown19,unknown20">
|
||||||
|
<i8 name="condition">
|
||||||
|
<i32 name="weight,skill_req1,skill_req2">
|
||||||
|
<i16 name="skill_min" oversized="127">
|
||||||
|
<i8 name="class_count">
|
||||||
|
<array name="class_array" count="var:class_count">
|
||||||
|
<i8 name="adventure_class,tradeskill_class">
|
||||||
|
<i16 name="level">
|
||||||
|
</array>
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
<i32 name="footer_type">
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version number="1188">
|
||||||
|
<i8 name="creator_flag">
|
||||||
|
<str8 name="creator">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i64 name="broker_item_id">
|
||||||
|
<si32 name="item_id,item_crc">
|
||||||
|
<i16 name="icon">
|
||||||
|
<i8 name="tier">
|
||||||
|
<i16 name="flags,flags2">
|
||||||
|
<i8 name="unknown8_1188" size="17">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i16 name="stat_type" oversized="127">
|
||||||
|
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||||
|
<f32 name="value" type2="si16" type2_if="stat_type!=6" oversized="127">
|
||||||
|
<i8 name="stat_unknown" if="var:stat_type_%i">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
<i8 name="stat_level">
|
||||||
|
</array>
|
||||||
|
<i8 name="stat_unknown,stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
<i8 name="stat_string_unknown">
|
||||||
|
<str16 name="stat_description">
|
||||||
|
</array>
|
||||||
|
<i16 name="unknown19,unknown20">
|
||||||
|
<i8 name="condition">
|
||||||
|
<i32 name="weight,skill_req1,skill_req2">
|
||||||
|
<i16 name="skill_min" oversized="127">
|
||||||
|
<i8 name="class_count">
|
||||||
|
<array name="class_array" count="var:class_count">
|
||||||
|
<i8 name="adventure_class,tradeskill_class">
|
||||||
|
<i16 name="level">
|
||||||
|
</array>
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
<i32 name="footer_type">
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version number="1208">
|
||||||
|
<i8 name="creator_flag">
|
||||||
|
<str8 name="creator">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i64 name="broker_item_id">
|
||||||
|
<si32 name="item_id,item_crc">
|
||||||
|
<i16 name="icon">
|
||||||
|
<i8 name="tier">
|
||||||
|
<i16 name="flags,flags2">
|
||||||
|
<i8 name="unknown8_1208" size="17">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i16 name="stat_type" oversized="127">
|
||||||
|
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||||
|
<f32 name="value" type2="si16" type2_if="stat_type!=6" oversized="127">
|
||||||
|
<i8 name="stat_unknown" if="var:stat_type_%i">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
<i16 name="stat_level" type2="i8" type2_if="stat_name!>2">
|
||||||
|
</array>
|
||||||
|
<i8 name="stat_unknown,stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
<i8 name="stat_string_unknown">
|
||||||
|
<str16 name="stat_description">
|
||||||
|
</array>
|
||||||
|
<i16 name="unknown19,unknown20">
|
||||||
|
<i8 name="condition">
|
||||||
|
<i32 name="weight,skill_req1,skill_req2">
|
||||||
|
<i16 name="skill_min" oversized="127">
|
||||||
|
<i8 name="class_count">
|
||||||
|
<array name="class_array" count="var:class_count">
|
||||||
|
<i8 name="adventure_class,tradeskill_class">
|
||||||
|
<i16 name="level">
|
||||||
|
</array>
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
<i32 name="footer_type">
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version number="58571">
|
||||||
|
<i8 name="creator_flag">
|
||||||
|
<str8 name="creator">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i64 name="broker_item_id">
|
||||||
|
<si32 name="item_id,item_crc">
|
||||||
|
<i16 name="icon">
|
||||||
|
<i8 name="tier">
|
||||||
|
<i16 name="flags,flags2">
|
||||||
|
<i8 name="unknown8_58570" size="17">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i16 name="stat_type" oversized="127">
|
||||||
|
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||||
|
<f32 name="value" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
<i16 name="stat_level" type2="i8" type2_if="stat_name!>2">
|
||||||
|
</array>
|
||||||
|
<i8 name="stat_unknown,stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
<i8 name="stat_string_unknown">
|
||||||
|
<str16 name="stat_description">
|
||||||
|
</array>
|
||||||
|
<i16 name="unknown19,unknown20">
|
||||||
|
<i8 name="condition">
|
||||||
|
<i32 name="weight,skill_req1,skill_req2">
|
||||||
|
<i16 name="skill_min" oversized="127">
|
||||||
|
<i8 name="class_count">
|
||||||
|
<array name="class_array" count="var:class_count">
|
||||||
|
<i8 name="adventure_class,tradeskill_class">
|
||||||
|
<i16 name="level">
|
||||||
|
</array>
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
<i32 name="footer_type">
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version number="58617">
|
||||||
|
<i8 name="creator_flag">
|
||||||
|
<str8 name="creator">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i64 name="broker_item_id">
|
||||||
|
<si32 name="item_id,item_crc">
|
||||||
|
<i16 name="icon">
|
||||||
|
<i8 name="tier">
|
||||||
|
<i16 name="flags,flags2">
|
||||||
|
<i8 name="unknown8_58617" size="17">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i16 name="stat_type" oversized="127">
|
||||||
|
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||||
|
<f32 name="value" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
<i16 name="stat_level" type2="i8" type2_if="stat_name!>2">
|
||||||
|
<f32 name="value2" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||||
|
</array>
|
||||||
|
<i8 name="stat_unknown,stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
<i8 name="stat_string_unknown">
|
||||||
|
<str16 name="stat_description">
|
||||||
|
</array>
|
||||||
|
<i16 name="unknown19,unknown20">
|
||||||
|
<i8 name="condition">
|
||||||
|
<i32 name="weight,skill_req1,skill_req2">
|
||||||
|
<i16 name="skill_min" oversized="127">
|
||||||
|
<i8 name="class_count">
|
||||||
|
<array name="class_array" count="var:class_count">
|
||||||
|
<i8 name="adventure_class,tradeskill_class">
|
||||||
|
<i16 name="level">
|
||||||
|
</array>
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
<i32 name="footer_type">
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version number="60174">
|
||||||
|
<i8 name="creator_flag">
|
||||||
|
<str8 name="creator">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i64 name="broker_item_id">
|
||||||
|
<si32 name="item_id,item_crc">
|
||||||
|
<i16 name="icon">
|
||||||
|
<i8 name="tier">
|
||||||
|
<i16 name="flags,flags2">
|
||||||
|
<i8 name="unknown8_60174" size="17">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i16 name="stat_type" oversized="127">
|
||||||
|
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||||
|
<f32 name="value" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
<i16 name="stat_level" type2="i8" type2_if="stat_name!>2">
|
||||||
|
</array>
|
||||||
|
<i8 name="stat_unknown,stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
<i8 name="stat_string_unknown">
|
||||||
|
<str16 name="stat_description">
|
||||||
|
</array>
|
||||||
|
<i16 name="unknown19,unknown20">
|
||||||
|
<i32 name="unknown21">
|
||||||
|
<i8 name="condition">
|
||||||
|
<i32 name="weight,skill_req1,skill_req2">
|
||||||
|
<i16 name="skill_min" oversized="127">
|
||||||
|
<i8 name="class_count">
|
||||||
|
<array name="class_array" count="var:class_count">
|
||||||
|
<i8 name="adventure_class,tradeskill_class">
|
||||||
|
<i16 name="level">
|
||||||
|
</array>
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
<i32 name="footer_type">
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version number="63119">
|
||||||
|
<i8 name="creator_flag">
|
||||||
|
<str8 name="creator">
|
||||||
|
<i32 name="unique_id">
|
||||||
|
<i64 name="broker_item_id">
|
||||||
|
<si32 name="item_id,item_crc">
|
||||||
|
<i16 name="icon">
|
||||||
|
<i8 name="tier">
|
||||||
|
<i16 name="flags,flags2">
|
||||||
|
<i8 name="unknown8_63119" size="17">
|
||||||
|
<i8 name="stat_unknown,stat_string_count">
|
||||||
|
<array name="stat_string_array" count="var:stat_string_count">
|
||||||
|
<str8 name="stat_string">
|
||||||
|
<i8 name="stat_string_unknown">
|
||||||
|
<str16 name="stat_description">
|
||||||
|
</array>
|
||||||
|
<i16 name="unknown19">
|
||||||
|
<i8 name="stat_count">
|
||||||
|
<array name="stat_array" count="var:stat_count">
|
||||||
|
<i16 name="stat_type" oversized="127">
|
||||||
|
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||||
|
<f32 name="value" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||||
|
<str8 name="stat_name">
|
||||||
|
<i16 name="stat_level" type2="i8" type2_if="stat_name!>2">
|
||||||
|
<f32 name="value2" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||||
|
</array>
|
||||||
|
<i8 name="unknown20,mod_count">
|
||||||
|
<array name="mod_array" count="var:mod_count">
|
||||||
|
<str8 name="mod_string">
|
||||||
|
<i8 name="mod_need">
|
||||||
|
<i8 name="mod_have" if="var:header_info_mod_need_0">
|
||||||
|
<i8 name="mod_unknown" size="2">
|
||||||
|
</array>
|
||||||
|
<i8 name="unknown21" size="4">
|
||||||
|
<i8 name="condition">
|
||||||
|
<i32 name="weight,skill_req1,skill_req2">
|
||||||
|
<i16 name="skill_min" oversized="127">
|
||||||
|
<i8 name="class_count">
|
||||||
|
<array name="class_array" count="var:class_count">
|
||||||
|
<i8 name="adventure_class,tradeskill_class">
|
||||||
|
<i16 name="level">
|
||||||
|
</array>
|
||||||
|
<i8 name="slot_count">
|
||||||
|
<array name="slot_array" count="var:slot_count">
|
||||||
|
<i8 name="slot">
|
||||||
|
</array>
|
||||||
|
<i32 name="footer_type">
|
||||||
|
</version>
|
||||||
|
</substruct>
|
Loading…
x
Reference in New Issue
Block a user