mirror of
https://github.com/batfasturd/BetterNPCEditor.git
synced 2025-04-19 10:51:18 +00:00
Added ability to Add / Del new root nodes for some things. Added loading of items from a Json file to easily select them while editing.
This commit is contained in:
parent
1a0cc36907
commit
0691e2c99e
@ -9,4 +9,25 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="beltitems.json" />
|
||||
<None Remove="weaponmoditems.json" />
|
||||
<None Remove="wearitems.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="allitems.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="beltitems.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="weaponmoditems.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="wearitems.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
@ -9,12 +10,15 @@ namespace Better_NCP_Editor
|
||||
public object NewValue { get; private set; }
|
||||
private Control inputControl;
|
||||
|
||||
public EditValueForm(string propertyName, string currentValue, Type valueType)
|
||||
// Constructor now takes an extra parameter: parentNodeName.
|
||||
public EditValueForm(string propertyName, string currentValue, Type valueType, List<string>? comboItems)
|
||||
{
|
||||
// Set the minimum size.
|
||||
this.MinimumSize = new Size(210, 150); // Example: 300x150 pixels
|
||||
// Optionally, set the default size if you want:
|
||||
this.ClientSize = new Size(210, 150);
|
||||
// Set the minimum and default size.
|
||||
this.MinimumSize = new Size(210, 120);
|
||||
|
||||
this.FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
this.MaximizeBox = false;
|
||||
|
||||
// Measure the width of the property name.
|
||||
Size keySize = TextRenderer.MeasureText(propertyName, this.Font);
|
||||
|
||||
@ -27,14 +31,13 @@ namespace Better_NCP_Editor
|
||||
}
|
||||
else
|
||||
{
|
||||
inputWidth = TextRenderer.MeasureText(currentValue, this.Font).Width + 20;
|
||||
inputWidth = TextRenderer.MeasureText(currentValue, this.Font).Width + 40;
|
||||
}
|
||||
|
||||
// Determine the desired width: the maximum of the key width and input width, plus extra padding.
|
||||
int desiredWidth = Math.Max(keySize.Width, inputWidth) + 40;
|
||||
|
||||
// Set the form's client size (you can also set MinimumSize here if needed).
|
||||
this.ClientSize = new Size(desiredWidth, 120);
|
||||
|
||||
this.Text = $"Edit {propertyName}";
|
||||
this.StartPosition = FormStartPosition.CenterParent;
|
||||
|
||||
@ -47,32 +50,79 @@ namespace Better_NCP_Editor
|
||||
};
|
||||
this.Controls.Add(lblProperty);
|
||||
|
||||
// Create the input control with width based on desiredWidth minus margins.
|
||||
int controlWidth = desiredWidth - 20;
|
||||
if (valueType == typeof(bool))
|
||||
|
||||
// Check if we need to use a special ComboBox (for "ShortName" in "Wear items").
|
||||
if (comboItems != null)
|
||||
{
|
||||
ComboBox combo = new ComboBox()
|
||||
{
|
||||
Location = new Point(10, 40),
|
||||
Width = controlWidth,
|
||||
Width = controlWidth, // initial width based on desiredWidth minus margins
|
||||
DropDownStyle = ComboBoxStyle.DropDownList
|
||||
};
|
||||
combo.Items.Add("true");
|
||||
combo.Items.Add("false");
|
||||
combo.SelectedItem = currentValue;
|
||||
|
||||
int maxWidth = 0;
|
||||
foreach (var key in comboItems)
|
||||
{
|
||||
combo.Items.Add(key);
|
||||
// Measure each item's width using the ComboBox's font.
|
||||
Size itemSize = TextRenderer.MeasureText(key, combo.Font);
|
||||
if (itemSize.Width > maxWidth)
|
||||
maxWidth = itemSize.Width;
|
||||
}
|
||||
|
||||
// Optionally add some extra padding.
|
||||
int paddedWidth = maxWidth + 20;
|
||||
|
||||
// Set the DropDownWidth to ensure items are fully visible.
|
||||
combo.DropDownWidth = paddedWidth;
|
||||
|
||||
// Optionally, you can also adjust the combo's Width if you want it to match the dropdown width.
|
||||
if (combo.Width < paddedWidth)
|
||||
combo.Width = paddedWidth;
|
||||
|
||||
// Set selected item to currentValue if found, otherwise select the first item.
|
||||
if (comboItems.Contains(currentValue))
|
||||
{
|
||||
combo.SelectedItem = currentValue;
|
||||
}
|
||||
else if (combo.Items.Count > 0)
|
||||
{
|
||||
combo.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
inputControl = combo;
|
||||
this.Controls.Add(combo);
|
||||
}
|
||||
else
|
||||
{
|
||||
TextBox txtBox = new TextBox()
|
||||
// Create the input control normally.
|
||||
if (valueType == typeof(bool))
|
||||
{
|
||||
Location = new Point(10, 40),
|
||||
Width = controlWidth,
|
||||
Text = currentValue
|
||||
};
|
||||
inputControl = txtBox;
|
||||
this.Controls.Add(txtBox);
|
||||
ComboBox combo = new ComboBox()
|
||||
{
|
||||
Location = new Point(10, 40),
|
||||
Width = controlWidth,
|
||||
DropDownStyle = ComboBoxStyle.DropDownList
|
||||
};
|
||||
combo.Items.Add("true");
|
||||
combo.Items.Add("false");
|
||||
combo.SelectedItem = currentValue;
|
||||
inputControl = combo;
|
||||
this.Controls.Add(combo);
|
||||
}
|
||||
else
|
||||
{
|
||||
TextBox txtBox = new TextBox()
|
||||
{
|
||||
Location = new Point(10, 40),
|
||||
Width = controlWidth,
|
||||
Text = currentValue
|
||||
};
|
||||
inputControl = txtBox;
|
||||
this.Controls.Add(txtBox);
|
||||
}
|
||||
}
|
||||
|
||||
// OK button.
|
||||
@ -91,24 +141,31 @@ namespace Better_NCP_Editor
|
||||
Button btnCancel = new Button()
|
||||
{
|
||||
Text = "Cancel",
|
||||
Location = new Point(100, 80), // Positioned to the right of OK.
|
||||
Location = new Point(100, 80),
|
||||
Size = new Size(80, 25),
|
||||
DialogResult = DialogResult.Cancel,
|
||||
Anchor = AnchorStyles.Left | AnchorStyles.Bottom
|
||||
};
|
||||
this.Controls.Add(btnCancel);
|
||||
|
||||
this.AcceptButton = btnOk;
|
||||
this.CancelButton = btnCancel;
|
||||
}
|
||||
|
||||
private void BtnOk_Click(object sender, EventArgs e)
|
||||
{
|
||||
// Determine new value based on input control.
|
||||
if (inputControl is ComboBox combo)
|
||||
// If the input control is the special ComboBox, return the dictionary value.
|
||||
if (inputControl is ComboBox combo && combo.DropDownStyle == ComboBoxStyle.DropDownList &&
|
||||
combo.Items.Count > 0)
|
||||
{
|
||||
NewValue = combo.SelectedItem.ToString() == "true";
|
||||
NewValue = combo.SelectedItem.ToString();
|
||||
}
|
||||
else if (inputControl is ComboBox comboBool)
|
||||
{
|
||||
NewValue = comboBool.SelectedItem.ToString() == "true";
|
||||
}
|
||||
else if (inputControl is TextBox txt)
|
||||
{
|
||||
// Try to parse an integer; if it fails, treat it as a string.
|
||||
if (int.TryParse(txt.Text, out int intValue))
|
||||
NewValue = intValue;
|
||||
else
|
||||
|
50
Better NCP Editor/Form1.Designer.cs
generated
50
Better NCP Editor/Form1.Designer.cs
generated
@ -43,9 +43,10 @@
|
||||
//
|
||||
// btn_load
|
||||
//
|
||||
btn_load.Location = new Point(17, 12);
|
||||
btn_load.Location = new Point(15, 9);
|
||||
btn_load.Margin = new Padding(3, 2, 3, 2);
|
||||
btn_load.Name = "btn_load";
|
||||
btn_load.Size = new Size(135, 29);
|
||||
btn_load.Size = new Size(118, 22);
|
||||
btn_load.TabIndex = 0;
|
||||
btn_load.Text = "Load Directory";
|
||||
btn_load.UseVisualStyleBackColor = true;
|
||||
@ -54,9 +55,10 @@
|
||||
// btn_save
|
||||
//
|
||||
btn_save.Enabled = false;
|
||||
btn_save.Location = new Point(214, 12);
|
||||
btn_save.Location = new Point(187, 9);
|
||||
btn_save.Margin = new Padding(3, 2, 3, 2);
|
||||
btn_save.Name = "btn_save";
|
||||
btn_save.Size = new Size(93, 29);
|
||||
btn_save.Size = new Size(81, 22);
|
||||
btn_save.TabIndex = 1;
|
||||
btn_save.Text = "Save File";
|
||||
btn_save.UseVisualStyleBackColor = true;
|
||||
@ -64,24 +66,27 @@
|
||||
//
|
||||
// dirTreeView
|
||||
//
|
||||
dirTreeView.Location = new Point(17, 53);
|
||||
dirTreeView.Location = new Point(15, 40);
|
||||
dirTreeView.Margin = new Padding(3, 2, 3, 2);
|
||||
dirTreeView.Name = "dirTreeView";
|
||||
dirTreeView.Size = new Size(290, 812);
|
||||
dirTreeView.Size = new Size(254, 610);
|
||||
dirTreeView.TabIndex = 2;
|
||||
//
|
||||
// entityTreeView
|
||||
//
|
||||
entityTreeView.Location = new Point(313, 53);
|
||||
entityTreeView.Location = new Point(274, 40);
|
||||
entityTreeView.Margin = new Padding(3, 2, 3, 2);
|
||||
entityTreeView.Name = "entityTreeView";
|
||||
entityTreeView.Size = new Size(843, 812);
|
||||
entityTreeView.Size = new Size(738, 610);
|
||||
entityTreeView.TabIndex = 3;
|
||||
//
|
||||
// btn_entity_del
|
||||
//
|
||||
btn_entity_del.Enabled = false;
|
||||
btn_entity_del.Location = new Point(366, 12);
|
||||
btn_entity_del.Location = new Point(320, 9);
|
||||
btn_entity_del.Margin = new Padding(3, 2, 3, 2);
|
||||
btn_entity_del.Name = "btn_entity_del";
|
||||
btn_entity_del.Size = new Size(47, 29);
|
||||
btn_entity_del.Size = new Size(41, 22);
|
||||
btn_entity_del.TabIndex = 8;
|
||||
btn_entity_del.Text = "Del";
|
||||
btn_entity_del.UseVisualStyleBackColor = true;
|
||||
@ -90,9 +95,10 @@
|
||||
// btn_entity_add
|
||||
//
|
||||
btn_entity_add.Enabled = false;
|
||||
btn_entity_add.Location = new Point(313, 12);
|
||||
btn_entity_add.Location = new Point(274, 9);
|
||||
btn_entity_add.Margin = new Padding(3, 2, 3, 2);
|
||||
btn_entity_add.Name = "btn_entity_add";
|
||||
btn_entity_add.Size = new Size(46, 29);
|
||||
btn_entity_add.Size = new Size(40, 22);
|
||||
btn_entity_add.TabIndex = 7;
|
||||
btn_entity_add.Text = "Add";
|
||||
btn_entity_add.UseVisualStyleBackColor = true;
|
||||
@ -101,9 +107,10 @@
|
||||
// btn_import_entityData
|
||||
//
|
||||
btn_import_entityData.Enabled = false;
|
||||
btn_import_entityData.Location = new Point(493, 12);
|
||||
btn_import_entityData.Location = new Point(431, 9);
|
||||
btn_import_entityData.Margin = new Padding(3, 2, 3, 2);
|
||||
btn_import_entityData.Name = "btn_import_entityData";
|
||||
btn_import_entityData.Size = new Size(70, 29);
|
||||
btn_import_entityData.Size = new Size(61, 22);
|
||||
btn_import_entityData.TabIndex = 9;
|
||||
btn_import_entityData.Text = "Import";
|
||||
btn_import_entityData.UseVisualStyleBackColor = true;
|
||||
@ -112,9 +119,10 @@
|
||||
// btn_export_entityData
|
||||
//
|
||||
btn_export_entityData.Enabled = false;
|
||||
btn_export_entityData.Location = new Point(569, 12);
|
||||
btn_export_entityData.Location = new Point(498, 9);
|
||||
btn_export_entityData.Margin = new Padding(3, 2, 3, 2);
|
||||
btn_export_entityData.Name = "btn_export_entityData";
|
||||
btn_export_entityData.Size = new Size(66, 29);
|
||||
btn_export_entityData.Size = new Size(58, 22);
|
||||
btn_export_entityData.TabIndex = 10;
|
||||
btn_export_entityData.Text = "Export";
|
||||
btn_export_entityData.UseVisualStyleBackColor = true;
|
||||
@ -124,17 +132,18 @@
|
||||
//
|
||||
statusTextbox.BorderStyle = BorderStyle.FixedSingle;
|
||||
statusTextbox.ImeMode = ImeMode.NoControl;
|
||||
statusTextbox.Location = new Point(660, 14);
|
||||
statusTextbox.Location = new Point(578, 10);
|
||||
statusTextbox.Margin = new Padding(3, 2, 3, 2);
|
||||
statusTextbox.Name = "statusTextbox";
|
||||
statusTextbox.ReadOnly = true;
|
||||
statusTextbox.Size = new Size(496, 27);
|
||||
statusTextbox.Size = new Size(434, 23);
|
||||
statusTextbox.TabIndex = 11;
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(8F, 20F);
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
ClientSize = new Size(1176, 881);
|
||||
ClientSize = new Size(1028, 661);
|
||||
Controls.Add(statusTextbox);
|
||||
Controls.Add(btn_export_entityData);
|
||||
Controls.Add(btn_import_entityData);
|
||||
@ -144,6 +153,7 @@
|
||||
Controls.Add(dirTreeView);
|
||||
Controls.Add(btn_save);
|
||||
Controls.Add(btn_load);
|
||||
Margin = new Padding(3, 2, 3, 2);
|
||||
Name = "Form1";
|
||||
Text = "BetterNPC Editor V1.0";
|
||||
Load += Form1_Load;
|
||||
|
@ -18,6 +18,10 @@ namespace Better_NCP_Editor
|
||||
// In your Form1 class:
|
||||
private ToolTip customToolTip = new ToolTip();
|
||||
private TreeNode lastHoveredNode = null;
|
||||
private List<String> _wearItems;
|
||||
private List<String> _beltItems;
|
||||
private List<String> _weaponModItems;
|
||||
private Dictionary<String, String> _allItems;
|
||||
|
||||
public Form1()
|
||||
{
|
||||
@ -27,7 +31,7 @@ namespace Better_NCP_Editor
|
||||
entityTreeView.AfterSelect += entityTreeView_AfterSelect;
|
||||
|
||||
// Prevent the form from shrinking below its current size.
|
||||
this.MinimumSize = new Size(1194, 928); // Set minimum allowed size
|
||||
this.MinimumSize = new Size(1044, 700); // Set minimum allowed size
|
||||
this.FormBorderStyle = FormBorderStyle.Sizable;
|
||||
|
||||
// Example layout using docking:
|
||||
@ -54,8 +58,41 @@ namespace Better_NCP_Editor
|
||||
entityTreeView.MouseMove += EntityTreeView_MouseMove;
|
||||
entityTreeView.MouseLeave += EntityTreeView_MouseLeave;
|
||||
|
||||
// Load the item database.
|
||||
_wearItems = LoadItemList("wearitems.json");
|
||||
_allItems = LoadItemDatabase("allitems.json");
|
||||
_beltItems = LoadItemList("beltitems.json");
|
||||
_weaponModItems = LoadItemList("weaponmoditems.json");
|
||||
|
||||
}
|
||||
|
||||
private List<String> LoadItemList(String filepath)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonListLoader.Load(filepath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error loading JSON file: " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<String,String> LoadItemDatabase(String filepath)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonDictionaryLoader.Load(filepath);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error loading JSON file: " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void EntityTreeView_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
int xOffset = 15;
|
||||
@ -252,7 +289,7 @@ namespace Better_NCP_Editor
|
||||
// Enable if the selected node's Tag is a JsonArray
|
||||
if (e.Node.Tag is JsonArray)
|
||||
{
|
||||
//enableButtons = true;
|
||||
enableAddDelButtons = true;
|
||||
enableImportExportButtons = true;
|
||||
}
|
||||
// Or if the selected node is an item in an array (its parent is a JsonArray)
|
||||
@ -261,6 +298,11 @@ namespace Better_NCP_Editor
|
||||
enableAddDelButtons = true;
|
||||
enableImportExportButtons = true;
|
||||
}
|
||||
|
||||
if (e.Node.Text.Equals("Presets", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
enableAddDelButtons = false;
|
||||
}
|
||||
// You can also add additional conditions for a "preset" node, e.g. by checking text:
|
||||
// else if (e.Node.Text.StartsWith("Preset", StringComparison.OrdinalIgnoreCase))
|
||||
// {
|
||||
@ -301,28 +343,68 @@ namespace Better_NCP_Editor
|
||||
valueType = typeof(bool);
|
||||
else if (int.TryParse(currentVal, out int i))
|
||||
valueType = typeof(int);
|
||||
|
||||
using (EditValueForm editForm = new EditValueForm(propName, currentVal, valueType))
|
||||
|
||||
String parentNodeName = "Root";
|
||||
String grandParentNodeName = "Root";
|
||||
List<String> comboList = null;
|
||||
|
||||
if (e.Node.Parent != null)
|
||||
{
|
||||
if (editForm.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
object newVal = editForm.NewValue;
|
||||
string displayVal = newVal is bool ? newVal.ToString().ToLower() : newVal.ToString();
|
||||
e.Node.Text = $"{propName}: {displayVal}";
|
||||
parentNodeName = e.Node.Parent.Text;
|
||||
|
||||
if (e.Node.Tag is JsonNode node)
|
||||
if (e.Node.Parent.Parent != null)
|
||||
{
|
||||
grandParentNodeName = e.Node.Parent.Parent.Text;
|
||||
|
||||
if (propName.Equals("ShortName", StringComparison.OrdinalIgnoreCase) && grandParentNodeName.Equals("Wear items"))
|
||||
{
|
||||
JsonNode newNode = JsonValue.Create(newVal);
|
||||
node.ReplaceWith(newNode);
|
||||
e.Node.Tag = newNode;
|
||||
comboList = _wearItems;
|
||||
}
|
||||
// Mark the file as modified.
|
||||
fileModified = true;
|
||||
btn_save.Enabled = true;
|
||||
else if (propName.Equals("ShortName", StringComparison.OrdinalIgnoreCase) && grandParentNodeName.Equals("Belt items"))
|
||||
{
|
||||
comboList = _beltItems;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (parentNodeName.Equals("Mods"))
|
||||
{
|
||||
comboList = _weaponModItems;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
using (EditValueForm editForm = new EditValueForm(propName, currentVal, valueType, comboList))
|
||||
{
|
||||
if (editForm.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
object newVal = editForm.NewValue;
|
||||
string displayVal = newVal is bool ? newVal.ToString().ToLower() : newVal.ToString();
|
||||
if (_allItems.ContainsKey(displayVal))
|
||||
{
|
||||
newVal = _allItems[displayVal];
|
||||
displayVal = _allItems[displayVal];
|
||||
}
|
||||
e.Node.Text = $"{propName}: {displayVal}";
|
||||
|
||||
if (e.Node.Tag is JsonNode node)
|
||||
{
|
||||
JsonNode newNode = JsonValue.Create(newVal);
|
||||
node.ReplaceWith(newNode);
|
||||
e.Node.Tag = newNode;
|
||||
}
|
||||
// Mark the file as modified.
|
||||
fileModified = true;
|
||||
btn_save.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -378,55 +460,124 @@ namespace Better_NCP_Editor
|
||||
TreeNode selected = entityTreeView.SelectedNode;
|
||||
if (selected == null)
|
||||
{
|
||||
MessageBox.Show("Please select a node to duplicate.", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBox.Show("Please select a node to add a new item.", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
TreeNode parent = selected.Parent;
|
||||
if (parent == null)
|
||||
JsonArray targetArray = null;
|
||||
bool duplicateExisting = false;
|
||||
|
||||
// If the selected node itself is an array node...
|
||||
if (selected.Tag is JsonArray arr)
|
||||
{
|
||||
MessageBox.Show("The selected node has no parent (cannot duplicate).", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
targetArray = arr;
|
||||
duplicateExisting = false; // We'll add a new blank node
|
||||
}
|
||||
|
||||
// Ensure the parent's Tag is a JsonArray.
|
||||
if (!(parent.Tag is JsonArray parentArray))
|
||||
// Otherwise, if the selected node's parent is an array...
|
||||
else if (selected.Parent != null && selected.Parent.Tag is JsonArray arrParent)
|
||||
{
|
||||
MessageBox.Show("The selected node's parent is not an array node.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
targetArray = arrParent;
|
||||
duplicateExisting = true; // We duplicate the selected item
|
||||
}
|
||||
|
||||
// Retrieve the underlying JsonNode for the selected node.
|
||||
if (!(selected.Tag is JsonNode selectedJsonNode))
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Selected node does not contain a valid JSON element.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
MessageBox.Show("The selected node is not part of an array.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Duplicate (deep clone) the selected JsonNode.
|
||||
JsonNode duplicate = selectedJsonNode.DeepClone();
|
||||
JsonNode newNode;
|
||||
if (!duplicateExisting)
|
||||
{
|
||||
// We're adding a new blank node to the array.
|
||||
// Use the selected node's text as the array name.
|
||||
string arrayName = selected.Text.Trim();
|
||||
if (arrayName.Equals("Wear items", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var obj = new JsonObject();
|
||||
obj["ShortName"] = "CHANGE ME";
|
||||
obj["SkinID (0 - default)"] = 0;
|
||||
newNode = obj;
|
||||
}
|
||||
else if (arrayName.Equals("Belt items", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var obj = new JsonObject();
|
||||
obj["ShortName"] = "CHANGE ME";
|
||||
obj["Amount"] = 1;
|
||||
obj["SkinID (0 - default)"] = 0;
|
||||
obj["Mods"] = new JsonArray(); // Empty array
|
||||
obj["Ammo"] = "";
|
||||
newNode = obj;
|
||||
} else if (arrayName.Equals("List of prefabs", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var obj = new JsonObject();
|
||||
obj["Chance [0.0-100.0]"] = 100.0;
|
||||
obj["The path to the prefab"] = "assets/rust.ai/agents/npcplayer/humannpc/scientist/CHANGEME";
|
||||
newNode = obj;
|
||||
}
|
||||
else if (arrayName.Equals("List of items", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var obj = new JsonObject();
|
||||
obj["ShortName"] = "CHANGEME";
|
||||
obj["Minimum"] = 1;
|
||||
obj["Maximum"] = 100;
|
||||
obj["Chance [0.0-100.0]"] = 50.0;
|
||||
obj["Is this a blueprint? [true/false]"] = false;
|
||||
obj["SkinID (0 - default)"] = 0;
|
||||
obj["Name (empty - default)"] = "";
|
||||
newNode = obj;
|
||||
}
|
||||
else if (arrayName.Equals("Mods", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
newNode = JsonValue.Create("CHANGE ME");
|
||||
}
|
||||
else if (arrayName.Equals("Names", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
newNode = JsonValue.Create("CHANGE ME");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default: create an empty string
|
||||
newNode = JsonValue.Create("CHANGE ME");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Duplicate the selected item.
|
||||
if (!(selected.Tag is JsonNode selectedJsonNode))
|
||||
{
|
||||
MessageBox.Show("Selected node does not contain a valid JSON element.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
newNode = selectedJsonNode.DeepClone();
|
||||
}
|
||||
|
||||
// Add the duplicate to the parent's array.
|
||||
parentArray.Add(duplicate);
|
||||
// Add the new node to the target array.
|
||||
targetArray.Add(newNode);
|
||||
|
||||
// Refresh only the parent's children.
|
||||
parent.Nodes.Clear();
|
||||
PopulateTreeRecursive((JsonNode)parent.Tag, parent);
|
||||
parent.ExpandAll(); // Expand the parent and all its child nodes
|
||||
// Determine the node representing the array.
|
||||
// If duplicating, the array node is the selected node's parent;
|
||||
// otherwise it is the selected node.
|
||||
TreeNode arrayNode = duplicateExisting ? selected.Parent : selected;
|
||||
|
||||
// Refresh only the children of the array node.
|
||||
arrayNode.Nodes.Clear();
|
||||
PopulateTreeRecursive((JsonNode)arrayNode.Tag, arrayNode);
|
||||
arrayNode.ExpandAll();
|
||||
|
||||
fileModified = true;
|
||||
btn_save.Enabled = true;
|
||||
|
||||
// Select the newly added item (last child in the parent's node collection).
|
||||
if (parent.Nodes.Count > 0)
|
||||
// Select the newly added item (the last child).
|
||||
if (arrayNode.Nodes.Count > 0)
|
||||
{
|
||||
TreeNode newSelected = parent.Nodes[parent.Nodes.Count - 1];
|
||||
TreeNode newSelected = arrayNode.Nodes[arrayNode.Nodes.Count - 1];
|
||||
entityTreeView.SelectedNode = newSelected;
|
||||
newSelected.EnsureVisible();
|
||||
entityTreeView.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void btn_entity_del_Click(object sender, EventArgs e)
|
||||
{
|
||||
TreeNode selected = entityTreeView.SelectedNode;
|
||||
|
22
Better NCP Editor/JsonDictionaryLoader.cs
Normal file
22
Better NCP Editor/JsonDictionaryLoader.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Better_NCP_Editor
|
||||
{
|
||||
public static class JsonDictionaryLoader
|
||||
{
|
||||
public static Dictionary<string, string> Load(string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
throw new FileNotFoundException("The specified JSON file was not found.", filePath);
|
||||
|
||||
string json = File.ReadAllText(filePath);
|
||||
Dictionary<string, string> dictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(json);
|
||||
return dictionary;
|
||||
}
|
||||
}
|
||||
}
|
22
Better NCP Editor/JsonListLoader.cs
Normal file
22
Better NCP Editor/JsonListLoader.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Better_NCP_Editor
|
||||
{
|
||||
public static class JsonListLoader
|
||||
{
|
||||
public static List<string> Load(string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
throw new FileNotFoundException("The specified JSON file was not found.", filePath);
|
||||
|
||||
string json = File.ReadAllText(filePath);
|
||||
List<string> list = JsonSerializer.Deserialize<List<string>>(json);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
1038
Better NCP Editor/allitems.json
Normal file
1038
Better NCP Editor/allitems.json
Normal file
File diff suppressed because it is too large
Load Diff
3
Better NCP Editor/beltitems.json
Normal file
3
Better NCP Editor/beltitems.json
Normal file
@ -0,0 +1,3 @@
|
||||
[
|
||||
"MP5A4"
|
||||
]
|
1036
Better NCP Editor/rawitems.txt
Normal file
1036
Better NCP Editor/rawitems.txt
Normal file
File diff suppressed because it is too large
Load Diff
3
Better NCP Editor/weaponmoditems.json
Normal file
3
Better NCP Editor/weaponmoditems.json
Normal file
@ -0,0 +1,3 @@
|
||||
[
|
||||
"Holosight"
|
||||
]
|
113
Better NCP Editor/wearitems.json
Normal file
113
Better NCP Editor/wearitems.json
Normal file
@ -0,0 +1,113 @@
|
||||
[
|
||||
"Abyss Divers Suit",
|
||||
"Arctic Scientist Suit",
|
||||
"Barrel Costume",
|
||||
"Bandana Mask",
|
||||
"Baseball Cap",
|
||||
"Beenie Hat",
|
||||
"Blue Jumpsuit",
|
||||
"Bone Armor",
|
||||
"Bone Helmet",
|
||||
"Boonie Hat",
|
||||
"Boots",
|
||||
"Bucket Helmet",
|
||||
"Bunny Hat",
|
||||
"Bunny Onesie",
|
||||
"Burlap Gloves",
|
||||
"Burlap Headwrap",
|
||||
"Burlap Shirt",
|
||||
"Burlap Shoes",
|
||||
"Burlap Trousers",
|
||||
"Candle Hat",
|
||||
"Chicken Costume",
|
||||
"Clatter Helmet",
|
||||
"Coffee Can Helmet",
|
||||
"Crate Costume",
|
||||
"Diving Fins",
|
||||
"Diving Mask",
|
||||
"Diving Tank",
|
||||
"Dracula Cape",
|
||||
"Dracula Mask",
|
||||
"Dragon Mask",
|
||||
"Egg Suit",
|
||||
"Frankenstein Mask",
|
||||
"Frog Boots",
|
||||
"Frontier Suit",
|
||||
"Gas Mask",
|
||||
"Ghost Costume",
|
||||
"Gingerbread Suit",
|
||||
"Hazmat Suit",
|
||||
"Heavy Plate Helmet",
|
||||
"Heavy Plate Jacket",
|
||||
"Heavy Plate Pants",
|
||||
"Heavy Scientist Suit",
|
||||
"Hide Boots",
|
||||
"Hide Halterneck",
|
||||
"Hide Pants",
|
||||
"Hide Poncho",
|
||||
"Hide Skirt",
|
||||
"Hide Vest",
|
||||
"Hockey Mask",
|
||||
"Ice Metal Chest Plate",
|
||||
"Ice Metal Facemask",
|
||||
"Improvised Balaclava",
|
||||
"Jacket",
|
||||
"Jumpsuit",
|
||||
"Knights armour cuirass",
|
||||
"Knights armour helmet",
|
||||
"Knights armour skirt plates",
|
||||
"Leather Gloves",
|
||||
"Lumberjack Hoodie",
|
||||
"Lumberjack Suit",
|
||||
"Metal Chest Plate",
|
||||
"Metal Facemask",
|
||||
"Miner Hat",
|
||||
"Mummy Mask",
|
||||
"Mummy Suit",
|
||||
"Nest Hat",
|
||||
"Night Vision Goggles",
|
||||
"Ninja Suit",
|
||||
"Nomad Suit",
|
||||
"NVGM Scientist Suit",
|
||||
"Ox Mask",
|
||||
"Pants",
|
||||
"Party Hat",
|
||||
"Prisoner Hood",
|
||||
"Purple Sunglasses",
|
||||
"Rabbit Mask",
|
||||
"Rat Mask",
|
||||
"Reindeer Antlers",
|
||||
"Riot Helmet",
|
||||
"Roadsign Gloves",
|
||||
"Road Sign Jacket",
|
||||
"Road Sign Kilt",
|
||||
"Santa Beard",
|
||||
"Santa Hat",
|
||||
"Scarecrow Suit",
|
||||
"Scarecrow Wrap",
|
||||
"Scientist Suit",
|
||||
"Shirt",
|
||||
"Shorts",
|
||||
"Snake mask",
|
||||
"Snow Jacket",
|
||||
"Space Suit",
|
||||
"Sunglasses",
|
||||
"Sunglasses Black",
|
||||
"Sunglasses Camo",
|
||||
"Sunglasses Red",
|
||||
"Sunglasses Black2",
|
||||
"Sunglasses Chrome",
|
||||
"Sunglasses Gold",
|
||||
"Surgeon Scrubs",
|
||||
"Tactical Gloves",
|
||||
"Tank Top",
|
||||
"Tiger Mask",
|
||||
"T-Shirt",
|
||||
"Twitch Rivals Hazmat Suit",
|
||||
"Waterwell NPC Jumpsuit",
|
||||
"Wetsuit",
|
||||
"Wolf Headdress",
|
||||
"Wood Armor Helmet",
|
||||
"Wood Chestplate",
|
||||
"Wooden Armor Pants"
|
||||
]
|
Loading…
x
Reference in New Issue
Block a user