MonsterInfoFormNew.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. using System.Data;
  2. using System.Text;
  3. using System.Text.RegularExpressions;
  4. using Server.MirDatabase;
  5. using Server.MirEnvir;
  6. namespace Server.Database
  7. {
  8. public partial class MonsterInfoFormNew : Form
  9. {
  10. public Envir Envir => SMain.EditEnvir;
  11. private readonly Array StatEnums = Enum.GetValues(typeof(Stat));
  12. private DataTable Table;
  13. public MonsterInfoFormNew()
  14. {
  15. InitializeComponent();
  16. SetDoubleBuffered(monsterInfoGridView);
  17. InitializeItemInfoGridView();
  18. CreateDynamicColumns();
  19. PopulateTable();
  20. LoadQuestScript();
  21. rbtnViewBasic.Checked = true;
  22. monsterInfoGridView.CellBeginEdit += MonsterInfoGridView_CellBeginEdit;
  23. monsterInfoGridView.CellEndEdit += MonsterInfoGridView_CellEndEdit;
  24. }
  25. public static void SetDoubleBuffered(System.Windows.Forms.Control c)
  26. {
  27. System.Reflection.PropertyInfo aProp =
  28. typeof(System.Windows.Forms.Control).GetProperty(
  29. "DoubleBuffered",
  30. System.Reflection.BindingFlags.NonPublic |
  31. System.Reflection.BindingFlags.Instance);
  32. aProp.SetValue(c, true, null);
  33. }
  34. private void InitializeItemInfoGridView()
  35. {
  36. Modified.ValueType = typeof(bool);
  37. MonsterIndex.ValueType = typeof(int);
  38. MonsterName.ValueType = typeof(string);
  39. MonsterAI.ValueType = typeof(byte);
  40. MonsterEffect.ValueType = typeof(byte);
  41. MonsterLevel.ValueType = typeof(ushort);
  42. MonsterLight.ValueType = typeof(byte);
  43. MonsterAttackSpeed.ValueType = typeof(ushort);
  44. MonsterMoveSpeed.ValueType = typeof(ushort);
  45. MonsterViewRange.ValueType = typeof(byte);
  46. MonsterCoolEye.ValueType = typeof(byte);
  47. MonsterExperience.ValueType = typeof(uint);
  48. MonsterCanPush.ValueType = typeof(bool);
  49. MonsterAutoRev.ValueType = typeof(bool);
  50. MonsterUndead.ValueType = typeof(bool);
  51. MonsterCanTame.ValueType = typeof(bool);
  52. MonsterIsBoss.ValueType = typeof(bool);
  53. MonsterRecall.ValueType = typeof(bool);
  54. MonsterDropPath.ValueType = typeof(string);
  55. //Basic
  56. this.MonsterImage.ValueType = typeof(Monster);
  57. this.MonsterImage.DataSource = Enum2DataTable<Monster>(true);
  58. this.MonsterImage.ValueMember = "Value";
  59. this.MonsterImage.DisplayMember = "Display";
  60. }
  61. public static DataTable Enum2DataTable<T>(bool sort = false)
  62. {
  63. DataTable enumTable = new DataTable();
  64. enumTable.Columns.Add(new DataColumn("Value", Enum.GetUnderlyingType(typeof(T))));
  65. enumTable.Columns.Add(new DataColumn("Display", typeof(string)));
  66. DataRow EnumRow;
  67. var values = Enum.GetValues(typeof(T)).Cast<T>();
  68. if (sort)
  69. {
  70. values = values.OrderBy(x => x.ToString());
  71. }
  72. foreach (T e in values)
  73. {
  74. EnumRow = enumTable.NewRow();
  75. EnumRow["Value"] = e;
  76. EnumRow["Display"] = e.ToString();
  77. enumTable.Rows.Add(EnumRow);
  78. }
  79. return enumTable;
  80. }
  81. private void CreateDynamicColumns()
  82. {
  83. foreach (Stat stat in StatEnums)
  84. {
  85. if (stat == Stat.Unknown) continue;
  86. var key = stat.ToString();
  87. var strKey = RegexFunctions.SeperateCamelCase(key.Replace("Rate", "").Replace("Multiplier", "").Replace("Percent", ""));
  88. var sign = "";
  89. if (key.Contains("Percent"))
  90. sign = "%";
  91. else if (key.Contains("Multiplier"))
  92. sign = "x";
  93. var col = new DataGridViewTextBoxColumn
  94. {
  95. HeaderText = $"{strKey} {sign}",
  96. Name = "Stat" + stat.ToString(),
  97. ValueType = typeof(int),
  98. DataPropertyName = "Stat" + stat.ToString()
  99. };
  100. monsterInfoGridView.Columns.Add(col);
  101. }
  102. }
  103. private void PopulateTable()
  104. {
  105. Table = new DataTable("monsterInfo");
  106. foreach (DataGridViewColumn col in monsterInfoGridView.Columns)
  107. {
  108. Table.Columns.Add(col.DataPropertyName, col.ValueType);
  109. }
  110. foreach (MirDatabase.MonsterInfo item in Envir.MonsterInfoList)
  111. {
  112. DataRow row = Table.NewRow();
  113. row["Modified"] = false;
  114. row["MonsterIndex"] = item.Index;
  115. row["MonsterName"] = item.Name;
  116. row["MonsterImage"] = item.Image;
  117. row["MonsterAI"] = item.AI;
  118. row["MonsterLevel"] = item.Level;
  119. row["MonsterEffect"] = item.Effect;
  120. row["MonsterLight"] = item.Light;
  121. row["MonsterAttackSpeed"] = item.AttackSpeed;
  122. row["MonsterMoveSpeed"] = item.MoveSpeed;
  123. row["MonsterViewRange"] = item.ViewRange;
  124. row["MonsterCoolEye"] = item.CoolEye;
  125. row["MonsterExperience"] = item.Experience;
  126. row["MonsterCanPush"] = item.CanPush;
  127. row["MonsterCanTame"] = item.CanTame;
  128. row["MonsterIsBoss"] = item.IsBoss;
  129. row["MonsterUndead"] = item.Undead;
  130. row["MonsterAutoRev"] = item.AutoRev;
  131. row["MonsterRecall"] = item.CanRecall;
  132. row["MonsterDropPath"] = item.DropPath;
  133. foreach (Stat stat in StatEnums)
  134. {
  135. if (stat == Stat.Unknown) continue;
  136. row["Stat" + stat.ToString()] = item.Stats[stat];
  137. }
  138. Table.Rows.Add(row);
  139. }
  140. monsterInfoGridView.DataSource = Table;
  141. }
  142. private void UpdateFilter()
  143. {
  144. var filterText = txtSearch.Text;
  145. if (string.IsNullOrEmpty(filterText))
  146. {
  147. (monsterInfoGridView.DataSource as DataTable).DefaultView.RowFilter = "";
  148. return;
  149. }
  150. string rowFilter = string.Format("[MonsterName] LIKE '%{0}%'", filterText);
  151. (monsterInfoGridView.DataSource as DataTable).DefaultView.RowFilter = rowFilter;
  152. }
  153. private void SaveForm()
  154. {
  155. int lastIndex = 0;
  156. if (Envir.MonsterInfoList.Count > 0)
  157. {
  158. lastIndex = Envir.MonsterInfoList.Max(x => x.Index);
  159. }
  160. foreach (DataGridViewRow row in monsterInfoGridView.Rows)
  161. {
  162. var name = row.Cells["MonsterName"].Value;
  163. if (name == null || name.GetType() == typeof(System.DBNull) || string.IsNullOrWhiteSpace((string)name))
  164. {
  165. continue;
  166. }
  167. MonsterInfo monster;
  168. if (string.IsNullOrEmpty((string)row.Cells["MonsterIndex"].FormattedValue))
  169. {
  170. Envir.MonsterInfoList.Add(monster = new MonsterInfo());
  171. monster.Index = ++lastIndex;
  172. }
  173. else
  174. {
  175. int index = (int)row.Cells["MonsterIndex"].Value;
  176. monster = Envir.MonsterInfoList.FirstOrDefault(x => x.Index == index);
  177. if (row.Cells["Modified"].Value != null && (bool)row.Cells["Modified"].Value == false) continue;
  178. }
  179. monster.Name = (string)row.Cells["MonsterName"].Value;
  180. monster.Image = (Monster)row.Cells["MonsterImage"].Value;
  181. monster.AI = (byte)row.Cells["MonsterAI"].Value;
  182. monster.Level = (ushort)row.Cells["MonsterLevel"].Value;
  183. monster.Effect = (byte)row.Cells["MonsterEffect"].Value;
  184. monster.Light = (byte)row.Cells["MonsterLight"].Value;
  185. monster.AttackSpeed = (ushort)row.Cells["MonsterAttackSpeed"].Value;
  186. monster.MoveSpeed = (ushort)row.Cells["MonsterMoveSpeed"].Value;
  187. monster.ViewRange = (byte)row.Cells["MonsterViewRange"].Value;
  188. monster.CoolEye = (byte)row.Cells["MonsterCoolEye"].Value;
  189. monster.Experience = (uint)row.Cells["MonsterExperience"].Value;
  190. monster.CanPush = (bool)row.Cells["MonsterCanPush"].Value;
  191. monster.CanTame = (bool)row.Cells["MonsterCanTame"].Value;
  192. monster.IsBoss = row.Cells["MonsterIsBoss"].Value != null && (bool)row.Cells["MonsterIsBoss"].Value;
  193. monster.Undead = (bool)row.Cells["MonsterUndead"].Value;
  194. monster.AutoRev = (bool)row.Cells["MonsterAutoRev"].Value;
  195. monster.CanRecall = row.Cells["MonsterRecall"].Value != null && (bool)row.Cells["MonsterRecall"].Value;
  196. monster.DropPath = row.Cells["MonsterDropPath"].Value?.ToString() ?? string.Empty;
  197. monster.Stats.Clear();
  198. foreach (DataGridViewColumn col in monsterInfoGridView.Columns)
  199. {
  200. if (col.Name.StartsWith("Stat"))
  201. {
  202. var stat = col.Name.Substring(4);
  203. Stat enumStat = (Stat)Enum.Parse(typeof(Stat), stat);
  204. monster.Stats[enumStat] = (int)row.Cells[col.Name].Value;
  205. }
  206. }
  207. }
  208. SaveQuestScript();
  209. }
  210. private DataRow FindRowByMonsterName(string value)
  211. {
  212. foreach (DataRow row in Table.Rows)
  213. {
  214. var val = row["MonsterName"];
  215. if (val?.ToString().Equals(value) ?? false)
  216. {
  217. return row;
  218. }
  219. }
  220. return null;
  221. }
  222. private DataRow FindRowByMonsterIndex(string index)
  223. {
  224. foreach (DataRow row in Table.Rows)
  225. {
  226. var val = row["MonsterIndex"];
  227. if (val?.ToString().Equals(index) ?? false)
  228. {
  229. return row;
  230. }
  231. }
  232. return null;
  233. }
  234. private void monsterInfoGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
  235. {
  236. var col = monsterInfoGridView.Columns[e.ColumnIndex];
  237. var cell = monsterInfoGridView.Rows[e.RowIndex].Cells[col.Name];
  238. if (cell.FormattedValue != null && e.FormattedValue != null && cell.FormattedValue.ToString() == e.FormattedValue.ToString())
  239. {
  240. return;
  241. }
  242. monsterInfoGridView.Rows[e.RowIndex].Cells["Modified"].Value = true;
  243. var val = e.FormattedValue.ToString();
  244. monsterInfoGridView.Rows[e.RowIndex].ErrorText = "";
  245. if (col.ValueType == typeof(int) && int.TryParse(val, out int val1) && val1 < 0)
  246. {
  247. e.Cancel = true;
  248. monsterInfoGridView.Rows[e.RowIndex].ErrorText = "the value must be a positive integer";
  249. }
  250. if (col.ValueType == typeof(int) && !int.TryParse(val, out _))
  251. {
  252. e.Cancel = true;
  253. monsterInfoGridView.Rows[e.RowIndex].ErrorText = "the value must be an integer";
  254. }
  255. else if (col.ValueType == typeof(byte) && !byte.TryParse(val, out _))
  256. {
  257. e.Cancel = true;
  258. monsterInfoGridView.Rows[e.RowIndex].ErrorText = "the value must be a byte";
  259. }
  260. else if (col.ValueType == typeof(short) && !short.TryParse(val, out _))
  261. {
  262. e.Cancel = true;
  263. monsterInfoGridView.Rows[e.RowIndex].ErrorText = "the value must be a short";
  264. }
  265. else if (col.ValueType == typeof(ushort) && !ushort.TryParse(val, out _))
  266. {
  267. e.Cancel = true;
  268. monsterInfoGridView.Rows[e.RowIndex].ErrorText = "the value must be a ushort";
  269. }
  270. else if (col.ValueType == typeof(long) && !long.TryParse(val, out _))
  271. {
  272. e.Cancel = true;
  273. monsterInfoGridView.Rows[e.RowIndex].ErrorText = "the value must be a long";
  274. }
  275. }
  276. private void rbtnViewAll_CheckedChanged(object sender, EventArgs e)
  277. {
  278. if (rbtnViewAll.Checked)
  279. {
  280. foreach (DataGridViewColumn col in monsterInfoGridView.Columns)
  281. {
  282. if (col.Name == "Modified") continue;
  283. col.Visible = true;
  284. continue;
  285. }
  286. }
  287. }
  288. private void rbtnViewBasic_CheckedChanged(object sender, EventArgs e)
  289. {
  290. if (rbtnViewBasic.Checked)
  291. {
  292. foreach (DataGridViewColumn col in monsterInfoGridView.Columns)
  293. {
  294. if (col.Name == "MonsterIndex" || col.Name == "MonsterName" || col.Name == "Modified")
  295. {
  296. continue;
  297. }
  298. if (col.Name.StartsWith("Monster"))
  299. {
  300. col.Visible = true;
  301. continue;
  302. }
  303. if (col.Name.Equals("StatHP") ||
  304. col.Name.Equals("StatMinAC") || col.Name.Equals("StatMaxAC") ||
  305. col.Name.Equals("StatMinMAC") || col.Name.Equals("StatMaxMAC") ||
  306. col.Name.Equals("StatMinDC") || col.Name.Equals("StatMaxDC") ||
  307. col.Name.Equals("StatMinMC") || col.Name.Equals("StatMaxMC") ||
  308. col.Name.Equals("StatMinSC") || col.Name.Equals("StatMaxSC") ||
  309. col.Name.Equals("StatAccuracy") || col.Name.Equals("StatAgility"))
  310. {
  311. col.Visible = true;
  312. continue;
  313. }
  314. col.Visible = false;
  315. }
  316. }
  317. }
  318. private void txtSearch_KeyDown(object sender, KeyEventArgs e)
  319. {
  320. if (e.KeyCode == Keys.Enter)
  321. {
  322. UpdateFilter();
  323. e.Handled = true;
  324. e.SuppressKeyPress = true;
  325. }
  326. }
  327. private void btnImport_Click(object sender, EventArgs e)
  328. {
  329. OpenFileDialog ofd = new OpenFileDialog();
  330. ofd.Filter = "CSV (*.csv)|*.csv";
  331. if (ofd.ShowDialog() == DialogResult.OK)
  332. {
  333. var fileName = ofd.FileName;
  334. bool fileError = false;
  335. var rows = File.ReadAllLines(fileName);
  336. if (rows.Length > 1)
  337. {
  338. var columns = rows[0].Split(',');
  339. if (columns.Length < 2)
  340. {
  341. fileError = true;
  342. MessageBox.Show("No columns to import.");
  343. }
  344. if (!fileError)
  345. {
  346. monsterInfoGridView.EditMode = DataGridViewEditMode.EditProgrammatically;
  347. int rowsEdited = 0;
  348. for (int i = 1; i < rows.Length; i++)
  349. {
  350. var row = rows[i];
  351. var cells = row.Split(',');
  352. if (string.IsNullOrWhiteSpace(cells[0]))
  353. {
  354. continue;
  355. }
  356. if (cells.Length != columns.Length)
  357. {
  358. fileError = true;
  359. MessageBox.Show($"Row {i} column count does not match the headers column count.");
  360. break;
  361. }
  362. var dataRow = FindRowByMonsterIndex(cells[0]);
  363. try
  364. {
  365. monsterInfoGridView.BeginEdit(true);
  366. bool isNew = false;
  367. if (dataRow == null)
  368. {
  369. dataRow = Table.NewRow();
  370. isNew = true;
  371. }
  372. for (int j = 1; j < columns.Length; j++)
  373. {
  374. var column = columns[j];
  375. if (string.IsNullOrWhiteSpace(column))
  376. {
  377. continue;
  378. }
  379. var dataColumn = monsterInfoGridView.Columns[column];
  380. if (dataColumn == null)
  381. {
  382. throw new Exception($"Column {column} was not found.");
  383. }
  384. if (dataColumn.Name == "MonsterName")
  385. {
  386. var existingRow = FindRowByMonsterName(cells[j]);
  387. if (existingRow != null)
  388. {
  389. var existingIndex = existingRow["MonsterIndex"].ToString();
  390. var currentIndex = dataRow["MonsterIndex"].ToString() ?? "";
  391. if (existingIndex != currentIndex)
  392. {
  393. throw new Exception($"An monster named {cells[j]} already exists.");
  394. }
  395. }
  396. if (!isNew) MonsterNameChange(dataRow[column].ToString(), cells[j]);
  397. }
  398. if (dataColumn.ValueType.IsEnum)
  399. {
  400. dataRow[column] = Enum.Parse(dataColumn.ValueType, cells[j]);
  401. }
  402. else
  403. {
  404. dataRow[column] = cells[j];
  405. }
  406. }
  407. dataRow["Modified"] = true;
  408. monsterInfoGridView.EndEdit();
  409. if (isNew)
  410. {
  411. Table.Rows.Add(dataRow);
  412. }
  413. rowsEdited++;
  414. }
  415. catch (Exception ex)
  416. {
  417. fileError = true;
  418. monsterInfoGridView.EndEdit();
  419. MessageBox.Show($"Error when importing item {cells[0]}. {ex.Message}");
  420. break;
  421. }
  422. }
  423. monsterInfoGridView.EditMode = DataGridViewEditMode.EditOnKeystrokeOrF2;
  424. if (!fileError)
  425. {
  426. MessageBox.Show($"{rowsEdited} monsters have been imported.");
  427. }
  428. else
  429. {
  430. monsterInfoGridView.ClearSelection();
  431. monsterInfoGridView.Rows[rowsEdited].Selected = true;
  432. monsterInfoGridView.CurrentCell = monsterInfoGridView.Rows[rowsEdited].Cells[0];
  433. }
  434. }
  435. }
  436. else
  437. {
  438. MessageBox.Show("No rows to import.");
  439. }
  440. }
  441. }
  442. private void btnExport_Click(object sender, EventArgs e)
  443. {
  444. if (monsterInfoGridView.Rows.Count > 0)
  445. {
  446. SaveFileDialog sfd = new SaveFileDialog();
  447. sfd.Filter = "CSV (*.csv)|*.csv";
  448. sfd.FileName = "MonsterInfo Output.csv";
  449. bool fileError = false;
  450. if (sfd.ShowDialog() == DialogResult.OK)
  451. {
  452. if (File.Exists(sfd.FileName))
  453. {
  454. try
  455. {
  456. File.Delete(sfd.FileName);
  457. }
  458. catch (IOException ex)
  459. {
  460. fileError = true;
  461. MessageBox.Show("It wasn't possible to write the data to the disk." + ex.Message);
  462. }
  463. }
  464. if (!fileError)
  465. {
  466. try
  467. {
  468. int columnCount = monsterInfoGridView.Columns.Count;
  469. string columnNames = "";
  470. string[] outputCsv = new string[monsterInfoGridView.Rows.Count + 1];
  471. for (int i = 1; i < columnCount; i++)
  472. {
  473. columnNames += monsterInfoGridView.Columns[i].Name.ToString() + ",";
  474. }
  475. outputCsv[0] += columnNames;
  476. for (int i = 1; (i - 1) < monsterInfoGridView.Rows.Count; i++)
  477. {
  478. for (int j = 1; j < columnCount; j++)
  479. {
  480. var cell = monsterInfoGridView.Rows[i - 1].Cells[j];
  481. var valueType = monsterInfoGridView.Columns[j].ValueType;
  482. if (valueType.IsEnum)
  483. {
  484. outputCsv[i] += ((Enum.ToObject(valueType, cell.Value ?? 0))?.ToString() ?? "") + ",";
  485. }
  486. else
  487. {
  488. outputCsv[i] += (cell.Value?.ToString() ?? "") + ",";
  489. }
  490. }
  491. }
  492. File.WriteAllLines(sfd.FileName, outputCsv, Encoding.UTF8);
  493. MessageBox.Show("Data Exported Successfully.", "Info");
  494. }
  495. catch (Exception ex)
  496. {
  497. MessageBox.Show("Error :" + ex.Message);
  498. }
  499. }
  500. }
  501. }
  502. else
  503. {
  504. MessageBox.Show("No Monsters To Export.", "Info");
  505. }
  506. }
  507. private void monsterInfoGridView_DefaultValuesNeeded(object sender, DataGridViewRowEventArgs e)
  508. {
  509. var row = e.Row;
  510. row.Cells["Modified"].Value = (bool)true;
  511. row.Cells["MonsterName"].Value = "";
  512. row.Cells["MonsterImage"].Value = (Monster)0;
  513. row.Cells["MonsterAI"].Value = (byte)0;
  514. row.Cells["MonsterLevel"].Value = (ushort)0;
  515. row.Cells["MonsterEffect"].Value = (byte)0;
  516. row.Cells["MonsterLight"].Value = (byte)0;
  517. row.Cells["MonsterAttackSpeed"].Value = (ushort)2500;
  518. row.Cells["MonsterMoveSpeed"].Value = (ushort)1800;
  519. row.Cells["MonsterViewRange"].Value = (byte)7;
  520. row.Cells["MonsterCoolEye"].Value = (byte)0;
  521. row.Cells["MonsterExperience"].Value = (uint)0;
  522. row.Cells["MonsterCanPush"].Value = (bool)true;
  523. row.Cells["MonsterCanTame"].Value = (bool)true;
  524. row.Cells["MonsterIsBoss"].Value = (bool)false;
  525. row.Cells["MonsterUndead"].Value = (bool)false;
  526. row.Cells["MonsterAutoRev"].Value = (bool)true;
  527. row.Cells["MonsterRecall"].Value = (bool)false;
  528. row.Cells["MonsterDropPath"].Value = "";
  529. foreach (Stat stat in StatEnums)
  530. {
  531. if (stat == Stat.Unknown) continue;
  532. row.Cells["Stat" + stat.ToString()].Value = 0;
  533. }
  534. }
  535. private void monsterInfoGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
  536. {
  537. var row = e.Row;
  538. if (row.Cells["MonsterIndex"].Value != null)
  539. {
  540. int index = (int)row.Cells["MonsterIndex"].Value;
  541. var item = Envir.MonsterInfoList.FirstOrDefault(x => x.Index == index);
  542. Envir.MonsterInfoList.Remove(item);
  543. }
  544. }
  545. private void monsterInfoFormNew_FormClosed(object sender, FormClosedEventArgs e)
  546. {
  547. SaveForm();
  548. Envir.SaveDB();
  549. }
  550. private void monsterInfoGridView_DataError(object sender, DataGridViewDataErrorEventArgs e)
  551. {
  552. }
  553. private Dictionary<string, string[]> questScriptFilesContent;
  554. private bool questFileChange;
  555. private string monsterNameCellOldValue;
  556. private void MonsterInfoGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
  557. {
  558. if (monsterInfoGridView.Columns[e.ColumnIndex].Name == "MonsterName")
  559. {
  560. monsterNameCellOldValue = monsterInfoGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value?.ToString();
  561. }
  562. else
  563. {
  564. monsterNameCellOldValue = string.Empty;
  565. }
  566. }
  567. private void MonsterInfoGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
  568. {
  569. if (monsterInfoGridView.Columns[e.ColumnIndex].Name == "MonsterName" && e.RowIndex != -1)
  570. {
  571. var newName = monsterInfoGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value?.ToString() ?? string.Empty;
  572. MonsterNameChange(monsterNameCellOldValue, newName);
  573. monsterNameCellOldValue = string.Empty;
  574. }
  575. }
  576. private Dictionary<string, string[]> LoadScriptFiles(string path, string searchPattern)
  577. {
  578. var filesContent = new Dictionary<string, string[]>();
  579. foreach (var file in Directory.GetFiles(path, searchPattern, SearchOption.AllDirectories))
  580. {
  581. filesContent.Add(file, File.ReadAllLines(file));
  582. }
  583. return filesContent;
  584. }
  585. private void SaveScriptFile(Dictionary<string, string[]> files)
  586. {
  587. foreach (var file in files)
  588. {
  589. File.WriteAllLines(file.Key, file.Value);
  590. }
  591. }
  592. private void LoadQuestScript()
  593. {
  594. questScriptFilesContent = LoadScriptFiles(@"Envir\Quests", "*.txt");
  595. }
  596. private void SaveQuestScript()
  597. {
  598. if (questFileChange) SaveScriptFile(questScriptFilesContent);
  599. }
  600. private void MonsterNameChange(string oldName, string newName)
  601. {
  602. if (!string.IsNullOrWhiteSpace(oldName) && !string.IsNullOrWhiteSpace(newName) && !oldName.Equals(newName, StringComparison.OrdinalIgnoreCase))
  603. {
  604. foreach (var file in questScriptFilesContent)
  605. {
  606. var lines = file.Value;
  607. bool isMonster = false;
  608. for (int i = 0; i < lines.Length; i++)
  609. {
  610. var line = lines[i];
  611. if (line.StartsWith("[@KillTasks]"))
  612. {
  613. isMonster = true;
  614. }
  615. else if (string.IsNullOrWhiteSpace(line) || line.StartsWith("["))
  616. {
  617. isMonster = false;
  618. }
  619. else if (isMonster)
  620. {
  621. var match = Regex.Match(line, @"^([^\s|[]+)(?=\s?)");
  622. if (match.Success)
  623. {
  624. string monsterName = match.Groups[1].Value;
  625. if (monsterName.Equals(oldName, StringComparison.OrdinalIgnoreCase))
  626. {
  627. lines[i] = line.Replace(monsterName, newName);
  628. questFileChange = true;
  629. }
  630. }
  631. }
  632. }
  633. }
  634. }
  635. }
  636. }
  637. }