/// <summary> /// Sets the reach spec size and commits the results back to the export /// </summary> /// <param name="spec"></param> /// <param name="radius"></param> /// <param name="height"></param> public static void SetReachSpecSize(IExportEntry spec, int radius, int height) { PropertyCollection specProperties = spec.GetProperties(); SetReachSpecSize(specProperties, radius, height); spec.WriteProperties(specProperties); //write it back. }
private void pathNodeSize_DropdownChanged(object sender, EventArgs e) { if (AllowChanges) { int selectedIndex = pathNodeSizeComboBox.SelectedIndex; Unreal.PropertyCollection props = export.GetProperties(); StructProperty maxPathSize = props.GetProp <StructProperty>("MaxPathSize"); if (maxPathSize != null) { FloatProperty height = maxPathSize.GetProp <FloatProperty>("Height"); FloatProperty radius = maxPathSize.GetProp <FloatProperty>("Radius"); if (radius != null && height != null) { int radVal = -1; int heightVal = -1; Point size = getDropdownSizePair(selectedIndex); radVal = size.X; heightVal = size.Y; long heightOffset = height.Offset; long radiusOffset = radius.Offset; //Manually write it to avoid property writing errors with cover stuff byte[] data = export.Data; WriteMem((int)heightOffset, data, BitConverter.GetBytes(Convert.ToSingle(heightVal))); WriteMem((int)radiusOffset, data, BitConverter.GetBytes(Convert.ToSingle(radVal))); export.Data = data; } } } }
private void reachspecSizeBox_Changed(object sender, EventArgs e) { int n = reachableNodesList.SelectedIndex; if (n < 0 || n >= reachSpecs.Count) { return; } if (AllowChanges) { int selectedIndex = reachSpecSizeSelector.SelectedIndex; IExportEntry reachSpec = export.FileRef.Exports[reachSpecs[n]]; Unreal.PropertyCollection props = reachSpec.GetProperties(); IntProperty radius = props.GetProp <IntProperty>("CollisionRadius"); IntProperty height = props.GetProp <IntProperty>("CollisionHeight"); if (radius != null && height != null) { int radVal = -1; int heightVal = -1; Point size = getDropdownSizePair(selectedIndex); radVal = size.X; heightVal = size.Y; radius.Value = radVal; height.Value = heightVal; reachSpec.WriteProperties(props); reachSpecSelection_Changed(null, null); } } }
private static void OnExportChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { IExportEntry export = e.NewValue as IExportEntry; PropertyEditorHost propEdHost = d as PropertyEditorHost; if (export != null && propEdHost != null) { propEdHost.propEd.Props = export.GetProperties(); propEdHost.propEd.Pcc = export.FileRef; } }
internal static IExportEntry GetReachSpecEndExport(IExportEntry 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 override bool CanParse(IExportEntry exportEntry) { if (exportEntry.FileRef.Game != MEGame.UDK) { var props = exportEntry.GetProperties(); foreach (var prop in props) { if (prop is StructProperty structProp && Enum.TryParse(structProp.StructType, out CurveType _)) { return(true); } } } return(false); }
private void recalculateReachSpec(IExportEntry reachSpecExport, int calculatedProperDistance, float dirX, float dirY, float dirZ) { Unreal.PropertyCollection props = reachSpecExport.GetProperties(); IntProperty prop = props.GetProp <IntProperty>("Distance"); StructProperty directionProp = props.GetProp <StructProperty>("Direction"); FloatProperty propX = directionProp.GetProp <FloatProperty>("X"); FloatProperty propY = directionProp.GetProp <FloatProperty>("Y"); FloatProperty propZ = directionProp.GetProp <FloatProperty>("Z"); prop.Value = calculatedProperDistance; propX.Value = dirX; propY.Value = dirY; propZ.Value = dirZ; reachSpecExport.WriteProperties(props); }
private void reachSpecSelection_Changed(object sender, EventArgs e) { int n = reachableNodesList.SelectedIndex; if (n < 0 || n >= reachSpecs.Count) { reachSpecDestLabel.Text = "No ReachSpec selected"; reachSpecSizeLabel.Text = "ReachSpec Size"; connectionToLabel.Text = "Connection to"; reachSpecSizeSelector.Enabled = false; return; } AllowChanges = false; reachSpecSizeSelector.Enabled = true; IExportEntry reachSpec = export.FileRef.Exports[reachSpecs[n]]; Unreal.PropertyCollection props = reachSpec.GetProperties(); StructProperty outgoingEndStructProp = props.GetProp <StructProperty>("End"); //Embeds END ObjectProperty outgoingSpecEndProp = outgoingEndStructProp.Properties.GetProp <ObjectProperty>("Actor"); //END if (outgoingSpecEndProp.Value - 1 > 0) { IExportEntry endNode = export.FileRef.Exports[outgoingSpecEndProp.Value - 1]; reachSpecDestLabel.Text = endNode.ObjectName + "_" + endNode.indexValue; connectionToLabel.Text = "Connection to " + endNode.Index; } IntProperty radius = props.GetProp <IntProperty>("CollisionRadius"); IntProperty height = props.GetProp <IntProperty>("CollisionHeight"); if (radius != null && height != null) { reachSpecSizeLabel.Text = "ReachSpec Size: " + radius.Value + "x" + height.Value; reachSpecSizeSelector.SelectedIndex = findClosestNextSizeIndex(radius, height); } AllowChanges = true; }
private void dEBUGCallReadPropertiesToolStripMenuItem_Click(object sender, EventArgs e) { int n; if (!GetSelected(out n)) { return; } if (n >= 0) { try { IExportEntry exp = pcc.Exports[n]; exp.GetProperties(true); //force properties to reload } catch (Exception ex) { } } }
static void addObjectToSequence(int index, bool removeLinks, IExportEntry sequenceExport) { var seqObjs = sequenceExport.GetProperty<ArrayProperty<ObjectProperty>>("SequenceObjects"); if (seqObjs != null) { seqObjs.Add(new ObjectProperty(index + 1)); sequenceExport.WriteProperty(seqObjs); PropertyCollection props = sequenceExport.GetProperties(); IExportEntry newObject = sequenceExport.FileRef.getExport(index); PropertyCollection newObjectProps = newObject.GetProperties(); newObjectProps.AddOrReplaceProp(new ObjectProperty(sequenceExport.UIndex, "ParentSequence")); if (removeLinks) { var outLinksProp = newObjectProps.GetProp<ArrayProperty<StructProperty>>("OutputLinks"); if (outLinksProp != null) { foreach (var prop in outLinksProp) { prop.GetProp<ArrayProperty<StructProperty>>("Links").Clear(); } } var varLinksProp = newObjectProps.GetProp<ArrayProperty<StructProperty>>("VariableLinks"); if (varLinksProp != null) { foreach (var prop in varLinksProp) { prop.GetProp<ArrayProperty<ObjectProperty>>("LinkedVariables").Clear(); } } } newObject.WriteProperties(newObjectProps); newObject.idxLink = sequenceExport.UIndex; } }
static void cloneSequence(IExportEntry exp, IExportEntry parentSequence) { IMEPackage pcc = exp.FileRef; if (exp.ClassName == "Sequence") { var seqObjs = exp.GetProperty<ArrayProperty<ObjectProperty>>("SequenceObjects"); if (seqObjs == null || seqObjs.Count == 0) { return; } //store original list of sequence objects; List<int> oldObjects = seqObjs.Select(x => x.Value).ToList(); //clear original sequence objects seqObjs.Clear(); exp.WriteProperty(seqObjs); //clone all children for (int i = 0; i < oldObjects.Count; i++) { cloneObject(oldObjects[i] - 1, exp, false); } //re-point children's links to new objects seqObjs = exp.GetProperty<ArrayProperty<ObjectProperty>>("SequenceObjects"); foreach (var seqObj in seqObjs) { IExportEntry obj = pcc.getExport(seqObj.Value - 1); var props = obj.GetProperties(); var outLinksProp = props.GetProp<ArrayProperty<StructProperty>>("OutputLinks"); if (outLinksProp != null) { foreach (var outLinkStruct in outLinksProp) { var links = outLinkStruct.GetProp<ArrayProperty<StructProperty>>("Links"); foreach (var link in links) { var linkedOp = link.GetProp<ObjectProperty>("LinkedOp"); linkedOp.Value = seqObjs[oldObjects.IndexOf(linkedOp.Value)].Value; } } } var varLinksProp = props.GetProp<ArrayProperty<StructProperty>>("VariableLinks"); if (varLinksProp != null) { foreach (var varLinkStruct in varLinksProp) { var links = varLinkStruct.GetProp<ArrayProperty<ObjectProperty>>("LinkedVariables"); foreach (var link in links) { link.Value = seqObjs[oldObjects.IndexOf(link.Value)].Value; } } } var eventLinksProp = props.GetProp<ArrayProperty<StructProperty>>("EventLinks"); if (eventLinksProp != null) { foreach (var eventLinkStruct in eventLinksProp) { var links = eventLinkStruct.GetProp<ArrayProperty<ObjectProperty>>("LinkedEvents"); foreach (var link in links) { link.Value = seqObjs[oldObjects.IndexOf(link.Value)].Value; } } } obj.WriteProperties(props); } //re-point sequence links to new objects int oldObj = 0; int newObj = 0; var propCollection = exp.GetProperties(); var inputLinksProp = propCollection.GetProp<ArrayProperty<StructProperty>>("InputLinks"); if (inputLinksProp != null) { foreach (var inLinkStruct in inputLinksProp) { var linkedOp = inLinkStruct.GetProp<ObjectProperty>("LinkedOp"); oldObj = linkedOp.Value; if (oldObj != 0) { newObj = seqObjs[oldObjects.IndexOf(oldObj)].Value; linkedOp.Value = newObj; NameProperty linkAction = inLinkStruct.GetProp<NameProperty>("LinkAction"); var nameRef = linkAction.Value; nameRef.count = pcc.getExport(newObj - 1).indexValue; linkAction.Value = nameRef; } } } var outputLinksProp = propCollection.GetProp<ArrayProperty<StructProperty>>("OutputLinks"); if (outputLinksProp != null) { foreach (var outLinkStruct in outputLinksProp) { var linkedOp = outLinkStruct.GetProp<ObjectProperty>("LinkedOp"); oldObj = linkedOp.Value; if (oldObj != 0) { newObj = seqObjs[oldObjects.IndexOf(oldObj)].Value; linkedOp.Value = newObj; NameProperty linkAction = outLinkStruct.GetProp<NameProperty>("LinkAction"); var nameRef = linkAction.Value; nameRef.count = pcc.getExport(newObj - 1).indexValue; linkAction.Value = nameRef; } } } exp.WriteProperties(propCollection); } else if (exp.ClassName == "SequenceReference") { //set OSequenceReference to new sequence var oSeqRefProp = exp.GetProperty<ObjectProperty>("oSequenceReference"); if (oSeqRefProp == null || oSeqRefProp.Value == 0) { return; } int oldSeqIndex = oSeqRefProp.Value; oSeqRefProp.Value = exp.UIndex + 1; exp.WriteProperty(oSeqRefProp); //clone sequence cloneObject(oldSeqIndex - 1, parentSequence, false); //remove cloned sequence from SeqRef's parent's sequenceobjects var seqObjs = parentSequence.GetProperty<ArrayProperty<ObjectProperty>>("SequenceObjects"); seqObjs.RemoveAt(seqObjs.Count - 1); parentSequence.WriteProperty(seqObjs); //set SequenceReference's linked name indices List<int> inputIndices = new List<int>(); List<int> outputIndices = new List<int>(); IExportEntry newSequence = pcc.getExport(exp.Index + 1); var props = newSequence.GetProperties(); var inLinksProp = props.GetProp<ArrayProperty<StructProperty>>("InputLinks"); if (inLinksProp != null) { foreach (var inLink in inLinksProp) { inputIndices.Add(inLink.GetProp<NameProperty>("LinkAction").Value.count); } } var outLinksProp = props.GetProp<ArrayProperty<StructProperty>>("OutputLinks"); if (outLinksProp != null) { foreach (var outLinks in outLinksProp) { outputIndices.Add(outLinks.GetProp<NameProperty>("LinkAction").Value.count); } } props = exp.GetProperties(); inLinksProp = props.GetProp<ArrayProperty<StructProperty>>("InputLinks"); if (inLinksProp != null) { for (int i = 0; i < inLinksProp.Count; i++) { NameProperty linkAction = inLinksProp[i].GetProp<NameProperty>("LinkAction"); var nameRef = linkAction.Value; nameRef.count = inputIndices[i]; linkAction.Value = nameRef; } } outLinksProp = props.GetProp<ArrayProperty<StructProperty>>("OutputLinks"); if (outLinksProp != null) { for (int i = 0; i < outLinksProp.Count; i++) { NameProperty linkAction = outLinksProp[i].GetProp<NameProperty>("LinkAction"); var nameRef = linkAction.Value; nameRef.count = outputIndices[i]; linkAction.Value = nameRef; } } exp.WriteProperties(props); //set new Sequence's link and ParentSequence prop to SeqRef newSequence.WriteProperty(new ObjectProperty(exp.UIndex, "ParentSequence")); newSequence.idxLink = exp.UIndex; //set DefaultViewZoom to magic number to flag that this is a cloned Sequence Reference and global saves cannot be used with it //ugly, but it should work newSequence.WriteProperty(new FloatProperty(CLONED_SEQREF_MAGIC, "DefaultViewZoom")); } }
public Bio2DA(IExportEntry export) { Console.WriteLine("Loading " + export.ObjectName); this.export = export; IMEPackage pcc = export.FileRef; byte[] data = export.Data; RowNames = new List <string>(); if (export.ClassName == "Bio2DA") { string rowLabelsVar = "m_sRowLabel"; var properties = export.GetProperties(); var props = export.GetProperty <ArrayProperty <NameProperty> >(rowLabelsVar); if (props != null) { foreach (NameProperty n in props) { RowNames.Add(n.ToString()); } } else { Console.WriteLine("Unable to find row names property!"); Debugger.Break(); return; } } else { string rowLabelsVar = "m_lstRowNumbers"; //Bio2DANumberedRows var props = export.GetProperty <ArrayProperty <IntProperty> >(rowLabelsVar); if (props != null) { foreach (IntProperty n in props) { RowNames.Add(n.Value.ToString()); } } else { Console.WriteLine("Unable to find row names property!"); Debugger.Break(); return; } } //Get Columns ColumnNames = new List <string>(); int colcount = BitConverter.ToInt32(data, data.Length - 4); int currentcoloffset = 0; while (colcount >= 0) { currentcoloffset += 4; int colindex = BitConverter.ToInt32(data, data.Length - currentcoloffset); currentcoloffset += 8; //names in this case don't use nameindex values. int nameindex = BitConverter.ToInt32(data, data.Length - currentcoloffset); string name = pcc.getNameEntry(nameindex); ColumnNames.Insert(0, name); colcount--; } Cells = new Bio2DACell[RowNames.Count(), ColumnNames.Count()]; currentcoloffset += 4; //column count. int infilecolcount = BitConverter.ToInt32(data, data.Length - currentcoloffset); //start of binary data int binstartoffset = export.propsEnd(); //arrayheader + nonenamesize + number of items in this list int curroffset = binstartoffset; int cellcount = BitConverter.ToInt32(data, curroffset); if (cellcount > 0) { curroffset += 4; for (int rowindex = 0; rowindex < RowNames.Count(); rowindex++) { for (int colindex = 0; colindex < ColumnNames.Count() && curroffset < data.Length - currentcoloffset; colindex++) { byte dataType = 255; dataType = data[curroffset]; curroffset++; int dataSize = dataType == Bio2DACell.TYPE_NAME ? 8 : 4; byte[] celldata = new byte[dataSize]; Buffer.BlockCopy(data, curroffset, celldata, 0, dataSize); Bio2DACell cell = new Bio2DACell(pcc, curroffset, dataType, celldata); Cells[rowindex, colindex] = cell; curroffset += dataSize; } } CellCount = RowNames.Count() * ColumnNames.Count(); } else { IsIndexed = true; curroffset += 4; //theres a 0 here for some reason cellcount = BitConverter.ToInt32(data, curroffset); curroffset += 4; //curroffset += 4; while (CellCount < cellcount) { int index = BitConverter.ToInt32(data, curroffset); int row = index / ColumnNames.Count(); int col = index % ColumnNames.Count(); curroffset += 4; byte dataType = data[curroffset]; int dataSize = dataType == Bio2DACell.TYPE_NAME ? 8 : 4; curroffset++; byte[] celldata = new byte[dataSize]; Buffer.BlockCopy(data, curroffset, celldata, 0, dataSize); Bio2DACell cell = new Bio2DACell(pcc, curroffset, dataType, celldata); Cells[row, col] = cell; CellCount++; curroffset += dataSize; } } Console.WriteLine("Finished loading " + export.ObjectName); }
/// <summary> /// Creates the reachspec connections from this pathfinding node to others. /// </summary> public override void CreateConnections(ref List <PathfindingNodeMaster> Objects) { var outLinksProp = export.GetProperty <ArrayProperty <ObjectProperty> >("PathList"); if (outLinksProp != null) { foreach (var prop in outLinksProp) { int reachspecexport = prop.Value; ReachSpecs.Add(pcc.Exports[reachspecexport - 1]); } foreach (IExportEntry spec in ReachSpecs) { Pen penToUse = halfReachSpecPen; switch (spec.ObjectName) { case "SlotToSlotReachSpec": penToUse = slotToSlotPen; break; case "SFXLadderReachSpec": penToUse = sfxLadderPen; break; case "SFXLargeBoostReachSpec": penToUse = sfxLargeBoostPen; break; case "SFXBoostReachSpec": penToUse = sfxBoostPen; break; case "SFXJumpDownReachSpec": penToUse = sfxJumpDownPen; break; } //Get ending PNode othernode = null; int othernodeidx = 0; PropertyCollection props = spec.GetProperties(); foreach (var prop in props) { if (prop.Name == "End") { PropertyCollection reachspecprops = (prop as StructProperty).Properties; foreach (var rprop in reachspecprops) { if (rprop.Name == "Actor") { othernodeidx = (rprop as ObjectProperty).Value; break; } } } } if (othernodeidx != 0) { foreach (PathfindingNodeMaster node in Objects) { if (node.export.UIndex == othernodeidx) { othernode = node; //Check for returning reachspec for pen drawing. This is going to incur a significant performance penalty... IExportEntry otherNode = node.export; var otherNodePathList = otherNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList"); if (otherNodePathList != null) { bool keepParsing = true; foreach (var path in otherNodePathList) { int reachspecexport = path.Value; IExportEntry possibleIncomingSpec = pcc.Exports[reachspecexport - 1]; PropertyCollection otherSpecProperties = possibleIncomingSpec.GetProperties(); foreach (var otherSpecProp in otherSpecProperties) { if (otherSpecProp.Name == "End") { PropertyCollection reachspecprops = (otherSpecProp as StructProperty).Properties; foreach (var rprop in reachspecprops) { if (rprop.Name == "Actor") { othernodeidx = (rprop as ObjectProperty).Value; if (othernodeidx == export.UIndex) { keepParsing = false; if (penToUse == halfReachSpecPen) { penToUse = blackPen; } break; } } } } } if (!keepParsing) { break; } } break; } } } if (othernode != null) { IntProperty radius = props.GetProp <IntProperty>("CollisionRadius"); IntProperty height = props.GetProp <IntProperty>("CollisionHeight"); if (radius != null && height != null && (radius >= PathfindingNodeInfoPanel.MINIBOSS_RADIUS || height >= PathfindingNodeInfoPanel.MINIBOSS_HEIGHT)) { penToUse = (Pen)penToUse.Clone(); if (radius >= PathfindingNodeInfoPanel.BOSS_RADIUS && height >= PathfindingNodeInfoPanel.BOSS_HEIGHT) { penToUse.Width = 3; } else { penToUse.Width = 2; } } PPath edge = new PPath(); edge.Pen = penToUse; ((ArrayList)Tag).Add(edge); ((ArrayList)othernode.Tag).Add(edge); edge.Tag = new ArrayList(); ((ArrayList)edge.Tag).Add(this); ((ArrayList)edge.Tag).Add(othernode); g.edgeLayer.AddChild(edge); } } } } }
protected PointF[] get3DBrushShape() { try { PropertyCollection props = export.GetProperties(); float xScalar = 1; float yScalar = 1; //float zScalar = 1; var drawScale = props.GetProp<FloatProperty>("DrawScale"); var drawScale3d = props.GetProp<StructProperty>("DrawScale3D"); if (drawScale != null) { xScalar = yScalar = drawScale.Value; } if (drawScale3d != null) { xScalar *= drawScale3d.GetProp<FloatProperty>("X").Value; yScalar *= drawScale3d.GetProp<FloatProperty>("Y").Value; } var brushComponent = props.GetProp<ObjectProperty>("BrushComponent"); if (brushComponent == null) { return null; } IExportEntry brush = export.FileRef.getExport(brushComponent.Value - 1); List<PointF> graphVertices = new List<PointF>(); List<Vector3> brushVertices = new List<Vector3>(); PropertyCollection brushProps = brush.GetProperties(); var brushAggGeom = brushProps.GetProp<StructProperty>("BrushAggGeom"); if (brushAggGeom == null) { return null; } var convexList = brushAggGeom.GetProp<ArrayProperty<StructProperty>>("ConvexElems"); //Vertices var verticiesList = convexList[0].Properties.GetProp<ArrayProperty<StructProperty>>("VertexData"); foreach (StructProperty vertex in verticiesList) { Vector3 point = new Vector3(); point.X = vertex.GetProp<FloatProperty>("X") * xScalar; point.Y = vertex.GetProp<FloatProperty>("Y") * yScalar; point.Z = vertex.GetProp<FloatProperty>("Z"); brushVertices.Add(point); } //FaceTris var faceTriData = convexList[0].Properties.GetProp<ArrayProperty<IntProperty>>("FaceTriData"); Vector3 previousVertex = new Vector3(); float prevX = float.MinValue; float prevY = float.MinValue; foreach (IntProperty triPoint in faceTriData) { Vector3 vertex = brushVertices[triPoint]; if (vertex.X == prevX && vertex.Y == prevY) { continue; //Z is on the difference } float x = vertex.X; float y = vertex.Y; prevX = x; prevY = y; PointF graphPoint = new PointF(x, y); graphVertices.Add(graphPoint); } return graphVertices.ToArray(); } catch (Exception) { return null; } }
public void LoadExport(IExportEntry export) { AllowChanges = false; this.export = export; reachableNodesList.Items.Clear(); reachSpecSizeSelector.Enabled = false; sfxCombatZoneList.Items.Clear(); combatZones = new List <int>(); reachSpecs = new List <int>(); var props = export.GetProperties(); exportTitleLabel.Text = export.ObjectName + "_" + export.indexValue; //Get Location StructProperty location = props.GetProp <StructProperty>("location"); if (location != null) { float x = location.GetProp <FloatProperty>("X"); float y = location.GetProp <FloatProperty>("Y"); float z = location.GetProp <FloatProperty>("Z"); xLabel.Text = "X: " + x; yLabel.Text = "Y: " + y; zLabel.Text = "Z: " + z; } else { xLabel.Text = "X: "; yLabel.Text = "Y: "; zLabel.Text = "Z: "; } //Calculate size StructProperty maxPathSize = props.GetProp <StructProperty>("MaxPathSize"); if (maxPathSize != null) { float height = maxPathSize.GetProp <FloatProperty>("Height"); float radius = maxPathSize.GetProp <FloatProperty>("Radius"); exportTitleLabel.Text += " - " + radius + "x" + height; pathNodeSizeComboBox.SelectedIndex = findClosestNextSizeIndex((int)radius, (int)height); pathNodeSizeComboBox.Enabled = true; } else { pathNodeSizeComboBox.Enabled = false; } //Calculate reachspecs ArrayProperty <ObjectProperty> PathList = props.GetProp <ArrayProperty <ObjectProperty> >("PathList"); if (PathList != null) { foreach (ObjectProperty prop in PathList) { IExportEntry outgoingSpec = export.FileRef.Exports[prop.Value - 1]; StructProperty outgoingEndStructProp = outgoingSpec.GetProperty <StructProperty>("End"); //Embeds END ObjectProperty outgoingSpecEndProp = outgoingEndStructProp.Properties.GetProp <ObjectProperty>("Actor"); //END if (outgoingSpecEndProp.Value - 1 > 0) { IExportEntry endNode = export.FileRef.Exports[outgoingSpecEndProp.Value - 1]; string targetNodeName = endNode.ObjectName + "_" + endNode.indexValue; reachableNodesList.Items.Add(endNode.Index + " " + targetNodeName + " via " + outgoingSpec.ObjectName + "_" + outgoingSpec.indexValue + " (" + outgoingSpec.Index + ")"); reachSpecs.Add(outgoingSpec.Index); } else { reachableNodesList.Items.Add("External File Node via " + outgoingSpec.ObjectName + "_" + outgoingSpec.indexValue + " (" + outgoingSpec.Index + ")"); reachSpecs.Add(outgoingSpec.Index); } } } //Calculate SFXCombatZones ArrayProperty <StructProperty> volumes = props.GetProp <ArrayProperty <StructProperty> >("Volumes"); if (volumes != null) { foreach (StructProperty volume in volumes) { ObjectProperty actorRef = volume.GetProp <ObjectProperty>("Actor"); if (actorRef != null && actorRef.Value > 0) { IExportEntry combatZoneExport = export.FileRef.Exports[actorRef.Value - 1]; combatZones.Add(combatZoneExport.Index); sfxCombatZoneList.Items.Add(combatZoneExport.ObjectName + "_" + combatZoneExport.indexValue + "(" + combatZoneExport.Index + ")"); } } } AllowChanges = true; }
private bool calculateReachSpec(IExportEntry reachSpecExport, bool readOnly, IExportEntry startNodeExport = null) { //Get start and end exports. var properties = reachSpecExport.GetProperties(); ObjectProperty start = properties.GetProp <ObjectProperty>("Start"); StructProperty end = properties.GetProp <StructProperty>("End"); ObjectProperty endActorObj = end.GetProp <ObjectProperty>("Actor"); if (start.Value > 0 && endActorObj.Value > 0) { //We should capture GUID here IExportEntry startNode = reachSpecExport.FileRef.Exports[start.Value - 1]; IExportEntry endNode = reachSpecExport.FileRef.Exports[endActorObj.Value - 1]; if (startNodeExport != null && startNode.Index != startNodeExport.Index) { //ERROR! MessageBox.Show(reachSpecExport.Index + " " + reachSpecExport.ObjectName + " start does not match it's containing pathlist reference (" + startNodeExport.Index + " " + startNodeExport.ObjectName + ")"); } float startX = 0, startY = 0, startZ = 0; float destX = 0, destY = 0, destZ = 0; StructProperty startLocationProp = startNode.GetProperty <StructProperty>("location"); StructProperty endLocationProp = endNode.GetProperty <StructProperty>("location"); if (startLocationProp != null && endLocationProp != null) { startX = startLocationProp.GetProp <FloatProperty>("X"); startY = startLocationProp.GetProp <FloatProperty>("Y"); startZ = startLocationProp.GetProp <FloatProperty>("Z"); destX = endLocationProp.GetProp <FloatProperty>("X"); destY = endLocationProp.GetProp <FloatProperty>("Y"); destZ = endLocationProp.GetProp <FloatProperty>("Z"); Point3D startPoint = new Point3D(startX, startY, startZ); Point3D destPoint = new Point3D(destX, destY, destZ); double distance = startPoint.getDistanceToOtherPoint(destPoint); if (distance != 0) { float dirX = (float)((destPoint.X - startPoint.X) / distance); float dirY = (float)((destPoint.Y - startPoint.Y) / distance); float dirZ = (float)((destPoint.Z - startPoint.Z) / distance); //Get Original Values, for comparison. StructProperty specDirection = properties.GetProp <StructProperty>("Direction"); float origX = 0, origY = 0, origZ = 0; if (specDirection != null) { origX = specDirection.GetProp <FloatProperty>("X"); origY = specDirection.GetProp <FloatProperty>("Y"); origZ = specDirection.GetProp <FloatProperty>("Z"); IntProperty origDistanceProp = properties.GetProp <IntProperty>("Distance"); if (origDistanceProp != null) { int origDistance = origDistanceProp.Value; int calculatedProperDistance = RoundDoubleToInt(distance); int distanceDiff = Math.Abs(origDistance - calculatedProperDistance); ReachSpecUpdaterUIThreadOptions recalcOption = new ReachSpecUpdaterUIThreadOptions(reachSpecExport, calculatedProperDistance, dirX, dirY, dirZ); if (distanceDiff > MAX_DISTANCE_TOLERANCE) { // Difference. Debug.WriteLine("Diff Distance is > tolerance: " + distanceDiff + ", should be " + calculatedProperDistance); if (!readOnly) { worker.ReportProgress(-2, recalcOption); } return(true); } float diffX = origX - dirX; float diffY = origY - dirY; float diffZ = origZ - dirZ; if (Math.Abs(diffX) > MAX_DIRECTION_TOLERANCE) { // Difference. Debug.WriteLine("Diff Direction X is > tolerance: " + diffX + ", should be " + dirX); if (!readOnly) { worker.ReportProgress(-2, recalcOption); } return(true); } if (Math.Abs(diffY) > MAX_DIRECTION_TOLERANCE) { // Difference. Debug.WriteLine("Diff Direction Y is > tolerance: " + diffY + ", should be " + dirY); if (!readOnly) { worker.ReportProgress(-2, recalcOption); } return(true); } if (Math.Abs(diffZ) > MAX_DIRECTION_TOLERANCE) { // Difference. Debug.WriteLine("Diff Direction Z is > tolerance: " + diffZ + ", should be " + dirZ); if (!readOnly) { worker.ReportProgress(-2, recalcOption); } return(true); } return(false); } } } } } //We really shouldn't reach here, hopefully. return(false); }
public static void CreateReachSpec(IExportEntry startNode, bool createTwoWay, IExportEntry destinationNode, string reachSpecClass, ReachSpecSize size, PropertyCollection externalGUIDProperties = null) { IMEPackage Pcc = startNode.FileRef; IExportEntry reachSpectoClone = Pcc.Exports.FirstOrDefault(x => x.ClassName == "ReachSpec"); if (externalGUIDProperties != null) //EXTERNAL { //external node //Debug.WriteLine("Num Exports: " + pcc.Exports.Count); if (reachSpectoClone != null) { IExportEntry 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) { IExportEntry outgoingSpec = reachSpectoClone.Clone(); Pcc.addExport(outgoingSpec); IExportEntry 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; }
public void SetExport(IExportEntry export) { Export = export; Props = export.GetProperties(); }