Changeset 6 for trunk/LocalPlayer/Term.pas
- Timestamp:
- Jan 7, 2017, 11:32:14 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LocalPlayer/Term.pas
r2 r6 1 1 {$INCLUDE switches} 2 3 2 unit Term; 4 3 … … 6 5 7 6 uses 8 Protocol,Tribes,PVSB,ClientTools,ScreenTools,BaseWin,Messg,ButtonBase, 9 10 Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Menus,ExtCtrls, 11 ButtonA,ButtonB, ButtonC, EOTButton, Area; 7 Protocol, Tribes, PVSB, ClientTools, ScreenTools, BaseWin, Messg, ButtonBase, 8 9 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Menus, 10 ExtCtrls, 11 ButtonA, ButtonB, ButtonC, EOTButton, Area; 12 12 13 13 const 14 WM_EOT=WM_USER; 15 16 pltsNormal=0; pltsBlink=1; 14 WM_EOT = WM_USER; 15 16 pltsNormal = 0; 17 pltsBlink = 1; 17 18 18 19 type 19 20 TMainScreen = class(TDrawDlg) 20 Timer1: TTimer;21 Timer1: TTimer; 21 22 GamePopup: TPopupMenu; 22 UnitPopup: TPopupMenu;23 mIrrigation: TMenuItem;24 mCity: TMenuItem;25 mRoad: TMenuItem;26 mMine: TMenuItem;27 mPollution: TMenuItem;28 mHome: TMenuItem;23 UnitPopup: TPopupMenu; 24 mIrrigation: TMenuItem; 25 mCity: TMenuItem; 26 mRoad: TMenuItem; 27 mMine: TMenuItem; 28 mPollution: TMenuItem; 29 mHome: TMenuItem; 29 30 mStay: TMenuItem; 30 mDisband: TMenuItem;31 mWait: TMenuItem;32 mNoOrders: TMenuItem;33 MTrans: TMenuItem;31 mDisband: TMenuItem; 32 mWait: TMenuItem; 33 mNoOrders: TMenuItem; 34 MTrans: TMenuItem; 34 35 UnitBtn: TButtonB; 35 36 mResign: TMenuItem; … … 163 164 N12: TMenuItem; 164 165 mRep14: TMenuItem; 165 procedure FormCreate(Sender:TObject); 166 procedure FormDestroy(Sender:TObject); 167 procedure Timer1Timer(Sender:TObject); 168 procedure MapBoxMouseDown(Sender:TObject;Button:TMouseButton; 169 Shift:TShiftState;x,y:integer); 170 procedure EOTClick(Sender:TObject); 171 procedure PanelBoxMouseDown(Sender:TObject;Button:TMouseButton; 172 Shift:TShiftState;x,y:integer); 173 procedure FormKeyDown(Sender:TObject;var Key:word; 174 Shift:TShiftState); 175 procedure MenuClick(Sender:TObject); 176 procedure FormResize(Sender:TObject); 166 procedure FormCreate(Sender: TObject); 167 procedure FormDestroy(Sender: TObject); 168 procedure Timer1Timer(Sender: TObject); 169 procedure MapBoxMouseDown(Sender: TObject; Button: TMouseButton; 170 Shift: TShiftState; x, y: integer); 171 procedure EOTClick(Sender: TObject); 172 procedure PanelBoxMouseDown(Sender: TObject; Button: TMouseButton; 173 Shift: TShiftState; x, y: integer); 174 procedure FormKeyDown(Sender: TObject; var Key: word; Shift: TShiftState); 175 procedure MenuClick(Sender: TObject); 176 procedure FormResize(Sender: TObject); 177 177 procedure PanelBtnClick(Sender: TObject); 178 178 procedure FormCloseQuery(Sender: TObject; var CanClose: boolean); 179 179 procedure Toggle(Sender: TObject); 180 procedure PanelBoxMouseMove(Sender: TObject; Shift: TShiftState; x,181 y: integer);180 procedure PanelBoxMouseMove(Sender: TObject; Shift: TShiftState; 181 x, y: integer); 182 182 procedure PanelBoxMouseUp(Sender: TObject; Button: TMouseButton; 183 183 Shift: TShiftState; x, y: integer); 184 procedure MapBoxMouseMove(Sender: TObject; Shift: TShiftState; x,185 y: integer);184 procedure MapBoxMouseMove(Sender: TObject; Shift: TShiftState; 185 x, y: integer); 186 186 procedure mShowClick(Sender: TObject); 187 187 procedure FormMouseDown(Sender: TObject; Button: TMouseButton; 188 188 Shift: TShiftState; x, y: integer); 189 procedure FormMouseMove(Sender: TObject; Shift: TShiftState; x, 190 y: integer); 189 procedure FormMouseMove(Sender: TObject; Shift: TShiftState; x, y: integer); 191 190 procedure FormMouseUp(Sender: TObject; Button: TMouseButton; 192 191 Shift: TShiftState; x, y: integer); … … 200 199 procedure mNamesClick(Sender: TObject); 201 200 procedure MapBtnClick(Sender: TObject); 202 procedure FormKeyUp(Sender: TObject; var Key: Word; 203 Shift: TShiftState); 201 procedure FormKeyUp(Sender: TObject; var Key: word; Shift: TShiftState); 204 202 procedure CreateUnitClick(Sender: TObject); 205 203 procedure mSoundOffClick(Sender: TObject); … … 217 215 public 218 216 procedure CreateParams(var p: TCreateParams); override; 219 procedure Client(Command, NewPlayer:integer;var Data);217 procedure Client(Command, NewPlayer: integer; var Data); 220 218 procedure SetAIName(p: integer; Name: string); 221 219 function ZoomToCity(Loc: integer; NextUnitOnClose: boolean = false; … … 229 227 230 228 private 231 xw,yw,xwd,ywd,xwMini,ywMini,xMidPanel,xRightPanel,xTroop,xTerrain,xMini, 232 yMini,ywmax,ywcenter,TroopLoc,TrCnt,TrRow,TrPitch,MapWidth,MapOffset, 233 MapHeight,BlinkTime,BrushLoc,EditLoc,xMouse,yMouse: integer; 229 xw, yw, xwd, ywd, xwMini, ywMini, xMidPanel, xRightPanel, xTroop, xTerrain, 230 xMini, yMini, ywmax, ywcenter, TroopLoc, TrCnt, TrRow, TrPitch, MapWidth, 231 MapOffset, MapHeight, BlinkTime, BrushLoc, EditLoc, xMouse, 232 yMouse: integer; 234 233 BrushType: Cardinal; 235 trix: array[0..63] of integer;236 AILogo: array [0..nPl-1] of TBitmap;237 Mini, Panel,TopBar: TBitmap;238 sb: TPVScrollbar;239 Closable, RepaintOnResize,Tracking,TurnComplete,Edited,GoOnPhase,234 trix: array [0 .. 63] of integer; 235 AILogo: array [0 .. nPl - 1] of TBitmap; 236 Mini, Panel, TopBar: TBitmap; 237 sb: TPVScrollbar; 238 Closable, RepaintOnResize, Tracking, TurnComplete, Edited, GoOnPhase, 240 239 HaveStrategyAdvice, FirstMovieTurn: boolean; 241 240 procedure ArrangeMidPanel; … … 246 245 procedure CopyMiniToPanel; 247 246 procedure PanelPaint; 248 procedure NextUnit(NearLoc: integer;AutoTurn:boolean);249 procedure Scroll(dx, dy: integer);250 procedure Centre(Loc: integer);251 procedure SetTroopLoc(Loc: integer);252 procedure ProcessRect(x0, y0,nx,ny,Options: integer);247 procedure NextUnit(NearLoc: integer; AutoTurn: boolean); 248 procedure Scroll(dx, dy: integer); 249 procedure Centre(Loc: integer); 250 procedure SetTroopLoc(Loc: integer); 251 procedure ProcessRect(x0, y0, nx, ny, Options: integer); 253 252 procedure PaintLoc(Loc: integer; Radius: integer = 0); 254 253 procedure PaintLoc_BeforeMove(FromLoc: integer); 255 254 procedure PaintLocTemp(Loc: integer; Style: integer = pltsNormal); 256 procedure PaintBufferToScreen(xMap, yMap,width,height: integer);255 procedure PaintBufferToScreen(xMap, yMap, width, height: integer); 257 256 procedure PaintDestination; 258 procedure SetUnFocus(uix: integer);259 function MoveUnit(dx, dy:integer; Options: integer = 0): integer;257 procedure SetUnFocus(uix: integer); 258 function MoveUnit(dx, dy: integer; Options: integer = 0): integer; 260 259 procedure MoveToLoc(Loc: integer; CheckSuicide: boolean); 261 procedure MoveOnScreen(ShowMove: TShowMove; Step0, Step1,nStep: integer;260 procedure MoveOnScreen(ShowMove: TShowMove; Step0, Step1, nStep: integer; 262 261 Restore: boolean = true); 263 procedure FocusOnLoc(Loc: integer; Options: integer = 0);262 procedure FocusOnLoc(Loc: integer; Options: integer = 0); 264 263 function EndTurn(WasSkipped: boolean = false): boolean; 265 264 procedure EndNego; 266 function IsPanelPixel(x, y: integer): boolean;265 function IsPanelPixel(x, y: integer): boolean; 267 266 procedure InitPopup(Popup: TPopupMenu); 268 267 procedure SetMapOptions; … … 272 271 procedure SetDebugMap(p: integer); 273 272 procedure SetViewpoint(p: integer); 274 function LocationOfScreenPixel(x, y: integer): integer;275 procedure SetTileSize(x, y: integer);276 procedure RectInvalidate(Left, Top,Rigth,Bottom: integer);277 procedure SmartRectInvalidate(Left, Top,Rigth,Bottom: integer);273 function LocationOfScreenPixel(x, y: integer): integer; 274 procedure SetTileSize(x, y: integer); 275 procedure RectInvalidate(Left, Top, Rigth, Bottom: integer); 276 procedure SmartRectInvalidate(Left, Top, Rigth, Bottom: integer); 278 277 procedure SaveSettings; 279 procedure OnScroll(var m: TMessage); message WM_VSCROLL;280 procedure OnEOT(var Msg: TMessage); message WM_EOT;278 procedure OnScroll(var m: TMessage); message WM_VSCROLL; 279 procedure OnEOT(var Msg: TMessage); message WM_EOT; 281 280 end; 282 281 283 282 var 284 MainScreen:TMainScreen;283 MainScreen: TMainScreen; 285 284 286 285 type 287 TTribeInfo=record288 trix: integer;289 FileName: ShortString;286 TTribeInfo = record 287 trix: integer; 288 FileName: ShortString; 290 289 end; 291 TCityNameInfo=record 292 ID: integer; 293 NewName: ShortString 294 end; 295 TModelNameInfo=record 296 mix: integer; 297 NewName: ShortString 298 end; 299 TPriceSet=Set of $00..$FF; 300 301 const 302 crImpDrag=2; 303 crFlatHand=3; 304 305 xxu=32; yyu=24; // half of unit slot size x/y 306 yyu_anchor=32; 307 xxc=32; yyc=16; // 1/2 of city slot size in x, 1/2 of ground tile size in y (=1/3 of slot) 308 309 // layout 310 TopBarHeight=41; 311 PanelHeight=168; 312 MidPanelHeight=120; // TopBarHeight+MidPanelHeight should be same as BaseWin.yUnused 313 MapCenterUp=(MidPanelHeight-TopBarHeight) div 2; 314 315 nCityType=4; 316 317 {client exclusive commands:} 318 cSetTribe=$9000;cSetNewModelPicture=$9100;cSetModelName=$9110; 319 cSetModelPicture=$9120;cSetSlaveIndex=$9131; 320 cSetCityName=$9200; 321 322 // city status flags 323 csTypeMask=$0007; csToldDelay=$0008; csResourceWeightsMask=$00F0; 324 csToldBombard=$0100; 325 326 {unit status flags} 327 usStay=$01; usWaiting=$02; usGoto=$04; usEnhance=$08; usRecover=$10; 328 usToldNoReturn=$100; 329 usPersistent=usStay or usGoto or usEnhance or usRecover or integer($FFFF0000); 330 331 {model status flags} 332 msObsolete=$1; msAllowConscripts=$2; 333 334 {additional city happened flags} 335 chTypeDel=$8000; chAllImpsMade=$4000; 336 337 adNone=$801; adFar=$802; adNexus=$803; 338 339 SpecialModelPictureCode: array[0..nSpecialModel-1] of integer= 340 (10,11,40,41,21,30,{50,51,}64,74,{71,}73); 341 342 pixSlaves=0; pixNoSlaves=1; // index of slaves in StdUnits 343 344 // icons.bmp properties 345 xSizeSmall=36; ySizeSmall=20; 346 SystemIconLines=2; // lines of system icons in icons.bmp before improvements 347 348 // save options apart from what's defined by SaveOption 349 soTellAI=30; 350 soExtraMask=$40000000; 351 352 nCityEventPriority=16; 353 CityEventPriority: array[0..nCityEventPriority-1] of integer= 354 (chDisorder,chImprovementLost,chUnitLost,chAllImpsMade,chProduction, 355 chOldWonder,chNoSettlerProd,chPopDecrease,chProductionSabotaged, 356 chNoGrowthWarning,chPollution,chTypeDel,chFounded,chSiege,chAfterCapture, 357 chPopIncrease); 358 359 CityEventSoundItem: array[0..15] of string= 360 ('CITY_DISORDER','','CITY_POPPLUS','CITY_POPMINUS','CITY_UNITLOST', 361 'CITY_IMPLOST','CITY_SABOTAGE','CITY_GROWTHNEEDSIMP','CITY_POLLUTION', 362 'CITY_SIEGE','CITY_WONDEREX','CITY_EMDELAY','CITY_FOUNDED','CITY_FOUNDED','', 363 'CITY_INVALIDTYPE'); 364 365 type 366 TPersistentData=record 367 FarTech, ToldAge, ToldModels, ToldAlive, ToldContact, ToldOwnCredibility, 368 ColdWarStart, PeaceEvaHappened: integer; 369 EnhancementJobs: TEnhancementJobs; 370 ImpOrder: array[0..nCityType-1] of TImpOrder; 371 ToldWonders: array[0..27] of TWonderInfo; 372 ToldTech: array[0..nAdv-1] of ShortInt; 373 end; 374 375 var 376 MyData: ^TPersistentData; 377 AdvIcon:array[0..nAdv-1] of integer; {icons displayed with the technologies} 378 xxt,yyt, // half of tile size x/y 379 GameMode,ClientMode,Age,UnFocus,OptionChecked,MapOptionChecked,nLostArmy, 380 ScienceSum,TaxSum,SoundPreloadDone,MarkCityLoc,HGrTerrain,HGrCities, 381 MovieSpeed: integer; 382 CityRepMask: cardinal; 383 ReceivedOffer: TOffer; 384 Buffer,SmallImp: TBitmap; 385 BlinkON,DestinationMarkON,StartRunning,StayOnTop_Ensured,supervising: boolean; 386 UnusedTribeFiles, TribeNames: tstringlist; 387 TribeOriginal: array[0..nPl-1] of boolean; 388 LostArmy: array[0..nPl*nMmax-1] of integer; 389 DipMem: array[0..nPl-1] of record 390 pContact, SentCommand, FormerTreaty: integer; 391 SentOffer: TOffer; 392 DeliveredPrices, ReceivedPrices: TPriceSet; 290 291 TCityNameInfo = record 292 ID: integer; 293 NewName: ShortString end; 294 TModelNameInfo = record mix: integer; 295 NewName: ShortString end; 296 TPriceSet = Set of $00 .. $FF; 297 298 const 299 crImpDrag = 2; 300 crFlatHand = 3; 301 302 xxu = 32; 303 yyu = 24; // half of unit slot size x/y 304 yyu_anchor = 32; 305 xxc = 32; 306 yyc = 16; // 1/2 of city slot size in x, 1/2 of ground tile size in y (=1/3 of slot) 307 308 // layout 309 TopBarHeight = 41; 310 PanelHeight = 168; 311 MidPanelHeight = 120; 312 // TopBarHeight+MidPanelHeight should be same as BaseWin.yUnused 313 MapCenterUp = (MidPanelHeight - TopBarHeight) div 2; 314 315 nCityType = 4; 316 317 { client exclusive commands: } 318 cSetTribe = $9000; 319 cSetNewModelPicture = $9100; 320 cSetModelName = $9110; 321 cSetModelPicture = $9120; 322 cSetSlaveIndex = $9131; 323 cSetCityName = $9200; 324 325 // city status flags 326 csTypeMask = $0007; 327 csToldDelay = $0008; 328 csResourceWeightsMask = $00F0; 329 csToldBombard = $0100; 330 331 { unit status flags } 332 usStay = $01; 333 usWaiting = $02; 334 usGoto = $04; 335 usEnhance = $08; 336 usRecover = $10; 337 usToldNoReturn = $100; 338 usPersistent = usStay or usGoto or usEnhance or usRecover or 339 integer($FFFF0000); 340 341 { model status flags } 342 msObsolete = $1; 343 msAllowConscripts = $2; 344 345 { additional city happened flags } 346 chTypeDel = $8000; 347 chAllImpsMade = $4000; 348 349 adNone = $801; 350 adFar = $802; 351 adNexus = $803; 352 353 SpecialModelPictureCode: array [0 .. nSpecialModel - 1] of integer = (10, 354 11, 40, 41, 21, 30, { 50,51, } 64, 74, { 71, } 73); 355 356 pixSlaves = 0; 357 pixNoSlaves = 1; // index of slaves in StdUnits 358 359 // icons.bmp properties 360 xSizeSmall = 36; 361 ySizeSmall = 20; 362 SystemIconLines = 2; 363 // lines of system icons in icons.bmp before improvements 364 365 // save options apart from what's defined by SaveOption 366 soTellAI = 30; 367 soExtraMask = $40000000; 368 369 nCityEventPriority = 16; 370 CityEventPriority: array [0 .. nCityEventPriority - 1] of integer = 371 (chDisorder, chImprovementLost, chUnitLost, chAllImpsMade, chProduction, 372 chOldWonder, chNoSettlerProd, chPopDecrease, chProductionSabotaged, 373 chNoGrowthWarning, chPollution, chTypeDel, chFounded, chSiege, 374 chAfterCapture, chPopIncrease); 375 376 CityEventSoundItem: array [0 .. 15] of string = ('CITY_DISORDER', '', 377 'CITY_POPPLUS', 'CITY_POPMINUS', 'CITY_UNITLOST', 'CITY_IMPLOST', 378 'CITY_SABOTAGE', 'CITY_GROWTHNEEDSIMP', 'CITY_POLLUTION', 'CITY_SIEGE', 379 'CITY_WONDEREX', 'CITY_EMDELAY', 'CITY_FOUNDED', 'CITY_FOUNDED', '', 380 'CITY_INVALIDTYPE'); 381 382 type 383 TPersistentData = record 384 FarTech, ToldAge, ToldModels, ToldAlive, ToldContact, ToldOwnCredibility, 385 ColdWarStart, PeaceEvaHappened: integer; 386 EnhancementJobs: TEnhancementJobs; 387 ImpOrder: array [0 .. nCityType - 1] of TImpOrder; 388 ToldWonders: array [0 .. 27] of TWonderInfo; 389 ToldTech: array [0 .. nAdv - 1] of ShortInt; 390 end; 391 392 var 393 MyData: ^TPersistentData; 394 AdvIcon: array [0 .. nAdv - 1] of integer; 395 { icons displayed with the technologies } 396 xxt, yyt, // half of tile size x/y 397 GameMode, ClientMode, Age, UnFocus, OptionChecked, MapOptionChecked, 398 nLostArmy, ScienceSum, TaxSum, SoundPreloadDone, MarkCityLoc, HGrTerrain, 399 HGrCities, MovieSpeed: integer; 400 CityRepMask: Cardinal; 401 ReceivedOffer: TOffer; 402 Buffer, SmallImp: TBitmap; 403 BlinkON, DestinationMarkON, StartRunning, StayOnTop_Ensured, 404 supervising: boolean; 405 UnusedTribeFiles, TribeNames: tstringlist; 406 TribeOriginal: array [0 .. nPl - 1] of boolean; 407 LostArmy: array [0 .. nPl * nMmax - 1] of integer; 408 DipMem: array [0 .. nPl - 1] of record pContact, SentCommand, 409 FormerTreaty: integer; 410 SentOffer: TOffer; 411 DeliveredPrices, ReceivedPrices: TPriceSet; 393 412 end; 394 413 … … 400 419 procedure InitMyModel(mix: integer; final: boolean); 401 420 402 procedure ImpImage(ca: TCanvas; x, y,iix: integer; Government: integer = -1;421 procedure ImpImage(ca: TCanvas; x, y, iix: integer; Government: integer = -1; 403 422 IsControl: boolean = false); 404 423 procedure HelpOnTerrain(Loc, NewMode: integer); 405 424 406 407 425 implementation 408 426 409 427 uses 410 Directories,IsoEngine,CityScreen,Draft,MessgEx,Select,CityType,Help, 411 UnitStat,Diplomacy,Inp,log,Diagram,NatStat,Wonders,Enhance,Nego,Battle,Rates, 428 Directories, IsoEngine, CityScreen, Draft, MessgEx, Select, CityType, Help, 429 UnitStat, Diplomacy, Inp, log, Diagram, NatStat, Wonders, Enhance, Nego, 430 Battle, Rates, 412 431 TechTree, 413 432 414 Registry,ShellAPI; 415 433 Registry, ShellAPI; 416 434 417 435 {$R *.DFM} … … 419 437 420 438 const 421 lxmax_xxx=130; 422 LeftPanelWidth=70; 423 LeftPanelWidth_Editor=46; 424 overlap=PanelHeight-MidPanelHeight; 425 yTroop=PanelHeight-83; 426 xPalace=66; yPalace=24; //120; 427 xAdvisor=108; yAdvisor=48; 428 xUnitText=80; 429 PaperShade=3; 430 BlinkOnTime=12; BlinkOffTime=6; 431 MoveTime=300; // {time for moving a unit in ms} 432 WaitAfterShowMove=32; 433 FastScrolling=false; // causes problems with overlapping windows 434 435 nBrushTypes=26; 436 BrushTypes: array[0..nBrushTypes-1] of Cardinal= 437 (fPrefStartPos,fStartPos, 438 fShore,fGrass,fTundra,fPrairie,fDesert,fSwamp,fForest,fHills,fMountains,fArctic, 439 fDeadLands,fDeadLands or fCobalt,fDeadLands or fUranium, 440 fDeadLands or fMercury,fRiver, 441 fRoad,fRR,fCanal,tiIrrigation,tiFarm,tiMine,fPoll,tiFort,tiBase); 442 443 // MoveUnit options: 444 muAutoNoWait=$0001; muAutoNext=$0002; muNoSuicideCheck=$0004; 445 446 // ProcessRect options: 447 prPaint=$0001; prAutoBounds=$0002; prInvalidate=$0004; 448 449 // FocusOnLoc options: 450 flRepaintPanel=$0001; flImmUpdate=$0002; 451 452 nSaveOption=22; 439 lxmax_xxx = 130; 440 LeftPanelWidth = 70; 441 LeftPanelWidth_Editor = 46; 442 overlap = PanelHeight - MidPanelHeight; 443 yTroop = PanelHeight - 83; 444 xPalace = 66; 445 yPalace = 24; // 120; 446 xAdvisor = 108; 447 yAdvisor = 48; 448 xUnitText = 80; 449 PaperShade = 3; 450 BlinkOnTime = 12; 451 BlinkOffTime = 6; 452 MoveTime = 300; // {time for moving a unit in ms} 453 WaitAfterShowMove = 32; 454 FastScrolling = false; // causes problems with overlapping windows 455 456 nBrushTypes = 26; 457 BrushTypes: array [0 .. nBrushTypes - 1] of Cardinal = (fPrefStartPos, 458 fStartPos, fShore, fGrass, fTundra, fPrairie, fDesert, fSwamp, fForest, 459 fHills, fMountains, fArctic, fDeadLands, fDeadLands or fCobalt, 460 fDeadLands or fUranium, fDeadLands or fMercury, fRiver, fRoad, fRR, fCanal, 461 tiIrrigation, tiFarm, tiMine, fPoll, tiFort, tiBase); 462 463 // MoveUnit options: 464 muAutoNoWait = $0001; 465 muAutoNext = $0002; 466 muNoSuicideCheck = $0004; 467 468 // ProcessRect options: 469 prPaint = $0001; 470 prAutoBounds = $0002; 471 prInvalidate = $0004; 472 473 // FocusOnLoc options: 474 flRepaintPanel = $0001; 475 flImmUpdate = $0002; 476 477 nSaveOption = 22; 453 478 454 479 var 455 Jump: array[0..nPl-1] of integer; 456 pTurn,pLogo,UnStartLoc,ToldSlavery: integer; 457 PerfFreq: int64; 458 SmallScreen, GameOK, MapValid, skipped, idle: boolean; 459 460 SaveOption: array[0..nSaveOption-1] of integer; 461 MiniColors: array[0..11,0..1] of TColor; 462 MainMap: TIsoMap; 463 CurrentMoveInfo: record 464 AfterMovePaintRadius,AfterAttackExpeller: integer; 465 DoShow,IsAlly: boolean; 466 end; 467 480 Jump: array [0 .. nPl - 1] of integer; 481 pTurn, pLogo, UnStartLoc, ToldSlavery: integer; 482 PerfFreq: int64; 483 SmallScreen, GameOK, MapValid, skipped, idle: boolean; 484 485 SaveOption: array [0 .. nSaveOption - 1] of integer; 486 MiniColors: array [0 .. 11, 0 .. 1] of TColor; 487 MainMap: TIsoMap; 488 CurrentMoveInfo: record AfterMovePaintRadius, AfterAttackExpeller: integer; 489 DoShow, IsAlly: boolean; 490 end; 468 491 469 492 function CityEventName(i: integer): string; 470 493 begin 471 if i=14 then // chAllImpsMade 472 if not Phrases2FallenBackToEnglish then 473 result:=Phrases2.Lookup('CITYEVENT_ALLIMPSMADE') 474 else result:=Phrases.Lookup('CITYEVENTS',1) 475 else result:=Phrases.Lookup('CITYEVENTS',i); 494 if i = 14 then // chAllImpsMade 495 if not Phrases2FallenBackToEnglish then 496 result := Phrases2.Lookup('CITYEVENT_ALLIMPSMADE') 497 else 498 result := Phrases.Lookup('CITYEVENTS', 1) 499 else 500 result := Phrases.Lookup('CITYEVENTS', i); 476 501 end; 477 502 478 503 procedure InitSmallImp; 479 504 const 480 cut=4;481 Sharpen=80;505 cut = 4; 506 Sharpen = 80; 482 507 type 483 TLine=array[0..99999,0..2] of Byte;484 TBuffer=array[0..99999,0..2] of integer;508 TLine = array [0 .. 99999, 0 .. 2] of Byte; 509 TBuffer = array [0 .. 99999, 0 .. 2] of integer; 485 510 var 486 sum,Cnt,dx,dy,nx,ny,ix,iy,ir,x,y,c,ch,xdivider,ydivider: integer; 487 resampled: ^TBuffer; 488 line: ^TLine; 511 sum, Cnt, dx, dy, nx, ny, ix, iy, ir, x, y, c, ch, xdivider, 512 ydivider: integer; 513 resampled: ^TBuffer; 514 line: ^TLine; 489 515 begin 490 nx:=BigImp.Width div xSizeBig *xSizeSmall; 491 ny:=BigImp.Height div ySizeBig *ySizeSmall; 492 493 // resample icons 494 GetMem(resampled,nx*ny*12); 495 FillChar(resampled^,nx*ny*12,0); 496 for ix:=0 to BigImp.Width div xSizeBig-1 do for iy:=0 to BigImp.Height div ySizeBig-1 do 497 for y:=0 to ySizeBig-2*cut-1 do 498 begin 499 ydivider:=(y*ySizeSmall div (ySizeBig-2*cut)+1)*(ySizeBig-2*cut)-y*ySizeSmall; 500 if ydivider>ySizeSmall then ydivider:=ySizeSmall; 501 line:=BigImp.ScanLine[cut+iy*ySizeBig+y]; 502 for x:=0 to xSizeBig-1 do 503 begin 504 ir:=ix*xSizeSmall+iy*nx*ySizeSmall 505 +x*xSizeSmall div xSizeBig + y*ySizeSmall div (ySizeBig-2*cut) *nx; 506 xdivider:=(x*xSizeSmall div xSizeBig+1)*xSizeBig-x*xSizeSmall; 507 if xdivider>xSizeSmall then xdivider:=xSizeSmall; 508 for ch:=0 to 2 do 509 begin 510 c:=line[ix*xSizeBig+x,ch]; 511 inc(resampled[ir,ch],c*xdivider*ydivider); 512 if xdivider<xSizeSmall then 513 inc(resampled[ir+1,ch],c*(xSizeSmall-xdivider)*ydivider); 514 if ydivider<ySizeSmall then 515 inc(resampled[ir+nx,ch],c*xdivider*(ySizeSmall-ydivider)); 516 if (xdivider<xSizeSmall) and (ydivider<ySizeSmall) then 517 inc(resampled[ir+nx+1,ch],c*(xSizeSmall-xdivider)*(ySizeSmall-ydivider)); 516 nx := BigImp.width div xSizeBig * xSizeSmall; 517 ny := BigImp.height div ySizeBig * ySizeSmall; 518 519 // resample icons 520 GetMem(resampled, nx * ny * 12); 521 FillChar(resampled^, nx * ny * 12, 0); 522 for ix := 0 to BigImp.width div xSizeBig - 1 do 523 for iy := 0 to BigImp.height div ySizeBig - 1 do 524 for y := 0 to ySizeBig - 2 * cut - 1 do 525 begin 526 ydivider := (y * ySizeSmall div (ySizeBig - 2 * cut) + 1) * 527 (ySizeBig - 2 * cut) - y * ySizeSmall; 528 if ydivider > ySizeSmall then 529 ydivider := ySizeSmall; 530 line := BigImp.ScanLine[cut + iy * ySizeBig + y]; 531 for x := 0 to xSizeBig - 1 do 532 begin 533 ir := ix * xSizeSmall + iy * nx * ySizeSmall + x * 534 xSizeSmall div xSizeBig + y * 535 ySizeSmall div (ySizeBig - 2 * cut) * nx; 536 xdivider := (x * xSizeSmall div xSizeBig + 1) * xSizeBig - x * 537 xSizeSmall; 538 if xdivider > xSizeSmall then 539 xdivider := xSizeSmall; 540 for ch := 0 to 2 do 541 begin 542 c := line[ix * xSizeBig + x, ch]; 543 inc(resampled[ir, ch], c * xdivider * ydivider); 544 if xdivider < xSizeSmall then 545 inc(resampled[ir + 1, ch], c * (xSizeSmall - xdivider) * 546 ydivider); 547 if ydivider < ySizeSmall then 548 inc(resampled[ir + nx, ch], 549 c * xdivider * (ySizeSmall - ydivider)); 550 if (xdivider < xSizeSmall) and (ydivider < ySizeSmall) then 551 inc(resampled[ir + nx + 1, ch], c * (xSizeSmall - xdivider) * 552 (ySizeSmall - ydivider)); 553 end 518 554 end 519 end 520 end; 521 522 // sharpen resampled icons 523 SmallImp.Width:=nx; SmallImp.Height:=ny;524 for y:=0 to ny-1 do555 end; 556 557 // sharpen resampled icons 558 SmallImp.width := nx; 559 SmallImp.height := ny; 560 for y := 0 to ny - 1 do 525 561 begin 526 line:=SmallImp.ScanLine[y]; 527 for x:=0 to nx-1 do 528 for ch:=0 to 2 do 529 begin 530 sum:=0; 531 Cnt:=0; 532 for dy:=-1 to 1 do 533 if ((dy>=0) or (y mod ySizeSmall>0)) and ((dy<=0) or (y mod ySizeSmall<ySizeSmall-1)) then 534 for dx:=-1 to 1 do 535 if ((dx>=0) or (x mod xSizeSmall>0)) and ((dx<=0) or (x mod xSizeSmall<xSizeSmall-1)) then 562 line := SmallImp.ScanLine[y]; 563 for x := 0 to nx - 1 do 564 for ch := 0 to 2 do 565 begin 566 sum := 0; 567 Cnt := 0; 568 for dy := -1 to 1 do 569 if ((dy >= 0) or (y mod ySizeSmall > 0)) and 570 ((dy <= 0) or (y mod ySizeSmall < ySizeSmall - 1)) then 571 for dx := -1 to 1 do 572 if ((dx >= 0) or (x mod xSizeSmall > 0)) and 573 ((dx <= 0) or (x mod xSizeSmall < xSizeSmall - 1)) then 536 574 begin 537 inc(sum,resampled[x+dx+nx*(y+dy),ch]);538 inc(Cnt);575 inc(sum, resampled[x + dx + nx * (y + dy), ch]); 576 inc(Cnt); 539 577 end; 540 sum:=((Cnt*Sharpen+800)*resampled[x+nx*y,ch]-sum*Sharpen) div (800*xSizeBig*(ySizeBig-2*cut)); 541 if sum<0 then sum:=0; 542 if sum>255 then sum:=255; 543 line[x][ch]:=sum; 578 sum := ((Cnt * Sharpen + 800) * resampled[x + nx * y, ch] - sum * 579 Sharpen) div (800 * xSizeBig * (ySizeBig - 2 * cut)); 580 if sum < 0 then 581 sum := 0; 582 if sum > 255 then 583 sum := 255; 584 line[x][ch] := sum; 544 585 end; 545 586 end; 546 FreeMem(resampled);547 //smallimp.savetofile(homedir+'smallimp.bmp'); //!!!587 FreeMem(resampled); 588 // smallimp.savetofile(homedir+'smallimp.bmp'); //!!! 548 589 end; 549 590 550 procedure ImpImage(ca: TCanvas; x, y,iix: integer; Government: integer;591 procedure ImpImage(ca: TCanvas; x, y, iix: integer; Government: integer; 551 592 IsControl: boolean); 552 593 begin 553 if Government<0 then 554 Government:=MyRO.Government; 555 if (iix=imPalace) and (Government<>gAnarchy) then 556 iix:=Government-8; 557 FrameImage(ca, BigImp, x, y, xSizeBig, ySizeBig, 558 (iix+SystemIconLines*7) mod 7*xSizeBig, 559 (iix+SystemIconLines*7) div 7*ySizeBig, IsControl); 594 if Government < 0 then 595 Government := MyRO.Government; 596 if (iix = imPalace) and (Government <> gAnarchy) then 597 iix := Government - 8; 598 FrameImage(ca, BigImp, x, y, xSizeBig, ySizeBig, (iix + SystemIconLines * 7) 599 mod 7 * xSizeBig, (iix + SystemIconLines * 7) div 7 * ySizeBig, IsControl); 560 600 end; 561 601 562 602 procedure HelpOnTerrain(Loc, NewMode: integer); 563 603 begin 564 if MyMap[Loc] and fDeadLands<>0 then 565 HelpDlg.ShowNewContent(NewMode, hkTer, 3*12) 566 else if (MyMap[Loc] and fTerrain=fForest) and IsJungle(Loc div G.lx) then 567 HelpDlg.ShowNewContent(NewMode, hkTer, fJungle + (MyMap[Loc] shr 5 and 3)*12) 568 else HelpDlg.ShowNewContent(NewMode, hkTer, 569 MyMap[Loc] and fTerrain + (MyMap[Loc] shr 5 and 3)*12); 604 if MyMap[Loc] and fDeadLands <> 0 then 605 HelpDlg.ShowNewContent(NewMode, hkTer, 3 * 12) 606 else if (MyMap[Loc] and fTerrain = fForest) and IsJungle(Loc div G.lx) then 607 HelpDlg.ShowNewContent(NewMode, hkTer, 608 fJungle + (MyMap[Loc] shr 5 and 3) * 12) 609 else 610 HelpDlg.ShowNewContent(NewMode, hkTer, MyMap[Loc] and fTerrain + 611 (MyMap[Loc] shr 5 and 3) * 12); 570 612 end; 571 613 572 573 {*** tribe management procedures ***} 614 { *** tribe management procedures *** } 574 615 575 616 function RoughCredibility(Credibility: integer): integer; 576 617 begin 577 case Credibility of 578 0..69: result:=0; 70..89: result:=1; 90..99: result:=2; 100: result:=3 end; 579 end; 580 581 procedure ChooseModelPicture(p,mix,code,Hash,Turn: integer; 582 ForceNew,final: boolean); 583 var 584 i: integer; 585 Picture: TModelPictureInfo; 586 IsNew: boolean; 587 begin 588 Picture.trix:=p; 589 Picture.mix:=mix; 590 if code=74 then 591 begin // use correct pictures for slaves 592 if Tribe[p].mixSlaves<0 then 593 if not TribeOriginal[p] then Tribe[p].mixSlaves:=mix 594 else begin i:=mix+p shl 16; Server(cSetSlaveIndex,0,0,i); end; 595 if ToldSlavery=1 then Picture.pix:=pixSlaves else Picture.pix:=pixNoSlaves; 596 Picture.Hash:=0; 597 Picture.GrName:='StdUnits'; 598 IsNew:=true; 599 end 600 else 601 begin 602 Picture.Hash:=Hash; 603 IsNew:=Tribe[p].ChooseModelPicture(Picture,code,Turn,ForceNew); 604 end; 605 if final then 606 if not TribeOriginal[p] then 607 Tribe[p].SetModelPicture(Picture, IsNew) 608 else if IsNew then 609 Server(cSetNewModelPicture+(Length(Picture.GrName)+1+16+3) div 4,0, 610 0,Picture) 611 else Server(cSetModelPicture+(Length(Picture.GrName)+1+16+3) div 4,0, 612 0,Picture) 613 else with Tribe[p].ModelPicture[mix] do 614 begin 615 HGr:=LoadGraphicSet(Picture.GrName); 616 pix:=Picture.pix; 618 case Credibility of 619 0 .. 69: 620 result := 0; 621 70 .. 89: 622 result := 1; 623 90 .. 99: 624 result := 2; 625 100: 626 result := 3 617 627 end; 618 628 end; 619 629 630 procedure ChooseModelPicture(p, mix, code, Hash, Turn: integer; 631 ForceNew, final: boolean); 632 var 633 i: integer; 634 Picture: TModelPictureInfo; 635 IsNew: boolean; 636 begin 637 Picture.trix := p; 638 Picture.mix := mix; 639 if code = 74 then 640 begin // use correct pictures for slaves 641 if Tribe[p].mixSlaves < 0 then 642 if not TribeOriginal[p] then 643 Tribe[p].mixSlaves := mix 644 else 645 begin 646 i := mix + p shl 16; 647 Server(cSetSlaveIndex, 0, 0, i); 648 end; 649 if ToldSlavery = 1 then 650 Picture.pix := pixSlaves 651 else 652 Picture.pix := pixNoSlaves; 653 Picture.Hash := 0; 654 Picture.GrName := 'StdUnits'; 655 IsNew := true; 656 end 657 else 658 begin 659 Picture.Hash := Hash; 660 IsNew := Tribe[p].ChooseModelPicture(Picture, code, Turn, ForceNew); 661 end; 662 if final then 663 if not TribeOriginal[p] then 664 Tribe[p].SetModelPicture(Picture, IsNew) 665 else if IsNew then 666 Server(cSetNewModelPicture + (Length(Picture.GrName) + 1 + 16 + 3) div 4, 667 0, 0, Picture) 668 else 669 Server(cSetModelPicture + (Length(Picture.GrName) + 1 + 16 + 3) div 4, 0, 670 0, Picture) 671 else 672 with Tribe[p].ModelPicture[mix] do 673 begin 674 HGr := LoadGraphicSet(Picture.GrName); 675 pix := Picture.pix; 676 end; 677 end; 678 620 679 function InitEnemyModel(emix: integer): boolean; 621 680 begin 622 if GameMode=cMovie then 623 begin result:=false; exit end; 624 with MyRO.EnemyModel[emix] do 625 ChooseModelPicture(Owner, mix, ModelCode(MyRO.EnemyModel[emix]), 626 ModelHash(MyRO.EnemyModel[emix]), MyRO.Turn, false, true); 627 result:=true 681 if GameMode = cMovie then 682 begin 683 result := false; 684 exit 685 end; 686 with MyRO.EnemyModel[emix] do 687 ChooseModelPicture(Owner, mix, ModelCode(MyRO.EnemyModel[emix]), 688 ModelHash(MyRO.EnemyModel[emix]), MyRO.Turn, false, true); 689 result := true 628 690 end; 629 691 630 692 procedure InitAllEnemyModels; 631 693 var 632 emix: integer;694 emix: integer; 633 695 begin 634 for emix:=0 to MyRO.nEnemyModel-1 do635 with MyRO.EnemyModel[emix] do636 if Tribe[Owner].ModelPicture[mix].HGr=0 then637 InitEnemyModel(emix);696 for emix := 0 to MyRO.nEnemyModel - 1 do 697 with MyRO.EnemyModel[emix] do 698 if Tribe[Owner].ModelPicture[mix].HGr = 0 then 699 InitEnemyModel(emix); 638 700 end; 639 701 640 702 procedure InitMyModel(mix: integer; final: boolean); 641 703 var 642 mi: TModelInfo;704 mi: TModelInfo; 643 705 begin 644 if (GameMode=cMovie) and (MyModel[mix].Kind<$08) then exit; 706 if (GameMode = cMovie) and (MyModel[mix].Kind < $08) then 707 exit; 645 708 // don't exit for special units because cSetModelPicture comes after TellNewModels 646 MakeModelInfo(me,mix,MyModel[mix],mi);647 ChooseModelPicture(me, mix, ModelCode(mi), ModelHash(mi), MyRO.Turn, false,648 final);709 MakeModelInfo(me, mix, MyModel[mix], mi); 710 ChooseModelPicture(me, mix, ModelCode(mi), ModelHash(mi), MyRO.Turn, 711 false, final); 649 712 end; 650 713 651 714 function AttackSound(code: integer): string; 652 715 begin 653 result:='ATTACK_'+char(48+code div 100 mod 10)+char(48+code div 10 mod 10) 654 +char(48+code mod 10);716 result := 'ATTACK_' + char(48 + code div 100 mod 10) + 717 char(48 + code div 10 mod 10) + char(48 + code mod 10); 655 718 end; 656 719 … … 658 721 // check whether aircraft survived low-fuel warning 659 722 begin 660 assert(not supervising);661 with MyUn[uix] do662 if (Status and usToldNoReturn<>0)663 and ((MyMap[Loc] and fCity<>0) or (MyMap[Loc] and fTerImp=tiBase)664 or (Master>=0)) then665 Status:=Status and not usToldNoReturn;723 assert(not supervising); 724 with MyUn[uix] do 725 if (Status and usToldNoReturn <> 0) and 726 ((MyMap[Loc] and fCity <> 0) or (MyMap[Loc] and fTerImp = tiBase) or 727 (Master >= 0)) then 728 Status := Status and not usToldNoReturn; 666 729 end; 667 730 668 function CreateTribe(p: integer; FileName:string; Original: boolean): boolean;731 function CreateTribe(p: integer; FileName: string; Original: boolean): boolean; 669 732 begin 670 if not FileExists(LocalizedFilePath('Tribes\'+FileName+'.tribe.txt')) then 671 begin result:=false; exit end; 672 673 TribeOriginal[p]:=Original; 674 Tribe[p]:=TTribe.Create(FileName); 675 with Tribe[p] do 733 if not FileExists(LocalizedFilePath('Tribes\' + FileName + '.tribe.txt')) then 676 734 begin 677 if (GameMode=cNewGame) or not Original then 678 begin 679 Term.ChooseModelPicture(p,0,010,1,0,true,true); 680 Term.ChooseModelPicture(p,1,040,1,0,true,true); 681 Term.ChooseModelPicture(p,2,041,1,0,true,true); 682 Term.ChooseModelPicture(p,-1,017,1,0,true,true); 683 end; 684 DipMem[p].pContact:=-1; 735 result := false; 736 exit 685 737 end; 686 result:=true; 738 739 TribeOriginal[p] := Original; 740 Tribe[p] := TTribe.Create(FileName); 741 with Tribe[p] do 742 begin 743 if (GameMode = cNewGame) or not Original then 744 begin 745 Term.ChooseModelPicture(p, 0, 010, 1, 0, true, true); 746 Term.ChooseModelPicture(p, 1, 040, 1, 0, true, true); 747 Term.ChooseModelPicture(p, 2, 041, 1, 0, true, true); 748 Term.ChooseModelPicture(p, -1, 017, 1, 0, true, true); 749 end; 750 DipMem[p].pContact := -1; 751 end; 752 result := true; 687 753 end; 688 754 689 755 procedure TellNewContacts; 690 756 var 691 p1: integer;757 p1: integer; 692 758 begin 693 if not supervising then694 for p1:=0 to nPl-1 do695 if (p1<>me) and (1 shl p1 and MyData.ToldContact=0)696 and (1 shl p1 and MyRO.Alive<>0) and (MyRO.Treaty[p1]>trNoContact) then697 begin 698 TribeMessage(p1, Tribe[p1].TPhrase('FRNEWNATION'), '');699 MyData.ToldContact:=MyData.ToldContact or (1 shl p1);759 if not supervising then 760 for p1 := 0 to nPl - 1 do 761 if (p1 <> me) and (1 shl p1 and MyData.ToldContact = 0) and 762 (1 shl p1 and MyRO.Alive <> 0) and (MyRO.Treaty[p1] > trNoContact) then 763 begin 764 TribeMessage(p1, Tribe[p1].TPhrase('FRNEWNATION'), ''); 765 MyData.ToldContact := MyData.ToldContact or (1 shl p1); 700 766 end 701 767 end; … … 703 769 procedure TellNewModels; 704 770 var 705 mix: integer;706 ModelNameInfo: TModelNameInfo;771 mix: integer; 772 ModelNameInfo: TModelNameInfo; 707 773 begin 708 if supervising then 709 exit; 710 with Tribe[me] do while MyData.ToldModels<MyRO.nModel do 711 begin {new Unit class available} 712 if (ModelPicture[MyData.ToldModels].HGr>0) 713 and (MyModel[MyData.ToldModels].Kind<>mkSelfDeveloped) then 714 begin // save picture of DevModel 715 ModelPicture[MyData.ToldModels+1]:=ModelPicture[MyData.ToldModels]; 716 ModelName[MyData.ToldModels+1]:=ModelName[MyData.ToldModels]; 717 ModelPicture[MyData.ToldModels].HGr:=0 718 end; 719 if ModelPicture[MyData.ToldModels].HGr=0 then 720 InitMyModel(MyData.ToldModels,true); {only run if no researched model} 721 with MessgExDlg do 722 begin 723 { MakeModelInfo(me,MyData.ToldModels,MyModel[MyData.ToldModels],mi); 724 if mi.Attack=0 then OpenSound:='MSG_DEFAULT' 725 else OpenSound:=AttackSound(ModelCode(mi));} 726 if MyModel[MyData.ToldModels].Kind=mkSelfDeveloped then 727 OpenSound:='NEWMODEL_'+char(48+Age); 728 MessgText:=Phrases.Lookup('MODELAVAILABLE'); 729 if GameMode=cMovie then 730 begin 731 Kind:=mkOkHelp; // doesn't matter 732 MessgText:=MessgText+'\'+ModelName[MyData.ToldModels]; 774 if supervising then 775 exit; 776 with Tribe[me] do 777 while MyData.ToldModels < MyRO.nModel do 778 begin { new Unit class available } 779 if (ModelPicture[MyData.ToldModels].HGr > 0) and 780 (MyModel[MyData.ToldModels].Kind <> mkSelfDeveloped) then 781 begin // save picture of DevModel 782 ModelPicture[MyData.ToldModels + 1] := ModelPicture[MyData.ToldModels]; 783 ModelName[MyData.ToldModels + 1] := ModelName[MyData.ToldModels]; 784 ModelPicture[MyData.ToldModels].HGr := 0 785 end; 786 if ModelPicture[MyData.ToldModels].HGr = 0 then 787 InitMyModel(MyData.ToldModels, true); 788 { only run if no researched model } 789 with MessgExDlg do 790 begin 791 { MakeModelInfo(me,MyData.ToldModels,MyModel[MyData.ToldModels],mi); 792 if mi.Attack=0 then OpenSound:='MSG_DEFAULT' 793 else OpenSound:=AttackSound(ModelCode(mi)); } 794 if MyModel[MyData.ToldModels].Kind = mkSelfDeveloped then 795 OpenSound := 'NEWMODEL_' + char(48 + Age); 796 MessgText := Phrases.Lookup('MODELAVAILABLE'); 797 if GameMode = cMovie then 798 begin 799 Kind := mkOkHelp; // doesn't matter 800 MessgText := MessgText + '\' + ModelName[MyData.ToldModels]; 801 end 802 else 803 begin 804 Kind := mkModel; 805 EInput.Text := ModelName[MyData.ToldModels]; 806 end; 807 IconKind := mikModel; 808 IconIndex := MyData.ToldModels; 809 ShowModal; 810 if (EInput.Text <> '') and (EInput.Text <> ModelName[MyData.ToldModels]) 811 then 812 begin // user renamed model 813 ModelNameInfo.mix := MyData.ToldModels; 814 ModelNameInfo.NewName := EInput.Text; 815 Server(cSetModelName + (Length(ModelNameInfo.NewName) + 1 + 4 + 3) 816 div 4, me, 0, ModelNameInfo); 817 end 818 end; 819 if MyModel[MyData.ToldModels].Kind = mkSettler then 820 begin // engineers make settlers obsolete 821 for mix := 0 to MyData.ToldModels - 1 do 822 if MyModel[mix].Kind = mkSettler then 823 MyModel[mix].Status := MyModel[mix].Status or msObsolete; 824 end; 825 inc(MyData.ToldModels) 826 end; 827 end; 828 829 procedure PaintZoomedTile(dst: TBitmap; x, y, Loc: integer); 830 831 procedure TSprite(xDst, yDst, xSrc, ySrc: integer); 832 begin 833 Sprite(dst, HGrTerrain, x + xDst, y + yDst, xxt * 2, yyt * 3, 834 1 + xSrc * (xxt * 2 + 1), 1 + ySrc * (yyt * 3 + 1)); 835 end; 836 837 procedure TSprite4(xSrc, ySrc: integer); 838 begin 839 Sprite(dst, HGrTerrain, x + xxt, y + yyt + 2, xxt * 2, yyt * 2 - 2, 840 1 + xSrc * (xxt * 2 + 1), 3 + yyt + ySrc * (yyt * 3 + 1)); 841 Sprite(dst, HGrTerrain, x + 4, y + 2 * yyt, xxt * 2 - 4, yyt * 2, 842 5 + xSrc * (xxt * 2 + 1), 1 + yyt + ySrc * (yyt * 3 + 1)); 843 Sprite(dst, HGrTerrain, x + xxt * 2, y + 2 * yyt, xxt * 2 - 4, yyt * 2, 844 1 + xSrc * (xxt * 2 + 1), 1 + yyt + ySrc * (yyt * 3 + 1)); 845 Sprite(dst, HGrTerrain, x + xxt, y + yyt * 3, xxt * 2, yyt * 2 - 2, 846 1 + xSrc * (xxt * 2 + 1), 1 + yyt + ySrc * (yyt * 3 + 1)); 847 end; 848 849 var 850 cix, ySrc, Tile: integer; 851 begin 852 Tile := MyMap[Loc]; 853 if Tile and fCity <> 0 then 854 begin 855 if MyRO.Tech[adRailroad] >= tsApplicable then 856 Tile := Tile or fRR 857 else 858 Tile := Tile or fRoad; 859 if Tile and fOwned <> 0 then 860 begin 861 cix := MyRO.nCity - 1; 862 while (cix >= 0) and (MyCity[cix].Loc <> Loc) do 863 dec(cix); 864 assert(cix >= 0); 865 if MyCity[cix].Built[imSupermarket] > 0 then 866 Tile := Tile or tiFarm 867 else 868 Tile := Tile or tiIrrigation; 869 end 870 else 871 Tile := Tile or tiIrrigation; 872 end; 873 874 if Tile and fTerrain >= fForest then 875 TSprite4(2, 2) 876 else 877 TSprite4(Tile and fTerrain, 0); 878 if Tile and fTerrain >= fForest then 879 begin 880 if (Tile and fTerrain = fForest) and IsJungle(Loc div G.lx) then 881 ySrc := 18 882 else 883 ySrc := 3 + 2 * (Tile and fTerrain - fForest); 884 TSprite(xxt, 0, 6, ySrc); 885 TSprite(0, yyt, 3, ySrc); 886 TSprite((xxt * 2), yyt, 4, ySrc + 1); 887 TSprite(xxt, (yyt * 2), 1, ySrc + 1); 888 end; 889 890 // irrigation 891 case Tile and fTerImp of 892 tiIrrigation: 893 begin 894 TSprite(xxt, 0, 0, 12); 895 TSprite(xxt * 2, yyt, 0, 12); 896 end; 897 tiFarm: 898 begin 899 TSprite(xxt, 0, 1, 12); 900 TSprite(xxt * 2, yyt, 1, 12); 733 901 end 902 end; 903 904 // river/canal/road/railroad 905 if Tile and fRiver <> 0 then 906 begin 907 TSprite(0, yyt, 2, 14); 908 TSprite(xxt, (yyt * 2), 2, 14); 909 end; 910 if Tile and fCanal <> 0 then 911 begin 912 TSprite(xxt, 0, 7, 11); 913 TSprite(xxt, 0, 3, 11); 914 TSprite(xxt * 2, yyt, 7, 11); 915 TSprite(xxt * 2, yyt, 3, 11); 916 end; 917 if Tile and fRR <> 0 then 918 begin 919 TSprite((xxt * 2), yyt, 1, 10); 920 TSprite((xxt * 2), yyt, 5, 10); 921 TSprite(xxt, (yyt * 2), 1, 10); 922 TSprite(xxt, (yyt * 2), 5, 10); 923 end 924 else if Tile and fRoad <> 0 then 925 begin 926 TSprite((xxt * 2), yyt, 8, 9); 927 TSprite((xxt * 2), yyt, 5, 9); 928 TSprite(xxt, (yyt * 2), 1, 9); 929 TSprite(xxt, (yyt * 2), 5, 9); 930 end; 931 932 if Tile and fPoll <> 0 then 933 TSprite(xxt, (yyt * 2), 6, 12); 934 935 // special 936 if Tile and (fTerrain or fSpecial) = fGrass or fSpecial1 then 937 TSprite4(2, 1) 938 else if Tile and fSpecial <> 0 then 939 if Tile and fTerrain < fForest then 940 TSprite(0, yyt, Tile and fTerrain, Tile and fSpecial shr 5) 941 else if (Tile and fTerrain = fForest) and IsJungle(Loc div G.lx) then 942 TSprite(0, yyt, 8, 17 + Tile and fSpecial shr 5) 734 943 else 735 begin 736 Kind:=mkModel; 737 EInput.Text:=ModelName[MyData.ToldModels]; 944 TSprite(0, yyt, 8, 2 + (Tile and fTerrain - fForest) * 2 + Tile and 945 fSpecial shr 5) 946 else if Tile and fDeadLands <> 0 then 947 begin 948 TSprite4(6, 2); 949 TSprite(xxt, yyt, 8, 12 + Tile shr 25 and 3); 950 end; 951 952 // other improvements 953 case Tile and fTerImp of 954 tiMine: 955 TSprite(xxt, 0, 2, 12); 956 tiFort: 957 begin 958 TSprite(xxt, 0, 7, 12); 959 TSprite(xxt, 0, 3, 12); 738 960 end; 739 IconKind:=mikModel; 740 IconIndex:=MyData.ToldModels; 741 ShowModal; 742 if (EInput.Text<>'') and (EInput.Text<>ModelName[MyData.ToldModels]) then 743 begin // user renamed model 744 ModelNameInfo.mix:=MyData.ToldModels; 745 ModelNameInfo.NewName:=EInput.Text; 746 Server(cSetModelName+(Length(ModelNameInfo.NewName)+1+4+3) div 4, 747 me,0,ModelNameInfo); 748 end 749 end; 750 if MyModel[MyData.ToldModels].kind=mkSettler then 751 begin // engineers make settlers obsolete 752 for mix:=0 to MyData.ToldModels-1 do 753 if MyModel[mix].Kind=mkSettler then 754 MyModel[mix].Status:=MyModel[mix].Status or msObsolete; 755 end; 756 inc(MyData.ToldModels) 961 tiBase: 962 TSprite(xxt, 0, 4, 12); 757 963 end; 758 964 end; 759 965 760 procedure PaintZoomedTile(dst: TBitmap; x,y,Loc: integer); 761 762 procedure TSprite(xDst, yDst, xSrc, ySrc: integer); 966 function ChooseResearch: boolean; 967 var 968 ChosenResearch: integer; 969 begin 970 if (MyData.FarTech <> adNone) and (MyRO.Tech[MyData.FarTech] >= tsApplicable) 971 then 972 MyData.FarTech := adNone; 973 repeat 974 { research complete -- select new } 975 repeat 976 ModalSelectDlg.ShowNewContent(wmModal, kAdvance); 977 if ModalSelectDlg.result < 0 then 978 begin 979 result := false; 980 exit 981 end; 982 ChosenResearch := ModalSelectDlg.result; 983 if ChosenResearch = adMilitary then 984 begin 985 DraftDlg.ShowNewContent(wmModal); 986 if DraftDlg.ModalResult <> mrOK then 987 Tribe[me].ModelPicture[MyRO.nModel].HGr := 0 988 end 989 until (ChosenResearch <> adMilitary) or (DraftDlg.ModalResult = mrOK); 990 991 if ChosenResearch = adMilitary then 992 InitMyModel(MyRO.nModel, true) 993 else if ChosenResearch = adFar then 994 begin 995 ModalSelectDlg.ShowNewContent(wmModal, kFarAdvance); 996 if ModalSelectDlg.result >= 0 then 997 if (ModalSelectDlg.result = adNone) or 998 (Server(sSetResearch - sExecute, me, ModalSelectDlg.result, nil^) < 999 rExecuted) then 1000 MyData.FarTech := ModalSelectDlg.result 1001 else 1002 begin 1003 ChosenResearch := ModalSelectDlg.result; 1004 // can be researched immediately 1005 MyData.FarTech := adNone 1006 end 1007 end; 1008 until ChosenResearch <> adFar; 1009 if ChosenResearch = adNexus then 1010 MyData.FarTech := adNexus 1011 else 1012 Server(sSetResearch, me, ChosenResearch, nil^); 1013 ListDlg.TechChange; 1014 result := true; 1015 end; 1016 1017 (* ** client function handling ** *) 1018 1019 function TMainScreen.DipCall(Command: integer): integer; 1020 var 1021 i: integer; 1022 IsTreatyDeal: boolean; 763 1023 begin 764 Sprite(dst, HGrTerrain, x+xDst, y+yDst, xxt*2, yyt*3, 1+xSrc*(xxt*2+1), 765 1+ySrc*(yyt*3+1)); 766 end; 767 768 procedure TSprite4(xSrc, ySrc: integer); 769 begin 770 Sprite(dst, HGrTerrain, x+xxt, y+yyt+2, xxt*2, yyt*2-2, 1+xSrc*(xxt*2+1), 771 3+yyt+ySrc*(yyt*3+1)); 772 Sprite(dst, HGrTerrain, x+4, y+2*yyt, xxt*2-4, yyt*2, 5+xSrc*(xxt*2+1), 773 1+yyt+ySrc*(yyt*3+1)); 774 Sprite(dst, HGrTerrain, x+xxt*2, y+2*yyt, xxt*2-4, yyt*2, 1+xSrc*(xxt*2+1), 775 1+yyt+ySrc*(yyt*3+1)); 776 Sprite(dst, HGrTerrain, x+xxt, y+yyt*3, xxt*2, yyt*2-2, 1+xSrc*(xxt*2+1), 777 1+yyt+ySrc*(yyt*3+1)); 778 end; 779 780 var 781 cix, ySrc, Tile: integer; 782 begin 783 Tile:=MyMap[Loc]; 784 if Tile and fCity<>0 then 785 begin 786 if MyRO.Tech[adRailroad]>=tsApplicable then 787 Tile:=Tile or fRR 788 else Tile:=Tile or fRoad; 789 if Tile and fOwned<>0 then 790 begin 791 cix:=MyRO.nCity-1; 792 while (cix>=0) and (MyCity[cix].Loc<>Loc) do dec(cix); 793 assert(cix>=0); 794 if MyCity[cix].Built[imSupermarket]>0 then 795 Tile:=Tile or tiFarm 796 else Tile:=Tile or tiIrrigation; 797 end 798 else Tile:=Tile or tiIrrigation; 799 end; 800 801 if Tile and fTerrain>=fForest then TSprite4(2,2) 802 else TSprite4(Tile and fTerrain,0); 803 if Tile and fTerrain>=fForest then 804 begin 805 if (Tile and fTerrain=fForest) and IsJungle(Loc div G.lx) then ySrc:=18 806 else ySrc:=3+2*(Tile and fTerrain-fForest); 807 TSprite(xxt, 0, 6, ySrc); 808 TSprite(0, yyt, 3, ySrc); 809 TSprite((xxt*2), yyt, 4, ySrc+1); 810 TSprite(xxt, (yyt*2), 1, ySrc+1); 811 end; 812 813 // irrigation 814 case Tile and fTerImp of 815 tiIrrigation: 816 begin 817 TSprite(xxt,0,0,12); 818 TSprite(xxt*2,yyt,0,12); 819 end; 820 tiFarm: 821 begin 822 TSprite(xxt,0,1,12); 823 TSprite(xxt*2,yyt,1,12); 1024 result := Server(Command, me, 0, nil^); 1025 if result >= rExecuted then 1026 begin 1027 if Command and $FF0F = scContact then 1028 begin 1029 DipMem[me].pContact := Command shr 4 and $F; 1030 NegoDlg.Initiate; 1031 DipMem[me].DeliveredPrices := []; 1032 DipMem[me].ReceivedPrices := []; 1033 end; 1034 1035 DipMem[me].SentCommand := Command; 1036 DipMem[me].FormerTreaty := MyRO.Treaty[DipMem[me].pContact]; 1037 if Command = scDipCancelTreaty then 1038 Play('CANCELTREATY') 1039 else if Command = scDipAccept then 1040 begin // remember delivered and received prices 1041 for i := 0 to ReceivedOffer.nDeliver - 1 do 1042 include(DipMem[me].ReceivedPrices, ReceivedOffer.Price[i] shr 24); 1043 for i := 0 to ReceivedOffer.nCost - 1 do 1044 include(DipMem[me].DeliveredPrices, 1045 ReceivedOffer.Price[ReceivedOffer.nDeliver + i] shr 24); 1046 IsTreatyDeal := false; 1047 for i := 0 to ReceivedOffer.nDeliver + ReceivedOffer.nCost - 1 do 1048 if ReceivedOffer.Price[i] and opMask = opTreaty then 1049 IsTreatyDeal := true; 1050 if IsTreatyDeal then 1051 Play('NEWTREATY') 1052 else 1053 Play('ACCEPTOFFER'); 1054 end; 1055 CityDlg.CloseAction := None; 1056 if G.RO[DipMem[me].pContact] <> nil then 1057 begin // close windows for next player 1058 for i := 0 to Screen.FormCount - 1 do 1059 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 1060 then 1061 Screen.Forms[i].Close; 1062 end 1063 else 1064 begin 1065 if CityDlg.Visible then 1066 CityDlg.Close; 1067 if UnitStatDlg.Visible then 1068 UnitStatDlg.Close; 1069 end 824 1070 end 825 1071 end; 826 1072 827 // river/canal/road/railroad 828 if Tile and fRiver<>0 then 1073 function TMainScreen.OfferCall(var Offer: TOffer): integer; 1074 var 1075 i: integer; 829 1076 begin 830 TSprite(0, yyt, 2, 14); 831 TSprite(xxt, (yyt*2), 2, 14); 1077 result := Server(scDipOffer, me, 0, Offer); 1078 if result >= rExecuted then 1079 begin 1080 DipMem[me].SentCommand := scDipOffer; 1081 DipMem[me].FormerTreaty := MyRO.Treaty[DipMem[me].pContact]; 1082 DipMem[me].SentOffer := Offer; 1083 CityDlg.CloseAction := None; 1084 if G.RO[DipMem[me].pContact] <> nil then 1085 begin // close windows for next player 1086 for i := 0 to Screen.FormCount - 1 do 1087 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 1088 then 1089 Screen.Forms[i].Close; 1090 end 1091 else 1092 begin 1093 if CityDlg.Visible then 1094 CityDlg.Close; 1095 if UnitStatDlg.Visible then 1096 UnitStatDlg.Close; 1097 end 1098 end 832 1099 end; 833 if Tile and fCanal<>0 then 1100 1101 procedure TMainScreen.SetUnFocus(uix: integer); 1102 var 1103 Loc0: integer; 834 1104 begin 835 TSprite(xxt, 0, 7, 11); 836 TSprite(xxt, 0, 3, 11); 837 TSprite(xxt*2,yyt,7,11); 838 TSprite(xxt*2,yyt,3,11); 839 end; 840 if Tile and fRR<>0 then 841 begin 842 TSprite((xxt*2), yyt, 1, 10); 843 TSprite((xxt*2), yyt, 5, 10); 844 TSprite(xxt, (yyt*2), 1, 10); 845 TSprite(xxt, (yyt*2), 5, 10); 846 end 847 else if Tile and fRoad<>0 then 848 begin 849 TSprite((xxt*2), yyt, 8, 9); 850 TSprite((xxt*2), yyt, 5, 9); 851 TSprite(xxt, (yyt*2), 1, 9); 852 TSprite(xxt, (yyt*2), 5, 9); 853 end; 854 855 if Tile and fPoll<>0 then 856 TSprite(xxt,(yyt*2),6,12); 857 858 // special 859 if Tile and (fTerrain or fSpecial)=fGrass or fSpecial1 then 860 TSprite4(2,1) 861 else if Tile and fSpecial<>0 then 862 if Tile and fTerrain<fForest then 863 TSprite(0, yyt, Tile and fTerrain, Tile and fSpecial shr 5) 864 else if (Tile and fTerrain=fForest) and IsJungle(Loc div G.lx) then 865 TSprite(0, yyt, 8, 17+Tile and fSpecial shr 5) 866 else TSprite(0, yyt, 8, 2+(Tile and fTerrain-fForest)*2+Tile and fSpecial shr 5) 867 else if Tile and fDeadLands<>0 then 868 begin 869 TSprite4(6,2); 870 TSprite(xxt, yyt, 8, 12+Tile shr 25 and 3); 871 end; 872 873 // other improvements 874 case Tile and fTerImp of 875 tiMine: TSprite(xxt, 0, 2, 12); 876 tiFort: begin TSprite(xxt, 0, 7, 12); TSprite(xxt, 0, 3, 12); end; 877 tiBase: TSprite(xxt, 0, 4, 12); 878 end; 879 end; 880 881 function ChooseResearch: boolean; 882 var 883 ChosenResearch: integer; 884 begin 885 if (MyData.FarTech<>adNone) and (MyRO.Tech[MyData.FarTech]>=tsApplicable) then 886 MyData.FarTech:=adNone; 887 repeat 888 {research complete -- select new} 889 repeat 890 ModalSelectDlg.ShowNewContent(wmModal,kAdvance); 891 if ModalSelectDlg.result<0 then 892 begin result:=false; exit end; 893 ChosenResearch:=ModalSelectDlg.result; 894 if ChosenResearch=adMilitary then 895 begin 896 DraftDlg.ShowNewContent(wmModal); 897 if DraftDlg.ModalResult<>mrOK then 898 Tribe[me].ModelPicture[MyRO.nModel].HGr:=0 899 end 900 until (ChosenResearch<>adMilitary) or (DraftDlg.ModalResult=mrOK); 901 902 if ChosenResearch=adMilitary then InitMyModel(MyRO.nModel,true) 903 else if ChosenResearch=adFar then 904 begin 905 ModalSelectDlg.ShowNewContent(wmModal,kFarAdvance); 906 if ModalSelectDlg.result>=0 then 907 if (ModalSelectDlg.Result=adNone) or 908 (Server(sSetResearch-sExecute,me,ModalSelectDlg.Result,nil^)<rExecuted) then 909 MyData.FarTech:=ModalSelectDlg.result 910 else 911 begin 912 ChosenResearch:=ModalSelectDlg.result; // can be researched immediately 913 MyData.FarTech:=adNone 914 end 915 end; 916 until ChosenResearch<>adFar; 917 if ChosenResearch=adNexus then MyData.FarTech:=adNexus 918 else Server(sSetResearch,me,ChosenResearch,nil^); 919 ListDlg.TechChange; 920 result:=true; 921 end; 922 923 924 (*** client function handling ***) 925 926 function TMainScreen.DipCall(Command: integer): integer; 927 var 928 i: integer; 929 IsTreatyDeal: boolean; 930 begin 931 result:=Server(Command,me,0,nil^); 932 if result>=rExecuted then 933 begin 934 if Command and $FF0F=scContact then 935 begin 936 DipMem[me].pContact:=Command shr 4 and $f; 937 NegoDlg.Initiate; 938 DipMem[me].DeliveredPrices:=[]; 939 DipMem[me].ReceivedPrices:=[]; 940 end; 941 942 DipMem[me].SentCommand:=Command; 943 DipMem[me].FormerTreaty:=MyRO.Treaty[DipMem[me].pContact]; 944 if Command=scDipCancelTreaty then Play('CANCELTREATY') 945 else if Command=scDipAccept then 946 begin // remember delivered and received prices 947 for i:=0 to ReceivedOffer.nDeliver-1 do 948 include(DipMem[me].ReceivedPrices,ReceivedOffer.Price[i] shr 24); 949 for i:=0 to ReceivedOffer.nCost-1 do 950 include(DipMem[me].DeliveredPrices, 951 ReceivedOffer.Price[ReceivedOffer.nDeliver+i] shr 24); 952 IsTreatyDeal:=false; 953 for i:=0 to ReceivedOffer.nDeliver+ReceivedOffer.nCost-1 do 954 if ReceivedOffer.Price[i] and opMask=opTreaty then 955 IsTreatyDeal:=true; 956 if IsTreatyDeal then Play('NEWTREATY') 957 else Play('ACCEPTOFFER'); 958 end; 959 CityDlg.CloseAction:=None; 960 if G.RO[DipMem[me].pContact]<>nil then 961 begin // close windows for next player 962 for i:=0 to Screen.FormCount-1 do 963 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 964 Screen.Forms[i].Close; 965 end 966 else 967 begin 968 if CityDlg.Visible then CityDlg.Close; 969 if UnitStatDlg.Visible then UnitStatDlg.Close; 970 end 971 end 972 end; 973 974 function TMainScreen.OfferCall(var Offer: TOffer): integer; 975 var 976 i: integer; 977 begin 978 result:=Server(scDipOffer,me,0,Offer); 979 if result>=rExecuted then 980 begin 981 DipMem[me].SentCommand:=scDipOffer; 982 DipMem[me].FormerTreaty:=MyRO.Treaty[DipMem[me].pContact]; 983 DipMem[me].SentOffer:=Offer; 984 CityDlg.CloseAction:=None; 985 if G.RO[DipMem[me].pContact]<>nil then 986 begin // close windows for next player 987 for i:=0 to Screen.FormCount-1 do 988 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 989 Screen.Forms[i].Close; 990 end 991 else 992 begin 993 if CityDlg.Visible then CityDlg.Close; 994 if UnitStatDlg.Visible then UnitStatDlg.Close; 995 end 996 end 997 end; 998 999 procedure TMainScreen.SetUnFocus(uix:integer); 1000 var 1001 Loc0: integer; 1002 begin 1003 assert(not ((uix>=0) and supervising)); 1004 if uix<>UnFocus then 1005 begin 1006 DestinationMarkON:=false; 1007 PaintDestination; 1008 if uix>=0 then UnStartLoc:=MyUn[uix].Loc; 1009 BlinkON:=false; 1010 BlinkTime:=-1; 1011 if UnFocus>=0 then 1012 begin 1013 Loc0:=MyUn[UnFocus].Loc; 1014 if (uix<0) or (Loc0<>MyUn[uix].Loc) then 1015 begin 1016 UnFocus:=-1; 1017 PaintLoc(Loc0); 1018 end 1019 end; 1020 UnFocus:=uix; 1021 end; 1022 UnitInfoBtn.Visible:= UnFocus>=0; 1023 UnitBtn.Visible:= UnFocus>=0; 1024 CheckTerrainBtnVisible; 1025 end; 1026 1027 procedure TMainScreen.CheckTerrainBtnVisible; 1028 var 1029 Tile: integer; 1030 mox: ^TModel; 1031 begin 1032 if UnFocus>=0 then 1033 begin 1034 mox:=@MyModel[MyUn[UnFocus].mix]; 1035 Tile:=MyMap[MyUn[UnFocus].Loc]; 1036 TerrainBtn.Visible:= (Tile and fCity=0) and (MyUn[UnFocus].Master<0) 1037 and ((mox.Kind=mkSettler) or (mox.Kind=mkSlaves) and (MyRO.Wonder[woPyramids].EffectiveOwner>=0)); 1038 end 1039 else TerrainBtn.Visible:=false; 1040 end; 1041 1042 procedure TMainScreen.CheckMovieSpeedBtnState; 1043 begin 1044 if GameMode=cMovie then 1045 begin 1046 MovieSpeed1Btn.Down:= MovieSpeed=1; 1047 MovieSpeed1Btn.Visible:=true; 1048 MovieSpeed2Btn.Down:= MovieSpeed=2; 1049 MovieSpeed2Btn.Visible:=true; 1050 MovieSpeed3Btn.Down:= MovieSpeed=3; 1051 MovieSpeed3Btn.Visible:=true; 1052 MovieSpeed4Btn.Down:= MovieSpeed=4; 1053 MovieSpeed4Btn.Visible:=true; 1054 end 1055 else 1056 begin 1057 MovieSpeed1Btn.Visible:=false; 1058 MovieSpeed2Btn.Visible:=false; 1059 MovieSpeed3Btn.Visible:=false; 1060 MovieSpeed4Btn.Visible:=false; 1061 end 1062 end; 1063 1064 procedure TMainScreen.SetMapOptions; 1065 begin 1066 IsoEngine.Options:=MapOptionChecked; 1067 if ClientMode=cEditMap then 1068 IsoEngine.Options:=IsoEngine.Options or (1 shl moEditMode); 1069 if mLocCodes.Checked then 1070 IsoEngine.Options:=IsoEngine.Options or (1 shl moLocCodes); 1071 end; 1072 1073 procedure TMainScreen.UpdateViews(UpdateCityScreen: boolean); 1074 begin 1075 SumCities(TaxSum,ScienceSum); 1076 PanelPaint; // TopBar was enough!!! 1077 ListDlg.EcoChange; 1078 NatStatDlg.EcoChange; 1079 if UpdateCityScreen then 1080 CityDlg.SmartUpdateContent; 1081 end; 1082 1083 procedure TMainScreen.SetAIName(p: integer; Name: string); 1084 begin 1085 if Name='' then 1086 begin 1087 if AILogo[p]<>nil then 1088 begin AILogo[p].free; AILogo[p]:=nil end 1089 end 1090 else 1091 begin 1092 if AILogo[p]=nil then 1093 AILogo[p]:=TBitmap.Create; 1094 if not LoadGraphicFile(AILogo[p], HomeDir+Name, gfNoError) then 1095 begin AILogo[p].free; AILogo[p]:=nil end 1096 end 1097 end; 1098 1099 function TMainScreen.ContactRefused(p: integer; Item: String): boolean; 1100 // return whether treaty was cancelled 1101 var 1102 s: string; 1103 begin 1104 assert(MyRO.Treaty[p]>=trPeace); 1105 s:=Tribe[p].TPhrase(Item); 1106 if MyRO.Turn<MyRO.LastCancelTreaty[p]+CancelTreatyTurns then 1107 begin 1108 SimpleMessage(s); 1109 result:=false; 1110 end 1111 else 1112 begin 1113 case MyRO.Treaty[p] of 1114 trPeace: s:=s+' '+Phrases.Lookup('FRCANCELQUERY_PEACE'); 1115 trFriendlyContact: s:=s+' '+Phrases.Lookup('FRCANCELQUERY_FRIENDLY'); 1116 trAlliance: s:=s+' '+Phrases.Lookup('FRCANCELQUERY_ALLIANCE'); 1117 end; 1118 result:= SimpleQuery(mkYesNo,s,'NEGO_REJECTED')=mrOK; 1119 if result then 1120 begin 1121 Play('CANCELTREATY'); 1122 Server(sCancelTreaty,me,0,nil^); 1123 if MyRO.Treaty[p]=trNone then 1124 CityOptimizer_BeginOfTurn; // peace treaty was cancelled -- use formerly forbidden tiles 1125 MapValid:=false; 1126 PaintAllMaps; 1127 end 1128 end 1129 end; 1130 1131 procedure TMainScreen.RememberPeaceViolation; 1132 var 1133 uix,p1: integer; 1134 begin 1135 MyData.PeaceEvaHappened:=0; 1136 for uix:=0 to MyRO.nUn-1 do with MyUn[uix] do if Loc>=0 then 1137 begin 1138 p1:=MyRO.Territory[Loc]; 1139 if (p1<>me) and (p1>=0) and (MyRO.Turn=MyRO.EvaStart[p1]+(PeaceEvaTurns-1)) then 1140 MyData.PeaceEvaHappened:=MyData.PeaceEvaHappened or (1 shl p1); 1141 end; 1142 end; 1143 1144 procedure TMainScreen.Client(Command,NewPlayer:integer;var Data); 1145 1146 procedure GetTribeList; 1147 var 1148 SearchRec: TSearchRec; 1149 Color: TColor; 1150 Name: string; 1151 ok: boolean; 1152 begin 1153 UnusedTribeFiles.Clear; 1154 ok:= FindFirst(DataDir+'Localization\'+'Tribes\*.tribe.txt', 1155 faArchive+faReadOnly,SearchRec)=0; 1156 if not ok then 1157 begin 1158 FindClose(SearchRec); 1159 ok:= FindFirst(HomeDir+'Tribes\*.tribe.txt', 1160 faArchive+faReadOnly,SearchRec)=0; 1161 end; 1162 if ok then 1163 repeat 1164 SearchRec.Name:=Copy(SearchRec.Name,1,Length(SearchRec.Name)-10); 1165 if GetTribeInfo(SearchRec.Name,Name,Color) then 1166 UnusedTribeFiles.AddObject(SearchRec.Name, TObject(Color)); 1167 until FindNext(SearchRec)<>0; 1168 FindClose(SearchRec); 1169 end; 1170 1171 function ChooseUnusedTribe: integer; 1172 var 1173 i,j,ColorDistance, BestColorDistance, TestColorDistance, CountBest: integer; 1174 begin 1175 Assert(UnusedTribeFiles.Count>0); 1176 result:=-1; 1177 BestColorDistance:=-1; 1178 for j:=0 to UnusedTribeFiles.Count-1 do 1179 begin 1180 ColorDistance:=250; // consider differences more than this infinite 1181 for i:=0 to nPl-1 do if Tribe[i]<>nil then 1182 begin 1183 TestColorDistance:=abs(integer(UnusedTribeFiles.Objects[j]) shr 16 and $FF - Tribe[i].Color shr 16 and $FF) 1184 +abs(integer(UnusedTribeFiles.Objects[j]) shr 8 and $FF - Tribe[i].Color shr 8 and $FF)*3 1185 +abs(integer(UnusedTribeFiles.Objects[j]) and $FF - Tribe[i].Color and $FF)*2; 1186 if TestColorDistance<ColorDistance then 1187 ColorDistance:=TestColorDistance 1188 end; 1189 if ColorDistance>BestColorDistance then 1190 begin CountBest:=0; BestColorDistance:=ColorDistance end; 1191 if ColorDistance=BestColorDistance then 1192 begin inc(CountBest); if random(CountBest)=0 then result:=j end 1193 end; 1194 end; 1195 1196 procedure ShowEnemyShipChange(ShowShipChange: TShowShipChange); 1197 var 1198 i,TestCost,MostCost: integer; 1199 Ship1Plus,Ship2Plus: boolean; 1200 begin 1201 with ShowShipChange, MessgExDlg do 1202 begin 1203 case Reason of 1204 scrProduction: 1205 begin 1206 OpenSound:='SHIP_BUILT'; 1207 MessgText:=Tribe[Ship1Owner].TPhrase('SHIPBUILT'); 1208 IconKind:=mikShip; 1209 IconIndex:=Ship1Owner; 1210 end; 1211 1212 scrDestruction: 1213 begin 1214 OpenSound:='SHIP_DESTROYED'; 1215 MessgText:=Tribe[Ship1Owner].TPhrase('SHIPDESTROYED'); 1216 IconKind:=mikImp; 1217 end; 1218 1219 scrTrade: 1220 begin 1221 OpenSound:='SHIP_TRADED'; 1222 Ship1Plus:=false; 1223 Ship2Plus:=false; 1224 for i:=0 to nShipPart-1 do 1225 begin 1226 if Ship1Change[i]>0 then Ship1Plus:=true; 1227 if Ship2Change[i]>0 then Ship2Plus:=true; 1228 end; 1229 if Ship1Plus and Ship2Plus then 1230 MessgText:=Tribe[Ship1Owner].TPhrase('SHIPBITRADE1') 1231 +' '+Tribe[Ship2Owner].TPhrase('SHIPBITRADE2') 1232 else if Ship1Plus then 1233 MessgText:=Tribe[Ship1Owner].TPhrase('SHIPUNITRADE1') 1234 +' '+Tribe[Ship2Owner].TPhrase('SHIPUNITRADE2') 1235 else //if Ship2Plus then 1236 MessgText:=Tribe[Ship2Owner].TPhrase('SHIPUNITRADE1') 1237 +' '+Tribe[Ship1Owner].TPhrase('SHIPUNITRADE2'); 1238 IconKind:=mikImp; 1239 end; 1240 1241 scrCapture: 1242 begin 1243 OpenSound:='SHIP_CAPTURED'; 1244 MessgText:=Tribe[Ship2Owner].TPhrase('SHIPCAPTURE1') 1245 +' '+Tribe[Ship1Owner].TPhrase('SHIPCAPTURE2'); 1246 IconKind:=mikShip; 1247 IconIndex:=Ship2Owner; 1105 assert(not((uix >= 0) and supervising)); 1106 if uix <> UnFocus then 1107 begin 1108 DestinationMarkON := false; 1109 PaintDestination; 1110 if uix >= 0 then 1111 UnStartLoc := MyUn[uix].Loc; 1112 BlinkON := false; 1113 BlinkTime := -1; 1114 if UnFocus >= 0 then 1115 begin 1116 Loc0 := MyUn[UnFocus].Loc; 1117 if (uix < 0) or (Loc0 <> MyUn[uix].Loc) then 1118 begin 1119 UnFocus := -1; 1120 PaintLoc(Loc0); 1248 1121 end 1249 1122 end; 1250 1251 if IconKind=mikImp then 1252 begin 1253 MostCost:=0; 1254 for i:=0 to nShipPart-1 do 1255 begin 1256 TestCost:=abs(Ship1Change[i])*Imp[imShipComp+i].Cost; 1257 if TestCost>MostCost then 1258 begin MostCost:=TestCost; IconIndex:=imShipComp+i end 1259 end; 1123 UnFocus := uix; 1124 end; 1125 UnitInfoBtn.Visible := UnFocus >= 0; 1126 UnitBtn.Visible := UnFocus >= 0; 1127 CheckTerrainBtnVisible; 1128 end; 1129 1130 procedure TMainScreen.CheckTerrainBtnVisible; 1131 var 1132 Tile: integer; 1133 mox: ^TModel; 1134 begin 1135 if UnFocus >= 0 then 1136 begin 1137 mox := @MyModel[MyUn[UnFocus].mix]; 1138 Tile := MyMap[MyUn[UnFocus].Loc]; 1139 TerrainBtn.Visible := (Tile and fCity = 0) and (MyUn[UnFocus].Master < 0) 1140 and ((mox.Kind = mkSettler) or (mox.Kind = mkSlaves) and 1141 (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)); 1142 end 1143 else 1144 TerrainBtn.Visible := false; 1145 end; 1146 1147 procedure TMainScreen.CheckMovieSpeedBtnState; 1148 begin 1149 if GameMode = cMovie then 1150 begin 1151 MovieSpeed1Btn.Down := MovieSpeed = 1; 1152 MovieSpeed1Btn.Visible := true; 1153 MovieSpeed2Btn.Down := MovieSpeed = 2; 1154 MovieSpeed2Btn.Visible := true; 1155 MovieSpeed3Btn.Down := MovieSpeed = 3; 1156 MovieSpeed3Btn.Visible := true; 1157 MovieSpeed4Btn.Down := MovieSpeed = 4; 1158 MovieSpeed4Btn.Visible := true; 1159 end 1160 else 1161 begin 1162 MovieSpeed1Btn.Visible := false; 1163 MovieSpeed2Btn.Visible := false; 1164 MovieSpeed3Btn.Visible := false; 1165 MovieSpeed4Btn.Visible := false; 1166 end 1167 end; 1168 1169 procedure TMainScreen.SetMapOptions; 1170 begin 1171 IsoEngine.Options := MapOptionChecked; 1172 if ClientMode = cEditMap then 1173 IsoEngine.Options := IsoEngine.Options or (1 shl moEditMode); 1174 if mLocCodes.Checked then 1175 IsoEngine.Options := IsoEngine.Options or (1 shl moLocCodes); 1176 end; 1177 1178 procedure TMainScreen.UpdateViews(UpdateCityScreen: boolean); 1179 begin 1180 SumCities(TaxSum, ScienceSum); 1181 PanelPaint; // TopBar was enough!!! 1182 ListDlg.EcoChange; 1183 NatStatDlg.EcoChange; 1184 if UpdateCityScreen then 1185 CityDlg.SmartUpdateContent; 1186 end; 1187 1188 procedure TMainScreen.SetAIName(p: integer; Name: string); 1189 begin 1190 if Name = '' then 1191 begin 1192 if AILogo[p] <> nil then 1193 begin 1194 AILogo[p].free; 1195 AILogo[p] := nil 1196 end 1197 end 1198 else 1199 begin 1200 if AILogo[p] = nil then 1201 AILogo[p] := TBitmap.Create; 1202 if not LoadGraphicFile(AILogo[p], HomeDir + Name, gfNoError) then 1203 begin 1204 AILogo[p].free; 1205 AILogo[p] := nil 1206 end 1207 end 1208 end; 1209 1210 function TMainScreen.ContactRefused(p: integer; Item: String): boolean; 1211 // return whether treaty was cancelled 1212 var 1213 s: string; 1214 begin 1215 assert(MyRO.Treaty[p] >= trPeace); 1216 s := Tribe[p].TPhrase(Item); 1217 if MyRO.Turn < MyRO.LastCancelTreaty[p] + CancelTreatyTurns then 1218 begin 1219 SimpleMessage(s); 1220 result := false; 1221 end 1222 else 1223 begin 1224 case MyRO.Treaty[p] of 1225 trPeace: 1226 s := s + ' ' + Phrases.Lookup('FRCANCELQUERY_PEACE'); 1227 trFriendlyContact: 1228 s := s + ' ' + Phrases.Lookup('FRCANCELQUERY_FRIENDLY'); 1229 trAlliance: 1230 s := s + ' ' + Phrases.Lookup('FRCANCELQUERY_ALLIANCE'); 1260 1231 end; 1261 1262 Kind:=mkOk; 1263 ShowModal; 1264 end; 1232 result := SimpleQuery(mkYesNo, s, 'NEGO_REJECTED') = mrOK; 1233 if result then 1234 begin 1235 Play('CANCELTREATY'); 1236 Server(sCancelTreaty, me, 0, nil^); 1237 if MyRO.Treaty[p] = trNone then 1238 CityOptimizer_BeginOfTurn; 1239 // peace treaty was cancelled -- use formerly forbidden tiles 1240 MapValid := false; 1241 PaintAllMaps; 1242 end 1243 end 1265 1244 end; 1266 1245 1267 procedure InitModule;1246 procedure TMainScreen.RememberPeaceViolation; 1268 1247 var 1269 x,y,i,j,Domain:integer;1248 uix, p1: integer; 1270 1249 begin 1271 {search icons for advances:} 1272 for i:=0 to nAdv-1 do 1273 if i in FutureTech then AdvIcon[i]:=96+i-futResearchTechnology 1274 else 1275 begin 1276 AdvIcon[i]:=-1; 1277 for Domain:=0 to nDomains-1 do 1278 for j:=0 to nUpgrade-1 do if upgrade[Domain,j].Preq=i then 1279 if AdvIcon[i]>=0 then AdvIcon[i]:=85 1280 else AdvIcon[i]:=86+Domain; 1281 for j:=0 to nFeature-1 do if Feature[j].Preq=i then 1282 for Domain:=0 to nDomains-1 do 1283 if 1 shl Domain and Feature[j].Domains<>0 then 1284 if (AdvIcon[i]>=0) and (AdvIcon[i]<>86+Domain) then AdvIcon[i]:=85 1285 else AdvIcon[i]:=86+Domain; 1286 for j:=28 to nImp-1 do if Imp[j].Preq=i then AdvIcon[i]:=j; 1287 for j:=28 to nImp-1 do 1288 if (Imp[j].Preq=i) and (Imp[j].Kind<>ikCommon) then AdvIcon[i]:=j; 1289 for j:=0 to nJob-1 do if i=JobPreq[j] then AdvIcon[i]:=84; 1290 for j:=0 to 27 do if Imp[j].Preq=i then AdvIcon[i]:=j; 1291 if AdvIcon[i]<0 then 1292 if AdvValue[i]<1000 then AdvIcon[i]:=-7 1293 else AdvIcon[i]:=24+AdvValue[i] div 1000; 1294 for j:=2 to nGov-1 do if GovPreq[j]=i then AdvIcon[i]:=j-8; 1250 MyData.PeaceEvaHappened := 0; 1251 for uix := 0 to MyRO.nUn - 1 do 1252 with MyUn[uix] do 1253 if Loc >= 0 then 1254 begin 1255 p1 := MyRO.Territory[Loc]; 1256 if (p1 <> me) and (p1 >= 0) and 1257 (MyRO.Turn = MyRO.EvaStart[p1] + (PeaceEvaTurns - 1)) then 1258 MyData.PeaceEvaHappened := MyData.PeaceEvaHappened or (1 shl p1); 1259 end; 1260 end; 1261 1262 procedure TMainScreen.Client(Command, NewPlayer: integer; var Data); 1263 1264 procedure GetTribeList; 1265 var 1266 SearchRec: TSearchRec; 1267 Color: TColor; 1268 Name: string; 1269 ok: boolean; 1270 begin 1271 UnusedTribeFiles.Clear; 1272 ok := FindFirst(DataDir + 'Localization\' + 'Tribes\*.tribe.txt', 1273 faArchive + faReadOnly, SearchRec) = 0; 1274 if not ok then 1275 begin 1276 FindClose(SearchRec); 1277 ok := FindFirst(HomeDir + 'Tribes\*.tribe.txt', faArchive + faReadOnly, 1278 SearchRec) = 0; 1295 1279 end; 1296 AdvIcon[adConscription]:=86+dGround; 1297 1298 UnusedTribeFiles:=tstringlist.Create; 1299 UnusedTribeFiles.Sorted:=true; 1300 TribeNames:=tstringlist.Create; 1301 1302 for x:=0 to 11 do for y:=0 to 1 do 1303 MiniColors[x,y]:=GrExt[HGrSystem].Data.Canvas.Pixels[66+x,67+y]; 1304 IsoEngine.Init(InitEnemyModel); 1305 if not IsoEngine.ApplyTileSize(xxt,yyt) and ((xxt<>48) or (yyt<>24)) then 1306 ApplyTileSize(48,24); // non-default tile size is missing a file, switch to default 1307 MainMap:=TIsoMap.Create; 1308 MainMap.SetOutput(offscreen); 1309 1310 HGrStdUnits:=LoadGraphicSet('StdUnits'); 1311 SmallImp:=TBitmap.Create; 1312 SmallImp.PixelFormat:=pf24bit; 1313 InitSmallImp; 1314 SoundPreloadDone:=0; 1315 StartRunning:=false; 1316 StayOnTop_Ensured:=false; 1317 1318 CreatePVSB(sb,Handle,100-200,122,100+MidPanelHeight-16-200); 1319 end;{InitModule} 1280 if ok then 1281 repeat 1282 SearchRec.Name := Copy(SearchRec.Name, 1, 1283 Length(SearchRec.Name) - 10); 1284 if GetTribeInfo(SearchRec.Name, Name, Color) then 1285 UnusedTribeFiles.AddObject(SearchRec.Name, TObject(Color)); 1286 until FindNext(SearchRec) <> 0; 1287 FindClose(SearchRec); 1288 end; 1289 1290 function ChooseUnusedTribe: integer; 1291 var 1292 i, j, ColorDistance, BestColorDistance, TestColorDistance, 1293 CountBest: integer; 1294 begin 1295 assert(UnusedTribeFiles.Count > 0); 1296 result := -1; 1297 BestColorDistance := -1; 1298 for j := 0 to UnusedTribeFiles.Count - 1 do 1299 begin 1300 ColorDistance := 250; // consider differences more than this infinite 1301 for i := 0 to nPl - 1 do 1302 if Tribe[i] <> nil then 1303 begin 1304 TestColorDistance := 1305 abs(integer(UnusedTribeFiles.Objects[j]) shr 16 and 1306 $FF - Tribe[i].Color shr 16 and $FF) + 1307 abs(integer(UnusedTribeFiles.Objects[j]) shr 8 and 1308 $FF - Tribe[i].Color shr 8 and $FF) * 3 + 1309 abs(integer(UnusedTribeFiles.Objects[j]) and 1310 $FF - Tribe[i].Color and $FF) * 2; 1311 if TestColorDistance < ColorDistance then 1312 ColorDistance := TestColorDistance 1313 end; 1314 if ColorDistance > BestColorDistance then 1315 begin 1316 CountBest := 0; 1317 BestColorDistance := ColorDistance 1318 end; 1319 if ColorDistance = BestColorDistance then 1320 begin 1321 inc(CountBest); 1322 if random(CountBest) = 0 then 1323 result := j 1324 end 1325 end; 1326 end; 1327 1328 procedure ShowEnemyShipChange(ShowShipChange: TShowShipChange); 1329 var 1330 i, TestCost, MostCost: integer; 1331 Ship1Plus, Ship2Plus: boolean; 1332 begin 1333 with ShowShipChange, MessgExDlg do 1334 begin 1335 case Reason of 1336 scrProduction: 1337 begin 1338 OpenSound := 'SHIP_BUILT'; 1339 MessgText := Tribe[Ship1Owner].TPhrase('SHIPBUILT'); 1340 IconKind := mikShip; 1341 IconIndex := Ship1Owner; 1342 end; 1343 1344 scrDestruction: 1345 begin 1346 OpenSound := 'SHIP_DESTROYED'; 1347 MessgText := Tribe[Ship1Owner].TPhrase('SHIPDESTROYED'); 1348 IconKind := mikImp; 1349 end; 1350 1351 scrTrade: 1352 begin 1353 OpenSound := 'SHIP_TRADED'; 1354 Ship1Plus := false; 1355 Ship2Plus := false; 1356 for i := 0 to nShipPart - 1 do 1357 begin 1358 if Ship1Change[i] > 0 then 1359 Ship1Plus := true; 1360 if Ship2Change[i] > 0 then 1361 Ship2Plus := true; 1362 end; 1363 if Ship1Plus and Ship2Plus then 1364 MessgText := Tribe[Ship1Owner].TPhrase('SHIPBITRADE1') + ' ' + 1365 Tribe[Ship2Owner].TPhrase('SHIPBITRADE2') 1366 else if Ship1Plus then 1367 MessgText := Tribe[Ship1Owner].TPhrase('SHIPUNITRADE1') + ' ' + 1368 Tribe[Ship2Owner].TPhrase('SHIPUNITRADE2') 1369 else // if Ship2Plus then 1370 MessgText := Tribe[Ship2Owner].TPhrase('SHIPUNITRADE1') + ' ' + 1371 Tribe[Ship1Owner].TPhrase('SHIPUNITRADE2'); 1372 IconKind := mikImp; 1373 end; 1374 1375 scrCapture: 1376 begin 1377 OpenSound := 'SHIP_CAPTURED'; 1378 MessgText := Tribe[Ship2Owner].TPhrase('SHIPCAPTURE1') + ' ' + 1379 Tribe[Ship1Owner].TPhrase('SHIPCAPTURE2'); 1380 IconKind := mikShip; 1381 IconIndex := Ship2Owner; 1382 end 1383 end; 1384 1385 if IconKind = mikImp then 1386 begin 1387 MostCost := 0; 1388 for i := 0 to nShipPart - 1 do 1389 begin 1390 TestCost := abs(Ship1Change[i]) * Imp[imShipComp + i].Cost; 1391 if TestCost > MostCost then 1392 begin 1393 MostCost := TestCost; 1394 IconIndex := imShipComp + i 1395 end 1396 end; 1397 end; 1398 1399 Kind := mkOk; 1400 ShowModal; 1401 end; 1402 end; 1403 1404 procedure InitModule; 1405 var 1406 x, y, i, j, Domain: integer; 1407 begin 1408 { search icons for advances: } 1409 for i := 0 to nAdv - 1 do 1410 if i in FutureTech then 1411 AdvIcon[i] := 96 + i - futResearchTechnology 1412 else 1413 begin 1414 AdvIcon[i] := -1; 1415 for Domain := 0 to nDomains - 1 do 1416 for j := 0 to nUpgrade - 1 do 1417 if upgrade[Domain, j].Preq = i then 1418 if AdvIcon[i] >= 0 then 1419 AdvIcon[i] := 85 1420 else 1421 AdvIcon[i] := 86 + Domain; 1422 for j := 0 to nFeature - 1 do 1423 if Feature[j].Preq = i then 1424 for Domain := 0 to nDomains - 1 do 1425 if 1 shl Domain and Feature[j].Domains <> 0 then 1426 if (AdvIcon[i] >= 0) and (AdvIcon[i] <> 86 + Domain) then 1427 AdvIcon[i] := 85 1428 else 1429 AdvIcon[i] := 86 + Domain; 1430 for j := 28 to nImp - 1 do 1431 if Imp[j].Preq = i then 1432 AdvIcon[i] := j; 1433 for j := 28 to nImp - 1 do 1434 if (Imp[j].Preq = i) and (Imp[j].Kind <> ikCommon) then 1435 AdvIcon[i] := j; 1436 for j := 0 to nJob - 1 do 1437 if i = JobPreq[j] then 1438 AdvIcon[i] := 84; 1439 for j := 0 to 27 do 1440 if Imp[j].Preq = i then 1441 AdvIcon[i] := j; 1442 if AdvIcon[i] < 0 then 1443 if AdvValue[i] < 1000 then 1444 AdvIcon[i] := -7 1445 else 1446 AdvIcon[i] := 24 + AdvValue[i] div 1000; 1447 for j := 2 to nGov - 1 do 1448 if GovPreq[j] = i then 1449 AdvIcon[i] := j - 8; 1450 end; 1451 AdvIcon[adConscription] := 86 + dGround; 1452 1453 UnusedTribeFiles := tstringlist.Create; 1454 UnusedTribeFiles.Sorted := true; 1455 TribeNames := tstringlist.Create; 1456 1457 for x := 0 to 11 do 1458 for y := 0 to 1 do 1459 MiniColors[x, y] := GrExt[HGrSystem].Data.Canvas.Pixels 1460 [66 + x, 67 + y]; 1461 IsoEngine.Init(InitEnemyModel); 1462 if not IsoEngine.ApplyTileSize(xxt, yyt) and ((xxt <> 48) or (yyt <> 24)) 1463 then 1464 ApplyTileSize(48, 24); 1465 // non-default tile size is missing a file, switch to default 1466 MainMap := TIsoMap.Create; 1467 MainMap.SetOutput(offscreen); 1468 1469 HGrStdUnits := LoadGraphicSet('StdUnits'); 1470 SmallImp := TBitmap.Create; 1471 SmallImp.PixelFormat := pf24bit; 1472 InitSmallImp; 1473 SoundPreloadDone := 0; 1474 StartRunning := false; 1475 StayOnTop_Ensured := false; 1476 1477 CreatePVSB(sb, Handle, 100 - 200, 122, 100 + MidPanelHeight - 16 - 200); 1478 end; { InitModule } 1320 1479 1321 1480 // sound blocks for preload 1322 1481 const 1323 sbStart=$01; sbWonder=$02; sbScience=$04; sbContact=$08; 1324 sbTurn=$10; sbAll=$FF; 1325 1326 procedure SoundPreload(Check: integer); 1327 const 1328 nStartBlock=27; 1329 StartBlock: array[0..nStartBlock-1] of string= 1330 ('INVALID','TURNEND','DISBAND','CHEAT','MSG_DEFAULT','WARNING_DISORDER', 1331 'WARNING_FAMINE','WARNING_LOWSUPPORT','WARNING_LOWFUNDS','MOVE_MOUNTAIN', 1332 'MOVE_LOAD','MOVE_UNLOAD','MOVE_DIE','NOMOVE_TIME','NOMOVE_DOMAIN', 1333 'NOMOVE_DEFAULT','CITY_SELLIMP','CITY_REBUILDIMP','CITY_BUYPROJECT', 1334 'CITY_UTILIZE','NEWMODEL_0','NEWADVANCE_0','AGE_0','REVOLUTION','NEWGOV', 1335 'CITY_INVALIDTYPE','MSG_GAMEOVER'); 1336 1337 nWonderBlock=6; 1338 WonderBlock: array[0..nWonderBlock-1] of string= 1339 ('WONDER_BUILT','WONDER_CAPTURED','WONDER_EXPIRED','WONDER_DESTROYED', 1340 'MSG_COLDWAR','NEWADVANCE_GRLIB'); 1341 1342 nScienceBlock=17; 1343 ScienceBlock: array[0..nScienceBlock-1] of string= 1344 ('MOVE_PARACHUTE','MOVE_PLANESTART','MOVE_PLANELANDING','MOVE_COVERT', 1345 'NEWMODEL_1','NEWMODEL_2','NEWMODEL_3','NEWADVANCE_1','NEWADVANCE_2', 1346 'NEWADVANCE_3','AGE_1','AGE_2','AGE_3','SHIP_BUILT','SHIP_TRADED', 1347 'SHIP_CAPTURED','SHIP_DESTROYED'); 1348 1349 nContactBlock=20; 1350 ContactBlock: array[0..nContactBlock-1] of string= 1351 ('NEWTREATY','CANCELTREATY','ACCEPTOFFER','MSG_WITHDRAW','MSG_BANKRUPT', 1352 'CONTACT_0','CONTACT_1','CONTACT_2','CONTACT_3','CONTACT_4','CONTACT_5', 1353 'CONTACT_5','CONTACT_6','NEGO_REJECTED','MOVE_CAPTURE','MOVE_EXPEL', 1354 'NOMOVE_TREATY','NOMOVE_ZOC','NOMOVE_SUBMARINE','NOMOVE_STEALTH'); 1355 1356 var 1357 i,cix,mix: integer; 1358 need: boolean; 1359 mi: TModelInfo; 1360 begin 1361 if Check and sbStart and not SoundPreloadDone<>0 then 1362 begin 1363 for i:=0 to nStartBlock-1 do PreparePlay(StartBlock[i]); 1364 SoundPreloadDone:=SoundPreloadDone or sbStart; 1365 end; 1366 if Check and sbWonder and not SoundPreloadDone<>0 then 1367 begin 1368 need:=false; 1369 for i:=0 to 27 do if MyRO.Wonder[i].CityID<>-1 then need:=true; 1370 if need then 1371 begin 1372 for i:=0 to nWonderBlock-1 do PreparePlay(WonderBlock[i]); 1373 SoundPreloadDone:=SoundPreloadDone or sbWonder; 1482 sbStart = $01; 1483 sbWonder = $02; 1484 sbScience = $04; 1485 sbContact = $08; 1486 sbTurn = $10; 1487 sbAll = $FF; 1488 1489 procedure SoundPreload(Check: integer); 1490 const 1491 nStartBlock = 27; 1492 StartBlock: array [0 .. nStartBlock - 1] of string = ('INVALID', 1493 'TURNEND', 'DISBAND', 'CHEAT', 'MSG_DEFAULT', 'WARNING_DISORDER', 1494 'WARNING_FAMINE', 'WARNING_LOWSUPPORT', 'WARNING_LOWFUNDS', 1495 'MOVE_MOUNTAIN', 'MOVE_LOAD', 'MOVE_UNLOAD', 'MOVE_DIE', 'NOMOVE_TIME', 1496 'NOMOVE_DOMAIN', 'NOMOVE_DEFAULT', 'CITY_SELLIMP', 'CITY_REBUILDIMP', 1497 'CITY_BUYPROJECT', 'CITY_UTILIZE', 'NEWMODEL_0', 'NEWADVANCE_0', 1498 'AGE_0', 'REVOLUTION', 'NEWGOV', 'CITY_INVALIDTYPE', 'MSG_GAMEOVER'); 1499 1500 nWonderBlock = 6; 1501 WonderBlock: array [0 .. nWonderBlock - 1] of string = ('WONDER_BUILT', 1502 'WONDER_CAPTURED', 'WONDER_EXPIRED', 'WONDER_DESTROYED', 'MSG_COLDWAR', 1503 'NEWADVANCE_GRLIB'); 1504 1505 nScienceBlock = 17; 1506 ScienceBlock: array [0 .. nScienceBlock - 1] of string = 1507 ('MOVE_PARACHUTE', 'MOVE_PLANESTART', 'MOVE_PLANELANDING', 1508 'MOVE_COVERT', 'NEWMODEL_1', 'NEWMODEL_2', 'NEWMODEL_3', 'NEWADVANCE_1', 1509 'NEWADVANCE_2', 'NEWADVANCE_3', 'AGE_1', 'AGE_2', 'AGE_3', 'SHIP_BUILT', 1510 'SHIP_TRADED', 'SHIP_CAPTURED', 'SHIP_DESTROYED'); 1511 1512 nContactBlock = 20; 1513 ContactBlock: array [0 .. nContactBlock - 1] of string = ('NEWTREATY', 1514 'CANCELTREATY', 'ACCEPTOFFER', 'MSG_WITHDRAW', 'MSG_BANKRUPT', 1515 'CONTACT_0', 'CONTACT_1', 'CONTACT_2', 'CONTACT_3', 'CONTACT_4', 1516 'CONTACT_5', 'CONTACT_5', 'CONTACT_6', 'NEGO_REJECTED', 'MOVE_CAPTURE', 1517 'MOVE_EXPEL', 'NOMOVE_TREATY', 'NOMOVE_ZOC', 'NOMOVE_SUBMARINE', 1518 'NOMOVE_STEALTH'); 1519 1520 var 1521 i, cix, mix: integer; 1522 need: boolean; 1523 mi: TModelInfo; 1524 begin 1525 if Check and sbStart and not SoundPreloadDone <> 0 then 1526 begin 1527 for i := 0 to nStartBlock - 1 do 1528 PreparePlay(StartBlock[i]); 1529 SoundPreloadDone := SoundPreloadDone or sbStart; 1374 1530 end; 1375 end; 1376 if (Check and sbScience and not SoundPreloadDone<>0) 1377 and (MyRO.Tech[adScience]>=tsApplicable) then 1378 begin 1379 for i:=0 to nScienceBlock-1 do PreparePlay(ScienceBlock[i]); 1380 SoundPreloadDone:=SoundPreloadDone or sbScience; 1381 end; 1382 if (Check and sbContact and not SoundPreloadDone<>0) 1383 and (MyRO.nEnemyModel+MyRO.nEnemyCity>0) then 1384 begin 1385 for i:=0 to nContactBlock-1 do PreparePlay(ContactBlock[i]); 1386 SoundPreloadDone:=SoundPreloadDone or sbContact; 1387 end; 1388 if Check and sbTurn<>0 then 1389 begin 1390 if MyRO.Happened and phShipComplete<>0 then 1391 PreparePlay('MSG_YOUWIN'); 1392 if MyData.ToldAlive<>MyRO.Alive then PreparePlay('MSG_EXTINCT'); 1393 for cix:=0 to MyRO.nCity-1 do with MyCity[cix] do 1394 if (Loc>=0) and (Flags and CityRepMask<>0) then 1395 for i:=0 to 12 do if 1 shl i and Flags and CityRepMask<>0 then 1396 PreparePlay(CityEventSoundItem[i]); 1397 for mix:=0 to MyRO.nModel-1 do with MyModel[mix] do if Attack>0 then 1398 begin 1399 MakeModelInfo(me,mix,MyModel[mix],mi); 1400 PreparePlay(AttackSound(ModelCode(mi))); 1401 end 1402 end 1403 end; 1404 1405 procedure InitTurn(p: integer); 1406 const 1407 nAdvBookIcon=16; 1408 AdvBookIcon: array[0..nAdvBookIcon-1] of record Adv,Icon: integer end= 1409 ((Adv:adPolyTheism;Icon:woZeus),(Adv:adBronzeWorking;Icon:woColossus), 1410 (Adv:adMapMaking;Icon:woLighthouse),(Adv:adPoetry;Icon:imTheater), 1411 (Adv:adMonotheism;Icon:woMich),(Adv:adPhilosophy;Icon:woLeo), 1412 (Adv:adTheoryOfGravity;Icon:woNewton),(Adv:adSteel;Icon:woEiffel), 1413 (Adv:adDemocracy;Icon:woLiberty),(Adv:adAutomobile;Icon:imHighways), 1414 (Adv:adSanitation;Icon:imSewer),(Adv:adElectronics;Icon:woHoover), 1415 (Adv:adNuclearFission;Icon:woManhattan),(Adv:adRecycling;Icon:imRecycling), 1416 (Adv:adComputers;Icon:imResLab),(Adv:adSpaceFlight;Icon:woMIR)); 1417 var 1418 Domain,p1,i,ad,uix,cix,MoveOptions,MoveResult,Loc1,Dist,NewAgeCenterTo, 1419 Bankrupt,ShipMore,Winners,NewGovAvailable,dx,dy:integer; 1420 MoveAdviceData: TMoveAdviceData; 1421 Picture: TModelPictureInfo; 1422 s, Item, Item2: string; 1423 UpdatePanel, OwnWonder, ok, Stop, ShowCityList, WondersOnly,AllowCityScreen: boolean; 1424 begin 1425 if IsMultiPlayerGame and (p<>me) then 1426 begin 1427 UnitInfoBtn.Visible:=false; 1428 UnitBtn.Visible:=false; 1429 TerrainBtn.Visible:=false; 1430 EOT.Visible:=false; 1431 end; 1432 if IsMultiPlayerGame and (p<>me) and (G.RO[0].Happened and phShipComplete=0) then 1433 begin //inter player screen 1434 for i:=0 to ControlCount-1 do if Controls[i] is TButtonC then 1435 Controls[i].visible:=false; 1436 me:=-1; 1437 SetMainTextureByAge(-1); 1438 with Panel.Canvas do 1439 begin 1440 Brush.Color:=$000000; 1441 FillRect(Rect(0,0,Panel.Width,Panel.Height)); 1442 Brush.Style:=bsClear; 1531 if Check and sbWonder and not SoundPreloadDone <> 0 then 1532 begin 1533 need := false; 1534 for i := 0 to 27 do 1535 if MyRO.Wonder[i].CityID <> -1 then 1536 need := true; 1537 if need then 1538 begin 1539 for i := 0 to nWonderBlock - 1 do 1540 PreparePlay(WonderBlock[i]); 1541 SoundPreloadDone := SoundPreloadDone or sbWonder; 1542 end; 1443 1543 end; 1444 with TopBar.Canvas do 1445 begin 1446 Brush.Color:=$000000; 1447 FillRect(Rect(0,0,TopBar.Width,TopBar.Height)); 1448 Brush.Style:=bsClear; 1544 if (Check and sbScience and not SoundPreloadDone <> 0) and 1545 (MyRO.Tech[adScience] >= tsApplicable) then 1546 begin 1547 for i := 0 to nScienceBlock - 1 do 1548 PreparePlay(ScienceBlock[i]); 1549 SoundPreloadDone := SoundPreloadDone or sbScience; 1449 1550 end; 1450 Invalidate; 1451 1452 s:=TurnToString(G.RO[0].Turn); 1453 if supervising then 1454 SimpleMessage(Format(Phrases.Lookup('SUPERTURN'),[s])) 1455 else SimpleMessage(Format(Tribe[NewPlayer].TPhrase('TURN'),[s])); 1456 end; 1457 for i:=0 to ControlCount-1 do if Controls[i] is TButtonC then 1458 Controls[i].visible:=true; 1459 1460 ItsMeAgain(p); 1461 MyData:=G.RO[p].Data; 1462 if not supervising then 1463 SoundPreload(sbAll); 1464 if (me=0) and ((MyRO.Turn=0) or (ClientMode=cResume)) then 1465 Invalidate; // colorize empty space 1466 1467 if not supervising then 1468 begin 1469 { if MyRO.Happened and phGameEnd<>0 then 1470 begin 1471 Age:=3; 1472 SetMainTextureByAge(-1); 1551 if (Check and sbContact and not SoundPreloadDone <> 0) and 1552 (MyRO.nEnemyModel + MyRO.nEnemyCity > 0) then 1553 begin 1554 for i := 0 to nContactBlock - 1 do 1555 PreparePlay(ContactBlock[i]); 1556 SoundPreloadDone := SoundPreloadDone or sbContact; 1557 end; 1558 if Check and sbTurn <> 0 then 1559 begin 1560 if MyRO.Happened and phShipComplete <> 0 then 1561 PreparePlay('MSG_YOUWIN'); 1562 if MyData.ToldAlive <> MyRO.Alive then 1563 PreparePlay('MSG_EXTINCT'); 1564 for cix := 0 to MyRO.nCity - 1 do 1565 with MyCity[cix] do 1566 if (Loc >= 0) and (Flags and CityRepMask <> 0) then 1567 for i := 0 to 12 do 1568 if 1 shl i and Flags and CityRepMask <> 0 then 1569 PreparePlay(CityEventSoundItem[i]); 1570 for mix := 0 to MyRO.nModel - 1 do 1571 with MyModel[mix] do 1572 if Attack > 0 then 1573 begin 1574 MakeModelInfo(me, mix, MyModel[mix], mi); 1575 PreparePlay(AttackSound(ModelCode(mi))); 1576 end 1473 1577 end 1474 else} 1475 begin 1476 Age:=GetAge(me); 1477 if SetMainTextureByAge(Age) then 1478 EOT.Invalidate; // has visible background parts in its bounds 1578 end; 1579 1580 procedure InitTurn(p: integer); 1581 const 1582 nAdvBookIcon = 16; 1583 AdvBookIcon: array [0 .. nAdvBookIcon - 1] of record Adv, 1584 Icon: integer end = ((Adv: adPolyTheism; Icon: woZeus), 1585 (Adv: adBronzeWorking; Icon: woColossus), (Adv: adMapMaking; 1586 Icon: woLighthouse), (Adv: adPoetry; Icon: imTheater), 1587 (Adv: adMonotheism; Icon: woMich), (Adv: adPhilosophy; Icon: woLeo), 1588 (Adv: adTheoryOfGravity; Icon: woNewton), (Adv: adSteel; 1589 Icon: woEiffel), (Adv: adDemocracy; Icon: woLiberty), 1590 (Adv: adAutomobile; Icon: imHighways), (Adv: adSanitation; 1591 Icon: imSewer), (Adv: adElectronics; Icon: woHoover), 1592 (Adv: adNuclearFission; Icon: woManhattan), (Adv: adRecycling; 1593 Icon: imRecycling), (Adv: adComputers; Icon: imResLab), 1594 (Adv: adSpaceFlight; Icon: woMIR)); 1595 var 1596 Domain, p1, i, ad, uix, cix, MoveOptions, MoveResult, Loc1, Dist, 1597 NewAgeCenterTo, Bankrupt, ShipMore, Winners, NewGovAvailable, dx, 1598 dy: integer; 1599 MoveAdviceData: TMoveAdviceData; 1600 Picture: TModelPictureInfo; 1601 s, Item, Item2: string; 1602 UpdatePanel, OwnWonder, ok, Stop, ShowCityList, WondersOnly, 1603 AllowCityScreen: boolean; 1604 begin 1605 if IsMultiPlayerGame and (p <> me) then 1606 begin 1607 UnitInfoBtn.Visible := false; 1608 UnitBtn.Visible := false; 1609 TerrainBtn.Visible := false; 1610 EOT.Visible := false; 1479 1611 end; 1480 // age:=MyRO.Turn mod 4; //!!! 1481 if ClientMode=cMovieTurn then 1482 EOT.ButtonIndex:=eotCancel 1483 else if ClientMode<scContact then 1484 EOT.ButtonIndex:=eotGray 1485 else EOT.ButtonIndex:=eotBackToNego; 1486 end 1487 else 1488 begin 1489 Age:=0; 1490 SetMainTextureByAge(-1); 1491 if ClientMode=cMovieTurn then 1492 EOT.ButtonIndex:=eotCancel 1493 else EOT.ButtonIndex:=eotBlinkOn; 1494 end; 1495 InitCityMark(MainTexture); 1496 CityDlg.CheckAge; 1497 NatStatDlg.CheckAge; 1498 UnitStatDlg.CheckAge; 1499 HelpDlg.Difficulty:=G.Difficulty[me]; 1500 1501 UnFocus:=-1; 1502 MarkCityLoc:=-1; 1503 BlinkON:=false; 1504 BlinkTime:=-1; 1505 Tracking:=false; 1506 TurnComplete:=false; 1507 1508 if (ToldSlavery<0) 1509 or ((ToldSlavery=1)<>(MyRO.Wonder[woPyramids].EffectiveOwner>=0)) then 1510 begin 1511 if MyRO.Wonder[woPyramids].EffectiveOwner>=0 then ToldSlavery:=1 1512 else ToldSlavery:=0; 1513 for p1:=0 to nPl-1 do 1514 if (Tribe[p1]<>nil) and (Tribe[p1].mixSlaves>=0) then 1515 with Picture do 1516 begin // replace unit picture 1517 mix:=Tribe[p1].mixSlaves; 1518 if ToldSlavery=1 then pix:=pixSlaves else pix:=pixNoSlaves; 1519 Hash:=0; 1520 GrName:='StdUnits'; 1521 Tribe[p1].SetModelPicture(Picture, true); 1612 if IsMultiPlayerGame and (p <> me) and 1613 (G.RO[0].Happened and phShipComplete = 0) then 1614 begin // inter player screen 1615 for i := 0 to ControlCount - 1 do 1616 if Controls[i] is TButtonC then 1617 Controls[i].Visible := false; 1618 me := -1; 1619 SetMainTextureByAge(-1); 1620 with Panel.Canvas do 1621 begin 1622 Brush.Color := $000000; 1623 FillRect(Rect(0, 0, Panel.width, Panel.height)); 1624 Brush.Style := bsClear; 1625 end; 1626 with TopBar.Canvas do 1627 begin 1628 Brush.Color := $000000; 1629 FillRect(Rect(0, 0, TopBar.width, TopBar.height)); 1630 Brush.Style := bsClear; 1631 end; 1632 Invalidate; 1633 1634 s := TurnToString(G.RO[0].Turn); 1635 if supervising then 1636 SimpleMessage(Format(Phrases.Lookup('SUPERTURN'), [s])) 1637 else 1638 SimpleMessage(Format(Tribe[NewPlayer].TPhrase('TURN'), [s])); 1639 end; 1640 for i := 0 to ControlCount - 1 do 1641 if Controls[i] is TButtonC then 1642 Controls[i].Visible := true; 1643 1644 ItsMeAgain(p); 1645 MyData := G.RO[p].Data; 1646 if not supervising then 1647 SoundPreload(sbAll); 1648 if (me = 0) and ((MyRO.Turn = 0) or (ClientMode = cResume)) then 1649 Invalidate; // colorize empty space 1650 1651 if not supervising then 1652 begin 1653 1654 { if MyRO.Happened and phGameEnd<>0 then 1655 begin 1656 Age:=3; 1657 SetMainTextureByAge(-1); 1522 1658 end 1523 end; 1524 1525 if not supervising and (ClientMode=cTurn) then 1526 begin 1527 for cix:=0 to MyRO.nCity-1 do 1528 if (MyCity[cix].Loc>=0) 1529 and ((MyRO.Turn=0) or (MyCity[cix].Flags and chFounded<>0)) then 1530 MyCity[cix].Status:=MyCity[cix].Status 1531 and not csResourceWeightsMask or (3 shl 4); // new city, set to maximum growth 1532 end; 1533 if (ClientMode=cTurn) or (ClientMode=cContinue) then 1534 CityOptimizer_BeginOfTurn; // maybe peace was made or has ended 1535 SumCities(TaxSum,ScienceSum); 1536 1537 if ClientMode=cMovieTurn then 1538 begin 1539 UnitInfoBtn.Visible:=false; 1540 UnitBtn.Visible:=false; 1541 TerrainBtn.Visible:=false; 1542 EOT.Hint:=Phrases.Lookup('BTN_STOP'); 1543 EOT.Visible:=true; 1544 end 1545 else if ClientMode<scContact then 1546 begin 1547 UnitInfoBtn.Visible:= UnFocus>=0; 1548 UnitBtn.Visible:= UnFocus>=0; 1549 CheckTerrainBtnVisible; 1550 TurnComplete:=supervising; 1551 EOT.Hint:=Phrases.Lookup('BTN_ENDTURN'); 1552 EOT.Visible:= Server(sTurn-sExecute,me,0,nil^)>=rExecuted; 1553 end 1554 else 1555 begin 1556 UnitInfoBtn.Visible:=false; 1557 UnitBtn.Visible:=false; 1558 TerrainBtn.Visible:=false; 1559 EOT.Hint:=Phrases.Lookup('BTN_NEGO'); 1560 EOT.Visible:=true; 1561 end; 1562 SetTroopLoc(-1); 1563 MapValid:=false; 1564 NewAgeCenterTo:=0; 1565 if ((MyRO.Turn=0) and not supervising or IsMultiPlayerGame 1566 or (ClientMode=cResume)) and (MyRO.nCity>0) then 1567 begin 1568 Loc1:=MyCity[0].Loc; 1569 if (ClientMode=cTurn) and (MyRO.Turn=0) then 1570 begin // move city out of center to not be covered by welcome screen 1571 dx:=MapWidth div (xxt*5); 1572 if dx>5 then 1573 dx:=5; 1574 dy:=MapHeight div (yyt*5); 1575 if dy>5 then 1576 dy:=5; 1577 if Loc1>=G.lx*G.ly div 2 then 1578 begin 1579 NewAgeCenterTo:=-1; 1580 Loc1:=dLoc(Loc1,-dx,-dy) 1581 end 1659 else } 1660 begin 1661 Age := GetAge(me); 1662 if SetMainTextureByAge(Age) then 1663 EOT.Invalidate; // has visible background parts in its bounds 1664 end; 1665 // age:=MyRO.Turn mod 4; //!!! 1666 if ClientMode = cMovieTurn then 1667 EOT.ButtonIndex := eotCancel 1668 else if ClientMode < scContact then 1669 EOT.ButtonIndex := eotGray 1670 else 1671 EOT.ButtonIndex := eotBackToNego; 1672 end 1582 1673 else 1583 begin 1584 NewAgeCenterTo:=1; 1585 Loc1:=dLoc(Loc1,-dx,dy); 1586 end 1674 begin 1675 Age := 0; 1676 SetMainTextureByAge(-1); 1677 if ClientMode = cMovieTurn then 1678 EOT.ButtonIndex := eotCancel 1679 else 1680 EOT.ButtonIndex := eotBlinkOn; 1587 1681 end; 1588 Centre(Loc1) 1589 end; 1590 1591 for i:=0 to Screen.FormCount-1 do 1592 if Screen.Forms[i] is TBufferedDrawDlg then 1593 Screen.Forms[i].Enabled:=true; 1594 1595 if ClientMode<>cResume then 1596 begin 1597 PaintAll; 1598 if (MyRO.Happened and phChangeGov<>0) and (MyRO.NatBuilt[imPalace]>0) then 1599 ImpImage(Panel.Canvas, ClientWidth-xPalace, yPalace, imPalace, gAnarchy{, GameMode<>cMovie}); 1600 // first turn after anarchy -- don't show despotism palace! 1601 Update; 1602 for i:=0 to Screen.FormCount-1 do 1603 if (Screen.Forms[i].Visible) and (Screen.Forms[i] is TBufferedDrawDlg) then 1604 begin 1605 if @Screen.Forms[i].OnShow<>nil then 1606 Screen.Forms[i].OnShow(nil); 1607 Screen.Forms[i].Invalidate; 1608 Screen.Forms[i].Update; 1609 end; 1610 1611 if MyRO.Happened and phGameEnd<>0 then 1612 with MessgExDlg do 1613 begin // game ended 1614 if MyRO.Happened and phExtinct<>0 then 1682 InitCityMark(MainTexture); 1683 CityDlg.CheckAge; 1684 NatStatDlg.CheckAge; 1685 UnitStatDlg.CheckAge; 1686 HelpDlg.Difficulty := G.Difficulty[me]; 1687 1688 UnFocus := -1; 1689 MarkCityLoc := -1; 1690 BlinkON := false; 1691 BlinkTime := -1; 1692 Tracking := false; 1693 TurnComplete := false; 1694 1695 if (ToldSlavery < 0) or 1696 ((ToldSlavery = 1) <> (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)) 1697 then 1698 begin 1699 if MyRO.Wonder[woPyramids].EffectiveOwner >= 0 then 1700 ToldSlavery := 1 1701 else 1702 ToldSlavery := 0; 1703 for p1 := 0 to nPl - 1 do 1704 if (Tribe[p1] <> nil) and (Tribe[p1].mixSlaves >= 0) then 1705 with Picture do 1706 begin // replace unit picture 1707 mix := Tribe[p1].mixSlaves; 1708 if ToldSlavery = 1 then 1709 pix := pixSlaves 1710 else 1711 pix := pixNoSlaves; 1712 Hash := 0; 1713 GrName := 'StdUnits'; 1714 Tribe[p1].SetModelPicture(Picture, true); 1715 end 1716 end; 1717 1718 if not supervising and (ClientMode = cTurn) then 1719 begin 1720 for cix := 0 to MyRO.nCity - 1 do 1721 if (MyCity[cix].Loc >= 0) and 1722 ((MyRO.Turn = 0) or (MyCity[cix].Flags and chFounded <> 0)) then 1723 MyCity[cix].Status := MyCity[cix].Status and 1724 not csResourceWeightsMask or (3 shl 4); 1725 // new city, set to maximum growth 1726 end; 1727 if (ClientMode = cTurn) or (ClientMode = cContinue) then 1728 CityOptimizer_BeginOfTurn; // maybe peace was made or has ended 1729 SumCities(TaxSum, ScienceSum); 1730 1731 if ClientMode = cMovieTurn then 1732 begin 1733 UnitInfoBtn.Visible := false; 1734 UnitBtn.Visible := false; 1735 TerrainBtn.Visible := false; 1736 EOT.Hint := Phrases.Lookup('BTN_STOP'); 1737 EOT.Visible := true; 1738 end 1739 else if ClientMode < scContact then 1740 begin 1741 UnitInfoBtn.Visible := UnFocus >= 0; 1742 UnitBtn.Visible := UnFocus >= 0; 1743 CheckTerrainBtnVisible; 1744 TurnComplete := supervising; 1745 EOT.Hint := Phrases.Lookup('BTN_ENDTURN'); 1746 EOT.Visible := Server(sTurn - sExecute, me, 0, nil^) >= rExecuted; 1747 end 1748 else 1749 begin 1750 UnitInfoBtn.Visible := false; 1751 UnitBtn.Visible := false; 1752 TerrainBtn.Visible := false; 1753 EOT.Hint := Phrases.Lookup('BTN_NEGO'); 1754 EOT.Visible := true; 1755 end; 1756 SetTroopLoc(-1); 1757 MapValid := false; 1758 NewAgeCenterTo := 0; 1759 if ((MyRO.Turn = 0) and not supervising or IsMultiPlayerGame or 1760 (ClientMode = cResume)) and (MyRO.nCity > 0) then 1761 begin 1762 Loc1 := MyCity[0].Loc; 1763 if (ClientMode = cTurn) and (MyRO.Turn = 0) then 1764 begin // move city out of center to not be covered by welcome screen 1765 dx := MapWidth div (xxt * 5); 1766 if dx > 5 then 1767 dx := 5; 1768 dy := MapHeight div (yyt * 5); 1769 if dy > 5 then 1770 dy := 5; 1771 if Loc1 >= G.lx * G.ly div 2 then 1615 1772 begin 1616 OpenSound:='MSG_GAMEOVER'; 1617 MessgText:=Tribe[me].TPhrase('GAMEOVER'); 1618 IconKind:=mikBigIcon; 1619 IconIndex:=8; 1773 NewAgeCenterTo := -1; 1774 Loc1 := dLoc(Loc1, -dx, -dy) 1620 1775 end 1621 else if MyRO.Happened and phShipComplete<>0 then1776 else 1622 1777 begin 1623 Winners:=0; 1624 for p1:=0 to nPl-1 do if 1 shl p1 and MyRO.Alive<>0 then 1778 NewAgeCenterTo := 1; 1779 Loc1 := dLoc(Loc1, -dx, dy); 1780 end 1781 end; 1782 Centre(Loc1) 1783 end; 1784 1785 for i := 0 to Screen.FormCount - 1 do 1786 if Screen.Forms[i] is TBufferedDrawDlg then 1787 Screen.Forms[i].Enabled := true; 1788 1789 if ClientMode <> cResume then 1790 begin 1791 PaintAll; 1792 if (MyRO.Happened and phChangeGov <> 0) and (MyRO.NatBuilt[imPalace] > 0) 1793 then 1794 ImpImage(Panel.Canvas, ClientWidth - xPalace, yPalace, imPalace, 1795 gAnarchy { , GameMode<>cMovie } ); 1796 // first turn after anarchy -- don't show despotism palace! 1797 Update; 1798 for i := 0 to Screen.FormCount - 1 do 1799 if (Screen.Forms[i].Visible) and (Screen.Forms[i] is TBufferedDrawDlg) 1800 then 1801 begin 1802 if @Screen.Forms[i].OnShow <> nil then 1803 Screen.Forms[i].OnShow(nil); 1804 Screen.Forms[i].Invalidate; 1805 Screen.Forms[i].Update; 1806 end; 1807 1808 if MyRO.Happened and phGameEnd <> 0 then 1809 with MessgExDlg do 1810 begin // game ended 1811 if MyRO.Happened and phExtinct <> 0 then 1625 1812 begin 1626 Winners:=Winners or 1 shl p1; 1627 for i:=0 to nShipPart-1 do 1628 if MyRO.Ship[p1].Parts[i]<ShipNeed[i] then 1629 Winners:=Winners and not (1 shl p1); 1813 OpenSound := 'MSG_GAMEOVER'; 1814 MessgText := Tribe[me].TPhrase('GAMEOVER'); 1815 IconKind := mikBigIcon; 1816 IconIndex := 8; 1817 end 1818 else if MyRO.Happened and phShipComplete <> 0 then 1819 begin 1820 Winners := 0; 1821 for p1 := 0 to nPl - 1 do 1822 if 1 shl p1 and MyRO.Alive <> 0 then 1823 begin 1824 Winners := Winners or 1 shl p1; 1825 for i := 0 to nShipPart - 1 do 1826 if MyRO.Ship[p1].Parts[i] < ShipNeed[i] then 1827 Winners := Winners and not(1 shl p1); 1828 end; 1829 assert(Winners <> 0); 1830 if Winners and (1 shl me) <> 0 then 1831 begin 1832 s := ''; 1833 for p1 := 0 to nPl - 1 do 1834 if (p1 <> me) and (1 shl p1 and Winners <> 0) then 1835 if s = '' then 1836 s := Tribe[p1].TPhrase('SHORTNAME') 1837 else 1838 s := Format(Phrases.Lookup('SHAREDWIN_CONCAT'), 1839 [s, Tribe[p1].TPhrase('SHORTNAME')]); 1840 1841 OpenSound := 'MSG_YOUWIN'; 1842 MessgText := Tribe[me].TPhrase('MYSPACESHIP'); 1843 if s <> '' then 1844 MessgText := MessgText + '\' + 1845 Format(Phrases.Lookup('SHAREDWIN'), [s]); 1846 IconKind := mikBigIcon; 1847 IconIndex := 9; 1848 end 1849 else 1850 begin 1851 assert(me = 0); 1852 OpenSound := 'MSG_GAMEOVER'; 1853 MessgText := ''; 1854 for p1 := 0 to nPl - 1 do 1855 if Winners and (1 shl p1) <> 0 then 1856 MessgText := MessgText + Tribe[p1].TPhrase('SPACESHIP1'); 1857 MessgText := MessgText + '\' + Phrases.Lookup('SPACESHIP2'); 1858 IconKind := mikEnemyShipComplete; 1859 end 1860 end 1861 else { if MyRO.Happened and fTimeUp<>0 then } 1862 begin 1863 assert(me = 0); 1864 OpenSound := 'MSG_GAMEOVER'; 1865 if not supervising then 1866 MessgText := Tribe[me].TPhrase('TIMEUP') 1867 else 1868 MessgText := Phrases.Lookup('TIMEUPSUPER'); 1869 IconKind := mikImp; 1870 IconIndex := 22; 1630 1871 end; 1631 assert(Winners<>0); 1632 if Winners and (1 shl me)<>0 then 1872 Kind := mkOk; 1873 ShowModal; 1874 if MyRO.Happened and phExtinct = 0 then 1633 1875 begin 1634 s:=''; 1635 for p1:=0 to nPl-1 do 1636 if (p1<>me) and (1 shl p1 and Winners<>0) then 1637 if s='' then s:=Tribe[p1].TPhrase('SHORTNAME') 1638 else s:=Format(Phrases.Lookup('SHAREDWIN_CONCAT'), 1639 [s,Tribe[p1].TPhrase('SHORTNAME')]); 1640 1641 OpenSound:='MSG_YOUWIN'; 1642 MessgText:=Tribe[me].TPhrase('MYSPACESHIP'); 1643 if s<>'' then 1644 MessgText:=MessgText+'\'+Format(Phrases.Lookup('SHAREDWIN'),[s]); 1645 IconKind:=mikBigIcon; 1646 IconIndex:=9; 1876 p1 := 0; 1877 while (p1 < nPl - 1) and (Winners and (1 shl p1) = 0) do 1878 inc(p1); 1879 if MyRO.Happened and phShipComplete = 0 then 1880 DiaDlg.ShowNewContent_Charts(wmModal); 1881 end; 1882 TurnComplete := true; 1883 exit; 1884 end; 1885 if not supervising and (1 shl me and MyRO.Alive = 0) then 1886 begin 1887 TurnComplete := true; 1888 exit; 1889 end; 1890 1891 if (ClientMode = cContinue) and 1892 (DipMem[me].SentCommand and $FF0F = scContact) then 1893 // contact was refused 1894 if MyRO.Treaty[DipMem[me].pContact] >= trPeace then 1895 ContactRefused(DipMem[me].pContact, 'FRREJECTED') 1896 else 1897 SoundMessage(Tribe[DipMem[me].pContact].TPhrase('FRREJECTED'), 1898 'NEGO_REJECTED'); 1899 1900 if not supervising and (Age > MyData.ToldAge) and 1901 ((Age > 0) or (ClientMode <> cMovieTurn)) then 1902 with MessgExDlg do 1903 begin 1904 if Age = 0 then 1905 begin 1906 if Phrases2FallenBackToEnglish then 1907 begin 1908 s := Tribe[me].TPhrase('AGE0'); 1909 MessgText := 1910 Format(s, [TurnToString(MyRO.Turn), CityName(MyCity[0].ID)]) 1911 end 1912 else 1913 begin 1914 s := Tribe[me].TString(Phrases2.Lookup('AGE0')); 1915 MessgText := Format(s, [TurnToString(MyRO.Turn)]); 1916 end 1647 1917 end 1648 else1918 else 1649 1919 begin 1650 assert(me=0); 1651 OpenSound:='MSG_GAMEOVER'; 1652 MessgText:=''; 1653 for p1:=0 to nPl-1 do if Winners and (1 shl p1)<>0 then 1654 MessgText:=MessgText+Tribe[p1].TPhrase('SPACESHIP1'); 1655 MessgText:=MessgText+'\'+Phrases.Lookup('SPACESHIP2'); 1656 IconKind:=mikEnemyShipComplete; 1920 s := Tribe[me].TPhrase('AGE' + char(48 + Age)); 1921 MessgText := Format(s, [TurnToString(MyRO.Turn)]); 1922 end; 1923 IconKind := mikAge; 1924 IconIndex := Age; 1925 { if age=0 then } Kind := mkOk 1926 { else begin Kind:=mkOkHelp; HelpKind:=hkAdv; HelpNo:=AgePreq[age]; end }; 1927 CenterTo := NewAgeCenterTo; 1928 OpenSound := 'AGE_' + char(48 + Age); 1929 ShowModal; 1930 MyData.ToldAge := Age; 1931 if Age > 0 then 1932 MyData.ToldTech[AgePreq[Age]] := MyRO.Tech[AgePreq[Age]]; 1933 end; 1934 1935 if MyData.ToldAlive <> MyRO.Alive then 1936 begin 1937 for p1 := 0 to nPl - 1 do 1938 if (MyData.ToldAlive - MyRO.Alive) and (1 shl p1) <> 0 then 1939 with MessgExDlg do 1940 begin 1941 OpenSound := 'MSG_EXTINCT'; 1942 s := Tribe[p1].TPhrase('EXTINCT'); 1943 MessgText := Format(s, [TurnToString(MyRO.Turn)]); 1944 if MyRO.Alive = 1 shl me then 1945 MessgText := MessgText + Phrases.Lookup('EXTINCTALL'); 1946 Kind := mkOk; 1947 IconKind := mikImp; 1948 IconIndex := 21; 1949 ShowModal; 1950 end; 1951 if (ClientMode <> cMovieTurn) and not supervising then 1952 DiaDlg.ShowNewContent_Charts(wmModal); 1953 end; 1954 1955 // tell changes of own credibility 1956 if not supervising then 1957 begin 1958 if RoughCredibility(MyRO.Credibility) <> 1959 RoughCredibility(MyData.ToldOwnCredibility) then 1960 begin 1961 if RoughCredibility(MyRO.Credibility) > 1962 RoughCredibility(MyData.ToldOwnCredibility) then 1963 s := Phrases.Lookup('CREDUP') 1964 else 1965 s := Phrases.Lookup('CREDDOWN'); 1966 TribeMessage(me, 1967 Format(s, [Phrases.Lookup('CREDIBILITY', 1968 RoughCredibility(MyRO.Credibility))]), ''); 1969 end; 1970 MyData.ToldOwnCredibility := MyRO.Credibility; 1971 end; 1972 1973 for i := 0 to 27 do 1974 begin 1975 OwnWonder := false; 1976 for cix := 0 to MyRO.nCity - 1 do 1977 if (MyCity[cix].Loc >= 0) and 1978 (MyCity[cix].ID = MyRO.Wonder[i].CityID) then 1979 OwnWonder := true; 1980 if MyRO.Wonder[i].CityID <> MyData.ToldWonders[i].CityID then 1981 begin 1982 if MyRO.Wonder[i].CityID = -2 then 1983 with MessgExDlg do 1984 begin { tell about destroyed wonders } 1985 OpenSound := 'WONDER_DESTROYED'; 1986 MessgText := Format(Phrases.Lookup('WONDERDEST'), 1987 [Phrases.Lookup('IMPROVEMENTS', i)]); 1988 Kind := mkOkHelp; 1989 HelpKind := hkImp; 1990 HelpNo := i; 1991 IconKind := mikImp; 1992 IconIndex := i; 1993 ShowModal; 1994 end 1995 else 1996 begin 1997 if i = woManhattan then 1998 if MyRO.Wonder[i].EffectiveOwner > me then 1999 MyData.ColdWarStart := MyRO.Turn - 1 2000 else 2001 MyData.ColdWarStart := MyRO.Turn; 2002 if not OwnWonder then 2003 with MessgExDlg do 2004 begin { tell about newly built wonders } 2005 if i = woManhattan then 2006 begin 2007 OpenSound := 'MSG_COLDWAR'; 2008 s := Tribe[MyRO.Wonder[i].EffectiveOwner].TPhrase('COLDWAR') 2009 end 2010 else if MyRO.Wonder[i].EffectiveOwner >= 0 then 2011 begin 2012 OpenSound := 'WONDER_BUILT'; 2013 s := Tribe[MyRO.Wonder[i].EffectiveOwner] 2014 .TPhrase('WONDERBUILT') 2015 end 2016 else 2017 begin 2018 OpenSound := 'MSG_DEFAULT'; 2019 s := Phrases.Lookup('WONDERBUILTEXP'); 2020 // already expired when built 2021 end; 2022 MessgText := Format(s, [Phrases.Lookup('IMPROVEMENTS', i), 2023 CityName(MyRO.Wonder[i].CityID)]); 2024 Kind := mkOkHelp; 2025 HelpKind := hkImp; 2026 HelpNo := i; 2027 IconKind := mikImp; 2028 IconIndex := i; 2029 ShowModal; 2030 end 1657 2031 end 1658 2032 end 1659 else {if MyRO.Happened and fTimeUp<>0 then} 2033 else if (MyRO.Wonder[i].EffectiveOwner <> MyData.ToldWonders[i] 2034 .EffectiveOwner) and (MyRO.Wonder[i].CityID > -2) then 2035 if MyRO.Wonder[i].EffectiveOwner < 0 then 2036 begin 2037 if i <> woMIR then 2038 with MessgExDlg do 2039 begin { tell about expired wonders } 2040 OpenSound := 'WONDER_EXPIRED'; 2041 MessgText := Format(Phrases.Lookup('WONDEREXP'), 2042 [Phrases.Lookup('IMPROVEMENTS', i), 2043 CityName(MyRO.Wonder[i].CityID)]); 2044 Kind := mkOkHelp; 2045 HelpKind := hkImp; 2046 HelpNo := i; 2047 IconKind := mikImp; 2048 IconIndex := i; 2049 ShowModal; 2050 end 2051 end 2052 else if (MyData.ToldWonders[i].EffectiveOwner >= 0) and not OwnWonder 2053 then 2054 with MessgExDlg do 2055 begin { tell about capture of wonders } 2056 OpenSound := 'WONDER_CAPTURED'; 2057 s := Tribe[MyRO.Wonder[i].EffectiveOwner].TPhrase('WONDERCAPT'); 2058 MessgText := Format(s, [Phrases.Lookup('IMPROVEMENTS', i), 2059 CityName(MyRO.Wonder[i].CityID)]); 2060 Kind := mkOkHelp; 2061 HelpKind := hkImp; 2062 HelpNo := i; 2063 IconKind := mikImp; 2064 IconIndex := i; 2065 ShowModal; 2066 end; 2067 end; 2068 2069 if MyRO.Turn = MyData.ColdWarStart + ColdWarTurns then 2070 begin 2071 SoundMessageEx(Phrases.Lookup('COLDWAREND'), 'MSG_DEFAULT'); 2072 MyData.ColdWarStart := -ColdWarTurns - 1 2073 end; 2074 2075 TellNewModels; 2076 end; // ClientMode<>cResume 2077 MyData.ToldAlive := MyRO.Alive; 2078 move(MyRO.Wonder, MyData.ToldWonders, SizeOf(MyData.ToldWonders)); 2079 2080 NewGovAvailable := -1; 2081 if ClientMode <> cResume then 2082 begin // tell about new techs 2083 for ad := 0 to nAdv - 1 do 2084 if (MyRO.TestFlags and tfAllTechs = 0) and 2085 ((MyRO.Tech[ad] >= tsApplicable) <> 2086 (MyData.ToldTech[ad] >= tsApplicable)) or (ad in FutureTech) and 2087 (MyRO.Tech[ad] <> MyData.ToldTech[ad]) then 2088 with MessgExDlg do 2089 begin 2090 Item := 'RESEARCH_GENERAL'; 2091 if GameMode <> cMovie then 2092 OpenSound := 'NEWADVANCE_' + char(48 + Age); 2093 Item2 := Phrases.Lookup('ADVANCES', ad); 2094 if ad in FutureTech then 2095 Item2 := Item2 + ' ' + IntToStr(MyRO.Tech[ad]); 2096 MessgText := Format(Phrases.Lookup(Item), [Item2]); 2097 Kind := mkOkHelp; 2098 HelpKind := hkAdv; 2099 HelpNo := ad; 2100 IconKind := mikBook; 2101 IconIndex := -1; 2102 for i := 0 to nAdvBookIcon - 1 do 2103 if AdvBookIcon[i].Adv = ad then 2104 IconIndex := AdvBookIcon[i].Icon; 2105 ShowModal; 2106 MyData.ToldTech[ad] := MyRO.Tech[ad]; 2107 for i := gMonarchy to nGov - 1 do 2108 if GovPreq[i] = ad then 2109 NewGovAvailable := i; 2110 end; 2111 end; 2112 2113 ShowCityList := false; 2114 if ClientMode = cTurn then 2115 begin 2116 if (MyRO.Happened and phTech <> 0) and (MyData.FarTech <> adNexus) then 2117 ChooseResearch; 2118 2119 UpdatePanel := false; 2120 if MyRO.Happened and phChangeGov <> 0 then 2121 begin 2122 ModalSelectDlg.ShowNewContent(wmModal, kGov); 2123 Play('NEWGOV'); 2124 Server(sSetGovernment, me, ModalSelectDlg.result, nil^); 2125 CityOptimizer_BeginOfTurn; 2126 UpdatePanel := true; 2127 end; 2128 end; // ClientMode=cTurn 2129 2130 if not supervising and ((ClientMode = cTurn) or (ClientMode = cMovieTurn)) 2131 then 2132 for cix := 0 to MyRO.nCity - 1 do 2133 with MyCity[cix] do 2134 Status := Status and not csToldBombard; 2135 2136 if ((ClientMode = cTurn) or (ClientMode = cMovieTurn)) and 2137 (MyRO.Government <> gAnarchy) then 2138 begin 2139 // tell what happened in cities 2140 for WondersOnly := true downto false do 2141 for cix := 0 to MyRO.nCity - 1 do 2142 with MyCity[cix] do 2143 if (MyRO.Turn > 0) and (Loc >= 0) and (Flags and chCaptured = 0) 2144 and (WondersOnly = (Flags and chProduction <> 0) and 2145 (Project0 and cpImp <> 0) and (Project0 and cpIndex < 28)) then 2146 begin 2147 if WondersOnly then 2148 with MessgExDlg do 2149 begin { tell about newly built wonder } 2150 OpenSound := 'WONDER_BUILT'; 2151 s := Tribe[me].TPhrase('WONDERBUILTOWN'); 2152 MessgText := 2153 Format(s, [Phrases.Lookup('IMPROVEMENTS', 2154 Project0 and cpIndex), CityName(ID)]); 2155 Kind := mkOkHelp; 2156 HelpKind := hkImp; 2157 HelpNo := Project0 and cpIndex; 2158 IconKind := mikImp; 2159 IconIndex := Project0 and cpIndex; 2160 ShowModal; 2161 end; 2162 if not supervising and (ClientMode = cTurn) then 2163 begin 2164 AllowCityScreen := true; 2165 if (Status and 7 <> 0) and 2166 (Project and (cpImp + cpIndex) = cpImp + imTrGoods) then 2167 if (MyData.ImpOrder[Status and 7 - 1, 0] >= 0) then 2168 begin 2169 if AutoBuild(cix, MyData.ImpOrder[Status and 7 - 1]) then 2170 AllowCityScreen := false 2171 else if Flags and chProduction <> 0 then 2172 Flags := (Flags and not chProduction) or chAllImpsMade 2173 end 2174 else 2175 Flags := Flags or chTypeDel; 2176 if (Size >= NeedAqueductSize) and 2177 (MyRO.Tech[Imp[imAqueduct].Preq] < tsApplicable) or 2178 (Size >= NeedSewerSize) and 2179 (MyRO.Tech[Imp[imSewer].Preq] < tsApplicable) then 2180 Flags := Flags and not chNoGrowthWarning; 2181 // don't remind of unknown building 2182 if Flags and chNoSettlerProd = 0 then 2183 Status := Status and not csToldDelay 2184 else if Status and csToldDelay = 0 then 2185 Status := Status or csToldDelay 2186 else 2187 Flags := Flags and not chNoSettlerProd; 2188 if mRepScreens.Checked then 2189 begin 2190 if (Flags and CityRepMask <> 0) and AllowCityScreen then 2191 begin { show what happened in cities } 2192 SetTroopLoc(MyCity[cix].Loc); 2193 MarkCityLoc := MyCity[cix].Loc; 2194 PanelPaint; 2195 CityDlg.CloseAction := None; 2196 CityDlg.ShowNewContent(wmModal, MyCity[cix].Loc, 2197 Flags and CityRepMask); 2198 UpdatePanel := true; 2199 end 2200 end 2201 else { if mRepList.Checked then } 2202 begin 2203 if Flags and CityRepMask <> 0 then 2204 ShowCityList := true 2205 end 2206 end 2207 end; { city loop } 2208 end; // ClientMode=cTurn 2209 2210 if ClientMode = cTurn then 2211 begin 2212 if NewGovAvailable >= 0 then 2213 with MessgExDlg do 1660 2214 begin 1661 assert(me=0); 1662 OpenSound:='MSG_GAMEOVER'; 1663 if not supervising then MessgText:=Tribe[me].TPhrase('TIMEUP') 1664 else MessgText:=Phrases.Lookup('TIMEUPSUPER'); 1665 IconKind:=mikImp; 1666 IconIndex:=22; 2215 MessgText := Format(Phrases.Lookup('AUTOREVOLUTION'), 2216 [Phrases.Lookup('GOVERNMENT', NewGovAvailable)]); 2217 Kind := mkYesNo; 2218 IconKind := mikPureIcon; 2219 IconIndex := 6 + NewGovAvailable; 2220 ShowModal; 2221 if ModalResult = mrOK then 2222 begin 2223 Play('REVOLUTION'); 2224 Server(sRevolution, me, 0, nil^); 2225 end 1667 2226 end; 1668 Kind:=mkOK; 1669 ShowModal; 1670 if MyRO.Happened and phExtinct=0 then 2227 end; // ClientMode=cTurn 2228 2229 if (ClientMode = cTurn) or (ClientMode = cMovieTurn) then 2230 begin 2231 if MyRO.Happened and phGliderLost <> 0 then 2232 ContextMessage(Phrases.Lookup('GLIDERLOST'), 'MSG_DEFAULT', 2233 hkModel, 200); 2234 if MyRO.Happened and phPlaneLost <> 0 then 2235 ContextMessage(Phrases.Lookup('PLANELOST'), 'MSG_DEFAULT', 2236 hkFeature, mcFuel); 2237 if MyRO.Happened and phPeaceEvacuation <> 0 then 2238 for p1 := 0 to nPl - 1 do 2239 if 1 shl p1 and MyData.PeaceEvaHappened <> 0 then 2240 SoundMessageEx(Tribe[p1].TPhrase('WITHDRAW'), 'MSG_DEFAULT'); 2241 if MyRO.Happened and phPeaceViolation <> 0 then 2242 for p1 := 0 to nPl - 1 do 2243 if (1 shl p1 and MyRO.Alive <> 0) and (MyRO.EvaStart[p1] = MyRO.Turn) 2244 then 2245 SoundMessageEx(Format(Tribe[p1].TPhrase('VIOLATION'), 2246 [TurnToString(MyRO.Turn + PeaceEvaTurns - 1)]), 'MSG_WITHDRAW'); 2247 TellNewContacts; 2248 end; 2249 2250 if ClientMode = cMovieTurn then 2251 Update 2252 else if ClientMode = cTurn then 2253 begin 2254 if UpdatePanel then 2255 UpdateViews; 2256 Application.ProcessMessages; 2257 2258 if not supervising then 2259 for uix := 0 to MyRO.nUn - 1 do 2260 with MyUn[uix] do 2261 if Loc >= 0 then 2262 begin 2263 if Flags and unWithdrawn <> 0 then 2264 Status := 0; 2265 if Health = 100 then 2266 Status := Status and not usRecover; 2267 if (Master >= 0) or UnitExhausted(uix) then 2268 Status := Status and not usWaiting 2269 else 2270 Status := Status or usWaiting; 2271 CheckToldNoReturn(uix); 2272 if Status and usGoto <> 0 then 2273 begin { continue multi-turn goto } 2274 SetUnFocus(uix); 2275 SetTroopLoc(Loc); 2276 FocusOnLoc(TroopLoc, flRepaintPanel or flImmUpdate); 2277 if Status shr 16 = $7FFF then 2278 MoveResult := GetMoveAdvice(UnFocus, maNextCity, 2279 MoveAdviceData) 2280 else 2281 MoveResult := GetMoveAdvice(UnFocus, Status shr 16, 2282 MoveAdviceData); 2283 if MoveResult >= rExecuted then 2284 begin // !!! Shinkansen 2285 MoveResult := eOK; 2286 ok := true; 2287 for i := 0 to MoveAdviceData.nStep - 1 do 2288 begin 2289 Loc1 := dLoc(Loc, MoveAdviceData.dx[i], 2290 MoveAdviceData.dy[i]); 2291 if (MyMap[Loc1] and (fCity or fOwned) = fCity) 2292 // don't capture cities during auto move 2293 or (MyMap[Loc1] and (fUnit or fOwned) = fUnit) then 2294 // don't attack during auto move 2295 begin 2296 ok := false; 2297 Break 2298 end 2299 else 2300 begin 2301 if (Loc1 = MoveAdviceData.ToLoc) or 2302 (MoveAdviceData.ToLoc = maNextCity) and 2303 (MyMap[dLoc(Loc, MoveAdviceData.dx[i], 2304 MoveAdviceData.dy[i])] and fCity <> 0) then 2305 MoveOptions := muAutoNoWait 2306 else 2307 MoveOptions := 0; 2308 MoveResult := MoveUnit(MoveAdviceData.dx[i], 2309 MoveAdviceData.dy[i], MoveOptions); 2310 if (MoveResult < rExecuted) or 2311 (MoveResult = eEnemySpotted) then 2312 begin 2313 ok := false; 2314 Break 2315 end; 2316 end 2317 end; 2318 Stop := not ok or (Loc = MoveAdviceData.ToLoc) or 2319 (MoveAdviceData.ToLoc = maNextCity) and 2320 (MyMap[Loc] and fCity <> 0) 2321 end 2322 else 2323 begin 2324 MoveResult := eOK; 2325 Stop := true; 2326 end; 2327 2328 if MoveResult <> eDied then 2329 if Stop then 2330 Status := Status and ($FFFF - usGoto) 2331 else 2332 Status := Status and not usWaiting; 2333 end; 2334 2335 if Status and (usEnhance or usGoto) = usEnhance then 2336 // continue terrain enhancement 2337 begin 2338 MoveResult := ProcessEnhancement(uix, MyData.EnhancementJobs); 2339 if MoveResult <> eDied then 2340 if MoveResult = eJobDone then 2341 Status := Status and not usEnhance 2342 else 2343 Status := Status and not usWaiting; 2344 end 2345 end; 2346 end; // ClientMode=cTurn 2347 2348 HaveStrategyAdvice := false; 2349 // (GameMode<>cMovie) and not supervising 2350 // and AdvisorDlg.HaveStrategyAdvice; 2351 GoOnPhase := true; 2352 if supervising or (GameMode = cMovie) then 2353 begin 2354 SetTroopLoc(-1); 2355 PaintAll 2356 end { supervisor } 2357 { else if (ClientMode=cTurn) and (MyRO.Turn=0) then 2358 begin 2359 SetUnFocus(0); 2360 ZoomToCity(MyCity[0].Loc) 2361 end } 2362 else 2363 begin 2364 if ClientMode >= scContact then 2365 SetUnFocus(-1) 2366 else 2367 NextUnit(-1, false); 2368 if UnFocus < 0 then 2369 begin 2370 UnStartLoc := -1; 2371 if IsMultiPlayerGame or (ClientMode = cResume) then 2372 if MyRO.nCity > 0 then 2373 FocusOnLoc(MyCity[0].Loc) 2374 else 2375 FocusOnLoc(G.lx * G.ly div 2); 2376 SetTroopLoc(-1); 2377 PanelPaint 2378 end; 2379 if ShowCityList then 2380 ListDlg.ShowNewContent(wmPersistent, kCityEvents); 2381 end; 2382 end; { InitTurn } 2383 2384 var 2385 i, j, p1, mix, ToLoc, AnimationSpeed, ShowMoveDomain, cix, ecix: integer; 2386 Color: TColor; 2387 Name, s: string; 2388 TribeInfo: TTribeInfo; 2389 mi: TModelInfo; 2390 SkipTurn, IsAlpine, IsTreatyDeal: boolean; 2391 2392 begin { >>>client } 2393 case Command of 2394 cTurn, cResume, cContinue, cMovieTurn, scContact, 2395 scDipStart .. scDipBreak: 2396 begin 2397 supervising := G.Difficulty[NewPlayer] = 0; 2398 ArrangeMidPanel; 2399 end 2400 end; 2401 case Command of 2402 cDebugMessage: 2403 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(@Data)); 2404 2405 cShowNego: 2406 with TShowNegoData(Data) do 2407 begin 2408 s := Format('P%d to P%d: ', [pSender, pTarget]); 2409 if (Action = scDipOffer) and (Offer.nDeliver + Offer.nCost > 0) then 1671 2410 begin 1672 p1:=0; 1673 while (p1<nPl-1) and (Winners and (1 shl p1)=0) do inc(p1); 1674 if MyRO.Happened and phShipComplete=0 then 1675 DiaDlg.ShowNewContent_Charts(wmModal); 2411 s := s + 'Offer '; 2412 for i := 0 to Offer.nDeliver + Offer.nCost - 1 do 2413 begin 2414 if i = Offer.nDeliver then 2415 s := s + ' for ' 2416 else if i > 0 then 2417 s := s + '+'; 2418 case Offer.Price[i] and opMask of 2419 opChoose: 2420 s := s + 'Price of choice'; 2421 opCivilReport: 2422 s := s + 'State report'; 2423 opMilReport: 2424 s := s + 'Military report'; 2425 opMap: 2426 s := s + 'Map'; 2427 opTreaty: 2428 s := s + 'Treaty'; 2429 opShipParts: 2430 s := s + 'Ship part'; 2431 opMoney: 2432 s := s + IntToStr(Offer.Price[i] and $FFFFFF) + 'o'; 2433 opTribute: 2434 s := s + IntToStr(Offer.Price[i] and $FFFFFF) + 'o tribute'; 2435 opTech: 2436 s := s + Phrases.Lookup('ADVANCES', 2437 Offer.Price[i] and $FFFFFF); 2438 opAllTech: 2439 s := s + 'All advances'; 2440 opModel: 2441 s := s + Tribe[pSender].ModelName[Offer.Price[i] and $FFFFFF]; 2442 opAllModel: 2443 s := s + 'All models'; 2444 end 2445 end; 2446 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(s)); 2447 end 2448 else if Action = scDipAccept then 2449 begin 2450 s := s + '--- ACCEPTED! ---'; 2451 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(s)); 2452 end 2453 end; 2454 2455 cInitModule: 2456 begin 2457 Server := TInitModuleData(Data).Server; 2458 // AdvisorDlg.Init; 2459 InitModule; 2460 TInitModuleData(Data).DataSize := SizeOf(TPersistentData); 2461 TInitModuleData(Data).Flags := aiThreaded; 2462 end; 2463 2464 cReleaseModule: 2465 begin 2466 SmallImp.free; 2467 UnusedTribeFiles.free; 2468 TribeNames.free; 2469 MainMap.free; 2470 IsoEngine.Done; 2471 // AdvisorDlg.DeInit; 2472 end; 2473 2474 cHelpOnly, cStartHelp, cStartCredits: 2475 begin 2476 Age := 0; 2477 if Command = cHelpOnly then 2478 SetMainTextureByAge(-1); 2479 Tribes.Init; 2480 HelpDlg.UserLeft := (Screen.width - HelpDlg.width) div 2; 2481 HelpDlg.UserTop := (Screen.height - HelpDlg.height) div 2; 2482 HelpDlg.Difficulty := 0; 2483 if Command = cStartCredits then 2484 HelpDlg.ShowNewContent(wmModal, hkMisc, miscCredits) 2485 else 2486 HelpDlg.ShowNewContent(wmModal, hkMisc, miscMain); 2487 Tribes.Done; 2488 end; 2489 2490 cNewGame, cLoadGame, cMovie, cNewMap: 2491 begin 2492 { if (Command=cNewGame) or (Command=cLoadGame) then 2493 AdvisorDlg.NewGame(Data); } 2494 GenerateNames := mNames.Checked; 2495 GameOK := true; 2496 G := TNewGameData(Data); 2497 me := -1; 2498 pLogo := -1; 2499 ClientMode := -1; 2500 SetMapOptions; 2501 IsoEngine.pDebugMap := -1; 2502 idle := false; 2503 FillChar(Jump, SizeOf(Jump), 0); 2504 if StartRunning then 2505 Jump[0] := 999999; 2506 GameMode := Command; 2507 for i := 0 to nGrExt - 1 do 2508 FillChar(GrExt[i].pixUsed, GrExt[i].Data.height div 49 * 10, 0); 2509 IsoEngine.Reset; 2510 Tribes.Init; 2511 GetTribeList; 2512 for p1 := 0 to nPl - 1 do 2513 if (G.RO[p1] <> nil) and (G.RO[p1].Data <> nil) then 2514 with TPersistentData(G.RO[p1].Data^) do 2515 begin 2516 FarTech := adNone; 2517 FillChar(EnhancementJobs, SizeOf(EnhancementJobs), jNone); 2518 FillChar(ImpOrder, SizeOf(ImpOrder), -1); 2519 ColdWarStart := -ColdWarTurns - 1; 2520 ToldAge := -1; 2521 ToldModels := 3; 2522 ToldAlive := 0; 2523 ToldContact := 0; 2524 ToldOwnCredibility := InitialCredibility; 2525 for i := 0 to nPl - 1 do 2526 if G.Difficulty[i] > 0 then 2527 inc(ToldAlive, 1 shl i); 2528 PeaceEvaHappened := 0; 2529 for i := 0 to 27 do 2530 with ToldWonders[i] do 2531 begin 2532 CityID := -1; 2533 EffectiveOwner := -1 2534 end; 2535 FillChar(ToldTech, SizeOf(ToldTech), tsNA); 2536 if G.Difficulty[p1] > 0 then 2537 SoundPreload(sbStart); 2538 end; 2539 2540 // arrange dialogs 2541 ListDlg.UserLeft := 8; 2542 ListDlg.UserTop := TopBarHeight + 8; 2543 HelpDlg.UserLeft := Screen.width - HelpDlg.width - 8; 2544 HelpDlg.UserTop := TopBarHeight + 8; 2545 UnitStatDlg.UserLeft := 397; 2546 UnitStatDlg.UserTop := TopBarHeight + 64; 2547 DiaDlg.UserLeft := (Screen.width - DiaDlg.width) div 2; 2548 DiaDlg.UserTop := (Screen.height - DiaDlg.height) div 2; 2549 NatStatDlg.UserLeft := Screen.width - NatStatDlg.width - 8; 2550 NatStatDlg.UserTop := Screen.height - PanelHeight - 2551 NatStatDlg.height - 8; 2552 if NatStatDlg.UserTop < 8 then 2553 NatStatDlg.UserTop := 8; 2554 2555 Age := 0; 2556 MovieSpeed := 1; 2557 LogDlg.mSlot.Visible := true; 2558 LogDlg.Host := self; 2559 HelpDlg.ClearHistory; 2560 CityDlg.Reset; 2561 2562 Mini.width := G.lx * 2; 2563 Mini.height := G.ly; 2564 for i := 0 to nPl - 1 do 2565 begin 2566 Tribe[i] := nil; 2567 TribeOriginal[i] := false; 1676 2568 end; 1677 TurnComplete:=true; 1678 exit; 1679 end; 1680 if not supervising and (1 shl me and MyRO.Alive=0) then 1681 begin TurnComplete:=true; exit; end; 1682 1683 if (ClientMode=cContinue) and (DipMem[me].SentCommand and $FF0F=scContact) then 1684 // contact was refused 1685 if MyRO.Treaty[DipMem[me].pContact]>=trPeace then 1686 ContactRefused(DipMem[me].pContact, 'FRREJECTED') 1687 else SoundMessage(Tribe[DipMem[me].pContact].TPhrase('FRREJECTED'),'NEGO_REJECTED'); 1688 1689 if not supervising and (Age>MyData.ToldAge) 1690 and ((Age>0) or (ClientMode<>cMovieTurn)) then with MessgExDlg do 1691 begin 1692 if Age=0 then 1693 begin 1694 if Phrases2FallenBackToEnglish then 2569 ToldSlavery := -1; 2570 RepaintOnResize := false; 2571 Closable := false; 2572 FirstMovieTurn := true; 2573 2574 MenuArea.Visible := GameMode <> cMovie; 2575 TreasuryArea.Visible := GameMode < cMovie; 2576 ResearchArea.Visible := GameMode < cMovie; 2577 ManagementArea.Visible := GameMode < cMovie; 2578 end; 2579 2580 cGetReady, cReplay: 2581 if NewPlayer = 0 then 2582 begin 2583 i := 0; 2584 for p1 := 0 to nPl - 1 do 2585 if (G.Difficulty[p1] > 0) and (Tribe[p1] = nil) then 2586 inc(i); 2587 if i > UnusedTribeFiles.Count then 1695 2588 begin 1696 s:=Tribe[me].TPhrase('AGE0');1697 MessgText:=Format(s,[TurnToString(MyRO.Turn),CityName(MyCity[0].ID)])2589 GameOK := false; 2590 SimpleMessage(Phrases.Lookup('TOOFEWTRIBES')); 1698 2591 end 2592 else 2593 begin 2594 for p1 := 0 to nPl - 1 do 2595 if (G.Difficulty[p1] > 0) and (Tribe[p1] = nil) and 2596 (G.RO[p1] <> nil) then 2597 begin // let player select own tribes 2598 TribeInfo.trix := p1; 2599 TribeNames.Clear; 2600 for j := 0 to UnusedTribeFiles.Count - 1 do 2601 begin 2602 GetTribeInfo(UnusedTribeFiles[j], Name, Color); 2603 TribeNames.AddObject(Name, TObject(Color)); 2604 end; 2605 assert(TribeNames.Count > 0); 2606 ModalSelectDlg.ShowNewContent(wmModal, kTribe); 2607 Application.ProcessMessages; 2608 TribeInfo.FileName := UnusedTribeFiles[ModalSelectDlg.result]; 2609 UnusedTribeFiles.Delete(ModalSelectDlg.result); 2610 2611 if GameMode = cLoadGame then 2612 CreateTribe(TribeInfo.trix, TribeInfo.FileName, false) 2613 else 2614 Server(cSetTribe + (Length(TribeInfo.FileName) + 1 + 7) div 4, 2615 0, 0, TribeInfo); 2616 end; 2617 2618 for p1 := 0 to nPl - 1 do 2619 if (G.Difficulty[p1] > 0) and (Tribe[p1] = nil) and 2620 (G.RO[p1] = nil) then 2621 begin // autoselect enemy tribes 2622 j := ChooseUnusedTribe; 2623 TribeInfo.FileName := UnusedTribeFiles[j]; 2624 UnusedTribeFiles.Delete(j); 2625 TribeInfo.trix := p1; 2626 if GameMode = cLoadGame then 2627 CreateTribe(TribeInfo.trix, TribeInfo.FileName, false) 2628 else 2629 Server(cSetTribe + (Length(TribeInfo.FileName) + 1 + 7) div 4, 2630 0, 0, TribeInfo); 2631 end; 2632 end; 2633 if not mNames.Checked then 2634 for p1 := 0 to nPl - 1 do 2635 if Tribe[p1] <> nil then 2636 Tribe[p1].NumberName := p1; 2637 end; 2638 2639 cBreakGame: 2640 begin 2641 SaveSettings; 2642 CityDlg.CloseAction := None; 2643 for i := 0 to Screen.FormCount - 1 do 2644 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 2645 then 2646 Screen.Forms[i].Close; 2647 if LogDlg.Visible then 2648 LogDlg.Close; 2649 LogDlg.List.Clear; 2650 StartRunning := not idle and (Jump[0] > 0); // AI called Reload 2651 me := -1; 2652 idle := false; 2653 ClientMode := -1; 2654 UnitInfoBtn.Visible := false; 2655 UnitBtn.Visible := false; 2656 TerrainBtn.Visible := false; 2657 MovieSpeed1Btn.Visible := false; 2658 MovieSpeed2Btn.Visible := false; 2659 MovieSpeed3Btn.Visible := false; 2660 MovieSpeed4Btn.Visible := false; 2661 EOT.Visible := false; 2662 for i := 0 to ControlCount - 1 do 2663 if Controls[i] is TButtonC then 2664 Controls[i].Visible := false; 2665 InitPVSB(sb, 0, 1); 2666 for p1 := 0 to nPl - 1 do 2667 if Tribe[p1] <> nil then 2668 Tribe[p1].free; 2669 Tribes.Done; 2670 RepaintOnResize := false; 2671 Closable := true; 2672 Close; 2673 { if (GameMode=cNewGame) or (GameMode=cLoadGame) then 2674 AdvisorDlg.BreakGame; } 2675 end; 2676 2677 cShowGame: 2678 begin 2679 with Panel.Canvas do 2680 begin 2681 Brush.Color := $000000; 2682 FillRect(Rect(0, 0, Panel.width, Panel.height)); 2683 Brush.Style := bsClear; 2684 end; 2685 with TopBar.Canvas do 2686 begin 2687 Brush.Color := $000000; 2688 FillRect(Rect(0, 0, TopBar.width, TopBar.height)); 2689 Brush.Style := bsClear; 2690 end; 2691 FormResize(nil); // place mini map correctly according to its size 2692 Show; 2693 Update; 2694 RepaintOnResize := true; 2695 xw := 0; 2696 yw := ywcenter; 2697 if not StayOnTop_Ensured then 2698 begin 2699 StayOnTop_Ensured := true; 2700 CityDlg.StayOnTop_Workaround; 2701 CityTypeDlg.StayOnTop_Workaround; 2702 DiaDlg.StayOnTop_Workaround; 2703 DraftDlg.StayOnTop_Workaround; 2704 EnhanceDlg.StayOnTop_Workaround; 2705 HelpDlg.StayOnTop_Workaround; 2706 NatStatDlg.StayOnTop_Workaround; 2707 NegoDlg.StayOnTop_Workaround; 2708 ModalSelectDlg.StayOnTop_Workaround; 2709 ListDlg.StayOnTop_Workaround; 2710 UnitStatDlg.StayOnTop_Workaround; 2711 WondersDlg.StayOnTop_Workaround; 2712 RatesDlg.StayOnTop_Workaround; 2713 end; 2714 end; 2715 2716 cShowTurnChange: 2717 begin 2718 if integer(Data) >= 0 then 2719 begin 2720 pLogo := integer(Data); 2721 if G.RO[pLogo] = nil then 2722 begin 2723 if AILogo[pLogo] <> nil then 2724 BitBlt(Canvas.Handle, (xRightPanel + 10) - (16 + 64), 2725 ClientHeight - PanelHeight, 64, 64, 2726 AILogo[pLogo].Canvas.Handle, 0, 0, SRCCOPY); 2727 end 2728 end 2729 end; 2730 2731 cTurn, cResume, cContinue: 2732 if not GameOK then 2733 Server(sResign, NewPlayer, 0, nil^) 1699 2734 else 2735 begin 2736 ClientMode := Command; 2737 pTurn := NewPlayer; 2738 pLogo := NewPlayer; 2739 2740 if Command = cResume then 2741 begin // init non-original model pictures (maybe tribes not found) 2742 for p1 := 0 to nPl - 1 do 2743 if G.RO[p1] <> nil then 2744 begin 2745 ItsMeAgain(p1); 2746 for mix := 0 to MyRO.nModel - 1 do 2747 if Tribe[me].ModelPicture[mix].HGr = 0 then 2748 InitMyModel(mix, true); 2749 end; 2750 me := -1; 2751 end; 2752 2753 if Jump[pTurn] > 0 then 2754 Application.ProcessMessages; 2755 if Jump[pTurn] > 0 then 2756 if G.RO[NewPlayer].Happened and phGameEnd <> 0 then 2757 Jump[pTurn] := 0 2758 else 2759 dec(Jump[pTurn]); 2760 SkipTurn := Jump[pTurn] > 0; 2761 if SkipTurn then 1700 2762 begin 1701 s:=Tribe[me].TString(Phrases2.Lookup('AGE0')); 1702 MessgText:=Format(s,[TurnToString(MyRO.Turn)]); 2763 ItsMeAgain(NewPlayer); 2764 MyData := G.RO[NewPlayer].Data; 2765 SetTroopLoc(-1); 2766 MiniPaint; 2767 InitAllEnemyModels; // necessary for correct replay 2768 if not EndTurn(true) then 2769 SkipTurn := false; 2770 end; 2771 if not SkipTurn then 2772 begin 2773 if ((ClientMode < scDipStart) or (ClientMode > scDipBreak)) and 2774 NegoDlg.Visible then 2775 NegoDlg.Close; 2776 skipped := false; // always show my moves during my turn 2777 idle := true; 2778 InitTurn(NewPlayer); 2779 DipMem[me].pContact := -1; 2780 (* if (me=0) and (MyRO.Alive and (1 shl me)=0)} then 2781 begin 2782 if SimpleQuery(Phrases.Lookup('RESIGN'))=mrIgnore then 2783 Server(sResign,me,0,nil^) 2784 else Server(sBreak,me,0,nil^) 2785 end 2786 else Play('TURNSTART'); *) 2787 end; 2788 end; 2789 2790 cMovieTurn: 2791 begin 2792 ClientMode := Command; 2793 pTurn := NewPlayer; 2794 pLogo := -1; 2795 skipped := false; // always show my moves during my turn 2796 idle := true; 2797 if FirstMovieTurn then 2798 begin 2799 CheckMovieSpeedBtnState; 2800 FirstMovieTurn := false; 2801 end; 2802 InitTurn(NewPlayer); 2803 Application.ProcessMessages; 2804 if MovieSpeed = 4 then 2805 begin 2806 Sleep(75); 2807 // this break will ensure speed of fast forward does not depend on cpu speed 2808 Application.ProcessMessages; 2809 end 2810 end; 2811 2812 cMovieEndTurn: 2813 begin 2814 RememberPeaceViolation; 2815 pTurn := -1; 2816 pLogo := -1; 2817 MapValid := false; 2818 ClientMode := -1; 2819 idle := false; 2820 skipped := false; 2821 end; 2822 2823 cEditMap: 2824 begin 2825 ClientMode := cEditMap; 2826 SetMapOptions; 2827 IsoEngine.pDebugMap := -1; 2828 ItsMeAgain(0); 2829 MyData := nil; 2830 UnitInfoBtn.Visible := false; 2831 UnitBtn.Visible := false; 2832 TerrainBtn.Visible := false; 2833 MovieSpeed1Btn.Visible := false; 2834 MovieSpeed2Btn.Visible := false; 2835 MovieSpeed3Btn.Visible := false; 2836 MovieSpeed4Btn.Visible := false; 2837 EOT.Visible := false; 2838 HelpDlg.Difficulty := 0; 2839 BrushType := fGrass; 2840 BrushLoc := -1; 2841 Edited := false; 2842 UnFocus := -1; 2843 MarkCityLoc := -1; 2844 Tracking := false; 2845 TurnComplete := false; 2846 MapValid := false; 2847 FormResize(nil); // calculate geometrics and paint all 2848 SetTroopLoc(-1); 2849 idle := true 2850 end; 2851 2852 (* cNewContact: 2853 begin 2854 end; 2855 *) 2856 2857 scContact: 2858 begin 2859 DipMem[NewPlayer].pContact := integer(Data); 2860 if Jump[NewPlayer] > 0 then 2861 DipCall(scReject) 2862 else 2863 begin 2864 ClientMode := Command; 2865 InitTurn(NewPlayer); 2866 MyData.ToldContact := MyData.ToldContact or (1 shl integer(Data)); 2867 // don't tell about new nation when already contacted by them 2868 with MessgExDlg do 2869 begin 2870 OpenSound := 'CONTACT_' + char(48 + MyRO.EnemyReport[integer(Data) 2871 ].Attitude); 2872 MessgText := Tribe[integer(Data)].TPhrase('FRCONTACT'); 2873 Kind := mkYesNo; 2874 IconKind := mikTribe; 2875 IconIndex := integer(Data); 2876 ShowModal; 2877 if ModalResult = mrOK then 2878 begin 2879 NegoDlg.Respond; 2880 DipMem[me].DeliveredPrices := []; 2881 DipMem[me].ReceivedPrices := []; 2882 DipCall(scDipStart) 2883 end 2884 else 2885 begin 2886 DipCall(scReject); 2887 EndNego 2888 end 2889 end 2890 end; 2891 end; 2892 2893 scDipStart .. scDipBreak: 2894 begin 2895 ClientMode := Command; 2896 InitTurn(NewPlayer); 2897 if Command = scDipStart then 2898 Play('CONTACT_' + char(48 + MyRO.Attitude[DipMem[NewPlayer] 2899 .pContact])) 2900 else if Command = scDipCancelTreaty then 2901 Play('CANCELTREATY') 2902 else if Command = scDipOffer then 2903 begin 2904 ReceivedOffer := TOffer(Data); 2905 InitAllEnemyModels; 2906 end 2907 else if Command = scDipAccept then 2908 begin // remember delivered and received prices 2909 for i := 0 to DipMem[me].SentOffer.nDeliver - 1 do 2910 include(DipMem[me].DeliveredPrices, 2911 DipMem[me].SentOffer.Price[i] shr 24); 2912 for i := 0 to DipMem[me].SentOffer.nCost - 1 do 2913 include(DipMem[me].ReceivedPrices, 2914 DipMem[me].SentOffer.Price[DipMem[me].SentOffer.nDeliver + 2915 i] shr 24); 2916 IsTreatyDeal := false; 2917 for i := 0 to ReceivedOffer.nDeliver + ReceivedOffer.nCost - 1 do 2918 if DipMem[me].SentOffer.Price[i] and opMask = opTreaty then 2919 IsTreatyDeal := true; 2920 if IsTreatyDeal then 2921 Play('NEWTREATY') 2922 else 2923 Play('ACCEPTOFFER'); 2924 end; 2925 NegoDlg.Start; 2926 idle := true 2927 end; 2928 2929 cShowCancelTreaty: 2930 if not IsMultiPlayerGame then 2931 begin 2932 case G.RO[NewPlayer].Treaty[integer(Data)] of 2933 trPeace: 2934 s := Tribe[integer(Data)].TPhrase('FRCANCELBYREJECT_PEACE'); 2935 trFriendlyContact: 2936 s := Tribe[integer(Data)].TPhrase('FRCANCELBYREJECT_FRIENDLY'); 2937 trAlliance: 2938 s := Tribe[integer(Data)].TPhrase('FRCANCELBYREJECT_ALLIANCE'); 2939 end; 2940 TribeMessage(integer(Data), s, 'CANCELTREATY'); 2941 end; 2942 2943 cShowCancelTreatyByAlliance: 2944 if idle and (NewPlayer = me) then 2945 TribeMessage(integer(Data), Tribe[integer(Data) 2946 ].TPhrase('FRENEMYALLIANCE'), 'CANCELTREATY'); 2947 2948 cShowSupportAllianceAgainst: 2949 if not IsMultiPlayerGame and (Jump[0] = 0) then 2950 TribeMessage(integer(Data) and $F, 2951 Tribe[integer(Data) and $F].TPhrase('FRMYALLIANCE1') + ' ' + 2952 Tribe[integer(Data) shr 4].TPhrase('FRMYALLIANCE2'), 2953 'CANCELTREATY'); 2954 2955 cShowPeaceViolation: 2956 if not IsMultiPlayerGame and (Jump[0] = 0) then 2957 TribeMessage(integer(Data), 2958 Format(Tribe[integer(Data)].TPhrase('EVIOLATION'), 2959 [TurnToString(MyRO.Turn + PeaceEvaTurns - 1)]), 'MSG_WITHDRAW'); 2960 2961 cShowEndContact: 2962 EndNego; 2963 2964 cShowUnitChanged, cShowCityChanged, cShowAfterMove, cShowAfterAttack: 2965 if (idle and (NewPlayer = me) or not idle and not skipped) and 2966 not((GameMode = cMovie) and (MovieSpeed = 4)) then 2967 begin 2968 assert(NewPlayer = me); 2969 if not idle or (GameMode = cMovie) then 2970 Application.ProcessMessages; 2971 if Command = cShowCityChanged then 2972 begin 2973 CurrentMoveInfo.DoShow := false; 2974 if idle then 2975 CurrentMoveInfo.DoShow := true 2976 else if CurrentMoveInfo.IsAlly then 2977 CurrentMoveInfo.DoShow := not mAlNoMoves.Checked 2978 else 2979 CurrentMoveInfo.DoShow := not mEnNoMoves.Checked 2980 end 2981 else if Command = cShowUnitChanged then 2982 begin 2983 CurrentMoveInfo.DoShow := false; 2984 if idle then 2985 CurrentMoveInfo.DoShow := not mEffectiveMovesOnly.Checked 2986 else if CurrentMoveInfo.IsAlly then 2987 CurrentMoveInfo.DoShow := 2988 not(mAlNoMoves.Checked or mAlEffectiveMovesOnly.Checked) 2989 else 2990 CurrentMoveInfo.DoShow := 2991 not(mEnNoMoves.Checked or mEnAttacks.Checked) 2992 end; 2993 // else keep DoShow from cShowMove/cShowAttack 2994 2995 if CurrentMoveInfo.DoShow then 2996 begin 2997 if Command = cShowCityChanged then 2998 MapValid := false; 2999 FocusOnLoc(integer(Data), flImmUpdate); 3000 // OldUnFocus:=UnFocus; 3001 // UnFocus:=-1; 3002 if Command = cShowAfterMove then 3003 PaintLoc(integer(Data), CurrentMoveInfo.AfterMovePaintRadius) 3004 // show discovered areas 3005 else 3006 PaintLoc(integer(Data), 1); 3007 // UnFocus:=OldUnFocus; 3008 if (Command = cShowAfterAttack) and 3009 (CurrentMoveInfo.AfterAttackExpeller >= 0) then 3010 begin 3011 SoundMessageEx(Tribe[CurrentMoveInfo.AfterAttackExpeller] 3012 .TPhrase('EXPEL'), ''); 3013 CurrentMoveInfo.AfterAttackExpeller := -1; 3014 Update; // remove message box from screen 3015 end 3016 else if not idle then 3017 if Command = cShowCityChanged then 3018 Sleep(MoveTime * WaitAfterShowMove div 16) 3019 else if (Command = cShowUnitChanged) and 3020 (MyMap[integer(Data)] and fUnit <> 0) then 3021 Sleep(MoveTime * WaitAfterShowMove div 32) 3022 end // if CurrentMoveInfo.DoShow 3023 else 3024 MapValid := false; 3025 end; 3026 3027 cShowMoving, cShowCapturing: 3028 if (idle and (NewPlayer = me) or not idle and not skipped and 3029 (TShowMove(Data).emix <> $FFFF)) and 3030 not((GameMode = cMovie) and (MovieSpeed = 4)) then 3031 begin 3032 assert(NewPlayer = me); 3033 if not idle or (GameMode = cMovie) then 3034 Application.ProcessMessages; 3035 with TShowMove(Data) do 3036 begin 3037 CurrentMoveInfo.DoShow := false; 3038 if not idle and (Tribe[Owner].ModelPicture[mix].HGr = 0) then 3039 InitEnemyModel(emix); 3040 3041 ToLoc := dLoc(FromLoc, dx, dy); 3042 if idle then 3043 begin // own unit -- make discovered land visible 3044 assert(Owner = me); // no foreign moves during my turn! 3045 CurrentMoveInfo.DoShow := not mEffectiveMovesOnly.Checked or 3046 (Command = cShowCapturing); 3047 if CurrentMoveInfo.DoShow then 3048 begin 3049 if GameMode = cMovie then 3050 begin 3051 if MovieSpeed = 3 then 3052 AnimationSpeed := 4 3053 else if MovieSpeed = 2 then 3054 AnimationSpeed := 8 3055 else 3056 AnimationSpeed := 16; 3057 end 3058 else 3059 begin 3060 if mVeryFastMoves.Checked then 3061 AnimationSpeed := 4 3062 else if mFastMoves.Checked then 3063 AnimationSpeed := 8 3064 else 3065 AnimationSpeed := 16; 3066 end; 3067 with MyModel[mix] do 3068 begin 3069 if (Kind = mkDiplomat) or (Domain = dAir) or 3070 (Cap[mcRadar] + Cap[mcCarrier] + Cap[mcAcademy] > 0) or 3071 (MyMap[ToLoc] and fTerrain = fMountains) or 3072 (MyMap[ToLoc] and fTerImp = tiFort) or 3073 (MyMap[ToLoc] and fTerImp = tiBase) then 3074 CurrentMoveInfo.AfterMovePaintRadius := 2 3075 else 3076 CurrentMoveInfo.AfterMovePaintRadius := 1; 3077 if (MyRO.Wonder[woShinkansen].EffectiveOwner = me) and 3078 (Domain = dGround) and 3079 (MyMap[FromLoc] and (fRR or fCity) <> 0) and 3080 (MyMap[ToLoc] and (fRR or fCity) <> 0) and 3081 (Flags and umPlaneUnloading = 0) then 3082 AnimationSpeed := 4; 3083 ShowMoveDomain := Domain; 3084 IsAlpine := Cap[mcAlpine] > 0; 3085 end 3086 end 3087 end 3088 else 3089 begin 3090 CurrentMoveInfo.IsAlly := MyRO.Treaty[Owner] = trAlliance; 3091 if GameMode = cMovie then 3092 CurrentMoveInfo.DoShow := true 3093 else if CurrentMoveInfo.IsAlly then 3094 CurrentMoveInfo.DoShow := not mAlNoMoves.Checked and 3095 not(mAlEffectiveMovesOnly.Checked and 3096 (Command <> cShowCapturing)) 3097 else 3098 CurrentMoveInfo.DoShow := not mEnNoMoves.Checked and 3099 not(mEnAttacks.Checked and (Command <> cShowCapturing)); 3100 if CurrentMoveInfo.DoShow then 3101 begin 3102 if Command = cShowCapturing then 3103 begin // show capture message 3104 if MyMap[ToLoc] and fOwned <> 0 then 3105 begin // own city, search 3106 cix := MyRO.nCity - 1; 3107 while (cix >= 0) and (MyCity[cix].Loc <> ToLoc) do 3108 dec(cix); 3109 s := CityName(MyCity[cix].ID); 3110 end 3111 else 3112 begin // foreign city, search 3113 ecix := MyRO.nEnemyCity - 1; 3114 while (ecix >= 0) and (MyRO.EnemyCity[ecix].Loc <> ToLoc) do 3115 dec(ecix); 3116 s := CityName(MyRO.EnemyCity[ecix].ID); 3117 end; 3118 TribeMessage(Owner, Format(Tribe[Owner].TPhrase('CAPTURE'), 3119 [s]), ''); 3120 Update; // remove message box from screen 3121 end; 3122 3123 if CurrentMoveInfo.IsAlly then 3124 begin // allied unit -- make discovered land visible 3125 if mAlFastMoves.Checked then 3126 AnimationSpeed := 8 3127 else 3128 AnimationSpeed := 16; 3129 with MyRO.EnemyModel[emix] do 3130 if (Kind = mkDiplomat) or (Domain = dAir) or 3131 (ATrans_Fuel > 0) or 3132 (Cap and (1 shl (mcRadar - mcFirstNonCap) or 3133 1 shl (mcAcademy - mcFirstNonCap)) <> 0) or 3134 (MyMap[ToLoc] and fTerrain = fMountains) or 3135 (MyMap[ToLoc] and fTerImp = tiFort) or 3136 (MyMap[ToLoc] and fTerImp = tiBase) then 3137 CurrentMoveInfo.AfterMovePaintRadius := 2 3138 else 3139 CurrentMoveInfo.AfterMovePaintRadius := 1 3140 end 3141 else 3142 begin 3143 if mEnFastMoves.Checked then 3144 AnimationSpeed := 8 3145 else 3146 AnimationSpeed := 16; 3147 CurrentMoveInfo.AfterMovePaintRadius := 0; 3148 // enemy unit, nothing discovered 3149 end; 3150 if GameMode = cMovie then 3151 begin 3152 if MovieSpeed = 3 then 3153 AnimationSpeed := 4 3154 else if MovieSpeed = 2 then 3155 AnimationSpeed := 8 3156 else 3157 AnimationSpeed := 16; 3158 end; 3159 ShowMoveDomain := MyRO.EnemyModel[emix].Domain; 3160 IsAlpine := MyRO.EnemyModel[emix].Cap and 3161 (1 shl (mcAlpine - mcFirstNonCap)) <> 0; 3162 end 3163 end; 3164 3165 if CurrentMoveInfo.DoShow then 3166 begin 3167 if Command = cShowCapturing then 3168 Play('MOVE_CAPTURE') 3169 else if EndHealth <= 0 then 3170 Play('MOVE_DIE') 3171 else if Flags and umSpyMission <> 0 then 3172 Play('MOVE_COVERT') 3173 else if Flags and umShipLoading <> 0 then 3174 if ShowMoveDomain = dAir then 3175 Play('MOVE_PLANELANDING') 3176 else 3177 Play('MOVE_LOAD') 3178 else if Flags and umPlaneLoading <> 0 then 3179 Play('MOVE_LOAD') 3180 else if Flags and umShipUnloading <> 0 then 3181 if ShowMoveDomain = dAir then 3182 Play('MOVE_PLANESTART') 3183 else 3184 Play('MOVE_UNLOAD') 3185 else if Flags and umPlaneUnloading <> 0 then 3186 if (MyMap[FromLoc] and fCity = 0) and 3187 (MyMap[FromLoc] and fTerImp <> tiBase) then 3188 Play('MOVE_PARACHUTE') 3189 else 3190 Play('MOVE_UNLOAD') 3191 else if (ShowMoveDomain = dGround) and not IsAlpine and 3192 (MyMap[ToLoc] and fTerrain = fMountains) and 3193 ((MyMap[FromLoc] and (fRoad or fRR or fCity) = 0) or 3194 (MyMap[ToLoc] and (fRoad or fRR or fCity) = 0)) then 3195 Play('MOVE_MOUNTAIN'); 3196 3197 FocusOnLoc(FromLoc, flImmUpdate); 3198 PaintLoc_BeforeMove(FromLoc); 3199 if Command = cShowCapturing then 3200 MoveOnScreen(TShowMove(Data), 1, 32, 32) 3201 else 3202 MoveOnScreen(TShowMove(Data), 1, AnimationSpeed, AnimationSpeed) 3203 end // if CurrentMoveInfo.DoShow 3204 else 3205 MapValid := false; 3206 end 3207 end; 3208 3209 cShowAttacking: 3210 if (idle and (NewPlayer = me) or not idle and not skipped and 3211 (TShowMove(Data).emix <> $FFFF)) and 3212 not((GameMode = cMovie) and (MovieSpeed = 4)) then 3213 begin 3214 assert(NewPlayer = me); 3215 if not idle or (GameMode = cMovie) then 3216 Application.ProcessMessages; 3217 with TShowMove(Data) do 3218 begin 3219 CurrentMoveInfo.AfterAttackExpeller := -1; 3220 CurrentMoveInfo.DoShow := false; 3221 if idle then 3222 CurrentMoveInfo.DoShow := true // own unit -- always show attacks 3223 else 3224 begin 3225 CurrentMoveInfo.IsAlly := MyRO.Treaty[Owner] = trAlliance; 3226 if CurrentMoveInfo.IsAlly then 3227 CurrentMoveInfo.DoShow := not mAlNoMoves.Checked 3228 else 3229 CurrentMoveInfo.DoShow := not mEnNoMoves.Checked; 3230 end; 3231 if CurrentMoveInfo.DoShow then 3232 begin 3233 ToLoc := dLoc(FromLoc, dx, dy); 3234 if Tribe[Owner].ModelPicture[mix].HGr = 0 then 3235 InitEnemyModel(emix); 3236 3237 if (MyMap[ToLoc] and (fCity or fUnit or fOwned) = fCity or fOwned) 3238 then 3239 begin // tell about bombardment 3240 cix := MyRO.nCity - 1; 3241 while (cix >= 0) and (MyCity[cix].Loc <> ToLoc) do 3242 dec(cix); 3243 if MyCity[cix].Status and csToldBombard = 0 then 3244 begin 3245 if not supervising then 3246 MyCity[cix].Status := MyCity[cix].Status or csToldBombard; 3247 s := CityName(MyCity[cix].ID); 3248 SoundMessageEx(Format(Tribe[Owner].TPhrase('BOMBARD'), 3249 [s]), ''); 3250 Update; // remove message box from screen 3251 end; 3252 end 3253 else if Flags and umExpelling <> 0 then 3254 CurrentMoveInfo.AfterAttackExpeller := Owner; 3255 3256 if Flags and umExpelling <> 0 then 3257 Play('MOVE_EXPEL') 3258 else if Owner = me then 3259 begin 3260 MakeModelInfo(me, mix, MyModel[mix], mi); 3261 Play(AttackSound(ModelCode(mi))); 3262 end 3263 else 3264 Play(AttackSound(ModelCode(MyRO.EnemyModel[emix]))); 3265 3266 FocusOnLoc(FromLoc, flImmUpdate); 3267 3268 // before combat 3269 MainMap.AttackBegin(TShowMove(Data)); 3270 if MyMap[ToLoc] and fCity <> 0 then 3271 PaintLoc(ToLoc); 3272 PaintLoc(FromLoc); 3273 MoveOnScreen(TShowMove(Data), 1, 9, 16); 3274 MoveOnScreen(TShowMove(Data), 17, 12, 32); 3275 MoveOnScreen(TShowMove(Data), 7, 11, 16); 3276 3277 // after combat 3278 MainMap.AttackEffect(TShowMove(Data)); 3279 PaintLoc(ToLoc); 3280 if EndHealth > 0 then 3281 begin 3282 Health := EndHealth; 3283 MoveOnScreen(TShowMove(Data), 10, 0, 16); 3284 end 3285 else if not idle then 3286 Sleep(MoveTime div 2); 3287 MainMap.AttackEnd; 3288 end // if CurrentMoveInfo.DoShow 3289 else 3290 MapValid := false; 3291 end 3292 end; 3293 3294 cShowMissionResult: 3295 if Cardinal(Data) = 0 then 3296 SoundMessageEx(Phrases.Lookup('NOFOREIGNINFO'), '') 3297 else 3298 begin 3299 s := Phrases.Lookup('FOREIGNINFO'); 3300 for p1 := 0 to nPl - 1 do 3301 if 3 shl (p1 * 2) and Cardinal(Data) <> 0 then 3302 s := s + '\' + Tribe[p1].TPhrase('SHORTNAME'); 3303 SoundMessageEx(s, '') 3304 end; 3305 3306 cShowShipChange: 3307 if not IsMultiPlayerGame and (Jump[0] = 0) then 3308 ShowEnemyShipChange(TShowShipChange(Data)); 3309 3310 cShowGreatLibTech: 3311 if not IsMultiPlayerGame and (Jump[0] = 0) then 3312 with MessgExDlg do 3313 begin 3314 MessgText := Format(Phrases.Lookup('GRLIB_GENERAL'), 3315 [Phrases.Lookup('ADVANCES', integer(Data))]); 3316 OpenSound := 'NEWADVANCE_GRLIB'; 3317 Kind := mkOk; 3318 IconKind := mikImp; 3319 IconIndex := woGrLibrary; 3320 ShowModal; 3321 end; 3322 3323 cRefreshDebugMap: 3324 begin 3325 if integer(Data) = IsoEngine.pDebugMap then 3326 begin 3327 MapValid := false; 3328 MainOffscreenPaint; 3329 Update; 3330 end 3331 end; 3332 3333 else 3334 if Command >= cClientEx then 3335 case Command and $FFF0 of 3336 3337 cSetTribe: 3338 with TTribeInfo(Data) do 3339 begin 3340 i := UnusedTribeFiles.Count - 1; 3341 while (i >= 0) and 3342 (AnsiCompareFileName(UnusedTribeFiles[i], FileName) <> 0) do 3343 dec(i); 3344 if i >= 0 then 3345 UnusedTribeFiles.Delete(i); 3346 CreateTribe(trix, FileName, true); 3347 end; 3348 3349 cSetNewModelPicture, cSetModelPicture: 3350 if TribeOriginal[TModelPictureInfo(Data).trix] then 3351 Tribe[TModelPictureInfo(Data).trix].SetModelPicture 3352 (TModelPictureInfo(Data), Command and 3353 $FFF0 = cSetNewModelPicture); 3354 3355 cSetSlaveIndex and $FFF0: 3356 Tribe[integer(Data) shr 16].mixSlaves := integer(Data) and $FFFF; 3357 3358 cSetCityName: 3359 with TCityNameInfo(Data) do 3360 if TribeOriginal[ID shr 12] then 3361 Tribe[ID shr 12].SetCityName(ID and $FFF, NewName); 3362 3363 cSetModelName: 3364 with TModelNameInfo(Data) do 3365 if TribeOriginal[NewPlayer] then 3366 Tribe[NewPlayer].ModelName[mix] := NewName; 3367 end 3368 end 3369 end; { <<<client } 3370 3371 { *** main part *** } 3372 3373 procedure TMainScreen.CreateParams(var p: TCreateParams); 3374 var 3375 DefaultOptionChecked: integer; 3376 Reg: TRegistry; 3377 doinit: boolean; 3378 begin 3379 inherited; 3380 3381 // define which menu settings to save 3382 SaveOption[0] := mAlEffectiveMovesOnly.Tag; 3383 SaveOption[1] := mEnMoves.Tag; 3384 SaveOption[2] := mEnAttacks.Tag; 3385 SaveOption[3] := mEnNoMoves.Tag; 3386 SaveOption[4] := mWaitTurn.Tag; 3387 SaveOption[5] := mEffectiveMovesOnly.Tag; 3388 SaveOption[6] := mEnFastMoves.Tag; 3389 SaveOption[7] := mSlowMoves.Tag; 3390 SaveOption[8] := mFastMoves.Tag; 3391 SaveOption[9] := mVeryFastMoves.Tag; 3392 SaveOption[10] := mNames.Tag; 3393 SaveOption[11] := mRepList.Tag; 3394 SaveOption[12] := mRepScreens.Tag; 3395 SaveOption[13] := mSoundOff.Tag; 3396 SaveOption[14] := mSoundOn.Tag; 3397 SaveOption[15] := mSoundOnAlt.Tag; 3398 SaveOption[16] := mScrollSlow.Tag; 3399 SaveOption[17] := mScrollFast.Tag; 3400 SaveOption[18] := mScrollOff.Tag; 3401 SaveOption[19] := mAlSlowMoves.Tag; 3402 SaveOption[20] := mAlFastMoves.Tag; 3403 SaveOption[21] := mAlNoMoves.Tag; 3404 DefaultOptionChecked := 1 shl 1 + 1 shl 7 + 1 shl 10 + 1 shl 12 + 1 shl 14 + 3405 1 shl 18 + 1 shl 19; 3406 3407 Reg := TRegistry.Create; 3408 doinit := true; 3409 if Reg.KeyExists('SOFTWARE\cevo\RegVer9') then 3410 begin 3411 doinit := false; 3412 Reg.OpenKey('SOFTWARE\cevo\RegVer9', false); 3413 try 3414 xxt := Reg.ReadInteger('TileWidth') div 2; 3415 yyt := Reg.ReadInteger('TileHeight') div 2; 3416 OptionChecked := Reg.ReadInteger('OptionChecked'); 3417 MapOptionChecked := Reg.ReadInteger('MapOptionChecked'); 3418 CityRepMask := Cardinal(Reg.ReadInteger('CityReport')); 3419 except 3420 doinit := true; 3421 end; 3422 Reg.closekey; 3423 if OptionChecked and (7 shl 16) = 0 then 3424 OptionChecked := OptionChecked or (1 shl 16); 3425 // old regver with no scrolling 3426 end; 3427 Reg.free; 3428 if doinit then 3429 begin 3430 xxt := 48; 3431 yyt := 24; 3432 OptionChecked := DefaultOptionChecked; 3433 MapOptionChecked := 1 shl moCityNames; 3434 CityRepMask := Cardinal(not chPopIncrease and not chNoGrowthWarning and 3435 not chCaptured); 3436 end; 3437 3438 if FullScreen then 3439 begin 3440 p.Style := $87000000; 3441 BorderStyle := bsNone; 3442 BorderIcons := []; 3443 end; 3444 3445 if 1 shl 13 and OptionChecked <> 0 then 3446 SoundMode := smOff 3447 else if 1 shl 15 and OptionChecked <> 0 then 3448 SoundMode := smOnAlt 3449 else 3450 SoundMode := smOn 3451 end; 3452 3453 procedure TMainScreen.FormCreate(Sender: TObject); 3454 var 3455 i, j: integer; 3456 begin 3457 Screen.Cursors[crImpDrag] := LoadCursor(HInstance, 'DRAG'); 3458 Screen.Cursors[crFlatHand] := LoadCursor(HInstance, 'FLATHAND'); 3459 3460 // tag-controlled language 3461 for i := 0 to ComponentCount - 1 do 3462 if Components[i].Tag and $FF <> 0 then 3463 if Components[i] is TMenuItem then 3464 begin 3465 TMenuItem(Components[i]).Caption := Phrases.Lookup('CONTROLS', 3466 -1 + Components[i].Tag and $FF); 3467 for j := 0 to nSaveOption - 1 do 3468 if Components[i].Tag and $FF = SaveOption[j] then 3469 TMenuItem(Components[i]).Checked := 1 shl j and 3470 OptionChecked <> 0; 3471 end 3472 else if Components[i] is TButtonBase then 3473 begin 3474 TButtonBase(Components[i]).Hint := Phrases.Lookup('CONTROLS', 3475 -1 + Components[i].Tag and $FF); 3476 if (Components[i] is TButtonC) and 3477 (TButtonC(Components[i]).ButtonIndex <> 1) then 3478 TButtonC(Components[i]).ButtonIndex := 3479 MapOptionChecked shr (Components[i].Tag shr 8) and 1 + 2 3480 end; 3481 3482 // non-tag-controlled language 3483 mTechTree.Caption := Phrases2.Lookup('MENU_ADVTREE'); 3484 mViewpoint.Caption := Phrases2.Lookup('MENU_VIEWPOINT'); 3485 if not Phrases2FallenBackToEnglish then 3486 begin 3487 MenuArea.Hint := Phrases2.Lookup('BTN_MENU'); 3488 TreasuryArea.Hint := Phrases2.Lookup('TIP_TREASURY'); 3489 ResearchArea.Hint := Phrases.Lookup('SCIENCE'); 3490 ManagementArea.Hint := Phrases2.Lookup('BTN_MANAGE'); 3491 end; 3492 for i := 0 to mRep.Count - 1 do 3493 begin 3494 j := mRep[i].Tag shr 8; 3495 mRep[i].Caption := CityEventName(j); 3496 mRep[i].Checked := CityRepMask and (1 shl j) <> 0; 3497 end; 3498 3499 Mini := TBitmap.Create; 3500 Mini.PixelFormat := pf24bit; 3501 Panel := TBitmap.Create; 3502 Panel.PixelFormat := pf24bit; 3503 Panel.Canvas.Font.Assign(UniFont[ftSmall]); 3504 Panel.Canvas.Brush.Style := bsClear; 3505 TopBar := TBitmap.Create; 3506 TopBar.PixelFormat := pf24bit; 3507 TopBar.Canvas.Font.Assign(UniFont[ftNormal]); 3508 TopBar.Canvas.Brush.Style := bsClear; 3509 Buffer := TBitmap.Create; 3510 Buffer.PixelFormat := pf24bit; 3511 if 2 * lxmax > 3 * xSizeBig then 3512 Buffer.width := 2 * lxmax 3513 else 3514 Buffer.width := 3 * xSizeBig; 3515 if lymax > 3 * ySizeBig then 3516 Buffer.height := lymax 3517 else 3518 Buffer.height := 3 * ySizeBig; 3519 Buffer.Canvas.Font.Assign(UniFont[ftSmall]); 3520 for i := 0 to nPl - 1 do 3521 AILogo[i] := nil; 3522 Canvas.Font.Assign(UniFont[ftSmall]); 3523 InitButtons(); 3524 EOT.Template := Templates; 3525 end; 3526 3527 procedure TMainScreen.FormDestroy(Sender: TObject); 3528 var 3529 i: integer; 3530 begin 3531 Mini.free; 3532 Buffer.free; 3533 Panel.free; 3534 for i := 0 to nPl - 1 do 3535 if AILogo[i] <> nil then 3536 AILogo[i].free; 3537 end; 3538 3539 procedure TMainScreen.FormResize(Sender: TObject); 3540 var 3541 MiniFrame, MaxMapWidth: integer; 3542 begin 3543 SmallScreen := ClientWidth < 1024; 3544 MaxMapWidth := (G.lx * 2 - 3) * xxt; 3545 // avoide the same tile being visible left and right 3546 if ClientWidth <= MaxMapWidth then 3547 begin 3548 MapWidth := ClientWidth; 3549 MapOffset := 0; 3550 end 3551 else 3552 begin 3553 MapWidth := MaxMapWidth; 3554 MapOffset := (ClientWidth - MapWidth) div 2; 3555 end; 3556 MapHeight := ClientHeight - TopBarHeight - PanelHeight + overlap; 3557 Panel.width := ClientWidth; 3558 Panel.height := PanelHeight; 3559 TopBar.width := ClientWidth; 3560 TopBar.height := TopBarHeight; 3561 MiniFrame := (lxmax_xxx - G.ly) div 2; 3562 xMidPanel := (G.lx + MiniFrame) * 2 + 1; 3563 xRightPanel := ClientWidth - LeftPanelWidth - 10; 3564 if ClientMode = cEditMap then 3565 TrPitch := 2 * xxt 3566 else 3567 TrPitch := 66; 3568 xMini := MiniFrame - 5; 3569 yMini := (PanelHeight - 26 - lxmax_xxx) div 2 + MiniFrame; 3570 ywmax := (G.ly - MapHeight div yyt + 1) and not 1; 3571 ywcenter := -((MapHeight - yyt * (G.ly - 1)) div (4 * yyt)) * 2; 3572 // only for ywmax<=0 3573 if ywmax <= 0 then 3574 yw := ywcenter 3575 else if yw < 0 then 3576 yw := 0 3577 else if yw > ywmax then 3578 yw := ywmax; 3579 UnitInfoBtn.Top := ClientHeight - 29; 3580 UnitInfoBtn.Left := xMidPanel + 7 + 99; 3581 UnitBtn.Top := ClientHeight - 29; 3582 UnitBtn.Left := xMidPanel + 7 + 99 + 31; 3583 TerrainBtn.Top := ClientHeight - 29; 3584 TerrainBtn.Left := xMidPanel + 7 + 99 + 62; 3585 MovieSpeed1Btn.Top := ClientHeight - 91; 3586 MovieSpeed1Btn.Left := ClientWidth div 2 - 62; 3587 MovieSpeed2Btn.Top := ClientHeight - 91; 3588 MovieSpeed2Btn.Left := ClientWidth div 2 - 62 + 29; 3589 MovieSpeed3Btn.Top := ClientHeight - 91; 3590 MovieSpeed3Btn.Left := ClientWidth div 2 - 62 + 2 * 29; 3591 MovieSpeed4Btn.Top := ClientHeight - 91; 3592 MovieSpeed4Btn.Left := ClientWidth div 2 - 62 + 3 * 29 + 12; 3593 EOT.Top := ClientHeight - 64; 3594 EOT.Left := ClientWidth - 62; 3595 SetWindowPos(sb.h, 0, xRightPanel + 10 - 14 - 3596 GetSystemMetrics(SM_CXVSCROLL), ClientHeight - MidPanelHeight + 8, 0, 0, 3597 SWP_NOSIZE or SWP_NOZORDER); 3598 MapBtn0.Left := xMini + G.lx - 44; 3599 MapBtn0.Top := ClientHeight - 15; 3600 MapBtn1.Left := xMini + G.lx - 28; 3601 MapBtn1.Top := ClientHeight - 15; 3602 { MapBtn2.Left:=xMini+G.lx-20; 3603 MapBtn2.Top:=ClientHeight-15; 3604 MapBtn3.Left:=xMini+G.lx-4; 3605 MapBtn3.Top:=ClientHeight-15; } 3606 MapBtn5.Left := xMini + G.lx - 12; 3607 MapBtn5.Top := ClientHeight - 15; 3608 MapBtn4.Left := xMini + G.lx + 20; 3609 MapBtn4.Top := ClientHeight - 15; 3610 MapBtn6.Left := xMini + G.lx + 36; 3611 MapBtn6.Top := ClientHeight - 15; 3612 TreasuryArea.Left := ClientWidth div 2 - 172; 3613 ResearchArea.Left := ClientWidth div 2; 3614 ManagementArea.Left := ClientWidth - xPalace; 3615 ManagementArea.Top := TopBarHeight + MapHeight - overlap + yPalace; 3616 ArrangeMidPanel; 3617 if RepaintOnResize then 3618 begin 3619 RectInvalidate(0, TopBarHeight, ClientWidth, TopBarHeight + MapHeight); 3620 MapValid := false; 3621 PaintAll 3622 end 3623 end; 3624 3625 procedure TMainScreen.FormCloseQuery(Sender: TObject; var CanClose: boolean); 3626 begin 3627 CanClose := Closable; 3628 if not Closable and idle and (me = 0) and (ClientMode < scContact) then 3629 MenuClick(mResign) 3630 end; 3631 3632 procedure TMainScreen.OnScroll(var m: TMessage); 3633 begin 3634 if ProcessPVSB(sb, m) then 3635 begin 3636 PanelPaint; 3637 Update 3638 end 3639 end; 3640 3641 procedure TMainScreen.OnEOT(var Msg: TMessage); 3642 begin 3643 EndTurn 3644 end; 3645 3646 procedure TMainScreen.EOTClick(Sender: TObject); 3647 begin 3648 if GameMode = cMovie then 3649 begin 3650 MessgExDlg.CancelMovie; 3651 Server(sBreak, me, 0, nil^) 3652 end 3653 else if ClientMode < 0 then 3654 skipped := true 3655 else if ClientMode >= scContact then 3656 NegoDlg.ShowNewContent(wmPersistent) 3657 else if Jump[pTurn] > 0 then 3658 begin 3659 Jump[pTurn] := 0; 3660 StartRunning := false 3661 end 3662 else 3663 EndTurn 3664 end; 3665 3666 // set xTerrain, xTroop, and TrRow 3667 procedure TMainScreen.ArrangeMidPanel; 3668 begin 3669 if ClientMode = cEditMap then 3670 xTroop := xMidPanel + 15 3671 else 3672 begin 3673 if supervising then 3674 xTerrain := xMidPanel + 2 * xxt + 14 3675 else if ClientWidth < 1280 then 3676 xTerrain := ClientWidth div 2 + (1280 - ClientWidth) div 3 3677 else 3678 xTerrain := ClientWidth div 2; 3679 xTroop := xTerrain + 2 * xxt + 12; 3680 if SmallScreen and not supervising then 3681 xTroop := xRightPanel + 10 - 3 * 66 - 3682 GetSystemMetrics(SM_CXVSCROLL) - 19 - 4; 3683 // not perfect but we assume almost no one is still playing on a 800x600 screen 3684 end; 3685 TrRow := (xRightPanel + 10 - xTroop - GetSystemMetrics(SM_CXVSCROLL) - 19) 3686 div TrPitch; 3687 end; 3688 3689 function TMainScreen.EndTurn(WasSkipped: boolean): boolean; 3690 3691 function IsResourceUnused(cix, NeedFood, NeedProd: integer): boolean; 3692 var 3693 dx, dy, fix: integer; 3694 CityAreaInfo: TCityAreaInfo; 3695 TileInfo: TTileInfo; 3696 begin 3697 Server(sGetCityAreaInfo, me, cix, CityAreaInfo); 3698 for dy := -3 to 3 do 3699 for dx := -3 to 3 do 3700 if ((dx + dy) and 1 = 0) and (dx * dx * dy * dy < 81) then 3701 begin 3702 fix := (dy + 3) shl 2 + (dx + 3) shr 1; 3703 if (MyCity[cix].Tiles and (1 shl fix) = 0) // not used yet 3704 and (CityAreaInfo.Available[fix] = faAvailable) then // usable 3705 begin 3706 TileInfo.ExplCity := cix; 3707 Server(sGetHypoCityTileInfo, me, dLoc(MyCity[cix].Loc, dx, dy), 3708 TileInfo); 3709 if (TileInfo.Food >= NeedFood) and (TileInfo.Prod >= NeedProd) 3710 then 3711 begin 3712 result := true; 3713 exit 3714 end; 3715 end 3716 end; 3717 result := false; 3718 end; 3719 3720 var 3721 i, p1, uix, cix, CenterLoc: integer; 3722 MsgItem: string; 3723 CityReport: TCityReport; 3724 PlaneReturnData: TPlaneReturnData; 3725 Zoom: boolean; 3726 begin 3727 result := false; 3728 if ClientMode >= scDipOffer then 3729 exit; 3730 3731 if supervising and (me <> 0) then 3732 begin 3733 for i := 0 to Screen.FormCount - 1 do 3734 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 3735 then 3736 Screen.Forms[i].Close; // close windows 3737 ItsMeAgain(0); 3738 end; 3739 3740 CityOptimizer_EndOfTurn; 3741 3742 if not WasSkipped then // check warnings 3743 begin 3744 // need to move planes home? 3745 for uix := 0 to MyRO.nUn - 1 do 3746 with MyUn[uix] do 3747 if (Loc >= 0) and (MyModel[mix].Domain = dAir) and 3748 (Status and usToldNoReturn = 0) and (Master < 0) and 3749 (MyMap[Loc] and fCity = 0) and (MyMap[Loc] and fTerImp <> tiBase) 3750 then 3751 begin 3752 PlaneReturnData.Fuel := Fuel; 3753 PlaneReturnData.Loc := Loc; 3754 PlaneReturnData.Movement := 0; // end turn without further movement? 3755 if Server(sGetPlaneReturn, me, uix, PlaneReturnData) = eNoWay then 3756 begin 3757 CenterLoc := Loc + G.lx * 6; 3758 // centering the unit itself would make it covered by the query dialog 3759 while CenterLoc >= G.lx * G.ly do 3760 dec(CenterLoc, G.lx * 2); 3761 Centre(CenterLoc); 3762 SetTroopLoc(-1); 3763 PaintAll; 3764 3765 if MyModel[mix].Kind = mkSpecial_Glider then 3766 MsgItem := 'LOWFUEL_GLIDER' 3767 else 3768 MsgItem := 'LOWFUEL'; 3769 if SimpleQuery(mkYesNo, Phrases.Lookup(MsgItem), 3770 'WARNING_LOWSUPPORT') <> mrOK then 3771 begin 3772 SetUnFocus(uix); 3773 SetTroopLoc(Loc); 3774 PanelPaint; 3775 exit; 3776 end; 3777 MyUn[uix].Status := MyUn[uix].Status or usToldNoReturn; 3778 end 3779 end; 3780 3781 if not supervising and (MyRO.TestFlags and tfImmImprove = 0) and 3782 (MyRO.Government <> gAnarchy) and (MyRO.Money + TaxSum < 0) and 3783 (MyRO.TaxRate < 100) then // low funds! 3784 with MessgExDlg do 3785 begin 3786 OpenSound := 'WARNING_LOWFUNDS'; 3787 MessgText := Phrases.Lookup('LOWFUNDS'); 3788 Kind := mkYesNo; 3789 IconKind := mikImp; 3790 IconIndex := imTrGoods; 3791 ShowModal; 3792 if ModalResult <> mrOK then 3793 exit 3794 end; 3795 3796 if MyRO.Government <> gAnarchy then 3797 for cix := 0 to MyRO.nCity - 1 do 3798 with MyCity[cix] do 3799 if (Loc >= 0) and (Flags and chCaptured = 0) then 3800 begin 3801 Zoom := false; 3802 CityReport.HypoTiles := -1; 3803 CityReport.HypoTax := -1; 3804 CityReport.HypoLux := -1; 3805 Server(sGetCityReport, me, cix, CityReport); 3806 3807 if (CityReport.Working - CityReport.Happy > Size shr 1) and 3808 (Flags and chCaptured <= $10000) then 3809 with MessgExDlg do 3810 begin 3811 OpenSound := 'WARNING_DISORDER'; 3812 if Status and csResourceWeightsMask = 0 then 3813 MsgItem := 'DISORDER' 3814 else 3815 MsgItem := 'DISORDER_UNREST'; 3816 MessgText := Format(Phrases.Lookup(MsgItem), [CityName(ID)]); 3817 Kind := mkYesNo; 3818 // BigIcon:=29; 3819 ShowModal; 3820 Zoom := ModalResult <> mrOK; 3821 end; 3822 if not Zoom and (Food + CityReport.FoodRep - CityReport.Eaten < 0) 3823 then 3824 with MessgExDlg do 3825 begin 3826 OpenSound := 'WARNING_FAMINE'; 3827 if Status and csResourceWeightsMask = 0 then 3828 MsgItem := 'FAMINE' 3829 else if (CityReport.Deployed <> 0) and 3830 IsResourceUnused(cix, 1, 0) then 3831 MsgItem := 'FAMINE_UNREST' 3832 else 3833 MsgItem := 'FAMINE_TILES'; 3834 MessgText := Format(Phrases.Lookup(MsgItem), [CityName(ID)]); 3835 Kind := mkYesNo; 3836 IconKind := mikImp; 3837 IconIndex := 22; 3838 ShowModal; 3839 Zoom := ModalResult <> mrOK; 3840 end; 3841 if not Zoom and (CityReport.ProdRep < CityReport.Support) then 3842 with MessgExDlg do 3843 begin 3844 OpenSound := 'WARNING_LOWSUPPORT'; 3845 if Status and csResourceWeightsMask = 0 then 3846 MsgItem := 'LOWSUPPORT' 3847 else if (CityReport.Deployed <> 0) and 3848 IsResourceUnused(cix, 0, 1) then 3849 MsgItem := 'LOWSUPPORT_UNREST' 3850 else 3851 MsgItem := 'LOWSUPPORT_TILES'; 3852 MessgText := Format(Phrases.Lookup(MsgItem), [CityName(ID)]); 3853 Kind := mkYesNo; 3854 IconKind := mikImp; 3855 IconIndex := 29; 3856 ShowModal; 3857 Zoom := ModalResult <> mrOK; 3858 end; 3859 if Zoom then 3860 begin // zoom to city 3861 ZoomToCity(Loc); 3862 exit 3863 end 3864 end; 3865 3866 if (MyRO.Happened and phTech <> 0) and (MyRO.ResearchTech < 0) and 3867 (MyData.FarTech <> adNexus) then 3868 if not ChooseResearch then 3869 exit; 3870 end; 3871 3872 RememberPeaceViolation; 3873 3874 SetUnFocus(-1); 3875 for uix := 0 to MyRO.nUn - 1 do 3876 MyUn[uix].Status := MyUn[uix].Status and usPersistent; 3877 3878 CityDlg.CloseAction := None; 3879 if IsMultiPlayerGame then 3880 begin // close windows for next player 3881 for i := 0 to Screen.FormCount - 1 do 3882 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 3883 then 3884 Screen.Forms[i].Close; 3885 end 3886 else 3887 begin 3888 if CityDlg.Visible then 3889 CityDlg.Close; 3890 if UnitStatDlg.Visible then 3891 UnitStatDlg.Close; 3892 end; 3893 for i := 0 to Screen.FormCount - 1 do 3894 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 3895 Screen.Forms[i].Enabled := false; 3896 3897 if Server(sTurn, pTurn, 0, nil^) >= rExecuted then 3898 begin 3899 if Jump[pTurn] > 0 then 3900 EOT.Hint := Phrases.Lookup('BTN_STOP') 3901 else 3902 EOT.Hint := Phrases.Lookup('BTN_SKIP'); 3903 result := true; 3904 SetTroopLoc(-1); 3905 pTurn := -1; 3906 pLogo := -1; 3907 UnitInfoBtn.Visible := false; 3908 UnitBtn.Visible := false; 3909 TerrainBtn.Visible := false; 3910 EOT.ButtonIndex := eotCancel; 3911 EOT.Visible := true; 3912 MapValid := false; 3913 PanelPaint; 3914 Update; 3915 ClientMode := -1; 3916 idle := false; 3917 skipped := WasSkipped; 3918 for p1 := 1 to nPl - 1 do 3919 if G.RO[p1] <> nil then 3920 skipped := true; // don't show enemy moves in hotseat mode 3921 end 3922 else 3923 PanelPaint 3924 end; // EndTurn 3925 3926 procedure TMainScreen.EndNego; 3927 begin 3928 if NegoDlg.Visible then 3929 NegoDlg.Close; 3930 HaveStrategyAdvice := false; 3931 // AdvisorDlg.HaveStrategyAdvice; 3932 // negotiation might have changed advices 3933 EOT.ButtonIndex := eotCancel; 3934 EOT.Visible := true; 3935 PanelPaint; 3936 Update; 3937 ClientMode := -1; 3938 idle := false; 3939 end; 3940 3941 procedure TMainScreen.ProcessRect(x0, y0, nx, ny, Options: integer); 3942 var 3943 xs, ys, xl, yl: integer; 3944 begin 3945 xl := nx * xxt + xxt; 3946 yl := ny * yyt + yyt * 2; 3947 xs := (x0 - xw) * (xxt * 2) + y0 and 1 * xxt - G.lx * (xxt * 2); 3948 // |xs+xl/2-MapWidth/2| -> min 3949 while abs(2 * (xs + G.lx * (xxt * 2)) + xl - MapWidth) < 3950 abs(2 * xs + xl - MapWidth) do 3951 inc(xs, G.lx * (xxt * 2)); 3952 ys := (y0 - yw) * yyt - yyt; 3953 if xs + xl > MapWidth then 3954 xl := MapWidth - xs; 3955 if ys + yl > MapHeight then 3956 yl := MapHeight - ys; 3957 if (xl <= 0) or (yl <= 0) then 3958 exit; 3959 if Options and prPaint <> 0 then 3960 begin 3961 if Options and prAutoBounds <> 0 then 3962 MainMap.SetPaintBounds(xs, ys, xs + xl, ys + yl); 3963 MainMap.Paint(xs, ys, x0 + G.lx * y0, nx, ny, -1, -1); 3964 end; 3965 if Options and prInvalidate <> 0 then 3966 RectInvalidate(MapOffset + xs, TopBarHeight + ys, MapOffset + xs + xl, 3967 TopBarHeight + ys + yl) 3968 end; 3969 3970 procedure TMainScreen.PaintLoc(Loc: integer; Radius: integer = 0); 3971 var 3972 yLoc, x0: integer; 3973 begin 3974 if MapValid then 3975 begin 3976 yLoc := (Loc + G.lx * 1024) div G.lx - 1024; 3977 x0 := (Loc + (yLoc and 1 - 2 * Radius + G.lx * 1024) div 2) mod G.lx; 3978 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 3979 ProcessRect(x0, yLoc - 2 * Radius, 4 * Radius + 1, 4 * Radius + 1, 3980 prPaint or prAutoBounds or prInvalidate); 3981 Update; 3982 end 3983 end; 3984 3985 procedure TMainScreen.PaintLocTemp(Loc, Style: integer); 3986 var 3987 y0, x0, xMap, yMap: integer; 3988 begin 3989 if not MapValid then 3990 exit; 3991 Buffer.Canvas.Font.Assign(UniFont[ftSmall]); 3992 y0 := Loc div G.lx; 3993 x0 := Loc mod G.lx; 3994 xMap := (x0 - xw) * (xxt * 2) + y0 and 1 * xxt - G.lx * (xxt * 2); 3995 // |xMap+xxt-MapWidth/2| -> min 3996 while abs(2 * (xMap + G.lx * (xxt * 2)) + 2 * xxt - MapWidth) < 3997 abs(2 * xMap + 2 * xxt - MapWidth) do 3998 inc(xMap, G.lx * (xxt * 2)); 3999 yMap := (y0 - yw) * yyt - yyt; 4000 NoMap.SetOutput(Buffer); 4001 NoMap.SetPaintBounds(0, 0, 2 * xxt, 3 * yyt); 4002 NoMap.Paint(0, 0, Loc, 1, 1, -1, -1, Style = pltsBlink); 4003 PaintBufferToScreen(xMap, yMap, 2 * xxt, 3 * yyt); 4004 end; 4005 4006 // paint content of buffer directly to screen instead of offscreen 4007 // panel protusions are added 4008 // NoMap must be set to buffer and bounds before 4009 procedure TMainScreen.PaintBufferToScreen(xMap, yMap, width, height: integer); 4010 begin 4011 if xMap + width > MapWidth then 4012 width := MapWidth - xMap; 4013 if yMap + height > MapHeight then 4014 height := MapHeight - yMap; 4015 if (width <= 0) or (height <= 0) or (width + xMap <= 0) or 4016 (height + yMap <= 0) then 4017 exit; 4018 4019 NoMap.BitBlt(Panel, -xMap - MapOffset, -yMap + MapHeight - overlap, 4020 xMidPanel, overlap, 0, 0, SRCCOPY); 4021 NoMap.BitBlt(Panel, -xMap - MapOffset + xRightPanel, 4022 -yMap + MapHeight - overlap, Panel.width - xRightPanel, overlap, 4023 xRightPanel, 0, SRCCOPY); 4024 if yMap < 0 then 4025 begin 4026 if xMap < 0 then 4027 BitBlt(Canvas.Handle, MapOffset, TopBarHeight, width + xMap, 4028 height + yMap, Buffer.Canvas.Handle, -xMap, -yMap, SRCCOPY) 4029 else 4030 BitBlt(Canvas.Handle, xMap + MapOffset, TopBarHeight, width, 4031 height + yMap, Buffer.Canvas.Handle, 0, -yMap, SRCCOPY) 4032 end 4033 else 4034 begin 4035 if xMap < 0 then 4036 BitBlt(Canvas.Handle, MapOffset, TopBarHeight + yMap, width + xMap, 4037 height, Buffer.Canvas.Handle, -xMap, 0, SRCCOPY) 4038 else 4039 BitBlt(Canvas.Handle, xMap + MapOffset, TopBarHeight + yMap, width, 4040 height, Buffer.Canvas.Handle, 0, 0, SRCCOPY); 4041 end 4042 end; 4043 4044 procedure TMainScreen.PaintLoc_BeforeMove(FromLoc: integer); 4045 var 4046 yLoc, x0: integer; 4047 begin 4048 if MapValid then 4049 begin 4050 yLoc := (FromLoc + G.lx * 1024) div G.lx - 1024; 4051 x0 := (FromLoc + (yLoc and 1 + G.lx * 1024) div 2) mod G.lx; 4052 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 4053 ProcessRect(x0, yLoc, 1, 1, prPaint or prAutoBounds); 4054 end 4055 end; 4056 4057 procedure TMainScreen.PaintDestination; 4058 var 4059 Destination: integer; 4060 begin 4061 if (UnFocus >= 0) and (MyUn[UnFocus].Status and usGoto <> 0) then 4062 begin 4063 Destination := MyUn[UnFocus].Status shr 16; 4064 if (Destination <> $7FFF) and (Destination <> MyUn[UnFocus].Loc) then 4065 PaintLocTemp(Destination, pltsBlink); 4066 end; 4067 end; 4068 4069 procedure TMainScreen.MiniPaint; 4070 type 4071 TLine = array [0 .. 99999999, 0 .. 2] of Byte; 4072 var 4073 uix, cix, x, y, Loc, i, hw, xm, cm, cmPolOcean, cmPolNone: integer; 4074 PrevMiniLine, MiniLine: ^TLine; 4075 begin 4076 cmPolOcean := GrExt[HGrSystem].Data.Canvas.Pixels[101, 67]; 4077 cmPolNone := GrExt[HGrSystem].Data.Canvas.Pixels[102, 67]; 4078 hw := MapWidth div (xxt * 2); 4079 with Mini.Canvas do 4080 begin 4081 Brush.Color := $000000; 4082 FillRect(Rect(0, 0, Mini.width, Mini.height)); 4083 end; 4084 MiniLine := nil; 4085 for y := 0 to G.ly - 1 do 4086 begin 4087 PrevMiniLine := MiniLine; 4088 MiniLine := Mini.ScanLine[y]; 4089 for x := 0 to G.lx - 1 do 4090 if MyMap[x + G.lx * y] and fTerrain <> fUNKNOWN then 4091 begin 4092 Loc := x + G.lx * y; 4093 for i := 0 to 1 do 4094 begin 4095 xm := ((x - xwMini) * 2 + i + y and 1 - hw + G.lx * 5) 4096 mod (G.lx * 2); 4097 cm := MiniColors[MyMap[Loc] and fTerrain, i]; 4098 if ClientMode = cEditMap then 4099 begin 4100 if MyMap[Loc] and (fPrefStartPos or fStartPos) <> 0 then 4101 cm := $FFFFFF; 4102 end 4103 else if MyMap[Loc] and fCity <> 0 then 4104 begin 4105 cix := MyRO.nCity - 1; 4106 while (cix >= 0) and (MyCity[cix].Loc <> Loc) do 4107 dec(cix); 4108 if cix >= 0 then 4109 cm := Tribe[me].Color 4110 else 4111 begin 4112 cix := MyRO.nEnemyCity - 1; 4113 while (cix >= 0) and (MyRO.EnemyCity[cix].Loc <> Loc) do 4114 dec(cix); 4115 if cix >= 0 then 4116 cm := Tribe[MyRO.EnemyCity[cix].Owner].Color 4117 end; 4118 cm := $808080 or cm shr 1; { increase brightness } 4119 if PrevMiniLine <> nil then 4120 begin // 2x2 city dot covers two scanlines 4121 PrevMiniLine[xm, 0] := cm shr 16; 4122 PrevMiniLine[xm, 1] := cm shr 8 and $FF; 4123 PrevMiniLine[xm, 2] := cm and $FF; 4124 end 4125 end 4126 else if (i = 0) and (MyMap[Loc] and fUnit <> 0) then 4127 begin 4128 uix := MyRO.nUn - 1; 4129 while (uix >= 0) and (MyUn[uix].Loc <> Loc) do 4130 dec(uix); 4131 if uix >= 0 then 4132 cm := Tribe[me].Color 4133 else 4134 begin 4135 uix := MyRO.nEnemyUn - 1; 4136 while (uix >= 0) and (MyRO.EnemyUn[uix].Loc <> Loc) do 4137 dec(uix); 4138 if uix >= 0 then 4139 cm := Tribe[MyRO.EnemyUn[uix].Owner].Color 4140 end; 4141 cm := $808080 or cm shr 1; { increase brightness } 4142 end 4143 else if MapOptionChecked and (1 shl moPolitical) <> 0 then 4144 begin 4145 if MyMap[Loc] and fTerrain < fGrass then 4146 cm := cmPolOcean 4147 else if MyRO.Territory[Loc] < 0 then 4148 cm := cmPolNone 4149 else 4150 cm := Tribe[MyRO.Territory[Loc]].Color; 4151 end; 4152 MiniLine[xm, 0] := cm shr 16; 4153 MiniLine[xm, 1] := cm shr 8 and $FF; 4154 MiniLine[xm, 2] := cm and $FF; 4155 end; 4156 end 4157 end; 4158 end; 4159 4160 procedure TMainScreen.MainOffscreenPaint; 4161 var 4162 ProcessOptions: integer; 4163 rec: TRect; 4164 DoInvalidate: boolean; 4165 begin 4166 if me < 0 then 4167 with offscreen.Canvas do 4168 begin 4169 Brush.Color := $000000; 4170 FillRect(Rect(0, 0, MapWidth, MapHeight)); 4171 Brush.Style := bsClear; 4172 OffscreenUser := self; 4173 exit 4174 end; 4175 4176 MainMap.SetPaintBounds(0, 0, MapWidth, MapHeight); 4177 if OffscreenUser <> self then 4178 begin 4179 if OffscreenUser <> nil then 4180 OffscreenUser.Update; 4181 // complete working with old owner to prevent rebound 4182 if MapValid and (xwd = xw) and (ywd = yw) then 4183 MainMap.SetPaintBounds(0, 0, UsedOffscreenWidth, UsedOffscreenHeight); 4184 MapValid := false; 4185 OffscreenUser := self; 4186 end; 4187 4188 if xw - xwd > G.lx div 2 then 4189 xwd := xwd + G.lx 4190 else if xwd - xw > G.lx div 2 then 4191 xwd := xwd - G.lx; 4192 if not MapValid or (xw - xwd > MapWidth div (xxt * 2)) or 4193 (xwd - xw > MapWidth div (xxt * 2)) or (yw - ywd > MapHeight div yyt) or 4194 (ywd - yw > MapHeight div yyt) then 4195 begin 4196 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 4197 ProcessRect(xw, yw, MapWidth div xxt, MapHeight div yyt, 4198 prPaint or prInvalidate) 4199 end 4200 else 4201 begin 4202 if (xwd = xw) and (ywd = yw) then 4203 exit; { map window not moved } 4204 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 4205 rec := Rect(0, 0, MapWidth, MapHeight); 4206 ScrollDC(offscreen.Canvas.Handle, (xwd - xw) * (xxt * 2), 4207 (ywd - yw) * yyt, rec, rec, 0, nil); 4208 for DoInvalidate := false to FastScrolling do 4209 begin 4210 if DoInvalidate then 4211 begin 4212 rec.Bottom := MapHeight - overlap; 4213 ScrollDC(Canvas.Handle, (xwd - xw) * (xxt * 2), (ywd - yw) * yyt, rec, 4214 rec, 0, nil); 4215 ProcessOptions := prInvalidate; 4216 end 4217 else 4218 ProcessOptions := prPaint or prAutoBounds; 4219 if yw < ywd then 4220 begin 4221 ProcessRect(xw, yw, MapWidth div xxt, ywd - yw - 1, ProcessOptions); 4222 if xw < xwd then 4223 ProcessRect(xw, ywd, (xwd - xw) * 2 - 1, MapHeight div yyt - ywd + 4224 yw, ProcessOptions) 4225 else if xw > xwd then 4226 ProcessRect((xwd + MapWidth div (xxt * 2)) mod G.lx, ywd, 4227 (xw - xwd) * 2 + 1, MapHeight div yyt - ywd + yw, ProcessOptions) 4228 end 4229 else if yw > ywd then 4230 begin 4231 if DoInvalidate then 4232 RectInvalidate(MapOffset, TopBarHeight + MapHeight - overlap - 4233 (yw - ywd) * yyt, MapOffset + MapWidth, TopBarHeight + MapHeight 4234 - overlap) 4235 else 4236 ProcessRect(xw, (ywd + MapHeight div (yyt * 2) * 2), 4237 MapWidth div xxt, yw - ywd + 1, ProcessOptions); 4238 if xw < xwd then 4239 ProcessRect(xw, yw, (xwd - xw) * 2 - 1, MapHeight div yyt - yw + ywd 4240 - 2, ProcessOptions) 4241 else if xw > xwd then 4242 ProcessRect((xwd + MapWidth div (xxt * 2)) mod G.lx, yw, 4243 (xw - xwd) * 2 + 1, MapHeight div yyt - yw + ywd - 2, 4244 ProcessOptions) 4245 end 4246 else if xw < xwd then 4247 ProcessRect(xw, yw, (xwd - xw) * 2 - 1, MapHeight div yyt, 4248 ProcessOptions) 4249 else if xw > xwd then 4250 ProcessRect((xwd + MapWidth div (xxt * 2)) mod G.lx, yw, 4251 (xw - xwd) * 2 + 1, MapHeight div yyt, ProcessOptions); 4252 end; 4253 if not FastScrolling then 4254 RectInvalidate(MapOffset, TopBarHeight, MapOffset + MapWidth, 4255 TopBarHeight + MapHeight - overlap); 4256 RectInvalidate(xMidPanel, TopBarHeight + MapHeight - overlap, xRightPanel, 4257 TopBarHeight + MapHeight) 4258 end; 4259 // if (xwd<>xw) or (ywd<>yw) then 4260 // Server(sChangeSuperView,me,yw*G.lx+xw,nil^); // for synchronizing client side viewer, not used currently 4261 xwd := xw; 4262 ywd := yw; 4263 MapValid := true; 4264 end; 4265 4266 procedure TMainScreen.PaintAll; 4267 begin 4268 MainOffscreenPaint; 4269 xwMini := xw; 4270 ywMini := yw; 4271 MiniPaint; 4272 PanelPaint; 4273 end; 4274 4275 procedure TMainScreen.PaintAllMaps; 4276 begin 4277 MainOffscreenPaint; 4278 xwMini := xw; 4279 ywMini := yw; 4280 MiniPaint; 4281 CopyMiniToPanel; 4282 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini + 2, 4283 xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini + 4284 2 + G.ly); 4285 end; 4286 4287 procedure TMainScreen.CopyMiniToPanel; 4288 begin 4289 BitBlt(Panel.Canvas.Handle, xMini + 2, yMini + 2, G.lx * 2, G.ly, 4290 Mini.Canvas.Handle, 0, 0, SRCCOPY); 4291 if MarkCityLoc >= 0 then 4292 Sprite(Panel, HGrSystem, 4293 xMini - 2 + (4 * G.lx + 2 * (MarkCityLoc mod G.lx) + 4294 (G.lx - MapWidth div (xxt * 2)) - 2 * xwd) mod (2 * G.lx) + 4295 MarkCityLoc div G.lx and 1, yMini - 3 + MarkCityLoc div G.lx, 10, 4296 10, 77, 47) 4297 else if ywmax <= 0 then 4298 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (xxt * 2), yMini + 2, 4299 xMini + 1 + G.lx + MapWidth div (xxt * 2), yMini + 2 + G.ly - 1, 4300 MainTexture.clMark, MainTexture.clMark) 4301 else 4302 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (xxt * 2), 4303 yMini + 2 + yw, xMini + 1 + G.lx + MapWidth div (xxt * 2), 4304 yMini + yw + MapHeight div yyt, MainTexture.clMark, MainTexture.clMark); 4305 end; 4306 4307 procedure TMainScreen.PanelPaint; 4308 4309 function MovementToString(var Un: TUn): string; 4310 begin 4311 result := ScreenTools.MovementToString(Un.Movement); 4312 if Un.Master >= 0 then 4313 result := '(' + result + ')' 4314 else if (MyModel[Un.mix].Domain = dAir) and 4315 (MyModel[Un.mix].Kind <> mkSpecial_Glider) then 4316 result := Format('%s(%d)', [result, Un.Fuel]); 4317 end; 4318 4319 var 4320 i, uix, uixDefender, x, xSrc, ySrc, xSrcBase, ySrcBase, CostFactor, Count, 4321 mixShow, xTreasurySection, xResearchSection, JobFocus, TrueMoney, 4322 TrueResearch: integer; 4323 Tile: Cardinal; 4324 s: string; 4325 unx: TUn; 4326 UnitInfo: TUnitInfo; 4327 JobProgressData: TJobProgressData; 4328 Prio: boolean; 4329 begin 4330 with Panel.Canvas do 4331 begin 4332 Fill(Panel.Canvas, 0, 3, xMidPanel + 7 - 10, PanelHeight - 3, 4333 wMainTexture - (xMidPanel + 7 - 10), hMainTexture - PanelHeight); 4334 Fill(Panel.Canvas, xRightPanel + 10 - 7, 3, Panel.width - xRightPanel - 10 4335 + 7, PanelHeight - 3, -(xRightPanel + 10 - 7), 4336 hMainTexture - PanelHeight); 4337 FillLarge(Panel.Canvas, xMidPanel - 2, PanelHeight - MidPanelHeight, 4338 xRightPanel + 2, PanelHeight, ClientWidth div 2); 4339 4340 Brush.Style := bsClear; 4341 Pen.Color := $000000; 4342 MoveTo(0, 0); 4343 LineTo(xMidPanel + 7 - 8, 0); 4344 LineTo(xMidPanel + 7 - 8, PanelHeight - MidPanelHeight); 4345 LineTo(xRightPanel, PanelHeight - MidPanelHeight); 4346 LineTo(xRightPanel, 0); 4347 LineTo(ClientWidth, 0); 4348 Pen.Color := MainTexture.clBevelLight; 4349 MoveTo(xMidPanel + 7 - 9, PanelHeight - MidPanelHeight + 2); 4350 LineTo(xRightPanel + 10 - 8, PanelHeight - MidPanelHeight + 2); 4351 Pen.Color := MainTexture.clBevelLight; 4352 MoveTo(0, 1); 4353 LineTo(xMidPanel + 7 - 9, 1); 4354 Pen.Color := MainTexture.clBevelShade; 4355 LineTo(xMidPanel + 7 - 9, PanelHeight - MidPanelHeight + 1); 4356 Pen.Color := MainTexture.clBevelLight; 4357 LineTo(xRightPanel + 10 - 9, PanelHeight - MidPanelHeight + 1); 4358 Pen.Color := MainTexture.clBevelLight; 4359 LineTo(xRightPanel + 10 - 9, 1); 4360 LineTo(ClientWidth, 1); 4361 MoveTo(ClientWidth, 2); 4362 LineTo(xRightPanel + 10 - 8, 2); 4363 LineTo(xRightPanel + 10 - 8, PanelHeight); 4364 MoveTo(0, 2); 4365 LineTo(xMidPanel + 7 - 10, 2); 4366 Pen.Color := MainTexture.clBevelShade; 4367 LineTo(xMidPanel + 7 - 10, PanelHeight); 4368 Corner(Panel.Canvas, xMidPanel + 7 - 16, 1, 1, MainTexture); 4369 Corner(Panel.Canvas, xRightPanel + 10 - 9, 1, 0, MainTexture); 4370 if ClientMode <> cEditMap then 4371 begin 4372 if supervising then 4373 begin 4374 Frame(Panel.Canvas, ClientWidth - xPalace - 1, yPalace - 1, 4375 ClientWidth - xPalace + xSizeBig, yPalace + ySizeBig, 4376 $B0B0B0, $FFFFFF); 4377 RFrame(Panel.Canvas, ClientWidth - xPalace - 2, yPalace - 2, 4378 ClientWidth - xPalace + xSizeBig + 1, yPalace + ySizeBig + 1, 4379 $FFFFFF, $B0B0B0); 4380 BitBlt(Panel.Canvas.Handle, ClientWidth - xPalace, yPalace, xSizeBig, 4381 ySizeBig, GrExt[HGrSystem2].Data.Canvas.Handle, 70, 123, SRCCOPY); 4382 end 4383 else if MyRO.NatBuilt[imPalace] > 0 then 4384 ImpImage(Panel.Canvas, ClientWidth - xPalace, yPalace, imPalace, -1, 4385 GameMode <> cMovie 4386 { (GameMode<>cMovie) and (MyRO.Government<>gAnarchy) } ) 4387 else 4388 ImpImage(Panel.Canvas, ClientWidth - xPalace, yPalace, 21, -1, 4389 GameMode <> cMovie 4390 { (GameMode<>cMovie) and (MyRO.Government<>gAnarchy) } ); 4391 end; 4392 4393 if GameMode = cMovie then 4394 Frame(Panel.Canvas, xMini + 1, yMini + 1, xMini + 2 + G.lx * 2, 4395 yMini + 2 + G.ly, $000000, $000000) 4396 else 4397 begin 4398 Frame(Panel.Canvas, xMini + 1, yMini + 1, xMini + 2 + G.lx * 2, 4399 yMini + 2 + G.ly, $B0B0B0, $FFFFFF); 4400 RFrame(Panel.Canvas, xMini, yMini, xMini + 3 + G.lx * 2, 4401 yMini + 3 + G.ly, $FFFFFF, $B0B0B0); 4402 end; 4403 CopyMiniToPanel; 4404 if ClientMode <> cEditMap then // MapBtn icons 4405 for i := 0 to 5 do 4406 if i <> 3 then 4407 Dump(Panel, HGrSystem, xMini + G.lx - 42 + 16 * i, PanelHeight - 26, 4408 8, 8, 121 + i * 9, 61); 4409 4410 if ClientMode = cEditMap then 4411 begin 4412 for i := 0 to TrRow - 1 do 4413 trix[i] := -1; 4414 Count := 0; 4415 for i := 0 to nBrushTypes - 1 do 4416 begin // display terrain types 4417 if (Count >= TrRow * sb.si.npos) and (Count < TrRow * (sb.si.npos + 1)) 4418 then 4419 begin 4420 trix[Count - TrRow * sb.si.npos] := BrushTypes[i]; 4421 x := (Count - TrRow * sb.si.npos) * TrPitch; 4422 xSrcBase := -1; 4423 case BrushTypes[i] of 4424 0 .. 8: 4425 begin 4426 xSrc := BrushTypes[i]; 4427 ySrc := 0 4428 end; 4429 9 .. 30: 4430 begin 4431 xSrcBase := 2; 4432 ySrcBase := 2; 4433 xSrc := 0; 4434 ySrc := 2 * integer(BrushTypes[i]) - 15 4435 end; 4436 fRiver: 4437 begin 4438 xSrc := 7; 4439 ySrc := 14 4440 end; 4441 fRoad: 4442 begin 4443 xSrc := 0; 4444 ySrc := 9 4445 end; 4446 fRR: 4447 begin 4448 xSrc := 0; 4449 ySrc := 10 4450 end; 4451 fCanal: 4452 begin 4453 xSrc := 0; 4454 ySrc := 11 4455 end; 4456 fPoll: 4457 begin 4458 xSrc := 6; 4459 ySrc := 12 4460 end; 4461 fDeadLands, fDeadLands or fCobalt, fDeadLands or fUranium, 4462 fDeadLands or fMercury: 4463 begin 4464 xSrcBase := 6; 4465 ySrcBase := 2; 4466 xSrc := 8; 4467 ySrc := 12 + BrushTypes[i] shr 25; 4468 end; 4469 tiIrrigation, tiFarm, tiMine, tiBase: 4470 begin 4471 xSrc := BrushTypes[i] shr 12 - 1; 4472 ySrc := 12 4473 end; 4474 tiFort: 4475 begin 4476 xSrc := 3; 4477 ySrc := 12; 4478 xSrcBase := 7; 4479 ySrcBase := 12 4480 end; 4481 fPrefStartPos: 4482 begin 4483 xSrc := 0; 4484 ySrc := 1 4485 end; 4486 fStartPos: 4487 begin 4488 xSrc := 0; 4489 ySrc := 2 4490 end; 4491 end; 4492 if xSrcBase >= 0 then 4493 Sprite(Panel, HGrTerrain, xTroop + 2 + x, yTroop + 9 - yyt, 4494 xxt * 2, yyt * 3, 1 + xSrcBase * (xxt * 2 + 1), 4495 1 + ySrcBase * (yyt * 3 + 1)); 4496 Sprite(Panel, HGrTerrain, xTroop + 2 + x, yTroop + 9 - yyt, xxt * 2, 4497 yyt * 3, 1 + xSrc * (xxt * 2 + 1), 1 + ySrc * (yyt * 3 + 1)); 4498 if BrushTypes[i] = BrushType then 4499 begin 4500 Frame(Panel.Canvas, xTroop + 2 + x, yTroop + 7 - yyt div 2, 4501 xTroop + 2 * xxt + x, yTroop + 2 * yyt + 11, $000000, $000000); 4502 Frame(Panel.Canvas, xTroop + 1 + x, yTroop + 6 - yyt div 2, 4503 xTroop + 2 * xxt - 1 + x, yTroop + 2 * yyt + 10, 4504 MainTexture.clMark, MainTexture.clMark); 4505 end 4506 end; 4507 inc(Count) 4508 end; 4509 case BrushType of 4510 fDesert, fPrairie, fTundra, fArctic, fSwamp, fHills, fMountains: 4511 s := Phrases.Lookup('TERRAIN', BrushType); 4512 fShore: 4513 s := Format(Phrases.Lookup('TWOTERRAINS'), 4514 [Phrases.Lookup('TERRAIN', fOcean), Phrases.Lookup('TERRAIN', 4515 fShore)]); 4516 fGrass: 4517 s := Format(Phrases.Lookup('TWOTERRAINS'), 4518 [Phrases.Lookup('TERRAIN', fGrass), Phrases.Lookup('TERRAIN', 4519 fGrass + 12)]); 4520 fForest: 4521 s := Format(Phrases.Lookup('TWOTERRAINS'), 4522 [Phrases.Lookup('TERRAIN', fForest), Phrases.Lookup('TERRAIN', 4523 fJungle)]); 4524 fRiver: 4525 s := Phrases.Lookup('RIVER'); 4526 fDeadLands, fDeadLands or fCobalt, fDeadLands or fUranium, 4527 fDeadLands or fMercury: 4528 s := Phrases.Lookup('TERRAIN', 3 * 12 + BrushType shr 25); 4529 fPrefStartPos: 4530 s := Phrases.Lookup('MAP_PREFSTART'); 4531 fStartPos: 4532 s := Phrases.Lookup('MAP_START'); 4533 fPoll: 4534 s := Phrases.Lookup('POLL'); 4535 else // terrain improvements 4536 begin 4537 case BrushType of 4538 fRoad: 4539 i := 1; 4540 fRR: 4541 i := 2; 4542 tiIrrigation: 4543 i := 4; 4544 tiFarm: 4545 i := 5; 4546 tiMine: 4547 i := 7; 4548 fCanal: 4549 i := 8; 4550 tiFort: 4551 i := 10; 4552 tiBase: 4553 i := 12; 4554 end; 4555 s := Phrases.Lookup('JOBRESULT', i); 4556 end 4557 end; 4558 LoweredTextOut(Panel.Canvas, -1, MainTexture, xTroop + 1, 4559 PanelHeight - 19, s); 4560 end 4561 else if TroopLoc >= 0 then 4562 begin 4563 Brush.Style := bsClear; 4564 if UnFocus >= 0 then 4565 with MyUn[UnFocus], MyModel[mix] do 4566 begin { display info about selected unit } 4567 if Job = jCity then 4568 mixShow := -1 // building site 4569 else 4570 mixShow := mix; 4571 with Tribe[me].ModelPicture[mixShow] do 4572 begin 4573 Sprite(Panel, HGr, xMidPanel + 7 + 12, yTroop + 1, 64, 48, 4574 pix mod 10 * 65 + 1, pix div 10 * 49 + 1); 4575 if MyUn[UnFocus].Flags and unFortified <> 0 then 4576 Sprite(Panel, HGrStdUnits, xMidPanel + 7 + 12, yTroop + 1, 4577 xxu * 2, yyu * 2, 1 + 6 * (xxu * 2 + 1), 1); 4578 end; 4579 4580 MakeBlue(Panel, xMidPanel + 7 + 12 + 10, yTroop - 13, 44, 12); 4581 s := MovementToString(MyUn[UnFocus]); 4582 RisedTextOut(Panel.Canvas, xMidPanel + 7 + 12 + 32 - 4583 BiColorTextWidth(Panel.Canvas, s) div 2, yTroop - 16, s); 4584 4585 s := IntToStr(Health) + '%'; 4586 LightGradient(Panel.Canvas, xMidPanel + 7 + 12 + 7, 4587 PanelHeight - 22, (Health + 1) div 2, 4588 (ColorOfHealth(Health) and $FEFEFE shr 2) * 3); 4589 if Health < 100 then 4590 LightGradient(Panel.Canvas, xMidPanel + 7 + 12 + 7 + (Health + 1) 4591 div 2, PanelHeight - 22, 50 - (Health + 1) div 2, $000000); 4592 RisedTextOut(Panel.Canvas, xMidPanel + 7 + 12 + 32 - 4593 BiColorTextWidth(Panel.Canvas, s) div 2, PanelHeight - 23, s); 4594 4595 FrameImage(Panel.Canvas, GrExt[HGrSystem].Data, 4596 xMidPanel + 7 + xUnitText, yTroop + 15, 12, 14, 4597 121 + Exp div ExpCost * 13, 28); 4598 if Job = jCity then 4599 s := Tribe[me].ModelName[-1] 4600 else 4601 s := Tribe[me].ModelName[mix]; 4602 if Home >= 0 then 4603 begin 4604 LoweredTextOut(Panel.Canvas, -1, MainTexture, 4605 xMidPanel + 7 + xUnitText + 18, yTroop + 5, s); 4606 LoweredTextOut(Panel.Canvas, -1, MainTexture, 4607 xMidPanel + 7 + xUnitText + 18, yTroop + 21, 4608 '(' + CityName(MyCity[Home].ID) + ')'); 4609 end 4610 else 4611 LoweredTextOut(Panel.Canvas, -1, MainTexture, 4612 xMidPanel + 7 + xUnitText + 18, yTroop + 13, s); 4613 end; 4614 4615 if (UnFocus >= 0) and (MyUn[UnFocus].Loc <> TroopLoc) then 4616 begin // divide panel 4617 if SmallScreen and not supervising then 4618 x := xTroop - 8 4619 else 4620 x := xTroop - 152; 4621 Pen.Color := MainTexture.clBevelShade; 4622 MoveTo(x - 1, PanelHeight - MidPanelHeight + 2); 4623 LineTo(x - 1, PanelHeight); 4624 Pen.Color := MainTexture.clBevelLight; 4625 MoveTo(x, PanelHeight - MidPanelHeight + 2); 4626 LineTo(x, PanelHeight); 4627 end; 4628 4629 for i := 0 to 23 do 4630 trix[i] := -1; 4631 if MyMap[TroopLoc] and fUnit <> 0 then 4632 begin 4633 if MyMap[TroopLoc] and fOwned <> 0 then 4634 begin 4635 if (TrCnt > 1) or (UnFocus < 0) or (MyUn[UnFocus].Loc <> TroopLoc) 4636 then 4637 begin 4638 LoweredTextOut(Panel.Canvas, -1, MainTexture, xTroop + 10, 4639 PanelHeight - 24, Phrases.Lookup('PRESENT')); 4640 Server(sGetDefender, me, TroopLoc, uixDefender); 4641 Count := 0; 4642 for Prio := true downto false do 4643 for uix := 0 to MyRO.nUn - 1 do 4644 if (uix = uixDefender) = Prio then 4645 begin // display own units 4646 unx := MyUn[uix]; 4647 if unx.Loc = TroopLoc then 4648 begin 4649 if (Count >= TrRow * sb.si.npos) and 4650 (Count < TrRow * (sb.si.npos + 1)) then 4651 begin 4652 trix[Count - TrRow * sb.si.npos] := uix; 4653 MakeUnitInfo(me, unx, UnitInfo); 4654 x := (Count - TrRow * sb.si.npos) * TrPitch; 4655 if uix = UnFocus then 4656 begin 4657 Frame(Panel.Canvas, xTroop + 4 + x, yTroop + 3, 4658 xTroop + 64 + x, yTroop + 47, $000000, $000000); 4659 Frame(Panel.Canvas, xTroop + 3 + x, yTroop + 2, 4660 xTroop + 63 + x, yTroop + 46, MainTexture.clMark, 4661 MainTexture.clMark); 4662 end 4663 else if (unx.Master >= 0) and (unx.Master = UnFocus) 4664 then 4665 begin 4666 CFrame(Panel.Canvas, xTroop + 4 + x, yTroop + 3, 4667 xTroop + 64 + x, yTroop + 47, 8, $000000); 4668 CFrame(Panel.Canvas, xTroop + 3 + x, yTroop + 2, 4669 xTroop + 63 + x, yTroop + 46, 8, 4670 MainTexture.clMark); 4671 end; 4672 NoMap.SetOutput(Panel); 4673 NoMap.PaintUnit(xTroop + 2 + x, yTroop + 1, UnitInfo, 4674 unx.Status); 4675 if (ClientMode < scContact) and 4676 ((unx.Job > jNone) or 4677 (unx.Status and (usStay or usRecover or usGoto) <> 0)) 4678 then 4679 Sprite(Panel, HGrSystem, xTroop + 2 + 60 - 20 + x, 4680 yTroop + 35, 20, 20, 81, 25); 4681 4682 if not supervising then 4683 begin 4684 MakeBlue(Panel, xTroop + 2 + 10 + x, 4685 yTroop - 13, 44, 12); 4686 s := MovementToString(unx); 4687 RisedTextOut(Panel.Canvas, 4688 xTroop + x + 34 - BiColorTextWidth(Panel.Canvas, s) 4689 div 2, yTroop - 16, s); 4690 end 4691 end; 4692 inc(Count) 4693 end; 4694 end; // for uix:=0 to MyRO.nUn-1 4695 assert(Count = TrCnt); 4696 end 4697 end 4698 else 4699 begin 4700 LoweredTextOut(Panel.Canvas, -1, MainTexture, xTroop + 8, 4701 PanelHeight - 24, Phrases.Lookup('PRESENT')); 4702 Server(sGetUnits, me, TroopLoc, Count); 4703 for i := 0 to Count - 1 do 4704 if (i >= TrRow * sb.si.npos) and (i < TrRow * (sb.si.npos + 1)) 4705 then 4706 begin // display enemy units 4707 trix[i - TrRow * sb.si.npos] := i; 4708 x := (i - TrRow * sb.si.npos) * TrPitch; 4709 NoMap.SetOutput(Panel); 4710 NoMap.PaintUnit(xTroop + 2 + x, yTroop + 1, 4711 MyRO.EnemyUn[MyRO.nEnemyUn + i], 0); 4712 end; 4713 end; 4714 end; 4715 if not SmallScreen or supervising then 4716 begin // show terrain and improvements 4717 PaintZoomedTile(Panel, xTerrain - xxt * 2, 110 - yyt * 3, TroopLoc); 4718 if (UnFocus >= 0) and (MyUn[UnFocus].Job <> jNone) then 4719 begin 4720 JobFocus := MyUn[UnFocus].Job; 4721 Server(sGetJobProgress, me, MyUn[UnFocus].Loc, JobProgressData); 4722 MakeBlue(Panel, xTerrain - 72, 148 - 17, 144, 31); 4723 PaintRelativeProgressBar(Panel.Canvas, 3, xTerrain - 68, 148 + 3, 4724 63, JobProgressData[JobFocus].Done, 4725 JobProgressData[JobFocus].NextTurnPlus, 4726 JobProgressData[JobFocus].Required, true, MainTexture); 4727 s := Format('%s/%s', 4728 [ScreenTools.MovementToString(JobProgressData[JobFocus].Done), 4729 ScreenTools.MovementToString(JobProgressData[JobFocus] 4730 .Required)]); 4731 RisedTextOut(Panel.Canvas, xTerrain + 6, 148 - 3, s); 4732 Tile := MyMap[MyUn[UnFocus].Loc]; 4733 if (JobFocus = jRoad) and (Tile and fRiver <> 0) then 4734 JobFocus := nJob + 0 4735 else if (JobFocus = jRR) and (Tile and fRiver <> 0) then 4736 JobFocus := nJob + 1 4737 else if JobFocus = jClear then 4738 begin 4739 if Tile and fTerrain = fForest then 4740 JobFocus := nJob + 2 4741 else if Tile and fTerrain = fDesert then 4742 JobFocus := nJob + 3 4743 else 4744 JobFocus := nJob + 4 4745 end; 4746 s := Phrases.Lookup('JOBRESULT', JobFocus); 4747 RisedTextOut(Panel.Canvas, xTerrain - BiColorTextWidth(Panel.Canvas, 4748 s) div 2, 148 - 19, s); 4749 end; 4750 if MyMap[TroopLoc] and (fTerrain or fSpecial) = fGrass or fSpecial1 4751 then 4752 s := Phrases.Lookup('TERRAIN', fGrass + 12) 4753 else if MyMap[TroopLoc] and fDeadLands <> 0 then 4754 s := Phrases.Lookup('TERRAIN', 3 * 12) 4755 else if (MyMap[TroopLoc] and fTerrain = fForest) and 4756 IsJungle(TroopLoc div G.lx) then 4757 s := Phrases.Lookup('TERRAIN', fJungle) 4758 else 4759 s := Phrases.Lookup('TERRAIN', MyMap[TroopLoc] and fTerrain); 4760 RisedTextOut(Panel.Canvas, xTerrain - BiColorTextWidth(Panel.Canvas, 4761 s) div 2, 99, s); 4762 end; 4763 4764 if TerrainBtn.Visible then 4765 with TerrainBtn do 4766 RFrame(Panel.Canvas, Left - 1, Top - self.ClientHeight + 4767 (PanelHeight - 1), Left + width, Top + height - self.ClientHeight 4768 + PanelHeight, MainTexture.clBevelShade, MainTexture.clBevelLight) 4769 end { if TroopLoc>=0 } 4770 end; 4771 4772 for i := 0 to ControlCount - 1 do 4773 if Controls[i] is TButtonB then 4774 with TButtonB(Controls[i]) do 4775 begin 4776 if Visible then 4777 begin 4778 Dump(Panel, HGrSystem, Left, Top - self.ClientHeight + PanelHeight, 4779 25, 25, 169, 243); 4780 Sprite(Panel, HGrSystem, Left, Top - self.ClientHeight + 4781 PanelHeight, 25, 25, 1 + 26 * ButtonIndex, 337); 4782 RFrame(Panel.Canvas, Left - 1, Top - self.ClientHeight + 4783 (PanelHeight - 1), Left + width, Top + height - self.ClientHeight 4784 + PanelHeight, MainTexture.clBevelShade, 4785 MainTexture.clBevelLight); 4786 end; 4787 end; 4788 4789 if ClientMode <> cEditMap then 4790 begin 4791 for i := 0 to ControlCount - 1 do 4792 if Controls[i] is TButtonC then 4793 with TButtonC(Controls[i]) do 4794 begin 4795 Dump(Panel, HGrSystem, Left, Top - self.ClientHeight + PanelHeight, 4796 12, 12, 169, 178 + 13 * ButtonIndex); 4797 RFrame(Panel.Canvas, Left - 1, Top - self.ClientHeight + 4798 (PanelHeight - 1), Left + width, Top + height - self.ClientHeight 4799 + PanelHeight, MainTexture.clBevelShade, 4800 MainTexture.clBevelLight); 4801 end 4802 end; 4803 EOT.SetBack(Panel.Canvas, EOT.Left, EOT.Top - (ClientHeight - PanelHeight)); 4804 SmartRectInvalidate(0, ClientHeight - PanelHeight, ClientWidth, 4805 ClientHeight); 4806 4807 // topbar 4808 xTreasurySection := ClientWidth div 2 - 172; 4809 xResearchSection := ClientWidth div 2; 4810 // ClientWidth div 2+68 = maximum to right 4811 FillLarge(TopBar.Canvas, 0, 0, ClientWidth, TopBarHeight - 3, 4812 ClientWidth div 2); 4813 with TopBar.Canvas do 4814 begin 4815 Pen.Color := $000000; 4816 MoveTo(0, TopBarHeight - 1); 4817 LineTo(ClientWidth, TopBarHeight - 1); 4818 Pen.Color := MainTexture.clBevelShade; 4819 MoveTo(0, TopBarHeight - 2); 4820 LineTo(ClientWidth, TopBarHeight - 2); 4821 MoveTo(0, TopBarHeight - 3); 4822 LineTo(ClientWidth, TopBarHeight - 3); 4823 Pen.Color := MainTexture.clBevelLight; 4824 Frame(TopBar.Canvas, 40, -1, xTreasurySection - 1, TopBarHeight - 7, 4825 MainTexture.clBevelShade, MainTexture.clBevelLight); 4826 Frame(TopBar.Canvas, xResearchSection + 332, -1, ClientWidth, 4827 TopBarHeight - 7, MainTexture.clBevelShade, MainTexture.clBevelLight); 4828 end; 4829 if GameMode <> cMovie then 4830 ImageOp_BCC(TopBar, Templates, 2, 1, 145, 38, 36, 36, $BFBF20, $4040DF); 4831 if MyRO.nCity > 0 then 4832 begin 4833 TrueMoney := MyRO.Money; 4834 TrueResearch := MyRO.Research; 4835 if supervising then 4836 begin // normalize values from after-turn state 4837 dec(TrueMoney, TaxSum); 4838 if TrueMoney < 0 then 4839 TrueMoney := 0; // shouldn't happen 4840 dec(TrueResearch, ScienceSum); 4841 if TrueResearch < 0 then 4842 TrueResearch := 0; // shouldn't happen 4843 end; 4844 4845 // treasury section 4846 ImageOp_BCC(TopBar, Templates, xTreasurySection + 8, 1, 145, 1, 36, 36, 4847 $40A040, $4030C0); 4848 s := IntToStr(TrueMoney); 4849 LoweredTextOut(TopBar.Canvas, -1, MainTexture, xTreasurySection + 48, 0, 4850 s + '%c'); 4851 if MyRO.Government <> gAnarchy then 4852 begin 4853 ImageOp_BCC(TopBar, Templates, xTreasurySection + 48, 22, 124, 1, 14, 4854 14, $0000C0, $0080C0); 4855 if TaxSum >= 0 then 4856 s := Format(Phrases.Lookup('MONEYGAINPOS'), [TaxSum]) 4857 else 4858 s := Format(Phrases.Lookup('MONEYGAINNEG'), [TaxSum]); 4859 LoweredTextOut(TopBar.Canvas, -1, MainTexture, 4860 xTreasurySection + 48 + 15, 18, s); 4861 end; 4862 4863 // research section 4864 ImageOp_BCC(TopBar, Templates, xResearchSection + 8, 1, 145, 75, 36, 36, 4865 $FF0000, $00FFE0); 4866 if MyData.FarTech <> adNexus then 4867 begin 4868 if MyRO.ResearchTech < 0 then 4869 CostFactor := 2 4870 else if (MyRO.ResearchTech = adMilitary) or 4871 (MyRO.Tech[MyRO.ResearchTech] = tsSeen) then 4872 CostFactor := 1 4873 else if MyRO.ResearchTech in FutureTech then 4874 if MyRO.Government = gFuture then 4875 CostFactor := 4 4876 else 4877 CostFactor := 8 4878 else 4879 CostFactor := 2; 4880 Server(sGetTechCost, me, 0, i); 4881 CostFactor := CostFactor * 22; // length of progress bar 4882 PaintRelativeProgressBar(TopBar.Canvas, 2, xResearchSection + 48 + 1, 4883 26, CostFactor, TrueResearch, ScienceSum, i, true, MainTexture); 4884 4885 if MyRO.ResearchTech < 0 then 4886 s := Phrases.Lookup('SCIENCE') 4887 else if MyRO.ResearchTech = adMilitary then 4888 s := Phrases.Lookup('INITUNIT') 4889 else 4890 begin 4891 s := Phrases.Lookup('ADVANCES', MyRO.ResearchTech); 4892 if MyRO.ResearchTech in FutureTech then 4893 if MyRO.Tech[MyRO.ResearchTech] >= 1 then 4894 s := s + ' ' + IntToStr(MyRO.Tech[MyRO.ResearchTech] + 1) 4895 else 4896 s := s + ' 1'; 4897 end; 4898 if ScienceSum > 0 then 4899 begin 4900 { j:=(i-MyRO.Research-1) div ScienceSum +1; 4901 if j<1 then j:=1; 4902 if j>1 then 4903 s:=Format(Phrases.Lookup('TECHWAIT'),[s,j]); } 4904 LoweredTextOut(TopBar.Canvas, -1, MainTexture, 4905 xResearchSection + 48, 0, s); 4906 end 4907 else 4908 LoweredTextOut(TopBar.Canvas, -1, MainTexture, 4909 xResearchSection + 48, 0, s); 4910 end 4911 else 4912 CostFactor := 0; 4913 if (MyData.FarTech <> adNexus) and (ScienceSum > 0) then 4914 begin 4915 ImageOp_BCC(TopBar, Templates, xResearchSection + 48 + CostFactor + 11, 4916 22, 124, 1, 14, 14, $0000C0, $0080C0); 4917 s := Format(Phrases.Lookup('TECHGAIN'), [ScienceSum]); 4918 LoweredTextOut(TopBar.Canvas, -1, MainTexture, xResearchSection + 48 + 4919 CostFactor + 26, 18, s); 4920 end 4921 end; 4922 if ClientMode <> cEditMap then 4923 begin 4924 TopBar.Canvas.Font.Assign(UniFont[ftCaption]); 4925 s := TurnToString(MyRO.Turn); 4926 RisedTextOut(TopBar.Canvas, 4927 40 + (xTreasurySection - 40 - BiColorTextWidth(TopBar.Canvas, s)) 4928 div 2, 6, s); 4929 TopBar.Canvas.Font.Assign(UniFont[ftNormal]); 4930 end; 4931 RectInvalidate(0, 0, ClientWidth, TopBarHeight); 4932 end; { PanelPaint } 4933 4934 procedure TMainScreen.FocusOnLoc(Loc: integer; Options: integer = 0); 4935 var 4936 dx: integer; 4937 Outside, Changed: boolean; 4938 begin 4939 dx := G.lx + 1 - (xw - Loc + G.lx * 1024 + 1) mod G.lx; 4940 Outside := (dx >= (MapWidth + 1) div (xxt * 2) - 2) or (ywmax > 0) and 4941 ((yw > 0) and (Loc div G.lx <= yw + 1) or (yw < ywmax) and 4942 (Loc div G.lx >= yw + (MapHeight - 1) div yyt - 2)); 4943 Changed := true; 4944 if Outside then 4945 begin 4946 Centre(Loc); 4947 PaintAllMaps 4948 end 4949 else if not MapValid then 4950 PaintAllMaps 4951 else 4952 Changed := false; 4953 if Options and flRepaintPanel <> 0 then 4954 PanelPaint; 4955 if Changed and (Options and flImmUpdate <> 0) then 4956 Update; 4957 end; 4958 4959 procedure TMainScreen.NextUnit(NearLoc: integer; AutoTurn: boolean); 4960 var 4961 Dist, TestDist: single; 4962 i, uix, NewFocus: integer; 4963 GotoOnly: boolean; 4964 begin 4965 if ClientMode >= scContact then 4966 exit; 4967 DestinationMarkON := false; 4968 PaintDestination; 4969 for GotoOnly := GoOnPhase downto false do 4970 begin 4971 NewFocus := -1; 4972 for i := 1 to MyRO.nUn do 4973 begin 4974 uix := (UnFocus + i) mod MyRO.nUn; 4975 if (MyUn[uix].Loc >= 0) and (MyUn[uix].Job = jNone) and 4976 (MyUn[uix].Status and (usStay or usRecover or usWaiting) = usWaiting) 4977 and (not GotoOnly or (MyUn[uix].Status and usGoto <> 0)) then 4978 if NearLoc < 0 then 4979 begin 4980 NewFocus := uix; 4981 Break 4982 end 4983 else 4984 begin 4985 TestDist := Distance(NearLoc, MyUn[uix].Loc); 4986 if (NewFocus < 0) or (TestDist < Dist) then 4987 begin 4988 NewFocus := uix; 4989 Dist := TestDist 4990 end 4991 end 4992 end; 4993 if GotoOnly then 4994 if NewFocus < 0 then 4995 GoOnPhase := false 4996 else 4997 Break; 4998 end; 4999 if NewFocus >= 0 then 5000 begin 5001 SetUnFocus(NewFocus); 5002 SetTroopLoc(MyUn[NewFocus].Loc); 5003 FocusOnLoc(TroopLoc, flRepaintPanel) 5004 end 5005 else if AutoTurn and not mWaitTurn.Checked then 5006 begin 5007 TurnComplete := true; 5008 SetUnFocus(-1); 5009 SetTroopLoc(-1); 5010 PostMessage(Handle, WM_EOT, 0, 0) 5011 end 5012 else 5013 begin 5014 if { (UnFocus>=0) and } not TurnComplete and EOT.Visible then 5015 Play('TURNEND'); 5016 TurnComplete := true; 5017 SetUnFocus(-1); 5018 SetTroopLoc(-1); 5019 PanelPaint; 5020 end; 5021 end; { NextUnit } 5022 5023 procedure TMainScreen.Scroll(dx, dy: integer); 5024 begin 5025 xw := (xw + G.lx + dx) mod G.lx; 5026 if ywmax > 0 then 5027 begin 5028 yw := yw + 2 * dy; 5029 if yw < 0 then 5030 yw := 0 5031 else if yw > ywmax then 5032 yw := ywmax; 5033 end; 5034 MainOffscreenPaint; 5035 xwMini := xw; 5036 ywMini := yw; 5037 MiniPaint; 5038 CopyMiniToPanel; 5039 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini + 2, 5040 xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini + 5041 2 + G.ly); 5042 Update; 5043 end; 5044 5045 procedure TMainScreen.Timer1Timer(Sender: TObject); 5046 var 5047 dx, dy, speed: integer; 5048 begin 5049 if idle and (me >= 0) and (GameMode <> cMovie) then 5050 if (fsModal in Screen.ActiveForm.FormState) or 5051 (Screen.ActiveForm is TBufferedDrawDlg) and 5052 (TBufferedDrawDlg(Screen.ActiveForm).WindowMode <> wmPersistent) then 5053 begin 5054 BlinkTime := BlinkOnTime + BlinkOffTime - 1; 5055 if not BlinkON then 5056 begin 5057 BlinkON := true; 5058 if UnFocus >= 0 then 5059 PaintLocTemp(MyUn[UnFocus].Loc) 5060 else if TurnComplete and not supervising then 5061 EOT.SetButtonIndexFast(eotBlinkOn) 5062 end 5063 end 5064 else 5065 begin 5066 if Application.Active and not mScrollOff.Checked then 5067 begin 5068 if mScrollFast.Checked then 5069 speed := 2 5070 else 5071 speed := 1; 5072 dx := 0; 5073 dy := 0; 5074 if Mouse.CursorPos.y < Screen.height - PanelHeight then 5075 if Mouse.CursorPos.x = 0 then 5076 dx := -speed // scroll left 5077 else if Mouse.CursorPos.x = Screen.width - 1 then 5078 dx := speed; // scroll right 5079 if Mouse.CursorPos.y = 0 then 5080 dy := -speed // scroll up 5081 else if (Mouse.CursorPos.y = Screen.height - 1) and 5082 (Mouse.CursorPos.x >= TerrainBtn.Left + TerrainBtn.width) and 5083 (Mouse.CursorPos.x < xRightPanel + 10 - 8) then 5084 dy := speed; // scroll down 5085 if (dx <> 0) or (dy <> 0) then 5086 begin 5087 if (Screen.ActiveForm <> MainScreen) and 5088 (@Screen.ActiveForm.OnDeactivate <> nil) then 5089 Screen.ActiveForm.OnDeactivate(nil); 5090 Scroll(dx, dy); 5091 end 5092 end; 5093 5094 BlinkTime := (BlinkTime + 1) mod (BlinkOnTime + BlinkOffTime); 5095 BlinkON := BlinkTime >= BlinkOffTime; 5096 DestinationMarkON := true; 5097 if UnFocus >= 0 then 5098 begin 5099 if (BlinkTime = 0) or (BlinkTime = BlinkOffTime) then 5100 begin 5101 PaintLocTemp(MyUn[UnFocus].Loc, pltsBlink); 5102 PaintDestination; 5103 // if MoveHintToLoc>=0 then 5104 // ShowMoveHint(MoveHintToLoc, true); 1703 5105 end 1704 5106 end 1705 else 1706 begin 1707 s:=Tribe[me].TPhrase('AGE'+char(48+Age)); 1708 MessgText:=Format(s,[TurnToString(MyRO.Turn)]); 1709 end; 1710 IconKind:=mikAge; 1711 IconIndex:=Age; 1712 {if age=0 then} Kind:=mkOK 1713 {else begin Kind:=mkOkHelp; HelpKind:=hkAdv; HelpNo:=AgePreq[age]; end}; 1714 CenterTo:=NewAgeCenterTo; 1715 OpenSound:='AGE_'+char(48+Age); 1716 ShowModal; 1717 MyData.ToldAge:=Age; 1718 if Age>0 then 1719 MyData.ToldTech[AgePreq[Age]]:=MyRO.Tech[AgePreq[Age]]; 1720 end; 1721 1722 if MyData.ToldAlive<>MyRO.Alive then 1723 begin 1724 for p1:=0 to nPl-1 do 1725 if (MyData.ToldAlive-MyRO.Alive) and (1 shl p1)<>0 then 1726 with MessgExDlg do 1727 begin 1728 OpenSound:='MSG_EXTINCT'; 1729 s:=Tribe[p1].TPhrase('EXTINCT'); 1730 MessgText:=Format(s,[TurnToString(MyRO.Turn)]); 1731 if MyRO.Alive=1 shl me then 1732 MessgText:=MessgText+Phrases.Lookup('EXTINCTALL'); 1733 Kind:=mkOK; 1734 IconKind:=mikImp; 1735 IconIndex:=21; 1736 ShowModal; 5107 else if TurnComplete and not supervising then 5108 begin 5109 if BlinkTime = 0 then 5110 EOT.SetButtonIndexFast(eotBlinkOff) 5111 else if BlinkTime = BlinkOffTime then 5112 EOT.SetButtonIndexFast(eotBlinkOn) 5113 end 5114 end 5115 end; 5116 5117 procedure TMainScreen.Centre(Loc: integer); 5118 begin 5119 if FastScrolling and MapValid then 5120 Update; 5121 // necessary because ScrollDC for form canvas is called after 5122 xw := (Loc mod G.lx - (MapWidth - xxt * 2 * ((Loc div G.lx) and 1)) 5123 div (xxt * 4) + G.lx) mod G.lx; 5124 if ywmax <= 0 then 5125 yw := ywcenter 5126 else 5127 begin 5128 yw := (Loc div G.lx - MapHeight div (yyt * 2) + 1) and not 1; 5129 if yw < 0 then 5130 yw := 0 5131 else if yw > ywmax then 5132 yw := ywmax; 5133 end 5134 end; 5135 5136 function TMainScreen.ZoomToCity(Loc: integer; 5137 NextUnitOnClose: boolean = false; ShowEvent: integer = 0): boolean; 5138 begin 5139 result := MyMap[Loc] and (fOwned or fSpiedOut) <> 0; 5140 if result then 5141 with CityDlg do 5142 begin 5143 if ClientMode >= scContact then 5144 begin 5145 CloseAction := None; 5146 RestoreUnFocus := -1; 5147 end 5148 else if NextUnitOnClose then 5149 begin 5150 CloseAction := StepFocus; 5151 RestoreUnFocus := -1; 5152 end 5153 else if not Visible then 5154 begin 5155 CloseAction := RestoreFocus; 5156 RestoreUnFocus := UnFocus; 5157 end; 5158 SetUnFocus(-1); 5159 SetTroopLoc(Loc); 5160 MarkCityLoc := Loc; 5161 PanelPaint; 5162 ShowNewContent(wmPersistent, Loc, ShowEvent); 5163 end 5164 end; 5165 5166 function TMainScreen.LocationOfScreenPixel(x, y: integer): integer; 5167 var 5168 qx, qy: integer; 5169 begin 5170 qx := (x * (yyt * 2) + y * (xxt * 2) + xxt * yyt * 2) 5171 div (xxt * yyt * 4) - 1; 5172 qy := (y * (xxt * 2) - x * (yyt * 2) - xxt * yyt * 2 + 4000 * xxt * yyt) 5173 div (xxt * yyt * 4) - 999; 5174 result := (xw + (qx - qy + 2048) div 2 - 1024 + G.lx) mod G.lx + G.lx * 5175 (yw + qx + qy); 5176 end; 5177 5178 procedure TMainScreen.MapBoxMouseDown(Sender: TObject; Button: TMouseButton; 5179 Shift: TShiftState; x, y: integer); 5180 var 5181 i, uix, emix, p1, dx, dy, MouseLoc: integer; 5182 EditTileData: TEditTileData; 5183 m, m2: TMenuItem; 5184 MoveAdviceData: TMoveAdviceData; 5185 DoCenter: boolean; 5186 begin 5187 if GameMode = cMovie then 5188 exit; 5189 5190 if CityDlg.Visible then 5191 CityDlg.Close; 5192 if UnitStatDlg.Visible then 5193 UnitStatDlg.Close; 5194 MouseLoc := LocationOfScreenPixel(x, y); 5195 if (MouseLoc < 0) or (MouseLoc >= G.lx * G.ly) then 5196 exit; 5197 if (Button = mbLeft) and not(ssShift in Shift) then 5198 begin 5199 DoCenter := true; 5200 if ClientMode = cEditMap then 5201 begin 5202 DoCenter := false; 5203 EditTileData.Loc := MouseLoc; 5204 if ssCtrl in Shift then // toggle special resource 5205 case MyMap[MouseLoc] and fTerrain of 5206 fOcean: 5207 EditTileData.NewTile := MyMap[MouseLoc]; 5208 fGrass, fArctic: 5209 EditTileData.NewTile := MyMap[MouseLoc] and not fSpecial or 5210 ((MyMap[MouseLoc] shr 5 and 3 + 1) mod 2 shl 5); 5211 else 5212 EditTileData.NewTile := MyMap[MouseLoc] and not fSpecial or 5213 ((MyMap[MouseLoc] shr 5 and 3 + 1) mod 3 shl 5) 5214 end 5215 else if BrushType <= fTerrain then 5216 EditTileData.NewTile := MyMap[MouseLoc] and not fTerrain or 5217 fSpecial or BrushType 5218 else if BrushType and fDeadLands <> 0 then 5219 if MyMap[MouseLoc] and (fDeadLands or fModern) = BrushType and 5220 (fDeadLands or fModern) then 5221 EditTileData.NewTile := MyMap[MouseLoc] and 5222 not(fDeadLands or fModern) 5223 else 5224 EditTileData.NewTile := MyMap[MouseLoc] and 5225 not(fDeadLands or fModern) or BrushType 5226 else if BrushType and fTerImp <> 0 then 5227 if MyMap[MouseLoc] and fTerImp = BrushType then 5228 EditTileData.NewTile := MyMap[MouseLoc] and not fTerImp 5229 else 5230 EditTileData.NewTile := MyMap[MouseLoc] and not fTerImp or BrushType 5231 else if BrushType and (fPrefStartPos or fStartPos) <> 0 then 5232 if MyMap[MouseLoc] and (fPrefStartPos or fStartPos) = BrushType and 5233 (fPrefStartPos or fStartPos) then 5234 EditTileData.NewTile := MyMap[MouseLoc] and 5235 not(fPrefStartPos or fStartPos) 5236 else 5237 EditTileData.NewTile := MyMap[MouseLoc] and 5238 not(fPrefStartPos or fStartPos) or BrushType 5239 else 5240 EditTileData.NewTile := MyMap[MouseLoc] xor BrushType; 5241 Server(sEditTile, me, 0, EditTileData); 5242 Edited := true; 5243 BrushLoc := MouseLoc; 5244 PaintLoc(MouseLoc, 2); 5245 MiniPaint; 5246 BitBlt(Panel.Canvas.Handle, xMini + 2, yMini + 2, G.lx * 2, G.ly, 5247 Mini.Canvas.Handle, 0, 0, SRCCOPY); 5248 if ywmax <= 0 then 5249 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (2 * xxt), 5250 yMini + 2, xMini + 1 + G.lx + MapWidth div (2 * xxt), 5251 yMini + 2 + G.ly - 1, MainTexture.clMark, MainTexture.clMark) 5252 else 5253 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (2 * xxt), 5254 yMini + 2 + yw, xMini + 2 + G.lx + MapWidth div (2 * xxt) - 1, 5255 yMini + 2 + yw + MapHeight div yyt - 2, MainTexture.clMark, 5256 MainTexture.clMark); 5257 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini + 5258 2, xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini 5259 + 2 + G.ly) 5260 end 5261 else if MyMap[MouseLoc] and fCity <> 0 then { city clicked } 5262 begin 5263 if MyMap[MouseLoc] and (fOwned or fSpiedOut) <> 0 then 5264 begin 5265 ZoomToCity(MouseLoc); 5266 DoCenter := false; 5267 end 5268 else 5269 begin 5270 UnitStatDlg.ShowNewContent_EnemyCity(wmPersistent, MouseLoc); 5271 DoCenter := false; 5272 end 5273 end 5274 else if MyMap[MouseLoc] and fUnit <> 0 then { unit clicked } 5275 if MyMap[MouseLoc] and fOwned <> 0 then 5276 begin 5277 DoCenter := false; 5278 if not supervising and (ClientMode < scContact) then 5279 begin // not in negotiation mode 5280 if (UnFocus >= 0) and (MyUn[UnFocus].Loc = MouseLoc) then 5281 begin // rotate 5282 uix := (UnFocus + 1) mod MyRO.nUn; 5283 i := MyRO.nUn - 1; 5284 while i > 0 do 5285 begin 5286 if (MyUn[uix].Loc = MouseLoc) and (MyUn[uix].Job = jNone) and 5287 (MyUn[uix].Status and (usStay or usRecover or usEnhance or 5288 usWaiting) = usWaiting) then 5289 Break; 5290 dec(i); 5291 uix := (uix + 1) mod MyRO.nUn; 5292 end; 5293 if i = 0 then 5294 uix := UnFocus 5295 end 5296 else 5297 Server(sGetDefender, me, MouseLoc, uix); 5298 if uix <> UnFocus then 5299 SetUnFocus(uix); 5300 TurnComplete := false; 5301 EOT.ButtonIndex := eotGray; 5302 end; 5303 SetTroopLoc(MouseLoc); 5304 PanelPaint; 5305 end // own unit 5306 else if (MyMap[MouseLoc] and fSpiedOut <> 0) and not(ssCtrl in Shift) 5307 then 5308 begin 5309 DoCenter := false; 5310 SetTroopLoc(MouseLoc); 5311 PanelPaint; 5312 end 5313 else 5314 begin 5315 DoCenter := false; 5316 UnitStatDlg.ShowNewContent_EnemyLoc(wmPersistent, MouseLoc); 5317 end; 5318 if DoCenter then 5319 begin 5320 Centre(MouseLoc); 5321 PaintAllMaps 5322 end 5323 end 5324 else if (ClientMode <> cEditMap) and (Button = mbRight) and 5325 not(ssShift in Shift) then 5326 begin 5327 if supervising then 5328 begin 5329 EditLoc := MouseLoc; 5330 Server(sGetModels, me, 0, nil^); 5331 EmptyMenu(mCreateUnit); 5332 for p1 := 0 to nPl - 1 do 5333 if 1 shl p1 and MyRO.Alive <> 0 then 5334 begin 5335 m := TMenuItem.Create(mCreateUnit); 5336 m.Caption := Tribe[p1].TPhrase('SHORTNAME'); 5337 for emix := MyRO.nEnemyModel - 1 downto 0 do 5338 if (MyRO.EnemyModel[emix].Owner = p1) and 5339 (Server(sCreateUnit - sExecute + p1 shl 4, me, 5340 MyRO.EnemyModel[emix].mix, MouseLoc) >= rExecuted) then 5341 begin 5342 if Tribe[p1].ModelPicture[MyRO.EnemyModel[emix].mix].HGr = 0 5343 then 5344 InitEnemyModel(emix); 5345 m2 := TMenuItem.Create(m); 5346 m2.Caption := Tribe[p1].ModelName[MyRO.EnemyModel[emix].mix]; 5347 m2.Tag := p1 shl 16 + MyRO.EnemyModel[emix].mix; 5348 m2.OnClick := CreateUnitClick; 5349 m.Add(m2); 5350 end; 5351 m.Visible := m.Count > 0; 5352 mCreateUnit.Add(m); 5353 end; 5354 if FullScreen then 5355 EditPopup.Popup(Left + x, Top + y) 5356 else 5357 EditPopup.Popup(Left + x + 4, 5358 Top + y + GetSystemMetrics(SM_CYCAPTION) + 4); 5359 end 5360 else if (UnFocus >= 0) and (MyUn[UnFocus].Loc <> MouseLoc) then 5361 with MyUn[UnFocus] do 5362 begin 5363 dx := ((MouseLoc mod G.lx * 2 + MouseLoc div G.lx and 1) - 5364 (Loc mod G.lx * 2 + Loc div G.lx and 1) + 3 * G.lx) 5365 mod (2 * G.lx) - G.lx; 5366 dy := MouseLoc div G.lx - Loc div G.lx; 5367 if abs(dx) + abs(dy) < 3 then 5368 begin 5369 DestinationMarkON := false; 5370 PaintDestination; 5371 Status := Status and 5372 ($FFFF - usStay - usRecover - usGoto - usEnhance) or usWaiting; 5373 MoveUnit(dx, dy, muAutoNext) { simple move } 5374 end 5375 else if GetMoveAdvice(UnFocus, MouseLoc, MoveAdviceData) >= rExecuted 5376 then 5377 begin 5378 if MyMap[MouseLoc] and (fUnit or fOwned) = fUnit then 5379 begin // check for suicide mission before movement 5380 with MyUn[UnFocus], BattleDlg.Forecast do 5381 begin 5382 pAtt := me; 5383 mixAtt := mix; 5384 HealthAtt := Health; 5385 ExpAtt := Exp; 5386 FlagsAtt := Flags; 5387 end; 5388 BattleDlg.Forecast.Movement := MyUn[UnFocus].Movement; 5389 if (Server(sGetBattleForecastEx, me, MouseLoc, BattleDlg.Forecast) 5390 >= rExecuted) and (BattleDlg.Forecast.EndHealthAtt <= 0) then 5391 begin 5392 BattleDlg.uix := UnFocus; 5393 BattleDlg.ToLoc := MouseLoc; 5394 BattleDlg.IsSuicideQuery := true; 5395 BattleDlg.ShowModal; 5396 if BattleDlg.ModalResult <> mrOK then 5397 exit; 5398 end 1737 5399 end; 1738 if (ClientMode<>cMovieTurn) and not supervising then 1739 DiaDlg.ShowNewContent_Charts(wmModal); 1740 end; 1741 1742 // tell changes of own credibility 1743 if not supervising then 1744 begin 1745 if RoughCredibility(MyRO.Credibility) 1746 <>RoughCredibility(MyData.ToldOwnCredibility) then 1747 begin 1748 if RoughCredibility(MyRO.Credibility) 1749 >RoughCredibility(MyData.ToldOwnCredibility) then 1750 s:=Phrases.Lookup('CREDUP') 1751 else s:=Phrases.Lookup('CREDDOWN'); 1752 TribeMessage(me, Format(s,[Phrases.Lookup('CREDIBILITY', 1753 RoughCredibility(MyRO.Credibility))]), ''); 1754 end; 1755 MyData.ToldOwnCredibility:=MyRO.Credibility; 1756 end; 1757 1758 for i:=0 to 27 do 1759 begin 1760 OwnWonder:=false; 1761 for cix:=0 to MyRO.nCity-1 do 1762 if (MyCity[cix].Loc>=0) and (MyCity[cix].ID=MyRO.Wonder[i].CityID) then 1763 OwnWonder:=true; 1764 if MyRO.Wonder[i].CityID<>MyData.ToldWonders[i].CityID then 1765 begin 1766 if MyRO.Wonder[i].CityID=-2 then with MessgExDlg do 1767 begin {tell about destroyed wonders} 1768 OpenSound:='WONDER_DESTROYED'; 1769 MessgText:=Format(Phrases.Lookup('WONDERDEST'), 1770 [Phrases.Lookup('IMPROVEMENTS',i)]); 1771 Kind:=mkOkHelp; 1772 HelpKind:=hkImp; 1773 HelpNo:=i; 1774 IconKind:=mikImp; 1775 IconIndex:=i; 1776 ShowModal; 1777 end 1778 else 1779 begin 1780 if i=woManhattan then 1781 if MyRO.Wonder[i].EffectiveOwner>me then 1782 MyData.ColdWarStart:=MyRO.Turn-1 1783 else MyData.ColdWarStart:=MyRO.Turn; 1784 if not OwnWonder then with MessgExDlg do 1785 begin {tell about newly built wonders} 1786 if i=woManhattan then 1787 begin 1788 OpenSound:='MSG_COLDWAR'; 1789 s:=Tribe[MyRO.Wonder[i].EffectiveOwner].TPhrase('COLDWAR') 1790 end 1791 else if MyRO.Wonder[i].EffectiveOwner>=0 then 1792 begin 1793 OpenSound:='WONDER_BUILT'; 1794 s:=Tribe[MyRO.Wonder[i].EffectiveOwner].TPhrase('WONDERBUILT') 1795 end 1796 else 1797 begin 1798 OpenSound:='MSG_DEFAULT'; 1799 s:=Phrases.Lookup('WONDERBUILTEXP'); // already expired when built 1800 end; 1801 MessgText:=Format(s, [Phrases.Lookup('IMPROVEMENTS',i), 1802 CityName(MyRO.Wonder[i].CityID)]); 1803 Kind:=mkOkHelp; 1804 HelpKind:=hkImp; 1805 HelpNo:=i; 1806 IconKind:=mikImp; 1807 IconIndex:=i; 1808 ShowModal; 1809 end 5400 DestinationMarkON := false; 5401 PaintDestination; 5402 Status := Status and not(usStay or usRecover or usEnhance) or 5403 usWaiting; 5404 MoveToLoc(MouseLoc, false); { goto } 1810 5405 end 1811 5406 end 1812 else if (MyRO.Wonder[i].EffectiveOwner<>MyData.ToldWonders[i].EffectiveOwner) 1813 and (MyRO.Wonder[i].CityID>-2) then 1814 if MyRO.Wonder[i].EffectiveOwner<0 then 5407 end 5408 else if (Button = mbMiddle) and (UnFocus >= 0) and 5409 (MyModel[MyUn[UnFocus].mix].Kind in [mkSettler, mkSlaves]) then 5410 begin 5411 DestinationMarkON := false; 5412 PaintDestination; 5413 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 5414 ($FFFF - usStay - usRecover - usGoto) or usEnhance; 5415 uix := UnFocus; 5416 if MouseLoc <> MyUn[uix].Loc then 5417 MoveToLoc(MouseLoc, true); { goto } 5418 if (UnFocus = uix) and (MyUn[uix].Loc = MouseLoc) then 5419 MenuClick(mEnhance) 5420 end 5421 else if (Button = mbLeft) and (ssShift in Shift) and 5422 (MyMap[MouseLoc] and fTerrain <> fUNKNOWN) then 5423 HelpOnTerrain(MouseLoc, wmPersistent) 5424 else if (ClientMode <= cContinue) and (Button = mbRight) and 5425 (ssShift in Shift) and (UnFocus >= 0) and 5426 (MyMap[MouseLoc] and (fUnit or fOwned) = fUnit) then 5427 begin // battle forecast 5428 with MyUn[UnFocus], BattleDlg.Forecast do 5429 begin 5430 pAtt := me; 5431 mixAtt := mix; 5432 HealthAtt := Health; 5433 ExpAtt := Exp; 5434 FlagsAtt := Flags; 5435 end; 5436 BattleDlg.Forecast.Movement := MyUn[UnFocus].Movement; 5437 if Server(sGetBattleForecastEx, me, MouseLoc, BattleDlg.Forecast) >= rExecuted 5438 then 5439 begin 5440 BattleDlg.uix := UnFocus; 5441 BattleDlg.ToLoc := MouseLoc; 5442 BattleDlg.Left := x - BattleDlg.width div 2; 5443 if BattleDlg.Left < 0 then 5444 BattleDlg.Left := 0 5445 else if BattleDlg.Left + BattleDlg.width > Screen.width then 5446 BattleDlg.Left := Screen.width - BattleDlg.width; 5447 BattleDlg.Top := y - BattleDlg.height div 2; 5448 if BattleDlg.Top < 0 then 5449 BattleDlg.Top := 0 5450 else if BattleDlg.Top + BattleDlg.height > Screen.height then 5451 BattleDlg.Top := Screen.height - BattleDlg.height; 5452 BattleDlg.IsSuicideQuery := false; 5453 BattleDlg.Show; 5454 end 5455 end 5456 end; 5457 5458 function TMainScreen.MoveUnit(dx, dy: integer; Options: integer): integer; 5459 // move focused unit to adjacent tile 5460 var 5461 i, cix, uix, euix, FromLoc, ToLoc, DirCode, UnFocus0, Defender, Mission, p1, 5462 NewTiles, cixChanged: integer; 5463 OldToTile: Cardinal; 5464 CityCaptured, IsAttack, OldUnrest, NewUnrest, NeedEcoUpdate, 5465 NeedRepaintPanel, ToTransport, ToShip: boolean; 5466 PlaneReturnData: TPlaneReturnData; 5467 QueryItem: string; 5468 begin 5469 result := eInvalid; 5470 UnFocus0 := UnFocus; 5471 FromLoc := MyUn[UnFocus].Loc; 5472 ToLoc := dLoc(FromLoc, dx, dy); 5473 if (ToLoc < 0) or (ToLoc >= G.lx * G.ly) then 5474 begin 5475 result := eInvalid; 5476 exit; 5477 end; 5478 if MyMap[ToLoc] and fStealthUnit <> 0 then 5479 begin 5480 SoundMessage(Phrases.Lookup('ATTACKSTEALTH'), ''); 5481 exit; 5482 end; 5483 if MyMap[ToLoc] and fHiddenUnit <> 0 then 5484 begin 5485 SoundMessage(Phrases.Lookup('ATTACKSUB'), ''); 5486 exit; 5487 end; 5488 5489 if MyMap[ToLoc] and (fUnit or fOwned) = fUnit then 5490 begin // attack -- search enemy unit 5491 if (MyModel[MyUn[UnFocus].mix].Attack = 0) and 5492 not((MyModel[MyUn[UnFocus].mix].Cap[mcBombs] > 0) and 5493 (MyUn[UnFocus].Flags and unBombsLoaded <> 0)) then 5494 begin 5495 SoundMessage(Phrases.Lookup('NOATTACKER'), ''); 5496 exit; 5497 end; 5498 euix := MyRO.nEnemyUn - 1; 5499 while (euix >= 0) and (MyRO.EnemyUn[euix].Loc <> ToLoc) do 5500 dec(euix); 5501 end; 5502 5503 DirCode := dx and 7 shl 4 + dy and 7 shl 7; 5504 result := Server(sMoveUnit - sExecute + DirCode, me, UnFocus, nil^); 5505 if (result < rExecuted) and (MyUn[UnFocus].Job > jNone) then 5506 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 5507 if (result < rExecuted) and (result <> eNoTime_Move) then 5508 begin 5509 case result of 5510 eNoTime_Load: 5511 if MyModel[MyUn[UnFocus].mix].Domain = dAir then 5512 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'), 'NOMOVE_TIME') 5513 else 5514 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 5515 [MovementToString(MyModel[MyUn[UnFocus].mix].speed)]), 5516 'NOMOVE_TIME'); 5517 eNoTime_Bombard: 5518 SoundMessage(Phrases.Lookup('NOTIMEBOMBARD'), 'NOMOVE_TIME'); 5519 eNoTime_Expel: 5520 SoundMessage(Phrases.Lookup('NOTIMEEXPEL'), 'NOMOVE_TIME'); 5521 eNoRoad: 5522 SoundMessage(Phrases.Lookup('NOROAD'), 'NOMOVE_DEFAULT'); 5523 eNoNav: 5524 SoundMessage(Phrases.Lookup('NONAV'), 'NOMOVE_DEFAULT'); 5525 eNoCapturer: 5526 SoundMessage(Phrases.Lookup('NOCAPTURER'), 'NOMOVE_DEFAULT'); 5527 eNoBombarder: 5528 SoundMessage(Phrases.Lookup('NOBOMBARDER'), 'NOMOVE_DEFAULT'); 5529 eZOC: 5530 ContextMessage(Phrases.Lookup('ZOC'), 'NOMOVE_ZOC', hkText, 5531 HelpDlg.TextIndex('MOVEMENT')); 5532 eTreaty: 5533 if MyMap[ToLoc] and (fUnit or fOwned) <> fUnit 5534 then { no enemy unit -- move } 5535 SoundMessage(Tribe[MyRO.Territory[ToLoc]].TPhrase('PEACE_NOMOVE'), 5536 'NOMOVE_TREATY') 5537 else 5538 SoundMessage(Tribe[MyRO.EnemyUn[euix].Owner] 5539 .TPhrase('PEACE_NOATTACK'), 'NOMOVE_TREATY'); 5540 eDomainMismatch: 1815 5541 begin 1816 if i<>woMir then with MessgExDlg do 1817 begin {tell about expired wonders} 1818 OpenSound:='WONDER_EXPIRED'; 1819 MessgText:=Format(Phrases.Lookup('WONDEREXP'), 1820 [Phrases.Lookup('IMPROVEMENTS',i), 1821 CityName(MyRO.Wonder[i].CityID)]); 1822 Kind:=mkOkHelp; 1823 HelpKind:=hkImp; 1824 HelpNo:=i; 1825 IconKind:=mikImp; 1826 IconIndex:=i; 1827 ShowModal; 5542 if (MyModel[MyUn[UnFocus].mix].Domain < dSea) and 5543 (MyMap[ToLoc] and (fUnit or fOwned) = fUnit or fOwned) then 5544 begin // false load attempt 5545 ToShip := false; 5546 ToTransport := false; 5547 for uix := 0 to MyRO.nUn - 1 do 5548 if (MyUn[uix].Loc = ToLoc) and 5549 (MyModel[MyUn[uix].mix].Domain = dSea) then 5550 begin 5551 ToShip := true; 5552 if MyModel[MyUn[uix].mix].Cap[mcSeaTrans] > 0 then 5553 ToTransport := true; 5554 end; 5555 if ToTransport then 5556 SoundMessage(Phrases.Lookup('FULLTRANSPORT'), 'NOMOVE_DEFAULT') 5557 else if ToShip then 5558 SoundMessage(Phrases.Lookup('NOTRANSPORT'), 'NOMOVE_DEFAULT') 5559 else 5560 Play('NOMOVE_DOMAIN'); 1828 5561 end 5562 else 5563 Play('NOMOVE_DOMAIN'); 1829 5564 end 1830 else if (MyData.ToldWonders[i].EffectiveOwner>=0) and not OwnWonder then 1831 with MessgExDlg do 1832 begin {tell about capture of wonders} 1833 OpenSound:='WONDER_CAPTURED'; 1834 s:=Tribe[MyRO.Wonder[i].EffectiveOwner].TPhrase('WONDERCAPT'); 1835 MessgText:=Format(s, [Phrases.Lookup('IMPROVEMENTS',i), 1836 CityName(MyRO.Wonder[i].CityID)]); 1837 Kind:=mkOkHelp; 1838 HelpKind:=hkImp; 1839 HelpNo:=i; 1840 IconKind:=mikImp; 1841 IconIndex:=i; 1842 ShowModal; 5565 else 5566 Play('NOMOVE_DEFAULT'); 5567 end; 5568 exit; 5569 end; 5570 5571 if ((result = eWon) or (result = eLost) or (result = eBloody)) and 5572 (MyUn[UnFocus].Movement < 100) and 5573 (MyModel[MyUn[UnFocus].mix].Cap[mcWill] = 0) then 5574 begin 5575 if SimpleQuery(mkYesNo, Format(Phrases.Lookup('FASTATTACK'), 5576 [MyUn[UnFocus].Movement]), 'NOMOVE_TIME') <> mrOK then 5577 begin 5578 result := eInvalid; 5579 exit; 5580 end; 5581 Update; // remove message box from screen 5582 end; 5583 5584 OldUnrest := false; 5585 NewUnrest := false; 5586 if (result >= rExecuted) and (result and rUnitRemoved = 0) and 5587 (MyMap[ToLoc] and (fUnit or fOwned) <> fUnit) then 5588 begin 5589 OldUnrest := UnrestAtLoc(UnFocus, FromLoc); 5590 NewUnrest := UnrestAtLoc(UnFocus, ToLoc); 5591 if NewUnrest > OldUnrest then 5592 begin 5593 if MyRO.Government = gDemocracy then 5594 begin 5595 QueryItem := 'UNREST_NOTOWN'; 5596 p1 := me; 5597 end 5598 else 5599 begin 5600 QueryItem := 'UNREST_FOREIGN'; 5601 p1 := MyRO.Territory[ToLoc]; 5602 end; 5603 with MessgExDlg do 5604 begin 5605 MessgText := Format(Tribe[p1].TPhrase(QueryItem), 5606 [Phrases.Lookup('GOVERNMENT', MyRO.Government)]); 5607 Kind := mkYesNo; 5608 IconKind := mikImp; 5609 IconIndex := imPalace; 5610 ShowModal; 5611 if ModalResult <> mrOK then 5612 begin 5613 result := eInvalid; 5614 exit; 5615 end; 5616 end; 5617 Update; // remove message box from screen 5618 end 5619 end; 5620 5621 if (result >= rExecuted) and (MyModel[MyUn[UnFocus].mix].Domain = dAir) and 5622 (MyUn[UnFocus].Status and usToldNoReturn = 0) then 5623 begin // can plane return? 5624 PlaneReturnData.Fuel := MyUn[UnFocus].Fuel; 5625 if (MyMap[ToLoc] and (fUnit or fOwned) = fUnit) or 5626 (MyMap[ToLoc] and (fCity or fOwned) = fCity) then 5627 begin // attack/expel/bombard -> 100MP 5628 PlaneReturnData.Loc := FromLoc; 5629 PlaneReturnData.Movement := MyUn[UnFocus].Movement - 100; 5630 if PlaneReturnData.Movement < 0 then 5631 PlaneReturnData.Movement := 0; 5632 end 5633 else // move 5634 begin 5635 PlaneReturnData.Loc := ToLoc; 5636 if dx and 1 <> 0 then 5637 PlaneReturnData.Movement := MyUn[UnFocus].Movement - 100 5638 else 5639 PlaneReturnData.Movement := MyUn[UnFocus].Movement - 150; 5640 end; 5641 if Server(sGetPlaneReturn, me, UnFocus, PlaneReturnData) = eNoWay then 5642 begin 5643 if MyModel[MyUn[UnFocus].mix].Kind = mkSpecial_Glider then 5644 QueryItem := 'LOWFUEL_GLIDER' 5645 else 5646 QueryItem := 'LOWFUEL'; 5647 if SimpleQuery(mkYesNo, Phrases.Lookup(QueryItem), 'WARNING_LOWSUPPORT') 5648 <> mrOK then 5649 begin 5650 result := eInvalid; 5651 exit; 5652 end; 5653 Update; // remove message box from screen 5654 MyUn[UnFocus].Status := MyUn[UnFocus].Status or usToldNoReturn; 5655 end 5656 end; 5657 5658 if result = eMissionDone then 5659 begin 5660 ModalSelectDlg.ShowNewContent(wmModal, kMission); 5661 Update; // dialog still on screen 5662 Mission := ModalSelectDlg.result; 5663 if Mission < 0 then 5664 exit; 5665 Server(sSetSpyMission + Mission shl 4, me, 0, nil^); 5666 end; 5667 5668 CityCaptured := false; 5669 if result = eNoTime_Move then 5670 Play('NOMOVE_TIME') 5671 else 5672 begin 5673 NeedEcoUpdate := false; 5674 DestinationMarkON := false; 5675 PaintDestination; 5676 if result and rUnitRemoved <> 0 then 5677 CityOptimizer_BeforeRemoveUnit(UnFocus); 5678 IsAttack := (result = eBombarded) or (result <> eMissionDone) and 5679 (MyMap[ToLoc] and (fUnit or fOwned) = fUnit); 5680 if not IsAttack then 5681 begin // move 5682 cix := MyRO.nCity - 1; { look for own city at dest location } 5683 while (cix >= 0) and (MyCity[cix].Loc <> ToLoc) do 5684 dec(cix); 5685 if (result <> eMissionDone) and (MyMap[ToLoc] and fCity <> 0) and 5686 (cix < 0) then 5687 CityCaptured := true; 5688 result := Server(sMoveUnit + DirCode, me, UnFocus, nil^); 5689 case result of 5690 eHiddenUnit: 5691 begin 5692 Play('NOMOVE_SUBMARINE'); 5693 PaintLoc(ToLoc) 1843 5694 end; 1844 end; 1845 1846 if MyRO.Turn=MyData.ColdWarStart+ColdWarTurns then 1847 begin 1848 SoundMessageEx(Phrases.Lookup('COLDWAREND'),'MSG_DEFAULT'); 1849 MyData.ColdWarStart:=-ColdWarTurns-1 1850 end; 1851 1852 TellNewModels; 1853 end; // ClientMode<>cResume 1854 MyData.ToldAlive:=MyRO.Alive; 1855 move(MyRO.Wonder,MyData.ToldWonders,SizeOf(MyData.ToldWonders)); 1856 1857 NewGovAvailable:=-1; 1858 if ClientMode<>cResume then 1859 begin // tell about new techs 1860 for ad:=0 to nAdv-1 do 1861 if (MyRO.TestFlags and tfAllTechs=0) 1862 and ((MyRO.Tech[ad]>=tsApplicable)<>(MyData.ToldTech[ad]>=tsApplicable)) 1863 or (ad in FutureTech ) and (MyRO.Tech[ad]<>MyData.ToldTech[ad]) then 1864 with MessgExDlg do 1865 begin 1866 Item:='RESEARCH_GENERAL'; 1867 if GameMode<>cMovie then 1868 OpenSound:='NEWADVANCE_'+char(48+Age); 1869 Item2:=Phrases.Lookup('ADVANCES',ad); 1870 if ad in FutureTech then Item2:=Item2+' '+IntToStr(MyRO.Tech[ad]); 1871 MessgText:=Format(Phrases.Lookup(Item),[Item2]); 1872 Kind:=mkOkHelp; 1873 HelpKind:=hkAdv; 1874 HelpNo:=ad; 1875 IconKind:=mikBook; 1876 IconIndex:=-1; 1877 for i:=0 to nAdvBookIcon-1 do if AdvBookIcon[i].Adv=ad then 1878 IconIndex:=AdvBookIcon[i].Icon; 1879 ShowModal; 1880 MyData.ToldTech[ad]:=MyRO.Tech[ad]; 1881 for i:=gMonarchy to nGov-1 do if GovPreq[i]=ad then 1882 NewGovAvailable:=i; 1883 end; 1884 end; 1885 1886 ShowCityList:=false; 1887 if ClientMode=cTurn then 1888 begin 1889 if (MyRO.Happened and phTech<>0) and (MyData.FarTech<>adNexus) then 1890 ChooseResearch; 1891 1892 UpdatePanel:=false; 1893 if MyRO.Happened and phChangeGov<>0 then 1894 begin 1895 ModalSelectDlg.ShowNewContent(wmModal,kGov); 1896 Play('NEWGOV'); 1897 Server(sSetGovernment,me,ModalSelectDlg.result,nil^); 1898 CityOptimizer_BeginOfTurn; 1899 UpdatePanel:=true; 1900 end; 1901 end; // ClientMode=cTurn 1902 1903 if not supervising and ((ClientMode=cTurn) or (ClientMode=cMovieTurn)) then 1904 for cix:=0 to MyRO.nCity-1 do with MyCity[cix] do 1905 Status:=Status and not csToldBombard; 1906 1907 if ((ClientMode=cTurn) or (ClientMode=cMovieTurn)) 1908 and (MyRO.Government<>gAnarchy) then 1909 begin 1910 // tell what happened in cities 1911 for WondersOnly:=true downto false do 1912 for cix:=0 to MyRO.nCity-1 do with MyCity[cix] do 1913 if (MyRO.Turn>0) and (Loc>=0) and (Flags and chCaptured=0) 1914 and (WondersOnly=(Flags and chProduction<>0) 1915 and (Project0 and cpImp<>0) and (Project0 and cpIndex<28)) then 1916 begin 1917 if WondersOnly then with MessgExDlg do 1918 begin {tell about newly built wonder} 1919 OpenSound:='WONDER_BUILT'; 1920 s:=Tribe[me].TPhrase('WONDERBUILTOWN'); 1921 MessgText:=Format(s, [Phrases.Lookup('IMPROVEMENTS',Project0 and cpIndex), 1922 CityName(ID)]); 1923 Kind:=mkOkHelp; 1924 HelpKind:=hkImp; 1925 HelpNo:=Project0 and cpIndex; 1926 IconKind:=mikImp; 1927 IconIndex:=Project0 and cpIndex; 1928 ShowModal; 5695 eStealthUnit: 5696 begin 5697 Play('NOMOVE_STEALTH'); 5698 PaintLoc(ToLoc) 1929 5699 end; 1930 if not supervising and (ClientMode=cTurn) then5700 eZOC_EnemySpotted: 1931 5701 begin 1932 AllowCityScreen:=true; 1933 if (Status and 7<>0) and (Project and (cpImp+cpIndex)=cpImp+imTrGoods) then 1934 if (MyData.ImpOrder[Status and 7-1,0]>=0) then 5702 Play('NOMOVE_ZOC'); 5703 PaintLoc(ToLoc, 1) 5704 end; 5705 rExecuted .. maxint: 5706 begin 5707 if result and rUnitRemoved <> 0 then 5708 UnFocus := -1 // unit died 5709 else 5710 begin 5711 assert(UnFocus >= 0); 5712 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 5713 not(usStay or usRecover); 5714 for uix := 0 to MyRO.nUn - 1 do 5715 if MyUn[uix].Master = UnFocus then 5716 MyUn[uix].Status := MyUn[uix].Status and not usWaiting; 5717 if CityCaptured and 5718 (MyRO.Government in [gRepublic, gDemocracy, gFuture]) then 5719 begin // borders have moved, unrest might have changed in any city 5720 CityOptimizer_BeginOfTurn; 5721 NeedEcoUpdate := true; 5722 end 5723 else 1935 5724 begin 1936 if AutoBuild(cix,MyData.ImpOrder[Status and 7-1]) then 1937 AllowCityScreen:=false 1938 else if Flags and chProduction<>0 then 1939 Flags:=(Flags and not chProduction) or chAllImpsMade 1940 end 1941 else Flags:=Flags or chTypeDel; 1942 if (Size>=NeedAqueductSize) and (MyRO.Tech[Imp[imAqueduct].Preq]<tsApplicable) 1943 or (Size>=NeedSewerSize) and (MyRO.Tech[Imp[imSewer].Preq]<tsApplicable) then 1944 Flags:=Flags and not chNoGrowthWarning; // don't remind of unknown building 1945 if Flags and chNoSettlerProd=0 then 1946 Status:=Status and not csToldDelay 1947 else if Status and csToldDelay=0 then 1948 Status:=Status or csToldDelay 1949 else Flags:=Flags and not chNoSettlerProd; 1950 if mRepScreens.Checked then 1951 begin 1952 if (Flags and CityRepMask<>0) and AllowCityScreen then 1953 begin {show what happened in cities} 1954 SetTroopLoc(MyCity[cix].Loc); 1955 MarkCityLoc:=MyCity[cix].Loc; 1956 PanelPaint; 1957 CityDlg.CloseAction:=None; 1958 CityDlg.ShowNewContent(wmModal, MyCity[cix].Loc, Flags and CityRepMask); 1959 UpdatePanel:=true; 1960 end 1961 end 1962 else {if mRepList.Checked then} 1963 begin 1964 if Flags and CityRepMask<>0 then 1965 ShowCityList:=true 1966 end 1967 end 1968 end; {city loop} 1969 end; // ClientMode=cTurn 1970 1971 if ClientMode=cTurn then 1972 begin 1973 if NewGovAvailable>=0 then with MessgExDlg do 1974 begin 1975 MessgText:=Format(Phrases.Lookup('AUTOREVOLUTION'), 1976 [Phrases.Lookup('GOVERNMENT',NewGovAvailable)]); 1977 Kind:=mkYesNo; 1978 IconKind:=mikPureIcon; 1979 IconIndex:=6+NewGovAvailable; 1980 ShowModal; 1981 if ModalResult=mrOK then 1982 begin 1983 Play('REVOLUTION'); 1984 Server(sRevolution,me,0,nil^); 1985 end 1986 end; 1987 end; // ClientMode=cTurn 1988 1989 if (ClientMode=cTurn) or (ClientMode=cMovieTurn) then 1990 begin 1991 if MyRO.Happened and phGliderLost<>0 then 1992 ContextMessage(Phrases.Lookup('GLIDERLOST'), 'MSG_DEFAULT', hkModel, 200); 1993 if MyRO.Happened and phPlaneLost<>0 then 1994 ContextMessage(Phrases.Lookup('PLANELOST'), 'MSG_DEFAULT', hkFeature, 1995 mcFuel); 1996 if MyRO.Happened and phPeaceEvacuation<>0 then 1997 for p1:=0 to nPl-1 do if 1 shl p1 and MyData.PeaceEvaHappened<>0 then 1998 SoundMessageEx(Tribe[p1].TPhrase('WITHDRAW'), 'MSG_DEFAULT'); 1999 if MyRO.Happened and phPeaceViolation<>0 then 2000 for p1:=0 to nPl-1 do 2001 if (1 shl p1 and MyRO.Alive<>0) and (MyRO.EvaStart[p1]=MyRO.Turn) then 2002 SoundMessageEx(Format(Tribe[p1].TPhrase('VIOLATION'), 2003 [TurnToString(MyRO.Turn+PeaceEvaTurns-1)]), 'MSG_WITHDRAW'); 2004 TellNewContacts; 2005 end; 2006 2007 if ClientMode=cMovieTurn then Update 2008 else if ClientMode=cTurn then 2009 begin 2010 if UpdatePanel then UpdateViews; 2011 Application.ProcessMessages; 2012 2013 if not supervising then 2014 for uix:=0 to MyRO.nUn-1 do with MyUn[uix] do if Loc>=0 then 2015 begin 2016 if Flags and unWithdrawn<>0 then Status:=0; 2017 if Health=100 then 2018 Status:=Status and not usRecover; 2019 if (Master>=0) or UnitExhausted(uix) then 2020 Status:=Status and not usWaiting 2021 else Status:=Status or usWaiting; 2022 CheckToldNoReturn(uix); 2023 if Status and usGoto<>0 then 2024 begin {continue multi-turn goto} 2025 SetUnFocus(uix); 2026 SetTroopLoc(Loc); 2027 FocusOnLoc(TroopLoc,flRepaintPanel or flImmUpdate); 2028 if Status shr 16=$7FFF then 2029 MoveResult:=GetMoveAdvice(UnFocus,maNextCity,MoveAdviceData) 2030 else MoveResult:=GetMoveAdvice(UnFocus,Status shr 16,MoveAdviceData); 2031 if MoveResult>=rExecuted then 2032 begin // !!! Shinkansen 2033 MoveResult:=eOK; 2034 ok:=true; 2035 for i:=0 to MoveAdviceData.nStep-1 do 2036 begin 2037 Loc1:=dLoc(Loc,MoveAdviceData.dx[i],MoveAdviceData.dy[i]); 2038 if (MyMap[Loc1] and (fCity or fOwned)=fCity) // don't capture cities during auto move 2039 or (MyMap[Loc1] and (fUnit or fOwned)=fUnit) then // don't attack during auto move 2040 begin ok:=false; Break end 2041 else 2042 begin 2043 if (Loc1=MoveAdviceData.ToLoc) or (MoveAdviceData.ToLoc=maNextCity) 2044 and (MyMap[dLoc(Loc,MoveAdviceData.dx[i],MoveAdviceData.dy[i])] and fCity<>0) then 2045 MoveOptions:=muAutoNoWait 2046 else MoveOptions:=0; 2047 MoveResult:=MoveUnit(MoveAdviceData.dx[i],MoveAdviceData.dy[i],MoveOptions); 2048 if (MoveResult<rExecuted) or (MoveResult=eEnemySpotted) then 2049 begin ok:=false; Break end; 5725 if OldUnrest <> NewUnrest then 5726 begin 5727 CityOptimizer_CityChange(MyUn[UnFocus].Home); 5728 for uix := 0 to MyRO.nUn - 1 do 5729 if MyUn[uix].Master = UnFocus then 5730 CityOptimizer_CityChange(MyUn[uix].Home); 5731 NeedEcoUpdate := true; 5732 end; 5733 if (MyRO.Government = gDespotism) and 5734 (MyModel[MyUn[UnFocus].mix].Kind = mkSpecial_TownGuard) then 5735 begin 5736 if MyMap[FromLoc] and fCity <> 0 then 5737 begin // town guard moved out of city in despotism -- reoptimize! 5738 cixChanged := MyRO.nCity - 1; 5739 while (cixChanged >= 0) and 5740 (MyCity[cixChanged].Loc <> FromLoc) do 5741 dec(cixChanged); 5742 assert(cixChanged >= 0); 5743 if cixChanged >= 0 then 5744 begin 5745 CityOptimizer_CityChange(cixChanged); 5746 NeedEcoUpdate := true; 5747 end; 5748 end; 5749 if (MyMap[ToLoc] and fCity <> 0) and not CityCaptured then 5750 begin // town guard moved into city in despotism -- reoptimize! 5751 cixChanged := MyRO.nCity - 1; 5752 while (cixChanged >= 0) and 5753 (MyCity[cixChanged].Loc <> ToLoc) do 5754 dec(cixChanged); 5755 assert(cixChanged >= 0); 5756 if cixChanged >= 0 then 5757 begin 5758 CityOptimizer_CityChange(cixChanged); 5759 NeedEcoUpdate := true; 5760 end 5761 end 5762 end 2050 5763 end 2051 5764 end; 2052 Stop:=not ok or (Loc=MoveAdviceData.ToLoc)2053 or (MoveAdviceData.ToLoc=maNextCity) and (MyMap[Loc] and fCity<>0)2054 end2055 else2056 begin2057 MoveResult:=eOK;2058 Stop:=true;2059 5765 end; 2060 2061 if MoveResult<>eDied then 2062 if Stop then Status:=Status and ($FFFF-usGoto) 2063 else Status:=Status and not usWaiting; 5766 else 5767 assert(false); 5768 end; 5769 SetTroopLoc(ToLoc); 5770 end 5771 else 5772 begin { enemy unit -- attack } 5773 if result = eBombarded then 5774 Defender := MyRO.Territory[ToLoc] 5775 else 5776 Defender := MyRO.EnemyUn[euix].Owner; 5777 { if MyRO.Treaty[Defender]=trCeaseFire then 5778 if SimpleQuery(mkYesNo,Phrases.Lookup('FRCANCELQUERY_CEASEFIRE'), 5779 'MSG_DEFAULT')<>mrOK then 5780 exit; } 5781 if (Options and muNoSuicideCheck = 0) and (result and rUnitRemoved <> 0) 5782 and (result <> eMissionDone) then 5783 begin // suicide query 5784 with MyUn[UnFocus], BattleDlg.Forecast do 5785 begin 5786 pAtt := me; 5787 mixAtt := mix; 5788 HealthAtt := Health; 5789 ExpAtt := Exp; 5790 FlagsAtt := Flags; 2064 5791 end; 2065 2066 if Status and (usEnhance or usGoto)=usEnhance then 2067 // continue terrain enhancement 5792 BattleDlg.Forecast.Movement := MyUn[UnFocus].Movement; 5793 Server(sGetBattleForecastEx, me, ToLoc, BattleDlg.Forecast); 5794 BattleDlg.uix := UnFocus; 5795 BattleDlg.ToLoc := ToLoc; 5796 BattleDlg.IsSuicideQuery := true; 5797 BattleDlg.ShowModal; 5798 if BattleDlg.ModalResult <> mrOK then 5799 exit; 5800 end; 5801 5802 cixChanged := -1; 5803 if (result and rUnitRemoved <> 0) and (MyRO.Government = gDespotism) and 5804 (MyModel[MyUn[UnFocus].mix].Kind = mkSpecial_TownGuard) and 5805 (MyMap[FromLoc] and fCity <> 0) then 5806 begin // town guard died in city in despotism -- reoptimize! 5807 cixChanged := MyRO.nCity - 1; 5808 while (cixChanged >= 0) and (MyCity[cixChanged].Loc <> FromLoc) do 5809 dec(cixChanged); 5810 assert(cixChanged >= 0); 5811 end; 5812 5813 for i := 0 to MyRO.nEnemyModel - 1 do 5814 LostArmy[i] := MyRO.EnemyModel[i].Lost; 5815 OldToTile := MyMap[ToLoc]; 5816 result := Server(sMoveUnit + DirCode, me, UnFocus, nil^); 5817 nLostArmy := 0; 5818 for i := 0 to MyRO.nEnemyModel - 1 do 5819 begin 5820 LostArmy[i] := MyRO.EnemyModel[i].Lost - LostArmy[i]; 5821 inc(nLostArmy, LostArmy[i]) 5822 end; 5823 if result and rUnitRemoved <> 0 then 5824 begin 5825 UnFocus := -1; 5826 SetTroopLoc(FromLoc); 5827 end; 5828 if (OldToTile and not MyMap[ToLoc] and fCity <> 0) and 5829 (MyRO.Government in [gRepublic, gDemocracy, gFuture]) then 5830 begin // city was destroyed, borders have moved, unrest might have changed in any city 5831 CityOptimizer_BeginOfTurn; 5832 NeedEcoUpdate := true; 5833 end 5834 else 5835 begin 5836 if cixChanged >= 0 then 2068 5837 begin 2069 MoveResult:=ProcessEnhancement(uix,MyData.EnhancementJobs); 2070 if MoveResult<>eDied then 2071 if MoveResult=eJobDone then Status:=Status and not usEnhance 2072 else Status:=Status and not usWaiting; 2073 end 2074 end; 2075 end; // ClientMode=cTurn 2076 2077 HaveStrategyAdvice:= false; 2078 // (GameMode<>cMovie) and not supervising 2079 // and AdvisorDlg.HaveStrategyAdvice; 2080 GoOnPhase:=true; 2081 if supervising or (GameMode=cMovie) then 2082 begin SetTroopLoc(-1); PaintAll end {supervisor} 2083 { else if (ClientMode=cTurn) and (MyRO.Turn=0) then 2084 begin 2085 SetUnFocus(0); 2086 ZoomToCity(MyCity[0].Loc) 2087 end} 2088 else 2089 begin 2090 if ClientMode>=scContact then SetUnFocus(-1) 2091 else NextUnit(-1,false); 2092 if UnFocus<0 then 2093 begin 2094 UnStartLoc:=-1; 2095 if IsMultiPlayerGame or (ClientMode=cResume) then 2096 if MyRO.nCity>0 then FocusOnLoc(MyCity[0].Loc) 2097 else FocusOnLoc(G.lx*G.ly div 2); 2098 SetTroopLoc(-1); 2099 PanelPaint 2100 end; 2101 if ShowCityList then 2102 ListDlg.ShowNewContent(wmPersistent,kCityEvents); 2103 end; 2104 end;{InitTurn} 2105 2106 var 2107 i,j,p1,mix,ToLoc,AnimationSpeed,ShowMoveDomain,cix,ecix: integer; 2108 Color: TColor; 2109 Name,s: string; 2110 TribeInfo: TTribeInfo; 2111 mi: TModelInfo; 2112 SkipTurn,IsAlpine,IsTreatyDeal: boolean; 2113 2114 begin {>>>client} 2115 case command of 2116 cTurn,cResume,cContinue,cMovieTurn,scContact,scDipStart..scDipBreak: 2117 begin 2118 supervising:= G.Difficulty[NewPlayer]=0; 2119 ArrangeMidPanel; 2120 end 2121 end; 2122 case Command of 2123 cDebugMessage: 2124 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(@Data)); 2125 2126 cShowNego: with TShowNegoData(Data) do 2127 begin 2128 s:=Format('P%d to P%d: ',[pSender,pTarget]); 2129 if (Action=scDipOffer) and (Offer.nDeliver+Offer.nCost>0) then 2130 begin 2131 s:=s+'Offer '; 2132 for i:=0 to Offer.nDeliver+Offer.nCost-1 do 2133 begin 2134 if i=Offer.nDeliver then s:=s+' for ' 2135 else if i>0 then s:=s+'+'; 2136 case Offer.Price[i] and opMask of 2137 opChoose: s:=s+'Price of choice'; 2138 opCivilReport: s:=s+'State report'; 2139 opMilReport: s:=s+'Military report'; 2140 opMap: s:=s+'Map'; 2141 opTreaty: s:=s+'Treaty'; 2142 opShipParts: s:=s+'Ship part'; 2143 opMoney: s:=s+InttoStr(Offer.Price[i] and $FFFFFF)+'o'; 2144 opTribute: s:=s+InttoStr(Offer.Price[i] and $FFFFFF)+'o tribute'; 2145 opTech: s:=s+Phrases.Lookup('ADVANCES', Offer.Price[i] and $FFFFFF); 2146 opAllTech: s:=s+'All advances'; 2147 opModel: s:=s+Tribe[pSender].ModelName[Offer.Price[i] and $FFFFFF]; 2148 opAllModel: s:=s+'All models'; 2149 end 2150 end; 2151 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(s)); 2152 end 2153 else if Action=scDipAccept then 2154 begin 2155 s:=s+'--- ACCEPTED! ---'; 2156 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(s)); 2157 end 2158 end; 2159 2160 cInitModule: 2161 begin 2162 Server:=TInitModuleData(Data).Server; 2163 //AdvisorDlg.Init; 2164 InitModule; 2165 TInitModuleData(Data).DataSize:=SizeOf(TPersistentData); 2166 TInitModuleData(Data).Flags:=aiThreaded; 2167 end; 2168 2169 cReleaseModule: 2170 begin 2171 SmallImp.Free; 2172 UnusedTribeFiles.Free; 2173 TribeNames.Free; 2174 MainMap.Free; 2175 IsoEngine.Done; 2176 //AdvisorDlg.DeInit; 2177 end; 2178 2179 cHelpOnly,cStartHelp,cStartCredits: 2180 begin 2181 Age:=0; 2182 if Command=cHelpOnly then 2183 SetMainTextureByAge(-1); 2184 Tribes.Init; 2185 HelpDlg.UserLeft:=(Screen.Width-HelpDlg.Width) div 2; 2186 HelpDlg.UserTop:=(Screen.Height-HelpDlg.Height) div 2; 2187 HelpDlg.Difficulty:=0; 2188 if Command=cStartCredits then 2189 HelpDlg.ShowNewContent(wmModal, hkMisc, miscCredits) 2190 else HelpDlg.ShowNewContent(wmModal, hkMisc, miscMain); 2191 Tribes.Done; 2192 end; 2193 2194 cNewGame,cLoadGame,cMovie,cNewMap: 2195 begin 2196 {if (Command=cNewGame) or (Command=cLoadGame) then 2197 AdvisorDlg.NewGame(Data);} 2198 GenerateNames:=mNames.Checked; 2199 GameOK:=true; 2200 G:=TNewGameData(Data); 2201 me:=-1; 2202 pLogo:=-1; 2203 ClientMode:=-1; 2204 SetMapOptions; 2205 IsoEngine.pDebugMap:=-1; 2206 idle:=false; 2207 FillChar(Jump,SizeOf(Jump),0); 2208 if StartRunning then Jump[0]:=999999; 2209 GameMode:=Command; 2210 for i:=0 to nGrExt-1 do 2211 FillChar(GrExt[i].pixUsed,GrExt[i].Data.Height div 49 *10,0); 2212 IsoEngine.Reset; 2213 Tribes.Init; 2214 GetTribeList; 2215 for p1:=0 to nPl-1 do if (G.RO[p1]<>nil) and (G.RO[p1].Data<>nil) then 2216 with TPersistentData(G.RO[p1].Data^) do 2217 begin 2218 FarTech:=adNone; 2219 FillChar(EnhancementJobs,SizeOf(EnhancementJobs),jNone); 2220 FillChar(ImpOrder,SizeOf(ImpOrder),-1); 2221 ColdWarStart:=-ColdWarTurns-1; 2222 ToldAge:=-1; 2223 ToldModels:=3; 2224 ToldAlive:=0; 2225 ToldContact:=0; 2226 ToldOwnCredibility:=InitialCredibility; 2227 for i:=0 to nPl-1 do if G.Difficulty[i]>0 then inc(ToldAlive,1 shl i); 2228 PeaceEvaHappened:=0; 2229 for i:=0 to 27 do with ToldWonders[i] do 2230 begin CityID:=-1; EffectiveOwner:=-1 end; 2231 FillChar(ToldTech,SizeOf(ToldTech),tsNA); 2232 if G.Difficulty[p1]>0 then 2233 SoundPreload(sbStart); 2234 end; 2235 2236 // arrange dialogs 2237 ListDlg.UserLeft:=8; 2238 ListDlg.UserTop:=TopBarHeight+8; 2239 HelpDlg.UserLeft:=Screen.Width-HelpDlg.Width-8; 2240 HelpDlg.UserTop:=TopBarHeight+8; 2241 UnitStatDlg.UserLeft:=397; 2242 UnitStatDlg.UserTop:=TopBarHeight+64; 2243 DiaDlg.UserLeft:=(Screen.Width-DiaDlg.Width) div 2; 2244 DiaDlg.UserTop:=(Screen.Height-DiaDlg.Height) div 2; 2245 NatStatDlg.UserLeft:=Screen.Width-NatStatDlg.Width-8; 2246 NatStatDlg.UserTop:=Screen.Height-PanelHeight-NatStatDlg.Height-8; 2247 if NatStatDlg.UserTop<8 then 2248 NatStatDlg.UserTop:=8; 2249 2250 Age:=0; 2251 MovieSpeed:=1; 2252 LogDlg.mSlot.Visible:=true; 2253 LogDlg.Host:=self; 2254 HelpDlg.ClearHistory; 2255 CityDlg.Reset; 2256 2257 Mini.Width:=G.lx*2; Mini.Height:=G.ly; 2258 for i:=0 to nPl-1 do 2259 begin Tribe[i]:=nil; TribeOriginal[i]:=false; end; 2260 ToldSlavery:=-1; 2261 RepaintOnResize:=false; 2262 Closable:=false; 2263 FirstMovieTurn:=true; 2264 2265 MenuArea.Visible:= GameMode<>cMovie; 2266 TreasuryArea.Visible:= GameMode<cMovie; 2267 ResearchArea.Visible:= GameMode<cMovie; 2268 ManagementArea.Visible:= GameMode<cMovie; 2269 end; 2270 2271 cGetReady,cReplay: if NewPlayer=0 then 2272 begin 2273 i:=0; 2274 for p1:=0 to nPl-1 do 2275 if (G.Difficulty[p1]>0) and (Tribe[p1]=nil) then inc(i); 2276 if i>UnusedTribeFiles.Count then 2277 begin 2278 GameOK:=false; 2279 SimpleMessage(Phrases.Lookup('TOOFEWTRIBES')); 2280 end 2281 else 2282 begin 2283 for p1:=0 to nPl-1 do 2284 if (G.Difficulty[p1]>0) and (Tribe[p1]=nil) and (G.RO[p1]<>nil) then 2285 begin // let player select own tribes 2286 TribeInfo.trix:=p1; 2287 TribeNames.Clear; 2288 for j:=0 to UnusedTribeFiles.Count-1 do 2289 begin 2290 GetTribeInfo(UnusedTribeFiles[j], Name, Color); 2291 TribeNames.AddObject(Name,TObject(Color)); 2292 end; 2293 assert(TribeNames.Count>0); 2294 ModalSelectDlg.ShowNewContent(wmModal,kTribe); 2295 Application.ProcessMessages; 2296 TribeInfo.FileName:=UnusedTribeFiles[ModalSelectDlg.result]; 2297 UnusedTribeFiles.Delete(ModalSelectDlg.result); 2298 2299 if GameMode=cLoadGame then 2300 CreateTribe(TribeInfo.trix,TribeInfo.FileName,false) 2301 else Server(cSetTribe+(Length(TribeInfo.FileName)+1+7) div 4, 2302 0,0,TribeInfo); 5838 CityOptimizer_CityChange(cixChanged); 5839 NeedEcoUpdate := true; 2303 5840 end; 2304 2305 for p1:=0 to nPl-1 do 2306 if (G.Difficulty[p1]>0) and (Tribe[p1]=nil) and (G.RO[p1]=nil) then 2307 begin // autoselect enemy tribes 2308 j:=ChooseUnusedTribe; 2309 TribeInfo.FileName:=UnusedTribeFiles[j]; 2310 UnusedTribeFiles.Delete(j); 2311 TribeInfo.trix:=p1; 2312 if GameMode=cLoadGame then 2313 CreateTribe(TribeInfo.trix,TribeInfo.FileName,false) 2314 else Server(cSetTribe+(Length(TribeInfo.FileName)+1+7) div 4, 2315 0,0,TribeInfo); 5841 if (result = eWon) or (result = eBloody) or (result = eExpelled) then 5842 begin 5843 CityOptimizer_TileBecomesAvailable(ToLoc); 5844 NeedEcoUpdate := true; 2316 5845 end; 2317 end; 2318 if not mNames.Checked then 2319 for p1:=0 to nPl-1 do if Tribe[p1]<>nil then 2320 Tribe[p1].NumberName:=p1; 2321 end; 2322 2323 cBreakGame: 2324 begin 2325 SaveSettings; 2326 CityDlg.CloseAction:=None; 2327 for i:=0 to Screen.FormCount-1 do 2328 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 2329 Screen.Forms[i].Close; 2330 if LogDlg.Visible then LogDlg.Close; 2331 LogDlg.List.Clear; 2332 StartRunning:=not idle and (Jump[0]>0); // AI called Reload 2333 me:=-1; 2334 idle:=false; 2335 ClientMode:=-1; 2336 UnitInfoBtn.Visible:=false; 2337 UnitBtn.Visible:=false; 2338 TerrainBtn.Visible:=false; 2339 MovieSpeed1Btn.Visible:=false; 2340 MovieSpeed2Btn.Visible:=false; 2341 MovieSpeed3Btn.Visible:=false; 2342 MovieSpeed4Btn.Visible:=false; 2343 EOT.Visible:=false; 2344 for i:=0 to ControlCount-1 do if Controls[i] is TButtonC then 2345 Controls[i].visible:=false; 2346 InitPVSB(sb,0,1); 2347 for p1:=0 to nPl-1 do if Tribe[p1]<>nil then Tribe[p1].Free; 2348 Tribes.Done; 2349 RepaintOnResize:=false; 2350 Closable:=true; Close; 2351 {if (GameMode=cNewGame) or (GameMode=cLoadGame) then 2352 AdvisorDlg.BreakGame;} 2353 end; 2354 2355 cShowGame: 2356 begin 2357 with Panel.Canvas do 2358 begin 2359 Brush.Color:=$000000; 2360 FillRect(Rect(0,0,Panel.Width,Panel.Height)); 2361 Brush.Style:=bsClear; 2362 end; 2363 with TopBar.Canvas do 2364 begin 2365 Brush.Color:=$000000; 2366 FillRect(Rect(0,0,TopBar.Width,TopBar.Height)); 2367 Brush.Style:=bsClear; 2368 end; 2369 FormResize(nil); // place mini map correctly according to its size 2370 Show; 2371 Update; 2372 RepaintOnResize:=true; 2373 xw:=0; yw:=ywcenter; 2374 if not StayOnTop_Ensured then 2375 begin 2376 StayOnTop_Ensured:=true; 2377 CityDlg.StayOnTop_Workaround; 2378 CityTypeDlg.StayOnTop_Workaround; 2379 DiaDlg.StayOnTop_Workaround; 2380 DraftDlg.StayOnTop_Workaround; 2381 EnhanceDlg.StayOnTop_Workaround; 2382 HelpDlg.StayOnTop_Workaround; 2383 NatStatDlg.StayOnTop_Workaround; 2384 NegoDlg.StayOnTop_Workaround; 2385 ModalSelectDlg.StayOnTop_Workaround; 2386 ListDlg.StayOnTop_Workaround; 2387 UnitStatDlg.StayOnTop_Workaround; 2388 WondersDlg.StayOnTop_Workaround; 2389 RatesDlg.StayOnTop_Workaround; 2390 end; 2391 end; 2392 2393 cShowTurnChange: 2394 begin 2395 if integer(data)>=0 then 2396 begin 2397 pLogo:=integer(data); 2398 if G.RO[pLogo]=nil then 2399 begin 2400 if AILogo[pLogo]<>nil then 2401 BitBlt(Canvas.Handle, (xRightPanel+10)-(16+64), ClientHeight-PanelHeight, 64,64, 2402 AILogo[pLogo].Canvas.Handle,0,0,SRCCOPY); 2403 end 2404 end 2405 end; 2406 2407 cTurn,cResume,cContinue: 2408 if not GameOK then Server(sResign,NewPlayer,0,nil^) 2409 else 2410 begin 2411 ClientMode:=Command; 2412 pTurn:=NewPlayer; 2413 pLogo:=NewPlayer; 2414 2415 if Command=cResume then 2416 begin // init non-original model pictures (maybe tribes not found) 2417 for p1:=0 to nPl-1 do if G.RO[p1]<>nil then 5846 end; 5847 if nLostArmy > 1 then 5848 begin 5849 with MessgExDlg do 2418 5850 begin 2419 ItsMeAgain(p1); 2420 for mix:=0 to MyRO.nModel-1 do 2421 if Tribe[me].ModelPicture[mix].HGr=0 then 2422 InitMyModel(mix, true); 2423 end; 2424 me:=-1; 2425 end; 2426 2427 if Jump[pTurn]>0 then 2428 Application.ProcessMessages; 2429 if Jump[pTurn]>0 then 2430 if G.RO[NewPlayer].Happened and phGameEnd<>0 then Jump[pTurn]:=0 2431 else dec(Jump[pTurn]); 2432 SkipTurn:= Jump[pTurn]>0; 2433 if SkipTurn then 2434 begin 2435 ItsMeAgain(NewPlayer); 2436 MyData:=G.RO[NewPlayer].Data; 2437 SetTroopLoc(-1); 2438 MiniPaint; 2439 InitAllEnemyModels; // necessary for correct replay 2440 if not EndTurn(true) then SkipTurn:=false; 2441 end; 2442 if not SkipTurn then 2443 begin 2444 if ((ClientMode<scDipStart) or (ClientMode>scDipBreak)) 2445 and NegoDlg.Visible then 2446 NegoDlg.Close; 2447 skipped:=false; // always show my moves during my turn 2448 idle:=true; 2449 InitTurn(NewPlayer); 2450 DipMem[me].pContact:=-1; 2451 (* if (me=0) and (MyRO.Alive and (1 shl me)=0)} then 2452 begin 2453 if SimpleQuery(Phrases.Lookup('RESIGN'))=mrIgnore then 2454 Server(sResign,me,0,nil^) 2455 else Server(sBreak,me,0,nil^) 2456 end 2457 else Play('TURNSTART');*) 2458 end; 2459 end; 2460 2461 cMovieTurn: 2462 begin 2463 ClientMode:=Command; 2464 pTurn:=NewPlayer; 2465 pLogo:=-1; 2466 skipped:=false; // always show my moves during my turn 2467 idle:=true; 2468 if FirstMovieTurn then 2469 begin 2470 CheckMovieSpeedBtnState; 2471 FirstMovieTurn:=false; 2472 end; 2473 InitTurn(NewPlayer); 2474 Application.ProcessMessages; 2475 if MovieSpeed=4 then 2476 begin 2477 Sleep(75); // this break will ensure speed of fast forward does not depend on cpu speed 2478 Application.ProcessMessages; 2479 end 2480 end; 2481 2482 cMovieEndTurn: 2483 begin 2484 RememberPeaceViolation; 2485 pTurn:=-1; 2486 pLogo:=-1; 2487 MapValid:=false; 2488 ClientMode:=-1; 2489 idle:=false; 2490 skipped:=false; 2491 end; 2492 2493 cEditMap: 2494 begin 2495 ClientMode:=cEditMap; 2496 SetMapOptions; 2497 IsoEngine.pDebugMap:=-1; 2498 ItsMeAgain(0); 2499 MyData:=nil; 2500 UnitInfoBtn.Visible:=false; 2501 UnitBtn.Visible:=false; 2502 TerrainBtn.Visible:=false; 2503 MovieSpeed1Btn.Visible:=false; 2504 MovieSpeed2Btn.Visible:=false; 2505 MovieSpeed3Btn.Visible:=false; 2506 MovieSpeed4Btn.Visible:=false; 2507 EOT.Visible:=false; 2508 HelpDlg.Difficulty:=0; 2509 BrushType:=fGrass; 2510 BrushLoc:=-1; 2511 Edited:=false; 2512 UnFocus:=-1; 2513 MarkCityLoc:=-1; 2514 Tracking:=false; 2515 TurnComplete:=false; 2516 MapValid:=false; 2517 FormResize(nil); // calculate geometrics and paint all 2518 SetTroopLoc(-1); 2519 idle:=true 2520 end; 2521 2522 (* cNewContact: 2523 begin 2524 end; 2525 *) 2526 2527 scContact: 2528 begin 2529 DipMem[NewPlayer].pContact:=integer(Data); 2530 if Jump[NewPlayer]>0 then DipCall(scReject) 2531 else 2532 begin 2533 ClientMode:=Command; 2534 InitTurn(NewPlayer); 2535 MyData.ToldContact:=MyData.ToldContact or (1 shl integer(Data)); 2536 // don't tell about new nation when already contacted by them 2537 with MessgExDlg do 2538 begin 2539 OpenSound:='CONTACT_'+char(48+MyRO.EnemyReport[integer(Data)].Attitude); 2540 MessgText:=Tribe[integer(Data)].TPhrase('FRCONTACT'); 2541 Kind:=mkYesNo; 2542 IconKind:=mikTribe; 2543 IconIndex:=integer(Data); 2544 ShowModal; 2545 if ModalResult=mrOK then 2546 begin 2547 NegoDlg.Respond; 2548 DipMem[me].DeliveredPrices:=[]; 2549 DipMem[me].ReceivedPrices:=[]; 2550 DipCall(scDipStart) 2551 end 2552 else 2553 begin 2554 DipCall(scReject); 2555 EndNego 5851 Kind := mkOk; 5852 IconKind := mikEnemyArmy; 5853 MessgText := Tribe[Defender].TString(Phrases.Lookup('ARMYLOST', 5854 MyRO.EnemyModel[MyRO.EnemyUn[euix].emix].Domain)); 5855 ShowModal; 2556 5856 end 2557 5857 end 2558 5858 end; 2559 end; 2560 2561 scDipStart..scDipBreak: 2562 begin 2563 ClientMode:=Command; 2564 InitTurn(NewPlayer); 2565 if Command=scDipStart then 2566 Play('CONTACT_'+char(48+MyRO.Attitude[DipMem[NewPlayer].pContact])) 2567 else if Command=scDipCancelTreaty then 2568 Play('CANCELTREATY') 2569 else if Command=scDipOffer then 2570 begin 2571 ReceivedOffer:=TOffer(Data); 2572 InitAllEnemyModels; 5859 if result and rUnitRemoved <> 0 then 5860 begin 5861 CityOptimizer_AfterRemoveUnit; 5862 ListDlg.RemoveUnit; 5863 NeedEcoUpdate := true; 5864 end; 5865 if NeedEcoUpdate then 5866 begin 5867 UpdateViews(true); 5868 Update 2573 5869 end 2574 else if Command=scDipAccept then 2575 begin // remember delivered and received prices 2576 for i:=0 to DipMem[me].SentOffer.nDeliver-1 do 2577 include(DipMem[me].DeliveredPrices,DipMem[me].SentOffer.Price[i] shr 24); 2578 for i:=0 to DipMem[me].SentOffer.nCost-1 do 2579 include(DipMem[me].ReceivedPrices, 2580 DipMem[me].SentOffer.Price[DipMem[me].SentOffer.nDeliver+i] shr 24); 2581 IsTreatyDeal:=false; 2582 for i:=0 to ReceivedOffer.nDeliver+ReceivedOffer.nCost-1 do 2583 if DipMem[me].SentOffer.Price[i] and opMask=opTreaty then 2584 IsTreatyDeal:=true; 2585 if IsTreatyDeal then Play('NEWTREATY') 2586 else Play('ACCEPTOFFER'); 5870 end; 5871 5872 if result = eMissionDone then 5873 begin 5874 p1 := MyRO.Territory[ToLoc]; 5875 case Mission of 5876 smStealMap: 5877 begin 5878 MapValid := false; 5879 PaintAllMaps 5880 end; 5881 smStealCivilReport: 5882 TribeMessage(p1, Tribe[p1].TPhrase('DOSSIER_PREPARED'), ''); 5883 smStealMilReport: 5884 ListDlg.ShowNewContent_MilReport(wmPersistent, p1); 2587 5885 end; 2588 NegoDlg.Start; 2589 idle:=true 2590 end; 2591 2592 cShowCancelTreaty: 2593 if not IsMultiPlayerGame then 2594 begin 2595 case G.RO[NewPlayer].Treaty[integer(data)] of 2596 trPeace: s:=Tribe[integer(data)].TPhrase('FRCANCELBYREJECT_PEACE'); 2597 trFriendlyContact: s:=Tribe[integer(data)].TPhrase('FRCANCELBYREJECT_FRIENDLY'); 2598 trAlliance: s:=Tribe[integer(data)].TPhrase('FRCANCELBYREJECT_ALLIANCE'); 2599 end; 2600 TribeMessage(integer(data), s, 'CANCELTREATY'); 5886 end; 5887 5888 if UnFocus >= 0 then 5889 CheckToldNoReturn(UnFocus); 5890 5891 NeedRepaintPanel := false; 5892 if result >= rExecuted then 5893 begin 5894 if CityCaptured and (MyMap[ToLoc] and fCity = 0) then 5895 begin // city destroyed 5896 for i := 0 to 27 do { tell about destroyed wonders } 5897 if (MyRO.Wonder[i].CityID = -2) and 5898 (MyData.ToldWonders[i].CityID <> -2) then 5899 with MessgExDlg do 5900 begin 5901 if WondersDlg.Visible then 5902 WondersDlg.SmartUpdateContent(false); 5903 OpenSound := 'WONDER_DESTROYED'; 5904 MessgText := Format(Phrases.Lookup('WONDERDEST'), 5905 [Phrases.Lookup('IMPROVEMENTS', i)]); 5906 Kind := mkOkHelp; 5907 HelpKind := hkImp; 5908 HelpNo := i; 5909 IconKind := mikImp; 5910 IconIndex := i; 5911 ShowModal; 5912 MyData.ToldWonders[i] := MyRO.Wonder[i]; 5913 end 2601 5914 end; 2602 2603 cShowCancelTreatyByAlliance: 2604 if idle and (NewPlayer=me) then 2605 TribeMessage(integer(data), Tribe[integer(data)].TPhrase('FRENEMYALLIANCE'), 2606 'CANCELTREATY'); 2607 2608 cShowSupportAllianceAgainst: 2609 if not IsMultiPlayerGame and (Jump[0]=0) then 2610 TribeMessage(integer(data) and $F, 2611 Tribe[integer(data) and $F].TPhrase('FRMYALLIANCE1') 2612 +' '+Tribe[integer(data) shr 4].TPhrase('FRMYALLIANCE2'), 2613 'CANCELTREATY'); 2614 2615 cShowPeaceViolation: 2616 if not IsMultiPlayerGame and (Jump[0]=0) then 2617 TribeMessage(integer(data), Format(Tribe[integer(data)].TPhrase('EVIOLATION'), 2618 [TurnToString(MyRO.Turn+PeaceEvaTurns-1)]), 'MSG_WITHDRAW'); 2619 2620 cShowEndContact: EndNego; 2621 2622 cShowUnitChanged,cShowCityChanged,cShowAfterMove,cShowAfterAttack: 2623 if (idle and (NewPlayer=me) or not idle and not skipped) 2624 and not ((GameMode=cMovie) and (MovieSpeed=4)) then 2625 begin 2626 assert(NewPlayer=me); 2627 if not idle or (GameMode=cMovie) then 2628 Application.ProcessMessages; 2629 if Command=cShowCityChanged then 2630 begin 2631 CurrentMoveInfo.DoShow:=false; 2632 if idle then 2633 CurrentMoveInfo.DoShow:=true 2634 else if CurrentMoveInfo.IsAlly then 2635 CurrentMoveInfo.DoShow:=not mAlNoMoves.Checked 2636 else CurrentMoveInfo.DoShow:=not mEnNoMoves.Checked 5915 if CityCaptured and (MyMap[ToLoc] and fCity <> 0) then 5916 begin // city captured 5917 ListDlg.AddCity; 5918 for i := 0 to 27 do { tell about capture of wonders } 5919 if MyRO.City[MyRO.nCity - 1].Built[i] > 0 then 5920 with MessgExDlg do 5921 begin 5922 if WondersDlg.Visible then 5923 WondersDlg.SmartUpdateContent(false); 5924 OpenSound := 'WONDER_CAPTURED'; 5925 MessgText := Format(Tribe[me].TPhrase('WONDERCAPTOWN'), 5926 [Phrases.Lookup('IMPROVEMENTS', i)]); 5927 Kind := mkOkHelp; 5928 HelpKind := hkImp; 5929 HelpNo := i; 5930 IconKind := mikImp; 5931 IconIndex := i; 5932 ShowModal; 5933 MyData.ToldWonders[i] := MyRO.Wonder[i]; 5934 end; 5935 5936 if MyRO.Happened and phStealTech <> 0 then 5937 begin { Temple of Zeus -- choose advance to steal } 5938 ModalSelectDlg.ShowNewContent(wmModal, kStealTech); 5939 Server(sStealTech, me, ModalSelectDlg.result, nil^); 5940 end; 5941 TellNewModels; 5942 5943 cix := MyRO.nCity - 1; 5944 while (cix >= 0) and (MyCity[cix].Loc <> ToLoc) do 5945 dec(cix); 5946 assert(cix >= 0); 5947 MyCity[cix].Status := MyCity[cix].Status and 5948 not csResourceWeightsMask or (3 shl 4); 5949 // captured city, set to maximum growth 5950 NewTiles := 1 shl 13; { exploit central tile only } 5951 Server(sSetCityTiles, me, cix, NewTiles); 5952 end 5953 else 5954 NeedRepaintPanel := true; 5955 end; 5956 TellNewContacts; 5957 5958 if (UnFocus >= 0) and (MyUn[UnFocus].Master >= 0) then 5959 with MyUn[MyUn[UnFocus].Master] do 5960 if Status and usStay <> 0 then 5961 begin 5962 Status := Status and not usStay; 5963 if (Movement >= 100) and (Status and (usRecover or usGoto) = 0) then 5964 Status := Status or usWaiting; 5965 end; 5966 if Options and (muAutoNoWait or muAutoNext) <> 0 then 5967 begin 5968 if (UnFocus >= 0) and ((result = eNoTime_Move) or UnitExhausted(UnFocus) 5969 or (MyUn[UnFocus].Master >= 0) or 5970 (MyModel[MyUn[UnFocus].mix].Domain = dAir) and 5971 ((MyMap[MyUn[UnFocus].Loc] and fCity <> 0) { aircrafts stop in cities } 5972 or (MyMap[MyUn[UnFocus].Loc] and fTerImp = tiBase))) then 5973 begin 5974 MyUn[UnFocus].Status := MyUn[UnFocus].Status and not usWaiting; 5975 if Options and muAutoNext <> 0 then 5976 if CityCaptured and (MyMap[ToLoc] and fCity <> 0) then 5977 begin 5978 UnFocus := -1; 5979 PaintLoc(ToLoc); // don't show unit in city if not selected 5980 end 5981 else 5982 NextUnit(UnStartLoc, true) 5983 end 5984 else if (UnFocus < 0) and (Options and muAutoNext <> 0) then 5985 NextUnit(UnStartLoc, result <> eMissionDone); 5986 end; 5987 5988 if NeedRepaintPanel and (UnFocus = UnFocus0) then 5989 if IsAttack then 5990 PanelPaint 5991 else 5992 begin 5993 assert(result <> eMissionDone); 5994 CheckTerrainBtnVisible; 5995 FocusOnLoc(ToLoc, flRepaintPanel or flImmUpdate) 5996 end; 5997 5998 if (result >= rExecuted) and CityCaptured and (MyMap[ToLoc] and fCity <> 0) 5999 then 6000 ZoomToCity(ToLoc, UnFocus < 0, chCaptured); // show captured city 6001 end; // moveunit 6002 6003 procedure TMainScreen.MoveOnScreen(ShowMove: TShowMove; 6004 Step0, Step1, nStep: integer; Restore: boolean = true); 6005 var 6006 ToLoc, xFromLoc, yFromLoc, xToLoc, yToLoc, xFrom, yFrom, xTo, yTo, xMin, 6007 yMin, xRange, yRange, xw1, Step, xMoving, yMoving, yl, 6008 SliceCount: integer; 6009 UnitInfo: TUnitInfo; 6010 Ticks0, Ticks: int64; 6011 begin 6012 Timer1.Enabled := false; 6013 QueryPerformanceCounter(Ticks0); 6014 with ShowMove do 6015 begin 6016 UnitInfo.Owner := Owner; 6017 UnitInfo.mix := mix; 6018 UnitInfo.Health := Health; 6019 UnitInfo.Job := jNone; 6020 UnitInfo.Flags := Flags; 6021 if Owner <> me then 6022 UnitInfo.emix := emix; 6023 6024 ToLoc := dLoc(FromLoc, dx, dy); 6025 xToLoc := ToLoc mod G.lx; 6026 yToLoc := ToLoc div G.lx; 6027 xFromLoc := FromLoc mod G.lx; 6028 yFromLoc := FromLoc div G.lx; 6029 if xToLoc > xFromLoc + 2 then 6030 xToLoc := xToLoc - G.lx 6031 else if xToLoc < xFromLoc - 2 then 6032 xToLoc := xToLoc + G.lx; 6033 6034 xw1 := xw + G.lx; 6035 // ((xFromLoc-xw1)*2+yFromLoc and 1+1)*xxt+dx*xxt/2-MapWidth/2 -> min 6036 while abs(((xFromLoc - xw1 + G.lx) * 2 + yFromLoc and 1 + 1) * xxt * 2 + 6037 dx * xxt - MapWidth) < abs(((xFromLoc - xw1) * 2 + yFromLoc and 1 + 1) * 6038 xxt * 2 + dx * xxt - MapWidth) do 6039 dec(xw1, G.lx); 6040 6041 xTo := (xToLoc - xw1) * (xxt * 2) + yToLoc and 1 * xxt + (xxt - xxu); 6042 yTo := (yToLoc - yw) * yyt + (yyt - yyu_anchor); 6043 xFrom := (xFromLoc - xw1) * (xxt * 2) + yFromLoc and 1 * xxt + 6044 (xxt - xxu); 6045 yFrom := (yFromLoc - yw) * yyt + (yyt - yyu_anchor); 6046 if xFrom < xTo then 6047 begin 6048 xMin := xFrom; 6049 xRange := xTo - xFrom 6050 end 6051 else 6052 begin 6053 xMin := xTo; 6054 xRange := xFrom - xTo 6055 end; 6056 if yFrom < yTo then 6057 begin 6058 yMin := yFrom; 6059 yRange := yTo - yFrom 6060 end 6061 else 6062 begin 6063 yMin := yTo; 6064 yRange := yFrom - yTo 6065 end; 6066 inc(xRange, xxt * 2); 6067 inc(yRange, yyt * 3); 6068 6069 MainOffscreenPaint; 6070 NoMap.SetOutput(Buffer); 6071 NoMap.SetPaintBounds(0, 0, xRange, yRange); 6072 for Step := 0 to abs(Step1 - Step0) do 6073 begin 6074 BitBlt(Buffer.Canvas.Handle, 0, 0, xRange, yRange, 6075 offscreen.Canvas.Handle, xMin, yMin, SRCCOPY); 6076 if Step1 <> Step0 then 6077 begin 6078 xMoving := xFrom + 6079 Round((Step0 + Step * (Step1 - Step0) div abs(Step1 - Step0)) * 6080 (xTo - xFrom) / nStep); 6081 yMoving := yFrom + 6082 Round((Step0 + Step * (Step1 - Step0) div abs(Step1 - Step0)) * 6083 (yTo - yFrom) / nStep); 2637 6084 end 2638 else if Command=cShowUnitChanged then 2639 begin 2640 CurrentMoveInfo.DoShow:=false; 2641 if idle then 2642 CurrentMoveInfo.DoShow:=not mEffectiveMovesOnly.Checked 2643 else if CurrentMoveInfo.IsAlly then 2644 CurrentMoveInfo.DoShow:=not (mAlNoMoves.Checked or mAlEffectiveMovesOnly.Checked) 2645 else CurrentMoveInfo.DoShow:=not (mEnNoMoves.Checked or mEnAttacks.Checked) 2646 end; 2647 // else keep DoShow from cShowMove/cShowAttack 2648 2649 if CurrentMoveInfo.DoShow then 2650 begin 2651 if Command=cShowCityChanged then MapValid:=false; 2652 FocusOnLoc(integer(Data),flImmUpdate); 2653 // OldUnFocus:=UnFocus; 2654 // UnFocus:=-1; 2655 if Command=cShowAfterMove then 2656 PaintLoc(integer(Data),CurrentMoveInfo.AfterMovePaintRadius) // show discovered areas 2657 else PaintLoc(integer(Data),1); 2658 // UnFocus:=OldUnFocus; 2659 if (Command=cShowAfterAttack) and (CurrentMoveInfo.AfterAttackExpeller>=0) then 6085 else 6086 begin 6087 xMoving := xFrom; 6088 yMoving := yFrom; 6089 end; 6090 NoMap.PaintUnit(xMoving - xMin, yMoving - yMin, UnitInfo, 0); 6091 PaintBufferToScreen(xMin, yMin, xRange, yRange); 6092 6093 SliceCount := 0; 6094 Ticks := Ticks0; 6095 repeat 6096 if (SliceCount = 0) or ((Ticks - Ticks0) * 12000 * (SliceCount + 1) 6097 div SliceCount < MoveTime * PerfFreq) then 2660 6098 begin 2661 SoundMessageEx(Tribe[CurrentMoveInfo.AfterAttackExpeller].TPhrase('EXPEL'),''); 2662 CurrentMoveInfo.AfterAttackExpeller:=-1; 2663 Update; // remove message box from screen 6099 if not idle or (GameMode = cMovie) then 6100 Application.ProcessMessages; 6101 Sleep(1); 6102 inc(SliceCount) 6103 end; 6104 QueryPerformanceCounter(Ticks); 6105 until (Ticks - Ticks0) * 12000 >= MoveTime * PerfFreq; 6106 Ticks0 := Ticks 6107 end; 6108 end; 6109 if Restore then 6110 begin 6111 BitBlt(Buffer.Canvas.Handle, 0, 0, xRange, yRange, 6112 offscreen.Canvas.Handle, xMin, yMin, SRCCOPY); 6113 PaintBufferToScreen(xMin, yMin, xRange, yRange); 6114 end; 6115 BlinkTime := -1; 6116 Timer1.Enabled := true; 6117 end; 6118 6119 procedure TMainScreen.MoveToLoc(Loc: integer; CheckSuicide: boolean); 6120 // path finder: move focused unit to loc, start multi-turn goto if too far 6121 var 6122 uix, i, MoveOptions, NextLoc, MoveResult: integer; 6123 MoveAdviceData: TMoveAdviceData; 6124 StopReason: (None, Arrived, Dead, NoTime, EnemySpotted, MoveError); 6125 begin 6126 if MyUn[UnFocus].Job > jNone then 6127 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 6128 if GetMoveAdvice(UnFocus, Loc, MoveAdviceData) >= rExecuted then 6129 begin 6130 uix := UnFocus; 6131 StopReason := None; 6132 repeat 6133 for i := 0 to MoveAdviceData.nStep - 1 do 6134 begin 6135 if i = MoveAdviceData.nStep - 1 then 6136 MoveOptions := muAutoNext 6137 else 6138 MoveOptions := 0; 6139 NextLoc := dLoc(MyUn[uix].Loc, MoveAdviceData.dx[i], 6140 MoveAdviceData.dy[i]); 6141 if (NextLoc = Loc) or (Loc = maNextCity) and 6142 (MyMap[NextLoc] and fCity <> 0) then 6143 StopReason := Arrived; 6144 if not CheckSuicide and (NextLoc = Loc) then 6145 MoveOptions := MoveOptions or muNoSuicideCheck; 6146 MoveResult := MoveUnit(MoveAdviceData.dx[i], MoveAdviceData.dy[i], 6147 MoveOptions); 6148 if MoveResult < rExecuted then 6149 StopReason := MoveError 6150 else if MoveResult and rUnitRemoved <> 0 then 6151 StopReason := Dead 6152 else if (StopReason = None) and (MoveResult and rEnemySpotted <> 0) 6153 then 6154 StopReason := EnemySpotted; 6155 if StopReason <> None then 6156 Break; 6157 end; 6158 if (StopReason = None) and 6159 ((MoveAdviceData.nStep < 25) or 6160 (MyRO.Wonder[woShinkansen].EffectiveOwner <> me)) then 6161 StopReason := NoTime; 6162 if StopReason <> None then 6163 Break; 6164 if GetMoveAdvice(UnFocus, Loc, MoveAdviceData) < rExecuted then 6165 begin 6166 assert(false); 6167 Break 6168 end 6169 until false; 6170 6171 case StopReason of 6172 None: 6173 assert(false); 6174 Arrived: 6175 MyUn[uix].Status := MyUn[uix].Status and ($FFFF - usGoto); 6176 Dead: 6177 if UnFocus < 0 then 6178 NextUnit(UnStartLoc, false); 6179 else 6180 begin // multi-turn goto 6181 if Loc = maNextCity then 6182 MyUn[uix].Status := MyUn[uix].Status and 6183 ($FFFF - usStay - usRecover) or usGoto + $7FFF shl 16 6184 else 6185 MyUn[uix].Status := MyUn[uix].Status and 6186 ($FFFF - usStay - usRecover) or usGoto + Loc shl 16; 6187 PaintLoc(MyUn[uix].Loc); 6188 if (StopReason = NoTime) and (UnFocus = uix) then 6189 begin 6190 MyUn[uix].Status := MyUn[uix].Status and not usWaiting; 6191 NextUnit(UnStartLoc, true) 6192 end; 2664 6193 end 2665 else if not idle then 2666 if Command=cShowCityChanged then 2667 Sleep(MoveTime*WaitAfterShowMove div 16) 2668 else if (Command=cShowUnitChanged) 2669 and (MyMap[integer(Data)] and fUnit<>0) then 2670 Sleep(MoveTime*WaitAfterShowMove div 32) 2671 end // if CurrentMoveInfo.DoShow 2672 else MapValid:=false; 6194 end 6195 end 6196 end; 6197 6198 procedure TMainScreen.PanelBoxMouseDown(Sender: TObject; 6199 Button: TMouseButton; Shift: TShiftState; x, y: integer); 6200 var 6201 i, xMouse, MouseLoc, p1: integer; 6202 begin 6203 if GameMode = cMovie then 6204 exit; 6205 6206 if Button = mbLeft then 6207 begin 6208 if (x >= xMini + 2) and (y >= yMini + 2) and (x < xMini + 2 + 2 * G.lx) 6209 and (y < yMini + 2 + G.ly) then 6210 if ssShift in Shift then 6211 begin 6212 xMouse := (xwMini + (x - (xMini + 2) + MapWidth div (xxt * 2) + 6213 G.lx) div 2) mod G.lx; 6214 MouseLoc := xMouse + G.lx * (y - (yMini + 2)); 6215 if MyMap[MouseLoc] and fTerrain <> fUNKNOWN then 6216 begin 6217 p1 := MyRO.Territory[MouseLoc]; 6218 if (p1 = me) or (p1 >= 0) and (MyRO.Treaty[p1] >= trNone) then 6219 NatStatDlg.ShowNewContent(wmPersistent, p1); 6220 end 6221 end 6222 else 6223 begin 6224 if CityDlg.Visible then 6225 CityDlg.Close; 6226 if UnitStatDlg.Visible then 6227 UnitStatDlg.Close; 6228 Tracking := true; 6229 PanelBoxMouseMove(Sender, Shift + [ssLeft], x, y); 6230 end 6231 else if (ClientMode <> cEditMap) and (x >= ClientWidth - xPalace) and 6232 (y >= yPalace) and (x < ClientWidth - xPalace + xSizeBig) and 6233 (y < yPalace + ySizeBig) then 6234 begin 6235 InitPopup(StatPopup); 6236 if FullScreen then 6237 StatPopup.Popup(Left + ClientWidth - xPalace + xSizeBig + 2, 6238 Top + ClientHeight - PanelHeight + yPalace - 1) 6239 else 6240 StatPopup.Popup(Left + ClientWidth - xPalace + 6, 6241 Top + ClientHeight - PanelHeight + yPalace + ySizeBig + 6242 GetSystemMetrics(SM_CYCAPTION) + 3) 6243 end 6244 (* else if (x>=xAdvisor-3) and (y>=yAdvisor-3) 6245 and (x<xAdvisor+16+3) and (y<yAdvisor+16+3) and HaveStrategyAdvice then 6246 AdviceBtnClick *) 6247 else if (x >= xTroop + 1) and (y >= yTroop + 1) and 6248 (x < xTroop + TrRow * TrPitch) and (y <= yTroop + 55) then 6249 begin 6250 i := (x - xTroop - 1) div TrPitch; 6251 if trix[i] >= 0 then 6252 if ClientMode = cEditMap then 6253 begin 6254 BrushType := trix[i]; 6255 PanelPaint 6256 end 6257 else if (TroopLoc >= 0) then 6258 if MyMap[TroopLoc] and fOwned <> 0 then 6259 begin 6260 if ssShift in Shift then 6261 UnitStatDlg.ShowNewContent_OwnModel(wmPersistent, 6262 MyUn[trix[i]].mix) 6263 else if not supervising and (ClientMode < scContact) and 6264 (x - xTroop - 1 - i * TrPitch >= 60 - 20) and 6265 (y >= yTroop + 35) and 6266 ((MyUn[trix[i]].Job > jNone) or (MyUn[trix[i]].Status and 6267 (usStay or usRecover or usGoto) <> 0)) then 6268 begin // wake up 6269 MyUn[trix[i]].Status := MyUn[trix[i]].Status and 6270 ($FFFF - usStay - usRecover - usGoto - usEnhance) or 6271 usWaiting; 6272 if MyUn[trix[i]].Job > jNone then 6273 Server(sStartJob + jNone shl 4, me, trix[i], nil^); 6274 if (UnFocus < 0) and not CityDlg.Visible then 6275 begin 6276 SetUnFocus(trix[i]); 6277 SetTroopLoc(MyUn[trix[i]].Loc); 6278 FocusOnLoc(TroopLoc, flRepaintPanel) 6279 end 6280 else 6281 begin 6282 if CityDlg.Visible and (CityDlg.RestoreUnFocus < 0) then 6283 CityDlg.RestoreUnFocus := trix[i]; 6284 PanelPaint; 6285 end 6286 end 6287 else if (ClientMode < scContact) then 6288 begin 6289 if supervising then 6290 UnitStatDlg.ShowNewContent_OwnUnit(wmPersistent, trix[i]) 6291 else if CityDlg.Visible then 6292 begin 6293 CityDlg.CloseAction := None; 6294 CityDlg.Close; 6295 SumCities(TaxSum, ScienceSum); 6296 SetUnFocus(trix[i]); 6297 end 6298 else 6299 begin 6300 DestinationMarkON := false; 6301 PaintDestination; 6302 UnFocus := trix[i]; 6303 UnStartLoc := TroopLoc; 6304 BlinkTime := 0; 6305 BlinkON := false; 6306 PaintLoc(TroopLoc); 6307 end; 6308 if UnFocus >= 0 then 6309 begin 6310 UnitInfoBtn.Visible := true; 6311 UnitBtn.Visible := true; 6312 TurnComplete := false; 6313 EOT.ButtonIndex := eotGray; 6314 end; 6315 CheckTerrainBtnVisible; 6316 PanelPaint; 6317 end 6318 end 6319 else if Server(sGetUnits, me, TroopLoc, TrCnt) >= rExecuted then 6320 if ssShift in Shift then 6321 UnitStatDlg.ShowNewContent_EnemyModel(wmPersistent, 6322 MyRO.EnemyUn[MyRO.nEnemyUn + trix[i]].emix) // model info 6323 else 6324 UnitStatDlg.ShowNewContent_EnemyUnit(wmPersistent, 6325 MyRO.nEnemyUn + trix[i]); // unit info 6326 end 6327 end 6328 end; 6329 6330 procedure TMainScreen.SetTroopLoc(Loc: integer); 6331 var 6332 trixFocus, uix, uixDefender: integer; 6333 Prio: boolean; 6334 begin 6335 TroopLoc := Loc; 6336 TrRow := (xRightPanel + 10 - xTroop - GetSystemMetrics(SM_CXVSCROLL) - 19) 6337 div TrPitch; 6338 TrCnt := 0; 6339 trixFocus := -1; 6340 if ClientMode = cEditMap then 6341 TrCnt := nBrushTypes 6342 else if (Loc >= 0) and (MyMap[Loc] and fUnit <> 0) then 6343 if MyMap[Loc] and fOwned <> 0 then 6344 begin // count own units here 6345 Server(sGetDefender, me, TroopLoc, uixDefender); 6346 for Prio := true downto false do 6347 for uix := 0 to MyRO.nUn - 1 do 6348 if ((uix = uixDefender) = Prio) and (MyUn[uix].Loc = Loc) then 6349 begin 6350 if uix = UnFocus then 6351 trixFocus := TrCnt; 6352 inc(TrCnt); 6353 end 6354 end 6355 else // count enemy units here 6356 Server(sGetUnits, me, Loc, TrCnt); 6357 if TrCnt = 0 then 6358 InitPVSB(sb, 0, 1) 6359 else 6360 begin 6361 InitPVSB(sb, (TrCnt + TrRow - 1) div TrRow - 1, 1); 6362 with sb.si do 6363 if (nMax >= integer(nPage)) and (trixFocus >= 0) then 6364 begin 6365 sb.si.npos := trixFocus div TrRow; 6366 sb.si.FMask := SIF_POS; 6367 SetScrollInfo(sb.h, SB_CTL, sb.si, true); 6368 end 6369 end 6370 end; 6371 6372 (* procedure TMainScreen.ShowMoveHint(ToLoc: integer; Force: boolean = false); 6373 var 6374 Step,Loc,x0,y0,xs,ys: integer; 6375 Info: string; 6376 InfoSize: TSize; 6377 MoveAdvice: TMoveAdviceData; 6378 begin 6379 if (ToLoc<0) or (ToLoc>=G.lx*G.ly) 6380 or (UnFocus<0) or (MyUn[UnFocus].Loc=ToLoc) then 6381 ToLoc:=-1 6382 else 6383 begin 6384 MoveAdvice.ToLoc:=ToLoc; 6385 MoveAdvice.MoreTurns:=0; 6386 MoveAdvice.MaxHostile_MovementLeft:=MyUn[UnFocus].Health-50; 6387 if Server(sGetMoveAdvice,me,UnFocus,MoveAdvice)<rExecuted then 6388 ToLoc:=-1 2673 6389 end; 2674 2675 cShowMoving,cShowCapturing: 2676 if (idle and (NewPlayer=me) 2677 or not idle and not skipped and (TShowMove(Data).emix<>$FFFF)) 2678 and not ((GameMode=cMovie) and (MovieSpeed=4)) then 2679 begin 2680 assert(NewPlayer=me); 2681 if not idle or (GameMode=cMovie) then 2682 Application.ProcessMessages; 2683 with TShowMove(Data) do 2684 begin 2685 CurrentMoveInfo.DoShow:=false; 2686 if not idle and (Tribe[Owner].ModelPicture[mix].HGr=0) then 2687 InitEnemyModel(emix); 2688 2689 ToLoc:=dLoc(FromLoc,dx,dy); 2690 if idle then 2691 begin // own unit -- make discovered land visible 2692 assert(Owner=me); // no foreign moves during my turn! 2693 CurrentMoveInfo.DoShow:=not mEffectiveMovesOnly.Checked 2694 or (Command=cShowCapturing); 2695 if CurrentMoveInfo.DoShow then 6390 if (ToLoc=MoveHintToLoc) and not Force then exit; 6391 if (ToLoc<>MoveHintToLoc) and (MoveHintToLoc>=0) then 6392 begin invalidate; update end; // clear old hint from screen 6393 MoveHintToLoc:=ToLoc; 6394 if ToLoc<0 then exit; 6395 6396 with canvas do 6397 begin 6398 Pen.Color:=$80C0FF; 6399 Pen.Width:=3; 6400 Loc:=MyUn[UnFocus].Loc; 6401 for Step:=0 to MoveAdvice.nStep do 6402 begin 6403 y0:=(Loc+G.lx*1024) div G.lx -1024; 6404 x0:=(Loc+(y0 and 1+G.lx*1024) div 2) mod G.lx; 6405 xs:=(x0-xw)*66+y0 and 1*33-G.lx*66; 6406 while abs(2*(xs+G.lx*66)-MapWidth)<abs(2*xs-MapWidth) do 6407 inc(xs,G.lx*66); 6408 ys:=(y0-yw)*16; 6409 if Step=0 then moveto(xs+33,ys+16) 6410 else lineto(xs+33,ys+16); 6411 if Step<MoveAdvice.nStep then 6412 Loc:=dLoc(Loc,MoveAdvice.dx[Step],MoveAdvice.dy[Step]); 6413 end; 6414 Brush.Color:=$80C0FF; 6415 Info:=' '+inttostr(88)+' '; 6416 InfoSize:=TextExtent(Info); 6417 TextOut(xs+33-InfoSize.cx div 2, ys+16-InfoSize.cy div 2, Info); 6418 Brush.Style:=bsClear; 6419 end 6420 end; *) 6421 6422 procedure TMainScreen.SetDebugMap(p: integer); 6423 begin 6424 IsoEngine.pDebugMap := p; 6425 IsoEngine.Options := IsoEngine.Options and not(1 shl moLocCodes); 6426 mLocCodes.Checked := false; 6427 MapValid := false; 6428 MainOffscreenPaint; 6429 end; 6430 6431 procedure TMainScreen.SetViewpoint(p: integer); 6432 var 6433 i: integer; 6434 begin 6435 if supervising and (G.RO[0].Turn > 0) and 6436 ((p = 0) or (1 shl p and G.RO[0].Alive <> 0)) then 6437 begin 6438 for i := 0 to Screen.FormCount - 1 do 6439 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 6440 then 6441 Screen.Forms[i].Close; // close windows 6442 ItsMeAgain(p); 6443 SumCities(TaxSum, ScienceSum); 6444 for i := 0 to MyRO.nModel - 1 do 6445 if Tribe[me].ModelPicture[i].HGr = 0 then 6446 InitMyModel(i, true); 6447 6448 SetTroopLoc(-1); 6449 PanelPaint; 6450 MapValid := false; 6451 PaintAllMaps; 6452 end 6453 end; 6454 6455 procedure TMainScreen.FormKeyDown(Sender: TObject; var Key: word; 6456 Shift: TShiftState); 6457 6458 procedure MenuClick_Check(Popup: TPopupMenu; Item: TMenuItem); 6459 begin 6460 InitPopup(Popup); 6461 if Item.Visible and Item.Enabled then 6462 MenuClick(Item); 6463 end; 6464 6465 var 6466 dx, dy: integer; 6467 time0, time1: int64; 6468 begin 6469 if GameMode = cMovie then 6470 begin 6471 case Key of 6472 VK_F4: 6473 MenuClick_Check(StatPopup, mScienceStat); 6474 VK_F6: 6475 MenuClick_Check(StatPopup, mDiagram); 6476 VK_F7: 6477 MenuClick_Check(StatPopup, mWonders); 6478 VK_F8: 6479 MenuClick_Check(StatPopup, mShips); 6480 end; 6481 exit; 6482 end; 6483 6484 if not idle then 6485 exit; 6486 6487 if ClientMode = cEditMap then 6488 begin 6489 if Shift = [ssCtrl] then 6490 case char(Key) of 6491 (* 'A': 6492 begin // auto symmetry 6493 Server($7F0,me,0,nil^); 6494 MapValid:=false; 6495 PaintAll; 6496 end; 6497 'B': 6498 begin // land mass 6499 dy:=0; 6500 for dx:=G.lx to G.lx*(G.ly-1)-1 do 6501 if MyMap[dx] and fTerrain>=fGrass then inc(dy); 6502 dy:=dy 6503 end; *) 6504 'Q': 6505 MenuClick(mResign); 6506 'R': 6507 MenuClick(mRandomMap); 6508 end 6509 else if Shift = [] then 6510 case char(Key) of 6511 char(VK_F1): 6512 MenuClick(mHelp); 6513 end; 6514 exit; 6515 end; 6516 6517 if Shift = [ssAlt] then 6518 case char(Key) of 6519 '0': 6520 SetDebugMap(-1); 6521 '1' .. '9': 6522 SetDebugMap(ord(Key) - 48); 6523 end 6524 else if Shift = [ssCtrl] then 6525 case char(Key) of 6526 'J': 6527 MenuClick(mJump); 6528 'K': 6529 mShowClick(mDebugMap); 6530 'L': 6531 mShowClick(mLocCodes); 6532 'M': 6533 if LogDlg.Visible then 6534 LogDlg.Close 6535 else 6536 LogDlg.Show; 6537 'N': 6538 mNamesClick(mNames); 6539 'Q': 6540 MenuClick_Check(GamePopup, mResign); 6541 'R': 6542 MenuClick(mRun); 6543 '0' .. '9': 2696 6544 begin 2697 if GameMode=cMovie then 6545 if ord(Key) - 48 = me then 6546 SetViewpoint(0) 6547 else 6548 SetViewpoint(ord(Key) - 48); 6549 end; 6550 ' ': 6551 begin // test map repaint time 6552 QueryPerformanceCounter(time0); 6553 MapValid := false; 6554 MainOffscreenPaint; 6555 QueryPerformanceCounter(time1); 6556 SimpleMessage(Format('Map repaint time: %.3f ms', 6557 [{$IFDEF VER100}(time1.LowPart - time0.LowPart) 6558 {$ELSE}(time1 - time0){$ENDIF} * 1000.0 / PerfFreq])); 6559 end 6560 end 6561 else if Shift = [] then 6562 case char(Key) of 6563 char(VK_F1): 6564 MenuClick(mHelp); 6565 char(VK_F2): 6566 MenuClick_Check(StatPopup, mUnitStat); 6567 char(VK_F3): 6568 MenuClick_Check(StatPopup, mCityStat); 6569 char(VK_F4): 6570 MenuClick_Check(StatPopup, mScienceStat); 6571 char(VK_F5): 6572 MenuClick_Check(StatPopup, mEUnitStat); 6573 char(VK_F6): 6574 MenuClick_Check(StatPopup, mDiagram); 6575 char(VK_F7): 6576 MenuClick_Check(StatPopup, mWonders); 6577 char(VK_F8): 6578 MenuClick_Check(StatPopup, mShips); 6579 char(VK_F9): 6580 MenuClick_Check(StatPopup, mNations); 6581 char(VK_F10): 6582 MenuClick_Check(StatPopup, mEmpire); 6583 char(VK_ADD): 6584 EndTurn; 6585 '1': 6586 MapBtnClick(MapBtn0); 6587 '2': 6588 MapBtnClick(MapBtn1); 6589 '3': 6590 MapBtnClick(MapBtn4); 6591 '4': 6592 MapBtnClick(MapBtn5); 6593 '5': 6594 MapBtnClick(MapBtn6); 6595 'T': 6596 MenuClick(mTechTree); 6597 'W': 6598 MenuClick(mWait); 6599 end; 6600 6601 if UnFocus >= 0 then 6602 if Shift = [ssCtrl] then 6603 case char(Key) of 6604 'C': 6605 MenuClick_Check(UnitPopup, mCancel); 6606 'D': 6607 MenuClick(mDisband); 6608 'P': 6609 MenuClick_Check(UnitPopup, mPillage); 6610 'T': 6611 MenuClick_Check(UnitPopup, mSelectTransport); 6612 end 6613 else if Shift = [] then 6614 case char(Key) of 6615 ' ': 6616 MenuClick(mNoOrders); 6617 'A': 6618 MenuClick_Check(TerrainPopup, mAirBase); 6619 'B': 6620 MenuClick_Check(UnitPopup, mCity); 6621 'C': 6622 MenuClick(mCentre); 6623 'E': 2698 6624 begin 2699 if MovieSpeed=3 then AnimationSpeed:=4 2700 else if MovieSpeed=2 then AnimationSpeed:=8 2701 else AnimationSpeed:=16; 6625 InitPopup(TerrainPopup); 6626 if mEnhance.Visible and mEnhance.Enabled then 6627 MenuClick(mEnhance) 6628 else 6629 MenuClick(mEnhanceDef) 6630 end; 6631 'F': 6632 MenuClick_Check(TerrainPopup, mFort); 6633 'G': 6634 MenuClick_Check(UnitPopup, mGoOn); 6635 'H': 6636 MenuClick_Check(UnitPopup, mHome); 6637 'I': 6638 if JobTest(UnFocus, jFarm, [eTreaty]) then 6639 MenuClick(mFarm) 6640 else if JobTest(UnFocus, jClear, [eTreaty]) then 6641 MenuClick(mClear) 6642 else 6643 MenuClick_Check(TerrainPopup, mIrrigation); 6644 'L': 6645 MenuClick_Check(UnitPopup, mLoad); 6646 'M': 6647 if JobTest(UnFocus, jAfforest, [eTreaty]) then 6648 MenuClick(mAfforest) 6649 else 6650 MenuClick_Check(TerrainPopup, mMine); 6651 'N': 6652 MenuClick_Check(TerrainPopup, mCanal); 6653 'O': 6654 MenuClick_Check(TerrainPopup, MTrans); 6655 'P': 6656 MenuClick_Check(TerrainPopup, mPollution); 6657 'R': 6658 if JobTest(UnFocus, jRR, [eTreaty]) then 6659 MenuClick(mRR) 6660 else 6661 MenuClick_Check(TerrainPopup, mRoad); 6662 'S': 6663 MenuClick(mStay); 6664 'U': 6665 MenuClick_Check(UnitPopup, mUnload); 6666 'V': 6667 MenuClick_Check(UnitPopup, mRecover); 6668 'Z': 6669 MenuClick_Check(UnitPopup, mUtilize); 6670 #33 .. #40, #97 .. #100, #102 .. #105: 6671 begin { arrow keys } 6672 DestinationMarkON := false; 6673 PaintDestination; 6674 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 6675 ($FFFF - usStay - usRecover - usGoto - usEnhance) or 6676 usWaiting; 6677 case Key of 6678 VK_NUMPAD1, VK_END: 6679 begin 6680 dx := -1; 6681 dy := 1 6682 end; 6683 VK_NUMPAD2, VK_DOWN: 6684 begin 6685 dx := 0; 6686 dy := 2 6687 end; 6688 VK_NUMPAD3, VK_NEXT: 6689 begin 6690 dx := 1; 6691 dy := 1 6692 end; 6693 VK_NUMPAD4, VK_LEFT: 6694 begin 6695 dx := -2; 6696 dy := 0 6697 end; 6698 VK_NUMPAD6, VK_RIGHT: 6699 begin 6700 dx := 2; 6701 dy := 0 6702 end; 6703 VK_NUMPAD7, VK_HOME: 6704 begin 6705 dx := -1; 6706 dy := -1 6707 end; 6708 VK_NUMPAD8, VK_UP: 6709 begin 6710 dx := 0; 6711 dy := -2 6712 end; 6713 VK_NUMPAD9, VK_PRIOR: 6714 begin 6715 dx := 1; 6716 dy := -1 6717 end; 6718 end; 6719 MoveUnit(dx, dy, muAutoNext) 6720 end; 6721 end 6722 end; 6723 6724 procedure TMainScreen.MenuClick(Sender: TObject); 6725 6726 function DoJob(j0: integer): integer; 6727 var 6728 Loc0, Movement0: integer; 6729 begin 6730 with MyUn[UnFocus] do 6731 begin 6732 DestinationMarkON := false; 6733 PaintDestination; 6734 Loc0 := Loc; 6735 Movement0 := Movement; 6736 if j0 < 0 then 6737 result := ProcessEnhancement(UnFocus, MyData.EnhancementJobs) 6738 // terrain enhancement 6739 else 6740 result := Server(sStartJob + j0 shl 4, me, UnFocus, nil^); 6741 if result >= rExecuted then 6742 begin 6743 if result = eDied then 6744 UnFocus := -1; 6745 PaintLoc(Loc0); 6746 if UnFocus >= 0 then 6747 begin 6748 if (j0 < 0) and (result <> eJobDone) then 6749 // multi-turn terrain enhancement 6750 Status := Status and ($FFFF - usStay - usRecover - usGoto) or 6751 usEnhance 6752 else 6753 Status := Status and 6754 ($FFFF - usStay - usRecover - usGoto - usEnhance); 6755 if (Job <> jNone) or (Movement0 < 100) then 6756 begin 6757 Status := Status and not usWaiting; 6758 NextUnit(UnStartLoc, true); 2702 6759 end 6760 else 6761 PanelPaint 6762 end 2703 6763 else 6764 NextUnit(UnStartLoc, true); 6765 end 6766 end; 6767 case result of 6768 eNoBridgeBuilding: 6769 SoundMessage(Phrases.Lookup('NOBB'), 'INVALID'); 6770 eNoCityTerrain: 6771 SoundMessage(Phrases.Lookup('NOCITY'), 'INVALID'); 6772 eTreaty: 6773 SoundMessage(Tribe[MyRO.Territory[Loc0]].TPhrase('PEACE_NOWORK'), 6774 'NOMOVE_TREATY'); 6775 else 6776 if result < rExecuted then 6777 Play('INVALID') 6778 end 6779 end; 6780 6781 var 6782 i, uix, NewFocus, Loc0, OldMaster, Destination, cix, cixOldHome, 6783 ServerResult: integer; 6784 AltGovs, Changed: boolean; 6785 QueryText: string; 6786 6787 begin 6788 if Sender = mResign then 6789 if ClientMode = cEditMap then 6790 begin 6791 if Edited then 6792 begin 6793 QueryText := Phrases.Lookup('MAP_CLOSE'); 6794 case SimpleQuery(mkYesNoCancel, QueryText, '') of 6795 mrIgnore: 6796 Server(sAbandonMap, me, 0, nil^); 6797 mrOK: 6798 Server(sSaveMap, me, 0, nil^); 6799 end 6800 end 6801 else 6802 Server(sAbandonMap, me, 0, nil^) 6803 end 6804 else 6805 begin 6806 if Server(sGetGameChanged, 0, 0, nil^) = eOK then 6807 begin 6808 QueryText := Phrases.Lookup('RESIGN'); 6809 case SimpleQuery(mkYesNoCancel, QueryText, '') of 6810 mrIgnore: 6811 Server(sResign, 0, 0, nil^); 6812 mrOK: 6813 Server(sBreak, 0, 0, nil^) 6814 end 6815 end 6816 else 6817 Server(sResign, 0, 0, nil^) 6818 end 6819 else if Sender = mEmpire then 6820 RatesDlg.ShowNewContent(wmPersistent) 6821 else if Sender = mRevolution then 6822 begin 6823 AltGovs := false; 6824 for i := 2 to nGov - 1 do 6825 if (GovPreq[i] <> preNA) and 6826 ((GovPreq[i] = preNone) or (MyRO.Tech[GovPreq[i]] >= tsApplicable)) 6827 then 6828 AltGovs := true; 6829 6830 if not AltGovs then 6831 SoundMessage(Phrases.Lookup('NOALTGOVS'), 'MSG_DEFAULT') 6832 else 6833 begin 6834 Changed := false; 6835 if MyRO.Happened and phChangeGov <> 0 then 6836 begin 6837 ModalSelectDlg.ShowNewContent(wmModal, kGov); 6838 if ModalSelectDlg.result >= 0 then 6839 begin 6840 Play('NEWGOV'); 6841 Server(sSetGovernment, me, ModalSelectDlg.result, nil^); 6842 CityOptimizer_BeginOfTurn; 6843 Changed := true; 6844 end 6845 end 6846 else 6847 with MessgExDlg do 6848 begin // revolution! 6849 MessgText := Tribe[me].TPhrase('REVOLUTION'); 6850 Kind := mkYesNo; 6851 IconKind := mikPureIcon; 6852 IconIndex := 72; // anarchy palace 6853 ShowModal; 6854 if ModalResult = mrOK then 2704 6855 begin 2705 if mVeryFastMoves.Checked then AnimationSpeed:=4 2706 else if mFastMoves.Checked then AnimationSpeed:=8 2707 else AnimationSpeed:=16; 2708 end; 2709 with MyModel[mix] do 6856 Play('REVOLUTION'); 6857 Server(sRevolution, me, 0, nil^); 6858 Changed := true; 6859 if NatStatDlg.Visible then 6860 NatStatDlg.Close; 6861 if CityDlg.Visible then 6862 CityDlg.Close; 6863 end 6864 end; 6865 if Changed then 6866 UpdateViews(true); 6867 end 6868 end 6869 else if Sender = mWebsite then 6870 ShellExecute(Handle, 'open', 'http://c-evo.org', '', '', SW_SHOWNORMAL) 6871 else if Sender = mRandomMap then 6872 begin 6873 if not Edited or (SimpleQuery(mkYesNo, Phrases.Lookup('MAP_RANDOM'), '') 6874 = mrOK) then 6875 begin 6876 Server(sRandomMap, me, 0, nil^); 6877 Edited := true; 6878 MapValid := false; 6879 PaintAllMaps; 6880 end 6881 end 6882 else if Sender = mJump then 6883 begin 6884 if supervising then 6885 Jump[0] := 20 6886 else 6887 Jump[me] := 20; 6888 EndTurn(true); 6889 end 6890 else if Sender = mRun then 6891 begin 6892 if supervising then 6893 Jump[0] := 999999 6894 else 6895 Jump[me] := 999999; 6896 EndTurn(true); 6897 end 6898 else if Sender = mEnhanceDef then 6899 begin 6900 if UnFocus >= 0 then 6901 EnhanceDlg.ShowNewContent(wmPersistent, 6902 MyMap[MyUn[UnFocus].Loc] and fTerrain) 6903 else 6904 EnhanceDlg.ShowNewContent(wmPersistent) 6905 end 6906 else if Sender = mCityTypes then 6907 CityTypeDlg.ShowNewContent(wmModal) 6908 // must be modal because types are not saved before closing 6909 else if Sender = mUnitStat then 6910 begin 6911 if G.Difficulty[me] > 0 then 6912 ListDlg.ShowNewContent_MilReport(wmPersistent, me) 6913 else 6914 begin 6915 i := 1; 6916 while (i < nPl) and (1 shl i and MyRO.Alive = 0) do 6917 inc(i); 6918 if i < nPl then 6919 ListDlg.ShowNewContent_MilReport(wmPersistent, i); 6920 end; 6921 end 6922 else if Sender = mEUnitStat then 6923 begin 6924 if MyRO.nEnemyModel > 0 then 6925 ListDlg.ShowNewContent(wmPersistent, kAllEModels); 6926 end 6927 else if Sender = mCityStat then 6928 ListDlg.ShowNewContent(wmPersistent, kCities) 6929 else if Sender = mScienceStat then 6930 ListDlg.ShowNewContent(wmPersistent, kScience) 6931 else if Sender = mNations then 6932 NatStatDlg.ShowNewContent(wmPersistent) 6933 else if Sender = mHelp then 6934 if ClientMode = cEditMap then 6935 HelpDlg.ShowNewContent(wmPersistent, hkText, 6936 HelpDlg.TextIndex('MAPEDIT')) 6937 else 6938 HelpDlg.ShowNewContent(wmPersistent, hkMisc, miscMain) 6939 else if Sender = mTechTree then 6940 TechTreeDlg.ShowModal 6941 else if Sender = mWonders then 6942 WondersDlg.ShowNewContent(wmPersistent) 6943 else if Sender = mDiagram then 6944 DiaDlg.ShowNewContent_Charts(wmPersistent) 6945 else if Sender = mShips then 6946 DiaDlg.ShowNewContent_Ship(wmPersistent) 6947 else if Sender = mWait then 6948 begin 6949 if UnFocus >= 0 then 6950 begin 6951 DestinationMarkON := false; 6952 PaintDestination; 6953 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 6954 ($FFFF - usStay - usRecover - usGoto - usEnhance) or usWaiting; 6955 end; 6956 NextUnit(-1, false); 6957 end 6958 else if UnFocus >= 0 then 6959 with MyUn[UnFocus] do 6960 if Sender = mGoOn then 6961 begin 6962 if Status shr 16 = $7FFF then 6963 Destination := maNextCity 6964 else 6965 Destination := Status shr 16; 6966 Status := Status and not(usStay or usRecover) or usWaiting; 6967 MoveToLoc(Destination, true); 6968 end 6969 else if Sender = mHome then 6970 if MyMap[Loc] and fCity <> 0 then 6971 begin 6972 cixOldHome := Home; 6973 if Server(sSetUnitHome, me, UnFocus, nil^) >= rExecuted then 2710 6974 begin 2711 if (Kind=mkDiplomat) or (Domain=dAir) 2712 or (Cap[mcRadar]+Cap[mcCarrier]+Cap[mcAcademy]>0) 2713 or (MyMap[ToLoc] and fTerrain=fMountains) 2714 or (MyMap[ToLoc] and fTerImp=tiFort) 2715 or (MyMap[ToLoc] and fTerImp=tiBase) then 2716 CurrentMoveInfo.AfterMovePaintRadius:=2 2717 else CurrentMoveInfo.AfterMovePaintRadius:=1; 2718 if (MyRO.Wonder[woShinkansen].EffectiveOwner=me) 2719 and (Domain=dGround) 2720 and (MyMap[FromLoc] and (fRR or fCity)<>0) 2721 and (MyMap[ToLoc] and (fRR or fCity)<>0) 2722 and (Flags and umPlaneUnloading=0) then 2723 AnimationSpeed:=4; 2724 ShowMoveDomain:=Domain; 2725 IsAlpine:= Cap[mcAlpine]>0; 6975 CityOptimizer_CityChange(cixOldHome); 6976 CityOptimizer_CityChange(Home); 6977 UpdateViews(true); 6978 end 6979 else 6980 Play('INVALID'); 6981 end 6982 else 6983 begin 6984 Status := Status and not(usStay or usRecover or usEnhance); 6985 MoveToLoc(maNextCity, true) 6986 end 6987 else if Sender = mCentre then 6988 begin 6989 Centre(Loc); 6990 PaintAllMaps 6991 end 6992 else if Sender = mCity then 6993 begin 6994 Loc0 := Loc; 6995 if MyMap[Loc] and fCity = 0 then 6996 begin // build city 6997 if DoJob(jCity) = eCity then 6998 begin 6999 MapValid := false; 7000 PaintAll; 7001 ZoomToCity(Loc0, true, chFounded); 2726 7002 end 2727 7003 end 7004 else 7005 begin 7006 CityOptimizer_BeforeRemoveUnit(UnFocus); 7007 ServerResult := Server(sAddToCity, me, UnFocus, nil^); 7008 if ServerResult >= rExecuted then 7009 begin 7010 cix := MyRO.nCity - 1; 7011 while (cix >= 0) and (MyCity[cix].Loc <> Loc0) do 7012 dec(cix); 7013 assert(cix >= 0); 7014 CityOptimizer_CityChange(cix); 7015 CityOptimizer_AfterRemoveUnit; // does nothing here 7016 SetTroopLoc(Loc0); 7017 UpdateViews(true); 7018 DestinationMarkON := false; 7019 PaintDestination; 7020 UnFocus := -1; 7021 PaintLoc(Loc0); 7022 NextUnit(UnStartLoc, true); 7023 end 7024 else if ServerResult = eMaxSize then 7025 SimpleMessage(Phrases.Lookup('ADDTOMAXSIZE')); 7026 end 2728 7027 end 7028 else if Sender = mRoad then 7029 DoJob(jRoad) 7030 else if Sender = mRR then 7031 DoJob(jRR) 7032 else if Sender = mClear then 7033 DoJob(jClear) 7034 else if Sender = mIrrigation then 7035 DoJob(jIrr) 7036 else if Sender = mFarm then 7037 DoJob(jFarm) 7038 else if Sender = mAfforest then 7039 DoJob(jAfforest) 7040 else if Sender = mMine then 7041 DoJob(jMine) 7042 else if Sender = mCanal then 7043 DoJob(jCanal) 7044 else if Sender = MTrans then 7045 DoJob(jTrans) 7046 else if Sender = mFort then 7047 DoJob(jFort) 7048 else if Sender = mAirBase then 7049 DoJob(jBase) 7050 else if Sender = mPollution then 7051 DoJob(jPoll) 7052 else if Sender = mPillage then 7053 DoJob(jPillage) 7054 else if Sender = mEnhance then 7055 DoJob(-1) 7056 else if Sender = mStay then 7057 begin 7058 DestinationMarkON := false; 7059 PaintDestination; 7060 Status := Status and ($FFFF - usRecover - usGoto - usEnhance) 7061 or usStay; 7062 if Job > jNone then 7063 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 7064 NextUnit(UnStartLoc, true) 7065 end 7066 else if Sender = mRecover then 7067 begin 7068 DestinationMarkON := false; 7069 PaintDestination; 7070 Status := Status and ($FFFF - usStay - usGoto - usEnhance) or 7071 usRecover; 7072 if Job > jNone then 7073 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 7074 NextUnit(UnStartLoc, true) 7075 end 7076 else if Sender = mNoOrders then 7077 begin 7078 Status := Status and not usWaiting; 7079 NextUnit(UnStartLoc, true) 7080 end 7081 else if Sender = mCancel then 7082 begin 7083 DestinationMarkON := false; 7084 PaintDestination; 7085 Status := Status and ($FFFF - usRecover - usGoto - usEnhance); 7086 if Job > jNone then 7087 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 7088 end 7089 else if (Sender = mDisband) or (Sender = mUtilize) then 7090 begin 7091 if (Sender = mUtilize) and 7092 not(Server(sRemoveUnit - sExecute, me, UnFocus, nil^) = eUtilized) 7093 then 7094 begin 7095 SimpleMessage(Phrases2.Lookup('SHIP_UTILIZE')); 7096 // freight for colony ship is the only case in which the command is 7097 // available to player though not valid 7098 exit 7099 end; 7100 if (Sender = mUtilize) and (Health < 100) then 7101 if SimpleQuery(mkYesNo, Phrases.Lookup('DAMAGED_UTILIZE'), '') <> mrOK 7102 then 7103 exit; 7104 Loc0 := Loc; 7105 CityOptimizer_BeforeRemoveUnit(UnFocus); 7106 if Server(sRemoveUnit, me, UnFocus, nil^) = eUtilized then 7107 Play('CITY_UTILIZE') 7108 else 7109 Play('DISBAND'); 7110 CityOptimizer_AfterRemoveUnit; 7111 SetTroopLoc(Loc0); 7112 UpdateViews(true); 7113 DestinationMarkON := false; 7114 PaintDestination; 7115 UnFocus := -1; 7116 PaintLoc(Loc0); 7117 NextUnit(UnStartLoc, true); 7118 end 7119 else if Sender = mLoad then 7120 begin 7121 i := Server(sLoadUnit, me, UnFocus, nil^); 7122 if i >= rExecuted then 7123 begin 7124 if MyModel[mix].Domain = dAir then 7125 Play('MOVE_PLANELANDING') 7126 else 7127 Play('MOVE_LOAD'); 7128 DestinationMarkON := false; 7129 PaintDestination; 7130 Status := Status and 7131 ($FFFF - usWaiting - usStay - usRecover - usGoto - usEnhance); 7132 NextUnit(UnStartLoc, true); 7133 end 7134 else if i = eNoTime_Load then 7135 if MyModel[mix].Domain = dAir then 7136 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'), 'NOMOVE_TIME') 7137 else 7138 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 7139 [MovementToString(MyModel[mix].speed)]), 'NOMOVE_TIME'); 7140 end 7141 else if Sender = mUnload then 7142 if Master >= 0 then 7143 begin 7144 OldMaster := Master; 7145 i := Server(sUnloadUnit, me, UnFocus, nil^); 7146 if i >= rExecuted then 7147 begin 7148 if MyModel[mix].Domain = dAir then 7149 Play('MOVE_PLANESTART') 7150 else if (MyModel[MyUn[OldMaster].mix].Domain = dAir) and 7151 (MyMap[Loc] and fCity = 0) and 7152 (MyMap[Loc] and fTerImp <> tiBase) then 7153 Play('MOVE_PARACHUTE') 7154 else 7155 Play('MOVE_UNLOAD'); 7156 Status := Status and not usWaiting; 7157 if MyModel[mix].Domain <> dAir then 7158 NextUnit(Loc, true) 7159 else 7160 PanelPaint 7161 end 7162 else if i = eNoTime_Load then 7163 if MyModel[mix].Domain = dAir then 7164 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'), 'NOMOVE_TIME') 7165 else 7166 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 7167 [MovementToString(MyModel[mix].speed)]), 'NOMOVE_TIME'); 7168 end 7169 else 7170 begin 7171 NewFocus := -1; 7172 uix := UnFocus; 7173 for i := 1 to MyRO.nUn - 1 do 7174 begin 7175 uix := (uix + MyRO.nUn - 1) mod MyRO.nUn; 7176 if (MyUn[uix].Master = UnFocus) and 7177 (MyUn[uix].Movement = integer(MyModel[MyUn[uix].mix].speed)) 7178 then 7179 begin 7180 MyUn[uix].Status := MyUn[uix].Status or usWaiting; 7181 NewFocus := uix 7182 end; 7183 end; 7184 if NewFocus >= 0 then 7185 begin 7186 SetUnFocus(NewFocus); 7187 SetTroopLoc(Loc); 7188 PanelPaint 7189 end 7190 end 7191 else if Sender = mSelectTransport then 7192 Server(sSelectTransport, me, UnFocus, nil^) 7193 end; 7194 7195 procedure TMainScreen.InitPopup(Popup: TPopupMenu); 7196 var 7197 i, p1, Tile, Test: integer; 7198 NoSuper, extended, Multi, NeedSep, HaveCities: boolean; 7199 LastSep, m: TMenuItem; 7200 mox: ^TModel; 7201 begin 7202 NoSuper := not supervising and (1 shl me and MyRO.Alive <> 0); 7203 HaveCities := false; 7204 for i := 0 to MyRO.nCity - 1 do 7205 if MyCity[i].Loc >= 0 then 7206 begin 7207 HaveCities := true; 7208 Break 7209 end; 7210 if Popup = GamePopup then 7211 begin 7212 mTechTree.Visible := ClientMode <> cEditMap; 7213 mResign.Enabled := supervising or (me = 0) and (ClientMode < scContact); 7214 mRandomMap.Visible := (ClientMode = cEditMap) and 7215 (Server(sMapGeneratorRequest, me, 0, nil^) = eOK); 7216 mOptions.Visible := ClientMode <> cEditMap; 7217 mManip.Visible := ClientMode <> cEditMap; 7218 if ClientMode <> cEditMap then 7219 begin 7220 mWaitTurn.Visible := NoSuper; 7221 mRep.Visible := NoSuper; 7222 mRepList.Visible := NoSuper; 7223 mRepScreens.Visible := NoSuper; 7224 N10.Visible := NoSuper; 7225 mOwnMovement.Visible := NoSuper; 7226 mAllyMovement.Visible := NoSuper; 7227 case SoundMode of 7228 smOff: 7229 mSoundOff.Checked := true; 7230 smOn: 7231 mSoundOn.Checked := true; 7232 smOnAlt: 7233 mSoundOnAlt.Checked := true; 7234 end; 7235 7236 for i := 0 to nTestFlags - 1 do 7237 mManip[i].Checked := MyRO.TestFlags and (1 shl i) <> 0; 7238 mManip.Enabled := supervising or (me = 0); 7239 7240 Multi := false; 7241 for p1 := 1 to nPl - 1 do 7242 if G.RO[p1] <> nil then 7243 Multi := true; 7244 mEnemyMovement.Visible := not Multi; 7245 end; 7246 mMacro.Visible := NoSuper and (ClientMode < scContact); 7247 if NoSuper and (ClientMode < scContact) then 7248 begin 7249 mCityTypes.Enabled := false; 7250 // check if city types already usefull: 7251 if MyRO.nCity > 0 then 7252 for i := 28 to nImp - 1 do 7253 if (i <> imTrGoods) and (Imp[i].Kind = ikCommon) and 7254 (Imp[i].Preq <> preNA) and 7255 ((Imp[i].Preq = preNone) or 7256 (MyRO.Tech[Imp[i].Preq] >= tsApplicable)) then 7257 begin 7258 mCityTypes.Enabled := true; 7259 Break 7260 end; 7261 end; 7262 mViewpoint.Visible := (ClientMode <> cEditMap) and supervising; 7263 mViewpoint.Enabled := G.RO[0].Turn > 0; 7264 if supervising then 7265 begin 7266 EmptyMenu(mViewpoint); 7267 for p1 := 0 to nPl - 1 do 7268 if (p1 = 0) or (1 shl p1 and G.RO[0].Alive <> 0) then 7269 begin 7270 m := TMenuItem.Create(mViewpoint); 7271 if p1 = 0 then 7272 m.Caption := Phrases.Lookup('SUPER') 7273 else 7274 m.Caption := Tribe[p1].TString(Phrases2.Lookup('BELONG')); 7275 m.Tag := p1; 7276 m.OnClick := ViewpointClick; 7277 if p1 < 10 then 7278 m.ShortCut := ShortCut(48 + p1, [ssCtrl]); 7279 m.RadioItem := true; 7280 if p1 = me then 7281 m.Checked := true; 7282 mViewpoint.Add(m); 7283 end 7284 end; 7285 mDebugMap.Visible := (ClientMode <> cEditMap) and supervising; 7286 if supervising then 7287 begin 7288 EmptyMenu(mDebugMap); 7289 for p1 := 0 to nPl - 1 do 7290 if (p1 = 0) or (1 shl p1 and G.RO[0].Alive <> 0) then 7291 begin 7292 m := TMenuItem.Create(mDebugMap); 7293 if p1 = 0 then 7294 m.Caption := Phrases2.Lookup('MENU_DEBUGMAPOFF') 7295 else 7296 m.Caption := Tribe[p1].TString(Phrases2.Lookup('BELONG')); 7297 if p1 = 0 then 7298 m.Tag := -1 7299 else 7300 m.Tag := p1; 7301 m.OnClick := DebugMapClick; 7302 if p1 < 10 then 7303 m.ShortCut := ShortCut(48 + p1, [ssAlt]); 7304 m.RadioItem := true; 7305 if m.Tag = IsoEngine.pDebugMap then 7306 m.Checked := true; 7307 mDebugMap.Add(m); 7308 end 7309 end; 7310 mSmallTiles.Checked := xxt = 33; 7311 mNormalTiles.Checked := xxt = 48; 7312 end 7313 else if Popup = StatPopup then 7314 begin 7315 mEmpire.Visible := NoSuper; 7316 mEmpire.Enabled := MyRO.Government <> gAnarchy; 7317 mRevolution.Visible := NoSuper; 7318 mRevolution.Enabled := (MyRO.Government <> gAnarchy) and 7319 (ClientMode < scContact); 7320 mUnitStat.Enabled := NoSuper or (MyRO.Turn > 0); 7321 mCityStat.Visible := 1 shl me and MyRO.Alive <> 0; 7322 mCityStat.Enabled := HaveCities; 7323 mScienceStat.Visible := true; 7324 mScienceStat.Enabled := not NoSuper or (MyRO.ResearchTech >= 0) or 7325 (MyRO.Happened and phTech <> 0) or (MyRO.Happened and phGameEnd <> 0) 7326 // no researchtech in case just completed 7327 or (MyRO.TestFlags and (tfAllTechs or tfUncover or 7328 tfAllContact) <> 0); 7329 mEUnitStat.Enabled := MyRO.nEnemyModel > 0; 7330 { mWonders.Enabled:= false; 7331 for i:=0 to 27 do if MyRO.Wonder[i].CityID<>-1 then 7332 mWonders.Enabled:=true; } 7333 mDiagram.Enabled := MyRO.Turn >= 2; 7334 mShips.Enabled := false; 7335 for p1 := 0 to nPl - 1 do 7336 if MyRO.Ship[p1].Parts[spComp] + MyRO.Ship[p1].Parts[spPow] + 7337 MyRO.Ship[p1].Parts[spHab] > 0 then 7338 mShips.Enabled := true; 7339 end 7340 else if Popup = UnitPopup then 7341 begin 7342 mox := @MyModel[MyUn[UnFocus].mix]; 7343 Tile := MyMap[MyUn[UnFocus].Loc]; 7344 extended := Tile and fCity = 0; 7345 if extended then 7346 begin 7347 mCity.Caption := Phrases.Lookup('BTN_FOUND'); 7348 mHome.Caption := Phrases.Lookup('BTN_MOVEHOME') 7349 end 2729 7350 else 7351 begin 7352 mCity.Caption := Phrases.Lookup('BTN_ADD'); 7353 mHome.Caption := Phrases.Lookup('BTN_SETHOME') 7354 end; 7355 7356 extended := extended and 7357 ((mox.Kind = mkSettler) or (mox.Kind = mkSlaves) and 7358 (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)) and 7359 (MyUn[UnFocus].Master < 0) and (Tile and fDeadLands = 0); 7360 if (mox.Kind = mkFreight) and (Tile and fCity <> 0) and 7361 not Phrases2FallenBackToEnglish or 7362 (Server(sRemoveUnit - sExecute, me, UnFocus, nil^) = eUtilized) then 7363 begin 7364 mDisband.Visible := false; 7365 mUtilize.Visible := true; 7366 if mox.Kind = mkFreight then 7367 mUtilize.Caption := Phrases.Lookup('UTILIZE') 7368 else 7369 mUtilize.Caption := Phrases.Lookup('INTEGRATE') 7370 end 7371 else 7372 begin 7373 mDisband.Visible := true; 7374 mUtilize.Visible := false 7375 end; 7376 mGoOn.Visible := MyUn[UnFocus].Status and (usGoto or usWaiting) 7377 = usGoto or usWaiting; 7378 mHome.Visible := HaveCities; 7379 mRecover.Visible := (MyUn[UnFocus].Health < 100) and 7380 (Tile and fTerrain >= fGrass) and 7381 ((MyRO.Wonder[woGardens].EffectiveOwner = me) or 7382 (Tile and fTerrain <> fArctic) and (Tile and fTerrain <> fDesert)) and 7383 not((mox.Domain = dAir) and (Tile and fCity = 0) and 7384 (Tile and fTerImp <> tiBase)); 7385 mStay.Visible := not((mox.Domain = dAir) and (Tile and fCity = 0) and 7386 (Tile and fTerImp <> tiBase)); 7387 mCity.Visible := extended and (mox.Kind = mkSettler) or 7388 (Tile and fCity <> 0) and ((mox.Kind in [mkSettler, mkSlaves]) or 7389 (MyUn[UnFocus].Flags and unConscripts <> 0)); 7390 mPillage.Visible := (Tile and (fRoad or fRR or fCanal or fTerImp) <> 0) 7391 and (MyUn[UnFocus].Master < 0) and (mox.Domain = dGround); 7392 mCancel.Visible := (MyUn[UnFocus].Job > jNone) or 7393 (MyUn[UnFocus].Status and (usRecover or usGoto) <> 0); 7394 7395 Test := Server(sLoadUnit - sExecute, me, UnFocus, nil^); 7396 mLoad.Visible := (Test >= rExecuted) or (Test = eNoTime_Load); 7397 mUnload.Visible := (MyUn[UnFocus].Master >= 0) or 7398 (MyUn[UnFocus].TroopLoad + MyUn[UnFocus].AirLoad > 0); 7399 mSelectTransport.Visible := Server(sSelectTransport - sExecute, me, 7400 UnFocus, nil^) >= rExecuted; 7401 end 7402 else { if Popup=TerrainPopup then } 7403 begin 7404 mox := @MyModel[MyUn[UnFocus].mix]; 7405 Tile := MyMap[MyUn[UnFocus].Loc]; 7406 extended := Tile and fCity = 0; 7407 7408 if (Tile and fRiver <> 0) and 7409 (MyRO.Tech[adBridgeBuilding] >= tsApplicable) then 7410 begin 7411 mRoad.Caption := Phrases.Lookup('BTN_BUILDBRIDGE'); 7412 mRR.Caption := Phrases.Lookup('BTN_BUILDRRBRIDGE'); 7413 end 7414 else 7415 begin 7416 mRoad.Caption := Phrases.Lookup('BTN_BUILDROAD'); 7417 mRR.Caption := Phrases.Lookup('BTN_BUILDRR'); 7418 end; 7419 if Tile and fTerrain = fForest then 7420 mClear.Caption := Phrases.Lookup('BTN_CLEAR') 7421 else if Tile and fTerrain = fDesert then 7422 mClear.Caption := Phrases.Lookup('BTN_UNDESERT') 7423 else 7424 mClear.Caption := Phrases.Lookup('BTN_DRAIN'); 7425 7426 extended := extended and 7427 ((mox.Kind = mkSettler) or (mox.Kind = mkSlaves) and 7428 (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)) and 7429 (MyUn[UnFocus].Master < 0); 7430 if extended then 7431 begin 7432 mRoad.Visible := JobTest(UnFocus, jRoad, 7433 [eNoBridgeBuilding, eTreaty]); 7434 mRR.Visible := JobTest(UnFocus, jRR, [eNoBridgeBuilding, eTreaty]); 7435 mClear.Visible := JobTest(UnFocus, jClear, [eTreaty]); 7436 mIrrigation.Visible := JobTest(UnFocus, jIrr, [eTreaty]); 7437 mFarm.Visible := JobTest(UnFocus, jFarm, [eTreaty]); 7438 mAfforest.Visible := JobTest(UnFocus, jAfforest, [eTreaty]); 7439 mMine.Visible := JobTest(UnFocus, jMine, [eTreaty]); 7440 MTrans.Visible := JobTest(UnFocus, jTrans, [eTreaty]); 7441 mCanal.Visible := JobTest(UnFocus, jCanal, [eTreaty]); 7442 mFort.Visible := JobTest(UnFocus, jFort, [eTreaty]); 7443 mAirBase.Visible := JobTest(UnFocus, jBase, [eTreaty]); 7444 mPollution.Visible := JobTest(UnFocus, jPoll, [eTreaty]); 7445 mEnhance.Visible := (Tile and fDeadLands = 0) and 7446 (MyData.EnhancementJobs[MyMap[MyUn[UnFocus].Loc] and fTerrain, 0] 7447 <> jNone); 7448 end 7449 else 7450 begin 7451 for i := 0 to Popup.Items.Count - 1 do 7452 Popup.Items[i].Visible := false; 7453 end; 7454 end; 7455 7456 // set menu seperators 7457 LastSep := nil; 7458 NeedSep := false; 7459 for i := 0 to Popup.Items.Count - 1 do 7460 if Popup.Items[i].Caption = '-' then 7461 begin 7462 Popup.Items[i].Visible := NeedSep; 7463 if NeedSep then 7464 LastSep := Popup.Items[i]; 7465 NeedSep := false 7466 end 7467 else if Popup.Items[i].Visible then 7468 NeedSep := true; 7469 if (LastSep <> nil) and not NeedSep then 7470 LastSep.Visible := false 7471 end; 7472 7473 procedure TMainScreen.PanelBtnClick(Sender: TObject); 7474 var 7475 Popup: TPopupMenu; 7476 begin 7477 if Sender = UnitBtn then 7478 Popup := UnitPopup 7479 else { if Sender=TerrainBtn then } 7480 Popup := TerrainPopup; 7481 InitPopup(Popup); 7482 if FullScreen then 7483 Popup.Popup(Left + TControl(Sender).Left, Top + TControl(Sender).Top) 7484 else 7485 Popup.Popup(Left + TControl(Sender).Left + 4, Top + TControl(Sender).Top 7486 + GetSystemMetrics(SM_CYCAPTION) + 4); 7487 end; 7488 7489 procedure TMainScreen.CityClosed(Activateuix: integer; StepFocus: boolean; 7490 SelectFocus: boolean); 7491 begin 7492 if supervising then 7493 begin 7494 SetTroopLoc(-1); 7495 PanelPaint 7496 end 7497 else 7498 begin 7499 if Activateuix >= 0 then 7500 begin 7501 SetUnFocus(Activateuix); 7502 SetTroopLoc(MyUn[Activateuix].Loc); 7503 if SelectFocus then 7504 FocusOnLoc(TroopLoc, flRepaintPanel) 7505 else 7506 PanelPaint 7507 end 7508 else if StepFocus then 7509 NextUnit(TroopLoc, true) 7510 else 7511 begin 7512 SetTroopLoc(-1); 7513 PanelPaint 7514 end 7515 end 7516 end; 7517 7518 procedure TMainScreen.Toggle(Sender: TObject); 7519 begin 7520 TMenuItem(Sender).Checked := not TMenuItem(Sender).Checked 7521 end; 7522 7523 procedure TMainScreen.PanelBoxMouseMove(Sender: TObject; Shift: TShiftState; 7524 x, y: integer); 7525 var 7526 xCentre, yCentre: integer; 7527 begin 7528 if Tracking and (ssLeft in Shift) then 7529 begin 7530 if (x >= xMini + 2) and (y >= yMini + 2) and (x < xMini + 2 + 2 * G.lx) 7531 and (y < yMini + 2 + G.ly) then 7532 begin 7533 xCentre := (xwMini + (x - xMini - 2) div 2 + G.lx div 2 + 7534 MapWidth div (xxt * 4)) mod G.lx; 7535 yCentre := (y - yMini - 2); 7536 xw := (xCentre - MapWidth div (xxt * 4) + G.lx) mod G.lx; 7537 if ywmax <= 0 then 7538 yw := ywcenter 7539 else 2730 7540 begin 2731 CurrentMoveInfo.IsAlly:= MyRO.Treaty[Owner]=trAlliance; 2732 if GameMode=cMovie then 2733 CurrentMoveInfo.DoShow:=true 2734 else if CurrentMoveInfo.IsAlly then 2735 CurrentMoveInfo.DoShow:=not mAlNoMoves.Checked 2736 and not(mAlEffectiveMovesOnly.Checked and (Command<>cShowCapturing)) 2737 else CurrentMoveInfo.DoShow:=not mEnNoMoves.Checked 2738 and not(mEnAttacks.Checked and (Command<>cShowCapturing)); 2739 if CurrentMoveInfo.DoShow then 2740 begin 2741 if Command=cShowCapturing then 2742 begin // show capture message 2743 if MyMap[ToLoc] and fOwned<>0 then 2744 begin // own city, search 2745 cix:=MyRO.nCity-1; 2746 while (cix>=0) and (MyCity[cix].Loc<>ToLoc) do 2747 dec(cix); 2748 s:=CityName(MyCity[cix].ID); 2749 end 2750 else 2751 begin // foreign city, search 2752 ecix:=MyRO.nEnemyCity-1; 2753 while (ecix>=0) and (MyRO.EnemyCity[ecix].Loc<>ToLoc) do 2754 dec(ecix); 2755 s:=CityName(MyRO.EnemyCity[ecix].ID); 2756 end; 2757 TribeMessage(Owner, Format(Tribe[Owner].TPhrase('CAPTURE'),[s]), ''); 2758 Update; // remove message box from screen 2759 end; 2760 2761 if CurrentMoveInfo.IsAlly then 2762 begin // allied unit -- make discovered land visible 2763 if mAlFastMoves.Checked then AnimationSpeed:=8 2764 else AnimationSpeed:=16; 2765 with MyRO.EnemyModel[emix] do 2766 if (Kind=mkDiplomat) or (Domain=dAir) or (ATrans_Fuel>0) 2767 or (Cap and (1 shl (mcRadar-mcFirstNonCap) or 1 shl (mcAcademy-mcFirstNonCap))<>0) 2768 or (MyMap[ToLoc] and fTerrain=fMountains) 2769 or (MyMap[ToLoc] and fTerImp=tiFort) 2770 or (MyMap[ToLoc] and fTerImp=tiBase) then 2771 CurrentMoveInfo.AfterMovePaintRadius:=2 2772 else CurrentMoveInfo.AfterMovePaintRadius:=1 2773 end 7541 yw := (yCentre - MapHeight div (yyt * 2) + 1) and not 1; 7542 if yw < 0 then 7543 yw := 0 7544 else if yw > ywmax then 7545 yw := ywmax; 7546 end; 7547 BitBlt(Buffer.Canvas.Handle, 0, 0, G.lx * 2, G.ly, Mini.Canvas.Handle, 7548 0, 0, SRCCOPY); 7549 if ywmax <= 0 then 7550 Frame(Buffer.Canvas, x - xMini - 2 - MapWidth div (xxt * 2), 0, 7551 x - xMini - 2 + MapWidth div (xxt * 2) - 1, G.ly - 1, 7552 MainTexture.clMark, MainTexture.clMark) 7553 else 7554 Frame(Buffer.Canvas, x - xMini - 2 - MapWidth div (xxt * 2), yw, 7555 x - xMini - 2 + MapWidth div (xxt * 2) - 1, 7556 yw + MapHeight div yyt - 2, MainTexture.clMark, 7557 MainTexture.clMark); 7558 BitBlt(Panel.Canvas.Handle, xMini + 2, yMini + 2, G.lx * 2, G.ly, 7559 Buffer.Canvas.Handle, 0, 0, SRCCOPY); 7560 MainOffscreenPaint; 7561 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini + 7562 2, xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini 7563 + 2 + G.ly); 7564 Update; 7565 end 7566 end 7567 else 7568 Tracking := false 7569 end; 7570 7571 procedure TMainScreen.PanelBoxMouseUp(Sender: TObject; Button: TMouseButton; 7572 Shift: TShiftState; x, y: integer); 7573 begin 7574 if Tracking then 7575 begin 7576 Tracking := false; 7577 xwMini := xw; 7578 ywMini := yw; 7579 MiniPaint; 7580 PanelPaint; 7581 end 7582 end; 7583 7584 procedure TMainScreen.MapBoxMouseMove(Sender: TObject; Shift: TShiftState; 7585 x, y: integer); 7586 var 7587 MouseLoc: integer; 7588 begin 7589 xMouse := x; 7590 yMouse := y; 7591 if (ClientMode = cEditMap) and (ssLeft in Shift) and not Tracking then 7592 begin 7593 MouseLoc := LocationOfScreenPixel(x, y); 7594 if MouseLoc <> BrushLoc then 7595 MapBoxMouseDown(nil, mbLeft, Shift, x, y); 7596 end 7597 (* else if idle and (UnFocus>=0) then 7598 begin 7599 qx:=(xMouse*32+yMouse*66+16*66) div(32*66)-1; 7600 qy:=(yMouse*66-xMouse*32-16*66+2000*33*32) div(32*66)-999; 7601 MouseLoc:=(xw+(qx-qy+2048) div 2-1024+G.lx) mod G.lx+G.lx*(yw+qx+qy); 7602 ShowMoveHint(MouseLoc); 7603 end *) 7604 end; 7605 7606 procedure TMainScreen.mShowClick(Sender: TObject); 7607 begin 7608 TMenuItem(Sender).Checked := not TMenuItem(Sender).Checked; 7609 SetMapOptions; 7610 MapValid := false; 7611 PaintAllMaps; 7612 end; 7613 7614 procedure TMainScreen.mNamesClick(Sender: TObject); 7615 var 7616 p1: integer; 7617 begin 7618 mNames.Checked := not mNames.Checked; 7619 GenerateNames := mNames.Checked; 7620 for p1 := 0 to nPl - 1 do 7621 if Tribe[p1] <> nil then 7622 if GenerateNames then 7623 Tribe[p1].NumberName := -1 7624 else 7625 Tribe[p1].NumberName := p1; 7626 MapValid := false; 7627 PaintAll; 7628 end; 7629 7630 function TMainScreen.IsPanelPixel(x, y: integer): boolean; 7631 begin 7632 result := (y >= TopBarHeight + MapHeight) or 7633 (y >= ClientHeight - PanelHeight) and 7634 ((x < xMidPanel) or (x >= xRightPanel)) 7635 end; 7636 7637 procedure TMainScreen.FormMouseDown(Sender: TObject; Button: TMouseButton; 7638 Shift: TShiftState; x, y: integer); 7639 begin 7640 if idle then 7641 if (x < 40) and (y < 40) then 7642 begin 7643 if GameMode <> cMovie then 7644 begin 7645 InitPopup(GamePopup); 7646 if FullScreen then 7647 GamePopup.Popup(Left, Top + TopBarHeight - 1) 2774 7648 else 2775 begin 2776 if mEnFastMoves.Checked then AnimationSpeed:=8 2777 else AnimationSpeed:=16; 2778 CurrentMoveInfo.AfterMovePaintRadius:=0; // enemy unit, nothing discovered 2779 end; 2780 if GameMode=cMovie then 2781 begin 2782 if MovieSpeed=3 then AnimationSpeed:=4 2783 else if MovieSpeed=2 then AnimationSpeed:=8 2784 else AnimationSpeed:=16; 2785 end; 2786 ShowMoveDomain:=MyRO.EnemyModel[emix].Domain; 2787 IsAlpine:= MyRO.EnemyModel[emix].Cap and (1 shl (mcAlpine-mcFirstNonCap))<>0; 2788 end 2789 end; 2790 2791 if CurrentMoveInfo.DoShow then 2792 begin 2793 if Command=cShowCapturing then Play('MOVE_CAPTURE') 2794 else if EndHealth<=0 then Play('MOVE_DIE') 2795 else if Flags and umSpyMission<>0 then Play('MOVE_COVERT') 2796 else if Flags and umShipLoading<>0 then 2797 if ShowMoveDomain=dAir then Play('MOVE_PLANELANDING') 2798 else Play('MOVE_LOAD') 2799 else if Flags and umPlaneLoading<>0 then Play('MOVE_LOAD') 2800 else if Flags and umShipUnloading<>0 then 2801 if ShowMoveDomain=dAir then Play('MOVE_PLANESTART') 2802 else Play('MOVE_UNLOAD') 2803 else if Flags and umPlaneUnloading<>0 then 2804 if (MyMap[FromLoc] and fCity=0) 2805 and (MyMap[FromLoc] and fTerImp<>tiBase) then 2806 Play('MOVE_PARACHUTE') 2807 else Play('MOVE_UNLOAD') 2808 else if (ShowMoveDomain=dGround) and not IsAlpine 2809 and (MyMap[ToLoc] and fTerrain=fMountains) 2810 and ((MyMap[FromLoc] and (fRoad or fRR or fCity)=0) 2811 or (MyMap[ToLoc] and (fRoad or fRR or fCity)=0)) then 2812 Play('MOVE_MOUNTAIN'); 2813 2814 FocusOnLoc(FromLoc,flImmUpdate); 2815 PaintLoc_BeforeMove(FromLoc); 2816 if Command=cShowCapturing then 2817 MoveOnScreen(TShowMove(Data),1,32,32) 2818 else MoveOnScreen(TShowMove(Data),1,AnimationSpeed,AnimationSpeed) 2819 end // if CurrentMoveInfo.DoShow 2820 else MapValid:=false; 2821 end 2822 end; 2823 2824 cShowAttacking: 2825 if (idle and (NewPlayer=me) 2826 or not idle and not skipped and (TShowMove(Data).emix<>$FFFF)) 2827 and not ((GameMode=cMovie) and (MovieSpeed=4)) then 2828 begin 2829 assert(NewPlayer=me); 2830 if not idle or (GameMode=cMovie) then 2831 Application.ProcessMessages; 2832 with TShowMove(Data) do 2833 begin 2834 CurrentMoveInfo.AfterAttackExpeller:=-1; 2835 CurrentMoveInfo.DoShow:=false; 2836 if idle then 2837 CurrentMoveInfo.DoShow:=true // own unit -- always show attacks 2838 else 2839 begin 2840 CurrentMoveInfo.IsAlly:= MyRO.Treaty[Owner]=trAlliance; 2841 if CurrentMoveInfo.IsAlly then 2842 CurrentMoveInfo.DoShow:=not mAlNoMoves.Checked 2843 else CurrentMoveInfo.DoShow:=not mEnNoMoves.Checked; 2844 end; 2845 if CurrentMoveInfo.DoShow then 2846 begin 2847 ToLoc:=dLoc(FromLoc,dx,dy); 2848 if Tribe[Owner].ModelPicture[mix].HGr=0 then 2849 InitEnemyModel(emix); 2850 2851 if (MyMap[ToLoc] and (fCity or fUnit or fOwned) = fCity or fOwned) then 2852 begin // tell about bombardment 2853 cix:=MyRO.nCity-1; 2854 while (cix>=0) and (MyCity[cix].Loc<>ToLoc) do 2855 dec(cix); 2856 if MyCity[cix].Status and csToldBombard=0 then 2857 begin 2858 if not supervising then 2859 MyCity[cix].Status:=MyCity[cix].Status or csToldBombard; 2860 s:=CityName(MyCity[cix].ID); 2861 SoundMessageEx(Format(Tribe[Owner].TPhrase('BOMBARD'),[s]),''); 2862 Update; // remove message box from screen 2863 end; 2864 end 2865 else if Flags and umExpelling<>0 then 2866 CurrentMoveInfo.AfterAttackExpeller:=Owner; 2867 2868 if Flags and umExpelling<>0 then Play('MOVE_EXPEL') 2869 else if Owner=me then 2870 begin 2871 MakeModelInfo(me,mix,MyModel[mix],mi); 2872 Play(AttackSound(ModelCode(mi))); 2873 end 2874 else Play(AttackSound(ModelCode(MyRO.EnemyModel[emix]))); 2875 2876 FocusOnLoc(FromLoc,flImmUpdate); 2877 2878 // before combat 2879 MainMap.AttackBegin(TShowMove(Data)); 2880 if MyMap[ToLoc] and fCity<>0 then PaintLoc(ToLoc); 2881 PaintLoc(FromLoc); 2882 MoveOnScreen(TShowMove(Data),1,9,16); 2883 MoveOnScreen(TShowMove(Data),17,12,32); 2884 MoveOnScreen(TShowMove(Data),7,11,16); 2885 2886 // after combat 2887 MainMap.AttackEffect(TShowMove(Data)); 2888 PaintLoc(ToLoc); 2889 if EndHealth>0 then 2890 begin 2891 Health:=EndHealth; 2892 MoveOnScreen(TShowMove(Data),10,0,16); 2893 end 2894 else if not idle then 2895 Sleep(MoveTime div 2); 2896 MainMap.AttackEnd; 2897 end // if CurrentMoveInfo.DoShow 2898 else MapValid:=false; 2899 end 2900 end; 2901 2902 cShowMissionResult: 2903 if Cardinal(Data)=0 then 2904 SoundMessageEx(Phrases.Lookup('NOFOREIGNINFO'),'') 2905 else 2906 begin 2907 s:=Phrases.Lookup('FOREIGNINFO'); 2908 for p1:=0 to nPl-1 do if 3 shl (p1*2) and Cardinal(Data)<>0 then 2909 s:=s+'\'+Tribe[p1].TPhrase('SHORTNAME'); 2910 SoundMessageEx(s,'') 2911 end; 2912 2913 cShowShipChange: 2914 if not IsMultiPlayerGame and (Jump[0]=0) then 2915 ShowEnemyShipChange(TShowShipChange(Data)); 2916 2917 cShowGreatLibTech: 2918 if not IsMultiPlayerGame and (Jump[0]=0) then with MessgExDlg do 2919 begin 2920 MessgText:=Format(Phrases.Lookup('GRLIB_GENERAL'), 2921 [Phrases.Lookup('ADVANCES',integer(Data))]); 2922 OpenSound:='NEWADVANCE_GRLIB'; 2923 Kind:=mkOK; 2924 IconKind:=mikImp; 2925 IconIndex:=woGrLibrary; 2926 ShowModal; 2927 end; 2928 2929 cRefreshDebugMap: 2930 begin 2931 if integer(data)=IsoEngine.pDebugMap then 2932 begin 2933 MapValid:=false; 2934 MainOffscreenPaint; 2935 Update; 2936 end 2937 end; 2938 2939 else if Command>=cClientEx then case Command and $FFF0 of 2940 2941 cSetTribe: with TTribeInfo(Data) do 2942 begin 2943 i:=UnusedTribeFiles.Count-1; 2944 while (i>=0) and (AnsiCompareFileName(UnusedTribeFiles[i],FileName)<>0) do 2945 dec(i); 2946 if i>=0 then UnusedTribeFiles.Delete(i); 2947 CreateTribe(trix,FileName,true); 2948 end; 2949 2950 cSetNewModelPicture, cSetModelPicture: 2951 if TribeOriginal[TModelPictureInfo(Data).trix] then 2952 Tribe[TModelPictureInfo(Data).trix].SetModelPicture( 2953 TModelPictureInfo(Data),Command and $FFF0=cSetNewModelPicture); 2954 2955 cSetSlaveIndex and $FFF0: 2956 Tribe[integer(data) shr 16].mixSlaves:=integer(data) and $FFFF; 2957 2958 cSetCityName: with TCityNameInfo(Data) do 2959 if TribeOriginal[ID shr 12] then 2960 Tribe[ID shr 12].SetCityName(ID and $FFF,NewName); 2961 2962 cSetModelName: with TModelNameInfo(Data) do 2963 if TribeOriginal[NewPlayer] then 2964 Tribe[NewPlayer].ModelName[mix]:=NewName; 2965 end 2966 end 2967 end;{<<<client} 2968 2969 {*** main part ***} 2970 2971 procedure TMainScreen.CreateParams (var p: TCreateParams); 2972 var 2973 DefaultOptionChecked: integer; 2974 Reg: TRegistry; 2975 doinit: boolean; 2976 begin 2977 inherited; 2978 2979 // define which menu settings to save 2980 SaveOption[0]:=mAlEffectiveMovesOnly.Tag; 2981 SaveOption[1]:=mEnMoves.Tag; 2982 SaveOption[2]:=mEnAttacks.Tag; 2983 SaveOption[3]:=mEnNoMoves.Tag; 2984 SaveOption[4]:=mWaitTurn.Tag; 2985 SaveOption[5]:=mEffectiveMovesOnly.Tag; 2986 SaveOption[6]:=mEnFastMoves.Tag; 2987 SaveOption[7]:=mSlowMoves.Tag; 2988 SaveOption[8]:=mFastMoves.Tag; 2989 SaveOption[9]:=mVeryFastMoves.Tag; 2990 SaveOption[10]:=mNames.Tag; 2991 SaveOption[11]:=mRepList.Tag; 2992 SaveOption[12]:=mRepScreens.Tag; 2993 SaveOption[13]:=mSoundOff.Tag; 2994 SaveOption[14]:=mSoundOn.Tag; 2995 SaveOption[15]:=mSoundOnAlt.Tag; 2996 SaveOption[16]:=mScrollSlow.Tag; 2997 SaveOption[17]:=mScrollFast.Tag; 2998 SaveOption[18]:=mScrollOff.Tag; 2999 SaveOption[19]:=mAlSlowMoves.Tag; 3000 SaveOption[20]:=mAlFastMoves.Tag; 3001 SaveOption[21]:=mAlNoMoves.Tag; 3002 DefaultOptionChecked:= 1 shl 1 + 1 shl 7 + 1 shl 10 + 1 shl 12 + 1 shl 14 + 1 shl 18 + 1 shl 19; 3003 3004 Reg:=TRegistry.Create; 3005 doinit:=true; 3006 if Reg.KeyExists('SOFTWARE\cevo\RegVer9') then 3007 begin 3008 doinit:=false; 3009 Reg.OpenKey('SOFTWARE\cevo\RegVer9',false); 3010 try 3011 xxt:=Reg.ReadInteger('TileWidth') div 2; 3012 yyt:=Reg.ReadInteger('TileHeight') div 2; 3013 OptionChecked:=Reg.ReadInteger('OptionChecked'); 3014 MapOptionChecked:=Reg.ReadInteger('MapOptionChecked'); 3015 CityRepMask:=cardinal(Reg.ReadInteger('CityReport')); 3016 except 3017 doinit:=true; 3018 end; 3019 Reg.closekey; 3020 if OptionChecked and (7 shl 16)=0 then 3021 OptionChecked:=OptionChecked or (1 shl 16); // old regver with no scrolling 3022 end; 3023 Reg.Free; 3024 if doinit then 3025 begin 3026 xxt:=48; 3027 yyt:=24; 3028 OptionChecked:=DefaultOptionChecked; 3029 MapOptionChecked:=1 shl moCityNames; 3030 CityRepMask:=cardinal(not chPopIncrease and not chNoGrowthWarning and not chCaptured); 3031 end; 3032 3033 if FullScreen then 3034 begin 3035 p.Style:=$87000000; 3036 BorderStyle:=bsNone; 3037 BorderIcons:=[]; 3038 end; 3039 3040 if 1 shl 13 and OptionChecked<>0 then SoundMode:=smOff 3041 else if 1 shl 15 and OptionChecked<>0 then SoundMode:=smOnAlt 3042 else SoundMode:=smOn 3043 end; 3044 3045 procedure TMainScreen.FormCreate(Sender:TObject); 3046 var 3047 i,j: integer; 3048 begin 3049 Screen.Cursors[crImpDrag]:=LoadCursor(HInstance,'DRAG'); 3050 Screen.Cursors[crFlatHand]:=LoadCursor(HInstance,'FLATHAND'); 3051 3052 // tag-controlled language 3053 for i:=0 to ComponentCount-1 do 3054 if Components[i].Tag and $FF<>0 then 3055 if Components[i] is TMenuItem then 3056 begin 3057 TMenuItem(Components[i]).Caption:= 3058 Phrases.Lookup('CONTROLS',-1+Components[i].Tag and $FF); 3059 for j:=0 to nSaveOption-1 do 3060 if Components[i].Tag and $FF=SaveOption[j] then 3061 TMenuItem(Components[i]).Checked:= 1 shl j and OptionChecked<>0; 3062 end 3063 else if Components[i] is TButtonBase then 3064 begin 3065 TButtonBase(Components[i]).Hint:= 3066 Phrases.Lookup('CONTROLS',-1+Components[i].Tag and $FF); 3067 if (Components[i] is TButtonC) and (TButtonC(Components[i]).ButtonIndex<>1) then 3068 TButtonC(Components[i]).ButtonIndex:= 3069 MapOptionChecked shr (Components[i].Tag shr 8) and 1 +2 3070 end; 3071 3072 // non-tag-controlled language 3073 mTechTree.Caption:=Phrases2.Lookup('MENU_ADVTREE'); 3074 mViewpoint.Caption:=Phrases2.Lookup('MENU_VIEWPOINT'); 3075 if not Phrases2FallenBackToEnglish then 3076 begin 3077 MenuArea.Hint:=Phrases2.Lookup('BTN_MENU'); 3078 TreasuryArea.Hint:=Phrases2.Lookup('TIP_TREASURY'); 3079 ResearchArea.Hint:=Phrases.Lookup('SCIENCE'); 3080 ManagementArea.Hint:=Phrases2.Lookup('BTN_MANAGE'); 3081 end; 3082 for i:=0 to mRep.Count-1 do 3083 begin 3084 j:=mRep[i].Tag shr 8; 3085 mRep[i].Caption:=CityEventName(j); 3086 mRep[i].Checked:= CityRepMask and (1 shl j)<>0; 3087 end; 3088 3089 Mini:=TBitmap.Create; 3090 Mini.PixelFormat:=pf24bit; 3091 Panel:=TBitmap.Create; 3092 Panel.PixelFormat:=pf24bit; 3093 Panel.Canvas.Font.Assign(UniFont[ftSmall]); 3094 Panel.Canvas.Brush.Style:=bsClear; 3095 TopBar:=TBitmap.Create; 3096 TopBar.PixelFormat:=pf24bit; 3097 TopBar.Canvas.Font.Assign(UniFont[ftNormal]); 3098 TopBar.Canvas.Brush.Style:=bsClear; 3099 Buffer:=TBitmap.Create; 3100 Buffer.PixelFormat:=pf24bit; 3101 if 2*lxmax>3*xSizeBig then 3102 Buffer.Width:=2*lxmax 3103 else Buffer.Width:=3*xSizeBig; 3104 if lymax>3*ySizeBig then 3105 Buffer.Height:=lymax 3106 else Buffer.Height:=3*ySizeBig; 3107 Buffer.Canvas.Font.Assign(UniFont[ftSmall]); 3108 for i:=0 to nPl-1 do AILogo[i]:=nil; 3109 Canvas.Font.Assign(UniFont[ftSmall]); 3110 InitButtons(); 3111 EOT.Template:=Templates; 3112 end; 3113 3114 procedure TMainScreen.FormDestroy(Sender:TObject); 3115 var 3116 i: integer; 3117 begin 3118 Mini.Free;Buffer.Free;Panel.Free; 3119 for i:=0 to nPl-1 do if AILogo[i]<>nil then 3120 AILogo[i].Free; 3121 end; 3122 3123 procedure TMainScreen.FormResize(Sender:TObject); 3124 var 3125 MiniFrame,MaxMapWidth: integer; 3126 begin 3127 SmallScreen:= ClientWidth<1024; 3128 MaxMapWidth:=(G.lx*2-3)*xxt; // avoide the same tile being visible left and right 3129 if ClientWidth<=MaxMapWidth then 3130 begin 3131 MapWidth:=ClientWidth; 3132 MapOffset:=0; 3133 end 3134 else 3135 begin 3136 MapWidth:=MaxMapWidth; 3137 MapOffset:=(ClientWidth-MapWidth) div 2; 3138 end; 3139 MapHeight:=ClientHeight-TopBarHeight-PanelHeight+overlap; 3140 Panel.Width:=ClientWidth; Panel.Height:=PanelHeight; 3141 TopBar.Width:=ClientWidth; TopBar.Height:=TopBarHeight; 3142 MiniFrame:=(lxmax_xxx-G.ly) div 2; 3143 xMidPanel:=(G.lx+MiniFrame)*2+1; 3144 xRightPanel:=ClientWidth-LeftPanelWidth-10; 3145 if ClientMode=cEditMap then 3146 TrPitch:=2*xxt 3147 else TrPitch:=66; 3148 xMini:=MiniFrame-5; yMini:=(PanelHeight-26-lxmax_xxx) div 2+MiniFrame; 3149 ywmax:=(G.ly-MapHeight div yyt+1) and not 1; 3150 ywcenter:=-((MapHeight-yyt*(G.ly-1)) div (4*yyt))*2; // only for ywmax<=0 3151 if ywmax<=0 then yw:=ywcenter 3152 else if yw<0 then yw:=0 3153 else if yw>ywmax then yw:=ywmax; 3154 UnitInfoBtn.Top:=ClientHeight-29; 3155 UnitInfoBtn.Left:=xMidPanel+7+99; 3156 UnitBtn.Top:=ClientHeight-29; 3157 UnitBtn.Left:=xMidPanel+7+99+31; 3158 TerrainBtn.Top:=ClientHeight-29; 3159 TerrainBtn.Left:=xMidPanel+7+99+62; 3160 MovieSpeed1Btn.Top:=ClientHeight-91; 3161 MovieSpeed1Btn.Left:=ClientWidth div 2-62; 3162 MovieSpeed2Btn.Top:=ClientHeight-91; 3163 MovieSpeed2Btn.Left:=ClientWidth div 2-62+29; 3164 MovieSpeed3Btn.Top:=ClientHeight-91; 3165 MovieSpeed3Btn.Left:=ClientWidth div 2-62+2*29; 3166 MovieSpeed4Btn.Top:=ClientHeight-91; 3167 MovieSpeed4Btn.Left:=ClientWidth div 2-62+3*29+12; 3168 EOT.Top:=ClientHeight-64; 3169 EOT.Left:=ClientWidth-62; 3170 SetWindowPos(sb.h,0,xRightPanel+10-14-GetSystemMetrics(SM_CXVSCROLL), 3171 ClientHeight-MidPanelHeight+8,0,0,SWP_NOSIZE or SWP_NOZORDER); 3172 MapBtn0.Left:=xMini+G.lx-44; 3173 MapBtn0.Top:=ClientHeight-15; 3174 MapBtn1.Left:=xMini+G.lx-28; 3175 MapBtn1.Top:=ClientHeight-15; 3176 {MapBtn2.Left:=xMini+G.lx-20; 3177 MapBtn2.Top:=ClientHeight-15; 3178 MapBtn3.Left:=xMini+G.lx-4; 3179 MapBtn3.Top:=ClientHeight-15;} 3180 MapBtn5.Left:=xMini+G.lx-12; 3181 MapBtn5.Top:=ClientHeight-15; 3182 MapBtn4.Left:=xMini+G.lx+20; 3183 MapBtn4.Top:=ClientHeight-15; 3184 MapBtn6.Left:=xMini+G.lx+36; 3185 MapBtn6.Top:=ClientHeight-15; 3186 TreasuryArea.Left:=ClientWidth div 2-172; 3187 ResearchArea.Left:=ClientWidth div 2; 3188 ManagementArea.Left:=ClientWidth-xPalace; 3189 ManagementArea.Top:=TopBarHeight+MapHeight-overlap+yPalace; 3190 ArrangeMidPanel; 3191 if RepaintOnResize then 3192 begin 3193 RectInvalidate(0,TopBarHeight,ClientWidth,TopBarHeight+MapHeight); 3194 MapValid:=false; 3195 PaintAll 3196 end 3197 end; 3198 3199 procedure TMainScreen.FormCloseQuery(Sender: TObject; var CanClose: boolean); 3200 begin 3201 CanClose:=Closable; 3202 if not Closable and idle and (me=0) and (ClientMode<scContact) then 3203 MenuClick(mResign) 3204 end; 3205 3206 procedure TMainScreen.OnScroll(var m:TMessage); 3207 begin 3208 if ProcessPVSB(sb,m) then begin PanelPaint; Update end 3209 end; 3210 3211 procedure TMainScreen.OnEOT(var Msg:TMessage); 3212 begin 3213 EndTurn 3214 end; 3215 3216 procedure TMainScreen.EOTClick(Sender:TObject); 3217 begin 3218 if GameMode=cMovie then 3219 begin 3220 MessgExDlg.CancelMovie; 3221 Server(sBreak,me,0,nil^) 3222 end 3223 else if ClientMode<0 then 3224 skipped:=true 3225 else if ClientMode>=scContact then 3226 NegoDlg.ShowNewContent(wmPersistent) 3227 else if Jump[pTurn]>0 then 3228 begin Jump[pTurn]:=0; StartRunning:=false end 3229 else EndTurn 3230 end; 3231 3232 // set xTerrain, xTroop, and TrRow 3233 procedure TMainScreen.ArrangeMidPanel; 3234 begin 3235 if ClientMode=cEditMap then 3236 xTroop:=xMidPanel+15 3237 else 3238 begin 3239 if supervising then 3240 xTerrain:=xMidPanel+2*xxt+14 3241 else if ClientWidth<1280 then 3242 xTerrain:=ClientWidth div 2+(1280-ClientWidth) div 3 3243 else xTerrain:=ClientWidth div 2; 3244 xTroop:=xTerrain+2*xxt+12; 3245 if SmallScreen and not supervising then 3246 xTroop:=xRightPanel+10-3*66-GetSystemMetrics(SM_CXVSCROLL)-19-4; 3247 // not perfect but we assume almost no one is still playing on a 800x600 screen 3248 end; 3249 TrRow:=(xRightPanel+10-xTroop-GetSystemMetrics(SM_CXVSCROLL)-19) div TrPitch; 3250 end; 3251 3252 function TMainScreen.EndTurn(WasSkipped: boolean): boolean; 3253 3254 function IsResourceUnused(cix, NeedFood, NeedProd: integer): boolean; 3255 var 3256 dx,dy,fix: integer; 3257 CityAreaInfo: TCityAreaInfo; 3258 TileInfo: TTileInfo; 3259 begin 3260 Server(sGetCityAreaInfo,me,cix,CityAreaInfo); 3261 for dy:=-3 to 3 do for dx:=-3 to 3 do 3262 if ((dx+dy) and 1=0) and (dx*dx*dy*dy<81) then 3263 begin 3264 fix:=(dy+3) shl 2+(dx+3) shr 1; 3265 if (MyCity[cix].Tiles and (1 shl fix)=0) // not used yet 3266 and (CityAreaInfo.Available[fix]=faAvailable) then // usable 3267 begin 3268 TileInfo.ExplCity:=cix; 3269 Server(sGetHypoCityTileInfo, me, dLoc(MyCity[cix].Loc,dx,dy), TileInfo); 3270 if (TileInfo.Food>=NeedFood) and (TileInfo.Prod>=NeedProd) then 3271 begin result:=true; exit end; 3272 end 3273 end; 3274 result:=false; 3275 end; 3276 3277 var 3278 i,p1,uix,cix,CenterLoc: integer; 3279 MsgItem: string; 3280 CityReport: TCityReport; 3281 PlaneReturnData: TPlaneReturnData; 3282 Zoom: boolean; 3283 begin 3284 result:=false; 3285 if ClientMode>=scDipOffer then exit; 3286 3287 if supervising and (me<>0) then 3288 begin 3289 for i:=0 to Screen.FormCount-1 do 3290 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 3291 Screen.Forms[i].Close; // close windows 3292 ItsMeAgain(0); 3293 end; 3294 3295 CityOptimizer_EndOfTurn; 3296 3297 if not WasSkipped then // check warnings 3298 begin 3299 // need to move planes home? 3300 for uix:=0 to MyRO.nUn-1 do with MyUn[uix] do 3301 if (Loc>=0) and (MyModel[mix].Domain=dAir) 3302 and (Status and usToldNoReturn=0) and (Master<0) 3303 and (MyMap[Loc] and fCity=0) and (MyMap[Loc] and fTerImp<>tiBase) then 3304 begin 3305 PlaneReturnData.Fuel:=Fuel; 3306 PlaneReturnData.Loc:=Loc; 3307 PlaneReturnData.Movement:=0; // end turn without further movement? 3308 if Server(sGetPlaneReturn, me, uix, PlaneReturnData)=eNoWay then 3309 begin 3310 CenterLoc:=Loc+G.lx*6; // centering the unit itself would make it covered by the query dialog 3311 while CenterLoc>=G.lx*G.ly do 3312 dec(CenterLoc, G.lx*2); 3313 Centre(CenterLoc); 3314 SetTroopLoc(-1); 3315 PaintAll; 3316 3317 if MyModel[mix].Kind=mkSpecial_Glider then 3318 MsgItem:='LOWFUEL_GLIDER' 3319 else MsgItem:='LOWFUEL'; 3320 if SimpleQuery(mkYesNo,Phrases.Lookup(MsgItem),'WARNING_LOWSUPPORT')<>mrOk then 3321 begin 3322 SetUnFocus(uix); 3323 SetTroopLoc(Loc); 3324 PanelPaint; 3325 exit; 3326 end; 3327 MyUn[uix].Status:=MyUn[uix].Status or usToldNoReturn; 3328 end 3329 end; 3330 3331 if not supervising and (MyRO.TestFlags and tfImmImprove=0) 3332 and (MyRO.Government<>gAnarchy) 3333 and (MyRO.Money+TaxSum<0) and (MyRO.TaxRate<100) then // low funds! 3334 with MessgExDlg do 3335 begin 3336 OpenSound:='WARNING_LOWFUNDS'; 3337 MessgText:=Phrases.Lookup('LOWFUNDS'); 3338 Kind:=mkYesNo; 3339 IconKind:=mikImp; 3340 IconIndex:=imTrGoods; 3341 ShowModal; 3342 if ModalResult<>mrOK then exit 3343 end; 3344 3345 if MyRO.Government<>gAnarchy then 3346 for cix:=0 to MyRO.nCity-1 do with MyCity[cix] do 3347 if (Loc>=0) and (Flags and chCaptured=0) then 3348 begin 3349 Zoom:=false; 3350 CityReport.HypoTiles:=-1; 3351 CityReport.HypoTax:=-1; 3352 CityReport.HypoLux:=-1; 3353 Server(sGetCityReport,me,cix,CityReport); 3354 3355 if (CityReport.Working-CityReport.Happy>Size shr 1) 3356 and (Flags and chCaptured<=$10000) then 3357 with MessgExDlg do 3358 begin 3359 OpenSound:='WARNING_DISORDER'; 3360 if Status and csResourceWeightsMask=0 then 3361 MsgItem:='DISORDER' 3362 else MsgItem:='DISORDER_UNREST'; 3363 MessgText:=Format(Phrases.Lookup(MsgItem),[CityName(ID)]); 3364 Kind:=mkYesNo; 3365 // BigIcon:=29; 3366 ShowModal; 3367 Zoom:= ModalResult<>mrOK; 3368 end; 3369 if not Zoom and (Food+CityReport.FoodRep-CityReport.Eaten<0) then 3370 with MessgExDlg do 3371 begin 3372 OpenSound:='WARNING_FAMINE'; 3373 if Status and csResourceWeightsMask=0 then 3374 MsgItem:='FAMINE' 3375 else if (CityReport.Deployed<>0) and IsResourceUnused(cix,1,0) then 3376 MsgItem:='FAMINE_UNREST' 3377 else MsgItem:='FAMINE_TILES'; 3378 MessgText:=Format(Phrases.Lookup(MsgItem),[CityName(ID)]); 3379 Kind:=mkYesNo; 3380 IconKind:=mikImp; 3381 IconIndex:=22; 3382 ShowModal; 3383 Zoom:= ModalResult<>mrOK; 3384 end; 3385 if not Zoom and (CityReport.ProdRep<CityReport.Support) then 3386 with MessgExDlg do 3387 begin 3388 OpenSound:='WARNING_LOWSUPPORT'; 3389 if Status and csResourceWeightsMask=0 then 3390 MsgItem:='LOWSUPPORT' 3391 else if (CityReport.Deployed<>0) and IsResourceUnused(cix,0,1) then 3392 MsgItem:='LOWSUPPORT_UNREST' 3393 else MsgItem:='LOWSUPPORT_TILES'; 3394 MessgText:=Format(Phrases.Lookup(MsgItem),[CityName(ID)]); 3395 Kind:=mkYesNo; 3396 IconKind:=mikImp; 3397 IconIndex:=29; 3398 ShowModal; 3399 Zoom:= ModalResult<>mrOK; 3400 end; 3401 if Zoom then 3402 begin // zoom to city 3403 ZoomToCity(Loc); 3404 exit 3405 end 3406 end; 3407 3408 if (MyRO.Happened and phTech<>0) and (MyRO.ResearchTech<0) 3409 and (MyData.FarTech<>adNexus) then 3410 if not ChooseResearch then 3411 exit; 3412 end; 3413 3414 RememberPeaceViolation; 3415 3416 SetUnFocus(-1); 3417 for uix:=0 to MyRO.nUn-1 do 3418 MyUn[uix].Status:=MyUn[uix].Status and usPersistent; 3419 3420 CityDlg.CloseAction:=None; 3421 if IsMultiPlayerGame then 3422 begin // close windows for next player 3423 for i:=0 to Screen.FormCount-1 do 3424 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 3425 Screen.Forms[i].Close; 3426 end 3427 else 3428 begin 3429 if CityDlg.Visible then CityDlg.Close; 3430 if UnitStatDlg.Visible then UnitStatDlg.Close; 3431 end; 3432 for i:=0 to Screen.FormCount-1 do 3433 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 3434 Screen.Forms[i].Enabled:=false; 3435 3436 if Server(sTurn,pTurn,0,nil^)>=rExecuted then 3437 begin 3438 if Jump[pTurn]>0 then EOT.Hint:=Phrases.Lookup('BTN_STOP') 3439 else EOT.Hint:=Phrases.Lookup('BTN_SKIP'); 3440 result:=true; 3441 SetTroopLoc(-1); 3442 pTurn:=-1; 3443 pLogo:=-1; 3444 UnitInfoBtn.Visible:=false; 3445 UnitBtn.Visible:=false; 3446 TerrainBtn.Visible:=false; 3447 EOT.ButtonIndex:=eotCancel; 3448 EOT.Visible:=true; 3449 MapValid:=false; 3450 PanelPaint; 3451 Update; 3452 ClientMode:=-1; 3453 idle:=false; 3454 skipped:=WasSkipped; 3455 for p1:=1 to nPl-1 do 3456 if G.RO[p1]<>nil then skipped:=true; // don't show enemy moves in hotseat mode 3457 end 3458 else PanelPaint 3459 end; // EndTurn 3460 3461 procedure TMainScreen.EndNego; 3462 begin 3463 if NegoDlg.Visible then NegoDlg.Close; 3464 HaveStrategyAdvice:=false; 3465 // AdvisorDlg.HaveStrategyAdvice; 3466 // negotiation might have changed advices 3467 EOT.ButtonIndex:=eotCancel; 3468 EOT.Visible:=true; 3469 PanelPaint; 3470 Update; 3471 ClientMode:=-1; 3472 idle:=false; 3473 end; 3474 3475 procedure TMainScreen.ProcessRect(x0,y0,nx,ny,Options: integer); 3476 var 3477 xs,ys,xl,yl: integer; 3478 begin 3479 xl:=nx*xxt+xxt; 3480 yl:=ny*yyt+yyt*2; 3481 xs:=(x0-xw)*(xxt*2)+y0 and 1*xxt-G.lx*(xxt*2); 3482 // |xs+xl/2-MapWidth/2| -> min 3483 while abs(2*(xs+G.lx*(xxt*2))+xl-MapWidth)<abs(2*xs+xl-MapWidth) do 3484 inc(xs,G.lx*(xxt*2)); 3485 ys:=(y0-yw)*yyt-yyt; 3486 if xs+xl>MapWidth then xl:=MapWidth-xs; 3487 if ys+yl>MapHeight then yl:=MapHeight-ys; 3488 if (xl<=0) or (yl<=0) then exit; 3489 if Options and prPaint<>0 then 3490 begin 3491 if Options and prAutoBounds<>0 then 3492 MainMap.SetPaintBounds(xs,ys,xs+xl,ys+yl); 3493 MainMap.Paint(xs,ys,x0+G.lx*y0,nx,ny,-1,-1); 3494 end; 3495 if Options and prInvalidate<>0 then 3496 RectInvalidate(MapOffset+xs,TopBarHeight+ys,MapOffset+xs+xl,TopBarHeight+ys+yl) 3497 end; 3498 3499 procedure TMainScreen.PaintLoc(Loc: integer; Radius: integer = 0); 3500 var 3501 yLoc,x0: integer; 3502 begin 3503 if MapValid then 3504 begin 3505 yLoc:=(Loc+G.lx*1024) div G.lx -1024; 3506 x0:=(Loc+(yLoc and 1-2*Radius+G.lx*1024) div 2) mod G.lx; 3507 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 3508 ProcessRect(x0,yLoc-2*Radius,4*Radius+1,4*Radius+1, 3509 prPaint or prAutoBounds or prInvalidate); 3510 Update; 3511 end 3512 end; 3513 3514 procedure TMainScreen.PaintLocTemp(Loc, Style: integer); 3515 var 3516 y0,x0,xMap,yMap: integer; 3517 begin 3518 if not MapValid then exit; 3519 Buffer.Canvas.Font.Assign(UniFont[ftSmall]); 3520 y0:=Loc div G.lx; 3521 x0:=Loc mod G.lx; 3522 xMap:=(x0-xw)*(xxt*2)+y0 and 1*xxt-G.lx*(xxt*2); 3523 // |xMap+xxt-MapWidth/2| -> min 3524 while abs(2*(xMap+G.lx*(xxt*2))+2*xxt-MapWidth)<abs(2*xMap+2*xxt-MapWidth) do 3525 inc(xMap,G.lx*(xxt*2)); 3526 yMap:=(y0-yw)*yyt-yyt; 3527 NoMap.SetOutput(Buffer); 3528 NoMap.SetPaintBounds(0,0,2*xxt,3*yyt); 3529 NoMap.Paint(0,0,Loc,1,1,-1,-1,Style=pltsBlink); 3530 PaintBufferToScreen(xMap,yMap,2*xxt,3*yyt); 3531 end; 3532 3533 // paint content of buffer directly to screen instead of offscreen 3534 // panel protusions are added 3535 // NoMap must be set to buffer and bounds before 3536 procedure TMainScreen.PaintBufferToScreen(xMap,yMap,width,height: integer); 3537 begin 3538 if xMap+width>MapWidth then 3539 width:=MapWidth-xMap; 3540 if yMap+height>MapHeight then 3541 height:=MapHeight-yMap; 3542 if (width<=0) or (height<=0) or (width+xMap<=0) or (height+yMap<=0) then 3543 exit; 3544 3545 NoMap.BitBlt(Panel,-xMap-MapOffset,-yMap+MapHeight-overlap,xMidPanel,overlap, 3546 0,0,SRCCOPY); 3547 NoMap.BitBlt(Panel,-xMap-MapOffset+xRightPanel,-yMap+MapHeight-overlap, 3548 Panel.Width-xRightPanel,overlap,xRightPanel,0,SRCCOPY); 3549 if yMap<0 then 3550 begin 3551 if xMap<0 then 3552 BitBlt(Canvas.Handle,MapOffset,TopBarHeight,width+xMap,height+yMap, 3553 Buffer.Canvas.Handle,-xMap,-yMap,SRCCOPY) 3554 else BitBlt(Canvas.Handle,xMap+MapOffset,TopBarHeight,width,height+yMap, 3555 Buffer.Canvas.Handle,0,-yMap,SRCCOPY) 3556 end 3557 else 3558 begin 3559 if xMap<0 then 3560 BitBlt(Canvas.Handle,MapOffset,TopBarHeight+yMap,width+xMap,height, 3561 Buffer.Canvas.Handle,-xMap,0,SRCCOPY) 3562 else BitBlt(Canvas.Handle,xMap+MapOffset,TopBarHeight+yMap,width,height, 3563 Buffer.Canvas.Handle,0,0,SRCCOPY); 3564 end 3565 end; 3566 3567 procedure TMainScreen.PaintLoc_BeforeMove(FromLoc: integer); 3568 var 3569 yLoc,x0: integer; 3570 begin 3571 if MapValid then 3572 begin 3573 yLoc:=(FromLoc+G.lx*1024) div G.lx -1024; 3574 x0:=(FromLoc+(yLoc and 1+G.lx*1024) div 2) mod G.lx; 3575 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 3576 ProcessRect(x0,yLoc,1,1,prPaint or prAutoBounds); 3577 end 3578 end; 3579 3580 procedure TMainScreen.PaintDestination; 3581 var 3582 Destination: integer; 3583 begin 3584 if (UnFocus>=0) and (MyUn[UnFocus].Status and usGoto<>0) then 3585 begin 3586 Destination:=MyUn[UnFocus].Status shr 16; 3587 if (Destination<>$7FFF) and (Destination<>MyUn[UnFocus].Loc) then 3588 PaintLocTemp(Destination,pltsBlink); 3589 end; 3590 end; 3591 3592 procedure TMainScreen.MiniPaint; 3593 type 3594 TLine=array[0..99999999,0..2] of Byte; 3595 var 3596 uix,cix,x,y,Loc,i,hw,xm,cm,cmPolOcean,cmPolNone:integer; 3597 PrevMiniLine,MiniLine:^TLine; 3598 begin 3599 cmPolOcean:=GrExt[HGrSystem].Data.Canvas.Pixels[101,67]; 3600 cmPolNone:=GrExt[HGrSystem].Data.Canvas.Pixels[102,67]; 3601 hw:=MapWidth div (xxt*2); 3602 with Mini.Canvas do 3603 begin 3604 Brush.Color:=$000000; 3605 FillRect(Rect(0,0,Mini.Width,Mini.Height)); 3606 end; 3607 MiniLine:=nil; 3608 for y:=0 to G.ly-1 do 3609 begin 3610 PrevMiniLine:=MiniLine; 3611 MiniLine:=Mini.ScanLine[y]; 3612 for x:=0 to G.lx-1 do if MyMap[x+G.lx*y] and fTerrain<>fUNKNOWN then 3613 begin 3614 Loc:=x+G.lx*y; 3615 for i:=0 to 1 do 3616 begin 3617 xm:=((x-xwMini)*2+i+y and 1-hw+G.lx*5) mod (G.lx*2); 3618 cm:=MiniColors[MyMap[Loc] and fTerrain,i]; 3619 if ClientMode=cEditMap then 3620 begin 3621 if MyMap[Loc] and (fPrefStartPos or fStartPos)<>0 then 3622 cm:=$FFFFFF; 3623 end 3624 else if MyMap[Loc] and fCity<>0 then 3625 begin 3626 cix:=MyRO.nCity-1; 3627 while (cix>=0) and (MyCity[cix].Loc<>Loc) do dec(cix); 3628 if cix>=0 then cm:=Tribe[me].Color 3629 else 3630 begin 3631 cix:=MyRO.nEnemyCity-1; 3632 while (cix>=0) and (MyRO.EnemyCity[cix].Loc<>Loc) do dec(cix); 3633 if cix>=0 then cm:=Tribe[MyRO.EnemyCity[cix].Owner].Color 3634 end; 3635 cm:=$808080 or cm shr 1; {increase brightness} 3636 if PrevMiniLine<>nil then 3637 begin // 2x2 city dot covers two scanlines 3638 PrevMiniLine[xm,0]:=cm shr 16; 3639 PrevMiniLine[xm,1]:=cm shr 8 and $FF; 3640 PrevMiniLine[xm,2]:=cm and $FF; 7649 GamePopup.Popup(Left + 4, Top + GetSystemMetrics(SM_CYCAPTION) + 4 7650 + TopBarHeight - 1); 3641 7651 end 3642 7652 end 3643 else if (i=0) and (MyMap[Loc] and fUnit<>0) then 3644 begin 3645 uix:=MyRO.nUn-1; 3646 while (uix>=0) and (MyUn[uix].Loc<>Loc) do dec(uix); 3647 if uix>=0 then cm:=Tribe[me].Color 7653 else if IsPanelPixel(x, y) then 7654 PanelBoxMouseDown(Sender, Button, Shift, x, 7655 y - (ClientHeight - PanelHeight)) 7656 else if (y >= TopBarHeight) and (x >= MapOffset) and 7657 (x < MapOffset + MapWidth) then 7658 MapBoxMouseDown(Sender, Button, Shift, x - MapOffset, 7659 y - TopBarHeight) 7660 end; 7661 7662 procedure TMainScreen.FormMouseMove(Sender: TObject; Shift: TShiftState; 7663 x, y: integer); 7664 begin 7665 if idle then 7666 if IsPanelPixel(x, y) then 7667 PanelBoxMouseMove(Sender, Shift, x, y - (ClientHeight - PanelHeight)) 7668 else if (y >= TopBarHeight) and (x >= MapOffset) and 7669 (x < MapOffset + MapWidth) then 7670 MapBoxMouseMove(Sender, Shift, x - MapOffset, y - TopBarHeight); 7671 end; 7672 7673 procedure TMainScreen.FormMouseUp(Sender: TObject; Button: TMouseButton; 7674 Shift: TShiftState; x, y: integer); 7675 begin 7676 if idle then 7677 PanelBoxMouseUp(Sender, Button, Shift, x, 7678 y - (ClientHeight - PanelHeight)); 7679 end; 7680 7681 procedure TMainScreen.FormPaint(Sender: TObject); 7682 begin 7683 MainOffscreenPaint; 7684 if (MapOffset > 0) or (MapOffset + MapWidth < ClientWidth) then 7685 with Canvas do 7686 begin // pillarbox, make left and right border black 7687 if me < 0 then 7688 Brush.Color := $000000 7689 else 7690 Brush.Color := EmptySpaceColor; 7691 if xMidPanel > MapOffset then 7692 FillRect(Rect(0, TopBarHeight, MapOffset, TopBarHeight + MapHeight 7693 - overlap)) 7694 else 7695 begin 7696 FillRect(Rect(0, TopBarHeight, xMidPanel, TopBarHeight + MapHeight - 7697 overlap)); 7698 FillRect(Rect(xMidPanel, TopBarHeight, MapOffset, 7699 TopBarHeight + MapHeight)); 7700 end; 7701 if xRightPanel < MapOffset + MapWidth then 7702 FillRect(Rect(MapOffset + MapWidth, TopBarHeight, ClientWidth, 7703 TopBarHeight + MapHeight - overlap)) 7704 else 7705 begin 7706 FillRect(Rect(MapOffset + MapWidth, TopBarHeight, xRightPanel, 7707 TopBarHeight + MapHeight)); 7708 FillRect(Rect(xRightPanel, TopBarHeight, ClientWidth, 7709 TopBarHeight + MapHeight - overlap)); 7710 end; 7711 Brush.Style := bsClear; 7712 end; 7713 BitBlt(Canvas.Handle, MapOffset, TopBarHeight, MapWidth, 7714 MapHeight - overlap, offscreen.Canvas.Handle, 0, 0, SRCCOPY); 7715 BitBlt(Canvas.Handle, 0, 0, ClientWidth, TopBarHeight, 7716 TopBar.Canvas.Handle, 0, 0, SRCCOPY); 7717 if xMidPanel > MapOffset then 7718 BitBlt(Canvas.Handle, xMidPanel, TopBarHeight + MapHeight - overlap, 7719 ClientWidth div 2 - xMidPanel, overlap, offscreen.Canvas.Handle, 7720 xMidPanel - MapOffset, MapHeight - overlap, SRCCOPY) 7721 else 7722 BitBlt(Canvas.Handle, MapOffset, TopBarHeight + MapHeight - overlap, 7723 ClientWidth div 2 - MapOffset, overlap, offscreen.Canvas.Handle, 0, 7724 MapHeight - overlap, SRCCOPY); 7725 if xRightPanel < MapOffset + MapWidth then 7726 BitBlt(Canvas.Handle, ClientWidth div 2, TopBarHeight + MapHeight - 7727 overlap, xRightPanel - ClientWidth div 2, overlap, 7728 offscreen.Canvas.Handle, ClientWidth div 2 - MapOffset, 7729 MapHeight - overlap, SRCCOPY) 7730 else 7731 BitBlt(Canvas.Handle, ClientWidth div 2, TopBarHeight + MapHeight - 7732 overlap, MapOffset + MapWidth - ClientWidth div 2, overlap, 7733 offscreen.Canvas.Handle, ClientWidth div 2 - MapOffset, 7734 MapHeight - overlap, SRCCOPY); 7735 BitBlt(Canvas.Handle, 0, TopBarHeight + MapHeight - overlap, xMidPanel, 7736 overlap, Panel.Canvas.Handle, 0, 0, SRCCOPY); 7737 BitBlt(Canvas.Handle, xRightPanel, TopBarHeight + MapHeight - overlap, 7738 Panel.width - xRightPanel, overlap, Panel.Canvas.Handle, xRightPanel, 7739 0, SRCCOPY); 7740 BitBlt(Canvas.Handle, 0, TopBarHeight + MapHeight, Panel.width, 7741 PanelHeight - overlap, Panel.Canvas.Handle, 0, overlap, SRCCOPY); 7742 if (pLogo >= 0) and (G.RO[pLogo] = nil) and (AILogo[pLogo] <> nil) then 7743 BitBlt(Canvas.Handle, xRightPanel + 10 - (16 + 64), 7744 ClientHeight - PanelHeight, 64, 64, AILogo[pLogo].Canvas.Handle, 0, 0, 7745 SRCCOPY); 7746 end; 7747 7748 procedure TMainScreen.RectInvalidate(Left, Top, Rigth, Bottom: integer); 7749 var 7750 r0: HRgn; 7751 begin 7752 r0 := CreateRectRgn(Left, Top, Rigth, Bottom); 7753 InvalidateRgn(Handle, r0, false); 7754 DeleteObject(r0); 7755 end; 7756 7757 procedure TMainScreen.SmartRectInvalidate(Left, Top, Rigth, 7758 Bottom: integer); 7759 var 7760 i: integer; 7761 r0, r1: HRgn; 7762 begin 7763 r0 := CreateRectRgn(Left, Top, Rigth, Bottom); 7764 for i := 0 to ControlCount - 1 do 7765 if not(Controls[i] is TArea) and Controls[i].Visible then 7766 begin 7767 with Controls[i].BoundsRect do 7768 r1 := CreateRectRgn(Left, Top, Right, Bottom); 7769 CombineRgn(r0, r0, r1, RGN_DIFF); 7770 DeleteObject(r1); 7771 end; 7772 InvalidateRgn(Handle, r0, false); 7773 DeleteObject(r0); 7774 end; 7775 7776 procedure TMainScreen.mRepClicked(Sender: TObject); 7777 begin 7778 with TMenuItem(Sender) do 7779 begin 7780 Checked := not Checked; 7781 if Checked then 7782 CityRepMask := CityRepMask or (1 shl (Tag shr 8)) 3648 7783 else 7784 CityRepMask := CityRepMask and not(1 shl (Tag shr 8)) 7785 end 7786 end; 7787 7788 procedure TMainScreen.mLogClick(Sender: TObject); 7789 begin 7790 LogDlg.Show 7791 end; 7792 7793 procedure TMainScreen.FormShow(Sender: TObject); 7794 begin 7795 Timer1.Enabled := true 7796 end; 7797 7798 procedure TMainScreen.FormClose(Sender: TObject; var Action: TCloseAction); 7799 begin 7800 Timer1.Enabled := false 7801 end; 7802 7803 procedure TMainScreen.Radio(Sender: TObject); 7804 begin 7805 TMenuItem(Sender).Checked := true 7806 end; 7807 7808 procedure TMainScreen.mManipClick(Sender: TObject); 7809 var 7810 Flag: integer; 7811 begin 7812 with TMenuItem(Sender) do 7813 begin 7814 Flag := 1 shl (Tag shr 8); 7815 if Checked then 7816 Server(sClearTestFlag, 0, Flag, nil^) 7817 else 7818 begin 7819 Server(sSetTestFlag, 0, Flag, nil^); 7820 Play('CHEAT'); 7821 end; 7822 if not supervising then 7823 begin 7824 if Flag = tfUncover then 3649 7825 begin 3650 uix:=MyRO.nEnemyUn-1; 3651 while (uix>=0) and (MyRO.EnemyUn[uix].Loc<>Loc) do dec(uix); 3652 if uix>=0 then cm:=Tribe[MyRO.EnemyUn[uix].Owner].Color 3653 end; 3654 cm:=$808080 or cm shr 1; {increase brightness} 3655 end 3656 else if MapOptionChecked and (1 shl moPolitical)<>0 then 3657 begin 3658 if MyMap[Loc] and fTerrain<fGrass then cm:=cmPolOcean 3659 else if MyRO.Territory[Loc]<0 then cm:=cmPolNone 3660 else cm:=Tribe[MyRO.Territory[Loc]].Color; 3661 end; 3662 MiniLine[xm,0]:=cm shr 16; 3663 MiniLine[xm,1]:=cm shr 8 and $FF; 3664 MiniLine[xm,2]:=cm and $FF; 3665 end; 3666 end 3667 end; 3668 end; 3669 3670 procedure TMainScreen.MainOffscreenPaint; 3671 var 3672 ProcessOptions: integer; 3673 rec:TRect; 3674 DoInvalidate: boolean; 3675 begin 3676 if me<0 then 3677 with offscreen.Canvas do 3678 begin 3679 Brush.Color:=$000000; 3680 FillRect(Rect(0,0,MapWidth,MapHeight)); 3681 Brush.Style:=bsClear; 3682 OffscreenUser:=self; 3683 exit 3684 end; 3685 3686 MainMap.SetPaintBounds(0,0,MapWidth,MapHeight); 3687 if OffscreenUser<>self then 3688 begin 3689 if OffscreenUser<>nil then OffscreenUser.Update; 3690 // complete working with old owner to prevent rebound 3691 if MapValid and (xwd=xw) and (ywd=yw) then 3692 MainMap.SetPaintBounds(0,0,UsedOffscreenWidth,UsedOffscreenHeight); 3693 MapValid:=false; 3694 OffscreenUser:=self; 3695 end; 3696 3697 if xw-xwd>G.lx div 2 then xwd:=xwd+G.lx 3698 else if xwd-xw>G.lx div 2 then xwd:=xwd-G.lx; 3699 if not MapValid or (xw-xwd>MapWidth div (xxt*2)) or (xwd-xw>MapWidth div (xxt*2)) 3700 or (yw-ywd>MapHeight div yyt) or (ywd-yw>MapHeight div yyt) then 3701 begin 3702 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 3703 ProcessRect(xw,yw,MapWidth div xxt,MapHeight div yyt,prPaint or prInvalidate) 3704 end 3705 else 3706 begin 3707 if (xwd=xw) and (ywd=yw) then exit; {map window not moved} 3708 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 3709 rec:=Rect(0,0,MapWidth,MapHeight); 3710 ScrollDC(offscreen.Canvas.Handle,(xwd-xw)*(xxt*2),(ywd-yw)*yyt,rec,rec,0,nil); 3711 for DoInvalidate:=false to FastScrolling do 3712 begin 3713 if DoInvalidate then 3714 begin 3715 rec.bottom:=MapHeight-overlap; 3716 ScrollDC(Canvas.Handle,(xwd-xw)*(xxt*2),(ywd-yw)*yyt,rec,rec,0,nil); 3717 ProcessOptions:=prInvalidate; 3718 end 3719 else ProcessOptions:=prPaint or prAutoBounds; 3720 if yw<ywd then 3721 begin 3722 ProcessRect(xw,yw,MapWidth div xxt,ywd-yw-1,ProcessOptions); 3723 if xw<xwd then 3724 ProcessRect(xw,ywd,(xwd-xw)*2-1,MapHeight div yyt-ywd+yw,ProcessOptions) 3725 else if xw>xwd then 3726 ProcessRect((xwd+MapWidth div (xxt*2)) mod G.lx,ywd,(xw-xwd)*2+1, 3727 MapHeight div yyt-ywd+yw,ProcessOptions) 3728 end 3729 else if yw>ywd then 3730 begin 3731 if DoInvalidate then 3732 RectInvalidate(MapOffset,TopBarHeight+MapHeight-overlap-(yw-ywd)*yyt,MapOffset+MapWidth, 3733 TopBarHeight+MapHeight-overlap) 3734 else ProcessRect(xw,(ywd+MapHeight div (yyt*2) *2),MapWidth div xxt, 3735 yw-ywd+1,ProcessOptions); 3736 if xw<xwd then 3737 ProcessRect(xw,yw,(xwd-xw)*2-1,MapHeight div yyt-yw+ywd-2, 3738 ProcessOptions) 3739 else if xw>xwd then 3740 ProcessRect((xwd+MapWidth div (xxt*2)) mod G.lx,yw,(xw-xwd)*2+1, 3741 MapHeight div yyt-yw+ywd-2,ProcessOptions) 3742 end 3743 else 3744 if xw<xwd then 3745 ProcessRect(xw,yw,(xwd-xw)*2-1,MapHeight div yyt,ProcessOptions) 3746 else if xw>xwd then 3747 ProcessRect((xwd+MapWidth div (xxt*2)) mod G.lx,yw,(xw-xwd)*2+1, 3748 MapHeight div yyt,ProcessOptions); 3749 end; 3750 if not FastScrolling then 3751 RectInvalidate(MapOffset,TopBarHeight,MapOffset+MapWidth,TopBarHeight+MapHeight-overlap); 3752 RectInvalidate(xMidPanel,TopBarHeight+MapHeight-overlap,xRightPanel,TopBarHeight+MapHeight) 3753 end; 3754 //if (xwd<>xw) or (ywd<>yw) then 3755 // Server(sChangeSuperView,me,yw*G.lx+xw,nil^); // for synchronizing client side viewer, not used currently 3756 xwd:=xw;ywd:=yw; 3757 MapValid:=true; 3758 end; 3759 3760 procedure TMainScreen.PaintAll; 3761 begin 3762 MainOffscreenPaint; 3763 xwMini:=xw; ywMini:=yw; 3764 MiniPaint; 3765 PanelPaint; 3766 end; 3767 3768 procedure TMainScreen.PaintAllMaps; 3769 begin 3770 MainOffscreenPaint; 3771 xwMini:=xw; ywMini:=yw; 3772 MiniPaint; 3773 CopyMiniToPanel; 3774 RectInvalidate(xMini+2,TopBarHeight+MapHeight-overlap+yMini+2,xMini+2+G.lx*2, 3775 TopBarHeight+MapHeight-overlap+yMini+2+G.ly); 3776 end; 3777 3778 procedure TMainScreen.CopyMiniToPanel; 3779 begin 3780 BitBlt(Panel.Canvas.Handle,xMini+2,yMini+2,G.lx*2,G.ly,Mini.Canvas.Handle,0,0,SRCCOPY); 3781 if MarkCityLoc>=0 then 3782 Sprite(Panel, HGrSystem, xMini-2+(4*G.lx+2*(MarkCityLoc mod G.lx) 3783 +(G.lx-MapWidth div (xxt*2))-2*xwd) mod (2*G.lx) +MarkCityLoc div G.lx and 1, 3784 yMini-3+MarkCityLoc div G.lx,10,10,77,47) 3785 else if ywmax<=0 then 3786 Frame(Panel.Canvas,xMini+2+G.lx-MapWidth div (xxt*2),yMini+2, 3787 xMini+1+G.lx+MapWidth div (xxt*2), 3788 yMini+2+G.ly-1,MainTexture.clMark,MainTexture.clMark) 3789 else Frame(Panel.Canvas,xMini+2+G.lx-MapWidth div (xxt*2),yMini+2+yw, 3790 xMini+1+G.lx+MapWidth div (xxt*2), 3791 yMini+yw+MapHeight div yyt,MainTexture.clMark,MainTexture.clMark); 3792 end; 3793 3794 procedure TMainScreen.PanelPaint; 3795 3796 function MovementToString(var Un: TUn): string; 3797 begin 3798 result:=ScreenTools.MovementToString(Un.Movement); 3799 if Un.Master>=0 then 3800 result:='('+result+')' 3801 else if (MyModel[Un.mix].Domain=dAir) 3802 and (MyModel[Un.mix].Kind<>mkSpecial_Glider) then 3803 result:=Format('%s(%d)',[result,Un.Fuel]); 3804 end; 3805 3806 var 3807 i,uix,uixDefender,x,xSrc,ySrc,xSrcBase,ySrcBase,CostFactor,Count,mixShow, 3808 xTreasurySection,xResearchSection,JobFocus,TrueMoney, 3809 TrueResearch: integer; 3810 Tile: cardinal; 3811 s: string; 3812 unx:TUn; 3813 UnitInfo: TUnitInfo; 3814 JobProgressData: TJobProgressData; 3815 Prio: boolean; 3816 begin 3817 with Panel.Canvas do 3818 begin 3819 Fill(Panel.Canvas,0,3,xMidPanel+7-10,PanelHeight-3, 3820 wMainTexture-(xMidPanel+7-10),hMainTexture-PanelHeight); 3821 Fill(Panel.Canvas,xRightPanel+10-7,3,Panel.Width-xRightPanel-10+7,PanelHeight-3, 3822 -(xRightPanel+10-7),hMainTexture-PanelHeight); 3823 FillLarge(Panel.Canvas,xMidPanel-2,PanelHeight-MidPanelHeight,xRightPanel+2,PanelHeight, 3824 ClientWidth div 2); 3825 3826 Brush.Style:=bsClear; 3827 Pen.Color:=$000000; 3828 MoveTo(0,0);LineTo(xMidPanel+7-8,0); LineTo(xMidPanel+7-8,PanelHeight-MidPanelHeight); 3829 LineTo(xRightPanel,PanelHeight-MidPanelHeight); LineTo(xRightPanel,0); 3830 LineTo(ClientWidth,0); 3831 Pen.Color:=MainTexture.clBevelLight; 3832 MoveTo(xMidPanel+7-9,PanelHeight-MidPanelHeight+2); 3833 LineTo(xRightPanel+10-8,PanelHeight-MidPanelHeight+2); 3834 Pen.Color:=MainTexture.clBevelLight; 3835 MoveTo(0,1);LineTo(xMidPanel+7-9,1); Pen.Color:=MainTexture.clBevelShade; 3836 LineTo(xMidPanel+7-9,PanelHeight-MidPanelHeight+1); Pen.Color:=MainTexture.clBevelLight; 3837 LineTo(xRightPanel+10-9,PanelHeight-MidPanelHeight+1); Pen.Color:=MainTexture.clBevelLight; 3838 LineTo(xRightPanel+10-9,1); LineTo(ClientWidth,1); 3839 MoveTo(ClientWidth,2); LineTo(xRightPanel+10-8,2); LineTo(xRightPanel+10-8,PanelHeight); 3840 MoveTo(0,2);LineTo(xMidPanel+7-10,2); Pen.Color:=MainTexture.clBevelShade; 3841 LineTo(xMidPanel+7-10,PanelHeight); 3842 Corner(Panel.Canvas,xMidPanel+7-16,1,1,MainTexture); 3843 Corner(Panel.Canvas,xRightPanel+10-9,1,0,MainTexture); 3844 if ClientMode<>cEditMap then 3845 begin 3846 if supervising then 3847 begin 3848 Frame(Panel.Canvas, ClientWidth-xPalace-1, yPalace-1, 3849 ClientWidth-xPalace+xSizeBig, yPalace+ySizeBig, $B0B0B0, $FFFFFF); 3850 RFrame(Panel.Canvas, ClientWidth-xPalace-2, yPalace-2, 3851 ClientWidth-xPalace+xSizeBig+1, yPalace+ySizeBig+1, $FFFFFF, $B0B0B0); 3852 BitBlt(Panel.Canvas.Handle, ClientWidth-xPalace, yPalace, xSizeBig, 3853 ySizeBig, GrExt[HGrSystem2].Data.Canvas.Handle, 70, 123, SRCCOPY); 3854 end 3855 else if MyRO.NatBuilt[imPalace]>0 then 3856 ImpImage(Panel.Canvas, ClientWidth-xPalace, yPalace, imPalace, -1, GameMode<>cMovie 3857 {(GameMode<>cMovie) and (MyRO.Government<>gAnarchy)}) 3858 else ImpImage(Panel.Canvas, ClientWidth-xPalace, yPalace, 21, -1, GameMode<>cMovie 3859 {(GameMode<>cMovie) and (MyRO.Government<>gAnarchy)}); 3860 end; 3861 3862 if GameMode=cMovie then 3863 Frame(Panel.Canvas,xMini+1,yMini+1,xMini+2+G.lx*2,yMini+2+G.ly,$000000,$000000) 3864 else 3865 begin 3866 Frame(Panel.Canvas,xMini+1,yMini+1,xMini+2+G.lx*2,yMini+2+G.ly,$B0B0B0,$FFFFFF); 3867 RFrame(Panel.Canvas,xMini,yMini,xMini+3+G.lx*2,yMini+3+G.ly,$FFFFFF,$B0B0B0); 3868 end; 3869 CopyMiniToPanel; 3870 if ClientMode<>cEditMap then // MapBtn icons 3871 for i:=0 to 5 do if i<>3 then 3872 Dump(Panel,HGrSystem,xMini+G.lx-42+16*i,PanelHeight-26,8,8,121+i*9,61); 3873 3874 if ClientMode=cEditMap then 3875 begin 3876 for i:=0 to TrRow-1 do trix[i]:=-1; 3877 Count:=0; 3878 for i:=0 to nBrushTypes-1 do 3879 begin // display terrain types 3880 if (Count>=TrRow*sb.si.npos) and (Count<TrRow*(sb.si.npos+1)) then 3881 begin 3882 trix[Count-TrRow*sb.si.npos]:=BrushTypes[i]; 3883 x:=(Count-TrRow*sb.si.npos)*TrPitch; 3884 xSrcBase:=-1; 3885 case BrushTypes[i] of 3886 0..8: begin xSrc:=BrushTypes[i]; ySrc:=0 end; 3887 9..30: 3888 begin 3889 xSrcBase:=2; ySrcBase:=2; 3890 xSrc:=0; ySrc:=2*integer(BrushTypes[i])-15 3891 end; 3892 fRiver: begin xSrc:=7; ySrc:=14 end; 3893 fRoad: begin xSrc:=0; ySrc:=9 end; 3894 fRR: begin xSrc:=0; ySrc:=10 end; 3895 fCanal: begin xSrc:=0; ySrc:=11 end; 3896 fPoll: begin xSrc:=6; ySrc:=12 end; 3897 fDeadLands,fDeadLands or fCobalt,fDeadLands or fUranium, 3898 fDeadLands or fMercury: 3899 begin 3900 xSrcBase:=6; ySrcBase:=2; 3901 xSrc:=8; ySrc:=12+BrushTypes[i] shr 25; 3902 end; 3903 tiIrrigation, tiFarm, tiMine, tiBase: 3904 begin xSrc:=BrushTypes[i] shr 12-1; ySrc:=12 end; 3905 tiFort: 3906 begin xSrc:=3; ySrc:=12; xSrcBase:=7; ySrcBase:=12 end; 3907 fPrefStartPos: begin xSrc:=0; ySrc:=1 end; 3908 fStartPos: begin xSrc:=0; ySrc:=2 end; 3909 end; 3910 if xSrcBase>=0 then 3911 Sprite(Panel,HGrTerrain,xTroop+2+x,yTroop+9-yyt,xxt*2,yyt*3, 3912 1+xSrcBase*(xxt*2+1),1+ySrcBase*(yyt*3+1)); 3913 Sprite(Panel,HGrTerrain,xTroop+2+x,yTroop+9-yyt,xxt*2,yyt*3, 3914 1+xSrc*(xxt*2+1),1+ySrc*(yyt*3+1)); 3915 if BrushTypes[i]=BrushType then 3916 begin 3917 Frame(Panel.Canvas,xTroop+2+x,yTroop+7-yyt div 2,xTroop+2*xxt+x, 3918 yTroop+2*yyt+11,$000000,$000000); 3919 Frame(Panel.Canvas,xTroop+1+x,yTroop+6-yyt div 2,xTroop+2*xxt-1+x, 3920 yTroop+2*yyt+10,MainTexture.clMark,MainTexture.clMark); 7826 MapValid := false; 7827 PaintAllMaps; 3921 7828 end 3922 end; 3923 inc(Count) 3924 end; 3925 case BrushType of 3926 fDesert, fPrairie, fTundra, fArctic, fSwamp, fHills, fMountains: 3927 s:=Phrases.Lookup('TERRAIN',BrushType); 3928 fShore: s:=Format(Phrases.Lookup('TWOTERRAINS'), 3929 [Phrases.Lookup('TERRAIN',fOcean),Phrases.Lookup('TERRAIN',fShore)]); 3930 fGrass: s:=Format(Phrases.Lookup('TWOTERRAINS'), 3931 [Phrases.Lookup('TERRAIN',fGrass),Phrases.Lookup('TERRAIN',fGrass+12)]); 3932 fForest: s:=Format(Phrases.Lookup('TWOTERRAINS'), 3933 [Phrases.Lookup('TERRAIN',fForest),Phrases.Lookup('TERRAIN',fJungle)]); 3934 fRiver: s:=Phrases.Lookup('RIVER'); 3935 fDeadLands,fDeadLands or fCobalt,fDeadLands or fUranium, 3936 fDeadLands or fMercury: 3937 s:=Phrases.Lookup('TERRAIN',3*12+BrushType shr 25); 3938 fPrefStartPos: s:=Phrases.Lookup('MAP_PREFSTART'); 3939 fStartPos: s:=Phrases.Lookup('MAP_START'); 3940 fPoll: s:=Phrases.Lookup('POLL'); 3941 else // terrain improvements 3942 begin 3943 case BrushType of 3944 fRoad: i:=1; 3945 fRR: i:=2; 3946 tiIrrigation: i:=4; 3947 tiFarm: i:=5; 3948 tiMine: i:=7; 3949 fCanal: i:=8; 3950 tiFort: i:=10; 3951 tiBase: i:=12; 3952 end; 3953 s:=Phrases.Lookup('JOBRESULT',i); 3954 end 3955 end; 3956 LoweredTextOut(Panel.Canvas,-1,MainTexture,xTroop+1,PanelHeight-19,s); 3957 end 3958 else if TroopLoc>=0 then 3959 begin 3960 Brush.Style:=bsClear; 3961 if UnFocus>=0 then with MyUn[UnFocus],MyModel[mix] do 3962 begin {display info about selected unit} 3963 if Job=jCity then 3964 mixShow:=-1 // building site 3965 else mixShow:=mix; 3966 with Tribe[me].ModelPicture[mixShow] do 3967 begin 3968 Sprite(Panel,HGr,xMidPanel+7+12,yTroop+1,64,48, 3969 pix mod 10 *65+1,pix div 10 *49+1); 3970 if MyUn[UnFocus].Flags and unFortified<>0 then 3971 Sprite(Panel,HGrStdUnits,xMidPanel+7+12,yTroop+1,xxu*2,yyu*2,1+6*(xxu*2+1),1); 3972 end; 3973 3974 MakeBlue(Panel,xMidPanel+7+12+10,yTroop-13,44,12); 3975 s:=MovementToString(MyUn[UnFocus]); 3976 RisedTextOut(Panel.Canvas,xMidPanel+7+12+32-BiColorTextWidth(Panel.Canvas,s) div 2, 3977 yTroop-16,s); 3978 3979 s:=IntToStr(Health)+'%'; 3980 LightGradient(Panel.Canvas,xMidPanel+7+12+7,PanelHeight-22,(Health+1) div 2, 3981 (ColorOfHealth(Health) and $FEFEFE shr 2)*3); 3982 if Health<100 then 3983 LightGradient(Panel.Canvas,xMidPanel+7+12+7+(Health+1) div 2, 3984 PanelHeight-22,50-(Health+1) div 2,$000000); 3985 RisedTextOut(Panel.Canvas,xMidPanel+7+12+32-BiColorTextWidth(Panel.Canvas,s) div 2, 3986 PanelHeight-23,s); 3987 3988 FrameImage(Panel.Canvas,GrExt[HGrSystem].Data,xMidPanel+7+xUnitText,yTroop+15,12,14, 3989 121+Exp div ExpCost *13,28); 3990 if Job=jCity then s:=Tribe[me].ModelName[-1] 3991 else s:=Tribe[me].ModelName[mix]; 3992 if Home>=0 then 3993 begin 3994 LoweredTextOut(Panel.Canvas,-1,MainTexture,xMidPanel+7+xUnitText+18,yTroop+5,s); 3995 LoweredTextOut(Panel.Canvas,-1,MainTexture,xMidPanel+7+xUnitText+18,yTroop+21, 3996 '('+CityName(MyCity[Home].ID)+')'); 3997 end 3998 else LoweredTextOut(Panel.Canvas,-1,MainTexture,xMidPanel+7+xUnitText+18,yTroop+13,s); 3999 end; 4000 4001 if (UnFocus>=0) and (MyUn[UnFocus].Loc<>TroopLoc) then 4002 begin // divide panel 4003 if SmallScreen and not supervising then 4004 x:=xTroop-8 4005 else x:=xTroop-152; 4006 Pen.Color:=MainTexture.clBevelShade; 4007 MoveTo(x-1,PanelHeight-MidPanelHeight+2); 4008 LineTo(x-1,PanelHeight); 4009 Pen.Color:=MainTexture.clBevelLight; 4010 MoveTo(x,PanelHeight-MidPanelHeight+2); 4011 LineTo(x,PanelHeight); 4012 end; 4013 4014 for i:=0 to 23 do trix[i]:=-1; 4015 if MyMap[TroopLoc] and fUnit<>0 then 4016 begin 4017 if MyMap[TroopLoc] and fOwned<>0 then 4018 begin 4019 if (TrCnt>1) or (UnFocus<0) or (MyUn[UnFocus].Loc<>TroopLoc) then 4020 begin 4021 LoweredTextOut(Panel.Canvas, -1, MainTexture, xTroop+10, PanelHeight-24, 4022 Phrases.Lookup('PRESENT')); 4023 Server(sGetDefender,me,TroopLoc,uixDefender); 4024 Count:=0; 4025 for Prio:=true downto false do 4026 for uix:=0 to MyRO.nUn-1 do if (uix=uixDefender)=Prio then 4027 begin // display own units 4028 unx:=MyUn[uix]; 4029 if unx.Loc=TroopLoc then 4030 begin 4031 if (Count>=TrRow*sb.si.npos) and (Count<TrRow*(sb.si.npos+1)) then 4032 begin 4033 trix[Count-TrRow*sb.si.npos]:=uix; 4034 MakeUnitInfo(me,unx,UnitInfo); 4035 x:=(Count-TrRow*sb.si.npos)*TrPitch; 4036 if uix=UnFocus then 4037 begin 4038 Frame(Panel.Canvas,xTroop+4+x,yTroop+3,xTroop+64+x, 4039 yTroop+47,$000000,$000000); 4040 Frame(Panel.Canvas,xTroop+3+x,yTroop+2,xTroop+63+x, 4041 yTroop+46,MainTexture.clMark,MainTexture.clMark); 4042 end 4043 else if (unx.Master>=0) and (unx.Master=UnFocus) then 4044 begin 4045 CFrame(Panel.Canvas,xTroop+4+x,yTroop+3,xTroop+64+x, 4046 yTroop+47,8,$000000); 4047 CFrame(Panel.Canvas,xTroop+3+x,yTroop+2,xTroop+63+x, 4048 yTroop+46,8,MainTexture.clMark); 4049 end; 4050 NoMap.SetOutput(Panel); 4051 NoMap.PaintUnit(xTroop+2+x,yTroop+1,UnitInfo,unx.Status); 4052 if (ClientMode<scContact) 4053 and ((unx.Job>jNone) 4054 or (unx.Status and (usStay or usRecover or usGoto)<>0)) then 4055 Sprite(Panel, HGrSystem, xTroop+2+60-20+x, yTroop+35, 4056 20, 20, 81, 25); 4057 4058 if not supervising then 4059 begin 4060 MakeBlue(Panel,xTroop+2+10+x,yTroop-13,44,12); 4061 s:=MovementToString(unx); 4062 RisedTextOut(Panel.Canvas,xTroop+x+34-BiColorTextWidth(Panel.Canvas,s) div 2, 4063 yTroop-16,s); 4064 end 4065 end; 4066 inc(Count) 4067 end; 4068 end; // for uix:=0 to MyRO.nUn-1 4069 assert(Count=TrCnt); 4070 end 4071 end 4072 else 4073 begin 4074 LoweredTextOut(Panel.Canvas, -1, MainTexture, xTroop+8, PanelHeight-24, 4075 Phrases.Lookup('PRESENT')); 4076 Server(sGetUnits,me,TroopLoc,Count); 4077 for i:=0 to Count-1 do 4078 if (i>=TrRow*sb.si.npos) and (i<TrRow*(sb.si.npos+1)) then 4079 begin // display enemy units 4080 trix[i-TrRow*sb.si.npos]:=i; 4081 x:=(i-TrRow*sb.si.npos)*TrPitch; 4082 NoMap.SetOutput(Panel); 4083 NoMap.PaintUnit(xTroop+2+x,yTroop+1,MyRO.EnemyUn[MyRO.nEnemyUn+i],0); 4084 end; 4085 end; 4086 end; 4087 if not SmallScreen or supervising then 4088 begin // show terrain and improvements 4089 PaintZoomedTile(Panel, xTerrain-xxt*2, 110-yyt*3, TroopLoc); 4090 if (UnFocus>=0) and (MyUn[UnFocus].Job<>jNone) then 4091 begin 4092 JobFocus:=MyUn[UnFocus].Job; 4093 Server(sGetJobProgress, me, MyUn[UnFocus].Loc, JobProgressData); 4094 MakeBlue(Panel,xTerrain-72,148-17,144,31); 4095 PaintRelativeProgressBar(Panel.Canvas,3,xTerrain-68,148+3,63, 4096 JobProgressData[JobFocus].Done, 4097 JobProgressData[JobFocus].NextTurnPlus, 4098 JobProgressData[JobFocus].Required,true,MainTexture); 4099 s:=Format('%s/%s',[ScreenTools.MovementToString(JobProgressData[JobFocus].Done), 4100 ScreenTools.MovementToString(JobProgressData[JobFocus].Required)]); 4101 RisedTextOut(Panel.Canvas,xTerrain+6,148-3,s); 4102 Tile:=MyMap[MyUn[UnFocus].Loc]; 4103 if (JobFocus=jRoad) and (Tile and fRiver<>0) then 4104 JobFocus:=nJob+0 4105 else if (JobFocus=jRR) and (Tile and fRiver<>0) then 4106 JobFocus:=nJob+1 4107 else if JobFocus=jClear then 4108 begin 4109 if Tile and fTerrain=fForest then 4110 JobFocus:=nJob+2 4111 else if Tile and fTerrain=fDesert then 4112 JobFocus:=nJob+3 4113 else JobFocus:=nJob+4 4114 end; 4115 s:=Phrases.Lookup('JOBRESULT', JobFocus); 4116 RisedTextOut(Panel.Canvas,xTerrain-BiColorTextWidth(Panel.Canvas,s) div 2, 4117 148-19,s); 4118 end; 4119 if MyMap[TroopLoc] and (fTerrain or fSpecial)=fGrass or fSpecial1 then 4120 s:=Phrases.Lookup('TERRAIN',fGrass+12) 4121 else if MyMap[TroopLoc] and fDeadlands<>0 then 4122 s:=Phrases.Lookup('TERRAIN',3*12) 4123 else if (MyMap[TroopLoc] and fTerrain=fForest) 4124 and IsJungle(TroopLoc div G.lx) then 4125 s:=Phrases.Lookup('TERRAIN',fJungle) 4126 else s:=Phrases.Lookup('TERRAIN',MyMap[TroopLoc] and fTerrain); 4127 RisedTextOut(Panel.Canvas,xTerrain-BiColorTextWidth(Panel.Canvas,s) div 2, 4128 99,s); 4129 end; 4130 4131 if TerrainBtn.Visible then with TerrainBtn do 4132 RFrame(Panel.Canvas,Left-1,Top-self.ClientHeight+(PanelHeight-1), 4133 Left+Width,Top+Height-self.ClientHeight+PanelHeight, 4134 MainTexture.clBevelShade,MainTexture.clBevelLight) 4135 end {if TroopLoc>=0} 4136 end; 4137 4138 for i:=0 to ControlCount-1 do 4139 if Controls[i] is TButtonB then with TButtonB(Controls[i]) do 4140 begin 4141 if Visible then 4142 begin 4143 Dump(Panel,HGrSystem,Left,Top-self.ClientHeight+PanelHeight,25,25,169,243); 4144 Sprite(Panel,HGrSystem,Left,Top-self.ClientHeight+PanelHeight,25,25, 4145 1+26*ButtonIndex,337); 4146 RFrame(Panel.Canvas,Left-1,Top-self.ClientHeight+(PanelHeight-1), 4147 Left+Width,Top+Height-self.ClientHeight+PanelHeight, 4148 MainTexture.clBevelShade,MainTexture.clBevelLight); 4149 end; 4150 end; 4151 4152 if ClientMode<>cEditMap then 4153 begin 4154 for i:=0 to ControlCount-1 do 4155 if Controls[i] is TButtonC then with TButtonC(Controls[i]) do 4156 begin 4157 Dump(Panel,HGrSystem,Left,Top-self.ClientHeight+PanelHeight,12,12, 4158 169,178+13*ButtonIndex); 4159 RFrame(Panel.Canvas,Left-1,Top-self.ClientHeight+(PanelHeight-1), 4160 Left+Width,Top+Height-self.ClientHeight+PanelHeight, 4161 MainTexture.clBevelShade,MainTexture.clBevelLight); 4162 end 4163 end; 4164 EOT.SetBack(Panel.Canvas,EOT.Left,EOT.Top-(ClientHeight-PanelHeight)); 4165 SmartRectInvalidate(0,ClientHeight-PanelHeight,ClientWidth,ClientHeight); 4166 4167 // topbar 4168 xTreasurySection:=ClientWidth div 2-172; 4169 xResearchSection:=ClientWidth div 2; //ClientWidth div 2+68 = maximum to right 4170 FillLarge(TopBar.Canvas,0,0,ClientWidth,TopBarHeight-3,ClientWidth div 2); 4171 with TopBar.Canvas do 4172 begin 4173 Pen.Color:=$000000; 4174 MoveTo(0,TopBarHeight-1); LineTo(ClientWidth, TopBarHeight-1); 4175 Pen.Color:=MainTexture.clBevelShade; 4176 MoveTo(0,TopBarHeight-2); LineTo(ClientWidth, TopBarHeight-2); 4177 MoveTo(0,TopBarHeight-3); LineTo(ClientWidth, TopBarHeight-3); 4178 Pen.Color:=MainTexture.clBevelLight; 4179 frame(TopBar.Canvas,40,-1,xTreasurySection-1,TopBarHeight-7, 4180 MainTexture.clBevelShade,MainTexture.clBevelLight); 4181 frame(TopBar.Canvas,xResearchSection+332,-1,ClientWidth,TopBarHeight-7, 4182 MainTexture.clBevelShade,MainTexture.clBevelLight); 4183 end; 4184 if GameMode<>cMovie then 4185 ImageOp_BCC(TopBar,Templates,2,1,145,38,36,36,$BFBF20,$4040DF); 4186 if MyRO.nCity>0 then 4187 begin 4188 TrueMoney:=MyRO.Money; 4189 TrueResearch:=MyRO.Research; 4190 if supervising then 4191 begin // normalize values from after-turn state 4192 dec(TrueMoney,TaxSum); 4193 if TrueMoney<0 then 4194 TrueMoney:=0; // shouldn't happen 4195 dec(TrueResearch,ScienceSum); 4196 if TrueResearch<0 then 4197 TrueResearch:=0; // shouldn't happen 4198 end; 4199 4200 // treasury section 4201 ImageOp_BCC(TopBar,Templates,xTreasurySection+8,1,145,1,36,36,$40A040,$4030C0); 4202 s:=IntToStr(TrueMoney); 4203 LoweredTextOut(TopBar.Canvas,-1,MainTexture,xTreasurySection+48,0,s+'%c'); 4204 if MyRO.Government<>gAnarchy then 4205 begin 4206 ImageOp_BCC(TopBar,Templates,xTreasurySection+48,22,124,1,14,14,$0000C0, $0080C0); 4207 if TaxSum>=0 then 4208 s:=Format(Phrases.Lookup('MONEYGAINPOS'),[TaxSum]) 4209 else s:=Format(Phrases.Lookup('MONEYGAINNEG'),[TaxSum]); 4210 LoweredTextOut(TopBar.Canvas,-1,MainTexture,xTreasurySection+48+15,18,s); 4211 end; 4212 4213 // research section 4214 ImageOp_BCC(TopBar,Templates,xResearchSection+8,1,145,75,36,36,$FF0000,$00FFE0); 4215 if MyData.FarTech<>adNexus then 4216 begin 4217 if MyRO.ResearchTech<0 then 4218 CostFactor:=2 4219 else if (MyRO.ResearchTech=adMilitary) or (MyRO.Tech[MyRO.ResearchTech]=tsSeen) then 4220 CostFactor:=1 4221 else if MyRO.ResearchTech in FutureTech then 4222 if MyRO.Government=gFuture then 4223 CostFactor:=4 4224 else CostFactor:=8 4225 else CostFactor:=2; 4226 Server(sGetTechCost,me,0,i); 4227 CostFactor:=CostFactor*22; // length of progress bar 4228 PaintRelativeProgressBar(TopBar.Canvas,2,xResearchSection+48+1,26, 4229 CostFactor,TrueResearch,ScienceSum,i,true,MainTexture); 4230 4231 if MyRO.ResearchTech<0 then 4232 s:=Phrases.Lookup('SCIENCE') 4233 else if MyRO.ResearchTech=adMilitary then 4234 s:=Phrases.Lookup('INITUNIT') 4235 else 4236 begin 4237 s:=Phrases.Lookup('ADVANCES', MyRO.ResearchTech); 4238 if MyRO.ResearchTech in FutureTech then 4239 if MyRO.Tech[MyRO.ResearchTech]>=1 then 4240 s:=s+' '+IntToStr(MyRO.Tech[MyRO.ResearchTech]+1) 4241 else s:=s+' 1'; 4242 end; 4243 if ScienceSum>0 then 4244 begin 4245 { j:=(i-MyRO.Research-1) div ScienceSum +1; 4246 if j<1 then j:=1; 4247 if j>1 then 4248 s:=Format(Phrases.Lookup('TECHWAIT'),[s,j]);} 4249 LoweredTextOut(TopBar.Canvas,-1,MainTexture,xResearchSection+48,0,s); 4250 end 4251 else LoweredTextOut(TopBar.Canvas,-1,MainTexture,xResearchSection+48,0,s); 4252 end 4253 else CostFactor:=0; 4254 if (MyData.FarTech<>adNexus) and (ScienceSum>0) then 4255 begin 4256 ImageOp_BCC(TopBar,Templates,xResearchSection+48+CostFactor+11,22,124,1,14,14,$0000C0, $0080C0); 4257 s:=Format(Phrases.Lookup('TECHGAIN'),[ScienceSum]); 4258 LoweredTextOut(TopBar.Canvas,-1,MainTexture,xResearchSection+48+CostFactor+26,18,s); 4259 end 4260 end; 4261 if ClientMode<>cEditMap then 4262 begin 4263 TopBar.Canvas.Font.Assign(UniFont[ftCaption]); 4264 s:=TurnToString(MyRO.Turn); 4265 RisedTextOut(TopBar.Canvas,40+(xTreasurySection-40-BiColorTextWidth(TopBar.Canvas,s)) div 2,6,s); 4266 TopBar.Canvas.Font.Assign(UniFont[ftNormal]); 4267 end; 4268 RectInvalidate(0,0,ClientWidth,TopBarHeight); 4269 end;{PanelPaint} 4270 4271 procedure TMainScreen.FocusOnLoc(Loc:integer; Options: integer = 0); 4272 var 4273 dx: integer; 4274 Outside, Changed: boolean; 4275 begin 4276 dx:=G.lx+1-(xw-Loc+G.lx*1024+1) mod G.lx; 4277 Outside:=(dx>=(MapWidth+1) div (xxt*2)-2) 4278 or (ywmax>0) and ((yw>0) and (Loc div G.lx<=yw+1) 4279 or (yw<ywmax) and (Loc div G.lx>=yw+(MapHeight-1) div yyt-2)); 4280 Changed:=true; 4281 if Outside then 4282 begin Centre(Loc); PaintAllMaps end 4283 else if not MapValid then 4284 PaintAllMaps 4285 else Changed:=false; 4286 if Options and flRepaintPanel<>0 then 4287 PanelPaint; 4288 if Changed and (Options and flImmUpdate<>0) then Update; 4289 end; 4290 4291 procedure TMainScreen.NextUnit(NearLoc:integer;AutoTurn:boolean); 4292 var 4293 Dist,TestDist:single; 4294 i,uix,NewFocus:integer; 4295 GotoOnly: boolean; 4296 begin 4297 if ClientMode>=scContact then exit; 4298 DestinationMarkON:=false; 4299 PaintDestination; 4300 for GotoOnly:=GoOnPhase downto false do 4301 begin 4302 NewFocus:=-1; 4303 for i:=1 to MyRO.nUn do 4304 begin 4305 uix:=(UnFocus+i) mod MyRO.nUn; 4306 if (MyUn[uix].Loc>=0) and (MyUn[uix].Job=jNone) 4307 and (MyUn[uix].Status and (usStay or usRecover or usWaiting)=usWaiting) 4308 and (not GotoOnly or (MyUn[uix].Status and usGoto<>0)) then 4309 if NearLoc<0 then begin NewFocus:=uix; Break end 4310 else 4311 begin 4312 TestDist:=Distance(NearLoc,MyUn[uix].Loc); 4313 if (NewFocus<0) or (TestDist<Dist) then 4314 begin NewFocus:=uix; Dist:=TestDist end 4315 end 4316 end; 4317 if GotoOnly then 4318 if NewFocus<0 then GoOnPhase:=false 4319 else break; 4320 end; 4321 if NewFocus>=0 then 4322 begin 4323 SetUnFocus(NewFocus); 4324 SetTroopLoc(MyUn[NewFocus].Loc); 4325 FocusOnLoc(TroopLoc,flRepaintPanel) 4326 end 4327 else if AutoTurn and not mWaitTurn.Checked then 4328 begin 4329 TurnComplete:=true; 4330 SetUnFocus(-1); 4331 SetTroopLoc(-1); 4332 PostMessage(Handle,WM_EOT,0,0) 4333 end 4334 else 4335 begin 4336 if {(UnFocus>=0) and} not TurnComplete and EOT.Visible then Play('TURNEND'); 4337 TurnComplete:=true; 4338 SetUnFocus(-1); 4339 SetTroopLoc(-1); 4340 PanelPaint; 4341 end; 4342 end;{NextUnit} 4343 4344 procedure TMainScreen.Scroll(dx,dy: integer); 4345 begin 4346 xw:=(xw+G.lx+dx) mod G.lx; 4347 if ywmax>0 then 4348 begin 4349 yw:=yw+2*dy; 4350 if yw<0 then yw:=0 4351 else if yw>ywmax then yw:=ywmax; 4352 end; 4353 MainOffscreenPaint; 4354 xwMini:=xw; ywMini:=yw; 4355 MiniPaint; 4356 CopyMiniToPanel; 4357 RectInvalidate(xMini+2,TopBarHeight+MapHeight-overlap+yMini+2,xMini+2+G.lx*2, 4358 TopBarHeight+MapHeight-overlap+yMini+2+G.ly); 4359 Update; 4360 end; 4361 4362 procedure TMainScreen.Timer1Timer(Sender:TObject); 4363 var 4364 dx, dy, speed: integer; 4365 begin 4366 if idle and (me>=0) and (GameMode<>cMovie) then 4367 if (fsModal in Screen.ActiveForm.FormState) 4368 or (Screen.ActiveForm is TBufferedDrawDlg) 4369 and (TBufferedDrawDlg(Screen.ActiveForm).WindowMode<>wmPersistent) then 4370 begin 4371 BlinkTime:=BlinkOnTime+BlinkOffTime-1; 4372 if not BlinkON then 4373 begin 4374 BlinkON:=true; 4375 if UnFocus>=0 then 4376 PaintLocTemp(MyUn[UnFocus].Loc) 4377 else if TurnComplete and not supervising then 4378 EOT.SetButtonIndexFast(eotBlinkOn) 4379 end 4380 end 4381 else 4382 begin 4383 if Application.Active and not mScrollOff.Checked then 4384 begin 4385 if mScrollFast.Checked then Speed:=2 4386 else Speed:=1; 4387 dx:=0; 4388 dy:=0; 4389 if Mouse.CursorPos.y<Screen.Height-PanelHeight then 4390 if Mouse.CursorPos.x=0 then dx:=-Speed // scroll left 4391 else if Mouse.CursorPos.x=Screen.Width-1 then dx:=Speed; // scroll right 4392 if Mouse.CursorPos.y=0 then dy:=-Speed // scroll up 4393 else if (Mouse.CursorPos.y=Screen.Height-1) 4394 and (Mouse.CursorPos.x>=TerrainBtn.Left+TerrainBtn.Width) 4395 and (Mouse.CursorPos.x<xRightPanel+10-8) then dy:=Speed; // scroll down 4396 if (dx<>0) or (dy<>0) then 4397 begin 4398 if (Screen.ActiveForm<>MainScreen) 4399 and (@Screen.ActiveForm.OnDeactivate<>nil) then 4400 Screen.ActiveForm.OnDeactivate(nil); 4401 Scroll(dx,dy); 4402 end 4403 end; 4404 4405 BlinkTime:=(BlinkTime+1) mod (BlinkOnTime+BlinkOffTime); 4406 BlinkON:= BlinkTime>=BlinkOffTime; 4407 DestinationMarkON:=true; 4408 if UnFocus>=0 then 4409 begin 4410 if (BlinkTime=0) or (BlinkTime=BlinkOffTime) then 4411 begin 4412 PaintLocTemp(MyUn[UnFocus].Loc,pltsBlink); 4413 PaintDestination; 4414 // if MoveHintToLoc>=0 then 4415 // ShowMoveHint(MoveHintToLoc, true); 7829 else if Flag = tfAllTechs then 7830 TellNewModels 4416 7831 end 4417 7832 end 4418 else if TurnComplete and not supervising then 4419 begin 4420 if BlinkTime=0 then EOT.SetButtonIndexFast(eotBlinkOff) 4421 else if BlinkTime=BlinkOffTime then EOT.SetButtonIndexFast(eotBlinkOn) 7833 end; 7834 7835 procedure TMainScreen.MapBtnClick(Sender: TObject); 7836 begin 7837 with TButtonC(Sender) do 7838 begin 7839 MapOptionChecked := MapOptionChecked xor (1 shl (Tag shr 8)); 7840 SetMapOptions; 7841 ButtonIndex := MapOptionChecked shr (Tag shr 8) and 1 + 2 7842 end; 7843 if Sender = MapBtn0 then 7844 begin 7845 MiniPaint; 7846 PanelPaint 7847 end // update mini map only 7848 else 7849 begin 7850 MapValid := false; 7851 PaintAllMaps; 7852 end; // update main map 7853 end; 7854 7855 procedure TMainScreen.GrWallBtnDownChanged(Sender: TObject); 7856 begin 7857 if TButtonBase(Sender).Down then 7858 begin 7859 MapOptionChecked := MapOptionChecked or (1 shl moGreatWall); 7860 TButtonBase(Sender).Hint := ''; 4422 7861 end 4423 end 4424 end; 4425 4426 procedure TMainScreen.Centre(Loc:integer); 4427 begin 4428 if FastScrolling and MapValid then update; 4429 // necessary because ScrollDC for form canvas is called after 4430 xw:=(Loc mod G.lx-(MapWidth-xxt*2*((Loc div G.lx) and 1)) div (xxt*4)+G.lx) mod G.lx; 4431 if ywmax<=0 then yw:=ywcenter 4432 else 4433 begin 4434 yw:=(Loc div G.lx-MapHeight div (yyt*2)+1) and not 1; 4435 if yw<0 then yw:=0 4436 else if yw>ywmax then yw:=ywmax; 4437 end 4438 end; 4439 4440 function TMainScreen.ZoomToCity(Loc: integer; NextUnitOnClose: boolean = false; 4441 ShowEvent: integer = 0): boolean; 4442 begin 4443 result:= MyMap[Loc] and (fOwned or fSpiedOut)<>0; 4444 if result then with CityDlg do 4445 begin 4446 if ClientMode>=scContact then 4447 begin 4448 CloseAction:=None; 4449 RestoreUnFocus:=-1; 4450 end 4451 else if NextUnitOnClose then 4452 begin 4453 CloseAction:=StepFocus; 4454 RestoreUnFocus:=-1; 4455 end 4456 else if not Visible then 4457 begin 4458 CloseAction:=RestoreFocus; 4459 RestoreUnFocus:=UnFocus; 4460 end; 4461 SetUnFocus(-1); 4462 SetTroopLoc(Loc); 4463 MarkCityLoc:=Loc; 4464 PanelPaint; 4465 ShowNewContent(wmPersistent, Loc, ShowEvent); 4466 end 4467 end; 4468 4469 function TMainScreen.LocationOfScreenPixel(x,y: integer): integer; 4470 var 4471 qx,qy: integer; 4472 begin 4473 qx:=(x*(yyt*2)+y*(xxt*2)+xxt*yyt*2) div (xxt*yyt*4)-1; 4474 qy:=(y*(xxt*2)-x*(yyt*2)-xxt*yyt*2+4000*xxt*yyt) div (xxt*yyt*4)-999; 4475 result:=(xw+(qx-qy+2048) div 2-1024+G.lx) mod G.lx+G.lx*(yw+qx+qy); 4476 end; 4477 4478 procedure TMainScreen.MapBoxMouseDown(Sender:TObject; 4479 Button:TMouseButton;Shift:TShiftState;x,y:integer); 4480 var 4481 i,uix,emix,p1,dx,dy,MouseLoc:integer; 4482 EditTileData: TEditTileData; 4483 m,m2: TMenuItem; 4484 MoveAdviceData: TMoveAdviceData; 4485 DoCenter: boolean; 4486 begin 4487 if GameMode=cMovie then 4488 exit; 4489 4490 if CityDlg.Visible then CityDlg.Close; 4491 if UnitStatDlg.Visible then UnitStatDlg.Close; 4492 MouseLoc:=LocationOfScreenPixel(x,y); 4493 if (MouseLoc<0) or (MouseLoc>=G.lx*G.ly) then exit; 4494 if (Button=mbLeft) and not(ssShift in Shift) then 4495 begin 4496 DoCenter:=true; 4497 if ClientMode=cEditMap then 4498 begin 4499 DoCenter:=false; 4500 EditTileData.Loc:=MouseLoc; 4501 if ssCtrl in Shift then // toggle special resource 4502 case MyMap[MouseLoc] and fTerrain of 4503 fOcean: EditTileData.NewTile:=MyMap[MouseLoc]; 4504 fGrass, fArctic: EditTileData.NewTile:=MyMap[MouseLoc] and not fSpecial 4505 or ((MyMap[MouseLoc] shr 5 and 3+1) mod 2 shl 5); 4506 else EditTileData.NewTile:=MyMap[MouseLoc] and not fSpecial 4507 or ((MyMap[MouseLoc] shr 5 and 3+1) mod 3 shl 5) 4508 end 4509 else if BrushType<=fTerrain then 4510 EditTileData.NewTile:=MyMap[MouseLoc] and not fTerrain or fSpecial or BrushType 4511 else if BrushType and fDeadLands<>0 then 4512 if MyMap[MouseLoc] and (fDeadLands or fModern) 4513 =BrushType and (fDeadLands or fModern) then 4514 EditTileData.NewTile:=MyMap[MouseLoc] and not (fDeadLands or fModern) 4515 else EditTileData.NewTile:=MyMap[MouseLoc] and not (fDeadLands or fModern) 4516 or BrushType 4517 else if BrushType and fTerImp<>0 then 4518 if MyMap[MouseLoc] and fTerImp=BrushType then 4519 EditTileData.NewTile:=MyMap[MouseLoc] and not fTerImp 4520 else EditTileData.NewTile:=MyMap[MouseLoc] and not fTerImp or BrushType 4521 else if BrushType and (fPrefStartPos or fStartPos)<>0 then 4522 if MyMap[MouseLoc] and (fPrefStartPos or fStartPos) 4523 =BrushType and (fPrefStartPos or fStartPos) then 4524 EditTileData.NewTile:=MyMap[MouseLoc] and not (fPrefStartPos or fStartPos) 4525 else EditTileData.NewTile:=MyMap[MouseLoc] 4526 and not (fPrefStartPos or fStartPos) or BrushType 4527 else EditTileData.NewTile:=MyMap[MouseLoc] xor BrushType; 4528 Server(sEditTile,me,0,EditTileData); 4529 Edited:=true; 4530 BrushLoc:=MouseLoc; 4531 PaintLoc(MouseLoc,2); 4532 MiniPaint; 4533 BitBlt(Panel.Canvas.Handle,xMini+2,yMini+2,G.lx*2,G.ly,Mini.Canvas.Handle, 4534 0,0,SRCCOPY); 4535 if ywmax<=0 then 4536 Frame(Panel.Canvas,xMini+2+G.lx-MapWidth div (2*xxt),yMini+2, 4537 xMini+1+G.lx+MapWidth div (2*xxt), 4538 yMini+2+G.ly-1,MainTexture.clMark,MainTexture.clMark) 4539 else Frame(Panel.Canvas,xMini+2+G.lx-MapWidth div (2*xxt),yMini+2+yw, 4540 xMini+2+G.lx+MapWidth div (2*xxt)-1, 4541 yMini+2+yw+MapHeight div yyt-2,MainTexture.clMark,MainTexture.clMark); 4542 RectInvalidate(xMini+2,TopBarHeight+MapHeight-overlap+yMini+2,xMini+2+G.lx*2, 4543 TopBarHeight+MapHeight-overlap+yMini+2+G.ly) 4544 end 4545 else if MyMap[MouseLoc] and fCity<>0 then {city clicked} 4546 begin 4547 if MyMap[MouseLoc] and (fOwned or fSpiedOut)<>0 then 4548 begin 4549 ZoomToCity(MouseLoc); 4550 DoCenter:=false; 7862 else 7863 begin 7864 MapOptionChecked := MapOptionChecked and not(1 shl moGreatWall); 7865 TButtonBase(Sender).Hint := Phrases.Lookup('CONTROLS', 7866 -1 + TButtonBase(Sender).Tag and $FF); 7867 end; 7868 SetMapOptions; 7869 MapValid := false; 7870 PaintAllMaps; 7871 end; 7872 7873 procedure TMainScreen.BareBtnDownChanged(Sender: TObject); 7874 begin 7875 if TButtonBase(Sender).Down then 7876 begin 7877 MapOptionChecked := MapOptionChecked or (1 shl moBareTerrain); 7878 TButtonBase(Sender).Hint := ''; 4551 7879 end 4552 else 4553 begin 4554 UnitStatDlg.ShowNewContent_EnemyCity(wmPersistent, MouseLoc); 4555 DoCenter:=false; 4556 end 4557 end 4558 else if MyMap[MouseLoc] and fUnit<>0 then {unit clicked} 4559 if MyMap[MouseLoc] and fOwned<>0 then 4560 begin 4561 DoCenter:=false; 4562 if not supervising and (ClientMode<scContact) then 4563 begin // not in negotiation mode 4564 if (UnFocus>=0) and (MyUn[UnFocus].Loc=MouseLoc) then 4565 begin // rotate 4566 uix:=(UnFocus+1) mod MyRO.nUn; 4567 i:=MyRO.nUn-1; 4568 while i>0 do 4569 begin 4570 if (MyUn[uix].Loc=MouseLoc) and (MyUn[uix].Job=jNone) 4571 and (MyUn[uix].Status and (usStay or usRecover or usEnhance or usWaiting)=usWaiting) then 4572 break; 4573 dec(i); 4574 uix:=(uix+1) mod MyRO.nUn; 4575 end; 4576 if i=0 then uix:=UnFocus 4577 end 4578 else Server(sGetDefender,me,MouseLoc,uix); 4579 if uix<>UnFocus then 4580 SetUnFocus(uix); 4581 TurnComplete:=false; 4582 EOT.ButtonIndex:=eotGray; 4583 end; 4584 SetTroopLoc(MouseLoc); 4585 PanelPaint; 4586 end // own unit 4587 else if (MyMap[MouseLoc] and fSpiedOut<>0) and not(ssCtrl in Shift) then 4588 begin 4589 DoCenter:=false; 4590 SetTroopLoc(MouseLoc); 4591 PanelPaint; 4592 end 4593 else 4594 begin 4595 DoCenter:=false; 4596 UnitStatDlg.ShowNewContent_EnemyLoc(wmPersistent, MouseLoc); 7880 else 7881 begin 7882 MapOptionChecked := MapOptionChecked and not(1 shl moBareTerrain); 7883 TButtonBase(Sender).Hint := Phrases.Lookup('CONTROLS', 7884 -1 + TButtonBase(Sender).Tag and $FF); 4597 7885 end; 4598 if DoCenter then begin Centre(MouseLoc); PaintAllMaps end 4599 end 4600 else if (ClientMode<>cEditMap) and (Button=mbRight) and not(ssShift in Shift) then 4601 begin 4602 if supervising then 4603 begin 4604 EditLoc:=MouseLoc; 4605 Server(sGetModels,me,0,nil^); 4606 EmptyMenu(mCreateUnit); 4607 for p1:=0 to nPl-1 do if 1 shl p1 and MyRO.Alive<>0 then 4608 begin 4609 m:=TMenuItem.Create(mCreateUnit); 4610 m.Caption:=Tribe[p1].TPhrase('SHORTNAME'); 4611 for emix:=MyRO.nEnemyModel-1 downto 0 do 4612 if (MyRO.EnemyModel[emix].Owner=p1) and 4613 (Server(sCreateUnit-sExecute+p1 shl 4,me,MyRO.EnemyModel[emix].mix,MouseLoc)>=rExecuted) then 4614 begin 4615 if Tribe[p1].ModelPicture[MyRO.EnemyModel[emix].mix].HGr=0 then 4616 InitEnemyModel(emix); 4617 m2:=TMenuItem.Create(m); 4618 m2.Caption:=Tribe[p1].ModelName[MyRO.EnemyModel[emix].mix]; 4619 m2.Tag:=p1 shl 16 + MyRO.EnemyModel[emix].mix; 4620 m2.OnClick:=CreateUnitClick; 4621 m.Add(m2); 4622 end; 4623 m.Visible:= m.Count>0; 4624 mCreateUnit.Add(m); 4625 end; 4626 if FullScreen then EditPopup.Popup(Left+x, Top+y) 4627 else EditPopup.Popup(Left+x+4, Top+y+GetSystemMetrics(SM_CYCAPTION)+4); 4628 end 4629 else if (UnFocus>=0) and (MyUn[UnFocus].Loc<>MouseLoc) then with MyUn[UnFocus] do 4630 begin 4631 dx:=((MouseLoc mod G.lx *2 +MouseLoc div G.lx and 1) 4632 -(Loc mod G.lx *2 +Loc div G.lx and 1)+3*G.lx) mod (2*G.lx) -G.lx; 4633 dy:=MouseLoc div G.lx-Loc div G.lx; 4634 if abs(dx)+abs(dy)<3 then 7886 SetMapOptions; 7887 MapValid := false; 7888 PaintAllMaps; 7889 end; 7890 7891 procedure TMainScreen.FormKeyUp(Sender: TObject; var Key: word; 7892 Shift: TShiftState); 7893 begin 7894 if idle and (Key = VK_APPS) then 7895 begin 7896 InitPopup(GamePopup); 7897 if FullScreen then 7898 GamePopup.Popup(Left, Top + TopBarHeight - 1) 7899 else 7900 GamePopup.Popup(Left + 4, Top + GetSystemMetrics(SM_CYCAPTION) + 4 + 7901 TopBarHeight - 1); 7902 exit 7903 end // windows menu button calls game menu 7904 end; 7905 7906 procedure TMainScreen.CreateUnitClick(Sender: TObject); 7907 var 7908 p1, mix: integer; 7909 begin 7910 p1 := TComponent(Sender).Tag shr 16; 7911 mix := TComponent(Sender).Tag and $FFFF; 7912 if Server(sCreateUnit + p1 shl 4, me, mix, EditLoc) >= rExecuted then 7913 PaintLoc(EditLoc); 7914 end; 7915 7916 procedure TMainScreen.mSoundOffClick(Sender: TObject); 7917 begin 7918 SoundMode := smOff; 7919 end; 7920 7921 procedure TMainScreen.mSoundOnClick(Sender: TObject); 7922 begin 7923 SoundMode := smOn; 7924 end; 7925 7926 procedure TMainScreen.mSoundOnAltClick(Sender: TObject); 7927 begin 7928 SoundMode := smOnAlt; 7929 end; 7930 7931 { procedure TMainScreen.AdviceBtnClick; 7932 var 7933 OldAdviceLoc: integer; 4635 7934 begin 4636 7935 DestinationMarkON:=false; 4637 7936 PaintDestination; 4638 Status:=Status and ($FFFF-usStay-usRecover-usGoto-usEnhance) or usWaiting; 4639 MoveUnit(dx,dy,muAutoNext) {simple move} 4640 end 4641 else if GetMoveAdvice(UnFocus,MouseLoc,MoveAdviceData)>=rExecuted then 4642 begin 4643 if MyMap[MouseLoc] and (fUnit or fOwned)=fUnit then 4644 begin // check for suicide mission before movement 4645 with MyUn[UnFocus],BattleDlg.Forecast do 4646 begin 4647 pAtt:=me; 4648 mixAtt:=mix; 4649 HealthAtt:=Health; 4650 ExpAtt:=Exp; 4651 FlagsAtt:=Flags; 4652 end; 4653 BattleDlg.Forecast.Movement:=MyUn[UnFocus].Movement; 4654 if (Server(sGetBattleForecastEx,me,MouseLoc,BattleDlg.Forecast)>=rExecuted) 4655 and (BattleDlg.Forecast.EndHealthAtt<=0) then 4656 begin 4657 BattleDlg.uix:=UnFocus; 4658 BattleDlg.ToLoc:=MouseLoc; 4659 BattleDlg.IsSuicideQuery:=true; 4660 BattleDlg.ShowModal; 4661 if BattleDlg.ModalResult<>mrOK then 4662 exit; 4663 end 4664 end; 4665 DestinationMarkON:=false; 4666 PaintDestination; 4667 Status:=Status and not (usStay or usRecover or usEnhance) or usWaiting; 4668 MoveToLoc(MouseLoc,false); {goto} 4669 end 4670 end 4671 end 4672 else if (Button=mbMiddle) and (UnFocus>=0) 4673 and (MyModel[MyUn[UnFocus].mix].Kind in [mkSettler,mkSlaves]) then 4674 begin 4675 DestinationMarkON:=false; 4676 PaintDestination; 4677 MyUn[UnFocus].Status:=MyUn[UnFocus].Status and ($FFFF-usStay-usRecover-usGoto) or usEnhance; 4678 uix:=UnFocus; 4679 if MouseLoc<>MyUn[uix].Loc then MoveToLoc(MouseLoc,true); {goto} 4680 if (UnFocus=uix) and (MyUn[uix].Loc=MouseLoc) then MenuClick(mEnhance) 4681 end 4682 else if (Button=mbLeft) and (ssShift in Shift) 4683 and (MyMap[MouseLoc] and fTerrain<>fUNKNOWN) then 4684 HelpOnTerrain(MouseLoc, wmPersistent) 4685 else if (ClientMode<=cContinue) and (Button=mbRight) and (ssShift in Shift) 4686 and (UnFocus>=0) and (MyMap[MouseLoc] and (fUnit or fOwned)=fUnit) then 4687 begin // battle forecast 4688 with MyUn[UnFocus],BattleDlg.Forecast do 4689 begin 4690 pAtt:=me; 4691 mixAtt:=mix; 4692 HealthAtt:=Health; 4693 ExpAtt:=Exp; 4694 FlagsAtt:=Flags; 4695 end; 4696 BattleDlg.Forecast.Movement:=MyUn[UnFocus].Movement; 4697 if Server(sGetBattleForecastEx,me,MouseLoc,BattleDlg.Forecast)>=rExecuted then 4698 begin 4699 BattleDlg.uix:=UnFocus; 4700 BattleDlg.ToLoc:=MouseLoc; 4701 BattleDlg.Left:=x-BattleDlg.Width div 2; 4702 if BattleDlg.Left<0 then 4703 BattleDlg.Left:=0 4704 else if BattleDlg.Left+BattleDlg.Width>Screen.Width then 4705 BattleDlg.Left:=Screen.Width-BattleDlg.Width; 4706 BattleDlg.Top:=y-BattleDlg.Height div 2; 4707 if BattleDlg.Top<0 then 4708 BattleDlg.Top:=0 4709 else if BattleDlg.Top+BattleDlg.Height>Screen.Height then 4710 BattleDlg.Top:=Screen.Height-BattleDlg.Height; 4711 BattleDlg.IsSuicideQuery:=false; 4712 BattleDlg.Show; 4713 end 4714 end 4715 end; 4716 4717 function TMainScreen.MoveUnit(dx,dy:integer; Options: integer): integer; 4718 // move focused unit to adjacent tile 4719 var 4720 i,cix,uix,euix,FromLoc,ToLoc,DirCode,UnFocus0,Defender,Mission,p1, 4721 NewTiles,cixChanged: integer; 4722 OldToTile: cardinal; 4723 CityCaptured, IsAttack, OldUnrest, NewUnrest, NeedEcoUpdate, NeedRepaintPanel, 4724 ToTransport, ToShip: boolean; 4725 PlaneReturnData: TPlaneReturnData; 4726 QueryItem: string; 4727 begin 4728 result:=eInvalid; 4729 UnFocus0:=UnFocus; 4730 FromLoc:=MyUn[UnFocus].Loc; 4731 ToLoc:=dLoc(FromLoc,dx,dy); 4732 if (ToLoc<0) or (ToLoc>=G.lx*G.ly) then begin result:=eInvalid; exit; end; 4733 if MyMap[ToLoc] and fStealthUnit<>0 then 4734 begin 4735 SoundMessage(Phrases.LookUp('ATTACKSTEALTH'),''); 4736 exit; 4737 end; 4738 if MyMap[ToLoc] and fHiddenUnit<>0 then 4739 begin 4740 SoundMessage(Phrases.LookUp('ATTACKSUB'),''); 4741 exit; 4742 end; 4743 4744 if MyMap[ToLoc] and (fUnit or fOwned)=fUnit then 4745 begin // attack -- search enemy unit 4746 if (MyModel[MyUn[UnFocus].mix].Attack=0) 4747 and not ((MyModel[MyUn[UnFocus].mix].Cap[mcBombs]>0) 4748 and (MyUn[UnFocus].Flags and unBombsLoaded<>0)) then 4749 begin 4750 SoundMessage(Phrases.LookUp('NOATTACKER'),''); 4751 exit; 4752 end; 4753 euix:=MyRO.nEnemyUn-1; 4754 while (euix>=0) and (MyRO.EnemyUn[euix].Loc<>ToLoc) do dec(euix); 4755 end; 4756 4757 DirCode:=dx and 7 shl 4+dy and 7 shl 7; 4758 result:=Server(sMoveUnit-sExecute+DirCode,me,UnFocus,nil^); 4759 if (result<rExecuted) and (MyUn[UnFocus].Job>jNone) then 4760 Server(sStartJob+jNone shl 4,me,UnFocus,nil^); 4761 if (result<rExecuted) and (result<>eNoTime_Move) then 4762 begin 4763 case result of 4764 eNoTime_Load: 4765 if MyModel[MyUn[UnFocus].mix].Domain=dAir then 4766 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'),'NOMOVE_TIME') 4767 else 4768 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 4769 [MovementToString(MyModel[MyUn[UnFocus].mix].Speed)]),'NOMOVE_TIME'); 4770 eNoTime_Bombard: SoundMessage(Phrases.Lookup('NOTIMEBOMBARD'),'NOMOVE_TIME'); 4771 eNoTime_Expel: SoundMessage(Phrases.Lookup('NOTIMEEXPEL'),'NOMOVE_TIME'); 4772 eNoRoad: SoundMessage(Phrases.Lookup('NOROAD'),'NOMOVE_DEFAULT'); 4773 eNoNav: SoundMessage(Phrases.Lookup('NONAV'),'NOMOVE_DEFAULT'); 4774 eNoCapturer: SoundMessage(Phrases.Lookup('NOCAPTURER'),'NOMOVE_DEFAULT'); 4775 eNoBombarder: SoundMessage(Phrases.Lookup('NOBOMBARDER'),'NOMOVE_DEFAULT'); 4776 eZOC: ContextMessage(Phrases.Lookup('ZOC'), 'NOMOVE_ZOC', hkText, HelpDlg.TextIndex('MOVEMENT')); 4777 eTreaty: 4778 if MyMap[ToLoc] and (fUnit or fOwned)<>fUnit then {no enemy unit -- move} 4779 SoundMessage(Tribe[MyRO.Territory[ToLoc]].TPhrase('PEACE_NOMOVE'), 4780 'NOMOVE_TREATY') 4781 else SoundMessage(Tribe[MyRO.EnemyUn[euix].Owner].TPhrase 4782 ('PEACE_NOATTACK'),'NOMOVE_TREATY'); 4783 eDomainMismatch: 4784 begin 4785 if (MyModel[MyUn[UnFocus].mix].Domain<dSea) 4786 and (MyMap[ToLoc] and (fUnit or fOwned)=fUnit or fOwned) then 4787 begin // false load attempt 4788 ToShip:=false; 4789 ToTransport:=false; 4790 for uix:=0 to MyRo.nUn-1 do 4791 if (MyUn[uix].Loc=ToLoc) and (MyModel[MyUn[uix].mix].Domain=dSea) then 4792 begin 4793 ToShip:=true; 4794 if MyModel[MyUn[uix].mix].Cap[mcSeaTrans]>0 then 4795 ToTransport:=true; 4796 end; 4797 if ToTransport then 4798 SoundMessage(Phrases.Lookup('FULLTRANSPORT'),'NOMOVE_DEFAULT') 4799 else if ToShip then 4800 SoundMessage(Phrases.Lookup('NOTRANSPORT'),'NOMOVE_DEFAULT') 4801 else Play('NOMOVE_DOMAIN'); 4802 end 4803 else Play('NOMOVE_DOMAIN'); 4804 end 4805 else Play('NOMOVE_DEFAULT'); 4806 end; 4807 exit; 4808 end; 4809 4810 if ((result=eWon) or (result=eLost) or (result=eBloody)) 4811 and (MyUn[UnFocus].Movement<100) 4812 and (MyModel[MyUn[UnFocus].mix].Cap[mcWill]=0) then 4813 begin 4814 if SimpleQuery(mkYesNo,Format(Phrases.Lookup('FASTATTACK'), 4815 [MyUn[UnFocus].Movement]),'NOMOVE_TIME')<>mrOk then 4816 begin result:=eInvalid; exit; end; 4817 Update; // remove message box from screen 4818 end; 4819 4820 OldUnrest:=false; 4821 NewUnrest:=false; 4822 if (result>=rExecuted) and (result and rUnitRemoved=0) 4823 and (MyMap[ToLoc] and (fUnit or fOwned)<>fUnit) then 4824 begin 4825 OldUnrest:=UnrestAtLoc(UnFocus,FromLoc); 4826 NewUnrest:=UnrestAtLoc(UnFocus,ToLoc); 4827 if NewUnrest>OldUnrest then 4828 begin 4829 if MyRO.Government=gDemocracy then 4830 begin 4831 QueryItem:='UNREST_NOTOWN'; 4832 p1:=me; 4833 end 4834 else 4835 begin 4836 QueryItem:='UNREST_FOREIGN'; 4837 p1:=MyRO.Territory[ToLoc]; 7937 AdvisorDlg.GiveStrategyAdvice; 7938 OldAdviceLoc:=MainMap.AdviceLoc; 7939 MainMap.AdviceLoc:=-1; 7940 PaintLoc(OldAdviceLoc); 7941 end; } 7942 7943 { procedure TMainScreen.SetAdviceLoc(Loc: integer; AvoidRect: TRect); 7944 var 7945 OldAdviceLoc,x,y: integer; 7946 begin 7947 if Loc<>MainMap.AdviceLoc then 7948 begin 7949 if Loc>=0 then 7950 begin // center 7951 y:=Loc div G.lx; 7952 x:=(Loc+G.lx - AvoidRect.Right div (2*66)) mod G.lx; 7953 Centre(y*G.lx+x); 7954 PaintAllMaps; 4838 7955 end; 4839 with MessgExDlg do 4840 begin 4841 MessgText:=Format(Tribe[p1].TPhrase(QueryItem),[Phrases.Lookup('GOVERNMENT',MyRO.Government)]); 4842 Kind:=mkYesNo; 4843 IconKind:=mikImp; 4844 IconIndex:=imPalace; 4845 ShowModal; 4846 if ModalResult<>mrOk then 4847 begin result:=eInvalid; exit; end; 7956 OldAdviceLoc:=MainMap.AdviceLoc; 7957 MainMap.AdviceLoc:=Loc; 7958 PaintLoc(OldAdviceLoc); 7959 PaintLoc(MainMap.AdviceLoc); 4848 7960 end; 4849 Update; // remove message box from screen 4850 end 4851 end; 4852 4853 if (result>=rExecuted) 4854 and (MyModel[MyUn[UnFocus].mix].Domain=dAir) 4855 and (MyUn[UnFocus].Status and usToldNoReturn=0) then 4856 begin // can plane return? 4857 PlaneReturnData.Fuel:=MyUn[UnFocus].Fuel; 4858 if (MyMap[ToLoc] and (fUnit or fOwned)=fUnit) 4859 or (MyMap[ToLoc] and (fCity or fOwned)=fCity) then 4860 begin // attack/expel/bombard -> 100MP 4861 PlaneReturnData.Loc:=FromLoc; 4862 PlaneReturnData.Movement:=MyUn[UnFocus].Movement-100; 4863 if PlaneReturnData.Movement<0 then PlaneReturnData.Movement:=0; 4864 end 4865 else // move 4866 begin 4867 PlaneReturnData.Loc:=ToLoc; 4868 if dx and 1<>0 then PlaneReturnData.Movement:=MyUn[UnFocus].Movement-100 4869 else PlaneReturnData.Movement:=MyUn[UnFocus].Movement-150; 4870 end; 4871 if Server(sGetPlaneReturn, me, UnFocus, PlaneReturnData)=eNoWay then 4872 begin 4873 if MyModel[MyUn[UnFocus].mix].Kind=mkSpecial_Glider then 4874 QueryItem:='LOWFUEL_GLIDER' 4875 else QueryItem:='LOWFUEL'; 4876 if SimpleQuery(mkYesNo,Phrases.Lookup(QueryItem),'WARNING_LOWSUPPORT')<>mrOk then 4877 begin result:=eInvalid; exit; end; 4878 Update; // remove message box from screen 4879 MyUn[UnFocus].Status:=MyUn[UnFocus].Status or usToldNoReturn; 4880 end 4881 end; 4882 4883 if result=eMissionDone then 4884 begin 4885 ModalSelectDlg.ShowNewContent(wmModal,kMission); 4886 Update; // dialog still on screen 4887 Mission:=ModalSelectDlg.result; 4888 if Mission<0 then exit; 4889 Server(sSetSpyMission+Mission shl 4, me, 0, nil^); 4890 end; 4891 4892 CityCaptured:=false; 4893 if result=eNoTime_Move then Play('NOMOVE_TIME') 4894 else 4895 begin 4896 NeedEcoUpdate:=false; 4897 DestinationMarkON:=false; 4898 PaintDestination; 4899 if result and rUnitRemoved<>0 then 4900 CityOptimizer_BeforeRemoveUnit(UnFocus); 4901 IsAttack:= (result=eBombarded) 4902 or (result<>eMissionDone) and (MyMap[ToLoc] and (fUnit or fOwned)=fUnit); 4903 if not IsAttack then 4904 begin // move 4905 cix:=MyRO.nCity-1; {look for own city at dest location} 4906 while (cix>=0) and (MyCity[cix].Loc<>ToLoc) do dec(cix); 4907 if (result<>eMissionDone) and (MyMap[ToLoc] and fCity<>0) and (cix<0) then 4908 CityCaptured:=true; 4909 result:=Server(sMoveUnit+DirCode,me,UnFocus,nil^); 4910 case result of 4911 eHiddenUnit: 4912 begin Play('NOMOVE_SUBMARINE'); PaintLoc(ToLoc) end; 4913 eStealthUnit: 4914 begin Play('NOMOVE_STEALTH'); PaintLoc(ToLoc) end; 4915 eZOC_EnemySpotted: 4916 begin Play('NOMOVE_ZOC'); PaintLoc(ToLoc,1) end; 4917 rExecuted..maxint: 4918 begin 4919 if result and rUnitRemoved<>0 then UnFocus:=-1 // unit died 4920 else 4921 begin 4922 assert(UnFocus>=0); 4923 MyUn[UnFocus].Status:=MyUn[UnFocus].Status and not (usStay or usRecover); 4924 for uix:=0 to MyRO.nUn-1 do if MyUn[uix].Master=UnFocus then 4925 MyUn[uix].Status:=MyUn[uix].Status and not usWaiting; 4926 if CityCaptured 4927 and (MyRO.Government in [gRepublic,gDemocracy,gFuture]) then 4928 begin // borders have moved, unrest might have changed in any city 4929 CityOptimizer_BeginOfTurn; 4930 NeedEcoUpdate:=true; 4931 end 4932 else 4933 begin 4934 if OldUnrest<>NewUnrest then 4935 begin 4936 CityOptimizer_CityChange(MyUn[UnFocus].Home); 4937 for uix:=0 to MyRO.nUn-1 do if MyUn[uix].Master=UnFocus then 4938 CityOptimizer_CityChange(MyUn[uix].Home); 4939 NeedEcoUpdate:=true; 4940 end; 4941 if (MyRO.Government=gDespotism) 4942 and (MyModel[MyUn[UnFocus].mix].Kind=mkSpecial_TownGuard) then 4943 begin 4944 if MyMap[FromLoc] and fCity<>0 then 4945 begin // town guard moved out of city in despotism -- reoptimize! 4946 cixChanged:=MyRO.nCity-1; 4947 while (cixChanged>=0) and (MyCity[cixChanged].Loc<>FromLoc) do 4948 dec(cixChanged); 4949 assert(cixChanged>=0); 4950 if cixChanged>=0 then 4951 begin 4952 CityOptimizer_CityChange(cixChanged); 4953 NeedEcoUpdate:=true; 4954 end; 4955 end; 4956 if (MyMap[ToLoc] and fCity<>0) and not CityCaptured then 4957 begin // town guard moved into city in despotism -- reoptimize! 4958 cixChanged:=MyRO.nCity-1; 4959 while (cixChanged>=0) and (MyCity[cixChanged].Loc<>ToLoc) do 4960 dec(cixChanged); 4961 assert(cixChanged>=0); 4962 if cixChanged>=0 then 4963 begin 4964 CityOptimizer_CityChange(cixChanged); 4965 NeedEcoUpdate:=true; 4966 end 4967 end 4968 end 4969 end 4970 end; 4971 end; 4972 else 4973 assert(false); 4974 end; 4975 SetTroopLoc(ToLoc); 4976 end 4977 else 4978 begin {enemy unit -- attack} 4979 if result=eBombarded then Defender:=MyRO.Territory[ToLoc] 4980 else Defender:=MyRO.EnemyUn[euix].Owner; 4981 {if MyRO.Treaty[Defender]=trCeaseFire then 4982 if SimpleQuery(mkYesNo,Phrases.Lookup('FRCANCELQUERY_CEASEFIRE'), 4983 'MSG_DEFAULT')<>mrOK then 4984 exit;} 4985 if (Options and muNoSuicideCheck=0) 4986 and (result and rUnitRemoved<>0) and (result<>eMissionDone) then 4987 begin // suicide query 4988 with MyUn[UnFocus],BattleDlg.Forecast do 4989 begin 4990 pAtt:=me; 4991 mixAtt:=mix; 4992 HealthAtt:=Health; 4993 ExpAtt:=Exp; 4994 FlagsAtt:=Flags; 4995 end; 4996 BattleDlg.Forecast.Movement:=MyUn[UnFocus].Movement; 4997 Server(sGetBattleForecastEx,me,ToLoc,BattleDlg.Forecast); 4998 BattleDlg.uix:=UnFocus; 4999 BattleDlg.ToLoc:=ToLoc; 5000 BattleDlg.IsSuicideQuery:=true; 5001 BattleDlg.ShowModal; 5002 if BattleDlg.ModalResult<>mrOK then 5003 exit; 5004 end; 5005 5006 cixChanged:=-1; 5007 if (result and rUnitRemoved<>0) and (MyRO.Government=gDespotism) 5008 and (MyModel[MyUn[UnFocus].mix].Kind=mkSpecial_TownGuard) 5009 and (MyMap[FromLoc] and fCity<>0) then 5010 begin // town guard died in city in despotism -- reoptimize! 5011 cixChanged:=MyRO.nCity-1; 5012 while (cixChanged>=0) and (MyCity[cixChanged].Loc<>FromLoc) do 5013 dec(cixChanged); 5014 assert(cixChanged>=0); 5015 end; 5016 5017 for i:=0 to MyRO.nEnemyModel-1 do 5018 LostArmy[i]:=MyRO.EnemyModel[i].Lost; 5019 OldToTile:=MyMap[ToLoc]; 5020 result:=Server(sMoveUnit+DirCode,me,UnFocus,nil^); 5021 nLostArmy:=0; 5022 for i:=0 to MyRO.nEnemyModel-1 do 5023 begin 5024 LostArmy[i]:=MyRO.EnemyModel[i].Lost-LostArmy[i]; 5025 inc(nLostArmy,LostArmy[i]) 5026 end; 5027 if result and rUnitRemoved<>0 then 5028 begin 5029 UnFocus:=-1; 5030 SetTroopLoc(FromLoc); 5031 end; 5032 if (OldToTile and not MyMap[ToLoc] and fCity<>0) 5033 and (MyRO.Government in [gRepublic,gDemocracy,gFuture]) then 5034 begin // city was destroyed, borders have moved, unrest might have changed in any city 5035 CityOptimizer_BeginOfTurn; 5036 NeedEcoUpdate:=true; 5037 end 5038 else 5039 begin 5040 if cixChanged>=0 then 5041 begin 5042 CityOptimizer_CityChange(cixChanged); 5043 NeedEcoUpdate:=true; 5044 end; 5045 if (result=eWon) or (result=eBloody) or (result=eExpelled) then 5046 begin 5047 CityOptimizer_TileBecomesAvailable(ToLoc); 5048 NeedEcoUpdate:=true; 5049 end; 5050 end; 5051 if nLostArmy>1 then 5052 begin 5053 with MessgExDlg do 5054 begin 5055 Kind:=mkOk; 5056 IconKind:=mikEnemyArmy; 5057 MessgText:=Tribe[Defender].TString(Phrases.Lookup('ARMYLOST', 5058 MyRO.EnemyModel[MyRO.EnemyUn[euix].emix].Domain)); 5059 ShowModal; 5060 end 5061 end 5062 end; 5063 if result and rUnitRemoved<>0 then 5064 begin 5065 CityOptimizer_AfterRemoveUnit; 5066 ListDlg.RemoveUnit; 5067 NeedEcoUpdate:=true; 5068 end; 5069 if NeedEcoUpdate then 5070 begin 5071 UpdateViews(true); 5072 Update 5073 end 5074 end; 5075 5076 if result=eMissionDone then 5077 begin 5078 p1:=MyRO.Territory[ToLoc]; 5079 case Mission of 5080 smStealMap: 5081 begin MapValid:=false; PaintAllMaps end; 5082 smStealCivilReport: 5083 TribeMessage(p1,Tribe[p1].TPhrase('DOSSIER_PREPARED'),''); 5084 smStealMilReport: 5085 ListDlg.ShowNewContent_MilReport(wmPersistent,p1); 5086 end; 5087 end; 5088 5089 if UnFocus>=0 then 5090 CheckToldNoReturn(UnFocus); 5091 5092 NeedRepaintPanel:=false; 5093 if result>=rExecuted then 5094 begin 5095 if CityCaptured and (MyMap[ToLoc] and fCity=0) then 5096 begin // city destroyed 5097 for i:=0 to 27 do {tell about destroyed wonders} 5098 if (MyRO.Wonder[i].CityID=-2) and (MyData.ToldWonders[i].CityID<>-2) then 5099 with MessgExDlg do 5100 begin 5101 if WondersDlg.Visible then 5102 WondersDlg.SmartUpdateContent(false); 5103 OpenSound:='WONDER_DESTROYED'; 5104 MessgText:=Format(Phrases.Lookup('WONDERDEST'), 5105 [Phrases.Lookup('IMPROVEMENTS',i)]); 5106 Kind:=mkOkHelp; 5107 HelpKind:=hkImp; 5108 HelpNo:=i; 5109 IconKind:=mikImp; 5110 IconIndex:=i; 5111 ShowModal; 5112 MyData.ToldWonders[i]:=MyRO.Wonder[i]; 5113 end 5114 end; 5115 if CityCaptured and (MyMap[ToLoc] and fCity<>0) then 5116 begin // city captured 5117 ListDlg.AddCity; 5118 for i:=0 to 27 do {tell about capture of wonders} 5119 if MyRO.City[MyRO.nCity-1].Built[i]>0 then with MessgExDlg do 5120 begin 5121 if WondersDlg.Visible then 5122 WondersDlg.SmartUpdateContent(false); 5123 OpenSound:='WONDER_CAPTURED'; 5124 MessgText:=Format(Tribe[me].TPhrase('WONDERCAPTOWN'), 5125 [Phrases.Lookup('IMPROVEMENTS',i)]); 5126 Kind:=mkOkHelp; 5127 HelpKind:=hkImp; 5128 HelpNo:=i; 5129 IconKind:=mikImp; 5130 IconIndex:=i; 5131 ShowModal; 5132 MyData.ToldWonders[i]:=MyRO.Wonder[i]; 5133 end; 5134 5135 if MyRO.Happened and phStealTech<>0 then 5136 begin {Temple of Zeus -- choose advance to steal} 5137 ModalSelectDlg.ShowNewContent(wmModal,kStealTech); 5138 Server(sStealTech,me,ModalSelectDlg.result,nil^); 5139 end; 5140 TellNewModels; 5141 5142 cix:=MyRO.nCity-1; 5143 while (cix>=0) and (MyCity[cix].Loc<>ToLoc) do 5144 dec(cix); 5145 assert(cix>=0); 5146 MyCity[cix].Status:=MyCity[cix].Status 5147 and not csResourceWeightsMask or (3 shl 4); // captured city, set to maximum growth 5148 NewTiles:=1 shl 13; {exploit central tile only} 5149 Server(sSetCityTiles,me,cix,NewTiles); 5150 end 5151 else NeedRepaintPanel:=true; 5152 end; 5153 TellNewContacts; 5154 5155 if (UnFocus>=0) and (MyUn[UnFocus].Master>=0) then 5156 with MyUn[MyUn[UnFocus].Master] do 5157 if Status and usStay<>0 then 5158 begin 5159 Status:=Status and not usStay; 5160 if (Movement>=100) and (Status and (usRecover or usGoto)=0) then 5161 Status:=Status or usWaiting; 5162 end; 5163 if Options and (muAutoNoWait or muAutoNext)<>0 then 5164 begin 5165 if (UnFocus>=0) and ((result=eNoTime_Move) or UnitExhausted(UnFocus) 5166 or (MyUn[UnFocus].Master>=0) 5167 or (MyModel[MyUn[UnFocus].mix].Domain=dAir) 5168 and ((MyMap[MyUn[UnFocus].Loc] and fCity<>0) {aircrafts stop in cities} 5169 or (MyMap[MyUn[UnFocus].Loc] and fTerImp=tiBase))) then 5170 begin 5171 MyUn[UnFocus].Status:=MyUn[UnFocus].Status and not usWaiting; 5172 if Options and muAutoNext<>0 then 5173 if CityCaptured and (MyMap[ToLoc] and fCity<>0) then 5174 begin 5175 UnFocus:=-1; 5176 PaintLoc(ToLoc); // don't show unit in city if not selected 5177 end 5178 else NextUnit(UnStartLoc,true) 5179 end 5180 else if (UnFocus<0) and (Options and muAutoNext<>0) then 5181 NextUnit(UnStartLoc,result<>eMissionDone); 5182 end; 5183 5184 if NeedRepaintPanel and (UnFocus=UnFocus0) then 5185 if IsAttack then PanelPaint 5186 else 5187 begin 5188 assert(result<>eMissionDone); 5189 CheckTerrainBtnVisible; 5190 FocusOnLoc(ToLoc,flRepaintPanel or flImmUpdate) 5191 end; 5192 5193 if (result>=rExecuted) and CityCaptured and (MyMap[ToLoc] and fCity<>0) then 5194 ZoomToCity(ToLoc,UnFocus<0,chCaptured); // show captured city 5195 end; // moveunit 5196 5197 procedure TMainScreen.MoveOnScreen(ShowMove: TShowMove; Step0,Step1,nStep: integer; 5198 Restore: boolean = true); 5199 var 5200 ToLoc,xFromLoc,yFromLoc,xToLoc,yToLoc,xFrom,yFrom,xTo,yTo,xMin,yMin,xRange,yRange, 5201 xw1,Step,xMoving,yMoving,yl,SliceCount:integer; 5202 UnitInfo: TUnitInfo; 5203 Ticks0,Ticks: int64; 5204 begin 5205 Timer1.Enabled:=false; 5206 QueryPerformanceCounter(Ticks0); 5207 with ShowMove do 5208 begin 5209 UnitInfo.Owner:=Owner; 5210 UnitInfo.mix:=mix; 5211 UnitInfo.Health:=Health; 5212 UnitInfo.Job:=jNone; 5213 UnitInfo.Flags:=Flags; 5214 if Owner<>me then 5215 UnitInfo.emix:=emix; 5216 5217 ToLoc:=dLoc(FromLoc,dx,dy); 5218 xToLoc:=ToLoc mod G.lx; yToLoc:=ToLoc div G.lx; 5219 xFromLoc:=FromLoc mod G.lx; yFromLoc:=FromLoc div G.lx; 5220 if xToLoc>xFromLoc+2 then xToLoc:=xToLoc-G.lx 5221 else if xToLoc<xFromLoc-2 then xToLoc:=xToLoc+G.lx; 5222 5223 xw1:=xw+G.lx; 5224 // ((xFromLoc-xw1)*2+yFromLoc and 1+1)*xxt+dx*xxt/2-MapWidth/2 -> min 5225 while abs(((xFromLoc-xw1+G.lx)*2+yFromLoc and 1+1)*xxt*2+dx*xxt-MapWidth) 5226 <abs(((xFromLoc-xw1)*2+yFromLoc and 1+1)*xxt*2+dx*xxt-MapWidth) do 5227 dec(xw1,G.lx); 5228 5229 xTo:=(xToLoc-xw1)*(xxt*2) + yToLoc and 1 *xxt +(xxt-xxu); 5230 yTo:=(yToLoc-yw)*yyt +(yyt-yyu_anchor); 5231 xFrom:=(xFromLoc-xw1)*(xxt*2) + yFromLoc and 1 *xxt +(xxt-xxu); 5232 yFrom:=(yFromLoc-yw)*yyt +(yyt-yyu_anchor); 5233 if xFrom<xTo then begin xMin:=xFrom;xRange:=xTo-xFrom end 5234 else begin xMin:=xTo;xRange:=xFrom-xTo end; 5235 if yFrom<yTo then begin yMin:=yFrom;yRange:=yTo-yFrom end 5236 else begin yMin:=yTo;yRange:=yFrom-yTo end; 5237 inc(xRange,xxt*2); 5238 inc(yRange,yyt*3); 5239 5240 MainOffscreenPaint; 5241 NoMap.SetOutput(Buffer); 5242 NoMap.SetPaintBounds(0,0,xRange,yRange); 5243 for Step:=0 to abs(Step1-Step0) do 5244 begin 5245 BitBlt(Buffer.Canvas.Handle,0,0,xRange,yRange, 5246 offscreen.Canvas.Handle,xMin,yMin,SRCCOPY); 5247 if Step1<>Step0 then 5248 begin 5249 xMoving:=xFrom+Round((Step0+Step*(Step1-Step0) div abs(Step1-Step0)) 5250 *(xTo-xFrom)/nStep); 5251 yMoving:=yFrom+Round((Step0+Step*(Step1-Step0) div abs(Step1-Step0)) 5252 *(yTo-yFrom)/nStep); 5253 end 5254 else begin xMoving:=xFrom; yMoving:=yFrom; end; 5255 NoMap.PaintUnit(xMoving-xMin,yMoving-yMin,UnitInfo,0); 5256 PaintBufferToScreen(xMin,yMin,xRange,yRange); 5257 5258 SliceCount:=0; 5259 Ticks:=Ticks0; 5260 repeat 5261 if (SliceCount=0) or ((Ticks-Ticks0)*12000 *(SliceCount+1) 5262 div SliceCount<MoveTime*PerfFreq) then 5263 begin 5264 if not idle or (GameMode=cMovie) then 5265 Application.ProcessMessages; 5266 Sleep(1); 5267 inc(SliceCount) 5268 end; 5269 QueryPerformanceCounter(Ticks); 5270 until (Ticks-Ticks0)*12000>=MoveTime*PerfFreq; 5271 Ticks0:=Ticks 5272 end; 5273 end; 5274 if Restore then 5275 begin 5276 BitBlt(Buffer.Canvas.Handle,0,0,xRange,yRange,offscreen.Canvas.Handle,xMin, 5277 yMin,SRCCOPY); 5278 PaintBufferToScreen(xMin,yMin,xRange,yRange); 5279 end; 5280 BlinkTime:=-1; 5281 Timer1.Enabled:=true; 5282 end; 5283 5284 procedure TMainScreen.MoveToLoc(Loc: integer; CheckSuicide: boolean); 5285 // path finder: move focused unit to loc, start multi-turn goto if too far 5286 var 5287 uix,i,MoveOptions,NextLoc,MoveResult: integer; 5288 MoveAdviceData: TMoveAdviceData; 5289 StopReason: (None, Arrived, Dead, NoTime, EnemySpotted, MoveError); 5290 begin 5291 if MyUn[UnFocus].Job>jNone then 5292 Server(sStartJob+jNone shl 4,me,UnFocus,nil^); 5293 if GetMoveAdvice(UnFocus,Loc,MoveAdviceData)>=rExecuted then 5294 begin 5295 uix:=UnFocus; 5296 StopReason:=None; 5297 repeat 5298 for i:=0 to MoveAdviceData.nStep-1 do 5299 begin 5300 if i=MoveAdviceData.nStep-1 then MoveOptions:=muAutoNext 5301 else MoveOptions:=0; 5302 NextLoc:=dLoc(MyUn[uix].Loc,MoveAdviceData.dx[i],MoveAdviceData.dy[i]); 5303 if (NextLoc=Loc) 5304 or (Loc=maNextCity) and (MyMap[NextLoc] and fCity<>0) then 5305 StopReason:=Arrived; 5306 if not CheckSuicide and (NextLoc=Loc) then 5307 MoveOptions:=MoveOptions or muNoSuicideCheck; 5308 MoveResult:=MoveUnit(MoveAdviceData.dx[i],MoveAdviceData.dy[i],MoveOptions); 5309 if MoveResult<rExecuted then StopReason:=MoveError 5310 else if MoveResult and rUnitRemoved<>0 then StopReason:=Dead 5311 else if (StopReason=None) and (MoveResult and rEnemySpotted<>0) then 5312 StopReason:=EnemySpotted; 5313 if StopReason<>None then break; 5314 end; 5315 if (StopReason=None) and ((MoveAdviceData.nStep<25) 5316 or (MyRO.Wonder[woShinkansen].EffectiveOwner<>me)) then 5317 StopReason:=NoTime; 5318 if StopReason<>None then break; 5319 if GetMoveAdvice(UnFocus,Loc,MoveAdviceData)<rExecuted then 5320 begin assert(false); break end 5321 until false; 5322 5323 case StopReason of 5324 None: assert(false); 5325 Arrived: MyUn[uix].Status:=MyUn[uix].Status and ($FFFF-usGoto); 5326 Dead: if UnFocus<0 then NextUnit(UnStartLoc,false); 5327 else 5328 begin // multi-turn goto 5329 if Loc=maNextCity then 5330 MyUn[uix].Status:=MyUn[uix].Status and ($FFFF-usStay-usRecover) or usGoto +$7FFF shl 16 5331 else MyUn[uix].Status:=MyUn[uix].Status and ($FFFF-usStay-usRecover) or usGoto +Loc shl 16; 5332 PaintLoc(MyUn[uix].Loc); 5333 if (StopReason=NoTime) and (UnFocus=uix) then 5334 begin 5335 MyUn[uix].Status:=MyUn[uix].Status and not usWaiting; 5336 NextUnit(UnStartLoc,true) 5337 end; 5338 end 5339 end 5340 end 5341 end; 5342 5343 procedure TMainScreen.PanelBoxMouseDown(Sender:TObject; 5344 Button:TMouseButton;Shift:TShiftState;x,y:integer); 5345 var 5346 i,xMouse,MouseLoc,p1: integer; 5347 begin 5348 if GameMode=cMovie then 5349 exit; 5350 5351 if Button=mbLeft then 5352 begin 5353 if (x>=xMini+2) and (y>=yMini+2) and (x<xMini+2+2*G.lx) and (y<yMini+2+G.ly) then 5354 if ssShift in Shift then 5355 begin 5356 xMouse:=(xwMini+(x-(xMini+2)+MapWidth div (xxt*2)+G.lx) div 2) mod G.lx; 5357 MouseLoc:=xMouse+G.lx*(y-(yMini+2)); 5358 if MyMap[MouseLoc] and fTerrain<>fUNKNOWN then 5359 begin 5360 p1:=MyRO.Territory[MouseLoc]; 5361 if (p1=me) or (p1>=0) and (MyRO.Treaty[p1]>=trNone) then 5362 NatStatDlg.ShowNewContent(wmPersistent, p1); 5363 end 5364 end 5365 else 5366 begin 5367 if CityDlg.Visible then CityDlg.Close; 5368 if UnitStatDlg.Visible then UnitStatDlg.Close; 5369 Tracking:=true; 5370 PanelBoxMouseMove(Sender,Shift+[ssLeft],x,y); 5371 end 5372 else if (ClientMode<>cEditMap) and (x>=ClientWidth-xPalace) and (y>=yPalace) 5373 and (x<ClientWidth-xPalace+xSizeBig) and (y<yPalace+ySizeBig) then 5374 begin 5375 InitPopup(StatPopup); 5376 if FullScreen then 5377 StatPopup.Popup(Left+ClientWidth-xPalace+xSizeBig+2, 5378 Top+ClientHeight-PanelHeight+yPalace-1) 5379 else StatPopup.Popup(Left+ClientWidth-xPalace+6, 5380 Top+ClientHeight-PanelHeight+yPalace+ySizeBig+GetSystemMetrics(SM_CYCAPTION)+3) 5381 end 5382 (* else if (x>=xAdvisor-3) and (y>=yAdvisor-3) 5383 and (x<xAdvisor+16+3) and (y<yAdvisor+16+3) and HaveStrategyAdvice then 5384 AdviceBtnClick*) 5385 else if (x>=xTroop+1) and (y>=yTroop+1) 5386 and (x<xTroop+TrRow*TrPitch) and (y<=yTroop+55) then 5387 begin 5388 i:=(x-xTroop-1) div TrPitch; 5389 if trix[i]>=0 then 5390 if ClientMode=cEditMap then begin BrushType:=trix[i]; PanelPaint end 5391 else if (TroopLoc>=0) then 5392 if MyMap[TroopLoc] and fOwned<>0 then 5393 begin 5394 if ssShift in Shift then 5395 UnitStatDlg.ShowNewContent_OwnModel(wmPersistent, MyUn[trix[i]].mix) 5396 else if not supervising and (ClientMode<scContact) 5397 and (x-xTroop-1-i*TrPitch>=60-20) and (y>=yTroop+35) 5398 and ((MyUn[trix[i]].Job>jNone) 5399 or (MyUn[trix[i]].Status and (usStay or usRecover or usGoto)<>0)) then 5400 begin // wake up 5401 MyUn[trix[i]].Status:=MyUn[trix[i]].Status 5402 and ($FFFF-usStay-usRecover-usGoto-usEnhance) or usWaiting; 5403 if MyUn[trix[i]].Job>jNone then 5404 Server(sStartJob+jNone shl 4,me,trix[i],nil^); 5405 if (UnFocus<0) and not CityDlg.Visible then 5406 begin 5407 SetUnFocus(trix[i]); 5408 SetTroopLoc(MyUn[trix[i]].Loc); 5409 FocusOnLoc(TroopLoc,flRepaintPanel) 5410 end 5411 else 5412 begin 5413 if CityDlg.Visible and (CityDlg.RestoreUnFocus<0) then 5414 CityDlg.RestoreUnFocus:=trix[i]; 5415 PanelPaint; 5416 end 5417 end 5418 else if (ClientMode<scContact) then 5419 begin 5420 if supervising then 5421 UnitStatDlg.ShowNewContent_OwnUnit(wmPersistent, trix[i]) 5422 else if CityDlg.Visible then 5423 begin 5424 CityDlg.CloseAction:=None; 5425 CityDlg.Close; 5426 SumCities(TaxSum,ScienceSum); 5427 SetUnFocus(trix[i]); 5428 end 5429 else 5430 begin 5431 DestinationMarkON:=false; 5432 PaintDestination; 5433 UnFocus:=trix[i]; 5434 UnStartLoc:=TroopLoc; 5435 BlinkTime:=0; 5436 BlinkOn:=false; 5437 PaintLoc(TroopLoc); 5438 end; 5439 if UnFocus>=0 then 5440 begin 5441 UnitInfoBtn.Visible:=true; 5442 UnitBtn.Visible:=true; 5443 TurnComplete:=false; 5444 EOT.ButtonIndex:=eotGray; 5445 end; 5446 CheckTerrainBtnVisible; 5447 PanelPaint; 5448 end 5449 end 5450 else if Server(sGetUnits,me,TroopLoc,TrCnt)>=rExecuted then 5451 if ssShift in Shift then 5452 UnitStatDlg.ShowNewContent_EnemyModel(wmPersistent, 5453 MyRO.EnemyUn[MyRO.nEnemyUn+trix[i]].emix) // model info 5454 else UnitStatDlg.ShowNewContent_EnemyUnit(wmPersistent, 5455 MyRO.nEnemyUn+trix[i]); // unit info 5456 end 5457 end 5458 end; 5459 5460 procedure TMainScreen.SetTroopLoc(Loc:integer); 5461 var 5462 trixFocus,uix,uixDefender: integer; 5463 Prio: boolean; 5464 begin 5465 TroopLoc:=Loc; 5466 TrRow:=(xRightPanel+10-xTroop-GetSystemMetrics(SM_CXVSCROLL)-19) div TrPitch; 5467 TrCnt:=0; 5468 trixFocus:=-1; 5469 if ClientMode=cEditMap then TrCnt:=nBrushTypes 5470 else if (Loc>=0) and (MyMap[Loc] and fUnit<>0) then 5471 if MyMap[Loc] and fOwned<>0 then 5472 begin // count own units here 5473 Server(sGetDefender,me,TroopLoc,uixDefender); 5474 for Prio:=true downto false do 5475 for uix:=0 to MyRO.nUn-1 do 5476 if ((uix=uixDefender)=Prio) and (MyUn[uix].Loc=Loc) then 5477 begin 5478 if uix=UnFocus then trixFocus:=TrCnt; 5479 inc(TrCnt); 5480 end 5481 end 5482 else // count enemy units here 5483 Server(sGetUnits,me,Loc,TrCnt); 5484 if TrCnt=0 then InitPVSB(sb,0,1) 5485 else 5486 begin 5487 InitPVSB(sb,(TrCnt+TrRow-1) div TrRow-1,1); 5488 with sb.si do if (nMax>=integer(nPage)) and (trixFocus>=0) then 5489 begin 5490 sb.si.npos:=trixFocus div TrRow; 5491 sb.si.FMask:=SIF_POS; 5492 SetScrollInfo(sb.h,SB_CTL,sb.si,true); 5493 end 5494 end 5495 end; 5496 5497 (*procedure TMainScreen.ShowMoveHint(ToLoc: integer; Force: boolean = false); 5498 var 5499 Step,Loc,x0,y0,xs,ys: integer; 5500 Info: string; 5501 InfoSize: TSize; 5502 MoveAdvice: TMoveAdviceData; 5503 begin 5504 if (ToLoc<0) or (ToLoc>=G.lx*G.ly) 5505 or (UnFocus<0) or (MyUn[UnFocus].Loc=ToLoc) then 5506 ToLoc:=-1 5507 else 5508 begin 5509 MoveAdvice.ToLoc:=ToLoc; 5510 MoveAdvice.MoreTurns:=0; 5511 MoveAdvice.MaxHostile_MovementLeft:=MyUn[UnFocus].Health-50; 5512 if Server(sGetMoveAdvice,me,UnFocus,MoveAdvice)<rExecuted then 5513 ToLoc:=-1 5514 end; 5515 if (ToLoc=MoveHintToLoc) and not Force then exit; 5516 if (ToLoc<>MoveHintToLoc) and (MoveHintToLoc>=0) then 5517 begin invalidate; update end; // clear old hint from screen 5518 MoveHintToLoc:=ToLoc; 5519 if ToLoc<0 then exit; 5520 5521 with canvas do 5522 begin 5523 Pen.Color:=$80C0FF; 5524 Pen.Width:=3; 5525 Loc:=MyUn[UnFocus].Loc; 5526 for Step:=0 to MoveAdvice.nStep do 5527 begin 5528 y0:=(Loc+G.lx*1024) div G.lx -1024; 5529 x0:=(Loc+(y0 and 1+G.lx*1024) div 2) mod G.lx; 5530 xs:=(x0-xw)*66+y0 and 1*33-G.lx*66; 5531 while abs(2*(xs+G.lx*66)-MapWidth)<abs(2*xs-MapWidth) do 5532 inc(xs,G.lx*66); 5533 ys:=(y0-yw)*16; 5534 if Step=0 then moveto(xs+33,ys+16) 5535 else lineto(xs+33,ys+16); 5536 if Step<MoveAdvice.nStep then 5537 Loc:=dLoc(Loc,MoveAdvice.dx[Step],MoveAdvice.dy[Step]); 5538 end; 5539 Brush.Color:=$80C0FF; 5540 Info:=' '+inttostr(88)+' '; 5541 InfoSize:=TextExtent(Info); 5542 TextOut(xs+33-InfoSize.cx div 2, ys+16-InfoSize.cy div 2, Info); 5543 Brush.Style:=bsClear; 5544 end 5545 end;*) 5546 5547 procedure TMainScreen.SetDebugMap(p: integer); 5548 begin 5549 IsoEngine.pDebugMap:=p; 5550 IsoEngine.Options:=IsoEngine.Options and not (1 shl moLocCodes); 5551 mLocCodes.Checked:=false; 5552 MapValid:=false; 5553 MainOffscreenPaint; 5554 end; 5555 5556 procedure TMainScreen.SetViewpoint(p: integer); 5557 var 5558 i: integer; 5559 begin 5560 if supervising and (G.RO[0].Turn>0) 5561 and ((p=0) or (1 shl p and G.RO[0].Alive<>0)) then 5562 begin 5563 for i:=0 to Screen.FormCount-1 do 5564 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 5565 Screen.Forms[i].Close; // close windows 5566 ItsMeAgain(p); 5567 SumCities(TaxSum,ScienceSum); 5568 for i:=0 to MyRO.nModel-1 do 5569 if Tribe[me].ModelPicture[i].HGr=0 then 5570 InitMyModel(i,true); 5571 5572 SetTroopLoc(-1); 5573 PanelPaint; 5574 MapValid:=false; 5575 PaintAllMaps; 5576 end 5577 end; 5578 5579 procedure TMainScreen.FormKeyDown(Sender:TObject;var Key:word; 5580 Shift:TShiftState); 5581 5582 procedure MenuClick_Check(Popup: TPopupMenu; Item: TMenuItem); 5583 begin 5584 InitPopup(Popup); 5585 if Item.Visible and Item.Enabled then MenuClick(Item); 5586 end; 5587 5588 var 5589 dx,dy: integer; 5590 time0,time1: int64; 5591 begin 5592 if GameMode=cMovie then 5593 begin 5594 case Key of 5595 VK_F4: MenuClick_Check(StatPopup,mScienceStat); 5596 VK_F6: MenuClick_Check(StatPopup,mDiagram); 5597 VK_F7: MenuClick_Check(StatPopup,mWonders); 5598 VK_F8: MenuClick_Check(StatPopup,mShips); 5599 end; 5600 exit; 5601 end; 5602 5603 if not idle then exit; 5604 5605 if ClientMode=cEditMap then 5606 begin 5607 if Shift=[ssCtrl] then 5608 case char(Key) of 5609 (* 'A': 5610 begin // auto symmetry 5611 Server($7F0,me,0,nil^); 5612 MapValid:=false; 5613 PaintAll; 5614 end; 5615 'B': 5616 begin // land mass 5617 dy:=0; 5618 for dx:=G.lx to G.lx*(G.ly-1)-1 do 5619 if MyMap[dx] and fTerrain>=fGrass then inc(dy); 5620 dy:=dy 5621 end;*) 5622 'Q':MenuClick(mResign); 5623 'R':MenuClick(mRandomMap); 5624 end 5625 else if Shift=[] then 5626 case char(Key) of 5627 char(VK_F1): MenuClick(mHelp); 5628 end; 5629 exit; 5630 end; 5631 5632 if Shift=[ssAlt] then 5633 case char(Key) of 5634 '0': SetDebugMap(-1); 5635 '1'..'9': SetDebugMap(ord(Key)-48); 5636 end 5637 else if Shift=[ssCtrl] then 5638 case char(Key) of 5639 'J':MenuClick(mJump); 5640 'K':mShowClick(mDebugMap); 5641 'L':mShowClick(mLocCodes); 5642 'M':if LogDlg.Visible then LogDlg.Close else LogDlg.Show; 5643 'N':mNamesClick(mNames); 5644 'Q':MenuClick_Check(GamePopup,mResign); 5645 'R':MenuClick(mRun); 5646 '0'..'9': 5647 begin 5648 if ord(Key)-48=me then 5649 SetViewpoint(0) 5650 else SetViewpoint(ord(Key)-48); 5651 end; 5652 ' ': 5653 begin // test map repaint time 5654 QueryPerformanceCounter(time0); 5655 MapValid:=false; 5656 MainOffscreenPaint; 5657 QueryPerformanceCounter(time1); 5658 SimpleMessage(Format('Map repaint time: %.3f ms',[{$IFDEF VER100}(time1.LowPart-time0.LowPart) 5659 {$ELSE}(time1-time0){$ENDIF}*1000.0/PerfFreq])); 5660 end 5661 end 5662 else if Shift=[] then 5663 case char(Key) of 5664 char(VK_F1): MenuClick(mHelp); 5665 char(VK_F2):MenuClick_Check(StatPopup,mUnitStat); 5666 char(VK_F3):MenuClick_Check(StatPopup,mCityStat); 5667 char(VK_F4):MenuClick_Check(StatPopup,mScienceStat); 5668 char(VK_F5):MenuClick_Check(StatPopup,mEUnitStat); 5669 char(VK_F6):MenuClick_Check(StatPopup,mDiagram); 5670 char(VK_F7):MenuClick_Check(StatPopup,mWonders); 5671 char(VK_F8):MenuClick_Check(StatPopup,mShips); 5672 char(VK_F9):MenuClick_Check(StatPopup,mNations); 5673 char(VK_F10):MenuClick_Check(StatPopup,mEmpire); 5674 char(VK_ADD): EndTurn; 5675 '1':MapBtnClick(MapBtn0); 5676 '2':MapBtnClick(MapBtn1); 5677 '3':MapBtnClick(MapBtn4); 5678 '4':MapBtnClick(MapBtn5); 5679 '5':MapBtnClick(MapBtn6); 5680 'T':MenuClick(mTechTree); 5681 'W':MenuClick(mWait); 5682 end; 5683 5684 if UnFocus>=0 then 5685 if Shift=[ssCtrl] then 5686 case char(Key) of 5687 'C':MenuClick_Check(UnitPopup,mCancel); 5688 'D':MenuClick(mDisband); 5689 'P':MenuClick_Check(UnitPopup,mPillage); 5690 'T':MenuClick_Check(UnitPopup,mSelectTransport); 5691 end 5692 else if Shift=[] then 5693 case char(Key) of 5694 ' ':MenuClick(mNoOrders); 5695 'A':MenuClick_Check(TerrainPopup,mAirBase); 5696 'B':MenuClick_Check(UnitPopup,mCity); 5697 'C':MenuClick(mCentre); 5698 'E': 5699 begin 5700 InitPopup(TerrainPopup); 5701 if mEnhance.Visible and mEnhance.Enabled then MenuClick(mEnhance) 5702 else MenuClick(mEnhanceDef) 5703 end; 5704 'F':MenuClick_Check(TerrainPopup,mFort); 5705 'G':MenuClick_Check(UnitPopup,mGoOn); 5706 'H':MenuClick_Check(UnitPopup,mHome); 5707 'I': 5708 if JobTest(UnFocus,jFarm,[eTreaty]) then MenuClick(mFarm) 5709 else if JobTest(UnFocus,jClear,[eTreaty]) then MenuClick(mClear) 5710 else MenuClick_Check(TerrainPopup,mIrrigation); 5711 'L':MenuClick_Check(UnitPopup,mLoad); 5712 'M': 5713 if JobTest(UnFocus,jAfforest,[eTreaty]) then MenuClick(mAfforest) 5714 else MenuClick_Check(TerrainPopup,mMine); 5715 'N':MenuClick_Check(TerrainPopup,mCanal); 5716 'O':MenuClick_Check(TerrainPopup,mTrans); 5717 'P':MenuClick_Check(TerrainPopup,mPollution); 5718 'R': 5719 if JobTest(UnFocus,jRR,[eTreaty]) then MenuClick(mRR) 5720 else MenuClick_Check(TerrainPopup,mRoad); 5721 'S':MenuClick(mStay); 5722 'U':MenuClick_Check(UnitPopup,mUnload); 5723 'V':MenuClick_Check(UnitPopup,mRecover); 5724 'Z':MenuClick_Check(UnitPopup,mUtilize); 5725 #33..#40,#97..#100,#102..#105: 5726 begin {arrow keys} 5727 DestinationMarkON:=false; 5728 PaintDestination; 5729 MyUn[UnFocus].Status:=MyUn[UnFocus].Status 5730 and ($FFFF-usStay-usRecover-usGoto-usEnhance) or usWaiting; 5731 case Key of 5732 VK_NUMPAD1,VK_END: begin dx:=-1; dy:=1 end; 5733 VK_NUMPAD2,VK_DOWN: begin dx:=0; dy:=2 end; 5734 VK_NUMPAD3,VK_NEXT: begin dx:=1; dy:=1 end; 5735 VK_NUMPAD4,VK_LEFT: begin dx:=-2; dy:=0 end; 5736 VK_NUMPAD6,VK_RIGHT: begin dx:=2; dy:=0 end; 5737 VK_NUMPAD7,VK_HOME: begin dx:=-1; dy:=-1 end; 5738 VK_NUMPAD8,VK_UP: begin dx:=0; dy:=-2 end; 5739 VK_NUMPAD9,VK_PRIOR: begin dx:=1; dy:=-1 end; 5740 end; 5741 MoveUnit(dx,dy,muAutoNext) 5742 end; 5743 end 5744 end; 5745 5746 procedure TMainScreen.MenuClick(Sender:TObject); 5747 5748 function DoJob(j0:integer): integer; 5749 var 5750 Loc0, Movement0: integer; 5751 begin 5752 with MyUn[UnFocus] do 5753 begin 5754 DestinationMarkON:=false; 5755 PaintDestination; 5756 Loc0:=Loc; 5757 Movement0:=Movement; 5758 if j0<0 then result:=ProcessEnhancement(UnFocus,MyData.EnhancementJobs) // terrain enhancement 5759 else result:=Server(sStartJob+j0 shl 4,me,UnFocus,nil^); 5760 if result>=rExecuted then 5761 begin 5762 if result=eDied then UnFocus:=-1; 5763 PaintLoc(Loc0); 5764 if UnFocus>=0 then 5765 begin 5766 if (j0<0) and (result<>eJobDone) then // multi-turn terrain enhancement 5767 Status:=Status and ($FFFF-usStay-usRecover-usGoto) or usEnhance 5768 else Status:=Status and ($FFFF-usStay-usRecover-usGoto-usEnhance); 5769 if (Job<>jNone) or (Movement0<100) then 5770 begin 5771 Status:=Status and not usWaiting; 5772 NextUnit(UnStartLoc,true); 5773 end 5774 else PanelPaint 5775 end 5776 else NextUnit(UnStartLoc,true); 5777 end 5778 end; 5779 case result of 5780 eNoBridgeBuilding: SoundMessage(Phrases.Lookup('NOBB'),'INVALID'); 5781 eNoCityTerrain: SoundMessage(Phrases.Lookup('NOCITY'),'INVALID'); 5782 eTreaty: SoundMessage(Tribe[MyRO.Territory[Loc0]].TPhrase('PEACE_NOWORK'),'NOMOVE_TREATY'); 5783 else if result<rExecuted then Play('INVALID') 5784 end 5785 end; 5786 5787 var 5788 i,uix,NewFocus,Loc0,OldMaster,Destination,cix,cixOldHome,ServerResult: integer; 5789 AltGovs,changed: boolean; 5790 QueryText: string; 5791 5792 begin 5793 if Sender=mResign then 5794 if ClientMode=cEditMap then 5795 begin 5796 if Edited then 5797 begin 5798 QueryText:=Phrases.Lookup('MAP_CLOSE'); 5799 case SimpleQuery(mkYesNoCancel,QueryText,'') of 5800 mrIgnore: 5801 Server(sAbandonMap,me,0,nil^); 5802 mrOK: 5803 Server(sSaveMap,me,0,nil^); 5804 end 5805 end 5806 else Server(sAbandonMap,me,0,nil^) 5807 end 5808 else 5809 begin 5810 if Server(sGetGameChanged,0,0,nil^)=eOK then 5811 begin 5812 QueryText:=Phrases.Lookup('RESIGN'); 5813 case SimpleQuery(mkYesNoCancel,QueryText,'') of 5814 mrIgnore: 5815 Server(sResign,0,0,nil^); 5816 mrOK: 5817 Server(sBreak,0,0,nil^) 5818 end 5819 end 5820 else Server(sResign,0,0,nil^) 5821 end 5822 else if Sender=mEmpire then 5823 RatesDlg.ShowNewContent(wmPersistent) 5824 else if Sender=mRevolution then 5825 begin 5826 AltGovs:=false; 5827 for i:=2 to nGov-1 do 5828 if (GovPreq[i]<>preNA) and ((GovPreq[i]=preNone) 5829 or (MyRO.Tech[GovPreq[i]]>=tsApplicable)) then 5830 AltGovs:=true; 5831 5832 if not AltGovs then 5833 SoundMessage(Phrases.Lookup('NOALTGOVS'),'MSG_DEFAULT') 5834 else 5835 begin 5836 changed:=false; 5837 if MyRO.Happened and phChangeGov<>0 then 5838 begin 5839 ModalSelectDlg.ShowNewContent(wmModal,kGov); 5840 if ModalSelectDlg.result>=0 then 5841 begin 5842 Play('NEWGOV'); 5843 Server(sSetGovernment,me,ModalSelectDlg.result,nil^); 5844 CityOptimizer_BeginOfTurn; 5845 changed:=true; 5846 end 5847 end 5848 else with MessgExDlg do 5849 begin // revolution! 5850 MessgText:=Tribe[me].TPhrase('REVOLUTION'); 5851 Kind:=mkYesNo; 5852 IconKind:=mikPureIcon; 5853 IconIndex:=72; // anarchy palace 5854 ShowModal; 5855 if ModalResult=mrOK then 5856 begin 5857 Play('REVOLUTION'); 5858 Server(sRevolution,me,0,nil^); 5859 changed:=true; 5860 if NatStatDlg.Visible then NatStatDlg.Close; 5861 if CityDlg.Visible then CityDlg.Close; 5862 end 5863 end; 5864 if changed then 5865 UpdateViews(true); 5866 end 5867 end 5868 else if Sender=mWebsite then 5869 ShellExecute(Handle,'open','http://c-evo.org','','',SW_SHOWNORMAL) 5870 else if Sender=mRandomMap then 5871 begin 5872 if not Edited or (SimpleQuery(mkYesNo,Phrases.Lookup('MAP_RANDOM'),'')=mrOK) then 5873 begin 5874 Server(sRandomMap,me,0,nil^); 5875 Edited:=true; 5876 MapValid:=false; 5877 PaintAllMaps; 5878 end 5879 end 5880 else if Sender=mJump then 5881 begin 5882 if supervising then 5883 Jump[0]:=20 5884 else Jump[me]:=20; 5885 EndTurn(true); 5886 end 5887 else if Sender=mRun then 5888 begin 5889 if supervising then 5890 Jump[0]:=999999 5891 else Jump[me]:=999999; 5892 EndTurn(true); 5893 end 5894 else if Sender=mEnhanceDef then 5895 begin 5896 if UnFocus>=0 then 5897 EnhanceDlg.ShowNewContent(wmPersistent, MyMap[MyUn[UnFocus].Loc] and fTerrain) 5898 else EnhanceDlg.ShowNewContent(wmPersistent) 5899 end 5900 else if Sender=mCityTypes then 5901 CityTypeDlg.ShowNewContent(wmModal) // must be modal because types are not saved before closing 5902 else if Sender=mUnitStat then 5903 begin 5904 if G.Difficulty[me]>0 then 5905 ListDlg.ShowNewContent_MilReport(wmPersistent,me) 5906 else 5907 begin 5908 i:=1; 5909 while (i<nPl) and (1 shl i and MyRO.Alive=0) do inc(i); 5910 if i<nPl then 5911 ListDlg.ShowNewContent_MilReport(wmPersistent,i); 5912 end; 5913 end 5914 else if Sender=mEUnitStat then 5915 begin 5916 if MyRO.nEnemyModel>0 then 5917 ListDlg.ShowNewContent(wmPersistent,kAllEModels); 5918 end 5919 else if Sender=mCityStat then 5920 ListDlg.ShowNewContent(wmPersistent,kCities) 5921 else if Sender=mScienceStat then 5922 ListDlg.ShowNewContent(wmPersistent,kScience) 5923 else if Sender=mNations then 5924 NatStatDlg.ShowNewContent(wmPersistent) 5925 else if Sender=mHelp then 5926 if ClientMode=cEditMap then 5927 HelpDlg.ShowNewContent(wmPersistent, hkText, HelpDlg.TextIndex('MAPEDIT')) 5928 else HelpDlg.ShowNewContent(wmPersistent, hkMisc, miscMain) 5929 else if Sender=mTechTree then 5930 TechTreeDlg.ShowModal 5931 else if Sender=mWonders then 5932 WondersDlg.ShowNewContent(wmPersistent) 5933 else if Sender=mDiagram then 5934 DiaDlg.ShowNewContent_Charts(wmPersistent) 5935 else if Sender=mShips then 5936 DiaDlg.ShowNewContent_Ship(wmPersistent) 5937 else if Sender=mWait then 5938 begin 5939 if UnFocus>=0 then 5940 begin 5941 DestinationMarkON:=false; 5942 PaintDestination; 5943 MyUn[UnFocus].Status:=MyUn[UnFocus].Status and ($FFFF-usStay-usRecover-usGoto-usEnhance) or usWaiting; 5944 end; 5945 NextUnit(-1,false); 5946 end 5947 else if UnFocus>=0 then with MyUn[UnFocus] do 5948 if Sender=mGoOn then 5949 begin 5950 if Status shr 16=$7FFF then Destination:=maNextCity 5951 else Destination:=Status shr 16; 5952 Status:=Status and not (usStay or usRecover) or usWaiting; 5953 MoveToLoc(Destination,true); 5954 end 5955 else if Sender=mHome then 5956 if MyMap[Loc] and fCity<>0 then 5957 begin 5958 cixOldHome:=Home; 5959 if Server(sSetUnitHome,me,UnFocus,nil^)>=rExecuted then 5960 begin 5961 CityOptimizer_CityChange(cixOldHome); 5962 CityOptimizer_CityChange(Home); 5963 UpdateViews(true); 5964 end 5965 else Play('INVALID'); 5966 end 5967 else 5968 begin 5969 Status:=Status and not (usStay or usRecover or usEnhance); 5970 MoveToLoc(maNextCity,true) 5971 end 5972 else if Sender=mCentre then begin Centre(Loc); PaintAllMaps end 5973 else if Sender=mCity then 5974 begin 5975 Loc0:=Loc; 5976 if MyMap[Loc] and fCity=0 then 5977 begin // build city 5978 if DoJob(jCity)=eCity then 5979 begin 5980 MapValid:=false; 5981 PaintAll; 5982 ZoomToCity(Loc0,true,chFounded); 5983 end 5984 end 5985 else 5986 begin 5987 CityOptimizer_BeforeRemoveUnit(UnFocus); 5988 ServerResult:=Server(sAddToCity,me,UnFocus,nil^); 5989 if ServerResult>=rExecuted then 5990 begin 5991 cix:=MyRO.nCity-1; 5992 while (cix>=0) and (MyCity[cix].Loc<>Loc0) do 5993 dec(cix); 5994 assert(cix>=0); 5995 CityOptimizer_CityChange(cix); 5996 CityOptimizer_AfterRemoveUnit; // does nothing here 5997 SetTroopLoc(Loc0); 5998 UpdateViews(true); 5999 DestinationMarkON:=false; 6000 PaintDestination; 6001 UnFocus:=-1; 6002 PaintLoc(Loc0); 6003 NextUnit(UnStartLoc,true); 6004 end 6005 else if ServerResult=eMaxSize then 6006 SimpleMessage(Phrases.Lookup('ADDTOMAXSIZE')); 6007 end 6008 end 6009 else if Sender=mRoad then DoJob(jRoad) 6010 else if Sender=mRR then DoJob(jRR) 6011 else if Sender=mClear then DoJob(jClear) 6012 else if Sender=mIrrigation then DoJob(jIrr) 6013 else if Sender=mFarm then DoJob(jFarm) 6014 else if Sender=mAfforest then DoJob(jAfforest) 6015 else if Sender=mMine then DoJob(jMine) 6016 else if Sender=mCanal then DoJob(jCanal) 6017 else if Sender=MTrans then DoJob(jTrans) 6018 else if Sender=mFort then DoJob(jFort) 6019 else if Sender=mAirBase then DoJob(jBase) 6020 else if Sender=mPollution then DoJob(jPoll) 6021 else if Sender=mPillage then DoJob(jPillage) 6022 else if Sender=mEnhance then DoJob(-1) 6023 else if Sender=mStay then 6024 begin 6025 DestinationMarkON:=false; 6026 PaintDestination; 6027 Status:=Status and ($FFFF-usRecover-usGoto-usEnhance) or usStay; 6028 if Job>jNone then 6029 Server(sStartJob+jNone shl 4,me,UnFocus,nil^); 6030 NextUnit(UnStartLoc,true) 6031 end 6032 else if Sender=mRecover then 6033 begin 6034 DestinationMarkON:=false; 6035 PaintDestination; 6036 Status:=Status and ($FFFF-usStay-usGoto-usEnhance) or usRecover; 6037 if Job>jNone then 6038 Server(sStartJob+jNone shl 4,me,UnFocus,nil^); 6039 NextUnit(UnStartLoc,true) 6040 end 6041 else if Sender=mNoOrders then 6042 begin 6043 Status:=Status and not usWaiting; 6044 NextUnit(UnStartLoc,true) 6045 end 6046 else if Sender=mCancel then 6047 begin 6048 DestinationMarkON:=false; 6049 PaintDestination; 6050 Status:=Status and ($FFFF-usRecover-usGoto-usEnhance); 6051 if Job>jNone then 6052 Server(sStartJob+jNone shl 4,me,UnFocus,nil^); 6053 end 6054 else if (Sender=mDisband) or (Sender=mUtilize) then 6055 begin 6056 if (Sender=mUtilize) 6057 and not (Server(sRemoveUnit-sExecute,me,UnFocus,nil^)=eUtilized) then 6058 begin 6059 SimpleMessage(Phrases2.Lookup('SHIP_UTILIZE')); 6060 // freight for colony ship is the only case in which the command is 6061 // available to player though not valid 6062 exit 6063 end; 6064 if (Sender=mUtilize) and (Health<100) then 6065 if SimpleQuery(mkYesNo,Phrases.Lookup('DAMAGED_UTILIZE'),'')<>mrOK then 6066 exit; 6067 Loc0:=Loc; 6068 CityOptimizer_BeforeRemoveUnit(UnFocus); 6069 if Server(sRemoveUnit,me,UnFocus,nil^)=eUtilized then Play('CITY_UTILIZE') 6070 else Play('DISBAND'); 6071 CityOptimizer_AfterRemoveUnit; 6072 SetTroopLoc(Loc0); 6073 UpdateViews(true); 6074 DestinationMarkON:=false; 6075 PaintDestination; 6076 UnFocus:=-1; 6077 PaintLoc(Loc0); 6078 NextUnit(UnStartLoc,true); 6079 end 6080 else if Sender=mLoad then 6081 begin 6082 i:=Server(sLoadUnit,me,UnFocus,nil^); 6083 if i>=rExecuted then 6084 begin 6085 if MyModel[mix].Domain=dAir then Play('MOVE_PLANELANDING') 6086 else Play('MOVE_LOAD'); 6087 DestinationMarkON:=false; 6088 PaintDestination; 6089 Status:=Status and ($FFFF-usWaiting-usStay-usRecover-usGoto-usEnhance); 6090 NextUnit(UnStartLoc,true); 6091 end 6092 else if i=eNoTime_Load then 6093 if MyModel[mix].Domain=dAir then 6094 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'),'NOMOVE_TIME') 6095 else 6096 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 6097 [MovementToString(MyModel[mix].Speed)]),'NOMOVE_TIME'); 6098 end 6099 else if Sender=mUnload then 6100 if Master>=0 then 6101 begin 6102 OldMaster:=Master; 6103 i:=Server(sUnloadUnit,me,UnFocus,nil^); 6104 if i>=rExecuted then 6105 begin 6106 if MyModel[mix].Domain=dAir then Play('MOVE_PLANESTART') 6107 else if (MyModel[MyUn[OldMaster].mix].Domain=dAir) 6108 and (MyMap[Loc] and fCity=0) and (MyMap[Loc] and fTerImp<>tiBase) then 6109 Play('MOVE_PARACHUTE') 6110 else Play('MOVE_UNLOAD'); 6111 Status:=Status and not usWaiting; 6112 if MyModel[mix].Domain<>dAir then NextUnit(Loc,true) 6113 else PanelPaint 6114 end 6115 else if i=eNoTime_Load then 6116 if MyModel[mix].Domain=dAir then 6117 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'),'NOMOVE_TIME') 6118 else 6119 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 6120 [MovementToString(MyModel[mix].Speed)]),'NOMOVE_TIME'); 6121 end 6122 else 6123 begin 6124 NewFocus:=-1; 6125 uix:=UnFocus; 6126 for i:=1 to MyRo.nUn-1 do 6127 begin 6128 uix:=(uix+MyRO.nUn-1) mod MyRO.nUn; 6129 if (MyUn[uix].Master=UnFocus) 6130 and (MyUn[uix].Movement=integer(MyModel[MyUn[uix].mix].Speed)) then 6131 begin 6132 MyUn[uix].Status:=MyUn[uix].Status or usWaiting; 6133 NewFocus:=uix 6134 end; 6135 end; 6136 if NewFocus>=0 then 6137 begin 6138 SetUnFocus(NewFocus); 6139 SetTroopLoc(Loc); 6140 PanelPaint 6141 end 6142 end 6143 else if Sender=mSelectTransport then 6144 Server(sSelectTransport,me,UnFocus,nil^) 6145 end; 6146 6147 procedure TMainScreen.InitPopup(Popup: TPopupMenu); 6148 var 6149 i,p1,Tile,Test: integer; 6150 NoSuper,extended,Multi,NeedSep,HaveCities: boolean; 6151 LastSep,m: TMenuItem; 6152 mox: ^TModel; 6153 begin 6154 NoSuper:=not supervising and (1 shl me and MyRO.Alive<>0); 6155 HaveCities:=false; 6156 for i:=0 to MyRO.nCity-1 do if MyCity[i].Loc>=0 then 6157 begin HaveCities:=true; Break end; 6158 if Popup=GamePopup then 6159 begin 6160 mTechTree.Visible:= ClientMode<>cEditMap; 6161 mResign.Enabled:= supervising or (me=0) and (ClientMode<scContact); 6162 mRandomMap.Visible:= (ClientMode=cEditMap) 6163 and (Server(sMapGeneratorRequest,me,0,nil^)=eOk); 6164 mOptions.Visible:= ClientMode<>cEditMap; 6165 mManip.Visible:= ClientMode<>cEditMap; 6166 if ClientMode<>cEditMap then 6167 begin 6168 mWaitTurn.Visible:= NoSuper; 6169 mRep.Visible:= NoSuper; 6170 mRepList.Visible:= NoSuper; 6171 mRepScreens.Visible:= NoSuper; 6172 N10.Visible:= NoSuper; 6173 mOwnMovement.Visible:= NoSuper; 6174 mAllyMovement.Visible:= NoSuper; 6175 case SoundMode of 6176 smOff: mSoundOff.Checked:=true; 6177 smOn: mSoundOn.Checked:=true; 6178 smOnAlt: mSoundOnAlt.Checked:=true; 6179 end; 6180 6181 for i:=0 to nTestFlags-1 do 6182 mManip[i].Checked:= MyRO.TestFlags and (1 shl i)<>0; 6183 mManip.Enabled:= supervising or (me=0); 6184 6185 Multi:=false; 6186 for p1:=1 to nPl-1 do 6187 if G.RO[p1]<>nil then Multi:=true; 6188 mEnemyMovement.Visible:=not Multi; 6189 end; 6190 mMacro.Visible:= NoSuper and (ClientMode<scContact); 6191 if NoSuper and (ClientMode<scContact) then 6192 begin 6193 mCityTypes.Enabled:=false; 6194 // check if city types already usefull: 6195 if MyRO.nCity>0 then 6196 for i:=28 to nImp-1 do 6197 if (i<>imTrGoods) and (Imp[i].Kind=ikCommon) and (Imp[i].Preq<>preNA) 6198 and ((Imp[i].Preq=preNone) or (MyRO.Tech[Imp[i].Preq]>=tsApplicable)) then 6199 begin mCityTypes.Enabled:=true; Break end; 6200 end; 6201 mViewpoint.visible:=(ClientMode<>cEditMap) and supervising; 6202 mViewpoint.enabled:= G.RO[0].Turn>0; 6203 if supervising then 6204 begin 6205 EmptyMenu(mViewpoint); 6206 for p1:=0 to nPl-1 do 6207 if (p1=0) or (1 shl p1 and G.RO[0].Alive<>0) then 6208 begin 6209 m:=TMenuItem.Create(mViewpoint); 6210 if p1=0 then 6211 m.Caption:=Phrases.Lookup('SUPER') 6212 else m.Caption:=Tribe[p1].TString(Phrases2.Lookup('BELONG')); 6213 m.Tag:=p1; 6214 m.OnClick:=ViewPointClick; 6215 if p1<10 then 6216 m.ShortCut:=Shortcut(48+p1, [ssCtrl]); 6217 m.RadioItem:=true; 6218 if p1=me then 6219 m.Checked:=true; 6220 mViewPoint.Add(m); 6221 end 6222 end; 6223 mDebugMap.visible:=(ClientMode<>cEditMap) and supervising; 6224 if supervising then 6225 begin 6226 EmptyMenu(mDebugMap); 6227 for p1:=0 to nPl-1 do 6228 if (p1=0) or (1 shl p1 and G.RO[0].Alive<>0) then 6229 begin 6230 m:=TMenuItem.Create(mDebugMap); 6231 if p1=0 then 6232 m.Caption:=Phrases2.Lookup('MENU_DEBUGMAPOFF') 6233 else m.Caption:=Tribe[p1].TString(Phrases2.Lookup('BELONG')); 6234 if p1=0 then 6235 m.Tag:=-1 6236 else m.Tag:=p1; 6237 m.OnClick:=DebugMapClick; 6238 if p1<10 then 6239 m.ShortCut:=Shortcut(48+p1, [ssAlt]); 6240 m.RadioItem:=true; 6241 if m.Tag=IsoEngine.pDebugMap then 6242 m.Checked:=true; 6243 mDebugMap.Add(m); 6244 end 6245 end; 6246 mSmallTiles.Checked:= xxt=33; 6247 mNormalTiles.Checked:= xxt=48; 6248 end 6249 else if Popup=StatPopup then 6250 begin 6251 mEmpire.Visible:= NoSuper; 6252 mEmpire.Enabled:= MyRO.Government<>gAnarchy; 6253 mRevolution.Visible:= NoSuper; 6254 mRevolution.Enabled:= (MyRO.Government<>gAnarchy) and (ClientMode<scContact); 6255 mUnitStat.Enabled:= NoSuper or (MyRO.Turn>0); 6256 mCityStat.Visible:= 1 shl me and MyRO.Alive<>0; 6257 mCityStat.Enabled:= HaveCities; 6258 mScienceStat.Visible:= true; 6259 mScienceStat.Enabled:= not NoSuper or (MyRO.ResearchTech>=0) 6260 or (MyRO.Happened and phTech<>0) 6261 or (MyRO.Happened and phGameEnd<>0) // no researchtech in case just completed 6262 or (MyRO.TestFlags and (tfAllTechs or tfUncover or tfAllContact)<>0); 6263 mEUnitStat.Enabled:= MyRO.nEnemyModel>0; 6264 { mWonders.Enabled:= false; 6265 for i:=0 to 27 do if MyRO.Wonder[i].CityID<>-1 then 6266 mWonders.Enabled:=true;} 6267 mDiagram.Enabled:= MyRO.Turn>=2; 6268 mShips.Enabled:=false; 6269 for p1:=0 to nPl-1 do 6270 if MyRO.Ship[p1].Parts[spComp]+MyRO.Ship[p1].Parts[spPow] 6271 +MyRO.Ship[p1].Parts[spHab]>0 then 6272 mShips.Enabled:=true; 6273 end 6274 else if Popup=UnitPopup then 6275 begin 6276 mox:=@MyModel[MyUn[UnFocus].mix]; 6277 Tile:=MyMap[MyUn[UnFocus].Loc]; 6278 extended:=Tile and fCity=0; 6279 if extended then 6280 begin 6281 mCity.Caption:=Phrases.Lookup('BTN_FOUND'); 6282 mHome.Caption:=Phrases.Lookup('BTN_MOVEHOME') 6283 end 6284 else 6285 begin 6286 mCity.Caption:=Phrases.Lookup('BTN_ADD'); 6287 mHome.Caption:=Phrases.Lookup('BTN_SETHOME') 6288 end; 6289 6290 extended:=extended and ((mox.Kind=mkSettler) or (mox.Kind=mkSlaves) 6291 and (MyRO.Wonder[woPyramids].EffectiveOwner>=0)) 6292 and (MyUn[UnFocus].Master<0) and (Tile and fDeadLands=0); 6293 if (mox.Kind=mkFreight) and (Tile and fCity<>0) and not Phrases2FallenBackToEnglish 6294 or (Server(sRemoveUnit-sExecute,me,UnFocus,nil^)=eUtilized) then 6295 begin 6296 mDisband.Visible:=false; 6297 mUtilize.Visible:=true; 6298 if mox.Kind=mkFreight then 6299 mUtilize.Caption:=Phrases.Lookup('UTILIZE') 6300 else mUtilize.Caption:=Phrases.Lookup('INTEGRATE') 6301 end 6302 else begin mDisband.Visible:=true; mUtilize.Visible:=false end; 6303 mGoOn.Visible:= MyUn[UnFocus].Status and (usGoto or usWaiting)=usGoto or usWaiting; 6304 mHome.Visible:=HaveCities; 6305 mRecover.Visible:= (MyUn[UnFocus].Health<100) and (Tile and fTerrain>=fGrass) 6306 and ((MyRO.Wonder[woGardens].EffectiveOwner=me) 6307 or (Tile and fTerrain<>fArctic) and (Tile and fTerrain<>fDesert)) 6308 and not ((mox.Domain=dAir) and (Tile and fCity=0) and (Tile and fTerImp<>tiBase)); 6309 mStay.Visible:= not ((mox.Domain=dAir) and (Tile and fCity=0) and (Tile and fTerImp<>tiBase)); 6310 mCity.Visible:=extended and (mox.Kind=mkSettler) or (Tile and fCity<>0) 6311 and ((mox.Kind in [mkSettler,mkSlaves]) or (MyUn[UnFocus].Flags and unConscripts<>0)); 6312 mPillage.Visible:=(Tile and (fRoad or fRR or fCanal or fTerImp)<>0) 6313 and (MyUn[UnFocus].Master<0) and (mox.Domain=dGround); 6314 mCancel.Visible:=(MyUn[UnFocus].Job>jNone) or (MyUn[UnFocus].Status and (usRecover or usGoto)<>0); 6315 6316 Test:=Server(sLoadUnit-sExecute,me,UnFocus,nil^); 6317 mLoad.Visible:= (Test>=rExecuted) or (Test=eNoTime_Load); 6318 mUnload.Visible:= (MyUn[UnFocus].Master>=0) 6319 or (MyUn[UnFocus].TroopLoad+MyUn[UnFocus].AirLoad>0); 6320 mSelectTransport.Visible:= 6321 Server(sSelectTransport-sExecute,me,UnFocus,nil^)>=rExecuted; 6322 end 6323 else {if Popup=TerrainPopup then} 6324 begin 6325 mox:=@MyModel[MyUn[UnFocus].mix]; 6326 Tile:=MyMap[MyUn[UnFocus].Loc]; 6327 extended:=Tile and fCity=0; 6328 6329 if (Tile and fRiver<>0) and (MyRO.Tech[adBridgeBuilding]>=tsApplicable) then 6330 begin 6331 mRoad.Caption:=Phrases.Lookup('BTN_BUILDBRIDGE'); 6332 mRR.Caption:=Phrases.Lookup('BTN_BUILDRRBRIDGE'); 6333 end 6334 else 6335 begin 6336 mRoad.Caption:=Phrases.Lookup('BTN_BUILDROAD'); 6337 mRR.Caption:=Phrases.Lookup('BTN_BUILDRR'); 6338 end; 6339 if Tile and fTerrain=fForest then 6340 mClear.Caption:=Phrases.Lookup('BTN_CLEAR') 6341 else if Tile and fTerrain=fDesert then 6342 mClear.Caption:=Phrases.Lookup('BTN_UNDESERT') 6343 else mClear.Caption:=Phrases.Lookup('BTN_DRAIN'); 6344 6345 extended:=extended and ((mox.Kind=mkSettler) or (mox.Kind=mkSlaves) 6346 and (MyRO.Wonder[woPyramids].EffectiveOwner>=0)) 6347 and (MyUn[UnFocus].Master<0); 6348 if extended then 6349 begin 6350 mRoad.Visible:= JobTest(UnFocus,jRoad,[eNoBridgeBuilding,eTreaty]); 6351 mRR.Visible:= JobTest(UnFocus,jRR,[eNoBridgeBuilding,eTreaty]); 6352 mClear.Visible:= JobTest(UnFocus,jClear,[eTreaty]); 6353 mIrrigation.Visible:= JobTest(UnFocus,jIrr,[eTreaty]); 6354 mFarm.Visible:= JobTest(UnFocus,jFarm,[eTreaty]); 6355 mAfforest.Visible:= JobTest(UnFocus,jAfforest,[eTreaty]); 6356 mMine.Visible:= JobTest(UnFocus,jMine,[eTreaty]); 6357 MTrans.Visible:= JobTest(UnFocus,jTrans,[eTreaty]); 6358 mCanal.Visible:= JobTest(UnFocus,jCanal,[eTreaty]); 6359 mFort.Visible:= JobTest(UnFocus,jFort,[eTreaty]); 6360 mAirBase.Visible:= JobTest(UnFocus,jBase,[eTreaty]); 6361 mPollution.Visible:=JobTest(UnFocus,jPoll,[eTreaty]); 6362 mEnhance.Visible:= (Tile and fDeadLands=0) 6363 and (MyData.EnhancementJobs[MyMap[MyUn[UnFocus].Loc] and fTerrain,0]<>jNone); 6364 end 6365 else 6366 begin 6367 for i:=0 to Popup.Items.Count-1 do Popup.Items[i].Visible:=false; 6368 end; 6369 end; 6370 6371 // set menu seperators 6372 LastSep:=nil; 6373 needsep:=false; 6374 for i:=0 to Popup.Items.Count-1 do 6375 if Popup.Items[i].Caption='-' then 6376 begin 6377 Popup.Items[i].Visible:=needsep; 6378 if needsep then LastSep:=Popup.Items[i]; 6379 needsep:=false 6380 end 6381 else if Popup.Items[i].Visible then needsep:=true; 6382 if (LastSep<>nil) and not NeedSep then LastSep.Visible:=false 6383 end; 6384 6385 procedure TMainScreen.PanelBtnClick(Sender: TObject); 6386 var 6387 Popup: TPopupMenu; 6388 begin 6389 if Sender=UnitBtn then Popup:=UnitPopup 6390 else {if Sender=TerrainBtn then} Popup:=TerrainPopup; 6391 InitPopup(Popup); 6392 if FullScreen then 6393 Popup.Popup(Left+TControl(Sender).Left,Top+TControl(Sender).Top) 6394 else Popup.Popup(Left+TControl(Sender).Left+4,Top+TControl(Sender).Top 6395 +GetSystemMetrics(SM_CYCAPTION)+4); 6396 end; 6397 6398 procedure TMainScreen.CityClosed(Activateuix: integer; StepFocus: boolean; 6399 SelectFocus: boolean); 6400 begin 6401 if supervising then 6402 begin 6403 SetTroopLoc(-1); 6404 PanelPaint 6405 end 6406 else 6407 begin 6408 if Activateuix>=0 then 6409 begin 6410 SetUnFocus(Activateuix); 6411 SetTroopLoc(MyUn[Activateuix].Loc); 6412 if SelectFocus then FocusOnLoc(TroopLoc,flRepaintPanel) 6413 else PanelPaint 6414 end 6415 else if StepFocus then NextUnit(TroopLoc,true) 6416 else 6417 begin 6418 SetTroopLoc(-1); 6419 PanelPaint 6420 end 6421 end 6422 end; 6423 6424 procedure TMainScreen.Toggle(Sender: TObject); 6425 begin 6426 TMenuItem(Sender).Checked:=not TMenuItem(Sender).Checked 6427 end; 6428 6429 procedure TMainScreen.PanelBoxMouseMove(Sender: TObject; 6430 Shift: TShiftState; x, y: integer); 6431 var 6432 xCentre,yCentre: integer; 6433 begin 6434 if Tracking and (ssLeft in Shift) then 6435 begin 6436 if (x>=xMini+2) and (y>=yMini+2) and (x<xMini+2+2*G.lx) and (y<yMini+2+G.ly) then 6437 begin 6438 xCentre:=(xwMini+(x-xMini-2) div 2+G.lx div 2+MapWidth div (xxt*4)) mod G.lx; 6439 yCentre:=(y-yMini-2); 6440 xw:=(xCentre-MapWidth div (xxt*4)+G.lx) mod G.lx; 6441 if ywmax<=0 then yw:=ywcenter 6442 else 6443 begin 6444 yw:=(yCentre-MapHeight div (yyt*2)+1) and not 1; 6445 if yw<0 then yw:=0 6446 else if yw>ywmax then yw:=ywmax; 6447 end; 6448 BitBlt(Buffer.Canvas.Handle,0,0,G.lx*2,G.ly,Mini.Canvas.Handle,0,0,SRCCOPY); 6449 if ywmax<=0 then 6450 Frame(Buffer.Canvas,x-xMini-2-MapWidth div (xxt*2),0, 6451 x-xMini-2+MapWidth div (xxt*2)-1, 6452 G.ly-1,MainTexture.clMark,MainTexture.clMark) 6453 else Frame(Buffer.Canvas,x-xMini-2-MapWidth div (xxt*2),yw, 6454 x-xMini-2+MapWidth div (xxt*2)-1, 6455 yw+MapHeight div yyt-2,MainTexture.clMark,MainTexture.clMark); 6456 BitBlt(Panel.Canvas.Handle,xMini+2,yMini+2,G.lx*2,G.ly,Buffer.Canvas.Handle, 6457 0,0,SRCCOPY); 6458 MainOffscreenPaint; 6459 RectInvalidate(xMini+2,TopBarHeight+MapHeight-overlap+yMini+2, 6460 xMini+2+G.lx*2,TopBarHeight+MapHeight-overlap+yMini+2+G.ly); 6461 Update; 6462 end 6463 end 6464 else Tracking:=false 6465 end; 6466 6467 procedure TMainScreen.PanelBoxMouseUp(Sender: TObject; 6468 Button: TMouseButton; Shift: TShiftState; x, y: integer); 6469 begin 6470 if Tracking then 6471 begin 6472 Tracking:=false; 6473 xwMini:=xw; ywMini:=yw; 6474 MiniPaint; 6475 PanelPaint; 6476 end 6477 end; 6478 6479 procedure TMainScreen.MapBoxMouseMove(Sender: TObject; Shift: TShiftState; x, 6480 y: integer); 6481 var 6482 MouseLoc: integer; 6483 begin 6484 xMouse:=x; yMouse:=y; 6485 if (ClientMode=cEditMap) and (ssLeft in Shift) and not tracking then 6486 begin 6487 MouseLoc:=LocationOfScreenPixel(x,y); 6488 if MouseLoc<>BrushLoc then 6489 MapBoxMouseDown(nil, mbLeft, Shift, x, y); 6490 end 6491 (*else if idle and (UnFocus>=0) then 6492 begin 6493 qx:=(xMouse*32+yMouse*66+16*66) div(32*66)-1; 6494 qy:=(yMouse*66-xMouse*32-16*66+2000*33*32) div(32*66)-999; 6495 MouseLoc:=(xw+(qx-qy+2048) div 2-1024+G.lx) mod G.lx+G.lx*(yw+qx+qy); 6496 ShowMoveHint(MouseLoc); 6497 end*) 6498 end; 6499 6500 procedure TMainScreen.mShowClick(Sender: TObject); 6501 begin 6502 TMenuItem(Sender).Checked:=not TMenuItem(Sender).Checked; 6503 SetMapOptions; 6504 MapValid:=false; 6505 PaintAllMaps; 6506 end; 6507 6508 procedure TMainScreen.mNamesClick(Sender: TObject); 6509 var 6510 p1: integer; 6511 begin 6512 mNames.Checked:=not mNames.Checked; 6513 GenerateNames:=mNames.Checked; 6514 for p1:=0 to nPl-1 do if Tribe[p1]<>nil then 6515 if GenerateNames then Tribe[p1].NumberName:=-1 6516 else Tribe[p1].NumberName:=p1; 6517 MapValid:=false; 6518 PaintAll; 6519 end; 6520 6521 function TMainScreen.IsPanelPixel(x,y: integer): boolean; 6522 begin 6523 result:= (y>=TopBarHeight+MapHeight) 6524 or (y>=ClientHeight-PanelHeight) and ((x<xMidPanel) or (x>=xRightPanel)) 6525 end; 6526 6527 procedure TMainScreen.FormMouseDown(Sender: TObject; Button: TMouseButton; 6528 Shift: TShiftState; x, y: integer); 6529 begin 6530 if idle then 6531 if (x<40) and (y<40) then 6532 begin 6533 if GameMode<>cMovie then 6534 begin 6535 InitPopup(GamePopup); 6536 if FullScreen then 6537 GamePopup.Popup(Left,Top+TopBarHeight-1) 6538 else GamePopup.Popup(Left+4,Top+GetSystemMetrics(SM_CYCAPTION)+4+TopBarHeight-1); 6539 end 6540 end 6541 else if IsPanelPixel(x,y) then 6542 PanelBoxMouseDown(Sender,Button,Shift,x,y-(ClientHeight-PanelHeight)) 6543 else if (y>=TopBarHeight) and (x>=MapOffset) and (x<MapOffset+MapWidth) then 6544 MapBoxMouseDown(Sender,Button,Shift,x-MapOffset,y-TopBarHeight) 6545 end; 6546 6547 procedure TMainScreen.FormMouseMove(Sender: TObject; Shift: TShiftState; x, 6548 y: integer); 6549 begin 6550 if idle then 6551 if IsPanelPixel(x,y) then 6552 PanelBoxMouseMove(Sender,Shift,x,y-(ClientHeight-PanelHeight)) 6553 else if (y>=TopBarHeight) and (x>=MapOffset) and (x<MapOffset+MapWidth) then 6554 MapBoxMouseMove(Sender,Shift,x-MapOffset,y-TopBarHeight); 6555 end; 6556 6557 procedure TMainScreen.FormMouseUp(Sender: TObject; Button: TMouseButton; 6558 Shift: TShiftState; x, y: integer); 6559 begin 6560 if idle then 6561 PanelBoxMouseUp(Sender,Button,Shift,x,y-(ClientHeight-PanelHeight)); 6562 end; 6563 6564 procedure TMainScreen.FormPaint(Sender: TObject); 6565 begin 6566 MainOffscreenPaint; 6567 if (MapOffset>0) or (MapOffset+MapWidth<ClientWidth) then with canvas do 6568 begin // pillarbox, make left and right border black 6569 if me<0 then 6570 brush.color:=$000000 6571 else brush.color:=EmptySpaceColor; 6572 if xMidPanel>MapOffset then 6573 FillRect(Rect(0,TopBarHeight,MapOffset,TopBarHeight+MapHeight-overlap)) 6574 else 6575 begin 6576 FillRect(Rect(0,TopBarHeight,xMidPanel,TopBarHeight+MapHeight-overlap)); 6577 FillRect(Rect(xMidPanel,TopBarHeight,MapOffset,TopBarHeight+MapHeight)); 6578 end; 6579 if xRightPanel<MapOffset+MapWidth then 6580 FillRect(Rect(MapOffset+MapWidth,TopBarHeight,ClientWidth,TopBarHeight+MapHeight-overlap)) 6581 else 6582 begin 6583 FillRect(Rect(MapOffset+MapWidth,TopBarHeight,xRightPanel,TopBarHeight+MapHeight)); 6584 FillRect(Rect(xRightPanel,TopBarHeight,ClientWidth,TopBarHeight+MapHeight-overlap)); 6585 end; 6586 Brush.Style:=bsClear; 6587 end; 6588 BitBlt(Canvas.Handle,MapOffset,TopBarHeight,MapWidth,MapHeight-overlap,offscreen.Canvas.Handle, 6589 0,0,SRCCOPY); 6590 BitBlt(Canvas.Handle,0,0,ClientWidth,TopBarHeight,TopBar.Canvas.Handle, 6591 0,0,SRCCOPY); 6592 if xMidPanel>MapOffset then 6593 BitBlt(Canvas.Handle,xMidPanel,TopBarHeight+MapHeight-overlap, 6594 ClientWidth div 2-xMidPanel,overlap, 6595 offscreen.Canvas.Handle,xMidPanel-MapOffset,MapHeight-overlap,SRCCOPY) 6596 else BitBlt(Canvas.Handle,MapOffset,TopBarHeight+MapHeight-overlap, 6597 ClientWidth div 2-MapOffset,overlap, 6598 offscreen.Canvas.Handle,0,MapHeight-overlap,SRCCOPY); 6599 if xRightPanel<MapOffset+MapWidth then 6600 BitBlt(Canvas.Handle,ClientWidth div 2,TopBarHeight+MapHeight-overlap, 6601 xRightPanel-ClientWidth div 2,overlap, 6602 offscreen.Canvas.Handle,ClientWidth div 2-MapOffset,MapHeight-overlap,SRCCOPY) 6603 else BitBlt(Canvas.Handle,ClientWidth div 2,TopBarHeight+MapHeight-overlap, 6604 MapOffset+MapWidth-ClientWidth div 2,overlap, 6605 offscreen.Canvas.Handle,ClientWidth div 2-MapOffset,MapHeight-overlap,SRCCOPY); 6606 BitBlt(Canvas.Handle,0,TopBarHeight+MapHeight-overlap,xMidPanel,overlap, 6607 Panel.Canvas.Handle,0,0,SRCCOPY); 6608 BitBlt(Canvas.Handle,xRightPanel,TopBarHeight+MapHeight-overlap,Panel.Width-xRightPanel, 6609 overlap,Panel.Canvas.Handle,xRightPanel,0,SRCCOPY); 6610 BitBlt(Canvas.Handle,0,TopBarHeight+MapHeight,Panel.Width,PanelHeight-overlap, 6611 Panel.Canvas.Handle,0,overlap,SRCCOPY); 6612 if (pLogo>=0) and (G.RO[pLogo]=nil) and (AILogo[pLogo]<>nil) then 6613 BitBlt(Canvas.Handle, xRightPanel+10-(16+64), ClientHeight-PanelHeight, 64,64, 6614 AILogo[pLogo].Canvas.Handle,0,0,SRCCOPY); 6615 end; 6616 6617 procedure TMainScreen.RectInvalidate(Left,Top,Rigth,Bottom: integer); 6618 var 6619 r0: HRgn; 6620 begin 6621 r0:=CreateRectRgn(Left,Top,Rigth,Bottom); 6622 InvalidateRgn(Handle,r0,false); 6623 DeleteObject(r0); 6624 end; 6625 6626 procedure TMainScreen.SmartRectInvalidate(Left,Top,Rigth,Bottom: integer); 6627 var 6628 i: integer; 6629 r0,r1: HRgn; 6630 begin 6631 r0:=CreateRectRgn(Left,Top,Rigth,Bottom); 6632 for i:=0 to ControlCount-1 do 6633 if not (Controls[i] is TArea) and Controls[i].Visible then 6634 begin 6635 with Controls[i].BoundsRect do 6636 r1:=CreateRectRgn(Left,Top,Right,Bottom); 6637 CombineRgn(r0,r0,r1,RGN_DIFF); 6638 DeleteObject(r1); 6639 end; 6640 InvalidateRgn(Handle,r0,false); 6641 DeleteObject(r0); 6642 end; 6643 6644 procedure TMainScreen.mRepClicked(Sender: TObject); 6645 begin 6646 with TMenuItem(Sender) do 6647 begin 6648 Checked:=not Checked; 6649 if Checked then CityRepMask:=CityRepMask or (1 shl (Tag shr 8)) 6650 else CityRepMask:=CityRepMask and not (1 shl (Tag shr 8)) 6651 end 6652 end; 6653 6654 procedure TMainScreen.mLogClick(Sender: TObject); 6655 begin 6656 LogDlg.Show 6657 end; 6658 6659 procedure TMainScreen.FormShow(Sender: TObject); 6660 begin 6661 Timer1.Enabled:=true 6662 end; 6663 6664 procedure TMainScreen.FormClose(Sender: TObject; var Action: TCloseAction); 6665 begin 6666 Timer1.Enabled:=false 6667 end; 6668 6669 procedure TMainScreen.Radio(Sender: TObject); 6670 begin 6671 TMenuItem(Sender).Checked:=true 6672 end; 6673 6674 procedure TMainScreen.mManipClick(Sender: TObject); 6675 var 6676 Flag: integer; 6677 begin 6678 with TMenuItem(Sender) do 6679 begin 6680 Flag:=1 shl (Tag shr 8); 6681 if Checked then Server(sClearTestFlag,0,Flag,nil^) 6682 else 6683 begin 6684 Server(sSetTestFlag,0,Flag,nil^); 6685 Play('CHEAT'); 6686 end; 6687 if not supervising then 6688 begin 6689 if Flag=tfUncover then 6690 begin MapValid:=false; PaintAllMaps; end 6691 else if Flag=tfAllTechs then 6692 TellNewModels 6693 end 6694 end 6695 end; 6696 6697 procedure TMainScreen.MapBtnClick(Sender: TObject); 6698 begin 6699 with TButtonC(Sender) do 6700 begin 6701 MapOptionChecked:=MapOptionChecked xor (1 shl (Tag shr 8)); 6702 SetMapOptions; 6703 ButtonIndex:=MapOptionChecked shr (Tag shr 8) and 1 +2 6704 end; 6705 if Sender=MapBtn0 then 6706 begin MiniPaint; PanelPaint end // update mini map only 6707 else begin MapValid:=false; PaintAllMaps; end; // update main map 6708 end; 6709 6710 procedure TMainScreen.GrWallBtnDownChanged(Sender: TObject); 6711 begin 6712 if TButtonBase(Sender).Down then 6713 begin 6714 MapOptionChecked:=MapOptionChecked or (1 shl moGreatWall); 6715 TButtonBase(Sender).Hint:=''; 6716 end 6717 else 6718 begin 6719 MapOptionChecked:=MapOptionChecked and not (1 shl moGreatWall); 6720 TButtonBase(Sender).Hint:=Phrases.Lookup('CONTROLS',-1+TButtonBase(Sender).Tag and $FF); 6721 end; 6722 SetMapOptions; 6723 MapValid:=false; 6724 PaintAllMaps; 6725 end; 6726 6727 procedure TMainScreen.BareBtnDownChanged(Sender: TObject); 6728 begin 6729 if TButtonBase(Sender).Down then 6730 begin 6731 MapOptionChecked:=MapOptionChecked or (1 shl moBareTerrain); 6732 TButtonBase(Sender).Hint:=''; 6733 end 6734 else 6735 begin 6736 MapOptionChecked:=MapOptionChecked and not (1 shl moBareTerrain); 6737 TButtonBase(Sender).Hint:=Phrases.Lookup('CONTROLS',-1+TButtonBase(Sender).Tag and $FF); 6738 end; 6739 SetMapOptions; 6740 MapValid:=false; 6741 PaintAllMaps; 6742 end; 6743 6744 procedure TMainScreen.FormKeyUp(Sender: TObject; var Key: Word; 6745 Shift: TShiftState); 6746 begin 6747 if idle and (Key=VK_APPS) then 6748 begin 6749 InitPopup(GamePopup); 6750 if FullScreen then 6751 GamePopup.Popup(Left,Top+TopBarHeight-1) 6752 else GamePopup.Popup(Left+4,Top+GetSystemMetrics(SM_CYCAPTION)+4+TopBarHeight-1); 6753 exit 6754 end // windows menu button calls game menu 6755 end; 6756 6757 procedure TMainScreen.CreateUnitClick(Sender: TObject); 6758 var 6759 p1,mix: integer; 6760 begin 6761 p1:=TComponent(Sender).Tag shr 16; 6762 mix:=TComponent(Sender).Tag and $FFFF; 6763 if Server(sCreateUnit+p1 shl 4,me,mix,EditLoc)>=rExecuted then 6764 PaintLoc(EditLoc); 6765 end; 6766 6767 procedure TMainScreen.mSoundOffClick(Sender: TObject); 6768 begin 6769 SoundMode:=smOff; 6770 end; 6771 6772 procedure TMainScreen.mSoundOnClick(Sender: TObject); 6773 begin 6774 SoundMode:=smOn; 6775 end; 6776 6777 procedure TMainScreen.mSoundOnAltClick(Sender: TObject); 6778 begin 6779 SoundMode:=smOnAlt; 6780 end; 6781 6782 {procedure TMainScreen.AdviceBtnClick; 6783 var 6784 OldAdviceLoc: integer; 6785 begin 6786 DestinationMarkON:=false; 6787 PaintDestination; 6788 AdvisorDlg.GiveStrategyAdvice; 6789 OldAdviceLoc:=MainMap.AdviceLoc; 6790 MainMap.AdviceLoc:=-1; 6791 PaintLoc(OldAdviceLoc); 6792 end;} 6793 6794 {procedure TMainScreen.SetAdviceLoc(Loc: integer; AvoidRect: TRect); 6795 var 6796 OldAdviceLoc,x,y: integer; 6797 begin 6798 if Loc<>MainMap.AdviceLoc then 6799 begin 6800 if Loc>=0 then 6801 begin // center 6802 y:=Loc div G.lx; 6803 x:=(Loc+G.lx - AvoidRect.Right div (2*66)) mod G.lx; 6804 Centre(y*G.lx+x); 6805 PaintAllMaps; 6806 end; 6807 OldAdviceLoc:=MainMap.AdviceLoc; 6808 MainMap.AdviceLoc:=Loc; 6809 PaintLoc(OldAdviceLoc); 6810 PaintLoc(MainMap.AdviceLoc); 6811 end; 6812 end;} 6813 6814 procedure TMainScreen.UnitInfoBtnClick(Sender: TObject); 6815 begin 6816 if UnFocus>=0 then 6817 UnitStatDlg.ShowNewContent_OwnModel(wmPersistent, MyUn[UnFocus].mix) 6818 end; 6819 6820 procedure TMainScreen.ViewpointClick(Sender: TObject); 6821 begin 6822 SetViewpoint(TMenuItem(Sender).Tag); 6823 end; 6824 6825 procedure TMainScreen.DebugMapClick(Sender: TObject); 6826 begin 6827 SetDebugMap(TMenuItem(Sender).Tag); 6828 end; 6829 6830 procedure TMainScreen.mSmallTilesClick(Sender: TObject); 6831 begin 6832 SetTileSize(33,16); 6833 end; 6834 6835 procedure TMainScreen.mNormalTilesClick(Sender: TObject); 6836 begin 6837 SetTileSize(48,24); 6838 end; 6839 6840 procedure TMainScreen.SetTileSize(x,y: integer); 6841 var 6842 i,CenterLoc: integer; 6843 begin 6844 CenterLoc:=(xw+MapWidth div (xxt*4)) mod G.lx+(yw+MapHeight div (yyt*2))*G.lx; 6845 IsoEngine.ApplyTileSize(x,y); 6846 FormResize(nil); 6847 Centre(CenterLoc); 6848 PaintAllMaps; 6849 for i:=0 to Screen.FormCount-1 do 6850 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 6851 TBufferedDrawDlg(Screen.Forms[i]).SmartUpdateContent(false); 6852 end; 6853 6854 procedure TMainScreen.SaveSettings; 6855 var 6856 i,j: integer; 6857 Reg: TRegistry; 6858 begin 6859 OptionChecked:=OptionChecked and soExtraMask; 6860 for i:=0 to ComponentCount-1 do if Components[i] is TMenuItem then 6861 for j:=0 to nSaveOption-1 do 6862 if TMenuItem(Components[i]).Checked 6863 and (TMenuItem(Components[i]).Tag=SaveOption[j]) then 6864 inc(OptionChecked,1 shl j); 6865 6866 Reg:=TRegistry.Create; 6867 Reg.OpenKey('SOFTWARE\cevo\RegVer9',true); 6868 Reg.WriteInteger('TileWidth',xxt*2); 6869 Reg.WriteInteger('TileHeight',yyt*2); 6870 Reg.WriteInteger('OptionChecked', OptionChecked); 6871 Reg.WriteInteger('MapOptionChecked', MapOptionChecked); 6872 Reg.WriteInteger('CityReport',integer(CityRepMask)); 6873 Reg.closekey; 6874 Reg.Free; 6875 end; 6876 6877 procedure TMainScreen.MovieSpeedBtnClick(Sender: TObject); 6878 begin 6879 MovieSpeed:=TButtonB(Sender).Tag shr 8; 6880 CheckMovieSpeedBtnState; 6881 end; 7961 end; } 7962 7963 procedure TMainScreen.UnitInfoBtnClick(Sender: TObject); 7964 begin 7965 if UnFocus >= 0 then 7966 UnitStatDlg.ShowNewContent_OwnModel(wmPersistent, MyUn[UnFocus].mix) 7967 end; 7968 7969 procedure TMainScreen.ViewpointClick(Sender: TObject); 7970 begin 7971 SetViewpoint(TMenuItem(Sender).Tag); 7972 end; 7973 7974 procedure TMainScreen.DebugMapClick(Sender: TObject); 7975 begin 7976 SetDebugMap(TMenuItem(Sender).Tag); 7977 end; 7978 7979 procedure TMainScreen.mSmallTilesClick(Sender: TObject); 7980 begin 7981 SetTileSize(33, 16); 7982 end; 7983 7984 procedure TMainScreen.mNormalTilesClick(Sender: TObject); 7985 begin 7986 SetTileSize(48, 24); 7987 end; 7988 7989 procedure TMainScreen.SetTileSize(x, y: integer); 7990 var 7991 i, CenterLoc: integer; 7992 begin 7993 CenterLoc := (xw + MapWidth div (xxt * 4)) mod G.lx + 7994 (yw + MapHeight div (yyt * 2)) * G.lx; 7995 IsoEngine.ApplyTileSize(x, y); 7996 FormResize(nil); 7997 Centre(CenterLoc); 7998 PaintAllMaps; 7999 for i := 0 to Screen.FormCount - 1 do 8000 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 8001 then 8002 TBufferedDrawDlg(Screen.Forms[i]).SmartUpdateContent(false); 8003 end; 8004 8005 procedure TMainScreen.SaveSettings; 8006 var 8007 i, j: integer; 8008 Reg: TRegistry; 8009 begin 8010 OptionChecked := OptionChecked and soExtraMask; 8011 for i := 0 to ComponentCount - 1 do 8012 if Components[i] is TMenuItem then 8013 for j := 0 to nSaveOption - 1 do 8014 if TMenuItem(Components[i]).Checked and 8015 (TMenuItem(Components[i]).Tag = SaveOption[j]) then 8016 inc(OptionChecked, 1 shl j); 8017 8018 Reg := TRegistry.Create; 8019 Reg.OpenKey('SOFTWARE\cevo\RegVer9', true); 8020 Reg.WriteInteger('TileWidth', xxt * 2); 8021 Reg.WriteInteger('TileHeight', yyt * 2); 8022 Reg.WriteInteger('OptionChecked', OptionChecked); 8023 Reg.WriteInteger('MapOptionChecked', MapOptionChecked); 8024 Reg.WriteInteger('CityReport', integer(CityRepMask)); 8025 Reg.closekey; 8026 Reg.free; 8027 end; 8028 8029 procedure TMainScreen.MovieSpeedBtnClick(Sender: TObject); 8030 begin 8031 MovieSpeed := TButtonB(Sender).Tag shr 8; 8032 CheckMovieSpeedBtnState; 8033 end; 6882 8034 6883 8035 initialization 8036 6884 8037 QueryPerformanceFrequency(PerfFreq); 6885 8038 6886 8039 end. 6887
Note:
See TracChangeset
for help on using the changeset viewer.