source: trunk/Start.pas

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