private void generateButton_Click(object sender, EventArgs e)
 {
     if (duplicatesListBox.SelectedIndex >= 0)
     {
         UnrealGUID guid = duplicateGuids[duplicatesListBox.SelectedIndex];
         SharedPathfinding.GenerateNewRandomGUID(guid.export);
         populateDuplicateGUIDs();
     }
 }
Example #2
0
        internal static ExportEntry GetReachSpecEndExport(ExportEntry reachSpec, PropertyCollection props = null)
        {
            if (props == null)
            {
                props = reachSpec.GetProperties();
            }

            if (props.GetProp <StructProperty>("End") is StructProperty endProperty &&
                endProperty.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(reachSpec)) is ObjectProperty otherNodeValue &&
                reachSpec.FileRef.isUExport(otherNodeValue.Value))
            {
                return(reachSpec.FileRef.getUExport(otherNodeValue.Value));
            }

            return(null); //can't get end, or is external
        }
Example #3
0
        public static void CreateReachSpec(ExportEntry startNode, bool createTwoWay, ExportEntry destinationNode, string reachSpecClass, ReachSpecSize size, PropertyCollection externalGUIDProperties = null)
        {
            IMEPackage  Pcc = startNode.FileRef;
            ExportEntry reachSpectoClone = Pcc.Exports.FirstOrDefault(x => x.ClassName == "ReachSpec");

            if (externalGUIDProperties != null) //EXTERNAL
            {
                //external node

                //Debug.WriteLine("Num Exports: " + pcc.Exports.Count);
                if (reachSpectoClone != null)
                {
                    ExportEntry outgoingSpec = reachSpectoClone.Clone();
                    Pcc.addExport(outgoingSpec);

                    IEntry reachSpecClassImp = GetEntryOrAddImport(Pcc, reachSpecClass); //new class type.

                    outgoingSpec.idxClass      = reachSpecClassImp.UIndex;
                    outgoingSpec.idxObjectName = reachSpecClassImp.idxObjectName;

                    var            properties            = outgoingSpec.GetProperties();
                    ObjectProperty outgoingSpecStartProp = properties.GetProp <ObjectProperty>("Start");                                                                   //START
                    StructProperty outgoingEndStructProp = properties.GetProp <StructProperty>("End");                                                                     //Embeds END
                    ObjectProperty outgoingSpecEndProp   = outgoingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(outgoingSpec)); //END
                    outgoingSpecStartProp.Value = startNode.UIndex;
                    outgoingSpecEndProp.Value   = 0;
                    var endGuid = outgoingEndStructProp.GetProp <StructProperty>("Guid");
                    endGuid.Properties = externalGUIDProperties; //set the other guid values to our guid values

                    //Add to source node prop
                    ArrayProperty <ObjectProperty> PathList = startNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList");
                    PathList.Add(new ObjectProperty(outgoingSpec.UIndex));
                    startNode.WriteProperty(PathList);
                    outgoingSpec.WriteProperties(properties);


                    //Write Spec Size
                    SharedPathfinding.SetReachSpecSize(outgoingSpec, size.SpecRadius, size.SpecHeight);

                    //Reindex reachspecs.
                    SharedPathfinding.ReindexMatchingObjects(outgoingSpec);
                }
            }
            else
            {
                //Debug.WriteLine("Source Node: " + startNode.Index);

                //Debug.WriteLine("Num Exports: " + pcc.Exports.Count);
                //int outgoingSpec = pcc.ExportCount;
                //int incomingSpec = pcc.ExportCount + 1;


                if (reachSpectoClone != null)
                {
                    ExportEntry outgoingSpec = reachSpectoClone.Clone();
                    Pcc.addExport(outgoingSpec);
                    ExportEntry incomingSpec = null;
                    if (createTwoWay)
                    {
                        incomingSpec = reachSpectoClone.Clone();
                        Pcc.addExport(incomingSpec);
                    }

                    IEntry reachSpecClassImp = GetEntryOrAddImport(Pcc, reachSpecClass); //new class type.

                    outgoingSpec.idxClass      = reachSpecClassImp.UIndex;
                    outgoingSpec.idxObjectName = reachSpecClassImp.idxObjectName;

                    var outgoingSpecProperties = outgoingSpec.GetProperties();
                    if (reachSpecClass == "Engine.SlotToSlotReachSpec")
                    {
                        outgoingSpecProperties.Add(new ByteProperty(1, "SpecDirection")); //We might need to find a way to support this edit
                    }

                    //Debug.WriteLine("Outgoing UIndex: " + outgoingSpecExp.UIndex);

                    ObjectProperty outgoingSpecStartProp = outgoingSpecProperties.GetProp <ObjectProperty>("Start");                                                       //START
                    StructProperty outgoingEndStructProp = outgoingSpecProperties.GetProp <StructProperty>("End");                                                         //Embeds END
                    ObjectProperty outgoingSpecEndProp   = outgoingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(outgoingSpec)); //END
                    outgoingSpecStartProp.Value = startNode.UIndex;
                    outgoingSpecEndProp.Value   = destinationNode.UIndex;

                    //Add to source node prop
                    var PathList = startNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList");
                    PathList.Add(new ObjectProperty(outgoingSpec.UIndex));
                    startNode.WriteProperty(PathList);

                    //Write Spec Size
                    SetReachSpecSize(outgoingSpecProperties, size.SpecRadius, size.SpecHeight);
                    outgoingSpec.WriteProperties(outgoingSpecProperties);

                    if (createTwoWay)
                    {
                        incomingSpec.idxClass      = reachSpecClassImp.UIndex;
                        incomingSpec.idxObjectName = reachSpecClassImp.idxObjectName;
                        var incomingSpecProperties = incomingSpec.GetProperties();
                        if (reachSpecClass == "Engine.SlotToSlotReachSpec")
                        {
                            incomingSpecProperties.Add(new ByteProperty(2, "SpecDirection"));
                        }

                        ObjectProperty incomingSpecStartProp = incomingSpecProperties.GetProp <ObjectProperty>("Start");                                                       //START
                        StructProperty incomingEndStructProp = incomingSpecProperties.GetProp <StructProperty>("End");                                                         //Embeds END
                        ObjectProperty incomingSpecEndProp   = incomingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(incomingSpec)); //END

                        incomingSpecStartProp.Value = destinationNode.UIndex;                                                                                                  //Uindex
                        incomingSpecEndProp.Value   = startNode.UIndex;


                        //Add reachspec to destination node's path list (returning)
                        var DestPathList = destinationNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList");
                        DestPathList.Add(new ObjectProperty(incomingSpec.UIndex));
                        destinationNode.WriteProperty(DestPathList);

                        //destNode.WriteProperty(DestPathList);
                        SetReachSpecSize(incomingSpecProperties, size.SpecRadius, size.SpecHeight);

                        incomingSpec.WriteProperties(incomingSpecProperties);
                    }

                    //Reindex reachspecs.
                    SharedPathfinding.ReindexMatchingObjects(outgoingSpec);
                }
            }
        }
        private void reachSpecCalculatorThread_DoWork(object sender, DoWorkEventArgs e)
        {
            worker.ReportProgress(-1, "Getting list of all used ReachSpecs in pcc");
            //Figure out which exports have PathList.
            BGThreadOptions  bgo = (BGThreadOptions)e.Argument;
            IMEPackage       pcc = bgo.pcc;
            HashSet <int>    reachSpecExportIndexes = new HashSet <int>();
            List <string>    badSpecs = new List <string>();
            HashSet <string> names    = new HashSet <string>();

            foreach (IExportEntry exp in pcc.Exports)
            {
                ArrayProperty <ObjectProperty> pathList = exp.GetProperty <ArrayProperty <ObjectProperty> >("PathList");
                if (pathList != null)
                {
                    foreach (ObjectProperty reachSpecObj in pathList)
                    {
                        reachSpecExportIndexes.Add(reachSpecObj.Value - 1);
                        IExportEntry   spec      = pcc.Exports[reachSpecObj.Value - 1];
                        var            specProps = spec.GetProperties();
                        ObjectProperty start     = specProps.GetProp <ObjectProperty>("Start");
                        if (start.Value != exp.UIndex)
                        {
                            badSpecs.Add((reachSpecObj.Value - 1).ToString() + " " + spec.ObjectName + " start value does not match the node that references it (" + exp.Index + ")");
                        }

                        //get end
                        StructProperty end         = specProps.GetProp <StructProperty>("End");
                        ObjectProperty endActorObj = end.GetProp <ObjectProperty>("Actor");
                        if (endActorObj.Value == start.Value)
                        {
                            badSpecs.Add((reachSpecObj.Value - 1).ToString() + " " + spec.ObjectName + " start and end property is the same. This will crash the game.");
                        }

                        var guid = SharedPathfinding.GetGUIDFromStruct(end.GetProp <StructProperty>("Guid"));
                        if ((guid.A | guid.B | guid.C | guid.D) == 0 && endActorObj.Value == 0)
                        {
                            badSpecs.Add((reachSpecObj.Value - 1).ToString() + " " + spec.ObjectName + " has no guid and has no endactor.");
                        }
                        if (endActorObj.Value - 1 > pcc.ExportCount)
                        {
                            badSpecs.Add((reachSpecObj.Value - 1).ToString() + " " + spec.ObjectName + " has invalid end property (past end of bounds).");
                        }
                        if (endActorObj.Value > 0)
                        {
                            IExportEntry expo = pcc.Exports[endActorObj.Value - 1];
                            names.Add(expo.ClassName);
                        }
                        //
                    }
                }
            }
            int i = 0;

            foreach (string item in names)
            {
                Debug.WriteLine(i + " " + item);
                i++;
            }
            worker.ReportProgress(-1, "Calculating " + reachSpecExportIndexes.Count + " reachspecs");

            int currentCalculationNum = 1; //Start at 1 cause humans.
            int numNeedingRecalc      = 0;

            foreach (int specExportId in reachSpecExportIndexes)
            {
                //worker.ReportProgress(-1, "Calculating reachspecs [" + currentCalculationNum + "/" + reachSpecExportIndexes.Count + "]");
                IExportEntry exp         = pcc.Exports[specExportId];
                bool         needsRecalc = calculateReachSpec(exp, bgo.readOnly);
                if (needsRecalc)
                {
                    numNeedingRecalc++;
                }
                double percent     = (currentCalculationNum / reachSpecExportIndexes.Count) * 100;
                int    feedPercent = RoundDoubleToInt(percent);
                worker.ReportProgress(feedPercent);
                currentCalculationNum++;
            }


            if (bgo.readOnly)
            {
                if (numNeedingRecalc == 0)
                {
                    worker.ReportProgress(-1, "No reachspecs need updated.");
                }
                else
                {
                    worker.ReportProgress(-1, numNeedingRecalc + " reachspec" + ((numNeedingRecalc > 1) ? "s" : "") + " need updated.");
                }
            }
            else
            {
                if (numNeedingRecalc == 0)
                {
                    worker.ReportProgress(-1, "No reachspecs needed updating.");
                }
                else
                {
                    worker.ReportProgress(-1, numNeedingRecalc + " reachspec" + ((numNeedingRecalc > 1) ? "s" : "") + " have been updated.");
                }
            }
            e.Result = badSpecs;
        }