private void generateButton_Click(object sender, EventArgs e) { if (duplicatesListBox.SelectedIndex >= 0) { UnrealGUID guid = duplicateGuids[duplicatesListBox.SelectedIndex]; SharedPathfinding.GenerateNewRandomGUID(guid.export); populateDuplicateGUIDs(); } }
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 }
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; }