Example #1
0
        /* Read all flowgraphs from the PAK */
        private void ReadFlowgraphs(BinaryReader reader)
        {
            int scriptStart = parameter_offsets[parameter_offsets.Length - 1] + 8; //Relies on the last param always being 4 in length

            for (int i = 0; i < flowgraph_count; i++)
            {
                CathodeFlowgraph flowgraph = new CathodeFlowgraph();

                //Game doesn't parse the script name, so there's no real nice way of grabbing it!!
                reader.BaseStream.Position = scriptStart;
                flowgraph.globalID         = reader.ReadUInt32();
                string name = "";
                while (true)
                {
                    byte thisByte = reader.ReadByte();
                    if (thisByte == 0x00)
                    {
                        break;
                    }
                    name += (char)thisByte;
                }
                flowgraph.name = name;
                scriptStart    = flowgraph_offsets[i] + 116;
                //End of crappy namegrab

                reader.BaseStream.Position  = flowgraph_offsets[i];
                reader.BaseStream.Position += 4; //Skip 0x00,0x00,0x00,0x00

                //Read the offsets and counts
                List <OffsetPair> offsetPairs = new List <OffsetPair>();
                for (int x = 0; x < 13; x++)
                {
                    if (x == 0)
                    {
                        flowgraph.uniqueID = reader.ReadUInt32();
                    }
                    if (x == 1)
                    {
                        flowgraph.nodeID = reader.ReadUInt32();
                    }
                    OffsetPair newPair = new OffsetPair();
                    newPair.GlobalOffset = reader.ReadInt32() * 4;
                    newPair.EntryCount   = reader.ReadInt32();
                    offsetPairs.Add(newPair);
                }

                //Pull data from those offsets
                for (int x = 0; x < offsetPairs.Count; x++)
                {
                    reader.BaseStream.Position = offsetPairs[x].GlobalOffset;
                    for (int y = 0; y < offsetPairs[x].EntryCount; y++)
                    {
                        switch ((CathodeScriptBlocks)x)
                        {
                        case CathodeScriptBlocks.DEFINE_NODE_LINKS:
                        {
                            reader.BaseStream.Position = offsetPairs[x].GlobalOffset + (y * 12);
                            UInt32 parentID = reader.ReadUInt32();

                            int OffsetToFindParams = reader.ReadInt32() * 4;
                            int NumberOfParams     = reader.ReadInt32();

                            for (int z = 0; z < NumberOfParams; z++)
                            {
                                reader.BaseStream.Position = OffsetToFindParams + (z * 16);
                                CathodeNodeLink newLink = new CathodeNodeLink();
                                newLink.connectionID  = reader.ReadUInt32();
                                newLink.parentParamID = reader.ReadUInt32();
                                newLink.childParamID  = reader.ReadUInt32();
                                newLink.childID       = reader.ReadUInt32();
                                newLink.parentID      = parentID;
                                flowgraph.links.Add(newLink);
                            }
                            break;
                        }

                        case CathodeScriptBlocks.DEFINE_NODE_PARAMETERS:
                        {
                            reader.BaseStream.Position = offsetPairs[x].GlobalOffset + (y * 12);
                            CathodeNodeEntity thisNode = flowgraph.GetNodeByID(reader.ReadUInt32());

                            int OffsetToFindParams = reader.ReadInt32() * 4;
                            int NumberOfParams     = reader.ReadInt32();

                            for (int z = 0; z < NumberOfParams; z++)
                            {
                                reader.BaseStream.Position = OffsetToFindParams + (z * 8);
                                CathodeParameterReference thisParamRef = new CathodeParameterReference();
                                thisParamRef.paramID    = reader.ReadUInt32();
                                thisParamRef.editOffset = (int)reader.BaseStream.Position;
                                thisParamRef.offset     = reader.ReadInt32() * 4;
                                thisNode.nodeParameterReferences.Add(thisParamRef);
                            }
                            break;
                        }

                        //NOT PARSING: This appears to define links to EnvironmentModelReference nodes through flowgraph ref nodes
                        case CathodeScriptBlocks.DEFINE_ENV_MODEL_REF_LINKS:
                        {
                            break;
                            reader.BaseStream.Position = offsetPairs[x].GlobalOffset + (y * 12);

                            //This block defines some kind of ID, then an offset and a count of data at that offset
                            byte[] thisID             = reader.ReadBytes(4);
                            int    OffsetToFindParams = reader.ReadInt32() * 4;
                            int    NumberOfParams     = reader.ReadInt32();

                            //We jump to that offset, and read the x-ref listing
                            reader.BaseStream.Position = OffsetToFindParams;
                            List <byte[]> content = new List <byte[]>();
                            for (int z = 0; z < NumberOfParams; z++)
                            {
                                content.Add(reader.ReadBytes(4));     //cross-refs: node ids (of flowgraph refs), then the EnvironmentModelReference node, then 0x00 (x4)
                            }
                            break;
                        }

                        //NOT PARSING: This block is only 8 bytes - first 4 is an ID for the block above, second is an ID not used anywhere else - potentially four 1-byte numbers?
                        case CathodeScriptBlocks.DEFINE_ENV_MODEL_REF_LINKS_EXTRA:
                        {
                            break;
                            reader.BaseStream.Position = offsetPairs[x].GlobalOffset + (y * 8);
                            byte[] linkID = reader.ReadBytes(4);   //ID from DEFINE_ENV_MODEL_REF_LINKS (is this actually a node id?)
                            byte[] unk2   = reader.ReadBytes(4);   //Dunno what this is, only appears to ever be used once
                            break;
                        }

                        case CathodeScriptBlocks.DEFINE_NODE_DATATYPES:
                        {
                            reader.BaseStream.Position = offsetPairs[x].GlobalOffset + (y * 12);

                            CathodeNodeEntity thisNode = flowgraph.GetNodeByID(reader.ReadUInt32());
                            thisNode.dataType      = GetDataType(reader.ReadBytes(4));
                            thisNode.dataTypeParam = reader.ReadUInt32();
                            break;
                        }

                        //NOT PARSING: This block is another x-ref list, potentially related to mission critical things (doors, maybe?)
                        case CathodeScriptBlocks.DEFINE_LINKED_NODES:
                        {
                            break;
                            //This block appears to be populated mainly in mission flowgraphs, rather than other ones like archetypes or model placement
                            //It defines a node from another flowgraph, which is referenced by executation hierarchy
                            reader.BaseStream.Position = offsetPairs[x].GlobalOffset + (y * 20);

                            byte[] unk1 = reader.ReadBytes(4);               //flowgraph id?

                            int OffsetToFindParams = reader.ReadInt32() * 4; //offset
                            int NumberOfParams     = reader.ReadInt32();     //count

                            int resetPos = (int)reader.BaseStream.Position;
                            reader.BaseStream.Position = OffsetToFindParams;
                            for (int p = 0; p < NumberOfParams; p++)
                            {
                                byte[] unk69 = reader.ReadBytes(4);     //cross-refs: node ids (of flowgraph refs), then the node, then 0x00 (x4)
                            }

                            reader.BaseStream.Position = resetPos;
                            byte[] unk4 = reader.ReadBytes(4);     //flowgraph id again
                            byte[] unk5 = reader.ReadBytes(4);     //another id for something else

                            break;
                        }

                        case CathodeScriptBlocks.DEFINE_NODE_NODETYPES:
                        {
                            CathodeNodeEntity thisNode = flowgraph.GetNodeByID(reader.ReadUInt32());
                            thisNode.nodeType = reader.ReadUInt32();
                            break;
                        }

                        //PARSING: I'm currently unsure on a lot of this, as the types vary (see entryType)
                        case CathodeScriptBlocks.DEFINE_RENDERABLE_ELEMENTS:
                        {
                            reader.BaseStream.Position = offsetPairs[x].GlobalOffset + (y * 40);

                            //TODO: these values change by entry type - need to work out what they're for before allowing editing
                            CathodeResourceReference resource_ref = new CathodeResourceReference();
                            resource_ref.editOffset     = (int)reader.BaseStream.Position;
                            resource_ref.resourceRefID  = reader.ReadUInt32();                                                        //renderable element ID (also used in one of the param blocks for something)
                            reader.BaseStream.Position += 4;                                                                          //unk (always 0x00 x4?)
                            resource_ref.positionOffset = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); //position offset
                            reader.BaseStream.Position += 4;                                                                          //unk (always 0x00 x4?)
                            resource_ref.resourceID     = reader.ReadUInt32();                                                        //resource id
                            resource_ref.entryType      = GetResourceEntryType(reader.ReadBytes(4));                                  //entry type
                            switch (resource_ref.entryType)
                            {
                            case CathodeResourceReferenceType.RENDERABLE_INSTANCE:
                                resource_ref.entryIndexREDS = reader.ReadInt32();         //REDS.BIN entry index
                                resource_ref.entryCountREDS = reader.ReadInt32();         //REDS.BIN entry count
                                break;

                            case CathodeResourceReferenceType.COLLISION_MAPPING:
                                resource_ref.unknownInteger = reader.ReadInt32();  //unknown integer (COLLISION.MAP index?)
                                resource_ref.nodeID         = reader.ReadUInt32(); //ID which maps to the node using the resource (?) - check GetFriendlyName
                                break;

                            case CathodeResourceReferenceType.EXCLUSIVE_MASTER_STATE_RESOURCE:
                            case CathodeResourceReferenceType.NAV_MESH_BARRIER_RESOURCE:
                            case CathodeResourceReferenceType.TRAVERSAL_SEGMENT:
                                reader.BaseStream.Position += 8;         //just two -1 32-bit integers for some reason
                                break;

                            case CathodeResourceReferenceType.ANIMATED_MODEL:
                            case CathodeResourceReferenceType.DYNAMIC_PHYSICS_SYSTEM:
                                resource_ref.unknownInteger = reader.ReadInt32();         //unknown integer
                                reader.BaseStream.Position += 4;
                                break;
                            }
                            flowgraph.resources.Add(resource_ref);
                            break;
                        }

                        //NOT PARSING: This is very similar in format to DEFINE_ENV_MODEL_REF_LINKS with the cross-references
                        case CathodeScriptBlocks.UNKNOWN_8:
                        {
                            break;
                            //This block is only four bytes - which translates to a pointer to another location... so read that
                            reader.BaseStream.Position = offsetPairs[x].GlobalOffset + (y * 4);
                            int offsetPos = reader.ReadInt32() * 4;

                            //Jump to the pointer location - this defines a node ID and another offset with count
                            reader.BaseStream.Position = offsetPos;
                            CathodeNodeEntity thisNode = flowgraph.GetNodeByID(reader.ReadUInt32());     //These always seem to be animation related nodes
                            int OffsetToFindParams     = reader.ReadInt32() * 4;
                            int NumberOfParams         = reader.ReadInt32();

                            //Now we jump to THAT pointer's location, and iterate by count. The blocks here are of length 32.
                            for (int z = 0; z < NumberOfParams; z++)
                            {
                                reader.BaseStream.Position = OffsetToFindParams + (z * 32);

                                //First 4: unknown id
                                byte[] unk1 = reader.ReadBytes(4);

                                //Second 4: datatype
                                byte[]          datatype1           = reader.ReadBytes(4);
                                CathodeDataType datatype1_converted = GetDataType(datatype1);

                                //Third 4: unknown id
                                byte[] unk2 = reader.ReadBytes(4);

                                //Fourth 4: parameter id
                                byte[] unk3 = reader.ReadBytes(4);
                                //string unk3_paramname_string = NodeDB.GetName(unk3);

                                //Fifth 4: datatype
                                byte[]          datatype2           = reader.ReadBytes(4);
                                CathodeDataType datatype2_converted = GetDataType(datatype2);

                                //Sixth 4: unknown ID
                                byte[] unk4 = reader.ReadBytes(4);

                                //Now we get ANOTHER offset. This is a pointer to a location and a count of IDs at that location.
                                int offset1 = reader.ReadInt32() * 4;
                                int count1  = reader.ReadInt32();
                                for (int p = 0; p < count1; p++)
                                {
                                    reader.BaseStream.Position = offset1 + (p * 4);
                                    byte[] unk69 = reader.ReadBytes(4);      //cross-refs: node ids (of flowgraph refs), then the node, then 0x00 (x4)
                                }
                            }
                            break;
                        }

                        //NOT PARSING: This is very similar in format to DEFINE_ENV_MODEL_REF_LINKS with the cross-references
                        case CathodeScriptBlocks.DEFINE_ZONE_CONTENT:
                        {
                            break;
                            reader.BaseStream.Position = offsetPairs[x].GlobalOffset + (y * 4);
                            int offsetPos = reader.ReadInt32() * 4;

                            reader.BaseStream.Position = offsetPos;
                            CathodeNodeEntity thisNode = flowgraph.GetNodeByID(reader.ReadUInt32());
                            //string test0 = NodeDB.GetFriendlyName(thisNode.nodeID);
                            int OffsetToFindParams = reader.ReadInt32() * 4;
                            int NumberOfParams     = reader.ReadInt32();

                            int goTo = OffsetToFindParams;
                            for (int m = 0; m < NumberOfParams; m++)
                            {
                                reader.BaseStream.Position = goTo;

                                byte[] firstFour = reader.ReadBytes(4);
                                int    offset1   = -1;
                                if (m > 0)     //for some reason only the first entry is 8 bytes long, the rest are 12, with four bytes of something at the start (some kind of ID, zone id maybe?)
                                {
                                    offset1 = reader.ReadInt32() * 4;
                                }
                                else
                                {
                                    offset1 = BitConverter.ToInt32(firstFour, 0) * 4;
                                }
                                int count1 = reader.ReadInt32();

                                goTo = (int)reader.BaseStream.Position;

                                reader.BaseStream.Position = offset1;
                                for (int p = 0; p < count1; p++)
                                {
                                    byte[] unk55 = reader.ReadBytes(4);      //cross-refs: node ids (of flowgraph refs), then the node, then 0x00 (x4)
                                }
                            }
                            break;
                        }
                        }
                    }
                }

                flowgraphs.Add(flowgraph);
            }
        }
