source: tags/1.2.0/LocalPlayer/CityScreen.pas

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