source: tags/1.3.5/Start.pas

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