expcurveformunit.pas 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. unit expcurveformunit;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
  6. ComCtrls, Spin, ButtonPanel, BGRABitmap, LCLTranslator;
  7. type
  8. { TExpCurveForm }
  9. TExpCurveForm = class(TForm)
  10. PreviewPaintBox: TPaintBox;
  11. ResultButtonPanel: TButtonPanel;
  12. ExtraValueGroupBox: TGroupBox;
  13. AccelAGroupBox: TGroupBox;
  14. AccelBGroupBox: TGroupBox;
  15. AccelASpinEdit: TSpinEdit;
  16. AccelATrackBar: TTrackBar;
  17. DisplayModeLabel: TLabel;
  18. ExpForNextLevelRadioButton: TRadioButton;
  19. BaseValueGroupBox: TGroupBox;
  20. AccelBSpinEdit: TSpinEdit;
  21. AccelBTrackBar: TTrackBar;
  22. BaseValueSpinEdit: TSpinEdit;
  23. ExtraValueSpinEdit: TSpinEdit;
  24. BaseValueTrackBar: TTrackBar;
  25. ExtraValueTrackBar: TTrackBar;
  26. ValueChangePanel: TPanel;
  27. TotalExpRadioButton: TRadioButton;
  28. procedure AccelASpinEditChange(Sender: TObject);
  29. procedure AccelATrackBarChange(Sender: TObject);
  30. procedure AccelBSpinEditChange(Sender: TObject);
  31. procedure AccelBTrackBarChange(Sender: TObject);
  32. procedure BaseValueSpinEditChange(Sender: TObject);
  33. procedure BaseValueTrackBarChange(Sender: TObject);
  34. procedure CancelButtonClick(Sender: TObject);
  35. procedure DisplayModeRadioButtonChange(Sender: TObject);
  36. procedure ExtraValueSpinEditChange(Sender: TObject);
  37. procedure ExtraValueTrackBarChange(Sender: TObject);
  38. procedure OKButtonClick(Sender: TObject);
  39. procedure PreviewPaintBoxPaint(Sender: TObject);
  40. { Draws graph image, used as a background for the preview image. Its width
  41. is not equal to the preview image, and is expected to be stretched. Return
  42. value of this function must be freed. }
  43. function DrawGraphImage: TBGRABitmap;
  44. { Return experience needed for a given level }
  45. function ExpForLevel(Level: Integer): Integer;
  46. function ExpFromPrevLevel(Level: Integer): Integer;
  47. private
  48. ResultWasAccepted: Boolean;
  49. public
  50. BaseValue, ExtraValue, AccelA, AccelB: Integer;
  51. function ShowExpCurveSetup(ABaseValue, AExtraValue, AAccelA, AAccelB: Integer): Boolean;
  52. end;
  53. var
  54. ExpCurveForm: TExpCurveForm;
  55. implementation
  56. uses
  57. BGRABitmapTypes, Math;
  58. {$R *.lfm}
  59. { TExpCurveForm }
  60. procedure TExpCurveForm.BaseValueTrackBarChange(Sender: TObject);
  61. begin
  62. BaseValue := BaseValueTrackBar.Position;
  63. BaseValueSpinEdit.Value := BaseValue;
  64. Refresh;
  65. end;
  66. procedure TExpCurveForm.CancelButtonClick(Sender: TObject);
  67. begin
  68. ResultWasAccepted := False;
  69. Close
  70. end;
  71. procedure TExpCurveForm.DisplayModeRadioButtonChange(Sender: TObject);
  72. begin
  73. Refresh
  74. end;
  75. procedure TExpCurveForm.ExtraValueSpinEditChange(Sender: TObject);
  76. begin
  77. ExtraValue := ExtraValueSpinEdit.Value;
  78. ExtraValueTrackBar.Position := ExtraValue;
  79. Refresh;
  80. end;
  81. procedure TExpCurveForm.ExtraValueTrackBarChange(Sender: TObject);
  82. begin
  83. ExtraValue := ExtraValueTrackBar.Position;
  84. ExtraValueSpinEdit.Value := ExtraValue;
  85. Refresh;
  86. end;
  87. procedure TExpCurveForm.OKButtonClick(Sender: TObject);
  88. begin
  89. ResultWasAccepted := True;
  90. Close
  91. end;
  92. procedure TExpCurveForm.PreviewPaintBoxPaint(Sender: TObject);
  93. var
  94. ImgWidth, ImgHeight: Integer;
  95. GraphImage, FinalImage: TBGRABitmap;
  96. StretchedImage: TBGRACustomBitmap;
  97. Row: Integer;
  98. Column, X, Y, LvTextShift: Integer;
  99. NumColumns, ItemsInColumn, I: Integer;
  100. ToNext: Boolean;
  101. begin
  102. { TODO: repaint the preview }
  103. GraphImage := DrawGraphImage;
  104. ImgWidth := PreviewPaintBox.Width;
  105. ImgHeight := PreviewPaintBox.Height;
  106. FinalImage := TBGRABitmap.Create(ImgWidth, ImgHeight, clWhite);
  107. StretchedImage := GraphImage.Resample(ImgWidth, ImgHeight);
  108. FinalImage.Assign(StretchedImage);
  109. StretchedImage.Free;
  110. GraphImage.Free;
  111. { TODO: find number of columns and rows dynamically? }
  112. NumColumns := 5;
  113. ItemsInColumn := 20;
  114. ToNext := ExpForNextLevelRadioButton.Checked;
  115. I := 1;
  116. FinalImage.CanvasBGRA.Font.Height := Min(20, ImgHeight div ItemsInColumn);
  117. if ImgHeight > ImgWidth then
  118. FinalImage.CanvasBGRA.Font.Height := Round(FinalImage.CanvasBGRA.Font.Height * ImgWidth / ImgHeight * 0.8);
  119. FinalImage.CanvasBGRA.Brush.Style := bsClear;
  120. LvTextShift := FinalImage.CanvasBGRA.TextWidth('L99: ');
  121. for Column := 1 to NumColumns do
  122. for Row := 1 to ItemsInColumn do begin
  123. if (I > 98) and (ToNext or (I > 99)) then
  124. Break;
  125. X := (Column - 1) * (ImgWidth div NumColumns);
  126. Y := (Row - 1) * (ImgHeight div ItemsInColumn);
  127. FinalImage.CanvasBGRA.Font.Color := clBlack;
  128. FinalImage.CanvasBGRA.TextOut(X, Y, 'L' + IntToStr(I) + ': ');
  129. X := X + LvTextShift;
  130. if ToNext then begin
  131. FinalImage.CanvasBGRA.Font.Color := clGreen;
  132. FinalImage.CanvasBGRA.TextOut(X, Y, IntToStr(ExpFromPrevLevel(I + 1)));
  133. end else begin
  134. FinalImage.CanvasBGRA.Font.Color := clRed;
  135. FinalImage.CanvasBGRA.TextOut(X, Y, IntToStr(ExpForLevel(I)));
  136. end;
  137. Inc(I);
  138. end;
  139. FinalImage.Draw(PreviewPaintBox.Canvas, 0, 0, True);
  140. FinalImage.Free;
  141. end;
  142. procedure TExpCurveForm.BaseValueSpinEditChange(Sender: TObject);
  143. begin
  144. BaseValue := BaseValueSpinEdit.Value;
  145. BaseValueTrackBar.Position := BaseValue;
  146. Refresh;
  147. end;
  148. procedure TExpCurveForm.AccelATrackBarChange(Sender: TObject);
  149. begin
  150. AccelA := AccelATrackBar.Position;
  151. AccelASpinEdit.Value := AccelA;
  152. Refresh;
  153. end;
  154. procedure TExpCurveForm.AccelBSpinEditChange(Sender: TObject);
  155. begin
  156. AccelB := AccelBSpinEdit.Value;
  157. AccelBTrackBar.Position := AccelB;
  158. Refresh;
  159. end;
  160. procedure TExpCurveForm.AccelBTrackBarChange(Sender: TObject);
  161. begin
  162. AccelB := AccelBTrackBar.Position;
  163. AccelBSpinEdit.Value := AccelB;
  164. Refresh;
  165. end;
  166. procedure TExpCurveForm.AccelASpinEditChange(Sender: TObject);
  167. begin
  168. AccelA := AccelASpinEdit.Value;
  169. AccelATrackBar.Position := AccelA;
  170. Refresh;
  171. end;
  172. function TExpCurveForm.DrawGraphImage: TBGRABitmap;
  173. var
  174. BarWidth, ImgWidth, ImgHeight, CurrentExp, CurrentY: Integer;
  175. Img: TBGRABitmap;
  176. I, CurrentX: Integer;
  177. begin
  178. BarWidth := Max(1, PreviewPaintBox.Width div 98);
  179. ImgWidth := BarWidth * 98;
  180. ImgHeight := PreviewPaintBox.Height;
  181. Img := TBGRABitmap.Create(ImgWidth, ImgHeight, clWhite);
  182. Img.CanvasBGRA.Brush.Color:= ColorToBGRA(clSilver);
  183. for I := 1 to 99 do begin
  184. CurrentExp := ExpForLevel(I);
  185. CurrentY := ImgHeight;
  186. if CurrentExp <> 0 then
  187. CurrentY := ImgHeight - (CurrentExp * ImgHeight div 7738286);
  188. CurrentX := (I - 1) * BarWidth;
  189. Img.CanvasBGRA.FillRect(CurrentX - 1, ImgHeight, CurrentX + BarWidth, CurrentY);
  190. end;
  191. DrawGraphImage := Img;
  192. end;
  193. function TExpCurveForm.ExpForLevel(Level: Integer): Integer;
  194. begin
  195. (* This formula is adapted from RPG Maker MV's corescript, from
  196. Game_Actor.prototype.expForLevel. Used under the MIT license. *)
  197. ExpForLevel := Round(
  198. BaseValue
  199. * (Power(Level - 1, 0.9 + AccelA / 250))
  200. * Level
  201. * (Level+1)
  202. / (6 + Power(Level,2) / 50 / AccelB)
  203. + (Level - 1) * ExtraValue
  204. );
  205. end;
  206. function TExpCurveForm.ExpFromPrevLevel(Level: Integer): Integer;
  207. begin
  208. ExpFromPrevLevel := ExpForLevel(Level) - ExpForLevel(Level - 1);
  209. end;
  210. function TExpCurveForm.ShowExpCurveSetup(ABaseValue, AExtraValue, AAccelA,
  211. AAccelB: Integer): Boolean;
  212. begin
  213. ResultWasAccepted := False;
  214. BaseValue := ABaseValue;
  215. ExtraValue := AExtraValue;
  216. AccelA := AAccelA;
  217. AccelB := AAccelB;
  218. BaseValueSpinEdit.Value := BaseValue;
  219. BaseValueTrackBar.Position := BaseValue;
  220. ExtraValueSpinEdit.Value := ExtraValue;
  221. ExtraValueTrackBar.Position := ExtraValue;
  222. AccelASpinEdit.Value := AccelA;
  223. AccelATrackBar.Position := AccelA;
  224. AccelBSpinEdit.Value := AccelB;
  225. AccelBTrackBar.Position := AccelB;
  226. ShowModal;
  227. ShowExpCurveSetup := ResultWasAccepted
  228. end;
  229. end.