source: tags/1.3.9/Start.pas

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