source: trunk/Start.pas

Last change on this file was 667, checked in by chronos, 2 days ago
  • Fixed: Repaint start window after language change in settings window.
File size: 68.4 KB
Line 
1{$INCLUDE Switches.inc}
2unit Start;
3
4interface
5
6uses
7 GameServer, Messg, ButtonBase, ButtonA, ButtonC, ButtonB, Area, Types,
8 LCLIntf, LCLType, SysUtils, Classes, BaseWin, ListBoxEx, LazFileUtils,
9 Registry, DrawDlg, Generics.Collections, Protocol, MiniMap, Brain, Translator,
10 {$IFDEF DPI}System.UITypes, Dpi.Graphics, Dpi.Controls, Dpi.Forms, Dpi.StdCtrls,
11 Dpi.Menus, Dpi.Common{$ELSE}
12 Graphics, Controls, Forms, StdCtrls, Menus{$ENDIF};
13
14type
15 { TPlayerSlot }
16
17 TPlayerSlot = class
18 DiffUpBtn: TButtonC;
19 DiffDownBtn: TButtonC;
20 MultiBtn: TButtonC;
21 OfferMultiple: Boolean;
22 Rect: TRect;
23 end;
24
25 TPlayerSlots = class(TObjectList<TPlayerSlot>)
26 end;
27
28 TStartPage = (
29 pgStartRandom,
30 pgStartMap,
31 pgNoLoad,
32 pgLoad,
33 pgEditRandom,
34 pgEditMap,
35 pgMain
36 );
37
38 TStartTab = (tbMain, tbMap, tbNew, tbPrevious);
39 TMainAction = (maConfig, maManual, maCredits, maAIDev, maWeb, maNone);
40 TMainActionSet = set of TMainAction;
41
42 { TStartDlg }
43
44 TStartDlg = class(TBufferedDrawDlg)
45 PopupMenu1: TPopupMenu;
46 StartBtn: TButtonA;
47 Down1Btn: TButtonC;
48 Up1Btn: TButtonC;
49 List: TListBoxEx;
50 RenameBtn: TButtonB;
51 DeleteBtn: TButtonB;
52 Down2Btn: TButtonC;
53 Up2Btn: TButtonC;
54 QuitBtn: TButtonB;
55 CustomizeBtn: TButtonC;
56 AutoDiffUpBtn: TButtonC;
57 AutoDiffDownBtn: TButtonC;
58 AutoEnemyUpBtn: TButtonC;
59 AutoEnemyDownBtn: TButtonC;
60 ReplayBtn: TButtonB;
61 procedure ListKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
62 procedure ListKeyPress(Sender: TObject; var Key: Char);
63 procedure StartBtnClick(Sender: TObject);
64 procedure FormShow(Sender: TObject);
65 procedure FormHide(Sender: TObject);
66 procedure FormClose(Sender: TObject; var Action: TCloseAction);
67 procedure FormCreate(Sender: TObject);
68 procedure FormDestroy(Sender: TObject);
69 procedure BrainClick(Sender: TObject);
70 procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
71 procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
72 Shift: TShiftState; X, Y: Integer);
73 procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
74 Shift: TShiftState; X, Y: Integer);
75 procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
76 procedure Up1BtnClick(Sender: TObject);
77 procedure Down1BtnClick(Sender: TObject);
78 procedure ListClick(Sender: TObject);
79 procedure RenameBtnClick(Sender: TObject);
80 procedure DeleteBtnClick(Sender: TObject);
81 procedure DiffBtnClick(Sender: TObject);
82 procedure MultiBtnClick(Sender: TObject);
83 procedure Up2BtnClick(Sender: TObject);
84 procedure Down2BtnClick(Sender: TObject);
85 procedure QuitBtnClick(Sender: TObject);
86 procedure CustomizeBtnClick(Sender: TObject);
87 procedure AutoDiffUpBtnClick(Sender: TObject);
88 procedure AutoDiffDownBtnClick(Sender: TObject);
89 procedure AutoEnemyUpBtnClick(Sender: TObject);
90 procedure AutoEnemyDownBtnClick(Sender: TObject);
91 procedure ReplayBtnClick(Sender: TObject);
92 private
93 WorldSize: Integer;
94 StartLandMass: Integer;
95 MaxTurn: Integer;
96 AutoEnemies: Integer;
97 AutoDiff: Integer;
98 MultiControl: Integer;
99 Page: TStartPage;
100 ShowTab: TStartTab;
101 Tab: TStartTab;
102 Diff0: Integer;
103 BrainDefault: TBrain;
104 nMapLandTiles: Integer;
105 nMapStartPositions: Integer;
106 LoadTurn: Integer;
107 LastTurn: Integer;
108 { last turn of selected former game }
109 SlotAvailable: Integer;
110 PlayerPopupIndex: Integer; { brain concerned by brain context menu }
111 ListIndex: array [TStartTab] of Integer;
112 MapFileName: string;
113 FormerGames: TStringList;
114 Maps: TStringList;
115 // BookDate: string;
116 PlayerSlots: TPlayerSlots;
117 ActionsOffered: TMainActionSet;
118 SelectedAction: TMainAction;
119 TurnValid: Boolean;
120 Tracking: Boolean;
121 DefaultAI: string;
122 MiniMap: TMiniMap;
123 LastGame: string;
124 LastMap: string;
125 procedure UpdateMusic;
126 procedure DrawAction(Y, IconIndex: Integer; HeaderItem, TextItem: string);
127 procedure InitPopup(PlayerIndex: Integer);
128 procedure OfferBrain(Brain: TBrain; FixedLines: Integer);
129 procedure PaintInfo;
130 procedure ChangePage(NewPage: TStartPage);
131 procedure ChangeTab(NewTab: TStartTab);
132 procedure UnlistBackupFile(FileName: string);
133 procedure SmartInvalidate(x0, y0, x1, y1: Integer;
134 InvalidateTab0: Boolean = False); overload;
135 procedure LoadConfig;
136 procedure SaveConfig;
137 procedure LoadLanguages;
138 procedure LoadAiBrainsPictures;
139 procedure UpdateInterface;
140 procedure ShowSettings;
141 protected
142 procedure OffscreenPaint; override;
143 public
144 EmptyPicture: TBitmap;
145 Translator: TTranslator;
146 procedure UpdateFormerGames;
147 procedure UpdateMaps(SelectLastMap: Boolean);
148 end;
149
150var
151 StartDlg: TStartDlg;
152
153
154implementation
155
156uses
157 Global, Directories, Direct, ScreenTools, Inp, Back, Settings, KeyBindings,
158 Languages, Music;
159
160{$R *.lfm}
161
162const
163 // predefined world size
164 // attention: lx * ly + 1 must be prime!
165 { MaxWorldSize = 8;
166 lxpre: array[0..nWorldSize - 1] of Integer = (30, 40, 50, 60, 70, 90, 110, 130);
167 lypre: array[0..nWorldSize - 1] of Integer = (46, 52, 60, 70, 84, 94, 110, 130);
168 DefaultWorldTiles = 4200; }
169 MaxWorldSize = 6;
170 WorldSizes: array [0 .. MaxWorldSize - 1] of TPoint = ((X: 30; Y: 46),
171 (X: 40; Y: 52), (X: 50; Y: 60), (X: 60; Y: 70), (X: 75; Y: 82),
172 (X: 100; Y: 96));
173 DefaultWorldTiles = 4150;
174 DefaultWorldSize = 3;
175 DefaultLandMass = 30;
176
177 nPlOffered = 9;
178 yMain = 14;
179 xActionIcon = 55;
180 xAction = 111;
181 yAction = 60;
182 ActionPitch = 56;
183 ActionSideBorder = 24;
184 ActionBottomBorder = 10;
185 x0Mini = 437;
186 y0Mini = 178;
187 xTurnSlider = 346;
188 yTurnSlider = 262;
189 wTurnSlider = 168;
190 yLogo = 74;
191 xDefault = 234;
192 yDefault = 148;
193 x0Brain = 146;
194 y0Brain = 148;
195 dxBrain = 104;
196 dyBrain = 80;
197 xBrain: array [0 .. nPlOffered - 1] of Integer = (x0Brain, x0Brain,
198 x0Brain + dxBrain, x0Brain + dxBrain, x0Brain + dxBrain, x0Brain,
199 x0Brain - dxBrain, x0Brain - dxBrain, x0Brain - dxBrain);
200 yBrain: array [0 .. nPlOffered - 1] of Integer = (y0Brain, y0Brain - dyBrain,
201 y0Brain - dyBrain, y0Brain, y0Brain + dyBrain, y0Brain + dyBrain,
202 y0Brain + dyBrain, y0Brain, y0Brain - dyBrain);
203 TabOffset = -115;
204 TabSize = 159;
205 TabHeight = 40;
206
207 InitAlive: array [1 .. nPl] of Integer = (1, 1 + 2, 1 + 2 + 32,
208 1 + 2 + 8 + 128, 1 + 2 + 8 + 32 + 128, 1 + 2 + 8 + 16 + 64 + 128,
209 1 + 2 + 4 + 16 + 32 + 64 + 256, 511 - 32, 511, 511 - 32, 511, 511 - 32, 511,
210 511 - 32, 511);
211 InitMulti: array [nPlOffered + 1 .. nPl] of Integer = (256, 256, 256 + 128,
212 256 + 128, 256 + 128 + 64, 256 + 128 + 64);
213
214 PlayerAutoDiff: array [1 .. 5] of Integer = (1, 1, 2, 2, 3);
215 EnemyAutoDiff: array [1 .. 5] of Integer = (4, 3, 2, 1, 1);
216
217{ TStartDlg }
218
219procedure TStartDlg.FormCreate(Sender: TObject);
220var
221 X, I: Integer;
222 PlayerSlot: TPlayerSlot;
223 AIBrains: TBrains;
224begin
225 TitleHeight := 0;
226 PlayerSlots := TPlayerSlots.Create;
227 PlayerSlots.Count := nPlOffered;
228 for I := 0 to PlayerSlots.Count - 1 do begin
229 PlayerSlot := TPlayerSlot.Create;
230 PlayerSlot.Rect := Bounds(xBrain[I], YBrain[I], 0, 0);
231 PlayerSlots[I] := PlayerSlot;
232 end;
233 LoadConfig;
234 LoadAssets;
235 LoadLanguages;
236
237 ActionsOffered := [maConfig, maManual, maCredits, maWeb];
238 if FileExists(GetAppSharePath(AITemplateFileName)) then
239 Include(ActionsOffered, maAIDev);
240
241 BrainDefault := nil;
242 for I := Brains.IndexOf(BrainRandom) to Brains.Count - 1 do
243 if AnsiCompareFileName(DefaultAI, Brains[I].FileName) = 0 then
244 BrainDefault := Brains[I];
245 if (BrainDefault = BrainRandom) and (Brains.GetKindCount(btAI) < 2) then
246 BrainDefault := nil;
247 if (not Assigned(BrainDefault)) and (Brains.GetKindCount(btAI) > 0) then
248 begin
249 AIBrains := TBrains.Create(False);
250 Brains.GetByKind(btAI, AIBrains);
251 BrainDefault := Brains[0];
252 FreeAndNil(AIBrains);
253 end; // default AI not found, use any
254
255 DirectDlg.CenterToScreen;
256
257 UpdateInterface;
258
259 Canvas.Font.Assign(UniFont[ftNormal]);
260 Canvas.Brush.Style := TBrushStyle.bsClear;
261
262 QuitBtn.Hint := Phrases.Lookup('STARTCONTROLS', 0);
263 ReplayBtn.Hint := Phrases.Lookup('BTN_REPLAY');
264 PlayerSlots.Count := nPlOffered;
265 for I := 0 to PlayerSlots.Count - 1 do
266 with PlayerSlots[I] do begin
267 DiffUpBtn := TButtonC.Create(Self);
268 DiffUpBtn.Graphic := HGrSystem.Data;
269 DiffUpBtn.Left := xBrain[I] - 18;
270 DiffUpBtn.Top := yBrain[I] + 39;
271 DiffUpBtn.ButtonIndex := 1;
272 DiffUpBtn.Parent := Self;
273 DiffUpBtn.OnClick := DiffBtnClick;
274 DiffDownBtn := TButtonC.Create(Self);
275 DiffDownBtn.Graphic := HGrSystem.Data;
276 DiffDownBtn.Left := xBrain[I] - 18;
277 DiffDownBtn.Top := yBrain[I] + 51;
278 DiffDownBtn.ButtonIndex := 0;
279 DiffDownBtn.Parent := Self;
280 DiffDownBtn.OnClick := DiffBtnClick;
281 end;
282 for I := 6 to 8 do
283 with PlayerSlots[I] do begin
284 MultiBtn := TButtonC.Create(Self);
285 MultiBtn.Graphic := HGrSystem.Data;
286 MultiBtn.Left := xBrain[I] - 18;
287 MultiBtn.Top := yBrain[I];
288 MultiBtn.Parent := Self;
289 MultiBtn.OnClick := MultiBtnClick;
290 OfferMultiple := True;
291 end;
292
293 X := BiColorTextWidth(Canvas, Phrases.Lookup('STARTCONTROLS', 7)) div 2;
294 CustomizeBtn.Left := x0Brain + 32 - 16 - X;
295 if AutoDiff < 0 then
296 CustomizeBtn.ButtonIndex := 3
297 else
298 CustomizeBtn.ButtonIndex := 2;
299
300 BitBltBitmap(BrainNoTerm.Picture, 0, 0, 64, 64, HGrSystem2.Data, GBrainNoTerm.Left, GBrainNoTerm.Top);
301 BitBltBitmap(BrainSuperVirtual.Picture, 0, 0, 64, 64, HGrSystem2.Data, GBrainSuperVirtual.Left, GBrainSuperVirtual.Top);
302 BitBltBitmap(BrainTerm.Picture, 0, 0, 64, 64, HGrSystem2.Data, GBrainTerm.Left, GBrainTerm.Top);
303 BitBltBitmap(BrainRandom.Picture, 0, 0, 64, 64, HGrSystem2.Data, GBrainRandom.Left, GBrainRandom.Top);
304
305 LoadAiBrainsPictures;
306
307 EmptyPicture := TBitmap.Create;
308 EmptyPicture.PixelFormat := TPixelFormat.pf24bit;
309 EmptyPicture.SetSize(64, 64);
310 EmptyPicture.Canvas.FillRect(0, 0, EmptyPicture.Width, EmptyPicture.Height);
311
312 MiniMap := TMiniMap.Create;
313 InitButtons;
314
315 PlayersBrain[0] := BrainTerm;
316 SlotAvailable := -1;
317 Tab := tbNew;
318 Diff0 := 2;
319 TurnValid := False;
320 Tracking := False;
321 FormerGames := TStringList.Create;
322 UpdateFormerGames;
323 MapFileName := '';
324 Maps := TStringList.Create;
325 UpdateMaps(True);
326end;
327
328procedure TStartDlg.FormDestroy(Sender: TObject);
329begin
330 SaveConfig;
331 FreeAndNil(Translator);
332 FreeAndNil(FormerGames);
333 FreeAndNil(Maps);
334 FreeAndNil(EmptyPicture);
335 FreeAndNil(PlayerSlots);
336 FreeAndNil(MiniMap);
337end;
338
339procedure TStartDlg.SmartInvalidate(x0, y0, x1, y1: Integer;
340 InvalidateTab0: Boolean);
341var
342 I: Integer;
343 R0, R1: HRgn;
344begin
345 OffscreenUser := nil;
346 R0 := CreateRectRgn(x0, y0, x1, y1);
347 for I := 0 to ControlCount - 1 do
348 if not (Controls[I] is TArea) and Controls[I].Visible then
349 begin
350 with Controls[I].BoundsRect do
351 R1 := CreateRectRgn(Left, Top, Right, Bottom);
352 CombineRgn(R0, R0, R1, RGN_DIFF);
353 DeleteObject(R1);
354 end;
355 if not InvalidateTab0 then begin
356 R1 := CreateRectRgn(0, 0, 6 + 36, 3 + 38); // tab 0 icon
357 CombineRgn(R0, R0, R1, RGN_DIFF);
358 DeleteObject(R1);
359 end;
360 InvalidateRgn(Handle, R0, False);
361 DeleteObject(R0);
362end;
363
364procedure TStartDlg.LoadConfig;
365var
366 Reg: TRegistry;
367 I: Integer;
368 S: string;
369 {$IFDEF WINDOWS}
370 ResolutionX, ResolutionY, ResolutionBPP, ResolutionFreq: Integer;
371 {$ENDIF}
372 ScreenMode: Integer;
373begin
374 Reg := TRegistry.Create;
375 with Reg do try
376 // Initialize AI assignment
377 OpenKey(AppRegistryKey + '\AI', True);
378 for I := 0 to nPlOffered - 1 do begin
379 if I = 0 then S := ':StdIntf'
380 else S := 'StdAI';
381 if not ValueExists('Control' + IntToStr(I)) then
382 WriteString('Control' + IntToStr(I), S);
383 if not ValueExists('Diff' + IntToStr(I)) then
384 WriteInteger('Diff' + IntToStr(I), 2);
385 end;
386
387 OpenKey(AppRegistryKey, True);
388 if ValueExists('Locale') then LocaleCode := ReadString('Locale')
389 else LocaleCode := '';
390 if ValueExists('WorldSize') then WorldSize := Reg.ReadInteger('WorldSize')
391 else WorldSize := DefaultWorldSize;
392 if WorldSize > MaxWorldSize then WorldSize := MaxWorldSize;
393 if WorldSize > 0 then WorldSize := 0;
394 if ValueExists('LandMass') then StartLandMass := Reg.ReadInteger('LandMass')
395 else StartLandMass := DefaultLandMass;
396 if ValueExists('MaxTurn') then MaxTurn := Reg.ReadInteger('MaxTurn')
397 else MaxTurn := 800;
398 if ValueExists('DefaultAI') then DefaultAI := Reg.ReadString('DefaultAI')
399 else DefaultAI := 'StdAI';
400 if ValueExists('AutoEnemies') then AutoEnemies := Reg.ReadInteger('AutoEnemies')
401 else AutoEnemies := 8;
402 if ValueExists('AutoDiff') then AutoDiff := Reg.ReadInteger('AutoDiff')
403 else AutoDiff := 1;
404 if ValueExists('StartTab') then ShowTab := TStartTab(Reg.ReadInteger('StartTab'))
405 else ShowTab := tbNew;
406 if ValueExists('LastGame') then LastGame := Reg.ReadString('LastGame')
407 else LastGame := '';
408 if ValueExists('LastMap') then LastMap := Reg.ReadString('LastMap')
409 else LastMap := '';
410 if ValueExists('NetworkEnabled') then NetworkEnabled := Reg.ReadBool('NetworkEnabled')
411 else NetworkEnabled := False;
412
413 if ValueExists('ScreenMode') then
414 ScreenMode := ReadInteger('ScreenMode')
415 else ScreenMode := 1;
416 FullScreen := ScreenMode > 0;
417 if ValueExists('MusicEnabled') then MusicEnabled := ReadBool('MusicEnabled')
418 else MusicEnabled := True;
419 if ValueExists('MusicVolume') then MusicVolume := ReadFloat('MusicVolume')
420 else MusicVolume := 0.5;
421 if ValueExists('TermLeft') then TermBounds.Left := ReadInteger('TermLeft')
422 else TermBounds.Left := 0;
423 if ValueExists('TermTop') then TermBounds.Top := ReadInteger('TermTop')
424 else TermBounds.Top := 0;
425 if ValueExists('TermWidth') then TermBounds.Width := ReadInteger('TermWidth')
426 else TermBounds.Width := 800;
427 if ValueExists('TermHeight') then TermBounds.Height := ReadInteger('TermHeight')
428 else TermBounds.Height := 480;
429
430 if ValueExists('MultiControl') then
431 MultiControl := ReadInteger('MultiControl')
432 else MultiControl := 0;
433 {$IFDEF WINDOWS}
434 if ValueExists('ResolutionX') then
435 ResolutionX := ReadInteger('ResolutionX');
436 if ValueExists('ResolutionY') then
437 ResolutionY := ReadInteger('ResolutionY');
438 if ValueExists('ResolutionBPP') then
439 ResolutionBPP := ReadInteger('ResolutionBPP');
440 if ValueExists('ResolutionFreq') then
441 ResolutionFreq := ReadInteger('ResolutionFreq');
442 if ScreenMode = 2 then
443 ChangeResolution(ResolutionX, ResolutionY, ResolutionBPP,
444 ResolutionFreq);
445 {$ENDIF}
446 finally
447 Free;
448 end;
449
450 KeyBindings.KeyBindings.LoadFromRegistry(HKEY_CURRENT_USER, AppRegistryKey + '\KeyBindings');
451end;
452
453procedure TStartDlg.SaveConfig;
454var
455 Reg: TRegistry;
456begin
457 ScreenTools.SaveConfig(AppRegistryKey);
458
459 Reg := TRegistry.Create;
460 with Reg do try
461 OpenKey(AppRegistryKey, True);
462 WriteInteger('WorldSize', WorldSize);
463 WriteInteger('LandMass', StartLandMass);
464 WriteString('Locale', LocaleCode);
465 if FullScreen then WriteInteger('ScreenMode', 1)
466 else WriteInteger('ScreenMode', 0);
467 WriteBool('MusicEnabled', MusicEnabled);
468 WriteFloat('MusicVolume', MusicVolume);
469 WriteInteger('TermWidth', TermBounds.Width);
470 WriteInteger('TermHeight', TermBounds.Height);
471 WriteInteger('TermLeft', TermBounds.Left);
472 WriteInteger('TermTop', TermBounds.Top);
473 WriteInteger('MultiControl', MultiControl);
474 WriteInteger('StartTab', Integer(ShowTab));
475 WriteString('LastGame', LastGame);
476 WriteString('LastMap', LastMap);
477 WriteBool('NetworkEnabled', NetworkEnabled);
478 finally
479 Free;
480 end;
481
482 KeyBindings.KeyBindings.SaveToRegistry(HKEY_CURRENT_USER, AppRegistryKey + '\KeyBindings');
483end;
484
485procedure TStartDlg.LoadLanguages;
486var
487 I: Integer;
488begin
489 Translator := TTranslator.Create(nil);
490 with Translator, Languages do begin
491 SearchByCode('').Available := True;
492
493 for I := 1 to Languages.Count - 1 do
494 with Languages[I] do begin
495 Available := DirectoryExists(GetAppSharePath('Localization' + DirectorySeparator + Code)) or (Code = 'en');
496 end;
497 end;
498end;
499
500procedure TStartDlg.LoadAiBrainsPictures;
501var
502 AiBrains: TBrains;
503begin
504 AiBrains := TBrains.Create(False);
505 try
506 Brains.GetByKind(btAI, AiBrains);
507 AiBrains.LoadPictures;
508 finally
509 FreeAndNil(AiBrains);
510 end;
511end;
512
513procedure TStartDlg.UpdateInterface;
514var
515 r0, r1: HRgn;
516 Location: TPoint;
517begin
518 if FullScreen then begin
519 Location := Point(Screen.PrimaryMonitor.Left + (Screen.PrimaryMonitor.Width - 800) * 3 div 8,
520 Screen.PrimaryMonitor.Top + Screen.PrimaryMonitor.Height - Height - (Screen.PrimaryMonitor.Height - 600) div 3);
521 BoundsRect := Bounds(Location.X, Location.Y, Width, Height);
522
523 r0 := CreateRectRgn(0, 0, Width, Height);
524 r1 := CreateRectRgn(TabOffset + 4 * TabSize + 2, 0, Width, TabHeight);
525 CombineRgn(r0, r0, r1, RGN_DIFF);
526 DeleteObject(r1);
527 r1 := CreateRectRgn(QuitBtn.Left, QuitBtn.Top, QuitBtn.Left + QuitBtn.Width,
528 QuitBtn.Top + QuitBtn.Height);
529 CombineRgn(r0, r0, r1, RGN_OR);
530 DeleteObject(r1);
531 SetWindowRgn(Handle, r0, False);
532 DeleteObject(r0); // causes crash with Windows 95
533 end else begin
534 CenterToScreen;
535 end;
536end;
537
538procedure TStartDlg.ShowSettings;
539begin
540 SettingsDlg := TSettingsDlg.Create(nil);
541 if SettingsDlg.ShowModal = mrOk then begin
542 LoadAssets;
543 SmartInvalidate(0, 0, ClientWidth, ClientHeight, Page = pgMain);
544 UpdateInterface;
545 Background.UpdateInterface;
546 UpdateMusic;
547 end;
548 FreeAndNil(SettingsDlg);
549end;
550
551procedure TStartDlg.DrawAction(Y, IconIndex: Integer; HeaderItem, TextItem: string);
552begin
553 with Offscreen do begin
554 Canvas.Font.Assign(UniFont[ftCaption]);
555 Canvas.Font.Style := Canvas.Font.Style + [TFontStyle.fsUnderline];
556 RisedTextOut(Canvas, xAction, Y - 3, Phrases2.Lookup(HeaderItem));
557 Canvas.Font.Assign(UniFont[ftNormal]);
558 BiColorTextOut(Canvas, Colors.Canvas.Pixels[clkAge0 - 1, cliDimmedText],
559 $000000, xAction, Y + 21, Phrases2.Lookup(TextItem));
560
561 UnshareBitmap(DrawBuffer);
562 DrawBufferEnsureSize(50, 50);
563 BitBltCanvas(DrawBuffer.Canvas, 0, 0, 50, 50, Canvas,
564 xActionIcon - 2, Y - 2);
565 GlowFrame(DrawBuffer, 8, 8, 34, 34, $202020);
566 BitBltCanvas(Canvas, xActionIcon - 2, Y - 2, 50, 50,
567 DrawBuffer.Canvas, 0, 0);
568 BitBltCanvas(Canvas, xActionIcon, Y, 40, 40, BigImp.Canvas,
569 (IconIndex mod 7) * xSizeBig + 8, (IconIndex div 7) * ySizeBig);
570 RFrame(Canvas, xActionIcon - 1, Y - 1, xActionIcon + 40, Y + 40,
571 $000000, $000000);
572 end;
573end;
574
575procedure TStartDlg.OffscreenPaint;
576const
577 TabNames: array[TStartTab] of Integer = (0, 11, 3, 4);
578var
579 I, W, H, xMini, yMini, Y: Integer;
580 S: string;
581 Tab2: TStartTab;
582 MainAction: TMainAction;
583begin
584 inherited;
585
586 with Offscreen do begin
587 PaintBackground(Canvas, 3, 3, TabOffset + 4 * TabSize - 4, TabHeight - 3,
588 ClientWidth, ClientHeight);
589 PaintBackground(Canvas, 3, TabHeight + 3, ClientWidth - 6,
590 ClientHeight - TabHeight - 6, ClientWidth, ClientHeight);
591 with Canvas do
592 begin
593 Brush.Color := $000000;
594 FillRect(Rect(0, 1, ClientWidth, 3));
595 FillRect(Rect(TabOffset + 4 * TabSize + 2, 0, ClientWidth, TabHeight));
596 Brush.Style := TBrushStyle.bsClear;
597 end;
598 if Page in [pgStartRandom, pgStartMap] then
599 begin
600 Frame(Canvas, 328, yMain + 112 - 15, ClientWidth + 10, Up2Btn.Top + 38,
601 MainTexture.ColorBevelShade, MainTexture.ColorBevelLight);
602 if AutoDiff > 0 then
603 begin
604 Frame(Canvas, -1 { x0Brain - dxBrain } ,
605 yMain + 112 - 15 { Up1Btn.Top - 12 }{ y0Brain - dyBrain } ,
606 x0Brain + dxBrain + 64, Up2Btn.Top + 38 { y0Brain + dyBrain + 64 } ,
607 MainTexture.ColorBevelShade, MainTexture.ColorBevelLight);
608 end;
609 end
610 else if Page <> pgMain then begin
611 Frame(Canvas, 328, Up1Btn.Top - 15, ClientWidth + 10, Up2Btn.Top + 38,
612 MainTexture.ColorBevelShade, MainTexture.ColorBevelLight);
613 end;
614 Frame(Canvas, 0, 0, ClientWidth - 1, ClientHeight - 1, 0, 0);
615
616 // draw tabs
617 Frame(Canvas, 2, 2 + 2 * Integer(Tab <> tbMain), TabOffset + (0 + 1) * TabSize - 1,
618 TabHeight, MainTexture.ColorBevelLight, MainTexture.ColorBevelShade);
619 Frame(Canvas, 1, 1 + 2 * Integer(Tab <> tbMain), TabOffset + (0 + 1) * TabSize,
620 TabHeight, MainTexture.ColorBevelLight, MainTexture.ColorBevelShade);
621 Canvas.Pixels[1, 1 + 2 * Integer(Tab <> tbMain)] := MainTexture.ColorBevelShade;
622 for Tab2 := tbMap to tbPrevious do
623 begin
624 Frame(Canvas, TabOffset + Integer(Tab2) * TabSize + 2, 2 + 2 * Integer(Tab <> Tab2),
625 TabOffset + (Integer(Tab2) + 1) * TabSize - 1, TabHeight, MainTexture.ColorBevelLight,
626 MainTexture.ColorBevelShade);
627 Frame(Canvas, TabOffset + Integer(Tab2) * TabSize + 1, 1 + 2 * Integer(Tab <> Tab2),
628 TabOffset + (Integer(Tab2) + 1) * TabSize, TabHeight, MainTexture.ColorBevelLight,
629 MainTexture.ColorBevelShade);
630 Canvas.Pixels[TabOffset + Integer(Tab2) * TabSize + 1, 1 + 2 * Integer(Tab <> Tab2)] :=
631 MainTexture.ColorBevelShade;
632 end;
633 Canvas.Font.Assign(UniFont[ftNormal]);
634 for Tab2 := tbMap to tbPrevious do
635 begin
636 S := Phrases.Lookup('STARTCONTROLS', TabNames[Tab2]);
637 RisedTextOut(Canvas, TabOffset + Integer(Tab2) * TabSize + 1 +
638 (TabSize - BiColorTextWidth(Canvas, S)) div 2,
639 10 + 2 * Integer(Tab <> Tab2), S);
640 end;
641 Frame(Canvas, TabOffset + 4 * TabSize + 1, -1, ClientWidth, TabHeight,
642 $000000, $000000);
643 Frame(Canvas, 1, TabHeight + 1, ClientWidth - 2, ClientHeight - 2,
644 MainTexture.ColorBevelLight, MainTexture.ColorBevelShade);
645 Frame(Canvas, 2, TabHeight + 2, ClientWidth - 3, ClientHeight - 3,
646 MainTexture.ColorBevelLight, MainTexture.ColorBevelShade);
647 if Tab = tbMain then
648 begin
649 PaintBackground(Canvas, 3, TabHeight - 1, TabSize - 4 - 3 + TabOffset + 3, 4,
650 ClientWidth, ClientHeight);
651 Canvas.Pixels[2, TabHeight] := MainTexture.ColorBevelLight;
652 end
653 else
654 begin
655 PaintBackground(Canvas, TabOffset + 3 + Integer(Tab) * TabSize, TabHeight - 1,
656 TabSize - 4, 4, ClientWidth, ClientHeight);
657 Canvas.Pixels[TabOffset + Integer(Tab) * TabSize + 2, TabHeight] :=
658 MainTexture.ColorBevelLight;
659 end;
660 Canvas.Pixels[TabOffset + (Integer(Tab) + 1) * TabSize - 1, TabHeight + 1] :=
661 MainTexture.ColorBevelShade;
662 if Tab < tbPrevious then
663 Frame(Canvas, TabOffset + (Integer(Tab) + 1) * TabSize + 1, 3,
664 TabOffset + (Integer(Tab) + 1) * TabSize + 2, TabHeight, MainTexture.ColorBevelShade,
665 MainTexture.ColorBevelShade); // Tab shadow
666
667 // Paint menu logo
668 UnshareBitmap(DrawBuffer);
669 DrawBufferEnsureSize(MenuLogo.Width, MenuLogo.Height);
670 BitBltCanvas(DrawBuffer.Canvas, 0, 0, MenuLogo.Width, MenuLogo.Height, Canvas, 6,
671 3 + 2 * Integer(Tab <> tbMain));
672
673 ImageOp_BCC(DrawBuffer, Templates.Data, 0, 0, MenuLogo.Left, MenuLogo.Top,
674 MenuLogo.Width, MenuLogo.Height - 9, $BFBF20, $4040DF); // logo part 1
675 ImageOp_BCC(DrawBuffer, Templates.Data, 10, 27, MenuLogo.Left + 10,
676 MenuLogo.Top + 27, MenuLogo.Width - 10, 9, $BFBF20, $4040DF); // logo part 2
677 BitBltCanvas(Canvas, 6, 3 + 2 * Integer(Tab <> tbMain), MenuLogo.Width, MenuLogo.Height,
678 DrawBuffer.Canvas, 0, 0);
679
680 if Page = pgMain then begin
681 if SelectedAction <> maNone then begin
682 // Mark selected action
683 W := ClientWidth - 2 * ActionSideBorder;
684 H := ActionPitch;
685 if yAction + Integer(SelectedAction) * ActionPitch - 8 + H > ClientHeight - ActionBottomBorder
686 then
687 H := ClientHeight - ActionBottomBorder -
688 (yAction + Integer(SelectedAction) * ActionPitch - 8);
689
690 UnshareBitmap(DrawBuffer);
691 DrawBufferEnsureSize(W, H);
692 BitBltCanvas(DrawBuffer.Canvas, 0, 0, W, H, Canvas,
693 ActionSideBorder, yAction + Integer(SelectedAction) * ActionPitch - 8);
694 MakeBlue(DrawBuffer, 0, 0, W, H);
695 BitBltCanvas(Canvas, ActionSideBorder, yAction + Integer(SelectedAction) *
696 ActionPitch - 8, W, H, DrawBuffer.Canvas, 0, 0);
697 end;
698 Y := yAction;
699 for MainAction := Low(TMainActionSet) to High(TMainActionSet) do
700 begin
701 if MainAction in ActionsOffered then
702 case MainAction of
703 maConfig: DrawAction(Y, 25, 'ACTIONHEADER_CONFIG', 'ACTION_CONFIG');
704 maManual: DrawAction(Y, 19, 'ACTIONHEADER_MANUAL', 'ACTION_MANUAL');
705 maCredits: DrawAction(Y, 22, 'ACTIONHEADER_CREDITS', 'ACTION_CREDITS');
706 maAIDev: DrawAction(Y, 24, 'ACTIONHEADER_AIDEV', 'ACTION_AIDEV');
707 maWeb:
708 begin
709 Canvas.Font.Assign(UniFont[ftCaption]);
710 // Canvas.Font.Style := Canvas.Font.Style + [fsUnderline];
711 RisedTextOut(Canvas, xActionIcon + 99, Y,
712 Format(Phrases2.Lookup('ACTIONHEADER_WEB'), [CevoHomepageShort]));
713 Canvas.Font.Assign(UniFont[ftNormal]);
714
715 UnshareBitmap(DrawBuffer);
716 DrawBufferEnsureSize(LinkArrows.Width, LinkArrows.Height);
717 BitBltCanvas(DrawBuffer.Canvas, 0, 0, LinkArrows.Width, LinkArrows.Height, Canvas,
718 xActionIcon, Y + 2);
719 ImageOp_BCC(DrawBuffer, Templates.Data, Point(0, 0), LinkArrows.BoundsRect, 0,
720 Colors.Canvas.Pixels[clkAge0 - 1, cliDimmedText]);
721 BitBltCanvas(Canvas, xActionIcon, Y + 2, LinkArrows.Width, LinkArrows.Height,
722 DrawBuffer.Canvas, 0, 0);
723 end;
724 end;
725 Inc(Y, ActionPitch);
726 end;
727 end
728 else if Page in [pgStartRandom, pgStartMap] then
729 begin
730 UnderlinedTitleValue(Canvas, Phrases.Lookup('STARTCONTROLS', 10),
731 TurnToString(MaxTurn), 344, y0Mini + 61, 170);
732
733 S := Phrases.Lookup('STARTCONTROLS', 7);
734 W := Canvas.TextWidth(S);
735 LoweredTextOut(Canvas, -2, MainTexture, x0Brain + 32 - W div 2,
736 y0Brain + dyBrain + 69, S);
737
738 InitOrnament;
739 if AutoDiff < 0 then
740 begin
741 for I := 12 to 19 do
742 if (I < 13) or (I > 17) then begin
743 Sprite(Canvas, 9 + I * 27, yLogo - 2, Ornament);
744 end;
745 PaintLogo(Canvas, 69 + 11 * 27, yLogo, MainTexture.ColorBevelLight,
746 MainTexture.ColorBevelShade);
747
748 for I := 0 to nPlOffered - 1 do
749 if 1 shl I and SlotAvailable <> 0 then
750 begin
751 if Assigned(PlayersBrain[I]) then
752 FrameImage(Canvas, PlayersBrain[I].Picture, xBrain[I], yBrain[I],
753 64, 64, 0, 0, True)
754 else
755 FrameImage(Canvas, EmptyPicture, xBrain[I], yBrain[I], 64, 64,
756 0, 0, True);
757 if Assigned(PlayersBrain[I]) and (PlayersBrain[I].Kind in [btTerm, btRandom, btAI]) then
758 begin
759 BitBltCanvas(Canvas, xBrain[I] - 18, yBrain[I] + 19, 12, 14,
760 HGrSystem.Data.Canvas, 134 + (Difficulty[I] - 1) *
761 13, 28);
762 Frame(Canvas, xBrain[I] - 19, yBrain[I] + 18, xBrain[I] - 18 + 12,
763 yBrain[I] + (19 + 14), $000000, $000000);
764 RFrame(Canvas, PlayerSlots[I].DiffUpBtn.Left - 1, PlayerSlots[I].DiffUpBtn.Top - 1,
765 PlayerSlots[I].DiffUpBtn.Left + 12, PlayerSlots[I].DiffUpBtn.Top + 24,
766 MainTexture.ColorBevelShade, MainTexture.ColorBevelLight);
767 with Canvas do
768 begin
769 Brush.Color := $000000;
770 FillRect(Rect(xBrain[I] - 5, yBrain[I] + 25, xBrain[I] - 2,
771 yBrain[I] + 27));
772 Brush.Style := TBrushStyle.bsClear;
773 end;
774 if PlayerSlots[I].OfferMultiple then
775 begin
776 RFrame(Canvas, PlayerSlots[I].MultiBtn.Left - 1, PlayerSlots[I].MultiBtn.Top - 1,
777 PlayerSlots[I].MultiBtn.Left + 12, PlayerSlots[I].MultiBtn.Top + 12,
778 MainTexture.ColorBevelShade, MainTexture.ColorBevelLight);
779 BitBltCanvas(Canvas, xBrain[I] - 31, yBrain[I], 13, 12,
780 HGrSystem.Data.Canvas, 88, 47);
781 end;
782 end;
783 if Assigned(PlayersBrain[I]) then
784 begin
785 PlayerSlots[I].DiffUpBtn.Hint := Format(Phrases.Lookup('STARTCONTROLS', 9),
786 [PlayersBrain[I].Name]);
787 PlayerSlots[I].DiffDownBtn.Hint := PlayerSlots[I].DiffUpBtn.Hint;
788 end;
789 end;
790 end
791 else
792 begin
793 DLine(Canvas, 24, 198, yMain + 140 + 19, MainTexture.ColorBevelLight,
794 MainTexture.ColorBevelShade);
795 RisedTextOut(Canvas, 24 { x0Brain+32-BiColorTextWidth(Canvas,s) div 2 } ,
796 yMain + 140 { y0Mini-77 } , Phrases.Lookup('STARTCONTROLS', 15));
797 if Page = pgStartRandom then
798 S := IntToStr(AutoEnemies)
799 else if nMapStartPositions = 0 then
800 S := '0'
801 else
802 S := IntToStr(nMapStartPositions - 1);
803 RisedTextOut(Canvas, 198 - BiColorTextWidth(Canvas, S), yMain + 140, S);
804
805 DLine(Canvas, 24, xDefault - 6, yMain + 164 + 19,
806 MainTexture.ColorBevelLight, MainTexture.ColorBevelShade);
807 RisedTextOut(Canvas, 24 { x0Brain+32-BiColorTextWidth(Canvas,s) div 2 } ,
808 yMain + 164 { y0Mini-77 } , Phrases.Lookup('STARTCONTROLS', 16));
809 if AutoDiff = 1 then
810 FrameImage(Canvas, Brains.GetBeginner.Picture, xDefault, yDefault, 64,
811 64, 0, 0, False)
812 else
813 FrameImage(Canvas, BrainDefault.Picture, xDefault, yDefault, 64, 64,
814 0, 0, True);
815 DLine(Canvas, 56, 272, y0Mini + 61 + 19, MainTexture.ColorBevelLight,
816 MainTexture.ColorBevelShade);
817
818 RisedTextOut(Canvas, 56, y0Mini + 61,
819 Phrases.Lookup('STARTCONTROLS', 14));
820 S := Phrases.Lookup('AUTODIFF', AutoDiff - 1);
821 RisedTextOut(Canvas, 272 - BiColorTextWidth(Canvas, S), y0Mini + 61, S);
822 for I := 0 to 19 do
823 if (I < 2) or (I > 6) then begin
824 Sprite(Canvas, 9 + I * 27, yLogo - 2, Ornament);
825 end;
826 PaintLogo(Canvas, 69, yLogo, MainTexture.ColorBevelLight,
827 MainTexture.ColorBevelShade);
828 end;
829 end
830 else if Page = pgLoad then
831 begin
832 // RisedTextOut(Canvas,x0Mini+2-BiColorTextWidth(Canvas,BookDate) div 2,y0Mini-73,BookDate);
833 if LastTurn > 0 then
834 begin
835 PaintProgressBar(Canvas, 6, xTurnSlider, yTurnSlider, 0,
836 LoadTurn * wTurnSlider div LastTurn, wTurnSlider, MainTexture);
837 Frame(Canvas, xTurnSlider - 2, yTurnSlider - 2, xTurnSlider + wTurnSlider
838 + 1, yTurnSlider + 8, $B0B0B0, $FFFFFF);
839 RFrame(Canvas, xTurnSlider - 3, yTurnSlider - 3, xTurnSlider + wTurnSlider
840 + 2, yTurnSlider + 9, $FFFFFF, $B0B0B0);
841 end
842 else
843 DLine(Canvas, 344, 514, y0Mini + 61 + 19, MainTexture.ColorBevelLight,
844 MainTexture.ColorBevelShade);
845 RisedTextOut(Canvas, 344, y0Mini + 61, Phrases.Lookup('STARTCONTROLS', 8));
846 S := TurnToString(LoadTurn);
847 RisedTextOut(Canvas, 514 - BiColorTextWidth(Canvas, S), y0Mini + 61, S);
848 end
849 else if Page = pgEditRandom then
850 begin
851 UnderlinedTitleValue(Canvas, Phrases.Lookup('STARTCONTROLS', 5),
852 IntToStr((WorldSizes[WorldSize].X * WorldSizes[WorldSize].Y * 20 +
853 DefaultWorldTiles div 2) div DefaultWorldTiles * 5) + '%',
854 344, y0Mini - 77, 170);
855 UnderlinedTitleValue(Canvas, Phrases.Lookup('STARTCONTROLS', 6),
856 IntToStr(StartLandMass) + '%', 344, y0Mini + 61, 170);
857 end
858 else if Page = pgEditMap then
859 begin
860 // DLine(Canvas,344,514,y0Mini+61+19,MainTexture.ColorBevelLight,MainTexture.ColorBevelShade);
861 S := Format(Phrases2.Lookup('MAPPROP'),
862 [(nMapLandTiles * 100 + 556) div 1112,
863 // 1112 is typical for world with 100% size and default land mass
864 nMapStartPositions]);
865 RisedTextOut(Canvas, x0Mini - BiColorTextWidth(Canvas, S) div 2,
866 y0Mini + 61, S);
867 end;
868
869 if StartBtn.Visible then
870 BtnFrame(Canvas, StartBtn.BoundsRect, MainTexture);
871 if Up2Btn.Visible then
872 RFrame(Canvas, Up2Btn.Left - 1, Up2Btn.Top - 1, Up2Btn.Left + 12,
873 Up2Btn.Top + 24, MainTexture.ColorBevelShade, MainTexture.ColorBevelLight);
874 if Up1Btn.Visible then
875 RFrame(Canvas, Up1Btn.Left - 1, Up1Btn.Top - 1, Up1Btn.Left + 12,
876 Up1Btn.Top + 24, MainTexture.ColorBevelShade, MainTexture.ColorBevelLight);
877 if AutoDiffUpBtn.Visible then
878 RFrame(Canvas, AutoDiffUpBtn.Left - 1, AutoDiffUpBtn.Top - 1,
879 AutoDiffUpBtn.Left + 12, AutoDiffUpBtn.Top + 24, MainTexture.ColorBevelShade,
880 MainTexture.ColorBevelLight);
881 if AutoEnemyUpBtn.Visible then
882 RFrame(Canvas, AutoEnemyUpBtn.Left - 1, AutoEnemyUpBtn.Top - 1,
883 AutoEnemyUpBtn.Left + 12, AutoEnemyUpBtn.Top + 24,
884 MainTexture.ColorBevelShade, MainTexture.ColorBevelLight);
885 if CustomizeBtn.Visible then
886 RFrame(Canvas, CustomizeBtn.Left - 1, CustomizeBtn.Top - 1,
887 CustomizeBtn.Left + 12, CustomizeBtn.Top + 12, MainTexture.ColorBevelShade,
888 MainTexture.ColorBevelLight);
889 if List.Visible then
890 EditFrame(Canvas, List.BoundsRect, MainTexture);
891 if RenameBtn.Visible then
892 BtnFrame(Canvas, RenameBtn.BoundsRect, MainTexture);
893 if DeleteBtn.Visible then
894 BtnFrame(Canvas, DeleteBtn.BoundsRect, MainTexture);
895 if Page = pgLoad then
896 BtnFrame(Canvas, ReplayBtn.BoundsRect, MainTexture);
897
898 if not (Page in [pgMain, pgNoLoad]) then
899 begin
900 xMini := x0Mini - MiniMap.Size.X;
901 yMini := y0Mini - MiniMap.Size.Y div 2;
902 Frame(Canvas, xMini, yMini, xMini + 3 + MiniMap.Size.X * 2,
903 yMini + 3 + MiniMap.Size.Y, MainTexture.ColorBevelLight,
904 MainTexture.ColorBevelShade);
905 Frame(Canvas, xMini + 1, yMini + 1, xMini + 2 + MiniMap.Size.X * 2,
906 yMini + 2 + MiniMap.Size.Y, MainTexture.ColorBevelShade,
907 MainTexture.ColorBevelLight);
908
909 S := '';
910 if MiniMap.Mode = mmPicture then begin
911 BitBltCanvas(Canvas, xMini + 2, yMini + 2, MiniMap.Size.X * 2, MiniMap.Size.Y,
912 MiniMap.Bitmap.Canvas, 0, 0);
913 if Page = pgStartRandom then
914 S := Phrases.Lookup('RANMAP')
915 end
916 else if MiniMap.Mode = mmMultiPlayer then
917 S := Phrases.Lookup('MPMAP')
918 else if Page = pgStartMap then
919 S := ExtractFileNameOnly(MapFileName)
920 else if Page = pgEditMap then
921 S := List.Items[List.ItemIndex]
922 else if Page = pgNoLoad then
923 S := Phrases.Lookup('NOGAMES');
924 if S <> '' then
925 RisedTextOut(Canvas, x0Mini + 2 - BiColorTextWidth(Canvas, S) div 2,
926 y0Mini - 8, S);
927 end;
928 end;
929 MarkUsedOffscreen(ClientWidth, ClientHeight);
930end;
931
932procedure TStartDlg.FormShow(Sender: TObject);
933begin
934 {$IFDEF UNIX}
935 ShowInTaskBar := TShowInTaskbar.stAlways;
936 {$ENDIF}
937 MainTexture.Age := -1;
938 List.Font.Color := MainTexture.ColorMark;
939
940 Fill(EmptyPicture.Canvas, Bounds(0, 0, 64, 64),
941 Point((Maintexture.Width - 64) div 2, (Maintexture.Height - 64) div 2));
942
943 DarkenImage(EmptyPicture, 28);
944
945 Difficulty[0] := Diff0;
946
947 SelectedAction := maNone;
948 if ShowTab = tbPrevious then
949 PreviewMap(StartLandMass); // avoid delay on first TabX change
950 ChangeTab(ShowTab);
951 Background.Enabled := False;
952
953 UpdateMusic;
954end;
955
956procedure TStartDlg.UnlistBackupFile(FileName: string);
957var
958 I: Integer;
959begin
960 if not IsAutoSaveFileName(FileName) then
961 FileName := ToAutoSaveFileName(FileName);
962 I := FormerGames.Count - 1;
963 while (I >= 0) and (AnsiCompareFileName(FormerGames[I], ExtractFileNameOnly(FileName)) <> 0) do
964 Dec(I);
965 if I >= 0 then begin
966 FormerGames.Delete(I);
967 if ListIndex[tbNew] = I then
968 ListIndex[tbNew] := 0;
969 end;
970end;
971
972procedure TStartDlg.StartBtnClick(Sender: TObject);
973var
974 I, GameCount, MapCount: Integer;
975 FileName: string;
976 Reg: TRegistry;
977begin
978 case Page of
979 pgLoad:
980 begin // load
981 FileName := GetSavedDir + DirectorySeparator + List.Items[List.ItemIndex] + CevoExt;
982 if LoadGame(FileName, LoadTurn, False)
983 then
984 UnlistBackupFile(FileName)
985 else
986 SimpleMessage(Phrases.Lookup('LOADERR'));
987 SlotAvailable := -1;
988 end;
989 pgStartRandom, pgStartMap:
990 if Assigned(PlayersBrain[0]) then
991 begin
992 if (Page = pgStartMap) and (nMapStartPositions = 0) and (AutoDiff > 0)
993 then
994 begin
995 SimpleMessage(Phrases.Lookup('NOSTARTPOS'));
996 Exit;
997 end;
998
999 Reg := TRegistry.Create;
1000 with Reg do
1001 try
1002 OpenKey(AppRegistryKey, True);
1003 if ValueExists('GameCount') then GameCount := ReadInteger('GameCount')
1004 else GameCount := 0;
1005
1006 if (AutoDiff < 0) and (PlayersBrain[0].Kind = btNoTerm) then
1007 FileName := GetSavedDir + DirectorySeparator + 'Round' + IntToStr(GetProcessID()) + CevoExt
1008 else begin
1009 Inc(GameCount);
1010 FileName := GetSavedDir + DirectorySeparator + Format(Phrases.Lookup('GAME'), [GameCount]) + CevoExt;
1011 end;
1012
1013 // Save settings and AI assignment
1014 if Page = pgStartRandom then begin
1015 SaveConfig;
1016 OpenKey(AppRegistryKey + '\AI', True);
1017 if AutoDiff < 0 then
1018 for I := 0 to nPlOffered - 1 do begin
1019 if not Assigned(PlayersBrain[I]) then
1020 Reg.WriteString('Control' + IntToStr(I), '')
1021 else Reg.WriteString('Control' + IntToStr(I),
1022 PlayersBrain[I].FileName);
1023 WriteInteger('Diff' + IntToStr(I), Difficulty[I]);
1024 end;
1025 end;
1026
1027 OpenKey(AppRegistryKey, True);
1028 if BrainDefault.Kind <> btNetworkClient then begin
1029 if AutoDiff > 0 then begin
1030 WriteString('DefaultAI', BrainDefault.FileName);
1031 SlotAvailable := 0; // PlayerSlot will be invalid hereafter
1032 PlayersBrain[0] := BrainTerm;
1033 Difficulty[0] := PlayerAutoDiff[AutoDiff];
1034 for I := 1 to nPl - 1 do
1035 if (Page = pgStartRandom) and (I <= AutoEnemies) or
1036 (Page = pgStartMap) and (I < nMapStartPositions) then begin
1037 if AutoDiff = 1 then PlayersBrain[I] := Brains.GetBeginner
1038 else PlayersBrain[I] := BrainDefault;
1039 Difficulty[I] := EnemyAutoDiff[AutoDiff];
1040 end else PlayersBrain[I] := nil;
1041 end else begin
1042 for I := 6 to 8 do
1043 if (PlayersBrain[0].Kind <> btNoTerm) and (MultiControl and (1 shl I) <> 0)
1044 then begin
1045 PlayersBrain[I + 3] := PlayersBrain[I];
1046 Difficulty[I + 3] := Difficulty[I];
1047 PlayersBrain[I + 6] := PlayersBrain[I];
1048 Difficulty[I + 6] := Difficulty[I];
1049 end else begin
1050 PlayersBrain[I + 3] := nil;
1051 PlayersBrain[I + 6] := nil;
1052 end;
1053 end;
1054 end;
1055
1056 WriteInteger('AutoDiff', AutoDiff);
1057 WriteInteger('AutoEnemies', AutoEnemies);
1058 WriteInteger('MaxTurn', MaxTurn);
1059 WriteInteger('GameCount', GameCount);
1060 finally
1061 Free;
1062 end;
1063
1064 StartNewGame(FileName, MapFileName, WorldSizes[WorldSize].X,
1065 WorldSizes[WorldSize].Y, StartLandMass, MaxTurn);
1066 UnlistBackupFile(FileName);
1067 end;
1068 pgEditMap:
1069 EditMap(MapFileName, lxmax, lymax, StartLandMass);
1070 pgEditRandom: // new map
1071 begin
1072 Reg := TRegistry.Create;
1073 with Reg do
1074 try
1075 OpenKey(AppRegistryKey, True);
1076 if ValueExists('MapCount') then MapCount := ReadInteger('MapCount')
1077 else MapCount := 0;
1078 Inc(MapCount);
1079 WriteInteger('MapCount', MapCount);
1080 finally
1081 Free;
1082 end;
1083 MapFileName := GetMapsDir + DirectorySeparator + Format(Phrases.Lookup('MAP'),
1084 [MapCount]) + CevoMapExt;
1085 EditMap(MapFileName, WorldSizes[WorldSize].X, WorldSizes[WorldSize].Y,
1086 StartLandMass);
1087 end;
1088 end;
1089end;
1090
1091procedure TStartDlg.ListKeyPress(Sender: TObject; var Key: Char);
1092begin
1093 if Key = #13 then StartBtnClick(Sender);
1094end;
1095
1096procedure TStartDlg.ListKeyDown(Sender: TObject; var Key: Word;
1097 Shift: TShiftState);
1098const
1099 DelKey = 46;
1100begin
1101 if Key = DelKey then DeleteBtnClick(Sender)
1102 else FormKeyDown(Sender, Key, Shift);
1103end;
1104
1105procedure TStartDlg.PaintInfo;
1106begin
1107 case Page of
1108 pgStartRandom: begin
1109 MiniMap.Mode := mmPicture;
1110 MiniMap.PaintRandom(3, StartLandMass, WorldSizes[WorldSize]);
1111 end;
1112 pgNoLoad: begin
1113 MiniMap.Mode := mmNone;
1114 MiniMap.Size := WorldSizes[DefaultWorldSize];
1115 end;
1116 pgLoad: begin
1117 MiniMap.LoadFromLogFile(GetSavedDir + DirectorySeparator +
1118 List.Items[List.ItemIndex] + CevoExt, LastTurn, WorldSizes[DefaultWorldSize]);
1119 // BookDate := DateToStr(FileDateToDateTime(FileAge(FileName)));
1120 if not TurnValid then begin
1121 LoadTurn := LastTurn;
1122 SmartInvalidate(xTurnSlider - 2, y0Mini + 61,
1123 xTurnSlider + wTurnSlider + 2, yTurnSlider + 9);
1124 end;
1125 TurnValid := True;
1126 end;
1127 pgEditRandom: begin
1128 MapFileName := '';
1129 MiniMap.Mode := mmPicture;
1130 MiniMap.PaintRandom(4, StartLandMass, WorldSizes[WorldSize]);
1131 end;
1132 pgStartMap, pgEditMap:
1133 begin
1134 if Page = pgEditMap then begin
1135 if List.ItemIndex >= 0 then
1136 MapFileName := GetMapsDir + DirectorySeparator + List.Items[List.ItemIndex] + CevoMapExt
1137 else Exit;
1138 end;
1139 MiniMap.LoadFromMapFile(MapFileName, nMapLandTiles, nMapStartPositions);
1140 if Page = pgEditMap then
1141 SmartInvalidate(x0Mini - 112, y0Mini + 61, x0Mini + 112, y0Mini + 91);
1142 end;
1143 end;
1144 SmartInvalidate(x0Mini - lxmax, y0Mini - lymax div 2,
1145 x0Mini - lxmax + 2 * lxmax + 4, y0Mini - lymax div 2 + lymax + 4);
1146end;
1147
1148procedure TStartDlg.BrainClick(Sender: TObject);
1149var
1150 I: Integer;
1151begin
1152 // Play('BUTTON_UP');
1153 if PlayerPopupIndex < 0 then
1154 begin // change default AI
1155 BrainDefault := Brains[TMenuItem(Sender).Tag];
1156 SmartInvalidate(xDefault, yDefault, xDefault + 64, yDefault + 64);
1157 end
1158 else
1159 begin
1160 if Assigned(PlayersBrain[PlayerPopupIndex]) then
1161 PlayersBrain[PlayerPopupIndex].Flags := PlayersBrain[PlayerPopupIndex].Flags and not fUsed;
1162 if TMenuItem(Sender).Tag = -1 then begin
1163 PlayersBrain[PlayerPopupIndex] := nil;
1164 PlayerSlots[PlayerPopupIndex].DiffUpBtn.Visible := False;
1165 PlayerSlots[PlayerPopupIndex].DiffDownBtn.Visible := False;
1166 if PlayerSlots[PlayerPopupIndex].OfferMultiple then begin
1167 PlayerSlots[PlayerPopupIndex].MultiBtn.Visible := False;
1168 PlayerSlots[PlayerPopupIndex].MultiBtn.ButtonIndex := 2 + (MultiControl shr PlayerPopupIndex) and 1;
1169 end;
1170 MultiControl := MultiControl and not (1 shl PlayerPopupIndex);
1171 end else begin
1172 PlayersBrain[PlayerPopupIndex] := Brains[TMenuItem(Sender).Tag];
1173 PlayerSlots[PlayerPopupIndex].DiffUpBtn.Visible := PlayersBrain[PlayerPopupIndex].Kind in [btTerm, btRandom, btAI];
1174 PlayerSlots[PlayerPopupIndex].DiffDownBtn.Visible := PlayersBrain[PlayerPopupIndex].Kind in [btTerm, btRandom, btAI];
1175 if PlayerSlots[PlayerPopupIndex].OfferMultiple then begin
1176 PlayerSlots[PlayerPopupIndex].MultiBtn.Visible := PlayersBrain[PlayerPopupIndex].Kind in [btTerm, btRandom, btAI];
1177 PlayerSlots[PlayerPopupIndex].MultiBtn.ButtonIndex := 2 + (MultiControl shr PlayerPopupIndex) and 1;
1178 end;
1179 PlayersBrain[PlayerPopupIndex].Flags := PlayersBrain[PlayerPopupIndex].Flags or fUsed;
1180 if PlayersBrain[PlayerPopupIndex].Kind in [btNoTerm, btSuperVirtual] then
1181 Difficulty[PlayerPopupIndex] := 0 { supervisor }
1182 else
1183 Difficulty[PlayerPopupIndex] := 2;
1184 if (Page = pgStartRandom) and (PlayerSlots[PlayerPopupIndex].OfferMultiple) and
1185 (not Assigned(PlayersBrain[PlayerPopupIndex])) then
1186 MultiControl := MultiControl and not (1 shl PlayerPopupIndex);
1187 if (PlayerPopupIndex = 0) and (MapFileName <> '') then
1188 ChangePage(Page);
1189 if PlayersBrain[PlayerPopupIndex].Kind = btNoTerm then
1190 begin // turn all local players off
1191 for I := 1 to PlayerSlots.Count - 1 do
1192 if Assigned(PlayersBrain[I]) and (PlayersBrain[I].Kind = btTerm) then begin
1193 PlayersBrain[I] := nil;
1194 PlayerSlots[I].DiffUpBtn.Visible := False;
1195 PlayerSlots[I].DiffUpBtn.Tag := 0;
1196 PlayerSlots[I].DiffDownBtn.Visible := False;
1197 PlayerSlots[I].DiffDownBtn.Tag := 0;
1198 if PlayerSlots[I].OfferMultiple then begin
1199 PlayerSlots[I].MultiBtn.Visible := False;
1200 PlayerSlots[I].MultiBtn.Tag := 0;
1201 end;
1202 SmartInvalidate(xBrain[I] - 31, yBrain[I] - 1, xBrain[I] + 64,
1203 PlayerSlots[I].DiffUpBtn.Top + 25);
1204 end;
1205 BrainTerm.Flags := BrainTerm.Flags and not fUsed;
1206 end;
1207 end;
1208 SmartInvalidate(xBrain[PlayerPopupIndex] - 31, yBrain[PlayerPopupIndex] - 1,
1209 xBrain[PlayerPopupIndex] + 64, PlayerSlots[PlayerPopupIndex].DiffUpBtn.Top + 25);
1210 end;
1211end;
1212
1213procedure TStartDlg.OfferBrain(Brain: TBrain; FixedLines: Integer);
1214var
1215 J: Integer;
1216 MenuItem: TMenuItem;
1217begin
1218 MenuItem := TMenuItem.Create(PopupMenu1);
1219 if not Assigned(Brain) then MenuItem.Caption := Phrases.Lookup('NOMOD')
1220 else MenuItem.Caption := Brain.Name;
1221 MenuItem.Tag := Brains.IndexOf(Brain);
1222 MenuItem.OnClick := BrainClick;
1223 J := FixedLines;
1224 while (J < PopupMenu1.Items.Count) and
1225 (StrIComp(PChar(MenuItem.Caption), PChar(PopupMenu1.Items[J].Caption)) > 0) do
1226 Inc(J);
1227 MenuItem.RadioItem := True;
1228 if (PlayerPopupIndex < 0) then MenuItem.Checked := BrainDefault = Brain
1229 else MenuItem.Checked := PlayersBrain[PlayerPopupIndex] = Brain;
1230 PopupMenu1.Items.Insert(J, MenuItem);
1231end;
1232
1233procedure TStartDlg.InitPopup(PlayerIndex: Integer);
1234var
1235 I: Integer;
1236 FixedLines: Integer;
1237 MenuItem: TMenuItem;
1238 AIBrains: TBrains;
1239begin
1240 FixedLines := 0;
1241 PlayerPopupIndex := PlayerIndex;
1242 EmptyMenu(PopupMenu1.Items);
1243 if PlayerPopupIndex < 0 then begin // select default AI
1244 if NetworkEnabled then begin
1245 OfferBrain(BrainNetworkClient, FixedLines);
1246 Inc(FixedLines);
1247 end;
1248
1249 MenuItem := TMenuItem.Create(PopupMenu1);
1250 MenuItem.Caption := '-';
1251 PopupMenu1.Items.Add(MenuItem);
1252
1253 Inc(FixedLines);
1254 if Brains.GetKindCount(btAI) >= 2 then begin
1255 OfferBrain(BrainRandom, FixedLines);
1256 Inc(FixedLines);
1257 end;
1258 AIBrains := TBrains.Create(False);
1259 Brains.GetByKind(btAI, AIBrains);
1260 for I := 0 to AIBrains.Count - 1 do // offer available AIs
1261 if AIBrains[I].Flags and fMultiple <> 0 then
1262 OfferBrain(AIBrains[I], FixedLines);
1263 FreeAndNil(AIBrains);
1264 end else begin
1265 if PlayerPopupIndex > 0 then begin
1266 OfferBrain(nil, FixedLines);
1267 Inc(FixedLines);
1268 end;
1269 for I := Brains.IndexOf(BrainTerm) downto 0 do // offer game interfaces
1270 if (PlayerPopupIndex = 0) or (Brains[I].Kind = btTerm) and
1271 (PlayersBrain[0].Kind <> btNoTerm) then begin
1272 OfferBrain(Brains[I], FixedLines);
1273 Inc(FixedLines);
1274 end;
1275 if PlayerPopupIndex > 0 then begin
1276 if NetworkEnabled then begin
1277 OfferBrain(BrainNetworkServer, FixedLines);
1278 Inc(FixedLines);
1279 end;
1280
1281 MenuItem := TMenuItem.Create(PopupMenu1);
1282 MenuItem.Caption := '-';
1283 PopupMenu1.Items.Add(MenuItem);
1284 Inc(FixedLines);
1285 if Brains.GetKindCount(btAI) >= 2 then begin
1286 OfferBrain(BrainRandom, FixedLines);
1287 Inc(FixedLines);
1288 end;
1289 AIBrains := TBrains.Create(False);
1290 Brains.GetByKind(btAI, AIBrains);
1291 for I := 0 to AIBrains.Count - 1 do // offer available AIs
1292 if (AIBrains[I].Flags and fMultiple <> 0) or (AIBrains[I].Flags and fUsed = 0)
1293 or (Brains[I] = PlayersBrain[PlayerPopupIndex]) then
1294 OfferBrain(AIBrains[I], FixedLines);
1295 FreeAndNil(AIBrains);
1296 end;
1297 end;
1298end;
1299
1300procedure TStartDlg.UpdateFormerGames;
1301var
1302 I: Integer;
1303 F: TSearchRec;
1304begin
1305 FormerGames.Clear;
1306 if FindFirst(GetSavedDir + DirectorySeparator + '*' + CevoExt, $21, F) = 0 then
1307 repeat
1308 I := FormerGames.Count;
1309 while (I > 0) and (F.Time < Integer(FormerGames.Objects[I - 1])) do
1310 Dec(I);
1311 FormerGames.InsertObject(I, ExtractFileNameOnly(F.Name),
1312 TObject(F.Time));
1313 until FindNext(F) <> 0;
1314 FindClose(F);
1315 I := FormerGames.IndexOf(LastGame);
1316 if I >= 0 then ListIndex[tbPrevious] := I
1317 else ListIndex[tbPrevious] := FormerGames.Count - 1;
1318 TurnValid := False;
1319end;
1320
1321procedure TStartDlg.UpdateMaps(SelectLastMap: Boolean);
1322var
1323 I: Integer;
1324 F: TSearchRec;
1325begin
1326 Maps.Clear;
1327 if FindFirst(GetMapsDir + DirectorySeparator + '*' + CevoMapExt, $21, F) = 0 then
1328 repeat
1329 Maps.Add(Copy(F.Name, 1, Length(F.Name) - Length(CevoMapExt)));
1330 until FindNext(F) <> 0;
1331 FindClose(F);
1332 Maps.Sort;
1333 Maps.Insert(0, Phrases.Lookup('RANMAP'));
1334 if SelectLastMap then begin
1335 I := Maps.IndexOf(LastMap);
1336 if I > 0 then begin // Skip random map on index 0
1337 ListIndex[tbMap] := I;
1338 MapFileName := GetMapsDir + DirectorySeparator + Maps[I] + CevoMapExt;
1339 end else ListIndex[tbMap] := Maps.IndexOf(ExtractFileNameOnly(MapFileName));
1340 end else ListIndex[tbMap] := Maps.IndexOf(ExtractFileNameOnly(MapFileName));
1341 if ListIndex[tbMap] < 0 then
1342 ListIndex[tbMap] := 0;
1343 ListIndex[tbMain] := ListIndex[tbMap];
1344 if ListIndex[tbMain] < 0 then
1345 ListIndex[tbMain] := 0;
1346end;
1347
1348procedure TStartDlg.ChangePage(NewPage: TStartPage);
1349var
1350 I, J, p1: Integer;
1351 S: string;
1352 Reg: TRegistry;
1353 InvalidateTab0: Boolean;
1354begin
1355 InvalidateTab0 := (Page = pgMain) or (NewPage = pgMain);
1356 Page := NewPage;
1357 case Page of
1358 pgStartRandom, pgStartMap:
1359 begin
1360 StartBtn.Caption := Phrases.Lookup('STARTCONTROLS', 1);
1361 if Page = pgStartRandom then
1362 I := nPlOffered
1363 else
1364 begin
1365 I := nMapStartPositions;
1366 if I = 0 then
1367 begin
1368 PlayersBrain[0] := BrainSuperVirtual;
1369 Difficulty[0] := 0;
1370 end;
1371 if PlayersBrain[0].Kind in [btNoTerm, btSuperVirtual] then
1372 Inc(I);
1373 if I > nPl then
1374 I := nPl;
1375 if I <= nPlOffered then
1376 MultiControl := 0
1377 else
1378 MultiControl := InitMulti[I];
1379 end;
1380 if InitAlive[I] <> SlotAvailable then
1381 if Page = pgStartRandom then
1382 begin // restore AI assignment of last start
1383 Reg := TRegistry.Create;
1384 with Reg do
1385 try
1386 OpenKey(AppRegistryKey + '\AI', True);
1387 for p1 := 0 to nPlOffered - 1 do begin
1388 PlayersBrain[p1] := nil;
1389 S := ReadString('Control' + IntToStr(p1));
1390 Difficulty[p1] := ReadInteger('Diff' + IntToStr(p1));
1391 if S <> '' then
1392 for J := 0 to Brains.Count - 1 do
1393 if AnsiCompareFileName(S, Brains[J].FileName) = 0 then
1394 PlayersBrain[p1] := Brains[J];
1395 end;
1396 finally
1397 Free;
1398 end;
1399 end
1400 else
1401 for p1 := 1 to nPl - 1 do
1402 if 1 shl p1 and InitAlive[I] <> 0 then
1403 begin
1404 PlayersBrain[p1] := BrainDefault;
1405 Difficulty[p1] := 2;
1406 end
1407 else
1408 PlayersBrain[p1] := nil;
1409 SlotAvailable := InitAlive[I];
1410 for I := 0 to nPlOffered - 1 do
1411 if (AutoDiff < 0) and Assigned(PlayersBrain[I]) and
1412 (PlayersBrain[I].Kind in [btTerm, btRandom, btAI]) then
1413 begin
1414 PlayerSlots[I].DiffUpBtn.Tag := 768;
1415 PlayerSlots[I].DiffDownBtn.Tag := 768;
1416 end
1417 else
1418 begin
1419 PlayerSlots[I].DiffUpBtn.Tag := 0;
1420 PlayerSlots[I].DiffDownBtn.Tag := 0;
1421 end;
1422 for I := 6 to 8 do
1423 if (AutoDiff < 0) and Assigned(PlayersBrain[I]) and
1424 (PlayersBrain[I].Kind in [btTerm, btRandom, btAI]) then
1425 begin
1426 PlayerSlots[I].MultiBtn.Tag := 768;
1427 PlayerSlots[I].MultiBtn.ButtonIndex := 2 + (MultiControl shr I) and 1;
1428 PlayerSlots[I].MultiBtn.Enabled := Page = pgStartRandom;
1429 end
1430 else
1431 PlayerSlots[I].MultiBtn.Tag := 0;
1432 if (AutoDiff > 0) and (Page <> pgStartMap) then
1433 begin
1434 AutoEnemyUpBtn.Tag := 768;
1435 AutoEnemyDownBtn.Tag := 768;
1436 end
1437 else
1438 begin
1439 AutoEnemyUpBtn.Tag := 0;
1440 AutoEnemyDownBtn.Tag := 0;
1441 end;
1442 if AutoDiff > 0 then
1443 begin
1444 AutoDiffUpBtn.Tag := 768;
1445 AutoDiffDownBtn.Tag := 768;
1446 end
1447 else
1448 begin
1449 AutoDiffUpBtn.Tag := 0;
1450 AutoDiffDownBtn.Tag := 0;
1451 end;
1452 end;
1453
1454 pgNoLoad, pgLoad:
1455 begin
1456 StartBtn.Caption := Phrases.Lookup('STARTCONTROLS', 2);
1457 RenameBtn.Hint := Phrases.Lookup('BTN_RENGAME');
1458 DeleteBtn.Hint := Phrases.Lookup('BTN_DELGAME');
1459 end;
1460
1461 pgEditRandom, pgEditMap:
1462 begin
1463 StartBtn.Caption := Phrases.Lookup('STARTCONTROLS', 12);
1464 RenameBtn.Hint := Phrases.Lookup('BTN_RENMAP');
1465 DeleteBtn.Hint := Phrases.Lookup('BTN_DELMAP');
1466 end;
1467 end;
1468
1469 PaintInfo;
1470 for I := 0 to ControlCount - 1 do
1471 Controls[I].Visible := Controls[I].Tag and (256 shl Integer(Page)) <> 0;
1472 if Page = pgLoad then
1473 ReplayBtn.Visible := MiniMap.Mode <> mmMultiPlayer;
1474 List.Invalidate;
1475 SmartInvalidate(0, 0, ClientWidth, ClientHeight, InvalidateTab0);
1476end;
1477
1478procedure TStartDlg.ChangeTab(NewTab: TStartTab);
1479begin
1480 Tab := NewTab;
1481 case Tab of
1482 tbMap:
1483 List.Items.Assign(Maps);
1484 tbPrevious:
1485 List.Items.Assign(FormerGames);
1486 end;
1487 if Tab <> tbNew then
1488 if List.Count > 0 then begin
1489 if (ListIndex[Tab] < List.Count) and (ListIndex[Tab] >= 0) then begin
1490 List.ItemIndex := ListIndex[Tab];
1491 end else List.ItemIndex := 0;
1492 end else List.ItemIndex := -1;
1493 case Tab of
1494 tbMain:
1495 ChangePage(pgMain);
1496 tbMap:
1497 if List.ItemIndex = 0 then
1498 ChangePage(pgEditRandom)
1499 else
1500 ChangePage(pgEditMap);
1501 tbNew:
1502 if MapFileName = '' then
1503 ChangePage(pgStartRandom)
1504 else
1505 ChangePage(pgStartMap);
1506 tbPrevious:
1507 if FormerGames.Count = 0 then
1508 ChangePage(pgNoLoad)
1509 else
1510 ChangePage(pgLoad);
1511 end;
1512end;
1513
1514procedure TStartDlg.FormMouseDown(Sender: TObject; Button: TMouseButton;
1515 Shift: TShiftState; X, Y: Integer);
1516var
1517 I: Integer;
1518begin
1519 if (Y < TabHeight + 1) and (X - TabOffset < TabSize * 4) and
1520 ((X - TabOffset) div TabSize <> Integer(Tab)) then
1521 begin
1522 // Play('BUTTON_DOWN');
1523 ListIndex[Tab] := List.ItemIndex;
1524 ChangeTab(TStartTab((X - TabOffset) div TabSize));
1525 end
1526 else if Page = pgMain then begin
1527 case SelectedAction of
1528 maConfig: ShowSettings;
1529 maManual: DirectHelp(cStartHelp);
1530 maCredits: DirectHelp(cStartCredits);
1531 maAIDev: OpenDocument(GetAppSharePath(AITemplateFileName));
1532 maWeb: OpenURL(CevoHomepage);
1533 end;
1534 end
1535 else if (AutoDiff < 0) and ((Page = pgStartRandom) or (Page = pgStartMap) and
1536 (nMapStartPositions > 0)) then
1537 begin
1538 for I := 0 to nPlOffered - 1 do
1539 if (1 shl I and SlotAvailable <> 0) and (X >= xBrain[I]) and
1540 (Y >= yBrain[I]) and (X < xBrain[I] + 64) and (Y < yBrain[I] + 64) then
1541 begin
1542 InitPopup(I);
1543 if yBrain[I] > y0Brain then
1544 PopupMenu1.Popup(Left + xBrain[I] + 4, Top + yBrain[I] + 60)
1545 else
1546 PopupMenu1.Popup(Left + xBrain[I] + 4, Top + yBrain[I] + 4);
1547 end;
1548 end
1549 else if (AutoDiff > 1) and ((Page = pgStartRandom) or (Page = pgStartMap)) and
1550 (X >= xDefault) and (Y >= yDefault) and (X < xDefault + 64) and
1551 (Y < yDefault + 64) then
1552 if Brains.GetKindCount(btAI) < 2 then
1553 SimpleMessage(Phrases.Lookup('NOALTAI'))
1554 else
1555 begin
1556 InitPopup(-1);
1557 PopupMenu1.Popup(Left + xDefault + 4, Top + yDefault + 4);
1558 end
1559 else if (Page = pgLoad) and (LastTurn > 0) and (Y >= yTurnSlider) and
1560 (Y < yTurnSlider + 7) and (X >= xTurnSlider) and
1561 (X <= xTurnSlider + wTurnSlider) then
1562 begin
1563 LoadTurn := LastTurn * (X - xTurnSlider) div wTurnSlider;
1564 SmartInvalidate(xTurnSlider - 2, y0Mini + 61, xTurnSlider + wTurnSlider + 2,
1565 yTurnSlider + 9);
1566 Tracking := True;
1567 end;
1568end;
1569
1570procedure TStartDlg.Up2BtnClick(Sender: TObject);
1571begin
1572 case Page of
1573 pgStartRandom, pgStartMap:
1574 if MaxTurn < 1400 then
1575 begin
1576 Inc(MaxTurn, 200);
1577 SmartInvalidate(344, y0Mini + 61, 514, y0Mini + 82);
1578 end;
1579 pgLoad:
1580 if LoadTurn < LastTurn then
1581 begin
1582 Inc(LoadTurn);
1583 SmartInvalidate(xTurnSlider - 2, y0Mini + 61, xTurnSlider + wTurnSlider
1584 + 2, yTurnSlider + 9);
1585 end;
1586 pgEditRandom:
1587 if StartLandMass < 96 then
1588 begin
1589 Inc(StartLandMass, 5);
1590 PaintInfo;
1591 SmartInvalidate(344, y0Mini + 61, 514, y0Mini + 61 + 21);
1592 end;
1593 end;
1594end;
1595
1596procedure TStartDlg.Down2BtnClick(Sender: TObject);
1597begin
1598 case Page of
1599 pgStartRandom, pgStartMap:
1600 if MaxTurn > 400 then
1601 begin
1602 Dec(MaxTurn, 200);
1603 SmartInvalidate(344, y0Mini + 61, 514, y0Mini + 82);
1604 end;
1605 pgLoad:
1606 if LoadTurn > 0 then
1607 begin
1608 Dec(LoadTurn);
1609 SmartInvalidate(xTurnSlider - 2, y0Mini + 61, xTurnSlider + wTurnSlider
1610 + 2, yTurnSlider + 9);
1611 end;
1612 pgEditRandom:
1613 if StartLandMass > 10 then
1614 begin
1615 Dec(StartLandMass, 5);
1616 PaintInfo;
1617 SmartInvalidate(344, y0Mini + 61, 514, y0Mini + 61 + 21);
1618 end;
1619 end;
1620end;
1621
1622procedure TStartDlg.Up1BtnClick(Sender: TObject);
1623begin
1624 if WorldSize < MaxWorldSize - 1 then
1625 begin
1626 Inc(WorldSize);
1627 PaintInfo;
1628 SmartInvalidate(344, y0Mini - 77, 510, y0Mini - 77 + 21);
1629 end;
1630end;
1631
1632procedure TStartDlg.Down1BtnClick(Sender: TObject);
1633begin
1634 if WorldSize > 0 then
1635 begin
1636 Dec(WorldSize);
1637 PaintInfo;
1638 SmartInvalidate(344, y0Mini - 77, 510, y0Mini - 77 + 21);
1639 end;
1640end;
1641
1642procedure TStartDlg.FormClose(Sender: TObject; var Action: TCloseAction);
1643begin
1644 DirectDlg.Close;
1645end;
1646
1647procedure TStartDlg.ListClick(Sender: TObject);
1648var
1649 I: Integer;
1650begin
1651 if (Tab = tbMap) and ((List.ItemIndex = 0) <> (Page = pgEditRandom)) then
1652 begin
1653 if List.ItemIndex = 0 then
1654 Page := pgEditRandom
1655 else
1656 Page := pgEditMap;
1657 for I := 0 to ControlCount - 1 do
1658 Controls[I].Visible := Controls[I].Tag and (256 shl Integer(Page)) <> 0;
1659 SmartInvalidate(328, Up1Btn.Top - 12, ClientWidth, Up2Btn.Top + 35);
1660 end;
1661 if Page = pgLoad then
1662 TurnValid := False;
1663 PaintInfo;
1664 if Page = pgLoad then
1665 ReplayBtn.Visible := MiniMap.Mode <> mmMultiPlayer;
1666end;
1667
1668procedure TStartDlg.RenameBtnClick(Sender: TObject);
1669var
1670 I: Integer;
1671 NewName: string;
1672 F: file;
1673 Ok: Boolean;
1674 MapPictureFileName: string;
1675begin
1676 if List.ItemIndex >= 0 then
1677 begin
1678 if Page = pgLoad then
1679 InputDlg.Caption := Phrases.Lookup('TITLE_BOOKNAME')
1680 else
1681 InputDlg.Caption := Phrases.Lookup('TITLE_MAPNAME');
1682 InputDlg.EditInput.Text := List.Items[List.ItemIndex];
1683 InputDlg.CenterToRect(BoundsRect);
1684 InputDlg.ShowModal;
1685 NewName := InputDlg.EditInput.Text;
1686 while IsAutoSaveFileName(NewName) do
1687 Delete(NewName, 1, 1);
1688 if (InputDlg.ModalResult = mrOK) and (NewName <> '') and
1689 (NewName <> List.Items[List.ItemIndex]) then
1690 begin
1691 for I := 1 to Length(NewName) do
1692 if NewName[I] in ['\', '/', ':', '*', '?', '"', '<', '>', '|'] then
1693 begin
1694 SimpleMessage(Format(Phrases.Lookup('NOFILENAME'), [NewName[I]]));
1695 Exit;
1696 end;
1697 if Page = pgLoad then
1698 AssignFile(F, GetSavedDir + DirectorySeparator + List.Items[List.ItemIndex] + CevoExt)
1699 else
1700 AssignFile(F, GetMapsDir + DirectorySeparator + List.Items[List.ItemIndex] +
1701 CevoMapExt);
1702 Ok := True;
1703 try
1704 if Page = pgLoad then
1705 Rename(F, GetSavedDir + DirectorySeparator + NewName + CevoExt)
1706 else
1707 Rename(F, GetMapsDir + DirectorySeparator + NewName + CevoMapExt);
1708 except
1709 // Play('INVALID');
1710 Ok := False;
1711 end;
1712 if Page <> pgLoad then begin
1713 // Rename map picture
1714 MapPictureFileName := GetMapsDir + DirectorySeparator +
1715 List.Items[List.ItemIndex] + CevoMapPictureExt;
1716 if FileExists(MapPictureFileName) then
1717 try
1718 AssignFile(F, GetMapsDir + DirectorySeparator + List.Items[List.ItemIndex]
1719 + CevoMapPictureExt);
1720 Rename(F, GetMapsDir + DirectorySeparator + NewName + CevoMapPictureExt);
1721 except
1722 end;
1723 end;
1724 if Ok then begin
1725 if Page = pgLoad then
1726 FormerGames[List.ItemIndex] := NewName
1727 else
1728 Maps[List.ItemIndex] := NewName;
1729 List.Items[List.ItemIndex] := NewName;
1730 if Page = pgEditMap then
1731 PaintInfo;
1732 List.Invalidate;
1733 end;
1734 end;
1735 end;
1736end;
1737
1738procedure TStartDlg.DeleteBtnClick(Sender: TObject);
1739var
1740 iDel: Integer;
1741 F: file;
1742begin
1743 if List.ItemIndex >= 0 then
1744 begin
1745 if Page = pgLoad then
1746 MessgDlg.MessgText := Phrases.Lookup('DELETEQUERY')
1747 else
1748 MessgDlg.MessgText := Phrases.Lookup('MAPDELETEQUERY');
1749 MessgDlg.Kind := mkOKCancel;
1750 MessgDlg.ShowModal;
1751 if MessgDlg.ModalResult = mrOK then
1752 begin
1753 if Page = pgLoad then
1754 AssignFile(F, GetSavedDir + DirectorySeparator + List.Items[List.ItemIndex] + CevoExt)
1755 else
1756 AssignFile(F, GetMapsDir + DirectorySeparator + List.Items[List.ItemIndex] +
1757 CevoMapExt);
1758 Erase(F);
1759 iDel := List.ItemIndex;
1760 if Page = pgLoad then
1761 FormerGames.Delete(iDel)
1762 else
1763 Maps.Delete(iDel);
1764 List.Items.Delete(iDel);
1765 if List.Items.Count = 0 then
1766 ChangePage(pgNoLoad)
1767 else
1768 begin
1769 if iDel = 0 then
1770 List.ItemIndex := 0
1771 else
1772 List.ItemIndex := iDel - 1;
1773 if (Page = pgEditMap) and (List.ItemIndex = 0) then
1774 ChangePage(pgEditRandom)
1775 else
1776 begin
1777 List.Invalidate;
1778 if Page = pgLoad then
1779 TurnValid := False;
1780 PaintInfo;
1781 if Page = pgLoad then
1782 ReplayBtn.Visible := MiniMap.Mode <> mmMultiPlayer;
1783 end;
1784 end;
1785 end;
1786 end;
1787end;
1788
1789procedure TStartDlg.DiffBtnClick(Sender: TObject);
1790var
1791 I: Integer;
1792begin
1793 for I := 0 to nPlOffered - 1 do
1794 if (Sender = PlayerSlots[I].DiffUpBtn) and (Difficulty[I] < 3) or
1795 (Sender = PlayerSlots[I].DiffDownBtn) and (Difficulty[I] > 1) then
1796 begin
1797 if Sender = PlayerSlots[I].DiffUpBtn then
1798 Inc(Difficulty[I])
1799 else
1800 Dec(Difficulty[I]);
1801 SmartInvalidate(xBrain[I] - 18, yBrain[I] + 19, xBrain[I] - 18 + 12,
1802 yBrain[I] + (19 + 14));
1803 end;
1804end;
1805
1806procedure TStartDlg.MultiBtnClick(Sender: TObject);
1807var
1808 I: Integer;
1809begin
1810 for I := 6 to 8 do
1811 if Sender = PlayerSlots[I].MultiBtn then
1812 begin
1813 MultiControl := MultiControl xor (1 shl I);
1814 TButtonC(Sender).ButtonIndex := 2 + (MultiControl shr I) and 1;
1815 end;
1816end;
1817
1818procedure TStartDlg.FormHide(Sender: TObject);
1819begin
1820 Diff0 := Difficulty[0];
1821 ListIndex[Tab] := List.ItemIndex;
1822 ShowTab := Tab;
1823 Background.Enabled := True;
1824 if (ListIndex[tbPrevious] >= 0) and (ListIndex[tbPrevious] < FormerGames.Count) then
1825 LastGame := FormerGames[ListIndex[tbPrevious]]
1826 else LastGame := '';
1827 if (ListIndex[tbMap] >= 0) and (ListIndex[tbMap] < Maps.Count) then
1828 LastMap := Maps[ListIndex[tbMap]]
1829 else LastMap := '';
1830end;
1831
1832procedure TStartDlg.QuitBtnClick(Sender: TObject);
1833begin
1834 Close;
1835end;
1836
1837procedure TStartDlg.FormKeyDown(Sender: TObject; var Key: Word;
1838 Shift: TShiftState);
1839var
1840 ShortCut: TShortCut;
1841begin
1842 ShortCut := KeyToShortCut(Key, Shift);
1843 if BFullScreen.Test(ShortCut) then begin
1844 FullScreen := not FullScreen;
1845 UpdateInterface;
1846 Background.UpdateInterface;
1847 SetFocus;
1848 end else
1849 if BHelp.Test(ShortCut) then
1850 DirectHelp(cStartHelp);
1851end;
1852
1853procedure TStartDlg.CustomizeBtnClick(Sender: TObject);
1854begin
1855 AutoDiff := -AutoDiff;
1856 CustomizeBtn.ButtonIndex := CustomizeBtn.ButtonIndex xor 1;
1857 ChangePage(Page);
1858end;
1859
1860procedure TStartDlg.AutoDiffUpBtnClick(Sender: TObject);
1861begin
1862 if AutoDiff < 5 then
1863 begin
1864 Inc(AutoDiff);
1865 SmartInvalidate(120, y0Mini + 61, 272, y0Mini + 61 + 21);
1866 SmartInvalidate(xDefault - 2, yDefault - 2, xDefault + 64 + 2,
1867 yDefault + 64 + 2);
1868 end;
1869end;
1870
1871procedure TStartDlg.AutoDiffDownBtnClick(Sender: TObject);
1872begin
1873 if AutoDiff > 1 then
1874 begin
1875 Dec(AutoDiff);
1876 SmartInvalidate(120, y0Mini + 61, 272, y0Mini + 61 + 21);
1877 SmartInvalidate(xDefault - 2, yDefault - 2, xDefault + 64 + 2,
1878 yDefault + 64 + 2);
1879 end;
1880end;
1881
1882procedure TStartDlg.FormMouseUp(Sender: TObject; Button: TMouseButton;
1883 Shift: TShiftState; X, Y: Integer);
1884begin
1885 Tracking := False;
1886end;
1887
1888procedure TStartDlg.FormMouseMove(Sender: TObject; Shift: TShiftState;
1889 X, Y: Integer);
1890var
1891 OldLoadTurn: Integer;
1892 NewSelectedAction: TMainAction;
1893begin
1894 if Tracking then
1895 begin
1896 X := X - xTurnSlider;
1897 if X < 0 then
1898 X := 0
1899 else if X > wTurnSlider then
1900 X := wTurnSlider;
1901 OldLoadTurn := LoadTurn;
1902 LoadTurn := LastTurn * X div wTurnSlider;
1903 if LoadTurn < OldLoadTurn then
1904 begin
1905 SmartInvalidate(xTurnSlider + LoadTurn * wTurnSlider div LastTurn,
1906 yTurnSlider, xTurnSlider + OldLoadTurn * wTurnSlider div LastTurn + 1,
1907 yTurnSlider + 7);
1908 SmartInvalidate(344, y0Mini + 61, 514, y0Mini + 82);
1909 end
1910 else if LoadTurn > OldLoadTurn then
1911 begin
1912 SmartInvalidate(xTurnSlider + OldLoadTurn * wTurnSlider div LastTurn,
1913 yTurnSlider, xTurnSlider + LoadTurn * wTurnSlider div LastTurn + 1,
1914 yTurnSlider + 7);
1915 SmartInvalidate(344, y0Mini + 61, 514, y0Mini + 82);
1916 end;
1917 end
1918 else if Page = pgMain then
1919 begin
1920 if (X >= ActionSideBorder) and (X < ClientWidth - ActionSideBorder) and
1921 (Y >= yAction - 8) and (Y < ClientHeight - ActionBottomBorder) then
1922 begin
1923 NewSelectedAction := TMainAction((Y - (yAction - 8)) div ActionPitch);
1924 if not (NewSelectedAction in ActionsOffered) then
1925 NewSelectedAction := maNone;
1926 end
1927 else
1928 NewSelectedAction := maNone;
1929 if NewSelectedAction <> SelectedAction then
1930 begin
1931 if SelectedAction <> maNone then
1932 SmartInvalidate(ActionSideBorder, yAction + Integer(SelectedAction) * ActionPitch
1933 - 8, ClientWidth - ActionSideBorder, yAction + (Integer(SelectedAction) + 1) *
1934 ActionPitch - 8);
1935 SelectedAction := NewSelectedAction;
1936 if SelectedAction <> maNone then
1937 SmartInvalidate(ActionSideBorder, yAction + Integer(SelectedAction) * ActionPitch
1938 - 8, ClientWidth - ActionSideBorder, yAction + (Integer(SelectedAction) + 1) *
1939 ActionPitch - 8);
1940 end;
1941 end;
1942end;
1943
1944procedure TStartDlg.AutoEnemyUpBtnClick(Sender: TObject);
1945begin
1946 if AutoEnemies < nPl - 1 then
1947 begin
1948 Inc(AutoEnemies);
1949 SmartInvalidate(160, yMain + 140, 198, yMain + 140 + 21);
1950 end;
1951end;
1952
1953procedure TStartDlg.AutoEnemyDownBtnClick(Sender: TObject);
1954begin
1955 if AutoEnemies > 0 then
1956 begin
1957 Dec(AutoEnemies);
1958 SmartInvalidate(160, yMain + 140, 198, yMain + 140 + 21);
1959 end;
1960end;
1961
1962procedure TStartDlg.ReplayBtnClick(Sender: TObject);
1963begin
1964 LoadGame(GetSavedDir + DirectorySeparator + List.Items[List.ItemIndex] + CevoExt,
1965 LastTurn, True);
1966 SlotAvailable := -1;
1967end;
1968
1969procedure TStartDlg.UpdateMusic;
1970begin
1971 if MusicEnabled then begin
1972 MusicPlayer.Volume := MusicVolume;
1973 if not MusicPlayer.Playing then begin
1974 MusicPlayer.LoadPlaylistFromDir(GetMusicDir + DirectorySeparator + 'Start');
1975 MusicPlayer.RandomizePlaylist;
1976 if MusicPlayer.Playlist.Count > 0 then MusicPlayer.Play;
1977 end;
1978 end else begin
1979 if MusicPlayer.Playing then MusicPlayer.Stop;
1980 end;
1981end;
1982
1983end.
Note: See TracBrowser for help on using the repository browser.