2026-01-01 22:18:40 -05:00
|
|
|
type materialtechniqueset [display="Material Technique Set"]
|
|
|
|
|
{
|
|
|
|
|
i32 technique_set_name_ptr [ui, readonly, display="Technique Set Name Ptr"];
|
|
|
|
|
|
|
|
|
|
u8 world_vert_format [ui, readonly, display="World Vert Format"];
|
|
|
|
|
u8 has_been_uploaded [ui, readonly, display="Has Been Uploaded"];
|
|
|
|
|
|
2026-01-07 16:36:40 -05:00
|
|
|
skip(2); // padding to align to 4 bytes (total header = 8 bytes)
|
2026-01-01 22:18:40 -05:00
|
|
|
|
|
|
|
|
// Technique count depends on game/platform
|
|
|
|
|
technique_count = 0;
|
|
|
|
|
if (game == "COD4") {
|
|
|
|
|
if (platform == "PC") {
|
|
|
|
|
technique_count = 34;
|
|
|
|
|
}
|
|
|
|
|
if (platform == "XBOX360") {
|
|
|
|
|
technique_count = 26;
|
|
|
|
|
}
|
|
|
|
|
if (platform == "PS3") {
|
|
|
|
|
technique_count = 26;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (game == "COD5") {
|
|
|
|
|
if (platform == "PC") {
|
|
|
|
|
technique_count = 59;
|
|
|
|
|
}
|
|
|
|
|
if (platform == "XBOX360") {
|
|
|
|
|
technique_count = 51;
|
|
|
|
|
}
|
|
|
|
|
if (platform == "PS3") {
|
|
|
|
|
technique_count = 51;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
technique_count = technique_count [ui, readonly, display="Technique Count"];
|
|
|
|
|
|
2026-01-07 16:36:40 -05:00
|
|
|
// Check if this looks like a valid techset
|
|
|
|
|
// In stub/minimal techsets (like in _load files), name_ptr is often a small positive value
|
|
|
|
|
// indicating a reference to another zone. world_vert_format and has_been_uploaded should be 0-1.
|
|
|
|
|
_is_valid_techset = 1;
|
|
|
|
|
if (world_vert_format > 1) {
|
|
|
|
|
_is_valid_techset = 0;
|
2026-01-01 22:18:40 -05:00
|
|
|
}
|
2026-01-07 16:36:40 -05:00
|
|
|
if (has_been_uploaded > 1) {
|
|
|
|
|
_is_valid_techset = 0;
|
2026-01-01 22:18:40 -05:00
|
|
|
}
|
|
|
|
|
|
2026-01-07 16:36:40 -05:00
|
|
|
// Only parse technique pointers and inline data for valid techsets
|
|
|
|
|
if (_is_valid_techset == 1) {
|
|
|
|
|
// Save position after technique count
|
|
|
|
|
_ptrs_start_pos = pos();
|
|
|
|
|
|
|
|
|
|
// Read technique pointers as raw bytes
|
|
|
|
|
if (technique_count > 0) {
|
|
|
|
|
_ptrs_size = technique_count * 4;
|
|
|
|
|
_technique_ptrs_raw = read(_ptrs_size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parse technique set name if inline
|
|
|
|
|
if (technique_set_name_ptr == -1) {
|
|
|
|
|
technique_set_name = cstring() [ui, readonly, display="Technique Set Name"];
|
|
|
|
|
_name = strip(technique_set_name, ",");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Second pass: Parse each technique if ptr == -1 (inline)
|
|
|
|
|
techniques = 0;
|
|
|
|
|
if (technique_count > 0) {
|
|
|
|
|
repeat(technique_count) {
|
|
|
|
|
_ptr_offset = _ptrs_start_pos + (_i * 4);
|
|
|
|
|
_ptr = u32at(_ptr_offset);
|
|
|
|
|
if (_ptr == 4294967295) { // -1 as u32
|
|
|
|
|
_technique = parse_here("materialtechnique");
|
|
|
|
|
techniques = push("techniques", _technique);
|
|
|
|
|
}
|
2026-01-01 22:18:40 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|