source: tags/1.3.4/Start.pas

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