Esempio n. 1
0
        /* If a node exists in the flowgraph, return it - otherwise create it, and return it */
        public CathodeNodeEntity GetNodeByID(UInt32 id)
        {
            foreach (CathodeNodeEntity node in nodes)
            {
                if (node.nodeID == id)
                {
                    return(node);
                }
            }
            CathodeNodeEntity newNode = new CathodeNodeEntity();

            newNode.nodeID = id;
            nodes.Add(newNode);
            return(newNode);
        }
Esempio n. 2
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);
            }
        }