Example #2
0
        /* Read all parameters from the PAK */
        private void ReadParameters(BinaryReader reader)
        {
            reader.BaseStream.Position = parameter_offsets[0];
            for (int i = 0; i < parameter_count; i++)
            {
                int length = (i == parameter_count - 1) ? flowgraph_offsets[0] - parameter_offsets[i] : parameter_offsets[i + 1] - parameter_offsets[i];
                CathodeParameter this_parameter = new CathodeParameter();
                CathodeDataType  this_datatype  = GetDataType(reader.ReadBytes(4));
                switch (this_datatype)
                {
                case CathodeDataType.POSITION:
                    this_parameter = new CathodeTransform();
                    ((CathodeTransform)this_parameter).position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                    float _x, _y, _z; _y = reader.ReadSingle(); _x = reader.ReadSingle(); _z = reader.ReadSingle();     //Y,X,Z!
                    ((CathodeTransform)this_parameter).rotation = new Vector3(_x, _y, _z);
                    break;

                case CathodeDataType.INTEGER:
                    this_parameter = new CathodeInteger();
                    ((CathodeInteger)this_parameter).value = reader.ReadInt32();
                    break;

                case CathodeDataType.STRING:
                    this_parameter = new CathodeString();
                    ((CathodeString)this_parameter).unk0 = reader.ReadBytes(4);     // some kind of ID sometimes referenced in script and resource id
                    ((CathodeString)this_parameter).unk1 = reader.ReadBytes(4);     // sometimes flowgraph id ?!
                    bool shouldStop = false;
                    for (int x = 0; x < length - 8; x++)
                    {
                        byte thisByte = reader.ReadByte();
                        if (thisByte == 0x00)
                        {
                            shouldStop = true; continue;
                        }
                        if (shouldStop && thisByte != 0x00)
                        {
                            break;
                        }
                        ((CathodeString)this_parameter).value += (char)thisByte;
                    }
                    ((CathodeString)this_parameter).initial_length = length - 13;
                    reader.BaseStream.Position -= 1;
                    break;

                case CathodeDataType.BOOL:
                    this_parameter = new CathodeBool();
                    ((CathodeBool)this_parameter).value = (reader.ReadInt32() == 1);
                    break;

                case CathodeDataType.FLOAT:
                    this_parameter = new CathodeFloat();
                    ((CathodeFloat)this_parameter).value = reader.ReadSingle();
                    break;

                case CathodeDataType.SHORT_GUID:
                    this_parameter = new CathodeResource();
                    ((CathodeResource)this_parameter).resourceID = reader.ReadUInt32();
                    break;

                case CathodeDataType.DIRECTION:
                    this_parameter = new CathodeVector3();
                    float __x, __y, __z; __y = reader.ReadSingle(); __x = reader.ReadSingle(); __z = reader.ReadSingle();     //Y,X,Z!
                    ((CathodeVector3)this_parameter).value = new Vector3(__x, __y, __z);
                    break;

                case CathodeDataType.ENUM:
                    this_parameter = new CathodeEnum();
                    ((CathodeEnum)this_parameter).enumID    = reader.ReadUInt32();
                    ((CathodeEnum)this_parameter).enumIndex = reader.ReadInt32();
                    break;

                /*
                 * case CathodeDataType.SPLINE_DATA:
                 * this_parameter = new CathodeSpline();
                 * int start_offset = reader.ReadInt32(); //This just gives us a pointless offset
                 * int num_points = reader.ReadInt32();
                 *
                 * if (length - 12 != num_points * 24)
                 * {
                 *  string dsfsdf = ""; //for some reason some have extra data at the end
                 * }
                 *
                 * for (int x = 0; x < num_points; x++)
                 * {
                 *  CathodeTransform this_point = new CathodeTransform();
                 *  this_point.position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                 *  this_point.rotation = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                 *  ((CathodeSpline)this_parameter).splinePoints.Add(this_point);
                 * }
                 * break;
                 */
                default:
                    this_parameter.unknownContent = reader.ReadBytes(length - 4);     //Should never hit this!
                    break;
                }

                this_parameter.offset   = parameter_offsets[i];
                this_parameter.dataType = this_datatype;

                parameters.Add(this_parameter);
            }
        }