source: tags/1.3.1/LocalPlayer/CityScreen.pas

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