source: tags/1.3.8/Start.pas

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