public static void BuildData2(MoveDefDataNode node, MovesetHeader* header, VoidPtr address, int length, bool force)
 {
     VoidPtr addr = address;
     foreach (MoveDefEntryNode e in MoveDefNode.nodeDictionary.Values)
     {
         if (e.External && !(e._extNode is MoveDefReferenceEntryNode)) continue;
         e.Rebuild(addr, e._calcSize, true);
     }
 }
        internal static unsafe void BuildData(MoveDefDataNode node, MovesetHeader* header, VoidPtr address, int length, bool force)
        {
            MoveDefNode RootNode = node.Parent.Parent as MoveDefNode;

            VoidPtr dataAddress = address;
            VoidPtr baseAddress = node._rebuildBase;

            node._entryOffset = header;

            bint* extraOffsets = (bint*)((VoidPtr)header + 124);

            bint* action1Offsets = (bint*)(dataAddress + node.part1Len + node.part2Len);
            bint* action2Offsets = action1Offsets + RootNode._actions.Children.Count;

            bint* mainOffsets = (bint*)(dataAddress + (node.part1Len + node.part2Len + node.part3Len + node.part4Len));
            bint* GFXOffsets = (bint*)((VoidPtr)mainOffsets + RootNode._subActions.Children.Count * 4);
            bint* SFXOffsets =  (bint*)((VoidPtr)GFXOffsets + RootNode._subActions.Children.Count * 4);
            bint* otherOffsets = (bint*)((VoidPtr)SFXOffsets + RootNode._subActions.Children.Count * 4);

            FDefMiscSection* miscOffsetsAddr = (FDefMiscSection*)(dataAddress + (node._childLength - 0x4C));

            if (node != null)
            {
                node._entryOffset = header;
                if (node.misc != null)
                {
                    node.misc._entryOffset = miscOffsetsAddr;
                    header->MiscSectionOffset = (int)miscOffsetsAddr - (int)baseAddress;
                }
            }

            header->SubactionMainStart = (int)mainOffsets - (int)baseAddress;
            header->SubactionGFXStart = (int)GFXOffsets - (int)baseAddress;
            header->SubactionSFXStart = (int)SFXOffsets - (int)baseAddress;
            header->SubactionOtherStart = (int)otherOffsets - (int)baseAddress;

            header->EntryActionsStart = (int)action1Offsets - (int)baseAddress;
            header->ExitActionsStart = (int)action2Offsets - (int)baseAddress;

            #region Part 1

            if ((int)dataAddress - (int)baseAddress != 0)
                Console.WriteLine("p1");

            header->AttributeStart = Rebuild(RootNode, node.attributes, ref dataAddress, baseAddress);
            MoveDefNode._lookupOffsets.Add(header->AttributeStart.Address);

            header->SSEAttributeStart = Rebuild(RootNode, node.sseAttributes, ref dataAddress, baseAddress);

            header->CommonActionFlagsStart = Rebuild(RootNode, node.commonActionFlags, ref dataAddress, baseAddress);

            header->Unknown7 = Rebuild(RootNode, node.unk7, ref dataAddress, baseAddress);

            foreach (MoveDefSubActionGroupNode grp in RootNode._subActions.Children)
                if (grp.Name != "<null>")
                    if (((grp.Children[3].Children.Count > 0 || ((MoveDefActionNode)grp.Children[3])._actionRefs.Count > 0 || ((MoveDefActionNode)grp.Children[3])._build)))
                    {
                        otherOffsets[grp.Index] = Rebuild(RootNode, grp.Children[3] as MoveDefActionNode, ref dataAddress, baseAddress);
                        MoveDefNode._lookupOffsets.Add(&otherOffsets[grp.Index]);
                    }
                    else otherOffsets[grp.Index] = 0;

            foreach (MoveDefSubActionGroupNode grp in RootNode._subActions.Children)
                if (grp.Name != "<null>")
                    if (((grp.Children[1].Children.Count > 0 || ((MoveDefActionNode)grp.Children[1])._actionRefs.Count > 0 || ((MoveDefActionNode)grp.Children[1])._build)))
                    {
                        GFXOffsets[grp.Index] = Rebuild(RootNode, grp.Children[1] as MoveDefActionNode, ref dataAddress, baseAddress);
                        MoveDefNode._lookupOffsets.Add(&GFXOffsets[grp.Index]);
                    }
                    else GFXOffsets[grp.Index] = 0;

            RebuildArticleActions(RootNode, node, ref dataAddress, baseAddress, true, 1);

            if ((miscOffsetsAddr->UnkBoneSectionOffset = Rebuild(RootNode, node.misc.unkBoneSection, ref dataAddress, baseAddress)) > 0)
                miscOffsetsAddr->UnkBoneSectionCount = node.misc.unkBoneSection.Children.Count;

            foreach (MoveDefSubActionGroupNode grp in RootNode._subActions.Children)
                if (grp.Name != "<null>")
                    if (((grp.Children[2].Children.Count > 0 || ((MoveDefActionNode)grp.Children[2])._actionRefs.Count > 0 || ((MoveDefActionNode)grp.Children[2])._build)))
                    {
                        SFXOffsets[grp.Index] = Rebuild(RootNode, grp.Children[2] as MoveDefActionNode, ref dataAddress, baseAddress);
                        MoveDefNode._lookupOffsets.Add(&SFXOffsets[grp.Index]);
                    }
                    else SFXOffsets[grp.Index] = 0;

            RebuildArticleActions(RootNode, node, ref dataAddress, baseAddress, true, 2);

            if (node.misc.soundData != null)
                foreach (MoveDefSoundDataNode r in node.misc.soundData.Children)
                {
                    foreach (MoveDefIndexNode b in r.Children)
                    {
                        b._entryOffset = dataAddress;
                        *(bint*)dataAddress = b.ItemIndex;
                        dataAddress += 4;
                    }
                }

            foreach (MoveDefSubActionGroupNode grp in RootNode._subActions.Children)
                if (grp.Name != "<null>")
                    if (((grp.Children[0].Children.Count > 0 || ((MoveDefActionNode)grp.Children[0])._actionRefs.Count > 0 || ((MoveDefActionNode)grp.Children[0])._build)))
                    {
                        mainOffsets[grp.Index] = Rebuild(RootNode, grp.Children[0] as MoveDefActionNode, ref dataAddress, baseAddress);
                        MoveDefNode._lookupOffsets.Add((int)&mainOffsets[grp.Index] - (int)baseAddress);
                    }
                    else mainOffsets[grp.Index] = 0;

            RebuildArticleActions(RootNode, node, ref dataAddress, baseAddress, true, 0);

            foreach (MoveDefActionGroupNode grp in RootNode._actions.Children)
            {
                if (grp.Children[0].Children.Count > 0 || (grp.Children[0] as MoveDefActionNode)._actionRefs.Count > 0 || (grp.Children[0] as MoveDefActionNode)._build) //Entry
                {
                    action1Offsets[grp.Index] = Rebuild(RootNode, grp.Children[0] as MoveDefActionNode, ref dataAddress, baseAddress);
                    MoveDefNode._lookupOffsets.Add((int)&action1Offsets[grp.Index] - (int)baseAddress);
                }
                if (grp.Children[1].Children.Count > 0 || (grp.Children[1] as MoveDefActionNode)._actionRefs.Count > 0 || (grp.Children[1] as MoveDefActionNode)._build) //Exit
                {
                    action2Offsets[grp.Index] = Rebuild(RootNode, grp.Children[1] as MoveDefActionNode, ref dataAddress, baseAddress);
                    MoveDefNode._lookupOffsets.Add((int)&action2Offsets[grp.Index] - (int)baseAddress);
                }
            }

            #endregion
            #region Part 2

            if ((int)dataAddress - (int)baseAddress != node.part1Len)
                Console.WriteLine("p2");

            miscOffsetsAddr->UnknownSection1Offset = Rebuild(RootNode, node.misc.unkSection1, ref dataAddress, baseAddress);

            if ((miscOffsetsAddr->HurtBoxOffset = Rebuild(RootNode, node.misc.hurtBoxes, ref dataAddress, baseAddress)) > 0)
                miscOffsetsAddr->HurtBoxCount = node.misc.hurtBoxes.Children.Count;

            //if (node.misc.collisionData != null)
            //    foreach (MoveDefOffsetNode offset in node.misc.collisionData.Children)
            //        if (offset.Children.Count > 0 && !(offset.Children[0] as MoveDefEntryNode).External)
            //            foreach (MoveDefBoneIndexNode b in offset.Children[0].Children)
            //            {
            //                b._entryOffset = dataAddress;
            //                *(bint*)dataAddress = b.boneIndex;
            //                dataAddress += 4;
            //            }

            if ((miscOffsetsAddr->LedgegrabOffset = Rebuild(RootNode, node.misc.ledgeGrabs, ref dataAddress, baseAddress)) > 0)
                miscOffsetsAddr->LedgegrabCount = node.misc.ledgeGrabs.Children.Count;

            miscOffsetsAddr->TetherOffset = Rebuild(RootNode, node.misc.tether, ref dataAddress, baseAddress);

            miscOffsetsAddr->CrawlOffset = Rebuild(RootNode, node.misc.crawl, ref dataAddress, baseAddress);

            miscOffsetsAddr->MultiJumpOffset = Rebuild(RootNode, node.misc.multiJump, ref dataAddress, baseAddress);

            miscOffsetsAddr->GlideOffset = Rebuild(RootNode, node.misc.glide, ref dataAddress, baseAddress);

            for (int i = 0; i < RootNode._subRoutineList.Count; i++)
                if ((RootNode._subRoutineList[i] as MoveDefActionNode)._actionRefs.Count > 0)
                    Rebuild(RootNode, RootNode._subRoutineList[i] as MoveDefActionNode, ref dataAddress, baseAddress);

            if (node.unk22 != null)
                if (node.unk22.Children.Count > 0)
                    Rebuild(RootNode, node.unk22.Children[0] as MoveDefActionNode, ref dataAddress, baseAddress);

            if (node.override1 != null)
                foreach (MoveDefActionOverrideEntryNode e in node.override1.Children)
                    Rebuild(RootNode, e.Children[0] as MoveDefActionNode, ref dataAddress, baseAddress);

            if (node.override2 != null)
                foreach (MoveDefActionOverrideEntryNode e in node.override2.Children)
                    Rebuild(RootNode, e.Children[0] as MoveDefActionNode, ref dataAddress, baseAddress);

            RebuildArticleActions(RootNode, node, ref dataAddress, baseAddress, false, 0);

            header->ActionFlagsStart = Rebuild(RootNode, node.actionFlags, ref dataAddress, baseAddress);

            #endregion
            #region Part 3

            if ((int)dataAddress - (int)baseAddress != node.part1Len + node.part2Len)
                Console.WriteLine("p3");

            //Actions part 1 and 2 already written
            dataAddress += RootNode._actions.Children.Count * 8;

            header->ActionPreStart = Rebuild(RootNode, node.actionPre, ref dataAddress, baseAddress);

            #endregion
            #region Part 4

            if ((int)dataAddress - (int)baseAddress != node.part1Len + node.part2Len + node.part3Len)
                Console.WriteLine("p4");

            node.subActionTable.WriteTable(dataAddress);

            dataAddress += node.subActionTable.TotalSize;

            header->SubactionFlagsStart = (int)dataAddress - (int)baseAddress;

            int index = 0;
            FDefSubActionFlag* flags = (FDefSubActionFlag*)dataAddress;
            foreach (MoveDefSubActionGroupNode g in RootNode._subActions.Children)
            {
                *flags = new FDefSubActionFlag() { _InTranslationTime = g._inTransTime, _Flags = g._flags, _stringOffset = (g.Name == "<null>" ? 0 : (int)node.subActionTable[g.Name] - (int)baseAddress) };

                if (flags->_stringOffset > 0)
                {
                    if (index == 412)
                        node.zssFirstOffset = (int)flags->_stringOffset.Address - (int)baseAddress;
                    if (index == 317)
                        node.warioSwing4StringOffset = (int)flags->_stringOffset.Address - (int)baseAddress;

                    MoveDefNode._lookupOffsets.Add((int)flags->_stringOffset.Address - (int)baseAddress);
                }

                flags++;
                index++;
            }

            dataAddress = flags;

            #endregion
            #region Part 5

            if ((int)dataAddress - (int)baseAddress != node.part1Len + node.part2Len + node.part3Len + node.part4Len)
                Console.WriteLine("p5");

            //Subaction offsets already written
            dataAddress += RootNode._subActions.Children.Count * 16;

            header->ModelVisibilityStart = Rebuild(RootNode, node.mdlVisibility, ref dataAddress, baseAddress);

            miscOffsetsAddr->UnknownSection3Offset = Rebuild(RootNode, node.misc.unkSection3, ref dataAddress, baseAddress);

            header->BoneRef2 = Rebuild(RootNode, node.boneRef2, ref dataAddress, baseAddress);

            if (node.nanaSubActions != null)
            {
                int dataOff = 0;
                foreach (MoveDefSubActionGroupNode grp in node.nanaSubActions.Children)
                    if (grp.Name != "<null>")
                        foreach (MoveDefActionNode a in grp.Children)
                            if (a.Children.Count > 0 || a._actionRefs.Count > 0)
                                dataOff += a._calcSize;

                bint* main2Offsets = (bint*)(dataAddress + dataOff);
                bint* GFX2Offsets = (bint*)((VoidPtr)main2Offsets + node.nanaSubActions.Children.Count * 4);
                bint* SFX2Offsets = (bint*)((VoidPtr)GFX2Offsets + node.nanaSubActions.Children.Count * 4);
                bint* other2Offsets = (bint*)((VoidPtr)SFX2Offsets + node.nanaSubActions.Children.Count * 4);

                extraOffsets[0] = (int)main2Offsets - (int)baseAddress;
                extraOffsets[1] = (int)GFX2Offsets - (int)baseAddress;
                extraOffsets[2] = (int)SFX2Offsets - (int)baseAddress;
                extraOffsets[3] = (int)other2Offsets - (int)baseAddress;

                foreach (MoveDefSubActionGroupNode grp in node.nanaSubActions.Children)
                    if ((grp.Name != "<null>" && (grp.Children[3].Children.Count > 0 || ((MoveDefActionNode)grp.Children[3])._actionRefs.Count > 0 || ((MoveDefActionNode)grp.Children[3])._build)))
                    {
                        other2Offsets[grp.Index] = Rebuild(RootNode, grp.Children[3] as MoveDefActionNode, ref dataAddress, baseAddress);
                        MoveDefNode._lookupOffsets.Add((int)&other2Offsets[grp.Index] - (int)baseAddress);
                    }
                    else other2Offsets[grp.Index] = 0;

                foreach (MoveDefSubActionGroupNode grp in node.nanaSubActions.Children)
                    if ((grp.Name != "<null>" && (grp.Children[1].Children.Count > 0 || ((MoveDefActionNode)grp.Children[1])._actionRefs.Count > 0 || ((MoveDefActionNode)grp.Children[1])._build)))
                    {
                        GFX2Offsets[grp.Index] = Rebuild(RootNode, grp.Children[1] as MoveDefActionNode, ref dataAddress, baseAddress);
                        MoveDefNode._lookupOffsets.Add((int)&GFX2Offsets[grp.Index] - (int)baseAddress);
                    }
                    else GFX2Offsets[grp.Index] = 0;

                foreach (MoveDefSubActionGroupNode grp in node.nanaSubActions.Children)
                    if ((grp.Name != "<null>" && (grp.Children[2].Children.Count > 0 || ((MoveDefActionNode)grp.Children[2])._actionRefs.Count > 0 || ((MoveDefActionNode)grp.Children[2])._build)))
                    {
                        SFX2Offsets[grp.Index] = Rebuild(RootNode, grp.Children[2] as MoveDefActionNode, ref dataAddress, baseAddress);
                        MoveDefNode._lookupOffsets.Add((int)&SFX2Offsets[grp.Index] - (int)baseAddress);
                    }
                    else SFX2Offsets[grp.Index] = 0;

                foreach (MoveDefSubActionGroupNode grp in node.nanaSubActions.Children)
                    if ((grp.Name != "<null>" && (grp.Children[0].Children.Count > 0 || ((MoveDefActionNode)grp.Children[0])._actionRefs.Count > 0 || ((MoveDefActionNode)grp.Children[0])._build)))
                    {
                        main2Offsets[grp.Index] = Rebuild(RootNode, grp.Children[0] as MoveDefActionNode, ref dataAddress, baseAddress);
                        MoveDefNode._lookupOffsets.Add((int)&main2Offsets[grp.Index] - (int)baseAddress);
                    }
                    else main2Offsets[grp.Index] = 0;

                dataAddress = (VoidPtr)other2Offsets + node.nanaSubActions.Children.Count * 4;
            }

            miscOffsetsAddr->CollisionDataOffset = Rebuild(RootNode, node.misc.collisionData, ref dataAddress, baseAddress);

            header->Unknown24 = Rebuild(RootNode, node.unk24, ref dataAddress, baseAddress);

            miscOffsetsAddr->UnknownSection12Offset = Rebuild(RootNode, node.misc.unk12, ref dataAddress, baseAddress);

            header->Unknown22 = Rebuild(RootNode, node.unk22, ref dataAddress, baseAddress);

            #endregion
            #region Part 6

            if ((int)dataAddress - (int)baseAddress != node.part1Len + node.part2Len + node.part3Len + node.part4Len+ node.part5Len)
                Console.WriteLine("p6");

            header->StaticArticlesStart = Rebuild(RootNode, node.staticArticles, ref dataAddress, baseAddress);

            header->EntryArticleStart = Rebuild(RootNode, node.entryArticle, ref dataAddress, baseAddress);

            foreach (MoveDefArticleNode e in node._articles.Values)
                Rebuild(RootNode, e, ref dataAddress, baseAddress);

            if ((miscOffsetsAddr->UnknownSection2Offset = Rebuild(RootNode, node.misc.unkSection2, ref dataAddress, baseAddress)) > 0)
                miscOffsetsAddr->UnknownSection2Count = node.misc.unkSection2.Children.Count;

            if (node.nanaSoundData != null)
            {
                foreach (MoveDefSoundDataNode r in node.nanaSoundData.Children)
                    foreach (MoveDefIndexNode b in r.Children)
                    {
                        b._entryOffset = dataAddress;
                        *(bint*)dataAddress = b.ItemIndex;
                        dataAddress += 4;
                    }

                FDefListOffset* sndLists = (FDefListOffset*)(dataAddress);
                FDefListOffset* data = (FDefListOffset*)&extraOffsets[10];

                node.nanaSoundData._entryOffset = data;

                if (node.nanaSoundData.Children.Count > 0)
                {
                    data->_startOffset = (int)sndLists - (int)baseAddress;
                    MoveDefNode._lookupOffsets.Add((int)data->_startOffset.Address - (int)baseAddress);
                }

                data->_listCount = node.nanaSoundData.Children.Count;

                foreach (MoveDefSoundDataNode r in node.nanaSoundData.Children)
                {
                    if (r.Children.Count > 0)
                    {
                        sndLists->_startOffset = (int)(r.Children[0] as MoveDefEntryNode)._entryOffset - (int)baseAddress;
                        MoveDefNode._lookupOffsets.Add((int)sndLists->_startOffset.Address - (int)baseAddress);
                    }
                    (sndLists++)->_listCount = r.Children.Count;
                }
                dataAddress = sndLists;
            }

            header->ActionInterrupts = Rebuild(RootNode, node.actionInterrupts, ref dataAddress, baseAddress);

            header->BoneFloats1 = Rebuild(RootNode, node.boneFloats1, ref dataAddress, baseAddress);

            header->BoneFloats2 = Rebuild(RootNode, node.boneFloats2, ref dataAddress, baseAddress);

            header->BoneFloats3 = Rebuild(RootNode, node.boneFloats3, ref dataAddress, baseAddress);

            header->BoneRef1 = Rebuild(RootNode, node.boneRef1, ref dataAddress, baseAddress);

            miscOffsetsAddr->BoneRef2Offset = Rebuild(RootNode, node.misc.boneRefs, ref dataAddress, baseAddress);

            miscOffsetsAddr->UnknownSection5Offset = Rebuild(RootNode, node.misc.unkSection5, ref dataAddress, baseAddress);

            miscOffsetsAddr->SoundDataOffset = Rebuild(RootNode, node.misc.soundData, ref dataAddress, baseAddress);

            #endregion
            #region Part 7

            if ((int)dataAddress - (int)baseAddress != node.part1Len + node.part2Len + node.part3Len + node.part4Len+ node.part5Len + node.part6Len)
                Console.WriteLine("p7");

            //Misc section, already written
            dataAddress += 0x4C;

            #endregion

            //Params
            int l = 0, ind = 0;
            foreach (int i in node._extraOffsets)
            {
                if (i > 1480 && i < RootNode.dataSize)
                {
                    MoveDefEntryNode e = node._extraEntries[l];

                    if (extraOffsets[ind] == 0)
                        if (e == null)
                            extraOffsets[ind] = i;
                        else
                            extraOffsets[ind] = (int)e._entryOffset - (int)baseAddress;

                    MoveDefNode._lookupOffsets.Add((int)&extraOffsets[ind] - (int)baseAddress);

                    l++;
                }
                else
                    extraOffsets[ind] = i;
                ind++;
            }

            header->EntryActionOverrides = ((node.override1 != null && node.override1.External) ? (int)node.override1._entryOffset - (int)baseAddress : 0);
            header->ExitActionOverrides = ((node.override2 != null && node.override2.External) ? (int)node.override2._entryOffset - (int)baseAddress : 0);

            header->Unknown27 = node.Unknown27;
            header->Unknown28 = node.Unknown28;
            header->Flags1 = node.Flags1uint;
            header->Flags2 = node.Flags2int;

            bint* offsets = (bint*)header;
            for (int i = 0; i < 27; i++)
                if (offsets[i] > 0)
                    MoveDefNode._lookupOffsets.Add((int)(&offsets[i]) - (int)baseAddress);

            offsets = (bint*)miscOffsetsAddr;
            for (int i = 0; i < 19; i++)
                if (offsets[i] > 0 && !(i % 2 == 0 && i > 0 && i < 9))
                    MoveDefNode._lookupOffsets.Add((int)(&offsets[i]) - (int)baseAddress);

            //Go back and add offsets to nodes that need them
            foreach (MoveDefEntryNode entry in RootNode._postProcessNodes)
                entry.PostProcess();
        }