source: tags/1.3.0/LocalPlayer/CityScreen.pas

Last change on this file was 380, checked in by chronos, 3 years ago
  • Modified: TTexture class moved to seprate unit.
File size: 58.7 KB
Line 
1{$INCLUDE Switches.inc}
2unit CityScreen;
3
4interface
5
6uses
7 {$IFDEF LINUX}LMessages,{$ENDIF}
8 Protocol, ClientTools, Term, ScreenTools, IsoEngine, BaseWin,
9 LCLIntf, LCLType, Messages, SysUtils, Classes, Graphics, Controls, Forms, ExtCtrls,
10 ButtonA, ButtonC, Area, GraphType, UTexture;
11
12const
13 WM_PLAYSOUND = WM_USER;
14
15type
16 TCityCloseAction = (None, RestoreFocus, StepFocus);
17 TSmallMapMode = (smSupportedUnits, smImprovements);
18
19 TCityDlg = class(TBufferedDrawDlg)
20 Timer1: TTimer;
21 CloseBtn: TButtonA;
22 PrevCityBtn: TButtonC;
23 NextCityBtn: TButtonC;
24 PageUpBtn: TButtonC;
25 PageDownBtn: TButtonC;
26 BuyBtn: TButtonC;
27 ProjectArea: TArea;
28 PrimacyArea: TArea;
29 Imp2Area: TArea;
30 Imp4Area: TArea;
31 Imp0Area: TArea;
32 Imp3Area: TArea;
33 Imp5Area: TArea;
34 Imp1Area: TArea;
35 Pop0Area: TArea;
36 Pop1Area: TArea;
37 SupportArea: TArea;
38 procedure FormCreate(Sender: TObject);
39 procedure FormDestroy(Sender: TObject);
40 procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
41 Shift: TShiftState; x, y: integer);
42 procedure BuyClick(Sender: TObject);
43 procedure CloseBtnClick(Sender: TObject);
44 procedure FormShow(Sender: TObject);
45 procedure FormClose(Sender: TObject; var Action: TCloseAction);
46 procedure Timer1Timer(Sender: TObject);
47 procedure FormPaint(Sender: TObject);
48 procedure NextCityBtnClick(Sender: TObject);
49 procedure PrevCityBtnClick(Sender: TObject);
50 procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
51 // procedure AdviceBtnClick(Sender: TObject);
52 procedure PageUpBtnClick(Sender: TObject);
53 procedure PageDownBtnClick(Sender: TObject);
54 private
55 c: TCity;
56 Report: TCityReportNew;
57 cOwner: Integer;
58 cGov: Integer;
59 emix: Integer; { enemy model index of produced unit }
60 cix: Integer;
61 cLoc: Integer;
62 SmallMapMode: TSmallMapMode;
63 ZoomArea: Integer;
64 Page: Integer;
65 PageCount: Integer;
66 BlinkTime: Integer;
67 OpenSoundEvent: Integer;
68 SizeClass: Integer;
69 AgePrepared: Integer;
70 Optimize_cixTileChange: Integer;
71 Optimize_TilesBeforeChange: Integer;
72 Happened: cardinal;
73 imix: array [0 .. 15] of integer;
74 CityAreaInfo: TCityAreaInfo;
75 AreaMap: TIsoMap;
76 NoMap: TIsoMap;
77 CityMapTemplate: TBitmap;
78 SmallCityMapTemplate: TBitmap;
79 Back: TBitmap;
80 SmallCityMap: TBitmap;
81 ZoomCityMap: TBitmap;
82 Template: TBitmap;
83 IsPort: Boolean;
84 ProdHint: Boolean;
85 AllowChange: Boolean;
86 RedTex: TTexture;
87 BarTex: TTexture;
88 procedure InitSmallCityMap;
89 procedure InitZoomCityMap;
90 procedure ChooseProject;
91 procedure ChangeCity(d: integer);
92 procedure ChangeResourceWeights(iResourceWeights: integer);
93 procedure OnPlaySound(var Msg: TMessage); message WM_PLAYSOUND;
94 public
95 RestoreUnFocus: integer;
96 CloseAction: TCityCloseAction;
97 procedure OffscreenPaint; override;
98 procedure ShowNewContent(NewMode, Loc: integer; ShowEvent: cardinal);
99 procedure Reset;
100 procedure CheckAge;
101 end;
102
103var
104 CityDlg: TCityDlg;
105
106
107implementation
108
109uses
110 Select, Messg, MessgEx, Help, Tribes, Directories, Math, Sound;
111
112{$R *.lfm}
113
114const
115 wBar = 106;
116 xDiv = 400;
117 xService = 296;
118 xmArea = 197;
119 ymArea = 170;
120 xView = 326;
121 yView = 275;
122 dxBar = wBar + 12;
123 dyBar = 39;
124 xHapp = 404;
125 yHapp = 9;
126 xFood = 404;
127 yFood = yHapp + 3 * dyBar + 6;
128 xProd = 404;
129 yProd = yFood + 3 * dyBar + 6;
130 xTrade = 404;
131 yTrade = yProd + 2 * dyBar + 22;
132 xPoll = xmArea - 186;
133 yPoll = ymArea + 64;
134 xmOpt = 40;
135 ymOpt = ymArea + 96 + 34;
136 xSmallMap = 271;
137 ySmallMap = 339;
138 wSmallMap = 98;
139 hSmallMap = 74;
140 xSupport = xSmallMap;
141 ySupport = ySmallMap + hSmallMap + 2;
142 wSupport = 64;
143 hSupport = 18;
144 xZoomMap = 34;
145 yZoomMap = 338;
146 wZoomMap = 228;
147 hZoomMap = 124;
148 wZoomEnvironment = 68;
149
150 ImpPosition: array [28 .. nImp - 1] of integer = (-1, // imTrGoods
151 21, // imBarracks
152 6, // imGranary
153 1, // imTemple
154 7, // imMarket
155 14, // imLibrary
156 8, // imCourt
157 18, // imWalls
158 10, // imAqueduct
159 11, // imBank
160 5, // imCathedral
161 13, // imUniversity
162 29, // imHarbor
163 2, // imTheater
164 24, // imFactory
165 25, // imMfgPlant
166 28, // imRecycling
167 27, // imPower
168 27, // imHydro
169 27, // imNuclear
170 26, // imPlatform
171 8, // imTownHall
172 10, // imSewer
173 3, // imSupermarket
174 17, // imHighways
175 15, // imResLab
176 19, // imMissileBat
177 23, // imCoastalFort
178 22, // imAirport
179 20, // imDockyard
180 8, // imPalace
181 -1, // imGrWall
182 4, // imColosseum
183 16, // imObservatory
184 21, // imMilAcademy
185 -1, // imBunker
186 -1, // imAlgae
187 9, // imStockEx
188 -1, // imSpacePort
189 -1, // imShipComp
190 -1, // imShipPow
191 -1); // imShipHab
192
193var
194 ImpSorted: array [0 .. nImp - 1] of integer;
195
196procedure TCityDlg.FormCreate(Sender: TObject);
197begin
198 inherited;
199 RedTex := TTexture.Create;
200 BarTex := TTexture.Create;
201 NoMap := TIsoMap.Create;
202 AreaMap := TIsoMap.Create;
203 AreaMap.SetOutput(offscreen);
204 AreaMap.SetPaintBounds(xmArea - 192, ymArea - 96 - 32, xmArea + 192,
205 ymArea + 96);
206 SmallMapMode := smImprovements;
207 ZoomArea := 1;
208 ProdHint := false;
209 RestoreUnFocus := -1;
210 OpenSoundEvent := -1;
211 AgePrepared := -2;
212 Optimize_cixTileChange := -1;
213 InitButtons;
214 // InitWindowRegion;
215 CloseBtn.Caption := Phrases.Lookup('BTN_OK');
216 BuyBtn.Hint := Phrases.Lookup('BTN_BUY');
217 if not Phrases2FallenBackToEnglish then
218 SupportArea.Hint := Phrases2.Lookup('TIP_SUPUNITS')
219 else
220 SupportArea.Hint := Phrases.Lookup('SUPUNITS');
221 if not Phrases2FallenBackToEnglish then
222 begin
223 Pop0Area.Hint := Phrases2.Lookup('TIP_WORKING');
224 Pop1Area.Hint := Phrases2.Lookup('TIP_CIVIL');
225 PrimacyArea.Hint := Phrases2.Lookup('TIP_PRIMACY');
226 ProjectArea.Hint := Phrases2.Lookup('TIP_PROJECT');
227 end;
228
229 Back := TBitmap.Create;
230 Back.PixelFormat := pf24bit;
231 Back.SetSize(Width, Height);
232 Back.Canvas.FillRect(0, 0, Back.Width, Back.Height);
233 Template := TBitmap.Create;
234 Template.PixelFormat := pf24bit;
235 LoadGraphicFile(Template, GetGraphicsDir + DirectorySeparator + 'City.png',
236 [gfNoGamma]);
237 CityMapTemplate := TBitmap.Create;
238 CityMapTemplate.PixelFormat := pf24bit;
239 LoadGraphicFile(CityMapTemplate, GetGraphicsDir + DirectorySeparator + 'BigCityMap.png',
240 [gfNoGamma]);
241 SmallCityMapTemplate := TBitmap.Create;
242 SmallCityMapTemplate.PixelFormat := pf24bit;
243 LoadGraphicFile(SmallCityMapTemplate, GetGraphicsDir + DirectorySeparator + 'SmallCityMap.png',
244 [gfNoGamma]);
245 SmallCityMap := TBitmap.Create;
246 SmallCityMap.PixelFormat := pf24bit;
247 SmallCityMap.SetSize(98, 74);
248 SmallCityMap.Canvas.FillRect(0, 0, SmallCityMap.Width, SmallCityMap.Height);
249 ZoomCityMap := TBitmap.Create;
250 ZoomCityMap.PixelFormat := pf24bit;
251 ZoomCityMap.SetSize(228, 124);
252 ZoomCityMap.Canvas.FillRect(0, 0, ZoomCityMap.Width, ZoomCityMap.Height);
253end;
254
255procedure TCityDlg.FormDestroy(Sender: TObject);
256begin
257 FreeAndNil(NoMap);
258 FreeAndNil(AreaMap);
259 FreeAndNil(SmallCityMap);
260 FreeAndNil(ZoomCityMap);
261 FreeAndNil(SmallCityMapTemplate);
262 FreeAndNil(CityMapTemplate);
263 FreeAndNil(Template);
264 FreeAndNil(Back);
265 FreeAndNil(RedTex);
266 FreeAndNil(BarTex);
267end;
268
269procedure TCityDlg.Reset;
270begin
271 SmallMapMode := smImprovements;
272 ZoomArea := 1;
273end;
274
275procedure TCityDlg.CheckAge;
276begin
277 if MainTexture.Age <> AgePrepared then begin
278 AgePrepared := MainTexture.Age;
279
280 UnshareBitmap(Back);
281 BitBltCanvas(Back.Canvas, 0, 0, ClientWidth, ClientHeight,
282 MainTexture.Image.Canvas, 0, 0);
283 ImageOp_B(Back, Template, 0, 0, 0, 0, ClientWidth, ClientHeight);
284 end;
285end;
286
287procedure TCityDlg.CloseBtnClick(Sender: TObject);
288begin
289 Close;
290end;
291
292procedure TCityDlg.InitSmallCityMap;
293var
294 i, iix, cli1, Color0, Color1, Color2: integer;
295begin
296 if cix >= 0 then
297 c := MyCity[cix];
298 case MyMap[cLoc] and fTerrain of
299 fPrairie: cli1 := cliPrairie;
300 fHills: cli1 := cliHills;
301 fTundra: cli1 := cliTundra;
302 else
303 cli1 := cliPlains;
304 end;
305 Color0 := Colors.Canvas.Pixels[clkAge0 + Age, cliRoad];
306 Color1 := Colors.Canvas.Pixels[clkCity, cli1];
307 Color2 := Colors.Canvas.Pixels[clkAge0 + Age, cliHouse];
308 SmallCityMap.Canvas.FillRect(0, 0, SmallCityMap.Width, SmallCityMap.Height);
309 BitBltCanvas(SmallCityMap.Canvas, 0, 0, 83, hSmallMap,
310 SmallCityMapTemplate.Canvas, 83 * SizeClass, 0);
311 if IsPort then
312 begin
313 BitBltCanvas(SmallCityMap.Canvas, 83, 0, 15, hSmallMap,
314 SmallCityMapTemplate.Canvas, 332 + 15, 0);
315 ImageOp_CCC(SmallCityMap, 0, 0, 83, hSmallMap, Color0, Color1, Color2);
316 Color2 := Colors.Canvas.Pixels[clkCity, cliWater];
317 ImageOp_CCC(SmallCityMap, 83, 0, 15, hSmallMap, Color0, Color1, Color2);
318 end
319 else
320 begin
321 BitBltCanvas(SmallCityMap.Canvas, 83, 0, 15, hSmallMap,
322 SmallCityMapTemplate.Canvas, 332, 0);
323 ImageOp_CCC(SmallCityMap, 0, 0, wSmallMap, hSmallMap, Color0,
324 Color1, Color2);
325 end;
326
327 with SmallCityMap.Canvas do
328 begin
329 Brush.Color := ScreenTools.Colors.Canvas.Pixels[clkAge0 + Age, cliImp];
330 for i := 0 to 29 do
331 begin
332 for iix := nWonder to nImp - 1 do
333 if (ImpPosition[iix] = i) and (c.Built[iix] > 0) then
334 begin
335 FillRect(Rect(5 + 16 * (i mod 3) + 48 * (i div 18),
336 3 + 12 * (i mod 18 div 3), 13 + 16 * (i mod 3) + 48 * (i div 18),
337 11 + 12 * (i mod 18 div 3)));
338 break;
339 end;
340 end;
341 i := 30;
342 for iix := 0 to nImp do
343 if (c.Built[iix] > 0) and ((iix < nWonder) or (ImpPosition[iix] < 0)) then
344 begin
345 FillRect(Rect(5 + 16 * (i mod 3) + 48 * (i div 18),
346 3 + 12 * (i mod 18 div 3), 13 + 16 * (i mod 3) + 48 * (i div 18),
347 11 + 12 * (i mod 18 div 3)));
348 inc(i);
349 if i = 36 then
350 break; // area is full
351 end;
352 if c.Project and cpImp <> 0 then
353 begin
354 iix := c.Project and cpIndex;
355 if iix <> imTrGoods then
356 begin
357 if (iix >= nWonder) and (ImpPosition[iix] >= 0) then
358 i := ImpPosition[iix];
359 if i < 36 then
360 begin
361 brush.Color := ScreenTools.Colors.Canvas.Pixels[clkAge0 + Age, cliImpProject];
362 FillRect(Rect(5 + 16 * (i mod 3) + 48 * (i div 18),
363 3 + 12 * (i mod 18 div 3), 13 + 16 * (i mod 3) + 48 * (i div 18),
364 11 + 12 * (i mod 18 div 3)));
365 end;
366 end;
367 end;
368 brush.style := bsClear;
369 end;
370end;
371
372procedure TCityDlg.InitZoomCityMap;
373begin
374 UnshareBitmap(ZoomCityMap);
375 BitBltCanvas(ZoomCityMap.Canvas, 0, 0, wZoomMap, hZoomMap,
376 Back.Canvas, xZoomMap, yZoomMap);
377 if SmallMapMode = smImprovements then begin
378 if ZoomArea < 3 then begin
379 ImageOp_B(ZoomCityMap, CityMapTemplate, 0, 0, 376 * SizeClass,
380 112 * ZoomArea, wZoomMap, hZoomMap);
381 end else begin
382 ImageOp_B(ZoomCityMap, CityMapTemplate, 0, 0, 376 * SizeClass + 216,
383 112 * (ZoomArea - 3), wZoomMap - wZoomEnvironment, hZoomMap);
384 ImageOp_B(ZoomCityMap, CityMapTemplate, wZoomMap - wZoomEnvironment, 0,
385 1504 + wZoomEnvironment * byte(IsPort), 112 * (ZoomArea - 3),
386 wZoomEnvironment, hZoomMap);
387 end;
388 end;
389end;
390
391procedure TCityDlg.OffscreenPaint;
392
393 procedure FillBar(x, y, pos, Growth, max, Kind: integer;
394 IndicateComplete: boolean);
395 begin
396 BarTex.Assign(MainTexture);
397 if Kind = 3 then begin
398 BarTex.ColorBevelLight := HGrSystem.Data.Canvas.Pixels[104, 36];
399 BarTex.ColorBevelShade := BarTex.ColorBevelLight;
400 end;
401 PaintRelativeProgressBar(offscreen.Canvas, Kind, x - 3, y, wBar - 4, pos,
402 Growth, max, IndicateComplete, BarTex);
403 end;
404
405 procedure PaintResources(x, y, Loc: integer; Add4Happy: boolean);
406 var
407 d, i, Total, xGr, yGr: integer;
408 TileInfo: TTileInfo;
409 rare: boolean;
410 begin
411 with AreaMap do begin
412 if Server(sGetCityTileInfo, me, Loc, TileInfo) <> eOk then
413 begin
414 assert(cix < 0);
415 exit
416 end;
417 Total := TileInfo.Food + TileInfo.Prod + TileInfo.Trade;
418 rare := MyMap[Loc] and $06000000 > 0;
419 if rare then
420 inc(Total);
421 if Add4Happy then
422 inc(Total, 4);
423 if Total > 1 then
424 d := (xxt - 11) div (Total - 1);
425 if d < 1 then
426 d := 1;
427 if d > 4 then
428 d := 4;
429 for i := 0 to Total - 1 do
430 begin
431 yGr := 115;
432 if Add4Happy and (i >= Total - 4) then
433 begin
434 xGr := 132;
435 yGr := 126
436 end
437 else if rare and (i = Total - 1) then
438 xGr := 66 + 110
439 else if i >= TileInfo.Food + TileInfo.Prod then
440 xGr := 66 + 44
441 else if i >= TileInfo.Prod then
442 xGr := 66
443 else
444 xGr := 66 + 22;
445 Sprite(offscreen, HGrSystem, x + xxt - 5 + d * (2 * i + 1 - Total),
446 y + yyt - 5, 10, 10, xGr, yGr);
447 end;
448 end;
449 end;
450var
451 line, MessageCount: integer;
452
453 procedure CheckMessage(Flag: integer);
454 var
455 i, test: integer;
456 s: string;
457 begin
458 if Happened and Flag <> 0 then
459 begin
460 i := 0;
461 test := 1;
462 while test < Flag do
463 begin
464 inc(i);
465 inc(test, test)
466 end;
467
468 if AllowChange and (Sounds <> nil) and (OpenSoundEvent = -1) then
469 begin
470 s := CityEventSoundItem[i];
471 if s <> '' then
472 s := Sounds.Lookup(s);
473 if (Flag = chProduction) or (s <> '') and (s[1] <> '*') and (s[1] <> '[')
474 then
475 OpenSoundEvent := i
476 end;
477
478 s := CityEventName(i);
479 { if Flag=chNoGrowthWarning then
480 if c.Built[imAqueduct]=0 then
481 s:=Format(s,[Phrases.Lookup('IMPROVEMENTS',imAqueduct)])
482 else s:=Format(s,[Phrases.Lookup('IMPROVEMENTS',imSewer)]); }
483 RisedTextOut(offscreen.Canvas, xmOpt + 40, ymOpt - 1 - 8 * MessageCount +
484 16 * line, s);
485 inc(line)
486 end;
487 end;
488
489var
490 x, y, xGr, i, j, iix, d, dx, dy, PrCost, Cnt, Loc1, FreeSupp, Paintiix,
491 HappyGain, OptiType, rx, ry, TrueFood, TrueProd, TruePoll: integer;
492 av: integer;
493 PrName, s: string;
494 UnitInfo: TUnitInfo;
495 UnitReport: TUnitReport;
496 IsCityAlive, CanGrow: boolean;
497begin
498 inherited;
499 if cix >= 0 then
500 c := MyCity[cix];
501 Report.HypoTiles := -1;
502 Report.HypoTaxRate := -1;
503 Report.HypoLuxuryRate := -1;
504 if cix >= 0 then
505 Server(sGetCityReportNew, me, cix, Report) // own city
506 else
507 Server(sGetEnemyCityReportNew, me, cLoc, Report); // enemy city
508 TrueFood := c.Food;
509 TrueProd := c.Prod;
510 TruePoll := c.Pollution;
511 if supervising or (cix < 0) then
512 begin // normalize city from after-turn state
513 dec(TrueFood, Report.FoodSurplus);
514 if TrueFood < 0 then
515 TrueFood := 0; // shouldn't happen
516 dec(TrueProd, Report.Production);
517 if TrueProd < 0 then
518 TrueProd := 0; // shouldn't happen
519 dec(TruePoll, Report.AddPollution);
520 if TruePoll < 0 then
521 TruePoll := 0; // shouldn't happen
522 end;
523 IsCityAlive := (cGov <> gAnarchy) and (c.Flags and chCaptured = 0);
524 if not IsCityAlive then
525 Report.Working := c.Size;
526
527 RedTex.Assign(MainTexture);
528 RedTex.ColorBevelLight := $0000FF;
529 RedTex.ColorBevelShade := $000000;
530 RedTex.ColorTextLight := $000000;
531 RedTex.ColorTextShade := $0000FF;
532
533 BitBltCanvas(offscreen.Canvas, 0, 0, 640, 480, Back.Canvas, 0, 0);
534
535 Offscreen.Canvas.Font.Assign(UniFont[ftCaption]);
536 RisedTextOut(offscreen.Canvas, 42, 7, Caption);
537 with offscreen.Canvas do
538 begin // city size
539 brush.Color := $000000;
540 FillRect(Rect(8 + 1, 7 + 1, 36 + 1, 32 + 1));
541 brush.Color := $FFFFFF;
542 FillRect(Rect(8, 7, 36, 32));
543 brush.style := bsClear;
544 Font.Color := $000000;
545 s := inttostr(c.Size);
546 TextOut(8 + 14 - textwidth(s) div 2, 7, s);
547 end;
548 Offscreen.Canvas.Font.Assign(UniFont[ftSmall]);
549
550 if not IsCityAlive then
551 begin
552 MakeRed(Offscreen, 18, 280, 298, 40);
553 if cGov = gAnarchy then
554 s := Phrases.Lookup('GOVERNMENT', gAnarchy)
555 else { if c.Flags and chCaptured<>0 then }
556 s := Phrases.Lookup('CITYEVENTS', 14);
557 RisedTextOut(offscreen.Canvas, 167 - BiColorTextWidth(offscreen.Canvas, s)
558 div 2, ymOpt - 9, s);
559 end
560 else if AllowChange then
561 begin
562 OptiType := c.Status shr 4 and $0F;
563 Sprite(offscreen, HGrSystem2, xmOpt - 32, ymOpt - 32, 64, 64,
564 1 + OptiType mod 3 * 64, 217 + OptiType div 3 * 64);
565
566 { display messages now }
567 MessageCount := 0;
568 for i := 0 to 31 do
569 if Happened and ($FFFFFFFF - chCaptured) and (1 shl i) <> 0 then
570 inc(MessageCount);
571 if MessageCount > 3 then
572 MessageCount := 3;
573 if MessageCount > 0 then
574 begin
575 MakeBlue(offscreen, 74, 280, 242, 40);
576 line := 0;
577 for i := 0 to nCityEventPriority - 1 do
578 if line < MessageCount then
579 CheckMessage(CityEventPriority[i]);
580 end
581 else
582 begin
583 s := Phrases.Lookup('CITYMANAGETYPE', OptiType);
584 j := pos('\', s);
585 if j = 0 then
586 LoweredTextout(offscreen.Canvas, -1, MainTexture, xmOpt + 40,
587 ymOpt - 9, s)
588 else
589 begin
590 LoweredTextout(offscreen.Canvas, -1, MainTexture, xmOpt + 40,
591 ymOpt - 17, copy(s, 1, j - 1));
592 LoweredTextout(offscreen.Canvas, -1, MainTexture, xmOpt + 40, ymOpt - 1,
593 copy(s, j + 1, 255));
594 end;
595 end;
596 end;
597
598 with AreaMap do begin
599 rx := (192 + xxt * 2 - 1) div (xxt * 2);
600 ry := (96 + yyt * 2 - 1) div (yyt * 2);
601 AreaMap.Paint(xmArea - xxt * 2 * rx, ymArea - yyt * 2 * ry - 3 * yyt,
602 dLoc(cLoc, -2 * rx + 1, -2 * ry - 1), 4 * rx - 1, 4 * ry + 1, cLoc, cOwner,
603 false, AllowChange and IsCityAlive and
604 (c.Status and csResourceWeightsMask = 0));
605 BitBltCanvas(offscreen.Canvas, xmArea + 102, 42, 90, 33, Back.Canvas,
606 xmArea + 102, 42);
607
608 if IsCityAlive then
609 for dy := -3 to 3 do
610 for dx := -3 to 3 do
611 if ((dx + dy) and 1 = 0) and (dx * dx * dy * dy < 81) then begin
612 Loc1 := dLoc(cLoc, dx, dy);
613 av := CityAreaInfo.Available[(dy + 3) shl 2 + (dx + 3) shr 1];
614 if ((av = faNotAvailable) or (av = faTreaty) or (av = faInvalid)) and
615 ((Loc1 < 0) or (Loc1 >= G.lx * G.ly) or (MyMap[Loc1] and fCity = 0))
616 then
617 Sprite(offscreen, HGrTerrain, xmArea - xxt + xxt * dx,
618 ymArea - yyt + yyt * dy, xxt * 2, yyt * 2, 1 + 5 * (xxt * 2 + 1),
619 1 + yyt + 15 * (yyt * 3 + 1));
620 if (1 shl ((dy + 3) shl 2 + (dx + 3) shr 1) and c.Tiles <> 0) then
621 PaintResources(xmArea - xxt + xxt * dx, ymArea - yyt + yyt * dy,
622 Loc1, (dx = 0) and (dy = 0));
623 end;
624 end;
625
626 if Report.Working > 1 then
627 d := (xService - (xmArea - 192) - 8 - 32) div (Report.Working - 1);
628 if d > 28 then
629 d := 28;
630 for i := Report.Working - 1 downto 0 do
631 begin
632 if IsCityAlive then
633 xGr := 29
634 else
635 xGr := 141;
636 BitBltCanvas(offscreen.Canvas, xmArea - 192 + 5 + i * d, ymArea - 96 - 29,
637 27, 30, HGrSystem.Mask.Canvas, xGr, 171, SRCAND); { shadow }
638 Sprite(offscreen, HGrSystem, xmArea - 192 + 4 + i * d, ymArea - 96 - 30, 27,
639 30, xGr, 171);
640 end;
641 if c.Size - Report.Working > 1 then
642 d := (xmArea + 192 - xService - 32) div (c.Size - Report.Working - 1);
643 if d > 28 then
644 d := 28;
645 for i := 0 to c.Size - Report.Working - 1 do
646 begin
647 xGr := 1 + 112;
648 BitBltCanvas(offscreen.Canvas, xmArea + 192 - 27 + 1 - i * d, 29 + 1, 27,
649 30, HGrSystem.Mask.Canvas, xGr, 171, SRCAND); { shadow }
650 Sprite(offscreen, HGrSystem, xmArea + 192 - 27 - i * d, 29, 27, 30,
651 xGr, 171);
652 Sprite(offscreen, HGrSystem, xmArea + 192 - 27 + 4 - i * d, 29 + 32, 10,
653 10, 121, 126);
654 Sprite(offscreen, HGrSystem, xmArea + 192 - 27 + 13 - i * d, 29 + 32, 10,
655 10, 121, 126);
656 // Sprite(offscreen,HGrSystem,xmArea+192-31+18-i*d,ymArea-96-80+32,10,10,88,115);
657 end;
658
659 if c.Project and cpImp = 0 then
660 PrName := Tribe[cOwner].ModelName[c.Project and cpIndex]
661 else
662 PrName := Phrases.Lookup('IMPROVEMENTS', c.Project and cpIndex);
663 PrCost := Report.ProjectCost;
664
665 // happiness section
666 if IsCityAlive then
667 begin
668 if cGov = gFundamentalism then
669 CountBar(offscreen, xHapp, yHapp + dyBar, wBar, 17,
670 Phrases.Lookup('FAITH'), Report.CollectedControl, MainTexture)
671 else
672 begin
673 CountBar(offscreen, xHapp, yHapp + dyBar, wBar, 17,
674 Phrases.Lookup('HAPPINESS'), Report.Morale, MainTexture);
675 CountBar(offscreen, xHapp, yHapp + 2 * dyBar, wBar, 16,
676 Phrases.Lookup('CONTROL'), Report.CollectedControl, MainTexture);
677 end;
678 CountBar(offscreen, xHapp, yHapp, wBar, 8, Phrases.Lookup('LUX'),
679 Report.Luxury, MainTexture);
680 CountBar(offscreen, xHapp + dxBar, yHapp, wBar, 19,
681 Phrases.Lookup('UNREST'), 2 * Report.Deployed, MainTexture);
682 CountBar(offscreen, xHapp + dxBar, yHapp + dyBar, wBar, 17,
683 Phrases.Lookup('HAPPINESSDEMAND'), c.Size, MainTexture);
684 if Report.HappinessBalance >= 0 then
685 CountBar(offscreen, xHapp + dxBar, yHapp + 2 * dyBar, wBar, 17,
686 Phrases.Lookup('HAPPINESSPLUS'), Report.HappinessBalance, MainTexture)
687 else
688 begin
689 MakeRed(Offscreen, xHapp + dxBar - 6, yHapp + 2 * dyBar, wBar + 10, 38);
690 CountBar(offscreen, xHapp + dxBar, yHapp + 2 * dyBar, wBar, 18,
691 Phrases.Lookup('LACK'), -Report.HappinessBalance, RedTex);
692 end;
693 end;
694
695 // food section
696 if IsCityAlive then
697 begin
698 CountBar(offscreen, xFood, yFood + dyBar div 2, wBar, 0,
699 Phrases.Lookup('FOOD'), Report.CollectedFood, MainTexture);
700 CountBar(offscreen, xFood + dxBar, yFood + dyBar, wBar, 0,
701 Phrases.Lookup('DEMAND'), 2 * c.Size, MainTexture);
702 CountBar(offscreen, xFood + dxBar, yFood, wBar, 0,
703 Phrases.Lookup('SUPPORT'), Report.FoodSupport, MainTexture);
704 if Report.FoodSurplus >= 0 then
705 if (cGov = gFuture) or (c.Size >= NeedAqueductSize) and
706 (Report.FoodSurplus < 2) then
707 CountBar(offscreen, xFood + dxBar, yFood + 2 * dyBar, wBar, 6,
708 Phrases.Lookup('PROFIT'), Report.FoodSurplus, MainTexture)
709 else
710 CountBar(offscreen, xFood + dxBar, yFood + 2 * dyBar, wBar, 0,
711 Phrases.Lookup('SURPLUS'), Report.FoodSurplus, MainTexture)
712 else
713 begin
714 MakeRed(Offscreen, xFood + dxBar - 6, yFood + 2 * dyBar, wBar + 10, 38);
715 CountBar(offscreen, xFood + dxBar, yFood + 2 * dyBar, wBar, 1,
716 Phrases.Lookup('LACK'), -Report.FoodSurplus, RedTex);
717 end;
718 end;
719 CanGrow := (c.Size < MaxCitySize) and (cGov <> gFuture) and
720 (Report.FoodSurplus > 0) and ((c.Size < NeedAqueductSize) or
721 (c.Built[imAqueduct] = 1) and (c.Size < NeedSewerSize) or
722 (c.Built[imSewer] = 1));
723 FillBar(xFood + 3, yFood + 102, TrueFood,
724 CutCityFoodSurplus(Report.FoodSurplus, IsCityAlive, cGov, c.Size),
725 Report.Storage, 1, CanGrow);
726 LoweredTextout(offscreen.Canvas, -1, MainTexture, xFood + 3 - 5,
727 yFood + 102 - 20, Format('%d/%d', [TrueFood, Report.Storage]));
728 LoweredTextout(offscreen.Canvas, -1, MainTexture, xFood - 2, yFood + 66,
729 Phrases.Lookup('STORAGE'));
730
731 // production section
732 if IsCityAlive then
733 begin
734 CountBar(offscreen, xProd, yProd, wBar, 2, Phrases.Lookup('MATERIAL'),
735 Report.CollectedMaterial, MainTexture);
736 CountBar(offscreen, xProd + dxBar, yProd, wBar, 2,
737 Phrases.Lookup('SUPPORT'), Report.MaterialSupport, MainTexture);
738 if Report.Production >= 0 then
739 if c.Project and (cpImp + cpIndex) = cpImp + imTrGoods then
740 CountBar(offscreen, xProd + dxBar, yProd + dyBar + 16, wBar, 6,
741 Phrases.Lookup('PROFIT'), Report.Production, MainTexture)
742 else
743 CountBar(offscreen, xProd + dxBar, yProd + dyBar + 16, wBar, 2,
744 Phrases.Lookup('PROD'), Report.Production, MainTexture)
745 else
746 begin
747 MakeRed(Offscreen, xProd + dxBar - 6, yProd + dyBar + 17, wBar + 10, 38);
748 CountBar(offscreen, xProd + dxBar, yProd + dyBar + 16, wBar, 3,
749 Phrases.Lookup('LACK'), -Report.Production, RedTex);
750 end;
751 end;
752 if c.Project and (cpImp + cpIndex) <> cpImp + imTrGoods then
753 with offscreen.Canvas do
754 begin
755 i := Report.Production;
756 if (i < 0) or not IsCityAlive then
757 i := 0;
758 FillBar(xProd + 3, yProd + 16 + 63, TrueProd, i, PrCost, 4, true);
759 LoweredTextout(offscreen.Canvas, -1, MainTexture, xProd + 3 - 5,
760 yProd + 16 + 43, Format('%d/%d', [TrueProd, PrCost]));
761 if BiColorTextWidth(offscreen.Canvas, PrName) > wBar + dxBar then
762 begin
763 repeat
764 Delete(PrName, length(PrName), 1)
765 until BiColorTextWidth(offscreen.Canvas, PrName) <= wBar + dxBar;
766 PrName := PrName + '.'
767 end;
768 end;
769 RisedTextOut(offscreen.Canvas, xProd - 2, yProd + 36, PrName);
770
771 // pollution section
772 if IsCityAlive and (Report.AddPollution > 0) then
773 begin
774 FillBar(xPoll + 3, yPoll + 20, TruePoll, Report.AddPollution,
775 MaxPollution, 3, true);
776 RisedTextOut(offscreen.Canvas, xPoll + 3 - 5, yPoll + 20 - 20,
777 Phrases.Lookup('POLL'));
778 end;
779
780 // trade section
781 if IsCityAlive and (Report.CollectedTrade > 0) then
782 begin
783 CountBar(offscreen, xTrade, yTrade + dyBar div 2, wBar, 4,
784 Phrases.Lookup('TRADE'), Report.CollectedTrade, MainTexture);
785 CountBar(offscreen, xTrade + dxBar, yTrade + 2 * dyBar, wBar, 5,
786 Phrases.Lookup('CORR'), Report.Corruption, MainTexture);
787 CountBar(offscreen, xTrade + dxBar, yTrade, wBar, 6, Phrases.Lookup('TAX'),
788 Report.Tax, MainTexture);
789 CountBar(offscreen, xTrade + dxBar, yTrade + dyBar, wBar, 12,
790 Phrases.Lookup('SCIENCE'), Report.Science, MainTexture);
791 end;
792
793 // small map
794 BitBltCanvas(offscreen.Canvas, xSmallMap, ySmallMap, wSmallMap, hSmallMap,
795 SmallCityMap.Canvas, 0, 0);
796 if SmallMapMode = smImprovements then
797 Frame(offscreen.Canvas, xSmallMap + 48 * (ZoomArea div 3),
798 ySmallMap + 24 * (ZoomArea mod 3), xSmallMap + 48 * (ZoomArea div 3) + 49,
799 ySmallMap + 24 * (ZoomArea mod 3) + 25, MainTexture.ColorMark,
800 MainTexture.ColorMark);
801 Frame(offscreen.Canvas, xSmallMap - 1, ySmallMap - 1, xSmallMap + wSmallMap,
802 ySmallMap + hSmallMap, $B0B0B0, $FFFFFF);
803 RFrame(offscreen.Canvas, xSmallMap - 2, ySmallMap - 2, xSmallMap + wSmallMap +
804 1, ySmallMap + hSmallMap + 1, $FFFFFF, $B0B0B0);
805
806 Frame(offscreen.Canvas, xSupport - 1, ySupport - 1, xSupport + wSupport,
807 ySupport + hSupport, $B0B0B0, $FFFFFF);
808 RFrame(offscreen.Canvas, xSupport - 2, ySupport - 2, xSupport + wSupport + 1,
809 ySupport + hSupport + 1, $FFFFFF, $B0B0B0);
810 x := xSupport + wSupport div 2;
811 y := ySupport + hSupport div 2;
812 if SmallMapMode = smSupportedUnits then
813 begin
814 offscreen.Canvas.brush.Color := MainTexture.ColorMark;
815 offscreen.Canvas.FillRect(Rect(x - 27, y - 6, x + 27, y + 6));
816 offscreen.Canvas.brush.style := bsClear;
817 end;
818 Sprite(offscreen, HGrSystem, x - 16, y - 5, 10, 10, 88, 115);
819 Sprite(offscreen, HGrSystem, x - 5, y - 5, 10, 10, 66, 115);
820 Sprite(offscreen, HGrSystem, x + 6, y - 5, 10, 10, 154, 126);
821
822 BitBltCanvas(offscreen.Canvas, xZoomMap, yZoomMap, wZoomMap, hZoomMap,
823 ZoomCityMap.Canvas, 0, 0);
824
825 for i := 0 to 5 do
826 imix[i] := -1;
827 if SmallMapMode = smImprovements then
828 begin
829 if ZoomArea = 5 then
830 begin
831 Cnt := 0;
832 for iix := 0 to nImp - 1 do
833 if ((iix < nWonder) or (ImpPosition[iix] < 0)) and (c.Built[iix] > 0) then
834 begin
835 i := Cnt - Page * 6;
836 if (i >= 0) and (i < 6) then
837 imix[i] := iix;
838 inc(Cnt);
839 end;
840 PageCount := (Cnt + 5) div 6;
841 end
842 else
843 begin
844 for iix := nWonder to nImp - 1 do
845 begin
846 i := ImpPosition[iix] - 6 * ZoomArea;
847 if (i >= 0) and (i < 6) and (c.Built[iix] > 0) then
848 imix[i] := iix;
849 end;
850 PageCount := 0;
851 end;
852 for i := 0 to 5 do
853 if imix[i] >= 0 then
854 begin
855 iix := imix[i];
856 x := xZoomMap + 14 + 72 * (i mod 3);
857 y := yZoomMap + 14 + 56 * (i div 3);
858 ImpImage(offscreen.Canvas, x, y, iix, cGov, AllowChange and
859 (ClientMode < scContact));
860 if IsCityAlive then
861 begin
862 if iix = imColosseum then
863 begin
864 Sprite(offscreen, HGrSystem, x + 46, y, 14, 14, 82, 100);
865 end
866 else
867 begin
868 HappyGain := 0;
869 case iix of
870 0 .. 27, imTemple:
871 HappyGain := 2;
872 imTheater:
873 HappyGain := 4;
874 imCathedral:
875 if MyRO.Wonder[woBach].EffectiveOwner = cOwner then
876 HappyGain := 6
877 else
878 HappyGain := 4;
879 end;
880 if HappyGain > 1 then
881 begin
882 d := 30 div (HappyGain - 1);
883 if d > 10 then
884 d := 10
885 end;
886 for j := 0 to HappyGain - 1 do
887 Sprite(offscreen, HGrSystem, x + 50, y + d * j, 10, 10, 132, 126);
888 end;
889 for j := 0 to Imp[iix].Maint - 1 do
890 Sprite(offscreen, HGrSystem, x - 4, y + 29 - 3 * j, 10, 10,
891 132, 115);
892 end
893 end;
894 if imix[0] >= 0 then
895 Imp0Area.Hint := Phrases.Lookup('IMPROVEMENTS', imix[0])
896 else
897 Imp0Area.Hint := '';
898 if imix[1] >= 0 then
899 Imp1Area.Hint := Phrases.Lookup('IMPROVEMENTS', imix[1])
900 else
901 Imp1Area.Hint := '';
902 if imix[2] >= 0 then
903 Imp2Area.Hint := Phrases.Lookup('IMPROVEMENTS', imix[2])
904 else
905 Imp2Area.Hint := '';
906 if imix[3] >= 0 then
907 Imp3Area.Hint := Phrases.Lookup('IMPROVEMENTS', imix[3])
908 else
909 Imp3Area.Hint := '';
910 if imix[4] >= 0 then
911 Imp4Area.Hint := Phrases.Lookup('IMPROVEMENTS', imix[4])
912 else
913 Imp4Area.Hint := '';
914 if imix[5] >= 0 then
915 Imp5Area.Hint := Phrases.Lookup('IMPROVEMENTS', imix[5])
916 else
917 Imp5Area.Hint := '';
918 end
919 else { if SmallMapMode = smSupportedUnits then }
920 begin
921 LoweredTextout(offscreen.Canvas, -1, MainTexture, xZoomMap + 6,
922 yZoomMap + 2, Phrases.Lookup('SUPUNITS'));
923 FreeSupp := c.Size * SupportFree[cGov] shr 1;
924 Cnt := 0;
925 for i := 0 to MyRO.nUn - 1 do
926 if (MyUn[i].Loc >= 0) and (MyUn[i].Home = cix) then
927 with MyModel[MyUn[i].mix] do
928 begin
929 Server(sGetUnitReport, me, i, UnitReport);
930 if (Cnt >= 6 * Page) and (Cnt < 6 * (Page + 1)) then
931 begin // unit visible in display
932 imix[Cnt - 6 * Page] := i;
933 x := ((Cnt - 6 * Page) mod 3) * 64 + xZoomMap;
934 y := ((Cnt - 6 * Page) div 3) * 52 + yZoomMap + 20;
935 MakeUnitInfo(me, MyUn[i], UnitInfo);
936 NoMap.SetOutput(offscreen);
937 NoMap.PaintUnit(x, y, UnitInfo, MyUn[i].Status);
938
939 for j := 0 to UnitReport.FoodSupport - 1 do
940 Sprite(offscreen, HGrSystem, x + 38 + 11 * j, y + 40, 10,
941 10, 66, 115);
942 for j := 0 to UnitReport.ProdSupport - 1 do
943 begin
944 if (FreeSupp > 0) and
945 (UnitReport.ReportFlags and urfAlwaysSupport = 0) then
946 begin
947 Sprite(offscreen, HGrSystem, x + 16 - 11 * j, y + 40, 10,
948 10, 143, 115);
949 dec(FreeSupp);
950 end
951 else
952 Sprite(offscreen, HGrSystem, x + 16 - 11 * j, y + 40, 10,
953 10, 88, 115);
954 end;
955 if UnitReport.ReportFlags and urfDeployed <> 0 then
956 for j := 0 to 1 do
957 Sprite(offscreen, HGrSystem, x + 27 + 11 * j, y + 40, 10,
958 10, 154, 126)
959 end // unit visible in display
960 else
961 dec(FreeSupp, UnitReport.ProdSupport);
962 inc(Cnt);
963 end;
964 PageCount := (Cnt + 5) div 6;
965 Imp0Area.Hint := '';
966 Imp1Area.Hint := '';
967 Imp2Area.Hint := '';
968 Imp3Area.Hint := '';
969 Imp4Area.Hint := '';
970 Imp5Area.Hint := '';
971 end;
972 PageUpBtn.Visible := PageCount > 1;
973 PageDownBtn.Visible := PageCount > 1;
974
975 with offscreen.Canvas do
976 begin
977 { display project now }
978 DLine(offscreen.Canvas, xView + 9 + xSizeBig, xProd + 2 * wBar + 10,
979 yProd + dyBar + 16, $FFFFFF, $B0B0B0);
980 if ProdHint then
981 begin
982 ScreenTools.Frame(offscreen.Canvas, xView + 9 - 1, yView + 5 - 1,
983 xView + 9 + xSizeBig, yView + 5 + ySizeBig, $B0B0B0, $FFFFFF);
984 RFrame(offscreen.Canvas, xView + 9 - 2, yView + 5 - 2,
985 xView + 9 + xSizeBig + 1, yView + 5 + ySizeBig + 1, $FFFFFF, $B0B0B0);
986 with offscreen.Canvas do
987 begin
988 brush.Color := $000000;
989 FillRect(Rect(xView + 9, yView + 5, xView + 1 + 72 - 8,
990 yView + 5 + 40));
991 brush.style := bsClear;
992 end;
993 end
994 else if AllowChange and (c.Status and 7 <> 0) then
995 begin // city type autobuild
996 FrameImage(offscreen.Canvas, bigimp, xView + 9, yView + 5, xSizeBig,
997 ySizeBig, (c.Status and 7 - 1 + 3) * xSizeBig, 0, (cix >= 0) and
998 (ClientMode < scContact));
999 end
1000 else if c.Project and cpImp = 0 then
1001 begin // project is unit
1002 FrameImage(offscreen.Canvas, bigimp, xView + 9, yView + 5, xSizeBig,
1003 ySizeBig, 0, 0, AllowChange and (ClientMode < scContact));
1004 with Tribe[cOwner].ModelPicture[c.Project and cpIndex] do
1005 Sprite(offscreen, HGr, xView + 5, yView + 1, 64, 44,
1006 pix mod 10 * 65 + 1, pix div 10 * 49 + 1);
1007 end
1008 else
1009 begin // project is building
1010 if ProdHint then
1011 Paintiix := c.Project0 and cpIndex
1012 else
1013 Paintiix := c.Project and cpIndex;
1014 ImpImage(offscreen.Canvas, xView + 9, yView + 5, Paintiix, cGov,
1015 AllowChange and (ClientMode < scContact));
1016 end;
1017 end;
1018
1019 if AllowChange and (ClientMode < scContact) then
1020 begin
1021 i := Server(sBuyCityProject - sExecute, me, cix, nil^);
1022 BuyBtn.Visible := (i = eOk) or (i = eViolation);
1023 end
1024 else
1025 BuyBtn.Visible := false;
1026
1027 MarkUsedOffscreen(ClientWidth, ClientHeight);
1028end; { OffscreenPaint }
1029
1030procedure TCityDlg.FormShow(Sender: TObject);
1031var
1032 dx, dy, Loc1: integer;
1033 GetCityData: TGetCityData;
1034begin
1035 BlinkTime := 5;
1036 if cix >= 0 then
1037 begin { own city }
1038 c := MyCity[cix];
1039 cOwner := me;
1040 cGov := MyRO.Government;
1041 ProdHint := (cGov <> gAnarchy) and
1042 (Happened and (chProduction or chFounded or chCaptured or
1043 chAllImpsMade) <> 0);
1044 Server(sGetCityAreaInfo, me, cix, CityAreaInfo);
1045 NextCityBtn.Visible := WindowMode = wmPersistent;
1046 PrevCityBtn.Visible := WindowMode = wmPersistent;
1047 end
1048 else { enemy city }
1049 begin
1050 SmallMapMode := smImprovements;
1051 Server(sGetCity, me, cLoc, GetCityData);
1052 c := GetCityData.c;
1053 cOwner := GetCityData.Owner;
1054 cGov := MyRO.EnemyReport[cOwner].Government;
1055 Happened := c.Flags and $7FFFFFFF;
1056 ProdHint := false;
1057 Server(sGetEnemyCityAreaInfo, me, cLoc, CityAreaInfo);
1058
1059 if c.Project and cpImp = 0 then
1060 begin
1061 emix := MyRO.nEnemyModel - 1;
1062 while (emix > 0) and ((MyRO.EnemyModel[emix].Owner <> cOwner) or
1063 (integer(MyRO.EnemyModel[emix].mix) <> c.Project and cpIndex)) do
1064 dec(emix);
1065 if not Assigned(Tribe[cOwner].ModelPicture[c.Project and cpIndex].HGr) then
1066 InitEnemyModel(emix);
1067 end;
1068
1069 NextCityBtn.Visible := false;
1070 PrevCityBtn.Visible := false;
1071 end;
1072 Page := 0;
1073
1074 if c.Size < 5 then
1075 SizeClass := 0
1076 else if c.Size < 9 then
1077 SizeClass := 1
1078 else if c.Size < 13 then
1079 SizeClass := 2
1080 else
1081 SizeClass := 3;
1082
1083 // check if port
1084 IsPort := false;
1085 for dx := -2 to 2 do
1086 for dy := -2 to 2 do
1087 if abs(dx) + abs(dy) = 2 then
1088 begin
1089 Loc1 := dLoc(cLoc, dx, dy);
1090 if (Loc1 >= 0) and (Loc1 < G.lx * G.ly) and
1091 (MyMap[Loc1] and fTerrain < fGrass) then
1092 IsPort := true;
1093 end;
1094
1095 if WindowMode = wmModal then
1096 begin { center on screen }
1097 Left := (Screen.Width - Width) div 2;
1098 Top := (Screen.Height - Height) div 2;
1099 end;
1100
1101 Caption := CityName(c.ID);
1102
1103 InitSmallCityMap;
1104 InitZoomCityMap;
1105 OpenSoundEvent := -1;
1106 OffscreenPaint;
1107 Timer1.Enabled := true;
1108end;
1109
1110procedure TCityDlg.ShowNewContent(NewMode, Loc: integer; ShowEvent: cardinal);
1111begin
1112 if MyMap[Loc] and fOwned <> 0 then
1113 begin // own city
1114 cix := MyRO.nCity - 1;
1115 while (cix >= 0) and (MyCity[cix].Loc <> Loc) do
1116 dec(cix);
1117 assert(cix >= 0);
1118 if (Optimize_cixTileChange >= 0) and
1119 (Optimize_TilesBeforeChange and not MyCity[Optimize_cixTileChange].Tiles
1120 <> 0) then
1121 begin
1122 CityOptimizer_ReleaseCityTiles(Optimize_cixTileChange,
1123 Optimize_TilesBeforeChange and
1124 not MyCity[Optimize_cixTileChange].Tiles);
1125 if WindowMode <> wmModal then
1126 MainScreen.UpdateViews;
1127 end;
1128 Optimize_cixTileChange := cix;
1129 Optimize_TilesBeforeChange := MyCity[cix].Tiles;
1130 end
1131 else
1132 cix := -1;
1133 AllowChange := not supervising and (cix >= 0);
1134 cLoc := Loc;
1135 Happened := ShowEvent;
1136 inherited ShowNewContent(NewMode);
1137end;
1138
1139procedure TCityDlg.FormMouseDown(Sender: TObject; Button: TMouseButton;
1140 Shift: TShiftState; x, y: integer);
1141var
1142 i, qx, qy, dx, dy, fix, NewTiles, Loc1, iix, SellResult: integer;
1143 Rebuild: boolean;
1144begin
1145 if (ssLeft in Shift) and (x >= xSmallMap) and (x < xSmallMap + wSmallMap) and
1146 (y >= ySmallMap) and (y < ySmallMap + hSmallMap) then
1147 begin
1148 SmallMapMode := smImprovements;
1149 ZoomArea := (y - ySmallMap) * 3 div hSmallMap + 3 *
1150 ((x - xSmallMap) * 2 div wSmallMap);
1151 Page := 0;
1152 InitZoomCityMap;
1153 SmartUpdateContent;
1154 exit;
1155 end;
1156 if (ssLeft in Shift) and (x >= xSupport) and (x < xSupport + wSupport) and
1157 (y >= ySupport) and (y < ySupport + hSupport) then
1158 begin
1159 SmallMapMode := smSupportedUnits;
1160 Page := 0;
1161 InitZoomCityMap;
1162 SmartUpdateContent;
1163 exit;
1164 end;
1165 if not AllowChange then
1166 exit; // not an own city
1167
1168 if (ssLeft in Shift) then
1169 if (ClientMode < scContact) and (x >= xView) and (y >= yView) and
1170 (x < xView + 73) and (y < yView + 50) then
1171 if cGov = gAnarchy then
1172 with MessgExDlg do
1173 begin
1174 { MessgText:=Phrases.Lookup('OUTOFCONTROL');
1175 if c.Project and cpImp=0 then
1176 MessgText:=Format(MessgText,[Tribe[cOwner].ModelName[c.Project and cpIndex]])
1177 else MessgText:=Format(MessgText,[Phrases.Lookup('IMPROVEMENTS',c.Project and cpIndex)]); }
1178 MessgText := Phrases.Lookup('NOCHANGEINANARCHY');
1179 Kind := mkOk;
1180 ShowModal;
1181 end
1182 else
1183 begin
1184 if ProdHint then
1185 begin
1186 ProdHint := false;
1187 SmartUpdateContent
1188 end;
1189 ChooseProject;
1190 end
1191 else if (SmallMapMode = smImprovements) and (x >= xZoomMap) and (x < xZoomMap + wZoomMap) and
1192 (y >= yZoomMap) and (y < yZoomMap + hZoomMap) then
1193 begin
1194 i := 5;
1195 while (i >= 0) and not((x >= xZoomMap + 14 + 72 * (i mod 3)) and
1196 (x < xZoomMap + 14 + 56 + 72 * (i mod 3)) and
1197 (y >= yZoomMap + 14 + 56 * (i div 3)) and
1198 (y < yZoomMap + 14 + 40 + 56 * (i div 3))) do
1199 dec(i);
1200 if i >= 0 then
1201 begin
1202 iix := imix[i];
1203 if iix >= 0 then
1204 if ssShift in Shift then
1205 HelpDlg.ShowNewContent(FWindowMode or wmPersistent, hkImp, iix)
1206 else if (ClientMode < scContact) then
1207 with MessgExDlg do
1208 begin
1209 IconKind := mikImp;
1210 IconIndex := iix;
1211 if (iix = imPalace) or (Imp[iix].Kind = ikWonder) then
1212 begin
1213 MessgText := Phrases.Lookup('IMPROVEMENTS', iix);
1214 if iix = woOracle then
1215 MessgText := MessgText + '\' +
1216 Format(Phrases.Lookup('ORACLEINCOME'), [MyRO.OracleIncome]);
1217 Kind := mkOk;
1218 ShowModal;
1219 end
1220 else
1221 begin
1222 SellResult := Server(sSellCityImprovement - sExecute, me,
1223 cix, iix);
1224 if SellResult < rExecuted then
1225 begin
1226 if SellResult = eOnlyOnce then
1227 MessgText := Phrases.Lookup('NOSELLAGAIN')
1228 else
1229 MessgText := Phrases.Lookup('OUTOFCONTROL');
1230 MessgText := Format(MessgText,
1231 [Phrases.Lookup('IMPROVEMENTS', iix)]);
1232 Kind := mkOk;
1233 ShowModal;
1234 end
1235 else
1236 begin
1237 if Server(sRebuildCityImprovement - sExecute, me, cix, iix) < rExecuted
1238 then
1239 begin // no rebuild possible, ask for sell only
1240 Rebuild := false;
1241 MessgText := Phrases.Lookup('IMPROVEMENTS', iix);
1242 if not Phrases2FallenBackToEnglish then
1243 MessgText := Format(Phrases2.Lookup('SELL2'),
1244 [MessgText, Imp[iix].Cost * BuildCostMod
1245 [G.Difficulty[me]] div 12])
1246 else
1247 MessgText := Format(Phrases.Lookup('SELL'), [MessgText]);
1248 if iix = imSpacePort then
1249 with MyRO.Ship[me] do
1250 if Parts[0] + Parts[1] + Parts[2] > 0 then
1251 MessgText := MessgText + ' ' +
1252 Phrases.Lookup('SPDESTRUCTQUERY');
1253 Kind := mkYesNo;
1254 ShowModal;
1255 if ModalResult <> mrOK then
1256 iix := -1
1257 end
1258 else
1259 begin
1260 Rebuild := true;
1261 MessgText := Phrases.Lookup('IMPROVEMENTS', iix);
1262 if not Phrases2FallenBackToEnglish then
1263 MessgText := Format(Phrases2.Lookup('DISPOSE2'),
1264 [MessgText, Imp[iix].Cost * BuildCostMod
1265 [G.Difficulty[me]] div 12 * 2 div 3])
1266 else
1267 MessgText := Format(Phrases.Lookup('DISPOSE'),
1268 [MessgText]);
1269 if iix = imSpacePort then
1270 with MyRO.Ship[me] do
1271 if Parts[0] + Parts[1] + Parts[2] > 0 then
1272 MessgText := MessgText + ' ' +
1273 Phrases.Lookup('SPDESTRUCTQUERY');
1274 Kind := mkYesNo;
1275 ShowModal;
1276 if ModalResult <> mrOK then
1277 iix := -1
1278 end;
1279 if iix >= 0 then
1280 begin
1281 if Rebuild then
1282 begin
1283 Play('CITY_REBUILDIMP');
1284 Server(sRebuildCityImprovement, me, cix, iix);
1285 end
1286 else
1287 begin
1288 Play('CITY_SELLIMP');
1289 Server(sSellCityImprovement, me, cix, iix);
1290 end;
1291 CityOptimizer_CityChange(cix);
1292 InitSmallCityMap;
1293 SmartUpdateContent;
1294 if WindowMode <> wmModal then
1295 MainScreen.UpdateViews;
1296 end;
1297 end;
1298 end;
1299 end;
1300 end;
1301 end
1302 else if (SmallMapMode = smSupportedUnits) and (x >= xZoomMap) and (x < xZoomMap + wZoomMap) and
1303 (y >= yZoomMap) and (y < yZoomMap + hZoomMap) then
1304 begin
1305 i := 5;
1306 while (i >= 0) and not((x >= xZoomMap + 64 * (i mod 3)) and
1307 (x < xZoomMap + 64 + 64 * (i mod 3)) and
1308 (y >= yZoomMap + 20 + 48 * (i div 3)) and
1309 (y < yZoomMap + 20 + 52 + 48 * (i div 3))) do
1310 dec(i);
1311 if (i >= 0) and (imix[i] >= 0) then
1312 if ssShift in Shift then
1313 else if (cix >= 0) and (ClientMode < scContact) and
1314 (WindowMode <> wmModal) then
1315 begin
1316 CloseAction := None;
1317 Close;
1318 MainScreen.CityClosed(imix[i], false, true);
1319 end;
1320 end
1321 else if (x >= xmArea - 192) and (x < xmArea + 192) and (y >= ymArea - 96)
1322 and (y < ymArea + 96) then
1323 with AreaMap do begin
1324 qx := ((4000 * xxt * yyt) + (x - xmArea) * (yyt * 2) + (y - ymArea + yyt)
1325 * (xxt * 2)) div (xxt * yyt * 4) - 1000;
1326 qy := ((4000 * xxt * yyt) + (y - ymArea + yyt) * (xxt * 2) - (x - xmArea)
1327 * (yyt * 2)) div (xxt * yyt * 4) - 1000;
1328 dx := qx - qy;
1329 dy := qx + qy;
1330 if (dx >= -3) and (dx <= 3) and (dy >= -3) and (dy <= 3) and
1331 (dx * dx * dy * dy < 81) and ((dx <> 0) or (dy <> 0)) then
1332 if ssShift in Shift then
1333 begin // terrain help
1334 Loc1 := dLoc(cLoc, dx, dy);
1335 if (Loc1 >= 0) and (Loc1 < G.lx * G.ly) then
1336 HelpOnTerrain(Loc1, FWindowMode or wmPersistent)
1337 end
1338 else if (ClientMode < scContact) and (cGov <> gAnarchy) and
1339 (c.Flags and chCaptured = 0) then
1340 begin // toggle exploitation
1341 assert(not supervising);
1342 if c.Status and csResourceWeightsMask <> 0 then
1343 begin
1344 with MessgExDlg do
1345 begin
1346 MessgText := Phrases.Lookup('CITYMANAGEOFF');
1347 OpenSound := 'MSG_DEFAULT';
1348 Kind := mkOkCancel;
1349 IconKind := mikFullControl;
1350 ShowModal;
1351 end;
1352 if MessgExDlg.ModalResult = mrOK then
1353 begin
1354 MyCity[cix].Status := MyCity[cix].Status and
1355 not csResourceWeightsMask; // off
1356 c.Status := MyCity[cix].Status;
1357 SmartUpdateContent;
1358 end;
1359 exit;
1360 end;
1361 fix := (dy + 3) shl 2 + (dx + 3) shr 1;
1362 NewTiles := MyCity[cix].Tiles xor (1 shl fix);
1363 if Server(sSetCityTiles, me, cix, NewTiles) >= rExecuted then
1364 begin
1365 SmartUpdateContent;
1366 if WindowMode <> wmModal then
1367 MainScreen.UpdateViews;
1368 end;
1369 end;
1370 end
1371 else if (ClientMode < scContact) and (cGov <> gAnarchy) and
1372 (c.Flags and chCaptured = 0) and (x >= xmOpt - 32) and (x < xmOpt + 32)
1373 and (y >= ymOpt - 32) and (y < ymOpt + 32) then
1374 begin
1375 i := sqr(x - xmOpt) + sqr(y - ymOpt); // click radius
1376 if i <= 32 * 32 then
1377 begin
1378 if i < 16 * 16 then // inner area clicked
1379 if c.Status and csResourceWeightsMask <> 0 then
1380 i := (c.Status shr 4 and $0F) mod 5 + 1 // rotate except off
1381 else
1382 i := 3 // rwGrowth
1383 else
1384 case trunc(arctan2(x - xmOpt, ymOpt - y) * 180 / pi) of
1385 - 25 - 52 * 2 .. -26 - 52:
1386 i := 1;
1387 -25 - 52 .. -26:
1388 i := 2;
1389 -25 .. 25:
1390 i := 3;
1391 26 .. 25 + 52:
1392 i := 4;
1393 26 + 52 .. 25 + 52 * 2:
1394 i := 5;
1395 180 - 26 .. 180, -180 .. -180 + 26:
1396 i := 0;
1397 else
1398 i := -1;
1399 end;
1400 if i >= 0 then
1401 begin
1402 ChangeResourceWeights(i);
1403 SmartUpdateContent;
1404 if WindowMode <> wmModal then
1405 MainScreen.UpdateViews;
1406 end;
1407 end;
1408 end;
1409end; { FormMouseDown }
1410
1411procedure TCityDlg.ChooseProject;
1412type
1413 TProjectType = (
1414 ptSelect = 0,
1415 ptTrGoods = 1,
1416 ptUn = 2,
1417 ptCaravan = 3,
1418 ptImp = 4,
1419 ptWonder = 6,
1420 ptShip = 7,
1421 ptInvalid = 8
1422 );
1423
1424 function ProjectType(Project: integer): TProjectType;
1425 begin
1426 if Project and cpCompleted <> 0 then
1427 Result := ptSelect
1428 else if Project and (cpImp + cpIndex) = cpImp + imTrGoods then
1429 Result := ptTrGoods
1430 else if Project and cpImp = 0 then begin
1431 if MyModel[Project and cpIndex].Kind = mkCaravan then
1432 Result := ptCaravan
1433 else Result := ptUn;
1434 end
1435 else if Project and cpIndex >= nImp then
1436 Result := ptInvalid
1437 else if Imp[Project and cpIndex].Kind = ikWonder then
1438 Result := ptWonder
1439 else if Imp[Project and cpIndex].Kind = ikShipPart then
1440 Result := ptShip
1441 else
1442 Result := ptImp;
1443 end;
1444
1445var
1446 NewProject, OldMoney, cix1: integer;
1447 pt0, pt1: TProjectType;
1448 QueryOk: boolean;
1449begin
1450 Assert(not supervising);
1451 ModalSelectDlg.ShowNewContent_CityProject(wmModal, cix);
1452 if ModalSelectDlg.result <> -1 then
1453 begin
1454 if ModalSelectDlg.result and cpType <> 0 then
1455 begin
1456 MyCity[cix].Status := MyCity[cix].Status and not 7 or
1457 (1 + ModalSelectDlg.result and cpIndex);
1458 AutoBuild(cix, MyData.ImpOrder[ModalSelectDlg.result and cpIndex]);
1459 end
1460 else
1461 begin
1462 NewProject := ModalSelectDlg.Result;
1463 QueryOk := True;
1464 if (NewProject and cpImp <> 0) and (NewProject and cpIndex >= 28) and
1465 (MyRO.NatBuilt[NewProject and cpIndex] > 0) then
1466 with MessgExDlg do
1467 begin
1468 cix1 := MyRO.nCity - 1;
1469 while (cix1 >= 0) and
1470 (MyCity[cix1].Built[NewProject and cpIndex] = 0) do
1471 Dec(cix1);
1472 MessgText := Format(Phrases.Lookup('DOUBLESTATEIMP'),
1473 [Phrases.Lookup('IMPROVEMENTS', NewProject and cpIndex),
1474 CityName(MyCity[cix1].ID)]);
1475 OpenSound := 'MSG_DEFAULT';
1476 Kind := mkOkCancel;
1477 IconKind := mikImp;
1478 IconIndex := NewProject and cpIndex;
1479 ShowModal;
1480 QueryOk := ModalResult = mrOK;
1481 end;
1482 if not QueryOk then
1483 Exit;
1484
1485 if (MyCity[cix].Prod > 0) then
1486 begin
1487 pt0 := ProjectType(MyCity[cix].Project0);
1488 pt1 := ProjectType(NewProject);
1489 if (pt0 <> ptSelect) and (pt1 <> ptTrGoods) then
1490 begin
1491 if NewProject and (cpImp or cpIndex) <> MyCity[cix].Project0 and
1492 (cpImp or cpIndex) then
1493 begin // loss of material -- do query
1494 Gtk2Fix;
1495 if (pt1 = ptTrGoods) or (pt1 = ptShip) or (pt1 <> pt0) and
1496 (pt0 <> ptCaravan) then begin
1497 QueryOk := SimpleQuery(mkOkCancel,
1498 Format(Phrases.Lookup('LOSEMAT'), [MyCity[cix].Prod0,
1499 MyCity[cix].Prod0]), 'MSG_DEFAULT') = mrOK
1500 end else
1501 if MyCity[cix].Project and (cpImp or cpIndex) = MyCity[cix]
1502 .Project0 and (cpImp or cpIndex) then begin
1503 QueryOk := SimpleQuery(mkOkCancel, Phrases.Lookup('LOSEMAT3'),
1504 'MSG_DEFAULT') = mrOK;
1505 end;
1506 end;
1507 end;
1508 end;
1509 if not QueryOk then
1510 Exit;
1511
1512 OldMoney := MyRO.Money;
1513 MyCity[cix].Status := MyCity[cix].Status and not 7;
1514 if (NewProject and cpImp = 0) and
1515 ((MyCity[cix].Size < 4) and
1516 (MyModel[NewProject and cpIndex].Kind = mkSettler) or
1517 (MyCity[cix].Size < 3) and
1518 ((MyModel[NewProject and cpIndex].Kind = mkSlaves) or
1519 (NewProject and cpConscripts <> 0))) then
1520 if SimpleQuery(mkYesNo, Phrases.Lookup('EMIGRATE'), 'MSG_DEFAULT') <> mrOK
1521 then
1522 NewProject := NewProject or cpDisbandCity;
1523 Server(sSetCityProject, me, cix, NewProject);
1524 c.Project := MyCity[cix].Project;
1525 if MyRO.Money > OldMoney then
1526 Play('CITY_SELLIMP');
1527 end;
1528 CityOptimizer_CityChange(cix);
1529
1530 if WindowMode <> wmModal then
1531 MainScreen.UpdateViews;
1532 InitSmallCityMap;
1533 SmartUpdateContent;
1534 end;
1535end;
1536
1537procedure TCityDlg.BuyClick(Sender: TObject);
1538var
1539 NextProd, Cost: integer;
1540begin
1541 if (cix < 0) or (ClientMode >= scContact) then
1542 exit;
1543 with MyCity[cix], MessgExDlg do
1544 begin
1545 Cost := Report.ProjectCost;
1546 NextProd := Report.Production;
1547 if NextProd < 0 then
1548 NextProd := 0;
1549 Cost := Cost - Prod - NextProd;
1550 if (MyRO.Wonder[woMich].EffectiveOwner = me) and (Project and cpImp <> 0)
1551 then
1552 Cost := Cost * 2
1553 else
1554 Cost := Cost * 4;
1555 if (Cost <= 0) and (Report.HappinessBalance >= 0) { no disorder } then
1556 begin
1557 MessgText := Phrases.Lookup('READY');
1558 Kind := mkOk;
1559 end
1560 else if Cost > MyRO.Money then
1561 begin
1562 OpenSound := 'MSG_DEFAULT';
1563 MessgText := Format(Phrases.Lookup('NOMONEY'), [Cost, MyRO.Money]);
1564 Kind := mkOk;
1565 end
1566 else
1567 begin
1568 MessgText := Format(Phrases.Lookup('BUY'), [Cost]);
1569 Kind := mkYesNo;
1570 end;
1571 ShowModal;
1572 if (Kind = mkYesNo) and (ModalResult = mrOK) then
1573 begin
1574 if Server(sBuyCityProject, me, cix, nil^) >= rExecuted then
1575 begin
1576 Play('CITY_BUYPROJECT');
1577 SmartUpdateContent;
1578 if WindowMode <> wmModal then
1579 MainScreen.UpdateViews;
1580 end;
1581 end;
1582 end;
1583end;
1584
1585procedure TCityDlg.FormClose(Sender: TObject; var Action: TCloseAction);
1586begin
1587 Timer1.Enabled := false;
1588 ProdHint := false;
1589 MarkCityLoc := -1;
1590 if Optimize_cixTileChange >= 0 then
1591 begin
1592 if Optimize_TilesBeforeChange and not MyCity[Optimize_cixTileChange]
1593 .Tiles <> 0 then
1594 begin
1595 CityOptimizer_ReleaseCityTiles(Optimize_cixTileChange,
1596 Optimize_TilesBeforeChange and
1597 not MyCity[Optimize_cixTileChange].Tiles);
1598 if WindowMode <> wmModal then
1599 MainScreen.UpdateViews;
1600 end;
1601 Optimize_cixTileChange := -1;
1602 end;
1603 if CloseAction > None then
1604 MainScreen.CityClosed(RestoreUnFocus, CloseAction = StepFocus);
1605 RestoreUnFocus := -1;
1606 inherited;
1607end;
1608
1609procedure TCityDlg.Timer1Timer(Sender: TObject);
1610begin
1611 if ProdHint then
1612 begin
1613 BlinkTime := (BlinkTime + 1) mod 12;
1614 if BlinkTime = 0 then
1615 with Canvas do
1616 begin
1617 BitBltCanvas(Canvas, xView + 5, yView + 1, 64, 2, Back.Canvas,
1618 xView + 5, yView + 1);
1619 BitBltCanvas(Canvas, xView + 5, yView + 3, 2, 42, Back.Canvas,
1620 xView + 5, yView + 3);
1621 BitBltCanvas(Canvas, xView + 5 + 62, yView + 3, 2, 42,
1622 Back.Canvas, xView + 5 + 62, yView + 3);
1623 ScreenTools.Frame(Canvas, xView + 9 - 1, yView + 5 - 1, xView + 9 + xSizeBig,
1624 yView + 5 + ySizeBig, $B0B0B0, $FFFFFF);
1625 RFrame(Canvas, xView + 9 - 2, yView + 5 - 2, xView + 9 + xSizeBig + 1,
1626 yView + 5 + ySizeBig + 1, $FFFFFF, $B0B0B0);
1627 Brush.Color := $000000;
1628 FillRect(Rect(xView + 9, yView + 5, xView + 1 + 72 - 8,
1629 yView + 5 + 40));
1630 Brush.style := bsClear;
1631 end
1632 else if BlinkTime = 6 then
1633 begin
1634 if AllowChange and (c.Status and 7 <> 0) then
1635 begin // city type autobuild
1636 FrameImage(Canvas, bigimp, xView + 9, yView + 5, xSizeBig, ySizeBig,
1637 (c.Status and 7 - 1 + 3) * xSizeBig, 0, true);
1638 end
1639 else if c.Project and cpImp = 0 then
1640 begin // project is unit
1641 BitBltCanvas(Canvas, xView + 9, yView + 5, xSizeBig, ySizeBig,
1642 Bigimp.Canvas, 0, 0);
1643 with Tribe[cOwner].ModelPicture[c.Project and cpIndex] do
1644 Sprite(Canvas, HGr, xView + 5, yView + 1, 64, 44, pix mod 10 * 65 + 1,
1645 pix div 10 * 49 + 1);
1646 end
1647 else
1648 ImpImage(Canvas, xView + 9, yView + 5, c.Project0 and cpIndex,
1649 cGov, true);
1650 end;
1651 end;
1652end;
1653
1654procedure TCityDlg.FormPaint(Sender: TObject);
1655begin
1656 inherited;
1657 if OpenSoundEvent >= 0 then
1658 PostMessage(Handle, WM_PLAYSOUND, 0, 0);
1659end;
1660
1661procedure TCityDlg.OnPlaySound(var Msg: TMessage);
1662begin
1663 if 1 shl OpenSoundEvent = chProduction then
1664 begin
1665 if c.Project0 and cpImp <> 0 then
1666 begin
1667 if c.Project0 and cpIndex >= 28 then
1668 // wonders have already extra message with sound
1669 if Imp[c.Project0 and cpIndex].Kind = ikShipPart then
1670 Play('SHIP_BUILT')
1671 else
1672 Play('CITY_IMPCOMPLETE')
1673 end
1674 else
1675 Play('CITY_UNITCOMPLETE');
1676 end
1677 else
1678 if OpenSoundEvent >= 0 then
1679 Play(CityEventSoundItem[OpenSoundEvent]);
1680 OpenSoundEvent := -2;
1681end;
1682
1683function Prio(iix: integer): integer;
1684begin
1685 case Imp[iix].Kind of
1686 ikWonder:
1687 result := iix + 10000;
1688 ikNatLocal, ikNatGlobal:
1689 case iix of
1690 imPalace:
1691 result := 0;
1692 else
1693 result := iix + 20000;
1694 end;
1695 else
1696 case iix of
1697 imTownHall, imCourt:
1698 result := iix + 30000;
1699 imAqueduct, imSewer:
1700 result := iix + 40000;
1701 imTemple, imTheater, imCathedral:
1702 result := iix + 50000;
1703 else
1704 result := iix + 90000;
1705 end;
1706 end;
1707end;
1708
1709procedure TCityDlg.NextCityBtnClick(Sender: TObject);
1710begin
1711 ChangeCity(+1);
1712end;
1713
1714procedure TCityDlg.PrevCityBtnClick(Sender: TObject);
1715begin
1716 ChangeCity(-1);
1717end;
1718
1719procedure TCityDlg.ChangeCity(d: integer);
1720var
1721 cixNew: integer;
1722begin
1723 cixNew := cix;
1724 repeat
1725 cixNew := (cixNew + MyRO.nCity + d) mod MyRO.nCity;
1726 until (MyCity[cixNew].Loc >= 0) or (cixNew = cix);
1727 if cixNew <> cix then
1728 MainScreen.ZoomToCity(MyCity[cixNew].Loc);
1729end;
1730
1731procedure TCityDlg.FormKeyDown(Sender: TObject; var Key: Word;
1732 Shift: TShiftState);
1733begin
1734 if ((Key = VK_UP) or (Key = VK_NUMPAD8)) and (cix >= 0) and
1735 (WindowMode = wmPersistent) then
1736 ChangeCity(-1)
1737 else if ((Key = VK_DOWN) or (Key = VK_NUMPAD2)) and (cix >= 0) and
1738 (WindowMode = wmPersistent) then
1739 ChangeCity(+1)
1740 else
1741 inherited;
1742end;
1743
1744{ procedure TCityDlg.AdviceBtnClick(Sender: TObject);
1745 begin
1746 AdvisorDlg.GiveCityAdvice(cix);
1747 end; }
1748
1749procedure TCityDlg.PageUpBtnClick(Sender: TObject);
1750begin
1751 if Page > 0 then
1752 begin
1753 dec(Page);
1754 SmartUpdateContent;
1755 end;
1756end;
1757
1758procedure TCityDlg.PageDownBtnClick(Sender: TObject);
1759begin
1760 if Page < PageCount - 1 then
1761 begin
1762 inc(Page);
1763 SmartUpdateContent;
1764 end;
1765end;
1766
1767procedure TCityDlg.ChangeResourceWeights(iResourceWeights: integer);
1768var
1769 Advice: TCityTileAdviceData;
1770begin
1771 assert(not supervising);
1772 assert(cix >= 0);
1773 MyCity[cix].Status := MyCity[cix].Status and not csResourceWeightsMask or
1774 (iResourceWeights shl 4);
1775 c.Status := MyCity[cix].Status;
1776 if iResourceWeights > 0 then
1777 begin
1778 Advice.ResourceWeights := OfferedResourceWeights[iResourceWeights];
1779 Server(sGetCityTileAdvice, me, cix, Advice);
1780 if Advice.Tiles <> MyCity[cix].Tiles then
1781 Server(sSetCityTiles, me, cix, Advice.Tiles);
1782 end;
1783end;
1784
1785procedure SortImprovements;
1786var
1787 i, j, k: integer;
1788begin
1789 for i := 0 to nImp - 1 do
1790 ImpSorted[i] := i;
1791 for i := 0 to nImp - 2 do
1792 for j := i + 1 to nImp - 1 do
1793 if Prio(ImpSorted[i]) > Prio(ImpSorted[j]) then begin
1794 k := ImpSorted[i];
1795 ImpSorted[i] := ImpSorted[j];
1796 ImpSorted[j] := k;
1797 end;
1798end;
1799
1800initialization
1801
1802SortImprovements;
1803
1804end.
Note: See TracBrowser for help on using the repository browser.