QuestInfoForm.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. using Server.MirDatabase;
  2. using Server.MirEnvir;
  3. using System.Diagnostics;
  4. namespace Server
  5. {
  6. public partial class QuestInfoForm : Form
  7. {
  8. public string QuestListPath = Path.Combine(Settings.ExportPath, "QuestList.csv");
  9. public Envir Envir => SMain.EditEnvir;
  10. private List<QuestInfo> _selectedQuestInfos;
  11. public QuestInfoForm()
  12. {
  13. InitializeComponent();
  14. QTypeComboBox.Items.AddRange(Enum.GetValues(typeof(QuestType)).Cast<object>().ToArray());
  15. RequiredClassComboBox.Items.AddRange(Enum.GetValues(typeof(RequiredClass)).Cast<object>().ToArray());
  16. QuestInfoListBox.SelectionMode = SelectionMode.One;
  17. QuestSearchBox_TextChanged(this, EventArgs.Empty);
  18. UpdateInterface();
  19. }
  20. private void AddButton_Click(object sender, EventArgs e)
  21. {
  22. Envir.CreateQuestInfo();
  23. if (!string.IsNullOrWhiteSpace(QuestSearchBox.Text))
  24. QuestSearchBox.Text = string.Empty;
  25. RefreshQuestList(preserveSelection: false);
  26. QuestInfoListBox.ClearSelected();
  27. int index = Envir.QuestInfoList.Count - 1;
  28. if (index >= 0)
  29. {
  30. QuestInfoListBox.SelectedIndex = index;
  31. QuestInfoListBox.TopIndex = Math.Max(0, index - 3);
  32. }
  33. UpdateInterface();
  34. }
  35. private void RemoveButton_Click(object sender, EventArgs e)
  36. {
  37. if (_selectedQuestInfos.Count == 0) return;
  38. if (MessageBox.Show("Are you sure you want to remove the selected Quests?", "Remove Quests?", MessageBoxButtons.YesNo) != DialogResult.Yes) return;
  39. for (int i = 0; i < _selectedQuestInfos.Count; i++) Envir.Remove(_selectedQuestInfos[i]);
  40. if (Envir.QuestInfoList.Count == 0) Envir.QuestIndex = 0;
  41. RefreshQuestList();
  42. QuestInfoListBox.ClearSelected();
  43. UpdateInterface();
  44. }
  45. private void UpdateInterface()
  46. {
  47. // Get selected quests from the ListBox
  48. _selectedQuestInfos = QuestInfoListBox.SelectedItems.Cast<QuestInfo>().ToList();
  49. if (_selectedQuestInfos.Count == 0)
  50. {
  51. ClearInterface();
  52. return;
  53. }
  54. QuestInfo info = _selectedQuestInfos[0];
  55. // Enable the panel and populate fields with selected quest details
  56. QuestInfoPanel.Enabled = true;
  57. QuestIndexTextBox.Text = info.Index.ToString();
  58. QFileNameTextBox.Text = info.FileName;
  59. QNameTextBox.Text = info.Name;
  60. QGroupTextBox.Text = info.Group;
  61. QTypeComboBox.SelectedItem = info.Type;
  62. QGotoTextBox.Text = info.GotoMessage;
  63. QKillTextBox.Text = info.KillMessage;
  64. QItemTextBox.Text = info.ItemMessage;
  65. QFlagTextBox.Text = info.FlagMessage;
  66. RequiredMinLevelTextBox.Text = info.RequiredMinLevel.ToString();
  67. RequiredMaxLevelTextBox.Text = info.RequiredMaxLevel.ToString();
  68. if (Convert.ToInt32(RequiredMaxLevelTextBox.Text) <= 0)
  69. RequiredMaxLevelTextBox.Text = byte.MaxValue.ToString();
  70. QuestInfo tempQuest = Envir.QuestInfoList.FirstOrDefault(c => c.Index == info.RequiredQuest);
  71. RequiredQuestComboBox.Items.Clear();
  72. RequiredQuestComboBox.Items.Add(new QuestInfo { Index = 0, Name = "None" });
  73. RequiredQuestComboBox.Items.AddRange(Envir.QuestInfoList.ToArray());
  74. RequiredQuestComboBox.SelectedItem = tempQuest ?? RequiredQuestComboBox.Items[0];
  75. RequiredClassComboBox.SelectedItem = info.RequiredClass;
  76. TimeLimitTextBox.Text = info.TimeLimitInSeconds.ToString();
  77. for (int i = 1; i < _selectedQuestInfos.Count; i++)
  78. {
  79. info = _selectedQuestInfos[i];
  80. if (QFileNameTextBox.Text != info.FileName) QFileNameTextBox.Text = string.Empty;
  81. if (QNameTextBox.Text != info.Name) QNameTextBox.Text = string.Empty;
  82. if (QGroupTextBox.Text != info.Group) QGroupTextBox.Text = string.Empty;
  83. if (QTypeComboBox.SelectedItem != null &&
  84. (QuestType)QTypeComboBox.SelectedItem != info.Type)
  85. {
  86. QTypeComboBox.SelectedItem = null;
  87. }
  88. if (QGotoTextBox.Text != info.GotoMessage) QGotoTextBox.Text = string.Empty;
  89. if (QKillTextBox.Text != info.KillMessage) QKillTextBox.Text = string.Empty;
  90. if (QItemTextBox.Text != info.ItemMessage) QItemTextBox.Text = string.Empty;
  91. // BUG 1: compare against FlagMessage (not ItemMessage)
  92. if (QFlagTextBox.Text != info.FlagMessage) QFlagTextBox.Text = string.Empty;
  93. if (RequiredMinLevelTextBox.Text != info.RequiredMinLevel.ToString())
  94. RequiredMinLevelTextBox.Text = string.Empty;
  95. if (RequiredMaxLevelTextBox.Text != info.RequiredMaxLevel.ToString())
  96. RequiredMaxLevelTextBox.Text = byte.MaxValue.ToString();
  97. // BUG 2: items are QuestInfo objects; compare selected item's Index
  98. if (RequiredQuestComboBox.SelectedItem is QuestInfo selReq &&
  99. selReq.Index != info.RequiredQuest)
  100. {
  101. RequiredQuestComboBox.SelectedItem = null;
  102. }
  103. if (RequiredClassComboBox.SelectedItem != null &&
  104. (RequiredClass)RequiredClassComboBox.SelectedItem != info.RequiredClass)
  105. {
  106. RequiredClassComboBox.SelectedItem = null;
  107. }
  108. // BUG 3: use Text, not SelectedText, and don't force "0" unless mismatched
  109. if (TimeLimitTextBox.Text != info.TimeLimitInSeconds.ToString())
  110. TimeLimitTextBox.Text = "0";
  111. }
  112. }
  113. // Method to clear the interface
  114. private void ClearInterface()
  115. {
  116. QuestInfoPanel.Enabled = false;
  117. QuestIndexTextBox.Text = string.Empty;
  118. QFileNameTextBox.Text = string.Empty;
  119. QNameTextBox.Text = string.Empty;
  120. QGroupTextBox.Text = string.Empty;
  121. QTypeComboBox.SelectedItem = null;
  122. QGotoTextBox.Text = string.Empty;
  123. QKillTextBox.Text = string.Empty;
  124. QItemTextBox.Text = string.Empty;
  125. QFlagTextBox.Text = string.Empty;
  126. RequiredMinLevelTextBox.Text = string.Empty;
  127. RequiredMaxLevelTextBox.Text = string.Empty;
  128. RequiredQuestComboBox.SelectedItem = null;
  129. RequiredClassComboBox.SelectedItem = null;
  130. TimeLimitTextBox.Text = string.Empty;
  131. }
  132. private void RefreshQuestList(bool preserveSelection = true)
  133. {
  134. QuestInfoListBox.SelectedIndexChanged -= QuestInfoListBox_SelectedIndexChanged;
  135. // Capture selection indices only if preserving
  136. List<int> selectedIndices = preserveSelection
  137. ? QuestInfoListBox.SelectedIndices.Cast<int>().ToList()
  138. : new List<int>();
  139. QuestInfoListBox.BeginUpdate();
  140. QuestInfoListBox.Items.Clear();
  141. // Fast add
  142. QuestInfoListBox.Items.AddRange(Envir.QuestInfoList.ToArray());
  143. // Clear selection, then optionally restore
  144. QuestInfoListBox.ClearSelected();
  145. if (preserveSelection)
  146. {
  147. foreach (int i in selectedIndices)
  148. if (i >= 0 && i < QuestInfoListBox.Items.Count)
  149. QuestInfoListBox.SetSelected(i, true);
  150. }
  151. QuestInfoListBox.EndUpdate();
  152. QuestInfoListBox.SelectedIndexChanged += QuestInfoListBox_SelectedIndexChanged;
  153. }
  154. private void QuestInfoListBox_SelectedIndexChanged(object sender, EventArgs e)
  155. {
  156. UpdateInterface();
  157. }
  158. private void QuestInfoForm_FormClosed(object sender, FormClosedEventArgs e)
  159. {
  160. Envir.SaveDB();
  161. }
  162. private void PasteMButton_Click(object sender, EventArgs e)
  163. {
  164. string data = Clipboard.GetText();
  165. if (!data.StartsWith("Quest", StringComparison.OrdinalIgnoreCase))
  166. {
  167. MessageBox.Show("Cannot Paste, Copied data is not Quest Information.");
  168. return;
  169. }
  170. string[] npcs = data.Split(new[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
  171. //for (int i = 1; i < npcs.Length; i++)
  172. // NPCInfo.FromText(npcs[i]);
  173. RefreshQuestList();
  174. UpdateInterface();
  175. }
  176. private void ExportAllButton_Click(object sender, EventArgs e)
  177. {
  178. ExportQuests(Envir.QuestInfoList);
  179. }
  180. private void ExportSelected_Click(object sender, EventArgs e)
  181. {
  182. var list = QuestInfoListBox.SelectedItems.Cast<QuestInfo>().ToList();
  183. ExportQuests(list);
  184. }
  185. public void ExportQuests(List<QuestInfo> Quests)
  186. {
  187. if (Quests.Count == 0) return;
  188. SaveFileDialog sfd = new SaveFileDialog();
  189. sfd.InitialDirectory = Path.Combine(Application.StartupPath, "Exports");
  190. sfd.FileName = "QuestInfoExport.csv";
  191. sfd.Filter = "CSV File|*.csv";
  192. sfd.ShowDialog();
  193. if (sfd.FileName == string.Empty) return;
  194. using (StreamWriter sw = File.CreateText(sfd.FileNames[0]))
  195. {
  196. sw.WriteLine("Index,Name,Group,Type,FileName,GotoMessage,KillMessage,ItemMessage,FlagMessage,RequiredMinLevel,RequiredMaxLevel,RequiredQuest,RequiredClass");
  197. for (int j = 0; j < Quests.Count; j++)
  198. {
  199. sw.WriteLine(Quests[j].ToText());
  200. }
  201. }
  202. MessageBox.Show("Quest Export complete");
  203. }
  204. private void ImportButton_Click(object sender, EventArgs e)
  205. {
  206. string Path = string.Empty;
  207. OpenFileDialog ofd = new OpenFileDialog();
  208. ofd.Filter = "CSV File|*.csv";
  209. ofd.ShowDialog();
  210. if (ofd.FileName == string.Empty) return;
  211. Path = ofd.FileName;
  212. foreach (var m in File.ReadAllLines(Path).Skip(1))
  213. QuestInfo.FromText(m);
  214. RefreshQuestList();
  215. UpdateInterface();
  216. MessageBox.Show("Quest Import complete");
  217. }
  218. private void QNameTextBox_TextChanged(object sender, EventArgs e)
  219. {
  220. if (ActiveControl != sender) return;
  221. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  222. _selectedQuestInfos[i].Name = ActiveControl.Text;
  223. RefreshQuestList();
  224. }
  225. private void QGroupTextBox_TextChanged(object sender, EventArgs e)
  226. {
  227. if (ActiveControl != sender) return;
  228. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  229. _selectedQuestInfos[i].Group = ActiveControl.Text;
  230. }
  231. private void QTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)
  232. {
  233. if (ActiveControl != sender) return;
  234. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  235. _selectedQuestInfos[i].Type = (QuestType)QTypeComboBox.SelectedItem;
  236. }
  237. private void QFileNameTextBox_TextChanged(object sender, EventArgs e)
  238. {
  239. if (ActiveControl != sender) return;
  240. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  241. _selectedQuestInfos[i].FileName = ActiveControl.Text;
  242. }
  243. private void QGotoTextBox_TextChanged(object sender, EventArgs e)
  244. {
  245. if (ActiveControl != sender) return;
  246. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  247. _selectedQuestInfos[i].GotoMessage = ActiveControl.Text;
  248. }
  249. private void QKillTextBox_TextChanged(object sender, EventArgs e)
  250. {
  251. if (ActiveControl != sender) return;
  252. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  253. _selectedQuestInfos[i].KillMessage = ActiveControl.Text;
  254. }
  255. private void QItemTextBox_TextChanged(object sender, EventArgs e)
  256. {
  257. if (ActiveControl != sender) return;
  258. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  259. _selectedQuestInfos[i].ItemMessage = ActiveControl.Text;
  260. }
  261. private void QFlagTextBox_TextChanged(object sender, EventArgs e)
  262. {
  263. if (ActiveControl != sender) return;
  264. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  265. _selectedQuestInfos[i].FlagMessage = ActiveControl.Text;
  266. }
  267. private void RequiredMinLevelTextBox_TextChanged(object sender, EventArgs e)
  268. {
  269. if (ActiveControl != sender) return;
  270. int temp;
  271. if (!int.TryParse(ActiveControl.Text, out temp) || temp > Convert.ToInt32(RequiredMaxLevelTextBox.Text) || temp < byte.MinValue)
  272. {
  273. ActiveControl.BackColor = Color.Red;
  274. return;
  275. }
  276. ActiveControl.BackColor = SystemColors.Window;
  277. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  278. _selectedQuestInfos[i].RequiredMinLevel = temp;
  279. }
  280. private void RequiredMaxLevelTextBox_TextChanged(object sender, EventArgs e)
  281. {
  282. if (ActiveControl != sender) return;
  283. int temp;
  284. if (!int.TryParse(ActiveControl.Text, out temp) || temp < Convert.ToInt32(RequiredMinLevelTextBox.Text) || temp > byte.MaxValue)
  285. {
  286. ActiveControl.BackColor = Color.Red;
  287. return;
  288. }
  289. ActiveControl.BackColor = SystemColors.Window;
  290. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  291. _selectedQuestInfos[i].RequiredMaxLevel = temp;
  292. }
  293. private void RequiredQuestComboBox_SelectedIndexChanged(object sender, EventArgs e)
  294. {
  295. if (ActiveControl != sender) return;
  296. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  297. {
  298. QuestInfo temp = (QuestInfo)RequiredQuestComboBox.SelectedItem;
  299. _selectedQuestInfos[i].RequiredQuest = temp.Index;
  300. }
  301. }
  302. private void RequiredClassComboBox_SelectedIndexChanged(object sender, EventArgs e)
  303. {
  304. if (ActiveControl != sender) return;
  305. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  306. _selectedQuestInfos[i].RequiredClass = (RequiredClass)RequiredClassComboBox.SelectedItem;
  307. }
  308. private void OpenQButton_Click(object sender, EventArgs e)
  309. {
  310. if (QFileNameTextBox.Text == string.Empty) return;
  311. var scriptPath = Path.Combine(Settings.QuestPath, QFileNameTextBox.Text + ".txt");
  312. if (File.Exists(scriptPath))
  313. {
  314. Shared.Helpers.FileIO.OpenScript(scriptPath, true);
  315. }
  316. else
  317. {
  318. Directory.CreateDirectory(Path.GetDirectoryName(scriptPath));
  319. File.Create(scriptPath).Close();
  320. File.WriteAllText(scriptPath,
  321. $"{"[@Description]"}\r\n\r\n{"[@TaskDescription]"}\r\n\r\n{"[@Completion]"}\r\n\r\n{"[@KillTasks]"}\r\n\r\n{"[@ItemTasks]"}\r\n\r\n{"[@FlagTasks]"}\r\n\r\n{"[@CarryItems]"}\r\n\r\n{"[@FixedRewards]"}\r\n\r\n{"[@SelectRewards]"}\r\n\r\n{"[@ExpReward]"}\r\n\r\n{"[@GoldReward]"}");
  322. Shared.Helpers.FileIO.OpenScript(scriptPath, true);
  323. }
  324. }
  325. private void TimeLimitTextBox_TextChanged(object sender, EventArgs e)
  326. {
  327. if (ActiveControl != sender) return;
  328. int temp;
  329. if (!int.TryParse(ActiveControl.Text, out temp))
  330. {
  331. ActiveControl.BackColor = Color.Red;
  332. return;
  333. }
  334. ActiveControl.BackColor = SystemColors.Window;
  335. for (int i = 0; i < _selectedQuestInfos.Count; i++)
  336. _selectedQuestInfos[i].TimeLimitInSeconds = temp;
  337. }
  338. #region Quest Search
  339. private void QuestSearchBox_TextChanged(object sender, EventArgs e)
  340. {
  341. string searchText = QuestSearchBox.Text.Trim().ToLower();
  342. // Show all items if the search box is empty or contains only whitespace
  343. if (string.IsNullOrWhiteSpace(searchText))
  344. {
  345. RefreshQuestList();
  346. QuestInfoListBox.ClearSelected();
  347. return;
  348. }
  349. QuestInfoListBox.Items.Clear();
  350. // Filter quests based on search text
  351. foreach (var quest in Envir.QuestInfoList)
  352. {
  353. if (!string.IsNullOrEmpty(quest.Name) && quest.Name.ToLower().Contains(searchText) ||
  354. !string.IsNullOrEmpty(quest.FileName) && quest.FileName.ToLower().Contains(searchText))
  355. {
  356. QuestInfoListBox.Items.Add(quest);
  357. }
  358. }
  359. }
  360. #endregion
  361. }
  362. }