source: branches/delphi/LocalPlayer/Help.pas

Last change on this file was 6, checked in by chronos, 7 years ago
  • Modified: Formated all project source files using Delphi formatter as original indentation and other formatting was really bad.
File size: 75.2 KB
Line 
1{$INCLUDE switches}
2unit Help;
3
4interface
5
6uses
7 Protocol, ScreenTools, BaseWin, StringTables,
8
9 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
10 ExtCtrls, ButtonB, PVSB, ButtonBase;
11
12const
13 MaxHist = 16;
14
15 { link categories }
16 hkNoLink = 0;
17 hkAdv = 1;
18 hkImp = 2;
19 hkTer = 3;
20 hkFeature = 4;
21 hkInternet = 5;
22 hkModel = 6;
23 hkMisc = 7;
24 hkCrossLink = $40;
25 hkText = $80;
26
27 liInvalid = $3FFF; // link index indicates invalid link
28
29 { link indices for category hkMisc }
30 miscMain = 0;
31 miscCredits = 1;
32 miscGovList = 2;
33 miscJobList = 3;
34 miscSearchResult = 7;
35
36 fJungle = 8; // pseudo terrain
37
38type
39 THyperText = class(TStringList)
40 procedure AddLine(s: String = ''; Format: integer = 0; Picpix: integer = 0;
41 LinkCategory: integer = 0; LinkIndex: integer = 0);
42 procedure LF;
43 end;
44
45 THelpDlg = class(TFramedDlg)
46 CloseBtn: TButtonB;
47 BackBtn: TButtonB;
48 TopBtn: TButtonB;
49 SearchBtn: TButtonB;
50 procedure FormCreate(Sender: TObject);
51 procedure FormDestroy(Sender: TObject);
52 procedure FormPaint(Sender: TObject);
53 procedure CloseBtnClick(Sender: TObject);
54 procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
55 x, y: integer);
56 procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
57 Shift: TShiftState; x, y: integer);
58 procedure BackBtnClick(Sender: TObject);
59 procedure TopBtnClick(Sender: TObject);
60 procedure FormClose(Sender: TObject; var Action: TCloseAction);
61 procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
62 procedure SearchBtnClick(Sender: TObject);
63 public
64 Difficulty: integer;
65 procedure ShowNewContent(NewMode, Category, Index: integer);
66 procedure ClearHistory;
67 function TextIndex(Item: string): integer;
68 protected
69 procedure OffscreenPaint; override;
70 private
71 Kind, no, Sel, nHist, CaptionColor: integer;
72 hADVHELP, hIMPHELP, hFEATUREHELP, hGOVHELP, hSPECIALMODEL,
73 hJOBHELP: integer;
74 SearchContent, NewSearchContent: string;
75 CaptionFont: TFont;
76 MainText, SearchResult: THyperText;
77 HelpText: TStringTable;
78 ExtPic, TerrIcon: TBitmap;
79 sb: TPVScrollbar;
80 x0: array [-2 .. 18] of integer;
81 HistKind: array [0 .. MaxHist - 1] of integer;
82 HistNo: array [0 .. MaxHist - 1] of integer;
83 HistPos: array [0 .. MaxHist - 1] of integer;
84 HistSearchContent: array [0 .. MaxHist - 1] of shortstring;
85 procedure line(ca: TCanvas; i: integer; lit: boolean);
86 procedure Prepare(sbPos: integer = 0);
87 procedure WaterSign(x0, y0, iix: integer);
88 procedure Search(SearchString: string);
89 procedure OnScroll(var m: TMessage); message WM_VSCROLL;
90 procedure OnMouseWheel(var m: TMessage); message WM_MOUSEWHEEL;
91 procedure OnMouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
92 end;
93
94var
95 HelpDlg: THelpDlg;
96
97implementation
98
99uses
100 Directories, ClientTools, Term, Tribes, ShellAPI, Inp, Messg;
101
102{$R *.DFM}
103
104type
105 THelpLineInfo = packed record
106 Format, Picpix: Byte;
107 Link: Word;
108 end;
109
110procedure THyperText.AddLine(s: String; Format: integer; Picpix: integer;
111 LinkCategory: integer; LinkIndex: integer);
112var
113 HelpLineInfo: THelpLineInfo;
114begin
115 if LinkIndex < 0 then
116 LinkIndex := liInvalid;
117 HelpLineInfo.Format := Format;
118 HelpLineInfo.Picpix := Picpix;
119 HelpLineInfo.Link := LinkCategory shl 8 + LinkIndex;
120 AddObject(s, TObject(HelpLineInfo));
121end;
122
123procedure THyperText.LF;
124begin
125 AddLine;
126end;
127
128const
129 { text formats }
130 pkNormal = 0;
131 pkCaption = 1;
132 pkSmallIcon = 2;
133 pkBigIcon = 3;
134 pkAdvIcon = 4;
135 pkTer = 5;
136 pkBigTer = 6;
137 pkFeature = 7;
138 pkDot = 8;
139 pkNormal_Dot = 9;
140 pkDomain = 10;
141 pkSection = 11;
142 pkBigFeature = 12;
143 pkExp = 13;
144 pkAITStat = 14;
145 pkExternal = 15;
146 pkModel = 16;
147 pkNormal_64 = 17;
148 pkIllu = 18;
149 pkLogo = 19;
150 pkTerImp = 20;
151 pkRightIcon = 21;
152 pkAdvIcon_AsPreq = 22;
153 pkSmallIcon_AsPreq = 23;
154 pkSpecialIcon = 24;
155 pkGov = 25;
156
157 nSeeAlso = 14;
158 SeeAlso: array [0 .. nSeeAlso - 1] of record Kind, no, SeeKind,
159 SeeNo: integer end = ((Kind: hkImp; no: imWalls; SeeKind: hkFeature;
160 SeeNo: mcArtillery), (Kind: hkImp; no: imHydro; SeeKind: hkImp;
161 SeeNo: woHoover), (Kind: hkImp; no: imWalls; SeeKind: hkImp;
162 SeeNo: imGrWall), (Kind: hkImp; no: imHighways; SeeKind: hkAdv;
163 SeeNo: adWheel), (Kind: hkImp; no: imCathedral; SeeKind: hkImp;
164 SeeNo: woBach), (Kind: hkImp; no: imBank; SeeKind: hkImp; SeeNo: imStockEx),
165 (Kind: hkImp; no: imShipComp; SeeKind: hkImp; SeeNo: imSpacePort),
166 (Kind: hkImp; no: imShipPow; SeeKind: hkImp; SeeNo: imSpacePort),
167 (Kind: hkImp; no: imShipHab; SeeKind: hkImp; SeeNo: imSpacePort),
168 (Kind: hkFeature; no: mcSub; SeeKind: hkFeature; SeeNo: mcRadar),
169 (Kind: hkFeature; no: mcDefense; SeeKind: hkAdv; SeeNo: adSteel),
170 (Kind: hkFeature; no: mcSE; SeeKind: hkFeature; SeeNo: mcNP), (Kind: hkAdv;
171 no: adWheel; SeeKind: hkImp; SeeNo: imHighways), (Kind: hkAdv; no: adSteel;
172 SeeKind: hkFeature; SeeNo: mcDefense));
173
174 nTerrainHelp = 14;
175 TerrainHelp: array [0 .. nTerrainHelp - 1] of integer = (fGrass, fGrass + 12,
176 fPrairie, fForest, fJungle, fHills, fMountains, fSwamp, fTundra, fArctic,
177 fDesert, 3 * 12 { DeadLands } , fShore, fOcean);
178
179 nJobHelp = 8;
180 JobHelp: array [0 .. nJobHelp - 1] of integer = (jRoad, jRR, jCanal, jIrr,
181 jFarm, jMine, jFort, jBase);
182
183procedure THelpDlg.FormCreate(Sender: TObject);
184begin
185 inherited;
186 CaptionLeft := BackBtn.Left + BackBtn.Width;
187 CaptionRight := SearchBtn.Left;
188 inc(ModalFrameIndent, 29);
189 MainText := THyperText.Create;
190 SearchResult := THyperText.Create;
191 CreatePVSB(sb, Handle, 36, 551, 36 + 432);
192
193 HelpText := TStringTable.Create;
194 HelpText.LoadFromFile(LocalizedFilePath('Help\help.txt'));
195 hADVHELP := HelpText.Gethandle('ADVHELP');
196 hIMPHELP := HelpText.Gethandle('IMPHELP');
197 hFEATUREHELP := HelpText.Gethandle('FEATUREHELP');
198 hGOVHELP := HelpText.Gethandle('GOVHELP');
199 hSPECIALMODEL := HelpText.Gethandle('SPECIALMODEL');
200 hJOBHELP := HelpText.Gethandle('JOBHELP');
201
202 CaptionFont := Font.Create;
203 CaptionFont.Assign(UniFont[ftNormal]);
204 CaptionFont.Style := CaptionFont.Style + [fsItalic, fsBold];
205 InitButtons();
206
207 TopBtn.Hint := Phrases.Lookup('BTN_CONTENTS');
208 BackBtn.Hint := Phrases.Lookup('BTN_BACK');
209 SearchBtn.Hint := Phrases.Lookup('BTN_SEARCH');
210
211 ExtPic := TBitmap.Create;
212 TerrIcon := TBitmap.Create;
213 TerrIcon.PixelFormat := pf24bit;
214 TerrIcon.Width := xSizeBig;
215 TerrIcon.Height := ySizeBig;
216 SearchContent := '';
217 nHist := -1;
218end;
219
220procedure THelpDlg.ClearHistory;
221begin
222 nHist := -1;
223end;
224
225procedure THelpDlg.FormDestroy(Sender: TObject);
226begin
227 MainText.Free;
228 SearchResult.Free;
229 ExtPic.Free;
230 TerrIcon.Free;
231 HelpText.Free;
232 // CaptionFont.Free;
233end;
234
235procedure THelpDlg.CloseBtnClick(Sender: TObject);
236begin
237 Close
238end;
239
240procedure THelpDlg.OnScroll(var m: TMessage);
241begin
242 if ProcessPVSB(sb, m) then
243 begin
244 Sel := -1;
245 SmartUpdateContent(true)
246 end
247end;
248
249procedure THelpDlg.OnMouseWheel(var m: TMessage);
250begin
251 if ProcessMouseWheel(sb, m) then
252 begin
253 Sel := -1;
254 SmartUpdateContent(true);
255 PaintBox1MouseMove(nil, [], m.lParam and $FFFF - Left,
256 m.lParam shr 16 - Top);
257 end
258end;
259
260procedure THelpDlg.OnMouseLeave(var Msg: TMessage);
261begin
262 if Sel <> -1 then
263 begin
264 line(Canvas, Sel, false);
265 Sel := -1
266 end
267end;
268
269procedure THelpDlg.FormPaint(Sender: TObject);
270begin
271 inherited;
272 Canvas.Font.Assign(UniFont[ftNormal]);
273end;
274
275procedure THelpDlg.line(ca: TCanvas; i: integer; lit: boolean);
276var
277 TextColor, x, y: integer;
278 TextSize: TSize;
279 s: string;
280begin
281 s := MainText[sb.si.npos + i];
282 if s = '' then
283 exit;
284 x := x0[i];
285 y := 2 + i * 24;
286 if ca = Canvas then
287 begin
288 x := x + SideFrame;
289 y := y + WideFrame
290 end;
291 if THelpLineInfo(MainText.Objects[sb.si.npos + i]).Format
292 in [pkCaption, pkBigTer, pkRightIcon, pkBigFeature] then
293 begin
294 ca.Font.Assign(CaptionFont);
295 { ca.brush.color:=CaptionColor;
296 ca.FillRect(rect(x,i*24,x+24,i*24+24));
297 ca.brush.color:=$FFFFFF;
298 ca.FrameRect(rect(x+1,i*24+1,x+24-1,i*24+24-1));
299 ca.Brush.Style:=bsClear; }
300 BitBlt(ca.Handle, x, y - 4, 24, 24, GrExt[HGrSystem].Data.Canvas.Handle, 1,
301 146, SRCCOPY);
302 BiColorTextOut(ca, $FFFFFF, $7F007F, x + 10 - ca.Textwidth(s[1]) div 2,
303 y - 3, s[1]);
304 BiColorTextOut(ca, CaptionColor, $7F007F, x + 24, y - 3, copy(s, 2, 255));
305 ca.Font.Assign(UniFont[ftNormal]);
306 end
307 else if THelpLineInfo(MainText.Objects[sb.si.npos + i]).Format = pkSection
308 then
309 begin
310 ca.Font.Assign(CaptionFont);
311 BiColorTextOut(ca, CaptionColor, $7F007F, x, y - 3, s);
312 ca.Font.Assign(UniFont[ftNormal]);
313 end
314 else
315 begin
316 if (Kind = hkMisc) and (no = miscMain) then
317 ca.Font.Assign(CaptionFont);
318 TextColor := Colors.Canvas.Pixels[clkMisc, cliPaperText];
319 if ca = Canvas then
320 begin
321 TextSize.cx := BiColorTextWidth(ca, s);
322 TextSize.cy := ca.TextHeight(s);
323 if y + TextSize.cy >= WideFrame + InnerHeight then
324 TextSize.cy := WideFrame + InnerHeight - y;
325 FillSeamless(ca, x, y, TextSize.cx, TextSize.cy, -SideFrame,
326 sb.si.npos * 24 - WideFrame, Paper);
327 end;
328 BiColorTextOut(ca, TextColor, $7F007F, x, y, s);
329 if lit then
330 with ca do
331 begin
332 assert(ca = Canvas);
333 pen.color := TextColor;
334 moveto(x + 1, y + TextSize.cy - 2);
335 lineto(x + TextSize.cx, y + TextSize.cy - 2);
336 end;
337 if (Kind = hkMisc) and (no = miscMain) then
338 ca.Font.Assign(UniFont[ftNormal]);
339 end
340end;
341
342procedure THelpDlg.WaterSign(x0, y0, iix: integer);
343const
344 nHeaven = 28;
345 maxsum = 9 * 9 * 255 * 75 div 100;
346type
347 TLine = array [0 .. 649, 0 .. 2] of Byte;
348var
349 x, y, dx, dy, xSrc, ySrc, sum, xx: integer;
350 Heaven: array [0 .. nHeaven] of integer;
351 PaintLine, CoalLine: ^TLine;
352 ImpLine: array [-1 .. 1] of ^TLine;
353begin
354 // assume eiffel tower has free common heaven
355 for dy := 0 to nHeaven - 1 do
356 Heaven[dy] := BigImp.Canvas.Pixels[woEiffel mod 7 * xSizeBig,
357 (SystemIconLines + woEiffel div 7) * ySizeBig + dy];
358
359 xSrc := iix mod 7 * xSizeBig;
360 ySrc := (iix div 7 + 1) * ySizeBig;
361 for y := 0 to ySizeBig * 2 - 1 do
362 if (y0 + y >= 0) and (y0 + y < InnerHeight) then
363 begin
364 PaintLine := OffScreen.ScanLine[y0 + y];
365 CoalLine := Templates.ScanLine[yCoal + y];
366 for dy := -1 to 1 do
367 if ((y + dy) shr 1 >= 0) and ((y + dy) shr 1 < ySizeBig) then
368 ImpLine[dy] := BigImp.ScanLine[ySrc + (y + dy) shr 1];
369 for x := 0 to xSizeBig * 2 - 1 do
370 begin
371 sum := 0;
372 for dx := -1 to 1 do
373 begin
374 xx := xSrc + (x + dx) shr 1;
375 for dy := -1 to 1 do
376 if ((y + dy) shr 1 < 0) or ((y + dy) shr 1 >= ySizeBig) or
377 ((x + dx) shr 1 < 0) or ((x + dx) shr 1 >= xSizeBig) or
378 ((y + dy) shr 1 < nHeaven) and
379 (ImpLine[dy, xx, 0] shl 16 + ImpLine[dy, xx, 1] shl 8 +
380 ImpLine[dy, xx, 2] = Heaven[(y + dy) shr 1]) then
381 sum := sum + 9 * 255
382 else
383 sum := sum + ImpLine[dy, xx, 0] + 5 * ImpLine[dy, xx, 1] + 3 *
384 ImpLine[dy, xx, 2];
385 end;
386 if sum < maxsum then
387 begin // no saturation
388 sum := 1 shl 22 - (maxsum - sum) * (256 - CoalLine[xCoal + x, 0] * 2);
389 PaintLine[x0 + x, 0] := PaintLine[x0 + x, 0] * sum shr 22;
390 PaintLine[x0 + x, 1] := PaintLine[x0 + x, 1] * sum shr 22;
391 PaintLine[x0 + x, 2] := PaintLine[x0 + x, 2] * sum shr 22;
392 end
393 end
394 end;
395end;
396
397procedure THelpDlg.OffscreenPaint;
398
399 procedure PaintTerrIcon(x, y, xSrc, ySrc: integer);
400 begin
401 Frame(OffScreen.Canvas, x - 1, y - 1, x + xSizeBig, y + ySizeBig,
402 $000000, $000000);
403 if 2 * yyt < 40 then
404 begin
405 Sprite(OffScreen, HGrTerrain, x, y, 56, 2 * yyt, xSrc, ySrc);
406 Sprite(OffScreen, HGrTerrain, x, y + 2 * yyt, 56, 40 - 2 * yyt,
407 xSrc, ySrc);
408 end
409 else
410 Sprite(OffScreen, HGrTerrain, x, y, 56, 40, xSrc, ySrc);
411 Sprite(OffScreen, HGrTerrain, x, y, xxt, yyt, xSrc + xxt, ySrc + yyt);
412 Sprite(OffScreen, HGrTerrain, x, y + yyt, xxt, 40 - yyt, xSrc + xxt, ySrc);
413 Sprite(OffScreen, HGrTerrain, x + xxt, y, 56 - xxt, yyt, xSrc, ySrc + yyt);
414 Sprite(OffScreen, HGrTerrain, x + xxt, y + yyt, 56 - xxt, 40 - yyt,
415 xSrc, ySrc);
416 end;
417
418var
419 i, j, yl, srcno, ofs, cnt, y: integer;
420 s: string;
421 HelpLineInfo: THelpLineInfo;
422begin
423 inherited;
424 CaptionColor := Colors.Canvas.Pixels[clkMisc, cliPaperCaption];
425 FillSeamless(OffScreen.Canvas, 0, 0, InnerWidth, InnerHeight, 0,
426 sb.si.npos * 24, Paper);
427 with OffScreen.Canvas do
428 begin
429 Font.Assign(UniFont[ftNormal]);
430 for i := -sb.si.npos to InnerHeight div 24 do
431 if sb.si.npos + i < MainText.Count then
432 begin
433 HelpLineInfo := THelpLineInfo(MainText.Objects[sb.si.npos + i]);
434 if HelpLineInfo.Format = pkExternal then
435 begin
436 yl := ExtPic.Height;
437 if 4 + i * 24 + yl > InnerHeight then
438 yl := InnerHeight - (4 + i * 24);
439 BitBlt(Handle, 8, 4 + i * 24, ExtPic.Width, yl, ExtPic.Canvas.Handle,
440 0, 0, SRCCOPY);
441 end
442 end;
443 for i := -2 to InnerHeight div 24 do
444 if (sb.si.npos + i >= 0) and (sb.si.npos + i < MainText.Count) then
445 begin
446 HelpLineInfo := THelpLineInfo(MainText.Objects[sb.si.npos + i]);
447 if HelpLineInfo.Link <> 0 then
448 begin
449 if (Kind = hkMisc) and (no = miscSearchResult) then
450 Sprite(OffScreen, HGrSystem, 18, 9 + i * 24, 8, 8, 90, 16)
451 else if HelpLineInfo.Format in [pkSmallIcon_AsPreq, pkAdvIcon_AsPreq]
452 then
453 Sprite(OffScreen, HGrSystem, 12, i * 24 + 5, 14, 14, 65, 20)
454 else if HelpLineInfo.Link and (hkCrossLink shl 8) <> 0 then
455 Sprite(OffScreen, HGrSystem, 12, i * 24 + 5, 14, 14, 80, 1)
456 else if not((Kind = hkMisc) and (no = miscMain)) then
457 Sprite(OffScreen, HGrSystem, 10, i * 24 + 6, 14, 14, 65, 1);
458 x0[i] := 24;
459 end
460 else
461 x0[i] := 0;
462 case HelpLineInfo.Format of
463 pkLogo:
464 begin
465 Server(sGetVersion, 0, 0, j);
466 s := Format('%d.%d.%d', [j shr 16 and $FF, j shr 8 and $FF,
467 j and $FF]);
468 PaintLogo(OffScreen.Canvas, (InnerWidth - 122) div 2, i * 24 + 1,
469 GrExt[HGrSystem].Data.Canvas.Pixels[95, 1], $000000);
470 Font.Assign(UniFont[ftSmall]);
471 BiColorTextOut(OffScreen.Canvas, $000000, $7F007F,
472 (InnerWidth - Textwidth(s)) div 2, i * 24 + 26, s);
473 Font.Assign(UniFont[ftNormal]);
474 end;
475 pkSmallIcon, pkSmallIcon_AsPreq:
476 begin
477 Frame(OffScreen.Canvas, 8 - 1 + x0[i], 2 - 1 + i * 24,
478 8 + xSizeSmall + x0[i], 2 + 20 + i * 24, $000000, $000000);
479 if HelpLineInfo.Picpix = imPalace then
480 BitBlt(OffScreen.Canvas.Handle, 8 + x0[i], 2 + i * 24,
481 xSizeSmall, ySizeSmall, SmallImp.Canvas.Handle,
482 0 * xSizeSmall, 1 * ySizeSmall, SRCCOPY)
483 else
484 BitBlt(OffScreen.Canvas.Handle, 8 + x0[i], 2 + i * 24,
485 xSizeSmall, ySizeSmall, SmallImp.Canvas.Handle,
486 HelpLineInfo.Picpix mod 7 * xSizeSmall,
487 (HelpLineInfo.Picpix + SystemIconLines * 7) div 7 *
488 ySizeSmall, SRCCOPY);
489 x0[i] := x0[i] + (8 + 8 + 36);
490 end;
491 pkBigIcon:
492 begin
493 FrameImage(OffScreen.Canvas, BigImp, x0[i] + 12, i * 24 - 7, 56,
494 40, HelpLineInfo.Picpix mod 7 * xSizeBig,
495 HelpLineInfo.Picpix div 7 * ySizeBig);
496 x0[i] := 64 + 8 + 8 + x0[i];
497 end;
498 pkSpecialIcon:
499 begin
500 case HelpLineInfo.Picpix of
501 0:
502 FrameImage(OffScreen.Canvas, GrExt[HGrSystem2].Data,
503 12 + x0[i], -7 + i * 24, 56, 40, 137, 127);
504 1:
505 begin
506 PaintTerrIcon(12 + x0[i], -7 + i * 24,
507 1 + 3 * (xxt * 2 + 1), 1 + yyt);
508 if 2 * yyt < 40 then
509 Sprite(OffScreen, HGrTerrain, 12 + x0[i], -7 + 4 + i * 24,
510 56, 2 * yyt, 1 + 3 * (xxt * 2 + 1) + xxt - 28,
511 1 + yyt + 1 * (yyt * 3 + 1))
512 else
513 Sprite(OffScreen, HGrTerrain, 12 + x0[i],
514 -7 + 4 + i * 24 - 4, 56, 40, 1 + 3 * (xxt * 2 + 1) + xxt
515 - 28, 1 + yyt + 1 * (yyt * 3 + 1) + yyt - 20);
516 end;
517 2:
518 begin
519 PaintTerrIcon(12 + x0[i], -7 + i * 24,
520 1 + 7 * (xxt * 2 + 1), 1 + yyt + 4 * (yyt * 3 + 1));
521 if 2 * yyt < 40 then
522 Sprite(OffScreen, HGrTerrain, 12 + x0[i], -7 + 4 + i * 24,
523 56, 32, 1 + 4 * (xxt * 2 + 1) + xxt - 28,
524 1 + yyt + 12 * (yyt * 3 + 1) + yyt - 16)
525 else
526 Sprite(OffScreen, HGrTerrain, 12 + x0[i], -7 + 4 + i * 24,
527 56, 32, 1 + 4 * (xxt * 2 + 1) + xxt - 28,
528 1 + yyt + 12 * (yyt * 3 + 1) + yyt - 16)
529 end;
530 end;
531 x0[i] := 64 + 8 + 8 + x0[i];
532 end;
533 pkDomain:
534 begin
535 Frame(OffScreen.Canvas, 8 - 1 + x0[i], 2 - 1 + i * 24,
536 8 + 36 + x0[i], 2 + 20 + i * 24, $000000, $000000);
537 Dump(OffScreen, HGrSystem, 8 + x0[i], 2 + i * 24, 36, 20,
538 75 + HelpLineInfo.Picpix * 37, 295);
539 x0[i] := x0[i] + (8 + 8 + 36);
540 end;
541 pkAdvIcon, pkAdvIcon_AsPreq:
542 begin
543 Frame(OffScreen.Canvas, 8 - 1 + x0[i], 2 - 1 + i * 24,
544 8 + xSizeSmall + x0[i], 2 + ySizeSmall + i * 24,
545 $000000, $000000);
546 if AdvIcon[HelpLineInfo.Picpix] < 84 then
547 BitBlt(OffScreen.Canvas.Handle, 8 + x0[i], 2 + i * 24,
548 xSizeSmall, ySizeSmall, SmallImp.Canvas.Handle,
549 (AdvIcon[HelpLineInfo.Picpix] + SystemIconLines * 7) mod 7 *
550 xSizeSmall, (AdvIcon[HelpLineInfo.Picpix] + SystemIconLines *
551 7) div 7 * ySizeSmall, SRCCOPY)
552 else
553 Dump(OffScreen, HGrSystem, 8 + x0[i], 2 + i * 24, 36, 20,
554 1 + (AdvIcon[HelpLineInfo.Picpix] - 84) mod 8 * 37,
555 295 + (AdvIcon[HelpLineInfo.Picpix] - 84) div 8 * 21);
556 j := AdvValue[HelpLineInfo.Picpix] div 1000;
557 BitBlt(Handle, x0[i] + 4, 4 + i * 24, 14, 14,
558 GrExt[HGrSystem].Mask.Canvas.Handle, 127 + j * 15, 85, SRCAND);
559 Sprite(OffScreen, HGrSystem, x0[i] + 3, 3 + i * 24, 14, 14,
560 127 + j * 15, 85);
561 x0[i] := x0[i] + (8 + 8 + 36);
562 end;
563 pkRightIcon:
564 begin
565 if Imp[HelpLineInfo.Picpix].Kind <> ikWonder then
566 ImpImage(OffScreen.Canvas, InnerWidth - (40 + xSizeBig), i * 24,
567 HelpLineInfo.Picpix, gDespotism)
568 else
569 WaterSign(InnerWidth - (40 + 2 * xSizeBig), i * 24 - 8,
570 HelpLineInfo.Picpix + 7);
571 x0[i] := x0[i] + 8;
572 end;
573 pkIllu:
574 WaterSign(8, i * 24 - 8, HelpLineInfo.Picpix);
575 pkBigFeature:
576 begin
577 cnt := 0;
578 for j := nDomains - 1 downto 0 do
579 if 1 shl j and Feature[HelpLineInfo.Picpix].Domains <> 0 then
580 begin
581 inc(cnt);
582 Dump(OffScreen, HGrSystem, InnerWidth - 38 - 38 * cnt,
583 i * 24 + 1, 36, 20, 75 + j * 37, 295);
584 Frame(OffScreen.Canvas, InnerWidth - 39 - 38 * cnt, i * 24,
585 InnerWidth - 2 - 38 * cnt, i * 24 + 21, $000000, $000000);
586 end;
587 DarkGradient(OffScreen.Canvas, InnerWidth - 38 - 38 * cnt,
588 i * 24 + 23, cnt * 38 - 2, 1);
589 ofs := InnerWidth - (39 + 7) - 19 * cnt;
590 with OffScreen.Canvas do
591 begin
592 Brush.color := $C0C0C0;
593 FrameRect(Rect(ofs, 1 + 23 + i * 24, ofs + 14,
594 15 + 23 + i * 24));
595 Brush.Style := bsClear;
596 Sprite(OffScreen, HGrSystem, ofs + 2, 3 + 23 + i * 24, 10, 10,
597 66 + HelpLineInfo.Picpix mod 11 * 11,
598 137 + HelpLineInfo.Picpix div 11 * 11);
599 end;
600 x0[i] := x0[i] + 8;
601 end;
602 pkTer, pkBigTer:
603 begin
604 if HelpLineInfo.Format = pkBigTer then
605 y := i * 24 - 3 + yyt
606 else
607 y := i * 24 + 13;
608 if HelpLineInfo.Picpix >= 3 * 12 then
609 srcno := 2 * 9 + 6
610 else if HelpLineInfo.Picpix mod 12 = fJungle then
611 srcno := 18 * 9
612 else if HelpLineInfo.Picpix mod 12 < fJungle then
613 srcno := HelpLineInfo.Picpix mod 12
614 else
615 srcno := 27 + (HelpLineInfo.Picpix mod 12 - 9) * 18;
616 if HelpLineInfo.Format = pkTer then
617 begin
618 ofs := x0[i] + 8;
619 x0[i] := 2 * xxt + 8 + ofs;
620 end
621 else
622 begin
623 ofs := InnerWidth - (2 * xxt + 38);
624 x0[i] := x0[i] + 8;
625 end;
626 if srcno >= fJungle then
627 begin
628 Sprite(OffScreen, HGrTerrain, ofs + 4, y - yyt + 2, xxt * 2 - 8,
629 yyt * 2 - 4, 5 + 2 * (xxt * 2 + 1),
630 3 + yyt + 2 * (yyt * 3 + 1));
631 Sprite(OffScreen, HGrTerrain, ofs, y - 2 * yyt, xxt * 2,
632 yyt * 3 - 2, 1 + srcno mod 9 * (xxt * 2 + 1),
633 1 + srcno div 9 * (yyt * 3 + 1));
634 end
635 else
636 Sprite(OffScreen, HGrTerrain, ofs + 4, y - yyt + 2, xxt * 2 - 8,
637 yyt * 2 - 4, 5 + srcno mod 9 * (xxt * 2 + 1),
638 3 + yyt + srcno div 9 * (yyt * 3 + 1));
639 if HelpLineInfo.Picpix >= 3 * 12 then { rare resource }
640 Sprite(OffScreen, HGrTerrain, ofs, y - 2 * yyt, xxt * 2,
641 yyt * 3, 1 + 8 * (xxt * 2 + 1),
642 1 + (HelpLineInfo.Picpix - 2 * 12) * (yyt * 3 + 1))
643 else if HelpLineInfo.Picpix >= 12 then { special tile }
644 begin
645 if HelpLineInfo.Picpix mod 12 = fJungle then
646 srcno := 17 * 9 + 8
647 else if HelpLineInfo.Picpix mod 12 < fJungle then
648 srcno := HelpLineInfo.Picpix mod 12
649 else
650 srcno := 18 + 8 + (HelpLineInfo.Picpix mod 12 - 9) * 18;
651 srcno := srcno + HelpLineInfo.Picpix div 12 * 9;
652 Sprite(OffScreen, HGrTerrain, ofs, y - 2 * yyt, xxt * 2,
653 yyt * 3, 1 + srcno mod 9 * (xxt * 2 + 1),
654 1 + srcno div 9 * (yyt * 3 + 1));
655 end;
656 end;
657 pkTerImp:
658 begin
659 ofs := 8;
660 if HelpLineInfo.Picpix = 5 then
661 begin // display mine on hills
662 Sprite(OffScreen, HGrTerrain, ofs + 4, i * 24 + 13 - yyt,
663 xxt * 2 - 8, yyt * 2 - 4, 5 + 2 * (xxt * 2 + 1),
664 3 + yyt + 2 * (yyt * 3 + 1));
665 srcno := 45
666 end
667 else
668 srcno := fPrairie; // display on prairie
669 Sprite(OffScreen, HGrTerrain, ofs + 4, i * 24 + 13 - yyt,
670 xxt * 2 - 8, yyt * 2 - 4, 5 + srcno mod 9 * (xxt * 2 + 1),
671 3 + yyt + srcno div 9 * (yyt * 3 + 1));
672 if HelpLineInfo.Picpix = 12 then { river }
673 Sprite(OffScreen, HGrTerrain, ofs, i * 24 + 11 - yyt, xxt * 2,
674 yyt * 2, 1 + 5 * (xxt * 2 + 1), 1 + yyt + 13 * (yyt * 3 + 1))
675 else if HelpLineInfo.Picpix >= 3 then { improvement 2 }
676 begin
677 if HelpLineInfo.Picpix = 6 then
678 Sprite(OffScreen, HGrTerrain, ofs, i * 24 + 11 - 2 * yyt,
679 xxt * 2, yyt * 3, 1 + 7 * (xxt * 2 + 1),
680 1 + 12 * (yyt * 3 + 1));
681 Sprite(OffScreen, HGrTerrain, ofs, i * 24 + 11 - 2 * yyt,
682 xxt * 2, yyt * 3, 1 + (HelpLineInfo.Picpix - 3) *
683 (xxt * 2 + 1), 1 + 12 * (yyt * 3 + 1))
684 end
685 else { improvement 1 }
686 begin
687 Sprite(OffScreen, HGrTerrain, ofs, i * 24 + 11 - 2 * yyt,
688 xxt * 2, yyt * 3, 1 + 2 * (xxt * 2 + 1),
689 1 + (9 + HelpLineInfo.Picpix) * (yyt * 3 + 1));
690 Sprite(OffScreen, HGrTerrain, ofs, i * 24 + 11 - 2 * yyt,
691 xxt * 2, yyt * 3, 1 + 5 * (xxt * 2 + 1),
692 1 + (9 + HelpLineInfo.Picpix) * (yyt * 3 + 1))
693 end;
694 x0[i] := x0[i] + 8;
695 end;
696 pkModel:
697 begin
698 FrameImage(OffScreen.Canvas, BigImp, x0[i] + 12, i * 24 - 7,
699 56, 40, 0, 0);
700 Sprite(OffScreen, HGrStdUnits, x0[i] + 8, i * 24 - 11, 64, 44,
701 1 + HelpLineInfo.Picpix mod 10 * 65,
702 1 + HelpLineInfo.Picpix div 10 * 49);
703 x0[i] := 64 + 8 + 8 + x0[i];
704 end;
705 pkFeature:
706 begin
707 DarkGradient(OffScreen.Canvas, x0[i] + 8 - 1,
708 7 + i * 24 - 3, 16, 1);
709 Frame(OffScreen.Canvas, x0[i] + 8, 7 + i * 24 - 2, x0[i] + 8 + 13,
710 7 + i * 24 - 2 + 13, $C0C0C0, $C0C0C0);
711 Sprite(OffScreen, HGrSystem, x0[i] + 8 + 2, 7 + i * 24, 10, 10,
712 66 + HelpLineInfo.Picpix mod 11 * 11,
713 137 + HelpLineInfo.Picpix div 11 * 11);
714 x0[i] := x0[i] + 8 + 8 + 2 + 13;
715 end;
716 pkExp:
717 begin
718 Frame(OffScreen.Canvas, 20 - 1, 8 - 4 + i * 24, 20 + 12,
719 8 + 11 + i * 24, $000000, $000000);
720 Dump(OffScreen, HGrSystem, 20, 8 - 3 + i * 24, 12, 14,
721 121 + HelpLineInfo.Picpix * 13, 28);
722 x0[i] := 20 + 8 + 11;
723 end;
724 pkAITStat:
725 begin
726 Sprite(OffScreen, HGrSystem, 20, 6 + i * 24, 14, 14,
727 1 + HelpLineInfo.Picpix * 15, 316);
728 x0[i] := 20 + 8 + 11;
729 end;
730 pkGov:
731 begin
732 Frame(OffScreen.Canvas, 8 - 1 + x0[i], 2 - 1 + i * 24,
733 8 + xSizeSmall + x0[i], 2 + 20 + i * 24, $000000, $000000);
734 BitBlt(OffScreen.Canvas.Handle, 8 + x0[i], 2 + i * 24, xSizeSmall,
735 ySizeSmall, SmallImp.Canvas.Handle, (HelpLineInfo.Picpix - 1) *
736 xSizeSmall, ySizeSmall, SRCCOPY);
737 x0[i] := x0[i] + (8 + 8 + 36);
738 end;
739 pkDot:
740 begin
741 Sprite(OffScreen, HGrSystem, x0[i] + 18, 9 + i * 24, 8,
742 8, 81, 16);
743 x0[i] := 20 + 8 + 4;
744 end;
745 pkNormal_Dot:
746 x0[i] := 20 + 8 + 4;
747 pkNormal_64:
748 x0[i] := 64 + 8 + 8;
749 else
750 x0[i] := x0[i] + 8
751 end;
752 line(OffScreen.Canvas, i, false)
753 end
754 end;
755 MarkUsedOffscreen(InnerWidth, InnerHeight + 13 + 48);
756end; { OffscreenPaint }
757
758procedure THelpDlg.Prepare(sbPos: integer = 0);
759var
760 i, j, special, Domain, Headline, TerrType, TerrSubType: integer;
761 s: string;
762 ps: pchar;
763 List: THyperText;
764 CheckSeeAlso: boolean;
765
766 procedure AddAdv(i: integer);
767 begin
768 MainText.AddLine(Phrases.Lookup('ADVANCES', i), pkAdvIcon, i,
769 hkAdv + hkCrossLink, i);
770 end;
771
772 procedure AddPreqAdv(i: integer);
773 begin
774 MainText.AddLine(Phrases.Lookup('ADVANCES', i), pkAdvIcon_AsPreq, i,
775 hkAdv + hkCrossLink, i);
776 end;
777
778 procedure AddImp(i: integer);
779 begin
780 MainText.AddLine(Phrases.Lookup('IMPROVEMENTS', i), pkSmallIcon, i,
781 hkImp + hkCrossLink, i);
782 end;
783
784 procedure AddPreqImp(i: integer);
785 begin
786 MainText.AddLine(Phrases.Lookup('IMPROVEMENTS', i), pkSmallIcon_AsPreq, i,
787 hkImp + hkCrossLink, i);
788 end;
789
790 procedure AddTer(i: integer);
791 begin
792 if MainText.Count > 1 then
793 begin
794 MainText.LF;
795 end;
796 MainText.AddLine(Phrases.Lookup('TERRAIN', i), pkTer, i, hkTer, i);
797 end;
798
799 procedure AddFeature(i: integer);
800 begin
801 MainText.AddLine(Phrases.Lookup('FEATURES', i), pkFeature, i,
802 hkFeature + hkCrossLink, i);
803 end;
804
805 procedure AddModel(i: integer);
806 var
807 pix: integer;
808 Name: string;
809 begin
810 if MainText.Count > 1 then
811 MainText.LF;
812 FindStdModelPicture(SpecialModelPictureCode[i], pix, Name);
813 MainText.AddLine(Name, pkModel, pix, hkModel + hkCrossLink, i)
814 end;
815
816 procedure AddStandardBlock(Item: string);
817 var
818 i: integer;
819 begin
820 with MainText do
821 begin
822 if Item = 'LOGO' then
823 begin
824 AddLine('', pkLogo);
825 LF;
826 end
827 else if Item = 'TECHFORMULA' then
828 begin
829 i := Difficulty;
830 if i = 0 then
831 i := 2;
832 AddLine(Format(HelpText.Lookup('TECHFORMULA'), [TechFormula_M[i],
833 TechFormula_D[i]]))
834 end
835 else if Item = 'EXPERIENCE' then
836 for i := 0 to nExp - 1 do
837 AddLine(Phrases.Lookup('EXPERIENCE', i), pkExp, i)
838 else if Item = 'MODERN' then
839 for i := 1 to 3 do
840 begin
841 LF;
842 AddLine(Phrases.Lookup('TERRAIN', 3 * 12 + i), pkTer, 3 * 12 + i);
843 end
844 else if Item = 'SAVED' then
845 AddLine(DataDir + 'Saved', pkNormal)
846 else if Item = 'AITSTAT' then
847 for i := 0 to 3 do
848 AddLine(Phrases2.Lookup('AITSTAT', i), pkAITStat, i)
849 end
850 end;
851
852 procedure DecodeItem(s: string; var Category, Index: integer);
853 var
854 i: integer;
855 begin
856 if (length(s) > 0) and (s[1] = ':') then
857 begin
858 Category := hkMisc;
859 Index := 0;
860 for i := 3 to length(s) do
861 Index := Index * 10 + ord(s[i]) - 48;
862 case s[2] of
863 'A':
864 Category := hkAdv;
865 'B':
866 Category := hkImp;
867 'T':
868 Category := hkTer;
869 'F':
870 Category := hkFeature;
871 'E':
872 Category := hkInternet;
873 'S':
874 Category := hkModel;
875 'C':
876 Index := miscCredits;
877 'J':
878 Index := miscJobList;
879 'G':
880 Index := miscGovList;
881 end;
882 if (Category <> hkMisc) and (Index = 0) then
883 Index := 200;
884 end
885 else
886 begin
887 Category := hkText;
888 Index := HelpText.Gethandle(copy(s, 1, 255));
889 end;
890 end;
891
892 procedure AddText(s: string);
893 var
894 i, p, l, ofs, CurrentFormat, FollowFormat, Picpix, LinkCategory, LinkIndex,
895 RightMargin: integer;
896 Name: string;
897 begin
898 RightMargin := InnerWidth - 16 - GetSystemMetrics(SM_CXVSCROLL);
899 FollowFormat := pkNormal;
900 while s <> '' do
901 begin
902 Picpix := 0;
903 LinkCategory := 0;
904 LinkIndex := 0;
905 if s[1] = '$' then
906 begin // window caption
907 p := 1;
908 repeat
909 inc(p)
910 until (p > length(s)) or (s[p] = '\');
911 Caption := copy(s, 2, p - 2);
912 Delete(s, 1, p);
913 end
914 else if s[1] = '&' then
915 begin // standard block
916 p := 1;
917 repeat
918 inc(p)
919 until (p > length(s)) or (s[p] = '\');
920 AddStandardBlock(copy(s, 2, p - 2));
921 Delete(s, 1, p);
922 end
923 else if s[1] = '@' then
924 begin // image
925 if (length(s) >= 2) and (s[2] = '@') then
926 begin // generate from icon
927 Picpix := 0;
928 p := 3;
929 while (p <= length(s)) and (s[p] <> '\') do
930 begin
931 Picpix := Picpix * 10 + ord(s[p]) - 48;
932 inc(p)
933 end;
934 if (Picpix < 0) or (Picpix >= nImp) then
935 Picpix := 0;
936 MainText.AddLine('', pkIllu, Picpix);
937 MainText.LF;
938 MainText.LF;
939 end
940 else
941 begin // external image
942 p := 1;
943 repeat
944 inc(p)
945 until (p > length(s)) or (s[p] = '\');
946 if LoadLocalizedGraphicFile(ExtPic, 'Help\' + copy(s, 2, p - 2)) then
947 begin
948 MainText.AddLine('', pkExternal);
949 for i := 0 to (ExtPic.Height - 12) div 24 do
950 MainText.LF;
951 end;
952 end;
953 Delete(s, 1, p);
954 end
955 else
956 begin
957 case s[1] of
958 ':', ';':
959 begin // link
960 p := 1;
961 repeat
962 inc(p)
963 until (p > length(s)) or (s[p] = '\') or (s[p] = ' ');
964 DecodeItem(copy(s, 2, p - 2), LinkCategory, LinkIndex);
965 CurrentFormat := 0;
966 if (LinkCategory <> hkText) and (LinkIndex < 200) then
967 // show icon
968 case LinkCategory of
969 hkAdv:
970 begin
971 CurrentFormat := pkAdvIcon;
972 Picpix := LinkIndex
973 end;
974 hkImp:
975 begin
976 CurrentFormat := pkSmallIcon;
977 Picpix := LinkIndex
978 end;
979 hkTer:
980 begin
981 CurrentFormat := pkTer;
982 Picpix := LinkIndex
983 end;
984 hkFeature:
985 begin
986 CurrentFormat := pkFeature;
987 Picpix := LinkIndex
988 end;
989 hkModel:
990 begin
991 CurrentFormat := pkModel;
992 FindStdModelPicture(SpecialModelPictureCode[LinkIndex],
993 Picpix, Name);
994 end;
995 end;
996 if s[1] = ':' then
997 LinkCategory := LinkCategory + hkCrossLink;
998 if (p > length(s)) or (s[p] = ' ') then
999 Delete(s, 1, p)
1000 else
1001 Delete(s, 1, p - 1)
1002 end;
1003 '!': // highlited
1004 if (length(s) >= 2) and (s[2] = '!') then
1005 begin
1006 if MainText.Count > 1 then
1007 MainText.LF;
1008 FollowFormat := pkCaption;
1009 CurrentFormat := pkCaption;
1010 Delete(s, 1, 2);
1011 end
1012 else
1013 begin
1014 FollowFormat := pkSection;
1015 CurrentFormat := pkSection;
1016 Delete(s, 1, 1);
1017 end;
1018 '-':
1019 begin // list
1020 FollowFormat := pkNormal_Dot;
1021 CurrentFormat := pkDot;
1022 Delete(s, 1, 1);
1023 end;
1024 else
1025 CurrentFormat := FollowFormat;
1026 end;
1027 if FollowFormat = pkNormal_Dot then
1028 ofs := 20 + 4 + 8
1029 else
1030 ofs := 8;
1031 p := 0;
1032 repeat
1033 repeat
1034 inc(p)
1035 until (p > length(s)) or (s[p] = ' ') or (s[p] = '\');
1036 if (BiColorTextWidth(OffScreen.Canvas, copy(s, 1, p - 1)) <=
1037 RightMargin - ofs) then
1038 l := p - 1
1039 else
1040 Break;
1041 until (p >= length(s)) or (s[l + 1] = '\');
1042 MainText.AddLine(copy(s, 1, l), CurrentFormat, Picpix, LinkCategory,
1043 LinkIndex);
1044 if (l < length(s)) and (s[l + 1] = '\') then
1045 FollowFormat := pkNormal;
1046 Delete(s, 1, l + 1);
1047 end
1048 end
1049 end;
1050
1051 procedure AddItem(Item: string);
1052 begin
1053 AddText(HelpText.Lookup(Item));
1054 end;
1055
1056 procedure AddModelText(i: integer);
1057 var
1058 pix: integer;
1059 s: string;
1060 begin
1061 with MainText do
1062 begin
1063 if Count > 1 then
1064 begin
1065 LF;
1066 LF;
1067 end;
1068 FindStdModelPicture(SpecialModelPictureCode[i], pix, s);
1069 AddLine(s, pkSection);
1070 AddLine(Format(HelpText.Lookup('STRENGTH'), [SpecialModel[i].Attack,
1071 SpecialModel[i].Defense]), pkNormal_64);
1072 AddLine(Format(HelpText.Lookup('SPEED'),
1073 [MovementToString(SpecialModel[i].Speed)]), pkModel, pix);
1074 if Difficulty = 0 then
1075 AddLine(Format(HelpText.Lookup('BUILDCOST'), [SpecialModel[i].Cost]),
1076 pkNormal_64)
1077 else
1078 AddLine(Format(HelpText.Lookup('BUILDCOST'),
1079 [SpecialModel[i].Cost * BuildCostMod[Difficulty] div 12]),
1080 pkNormal_64);
1081 s := HelpText.LookupByHandle(hSPECIALMODEL, i);
1082 if (s <> '') and (s <> '*') then
1083 AddText(s);
1084 if SpecialModelPreq[i] >= 0 then
1085 AddPreqAdv(SpecialModelPreq[i])
1086 else if SpecialModelPreq[i] = preLighthouse then
1087 AddPreqImp(woLighthouse)
1088 else if SpecialModelPreq[i] = preBuilder then
1089 AddPreqImp(woPyramids)
1090 else if SpecialModelPreq[i] = preLeo then
1091 AddPreqImp(woLeo);
1092 if SpecialModelPreq[i] <> preNone then
1093 MainText[Count - 1] := Format(HelpText.Lookup('REQUIRED'),
1094 [MainText[Count - 1]]);
1095 end
1096 end;
1097
1098 procedure AddJobList;
1099 var
1100 i, JobCost: integer;
1101 begin
1102 with MainText do
1103 begin
1104 for i := 0 to nJobHelp - 1 do
1105 begin
1106 if i > 0 then
1107 begin
1108 LF;
1109 LF
1110 end;
1111 AddLine(Phrases.Lookup('JOBRESULT', JobHelp[i]), pkSection);
1112 AddLine;
1113 AddLine('', pkTerImp, i);
1114 AddLine;
1115 AddText(HelpText.LookupByHandle(hJOBHELP, i));
1116 JobCost := -1;
1117 case JobHelp[i] of
1118 jCanal:
1119 JobCost := CanalWork;
1120 jFort:
1121 JobCost := FortWork;
1122 jBase:
1123 JobCost := BaseWork;
1124 end;
1125 if JobCost >= 0 then
1126 AddText(Format(HelpText.Lookup('JOBCOST'),
1127 [MovementToString(JobCost)]))
1128 else
1129 AddText(HelpText.Lookup('JOBCOSTVAR'));
1130 if JobPreq[JobHelp[i]] <> preNone then
1131 begin
1132 AddPreqAdv(JobPreq[JobHelp[i]]);
1133 MainText[Count - 1] := Format(HelpText.Lookup('REQUIRED'),
1134 [MainText[Count - 1]]);
1135 end
1136 end;
1137 end
1138 end;
1139
1140 procedure AddGraphicCredits;
1141 var
1142 i: integer;
1143 s: string;
1144 sr: TSearchRec;
1145 List, plus: TStringList;
1146 begin
1147 List := TStringList.Create;
1148 plus := TStringList.Create;
1149 if FindFirst(HomeDir + 'Graphics\*.credits.txt', $27, sr) = 0 then
1150 repeat
1151 plus.LoadFromFile(HomeDir + 'Graphics\' + sr.Name);
1152 List.AddStrings(plus);
1153 until FindNext(sr) <> 0;
1154 FindClose(sr);
1155 plus.Free;
1156
1157 List.Sort;
1158 i := 1;
1159 while i < List.Count do
1160 if List[i] = List[i - 1] then
1161 List.Delete(i)
1162 else
1163 inc(i);
1164
1165 for i := 0 to List.Count - 1 do
1166 begin
1167 s := List[i];
1168 while BiColorTextWidth(OffScreen.Canvas, s) > InnerWidth - 16 -
1169 GetSystemMetrics(SM_CXVSCROLL) do
1170 Delete(s, length(s), 1);
1171 MainText.AddLine(s);
1172 end;
1173 List.Free;
1174 end;
1175
1176 procedure AddSoundCredits;
1177 var
1178 i: integer;
1179 s: string;
1180 List: TStringList;
1181 begin
1182 List := TStringList.Create;
1183 List.LoadFromFile(HomeDir + 'Sounds\sound.credits.txt');
1184 for i := 0 to List.Count - 1 do
1185 begin
1186 s := List[i];
1187 while BiColorTextWidth(OffScreen.Canvas, s) > InnerWidth - 16 -
1188 GetSystemMetrics(SM_CXVSCROLL) do
1189 Delete(s, length(s), 1);
1190 MainText.AddLine(s);
1191 end;
1192 List.Free;
1193 end;
1194
1195 procedure NextSection(Item: string);
1196 begin
1197 if MainText.Count > 1 then
1198 if MainText.Count = Headline + 1 then
1199 MainText.Delete(Headline)
1200 else
1201 MainText.LF;
1202 MainText.AddLine(HelpText.Lookup(Item), pkSection);
1203 Headline := MainText.Count - 1;
1204 end;
1205
1206begin { Prepare }
1207 with MainText do
1208 begin
1209 OffScreen.Canvas.Font.Assign(UniFont[ftNormal]);
1210 CheckSeeAlso := false;
1211 Clear;
1212 Headline := -1;
1213 if (no >= 200) or not(Kind in [hkAdv, hkImp, hkTer, hkFeature]) then
1214 LF;
1215 case Kind of
1216 hkText:
1217 AddText(HelpText.LookupByHandle(no));
1218 hkMisc:
1219 begin
1220 case no of
1221 miscMain:
1222 begin
1223 Caption := HelpText.Lookup('HELPTITLE_MAIN');
1224 AddLine(HelpText.Lookup('HELPTITLE_QUICKSTART'), pkSpecialIcon,
1225 0, { pkBigIcon,22, } hkText, HelpText.Gethandle('QUICK'));
1226 LF;
1227 AddLine(HelpText.Lookup('HELPTITLE_CONCEPTS'), pkBigIcon, 6,
1228 hkText, HelpText.Gethandle('CONCEPTS'));
1229 LF;
1230 AddLine(HelpText.Lookup('HELPTITLE_TERLIST'), pkSpecialIcon, 1,
1231 hkTer, 200);
1232 LF;
1233 AddLine(HelpText.Lookup('HELPTITLE_JOBLIST'), pkSpecialIcon, 2,
1234 hkMisc, miscJobList);
1235 LF;
1236 AddLine(HelpText.Lookup('HELPTITLE_TECHLIST'), pkBigIcon, 39,
1237 hkAdv, 200);
1238 LF;
1239 FindStdModelPicture(SpecialModelPictureCode[6], i, s);
1240 AddLine(HelpText.Lookup('HELPTITLE_MODELLIST'), pkModel, i,
1241 hkModel, 0);
1242 LF;
1243 AddLine(HelpText.Lookup('HELPTITLE_FEATURELIST'), pkBigIcon, 28,
1244 hkFeature, 200);
1245 LF;
1246 AddLine(HelpText.Lookup('HELPTITLE_IMPLIST'), pkBigIcon,
1247 7 * SystemIconLines + imCourt, hkImp, 200);
1248 LF;
1249 AddLine(HelpText.Lookup('HELPTITLE_UNIQUELIST'), pkBigIcon,
1250 7 * SystemIconLines + imStockEx, hkImp, 201);
1251 LF;
1252 AddLine(HelpText.Lookup('HELPTITLE_WONDERLIST'), pkBigIcon,
1253 7 * SystemIconLines, hkImp, 202);
1254 LF;
1255 AddLine(HelpText.Lookup('HELPTITLE_GOVLIST'), pkBigIcon,
1256 gDemocracy + 6, hkMisc, miscGovList);
1257 LF;
1258 AddLine(HelpText.Lookup('HELPTITLE_KEYS'), pkBigIcon, 2, hkText,
1259 HelpText.Gethandle('HOTKEYS'));
1260 LF;
1261 AddLine(HelpText.Lookup('HELPTITLE_ABOUT'), pkBigIcon, 1,
1262 hkText, HelpText.Gethandle('ABOUT'));
1263 LF;
1264 AddLine(HelpText.Lookup('HELPTITLE_CREDITS'), pkBigIcon, 22,
1265 hkMisc, miscCredits);
1266 end;
1267 miscCredits:
1268 begin
1269 AddItem('CREDITS');
1270 LF;
1271 AddGraphicCredits;
1272 NextSection('CRED_CAPSOUND');
1273 AddSoundCredits;
1274 NextSection('CRED_CAPAI');
1275 Server(sGetAICredits, 0, 0, ps);
1276 AddText(ps);
1277 NextSection('CRED_CAPLANG');
1278 AddItem('AUTHOR');
1279 end;
1280 miscJobList:
1281 begin
1282 Caption := HelpText.Lookup('HELPTITLE_JOBLIST');
1283 AddJobList;
1284 LF;
1285 AddItem('TERIMPEXCLUDE');
1286 LF;
1287 AddItem('TERIMPCITY');
1288 end;
1289 miscGovList:
1290 begin
1291 Caption := HelpText.Lookup('HELPTITLE_GOVLIST');
1292 for i := 1 to nGov do
1293 begin
1294 AddLine(Phrases.Lookup('GOVERNMENT', i mod nGov), pkSection);
1295 LF;
1296 if i = nGov then
1297 AddLine('', pkBigIcon, 7 * SystemIconLines + imPalace)
1298 else
1299 AddLine('', pkBigIcon, i + 6);
1300 LF;
1301 AddText(HelpText.LookupByHandle(hGOVHELP, i mod nGov));
1302 if i mod nGov >= 2 then
1303 begin
1304 AddPreqAdv(GovPreq[i mod nGov]);
1305 MainText[Count - 1] := Format(HelpText.Lookup('REQUIRED'),
1306 [MainText[Count - 1]]);
1307 end;
1308 if i < nGov then
1309 begin
1310 LF;
1311 LF;
1312 end
1313 end
1314 end;
1315 miscSearchResult:
1316 begin
1317 Caption := HelpText.Lookup('HELPTITLE_SEARCHRESULTS');
1318 AddText(Format(HelpText.Lookup('MATCHES'), [SearchContent]));
1319 MainText.AddStrings(SearchResult);
1320 end
1321 end; // case no
1322 end;
1323
1324 hkAdv:
1325 if no = 200 then
1326 begin // complete advance list
1327 Caption := HelpText.Lookup('HELPTITLE_TECHLIST');
1328 List := THyperText.Create;
1329 for j := 0 to 3 do
1330 begin
1331 if j > 0 then
1332 begin
1333 LF;
1334 LF;
1335 end;
1336 AddLine(HelpText.Lookup('TECHAGE', j), pkSection);
1337 if j = 1 then
1338 AddLine(Phrases.Lookup('ADVANCES', adScience) + ' ' +
1339 HelpText.Lookup('BASETECH'), pkAdvIcon, adScience, hkAdv,
1340 adScience);
1341 if j = 2 then
1342 AddLine(Phrases.Lookup('ADVANCES', adMassProduction) + ' ' +
1343 HelpText.Lookup('BASETECH'), pkAdvIcon, adMassProduction, hkAdv,
1344 adMassProduction);
1345 List.Clear;
1346 for i := 0 to nAdv - 1 do
1347 if (i <> adScience) and (i <> adMassProduction) and
1348 (AdvValue[i] div 1000 = j) then
1349 List.AddLine(Phrases.Lookup('ADVANCES', i), pkAdvIcon, i,
1350 hkAdv, i);
1351 List.Sort;
1352 AddStrings(List);
1353 end;
1354 List.Free
1355 end
1356 else // single advance
1357 begin
1358 Caption := Phrases.Lookup('ADVANCES', no);
1359 LF;
1360 AddLine(Phrases.Lookup('ADVANCES', no), pkCaption);
1361 if no in FutureTech then
1362 begin
1363 AddLine(HelpText.Lookup('HELPSPEC_FUTURE'));
1364 LF;
1365 if no = futResearchTechnology then
1366 AddItem('FUTURETECHHELP100')
1367 else
1368 AddItem('FUTURETECHHELP25');
1369 end
1370 else
1371 AddLine(HelpText.Lookup('HELPSPEC_ADV'));
1372 if AdvPreq[no, 2] <> preNone then
1373 NextSection('PREREQALT')
1374 else
1375 NextSection('PREREQ');
1376 for i := 0 to 2 do
1377 if AdvPreq[no, i] <> preNone then
1378 AddPreqAdv(AdvPreq[no, i]);
1379 NextSection('GOVALLOW');
1380 for i := 2 to nGov - 1 do
1381 if GovPreq[i] = no then
1382 AddLine(Phrases.Lookup('GOVERNMENT', i), pkGov, i,
1383 hkMisc + hkCrossLink, miscGovList);
1384 NextSection('BUILDALLOW');
1385 for i := 0 to 27 do
1386 if Imp[i].Preq = no then
1387 AddImp(i);
1388 for i := 28 to nImp - 1 do
1389 if (Imp[i].Preq = no) and (Imp[i].Kind <> ikCommon) then
1390 AddImp(i);
1391 for i := 28 to nImp - 1 do
1392 if (Imp[i].Preq = no) and (Imp[i].Kind = ikCommon) then
1393 AddImp(i);
1394 NextSection('MODELALLOW');
1395 for i := 0 to nSpecialModel - 1 do
1396 if SpecialModelPreq[i] = no then
1397 AddModel(i);
1398 NextSection('FEATALLOW');
1399 for i := 0 to nFeature - 1 do
1400 if Feature[i].Preq = no then
1401 AddFeature(i);
1402 NextSection('FOLLOWADV');
1403 for i := 0 to nAdv - 1 do
1404 if (AdvPreq[i, 0] = no) or (AdvPreq[i, 1] = no) or
1405 (AdvPreq[i, 2] = no) then
1406 AddAdv(i);
1407 NextSection('UPGRADEALLOW');
1408 for Domain := 0 to nDomains - 1 do
1409 for i := 1 to nUpgrade - 1 do
1410 if upgrade[Domain, i].Preq = no then
1411 begin
1412 if upgrade[Domain, i].Strength > 0 then
1413 AddLine(Format(HelpText.Lookup('STRENGTHUP'),
1414 [Phrases.Lookup('DOMAIN', Domain), upgrade[Domain,
1415 i].Strength]), pkDomain, Domain);
1416 if upgrade[Domain, i].Trans > 0 then
1417 AddLine(Format(HelpText.Lookup('TRANSUP'),
1418 [Phrases.Lookup('DOMAIN', Domain), upgrade[Domain, i].Trans]
1419 ), pkDomain, Domain);
1420 if no in FutureTech then
1421 AddLine(Format(HelpText.Lookup('COSTUP'),
1422 [upgrade[Domain, i].Cost]), pkNormal_Dot)
1423 else
1424 AddLine(Format(HelpText.Lookup('COSTMIN'),
1425 [upgrade[Domain, i].Cost]), pkNormal_Dot)
1426 end;
1427 NextSection('EXPIRATION');
1428 for i := 0 to 27 do
1429 if (Imp[i].Preq <> preNA) and (Imp[i].Expiration = no) then
1430 AddImp(i);
1431 NextSection('ADVEFFECT');
1432 s := HelpText.LookupByHandle(hADVHELP, no);
1433 if s <> '*' then
1434 AddText(s);
1435 NextSection('SEEALSO');
1436 CheckSeeAlso := true
1437 end;
1438
1439 hkImp:
1440 if no = 200 then
1441 begin // complete city improvement list
1442 Caption := HelpText.Lookup('HELPTITLE_IMPLIST');
1443 // AddLine(HelpText.Lookup('HELPTITLE_IMPLIST'),pkSection);
1444 List := THyperText.Create;
1445 for i := 28 to nImp - 1 do
1446 if (i <> imTrGoods) and (Imp[i].Preq <> preNA) and
1447 (Imp[i].Kind = ikCommon) then
1448 List.AddLine(Phrases.Lookup('IMPROVEMENTS', i), pkSmallIcon,
1449 i, hkImp, i);
1450 List.Sort;
1451 AddStrings(List);
1452 List.Free
1453 end
1454 else if no = 201 then
1455 begin // complete nat. project list
1456 Caption := HelpText.Lookup('HELPTITLE_UNIQUELIST');
1457 // AddLine(HelpText.Lookup('HELPTITLE_UNIQUELIST'),pkSection);
1458 for i := 28 to nImp - 1 do
1459 if (Imp[i].Preq <> preNA) and
1460 ((Imp[i].Kind = ikNatLocal) or (Imp[i].Kind = ikNatGlobal)) then
1461 AddLine(Phrases.Lookup('IMPROVEMENTS', i), pkSmallIcon, i,
1462 hkImp, i);
1463 { LF;
1464 LF;
1465 AddLine(HelpText.Lookup('HELPTITLE_SHIPPARTLIST'),pkSection);
1466 for i:=28 to nImp-1 do
1467 if (Imp[i].Preq<>preNA) and (Imp[i].Kind=ikShipPart) then
1468 AddLine(Phrases.Lookup('IMPROVEMENTS',i),pkSmallIcon,i,hkImp,i); }
1469 end
1470 else if no = 202 then
1471 begin // complete wonder list
1472 Caption := HelpText.Lookup('HELPTITLE_WONDERLIST');
1473 // AddLine(HelpText.Lookup('HELPTITLE_WONDERLIST'),pkSection);
1474 for i := 0 to 27 do
1475 if Imp[i].Preq <> preNA then
1476 AddLine(Phrases.Lookup('IMPROVEMENTS', i), pkSmallIcon, i,
1477 hkImp, i);
1478 end
1479 else
1480 begin // single building
1481 Caption := Phrases.Lookup('IMPROVEMENTS', no);
1482 LF;
1483 AddLine(Phrases.Lookup('IMPROVEMENTS', no), pkRightIcon, no);
1484 case Imp[no].Kind of
1485 ikWonder:
1486 AddLine(HelpText.Lookup('HELPSPEC_WONDER'));
1487 ikCommon:
1488 AddLine(HelpText.Lookup('HELPSPEC_IMP'));
1489 ikShipPart:
1490 AddLine(HelpText.Lookup('HELPSPEC_SHIPPART'));
1491 else
1492 AddLine(HelpText.Lookup('HELPSPEC_NAT'))
1493 end;
1494 if Imp[no].Kind <> ikShipPart then
1495 begin
1496 NextSection('EFFECT');
1497 AddText(HelpText.LookupByHandle(hIMPHELP, no));
1498 end;
1499 if no = woSun then
1500 begin
1501 AddFeature(mcFirst);
1502 AddFeature(mcWill);
1503 AddFeature(mcAcademy);
1504 end;
1505 if (no < 28) and not Phrases2FallenBackToEnglish then
1506 begin
1507 LF;
1508 if Imp[no].Expiration >= 0 then
1509 AddText(Phrases2.Lookup('HELP_WONDERMORALE1'))
1510 else
1511 AddText(Phrases2.Lookup('HELP_WONDERMORALE2'));
1512 end;
1513 if Imp[no].Preq <> preNone then
1514 begin
1515 NextSection('PREREQ');
1516 AddPreqAdv(Imp[no].Preq);
1517 end;
1518 NextSection('COSTS');
1519 if Difficulty = 0 then
1520 s := Format(HelpText.Lookup('BUILDCOST'), [Imp[no].Cost])
1521 else
1522 s := Format(HelpText.Lookup('BUILDCOST'),
1523 [Imp[no].Cost * BuildCostMod[Difficulty] div 12]);
1524 AddLine(s);
1525 if Imp[no].Maint > 0 then
1526 AddLine(Format(HelpText.Lookup('MAINTCOST'), [Imp[no].Maint]));
1527 j := 0;
1528 for i := 0 to nImpReplacement - 1 do
1529 if ImpReplacement[i].NewImp = no then
1530 begin
1531 if j = 0 then
1532 begin
1533 NextSection('REPLACE');
1534 AddItem('REPLACETEXT');
1535 j := 1
1536 end;
1537 AddImp(ImpReplacement[i].OldImp);
1538 end;
1539 if Imp[no].Kind = ikShipPart then
1540 begin
1541 LF;
1542 if no = imShipComp then
1543 i := 1
1544 else if no = imShipPow then
1545 i := 2
1546 else { if no=imShipHab then }
1547 i := 3;
1548 AddLine(Format(HelpText.Lookup('RAREREQUIRED'),
1549 [Phrases.Lookup('TERRAIN', 3 * 12 + i)]), pkTer, 3 * 12 + i);
1550 end;
1551 if (no < 28) and (Imp[no].Expiration >= 0) then
1552 begin
1553 NextSection('EXPIRATION');
1554 s := Format(HelpText.Lookup('EXPWITH'),
1555 [Phrases.Lookup('ADVANCES', Imp[no].Expiration)]);
1556 if no = woPyramids then
1557 s := s + ' ' + HelpText.Lookup('EXPSLAVE');
1558 AddText(s);
1559 end;
1560 NextSection('SEEALSO');
1561 if (no < 28) and (Imp[no].Expiration >= 0) then
1562 AddImp(woEiffel);
1563 for i := 0 to nImpReplacement - 1 do
1564 if ImpReplacement[i].OldImp = no then
1565 AddImp(ImpReplacement[i].NewImp);
1566 if no = imSupermarket then
1567 AddLine(HelpText.Lookup('HELPTITLE_JOBLIST'), pkNormal, 0,
1568 hkMisc + hkCrossLink, miscJobList);
1569 CheckSeeAlso := true
1570 end;
1571
1572 hkTer:
1573 if no = 200 then
1574 begin // complete terrain type list
1575 Caption := HelpText.Lookup('HELPTITLE_TERLIST');
1576 // AddLine(HelpText.Lookup('HELPTITLE_TERLIST'),pkSection);
1577 for i := 0 to nTerrainHelp - 1 do
1578 AddTer(TerrainHelp[i]);
1579 end
1580 else
1581 begin // sigle terrain type
1582 TerrType := no mod 12;
1583 if TerrType = fJungle then
1584 TerrType := fForest;
1585 TerrSubType := no div 12;
1586 if no = 3 * 12 then
1587 begin
1588 TerrType := fDesert;
1589 TerrSubType := 0
1590 end;
1591 with Terrain[TerrType] do
1592 begin
1593 Caption := Phrases.Lookup('TERRAIN', no);
1594 LF;
1595 AddLine(Phrases.Lookup('TERRAIN', no), pkBigTer, no);
1596 AddLine(HelpText.Lookup('HELPSPEC_TER'));
1597 LF;
1598 if (ProdRes[TerrSubType] > 0) or (MineEff > 0) then
1599 AddLine(Format(HelpText.Lookup('RESPROD'),
1600 [ProdRes[TerrSubType]]));
1601 if (no < 3 * 12) and (MineEff > 0) then
1602 MainText[Count - 1] := MainText[Count - 1] + ' ' +
1603 Format(HelpText.Lookup('MOREMINE'), [MineEff]);
1604 if (FoodRes[TerrSubType] > 0) or (IrrEff > 0) then
1605 AddLine(Format(HelpText.Lookup('RESFOOD'),
1606 [FoodRes[TerrSubType]]));
1607 if (no < 3 * 12) and (IrrEff > 0) then
1608 MainText[Count - 1] := MainText[Count - 1] + ' ' +
1609 Format(HelpText.Lookup('MOREIRR'), [IrrEff]);
1610 if TradeRes[TerrSubType] > 0 then
1611 AddLine(Format(HelpText.Lookup('RESTRADE'),
1612 [TradeRes[TerrSubType]]));
1613 if Defense > 4 then
1614 AddLine(Format(HelpText.Lookup('DEFBONUS'),
1615 [(Defense - 4) * 25]));
1616 if (TerrType >= fGrass) and (TerrType <> fMountains) then
1617 if MoveCost = 2 then
1618 AddLine(HelpText.Lookup('MOVEHEAVY'))
1619 else
1620 AddLine(HelpText.Lookup('MOVEPLAIN'));
1621 if no = 3 * 12 then
1622 begin
1623 LF;
1624 AddText(HelpText.Lookup('DEADLANDS'));
1625 end;
1626 if (TerrType = fDesert) and (no <> fDesert + 12) then
1627 begin
1628 LF;
1629 AddText(Format(HelpText.Lookup('HOSTILE'), [DesertThurst]));
1630 end;
1631 if TerrType = fArctic then
1632 begin
1633 LF;
1634 AddText(Format(HelpText.Lookup('HOSTILE'), [ArcticThurst]));
1635 end;
1636 if (no < 3 * 12) and (TransTerrain >= 0) then
1637 begin
1638 LF;
1639 i := TransTerrain;
1640 if (TerrType <> fGrass) and (i <> fGrass) then
1641 i := i + TerrSubType * 12;
1642 // trafo to same special resource group
1643 AddLine(Format(HelpText.Lookup('TRAFO'),
1644 [Phrases.Lookup('TERRAIN', i)]), pkTer, i,
1645 hkTer + hkCrossLink, i);
1646 if no = fSwamp + 12 then
1647 begin
1648 LF;
1649 AddLine(Format(HelpText.Lookup('TRAFO'),
1650 [Phrases.Lookup('TERRAIN', TransTerrain + 24)]), pkTer,
1651 TransTerrain + 24, hkTer + hkCrossLink, TransTerrain + 24);
1652 end
1653 else if i = fGrass then
1654 begin
1655 LF;
1656 AddLine(Format(HelpText.Lookup('TRAFO'),
1657 [Phrases.Lookup('TERRAIN', fGrass + 12)]), pkTer, fGrass + 12,
1658 hkTer + hkCrossLink, fGrass + 12);
1659 end
1660 end;
1661 NextSection('SPECIAL');
1662 if no = 3 * 12 then
1663 begin
1664 LF;
1665 for special := 1 to 3 do
1666 begin
1667 if special > 1 then
1668 LF;
1669 AddLine(Phrases.Lookup('TERRAIN', 3 * 12 + special), pkTer,
1670 3 * 12 + special);
1671 end
1672 end
1673 else if (no < 12) and (no <> fGrass) and (no <> fOcean) then
1674 begin
1675 LF;
1676 for special := 1 to 2 do
1677 if (no <> fArctic) and (no <> fSwamp) or (special < 2) then
1678 begin
1679 if special > 1 then
1680 LF;
1681 AddLine(Phrases.Lookup('TERRAIN', no + special * 12), pkTer,
1682 no + special * 12);
1683 i := FoodRes[special] - FoodRes[0];
1684 if i <> 0 then
1685 MainText[Count - 1] := MainText[Count - 1] +
1686 Format(HelpText.Lookup('SPECIALFOOD'), [i]);
1687 i := ProdRes[special] - ProdRes[0];
1688 if i <> 0 then
1689 MainText[Count - 1] := MainText[Count - 1] +
1690 Format(HelpText.Lookup('SPECIALPROD'), [i]);
1691 i := TradeRes[special] - TradeRes[0];
1692 if i <> 0 then
1693 MainText[Count - 1] := MainText[Count - 1] +
1694 Format(HelpText.Lookup('SPECIALTRADE'), [i]);
1695 end;
1696 end;
1697 if no = 3 * 12 then
1698 begin
1699 LF;
1700 AddText(HelpText.Lookup('RARE'));
1701 end;
1702 if (no < 3 * 12) and (TerrType in [fDesert, fArctic]) then
1703 begin
1704 NextSection('SEEALSO');
1705 AddImp(woGardens);
1706 CheckSeeAlso := true
1707 end
1708 end
1709 end;
1710
1711 hkFeature:
1712 if no = 200 then
1713 begin // complete feature list
1714 Caption := HelpText.Lookup('HELPTITLE_FEATURELIST');
1715 List := THyperText.Create;
1716 for special := 0 to 2 do
1717 begin
1718 if special > 0 then
1719 begin
1720 LF;
1721 LF
1722 end;
1723 case special of
1724 0:
1725 AddLine(HelpText.Lookup('HELPTITLE_FEATURE1LIST'), pkSection);
1726 1:
1727 AddLine(HelpText.Lookup('HELPTITLE_FEATURE2LIST'), pkSection);
1728 2:
1729 AddLine(HelpText.Lookup('HELPTITLE_FEATURE3LIST'), pkSection);
1730 end;
1731 List.Clear;
1732 for i := 0 to nFeature - 1 do
1733 if Feature[i].Preq <> preNA then
1734 begin
1735 if i < mcFirstNonCap then
1736 j := 0
1737 else if i in AutoFeature then
1738 j := 2
1739 else
1740 j := 1;
1741 if j = special then
1742 List.AddLine(Phrases.Lookup('FEATURES', i), pkFeature, i,
1743 hkFeature, i);
1744 end;
1745 List.Sort;
1746 AddStrings(List);
1747 end;
1748 List.Free
1749 end
1750 else
1751 begin // single feature
1752 Caption := Phrases.Lookup('FEATURES', no);
1753 LF;
1754 AddLine(Phrases.Lookup('FEATURES', no), pkBigFeature, no);
1755 if no < mcFirstNonCap then
1756 AddLine(HelpText.Lookup('HELPSPEC_CAP'))
1757 else if no in AutoFeature then
1758 AddLine(HelpText.Lookup('HELPSPEC_STANDARD'))
1759 else
1760 AddLine(HelpText.Lookup('HELPSPEC_FEATURE'));
1761 NextSection('EFFECT');
1762 AddText(HelpText.LookupByHandle(hFEATUREHELP, no));
1763 if (Feature[no].Weight <> 0) or (Feature[no].Cost <> 0) then
1764 begin
1765 NextSection('COSTS');
1766 s := IntToStr(Feature[no].Cost);
1767 if Feature[no].Cost >= 0 then
1768 s := '+' + s;
1769 AddLine(Format(HelpText.Lookup('COSTBASE'), [s]));
1770 if Feature[no].Weight > 0 then
1771 begin
1772 AddLine(Format(HelpText.Lookup('WEIGHT'),
1773 ['+' + IntToStr(Feature[no].Weight)]));
1774 if no = mcDefense then
1775 AddLine(Format(HelpText.Lookup('WEIGHT'), ['+2']),
1776 pkDomain, dGround);
1777 end
1778 end;
1779 if Feature[no].Preq <> preNone then
1780 begin
1781 LF;
1782 if Feature[no].Preq = preSun then
1783 AddPreqImp(woSun) // sun tsu feature
1784 else
1785 AddPreqAdv(Feature[no].Preq);
1786 MainText[Count - 1] := Format(HelpText.Lookup('REQUIRED'),
1787 [MainText[Count - 1]]);
1788 end;
1789 NextSection('SEEALSO');
1790 CheckSeeAlso := true
1791 end;
1792
1793 hkModel:
1794 begin
1795 Caption := HelpText.Lookup('HELPTITLE_MODELLIST');
1796 for i := 0 to nSpecialModel - 1 do
1797 if i <> 2 then
1798 AddModelText(i);
1799 LF;
1800 AddItem('MODELNOTE');
1801 end;
1802
1803 end;
1804 if CheckSeeAlso then
1805 for i := 0 to nSeeAlso - 1 do
1806 if (SeeAlso[i].Kind = Kind) and (SeeAlso[i].no = no) then
1807 case SeeAlso[i].SeeKind of
1808 hkImp:
1809 AddImp(SeeAlso[i].SeeNo);
1810 hkAdv:
1811 AddAdv(SeeAlso[i].SeeNo);
1812 hkFeature:
1813 AddFeature(SeeAlso[i].SeeNo);
1814 end;
1815 if (Headline >= 0) and (Count = Headline + 1) then
1816 Delete(Headline)
1817 else
1818 LF;
1819
1820 InitPVSB(sb, Count - 1, InnerHeight div 24);
1821 if sbPos <> 0 then
1822 begin
1823 sb.si.npos := sbPos;
1824 sb.si.FMask := SIF_POS;
1825 SetScrollInfo(sb.h, SB_CTL, sb.si, true);
1826 end;
1827 BackBtn.Visible := nHist > 0;
1828 TopBtn.Visible := (nHist > 0) or (Kind <> hkMisc) or (no <> miscMain);
1829 Sel := -1;
1830 end; // with MainText
1831end; { Prepare }
1832
1833procedure THelpDlg.ShowNewContent(NewMode, Category, Index: integer);
1834begin
1835 if (Category <> Kind) or (Index <> no) or (Category = hkMisc) and
1836 (Index = miscSearchResult) then
1837 begin
1838 if nHist = MaxHist then
1839 begin
1840 move(HistKind[2], HistKind[1], 4 * (nHist - 2));
1841 move(HistNo[2], HistNo[1], 4 * (nHist - 2));
1842 move(HistPos[2], HistPos[1], 4 * (nHist - 2));
1843 move(HistSearchContent[2], HistSearchContent[1],
1844 sizeof(shortstring) * (nHist - 2));
1845 end
1846 else
1847 inc(nHist);
1848 if nHist > 0 then
1849 begin
1850 HistKind[nHist - 1] := Kind;
1851 HistNo[nHist - 1] := no;
1852 HistPos[nHist - 1] := sb.si.npos;
1853 HistSearchContent[nHist - 1] := SearchContent
1854 end
1855 end;
1856 Kind := Category;
1857 no := Index;
1858 SearchContent := NewSearchContent;
1859 Prepare;
1860 OffscreenPaint;
1861 inherited ShowNewContent(NewMode);
1862end;
1863
1864procedure THelpDlg.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
1865 x, y: integer);
1866var
1867 i0, Sel0: integer;
1868begin
1869 y := y - WideFrame;
1870 i0 := sb.si.npos;
1871 Sel0 := Sel;
1872 if (x >= SideFrame) and (x < SideFrame + InnerWidth) and (y >= 0) and
1873 (y < InnerHeight) and (y mod 24 >= 8) then
1874 Sel := y div 24
1875 else
1876 Sel := -1;
1877 if (Sel + i0 >= MainText.Count) or (Sel >= 0) and
1878 (THelpLineInfo(MainText.Objects[Sel + i0]).Link = 0) then
1879 Sel := -1;
1880 if Sel <> Sel0 then
1881 begin
1882 if Sel0 <> -1 then
1883 line(Canvas, Sel0, false);
1884 if Sel <> -1 then
1885 line(Canvas, Sel, true)
1886 end
1887end;
1888
1889procedure THelpDlg.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
1890 Shift: TShiftState; x, y: integer);
1891begin
1892 if Sel >= 0 then
1893 with THelpLineInfo(MainText.Objects[Sel + sb.si.npos]) do
1894 if Link shr 8 and $3F = hkInternet then
1895 case Link and $FF of
1896 1:
1897 ShellExecute(Handle, 'open',
1898 pchar(HomeDir + 'AI Template\AI development manual.html'), '', '',
1899 SW_SHOWNORMAL);
1900 2:
1901 ShellExecute(Handle, 'open', 'http://c-evo.org', '', '',
1902 SW_SHOWNORMAL);
1903 3:
1904 ShellExecute(Handle, 'open', 'http://c-evo.org/_sg/contact', '', '',
1905 SW_SHOWNORMAL);
1906 end
1907 else
1908 begin
1909 if (Link >= $8000) and (Link and $3FFF = liInvalid) then
1910 exit; // invalid link;
1911 if Link >= $8000 then
1912 ShowNewContent(FWindowMode, hkText, Link and $3FFF)
1913 else
1914 ShowNewContent(FWindowMode, Link shr 8 and $3F, Link and $FF);
1915 end
1916end;
1917
1918procedure THelpDlg.BackBtnClick(Sender: TObject);
1919begin
1920 if nHist > 0 then
1921 begin
1922 dec(nHist);
1923 if (HistKind[nHist] = hkMisc) and (HistNo[nHist] = miscSearchResult) and
1924 (HistSearchContent[nHist] <> SearchContent) then
1925 begin
1926 SearchContent := HistSearchContent[nHist];
1927 Search(SearchContent);
1928 end;
1929 Kind := HistKind[nHist];
1930 no := HistNo[nHist];
1931 Prepare(HistPos[nHist]);
1932 OffscreenPaint;
1933 Invalidate;
1934 end
1935end;
1936
1937procedure THelpDlg.TopBtnClick(Sender: TObject);
1938begin
1939 nHist := 0;
1940 Kind := hkMisc;
1941 no := miscMain;
1942 Prepare;
1943 OffscreenPaint;
1944 Invalidate;
1945end;
1946
1947procedure THelpDlg.FormClose(Sender: TObject; var Action: TCloseAction);
1948begin
1949 ExtPic.Height := 0;
1950 inherited;
1951end;
1952
1953function THelpDlg.TextIndex(Item: string): integer;
1954begin
1955 result := HelpText.Gethandle(Item)
1956end;
1957
1958procedure THelpDlg.FormKeyDown(Sender: TObject; var Key: Word;
1959 Shift: TShiftState);
1960begin
1961 if Key = VK_F1 then // my key
1962 else
1963 inherited
1964end;
1965
1966procedure THelpDlg.SearchBtnClick(Sender: TObject);
1967begin
1968 InputDlg.Caption := Phrases.Lookup('SEARCH');
1969 InputDlg.EInput.Text := SearchContent;
1970 InputDlg.CenterToRect(BoundsRect);
1971 InputDlg.ShowModal;
1972 if (InputDlg.ModalResult = mrOK) and (length(InputDlg.EInput.Text) >= 2) then
1973 begin
1974 Search(InputDlg.EInput.Text);
1975 case SearchResult.Count of
1976 0:
1977 SimpleMessage(Format(HelpText.Lookup('NOMATCHES'),
1978 [InputDlg.EInput.Text]));
1979 1:
1980 with THelpLineInfo(SearchResult.Objects[0]) do
1981 if Link >= $8000 then
1982 ShowNewContent(FWindowMode, hkText, Link and $3FFF)
1983 else
1984 ShowNewContent(FWindowMode, Link shr 8 and $3F, Link and $FF);
1985 else
1986 begin
1987 NewSearchContent := InputDlg.EInput.Text;
1988 ShowNewContent(FWindowMode, hkMisc, miscSearchResult);
1989 end
1990 end
1991 end
1992end;
1993
1994procedure THelpDlg.Search(SearchString: string);
1995var
1996 h, i, PrevHandle, PrevIndex, p, RightMargin: integer;
1997 s: string;
1998 mADVHELP, mIMPHELP, mFEATUREHELP: set of 0 .. 255;
1999 bGOVHELP, bSPECIALMODEL, bJOBHELP: boolean;
2000begin
2001 SearchResult.Clear;
2002 mADVHELP := [];
2003 mIMPHELP := [];
2004 mFEATUREHELP := [];
2005 bGOVHELP := false;
2006 bSPECIALMODEL := false;
2007 bJOBHELP := false;
2008
2009 // search in generic reference
2010 SearchString := UpperCase(SearchString);
2011 for i := 0 to 35 + 4 do
2012 begin
2013 s := Phrases.Lookup('TERRAIN', i);
2014 if pos(SearchString, UpperCase(s)) > 0 then
2015 if i < 36 then
2016 SearchResult.AddLine(s + ' ' + HelpText.Lookup('HELPSPEC_TER'),
2017 pkNormal, 0, hkTer + hkCrossLink, i)
2018 else
2019 begin
2020 SearchResult.AddLine(Phrases.Lookup('TERRAIN', 36) + ' ' +
2021 HelpText.Lookup('HELPSPEC_TER'), pkNormal, 0,
2022 hkTer + hkCrossLink, 36);
2023 if i > 36 then
2024 SearchResult.AddLine(Phrases.Lookup('IMPROVEMENTS',
2025 imShipComp + i - 37) + ' ' + HelpText.Lookup('HELPSPEC_SHIPPART'),
2026 pkNormal, 0, hkImp + hkCrossLink, imShipComp + i - 37);
2027 Break
2028 end
2029 end;
2030 for i := 0 to nJobHelp - 1 do
2031 if pos(SearchString, UpperCase(Phrases.Lookup('JOBRESULT', JobHelp[i]))) > 0
2032 then
2033 begin
2034 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_JOBLIST'), pkNormal, 0,
2035 hkMisc + hkCrossLink, miscJobList);
2036 bJOBHELP := true;
2037 Break
2038 end;
2039 for i := 0 to nAdv - 1 do
2040 begin
2041 s := Phrases.Lookup('ADVANCES', i);
2042 if pos(SearchString, UpperCase(s)) > 0 then
2043 begin
2044 if i in FutureTech then
2045 s := s + ' ' + HelpText.Lookup('HELPSPEC_FUTURE')
2046 else
2047 s := s + ' ' + HelpText.Lookup('HELPSPEC_ADV');
2048 SearchResult.AddLine(s, pkNormal, 0, hkAdv + hkCrossLink, i);
2049 include(mADVHELP, i);
2050 end
2051 end;
2052 for i := 0 to nSpecialModel - 1 do
2053 begin
2054 FindStdModelPicture(SpecialModelPictureCode[i], h, s);
2055 if pos(SearchString, UpperCase(s)) > 0 then
2056 begin
2057 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_MODELLIST'), pkNormal, 0,
2058 hkModel + hkCrossLink, 0);
2059 bSPECIALMODEL := true;
2060 Break
2061 end;
2062 end;
2063 for i := 0 to nFeature - 1 do
2064 begin
2065 s := Phrases.Lookup('FEATURES', i);
2066 if pos(SearchString, UpperCase(s)) > 0 then
2067 begin
2068 if i < mcFirstNonCap then
2069 s := s + ' ' + HelpText.Lookup('HELPSPEC_CAP')
2070 else if i in AutoFeature then
2071 s := s + ' ' + HelpText.Lookup('HELPSPEC_STANDARD')
2072 else
2073 s := s + ' ' + HelpText.Lookup('HELPSPEC_FEATURE');
2074 SearchResult.AddLine(s, pkNormal, 0, hkFeature + hkCrossLink, i);
2075 include(mFEATUREHELP, i);
2076 end
2077 end;
2078 for i := 0 to nImp - 1 do
2079 begin
2080 s := Phrases.Lookup('IMPROVEMENTS', i);
2081 if pos(SearchString, UpperCase(s)) > 0 then
2082 begin
2083 case Imp[i].Kind of
2084 ikWonder:
2085 s := s + ' ' + HelpText.Lookup('HELPSPEC_WONDER');
2086 ikCommon:
2087 s := s + ' ' + HelpText.Lookup('HELPSPEC_IMP');
2088 ikShipPart:
2089 s := s + ' ' + HelpText.Lookup('HELPSPEC_SHIPPART');
2090 else
2091 s := s + ' ' + HelpText.Lookup('HELPSPEC_NAT')
2092 end;
2093 SearchResult.AddLine(s, pkNormal, 0, hkImp + hkCrossLink, i);
2094 include(mIMPHELP, i);
2095 end
2096 end;
2097 for i := 0 to nGov - 1 do
2098 if pos(SearchString, UpperCase(Phrases.Lookup('GOVERNMENT', i))) > 0 then
2099 begin
2100 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_GOVLIST'), pkNormal, 0,
2101 hkMisc + hkCrossLink, miscGovList);
2102 bGOVHELP := true;
2103 Break
2104 end;
2105
2106 // full text search
2107 h := -1;
2108 repeat
2109 PrevHandle := h;
2110 PrevIndex := i;
2111 if not HelpText.Search(SearchString, h, i) then
2112 Break;
2113 if h = hADVHELP then
2114 begin
2115 if (i >= 0) and ((i <> PrevIndex) or (h <> PrevHandle)) and
2116 not(i in mADVHELP) then
2117 begin
2118 s := Phrases.Lookup('ADVANCES', i);
2119 if i in FutureTech then
2120 s := s + ' ' + HelpText.Lookup('HELPSPEC_FUTURE')
2121 else
2122 s := s + ' ' + HelpText.Lookup('HELPSPEC_ADV');
2123 SearchResult.AddLine(s, pkNormal, 0, hkAdv + hkCrossLink, i)
2124 end
2125 end
2126 else if h = hIMPHELP then
2127 begin
2128 if (i >= 0) and ((i <> PrevIndex) or (h <> PrevHandle)) and
2129 not(i in mIMPHELP) then
2130 begin
2131 s := Phrases.Lookup('IMPROVEMENTS', i);
2132 case Imp[i].Kind of
2133 ikWonder:
2134 s := s + ' ' + HelpText.Lookup('HELPSPEC_WONDER');
2135 ikCommon:
2136 s := s + ' ' + HelpText.Lookup('HELPSPEC_IMP');
2137 ikShipPart:
2138 s := s + ' ' + HelpText.Lookup('HELPSPEC_SHIPPART');
2139 else
2140 s := s + ' ' + HelpText.Lookup('HELPSPEC_NAT')
2141 end;
2142 SearchResult.AddLine(s, pkNormal, 0, hkImp + hkCrossLink, i)
2143 end
2144 end
2145 else if h = hFEATUREHELP then
2146 begin
2147 if (i >= 0) and ((i <> PrevIndex) or (h <> PrevHandle)) and
2148 not(i in mFEATUREHELP) then
2149 begin
2150 s := Phrases.Lookup('FEATURES', i);
2151 if i < mcFirstNonCap then
2152 s := s + ' ' + HelpText.Lookup('HELPSPEC_CAP')
2153 else if i in AutoFeature then
2154 s := s + ' ' + HelpText.Lookup('HELPSPEC_STANDARD')
2155 else
2156 s := s + ' ' + HelpText.Lookup('HELPSPEC_FEATURE');
2157 SearchResult.AddLine(s, pkNormal, 0, hkFeature + hkCrossLink, i);
2158 end
2159 end
2160 else if h = hGOVHELP then
2161 begin
2162 if (i >= 0) and (h <> PrevHandle) and not bGOVHELP then
2163 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_GOVLIST'), pkNormal, 0,
2164 hkMisc + hkCrossLink, miscGovList)
2165 end
2166 else if h = hSPECIALMODEL then
2167 begin
2168 if (i >= 0) and (h <> PrevHandle) and not bSPECIALMODEL then
2169 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_MODELLIST'), pkNormal,
2170 0, hkModel + hkCrossLink, 0)
2171 end
2172 else if h = hJOBHELP then
2173 begin
2174 if (i >= 0) and (h <> PrevHandle) and not bJOBHELP then
2175 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_JOBLIST'), pkNormal, 0,
2176 hkMisc + hkCrossLink, miscJobList)
2177 end
2178 else if { (h<>hMAIN) and } (h <> PrevHandle) then
2179 begin
2180 s := HelpText.LookupByHandle(h);
2181 p := pos('$', s);
2182 if p > 0 then
2183 begin
2184 s := copy(s, p + 1, maxint);
2185 p := pos('\', s);
2186 if p > 0 then
2187 s := copy(s, 1, p - 1);
2188 SearchResult.AddLine(s, pkNormal, 0, hkText + hkCrossLink, h);
2189 end
2190 end
2191 until false;
2192
2193 // cut lines to fit to window
2194 RightMargin := InnerWidth - 16 - GetSystemMetrics(SM_CXVSCROLL);
2195 OffScreen.Canvas.Font.Assign(UniFont[ftNormal]);
2196 for i := 0 to SearchResult.Count - 1 do
2197 begin
2198 while BiColorTextWidth(OffScreen.Canvas, SearchResult[i]) >
2199 RightMargin - 32 do
2200 SearchResult[i] := copy(SearchResult[i], 1, length(SearchResult[i]) - 1)
2201 end;
2202 end;
2203
2204end.
Note: See TracBrowser for help on using the repository browser.