mirror of
https://github.com/batfasturd/BetterNPCEditor.git
synced 2025-06-23 16:05:34 +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>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</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>
|
</Project>
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
@ -9,12 +10,15 @@ namespace Better_NCP_Editor
|
|||||||
public object NewValue { get; private set; }
|
public object NewValue { get; private set; }
|
||||||
private Control inputControl;
|
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.
|
// Set the minimum and default size.
|
||||||
this.MinimumSize = new Size(210, 150); // Example: 300x150 pixels
|
this.MinimumSize = new Size(210, 120);
|
||||||
// Optionally, set the default size if you want:
|
|
||||||
this.ClientSize = new Size(210, 150);
|
this.FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
|
||||||
// Measure the width of the property name.
|
// Measure the width of the property name.
|
||||||
Size keySize = TextRenderer.MeasureText(propertyName, this.Font);
|
Size keySize = TextRenderer.MeasureText(propertyName, this.Font);
|
||||||
|
|
||||||
@ -27,14 +31,13 @@ namespace Better_NCP_Editor
|
|||||||
}
|
}
|
||||||
else
|
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.
|
// Determine the desired width: the maximum of the key width and input width, plus extra padding.
|
||||||
int desiredWidth = Math.Max(keySize.Width, inputWidth) + 40;
|
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.ClientSize = new Size(desiredWidth, 120);
|
||||||
|
|
||||||
this.Text = $"Edit {propertyName}";
|
this.Text = $"Edit {propertyName}";
|
||||||
this.StartPosition = FormStartPosition.CenterParent;
|
this.StartPosition = FormStartPosition.CenterParent;
|
||||||
|
|
||||||
@ -47,32 +50,79 @@ namespace Better_NCP_Editor
|
|||||||
};
|
};
|
||||||
this.Controls.Add(lblProperty);
|
this.Controls.Add(lblProperty);
|
||||||
|
|
||||||
// Create the input control with width based on desiredWidth minus margins.
|
|
||||||
int controlWidth = desiredWidth - 20;
|
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()
|
ComboBox combo = new ComboBox()
|
||||||
{
|
{
|
||||||
Location = new Point(10, 40),
|
Location = new Point(10, 40),
|
||||||
Width = controlWidth,
|
Width = controlWidth, // initial width based on desiredWidth minus margins
|
||||||
DropDownStyle = ComboBoxStyle.DropDownList
|
DropDownStyle = ComboBoxStyle.DropDownList
|
||||||
};
|
};
|
||||||
combo.Items.Add("true");
|
|
||||||
combo.Items.Add("false");
|
int maxWidth = 0;
|
||||||
combo.SelectedItem = currentValue;
|
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;
|
inputControl = combo;
|
||||||
this.Controls.Add(combo);
|
this.Controls.Add(combo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TextBox txtBox = new TextBox()
|
// Create the input control normally.
|
||||||
|
if (valueType == typeof(bool))
|
||||||
{
|
{
|
||||||
Location = new Point(10, 40),
|
ComboBox combo = new ComboBox()
|
||||||
Width = controlWidth,
|
{
|
||||||
Text = currentValue
|
Location = new Point(10, 40),
|
||||||
};
|
Width = controlWidth,
|
||||||
inputControl = txtBox;
|
DropDownStyle = ComboBoxStyle.DropDownList
|
||||||
this.Controls.Add(txtBox);
|
};
|
||||||
|
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.
|
// OK button.
|
||||||
@ -91,24 +141,31 @@ namespace Better_NCP_Editor
|
|||||||
Button btnCancel = new Button()
|
Button btnCancel = new Button()
|
||||||
{
|
{
|
||||||
Text = "Cancel",
|
Text = "Cancel",
|
||||||
Location = new Point(100, 80), // Positioned to the right of OK.
|
Location = new Point(100, 80),
|
||||||
Size = new Size(80, 25),
|
Size = new Size(80, 25),
|
||||||
DialogResult = DialogResult.Cancel,
|
DialogResult = DialogResult.Cancel,
|
||||||
Anchor = AnchorStyles.Left | AnchorStyles.Bottom
|
Anchor = AnchorStyles.Left | AnchorStyles.Bottom
|
||||||
};
|
};
|
||||||
this.Controls.Add(btnCancel);
|
this.Controls.Add(btnCancel);
|
||||||
|
|
||||||
|
this.AcceptButton = btnOk;
|
||||||
|
this.CancelButton = btnCancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BtnOk_Click(object sender, EventArgs e)
|
private void BtnOk_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
// Determine new value based on input control.
|
// If the input control is the special ComboBox, return the dictionary value.
|
||||||
if (inputControl is ComboBox combo)
|
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)
|
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))
|
if (int.TryParse(txt.Text, out int intValue))
|
||||||
NewValue = intValue;
|
NewValue = intValue;
|
||||||
else
|
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
|
||||||
//
|
//
|
||||||
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.Name = "btn_load";
|
||||||
btn_load.Size = new Size(135, 29);
|
btn_load.Size = new Size(118, 22);
|
||||||
btn_load.TabIndex = 0;
|
btn_load.TabIndex = 0;
|
||||||
btn_load.Text = "Load Directory";
|
btn_load.Text = "Load Directory";
|
||||||
btn_load.UseVisualStyleBackColor = true;
|
btn_load.UseVisualStyleBackColor = true;
|
||||||
@ -54,9 +55,10 @@
|
|||||||
// btn_save
|
// btn_save
|
||||||
//
|
//
|
||||||
btn_save.Enabled = false;
|
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.Name = "btn_save";
|
||||||
btn_save.Size = new Size(93, 29);
|
btn_save.Size = new Size(81, 22);
|
||||||
btn_save.TabIndex = 1;
|
btn_save.TabIndex = 1;
|
||||||
btn_save.Text = "Save File";
|
btn_save.Text = "Save File";
|
||||||
btn_save.UseVisualStyleBackColor = true;
|
btn_save.UseVisualStyleBackColor = true;
|
||||||
@ -64,24 +66,27 @@
|
|||||||
//
|
//
|
||||||
// dirTreeView
|
// 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.Name = "dirTreeView";
|
||||||
dirTreeView.Size = new Size(290, 812);
|
dirTreeView.Size = new Size(254, 610);
|
||||||
dirTreeView.TabIndex = 2;
|
dirTreeView.TabIndex = 2;
|
||||||
//
|
//
|
||||||
// entityTreeView
|
// 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.Name = "entityTreeView";
|
||||||
entityTreeView.Size = new Size(843, 812);
|
entityTreeView.Size = new Size(738, 610);
|
||||||
entityTreeView.TabIndex = 3;
|
entityTreeView.TabIndex = 3;
|
||||||
//
|
//
|
||||||
// btn_entity_del
|
// btn_entity_del
|
||||||
//
|
//
|
||||||
btn_entity_del.Enabled = false;
|
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.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.TabIndex = 8;
|
||||||
btn_entity_del.Text = "Del";
|
btn_entity_del.Text = "Del";
|
||||||
btn_entity_del.UseVisualStyleBackColor = true;
|
btn_entity_del.UseVisualStyleBackColor = true;
|
||||||
@ -90,9 +95,10 @@
|
|||||||
// btn_entity_add
|
// btn_entity_add
|
||||||
//
|
//
|
||||||
btn_entity_add.Enabled = false;
|
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.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.TabIndex = 7;
|
||||||
btn_entity_add.Text = "Add";
|
btn_entity_add.Text = "Add";
|
||||||
btn_entity_add.UseVisualStyleBackColor = true;
|
btn_entity_add.UseVisualStyleBackColor = true;
|
||||||
@ -101,9 +107,10 @@
|
|||||||
// btn_import_entityData
|
// btn_import_entityData
|
||||||
//
|
//
|
||||||
btn_import_entityData.Enabled = false;
|
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.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.TabIndex = 9;
|
||||||
btn_import_entityData.Text = "Import";
|
btn_import_entityData.Text = "Import";
|
||||||
btn_import_entityData.UseVisualStyleBackColor = true;
|
btn_import_entityData.UseVisualStyleBackColor = true;
|
||||||
@ -112,9 +119,10 @@
|
|||||||
// btn_export_entityData
|
// btn_export_entityData
|
||||||
//
|
//
|
||||||
btn_export_entityData.Enabled = false;
|
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.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.TabIndex = 10;
|
||||||
btn_export_entityData.Text = "Export";
|
btn_export_entityData.Text = "Export";
|
||||||
btn_export_entityData.UseVisualStyleBackColor = true;
|
btn_export_entityData.UseVisualStyleBackColor = true;
|
||||||
@ -124,17 +132,18 @@
|
|||||||
//
|
//
|
||||||
statusTextbox.BorderStyle = BorderStyle.FixedSingle;
|
statusTextbox.BorderStyle = BorderStyle.FixedSingle;
|
||||||
statusTextbox.ImeMode = ImeMode.NoControl;
|
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.Name = "statusTextbox";
|
||||||
statusTextbox.ReadOnly = true;
|
statusTextbox.ReadOnly = true;
|
||||||
statusTextbox.Size = new Size(496, 27);
|
statusTextbox.Size = new Size(434, 23);
|
||||||
statusTextbox.TabIndex = 11;
|
statusTextbox.TabIndex = 11;
|
||||||
//
|
//
|
||||||
// Form1
|
// Form1
|
||||||
//
|
//
|
||||||
AutoScaleDimensions = new SizeF(8F, 20F);
|
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||||
AutoScaleMode = AutoScaleMode.Font;
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
ClientSize = new Size(1176, 881);
|
ClientSize = new Size(1028, 661);
|
||||||
Controls.Add(statusTextbox);
|
Controls.Add(statusTextbox);
|
||||||
Controls.Add(btn_export_entityData);
|
Controls.Add(btn_export_entityData);
|
||||||
Controls.Add(btn_import_entityData);
|
Controls.Add(btn_import_entityData);
|
||||||
@ -144,6 +153,7 @@
|
|||||||
Controls.Add(dirTreeView);
|
Controls.Add(dirTreeView);
|
||||||
Controls.Add(btn_save);
|
Controls.Add(btn_save);
|
||||||
Controls.Add(btn_load);
|
Controls.Add(btn_load);
|
||||||
|
Margin = new Padding(3, 2, 3, 2);
|
||||||
Name = "Form1";
|
Name = "Form1";
|
||||||
Text = "BetterNPC Editor V1.0";
|
Text = "BetterNPC Editor V1.0";
|
||||||
Load += Form1_Load;
|
Load += Form1_Load;
|
||||||
|
@ -18,6 +18,10 @@ namespace Better_NCP_Editor
|
|||||||
// In your Form1 class:
|
// In your Form1 class:
|
||||||
private ToolTip customToolTip = new ToolTip();
|
private ToolTip customToolTip = new ToolTip();
|
||||||
private TreeNode lastHoveredNode = null;
|
private TreeNode lastHoveredNode = null;
|
||||||
|
private List<String> _wearItems;
|
||||||
|
private List<String> _beltItems;
|
||||||
|
private List<String> _weaponModItems;
|
||||||
|
private Dictionary<String, String> _allItems;
|
||||||
|
|
||||||
public Form1()
|
public Form1()
|
||||||
{
|
{
|
||||||
@ -27,7 +31,7 @@ namespace Better_NCP_Editor
|
|||||||
entityTreeView.AfterSelect += entityTreeView_AfterSelect;
|
entityTreeView.AfterSelect += entityTreeView_AfterSelect;
|
||||||
|
|
||||||
// Prevent the form from shrinking below its current size.
|
// 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;
|
this.FormBorderStyle = FormBorderStyle.Sizable;
|
||||||
|
|
||||||
// Example layout using docking:
|
// Example layout using docking:
|
||||||
@ -54,8 +58,41 @@ namespace Better_NCP_Editor
|
|||||||
entityTreeView.MouseMove += EntityTreeView_MouseMove;
|
entityTreeView.MouseMove += EntityTreeView_MouseMove;
|
||||||
entityTreeView.MouseLeave += EntityTreeView_MouseLeave;
|
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)
|
private void EntityTreeView_MouseMove(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
int xOffset = 15;
|
int xOffset = 15;
|
||||||
@ -252,7 +289,7 @@ namespace Better_NCP_Editor
|
|||||||
// Enable if the selected node's Tag is a JsonArray
|
// Enable if the selected node's Tag is a JsonArray
|
||||||
if (e.Node.Tag is JsonArray)
|
if (e.Node.Tag is JsonArray)
|
||||||
{
|
{
|
||||||
//enableButtons = true;
|
enableAddDelButtons = true;
|
||||||
enableImportExportButtons = true;
|
enableImportExportButtons = true;
|
||||||
}
|
}
|
||||||
// Or if the selected node is an item in an array (its parent is a JsonArray)
|
// 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;
|
enableAddDelButtons = true;
|
||||||
enableImportExportButtons = 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:
|
// You can also add additional conditions for a "preset" node, e.g. by checking text:
|
||||||
// else if (e.Node.Text.StartsWith("Preset", StringComparison.OrdinalIgnoreCase))
|
// else if (e.Node.Text.StartsWith("Preset", StringComparison.OrdinalIgnoreCase))
|
||||||
// {
|
// {
|
||||||
@ -302,27 +344,67 @@ namespace Better_NCP_Editor
|
|||||||
else if (int.TryParse(currentVal, out int i))
|
else if (int.TryParse(currentVal, out int i))
|
||||||
valueType = typeof(int);
|
valueType = typeof(int);
|
||||||
|
|
||||||
using (EditValueForm editForm = new EditValueForm(propName, currentVal, valueType))
|
String parentNodeName = "Root";
|
||||||
{
|
String grandParentNodeName = "Root";
|
||||||
if (editForm.ShowDialog() == DialogResult.OK)
|
List<String> comboList = null;
|
||||||
{
|
|
||||||
object newVal = editForm.NewValue;
|
|
||||||
string displayVal = newVal is bool ? newVal.ToString().ToLower() : newVal.ToString();
|
|
||||||
e.Node.Text = $"{propName}: {displayVal}";
|
|
||||||
|
|
||||||
if (e.Node.Tag is JsonNode node)
|
if (e.Node.Parent != null)
|
||||||
|
{
|
||||||
|
parentNodeName = e.Node.Parent.Text;
|
||||||
|
|
||||||
|
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);
|
comboList = _wearItems;
|
||||||
node.ReplaceWith(newNode);
|
|
||||||
e.Node.Tag = newNode;
|
|
||||||
}
|
}
|
||||||
// Mark the file as modified.
|
else if (propName.Equals("ShortName", StringComparison.OrdinalIgnoreCase) && grandParentNodeName.Equals("Belt items"))
|
||||||
fileModified = true;
|
{
|
||||||
btn_save.Enabled = true;
|
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;
|
TreeNode selected = entityTreeView.SelectedNode;
|
||||||
if (selected == null)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeNode parent = selected.Parent;
|
JsonArray targetArray = null;
|
||||||
if (parent == 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);
|
targetArray = arr;
|
||||||
return;
|
duplicateExisting = false; // We'll add a new blank node
|
||||||
}
|
}
|
||||||
|
// Otherwise, if the selected node's parent is an array...
|
||||||
// Ensure the parent's Tag is a JsonArray.
|
else if (selected.Parent != null && selected.Parent.Tag is JsonArray arrParent)
|
||||||
if (!(parent.Tag is JsonArray parentArray))
|
|
||||||
{
|
{
|
||||||
MessageBox.Show("The selected node's parent is not an array node.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
targetArray = arrParent;
|
||||||
return;
|
duplicateExisting = true; // We duplicate the selected item
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Retrieve the underlying JsonNode for the selected node.
|
|
||||||
if (!(selected.Tag is JsonNode selectedJsonNode))
|
|
||||||
{
|
{
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Duplicate (deep clone) the selected JsonNode.
|
JsonNode newNode;
|
||||||
JsonNode duplicate = selectedJsonNode.DeepClone();
|
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.
|
// Add the new node to the target array.
|
||||||
parentArray.Add(duplicate);
|
targetArray.Add(newNode);
|
||||||
|
|
||||||
// Refresh only the parent's children.
|
// Determine the node representing the array.
|
||||||
parent.Nodes.Clear();
|
// If duplicating, the array node is the selected node's parent;
|
||||||
PopulateTreeRecursive((JsonNode)parent.Tag, parent);
|
// otherwise it is the selected node.
|
||||||
parent.ExpandAll(); // Expand the parent and all its child nodes
|
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;
|
fileModified = true;
|
||||||
btn_save.Enabled = true;
|
btn_save.Enabled = true;
|
||||||
|
|
||||||
// Select the newly added item (last child in the parent's node collection).
|
// Select the newly added item (the last child).
|
||||||
if (parent.Nodes.Count > 0)
|
if (arrayNode.Nodes.Count > 0)
|
||||||
{
|
{
|
||||||
TreeNode newSelected = parent.Nodes[parent.Nodes.Count - 1];
|
TreeNode newSelected = arrayNode.Nodes[arrayNode.Nodes.Count - 1];
|
||||||
entityTreeView.SelectedNode = newSelected;
|
entityTreeView.SelectedNode = newSelected;
|
||||||
newSelected.EnsureVisible();
|
newSelected.EnsureVisible();
|
||||||
entityTreeView.Focus();
|
entityTreeView.Focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void btn_entity_del_Click(object sender, EventArgs e)
|
private void btn_entity_del_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
TreeNode selected = entityTreeView.SelectedNode;
|
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