source: tags/1.3.6/Start.pas

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