effectlistframeunit.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. unit effectlistframeunit;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, Forms, Controls, StdCtrls, Menus, database, fpjson,
  6. LCLTranslator;
  7. type
  8. { TEffectListFrame }
  9. TEffectListFrame = class(TFrame)
  10. CopyEffectMenuItem: TMenuItem;
  11. CutEffectMenuItem: TMenuItem;
  12. DeleteEffectMenuItem: TMenuItem;
  13. EditEffectMenuItem: TMenuItem;
  14. EffectListBox: TListBox;
  15. PasteEffectMenuItem: TMenuItem;
  16. EffectPopupMenu: TPopupMenu;
  17. procedure CopyEffectMenuItemClick(Sender: TObject);
  18. procedure CutEffectMenuItemClick(Sender: TObject);
  19. procedure DeleteEffectMenuItemClick(Sender: TObject);
  20. procedure EditEffectMenuItemClick(Sender: TObject);
  21. procedure EffectListBoxDblClick(Sender: TObject);
  22. procedure EffectListBoxKeyUp(Sender: TObject; var Key: Word;
  23. Shift: TShiftState);
  24. procedure EffectListBoxMouseUp(Sender: TObject; Button: TMouseButton;
  25. Shift: TShiftState; X, Y: Integer);
  26. procedure PasteEffectMenuItemClick(Sender: TObject);
  27. private
  28. { This is handled never disposed, handled by outer object. }
  29. Db: TDatabase;
  30. { This is disposed by the JSON object in the database, it's NOT handled
  31. by TEffectListFrame }
  32. EffectList: TJSONArray;
  33. procedure UpdateEffects;
  34. function EffectToText(Effect: TJSONObject): String;
  35. function IsRealEffectSelected: Boolean;
  36. procedure AddNewEffect;
  37. procedure EditSelectedEffect;
  38. procedure ShowPopupMenu;
  39. procedure PasteFromClipboard;
  40. procedure CopySelectedToClipboard;
  41. procedure DeleteSelectedEffects;
  42. public
  43. procedure SetDatabase(ADb: TDatabase);
  44. procedure SetEffectList(AEffectList: TJSONArray);
  45. end;
  46. resourcestring
  47. AddNewEffectStr = '<Add new effect>';
  48. EffectRecoverHp = 'Recover HP: ';
  49. EffectRecoverMp = 'Recover MP: ';
  50. EffectGainTp = 'Gain TP: ';
  51. EffectAddState = 'Add state: ';
  52. EffectRemoveState = 'Remove state: ';
  53. EffectAddBuff = 'Add buff: ';
  54. EffectAddDebuff = 'Add debuff: ';
  55. EffectRemoveBuff = 'Remove buff: ';
  56. DurationTurns = ' turns'; {TODO: add correct language-dependent form}
  57. EffectRemoveDebuff = 'Remove debuff: ';
  58. EffectSpecialEscape = 'Escape from battle';
  59. EffectSpecialUnknown = 'Special: (unknown)';
  60. EffectGrow = 'Increase param: ';
  61. EffectLearnSkill = 'Learn skill: ';
  62. EffectCommonEvent = 'Common event: ';
  63. EffectUnknownEffect = '(Unknown effect)';
  64. EditEffectMenuItemStr = 'Edit';
  65. AddNewEffectMenuItemStr = 'Add new effect';
  66. implementation
  67. uses
  68. effectselector, clipboardhelper, listboxhelper, LCLType;
  69. {$R *.lfm}
  70. { TEffectListFrame }
  71. procedure TEffectListFrame.EffectListBoxDblClick(Sender: TObject);
  72. begin
  73. if not IsRealEffectSelected then
  74. AddNewEffect
  75. else
  76. EditSelectedEffect
  77. end;
  78. procedure TEffectListFrame.EffectListBoxKeyUp(Sender: TObject; var Key: Word;
  79. Shift: TShiftState);
  80. begin
  81. begin
  82. if Key = VK_DELETE then
  83. DeleteSelectedEffects;
  84. if Key = VK_RETURN then
  85. EffectListBoxDblClick(Sender);
  86. end;
  87. end;
  88. procedure TEffectListFrame.EditEffectMenuItemClick(Sender: TObject);
  89. begin
  90. if not IsRealEffectSelected then
  91. AddNewEffect
  92. else
  93. EditSelectedEffect
  94. end;
  95. procedure TEffectListFrame.CutEffectMenuItemClick(Sender: TObject);
  96. begin
  97. CopySelectedToClipboard;
  98. DeleteSelectedEffects
  99. end;
  100. procedure TEffectListFrame.DeleteEffectMenuItemClick(Sender: TObject);
  101. begin
  102. DeleteSelectedEffects
  103. end;
  104. procedure TEffectListFrame.CopyEffectMenuItemClick(Sender: TObject);
  105. begin
  106. CopySelectedToClipboard
  107. end;
  108. procedure TEffectListFrame.EffectListBoxMouseUp(Sender: TObject;
  109. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  110. begin
  111. if Button = mbRight then begin
  112. ShowPopupMenu;
  113. end;
  114. end;
  115. procedure TEffectListFrame.PasteEffectMenuItemClick(Sender: TObject);
  116. begin
  117. PasteFromClipboard
  118. end;
  119. procedure TEffectListFrame.UpdateEffects;
  120. var
  121. I: Integer;
  122. begin
  123. Assert(Db <> nil, 'Database must be set before setting effect list!');
  124. with EffectListBox.Items do begin
  125. BeginUpdate;
  126. Clear;
  127. if EffectList <> nil then begin
  128. for I := 0 to EffectList.Count -1 do begin
  129. EffectListBox.Items.Add(EffectToText(EffectList.Objects[I]));
  130. end;
  131. end;
  132. Add(AddNewEffectStr);
  133. EndUpdate;
  134. end;
  135. end;
  136. function TEffectListFrame.EffectToText(Effect: TJSONObject): String;
  137. var
  138. Code: Integer = 0;
  139. DataId: Integer = 0;
  140. Value1: Double = 0;
  141. Value2: Double = 0;
  142. CodeJson, DataIdJson, Value1Json, Value2Json: TJSONNumber;
  143. function PercentsPlusConst: String;
  144. var
  145. Percents, ConstVal: Integer;
  146. begin
  147. Percents := Round(Value1 * 100);
  148. ConstVal := Round(Value2);
  149. if (Percents <> 0) and (ConstVal <> 0) then
  150. PercentsPlusConst := Format('%d%% + %d', [Percents, ConstVal])
  151. else if (Percents <> 0) then
  152. PercentsPlusConst := IntToStr(Percents) + '%'
  153. else
  154. PercentsPlusConst := IntToStr(ConstVal)
  155. end;
  156. begin
  157. if (Effect <> nil) and Effect.Find('code', CodeJson) then
  158. Code := CodeJson.AsInteger;
  159. if (Effect <> nil) and Effect.Find('dataId', DataIdJson) then
  160. DataId := DataIdJson.AsInteger;
  161. if (Effect <> nil) and Effect.Find('value1', Value1Json) then
  162. Value1 := Value1Json.AsFloat;
  163. if (Effect <> nil) and Effect.Find('value2', Value2Json) then
  164. Value2 := Value2Json.AsFloat;
  165. case Code of
  166. EFFECT_RECOVER_HP:
  167. EffectToText := EffectRecoverHp + PercentsPlusConst;
  168. EFFECT_RECOVER_MP:
  169. EffectToText := EffectRecoverMp + PercentsPlusConst;
  170. EFFECT_GAIN_TP:
  171. EffectToText := EffectGainTp + IntToStr(Round(Value1));
  172. EFFECT_ADD_STATE:
  173. EffectToText := EffectAddState + Db.GetStateName(DataId) + ' '
  174. + IntToStr(Round(Value1 * 100)) + '%';
  175. EFFECT_REMOVE_STATE:
  176. EffectToText := EffectRemoveState + Db.GetStateName(DataId) + ' '
  177. + IntToStr(Round(Value1 * 100)) + '%';
  178. EFFECT_ADD_BUFF:
  179. EffectToText := EffectAddBuff + Db.GetParamName(DataId) + ' '
  180. + IntToStr(Round(Value1)) + DurationTurns;
  181. EFFECT_ADD_DEBUFF:
  182. EffectToText := EffectAddDebuff + Db.GetParamName(DataId) + ' '
  183. + IntToStr(Round(Value1)) + DurationTurns;
  184. EFFECT_REMOVE_BUFF:
  185. EffectToText := EffectRemoveBuff + Db.GetParamName(DataId);
  186. EFFECT_REMOVE_DEBUFF:
  187. EffectToText := EffectRemoveDebuff + Db.GetParamName(DataId);
  188. EFFECT_SPECIAL:
  189. if dataId = SPECIAL_EFFECT_ESCAPE then
  190. EffectToText := EffectSpecialEscape
  191. else
  192. EffectToText := EffectSpecialUnknown;
  193. EFFECT_GROW:
  194. EffectToText := EffectGrow + Db.GetParamName(DataId) + ' +'
  195. + IntToStr(Round(Value1));
  196. EFFECT_LEARN_SKILL:
  197. EffectToText := EffectLearnSkill + Db.GetSkillName(DataId);
  198. EFFECT_COMMON_EVENT:
  199. EffectToText := EffectCommonEvent + Db.GetCommonEventName(DataId);
  200. else
  201. EffectToText := EffectUnknownEffect;
  202. end;
  203. end;
  204. function TEffectListFrame.IsRealEffectSelected: Boolean;
  205. var
  206. LastIsSelected, NoneSelected: Boolean;
  207. begin
  208. LastIsSelected := EffectListBox.ItemIndex = EffectListBox.Items.Count - 1;
  209. NoneSelected := EffectListBox.ItemIndex < 0;
  210. IsRealEffectSelected := not LastIsSelected and not NoneSelected;
  211. end;
  212. procedure TEffectListFrame.AddNewEffect;
  213. var
  214. NewEffect: TJSONObject;
  215. begin
  216. if EffectSelectorForm.ShowEffectSelection(Db) then begin
  217. NewEffect := TJSONObject.Create;
  218. NewEffect.Add('code', EffectSelectorForm.SelectedCode);
  219. NewEffect.Add('dataId', EffectSelectorForm.SelectedDataId);
  220. NewEffect.Add('value1', EffectSelectorForm.SelectedValue1);
  221. NewEffect.Add('value2', EffectSelectorForm.SelectedValue2);
  222. EffectList.Add(NewEffect);
  223. with EffectListBox do begin
  224. Items.BeginUpdate;
  225. Items[Items.Count -1] := EffectToText(NewEffect);
  226. Items.Add(AddNewEffectStr);
  227. Items.EndUpdate;
  228. end;
  229. end;
  230. end;
  231. procedure TEffectListFrame.EditSelectedEffect;
  232. var
  233. Effect: TJSONObject;
  234. CodeJson, DataIdJson, Value1Json, Value2Json: TJSONNumber;
  235. Code: Integer = 0;
  236. DataId: Integer = 0;
  237. Value1: Double = 0;
  238. Value2: Double = 0;
  239. begin
  240. Effect := EffectList.Objects[EffectListBox.ItemIndex];
  241. if Effect.Find('code', CodeJson) then
  242. Code := CodeJson.AsInteger;
  243. if Effect.Find('dataId', DataIdJson) then
  244. DataId := DataIdJson.AsInteger;
  245. if Effect.Find('value1', Value1Json) then
  246. Value1 := Value1Json.AsFloat;
  247. if Effect.Find('value2', Value2Json) then
  248. Value2 := Value2Json.AsFloat;
  249. if EffectSelectorForm.ShowEffectSelection(Db, Code, DataId, Value1, Value2) then begin
  250. Effect.Integers['code'] := EffectSelectorForm.SelectedCode;
  251. Effect.Integers['dataId'] := EffectSelectorForm.SelectedDataId;
  252. Effect.Floats['value1'] := EffectSelectorForm.SelectedValue1;
  253. Effect.Floats['value2'] := EffectSelectorForm.SelectedValue2;
  254. EffectListBox.Items[EffectListBox.ItemIndex] := EffectToText(Effect);
  255. end
  256. end;
  257. procedure TEffectListFrame.ShowPopupMenu;
  258. var
  259. IsForRealEffect: Boolean;
  260. begin
  261. IsForRealEffect := IsRealEffectSelected;
  262. DeleteEffectMenuItem.Enabled := ListboxSelectionNotEmpty(EffectListBox);
  263. if IsForRealEffect then
  264. EditEffectMenuItem.Caption := EditEffectMenuItemStr
  265. else
  266. EditEffectMenuItem.Caption := AddNewEffectMenuItemStr;
  267. EffectPopupMenu.PopUp;
  268. end;
  269. procedure TEffectListFrame.PasteFromClipboard;
  270. var
  271. PastedArray: TJSONArray;
  272. I: Integer;
  273. StartId: Integer;
  274. begin
  275. StartId := EffectListBox.ItemIndex;
  276. PastedArray := GetJsonArrayFromClipboard('application/rpgmv-effects');
  277. if PastedArray = nil then
  278. Exit;
  279. try
  280. for I := 0 to PastedArray.Count -1 do begin
  281. if PastedArray[I].JSONType = jtObject then begin
  282. EffectList.Insert(StartId + I, PastedArray.Objects[I].Clone as TJSONObject);
  283. end;
  284. end;
  285. finally
  286. PastedArray.Free;
  287. end;
  288. UpdateEffects;
  289. end;
  290. procedure TEffectListFrame.CopySelectedToClipboard;
  291. var
  292. ArrSrl: TClipboardArraySerializer;
  293. I, NumCopied: Integer;
  294. begin
  295. ArrSrl := TClipboardArraySerializer.Create(DataTypeIds[DATA_TYPE_ID_EFFECTS]);
  296. try
  297. NumCopied := 0;
  298. for I := 0 to EffectListBox.Count -1 do begin
  299. if EffectListBox.Selected[I] then begin
  300. ArrSrl.AddItem(EffectList.Objects[I]);
  301. Inc(NumCopied)
  302. end
  303. end;
  304. if NumCopied > 0 then
  305. ArrSrl.CopyToClipboard
  306. finally
  307. ArrSrl.Free;
  308. end;
  309. end;
  310. procedure TEffectListFrame.DeleteSelectedEffects;
  311. var
  312. I: Integer;
  313. begin
  314. for I := EffectListBox.Count -1 downto 0 do begin
  315. if EffectListBox.Selected[I] then begin
  316. EffectList.Delete(I);
  317. end
  318. end;
  319. UpdateEffects
  320. end;
  321. procedure TEffectListFrame.SetDatabase(ADb: TDatabase);
  322. begin
  323. Db := ADb;
  324. end;
  325. procedure TEffectListFrame.SetEffectList(AEffectList: TJSONArray);
  326. begin
  327. EffectList := AEffectList;
  328. UpdateEffects
  329. end;
  330. end.