source: trunk/LocalPlayer/CityScreen.pas@ 328

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