- Timestamp:
- Jan 8, 2017, 11:42:00 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/IPQ.pas
r17 r33 1 { binary heap priority queue2 code contributed by Rassim Eminli}1 { binary heap priority queue 2 code contributed by Rassim Eminli } 3 3 4 4 {$INCLUDE Switches.pas} 5 6 5 unit IPQ; 7 6 … … 10 9 type 11 10 12 TIntegerArray = array[0..$40000000 div sizeof(integer)] of integer;13 PIntegerArray = ^TIntegerArray;11 TIntegerArray = array [0 .. $40000000 div sizeof(integer)] of integer; 12 PIntegerArray = ^TIntegerArray; 14 13 15 TheapItem = record 16 Item: integer; 17 Value: integer; 18 end; 19 20 TItemArray = array[0..$40000000 div sizeof(TheapItem)] of TheapItem; 21 PItemArray = ^TItemArray; 22 23 TIPQ = class 24 constructor Create(max: integer); 25 destructor Destroy; override; 26 procedure Empty; 27 function Put(Item, Value: integer): boolean; 28 function TestPut(Item, Value: integer): boolean; 29 function Get(var Item, Value: integer): boolean; 30 private 31 // n - is the size of the heap. 32 // fmax - is the max size of the heap. 33 n, fmax: integer; 34 35 // bh - stores (Value, Item) pairs of the heap. 36 // Ix - stores the positions of pairs in the heap bh. 37 bh: PItemArray; 38 Ix: PIntegerArray; 14 TheapItem = record 15 Item: integer; 16 Value: integer; 39 17 end; 40 18 19 TItemArray = array [0 .. $40000000 div sizeof(TheapItem)] of TheapItem; 20 PItemArray = ^TItemArray; 21 22 TIPQ = class 23 constructor Create(max: integer); 24 destructor Destroy; override; 25 procedure Empty; 26 function Put(Item, Value: integer): boolean; 27 function TestPut(Item, Value: integer): boolean; 28 function Get(var Item, Value: integer): boolean; 29 private 30 // n - is the size of the heap. 31 // fmax - is the max size of the heap. 32 n, fmax: integer; 33 34 // bh - stores (Value, Item) pairs of the heap. 35 // Ix - stores the positions of pairs in the heap bh. 36 bh: PItemArray; 37 Ix: PIntegerArray; 38 end; 41 39 42 40 implementation … … 44 42 constructor TIPQ.Create(max: integer); 45 43 begin 46 47 48 GetMem(bh, fmax*SizeOf(TheapItem));49 GetMem(Ix, fmax*SizeOf(integer));50 n:=-1;51 44 inherited Create; 45 fmax := max; 46 GetMem(bh, fmax * sizeof(TheapItem)); 47 GetMem(Ix, fmax * sizeof(integer)); 48 n := -1; 49 Empty 52 50 end; 53 51 54 52 destructor TIPQ.Destroy; 55 53 begin 56 57 58 54 FreeMem(bh); 55 FreeMem(Ix); 56 inherited Destroy; 59 57 end; 60 58 61 59 procedure TIPQ.Empty; 62 60 begin 63 64 65 FillChar(Ix^, fmax*sizeOf(integer), 255);66 67 61 if n <> 0 then 62 begin 63 FillChar(Ix^, fmax * sizeof(integer), 255); 64 n := 0; 65 end; 68 66 end; 69 67 70 // Parent(i) = (i-1)/2.71 function TIPQ.Put(Item, Value: integer): boolean; // O(lg(n))68 // Parent(i) = (i-1)/2. 69 function TIPQ.Put(Item, Value: integer): boolean; // O(lg(n)) 72 70 var 73 i, j:integer;74 lbh:PItemArray;75 lIx:PIntegerArray;71 i, j: integer; 72 lbh: PItemArray; 73 lIx: PIntegerArray; 76 74 begin 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 75 lIx := Ix; 76 lbh := bh; 77 i := lIx[Item]; 78 if i >= 0 then 79 begin 80 if lbh[i].Value <= Value then 81 begin 82 result := False; 83 exit; 84 end; 85 end 86 else 87 begin 88 i := n; 89 Inc(n); 90 end; 93 91 94 while i > 0 do 95 begin 96 j := (i-1) shr 1; //Parent(i) = (i-1)/2 97 if Value >= lbh[j].Value then break; 98 lbh[i] := lbh[j]; 99 lIx[lbh[i].Item] := i; 100 i := j; 101 end; 102 // Insert the new Item at the insertion point found. 103 lbh[i].Value := Value; 104 lbh[i].Item := Item; 105 lIx[lbh[i].Item] := i; 106 result := True; 92 while i > 0 do 93 begin 94 j := (i - 1) shr 1; // Parent(i) = (i-1)/2 95 if Value >= lbh[j].Value then 96 break; 97 lbh[i] := lbh[j]; 98 lIx[lbh[i].Item] := i; 99 i := j; 100 end; 101 // Insert the new Item at the insertion point found. 102 lbh[i].Value := Value; 103 lbh[i].Item := Item; 104 lIx[lbh[i].Item] := i; 105 result := True; 107 106 end; 108 107 109 108 function TIPQ.TestPut(Item, Value: integer): boolean; 110 109 var 111 110 i: integer; 112 111 begin 113 114 112 i := Ix[Item]; 113 result := (i < 0) or (bh[i].Value > Value); 115 114 end; 116 115 117 // Left(i) = 2*i+1.118 // Right(i) = 2*i+2 => Left(i)+1119 function TIPQ.Get(var Item, Value: integer): boolean; // O(lg(n))116 // Left(i) = 2*i+1. 117 // Right(i) = 2*i+2 => Left(i)+1 118 function TIPQ.Get(var Item, Value: integer): boolean; // O(lg(n)) 120 119 var 121 i, j:integer;122 last:TheapItem;123 lbh:PItemArray;120 i, j: integer; 121 last: TheapItem; 122 lbh: PItemArray; 124 123 begin 125 126 127 128 129 124 if n = 0 then 125 begin 126 result := False; 127 exit; 128 end; 130 129 131 132 133 130 lbh := bh; 131 Item := lbh[0].Item; 132 Value := lbh[0].Value; 134 133 135 134 Ix[Item] := -1; 136 135 137 dec(n); 138 if n > 0 then 139 begin 140 last := lbh[n]; 141 i := 0; j := 1; 142 while j < n do 143 begin 144 // Right(i) = Left(i)+1 145 if(j < n-1) and (lbh[j].Value > lbh[j + 1].Value)then 146 inc(j); 147 if last.Value <= lbh[j].Value then break; 136 dec(n); 137 if n > 0 then 138 begin 139 last := lbh[n]; 140 i := 0; 141 j := 1; 142 while j < n do 143 begin 144 // Right(i) = Left(i)+1 145 if (j < n - 1) and (lbh[j].Value > lbh[j + 1].Value) then 146 Inc(j); 147 if last.Value <= lbh[j].Value then 148 break; 148 149 149 150 151 152 j := j shl 1+1; //Left(j) = 2*j+1153 150 lbh[i] := lbh[j]; 151 Ix[lbh[i].Item] := i; 152 i := j; 153 j := j shl 1 + 1; // Left(j) = 2*j+1 154 end; 154 155 155 156 157 158 159 156 // Insert the root in the correct place in the heap. 157 lbh[i] := last; 158 Ix[last.Item] := i; 159 end; 160 result := True 160 161 end; 161 162 162 163 end. 163 -
trunk/Integrated.lpi
r32 r33 214 214 <Filename Value="Direct.pas"/> 215 215 <IsPartOfProject Value="True"/> 216 <HasResources Value="True"/> 216 <ComponentName Value="DirectDlg"/> 217 <HasResources Value="True"/> 218 <ResourceBaseClass Value="Form"/> 217 219 </Unit9> 218 220 <Unit10> … … 395 397 <Filename Value="LocalPlayer\TechTree.pas"/> 396 398 <IsPartOfProject Value="True"/> 397 <HasResources Value="True"/> 399 <ComponentName Value="TechTreeDlg"/> 400 <HasResources Value="True"/> 401 <ResourceBaseClass Value="Form"/> 398 402 </Unit40> 399 403 <Unit41> -
trunk/LocalPlayer/IsoEngine.pas
r28 r33 360 360 if Border then 361 361 inc(TSpriteSize[i].Left); 362 until not Border or 363 (TSpriteSize[i].Left = xxt * 2 - 1); 362 until not Border or (TSpriteSize[i].Left = xxt * 2 - 1); 364 363 TSpriteSize[i].Top := 0; 365 364 repeat … … 371 370 if Border then 372 371 inc(TSpriteSize[i].Top); 373 until not Border or 374 (TSpriteSize[i].Top = yyt * 3 - 1); 372 until not Border or (TSpriteSize[i].Top = yyt * 3 - 1); 375 373 TSpriteSize[i].Right := xxt * 2; 376 374 repeat … … 382 380 if Border then 383 381 dec(TSpriteSize[i].Right); 384 until not Border or 385 (TSpriteSize[i].Right = TSpriteSize[i].Left); 382 until not Border or (TSpriteSize[i].Right = TSpriteSize[i].Left); 386 383 TSpriteSize[i].Bottom := yyt * 3; 387 384 repeat 388 385 Border := true; 389 386 for x := 0 to xxt * 2 - 1 do 390 if MaskLine[TSpriteSize[i].Bottom - 1]^ 391 [1 + xSrc * (xxt * 2 + 1) + x,0] = 0 then392 387 if MaskLine[TSpriteSize[i].Bottom - 1]^[1 + xSrc * (xxt * 2 + 1) + x, 388 0] = 0 then 389 Border := false; 393 390 if Border then 394 391 dec(TSpriteSize[i].Bottom); 395 until not Border or 396 (TSpriteSize[i].Bottom = TSpriteSize[i].Top); 392 until not Border or (TSpriteSize[i].Bottom = TSpriteSize[i].Top); 397 393 end 398 394 end; … … 409 405 end; 410 406 411 procedure Done; 407 procedure Done; 408 begin 409 NoMap.Free; 410 NoMap := nil; 411 LandPatch.Free; 412 LandPatch := nil; 413 OceanPatch.Free; 414 OceanPatch := nil; 415 Borders.Free; 416 Borders := nil; 417 end; 418 419 procedure Reset; 420 begin 421 BordersOK := 0; 422 end; 423 424 constructor TIsoMap.Create; 425 begin 426 inherited; 427 FLeft := 0; 428 FTop := 0; 429 FRight := 0; 430 FBottom := 0; 431 AttLoc := -1; 432 DefLoc := -1; 433 FAdviceLoc := -1; 434 end; 435 436 procedure TIsoMap.SetOutput(Output: TBitmap); 437 begin 438 FOutput := Output; 439 FLeft := 0; 440 FTop := 0; 441 FRight := FOutput.Width; 442 FBottom := FOutput.Height; 443 end; 444 445 procedure TIsoMap.SetPaintBounds(Left, Top, Right, Bottom: integer); 446 begin 447 FLeft := Left; 448 FTop := Top; 449 FRight := Right; 450 FBottom := Bottom; 451 end; 452 453 procedure TIsoMap.FillRect(x, y, Width, Height, Color: integer); 454 begin 455 if x < FLeft then 456 begin 457 Width := Width - (FLeft - x); 458 x := FLeft 459 end; 460 if y < FTop then 461 begin 462 Height := Height - (FTop - y); 463 y := FTop 464 end; 465 if x + Width >= FRight then 466 Width := FRight - x; 467 if y + Height >= FBottom then 468 Height := FBottom - y; 469 if (Width <= 0) or (Height <= 0) then 470 exit; 471 472 with FOutput.Canvas do 473 begin 474 Brush.Color := Color; 475 FillRect(Rect(x, y, x + Width, y + Height)); 476 Brush.Style := bsClear; 477 end 478 end; 479 480 procedure TIsoMap.Textout(x, y, Color: integer; const s: string); 481 begin 482 FOutput.Canvas.Font.Color := Color; 483 FOutput.Canvas.TextRect(Rect(FLeft, FTop, FRight, FBottom), x, y, s) 484 end; 485 486 procedure TIsoMap.BitBlt(Src: TBitmap; x, y, Width, Height, xSrc, ySrc, 487 Rop: integer); 488 begin 489 if x < FLeft then 490 begin 491 Width := Width - (FLeft - x); 492 xSrc := xSrc + (FLeft - x); 493 x := FLeft 494 end; 495 if y < FTop then 496 begin 497 Height := Height - (FTop - y); 498 ySrc := ySrc + (FTop - y); 499 y := FTop 500 end; 501 if x + Width >= FRight then 502 Width := FRight - x; 503 if y + Height >= FBottom then 504 Height := FBottom - y; 505 if (Width <= 0) or (Height <= 0) then 506 exit; 507 508 LCLIntf.BitBlt(FOutput.Canvas.Handle, x, y, Width, Height, Src.Canvas.Handle, 509 xSrc, ySrc, Rop); 510 end; 511 512 procedure TIsoMap.Sprite(HGr, xDst, yDst, Width, Height, xGr, yGr: integer); 513 begin 514 BitBlt(GrExt[HGr].Mask, xDst, yDst, Width, Height, xGr, yGr, SRCAND); 515 BitBlt(GrExt[HGr].Data, xDst, yDst, Width, Height, xGr, yGr, SRCPAINT); 516 end; 517 518 procedure TIsoMap.TSprite(xDst, yDst, grix: integer; 519 PureBlack: boolean = false); 520 var 521 Width, Height, xSrc, ySrc: integer; 522 begin 523 Width := TSpriteSize[grix].Right - TSpriteSize[grix].Left; 524 Height := TSpriteSize[grix].Bottom - TSpriteSize[grix].Top; 525 xSrc := 1 + grix mod 9 * (xxt * 2 + 1) + TSpriteSize[grix].Left; 526 ySrc := 1 + grix div 9 * (yyt * 3 + 1) + TSpriteSize[grix].Top; 527 xDst := xDst + TSpriteSize[grix].Left; 528 yDst := yDst - yyt + TSpriteSize[grix].Top; 529 if xDst < FLeft then 530 begin 531 Width := Width - (FLeft - xDst); 532 xSrc := xSrc + (FLeft - xDst); 533 xDst := FLeft 534 end; 535 if yDst < FTop then 536 begin 537 Height := Height - (FTop - yDst); 538 ySrc := ySrc + (FTop - yDst); 539 yDst := FTop 540 end; 541 if xDst + Width >= FRight then 542 Width := FRight - xDst; 543 if yDst + Height >= FBottom then 544 Height := FBottom - yDst; 545 if (Width <= 0) or (Height <= 0) then 546 exit; 547 548 LCLIntf.BitBlt(OutDC, xDst, yDst, Width, Height, MaskDC, xSrc, ySrc, SRCAND); 549 if not PureBlack then 550 LCLIntf.BitBlt(OutDC, xDst, yDst, Width, Height, DataDC, xSrc, ySrc, 551 SRCPAINT); 552 end; 553 554 procedure TIsoMap.PaintUnit(x, y: integer; const UnitInfo: TUnitInfo; 555 Status: integer); 556 var 557 xsh, ysh, xGr, yGr, j, mixShow: integer; 558 begin 559 with UnitInfo do 560 if (Owner = me) or (emix <> $FFFF) then 561 begin 562 if Job = jCity then 563 mixShow := -1 // building site 564 else 565 mixShow := mix; 566 if (Tribe[Owner].ModelPicture[mixShow].HGr = 0) and 567 (@OnInitEnemyModel <> nil) then 568 if not OnInitEnemyModel(emix) then 569 exit; 570 xsh := Tribe[Owner].ModelPicture[mixShow].xShield; 571 ysh := Tribe[Owner].ModelPicture[mixShow].yShield; 572 {$IFNDEF SCR} if Status and usStay <> 0 then 573 j := 19 574 else if Status and usRecover <> 0 then 575 j := 16 576 else if Status and (usGoto or usEnhance) = usGoto or usEnhance then 577 j := 18 578 else if Status and usEnhance <> 0 then 579 j := 17 580 else if Status and usGoto <> 0 then 581 j := 20 582 else {$ENDIF} if Job = jCity then 583 j := jNone 584 else 585 j := Job; 586 if Flags and unMulti <> 0 then 587 Sprite(Tribe[Owner].symHGr, x + xsh - 1 + 4, y + ysh - 2, 14, 12, 588 33 + Tribe[Owner].sympix mod 10 * 65, 589 1 + Tribe[Owner].sympix div 10 * 49); 590 Sprite(Tribe[Owner].symHGr, x + xsh - 1, y + ysh - 2, 14, 12, 591 18 + Tribe[Owner].sympix mod 10 * 65, 592 1 + Tribe[Owner].sympix div 10 * 49); 593 FillRect(x + xsh, y + ysh + 5, 1 + Health * 11 div 100, 3, 594 ColorOfHealth(Health)); 595 if j > 0 then 596 begin 597 xGr := 121 + j mod 7 * 9; 598 yGr := 1 + j div 7 * 9; 599 BitBlt(GrExt[HGrSystem].Mask, x + xsh + 3, y + ysh + 9, 8, 8, xGr, 600 yGr, SRCAND); 601 Sprite(HGrSystem, x + xsh + 2, y + ysh + 8, 8, 8, xGr, yGr); 602 end; 603 with Tribe[Owner].ModelPicture[mixShow] do 604 Sprite(HGr, x, y, 64, 48, pix mod 10 * 65 + 1, pix div 10 * 49 + 1); 605 if Flags and unFortified <> 0 then 606 begin 607 { OutDC:=FOutput.Canvas.Handle; 608 DataDC:=GrExt[HGrTerrain].Data.Canvas.Handle; 609 MaskDC:=GrExt[HGrTerrain].Mask.Canvas.Handle; 610 TSprite(x,y+16,12*9+7); } 611 Sprite(HGrStdUnits, x, y, xxu * 2, yyu * 2, 1 + 6 * (xxu * 2 + 1), 1); 612 end 613 end 614 end; { PaintUnit } 615 616 procedure TIsoMap.PaintCity(x, y: integer; const CityInfo: TCityInfo; 617 accessory: boolean); 618 var 619 age, cHGr, cpix, xGr, xShield, yShield, LabelTextColor, LabelLength: integer; 620 cpic: TCityPicture; 621 s: string; 622 begin 623 age := GetAge(CityInfo.Owner); 624 if CityInfo.size < 5 then 625 xGr := 0 626 else if CityInfo.size < 9 then 627 xGr := 1 628 else if CityInfo.size < 13 then 629 xGr := 2 630 else 631 xGr := 3; 632 Tribe[CityInfo.Owner].InitAge(age); 633 if age < 2 then 634 begin 635 cHGr := Tribe[CityInfo.Owner].cHGr; 636 cpix := Tribe[CityInfo.Owner].cpix; 637 if (ciWalled and CityInfo.Flags = 0) or 638 (GrExt[cHGr].Data.Canvas.Pixels[(xGr + 4) * 65, cpix * 49 + 48] = $00FFFF) 639 then 640 Sprite(cHGr, x - xxc, y - 2 * yyc, xxc * 2, yyc * 3, 641 xGr * (xxc * 2 + 1) + 1, 1 + cpix * (yyc * 3 + 1)); 642 if ciWalled and CityInfo.Flags <> 0 then 643 Sprite(cHGr, x - xxc, y - 2 * yyc, xxc * 2, yyc * 3, 644 (xGr + 4) * (xxc * 2 + 1) + 1, 1 + cpix * (yyc * 3 + 1)); 645 end 646 else 647 begin 648 if ciWalled and CityInfo.Flags <> 0 then 649 Sprite(HGrCities, x - xxt, y - 2 * yyt, 2 * xxt, 3 * yyt, 650 (xGr + 4) * (2 * xxt + 1) + 1, 1 + (age - 2) * (3 * yyt + 1)) 651 else 652 Sprite(HGrCities, x - xxt, y - 2 * yyt, 2 * xxt, 3 * yyt, 653 xGr * (2 * xxt + 1) + 1, 1 + (age - 2) * (3 * yyt + 1)); 654 end; 655 656 if not accessory then 657 exit; 658 659 { if ciCapital and CityInfo.Flags<>0 then 660 Sprite(Tribe[CityInfo.Owner].symHGr,x+cpic.xf,y-13+cpic.yf,13,14, 661 1+Tribe[CityInfo.Owner].sympix mod 10 *65, 662 1+Tribe[CityInfo.Owner].sympix div 10 *49); {capital -- paint flag } 663 664 if MyMap[CityInfo.Loc] and fObserved <> 0 then 665 begin 666 if age < 2 then 667 begin 668 cpic := Tribe[CityInfo.Owner].CityPicture[xGr]; 669 xShield := x - xxc + cpic.xShield; 670 yShield := y - 2 * yyc + cpic.yShield; 671 end 672 else 673 begin 674 cpic := CitiesPictures[age, xGr]; 675 xShield := x - xxt + cpic.xShield; 676 yShield := y - 2 * yyt + cpic.yShield; 677 end; 678 s := IntToStr(CityInfo.size); 679 LabelLength := FOutput.Canvas.TextWidth(s); 680 FillRect(xShield, yShield, LabelLength + 4, 16, $000000); 681 if MyMap[CityInfo.Loc] and (fUnit or fObserved) = fObserved then 682 // empty city 683 LabelTextColor := Tribe[CityInfo.Owner].Color 684 else 685 begin 686 FillRect(xShield + 1, yShield + 1, LabelLength + 2, 14, 687 Tribe[CityInfo.Owner].Color); 688 LabelTextColor := $000000; 689 end; 690 Textout(xShield + 2, yShield - 1, LabelTextColor, s); 691 end 692 end; { PaintCity } 693 694 function PoleTile(Loc: integer): integer; 695 begin { virtual pole tile } 696 result := fUNKNOWN; 697 if Loc < -2 * G.lx then 698 else if Loc < -G.lx then 699 begin 700 if (MyMap[dLoc(Loc, 0, 2)] and fTerrain <> fUNKNOWN) and 701 (MyMap[dLoc(Loc, -2, 2)] and fTerrain <> fUNKNOWN) and 702 (MyMap[dLoc(Loc, 2, 2)] and fTerrain <> fUNKNOWN) then 703 result := fArctic; 704 if (MyMap[dLoc(Loc, 0, 2)] and fObserved <> 0) and 705 (MyMap[dLoc(Loc, -2, 2)] and fObserved <> 0) and 706 (MyMap[dLoc(Loc, 2, 2)] and fObserved <> 0) then 707 result := result or fObserved 708 end 709 else if Loc < 0 then 710 begin 711 if (MyMap[dLoc(Loc, -1, 1)] and fTerrain <> fUNKNOWN) and 712 (MyMap[dLoc(Loc, 1, 1)] and fTerrain <> fUNKNOWN) then 713 result := fArctic; 714 if (MyMap[dLoc(Loc, -1, 1)] and fObserved <> 0) and 715 (MyMap[dLoc(Loc, 1, 1)] and fObserved <> 0) then 716 result := result or fObserved 717 end 718 else if Loc < G.lx * (G.ly + 1) then 719 begin 720 if (MyMap[dLoc(Loc, -1, -1)] and fTerrain <> fUNKNOWN) and 721 (MyMap[dLoc(Loc, 1, -1)] and fTerrain <> fUNKNOWN) then 722 result := fArctic; 723 if (MyMap[dLoc(Loc, -1, -1)] and fObserved <> 0) and 724 (MyMap[dLoc(Loc, 1, -1)] and fObserved <> 0) then 725 result := result or fObserved 726 end 727 else if Loc < G.lx * (G.ly + 2) then 728 begin 729 if (MyMap[dLoc(Loc, 0, -2)] and fTerrain <> fUNKNOWN) and 730 (MyMap[dLoc(Loc, -2, -2)] and fTerrain <> fUNKNOWN) and 731 (MyMap[dLoc(Loc, 2, -2)] and fTerrain <> fUNKNOWN) then 732 result := fArctic; 733 if (MyMap[dLoc(Loc, 0, -2)] and fObserved <> 0) and 734 (MyMap[dLoc(Loc, -2, -2)] and fObserved <> 0) and 735 (MyMap[dLoc(Loc, 2, -2)] and fObserved <> 0) then 736 result := result or fObserved 737 end 738 end; 739 740 const 741 Dirx: array [0 .. 7] of integer = (1, 2, 1, 0, -1, -2, -1, 0); 742 Diry: array [0 .. 7] of integer = (-1, 0, 1, 2, 1, 0, -1, -2); 743 744 function TIsoMap.Connection4(Loc, Mask, Value: integer): integer; 745 begin 746 result := 0; 747 if dLoc(Loc, 1, -1) >= 0 then 748 begin 749 if MyMap[dLoc(Loc, 1, -1)] and Mask = Cardinal(Value) then 750 inc(result, 1); 751 if MyMap[dLoc(Loc, -1, -1)] and Mask = Cardinal(Value) then 752 inc(result, 8); 753 end; 754 if dLoc(Loc, 1, 1) < G.lx * G.ly then 755 begin 756 if MyMap[dLoc(Loc, 1, 1)] and Mask = Cardinal(Value) then 757 inc(result, 2); 758 if MyMap[dLoc(Loc, -1, 1)] and Mask = Cardinal(Value) then 759 inc(result, 4); 760 end 761 end; 762 763 function TIsoMap.Connection8(Loc, Mask: integer): integer; 764 var 765 Dir, ConnLoc: integer; 766 begin 767 result := 0; 768 for Dir := 0 to 7 do 769 begin 770 ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]); 771 if (ConnLoc >= 0) and (ConnLoc < G.lx * G.ly) and 772 (MyMap[ConnLoc] and Mask <> 0) then 773 inc(result, 1 shl Dir); 774 end 775 end; 776 777 function TIsoMap.OceanConnection(Loc: integer): integer; 778 var 779 Dir, ConnLoc: integer; 780 begin 781 result := 0; 782 for Dir := 0 to 7 do 783 begin 784 ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]); 785 if (ConnLoc < 0) or (ConnLoc >= G.lx * G.ly) or 786 ((MyMap[ConnLoc] - 2) and fTerrain < 13) then 787 inc(result, 1 shl Dir); 788 end 789 end; 790 791 procedure TIsoMap.PaintShore(x, y, Loc: integer); 792 var 793 Conn, Tile: integer; 794 begin 795 if (y <= FTop - yyt * 2) or (y > FBottom) or (x <= FLeft - xxt * 2) or 796 (x > FRight) then 797 exit; 798 if (Loc < 0) or (Loc >= G.lx * G.ly) then 799 exit; 800 Tile := MyMap[Loc]; 801 if Tile and fTerrain >= fGrass then 802 exit; 803 Conn := OceanConnection(Loc); 804 if Conn = 0 then 805 exit; 806 807 BitBlt(GrExt[HGrTerrain].Data, x + xxt div 2, y, xxt, yyt, 808 1 + (Conn shr 6 + Conn and 1 shl 2) * (xxt * 2 + 1), 809 1 + yyt + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT); 810 BitBlt(GrExt[HGrTerrain].Data, x + xxt, y + yyt div 2, xxt, yyt, 811 1 + (Conn and 7) * (xxt * 2 + 1) + xxt, 812 1 + yyt * 2 + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT); 813 BitBlt(GrExt[HGrTerrain].Data, x + xxt div 2, y + yyt, xxt, yyt, 814 1 + (Conn shr 2 and 7) * (xxt * 2 + 1) + xxt, 815 1 + yyt + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT); 816 BitBlt(GrExt[HGrTerrain].Data, x, y + yyt div 2, xxt, yyt, 817 1 + (Conn shr 4 and 7) * (xxt * 2 + 1), 818 1 + yyt * 2 + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT); 819 Conn := Connection4(Loc, fTerrain, fUNKNOWN); { dither to black } 820 if Conn and 1 <> 0 then 821 BitBlt(GrExt[HGrTerrain].Mask, x + xxt, y, xxt, yyt, 1 + 7 * (xxt * 2 + 1) + 822 xxt, 1 + yyt + 15 * (yyt * 3 + 1), SRCAND); 823 if Conn and 2 <> 0 then 824 BitBlt(GrExt[HGrTerrain].Mask, x + xxt, y + yyt, xxt, yyt, 825 1 + 7 * (xxt * 2 + 1) + xxt, 1 + yyt * 2 + 15 * (yyt * 3 + 1), SRCAND); 826 if Conn and 4 <> 0 then 827 BitBlt(GrExt[HGrTerrain].Mask, x, y + yyt, xxt, yyt, 1 + 7 * (xxt * 2 + 1), 828 1 + yyt * 2 + 15 * (yyt * 3 + 1), SRCAND); 829 if Conn and 8 <> 0 then 830 BitBlt(GrExt[HGrTerrain].Mask, x, y, xxt, yyt, 1 + 7 * (xxt * 2 + 1), 831 1 + yyt + 15 * (yyt * 3 + 1), SRCAND); 832 end; 833 834 procedure TIsoMap.PaintTileExtraTerrain(x, y, Loc: integer); 835 var 836 Dir, Conn, RRConn, yGr, Tile, yLoc: integer; 837 begin 838 if (Loc < 0) or (Loc >= G.lx * G.ly) or (y <= -yyt * 2) or 839 (y > FOutput.Height) or (x <= -xxt * 2) or (x > FOutput.Width) then 840 exit; 841 Tile := MyMap[Loc]; 842 if Tile and fTerrain = fForest then 843 begin 844 yLoc := Loc div G.lx; 845 if IsJungle(yLoc) then 846 yGr := 18 847 else 848 yGr := 3; 849 Conn := Connection4(Loc, fTerrain, Tile and fTerrain); 850 if (yLoc = (G.ly - 2) div 4) or (G.ly - 1 - yLoc = (G.ly + 2) div 4) then 851 Conn := Conn and not 6 // no connection to south 852 else if (yLoc = (G.ly + 2) div 4) or (G.ly - 1 - yLoc = (G.ly - 2) div 4) 853 then 854 Conn := Conn and not 9; // no connection to north 855 TSprite(x, y, Conn mod 8 + (yGr + Conn div 8) * 9); 856 end 857 else if Tile and fTerrain in [fHills, fMountains, fForest] then 858 begin 859 yGr := 3 + 2 * (Tile and fTerrain - fForest); 860 Conn := Connection4(Loc, fTerrain, Tile and fTerrain); 861 TSprite(x, y, Conn mod 8 + (yGr + Conn div 8) * 9); 862 end 863 else if Tile and fDeadLands <> 0 then 864 TSprite(x, y, 2 * 9 + 6); 865 866 if ShowObjects then 867 begin 868 if Tile and fTerImp = tiFarm then 869 TSprite(x, y, 109) { farmland } 870 else if Tile and fTerImp = tiIrrigation then 871 TSprite(x, y, 108); // irrigation 872 end; 873 if Tile and fRiver <> 0 then 874 begin 875 Conn := Connection4(Loc, fRiver, fRiver) or 876 Connection4(Loc, fTerrain, fShore) or Connection4(Loc, fTerrain, 877 fUNKNOWN); 878 TSprite(x, y, Conn mod 8 + (13 + Conn div 8) * 9); 879 end; 880 881 if Tile and fTerrain < fGrass then 882 begin 883 Conn := Connection4(Loc, fRiver, fRiver); 884 for Dir := 0 to 3 do 885 if Conn and (1 shl Dir) <> 0 then { river mouths } 886 TSprite(x, y, 15 * 9 + Dir); 887 if ShowObjects then 888 begin 889 Conn := Connection8(Loc, fCanal); 890 for Dir := 0 to 7 do 891 if Conn and (1 shl Dir) <> 0 then { canal mouths } 892 TSprite(x, y, 20 * 9 + 1 + Dir); 893 end 894 end; 895 896 if ShowObjects then 897 begin 898 if (Tile and fCanal <> 0) or (Tile and fCity <> 0) then 899 begin // paint canal connections 900 Conn := Connection8(Loc, fCanal or fCity); 901 if Tile and fCanal <> 0 then 902 Conn := Conn or ($FF - OceanConnection(Loc)); 903 if Conn = 0 then 904 begin 905 if Tile and fCanal <> 0 then 906 TSprite(x, y, 99) 907 end 908 else 909 for Dir := 0 to 7 do 910 if (1 shl Dir) and Conn <> 0 then 911 TSprite(x, y, 100 + Dir); 912 end; 913 if Tile and (fRR or fCity) <> 0 then 914 RRConn := Connection8(Loc, fRR or fCity) 915 else 916 RRConn := 0; 917 if Tile and (fRoad or fRR or fCity) <> 0 then 918 begin // paint road connections 919 Conn := Connection8(Loc, fRoad or fRR or fCity) and not RRConn; 920 if (Conn = 0) and (Tile and (fRR or fCity) = 0) then 921 TSprite(x, y, 81) 922 else if Conn > 0 then 923 for Dir := 0 to 7 do 924 if (1 shl Dir) and Conn <> 0 then 925 TSprite(x, y, 82 + Dir); 926 end; 927 // paint railroad connections 928 if (Tile and fRR <> 0) and (RRConn = 0) then 929 TSprite(x, y, 90) 930 else if RRConn > 0 then 931 for Dir := 0 to 7 do 932 if (1 shl Dir) and RRConn <> 0 then 933 TSprite(x, y, 91 + Dir); 934 end; 935 end; 936 937 // (x,y) is top left pixel of (2*xxt,3*yyt) rectangle 938 procedure TIsoMap.PaintTileObjects(x, y, Loc, CityLoc, CityOwner: integer; 939 UseBlink: boolean); 940 type 941 TLine = array [0 .. 9 * 65, 0 .. 2] of Byte; 942 var 943 p1, p2, uix, cix, dy, Loc1, Tile, Multi, Destination: integer; 944 CityInfo: TCityInfo; 945 UnitInfo: TUnitInfo; 946 fog: boolean; 947 948 procedure NameCity; 949 var 950 cix, xs, w: integer; 951 BehindCityInfo: TCityInfo; 952 s: string; 953 IsCapital: boolean; 954 begin 955 BehindCityInfo.Loc := Loc - 2 * G.lx; 956 if ShowCityNames and (Options and (1 shl moEditMode) = 0) and 957 (BehindCityInfo.Loc >= 0) and (BehindCityInfo.Loc < G.lx * G.ly) and 958 (MyMap[BehindCityInfo.Loc] and fCity <> 0) then 959 begin 960 GetCityInfo(BehindCityInfo.Loc, cix, BehindCityInfo); 961 IsCapital := BehindCityInfo.Flags and ciCapital <> 0; 962 { if Showuix and (cix>=0) then s:=IntToStr(cix) 963 else } s := CityName(BehindCityInfo.ID); 964 w := FOutput.Canvas.TextWidth(s); 965 xs := x + xxt - (w + 1) div 2; 966 if IsCapital then 967 FOutput.Canvas.Font.Style := FOutput.Canvas.Font.Style + [fsUnderline]; 968 Textout(xs + 1, y - 9, $000000, s); 969 Textout(xs, y - 10, $FFFFFF, s); 970 if IsCapital then 971 FOutput.Canvas.Font.Style := FOutput.Canvas.Font.Style - [fsUnderline]; 972 end; 973 end; 974 975 procedure ShowSpacePort; 976 begin 977 if ShowObjects and (Options and (1 shl moEditMode) = 0) and 978 (Tile and fCity <> 0) and (CityInfo.Flags and ciSpacePort <> 0) then 979 TSprite(x + xxt, y - 6, 12 * 9 + 5); 980 end; 981 982 procedure PaintBorder; 983 var 984 dx, dy: integer; 985 Line: ^TLine; 986 begin 987 if ShowBorder and (Loc >= 0) and (Loc < G.lx * G.ly) and 988 (Tile and fTerrain <> fUNKNOWN) then 989 begin 990 p1 := MyRO.Territory[Loc]; 991 if (p1 >= 0) and (ShowMyBorder or (p1 <> me)) then 992 begin 993 if BordersOK and (1 shl p1) = 0 then 412 994 begin 413 NoMap.Free; 414 NoMap := nil; 415 LandPatch.Free; 416 LandPatch := nil; 417 OceanPatch.Free; 418 OceanPatch := nil; 419 Borders.Free; 420 Borders := nil; 995 LCLIntf.BitBlt(Borders.Canvas.Handle, 0, p1 * (yyt * 2), xxt * 2, 996 yyt * 2, GrExt[HGrTerrain].Data.Canvas.Handle, 997 1 + 8 * (xxt * 2 + 1), 1 + yyt + 16 * (yyt * 3 + 1), SRCCOPY); 998 Borders.BeginUpdate; 999 for dy := 0 to yyt * 2 - 1 do 1000 begin 1001 Line := Borders.ScanLine[p1 * (yyt * 2) + dy]; 1002 for dx := 0 to xxt * 2 - 1 do 1003 if Line[dx, 0] = 99 then 1004 begin 1005 Line[dx, 0] := Tribe[p1].Color shr 16 and $FF; 1006 Line[dx, 1] := Tribe[p1].Color shr 8 and $FF; 1007 Line[dx, 2] := Tribe[p1].Color and $FF; 1008 end 1009 end; 1010 Borders.EndUpdate; 1011 BordersOK := BordersOK or 1 shl p1; 421 1012 end; 422 423 procedure Reset; 1013 for dy := 0 to 1 do 1014 for dx := 0 to 1 do 1015 begin 1016 Loc1 := dLoc(Loc, dx * 2 - 1, dy * 2 - 1); 1017 begin 1018 if (Loc1 < 0) or (Loc1 >= G.lx * G.ly) then 1019 p2 := -1 1020 else if MyMap[Loc1] and fTerrain = fUNKNOWN then 1021 p2 := p1 1022 else 1023 p2 := MyRO.Territory[Loc1]; 1024 if p2 <> p1 then 1025 begin 1026 BitBlt(GrExt[HGrTerrain].Mask, x + dx * xxt, y + dy * yyt, xxt, 1027 yyt, 1 + 8 * (xxt * 2 + 1) + dx * xxt, 1028 1 + yyt + 16 * (yyt * 3 + 1) + dy * yyt, SRCAND); 1029 BitBlt(Borders, x + dx * xxt, y + dy * yyt, xxt, yyt, dx * xxt, 1030 p1 * (yyt * 2) + dy * yyt, SRCPAINT); 1031 end 1032 end; 1033 end 1034 end 1035 end; 1036 end; 1037 1038 begin 1039 if (Loc < 0) or (Loc >= G.lx * G.ly) then 1040 Tile := PoleTile(Loc) 1041 else 1042 Tile := MyMap[Loc]; 1043 if ShowObjects and (Options and (1 shl moEditMode) = 0) and 1044 (Tile and fCity <> 0) then 1045 GetCityInfo(Loc, cix, CityInfo); 1046 if (y <= FTop - yyt * 2) or (y > FBottom) or (x <= FLeft - xxt * 2) or 1047 (x > FRight) then 1048 begin 1049 NameCity; 1050 ShowSpacePort; 1051 exit; 1052 end; 1053 if Tile and fTerrain = fUNKNOWN then 1054 begin 1055 NameCity; 1056 ShowSpacePort; 1057 exit 1058 end; { square not discovered } 1059 1060 if not(FoW and (Tile and fObserved = 0)) then 1061 PaintBorder; 1062 1063 if (Loc >= 0) and (Loc < G.lx * G.ly) and (Loc = FAdviceLoc) then 1064 TSprite(x, y, 7 + 9 * 2); 1065 1066 if (Loc >= 0) and (Loc < G.lx * G.ly) and (Tile and fSpecial <> 0) 1067 then { special ressources } 1068 begin 1069 dy := Loc div G.lx; 1070 if Tile and fTerrain < fForest then 1071 TSprite(x, y, Tile and fTerrain + (Tile and fSpecial shr 5) * 9) 1072 else if (Tile and fTerrain = fForest) and IsJungle(dy) then 1073 TSprite(x, y, 8 + 17 * 9 + (Tile and fSpecial shr 5) * 9) 1074 else 1075 TSprite(x, y, 8 + 2 * 9 + ((Tile and fTerrain - fForest) * 2 + Tile and 1076 fSpecial shr 5) * 9); 1077 end; 1078 1079 if ShowObjects then 1080 begin 1081 if Tile and fTerImp = tiMine then 1082 TSprite(x, y, 2 + 9 * 12); 1083 if Tile and fTerImp = tiBase then 1084 TSprite(x, y, 4 + 9 * 12); 1085 if Tile and fPoll <> 0 then 1086 TSprite(x, y, 6 + 9 * 12); 1087 if Tile and fTerImp = tiFort then 1088 begin 1089 TSprite(x, y, 7 + 9 * 12); 1090 if Tile and fObserved = 0 then 1091 TSprite(x, y, 3 + 9 * 12); 1092 end; 1093 end; 1094 if Tile and fDeadLands <> 0 then 1095 TSprite(x, y, (12 + Tile shr 25 and 3) * 9 + 8); 1096 1097 if Options and (1 shl moEditMode) <> 0 then 1098 fog := (Loc < 0) or (Loc >= G.lx * G.ly) 1099 // else if CityLoc>=0 then 1100 // fog:= (Loc<0) or (Loc>=G.lx*G.ly) or (Distance(Loc,CityLoc)>5) 1101 else if ShowGrWall then 1102 fog := Tile and fGrWall = 0 1103 else 1104 fog := FoW and (Tile and fObserved = 0); 1105 if fog and ShowObjects then 1106 if Loc < -G.lx then 1107 Sprite(HGrTerrain, x, y + yyt, xxt * 2, yyt, 1 + 6 * (xxt * 2 + 1), 1108 1 + yyt * 2 + 15 * (yyt * 3 + 1)) 1109 else if Loc >= G.lx * (G.ly + 1) then 1110 Sprite(HGrTerrain, x, y, xxt * 2, yyt, 1 + 6 * (xxt * 2 + 1), 1111 1 + yyt + 15 * (yyt * 3 + 1)) 1112 else 1113 TSprite(x, y, 6 + 9 * 15, xxt <> 33); 1114 1115 if FoW and (Tile and fObserved = 0) then 1116 PaintBorder; 1117 1118 {$IFNDEF SCR} 1119 // paint goto destination mark 1120 if DestinationMarkON and (CityOwner < 0) and (UnFocus >= 0) and 1121 (MyUn[UnFocus].Status and usGoto <> 0) then 1122 begin 1123 Destination := MyUn[UnFocus].Status shr 16; 1124 if (Destination = Loc) and (Destination <> MyUn[UnFocus].Loc) then 1125 if not UseBlink or BlinkOn then 1126 TSprite(x, y, 8 + 9 * 1) 1127 else 1128 TSprite(x, y, 8 + 9 * 2) 1129 end; 1130 {$ENDIF} 1131 if Options and (1 shl moEditMode) <> 0 then 1132 begin 1133 if Tile and fPrefStartPos <> 0 then 1134 TSprite(x, y, 0 + 9 * 1) 1135 else if Tile and fStartPos <> 0 then 1136 TSprite(x, y, 0 + 9 * 2); 1137 end 1138 else if ShowObjects then 1139 begin 1140 { if (CityLoc<0) and (UnFocus>=0) and (Loc=MyUn[UnFocus].Loc) then 1141 if BlinkOn then TSprite(x,y,8+9*0) 1142 else TSprite(x,y,8+9*1); } 1143 1144 NameCity; 1145 ShowSpacePort; 1146 if Tile and fCity <> 0 then 1147 PaintCity(x + xxt, y + yyt, CityInfo, CityOwner < 0); 1148 1149 if (Tile and fUnit <> 0) and (Loc <> AttLoc) and 1150 ((Loc <> DefLoc) or (DefHealth <> 0)) 1151 {$IFNDEF SCR} and ((CityOwner >= 0) or (UnFocus < 0) or not UseBlink or 1152 BlinkOn or (Loc <> MyUn[UnFocus].Loc)){$ENDIF} 1153 and ((Tile and fCity <> fCity) or (Loc = DefLoc) 1154 {$IFNDEF SCR} or (not UseBlink or BlinkOn) and (UnFocus >= 0) and 1155 (Loc = MyUn[UnFocus].Loc){$ENDIF}) then 1156 begin { unit } 1157 GetUnitInfo(Loc, uix, UnitInfo); 1158 if (Loc = DefLoc) and (DefHealth >= 0) then 1159 UnitInfo.Health := DefHealth; 1160 if (UnitInfo.Owner <> CityOwner) and 1161 not((CityOwner = me) and (MyRO.Treaty[UnitInfo.Owner] = trAlliance)) 1162 then 1163 {$IFNDEF SCR} if (UnFocus >= 0) and (Loc = MyUn[UnFocus].Loc) then { active unit } 424 1164 begin 425 BordersOK := 0; 1165 Multi := UnitInfo.Flags and unMulti; 1166 MakeUnitInfo(me, MyUn[UnFocus], UnitInfo); 1167 UnitInfo.Flags := UnitInfo.Flags or Multi; 1168 PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo, 1169 MyUn[UnFocus].Status); 1170 end 1171 else if UnitInfo.Owner = me then 1172 begin 1173 if ClientMode = cMovieTurn then 1174 PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo, 0) 1175 // status is not set with precise timing during loading 1176 else 1177 PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo, 1178 MyUn[uix].Status); 1179 // if Showuix then Textout(x+16,y+5,$80FF00,IntToStr(uix)); 1180 end 1181 else {$ENDIF} PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo, 0); 1182 end 1183 else if Tile and fHiddenUnit <> 0 then 1184 Sprite(HGrStdUnits, x + (xxt - xxu), y + (yyt - yyu_anchor), xxu * 2, 1185 yyu * 2, 1 + 5 * (xxu * 2 + 1), 1) 1186 else if Tile and fStealthUnit <> 0 then 1187 Sprite(HGrStdUnits, x + (xxt - xxu), y + (yyt - yyu_anchor), xxu * 2, 1188 yyu * 2, 1 + 5 * (xxu * 2 + 1), 1 + 1 * (yyu * 2 + 1)) 1189 end; 1190 1191 if ShowObjects and (Tile and fTerImp = tiFort) and (Tile and fObserved <> 0) 1192 then 1193 TSprite(x, y, 3 + 9 * 12); 1194 1195 if (Loc >= 0) and (Loc < G.lx * G.ly) then 1196 if ShowLoc then 1197 Textout(x + xxt - 16, y + yyt - 9, $FFFF00, IntToStr(Loc)) 1198 else if ShowDebug and (DebugMap <> nil) and (Loc >= 0) and 1199 (Loc < G.lx * G.ly) and (DebugMap[Loc] <> 0) then 1200 Textout(x + xxt - 16, y + yyt - 9, $00E0FF, 1201 IntToStr(integer(DebugMap[Loc]))) 1202 end; { PaintTileObjects } 1203 1204 procedure TIsoMap.PaintGrid(x, y, nx, ny: integer); 1205 1206 procedure ClippedLine(dx0, dy0: integer; mirror: boolean); 1207 var 1208 x0, x1, dxmin, dymin, dxmax, dymax, n: integer; 1209 begin 1210 with FOutput.Canvas do 1211 begin 1212 dxmin := (FLeft - x) div xxt; 1213 dymin := (RealTop - y) div yyt; 1214 dxmax := (FRight - x - 1) div xxt + 1; 1215 dymax := (RealBottom - y - 1) div yyt + 1; 1216 n := dymax - dy0; 1217 if mirror then 1218 begin 1219 if dx0 - dxmin < n then 1220 n := dx0 - dxmin; 1221 if dx0 > dxmax then 1222 begin 1223 n := n - (dx0 - dxmax); 1224 dy0 := dy0 + (dx0 - dxmax); 1225 dx0 := dxmax 426 1226 end; 427 428 constructor TIsoMap.Create; 1227 if dy0 < dymin then 429 1228 begin 430 inherited; 431 FLeft := 0; 432 FTop := 0; 433 FRight := 0; 434 FBottom := 0; 435 AttLoc := -1; 436 DefLoc := -1; 437 FAdviceLoc := -1; 1229 n := n - (dymin - dy0); 1230 dx0 := dx0 - (dymin - dy0); 1231 dy0 := dymin 438 1232 end; 439 440 procedure TIsoMap.SetOutput(Output: TBitmap); 1233 end 1234 else 1235 begin 1236 if dxmax - dx0 < n then 1237 n := dxmax - dx0; 1238 if dx0 < dxmin then 441 1239 begin 442 FOutput := Output; 443 FLeft := 0; 444 FTop := 0; 445 FRight := FOutput.Width; 446 FBottom := FOutput.Height; 1240 n := n - (dxmin - dx0); 1241 dy0 := dy0 + (dxmin - dx0); 1242 dx0 := dxmin 447 1243 end; 448 449 procedure TIsoMap.SetPaintBounds(Left, Top, Right, Bottom: integer); 1244 if dy0 < dymin then 450 1245 begin 451 FLeft := Left; 452 FTop := Top; 453 FRight := Right; 454 FBottom := Bottom; 1246 n := n - (dymin - dy0); 1247 dx0 := dx0 + (dymin - dy0); 1248 dy0 := dymin 455 1249 end; 456 457 procedure TIsoMap.FillRect(x, y, Width, Height, Color: integer); 458 begin 459 if x < FLeft then 1250 end; 1251 if n <= 0 then 1252 exit; 1253 if mirror then 1254 begin 1255 x0 := x + dx0 * xxt - 1; 1256 x1 := x + (dx0 - n) * xxt - 1; 1257 end 1258 else 1259 begin 1260 x0 := x + dx0 * xxt; 1261 x1 := x + (dx0 + n) * xxt; 1262 end; 1263 moveto(x0, y + dy0 * yyt); 1264 lineto(x1, y + (dy0 + n) * yyt); 1265 end 1266 end; 1267 1268 var 1269 i: integer; 1270 begin 1271 FOutput.Canvas.pen.Color := $000000; // $FF shl (8*random(3)); 1272 for i := 0 to nx div 2 do 1273 ClippedLine(i * 2, 0, false); 1274 for i := 1 to (nx + 1) div 2 do 1275 ClippedLine(i * 2, 0, true); 1276 for i := 0 to ny div 2 do 1277 begin 1278 ClippedLine(0, 2 * i + 2, false); 1279 ClippedLine(nx + 1, 2 * i + 1 + nx and 1, true); 1280 end; 1281 end; 1282 1283 procedure TIsoMap.Paint(x, y, Loc, nx, ny, CityLoc, CityOwner: integer; 1284 UseBlink: boolean; CityAllowClick: boolean); 1285 1286 function IsShoreTile(Loc: integer): boolean; 1287 const 1288 Dirx: array [0 .. 7] of integer = (1, 2, 1, 0, -1, -2, -1, 0); 1289 Diry: array [0 .. 7] of integer = (-1, 0, 1, 2, 1, 0, -1, -2); 1290 var 1291 Dir, ConnLoc: integer; 1292 begin 1293 result := false; 1294 for Dir := 0 to 7 do 1295 begin 1296 ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]); 1297 if (ConnLoc < 0) or (ConnLoc >= G.lx * G.ly) or 1298 ((MyMap[ConnLoc] - 2) and fTerrain < 13) then 1299 result := true 1300 end 1301 end; 1302 1303 procedure ShadeOutside(x0, y0, x1, y1, xm, ym: integer); 1304 const 1305 rShade = 3.75; 1306 1307 procedure MakeDark(Line: pointer; length: integer); 1308 type 1309 TCardArray = array [0 .. 9999] of Cardinal; 1310 PCardArray = ^TCardArray; 1311 TByteArray = array [0 .. 9999] of Byte; 1312 PByteArray = ^TByteArray; 1313 var 1314 i, rest: integer; 1315 begin 1316 for i := length * 3 div 4 - 1 downto 0 do 1317 PCardArray(Line)[i] := PCardArray(Line)[i] shr 1 and $7F7F7F7F; 1318 rest := (length * 3 div 4) * 4; 1319 for i := length * 3 mod 4 - 1 downto 0 do 1320 PByteArray(Line)[rest + i] := PByteArray(Line)[rest + i] shr 1 and $7F; 1321 end; 1322 1323 type 1324 TLine = array [0 .. 99999, 0 .. 2] of Byte; 1325 var 1326 y, wBright: integer; 1327 y_n, w_n: single; 1328 Line: ^TLine; 1329 begin 1330 FOutput.BeginUpdate; 1331 for y := y0 to y1 - 1 do 1332 begin 1333 Line := FOutput.ScanLine[y]; 1334 y_n := (y - ym) / yyt; 1335 if abs(y_n) < rShade then 1336 begin 1337 w_n := sqrt(sqr(rShade) - sqr(y_n)); 1338 wBright := trunc(w_n * xxt + 0.5); 1339 MakeDark(@Line[x0], xm - x0 - wBright); 1340 MakeDark(@Line[xm + wBright], x1 - xm - wBright); 1341 end 1342 else 1343 MakeDark(@Line[x0], x1 - x0); 1344 end; 1345 FOutput.EndUpdate; 1346 end; 1347 1348 procedure CityGrid(xm, ym: integer); 1349 var 1350 i: integer; 1351 begin 1352 with FOutput.Canvas do 1353 begin 1354 if CityAllowClick then 1355 pen.Color := $FFFFFF 1356 else 1357 pen.Color := $000000; 1358 pen.Width := 1; 1359 for i := 0 to 3 do 1360 begin 1361 moveto(xm - xxt * (4 - i), ym + yyt * (1 + i)); 1362 lineto(xm + xxt * (1 + i), ym - yyt * (4 - i)); 1363 moveto(xm - xxt * (4 - i), ym - yyt * (1 + i)); 1364 lineto(xm + xxt * (1 + i), ym + yyt * (4 - i)); 1365 end; 1366 moveto(xm - xxt * 4, ym + yyt * 1); 1367 lineto(xm - xxt * 1, ym + yyt * 4); 1368 moveto(xm + xxt * 1, ym + yyt * 4); 1369 lineto(xm + xxt * 4, ym + yyt * 1); 1370 moveto(xm - xxt * 4, ym - yyt * 1); 1371 lineto(xm - xxt * 1, ym - yyt * 4); 1372 moveto(xm + xxt * 1, ym - yyt * 4); 1373 lineto(xm + xxt * 4, ym - yyt * 1); 1374 pen.Width := 1; 1375 end 1376 end; 1377 1378 var 1379 dx, dy, xm, ym, ALoc, BLoc, ATer, BTer, Aix, bix: integer; 1380 begin 1381 FoW := true; 1382 ShowLoc := Options and (1 shl moLocCodes) <> 0; 1383 ShowDebug := pDebugMap >= 0; 1384 ShowObjects := (CityOwner >= 0) or (Options and (1 shl moBareTerrain) = 0); 1385 ShowCityNames := ShowObjects and (CityOwner < 0) and 1386 (Options and (1 shl moCityNames) <> 0); 1387 ShowBorder := true; 1388 ShowMyBorder := CityOwner < 0; 1389 ShowGrWall := (CityOwner < 0) and (Options and (1 shl moGreatWall) <> 0); 1390 if ShowDebug then 1391 Server(sGetDebugMap, me, pDebugMap, DebugMap) 1392 else 1393 DebugMap := nil; 1394 with FOutput.Canvas do 1395 begin 1396 RealTop := y - ((Loc + 12345 * G.lx) div G.lx - 12345) * yyt; 1397 RealBottom := y + (G.ly - ((Loc + 12345 * G.lx) div G.lx - 12345) + 1398 3) * yyt; 1399 Brush.Color := EmptySpaceColor; 1400 if RealTop > FTop then 1401 FillRect(Rect(FLeft, FTop, FRight, RealTop)) 1402 else 1403 RealTop := FTop; 1404 if RealBottom < FBottom then 1405 FillRect(Rect(FLeft, RealBottom, FRight, FBottom)) 1406 else 1407 RealBottom := FBottom; 1408 Brush.Color := $000000; 1409 FillRect(Rect(FLeft, RealTop, FRight, RealBottom)); 1410 Brush.Style := bsClear; 1411 end; 1412 1413 for dy := 0 to ny + 1 do 1414 if (Loc + dy * G.lx >= 0) and (Loc + (dy - 3) * G.lx < G.lx * G.ly) then 1415 for dx := 0 to nx do 1416 begin 1417 ALoc := dLoc(Loc, dx - (dy + dx) and 1, dy - 2); 1418 BLoc := dLoc(Loc, dx - (dy + dx + 1) and 1, dy - 1); 1419 if (ALoc < 0) or (ALoc >= G.lx * G.ly) then 1420 ATer := PoleTile(ALoc) and fTerrain 1421 else 1422 ATer := MyMap[ALoc] and fTerrain; 1423 if (BLoc < 0) or (BLoc >= G.lx * G.ly) then 1424 BTer := PoleTile(BLoc) and fTerrain 1425 else 1426 BTer := MyMap[BLoc] and fTerrain; 1427 1428 if (ATer <> fUNKNOWN) or (BTer <> fUNKNOWN) then 1429 if ((ATer < fGrass) or (ATer = fUNKNOWN)) and 1430 ((BTer < fGrass) or (BTer = fUNKNOWN)) then 460 1431 begin 461 Width := Width - (FLeft - x); 462 x := FLeft 463 end; 464 if y < FTop then 465 begin 466 Height := Height - (FTop - y); 467 y := FTop 468 end; 469 if x + Width >= FRight then 470 Width := FRight - x; 471 if y + Height >= FBottom then 472 Height := FBottom - y; 473 if (Width <= 0) or (Height <= 0) then 474 exit; 475 476 with FOutput.Canvas do 477 begin 478 Brush.Color := Color; 479 FillRect(Rect(x, y, x + Width, y + Height)); 480 Brush.Style := bsClear; 481 end 482 end; 483 484 procedure TIsoMap.Textout(x, y, Color: integer; const s: string); 485 begin 486 FOutput.Canvas.Font.Color := Color; 487 FOutput.Canvas.TextRect(Rect(FLeft, FTop, FRight, FBottom), x, y, s) 488 end; 489 490 procedure TIsoMap.BitBlt(Src: TBitmap; x, y, Width, Height, xSrc, ySrc, 491 Rop: integer); 492 begin 493 if x < FLeft then 494 begin 495 Width := Width - (FLeft - x); 496 xSrc := xSrc + (FLeft - x); 497 x := FLeft 498 end; 499 if y < FTop then 500 begin 501 Height := Height - (FTop - y); 502 ySrc := ySrc + (FTop - y); 503 y := FTop 504 end; 505 if x + Width >= FRight then 506 Width := FRight - x; 507 if y + Height >= FBottom then 508 Height := FBottom - y; 509 if (Width <= 0) or (Height <= 0) then 510 exit; 511 512 LCLIntf.BitBlt(FOutput.Canvas.Handle, x, y, Width, Height, 513 Src.Canvas.Handle, xSrc, ySrc, Rop); 514 end; 515 516 procedure TIsoMap.Sprite(HGr, xDst, yDst, Width, Height, xGr, 517 yGr: integer); 518 begin 519 BitBlt(GrExt[HGr].Mask, xDst, yDst, Width, Height, xGr, yGr, SRCAND); 520 BitBlt(GrExt[HGr].Data, xDst, yDst, Width, Height, xGr, yGr, 521 SRCPAINT); 522 end; 523 524 procedure TIsoMap.TSprite(xDst, yDst, grix: integer; 525 PureBlack: boolean = false); 526 var 527 Width, Height, xSrc, ySrc: integer; 528 begin 529 Width := TSpriteSize[grix].Right - TSpriteSize[grix].Left; 530 Height := TSpriteSize[grix].Bottom - TSpriteSize[grix].Top; 531 xSrc := 1 + grix mod 9 * (xxt * 2 + 1) + TSpriteSize[grix].Left; 532 ySrc := 1 + grix div 9 * (yyt * 3 + 1) + TSpriteSize[grix].Top; 533 xDst := xDst + TSpriteSize[grix].Left; 534 yDst := yDst - yyt + TSpriteSize[grix].Top; 535 if xDst < FLeft then 536 begin 537 Width := Width - (FLeft - xDst); 538 xSrc := xSrc + (FLeft - xDst); 539 xDst := FLeft 540 end; 541 if yDst < FTop then 542 begin 543 Height := Height - (FTop - yDst); 544 ySrc := ySrc + (FTop - yDst); 545 yDst := FTop 546 end; 547 if xDst + Width >= FRight then 548 Width := FRight - xDst; 549 if yDst + Height >= FBottom then 550 Height := FBottom - yDst; 551 if (Width <= 0) or (Height <= 0) then 552 exit; 553 554 LCLIntf.BitBlt(OutDC, xDst, yDst, Width, Height, MaskDC, xSrc, 555 ySrc, SRCAND); 556 if not PureBlack then 557 LCLIntf.BitBlt(OutDC, xDst, yDst, Width, Height, DataDC, xSrc, ySrc, 558 SRCPAINT); 559 end; 560 561 procedure TIsoMap.PaintUnit(x, y: integer; const UnitInfo: TUnitInfo; 562 Status: integer); 563 var 564 xsh, ysh, xGr, yGr, j, mixShow: integer; 565 begin 566 with UnitInfo do 567 if (Owner = me) or (emix <> $FFFF) then 1432 if ATer = fUNKNOWN then 1433 Aix := 0 1434 else if IsShoreTile(ALoc) then 1435 if ATer = fOcean then 1436 Aix := -1 1437 else 1438 Aix := 1 1439 else 1440 Aix := ATer + 2; 1441 if BTer = fUNKNOWN then 1442 bix := 0 1443 else if IsShoreTile(BLoc) then 1444 if BTer = fOcean then 1445 bix := -1 1446 else 1447 bix := 1 1448 else 1449 bix := BTer + 2; 1450 if (Aix > 1) or (bix > 1) then 568 1451 begin 569 if Job = jCity then 570 mixShow := -1 // building site 571 else 572 mixShow := mix; 573 if (Tribe[Owner].ModelPicture[mixShow].HGr = 0) and 574 (@OnInitEnemyModel <> nil) then 575 if not OnInitEnemyModel(emix) then 576 exit; 577 xsh := Tribe[Owner].ModelPicture[mixShow].xShield; 578 ysh := Tribe[Owner].ModelPicture[mixShow].yShield; 579 {$IFNDEF SCR} if Status and usStay <> 0 then 580 j := 19 581 else if Status and usRecover <> 0 then 582 j := 16 583 else if Status and (usGoto or usEnhance) = usGoto or usEnhance 584 then 585 j := 18 586 else if Status and usEnhance <> 0 then 587 j := 17 588 else if Status and usGoto <> 0 then 589 j := 20 590 else {$ENDIF} if Job = jCity then 591 j := jNone 1452 if Aix = -1 then 1453 if bix = fOcean + 2 then 1454 begin 1455 Aix := 0; 1456 bix := 0 1457 end 592 1458 else 593 j := Job; 594 if Flags and unMulti <> 0 then 595 Sprite(Tribe[Owner].symHGr, x + xsh - 1 + 4, y + ysh - 2, 14, 596 12, 33 + Tribe[Owner].sympix mod 10 * 65, 597 1 + Tribe[Owner].sympix div 10 * 49); 598 Sprite(Tribe[Owner].symHGr, x + xsh - 1, y + ysh - 2, 14, 12, 599 18 + Tribe[Owner].sympix mod 10 * 65, 600 1 + Tribe[Owner].sympix div 10 * 49); 601 FillRect(x + xsh, y + ysh + 5, 1 + Health * 11 div 100, 3, 602 ColorOfHealth(Health)); 603 if j > 0 then 604 begin 605 xGr := 121 + j mod 7 * 9; 606 yGr := 1 + j div 7 * 9; 607 BitBlt(GrExt[HGrSystem].Mask, x + xsh + 3, y + ysh + 9, 8, 8, 608 xGr, yGr, SRCAND); 609 Sprite(HGrSystem, x + xsh + 2, y + ysh + 8, 8, 8, xGr, yGr); 610 end; 611 with Tribe[Owner].ModelPicture[mixShow] do 612 Sprite(HGr, x, y, 64, 48, pix mod 10 * 65 + 1, 613 pix div 10 * 49 + 1); 614 if Flags and unFortified <> 0 then 615 begin 616 { OutDC:=FOutput.Canvas.Handle; 617 DataDC:=GrExt[HGrTerrain].Data.Canvas.Handle; 618 MaskDC:=GrExt[HGrTerrain].Mask.Canvas.Handle; 619 TSprite(x,y+16,12*9+7); } 620 Sprite(HGrStdUnits, x, y, xxu * 2, yyu * 2, 621 1 + 6 * (xxu * 2 + 1), 1); 622 end 1459 begin 1460 Aix := 0; 1461 bix := 1 1462 end 1463 else if bix = -1 then 1464 if Aix = fOcean + 2 then 1465 begin 1466 Aix := 1; 1467 bix := 1 1468 end 1469 else 1470 begin 1471 Aix := 1; 1472 bix := 0 1473 end; 1474 BitBlt(OceanPatch, x + dx * xxt, y + dy * yyt, xxt, yyt, 1475 Aix * (xxt * 2) + (dx + dy + 1) and 1 * xxt, bix * yyt, SRCCOPY) 623 1476 end 624 end; { PaintUnit }625 626 procedure TIsoMap.PaintCity(x, y: integer; const CityInfo: TCityInfo;627 accessory: boolean);628 var629 age, cHGr, cpix, xGr, xShield, yShield, LabelTextColor,630 LabelLength: integer;631 cpic: TCityPicture;632 s: string;633 begin634 age := GetAge(CityInfo.Owner);635 if CityInfo.size < 5 then636 xGr := 0637 else if CityInfo.size < 9 then638 xGr := 1639 else if CityInfo.size < 13 then640 xGr := 2641 else642 xGr := 3;643 Tribe[CityInfo.Owner].InitAge(age);644 if age < 2 then645 begin646 cHGr := Tribe[CityInfo.Owner].cHGr;647 cpix := Tribe[CityInfo.Owner].cpix;648 if (ciWalled and CityInfo.Flags = 0) or649 (GrExt[cHGr].Data.Canvas.Pixels[(xGr + 4) * 65, cpix * 49 + 48]650 = $00FFFF) then651 Sprite(cHGr, x - xxc, y - 2 * yyc, xxc * 2, yyc * 3,652 xGr * (xxc * 2 + 1) + 1, 1 + cpix * (yyc * 3 + 1));653 if ciWalled and CityInfo.Flags <> 0 then654 Sprite(cHGr, x - xxc, y - 2 * yyc, xxc * 2, yyc * 3,655 (xGr + 4) * (xxc * 2 + 1) + 1, 1 + cpix * (yyc * 3 + 1));656 1477 end 657 1478 else 658 1479 begin 659 if ciWalled and CityInfo.Flags <> 0 then 660 Sprite(HGrCities, x - xxt, y - 2 * yyt, 2 * xxt, 3 * yyt, 661 (xGr + 4) * (2 * xxt + 1) + 1, 1 + (age - 2) * (3 * yyt + 1)) 1480 if ATer = fUNKNOWN then 1481 Aix := 0 1482 else if (ALoc >= 0) and (ALoc < G.lx * G.ly) and 1483 (MyMap[ALoc] and fDeadLands <> 0) then 1484 Aix := -2 1485 else if ATer = fOcean then 1486 Aix := -1 1487 else if ATer = fShore then 1488 Aix := 1 1489 else if ATer >= fForest then 1490 Aix := 8 662 1491 else 663 Sprite(HGrCities, x - xxt, y - 2 * yyt, 2 * xxt, 3 * yyt,664 xGr * (2 * xxt + 1) + 1, 1 + (age - 2) * (3 * yyt + 1));665 end;666 667 if not accessorythen668 exit;669 670 { if ciCapital and CityInfo.Flags<>0 then671 Sprite(Tribe[CityInfo.Owner].symHGr,x+cpic.xf,y-13+cpic.yf,13,14,672 1+Tribe[CityInfo.Owner].sympix mod 10 *65,673 1+Tribe[CityInfo.Owner].sympix div 10 *49); {capital -- paint flag }674 675 if MyMap[CityInfo.Loc] and fObserved <> 0 then676 begin677 if age < 2then1492 Aix := ATer; 1493 if BTer = fUNKNOWN then 1494 bix := 0 1495 else if (BLoc >= 0) and (BLoc < G.lx * G.ly) and 1496 (MyMap[BLoc] and fDeadLands <> 0) then 1497 bix := -2 1498 else if BTer = fOcean then 1499 bix := -1 1500 else if BTer = fShore then 1501 bix := 1 1502 else if BTer >= fForest then 1503 bix := 8 1504 else 1505 bix := BTer; 1506 if (Aix = -2) and (bix = -2) then 678 1507 begin 679 cpic := Tribe[CityInfo.Owner].CityPicture[xGr]; 680 xShield := x - xxc + cpic.xShield; 681 yShield := y - 2 * yyc + cpic.yShield; 1508 Aix := fDesert; 1509 bix := fDesert 682 1510 end 1511 else if Aix = -2 then 1512 if bix < 2 then 1513 Aix := 8 1514 else 1515 Aix := bix 1516 else if bix = -2 then 1517 if Aix < 2 then 1518 bix := 8 1519 else 1520 bix := Aix; 1521 if Aix = -1 then 1522 BitBlt(GrExt[HGrTerrain].Data, x + dx * xxt, y + dy * yyt, xxt, 1523 yyt, 1 + 6 * (xxt * 2 + 1) + (dx + dy + 1) and 1 * xxt, 1 + yyt, 1524 SRCCOPY) // arctic <-> ocean 1525 else if bix = -1 then 1526 BitBlt(GrExt[HGrTerrain].Data, x + dx * xxt, y + dy * yyt, xxt, 1527 yyt, 1 + 6 * (xxt * 2 + 1) + xxt - (dx + dy + 1) and 1 * xxt, 1528 1 + yyt * 2, SRCCOPY) // arctic <-> ocean 683 1529 else 684 begin 685 cpic := CitiesPictures[age, xGr]; 686 xShield := x - xxt + cpic.xShield; 687 yShield := y - 2 * yyt + cpic.yShield; 688 end; 689 s := IntToStr(CityInfo.size); 690 LabelLength := FOutput.Canvas.TextWidth(s); 691 FillRect(xShield, yShield, LabelLength + 4, 16, $000000); 692 if MyMap[CityInfo.Loc] and (fUnit or fObserved) = fObserved then 693 // empty city 694 LabelTextColor := Tribe[CityInfo.Owner].Color 695 else 696 begin 697 FillRect(xShield + 1, yShield + 1, LabelLength + 2, 14, 698 Tribe[CityInfo.Owner].Color); 699 LabelTextColor := $000000; 700 end; 701 Textout(xShield + 2, yShield - 1, LabelTextColor, s); 1530 BitBlt(LandPatch, x + dx * xxt, y + dy * yyt, xxt, yyt, 1531 Aix * (xxt * 2) + (dx + dy + 1) and 1 * xxt, bix * yyt, SRCCOPY) 702 1532 end 703 end; { PaintCity } 704 705 function PoleTile(Loc: integer): integer; 706 begin { virtual pole tile } 707 result := fUNKNOWN; 708 if Loc < -2 * G.lx then 709 else if Loc < -G.lx then 710 begin 711 if (MyMap[dLoc(Loc, 0, 2)] and fTerrain <> fUNKNOWN) and 712 (MyMap[dLoc(Loc, -2, 2)] and fTerrain <> fUNKNOWN) and 713 (MyMap[dLoc(Loc, 2, 2)] and fTerrain <> fUNKNOWN) then 714 result := fArctic; 715 if (MyMap[dLoc(Loc, 0, 2)] and fObserved <> 0) and 716 (MyMap[dLoc(Loc, -2, 2)] and fObserved <> 0) and 717 (MyMap[dLoc(Loc, 2, 2)] and fObserved <> 0) then 718 result := result or fObserved 719 end 720 else if Loc < 0 then 721 begin 722 if (MyMap[dLoc(Loc, -1, 1)] and fTerrain <> fUNKNOWN) and 723 (MyMap[dLoc(Loc, 1, 1)] and fTerrain <> fUNKNOWN) then 724 result := fArctic; 725 if (MyMap[dLoc(Loc, -1, 1)] and fObserved <> 0) and 726 (MyMap[dLoc(Loc, 1, 1)] and fObserved <> 0) then 727 result := result or fObserved 728 end 729 else if Loc < G.lx * (G.ly + 1) then 730 begin 731 if (MyMap[dLoc(Loc, -1, -1)] and fTerrain <> fUNKNOWN) and 732 (MyMap[dLoc(Loc, 1, -1)] and fTerrain <> fUNKNOWN) then 733 result := fArctic; 734 if (MyMap[dLoc(Loc, -1, -1)] and fObserved <> 0) and 735 (MyMap[dLoc(Loc, 1, -1)] and fObserved <> 0) then 736 result := result or fObserved 737 end 738 else if Loc < G.lx * (G.ly + 2) then 739 begin 740 if (MyMap[dLoc(Loc, 0, -2)] and fTerrain <> fUNKNOWN) and 741 (MyMap[dLoc(Loc, -2, -2)] and fTerrain <> fUNKNOWN) and 742 (MyMap[dLoc(Loc, 2, -2)] and fTerrain <> fUNKNOWN) then 743 result := fArctic; 744 if (MyMap[dLoc(Loc, 0, -2)] and fObserved <> 0) and 745 (MyMap[dLoc(Loc, -2, -2)] and fObserved <> 0) and 746 (MyMap[dLoc(Loc, 2, -2)] and fObserved <> 0) then 747 result := result or fObserved 748 end 1533 end; 1534 1535 OutDC := FOutput.Canvas.Handle; 1536 DataDC := GrExt[HGrTerrain].Data.Canvas.Handle; 1537 MaskDC := GrExt[HGrTerrain].Mask.Canvas.Handle; 1538 for dy := -2 to ny + 1 do 1539 for dx := -1 to nx do 1540 if (dx + dy) and 1 = 0 then 1541 PaintShore(x + xxt * dx, y + yyt + yyt * dy, dLoc(Loc, dx, dy)); 1542 for dy := -2 to ny + 1 do 1543 for dx := -1 to nx do 1544 if (dx + dy) and 1 = 0 then 1545 PaintTileExtraTerrain(x + xxt * dx, y + yyt + yyt * dy, 1546 dLoc(Loc, dx, dy)); 1547 if CityOwner >= 0 then 1548 begin 1549 for dy := -2 to ny + 1 do 1550 for dx := -2 to nx + 1 do 1551 if (dx + dy) and 1 = 0 then 1552 begin 1553 ALoc := dLoc(Loc, dx, dy); 1554 if Distance(ALoc, CityLoc) > 5 then 1555 PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy, ALoc, CityLoc, 1556 CityOwner, UseBlink); 749 1557 end; 750 751 const 752 Dirx: array [0 .. 7] of integer = (1, 2, 1, 0, -1, -2, -1, 0); 753 Diry: array [0 .. 7] of integer = (-1, 0, 1, 2, 1, 0, -1, -2); 754 755 function TIsoMap.Connection4(Loc, Mask, Value: integer): integer; 1558 dx := ((CityLoc mod G.lx * 2 + CityLoc div G.lx and 1) - 1559 ((Loc + 666 * G.lx) mod G.lx * 2 + (Loc + 666 * G.lx) div G.lx and 1) + 3 1560 * G.lx) mod (2 * G.lx) - G.lx; 1561 dy := CityLoc div G.lx - (Loc + 666 * G.lx) div G.lx + 666; 1562 xm := x + (dx + 1) * xxt; 1563 ym := y + (dy + 1) * yyt + yyt; 1564 ShadeOutside(FLeft, FTop, FRight, FBottom, xm, ym); 1565 CityGrid(xm, ym); 1566 for dy := -2 to ny + 1 do 1567 for dx := -2 to nx + 1 do 1568 if (dx + dy) and 1 = 0 then 756 1569 begin 757 result := 0; 758 if dLoc(Loc, 1, -1) >= 0 then 759 begin 760 if MyMap[dLoc(Loc, 1, -1)] and Mask = Cardinal(Value) then 761 inc(result, 1); 762 if MyMap[dLoc(Loc, -1, -1)] and Mask = Cardinal(Value) then 763 inc(result, 8); 764 end; 765 if dLoc(Loc, 1, 1) < G.lx * G.ly then 766 begin 767 if MyMap[dLoc(Loc, 1, 1)] and Mask = Cardinal(Value) then 768 inc(result, 2); 769 if MyMap[dLoc(Loc, -1, 1)] and Mask = Cardinal(Value) then 770 inc(result, 4); 771 end 1570 ALoc := dLoc(Loc, dx, dy); 1571 if Distance(ALoc, CityLoc) <= 5 then 1572 PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy, ALoc, CityLoc, 1573 CityOwner, UseBlink); 772 1574 end; 773 774 function TIsoMap.Connection8(Loc, Mask: integer): integer; 775 var 776 Dir, ConnLoc: integer; 777 begin 778 result := 0; 779 for Dir := 0 to 7 do 780 begin 781 ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]); 782 if (ConnLoc >= 0) and (ConnLoc < G.lx * G.ly) and 783 (MyMap[ConnLoc] and Mask <> 0) then 784 inc(result, 1 shl Dir); 785 end 786 end; 787 788 function TIsoMap.OceanConnection(Loc: integer): integer; 789 var 790 Dir, ConnLoc: integer; 791 begin 792 result := 0; 793 for Dir := 0 to 7 do 794 begin 795 ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]); 796 if (ConnLoc < 0) or (ConnLoc >= G.lx * G.ly) or 797 ((MyMap[ConnLoc] - 2) and fTerrain < 13) then 798 inc(result, 1 shl Dir); 799 end 800 end; 801 802 procedure TIsoMap.PaintShore(x, y, Loc: integer); 803 var 804 Conn, Tile: integer; 805 begin 806 if (y <= FTop - yyt * 2) or (y > FBottom) or (x <= FLeft - xxt * 2) or 807 (x > FRight) then 808 exit; 809 if (Loc < 0) or (Loc >= G.lx * G.ly) then 810 exit; 811 Tile := MyMap[Loc]; 812 if Tile and fTerrain >= fGrass then 813 exit; 814 Conn := OceanConnection(Loc); 815 if Conn = 0 then 816 exit; 817 818 BitBlt(GrExt[HGrTerrain].Data, x + xxt div 2, y, xxt, yyt, 819 1 + (Conn shr 6 + Conn and 1 shl 2) * (xxt * 2 + 1), 820 1 + yyt + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT); 821 BitBlt(GrExt[HGrTerrain].Data, x + xxt, y + yyt div 2, xxt, yyt, 822 1 + (Conn and 7) * (xxt * 2 + 1) + xxt, 823 1 + yyt * 2 + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT); 824 BitBlt(GrExt[HGrTerrain].Data, x + xxt div 2, y + yyt, xxt, yyt, 825 1 + (Conn shr 2 and 7) * (xxt * 2 + 1) + xxt, 826 1 + yyt + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT); 827 BitBlt(GrExt[HGrTerrain].Data, x, y + yyt div 2, xxt, yyt, 828 1 + (Conn shr 4 and 7) * (xxt * 2 + 1), 829 1 + yyt * 2 + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT); 830 Conn := Connection4(Loc, fTerrain, fUNKNOWN); { dither to black } 831 if Conn and 1 <> 0 then 832 BitBlt(GrExt[HGrTerrain].Mask, x + xxt, y, xxt, yyt, 833 1 + 7 * (xxt * 2 + 1) + xxt, 834 1 + yyt + 15 * (yyt * 3 + 1), SRCAND); 835 if Conn and 2 <> 0 then 836 BitBlt(GrExt[HGrTerrain].Mask, x + xxt, y + yyt, xxt, yyt, 837 1 + 7 * (xxt * 2 + 1) + xxt, 1 + yyt * 2 + 15 * 838 (yyt * 3 + 1), SRCAND); 839 if Conn and 4 <> 0 then 840 BitBlt(GrExt[HGrTerrain].Mask, x, y + yyt, xxt, yyt, 841 1 + 7 * (xxt * 2 + 1), 1 + yyt * 2 + 15 * (yyt * 3 + 1), SRCAND); 842 if Conn and 8 <> 0 then 843 BitBlt(GrExt[HGrTerrain].Mask, x, y, xxt, yyt, 844 1 + 7 * (xxt * 2 + 1), 1 + yyt + 15 * (yyt * 3 + 1), SRCAND); 845 end; 846 847 procedure TIsoMap.PaintTileExtraTerrain(x, y, Loc: integer); 848 var 849 Dir, Conn, RRConn, yGr, Tile, yLoc: integer; 850 begin 851 if (Loc < 0) or (Loc >= G.lx * G.ly) or (y <= -yyt * 2) or 852 (y > FOutput.Height) or (x <= -xxt * 2) or (x > FOutput.Width) then 853 exit; 854 Tile := MyMap[Loc]; 855 if Tile and fTerrain = fForest then 856 begin 857 yLoc := Loc div G.lx; 858 if IsJungle(yLoc) then 859 yGr := 18 860 else 861 yGr := 3; 862 Conn := Connection4(Loc, fTerrain, Tile and fTerrain); 863 if (yLoc = (G.ly - 2) div 4) or (G.ly - 1 - yLoc = (G.ly + 2) div 4) 864 then 865 Conn := Conn and not 6 // no connection to south 866 else if (yLoc = (G.ly + 2) div 4) or 867 (G.ly - 1 - yLoc = (G.ly - 2) div 4) then 868 Conn := Conn and not 9; // no connection to north 869 TSprite(x, y, Conn mod 8 + (yGr + Conn div 8) * 9); 870 end 871 else if Tile and fTerrain in [fHills, fMountains, fForest] then 872 begin 873 yGr := 3 + 2 * (Tile and fTerrain - fForest); 874 Conn := Connection4(Loc, fTerrain, Tile and fTerrain); 875 TSprite(x, y, Conn mod 8 + (yGr + Conn div 8) * 9); 876 end 877 else if Tile and fDeadLands <> 0 then 878 TSprite(x, y, 2 * 9 + 6); 879 880 if ShowObjects then 881 begin 882 if Tile and fTerImp = tiFarm then 883 TSprite(x, y, 109) { farmland } 884 else if Tile and fTerImp = tiIrrigation then 885 TSprite(x, y, 108); // irrigation 886 end; 887 if Tile and fRiver <> 0 then 888 begin 889 Conn := Connection4(Loc, fRiver, fRiver) or 890 Connection4(Loc, fTerrain, fShore) or 891 Connection4(Loc, fTerrain, fUNKNOWN); 892 TSprite(x, y, Conn mod 8 + (13 + Conn div 8) * 9); 893 end; 894 895 if Tile and fTerrain < fGrass then 896 begin 897 Conn := Connection4(Loc, fRiver, fRiver); 898 for Dir := 0 to 3 do 899 if Conn and (1 shl Dir) <> 0 then { river mouths } 900 TSprite(x, y, 15 * 9 + Dir); 901 if ShowObjects then 902 begin 903 Conn := Connection8(Loc, fCanal); 904 for Dir := 0 to 7 do 905 if Conn and (1 shl Dir) <> 0 then { canal mouths } 906 TSprite(x, y, 20 * 9 + 1 + Dir); 907 end 908 end; 909 910 if ShowObjects then 911 begin 912 if (Tile and fCanal <> 0) or (Tile and fCity <> 0) then 913 begin // paint canal connections 914 Conn := Connection8(Loc, fCanal or fCity); 915 if Tile and fCanal <> 0 then 916 Conn := Conn or ($FF - OceanConnection(Loc)); 917 if Conn = 0 then 918 begin 919 if Tile and fCanal <> 0 then 920 TSprite(x, y, 99) 921 end 922 else 923 for Dir := 0 to 7 do 924 if (1 shl Dir) and Conn <> 0 then 925 TSprite(x, y, 100 + Dir); 926 end; 927 if Tile and (fRR or fCity) <> 0 then 928 RRConn := Connection8(Loc, fRR or fCity) 929 else 930 RRConn := 0; 931 if Tile and (fRoad or fRR or fCity) <> 0 then 932 begin // paint road connections 933 Conn := Connection8(Loc, fRoad or fRR or fCity) and not RRConn; 934 if (Conn = 0) and (Tile and (fRR or fCity) = 0) then 935 TSprite(x, y, 81) 936 else if Conn > 0 then 937 for Dir := 0 to 7 do 938 if (1 shl Dir) and Conn <> 0 then 939 TSprite(x, y, 82 + Dir); 940 end; 941 // paint railroad connections 942 if (Tile and fRR <> 0) and (RRConn = 0) then 943 TSprite(x, y, 90) 944 else if RRConn > 0 then 945 for Dir := 0 to 7 do 946 if (1 shl Dir) and RRConn <> 0 then 947 TSprite(x, y, 91 + Dir); 948 end; 949 end; 950 951 // (x,y) is top left pixel of (2*xxt,3*yyt) rectangle 952 procedure TIsoMap.PaintTileObjects(x, y, Loc, CityLoc, 953 CityOwner: integer; UseBlink: boolean); 954 type 955 TLine = array [0 .. 9 * 65, 0 .. 2] of Byte; 956 var 957 p1, p2, uix, cix, dy, Loc1, Tile, Multi, Destination: integer; 958 CityInfo: TCityInfo; 959 UnitInfo: TUnitInfo; 960 fog: boolean; 961 962 procedure NameCity; 963 var 964 cix, xs, w: integer; 965 BehindCityInfo: TCityInfo; 966 s: string; 967 IsCapital: boolean; 968 begin 969 BehindCityInfo.Loc := Loc - 2 * G.lx; 970 if ShowCityNames and (Options and (1 shl moEditMode) = 0) and 971 (BehindCityInfo.Loc >= 0) and (BehindCityInfo.Loc < G.lx * G.ly) 972 and (MyMap[BehindCityInfo.Loc] and fCity <> 0) then 973 begin 974 GetCityInfo(BehindCityInfo.Loc, cix, BehindCityInfo); 975 IsCapital := BehindCityInfo.Flags and ciCapital <> 0; 976 { if Showuix and (cix>=0) then s:=IntToStr(cix) 977 else } s := CityName(BehindCityInfo.ID); 978 w := FOutput.Canvas.TextWidth(s); 979 xs := x + xxt - (w + 1) div 2; 980 if IsCapital then 981 FOutput.Canvas.Font.Style := FOutput.Canvas.Font.Style + 982 [fsUnderline]; 983 Textout(xs + 1, y - 9, $000000, s); 984 Textout(xs, y - 10, $FFFFFF, s); 985 if IsCapital then 986 FOutput.Canvas.Font.Style := FOutput.Canvas.Font.Style - 987 [fsUnderline]; 988 end; 989 end; 990 991 procedure ShowSpacePort; 992 begin 993 if ShowObjects and (Options and (1 shl moEditMode) = 0) and 994 (Tile and fCity <> 0) and (CityInfo.Flags and ciSpacePort <> 0) 995 then 996 TSprite(x + xxt, y - 6, 12 * 9 + 5); 997 end; 998 999 procedure PaintBorder; 1000 var 1001 dx, dy: integer; 1002 Line: ^TLine; 1003 begin 1004 if ShowBorder and (Loc >= 0) and (Loc < G.lx * G.ly) and 1005 (Tile and fTerrain <> fUNKNOWN) then 1006 begin 1007 p1 := MyRO.Territory[Loc]; 1008 if (p1 >= 0) and (ShowMyBorder or (p1 <> me)) then 1009 begin 1010 if BordersOK and (1 shl p1) = 0 then 1011 begin 1012 LCLIntf.BitBlt(Borders.Canvas.Handle, 0, p1 * (yyt * 2), 1013 xxt * 2, yyt * 2, GrExt[HGrTerrain].Data.Canvas.Handle, 1014 1 + 8 * (xxt * 2 + 1), 1015 1 + yyt + 16 * (yyt * 3 + 1), SRCCOPY); 1016 Borders.BeginUpdate; 1017 for dy := 0 to yyt * 2 - 1 do 1018 begin 1019 Line := Borders.ScanLine[p1 * (yyt * 2) + dy]; 1020 for dx := 0 to xxt * 2 - 1 do 1021 if Line[dx, 0] = 99 then 1022 begin 1023 Line[dx, 0] := Tribe[p1].Color shr 16 and $FF; 1024 Line[dx, 1] := Tribe[p1].Color shr 8 and $FF; 1025 Line[dx, 2] := Tribe[p1].Color and $FF; 1026 end 1027 end; 1028 Borders.EndUpdate; 1029 BordersOK := BordersOK or 1 shl p1; 1030 end; 1031 for dy := 0 to 1 do 1032 for dx := 0 to 1 do 1033 begin 1034 Loc1 := dLoc(Loc, dx * 2 - 1, dy * 2 - 1); 1035 begin 1036 if (Loc1 < 0) or (Loc1 >= G.lx * G.ly) then 1037 p2 := -1 1038 else if MyMap[Loc1] and fTerrain = fUNKNOWN then 1039 p2 := p1 1040 else 1041 p2 := MyRO.Territory[Loc1]; 1042 if p2 <> p1 then 1043 begin 1044 BitBlt(GrExt[HGrTerrain].Mask, x + dx * xxt, 1045 y + dy * yyt, xxt, yyt, 1 + 8 * (xxt * 2 + 1) + dx * 1046 xxt, 1 + yyt + 16 * (yyt * 3 + 1) + dy * yyt, SRCAND); 1047 BitBlt(Borders, x + dx * xxt, y + dy * yyt, xxt, yyt, 1048 dx * xxt, p1 * (yyt * 2) + dy * yyt, SRCPAINT); 1049 end 1050 end; 1051 end 1052 end 1053 end; 1054 end; 1055 1056 begin 1057 if (Loc < 0) or (Loc >= G.lx * G.ly) then 1058 Tile := PoleTile(Loc) 1059 else 1060 Tile := MyMap[Loc]; 1061 if ShowObjects and (Options and (1 shl moEditMode) = 0) and 1062 (Tile and fCity <> 0) then 1063 GetCityInfo(Loc, cix, CityInfo); 1064 if (y <= FTop - yyt * 2) or (y > FBottom) or (x <= FLeft - xxt * 2) or 1065 (x > FRight) then 1066 begin 1067 NameCity; 1068 ShowSpacePort; 1069 exit; 1070 end; 1071 if Tile and fTerrain = fUNKNOWN then 1072 begin 1073 NameCity; 1074 ShowSpacePort; 1075 exit 1076 end; { square not discovered } 1077 1078 if not(FoW and (Tile and fObserved = 0)) then 1079 PaintBorder; 1080 1081 if (Loc >= 0) and (Loc < G.lx * G.ly) and (Loc = FAdviceLoc) then 1082 TSprite(x, y, 7 + 9 * 2); 1083 1084 if (Loc >= 0) and (Loc < G.lx * G.ly) and (Tile and fSpecial <> 0) 1085 then { special ressources } 1086 begin 1087 dy := Loc div G.lx; 1088 if Tile and fTerrain < fForest then 1089 TSprite(x, y, Tile and fTerrain + (Tile and fSpecial shr 5) * 9) 1090 else if (Tile and fTerrain = fForest) and IsJungle(dy) then 1091 TSprite(x, y, 8 + 17 * 9 + (Tile and fSpecial shr 5) * 9) 1092 else 1093 TSprite(x, y, 8 + 2 * 9 + ((Tile and fTerrain - fForest) * 2 + 1094 Tile and fSpecial shr 5) * 9); 1095 end; 1096 1097 if ShowObjects then 1098 begin 1099 if Tile and fTerImp = tiMine then 1100 TSprite(x, y, 2 + 9 * 12); 1101 if Tile and fTerImp = tiBase then 1102 TSprite(x, y, 4 + 9 * 12); 1103 if Tile and fPoll <> 0 then 1104 TSprite(x, y, 6 + 9 * 12); 1105 if Tile and fTerImp = tiFort then 1106 begin 1107 TSprite(x, y, 7 + 9 * 12); 1108 if Tile and fObserved = 0 then 1109 TSprite(x, y, 3 + 9 * 12); 1110 end; 1111 end; 1112 if Tile and fDeadLands <> 0 then 1113 TSprite(x, y, (12 + Tile shr 25 and 3) * 9 + 8); 1114 1115 if Options and (1 shl moEditMode) <> 0 then 1116 fog := (Loc < 0) or (Loc >= G.lx * G.ly) 1117 // else if CityLoc>=0 then 1118 // fog:= (Loc<0) or (Loc>=G.lx*G.ly) or (Distance(Loc,CityLoc)>5) 1119 else if ShowGrWall then 1120 fog := Tile and fGrWall = 0 1121 else 1122 fog := FoW and (Tile and fObserved = 0); 1123 if fog and ShowObjects then 1124 if Loc < -G.lx then 1125 Sprite(HGrTerrain, x, y + yyt, xxt * 2, yyt, 1126 1 + 6 * (xxt * 2 + 1), 1 + yyt * 2 + 15 * (yyt * 3 + 1)) 1127 else if Loc >= G.lx * (G.ly + 1) then 1128 Sprite(HGrTerrain, x, y, xxt * 2, yyt, 1 + 6 * (xxt * 2 + 1), 1129 1 + yyt + 15 * (yyt * 3 + 1)) 1130 else 1131 TSprite(x, y, 6 + 9 * 15, xxt <> 33); 1132 1133 if FoW and (Tile and fObserved = 0) then 1134 PaintBorder; 1135 1136 {$IFNDEF SCR} 1137 // paint goto destination mark 1138 if DestinationMarkON and (CityOwner < 0) and (UnFocus >= 0) and 1139 (MyUn[UnFocus].Status and usGoto <> 0) then 1140 begin 1141 Destination := MyUn[UnFocus].Status shr 16; 1142 if (Destination = Loc) and (Destination <> MyUn[UnFocus].Loc) then 1143 if not UseBlink or BlinkOn then 1144 TSprite(x, y, 8 + 9 * 1) 1145 else 1146 TSprite(x, y, 8 + 9 * 2) 1147 end; 1148 {$ENDIF} 1149 if Options and (1 shl moEditMode) <> 0 then 1150 begin 1151 if Tile and fPrefStartPos <> 0 then 1152 TSprite(x, y, 0 + 9 * 1) 1153 else if Tile and fStartPos <> 0 then 1154 TSprite(x, y, 0 + 9 * 2); 1155 end 1156 else if ShowObjects then 1157 begin 1158 { if (CityLoc<0) and (UnFocus>=0) and (Loc=MyUn[UnFocus].Loc) then 1159 if BlinkOn then TSprite(x,y,8+9*0) 1160 else TSprite(x,y,8+9*1); } 1161 1162 NameCity; 1163 ShowSpacePort; 1164 if Tile and fCity <> 0 then 1165 PaintCity(x + xxt, y + yyt, CityInfo, CityOwner < 0); 1166 1167 if (Tile and fUnit <> 0) and (Loc <> AttLoc) and 1168 ((Loc <> DefLoc) or (DefHealth <> 0)) 1169 {$IFNDEF SCR} and ((CityOwner >= 0) or (UnFocus < 0) or not UseBlink or 1170 BlinkOn or (Loc <> MyUn[UnFocus].Loc)){$ENDIF} 1171 and ((Tile and fCity <> fCity) or (Loc = DefLoc) 1172 {$IFNDEF SCR} or (not UseBlink or BlinkOn) and (UnFocus >= 0) and 1173 (Loc = MyUn[UnFocus].Loc){$ENDIF}) then 1174 begin { unit } 1175 GetUnitInfo(Loc, uix, UnitInfo); 1176 if (Loc = DefLoc) and (DefHealth >= 0) then 1177 UnitInfo.Health := DefHealth; 1178 if (UnitInfo.Owner <> CityOwner) and 1179 not((CityOwner = me) and 1180 (MyRO.Treaty[UnitInfo.Owner] = trAlliance)) then 1181 {$IFNDEF SCR} if (UnFocus >= 0) and (Loc = MyUn[UnFocus].Loc) then { active unit } 1182 begin 1183 Multi := UnitInfo.Flags and unMulti; 1184 MakeUnitInfo(me, MyUn[UnFocus], UnitInfo); 1185 UnitInfo.Flags := UnitInfo.Flags or Multi; 1186 PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo, 1187 MyUn[UnFocus].Status); 1188 end 1189 else if UnitInfo.Owner = me then 1190 begin 1191 if ClientMode = cMovieTurn then 1192 PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), 1193 UnitInfo, 0) 1194 // status is not set with precise timing during loading 1195 else 1196 PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo, 1197 MyUn[uix].Status); 1198 // if Showuix then Textout(x+16,y+5,$80FF00,IntToStr(uix)); 1199 end 1200 else {$ENDIF} PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo, 0); 1201 end 1202 else if Tile and fHiddenUnit <> 0 then 1203 Sprite(HGrStdUnits, x + (xxt - xxu), y + (yyt - yyu_anchor), 1204 xxu * 2, yyu * 2, 1 + 5 * (xxu * 2 + 1), 1) 1205 else if Tile and fStealthUnit <> 0 then 1206 Sprite(HGrStdUnits, x + (xxt - xxu), y + (yyt - yyu_anchor), 1207 xxu * 2, yyu * 2, 1 + 5 * (xxu * 2 + 1), 1 + 1 * (yyu * 2 + 1)) 1208 end; 1209 1210 if ShowObjects and (Tile and fTerImp = tiFort) and 1211 (Tile and fObserved <> 0) then 1212 TSprite(x, y, 3 + 9 * 12); 1213 1214 if (Loc >= 0) and (Loc < G.lx * G.ly) then 1215 if ShowLoc then 1216 Textout(x + xxt - 16, y + yyt - 9, $FFFF00, IntToStr(Loc)) 1217 else if ShowDebug and (DebugMap <> nil) and (Loc >= 0) and 1218 (Loc < G.lx * G.ly) and (DebugMap[Loc] <> 0) then 1219 Textout(x + xxt - 16, y + yyt - 9, $00E0FF, 1220 IntToStr(integer(DebugMap[Loc]))) 1221 end; { PaintTileObjects } 1222 1223 procedure TIsoMap.PaintGrid(x, y, nx, ny: integer); 1224 1225 procedure ClippedLine(dx0, dy0: integer; mirror: boolean); 1226 var 1227 x0, x1, dxmin, dymin, dxmax, dymax, n: integer; 1228 begin 1229 with FOutput.Canvas do 1230 begin 1231 dxmin := (FLeft - x) div xxt; 1232 dymin := (RealTop - y) div yyt; 1233 dxmax := (FRight - x - 1) div xxt + 1; 1234 dymax := (RealBottom - y - 1) div yyt + 1; 1235 n := dymax - dy0; 1236 if mirror then 1237 begin 1238 if dx0 - dxmin < n then 1239 n := dx0 - dxmin; 1240 if dx0 > dxmax then 1241 begin 1242 n := n - (dx0 - dxmax); 1243 dy0 := dy0 + (dx0 - dxmax); 1244 dx0 := dxmax 1245 end; 1246 if dy0 < dymin then 1247 begin 1248 n := n - (dymin - dy0); 1249 dx0 := dx0 - (dymin - dy0); 1250 dy0 := dymin 1251 end; 1252 end 1253 else 1254 begin 1255 if dxmax - dx0 < n then 1256 n := dxmax - dx0; 1257 if dx0 < dxmin then 1258 begin 1259 n := n - (dxmin - dx0); 1260 dy0 := dy0 + (dxmin - dx0); 1261 dx0 := dxmin 1262 end; 1263 if dy0 < dymin then 1264 begin 1265 n := n - (dymin - dy0); 1266 dx0 := dx0 + (dymin - dy0); 1267 dy0 := dymin 1268 end; 1269 end; 1270 if n <= 0 then 1271 exit; 1272 if mirror then 1273 begin 1274 x0 := x + dx0 * xxt - 1; 1275 x1 := x + (dx0 - n) * xxt - 1; 1276 end 1277 else 1278 begin 1279 x0 := x + dx0 * xxt; 1280 x1 := x + (dx0 + n) * xxt; 1281 end; 1282 moveto(x0, y + dy0 * yyt); 1283 lineto(x1, y + (dy0 + n) * yyt); 1284 end 1285 end; 1286 1287 var 1288 i: integer; 1289 begin 1290 FOutput.Canvas.pen.Color := $000000; // $FF shl (8*random(3)); 1291 for i := 0 to nx div 2 do 1292 ClippedLine(i * 2, 0, false); 1293 for i := 1 to (nx + 1) div 2 do 1294 ClippedLine(i * 2, 0, true); 1295 for i := 0 to ny div 2 do 1296 begin 1297 ClippedLine(0, 2 * i + 2, false); 1298 ClippedLine(nx + 1, 2 * i + 1 + nx and 1, true); 1299 end; 1300 end; 1301 1302 procedure TIsoMap.Paint(x, y, Loc, nx, ny, CityLoc, CityOwner: integer; 1303 UseBlink: boolean; CityAllowClick: boolean); 1304 1305 function IsShoreTile(Loc: integer): boolean; 1306 const 1307 Dirx: array [0 .. 7] of integer = (1, 2, 1, 0, -1, -2, -1, 0); 1308 Diry: array [0 .. 7] of integer = (-1, 0, 1, 2, 1, 0, -1, -2); 1309 var 1310 Dir, ConnLoc: integer; 1311 begin 1312 result := false; 1313 for Dir := 0 to 7 do 1314 begin 1315 ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]); 1316 if (ConnLoc < 0) or (ConnLoc >= G.lx * G.ly) or 1317 ((MyMap[ConnLoc] - 2) and fTerrain < 13) then 1318 result := true 1319 end 1320 end; 1321 1322 procedure ShadeOutside(x0, y0, x1, y1, xm, ym: integer); 1323 const 1324 rShade = 3.75; 1325 1326 procedure MakeDark(Line: pointer; length: integer); 1327 type 1328 TCardArray = array [0 .. 9999] of Cardinal; 1329 PCardArray = ^TCardArray; 1330 TByteArray = array [0 .. 9999] of Byte; 1331 PByteArray = ^TByteArray; 1332 var 1333 i, rest: integer; 1334 begin 1335 for i := length * 3 div 4 - 1 downto 0 do 1336 PCardArray(Line)[i] := PCardArray(Line)[i] shr 1 and $7F7F7F7F; 1337 rest := (length * 3 div 4) * 4; 1338 for i := length * 3 mod 4 - 1 downto 0 do 1339 PByteArray(Line)[rest + i] := PByteArray(Line) 1340 [rest + i] shr 1 and $7F; 1341 end; 1342 1343 type 1344 TLine = array [0 .. 99999, 0 .. 2] of Byte; 1345 var 1346 y, wBright: integer; 1347 y_n, w_n: single; 1348 Line: ^TLine; 1349 begin 1350 FOutput.BeginUpdate; 1351 for y := y0 to y1 - 1 do 1352 begin 1353 Line := FOutput.ScanLine[y]; 1354 y_n := (y - ym) / yyt; 1355 if abs(y_n) < rShade then 1356 begin 1357 w_n := sqrt(sqr(rShade) - sqr(y_n)); 1358 wBright := trunc(w_n * xxt + 0.5); 1359 MakeDark(@Line[x0], xm - x0 - wBright); 1360 MakeDark(@Line[xm + wBright], x1 - xm - wBright); 1361 end 1362 else 1363 MakeDark(@Line[x0], x1 - x0); 1364 end; 1365 FOutput.EndUpdate; 1366 end; 1367 1368 procedure CityGrid(xm, ym: integer); 1369 var 1370 i: integer; 1371 begin 1372 with FOutput.Canvas do 1373 begin 1374 if CityAllowClick then 1375 pen.Color := $FFFFFF 1376 else 1377 pen.Color := $000000; 1378 pen.Width := 1; 1379 for i := 0 to 3 do 1380 begin 1381 moveto(xm - xxt * (4 - i), ym + yyt * (1 + i)); 1382 lineto(xm + xxt * (1 + i), ym - yyt * (4 - i)); 1383 moveto(xm - xxt * (4 - i), ym - yyt * (1 + i)); 1384 lineto(xm + xxt * (1 + i), ym + yyt * (4 - i)); 1385 end; 1386 moveto(xm - xxt * 4, ym + yyt * 1); 1387 lineto(xm - xxt * 1, ym + yyt * 4); 1388 moveto(xm + xxt * 1, ym + yyt * 4); 1389 lineto(xm + xxt * 4, ym + yyt * 1); 1390 moveto(xm - xxt * 4, ym - yyt * 1); 1391 lineto(xm - xxt * 1, ym - yyt * 4); 1392 moveto(xm + xxt * 1, ym - yyt * 4); 1393 lineto(xm + xxt * 4, ym - yyt * 1); 1394 pen.Width := 1; 1395 end 1396 end; 1397 1398 var 1399 dx, dy, xm, ym, ALoc, BLoc, ATer, BTer, Aix, bix: integer; 1400 begin 1401 FoW := true; 1402 ShowLoc := Options and (1 shl moLocCodes) <> 0; 1403 ShowDebug := pDebugMap >= 0; 1404 ShowObjects := (CityOwner >= 0) or 1405 (Options and (1 shl moBareTerrain) = 0); 1406 ShowCityNames := ShowObjects and (CityOwner < 0) and 1407 (Options and (1 shl moCityNames) <> 0); 1408 ShowBorder := true; 1409 ShowMyBorder := CityOwner < 0; 1410 ShowGrWall := (CityOwner < 0) and 1411 (Options and (1 shl moGreatWall) <> 0); 1412 if ShowDebug then 1413 Server(sGetDebugMap, me, pDebugMap, DebugMap) 1414 else 1415 DebugMap := nil; 1416 with FOutput.Canvas do 1417 begin 1418 RealTop := y - ((Loc + 12345 * G.lx) div G.lx - 12345) * yyt; 1419 RealBottom := y + 1420 (G.ly - ((Loc + 12345 * G.lx) div G.lx - 12345) + 3) * yyt; 1421 Brush.Color := EmptySpaceColor; 1422 if RealTop > FTop then 1423 FillRect(Rect(FLeft, FTop, FRight, RealTop)) 1424 else 1425 RealTop := FTop; 1426 if RealBottom < FBottom then 1427 FillRect(Rect(FLeft, RealBottom, FRight, FBottom)) 1428 else 1429 RealBottom := FBottom; 1430 Brush.Color := $000000; 1431 FillRect(Rect(FLeft, RealTop, FRight, RealBottom)); 1432 Brush.Style := bsClear; 1433 end; 1434 1435 for dy := 0 to ny + 1 do 1436 if (Loc + dy * G.lx >= 0) and (Loc + (dy - 3) * G.lx < G.lx * G.ly) 1437 then 1438 for dx := 0 to nx do 1439 begin 1440 ALoc := dLoc(Loc, dx - (dy + dx) and 1, dy - 2); 1441 BLoc := dLoc(Loc, dx - (dy + dx + 1) and 1, dy - 1); 1442 if (ALoc < 0) or (ALoc >= G.lx * G.ly) then 1443 ATer := PoleTile(ALoc) and fTerrain 1444 else 1445 ATer := MyMap[ALoc] and fTerrain; 1446 if (BLoc < 0) or (BLoc >= G.lx * G.ly) then 1447 BTer := PoleTile(BLoc) and fTerrain 1448 else 1449 BTer := MyMap[BLoc] and fTerrain; 1450 1451 if (ATer <> fUNKNOWN) or (BTer <> fUNKNOWN) then 1452 if ((ATer < fGrass) or (ATer = fUNKNOWN)) and 1453 ((BTer < fGrass) or (BTer = fUNKNOWN)) then 1454 begin 1455 if ATer = fUNKNOWN then 1456 Aix := 0 1457 else if IsShoreTile(ALoc) then 1458 if ATer = fOcean then 1459 Aix := -1 1460 else 1461 Aix := 1 1462 else 1463 Aix := ATer + 2; 1464 if BTer = fUNKNOWN then 1465 bix := 0 1466 else if IsShoreTile(BLoc) then 1467 if BTer = fOcean then 1468 bix := -1 1469 else 1470 bix := 1 1471 else 1472 bix := BTer + 2; 1473 if (Aix > 1) or (bix > 1) then 1474 begin 1475 if Aix = -1 then 1476 if bix = fOcean + 2 then 1477 begin 1478 Aix := 0; 1479 bix := 0 1480 end 1481 else 1482 begin 1483 Aix := 0; 1484 bix := 1 1485 end 1486 else if bix = -1 then 1487 if Aix = fOcean + 2 then 1488 begin 1489 Aix := 1; 1490 bix := 1 1491 end 1492 else 1493 begin 1494 Aix := 1; 1495 bix := 0 1496 end; 1497 BitBlt(OceanPatch, x + dx * xxt, y + dy * yyt, xxt, yyt, 1498 Aix * (xxt * 2) + (dx + dy + 1) and 1 * xxt, 1499 bix * yyt, SRCCOPY) 1500 end 1501 end 1502 else 1503 begin 1504 if ATer = fUNKNOWN then 1505 Aix := 0 1506 else if (ALoc >= 0) and (ALoc < G.lx * G.ly) and 1507 (MyMap[ALoc] and fDeadLands <> 0) then 1508 Aix := -2 1509 else if ATer = fOcean then 1510 Aix := -1 1511 else if ATer = fShore then 1512 Aix := 1 1513 else if ATer >= fForest then 1514 Aix := 8 1515 else 1516 Aix := ATer; 1517 if BTer = fUNKNOWN then 1518 bix := 0 1519 else if (BLoc >= 0) and (BLoc < G.lx * G.ly) and 1520 (MyMap[BLoc] and fDeadLands <> 0) then 1521 bix := -2 1522 else if BTer = fOcean then 1523 bix := -1 1524 else if BTer = fShore then 1525 bix := 1 1526 else if BTer >= fForest then 1527 bix := 8 1528 else 1529 bix := BTer; 1530 if (Aix = -2) and (bix = -2) then 1531 begin 1532 Aix := fDesert; 1533 bix := fDesert 1534 end 1535 else if Aix = -2 then 1536 if bix < 2 then 1537 Aix := 8 1538 else 1539 Aix := bix 1540 else if bix = -2 then 1541 if Aix < 2 then 1542 bix := 8 1543 else 1544 bix := Aix; 1545 if Aix = -1 then 1546 BitBlt(GrExt[HGrTerrain].Data, x + dx * xxt, y + dy * yyt, 1547 xxt, yyt, 1 + 6 * (xxt * 2 + 1) + (dx + dy + 1) and 1548 1 * xxt, 1 + yyt, SRCCOPY) // arctic <-> ocean 1549 else if bix = -1 then 1550 BitBlt(GrExt[HGrTerrain].Data, x + dx * xxt, y + dy * yyt, 1551 xxt, yyt, 1 + 6 * (xxt * 2 + 1) + xxt - (dx + dy + 1) 1552 and 1 * xxt, 1 + yyt * 2, SRCCOPY) // arctic <-> ocean 1553 else 1554 BitBlt(LandPatch, x + dx * xxt, y + dy * yyt, xxt, yyt, 1555 Aix * (xxt * 2) + (dx + dy + 1) and 1 * xxt, 1556 bix * yyt, SRCCOPY) 1557 end 1558 end; 1559 1560 OutDC := FOutput.Canvas.Handle; 1561 DataDC := GrExt[HGrTerrain].Data.Canvas.Handle; 1562 MaskDC := GrExt[HGrTerrain].Mask.Canvas.Handle; 1563 for dy := -2 to ny + 1 do 1564 for dx := -1 to nx do 1565 if (dx + dy) and 1 = 0 then 1566 PaintShore(x + xxt * dx, y + yyt + yyt * dy, dLoc(Loc, dx, dy)); 1567 for dy := -2 to ny + 1 do 1568 for dx := -1 to nx do 1569 if (dx + dy) and 1 = 0 then 1570 PaintTileExtraTerrain(x + xxt * dx, y + yyt + yyt * dy, 1571 dLoc(Loc, dx, dy)); 1572 if CityOwner >= 0 then 1573 begin 1574 for dy := -2 to ny + 1 do 1575 for dx := -2 to nx + 1 do 1576 if (dx + dy) and 1 = 0 then 1577 begin 1578 ALoc := dLoc(Loc, dx, dy); 1579 if Distance(ALoc, CityLoc) > 5 then 1580 PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy, ALoc, 1581 CityLoc, CityOwner, UseBlink); 1582 end; 1583 dx := ((CityLoc mod G.lx * 2 + CityLoc div G.lx and 1) - 1584 ((Loc + 666 * G.lx) mod G.lx * 2 + (Loc + 666 * G.lx) div G.lx and 1585 1) + 3 * G.lx) mod (2 * G.lx) - G.lx; 1586 dy := CityLoc div G.lx - (Loc + 666 * G.lx) div G.lx + 666; 1587 xm := x + (dx + 1) * xxt; 1588 ym := y + (dy + 1) * yyt + yyt; 1589 ShadeOutside(FLeft, FTop, FRight, FBottom, xm, ym); 1590 CityGrid(xm, ym); 1591 for dy := -2 to ny + 1 do 1592 for dx := -2 to nx + 1 do 1593 if (dx + dy) and 1 = 0 then 1594 begin 1595 ALoc := dLoc(Loc, dx, dy); 1596 if Distance(ALoc, CityLoc) <= 5 then 1597 PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy, ALoc, 1598 CityLoc, CityOwner, UseBlink); 1599 end; 1600 end 1601 else 1602 begin 1603 if ShowLoc or (Options and (1 shl moEditMode) <> 0) or 1604 (Options and (1 shl moGrid) <> 0) then 1605 PaintGrid(x, y, nx, ny); 1606 for dy := -2 to ny + 1 do 1607 for dx := -2 to nx + 1 do 1608 if (dx + dy) and 1 = 0 then 1609 PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy, 1610 dLoc(Loc, dx, dy), CityLoc, CityOwner, UseBlink); 1611 end; 1612 1613 // frame(FOutput.Canvas,x+1,y+1,x+nx*33+33-2,y+ny*16+32-2,$FFFF,$FFFF); 1614 end; { Paint } 1615 1616 procedure TIsoMap.AttackBegin(const ShowMove: TShowMove); 1617 begin 1618 AttLoc := ShowMove.FromLoc; 1619 DefLoc := dLoc(AttLoc, ShowMove.dx, ShowMove.dy); 1620 DefHealth := -1; 1621 end; 1622 1623 procedure TIsoMap.AttackEffect(const ShowMove: TShowMove); 1624 begin 1625 DefHealth := ShowMove.EndHealthDef; 1626 end; 1627 1628 procedure TIsoMap.AttackEnd; 1629 begin 1630 AttLoc := -1; 1631 DefLoc := -1; 1632 end; 1575 end 1576 else 1577 begin 1578 if ShowLoc or (Options and (1 shl moEditMode) <> 0) or 1579 (Options and (1 shl moGrid) <> 0) then 1580 PaintGrid(x, y, nx, ny); 1581 for dy := -2 to ny + 1 do 1582 for dx := -2 to nx + 1 do 1583 if (dx + dy) and 1 = 0 then 1584 PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy, dLoc(Loc, dx, dy), 1585 CityLoc, CityOwner, UseBlink); 1586 end; 1587 1588 // frame(FOutput.Canvas,x+1,y+1,x+nx*33+33-2,y+ny*16+32-2,$FFFF,$FFFF); 1589 end; { Paint } 1590 1591 procedure TIsoMap.AttackBegin(const ShowMove: TShowMove); 1592 begin 1593 AttLoc := ShowMove.FromLoc; 1594 DefLoc := dLoc(AttLoc, ShowMove.dx, ShowMove.dy); 1595 DefHealth := -1; 1596 end; 1597 1598 procedure TIsoMap.AttackEffect(const ShowMove: TShowMove); 1599 begin 1600 DefHealth := ShowMove.EndHealthDef; 1601 end; 1602 1603 procedure TIsoMap.AttackEnd; 1604 begin 1605 AttLoc := -1; 1606 DefLoc := -1; 1607 end; 1633 1608 1634 1609 initialization -
trunk/LocalPlayer/Term.pas
r29 r33 1 {$INCLUDE Switches.pas}1 {$INCLUDE Switches.pas} 2 2 unit Term; 3 3 … … 5 5 6 6 uses 7 7 {$IFDEF Windows} 8 8 Windows, 9 9 {$ENDIF} 10 10 Protocol, Tribes, PVSB, ClientTools, ScreenTools, BaseWin, Messg, ButtonBase, 11 11 12 LCLIntf, LCLType, LMessages, Messages, SysUtils, Classes, Graphics, Controls, Forms, Menus, 12 LCLIntf, LCLType, LMessages, Messages, SysUtils, Classes, Graphics, Controls, 13 Forms, Menus, 13 14 ExtCtrls, dateutils, Platform, 14 15 ButtonA, ButtonB, ButtonC, EOTButton, Area; … … 437 438 438 439 {$R *.lfm} 439 { TODO {$R Res1.res}440 { TODO {$R Res1.res } 440 441 441 442 const … … 737 738 function CreateTribe(p: integer; FileName: string; Original: boolean): boolean; 738 739 begin 739 if not FileExists(LocalizedFilePath('Tribes' + DirectorySeparator + FileName + '.tribe.txt')) then 740 if not FileExists(LocalizedFilePath('Tribes' + DirectorySeparator + FileName + 741 '.tribe.txt')) then 740 742 begin 741 743 result := false; … … 992 994 if DraftDlg.ModalResult <> mrOK then 993 995 Tribe[me].ModelPicture[MyRO.nModel].HGr := 0 996 end; 997 until (ChosenResearch <> adMilitary) or (DraftDlg.ModalResult = mrOK); 998 999 if ChosenResearch = adMilitary then 1000 InitMyModel(MyRO.nModel, true) 1001 else if ChosenResearch = adFar then 1002 begin 1003 ModalSelectDlg.ShowNewContent(wmModal, kFarAdvance); 1004 if ModalSelectDlg.result >= 0 then 1005 if (ModalSelectDlg.result = adNone) or 1006 (Server(sSetResearch - sExecute, me, ModalSelectDlg.result, nil^) < 1007 rExecuted) then 1008 MyData.FarTech := ModalSelectDlg.result 1009 else 1010 begin 1011 ChosenResearch := ModalSelectDlg.result; 1012 // can be researched immediately 1013 MyData.FarTech := adNone 1014 end; 1015 end; 1016 until ChosenResearch <> adFar; 1017 if ChosenResearch = adNexus then 1018 MyData.FarTech := adNexus 1019 else 1020 Server(sSetResearch, me, ChosenResearch, nil^); 1021 ListDlg.TechChange; 1022 result := true; 1023 end; 1024 1025 (* ** client function handling ** *) 1026 1027 function TMainScreen.DipCall(Command: integer): integer; 1028 var 1029 i: integer; 1030 IsTreatyDeal: boolean; 1031 begin 1032 result := Server(Command, me, 0, nil^); 1033 if result >= rExecuted then 1034 begin 1035 if Command and $FF0F = scContact then 1036 begin 1037 DipMem[me].pContact := Command shr 4 and $F; 1038 NegoDlg.Initiate; 1039 DipMem[me].DeliveredPrices := []; 1040 DipMem[me].ReceivedPrices := []; 1041 end; 1042 1043 DipMem[me].SentCommand := Command; 1044 DipMem[me].FormerTreaty := MyRO.Treaty[DipMem[me].pContact]; 1045 if Command = scDipCancelTreaty then 1046 Play('CANCELTREATY') 1047 else if Command = scDipAccept then 1048 begin // remember delivered and received prices 1049 for i := 0 to ReceivedOffer.nDeliver - 1 do 1050 include(DipMem[me].ReceivedPrices, ReceivedOffer.Price[i] shr 24); 1051 for i := 0 to ReceivedOffer.nCost - 1 do 1052 include(DipMem[me].DeliveredPrices, 1053 ReceivedOffer.Price[ReceivedOffer.nDeliver + i] shr 24); 1054 IsTreatyDeal := false; 1055 for i := 0 to ReceivedOffer.nDeliver + ReceivedOffer.nCost - 1 do 1056 if ReceivedOffer.Price[i] and opMask = opTreaty then 1057 IsTreatyDeal := true; 1058 if IsTreatyDeal then 1059 Play('NEWTREATY') 1060 else 1061 Play('ACCEPTOFFER'); 1062 end; 1063 CityDlg.CloseAction := None; 1064 if G.RO[DipMem[me].pContact] <> nil then 1065 begin // close windows for next player 1066 for i := 0 to Screen.FormCount - 1 do 1067 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 1068 then 1069 Screen.Forms[i].Close; 1070 end 1071 else 1072 begin 1073 if CityDlg.Visible then 1074 CityDlg.Close; 1075 if UnitStatDlg.Visible then 1076 UnitStatDlg.Close; 1077 end 1078 end 1079 end; 1080 1081 function TMainScreen.OfferCall(var Offer: TOffer): integer; 1082 var 1083 i: integer; 1084 begin 1085 result := Server(scDipOffer, me, 0, Offer); 1086 if result >= rExecuted then 1087 begin 1088 DipMem[me].SentCommand := scDipOffer; 1089 DipMem[me].FormerTreaty := MyRO.Treaty[DipMem[me].pContact]; 1090 DipMem[me].SentOffer := Offer; 1091 CityDlg.CloseAction := None; 1092 if G.RO[DipMem[me].pContact] <> nil then 1093 begin // close windows for next player 1094 for i := 0 to Screen.FormCount - 1 do 1095 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 1096 then 1097 Screen.Forms[i].Close; 1098 end 1099 else 1100 begin 1101 if CityDlg.Visible then 1102 CityDlg.Close; 1103 if UnitStatDlg.Visible then 1104 UnitStatDlg.Close; 1105 end 1106 end 1107 end; 1108 1109 procedure TMainScreen.SetUnFocus(uix: integer); 1110 var 1111 Loc0: integer; 1112 begin 1113 assert(not((uix >= 0) and supervising)); 1114 if uix <> UnFocus then 1115 begin 1116 DestinationMarkON := false; 1117 PaintDestination; 1118 if uix >= 0 then 1119 UnStartLoc := MyUn[uix].Loc; 1120 BlinkON := false; 1121 BlinkTime := -1; 1122 if UnFocus >= 0 then 1123 begin 1124 Loc0 := MyUn[UnFocus].Loc; 1125 if (uix < 0) or (Loc0 <> MyUn[uix].Loc) then 1126 begin 1127 UnFocus := -1; 1128 PaintLoc(Loc0); 994 1129 end 995 until (ChosenResearch <> adMilitary) or (DraftDlg.ModalResult = mrOK); 996 997 if ChosenResearch = adMilitary then 998 InitMyModel(MyRO.nModel, true) 999 else if ChosenResearch = adFar then 1000 begin 1001 ModalSelectDlg.ShowNewContent(wmModal, kFarAdvance); 1002 if ModalSelectDlg.result >= 0 then 1003 if (ModalSelectDlg.result = adNone) or 1004 (Server(sSetResearch - sExecute, me, ModalSelectDlg.result, nil^) < 1005 rExecuted) then 1006 MyData.FarTech := ModalSelectDlg.result 1130 end; 1131 UnFocus := uix; 1132 end; 1133 UnitInfoBtn.Visible := UnFocus >= 0; 1134 UnitBtn.Visible := UnFocus >= 0; 1135 CheckTerrainBtnVisible; 1136 end; 1137 1138 procedure TMainScreen.CheckTerrainBtnVisible; 1139 var 1140 Tile: integer; 1141 mox: ^TModel; 1142 begin 1143 if UnFocus >= 0 then 1144 begin 1145 mox := @MyModel[MyUn[UnFocus].mix]; 1146 Tile := MyMap[MyUn[UnFocus].Loc]; 1147 TerrainBtn.Visible := (Tile and fCity = 0) and (MyUn[UnFocus].Master < 0) 1148 and ((mox.Kind = mkSettler) or (mox.Kind = mkSlaves) and 1149 (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)); 1150 end 1151 else 1152 TerrainBtn.Visible := false; 1153 end; 1154 1155 procedure TMainScreen.CheckMovieSpeedBtnState; 1156 begin 1157 if GameMode = cMovie then 1158 begin 1159 MovieSpeed1Btn.Down := MovieSpeed = 1; 1160 MovieSpeed1Btn.Visible := true; 1161 MovieSpeed2Btn.Down := MovieSpeed = 2; 1162 MovieSpeed2Btn.Visible := true; 1163 MovieSpeed3Btn.Down := MovieSpeed = 3; 1164 MovieSpeed3Btn.Visible := true; 1165 MovieSpeed4Btn.Down := MovieSpeed = 4; 1166 MovieSpeed4Btn.Visible := true; 1167 end 1168 else 1169 begin 1170 MovieSpeed1Btn.Visible := false; 1171 MovieSpeed2Btn.Visible := false; 1172 MovieSpeed3Btn.Visible := false; 1173 MovieSpeed4Btn.Visible := false; 1174 end 1175 end; 1176 1177 procedure TMainScreen.SetMapOptions; 1178 begin 1179 IsoEngine.Options := MapOptionChecked; 1180 if ClientMode = cEditMap then 1181 IsoEngine.Options := IsoEngine.Options or (1 shl moEditMode); 1182 if mLocCodes.Checked then 1183 IsoEngine.Options := IsoEngine.Options or (1 shl moLocCodes); 1184 end; 1185 1186 procedure TMainScreen.UpdateViews(UpdateCityScreen: boolean); 1187 begin 1188 SumCities(TaxSum, ScienceSum); 1189 PanelPaint; // TopBar was enough!!! 1190 ListDlg.EcoChange; 1191 NatStatDlg.EcoChange; 1192 if UpdateCityScreen then 1193 CityDlg.SmartUpdateContent; 1194 end; 1195 1196 procedure TMainScreen.SetAIName(p: integer; Name: string); 1197 begin 1198 if Name = '' then 1199 begin 1200 if AILogo[p] <> nil then 1201 begin 1202 AILogo[p].free; 1203 AILogo[p] := nil 1204 end 1205 end 1206 else 1207 begin 1208 if AILogo[p] = nil then 1209 AILogo[p] := TBitmap.Create; 1210 if not LoadGraphicFile(AILogo[p], HomeDir + Name, gfNoError) then 1211 begin 1212 AILogo[p].free; 1213 AILogo[p] := nil 1214 end 1215 end 1216 end; 1217 1218 function TMainScreen.ContactRefused(p: integer; Item: String): boolean; 1219 // return whether treaty was cancelled 1220 var 1221 s: string; 1222 begin 1223 assert(MyRO.Treaty[p] >= trPeace); 1224 s := Tribe[p].TPhrase(Item); 1225 if MyRO.Turn < MyRO.LastCancelTreaty[p] + CancelTreatyTurns then 1226 begin 1227 SimpleMessage(s); 1228 result := false; 1229 end 1230 else 1231 begin 1232 case MyRO.Treaty[p] of 1233 trPeace: 1234 s := s + ' ' + Phrases.Lookup('FRCANCELQUERY_PEACE'); 1235 trFriendlyContact: 1236 s := s + ' ' + Phrases.Lookup('FRCANCELQUERY_FRIENDLY'); 1237 trAlliance: 1238 s := s + ' ' + Phrases.Lookup('FRCANCELQUERY_ALLIANCE'); 1239 end; 1240 result := SimpleQuery(mkYesNo, s, 'NEGO_REJECTED') = mrOK; 1241 if result then 1242 begin 1243 Play('CANCELTREATY'); 1244 Server(sCancelTreaty, me, 0, nil^); 1245 if MyRO.Treaty[p] = trNone then 1246 CityOptimizer_BeginOfTurn; 1247 // peace treaty was cancelled -- use formerly forbidden tiles 1248 MapValid := false; 1249 PaintAllMaps; 1250 end 1251 end 1252 end; 1253 1254 procedure TMainScreen.RememberPeaceViolation; 1255 var 1256 uix, p1: integer; 1257 begin 1258 MyData.PeaceEvaHappened := 0; 1259 for uix := 0 to MyRO.nUn - 1 do 1260 with MyUn[uix] do 1261 if Loc >= 0 then 1262 begin 1263 p1 := MyRO.Territory[Loc]; 1264 if (p1 <> me) and (p1 >= 0) and 1265 (MyRO.Turn = MyRO.EvaStart[p1] + (PeaceEvaTurns - 1)) then 1266 MyData.PeaceEvaHappened := MyData.PeaceEvaHappened or (1 shl p1); 1267 end; 1268 end; 1269 1270 procedure TMainScreen.Client(Command, NewPlayer: integer; var Data); 1271 1272 procedure GetTribeList; 1273 var 1274 SearchRec: TSearchRec; 1275 Color: TColor; 1276 Name: string; 1277 ok: boolean; 1278 begin 1279 UnusedTribeFiles.Clear; 1280 ok := FindFirst(DataDir + 'Localization' + DirectorySeparator + 'Tribes' + 1281 DirectorySeparator + '*.tribe.txt', faArchive + faReadOnly, 1282 SearchRec) = 0; 1283 if not ok then 1284 begin 1285 FindClose(SearchRec); 1286 ok := FindFirst(HomeDir + 'Tribes' + DirectorySeparator + '*.tribe.txt', 1287 faArchive + faReadOnly, SearchRec) = 0; 1288 end; 1289 if ok then 1290 repeat 1291 SearchRec.Name := Copy(SearchRec.Name, 1, Length(SearchRec.Name) - 10); 1292 if GetTribeInfo(SearchRec.Name, Name, Color) then 1293 UnusedTribeFiles.AddObject(SearchRec.Name, TObject(Color)); 1294 until FindNext(SearchRec) <> 0; 1295 FindClose(SearchRec); 1296 end; 1297 1298 function ChooseUnusedTribe: integer; 1299 var 1300 i, j, ColorDistance, BestColorDistance, TestColorDistance, 1301 CountBest: integer; 1302 begin 1303 assert(UnusedTribeFiles.Count > 0); 1304 result := -1; 1305 BestColorDistance := -1; 1306 for j := 0 to UnusedTribeFiles.Count - 1 do 1307 begin 1308 ColorDistance := 250; // consider differences more than this infinite 1309 for i := 0 to nPl - 1 do 1310 if Tribe[i] <> nil then 1311 begin 1312 TestColorDistance := abs(integer(UnusedTribeFiles.Objects[j]) 1313 shr 16 and $FF - Tribe[i].Color shr 16 and $FF) + 1314 abs(integer(UnusedTribeFiles.Objects[j]) shr 8 and 1315 $FF - Tribe[i].Color shr 8 and $FF) * 3 + 1316 abs(integer(UnusedTribeFiles.Objects[j]) and 1317 $FF - Tribe[i].Color and $FF) * 2; 1318 if TestColorDistance < ColorDistance then 1319 ColorDistance := TestColorDistance 1320 end; 1321 if ColorDistance > BestColorDistance then 1322 begin 1323 CountBest := 0; 1324 BestColorDistance := ColorDistance 1325 end; 1326 if ColorDistance = BestColorDistance then 1327 begin 1328 inc(CountBest); 1329 if random(CountBest) = 0 then 1330 result := j 1331 end 1332 end; 1333 end; 1334 1335 procedure ShowEnemyShipChange(ShowShipChange: TShowShipChange); 1336 var 1337 i, TestCost, MostCost: integer; 1338 Ship1Plus, Ship2Plus: boolean; 1339 begin 1340 with ShowShipChange, MessgExDlg do 1341 begin 1342 case Reason of 1343 scrProduction: 1344 begin 1345 OpenSound := 'SHIP_BUILT'; 1346 MessgText := Tribe[Ship1Owner].TPhrase('SHIPBUILT'); 1347 IconKind := mikShip; 1348 IconIndex := Ship1Owner; 1349 end; 1350 1351 scrDestruction: 1352 begin 1353 OpenSound := 'SHIP_DESTROYED'; 1354 MessgText := Tribe[Ship1Owner].TPhrase('SHIPDESTROYED'); 1355 IconKind := mikImp; 1356 end; 1357 1358 scrTrade: 1359 begin 1360 OpenSound := 'SHIP_TRADED'; 1361 Ship1Plus := false; 1362 Ship2Plus := false; 1363 for i := 0 to nShipPart - 1 do 1364 begin 1365 if Ship1Change[i] > 0 then 1366 Ship1Plus := true; 1367 if Ship2Change[i] > 0 then 1368 Ship2Plus := true; 1369 end; 1370 if Ship1Plus and Ship2Plus then 1371 MessgText := Tribe[Ship1Owner].TPhrase('SHIPBITRADE1') + ' ' + 1372 Tribe[Ship2Owner].TPhrase('SHIPBITRADE2') 1373 else if Ship1Plus then 1374 MessgText := Tribe[Ship1Owner].TPhrase('SHIPUNITRADE1') + ' ' + 1375 Tribe[Ship2Owner].TPhrase('SHIPUNITRADE2') 1376 else // if Ship2Plus then 1377 MessgText := Tribe[Ship2Owner].TPhrase('SHIPUNITRADE1') + ' ' + 1378 Tribe[Ship1Owner].TPhrase('SHIPUNITRADE2'); 1379 IconKind := mikImp; 1380 end; 1381 1382 scrCapture: 1383 begin 1384 OpenSound := 'SHIP_CAPTURED'; 1385 MessgText := Tribe[Ship2Owner].TPhrase('SHIPCAPTURE1') + ' ' + 1386 Tribe[Ship1Owner].TPhrase('SHIPCAPTURE2'); 1387 IconKind := mikShip; 1388 IconIndex := Ship2Owner; 1389 end 1390 end; 1391 1392 if IconKind = mikImp then 1393 begin 1394 MostCost := 0; 1395 for i := 0 to nShipPart - 1 do 1396 begin 1397 TestCost := abs(Ship1Change[i]) * Imp[imShipComp + i].Cost; 1398 if TestCost > MostCost then 1399 begin 1400 MostCost := TestCost; 1401 IconIndex := imShipComp + i 1402 end 1403 end; 1404 end; 1405 1406 Kind := mkOk; 1407 ShowModal; 1408 end; 1409 end; 1410 1411 procedure InitModule; 1412 var 1413 x, y, i, j, Domain: integer; 1414 begin 1415 { search icons for advances: } 1416 for i := 0 to nAdv - 1 do 1417 if i in FutureTech then 1418 AdvIcon[i] := 96 + i - futResearchTechnology 1419 else 1420 begin 1421 AdvIcon[i] := -1; 1422 for Domain := 0 to nDomains - 1 do 1423 for j := 0 to nUpgrade - 1 do 1424 if upgrade[Domain, j].Preq = i then 1425 if AdvIcon[i] >= 0 then 1426 AdvIcon[i] := 85 1427 else 1428 AdvIcon[i] := 86 + Domain; 1429 for j := 0 to nFeature - 1 do 1430 if Feature[j].Preq = i then 1431 for Domain := 0 to nDomains - 1 do 1432 if 1 shl Domain and Feature[j].Domains <> 0 then 1433 if (AdvIcon[i] >= 0) and (AdvIcon[i] <> 86 + Domain) then 1434 AdvIcon[i] := 85 1435 else 1436 AdvIcon[i] := 86 + Domain; 1437 for j := 28 to nImp - 1 do 1438 if Imp[j].Preq = i then 1439 AdvIcon[i] := j; 1440 for j := 28 to nImp - 1 do 1441 if (Imp[j].Preq = i) and (Imp[j].Kind <> ikCommon) then 1442 AdvIcon[i] := j; 1443 for j := 0 to nJob - 1 do 1444 if i = JobPreq[j] then 1445 AdvIcon[i] := 84; 1446 for j := 0 to 27 do 1447 if Imp[j].Preq = i then 1448 AdvIcon[i] := j; 1449 if AdvIcon[i] < 0 then 1450 if AdvValue[i] < 1000 then 1451 AdvIcon[i] := -7 1452 else 1453 AdvIcon[i] := 24 + AdvValue[i] div 1000; 1454 for j := 2 to nGov - 1 do 1455 if GovPreq[j] = i then 1456 AdvIcon[i] := j - 8; 1457 end; 1458 AdvIcon[adConscription] := 86 + dGround; 1459 1460 UnusedTribeFiles := tstringlist.Create; 1461 UnusedTribeFiles.Sorted := true; 1462 TribeNames := tstringlist.Create; 1463 1464 for x := 0 to 11 do 1465 for y := 0 to 1 do 1466 MiniColors[x, y] := GrExt[HGrSystem].Data.Canvas.Pixels[66 + x, 67 + y]; 1467 IsoEngine.Init(InitEnemyModel); 1468 if not IsoEngine.ApplyTileSize(xxt, yyt) and ((xxt <> 48) or (yyt <> 24)) 1469 then 1470 ApplyTileSize(48, 24); 1471 // non-default tile size is missing a file, switch to default 1472 MainMap := TIsoMap.Create; 1473 MainMap.SetOutput(offscreen); 1474 1475 HGrStdUnits := LoadGraphicSet('StdUnits'); 1476 SmallImp := TBitmap.Create; 1477 SmallImp.PixelFormat := pf24bit; 1478 InitSmallImp; 1479 SoundPreloadDone := 0; 1480 StartRunning := false; 1481 StayOnTop_Ensured := false; 1482 1483 CreatePVSB(sb, Handle, 100 - 200, 122, 100 + MidPanelHeight - 16 - 200); 1484 end; { InitModule } 1485 1486 // sound blocks for preload 1487 const 1488 sbStart = $01; 1489 sbWonder = $02; 1490 sbScience = $04; 1491 sbContact = $08; 1492 sbTurn = $10; 1493 sbAll = $FF; 1494 1495 procedure SoundPreload(Check: integer); 1496 const 1497 nStartBlock = 27; 1498 StartBlock: array [0 .. nStartBlock - 1] of string = ('INVALID', 'TURNEND', 1499 'DISBAND', 'CHEAT', 'MSG_DEFAULT', 'WARNING_DISORDER', 'WARNING_FAMINE', 1500 'WARNING_LOWSUPPORT', 'WARNING_LOWFUNDS', 'MOVE_MOUNTAIN', 'MOVE_LOAD', 1501 'MOVE_UNLOAD', 'MOVE_DIE', 'NOMOVE_TIME', 'NOMOVE_DOMAIN', 1502 'NOMOVE_DEFAULT', 'CITY_SELLIMP', 'CITY_REBUILDIMP', 'CITY_BUYPROJECT', 1503 'CITY_UTILIZE', 'NEWMODEL_0', 'NEWADVANCE_0', 'AGE_0', 'REVOLUTION', 1504 'NEWGOV', 'CITY_INVALIDTYPE', 'MSG_GAMEOVER'); 1505 1506 nWonderBlock = 6; 1507 WonderBlock: array [0 .. nWonderBlock - 1] of string = ('WONDER_BUILT', 1508 'WONDER_CAPTURED', 'WONDER_EXPIRED', 'WONDER_DESTROYED', 'MSG_COLDWAR', 1509 'NEWADVANCE_GRLIB'); 1510 1511 nScienceBlock = 17; 1512 ScienceBlock: array [0 .. nScienceBlock - 1] of string = ('MOVE_PARACHUTE', 1513 'MOVE_PLANESTART', 'MOVE_PLANELANDING', 'MOVE_COVERT', 'NEWMODEL_1', 1514 'NEWMODEL_2', 'NEWMODEL_3', 'NEWADVANCE_1', 'NEWADVANCE_2', 1515 'NEWADVANCE_3', 'AGE_1', 'AGE_2', 'AGE_3', 'SHIP_BUILT', 'SHIP_TRADED', 1516 'SHIP_CAPTURED', 'SHIP_DESTROYED'); 1517 1518 nContactBlock = 20; 1519 ContactBlock: array [0 .. nContactBlock - 1] of string = ('NEWTREATY', 1520 'CANCELTREATY', 'ACCEPTOFFER', 'MSG_WITHDRAW', 'MSG_BANKRUPT', 1521 'CONTACT_0', 'CONTACT_1', 'CONTACT_2', 'CONTACT_3', 'CONTACT_4', 1522 'CONTACT_5', 'CONTACT_5', 'CONTACT_6', 'NEGO_REJECTED', 'MOVE_CAPTURE', 1523 'MOVE_EXPEL', 'NOMOVE_TREATY', 'NOMOVE_ZOC', 'NOMOVE_SUBMARINE', 1524 'NOMOVE_STEALTH'); 1525 1526 var 1527 i, cix, mix: integer; 1528 need: boolean; 1529 mi: TModelInfo; 1530 begin 1531 if Check and sbStart and not SoundPreloadDone <> 0 then 1532 begin 1533 for i := 0 to nStartBlock - 1 do 1534 PreparePlay(StartBlock[i]); 1535 SoundPreloadDone := SoundPreloadDone or sbStart; 1536 end; 1537 if Check and sbWonder and not SoundPreloadDone <> 0 then 1538 begin 1539 need := false; 1540 for i := 0 to 27 do 1541 if MyRO.Wonder[i].CityID <> -1 then 1542 need := true; 1543 if need then 1544 begin 1545 for i := 0 to nWonderBlock - 1 do 1546 PreparePlay(WonderBlock[i]); 1547 SoundPreloadDone := SoundPreloadDone or sbWonder; 1548 end; 1549 end; 1550 if (Check and sbScience and not SoundPreloadDone <> 0) and 1551 (MyRO.Tech[adScience] >= tsApplicable) then 1552 begin 1553 for i := 0 to nScienceBlock - 1 do 1554 PreparePlay(ScienceBlock[i]); 1555 SoundPreloadDone := SoundPreloadDone or sbScience; 1556 end; 1557 if (Check and sbContact and not SoundPreloadDone <> 0) and 1558 (MyRO.nEnemyModel + MyRO.nEnemyCity > 0) then 1559 begin 1560 for i := 0 to nContactBlock - 1 do 1561 PreparePlay(ContactBlock[i]); 1562 SoundPreloadDone := SoundPreloadDone or sbContact; 1563 end; 1564 if Check and sbTurn <> 0 then 1565 begin 1566 if MyRO.Happened and phShipComplete <> 0 then 1567 PreparePlay('MSG_YOUWIN'); 1568 if MyData.ToldAlive <> MyRO.Alive then 1569 PreparePlay('MSG_EXTINCT'); 1570 for cix := 0 to MyRO.nCity - 1 do 1571 with MyCity[cix] do 1572 if (Loc >= 0) and (Flags and CityRepMask <> 0) then 1573 for i := 0 to 12 do 1574 if 1 shl i and Flags and CityRepMask <> 0 then 1575 PreparePlay(CityEventSoundItem[i]); 1576 for mix := 0 to MyRO.nModel - 1 do 1577 with MyModel[mix] do 1578 if Attack > 0 then 1579 begin 1580 MakeModelInfo(me, mix, MyModel[mix], mi); 1581 PreparePlay(AttackSound(ModelCode(mi))); 1582 end 1583 end 1584 end; 1585 1586 procedure InitTurn(p: integer); 1587 const 1588 nAdvBookIcon = 16; 1589 AdvBookIcon: array [0 .. nAdvBookIcon - 1] of record Adv, 1590 Icon: integer end = ((Adv: adPolyTheism; Icon: woZeus), 1591 (Adv: adBronzeWorking; Icon: woColossus), (Adv: adMapMaking; 1592 Icon: woLighthouse), (Adv: adPoetry; Icon: imTheater), (Adv: adMonotheism; 1593 Icon: woMich), (Adv: adPhilosophy; Icon: woLeo), (Adv: adTheoryOfGravity; 1594 Icon: woNewton), (Adv: adSteel; Icon: woEiffel), (Adv: adDemocracy; 1595 Icon: woLiberty), (Adv: adAutomobile; Icon: imHighways), 1596 (Adv: adSanitation; Icon: imSewer), (Adv: adElectronics; Icon: woHoover), 1597 (Adv: adNuclearFission; Icon: woManhattan), (Adv: adRecycling; 1598 Icon: imRecycling), (Adv: adComputers; Icon: imResLab), 1599 (Adv: adSpaceFlight; Icon: woMIR)); 1600 var 1601 Domain, p1, i, ad, uix, cix, MoveOptions, MoveResult, Loc1, Dist, 1602 NewAgeCenterTo, Bankrupt, ShipMore, Winners, NewGovAvailable, dx, 1603 dy: integer; 1604 MoveAdviceData: TMoveAdviceData; 1605 Picture: TModelPictureInfo; 1606 s, Item, Item2: string; 1607 UpdatePanel, OwnWonder, ok, Stop, ShowCityList, WondersOnly, 1608 AllowCityScreen: boolean; 1609 begin 1610 if IsMultiPlayerGame and (p <> me) then 1611 begin 1612 UnitInfoBtn.Visible := false; 1613 UnitBtn.Visible := false; 1614 TerrainBtn.Visible := false; 1615 EOT.Visible := false; 1616 end; 1617 if IsMultiPlayerGame and (p <> me) and 1618 (G.RO[0].Happened and phShipComplete = 0) then 1619 begin // inter player screen 1620 for i := 0 to ControlCount - 1 do 1621 if Controls[i] is TButtonC then 1622 Controls[i].Visible := false; 1623 me := -1; 1624 SetMainTextureByAge(-1); 1625 with Panel.Canvas do 1626 begin 1627 Brush.Color := $000000; 1628 FillRect(Rect(0, 0, Panel.width, Panel.height)); 1629 Brush.Style := bsClear; 1630 end; 1631 with TopBar.Canvas do 1632 begin 1633 Brush.Color := $000000; 1634 FillRect(Rect(0, 0, TopBar.width, TopBar.height)); 1635 Brush.Style := bsClear; 1636 end; 1637 Invalidate; 1638 1639 s := TurnToString(G.RO[0].Turn); 1640 if supervising then 1641 SimpleMessage(Format(Phrases.Lookup('SUPERTURN'), [s])) 1642 else 1643 SimpleMessage(Format(Tribe[NewPlayer].TPhrase('TURN'), [s])); 1644 end; 1645 for i := 0 to ControlCount - 1 do 1646 if Controls[i] is TButtonC then 1647 Controls[i].Visible := true; 1648 1649 ItsMeAgain(p); 1650 MyData := G.RO[p].Data; 1651 if not supervising then 1652 SoundPreload(sbAll); 1653 if (me = 0) and ((MyRO.Turn = 0) or (ClientMode = cResume)) then 1654 Invalidate; // colorize empty space 1655 1656 if not supervising then 1657 begin 1658 1659 { if MyRO.Happened and phGameEnd<>0 then 1660 begin 1661 Age:=3; 1662 SetMainTextureByAge(-1); 1663 end 1664 else } 1665 begin 1666 Age := GetAge(me); 1667 if SetMainTextureByAge(Age) then 1668 EOT.Invalidate; // has visible background parts in its bounds 1669 end; 1670 // age:=MyRO.Turn mod 4; //!!! 1671 if ClientMode = cMovieTurn then 1672 EOT.ButtonIndex := eotCancel 1673 else if ClientMode < scContact then 1674 EOT.ButtonIndex := eotGray 1675 else 1676 EOT.ButtonIndex := eotBackToNego; 1677 end 1678 else 1679 begin 1680 Age := 0; 1681 SetMainTextureByAge(-1); 1682 if ClientMode = cMovieTurn then 1683 EOT.ButtonIndex := eotCancel 1684 else 1685 EOT.ButtonIndex := eotBlinkOn; 1686 end; 1687 InitCityMark(MainTexture); 1688 CityDlg.CheckAge; 1689 NatStatDlg.CheckAge; 1690 UnitStatDlg.CheckAge; 1691 HelpDlg.Difficulty := G.Difficulty[me]; 1692 1693 UnFocus := -1; 1694 MarkCityLoc := -1; 1695 BlinkON := false; 1696 BlinkTime := -1; 1697 Tracking := false; 1698 TurnComplete := false; 1699 1700 if (ToldSlavery < 0) or 1701 ((ToldSlavery = 1) <> (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)) then 1702 begin 1703 if MyRO.Wonder[woPyramids].EffectiveOwner >= 0 then 1704 ToldSlavery := 1 1705 else 1706 ToldSlavery := 0; 1707 for p1 := 0 to nPl - 1 do 1708 if (Tribe[p1] <> nil) and (Tribe[p1].mixSlaves >= 0) then 1709 with Picture do 1710 begin // replace unit picture 1711 mix := Tribe[p1].mixSlaves; 1712 if ToldSlavery = 1 then 1713 pix := pixSlaves 1714 else 1715 pix := pixNoSlaves; 1716 Hash := 0; 1717 GrName := 'StdUnits'; 1718 Tribe[p1].SetModelPicture(Picture, true); 1719 end 1720 end; 1721 1722 if not supervising and (ClientMode = cTurn) then 1723 begin 1724 for cix := 0 to MyRO.nCity - 1 do 1725 if (MyCity[cix].Loc >= 0) and 1726 ((MyRO.Turn = 0) or (MyCity[cix].Flags and chFounded <> 0)) then 1727 MyCity[cix].Status := MyCity[cix].Status and 1728 not csResourceWeightsMask or (3 shl 4); 1729 // new city, set to maximum growth 1730 end; 1731 if (ClientMode = cTurn) or (ClientMode = cContinue) then 1732 CityOptimizer_BeginOfTurn; // maybe peace was made or has ended 1733 SumCities(TaxSum, ScienceSum); 1734 1735 if ClientMode = cMovieTurn then 1736 begin 1737 UnitInfoBtn.Visible := false; 1738 UnitBtn.Visible := false; 1739 TerrainBtn.Visible := false; 1740 EOT.Hint := Phrases.Lookup('BTN_STOP'); 1741 EOT.Visible := true; 1742 end 1743 else if ClientMode < scContact then 1744 begin 1745 UnitInfoBtn.Visible := UnFocus >= 0; 1746 UnitBtn.Visible := UnFocus >= 0; 1747 CheckTerrainBtnVisible; 1748 TurnComplete := supervising; 1749 EOT.Hint := Phrases.Lookup('BTN_ENDTURN'); 1750 EOT.Visible := Server(sTurn - sExecute, me, 0, nil^) >= rExecuted; 1751 end 1752 else 1753 begin 1754 UnitInfoBtn.Visible := false; 1755 UnitBtn.Visible := false; 1756 TerrainBtn.Visible := false; 1757 EOT.Hint := Phrases.Lookup('BTN_NEGO'); 1758 EOT.Visible := true; 1759 end; 1760 SetTroopLoc(-1); 1761 MapValid := false; 1762 NewAgeCenterTo := 0; 1763 if ((MyRO.Turn = 0) and not supervising or IsMultiPlayerGame or 1764 (ClientMode = cResume)) and (MyRO.nCity > 0) then 1765 begin 1766 Loc1 := MyCity[0].Loc; 1767 if (ClientMode = cTurn) and (MyRO.Turn = 0) then 1768 begin // move city out of center to not be covered by welcome screen 1769 dx := MapWidth div (xxt * 5); 1770 if dx > 5 then 1771 dx := 5; 1772 dy := MapHeight div (yyt * 5); 1773 if dy > 5 then 1774 dy := 5; 1775 if Loc1 >= G.lx * G.ly div 2 then 1776 begin 1777 NewAgeCenterTo := -1; 1778 Loc1 := dLoc(Loc1, -dx, -dy) 1779 end 1780 else 1781 begin 1782 NewAgeCenterTo := 1; 1783 Loc1 := dLoc(Loc1, -dx, dy); 1784 end 1785 end; 1786 Centre(Loc1) 1787 end; 1788 1789 for i := 0 to Screen.FormCount - 1 do 1790 if Screen.Forms[i] is TBufferedDrawDlg then 1791 Screen.Forms[i].Enabled := true; 1792 1793 if ClientMode <> cResume then 1794 begin 1795 PaintAll; 1796 if (MyRO.Happened and phChangeGov <> 0) and (MyRO.NatBuilt[imPalace] > 0) 1797 then 1798 ImpImage(Panel.Canvas, ClientWidth - xPalace, yPalace, imPalace, 1799 gAnarchy { , GameMode<>cMovie } ); 1800 // first turn after anarchy -- don't show despotism palace! 1801 Update; 1802 for i := 0 to Screen.FormCount - 1 do 1803 if (Screen.Forms[i].Visible) and (Screen.Forms[i] is TBufferedDrawDlg) 1804 then 1805 begin 1806 if @Screen.Forms[i].OnShow <> nil then 1807 Screen.Forms[i].OnShow(nil); 1808 Screen.Forms[i].Invalidate; 1809 Screen.Forms[i].Update; 1810 end; 1811 1812 if MyRO.Happened and phGameEnd <> 0 then 1813 with MessgExDlg do 1814 begin // game ended 1815 if MyRO.Happened and phExtinct <> 0 then 1816 begin 1817 OpenSound := 'MSG_GAMEOVER'; 1818 MessgText := Tribe[me].TPhrase('GAMEOVER'); 1819 IconKind := mikBigIcon; 1820 IconIndex := 8; 1821 end 1822 else if MyRO.Happened and phShipComplete <> 0 then 1823 begin 1824 Winners := 0; 1825 for p1 := 0 to nPl - 1 do 1826 if 1 shl p1 and MyRO.Alive <> 0 then 1827 begin 1828 Winners := Winners or 1 shl p1; 1829 for i := 0 to nShipPart - 1 do 1830 if MyRO.Ship[p1].Parts[i] < ShipNeed[i] then 1831 Winners := Winners and not(1 shl p1); 1832 end; 1833 assert(Winners <> 0); 1834 if Winners and (1 shl me) <> 0 then 1835 begin 1836 s := ''; 1837 for p1 := 0 to nPl - 1 do 1838 if (p1 <> me) and (1 shl p1 and Winners <> 0) then 1839 if s = '' then 1840 s := Tribe[p1].TPhrase('SHORTNAME') 1841 else 1842 s := Format(Phrases.Lookup('SHAREDWIN_CONCAT'), 1843 [s, Tribe[p1].TPhrase('SHORTNAME')]); 1844 1845 OpenSound := 'MSG_YOUWIN'; 1846 MessgText := Tribe[me].TPhrase('MYSPACESHIP'); 1847 if s <> '' then 1848 MessgText := MessgText + '\' + 1849 Format(Phrases.Lookup('SHAREDWIN'), [s]); 1850 IconKind := mikBigIcon; 1851 IconIndex := 9; 1852 end 1853 else 1854 begin 1855 assert(me = 0); 1856 OpenSound := 'MSG_GAMEOVER'; 1857 MessgText := ''; 1858 for p1 := 0 to nPl - 1 do 1859 if Winners and (1 shl p1) <> 0 then 1860 MessgText := MessgText + Tribe[p1].TPhrase('SPACESHIP1'); 1861 MessgText := MessgText + '\' + Phrases.Lookup('SPACESHIP2'); 1862 IconKind := mikEnemyShipComplete; 1863 end 1864 end 1865 else { if MyRO.Happened and fTimeUp<>0 then } 1866 begin 1867 assert(me = 0); 1868 OpenSound := 'MSG_GAMEOVER'; 1869 if not supervising then 1870 MessgText := Tribe[me].TPhrase('TIMEUP') 1871 else 1872 MessgText := Phrases.Lookup('TIMEUPSUPER'); 1873 IconKind := mikImp; 1874 IconIndex := 22; 1875 end; 1876 Kind := mkOk; 1877 ShowModal; 1878 if MyRO.Happened and phExtinct = 0 then 1879 begin 1880 p1 := 0; 1881 while (p1 < nPl - 1) and (Winners and (1 shl p1) = 0) do 1882 inc(p1); 1883 if MyRO.Happened and phShipComplete = 0 then 1884 DiaDlg.ShowNewContent_Charts(wmModal); 1885 end; 1886 TurnComplete := true; 1887 exit; 1888 end; 1889 if not supervising and (1 shl me and MyRO.Alive = 0) then 1890 begin 1891 TurnComplete := true; 1892 exit; 1893 end; 1894 1895 if (ClientMode = cContinue) and 1896 (DipMem[me].SentCommand and $FF0F = scContact) then 1897 // contact was refused 1898 if MyRO.Treaty[DipMem[me].pContact] >= trPeace then 1899 ContactRefused(DipMem[me].pContact, 'FRREJECTED') 1900 else 1901 SoundMessage(Tribe[DipMem[me].pContact].TPhrase('FRREJECTED'), 1902 'NEGO_REJECTED'); 1903 1904 if not supervising and (Age > MyData.ToldAge) and 1905 ((Age > 0) or (ClientMode <> cMovieTurn)) then 1906 with MessgExDlg do 1907 begin 1908 if Age = 0 then 1909 begin 1910 if Phrases2FallenBackToEnglish then 1911 begin 1912 s := Tribe[me].TPhrase('AGE0'); 1913 MessgText := 1914 Format(s, [TurnToString(MyRO.Turn), CityName(MyCity[0].ID)]) 1915 end 1916 else 1917 begin 1918 s := Tribe[me].TString(Phrases2.Lookup('AGE0')); 1919 MessgText := Format(s, [TurnToString(MyRO.Turn)]); 1920 end 1921 end 1007 1922 else 1008 1923 begin 1009 ChosenResearch := ModalSelectDlg.result; 1010 // can be researched immediately 1011 MyData.FarTech := adNone 1924 s := Tribe[me].TPhrase('AGE' + char(48 + Age)); 1925 MessgText := Format(s, [TurnToString(MyRO.Turn)]); 1926 end; 1927 IconKind := mikAge; 1928 IconIndex := Age; 1929 { if age=0 then } Kind := mkOk 1930 { else begin Kind:=mkOkHelp; HelpKind:=hkAdv; HelpNo:=AgePreq[age]; end }; 1931 CenterTo := NewAgeCenterTo; 1932 OpenSound := 'AGE_' + char(48 + Age); 1933 ShowModal; 1934 MyData.ToldAge := Age; 1935 if Age > 0 then 1936 MyData.ToldTech[AgePreq[Age]] := MyRO.Tech[AgePreq[Age]]; 1937 end; 1938 1939 if MyData.ToldAlive <> MyRO.Alive then 1940 begin 1941 for p1 := 0 to nPl - 1 do 1942 if (MyData.ToldAlive - MyRO.Alive) and (1 shl p1) <> 0 then 1943 with MessgExDlg do 1944 begin 1945 OpenSound := 'MSG_EXTINCT'; 1946 s := Tribe[p1].TPhrase('EXTINCT'); 1947 MessgText := Format(s, [TurnToString(MyRO.Turn)]); 1948 if MyRO.Alive = 1 shl me then 1949 MessgText := MessgText + Phrases.Lookup('EXTINCTALL'); 1950 Kind := mkOk; 1951 IconKind := mikImp; 1952 IconIndex := 21; 1953 ShowModal; 1954 end; 1955 if (ClientMode <> cMovieTurn) and not supervising then 1956 DiaDlg.ShowNewContent_Charts(wmModal); 1957 end; 1958 1959 // tell changes of own credibility 1960 if not supervising then 1961 begin 1962 if RoughCredibility(MyRO.Credibility) <> 1963 RoughCredibility(MyData.ToldOwnCredibility) then 1964 begin 1965 if RoughCredibility(MyRO.Credibility) > 1966 RoughCredibility(MyData.ToldOwnCredibility) then 1967 s := Phrases.Lookup('CREDUP') 1968 else 1969 s := Phrases.Lookup('CREDDOWN'); 1970 TribeMessage(me, Format(s, [Phrases.Lookup('CREDIBILITY', 1971 RoughCredibility(MyRO.Credibility))]), ''); 1972 end; 1973 MyData.ToldOwnCredibility := MyRO.Credibility; 1974 end; 1975 1976 for i := 0 to 27 do 1977 begin 1978 OwnWonder := false; 1979 for cix := 0 to MyRO.nCity - 1 do 1980 if (MyCity[cix].Loc >= 0) and (MyCity[cix].ID = MyRO.Wonder[i].CityID) 1981 then 1982 OwnWonder := true; 1983 if MyRO.Wonder[i].CityID <> MyData.ToldWonders[i].CityID then 1984 begin 1985 if MyRO.Wonder[i].CityID = -2 then 1986 with MessgExDlg do 1987 begin { tell about destroyed wonders } 1988 OpenSound := 'WONDER_DESTROYED'; 1989 MessgText := Format(Phrases.Lookup('WONDERDEST'), 1990 [Phrases.Lookup('IMPROVEMENTS', i)]); 1991 Kind := mkOkHelp; 1992 HelpKind := hkImp; 1993 HelpNo := i; 1994 IconKind := mikImp; 1995 IconIndex := i; 1996 ShowModal; 1997 end 1998 else 1999 begin 2000 if i = woManhattan then 2001 if MyRO.Wonder[i].EffectiveOwner > me then 2002 MyData.ColdWarStart := MyRO.Turn - 1 2003 else 2004 MyData.ColdWarStart := MyRO.Turn; 2005 if not OwnWonder then 2006 with MessgExDlg do 2007 begin { tell about newly built wonders } 2008 if i = woManhattan then 2009 begin 2010 OpenSound := 'MSG_COLDWAR'; 2011 s := Tribe[MyRO.Wonder[i].EffectiveOwner].TPhrase('COLDWAR') 2012 end 2013 else if MyRO.Wonder[i].EffectiveOwner >= 0 then 2014 begin 2015 OpenSound := 'WONDER_BUILT'; 2016 s := Tribe[MyRO.Wonder[i].EffectiveOwner] 2017 .TPhrase('WONDERBUILT') 2018 end 2019 else 2020 begin 2021 OpenSound := 'MSG_DEFAULT'; 2022 s := Phrases.Lookup('WONDERBUILTEXP'); 2023 // already expired when built 2024 end; 2025 MessgText := Format(s, [Phrases.Lookup('IMPROVEMENTS', i), 2026 CityName(MyRO.Wonder[i].CityID)]); 2027 Kind := mkOkHelp; 2028 HelpKind := hkImp; 2029 HelpNo := i; 2030 IconKind := mikImp; 2031 IconIndex := i; 2032 ShowModal; 2033 end 1012 2034 end 1013 end; 1014 until ChosenResearch <> adFar; 1015 if ChosenResearch = adNexus then 1016 MyData.FarTech := adNexus 2035 end 2036 else if (MyRO.Wonder[i].EffectiveOwner <> MyData.ToldWonders[i] 2037 .EffectiveOwner) and (MyRO.Wonder[i].CityID > -2) then 2038 if MyRO.Wonder[i].EffectiveOwner < 0 then 2039 begin 2040 if i <> woMIR then 2041 with MessgExDlg do 2042 begin { tell about expired wonders } 2043 OpenSound := 'WONDER_EXPIRED'; 2044 MessgText := Format(Phrases.Lookup('WONDEREXP'), 2045 [Phrases.Lookup('IMPROVEMENTS', i), 2046 CityName(MyRO.Wonder[i].CityID)]); 2047 Kind := mkOkHelp; 2048 HelpKind := hkImp; 2049 HelpNo := i; 2050 IconKind := mikImp; 2051 IconIndex := i; 2052 ShowModal; 2053 end 2054 end 2055 else if (MyData.ToldWonders[i].EffectiveOwner >= 0) and not OwnWonder 2056 then 2057 with MessgExDlg do 2058 begin { tell about capture of wonders } 2059 OpenSound := 'WONDER_CAPTURED'; 2060 s := Tribe[MyRO.Wonder[i].EffectiveOwner].TPhrase('WONDERCAPT'); 2061 MessgText := Format(s, [Phrases.Lookup('IMPROVEMENTS', i), 2062 CityName(MyRO.Wonder[i].CityID)]); 2063 Kind := mkOkHelp; 2064 HelpKind := hkImp; 2065 HelpNo := i; 2066 IconKind := mikImp; 2067 IconIndex := i; 2068 ShowModal; 2069 end; 2070 end; 2071 2072 if MyRO.Turn = MyData.ColdWarStart + ColdWarTurns then 2073 begin 2074 SoundMessageEx(Phrases.Lookup('COLDWAREND'), 'MSG_DEFAULT'); 2075 MyData.ColdWarStart := -ColdWarTurns - 1 2076 end; 2077 2078 TellNewModels; 2079 end; // ClientMode<>cResume 2080 MyData.ToldAlive := MyRO.Alive; 2081 move(MyRO.Wonder, MyData.ToldWonders, SizeOf(MyData.ToldWonders)); 2082 2083 NewGovAvailable := -1; 2084 if ClientMode <> cResume then 2085 begin // tell about new techs 2086 for ad := 0 to nAdv - 1 do 2087 if (MyRO.TestFlags and tfAllTechs = 0) and 2088 ((MyRO.Tech[ad] >= tsApplicable) <> (MyData.ToldTech[ad] >= 2089 tsApplicable)) or (ad in FutureTech) and 2090 (MyRO.Tech[ad] <> MyData.ToldTech[ad]) then 2091 with MessgExDlg do 2092 begin 2093 Item := 'RESEARCH_GENERAL'; 2094 if GameMode <> cMovie then 2095 OpenSound := 'NEWADVANCE_' + char(48 + Age); 2096 Item2 := Phrases.Lookup('ADVANCES', ad); 2097 if ad in FutureTech then 2098 Item2 := Item2 + ' ' + IntToStr(MyRO.Tech[ad]); 2099 MessgText := Format(Phrases.Lookup(Item), [Item2]); 2100 Kind := mkOkHelp; 2101 HelpKind := hkAdv; 2102 HelpNo := ad; 2103 IconKind := mikBook; 2104 IconIndex := -1; 2105 for i := 0 to nAdvBookIcon - 1 do 2106 if AdvBookIcon[i].Adv = ad then 2107 IconIndex := AdvBookIcon[i].Icon; 2108 ShowModal; 2109 MyData.ToldTech[ad] := MyRO.Tech[ad]; 2110 for i := gMonarchy to nGov - 1 do 2111 if GovPreq[i] = ad then 2112 NewGovAvailable := i; 2113 end; 2114 end; 2115 2116 ShowCityList := false; 2117 if ClientMode = cTurn then 2118 begin 2119 if (MyRO.Happened and phTech <> 0) and (MyData.FarTech <> adNexus) then 2120 ChooseResearch; 2121 2122 UpdatePanel := false; 2123 if MyRO.Happened and phChangeGov <> 0 then 2124 begin 2125 ModalSelectDlg.ShowNewContent(wmModal, kGov); 2126 Play('NEWGOV'); 2127 Server(sSetGovernment, me, ModalSelectDlg.result, nil^); 2128 CityOptimizer_BeginOfTurn; 2129 UpdatePanel := true; 2130 end; 2131 end; // ClientMode=cTurn 2132 2133 if not supervising and ((ClientMode = cTurn) or (ClientMode = cMovieTurn)) 2134 then 2135 for cix := 0 to MyRO.nCity - 1 do 2136 with MyCity[cix] do 2137 Status := Status and not csToldBombard; 2138 2139 if ((ClientMode = cTurn) or (ClientMode = cMovieTurn)) and 2140 (MyRO.Government <> gAnarchy) then 2141 begin 2142 // tell what happened in cities 2143 for WondersOnly := true downto false do 2144 for cix := 0 to MyRO.nCity - 1 do 2145 with MyCity[cix] do 2146 if (MyRO.Turn > 0) and (Loc >= 0) and (Flags and chCaptured = 0) and 2147 (WondersOnly = (Flags and chProduction <> 0) and 2148 (Project0 and cpImp <> 0) and (Project0 and cpIndex < 28)) then 2149 begin 2150 if WondersOnly then 2151 with MessgExDlg do 2152 begin { tell about newly built wonder } 2153 OpenSound := 'WONDER_BUILT'; 2154 s := Tribe[me].TPhrase('WONDERBUILTOWN'); 2155 MessgText := 2156 Format(s, [Phrases.Lookup('IMPROVEMENTS', 2157 Project0 and cpIndex), CityName(ID)]); 2158 Kind := mkOkHelp; 2159 HelpKind := hkImp; 2160 HelpNo := Project0 and cpIndex; 2161 IconKind := mikImp; 2162 IconIndex := Project0 and cpIndex; 2163 ShowModal; 2164 end; 2165 if not supervising and (ClientMode = cTurn) then 2166 begin 2167 AllowCityScreen := true; 2168 if (Status and 7 <> 0) and 2169 (Project and (cpImp + cpIndex) = cpImp + imTrGoods) then 2170 if (MyData.ImpOrder[Status and 7 - 1, 0] >= 0) then 2171 begin 2172 if AutoBuild(cix, MyData.ImpOrder[Status and 7 - 1]) then 2173 AllowCityScreen := false 2174 else if Flags and chProduction <> 0 then 2175 Flags := (Flags and not chProduction) or chAllImpsMade 2176 end 2177 else 2178 Flags := Flags or chTypeDel; 2179 if (Size >= NeedAqueductSize) and 2180 (MyRO.Tech[Imp[imAqueduct].Preq] < tsApplicable) or 2181 (Size >= NeedSewerSize) and 2182 (MyRO.Tech[Imp[imSewer].Preq] < tsApplicable) then 2183 Flags := Flags and not chNoGrowthWarning; 2184 // don't remind of unknown building 2185 if Flags and chNoSettlerProd = 0 then 2186 Status := Status and not csToldDelay 2187 else if Status and csToldDelay = 0 then 2188 Status := Status or csToldDelay 2189 else 2190 Flags := Flags and not chNoSettlerProd; 2191 if mRepScreens.Checked then 2192 begin 2193 if (Flags and CityRepMask <> 0) and AllowCityScreen then 2194 begin { show what happened in cities } 2195 SetTroopLoc(MyCity[cix].Loc); 2196 MarkCityLoc := MyCity[cix].Loc; 2197 PanelPaint; 2198 CityDlg.CloseAction := None; 2199 CityDlg.ShowNewContent(wmModal, MyCity[cix].Loc, 2200 Flags and CityRepMask); 2201 UpdatePanel := true; 2202 end 2203 end 2204 else { if mRepList.Checked then } 2205 begin 2206 if Flags and CityRepMask <> 0 then 2207 ShowCityList := true 2208 end 2209 end 2210 end; { city loop } 2211 end; // ClientMode=cTurn 2212 2213 if ClientMode = cTurn then 2214 begin 2215 if NewGovAvailable >= 0 then 2216 with MessgExDlg do 2217 begin 2218 MessgText := Format(Phrases.Lookup('AUTOREVOLUTION'), 2219 [Phrases.Lookup('GOVERNMENT', NewGovAvailable)]); 2220 Kind := mkYesNo; 2221 IconKind := mikPureIcon; 2222 IconIndex := 6 + NewGovAvailable; 2223 ShowModal; 2224 if ModalResult = mrOK then 2225 begin 2226 Play('REVOLUTION'); 2227 Server(sRevolution, me, 0, nil^); 2228 end 2229 end; 2230 end; // ClientMode=cTurn 2231 2232 if (ClientMode = cTurn) or (ClientMode = cMovieTurn) then 2233 begin 2234 if MyRO.Happened and phGliderLost <> 0 then 2235 ContextMessage(Phrases.Lookup('GLIDERLOST'), 'MSG_DEFAULT', 2236 hkModel, 200); 2237 if MyRO.Happened and phPlaneLost <> 0 then 2238 ContextMessage(Phrases.Lookup('PLANELOST'), 'MSG_DEFAULT', 2239 hkFeature, mcFuel); 2240 if MyRO.Happened and phPeaceEvacuation <> 0 then 2241 for p1 := 0 to nPl - 1 do 2242 if 1 shl p1 and MyData.PeaceEvaHappened <> 0 then 2243 SoundMessageEx(Tribe[p1].TPhrase('WITHDRAW'), 'MSG_DEFAULT'); 2244 if MyRO.Happened and phPeaceViolation <> 0 then 2245 for p1 := 0 to nPl - 1 do 2246 if (1 shl p1 and MyRO.Alive <> 0) and (MyRO.EvaStart[p1] = MyRO.Turn) 2247 then 2248 SoundMessageEx(Format(Tribe[p1].TPhrase('VIOLATION'), 2249 [TurnToString(MyRO.Turn + PeaceEvaTurns - 1)]), 'MSG_WITHDRAW'); 2250 TellNewContacts; 2251 end; 2252 2253 if ClientMode = cMovieTurn then 2254 Update 2255 else if ClientMode = cTurn then 2256 begin 2257 if UpdatePanel then 2258 UpdateViews; 2259 Application.ProcessMessages; 2260 2261 if not supervising then 2262 for uix := 0 to MyRO.nUn - 1 do 2263 with MyUn[uix] do 2264 if Loc >= 0 then 2265 begin 2266 if Flags and unWithdrawn <> 0 then 2267 Status := 0; 2268 if Health = 100 then 2269 Status := Status and not usRecover; 2270 if (Master >= 0) or UnitExhausted(uix) then 2271 Status := Status and not usWaiting 2272 else 2273 Status := Status or usWaiting; 2274 CheckToldNoReturn(uix); 2275 if Status and usGoto <> 0 then 2276 begin { continue multi-turn goto } 2277 SetUnFocus(uix); 2278 SetTroopLoc(Loc); 2279 FocusOnLoc(TroopLoc, flRepaintPanel or flImmUpdate); 2280 if Status shr 16 = $7FFF then 2281 MoveResult := GetMoveAdvice(UnFocus, maNextCity, 2282 MoveAdviceData) 2283 else 2284 MoveResult := GetMoveAdvice(UnFocus, Status shr 16, 2285 MoveAdviceData); 2286 if MoveResult >= rExecuted then 2287 begin // !!! Shinkansen 2288 MoveResult := eOK; 2289 ok := true; 2290 for i := 0 to MoveAdviceData.nStep - 1 do 2291 begin 2292 Loc1 := dLoc(Loc, MoveAdviceData.dx[i], 2293 MoveAdviceData.dy[i]); 2294 if (MyMap[Loc1] and (fCity or fOwned) = fCity) 2295 // don't capture cities during auto move 2296 or (MyMap[Loc1] and (fUnit or fOwned) = fUnit) then 2297 // don't attack during auto move 2298 begin 2299 ok := false; 2300 Break 2301 end 2302 else 2303 begin 2304 if (Loc1 = MoveAdviceData.ToLoc) or 2305 (MoveAdviceData.ToLoc = maNextCity) and 2306 (MyMap[dLoc(Loc, MoveAdviceData.dx[i], 2307 MoveAdviceData.dy[i])] and fCity <> 0) then 2308 MoveOptions := muAutoNoWait 2309 else 2310 MoveOptions := 0; 2311 MoveResult := MoveUnit(MoveAdviceData.dx[i], 2312 MoveAdviceData.dy[i], MoveOptions); 2313 if (MoveResult < rExecuted) or (MoveResult = eEnemySpotted) 2314 then 2315 begin 2316 ok := false; 2317 Break 2318 end; 2319 end 2320 end; 2321 Stop := not ok or (Loc = MoveAdviceData.ToLoc) or 2322 (MoveAdviceData.ToLoc = maNextCity) and 2323 (MyMap[Loc] and fCity <> 0) 2324 end 2325 else 2326 begin 2327 MoveResult := eOK; 2328 Stop := true; 2329 end; 2330 2331 if MoveResult <> eDied then 2332 if Stop then 2333 Status := Status and ($FFFF - usGoto) 2334 else 2335 Status := Status and not usWaiting; 2336 end; 2337 2338 if Status and (usEnhance or usGoto) = usEnhance then 2339 // continue terrain enhancement 2340 begin 2341 MoveResult := ProcessEnhancement(uix, MyData.EnhancementJobs); 2342 if MoveResult <> eDied then 2343 if MoveResult = eJobDone then 2344 Status := Status and not usEnhance 2345 else 2346 Status := Status and not usWaiting; 2347 end 2348 end; 2349 end; // ClientMode=cTurn 2350 2351 HaveStrategyAdvice := false; 2352 // (GameMode<>cMovie) and not supervising 2353 // and AdvisorDlg.HaveStrategyAdvice; 2354 GoOnPhase := true; 2355 if supervising or (GameMode = cMovie) then 2356 begin 2357 SetTroopLoc(-1); 2358 PaintAll 2359 end { supervisor } 2360 { else if (ClientMode=cTurn) and (MyRO.Turn=0) then 2361 begin 2362 SetUnFocus(0); 2363 ZoomToCity(MyCity[0].Loc) 2364 end } 1017 2365 else 1018 Server(sSetResearch, me, ChosenResearch, nil^); 1019 ListDlg.TechChange; 1020 result := true; 2366 begin 2367 if ClientMode >= scContact then 2368 SetUnFocus(-1) 2369 else 2370 NextUnit(-1, false); 2371 if UnFocus < 0 then 2372 begin 2373 UnStartLoc := -1; 2374 if IsMultiPlayerGame or (ClientMode = cResume) then 2375 if MyRO.nCity > 0 then 2376 FocusOnLoc(MyCity[0].Loc) 2377 else 2378 FocusOnLoc(G.lx * G.ly div 2); 2379 SetTroopLoc(-1); 2380 PanelPaint 2381 end; 2382 if ShowCityList then 2383 ListDlg.ShowNewContent(wmPersistent, kCityEvents); 2384 end; 2385 end; { InitTurn } 2386 2387 var 2388 i, j, p1, mix, ToLoc, AnimationSpeed, ShowMoveDomain, cix, ecix: integer; 2389 Color: TColor; 2390 Name, s: string; 2391 TribeInfo: TTribeInfo; 2392 mi: TModelInfo; 2393 SkipTurn, IsAlpine, IsTreatyDeal: boolean; 2394 2395 begin { >>>client } 2396 case Command of 2397 cTurn, cResume, cContinue, cMovieTurn, scContact, scDipStart .. scDipBreak: 2398 begin 2399 supervising := G.Difficulty[NewPlayer] = 0; 2400 ArrangeMidPanel; 2401 end 1021 2402 end; 1022 1023 (* ** client function handling ** *) 1024 1025 function TMainScreen.DipCall(Command: integer): integer; 1026 var 1027 i: integer; 1028 IsTreatyDeal: boolean; 1029 begin 1030 result := Server(Command, me, 0, nil^); 1031 if result >= rExecuted then 1032 begin 1033 if Command and $FF0F = scContact then 1034 begin 1035 DipMem[me].pContact := Command shr 4 and $F; 1036 NegoDlg.Initiate; 1037 DipMem[me].DeliveredPrices := []; 1038 DipMem[me].ReceivedPrices := []; 1039 end; 1040 1041 DipMem[me].SentCommand := Command; 1042 DipMem[me].FormerTreaty := MyRO.Treaty[DipMem[me].pContact]; 1043 if Command = scDipCancelTreaty then 1044 Play('CANCELTREATY') 1045 else if Command = scDipAccept then 1046 begin // remember delivered and received prices 1047 for i := 0 to ReceivedOffer.nDeliver - 1 do 1048 include(DipMem[me].ReceivedPrices, ReceivedOffer.Price[i] shr 24); 1049 for i := 0 to ReceivedOffer.nCost - 1 do 1050 include(DipMem[me].DeliveredPrices, 1051 ReceivedOffer.Price[ReceivedOffer.nDeliver + i] shr 24); 1052 IsTreatyDeal := false; 1053 for i := 0 to ReceivedOffer.nDeliver + ReceivedOffer.nCost - 1 do 1054 if ReceivedOffer.Price[i] and opMask = opTreaty then 1055 IsTreatyDeal := true; 1056 if IsTreatyDeal then 1057 Play('NEWTREATY') 2403 case Command of 2404 cDebugMessage: 2405 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(@Data)); 2406 2407 cShowNego: 2408 with TShowNegoData(Data) do 2409 begin 2410 s := Format('P%d to P%d: ', [pSender, pTarget]); 2411 if (Action = scDipOffer) and (Offer.nDeliver + Offer.nCost > 0) then 2412 begin 2413 s := s + 'Offer '; 2414 for i := 0 to Offer.nDeliver + Offer.nCost - 1 do 2415 begin 2416 if i = Offer.nDeliver then 2417 s := s + ' for ' 2418 else if i > 0 then 2419 s := s + '+'; 2420 case Offer.Price[i] and opMask of 2421 opChoose: 2422 s := s + 'Price of choice'; 2423 opCivilReport: 2424 s := s + 'State report'; 2425 opMilReport: 2426 s := s + 'Military report'; 2427 opMap: 2428 s := s + 'Map'; 2429 opTreaty: 2430 s := s + 'Treaty'; 2431 opShipParts: 2432 s := s + 'Ship part'; 2433 opMoney: 2434 s := s + IntToStr(Offer.Price[i] and $FFFFFF) + 'o'; 2435 opTribute: 2436 s := s + IntToStr(Offer.Price[i] and $FFFFFF) + 'o tribute'; 2437 opTech: 2438 s := s + Phrases.Lookup('ADVANCES', Offer.Price[i] and $FFFFFF); 2439 opAllTech: 2440 s := s + 'All advances'; 2441 opModel: 2442 s := s + Tribe[pSender].ModelName[Offer.Price[i] and $FFFFFF]; 2443 opAllModel: 2444 s := s + 'All models'; 2445 end 2446 end; 2447 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(s)); 2448 end 2449 else if Action = scDipAccept then 2450 begin 2451 s := s + '--- ACCEPTED! ---'; 2452 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(s)); 2453 end 2454 end; 2455 2456 cInitModule: 2457 begin 2458 Server := TInitModuleData(Data).Server; 2459 // AdvisorDlg.Init; 2460 InitModule; 2461 TInitModuleData(Data).DataSize := SizeOf(TPersistentData); 2462 TInitModuleData(Data).Flags := aiThreaded; 2463 end; 2464 2465 cReleaseModule: 2466 begin 2467 SmallImp.free; 2468 UnusedTribeFiles.free; 2469 TribeNames.free; 2470 MainMap.free; 2471 IsoEngine.Done; 2472 // AdvisorDlg.DeInit; 2473 end; 2474 2475 cHelpOnly, cStartHelp, cStartCredits: 2476 begin 2477 Age := 0; 2478 if Command = cHelpOnly then 2479 SetMainTextureByAge(-1); 2480 Tribes.Init; 2481 HelpDlg.UserLeft := (Screen.width - HelpDlg.width) div 2; 2482 HelpDlg.UserTop := (Screen.height - HelpDlg.height) div 2; 2483 HelpDlg.Difficulty := 0; 2484 if Command = cStartCredits then 2485 HelpDlg.ShowNewContent(wmModal, hkMisc, miscCredits) 1058 2486 else 1059 Play('ACCEPTOFFER'); 1060 end; 1061 CityDlg.CloseAction := None; 1062 if G.RO[DipMem[me].pContact] <> nil then 1063 begin // close windows for next player 2487 HelpDlg.ShowNewContent(wmModal, hkMisc, miscMain); 2488 Tribes.Done; 2489 end; 2490 2491 cNewGame, cLoadGame, cMovie, cNewMap: 2492 begin 2493 { if (Command=cNewGame) or (Command=cLoadGame) then 2494 AdvisorDlg.NewGame(Data); } 2495 GenerateNames := mNames.Checked; 2496 GameOK := true; 2497 G := TNewGameData(Data); 2498 me := -1; 2499 pLogo := -1; 2500 ClientMode := -1; 2501 SetMapOptions; 2502 IsoEngine.pDebugMap := -1; 2503 idle := false; 2504 FillChar(Jump, SizeOf(Jump), 0); 2505 if StartRunning then 2506 Jump[0] := 999999; 2507 GameMode := Command; 2508 for i := 0 to nGrExt - 1 do 2509 FillChar(GrExt[i].pixUsed, GrExt[i].Data.height div 49 * 10, 0); 2510 IsoEngine.Reset; 2511 Tribes.Init; 2512 GetTribeList; 2513 for p1 := 0 to nPl - 1 do 2514 if (G.RO[p1] <> nil) and (G.RO[p1].Data <> nil) then 2515 with TPersistentData(G.RO[p1].Data^) do 2516 begin 2517 FarTech := adNone; 2518 FillChar(EnhancementJobs, SizeOf(EnhancementJobs), jNone); 2519 FillChar(ImpOrder, SizeOf(ImpOrder), Byte(-1)); 2520 ColdWarStart := -ColdWarTurns - 1; 2521 ToldAge := -1; 2522 ToldModels := 3; 2523 ToldAlive := 0; 2524 ToldContact := 0; 2525 ToldOwnCredibility := InitialCredibility; 2526 for i := 0 to nPl - 1 do 2527 if G.Difficulty[i] > 0 then 2528 inc(ToldAlive, 1 shl i); 2529 PeaceEvaHappened := 0; 2530 for i := 0 to 27 do 2531 with ToldWonders[i] do 2532 begin 2533 CityID := -1; 2534 EffectiveOwner := -1 2535 end; 2536 FillChar(ToldTech, SizeOf(ToldTech), Byte(tsNA)); 2537 if G.Difficulty[p1] > 0 then 2538 SoundPreload(sbStart); 2539 end; 2540 2541 // arrange dialogs 2542 ListDlg.UserLeft := 8; 2543 ListDlg.UserTop := TopBarHeight + 8; 2544 HelpDlg.UserLeft := Screen.width - HelpDlg.width - 8; 2545 HelpDlg.UserTop := TopBarHeight + 8; 2546 UnitStatDlg.UserLeft := 397; 2547 UnitStatDlg.UserTop := TopBarHeight + 64; 2548 DiaDlg.UserLeft := (Screen.width - DiaDlg.width) div 2; 2549 DiaDlg.UserTop := (Screen.height - DiaDlg.height) div 2; 2550 NatStatDlg.UserLeft := Screen.width - NatStatDlg.width - 8; 2551 NatStatDlg.UserTop := Screen.height - PanelHeight - 2552 NatStatDlg.height - 8; 2553 if NatStatDlg.UserTop < 8 then 2554 NatStatDlg.UserTop := 8; 2555 2556 Age := 0; 2557 MovieSpeed := 1; 2558 LogDlg.mSlot.Visible := true; 2559 LogDlg.Host := self; 2560 HelpDlg.ClearHistory; 2561 CityDlg.Reset; 2562 2563 Mini.width := G.lx * 2; 2564 Mini.height := G.ly; 2565 for i := 0 to nPl - 1 do 2566 begin 2567 Tribe[i] := nil; 2568 TribeOriginal[i] := false; 2569 end; 2570 ToldSlavery := -1; 2571 RepaintOnResize := false; 2572 Closable := false; 2573 FirstMovieTurn := true; 2574 2575 MenuArea.Visible := GameMode <> cMovie; 2576 TreasuryArea.Visible := GameMode < cMovie; 2577 ResearchArea.Visible := GameMode < cMovie; 2578 ManagementArea.Visible := GameMode < cMovie; 2579 end; 2580 2581 cGetReady, cReplay: 2582 if NewPlayer = 0 then 2583 begin 2584 i := 0; 2585 for p1 := 0 to nPl - 1 do 2586 if (G.Difficulty[p1] > 0) and (Tribe[p1] = nil) then 2587 inc(i); 2588 if i > UnusedTribeFiles.Count then 2589 begin 2590 GameOK := false; 2591 SimpleMessage(Phrases.Lookup('TOOFEWTRIBES')); 2592 end 2593 else 2594 begin 2595 for p1 := 0 to nPl - 1 do 2596 if (G.Difficulty[p1] > 0) and (Tribe[p1] = nil) and (G.RO[p1] <> nil) 2597 then 2598 begin // let player select own tribes 2599 TribeInfo.trix := p1; 2600 TribeNames.Clear; 2601 for j := 0 to UnusedTribeFiles.Count - 1 do 2602 begin 2603 GetTribeInfo(UnusedTribeFiles[j], Name, Color); 2604 TribeNames.AddObject(Name, TObject(Color)); 2605 end; 2606 assert(TribeNames.Count > 0); 2607 ModalSelectDlg.ShowNewContent(wmModal, kTribe); 2608 Application.ProcessMessages; 2609 TribeInfo.FileName := UnusedTribeFiles[ModalSelectDlg.result]; 2610 UnusedTribeFiles.Delete(ModalSelectDlg.result); 2611 2612 if GameMode = cLoadGame then 2613 CreateTribe(TribeInfo.trix, TribeInfo.FileName, false) 2614 else 2615 Server(cSetTribe + (Length(TribeInfo.FileName) + 1 + 7) div 4, 2616 0, 0, TribeInfo); 2617 end; 2618 2619 for p1 := 0 to nPl - 1 do 2620 if (G.Difficulty[p1] > 0) and (Tribe[p1] = nil) and (G.RO[p1] = nil) 2621 then 2622 begin // autoselect enemy tribes 2623 j := ChooseUnusedTribe; 2624 TribeInfo.FileName := UnusedTribeFiles[j]; 2625 UnusedTribeFiles.Delete(j); 2626 TribeInfo.trix := p1; 2627 if GameMode = cLoadGame then 2628 CreateTribe(TribeInfo.trix, TribeInfo.FileName, false) 2629 else 2630 Server(cSetTribe + (Length(TribeInfo.FileName) + 1 + 7) div 4, 2631 0, 0, TribeInfo); 2632 end; 2633 end; 2634 if not mNames.Checked then 2635 for p1 := 0 to nPl - 1 do 2636 if Tribe[p1] <> nil then 2637 Tribe[p1].NumberName := p1; 2638 end; 2639 2640 cBreakGame: 2641 begin 2642 SaveSettings; 2643 CityDlg.CloseAction := None; 1064 2644 for i := 0 to Screen.FormCount - 1 do 1065 2645 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 1066 2646 then 1067 2647 Screen.Forms[i].Close; 1068 end 1069 else 1070 begin 1071 if CityDlg.Visible then 1072 CityDlg.Close; 1073 if UnitStatDlg.Visible then 1074 UnitStatDlg.Close; 1075 end 1076 end 1077 end; 1078 1079 function TMainScreen.OfferCall(var Offer: TOffer): integer; 1080 var 1081 i: integer; 1082 begin 1083 result := Server(scDipOffer, me, 0, Offer); 1084 if result >= rExecuted then 1085 begin 1086 DipMem[me].SentCommand := scDipOffer; 1087 DipMem[me].FormerTreaty := MyRO.Treaty[DipMem[me].pContact]; 1088 DipMem[me].SentOffer := Offer; 1089 CityDlg.CloseAction := None; 1090 if G.RO[DipMem[me].pContact] <> nil then 1091 begin // close windows for next player 1092 for i := 0 to Screen.FormCount - 1 do 1093 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 1094 then 1095 Screen.Forms[i].Close; 1096 end 1097 else 1098 begin 1099 if CityDlg.Visible then 1100 CityDlg.Close; 1101 if UnitStatDlg.Visible then 1102 UnitStatDlg.Close; 1103 end 1104 end 1105 end; 1106 1107 procedure TMainScreen.SetUnFocus(uix: integer); 1108 var 1109 Loc0: integer; 1110 begin 1111 assert(not((uix >= 0) and supervising)); 1112 if uix <> UnFocus then 1113 begin 1114 DestinationMarkON := false; 1115 PaintDestination; 1116 if uix >= 0 then 1117 UnStartLoc := MyUn[uix].Loc; 1118 BlinkON := false; 1119 BlinkTime := -1; 1120 if UnFocus >= 0 then 1121 begin 1122 Loc0 := MyUn[UnFocus].Loc; 1123 if (uix < 0) or (Loc0 <> MyUn[uix].Loc) then 1124 begin 1125 UnFocus := -1; 1126 PaintLoc(Loc0); 1127 end 1128 end; 1129 UnFocus := uix; 1130 end; 1131 UnitInfoBtn.Visible := UnFocus >= 0; 1132 UnitBtn.Visible := UnFocus >= 0; 1133 CheckTerrainBtnVisible; 1134 end; 1135 1136 procedure TMainScreen.CheckTerrainBtnVisible; 1137 var 1138 Tile: integer; 1139 mox: ^TModel; 1140 begin 1141 if UnFocus >= 0 then 1142 begin 1143 mox := @MyModel[MyUn[UnFocus].mix]; 1144 Tile := MyMap[MyUn[UnFocus].Loc]; 1145 TerrainBtn.Visible := (Tile and fCity = 0) and (MyUn[UnFocus].Master < 0) 1146 and ((mox.Kind = mkSettler) or (mox.Kind = mkSlaves) and 1147 (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)); 1148 end 1149 else 1150 TerrainBtn.Visible := false; 1151 end; 1152 1153 procedure TMainScreen.CheckMovieSpeedBtnState; 1154 begin 1155 if GameMode = cMovie then 1156 begin 1157 MovieSpeed1Btn.Down := MovieSpeed = 1; 1158 MovieSpeed1Btn.Visible := true; 1159 MovieSpeed2Btn.Down := MovieSpeed = 2; 1160 MovieSpeed2Btn.Visible := true; 1161 MovieSpeed3Btn.Down := MovieSpeed = 3; 1162 MovieSpeed3Btn.Visible := true; 1163 MovieSpeed4Btn.Down := MovieSpeed = 4; 1164 MovieSpeed4Btn.Visible := true; 1165 end 1166 else 1167 begin 1168 MovieSpeed1Btn.Visible := false; 1169 MovieSpeed2Btn.Visible := false; 1170 MovieSpeed3Btn.Visible := false; 1171 MovieSpeed4Btn.Visible := false; 1172 end 1173 end; 1174 1175 procedure TMainScreen.SetMapOptions; 1176 begin 1177 IsoEngine.Options := MapOptionChecked; 1178 if ClientMode = cEditMap then 1179 IsoEngine.Options := IsoEngine.Options or (1 shl moEditMode); 1180 if mLocCodes.Checked then 1181 IsoEngine.Options := IsoEngine.Options or (1 shl moLocCodes); 1182 end; 1183 1184 procedure TMainScreen.UpdateViews(UpdateCityScreen: boolean); 1185 begin 1186 SumCities(TaxSum, ScienceSum); 1187 PanelPaint; // TopBar was enough!!! 1188 ListDlg.EcoChange; 1189 NatStatDlg.EcoChange; 1190 if UpdateCityScreen then 1191 CityDlg.SmartUpdateContent; 1192 end; 1193 1194 procedure TMainScreen.SetAIName(p: integer; Name: string); 1195 begin 1196 if Name = '' then 1197 begin 1198 if AILogo[p] <> nil then 1199 begin 1200 AILogo[p].free; 1201 AILogo[p] := nil 1202 end 1203 end 1204 else 1205 begin 1206 if AILogo[p] = nil then 1207 AILogo[p] := TBitmap.Create; 1208 if not LoadGraphicFile(AILogo[p], HomeDir + Name, gfNoError) then 1209 begin 1210 AILogo[p].free; 1211 AILogo[p] := nil 1212 end 1213 end 1214 end; 1215 1216 function TMainScreen.ContactRefused(p: integer; Item: String): boolean; 1217 // return whether treaty was cancelled 1218 var 1219 s: string; 1220 begin 1221 assert(MyRO.Treaty[p] >= trPeace); 1222 s := Tribe[p].TPhrase(Item); 1223 if MyRO.Turn < MyRO.LastCancelTreaty[p] + CancelTreatyTurns then 1224 begin 1225 SimpleMessage(s); 1226 result := false; 1227 end 1228 else 1229 begin 1230 case MyRO.Treaty[p] of 1231 trPeace: 1232 s := s + ' ' + Phrases.Lookup('FRCANCELQUERY_PEACE'); 1233 trFriendlyContact: 1234 s := s + ' ' + Phrases.Lookup('FRCANCELQUERY_FRIENDLY'); 1235 trAlliance: 1236 s := s + ' ' + Phrases.Lookup('FRCANCELQUERY_ALLIANCE'); 1237 end; 1238 result := SimpleQuery(mkYesNo, s, 'NEGO_REJECTED') = mrOK; 1239 if result then 1240 begin 1241 Play('CANCELTREATY'); 1242 Server(sCancelTreaty, me, 0, nil^); 1243 if MyRO.Treaty[p] = trNone then 1244 CityOptimizer_BeginOfTurn; 1245 // peace treaty was cancelled -- use formerly forbidden tiles 1246 MapValid := false; 1247 PaintAllMaps; 1248 end 1249 end 1250 end; 1251 1252 procedure TMainScreen.RememberPeaceViolation; 1253 var 1254 uix, p1: integer; 1255 begin 1256 MyData.PeaceEvaHappened := 0; 1257 for uix := 0 to MyRO.nUn - 1 do 1258 with MyUn[uix] do 1259 if Loc >= 0 then 1260 begin 1261 p1 := MyRO.Territory[Loc]; 1262 if (p1 <> me) and (p1 >= 0) and 1263 (MyRO.Turn = MyRO.EvaStart[p1] + (PeaceEvaTurns - 1)) then 1264 MyData.PeaceEvaHappened := MyData.PeaceEvaHappened or (1 shl p1); 1265 end; 1266 end; 1267 1268 procedure TMainScreen.Client(Command, NewPlayer: integer; var Data); 1269 1270 procedure GetTribeList; 1271 var 1272 SearchRec: TSearchRec; 1273 Color: TColor; 1274 Name: string; 1275 ok: boolean; 1276 begin 1277 UnusedTribeFiles.Clear; 1278 ok := FindFirst(DataDir + 'Localization' + DirectorySeparator + 'Tribes' + DirectorySeparator + '*.tribe.txt', 1279 faArchive + faReadOnly, SearchRec) = 0; 1280 if not ok then 1281 begin 1282 FindClose(SearchRec); 1283 ok := FindFirst(HomeDir + 'Tribes' + DirectorySeparator + '*.tribe.txt', faArchive + faReadOnly, 1284 SearchRec) = 0; 1285 end; 1286 if ok then 1287 repeat 1288 SearchRec.Name := Copy(SearchRec.Name, 1, 1289 Length(SearchRec.Name) - 10); 1290 if GetTribeInfo(SearchRec.Name, Name, Color) then 1291 UnusedTribeFiles.AddObject(SearchRec.Name, TObject(Color)); 1292 until FindNext(SearchRec) <> 0; 1293 FindClose(SearchRec); 1294 end; 1295 1296 function ChooseUnusedTribe: integer; 1297 var 1298 i, j, ColorDistance, BestColorDistance, TestColorDistance, 1299 CountBest: integer; 1300 begin 1301 assert(UnusedTribeFiles.Count > 0); 1302 result := -1; 1303 BestColorDistance := -1; 1304 for j := 0 to UnusedTribeFiles.Count - 1 do 1305 begin 1306 ColorDistance := 250; // consider differences more than this infinite 1307 for i := 0 to nPl - 1 do 1308 if Tribe[i] <> nil then 1309 begin 1310 TestColorDistance := 1311 abs(integer(UnusedTribeFiles.Objects[j]) shr 16 and 1312 $FF - Tribe[i].Color shr 16 and $FF) + 1313 abs(integer(UnusedTribeFiles.Objects[j]) shr 8 and 1314 $FF - Tribe[i].Color shr 8 and $FF) * 3 + 1315 abs(integer(UnusedTribeFiles.Objects[j]) and 1316 $FF - Tribe[i].Color and $FF) * 2; 1317 if TestColorDistance < ColorDistance then 1318 ColorDistance := TestColorDistance 1319 end; 1320 if ColorDistance > BestColorDistance then 1321 begin 1322 CountBest := 0; 1323 BestColorDistance := ColorDistance 1324 end; 1325 if ColorDistance = BestColorDistance then 1326 begin 1327 inc(CountBest); 1328 if random(CountBest) = 0 then 1329 result := j 1330 end 1331 end; 1332 end; 1333 1334 procedure ShowEnemyShipChange(ShowShipChange: TShowShipChange); 1335 var 1336 i, TestCost, MostCost: integer; 1337 Ship1Plus, Ship2Plus: boolean; 1338 begin 1339 with ShowShipChange, MessgExDlg do 1340 begin 1341 case Reason of 1342 scrProduction: 1343 begin 1344 OpenSound := 'SHIP_BUILT'; 1345 MessgText := Tribe[Ship1Owner].TPhrase('SHIPBUILT'); 1346 IconKind := mikShip; 1347 IconIndex := Ship1Owner; 1348 end; 1349 1350 scrDestruction: 1351 begin 1352 OpenSound := 'SHIP_DESTROYED'; 1353 MessgText := Tribe[Ship1Owner].TPhrase('SHIPDESTROYED'); 1354 IconKind := mikImp; 1355 end; 1356 1357 scrTrade: 1358 begin 1359 OpenSound := 'SHIP_TRADED'; 1360 Ship1Plus := false; 1361 Ship2Plus := false; 1362 for i := 0 to nShipPart - 1 do 1363 begin 1364 if Ship1Change[i] > 0 then 1365 Ship1Plus := true; 1366 if Ship2Change[i] > 0 then 1367 Ship2Plus := true; 1368 end; 1369 if Ship1Plus and Ship2Plus then 1370 MessgText := Tribe[Ship1Owner].TPhrase('SHIPBITRADE1') + ' ' + 1371 Tribe[Ship2Owner].TPhrase('SHIPBITRADE2') 1372 else if Ship1Plus then 1373 MessgText := Tribe[Ship1Owner].TPhrase('SHIPUNITRADE1') + ' ' + 1374 Tribe[Ship2Owner].TPhrase('SHIPUNITRADE2') 1375 else // if Ship2Plus then 1376 MessgText := Tribe[Ship2Owner].TPhrase('SHIPUNITRADE1') + ' ' + 1377 Tribe[Ship1Owner].TPhrase('SHIPUNITRADE2'); 1378 IconKind := mikImp; 1379 end; 1380 1381 scrCapture: 1382 begin 1383 OpenSound := 'SHIP_CAPTURED'; 1384 MessgText := Tribe[Ship2Owner].TPhrase('SHIPCAPTURE1') + ' ' + 1385 Tribe[Ship1Owner].TPhrase('SHIPCAPTURE2'); 1386 IconKind := mikShip; 1387 IconIndex := Ship2Owner; 1388 end 1389 end; 1390 1391 if IconKind = mikImp then 1392 begin 1393 MostCost := 0; 1394 for i := 0 to nShipPart - 1 do 1395 begin 1396 TestCost := abs(Ship1Change[i]) * Imp[imShipComp + i].Cost; 1397 if TestCost > MostCost then 1398 begin 1399 MostCost := TestCost; 1400 IconIndex := imShipComp + i 1401 end 1402 end; 1403 end; 1404 1405 Kind := mkOk; 1406 ShowModal; 1407 end; 1408 end; 1409 1410 procedure InitModule; 1411 var 1412 x, y, i, j, Domain: integer; 1413 begin 1414 { search icons for advances: } 1415 for i := 0 to nAdv - 1 do 1416 if i in FutureTech then 1417 AdvIcon[i] := 96 + i - futResearchTechnology 1418 else 1419 begin 1420 AdvIcon[i] := -1; 1421 for Domain := 0 to nDomains - 1 do 1422 for j := 0 to nUpgrade - 1 do 1423 if upgrade[Domain, j].Preq = i then 1424 if AdvIcon[i] >= 0 then 1425 AdvIcon[i] := 85 1426 else 1427 AdvIcon[i] := 86 + Domain; 1428 for j := 0 to nFeature - 1 do 1429 if Feature[j].Preq = i then 1430 for Domain := 0 to nDomains - 1 do 1431 if 1 shl Domain and Feature[j].Domains <> 0 then 1432 if (AdvIcon[i] >= 0) and (AdvIcon[i] <> 86 + Domain) then 1433 AdvIcon[i] := 85 1434 else 1435 AdvIcon[i] := 86 + Domain; 1436 for j := 28 to nImp - 1 do 1437 if Imp[j].Preq = i then 1438 AdvIcon[i] := j; 1439 for j := 28 to nImp - 1 do 1440 if (Imp[j].Preq = i) and (Imp[j].Kind <> ikCommon) then 1441 AdvIcon[i] := j; 1442 for j := 0 to nJob - 1 do 1443 if i = JobPreq[j] then 1444 AdvIcon[i] := 84; 1445 for j := 0 to 27 do 1446 if Imp[j].Preq = i then 1447 AdvIcon[i] := j; 1448 if AdvIcon[i] < 0 then 1449 if AdvValue[i] < 1000 then 1450 AdvIcon[i] := -7 1451 else 1452 AdvIcon[i] := 24 + AdvValue[i] div 1000; 1453 for j := 2 to nGov - 1 do 1454 if GovPreq[j] = i then 1455 AdvIcon[i] := j - 8; 1456 end; 1457 AdvIcon[adConscription] := 86 + dGround; 1458 1459 UnusedTribeFiles := tstringlist.Create; 1460 UnusedTribeFiles.Sorted := true; 1461 TribeNames := tstringlist.Create; 1462 1463 for x := 0 to 11 do 1464 for y := 0 to 1 do 1465 MiniColors[x, y] := GrExt[HGrSystem].Data.Canvas.Pixels 1466 [66 + x, 67 + y]; 1467 IsoEngine.Init(InitEnemyModel); 1468 if not IsoEngine.ApplyTileSize(xxt, yyt) and ((xxt <> 48) or (yyt <> 24)) 1469 then 1470 ApplyTileSize(48, 24); 1471 // non-default tile size is missing a file, switch to default 1472 MainMap := TIsoMap.Create; 1473 MainMap.SetOutput(offscreen); 1474 1475 HGrStdUnits := LoadGraphicSet('StdUnits'); 1476 SmallImp := TBitmap.Create; 1477 SmallImp.PixelFormat := pf24bit; 1478 InitSmallImp; 1479 SoundPreloadDone := 0; 1480 StartRunning := false; 1481 StayOnTop_Ensured := false; 1482 1483 CreatePVSB(sb, Handle, 100 - 200, 122, 100 + MidPanelHeight - 16 - 200); 1484 end; { InitModule } 1485 1486 // sound blocks for preload 1487 const 1488 sbStart = $01; 1489 sbWonder = $02; 1490 sbScience = $04; 1491 sbContact = $08; 1492 sbTurn = $10; 1493 sbAll = $FF; 1494 1495 procedure SoundPreload(Check: integer); 1496 const 1497 nStartBlock = 27; 1498 StartBlock: array [0 .. nStartBlock - 1] of string = ('INVALID', 1499 'TURNEND', 'DISBAND', 'CHEAT', 'MSG_DEFAULT', 'WARNING_DISORDER', 1500 'WARNING_FAMINE', 'WARNING_LOWSUPPORT', 'WARNING_LOWFUNDS', 1501 'MOVE_MOUNTAIN', 'MOVE_LOAD', 'MOVE_UNLOAD', 'MOVE_DIE', 'NOMOVE_TIME', 1502 'NOMOVE_DOMAIN', 'NOMOVE_DEFAULT', 'CITY_SELLIMP', 'CITY_REBUILDIMP', 1503 'CITY_BUYPROJECT', 'CITY_UTILIZE', 'NEWMODEL_0', 'NEWADVANCE_0', 1504 'AGE_0', 'REVOLUTION', 'NEWGOV', 'CITY_INVALIDTYPE', 'MSG_GAMEOVER'); 1505 1506 nWonderBlock = 6; 1507 WonderBlock: array [0 .. nWonderBlock - 1] of string = ('WONDER_BUILT', 1508 'WONDER_CAPTURED', 'WONDER_EXPIRED', 'WONDER_DESTROYED', 'MSG_COLDWAR', 1509 'NEWADVANCE_GRLIB'); 1510 1511 nScienceBlock = 17; 1512 ScienceBlock: array [0 .. nScienceBlock - 1] of string = 1513 ('MOVE_PARACHUTE', 'MOVE_PLANESTART', 'MOVE_PLANELANDING', 1514 'MOVE_COVERT', 'NEWMODEL_1', 'NEWMODEL_2', 'NEWMODEL_3', 'NEWADVANCE_1', 1515 'NEWADVANCE_2', 'NEWADVANCE_3', 'AGE_1', 'AGE_2', 'AGE_3', 'SHIP_BUILT', 1516 'SHIP_TRADED', 'SHIP_CAPTURED', 'SHIP_DESTROYED'); 1517 1518 nContactBlock = 20; 1519 ContactBlock: array [0 .. nContactBlock - 1] of string = ('NEWTREATY', 1520 'CANCELTREATY', 'ACCEPTOFFER', 'MSG_WITHDRAW', 'MSG_BANKRUPT', 1521 'CONTACT_0', 'CONTACT_1', 'CONTACT_2', 'CONTACT_3', 'CONTACT_4', 1522 'CONTACT_5', 'CONTACT_5', 'CONTACT_6', 'NEGO_REJECTED', 'MOVE_CAPTURE', 1523 'MOVE_EXPEL', 'NOMOVE_TREATY', 'NOMOVE_ZOC', 'NOMOVE_SUBMARINE', 1524 'NOMOVE_STEALTH'); 1525 1526 var 1527 i, cix, mix: integer; 1528 need: boolean; 1529 mi: TModelInfo; 1530 begin 1531 if Check and sbStart and not SoundPreloadDone <> 0 then 1532 begin 1533 for i := 0 to nStartBlock - 1 do 1534 PreparePlay(StartBlock[i]); 1535 SoundPreloadDone := SoundPreloadDone or sbStart; 1536 end; 1537 if Check and sbWonder and not SoundPreloadDone <> 0 then 1538 begin 1539 need := false; 1540 for i := 0 to 27 do 1541 if MyRO.Wonder[i].CityID <> -1 then 1542 need := true; 1543 if need then 1544 begin 1545 for i := 0 to nWonderBlock - 1 do 1546 PreparePlay(WonderBlock[i]); 1547 SoundPreloadDone := SoundPreloadDone or sbWonder; 1548 end; 1549 end; 1550 if (Check and sbScience and not SoundPreloadDone <> 0) and 1551 (MyRO.Tech[adScience] >= tsApplicable) then 1552 begin 1553 for i := 0 to nScienceBlock - 1 do 1554 PreparePlay(ScienceBlock[i]); 1555 SoundPreloadDone := SoundPreloadDone or sbScience; 1556 end; 1557 if (Check and sbContact and not SoundPreloadDone <> 0) and 1558 (MyRO.nEnemyModel + MyRO.nEnemyCity > 0) then 1559 begin 1560 for i := 0 to nContactBlock - 1 do 1561 PreparePlay(ContactBlock[i]); 1562 SoundPreloadDone := SoundPreloadDone or sbContact; 1563 end; 1564 if Check and sbTurn <> 0 then 1565 begin 1566 if MyRO.Happened and phShipComplete <> 0 then 1567 PreparePlay('MSG_YOUWIN'); 1568 if MyData.ToldAlive <> MyRO.Alive then 1569 PreparePlay('MSG_EXTINCT'); 1570 for cix := 0 to MyRO.nCity - 1 do 1571 with MyCity[cix] do 1572 if (Loc >= 0) and (Flags and CityRepMask <> 0) then 1573 for i := 0 to 12 do 1574 if 1 shl i and Flags and CityRepMask <> 0 then 1575 PreparePlay(CityEventSoundItem[i]); 1576 for mix := 0 to MyRO.nModel - 1 do 1577 with MyModel[mix] do 1578 if Attack > 0 then 1579 begin 1580 MakeModelInfo(me, mix, MyModel[mix], mi); 1581 PreparePlay(AttackSound(ModelCode(mi))); 1582 end 1583 end 1584 end; 1585 1586 procedure InitTurn(p: integer); 1587 const 1588 nAdvBookIcon = 16; 1589 AdvBookIcon: array [0 .. nAdvBookIcon - 1] of record Adv, 1590 Icon: integer end = ((Adv: adPolyTheism; Icon: woZeus), 1591 (Adv: adBronzeWorking; Icon: woColossus), (Adv: adMapMaking; 1592 Icon: woLighthouse), (Adv: adPoetry; Icon: imTheater), 1593 (Adv: adMonotheism; Icon: woMich), (Adv: adPhilosophy; Icon: woLeo), 1594 (Adv: adTheoryOfGravity; Icon: woNewton), (Adv: adSteel; 1595 Icon: woEiffel), (Adv: adDemocracy; Icon: woLiberty), 1596 (Adv: adAutomobile; Icon: imHighways), (Adv: adSanitation; 1597 Icon: imSewer), (Adv: adElectronics; Icon: woHoover), 1598 (Adv: adNuclearFission; Icon: woManhattan), (Adv: adRecycling; 1599 Icon: imRecycling), (Adv: adComputers; Icon: imResLab), 1600 (Adv: adSpaceFlight; Icon: woMIR)); 1601 var 1602 Domain, p1, i, ad, uix, cix, MoveOptions, MoveResult, Loc1, Dist, 1603 NewAgeCenterTo, Bankrupt, ShipMore, Winners, NewGovAvailable, dx, 1604 dy: integer; 1605 MoveAdviceData: TMoveAdviceData; 1606 Picture: TModelPictureInfo; 1607 s, Item, Item2: string; 1608 UpdatePanel, OwnWonder, ok, Stop, ShowCityList, WondersOnly, 1609 AllowCityScreen: boolean; 1610 begin 1611 if IsMultiPlayerGame and (p <> me) then 1612 begin 2648 if LogDlg.Visible then 2649 LogDlg.Close; 2650 LogDlg.List.Clear; 2651 StartRunning := not idle and (Jump[0] > 0); // AI called Reload 2652 me := -1; 2653 idle := false; 2654 ClientMode := -1; 1613 2655 UnitInfoBtn.Visible := false; 1614 2656 UnitBtn.Visible := false; 1615 2657 TerrainBtn.Visible := false; 2658 MovieSpeed1Btn.Visible := false; 2659 MovieSpeed2Btn.Visible := false; 2660 MovieSpeed3Btn.Visible := false; 2661 MovieSpeed4Btn.Visible := false; 1616 2662 EOT.Visible := false; 1617 end;1618 if IsMultiPlayerGame and (p <> me) and1619 (G.RO[0].Happened and phShipComplete = 0) then1620 begin // inter player screen1621 2663 for i := 0 to ControlCount - 1 do 1622 2664 if Controls[i] is TButtonC then 1623 2665 Controls[i].Visible := false; 1624 me := -1; 1625 SetMainTextureByAge(-1); 2666 InitPVSB(sb, 0, 1); 2667 for p1 := 0 to nPl - 1 do 2668 if Tribe[p1] <> nil then 2669 Tribe[p1].free; 2670 Tribes.Done; 2671 RepaintOnResize := false; 2672 Closable := true; 2673 Close; 2674 { if (GameMode=cNewGame) or (GameMode=cLoadGame) then 2675 AdvisorDlg.BreakGame; } 2676 end; 2677 2678 cShowGame: 2679 begin 1626 2680 with Panel.Canvas do 1627 2681 begin … … 1636 2690 Brush.Style := bsClear; 1637 2691 end; 1638 Invalidate; 1639 1640 s := TurnToString(G.RO[0].Turn); 1641 if supervising then 1642 SimpleMessage(Format(Phrases.Lookup('SUPERTURN'), [s])) 1643 else 1644 SimpleMessage(Format(Tribe[NewPlayer].TPhrase('TURN'), [s])); 1645 end; 1646 for i := 0 to ControlCount - 1 do 1647 if Controls[i] is TButtonC then 1648 Controls[i].Visible := true; 1649 1650 ItsMeAgain(p); 1651 MyData := G.RO[p].Data; 1652 if not supervising then 1653 SoundPreload(sbAll); 1654 if (me = 0) and ((MyRO.Turn = 0) or (ClientMode = cResume)) then 1655 Invalidate; // colorize empty space 1656 1657 if not supervising then 1658 begin 1659 1660 { if MyRO.Happened and phGameEnd<>0 then 2692 FormResize(nil); // place mini map correctly according to its size 2693 Show; 2694 Update; 2695 RepaintOnResize := true; 2696 xw := 0; 2697 yw := ywcenter; 2698 if not StayOnTop_Ensured then 2699 begin 2700 StayOnTop_Ensured := true; 2701 CityDlg.StayOnTop_Workaround; 2702 CityTypeDlg.StayOnTop_Workaround; 2703 DiaDlg.StayOnTop_Workaround; 2704 DraftDlg.StayOnTop_Workaround; 2705 EnhanceDlg.StayOnTop_Workaround; 2706 HelpDlg.StayOnTop_Workaround; 2707 NatStatDlg.StayOnTop_Workaround; 2708 NegoDlg.StayOnTop_Workaround; 2709 ModalSelectDlg.StayOnTop_Workaround; 2710 ListDlg.StayOnTop_Workaround; 2711 UnitStatDlg.StayOnTop_Workaround; 2712 WondersDlg.StayOnTop_Workaround; 2713 RatesDlg.StayOnTop_Workaround; 2714 end; 2715 end; 2716 2717 cShowTurnChange: 2718 begin 2719 if integer(Data) >= 0 then 2720 begin 2721 pLogo := integer(Data); 2722 if G.RO[pLogo] = nil then 1661 2723 begin 1662 Age:=3; 1663 SetMainTextureByAge(-1); 2724 if AILogo[pLogo] <> nil then 2725 BitBlt(Canvas.Handle, (xRightPanel + 10) - (16 + 64), 2726 ClientHeight - PanelHeight, 64, 64, AILogo[pLogo].Canvas.Handle, 2727 0, 0, SRCCOPY); 1664 2728 end 1665 else } 2729 end 2730 end; 2731 2732 cTurn, cResume, cContinue: 2733 if not GameOK then 2734 Server(sResign, NewPlayer, 0, nil^) 2735 else 2736 begin 2737 ClientMode := Command; 2738 pTurn := NewPlayer; 2739 pLogo := NewPlayer; 2740 2741 if Command = cResume then 2742 begin // init non-original model pictures (maybe tribes not found) 2743 for p1 := 0 to nPl - 1 do 2744 if G.RO[p1] <> nil then 2745 begin 2746 ItsMeAgain(p1); 2747 for mix := 0 to MyRO.nModel - 1 do 2748 if Tribe[me].ModelPicture[mix].HGr = 0 then 2749 InitMyModel(mix, true); 2750 end; 2751 me := -1; 2752 end; 2753 2754 if Jump[pTurn] > 0 then 2755 Application.ProcessMessages; 2756 if Jump[pTurn] > 0 then 2757 if G.RO[NewPlayer].Happened and phGameEnd <> 0 then 2758 Jump[pTurn] := 0 2759 else 2760 dec(Jump[pTurn]); 2761 SkipTurn := Jump[pTurn] > 0; 2762 if SkipTurn then 1666 2763 begin 1667 Age := GetAge(me); 1668 if SetMainTextureByAge(Age) then 1669 EOT.Invalidate; // has visible background parts in its bounds 2764 ItsMeAgain(NewPlayer); 2765 MyData := G.RO[NewPlayer].Data; 2766 SetTroopLoc(-1); 2767 MiniPaint; 2768 InitAllEnemyModels; // necessary for correct replay 2769 if not EndTurn(true) then 2770 SkipTurn := false; 1670 2771 end; 1671 // age:=MyRO.Turn mod 4; //!!! 1672 if ClientMode = cMovieTurn then 1673 EOT.ButtonIndex := eotCancel 1674 else if ClientMode < scContact then 1675 EOT.ButtonIndex := eotGray 1676 else 1677 EOT.ButtonIndex := eotBackToNego; 1678 end 1679 else 1680 begin 1681 Age := 0; 1682 SetMainTextureByAge(-1); 1683 if ClientMode = cMovieTurn then 1684 EOT.ButtonIndex := eotCancel 1685 else 1686 EOT.ButtonIndex := eotBlinkOn; 1687 end; 1688 InitCityMark(MainTexture); 1689 CityDlg.CheckAge; 1690 NatStatDlg.CheckAge; 1691 UnitStatDlg.CheckAge; 1692 HelpDlg.Difficulty := G.Difficulty[me]; 1693 1694 UnFocus := -1; 1695 MarkCityLoc := -1; 1696 BlinkON := false; 1697 BlinkTime := -1; 1698 Tracking := false; 1699 TurnComplete := false; 1700 1701 if (ToldSlavery < 0) or 1702 ((ToldSlavery = 1) <> (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)) 1703 then 1704 begin 1705 if MyRO.Wonder[woPyramids].EffectiveOwner >= 0 then 1706 ToldSlavery := 1 1707 else 1708 ToldSlavery := 0; 1709 for p1 := 0 to nPl - 1 do 1710 if (Tribe[p1] <> nil) and (Tribe[p1].mixSlaves >= 0) then 1711 with Picture do 1712 begin // replace unit picture 1713 mix := Tribe[p1].mixSlaves; 1714 if ToldSlavery = 1 then 1715 pix := pixSlaves 1716 else 1717 pix := pixNoSlaves; 1718 Hash := 0; 1719 GrName := 'StdUnits'; 1720 Tribe[p1].SetModelPicture(Picture, true); 2772 if not SkipTurn then 2773 begin 2774 if ((ClientMode < scDipStart) or (ClientMode > scDipBreak)) and 2775 NegoDlg.Visible then 2776 NegoDlg.Close; 2777 skipped := false; // always show my moves during my turn 2778 idle := true; 2779 InitTurn(NewPlayer); 2780 DipMem[me].pContact := -1; 2781 (* if (me=0) and (MyRO.Alive and (1 shl me)=0)} then 2782 begin 2783 if SimpleQuery(Phrases.Lookup('RESIGN'))=mrIgnore then 2784 Server(sResign,me,0,nil^) 2785 else Server(sBreak,me,0,nil^) 1721 2786 end 1722 end; 1723 1724 if not supervising and (ClientMode = cTurn) then 1725 begin 1726 for cix := 0 to MyRO.nCity - 1 do 1727 if (MyCity[cix].Loc >= 0) and 1728 ((MyRO.Turn = 0) or (MyCity[cix].Flags and chFounded <> 0)) then 1729 MyCity[cix].Status := MyCity[cix].Status and 1730 not csResourceWeightsMask or (3 shl 4); 1731 // new city, set to maximum growth 1732 end; 1733 if (ClientMode = cTurn) or (ClientMode = cContinue) then 1734 CityOptimizer_BeginOfTurn; // maybe peace was made or has ended 1735 SumCities(TaxSum, ScienceSum); 1736 1737 if ClientMode = cMovieTurn then 1738 begin 2787 else Play('TURNSTART'); *) 2788 end; 2789 end; 2790 2791 cMovieTurn: 2792 begin 2793 ClientMode := Command; 2794 pTurn := NewPlayer; 2795 pLogo := -1; 2796 skipped := false; // always show my moves during my turn 2797 idle := true; 2798 if FirstMovieTurn then 2799 begin 2800 CheckMovieSpeedBtnState; 2801 FirstMovieTurn := false; 2802 end; 2803 InitTurn(NewPlayer); 2804 Application.ProcessMessages; 2805 if MovieSpeed = 4 then 2806 begin 2807 Sleep(75); 2808 // this break will ensure speed of fast forward does not depend on cpu speed 2809 Application.ProcessMessages; 2810 end 2811 end; 2812 2813 cMovieEndTurn: 2814 begin 2815 RememberPeaceViolation; 2816 pTurn := -1; 2817 pLogo := -1; 2818 MapValid := false; 2819 ClientMode := -1; 2820 idle := false; 2821 skipped := false; 2822 end; 2823 2824 cEditMap: 2825 begin 2826 ClientMode := cEditMap; 2827 SetMapOptions; 2828 IsoEngine.pDebugMap := -1; 2829 ItsMeAgain(0); 2830 MyData := nil; 1739 2831 UnitInfoBtn.Visible := false; 1740 2832 UnitBtn.Visible := false; 1741 2833 TerrainBtn.Visible := false; 1742 EOT.Hint := Phrases.Lookup('BTN_STOP');1743 EOT.Visible := true;1744 end1745 else if ClientMode < scContact then1746 begin1747 UnitInfoBtn.Visible := UnFocus >= 0;1748 UnitBtn.Visible := UnFocus >= 0;1749 CheckTerrainBtnVisible;1750 TurnComplete := supervising;1751 EOT.Hint := Phrases.Lookup('BTN_ENDTURN');1752 EOT.Visible := Server(sTurn - sExecute, me, 0, nil^) >= rExecuted;1753 end1754 else1755 begin1756 UnitInfoBtn.Visible := false;1757 UnitBtn.Visible := false;1758 TerrainBtn.Visible := false;1759 EOT.Hint := Phrases.Lookup('BTN_NEGO');1760 EOT.Visible := true; 1761 end;1762 SetTroopLoc(-1);1763 MapValid := false;1764 NewAgeCenterTo := 0;1765 if ((MyRO.Turn = 0) and not supervising or IsMultiPlayerGame or 1766 (ClientMode = cResume)) and (MyRO.nCity > 0) then1767 begin 1768 Loc1 := MyCity[0].Loc;1769 if (ClientMode = cTurn) and (MyRO.Turn = 0)then1770 begin // move city out of center to not be covered by welcome screen1771 dx := MapWidth div (xxt * 5);1772 if dx > 5 then1773 dx := 5;1774 dy := MapHeight div (yyt * 5);1775 if dy > 5 then1776 dy := 5;1777 if Loc1 >= G.lx * G.ly div 2 then2834 MovieSpeed1Btn.Visible := false; 2835 MovieSpeed2Btn.Visible := false; 2836 MovieSpeed3Btn.Visible := false; 2837 MovieSpeed4Btn.Visible := false; 2838 EOT.Visible := false; 2839 HelpDlg.Difficulty := 0; 2840 BrushType := fGrass; 2841 BrushLoc := -1; 2842 Edited := false; 2843 UnFocus := -1; 2844 MarkCityLoc := -1; 2845 Tracking := false; 2846 TurnComplete := false; 2847 MapValid := false; 2848 FormResize(nil); // calculate geometrics and paint all 2849 SetTroopLoc(-1); 2850 idle := true 2851 end; 2852 2853 (* cNewContact: 2854 begin 2855 end; 2856 *) 2857 2858 scContact: 2859 begin 2860 DipMem[NewPlayer].pContact := integer(Data); 2861 if Jump[NewPlayer] > 0 then 2862 DipCall(scReject) 2863 else 2864 begin 2865 ClientMode := Command; 2866 InitTurn(NewPlayer); 2867 MyData.ToldContact := MyData.ToldContact or (1 shl integer(Data)); 2868 // don't tell about new nation when already contacted by them 2869 with MessgExDlg do 1778 2870 begin 1779 NewAgeCenterTo := -1; 1780 Loc1 := dLoc(Loc1, -dx, -dy) 2871 OpenSound := 'CONTACT_' + char(48 + MyRO.EnemyReport[integer(Data) 2872 ].Attitude); 2873 MessgText := Tribe[integer(Data)].TPhrase('FRCONTACT'); 2874 Kind := mkYesNo; 2875 IconKind := mikTribe; 2876 IconIndex := integer(Data); 2877 ShowModal; 2878 if ModalResult = mrOK then 2879 begin 2880 NegoDlg.Respond; 2881 DipMem[me].DeliveredPrices := []; 2882 DipMem[me].ReceivedPrices := []; 2883 DipCall(scDipStart) 2884 end 2885 else 2886 begin 2887 DipCall(scReject); 2888 EndNego 2889 end 2890 end 2891 end; 2892 end; 2893 2894 scDipStart .. scDipBreak: 2895 begin 2896 ClientMode := Command; 2897 InitTurn(NewPlayer); 2898 if Command = scDipStart then 2899 Play('CONTACT_' + char(48 + MyRO.Attitude[DipMem[NewPlayer] 2900 .pContact])) 2901 else if Command = scDipCancelTreaty then 2902 Play('CANCELTREATY') 2903 else if Command = scDipOffer then 2904 begin 2905 ReceivedOffer := TOffer(Data); 2906 InitAllEnemyModels; 2907 end 2908 else if Command = scDipAccept then 2909 begin // remember delivered and received prices 2910 for i := 0 to DipMem[me].SentOffer.nDeliver - 1 do 2911 include(DipMem[me].DeliveredPrices, 2912 DipMem[me].SentOffer.Price[i] shr 24); 2913 for i := 0 to DipMem[me].SentOffer.nCost - 1 do 2914 include(DipMem[me].ReceivedPrices, 2915 DipMem[me].SentOffer.Price[DipMem[me].SentOffer.nDeliver + 2916 i] shr 24); 2917 IsTreatyDeal := false; 2918 for i := 0 to ReceivedOffer.nDeliver + ReceivedOffer.nCost - 1 do 2919 if DipMem[me].SentOffer.Price[i] and opMask = opTreaty then 2920 IsTreatyDeal := true; 2921 if IsTreatyDeal then 2922 Play('NEWTREATY') 2923 else 2924 Play('ACCEPTOFFER'); 2925 end; 2926 NegoDlg.Start; 2927 idle := true 2928 end; 2929 2930 cShowCancelTreaty: 2931 if not IsMultiPlayerGame then 2932 begin 2933 case G.RO[NewPlayer].Treaty[integer(Data)] of 2934 trPeace: 2935 s := Tribe[integer(Data)].TPhrase('FRCANCELBYREJECT_PEACE'); 2936 trFriendlyContact: 2937 s := Tribe[integer(Data)].TPhrase('FRCANCELBYREJECT_FRIENDLY'); 2938 trAlliance: 2939 s := Tribe[integer(Data)].TPhrase('FRCANCELBYREJECT_ALLIANCE'); 2940 end; 2941 TribeMessage(integer(Data), s, 'CANCELTREATY'); 2942 end; 2943 2944 cShowCancelTreatyByAlliance: 2945 if idle and (NewPlayer = me) then 2946 TribeMessage(integer(Data), Tribe[integer(Data) 2947 ].TPhrase('FRENEMYALLIANCE'), 'CANCELTREATY'); 2948 2949 cShowSupportAllianceAgainst: 2950 if not IsMultiPlayerGame and (Jump[0] = 0) then 2951 TribeMessage(integer(Data) and $F, Tribe[integer(Data) and $F] 2952 .TPhrase('FRMYALLIANCE1') + ' ' + Tribe[integer(Data) shr 4] 2953 .TPhrase('FRMYALLIANCE2'), '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 1781 3087 end 1782 3088 else 1783 3089 begin 1784 NewAgeCenterTo := 1; 1785 Loc1 := dLoc(Loc1, -dx, dy); 1786 end 1787 end; 1788 Centre(Loc1) 1789 end; 1790 1791 for i := 0 to Screen.FormCount - 1 do 1792 if Screen.Forms[i] is TBufferedDrawDlg then 1793 Screen.Forms[i].Enabled := true; 1794 1795 if ClientMode <> cResume then 1796 begin 1797 PaintAll; 1798 if (MyRO.Happened and phChangeGov <> 0) and (MyRO.NatBuilt[imPalace] > 0) 1799 then 1800 ImpImage(Panel.Canvas, ClientWidth - xPalace, yPalace, imPalace, 1801 gAnarchy { , GameMode<>cMovie } ); 1802 // first turn after anarchy -- don't show despotism palace! 1803 Update; 1804 for i := 0 to Screen.FormCount - 1 do 1805 if (Screen.Forms[i].Visible) and (Screen.Forms[i] is TBufferedDrawDlg) 1806 then 1807 begin 1808 if @Screen.Forms[i].OnShow <> nil then 1809 Screen.Forms[i].OnShow(nil); 1810 Screen.Forms[i].Invalidate; 1811 Screen.Forms[i].Update; 1812 end; 1813 1814 if MyRO.Happened and phGameEnd <> 0 then 1815 with MessgExDlg do 1816 begin // game ended 1817 if MyRO.Happened and phExtinct <> 0 then 1818 begin 1819 OpenSound := 'MSG_GAMEOVER'; 1820 MessgText := Tribe[me].TPhrase('GAMEOVER'); 1821 IconKind := mikBigIcon; 1822 IconIndex := 8; 1823 end 1824 else if MyRO.Happened and phShipComplete <> 0 then 1825 begin 1826 Winners := 0; 1827 for p1 := 0 to nPl - 1 do 1828 if 1 shl p1 and MyRO.Alive <> 0 then 1829 begin 1830 Winners := Winners or 1 shl p1; 1831 for i := 0 to nShipPart - 1 do 1832 if MyRO.Ship[p1].Parts[i] < ShipNeed[i] then 1833 Winners := Winners and not(1 shl p1); 1834 end; 1835 assert(Winners <> 0); 1836 if Winners and (1 shl me) <> 0 then 1837 begin 1838 s := ''; 1839 for p1 := 0 to nPl - 1 do 1840 if (p1 <> me) and (1 shl p1 and Winners <> 0) then 1841 if s = '' then 1842 s := Tribe[p1].TPhrase('SHORTNAME') 1843 else 1844 s := Format(Phrases.Lookup('SHAREDWIN_CONCAT'), 1845 [s, Tribe[p1].TPhrase('SHORTNAME')]); 1846 1847 OpenSound := 'MSG_YOUWIN'; 1848 MessgText := Tribe[me].TPhrase('MYSPACESHIP'); 1849 if s <> '' then 1850 MessgText := MessgText + '\' + 1851 Format(Phrases.Lookup('SHAREDWIN'), [s]); 1852 IconKind := mikBigIcon; 1853 IconIndex := 9; 1854 end 1855 else 1856 begin 1857 assert(me = 0); 1858 OpenSound := 'MSG_GAMEOVER'; 1859 MessgText := ''; 1860 for p1 := 0 to nPl - 1 do 1861 if Winners and (1 shl p1) <> 0 then 1862 MessgText := MessgText + Tribe[p1].TPhrase('SPACESHIP1'); 1863 MessgText := MessgText + '\' + Phrases.Lookup('SPACESHIP2'); 1864 IconKind := mikEnemyShipComplete; 1865 end 1866 end 1867 else { if MyRO.Happened and fTimeUp<>0 then } 1868 begin 1869 assert(me = 0); 1870 OpenSound := 'MSG_GAMEOVER'; 1871 if not supervising then 1872 MessgText := Tribe[me].TPhrase('TIMEUP') 1873 else 1874 MessgText := Phrases.Lookup('TIMEUPSUPER'); 1875 IconKind := mikImp; 1876 IconIndex := 22; 1877 end; 1878 Kind := mkOk; 1879 ShowModal; 1880 if MyRO.Happened and phExtinct = 0 then 1881 begin 1882 p1 := 0; 1883 while (p1 < nPl - 1) and (Winners and (1 shl p1) = 0) do 1884 inc(p1); 1885 if MyRO.Happened and phShipComplete = 0 then 1886 DiaDlg.ShowNewContent_Charts(wmModal); 1887 end; 1888 TurnComplete := true; 1889 exit; 1890 end; 1891 if not supervising and (1 shl me and MyRO.Alive = 0) then 1892 begin 1893 TurnComplete := true; 1894 exit; 1895 end; 1896 1897 if (ClientMode = cContinue) and 1898 (DipMem[me].SentCommand and $FF0F = scContact) then 1899 // contact was refused 1900 if MyRO.Treaty[DipMem[me].pContact] >= trPeace then 1901 ContactRefused(DipMem[me].pContact, 'FRREJECTED') 1902 else 1903 SoundMessage(Tribe[DipMem[me].pContact].TPhrase('FRREJECTED'), 1904 'NEGO_REJECTED'); 1905 1906 if not supervising and (Age > MyData.ToldAge) and 1907 ((Age > 0) or (ClientMode <> cMovieTurn)) then 1908 with MessgExDlg do 1909 begin 1910 if Age = 0 then 1911 begin 1912 if Phrases2FallenBackToEnglish then 1913 begin 1914 s := Tribe[me].TPhrase('AGE0'); 1915 MessgText := 1916 Format(s, [TurnToString(MyRO.Turn), CityName(MyCity[0].ID)]) 1917 end 1918 else 1919 begin 1920 s := Tribe[me].TString(Phrases2.Lookup('AGE0')); 1921 MessgText := Format(s, [TurnToString(MyRO.Turn)]); 1922 end 1923 end 1924 else 1925 begin 1926 s := Tribe[me].TPhrase('AGE' + char(48 + Age)); 1927 MessgText := Format(s, [TurnToString(MyRO.Turn)]); 1928 end; 1929 IconKind := mikAge; 1930 IconIndex := Age; 1931 { if age=0 then } Kind := mkOk 1932 { else begin Kind:=mkOkHelp; HelpKind:=hkAdv; HelpNo:=AgePreq[age]; end }; 1933 CenterTo := NewAgeCenterTo; 1934 OpenSound := 'AGE_' + char(48 + Age); 1935 ShowModal; 1936 MyData.ToldAge := Age; 1937 if Age > 0 then 1938 MyData.ToldTech[AgePreq[Age]] := MyRO.Tech[AgePreq[Age]]; 1939 end; 1940 1941 if MyData.ToldAlive <> MyRO.Alive then 1942 begin 1943 for p1 := 0 to nPl - 1 do 1944 if (MyData.ToldAlive - MyRO.Alive) and (1 shl p1) <> 0 then 1945 with MessgExDlg do 1946 begin 1947 OpenSound := 'MSG_EXTINCT'; 1948 s := Tribe[p1].TPhrase('EXTINCT'); 1949 MessgText := Format(s, [TurnToString(MyRO.Turn)]); 1950 if MyRO.Alive = 1 shl me then 1951 MessgText := MessgText + Phrases.Lookup('EXTINCTALL'); 1952 Kind := mkOk; 1953 IconKind := mikImp; 1954 IconIndex := 21; 1955 ShowModal; 1956 end; 1957 if (ClientMode <> cMovieTurn) and not supervising then 1958 DiaDlg.ShowNewContent_Charts(wmModal); 1959 end; 1960 1961 // tell changes of own credibility 1962 if not supervising then 1963 begin 1964 if RoughCredibility(MyRO.Credibility) <> 1965 RoughCredibility(MyData.ToldOwnCredibility) then 1966 begin 1967 if RoughCredibility(MyRO.Credibility) > 1968 RoughCredibility(MyData.ToldOwnCredibility) then 1969 s := Phrases.Lookup('CREDUP') 1970 else 1971 s := Phrases.Lookup('CREDDOWN'); 1972 TribeMessage(me, 1973 Format(s, [Phrases.Lookup('CREDIBILITY', 1974 RoughCredibility(MyRO.Credibility))]), ''); 1975 end; 1976 MyData.ToldOwnCredibility := MyRO.Credibility; 1977 end; 1978 1979 for i := 0 to 27 do 1980 begin 1981 OwnWonder := false; 1982 for cix := 0 to MyRO.nCity - 1 do 1983 if (MyCity[cix].Loc >= 0) and 1984 (MyCity[cix].ID = MyRO.Wonder[i].CityID) then 1985 OwnWonder := true; 1986 if MyRO.Wonder[i].CityID <> MyData.ToldWonders[i].CityID then 1987 begin 1988 if MyRO.Wonder[i].CityID = -2 then 1989 with MessgExDlg do 1990 begin { tell about destroyed wonders } 1991 OpenSound := 'WONDER_DESTROYED'; 1992 MessgText := Format(Phrases.Lookup('WONDERDEST'), 1993 [Phrases.Lookup('IMPROVEMENTS', i)]); 1994 Kind := mkOkHelp; 1995 HelpKind := hkImp; 1996 HelpNo := i; 1997 IconKind := mikImp; 1998 IconIndex := i; 1999 ShowModal; 2000 end 2001 else 2002 begin 2003 if i = woManhattan then 2004 if MyRO.Wonder[i].EffectiveOwner > me then 2005 MyData.ColdWarStart := MyRO.Turn - 1 2006 else 2007 MyData.ColdWarStart := MyRO.Turn; 2008 if not OwnWonder then 2009 with MessgExDlg do 2010 begin { tell about newly built wonders } 2011 if i = woManhattan then 2012 begin 2013 OpenSound := 'MSG_COLDWAR'; 2014 s := Tribe[MyRO.Wonder[i].EffectiveOwner].TPhrase('COLDWAR') 2015 end 2016 else if MyRO.Wonder[i].EffectiveOwner >= 0 then 2017 begin 2018 OpenSound := 'WONDER_BUILT'; 2019 s := Tribe[MyRO.Wonder[i].EffectiveOwner] 2020 .TPhrase('WONDERBUILT') 2021 end 2022 else 2023 begin 2024 OpenSound := 'MSG_DEFAULT'; 2025 s := Phrases.Lookup('WONDERBUILTEXP'); 2026 // already expired when built 2027 end; 2028 MessgText := Format(s, [Phrases.Lookup('IMPROVEMENTS', i), 2029 CityName(MyRO.Wonder[i].CityID)]); 2030 Kind := mkOkHelp; 2031 HelpKind := hkImp; 2032 HelpNo := i; 2033 IconKind := mikImp; 2034 IconIndex := i; 2035 ShowModal; 2036 end 2037 end 2038 end 2039 else if (MyRO.Wonder[i].EffectiveOwner <> MyData.ToldWonders[i] 2040 .EffectiveOwner) and (MyRO.Wonder[i].CityID > -2) then 2041 if MyRO.Wonder[i].EffectiveOwner < 0 then 2042 begin 2043 if i <> woMIR then 2044 with MessgExDlg do 2045 begin { tell about expired wonders } 2046 OpenSound := 'WONDER_EXPIRED'; 2047 MessgText := Format(Phrases.Lookup('WONDEREXP'), 2048 [Phrases.Lookup('IMPROVEMENTS', i), 2049 CityName(MyRO.Wonder[i].CityID)]); 2050 Kind := mkOkHelp; 2051 HelpKind := hkImp; 2052 HelpNo := i; 2053 IconKind := mikImp; 2054 IconIndex := i; 2055 ShowModal; 2056 end 2057 end 2058 else if (MyData.ToldWonders[i].EffectiveOwner >= 0) and not OwnWonder 2059 then 2060 with MessgExDlg do 2061 begin { tell about capture of wonders } 2062 OpenSound := 'WONDER_CAPTURED'; 2063 s := Tribe[MyRO.Wonder[i].EffectiveOwner].TPhrase('WONDERCAPT'); 2064 MessgText := Format(s, [Phrases.Lookup('IMPROVEMENTS', i), 2065 CityName(MyRO.Wonder[i].CityID)]); 2066 Kind := mkOkHelp; 2067 HelpKind := hkImp; 2068 HelpNo := i; 2069 IconKind := mikImp; 2070 IconIndex := i; 2071 ShowModal; 2072 end; 2073 end; 2074 2075 if MyRO.Turn = MyData.ColdWarStart + ColdWarTurns then 2076 begin 2077 SoundMessageEx(Phrases.Lookup('COLDWAREND'), 'MSG_DEFAULT'); 2078 MyData.ColdWarStart := -ColdWarTurns - 1 2079 end; 2080 2081 TellNewModels; 2082 end; // ClientMode<>cResume 2083 MyData.ToldAlive := MyRO.Alive; 2084 move(MyRO.Wonder, MyData.ToldWonders, SizeOf(MyData.ToldWonders)); 2085 2086 NewGovAvailable := -1; 2087 if ClientMode <> cResume then 2088 begin // tell about new techs 2089 for ad := 0 to nAdv - 1 do 2090 if (MyRO.TestFlags and tfAllTechs = 0) and 2091 ((MyRO.Tech[ad] >= tsApplicable) <> 2092 (MyData.ToldTech[ad] >= tsApplicable)) or (ad in FutureTech) and 2093 (MyRO.Tech[ad] <> MyData.ToldTech[ad]) then 2094 with MessgExDlg do 2095 begin 2096 Item := 'RESEARCH_GENERAL'; 2097 if GameMode <> cMovie then 2098 OpenSound := 'NEWADVANCE_' + char(48 + Age); 2099 Item2 := Phrases.Lookup('ADVANCES', ad); 2100 if ad in FutureTech then 2101 Item2 := Item2 + ' ' + IntToStr(MyRO.Tech[ad]); 2102 MessgText := Format(Phrases.Lookup(Item), [Item2]); 2103 Kind := mkOkHelp; 2104 HelpKind := hkAdv; 2105 HelpNo := ad; 2106 IconKind := mikBook; 2107 IconIndex := -1; 2108 for i := 0 to nAdvBookIcon - 1 do 2109 if AdvBookIcon[i].Adv = ad then 2110 IconIndex := AdvBookIcon[i].Icon; 2111 ShowModal; 2112 MyData.ToldTech[ad] := MyRO.Tech[ad]; 2113 for i := gMonarchy to nGov - 1 do 2114 if GovPreq[i] = ad then 2115 NewGovAvailable := i; 2116 end; 2117 end; 2118 2119 ShowCityList := false; 2120 if ClientMode = cTurn then 2121 begin 2122 if (MyRO.Happened and phTech <> 0) and (MyData.FarTech <> adNexus) then 2123 ChooseResearch; 2124 2125 UpdatePanel := false; 2126 if MyRO.Happened and phChangeGov <> 0 then 2127 begin 2128 ModalSelectDlg.ShowNewContent(wmModal, kGov); 2129 Play('NEWGOV'); 2130 Server(sSetGovernment, me, ModalSelectDlg.result, nil^); 2131 CityOptimizer_BeginOfTurn; 2132 UpdatePanel := true; 2133 end; 2134 end; // ClientMode=cTurn 2135 2136 if not supervising and ((ClientMode = cTurn) or (ClientMode = cMovieTurn)) 2137 then 2138 for cix := 0 to MyRO.nCity - 1 do 2139 with MyCity[cix] do 2140 Status := Status and not csToldBombard; 2141 2142 if ((ClientMode = cTurn) or (ClientMode = cMovieTurn)) and 2143 (MyRO.Government <> gAnarchy) then 2144 begin 2145 // tell what happened in cities 2146 for WondersOnly := true downto false do 2147 for cix := 0 to MyRO.nCity - 1 do 2148 with MyCity[cix] do 2149 if (MyRO.Turn > 0) and (Loc >= 0) and (Flags and chCaptured = 0) 2150 and (WondersOnly = (Flags and chProduction <> 0) and 2151 (Project0 and cpImp <> 0) and (Project0 and cpIndex < 28)) then 2152 begin 2153 if WondersOnly then 2154 with MessgExDlg do 2155 begin { tell about newly built wonder } 2156 OpenSound := 'WONDER_BUILT'; 2157 s := Tribe[me].TPhrase('WONDERBUILTOWN'); 2158 MessgText := 2159 Format(s, [Phrases.Lookup('IMPROVEMENTS', 2160 Project0 and cpIndex), CityName(ID)]); 2161 Kind := mkOkHelp; 2162 HelpKind := hkImp; 2163 HelpNo := Project0 and cpIndex; 2164 IconKind := mikImp; 2165 IconIndex := Project0 and cpIndex; 2166 ShowModal; 2167 end; 2168 if not supervising and (ClientMode = cTurn) then 2169 begin 2170 AllowCityScreen := true; 2171 if (Status and 7 <> 0) and 2172 (Project and (cpImp + cpIndex) = cpImp + imTrGoods) then 2173 if (MyData.ImpOrder[Status and 7 - 1, 0] >= 0) then 2174 begin 2175 if AutoBuild(cix, MyData.ImpOrder[Status and 7 - 1]) then 2176 AllowCityScreen := false 2177 else if Flags and chProduction <> 0 then 2178 Flags := (Flags and not chProduction) or chAllImpsMade 2179 end 2180 else 2181 Flags := Flags or chTypeDel; 2182 if (Size >= NeedAqueductSize) and 2183 (MyRO.Tech[Imp[imAqueduct].Preq] < tsApplicable) or 2184 (Size >= NeedSewerSize) and 2185 (MyRO.Tech[Imp[imSewer].Preq] < tsApplicable) then 2186 Flags := Flags and not chNoGrowthWarning; 2187 // don't remind of unknown building 2188 if Flags and chNoSettlerProd = 0 then 2189 Status := Status and not csToldDelay 2190 else if Status and csToldDelay = 0 then 2191 Status := Status or csToldDelay 2192 else 2193 Flags := Flags and not chNoSettlerProd; 2194 if mRepScreens.Checked then 2195 begin 2196 if (Flags and CityRepMask <> 0) and AllowCityScreen then 2197 begin { show what happened in cities } 2198 SetTroopLoc(MyCity[cix].Loc); 2199 MarkCityLoc := MyCity[cix].Loc; 2200 PanelPaint; 2201 CityDlg.CloseAction := None; 2202 CityDlg.ShowNewContent(wmModal, MyCity[cix].Loc, 2203 Flags and CityRepMask); 2204 UpdatePanel := true; 2205 end 2206 end 2207 else { if mRepList.Checked then } 2208 begin 2209 if Flags and CityRepMask <> 0 then 2210 ShowCityList := true 2211 end 2212 end 2213 end; { city loop } 2214 end; // ClientMode=cTurn 2215 2216 if ClientMode = cTurn then 2217 begin 2218 if NewGovAvailable >= 0 then 2219 with MessgExDlg do 2220 begin 2221 MessgText := Format(Phrases.Lookup('AUTOREVOLUTION'), 2222 [Phrases.Lookup('GOVERNMENT', NewGovAvailable)]); 2223 Kind := mkYesNo; 2224 IconKind := mikPureIcon; 2225 IconIndex := 6 + NewGovAvailable; 2226 ShowModal; 2227 if ModalResult = mrOK then 2228 begin 2229 Play('REVOLUTION'); 2230 Server(sRevolution, me, 0, nil^); 2231 end 2232 end; 2233 end; // ClientMode=cTurn 2234 2235 if (ClientMode = cTurn) or (ClientMode = cMovieTurn) then 2236 begin 2237 if MyRO.Happened and phGliderLost <> 0 then 2238 ContextMessage(Phrases.Lookup('GLIDERLOST'), 'MSG_DEFAULT', 2239 hkModel, 200); 2240 if MyRO.Happened and phPlaneLost <> 0 then 2241 ContextMessage(Phrases.Lookup('PLANELOST'), 'MSG_DEFAULT', 2242 hkFeature, mcFuel); 2243 if MyRO.Happened and phPeaceEvacuation <> 0 then 2244 for p1 := 0 to nPl - 1 do 2245 if 1 shl p1 and MyData.PeaceEvaHappened <> 0 then 2246 SoundMessageEx(Tribe[p1].TPhrase('WITHDRAW'), 'MSG_DEFAULT'); 2247 if MyRO.Happened and phPeaceViolation <> 0 then 2248 for p1 := 0 to nPl - 1 do 2249 if (1 shl p1 and MyRO.Alive <> 0) and (MyRO.EvaStart[p1] = MyRO.Turn) 2250 then 2251 SoundMessageEx(Format(Tribe[p1].TPhrase('VIOLATION'), 2252 [TurnToString(MyRO.Turn + PeaceEvaTurns - 1)]), 'MSG_WITHDRAW'); 2253 TellNewContacts; 2254 end; 2255 2256 if ClientMode = cMovieTurn then 2257 Update 2258 else if ClientMode = cTurn then 2259 begin 2260 if UpdatePanel then 2261 UpdateViews; 2262 Application.ProcessMessages; 2263 2264 if not supervising then 2265 for uix := 0 to MyRO.nUn - 1 do 2266 with MyUn[uix] do 2267 if Loc >= 0 then 2268 begin 2269 if Flags and unWithdrawn <> 0 then 2270 Status := 0; 2271 if Health = 100 then 2272 Status := Status and not usRecover; 2273 if (Master >= 0) or UnitExhausted(uix) then 2274 Status := Status and not usWaiting 2275 else 2276 Status := Status or usWaiting; 2277 CheckToldNoReturn(uix); 2278 if Status and usGoto <> 0 then 2279 begin { continue multi-turn goto } 2280 SetUnFocus(uix); 2281 SetTroopLoc(Loc); 2282 FocusOnLoc(TroopLoc, flRepaintPanel or flImmUpdate); 2283 if Status shr 16 = $7FFF then 2284 MoveResult := GetMoveAdvice(UnFocus, maNextCity, 2285 MoveAdviceData) 2286 else 2287 MoveResult := GetMoveAdvice(UnFocus, Status shr 16, 2288 MoveAdviceData); 2289 if MoveResult >= rExecuted then 2290 begin // !!! Shinkansen 2291 MoveResult := eOK; 2292 ok := true; 2293 for i := 0 to MoveAdviceData.nStep - 1 do 2294 begin 2295 Loc1 := dLoc(Loc, MoveAdviceData.dx[i], 2296 MoveAdviceData.dy[i]); 2297 if (MyMap[Loc1] and (fCity or fOwned) = fCity) 2298 // don't capture cities during auto move 2299 or (MyMap[Loc1] and (fUnit or fOwned) = fUnit) then 2300 // don't attack during auto move 2301 begin 2302 ok := false; 2303 Break 2304 end 2305 else 2306 begin 2307 if (Loc1 = MoveAdviceData.ToLoc) or 2308 (MoveAdviceData.ToLoc = maNextCity) and 2309 (MyMap[dLoc(Loc, MoveAdviceData.dx[i], 2310 MoveAdviceData.dy[i])] and fCity <> 0) then 2311 MoveOptions := muAutoNoWait 2312 else 2313 MoveOptions := 0; 2314 MoveResult := MoveUnit(MoveAdviceData.dx[i], 2315 MoveAdviceData.dy[i], MoveOptions); 2316 if (MoveResult < rExecuted) or 2317 (MoveResult = eEnemySpotted) then 2318 begin 2319 ok := false; 2320 Break 2321 end; 2322 end 2323 end; 2324 Stop := not ok or (Loc = MoveAdviceData.ToLoc) or 2325 (MoveAdviceData.ToLoc = maNextCity) and 2326 (MyMap[Loc] and fCity <> 0) 2327 end 2328 else 2329 begin 2330 MoveResult := eOK; 2331 Stop := true; 2332 end; 2333 2334 if MoveResult <> eDied then 2335 if Stop then 2336 Status := Status and ($FFFF - usGoto) 2337 else 2338 Status := Status and not usWaiting; 2339 end; 2340 2341 if Status and (usEnhance or usGoto) = usEnhance then 2342 // continue terrain enhancement 2343 begin 2344 MoveResult := ProcessEnhancement(uix, MyData.EnhancementJobs); 2345 if MoveResult <> eDied then 2346 if MoveResult = eJobDone then 2347 Status := Status and not usEnhance 2348 else 2349 Status := Status and not usWaiting; 2350 end 2351 end; 2352 end; // ClientMode=cTurn 2353 2354 HaveStrategyAdvice := false; 2355 // (GameMode<>cMovie) and not supervising 2356 // and AdvisorDlg.HaveStrategyAdvice; 2357 GoOnPhase := true; 2358 if supervising or (GameMode = cMovie) then 2359 begin 2360 SetTroopLoc(-1); 2361 PaintAll 2362 end { supervisor } 2363 { else if (ClientMode=cTurn) and (MyRO.Turn=0) then 2364 begin 2365 SetUnFocus(0); 2366 ZoomToCity(MyCity[0].Loc) 2367 end } 2368 else 2369 begin 2370 if ClientMode >= scContact then 2371 SetUnFocus(-1) 2372 else 2373 NextUnit(-1, false); 2374 if UnFocus < 0 then 2375 begin 2376 UnStartLoc := -1; 2377 if IsMultiPlayerGame or (ClientMode = cResume) then 2378 if MyRO.nCity > 0 then 2379 FocusOnLoc(MyCity[0].Loc) 2380 else 2381 FocusOnLoc(G.lx * G.ly div 2); 2382 SetTroopLoc(-1); 2383 PanelPaint 2384 end; 2385 if ShowCityList then 2386 ListDlg.ShowNewContent(wmPersistent, kCityEvents); 2387 end; 2388 end; { InitTurn } 2389 2390 var 2391 i, j, p1, mix, ToLoc, AnimationSpeed, ShowMoveDomain, cix, ecix: integer; 2392 Color: TColor; 2393 Name, s: string; 2394 TribeInfo: TTribeInfo; 2395 mi: TModelInfo; 2396 SkipTurn, IsAlpine, IsTreatyDeal: boolean; 2397 2398 begin { >>>client } 2399 case Command of 2400 cTurn, cResume, cContinue, cMovieTurn, scContact, 2401 scDipStart .. scDipBreak: 2402 begin 2403 supervising := G.Difficulty[NewPlayer] = 0; 2404 ArrangeMidPanel; 2405 end 2406 end; 2407 case Command of 2408 cDebugMessage: 2409 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(@Data)); 2410 2411 cShowNego: 2412 with TShowNegoData(Data) do 2413 begin 2414 s := Format('P%d to P%d: ', [pSender, pTarget]); 2415 if (Action = scDipOffer) and (Offer.nDeliver + Offer.nCost > 0) then 2416 begin 2417 s := s + 'Offer '; 2418 for i := 0 to Offer.nDeliver + Offer.nCost - 1 do 2419 begin 2420 if i = Offer.nDeliver then 2421 s := s + ' for ' 2422 else if i > 0 then 2423 s := s + '+'; 2424 case Offer.Price[i] and opMask of 2425 opChoose: 2426 s := s + 'Price of choice'; 2427 opCivilReport: 2428 s := s + 'State report'; 2429 opMilReport: 2430 s := s + 'Military report'; 2431 opMap: 2432 s := s + 'Map'; 2433 opTreaty: 2434 s := s + 'Treaty'; 2435 opShipParts: 2436 s := s + 'Ship part'; 2437 opMoney: 2438 s := s + IntToStr(Offer.Price[i] and $FFFFFF) + 'o'; 2439 opTribute: 2440 s := s + IntToStr(Offer.Price[i] and $FFFFFF) + 'o tribute'; 2441 opTech: 2442 s := s + Phrases.Lookup('ADVANCES', 2443 Offer.Price[i] and $FFFFFF); 2444 opAllTech: 2445 s := s + 'All advances'; 2446 opModel: 2447 s := s + Tribe[pSender].ModelName[Offer.Price[i] and $FFFFFF]; 2448 opAllModel: 2449 s := s + 'All models'; 2450 end 2451 end; 2452 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(s)); 2453 end 2454 else if Action = scDipAccept then 2455 begin 2456 s := s + '--- ACCEPTED! ---'; 2457 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(s)); 2458 end 2459 end; 2460 2461 cInitModule: 2462 begin 2463 Server := TInitModuleData(Data).Server; 2464 // AdvisorDlg.Init; 2465 InitModule; 2466 TInitModuleData(Data).DataSize := SizeOf(TPersistentData); 2467 TInitModuleData(Data).Flags := aiThreaded; 2468 end; 2469 2470 cReleaseModule: 2471 begin 2472 SmallImp.free; 2473 UnusedTribeFiles.free; 2474 TribeNames.free; 2475 MainMap.free; 2476 IsoEngine.Done; 2477 // AdvisorDlg.DeInit; 2478 end; 2479 2480 cHelpOnly, cStartHelp, cStartCredits: 2481 begin 2482 Age := 0; 2483 if Command = cHelpOnly then 2484 SetMainTextureByAge(-1); 2485 Tribes.Init; 2486 HelpDlg.UserLeft := (Screen.width - HelpDlg.width) div 2; 2487 HelpDlg.UserTop := (Screen.height - HelpDlg.height) div 2; 2488 HelpDlg.Difficulty := 0; 2489 if Command = cStartCredits then 2490 HelpDlg.ShowNewContent(wmModal, hkMisc, miscCredits) 2491 else 2492 HelpDlg.ShowNewContent(wmModal, hkMisc, miscMain); 2493 Tribes.Done; 2494 end; 2495 2496 cNewGame, cLoadGame, cMovie, cNewMap: 2497 begin 2498 { if (Command=cNewGame) or (Command=cLoadGame) then 2499 AdvisorDlg.NewGame(Data); } 2500 GenerateNames := mNames.Checked; 2501 GameOK := true; 2502 G := TNewGameData(Data); 2503 me := -1; 2504 pLogo := -1; 2505 ClientMode := -1; 2506 SetMapOptions; 2507 IsoEngine.pDebugMap := -1; 2508 idle := false; 2509 FillChar(Jump, SizeOf(Jump), 0); 2510 if StartRunning then 2511 Jump[0] := 999999; 2512 GameMode := Command; 2513 for i := 0 to nGrExt - 1 do 2514 FillChar(GrExt[i].pixUsed, GrExt[i].Data.height div 49 * 10, 0); 2515 IsoEngine.Reset; 2516 Tribes.Init; 2517 GetTribeList; 2518 for p1 := 0 to nPl - 1 do 2519 if (G.RO[p1] <> nil) and (G.RO[p1].Data <> nil) then 2520 with TPersistentData(G.RO[p1].Data^) do 2521 begin 2522 FarTech := adNone; 2523 FillChar(EnhancementJobs, SizeOf(EnhancementJobs), jNone); 2524 FillChar(ImpOrder, SizeOf(ImpOrder), Byte(-1)); 2525 ColdWarStart := -ColdWarTurns - 1; 2526 ToldAge := -1; 2527 ToldModels := 3; 2528 ToldAlive := 0; 2529 ToldContact := 0; 2530 ToldOwnCredibility := InitialCredibility; 2531 for i := 0 to nPl - 1 do 2532 if G.Difficulty[i] > 0 then 2533 inc(ToldAlive, 1 shl i); 2534 PeaceEvaHappened := 0; 2535 for i := 0 to 27 do 2536 with ToldWonders[i] do 2537 begin 2538 CityID := -1; 2539 EffectiveOwner := -1 2540 end; 2541 FillChar(ToldTech, SizeOf(ToldTech), Byte(tsNA)); 2542 if G.Difficulty[p1] > 0 then 2543 SoundPreload(sbStart); 2544 end; 2545 2546 // arrange dialogs 2547 ListDlg.UserLeft := 8; 2548 ListDlg.UserTop := TopBarHeight + 8; 2549 HelpDlg.UserLeft := Screen.width - HelpDlg.width - 8; 2550 HelpDlg.UserTop := TopBarHeight + 8; 2551 UnitStatDlg.UserLeft := 397; 2552 UnitStatDlg.UserTop := TopBarHeight + 64; 2553 DiaDlg.UserLeft := (Screen.width - DiaDlg.width) div 2; 2554 DiaDlg.UserTop := (Screen.height - DiaDlg.height) div 2; 2555 NatStatDlg.UserLeft := Screen.width - NatStatDlg.width - 8; 2556 NatStatDlg.UserTop := Screen.height - PanelHeight - 2557 NatStatDlg.height - 8; 2558 if NatStatDlg.UserTop < 8 then 2559 NatStatDlg.UserTop := 8; 2560 2561 Age := 0; 2562 MovieSpeed := 1; 2563 LogDlg.mSlot.Visible := true; 2564 LogDlg.Host := self; 2565 HelpDlg.ClearHistory; 2566 CityDlg.Reset; 2567 2568 Mini.width := G.lx * 2; 2569 Mini.height := G.ly; 2570 for i := 0 to nPl - 1 do 2571 begin 2572 Tribe[i] := nil; 2573 TribeOriginal[i] := false; 2574 end; 2575 ToldSlavery := -1; 2576 RepaintOnResize := false; 2577 Closable := false; 2578 FirstMovieTurn := true; 2579 2580 MenuArea.Visible := GameMode <> cMovie; 2581 TreasuryArea.Visible := GameMode < cMovie; 2582 ResearchArea.Visible := GameMode < cMovie; 2583 ManagementArea.Visible := GameMode < cMovie; 2584 end; 2585 2586 cGetReady, cReplay: 2587 if NewPlayer = 0 then 2588 begin 2589 i := 0; 2590 for p1 := 0 to nPl - 1 do 2591 if (G.Difficulty[p1] > 0) and (Tribe[p1] = nil) then 2592 inc(i); 2593 if i > UnusedTribeFiles.Count then 2594 begin 2595 GameOK := false; 2596 SimpleMessage(Phrases.Lookup('TOOFEWTRIBES')); 2597 end 2598 else 2599 begin 2600 for p1 := 0 to nPl - 1 do 2601 if (G.Difficulty[p1] > 0) and (Tribe[p1] = nil) and 2602 (G.RO[p1] <> nil) then 2603 begin // let player select own tribes 2604 TribeInfo.trix := p1; 2605 TribeNames.Clear; 2606 for j := 0 to UnusedTribeFiles.Count - 1 do 2607 begin 2608 GetTribeInfo(UnusedTribeFiles[j], Name, Color); 2609 TribeNames.AddObject(Name, TObject(Color)); 2610 end; 2611 assert(TribeNames.Count > 0); 2612 ModalSelectDlg.ShowNewContent(wmModal, kTribe); 2613 Application.ProcessMessages; 2614 TribeInfo.FileName := UnusedTribeFiles[ModalSelectDlg.result]; 2615 UnusedTribeFiles.Delete(ModalSelectDlg.result); 2616 2617 if GameMode = cLoadGame then 2618 CreateTribe(TribeInfo.trix, TribeInfo.FileName, false) 2619 else 2620 Server(cSetTribe + (Length(TribeInfo.FileName) + 1 + 7) div 4, 2621 0, 0, TribeInfo); 2622 end; 2623 2624 for p1 := 0 to nPl - 1 do 2625 if (G.Difficulty[p1] > 0) and (Tribe[p1] = nil) and 2626 (G.RO[p1] = nil) then 2627 begin // autoselect enemy tribes 2628 j := ChooseUnusedTribe; 2629 TribeInfo.FileName := UnusedTribeFiles[j]; 2630 UnusedTribeFiles.Delete(j); 2631 TribeInfo.trix := p1; 2632 if GameMode = cLoadGame then 2633 CreateTribe(TribeInfo.trix, TribeInfo.FileName, false) 2634 else 2635 Server(cSetTribe + (Length(TribeInfo.FileName) + 1 + 7) div 4, 2636 0, 0, TribeInfo); 2637 end; 2638 end; 2639 if not mNames.Checked then 2640 for p1 := 0 to nPl - 1 do 2641 if Tribe[p1] <> nil then 2642 Tribe[p1].NumberName := p1; 2643 end; 2644 2645 cBreakGame: 2646 begin 2647 SaveSettings; 2648 CityDlg.CloseAction := None; 2649 for i := 0 to Screen.FormCount - 1 do 2650 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 2651 then 2652 Screen.Forms[i].Close; 2653 if LogDlg.Visible then 2654 LogDlg.Close; 2655 LogDlg.List.Clear; 2656 StartRunning := not idle and (Jump[0] > 0); // AI called Reload 2657 me := -1; 2658 idle := false; 2659 ClientMode := -1; 2660 UnitInfoBtn.Visible := false; 2661 UnitBtn.Visible := false; 2662 TerrainBtn.Visible := false; 2663 MovieSpeed1Btn.Visible := false; 2664 MovieSpeed2Btn.Visible := false; 2665 MovieSpeed3Btn.Visible := false; 2666 MovieSpeed4Btn.Visible := false; 2667 EOT.Visible := false; 2668 for i := 0 to ControlCount - 1 do 2669 if Controls[i] is TButtonC then 2670 Controls[i].Visible := false; 2671 InitPVSB(sb, 0, 1); 2672 for p1 := 0 to nPl - 1 do 2673 if Tribe[p1] <> nil then 2674 Tribe[p1].free; 2675 Tribes.Done; 2676 RepaintOnResize := false; 2677 Closable := true; 2678 Close; 2679 { if (GameMode=cNewGame) or (GameMode=cLoadGame) then 2680 AdvisorDlg.BreakGame; } 2681 end; 2682 2683 cShowGame: 2684 begin 2685 with Panel.Canvas do 2686 begin 2687 Brush.Color := $000000; 2688 FillRect(Rect(0, 0, Panel.width, Panel.height)); 2689 Brush.Style := bsClear; 2690 end; 2691 with TopBar.Canvas do 2692 begin 2693 Brush.Color := $000000; 2694 FillRect(Rect(0, 0, TopBar.width, TopBar.height)); 2695 Brush.Style := bsClear; 2696 end; 2697 FormResize(nil); // place mini map correctly according to its size 2698 Show; 2699 Update; 2700 RepaintOnResize := true; 2701 xw := 0; 2702 yw := ywcenter; 2703 if not StayOnTop_Ensured then 2704 begin 2705 StayOnTop_Ensured := true; 2706 CityDlg.StayOnTop_Workaround; 2707 CityTypeDlg.StayOnTop_Workaround; 2708 DiaDlg.StayOnTop_Workaround; 2709 DraftDlg.StayOnTop_Workaround; 2710 EnhanceDlg.StayOnTop_Workaround; 2711 HelpDlg.StayOnTop_Workaround; 2712 NatStatDlg.StayOnTop_Workaround; 2713 NegoDlg.StayOnTop_Workaround; 2714 ModalSelectDlg.StayOnTop_Workaround; 2715 ListDlg.StayOnTop_Workaround; 2716 UnitStatDlg.StayOnTop_Workaround; 2717 WondersDlg.StayOnTop_Workaround; 2718 RatesDlg.StayOnTop_Workaround; 2719 end; 2720 end; 2721 2722 cShowTurnChange: 2723 begin 2724 if integer(Data) >= 0 then 2725 begin 2726 pLogo := integer(Data); 2727 if G.RO[pLogo] = nil then 2728 begin 2729 if AILogo[pLogo] <> nil then 2730 BitBlt(Canvas.Handle, (xRightPanel + 10) - (16 + 64), 2731 ClientHeight - PanelHeight, 64, 64, 2732 AILogo[pLogo].Canvas.Handle, 0, 0, SRCCOPY); 2733 end 2734 end 2735 end; 2736 2737 cTurn, cResume, cContinue: 2738 if not GameOK then 2739 Server(sResign, NewPlayer, 0, nil^) 2740 else 2741 begin 2742 ClientMode := Command; 2743 pTurn := NewPlayer; 2744 pLogo := NewPlayer; 2745 2746 if Command = cResume then 2747 begin // init non-original model pictures (maybe tribes not found) 2748 for p1 := 0 to nPl - 1 do 2749 if G.RO[p1] <> nil then 2750 begin 2751 ItsMeAgain(p1); 2752 for mix := 0 to MyRO.nModel - 1 do 2753 if Tribe[me].ModelPicture[mix].HGr = 0 then 2754 InitMyModel(mix, true); 2755 end; 2756 me := -1; 2757 end; 2758 2759 if Jump[pTurn] > 0 then 2760 Application.ProcessMessages; 2761 if Jump[pTurn] > 0 then 2762 if G.RO[NewPlayer].Happened and phGameEnd <> 0 then 2763 Jump[pTurn] := 0 2764 else 2765 dec(Jump[pTurn]); 2766 SkipTurn := Jump[pTurn] > 0; 2767 if SkipTurn then 2768 begin 2769 ItsMeAgain(NewPlayer); 2770 MyData := G.RO[NewPlayer].Data; 2771 SetTroopLoc(-1); 2772 MiniPaint; 2773 InitAllEnemyModels; // necessary for correct replay 2774 if not EndTurn(true) then 2775 SkipTurn := false; 2776 end; 2777 if not SkipTurn then 2778 begin 2779 if ((ClientMode < scDipStart) or (ClientMode > scDipBreak)) and 2780 NegoDlg.Visible then 2781 NegoDlg.Close; 2782 skipped := false; // always show my moves during my turn 2783 idle := true; 2784 InitTurn(NewPlayer); 2785 DipMem[me].pContact := -1; 2786 (* if (me=0) and (MyRO.Alive and (1 shl me)=0)} then 2787 begin 2788 if SimpleQuery(Phrases.Lookup('RESIGN'))=mrIgnore then 2789 Server(sResign,me,0,nil^) 2790 else Server(sBreak,me,0,nil^) 2791 end 2792 else Play('TURNSTART'); *) 2793 end; 2794 end; 2795 2796 cMovieTurn: 2797 begin 2798 ClientMode := Command; 2799 pTurn := NewPlayer; 2800 pLogo := -1; 2801 skipped := false; // always show my moves during my turn 2802 idle := true; 2803 if FirstMovieTurn then 2804 begin 2805 CheckMovieSpeedBtnState; 2806 FirstMovieTurn := false; 2807 end; 2808 InitTurn(NewPlayer); 2809 Application.ProcessMessages; 2810 if MovieSpeed = 4 then 2811 begin 2812 Sleep(75); 2813 // this break will ensure speed of fast forward does not depend on cpu speed 2814 Application.ProcessMessages; 2815 end 2816 end; 2817 2818 cMovieEndTurn: 2819 begin 2820 RememberPeaceViolation; 2821 pTurn := -1; 2822 pLogo := -1; 2823 MapValid := false; 2824 ClientMode := -1; 2825 idle := false; 2826 skipped := false; 2827 end; 2828 2829 cEditMap: 2830 begin 2831 ClientMode := cEditMap; 2832 SetMapOptions; 2833 IsoEngine.pDebugMap := -1; 2834 ItsMeAgain(0); 2835 MyData := nil; 2836 UnitInfoBtn.Visible := false; 2837 UnitBtn.Visible := false; 2838 TerrainBtn.Visible := false; 2839 MovieSpeed1Btn.Visible := false; 2840 MovieSpeed2Btn.Visible := false; 2841 MovieSpeed3Btn.Visible := false; 2842 MovieSpeed4Btn.Visible := false; 2843 EOT.Visible := false; 2844 HelpDlg.Difficulty := 0; 2845 BrushType := fGrass; 2846 BrushLoc := -1; 2847 Edited := false; 2848 UnFocus := -1; 2849 MarkCityLoc := -1; 2850 Tracking := false; 2851 TurnComplete := false; 2852 MapValid := false; 2853 FormResize(nil); // calculate geometrics and paint all 2854 SetTroopLoc(-1); 2855 idle := true 2856 end; 2857 2858 (* cNewContact: 2859 begin 2860 end; 2861 *) 2862 2863 scContact: 2864 begin 2865 DipMem[NewPlayer].pContact := integer(Data); 2866 if Jump[NewPlayer] > 0 then 2867 DipCall(scReject) 2868 else 2869 begin 2870 ClientMode := Command; 2871 InitTurn(NewPlayer); 2872 MyData.ToldContact := MyData.ToldContact or (1 shl integer(Data)); 2873 // don't tell about new nation when already contacted by them 2874 with MessgExDlg do 2875 begin 2876 OpenSound := 'CONTACT_' + char(48 + MyRO.EnemyReport[integer(Data) 2877 ].Attitude); 2878 MessgText := Tribe[integer(Data)].TPhrase('FRCONTACT'); 2879 Kind := mkYesNo; 2880 IconKind := mikTribe; 2881 IconIndex := integer(Data); 2882 ShowModal; 2883 if ModalResult = mrOK then 2884 begin 2885 NegoDlg.Respond; 2886 DipMem[me].DeliveredPrices := []; 2887 DipMem[me].ReceivedPrices := []; 2888 DipCall(scDipStart) 2889 end 2890 else 2891 begin 2892 DipCall(scReject); 2893 EndNego 2894 end 2895 end 2896 end; 2897 end; 2898 2899 scDipStart .. scDipBreak: 2900 begin 2901 ClientMode := Command; 2902 InitTurn(NewPlayer); 2903 if Command = scDipStart then 2904 Play('CONTACT_' + char(48 + MyRO.Attitude[DipMem[NewPlayer] 2905 .pContact])) 2906 else if Command = scDipCancelTreaty then 2907 Play('CANCELTREATY') 2908 else if Command = scDipOffer then 2909 begin 2910 ReceivedOffer := TOffer(Data); 2911 InitAllEnemyModels; 2912 end 2913 else if Command = scDipAccept then 2914 begin // remember delivered and received prices 2915 for i := 0 to DipMem[me].SentOffer.nDeliver - 1 do 2916 include(DipMem[me].DeliveredPrices, 2917 DipMem[me].SentOffer.Price[i] shr 24); 2918 for i := 0 to DipMem[me].SentOffer.nCost - 1 do 2919 include(DipMem[me].ReceivedPrices, 2920 DipMem[me].SentOffer.Price[DipMem[me].SentOffer.nDeliver + 2921 i] shr 24); 2922 IsTreatyDeal := false; 2923 for i := 0 to ReceivedOffer.nDeliver + ReceivedOffer.nCost - 1 do 2924 if DipMem[me].SentOffer.Price[i] and opMask = opTreaty then 2925 IsTreatyDeal := true; 2926 if IsTreatyDeal then 2927 Play('NEWTREATY') 2928 else 2929 Play('ACCEPTOFFER'); 2930 end; 2931 NegoDlg.Start; 2932 idle := true 2933 end; 2934 2935 cShowCancelTreaty: 2936 if not IsMultiPlayerGame then 2937 begin 2938 case G.RO[NewPlayer].Treaty[integer(Data)] of 2939 trPeace: 2940 s := Tribe[integer(Data)].TPhrase('FRCANCELBYREJECT_PEACE'); 2941 trFriendlyContact: 2942 s := Tribe[integer(Data)].TPhrase('FRCANCELBYREJECT_FRIENDLY'); 2943 trAlliance: 2944 s := Tribe[integer(Data)].TPhrase('FRCANCELBYREJECT_ALLIANCE'); 2945 end; 2946 TribeMessage(integer(Data), s, 'CANCELTREATY'); 2947 end; 2948 2949 cShowCancelTreatyByAlliance: 2950 if idle and (NewPlayer = me) then 2951 TribeMessage(integer(Data), Tribe[integer(Data) 2952 ].TPhrase('FRENEMYALLIANCE'), 'CANCELTREATY'); 2953 2954 cShowSupportAllianceAgainst: 2955 if not IsMultiPlayerGame and (Jump[0] = 0) then 2956 TribeMessage(integer(Data) and $F, 2957 Tribe[integer(Data) and $F].TPhrase('FRMYALLIANCE1') + ' ' + 2958 Tribe[integer(Data) shr 4].TPhrase('FRMYALLIANCE2'), 2959 'CANCELTREATY'); 2960 2961 cShowPeaceViolation: 2962 if not IsMultiPlayerGame and (Jump[0] = 0) then 2963 TribeMessage(integer(Data), 2964 Format(Tribe[integer(Data)].TPhrase('EVIOLATION'), 2965 [TurnToString(MyRO.Turn + PeaceEvaTurns - 1)]), 'MSG_WITHDRAW'); 2966 2967 cShowEndContact: 2968 EndNego; 2969 2970 cShowUnitChanged, cShowCityChanged, cShowAfterMove, cShowAfterAttack: 2971 if (idle and (NewPlayer = me) or not idle and not skipped) and 2972 not((GameMode = cMovie) and (MovieSpeed = 4)) then 2973 begin 2974 assert(NewPlayer = me); 2975 if not idle or (GameMode = cMovie) then 2976 Application.ProcessMessages; 2977 if Command = cShowCityChanged then 2978 begin 2979 CurrentMoveInfo.DoShow := false; 2980 if idle then 3090 CurrentMoveInfo.IsAlly := MyRO.Treaty[Owner] = trAlliance; 3091 if GameMode = cMovie then 2981 3092 CurrentMoveInfo.DoShow := true 2982 3093 else if CurrentMoveInfo.IsAlly then 2983 CurrentMoveInfo.DoShow := not mAlNoMoves.Checked 3094 CurrentMoveInfo.DoShow := not mAlNoMoves.Checked and 3095 not(mAlEffectiveMovesOnly.Checked and 3096 (Command <> cShowCapturing)) 2984 3097 else 2985 CurrentMoveInfo.DoShow := not mEnNoMoves.Checked 2986 end 2987 else if Command = cShowUnitChanged then 2988 begin 2989 CurrentMoveInfo.DoShow := false; 2990 if idle then 2991 CurrentMoveInfo.DoShow := not mEffectiveMovesOnly.Checked 2992 else if CurrentMoveInfo.IsAlly then 2993 CurrentMoveInfo.DoShow := 2994 not(mAlNoMoves.Checked or mAlEffectiveMovesOnly.Checked) 2995 else 2996 CurrentMoveInfo.DoShow := 2997 not(mEnNoMoves.Checked or mEnAttacks.Checked) 2998 end; 2999 // else keep DoShow from cShowMove/cShowAttack 3000 3001 if CurrentMoveInfo.DoShow then 3002 begin 3003 if Command = cShowCityChanged then 3004 MapValid := false; 3005 FocusOnLoc(integer(Data), flImmUpdate); 3006 // OldUnFocus:=UnFocus; 3007 // UnFocus:=-1; 3008 if Command = cShowAfterMove then 3009 PaintLoc(integer(Data), CurrentMoveInfo.AfterMovePaintRadius) 3010 // show discovered areas 3011 else 3012 PaintLoc(integer(Data), 1); 3013 // UnFocus:=OldUnFocus; 3014 if (Command = cShowAfterAttack) and 3015 (CurrentMoveInfo.AfterAttackExpeller >= 0) then 3098 CurrentMoveInfo.DoShow := not mEnNoMoves.Checked and 3099 not(mEnAttacks.Checked and (Command <> cShowCapturing)); 3100 if CurrentMoveInfo.DoShow then 3016 3101 begin 3017 SoundMessageEx(Tribe[CurrentMoveInfo.AfterAttackExpeller] 3018 .TPhrase('EXPEL'), ''); 3019 CurrentMoveInfo.AfterAttackExpeller := -1; 3020 Update; // remove message box from screen 3021 end 3022 else if not idle then 3023 if Command = cShowCityChanged then 3024 Sleep(MoveTime * WaitAfterShowMove div 16) 3025 else if (Command = cShowUnitChanged) and 3026 (MyMap[integer(Data)] and fUnit <> 0) then 3027 Sleep(MoveTime * WaitAfterShowMove div 32) 3028 end // if CurrentMoveInfo.DoShow 3029 else 3030 MapValid := false; 3031 end; 3032 3033 cShowMoving, cShowCapturing: 3034 if (idle and (NewPlayer = me) or not idle and not skipped and 3035 (TShowMove(Data).emix <> $FFFF)) and 3036 not((GameMode = cMovie) and (MovieSpeed = 4)) then 3037 begin 3038 assert(NewPlayer = me); 3039 if not idle or (GameMode = cMovie) then 3040 Application.ProcessMessages; 3041 with TShowMove(Data) do 3042 begin 3043 CurrentMoveInfo.DoShow := false; 3044 if not idle and (Tribe[Owner].ModelPicture[mix].HGr = 0) then 3045 InitEnemyModel(emix); 3046 3047 ToLoc := dLoc(FromLoc, dx, dy); 3048 if idle then 3049 begin // own unit -- make discovered land visible 3050 assert(Owner = me); // no foreign moves during my turn! 3051 CurrentMoveInfo.DoShow := not mEffectiveMovesOnly.Checked or 3052 (Command = cShowCapturing); 3053 if CurrentMoveInfo.DoShow then 3054 begin 3055 if GameMode = cMovie then 3056 begin 3057 if MovieSpeed = 3 then 3058 AnimationSpeed := 4 3059 else if MovieSpeed = 2 then 3060 AnimationSpeed := 8 3061 else 3062 AnimationSpeed := 16; 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); 3063 3110 end 3064 3111 else 3065 begin 3066 if mVeryFastMoves.Checked then 3067 AnimationSpeed := 4 3068 else if mFastMoves.Checked then 3069 AnimationSpeed := 8 3070 else 3071 AnimationSpeed := 16; 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); 3072 3117 end; 3073 with MyModel[mix] do 3074 begin 3075 if (Kind = mkDiplomat) or (Domain = dAir) or 3076 (Cap[mcRadar] + Cap[mcCarrier] + Cap[mcAcademy] > 0) or 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 (ATrans_Fuel > 0) 3131 or (Cap and (1 shl (mcRadar - mcFirstNonCap) or 3132 1 shl (mcAcademy - mcFirstNonCap)) <> 0) or 3077 3133 (MyMap[ToLoc] and fTerrain = fMountains) or 3078 3134 (MyMap[ToLoc] and fTerImp = tiFort) or … … 3080 3136 CurrentMoveInfo.AfterMovePaintRadius := 2 3081 3137 else 3082 CurrentMoveInfo.AfterMovePaintRadius := 1; 3083 if (MyRO.Wonder[woShinkansen].EffectiveOwner = me) and 3084 (Domain = dGround) and 3085 (MyMap[FromLoc] and (fRR or fCity) <> 0) and 3086 (MyMap[ToLoc] and (fRR or fCity) <> 0) and 3087 (Flags and umPlaneUnloading = 0) then 3088 AnimationSpeed := 4; 3089 ShowMoveDomain := Domain; 3090 IsAlpine := Cap[mcAlpine] > 0; 3091 end 3138 CurrentMoveInfo.AfterMovePaintRadius := 1 3092 3139 end 3140 else 3141 begin 3142 if mEnFastMoves.Checked then 3143 AnimationSpeed := 8 3144 else 3145 AnimationSpeed := 16; 3146 CurrentMoveInfo.AfterMovePaintRadius := 0; 3147 // enemy unit, nothing discovered 3148 end; 3149 if GameMode = cMovie then 3150 begin 3151 if MovieSpeed = 3 then 3152 AnimationSpeed := 4 3153 else if MovieSpeed = 2 then 3154 AnimationSpeed := 8 3155 else 3156 AnimationSpeed := 16; 3157 end; 3158 ShowMoveDomain := MyRO.EnemyModel[emix].Domain; 3159 IsAlpine := MyRO.EnemyModel[emix].Cap and 3160 (1 shl (mcAlpine - mcFirstNonCap)) <> 0; 3161 end 3162 end; 3163 3164 if CurrentMoveInfo.DoShow then 3165 begin 3166 if Command = cShowCapturing then 3167 Play('MOVE_CAPTURE') 3168 else if EndHealth <= 0 then 3169 Play('MOVE_DIE') 3170 else if Flags and umSpyMission <> 0 then 3171 Play('MOVE_COVERT') 3172 else if Flags and umShipLoading <> 0 then 3173 if ShowMoveDomain = dAir then 3174 Play('MOVE_PLANELANDING') 3175 else 3176 Play('MOVE_LOAD') 3177 else if Flags and umPlaneLoading <> 0 then 3178 Play('MOVE_LOAD') 3179 else if Flags and umShipUnloading <> 0 then 3180 if ShowMoveDomain = dAir then 3181 Play('MOVE_PLANESTART') 3182 else 3183 Play('MOVE_UNLOAD') 3184 else if Flags and umPlaneUnloading <> 0 then 3185 if (MyMap[FromLoc] and fCity = 0) and 3186 (MyMap[FromLoc] and fTerImp <> tiBase) then 3187 Play('MOVE_PARACHUTE') 3188 else 3189 Play('MOVE_UNLOAD') 3190 else if (ShowMoveDomain = dGround) and not IsAlpine and 3191 (MyMap[ToLoc] and fTerrain = fMountains) and 3192 ((MyMap[FromLoc] and (fRoad or fRR or fCity) = 0) or 3193 (MyMap[ToLoc] and (fRoad or fRR or fCity) = 0)) then 3194 Play('MOVE_MOUNTAIN'); 3195 3196 FocusOnLoc(FromLoc, flImmUpdate); 3197 PaintLoc_BeforeMove(FromLoc); 3198 if Command = cShowCapturing then 3199 MoveOnScreen(TShowMove(Data), 1, 32, 32) 3200 else 3201 MoveOnScreen(TShowMove(Data), 1, AnimationSpeed, AnimationSpeed) 3202 end // if CurrentMoveInfo.DoShow 3203 else 3204 MapValid := false; 3205 end 3206 end; 3207 3208 cShowAttacking: 3209 if (idle and (NewPlayer = me) or not idle and not skipped and 3210 (TShowMove(Data).emix <> $FFFF)) and 3211 not((GameMode = cMovie) and (MovieSpeed = 4)) then 3212 begin 3213 assert(NewPlayer = me); 3214 if not idle or (GameMode = cMovie) then 3215 Application.ProcessMessages; 3216 with TShowMove(Data) do 3217 begin 3218 CurrentMoveInfo.AfterAttackExpeller := -1; 3219 CurrentMoveInfo.DoShow := false; 3220 if idle then 3221 CurrentMoveInfo.DoShow := true // own unit -- always show attacks 3222 else 3223 begin 3224 CurrentMoveInfo.IsAlly := MyRO.Treaty[Owner] = trAlliance; 3225 if CurrentMoveInfo.IsAlly then 3226 CurrentMoveInfo.DoShow := not mAlNoMoves.Checked 3227 else 3228 CurrentMoveInfo.DoShow := not mEnNoMoves.Checked; 3229 end; 3230 if CurrentMoveInfo.DoShow then 3231 begin 3232 ToLoc := dLoc(FromLoc, dx, dy); 3233 if Tribe[Owner].ModelPicture[mix].HGr = 0 then 3234 InitEnemyModel(emix); 3235 3236 if (MyMap[ToLoc] and (fCity or fUnit or fOwned) = fCity or fOwned) 3237 then 3238 begin // tell about bombardment 3239 cix := MyRO.nCity - 1; 3240 while (cix >= 0) and (MyCity[cix].Loc <> ToLoc) do 3241 dec(cix); 3242 if MyCity[cix].Status and csToldBombard = 0 then 3243 begin 3244 if not supervising then 3245 MyCity[cix].Status := MyCity[cix].Status or csToldBombard; 3246 s := CityName(MyCity[cix].ID); 3247 SoundMessageEx(Format(Tribe[Owner].TPhrase('BOMBARD'), 3248 [s]), ''); 3249 Update; // remove message box from screen 3250 end; 3251 end 3252 else if Flags and umExpelling <> 0 then 3253 CurrentMoveInfo.AfterAttackExpeller := Owner; 3254 3255 if Flags and umExpelling <> 0 then 3256 Play('MOVE_EXPEL') 3257 else if Owner = me then 3258 begin 3259 MakeModelInfo(me, mix, MyModel[mix], mi); 3260 Play(AttackSound(ModelCode(mi))); 3093 3261 end 3094 3262 else 3263 Play(AttackSound(ModelCode(MyRO.EnemyModel[emix]))); 3264 3265 FocusOnLoc(FromLoc, flImmUpdate); 3266 3267 // before combat 3268 MainMap.AttackBegin(TShowMove(Data)); 3269 if MyMap[ToLoc] and fCity <> 0 then 3270 PaintLoc(ToLoc); 3271 PaintLoc(FromLoc); 3272 MoveOnScreen(TShowMove(Data), 1, 9, 16); 3273 MoveOnScreen(TShowMove(Data), 17, 12, 32); 3274 MoveOnScreen(TShowMove(Data), 7, 11, 16); 3275 3276 // after combat 3277 MainMap.AttackEffect(TShowMove(Data)); 3278 PaintLoc(ToLoc); 3279 if EndHealth > 0 then 3095 3280 begin 3096 CurrentMoveInfo.IsAlly := MyRO.Treaty[Owner] = trAlliance; 3097 if GameMode = cMovie then 3098 CurrentMoveInfo.DoShow := true 3099 else if CurrentMoveInfo.IsAlly then 3100 CurrentMoveInfo.DoShow := not mAlNoMoves.Checked and 3101 not(mAlEffectiveMovesOnly.Checked and 3102 (Command <> cShowCapturing)) 3103 else 3104 CurrentMoveInfo.DoShow := not mEnNoMoves.Checked and 3105 not(mEnAttacks.Checked and (Command <> cShowCapturing)); 3106 if CurrentMoveInfo.DoShow then 3107 begin 3108 if Command = cShowCapturing then 3109 begin // show capture message 3110 if MyMap[ToLoc] and fOwned <> 0 then 3111 begin // own city, search 3112 cix := MyRO.nCity - 1; 3113 while (cix >= 0) and (MyCity[cix].Loc <> ToLoc) do 3114 dec(cix); 3115 s := CityName(MyCity[cix].ID); 3116 end 3117 else 3118 begin // foreign city, search 3119 ecix := MyRO.nEnemyCity - 1; 3120 while (ecix >= 0) and (MyRO.EnemyCity[ecix].Loc <> ToLoc) do 3121 dec(ecix); 3122 s := CityName(MyRO.EnemyCity[ecix].ID); 3123 end; 3124 TribeMessage(Owner, Format(Tribe[Owner].TPhrase('CAPTURE'), 3125 [s]), ''); 3126 Update; // remove message box from screen 3127 end; 3128 3129 if CurrentMoveInfo.IsAlly then 3130 begin // allied unit -- make discovered land visible 3131 if mAlFastMoves.Checked then 3132 AnimationSpeed := 8 3133 else 3134 AnimationSpeed := 16; 3135 with MyRO.EnemyModel[emix] do 3136 if (Kind = mkDiplomat) or (Domain = dAir) or 3137 (ATrans_Fuel > 0) or 3138 (Cap and (1 shl (mcRadar - mcFirstNonCap) or 3139 1 shl (mcAcademy - mcFirstNonCap)) <> 0) or 3140 (MyMap[ToLoc] and fTerrain = fMountains) or 3141 (MyMap[ToLoc] and fTerImp = tiFort) or 3142 (MyMap[ToLoc] and fTerImp = tiBase) then 3143 CurrentMoveInfo.AfterMovePaintRadius := 2 3144 else 3145 CurrentMoveInfo.AfterMovePaintRadius := 1 3146 end 3147 else 3148 begin 3149 if mEnFastMoves.Checked then 3150 AnimationSpeed := 8 3151 else 3152 AnimationSpeed := 16; 3153 CurrentMoveInfo.AfterMovePaintRadius := 0; 3154 // enemy unit, nothing discovered 3155 end; 3156 if GameMode = cMovie then 3157 begin 3158 if MovieSpeed = 3 then 3159 AnimationSpeed := 4 3160 else if MovieSpeed = 2 then 3161 AnimationSpeed := 8 3162 else 3163 AnimationSpeed := 16; 3164 end; 3165 ShowMoveDomain := MyRO.EnemyModel[emix].Domain; 3166 IsAlpine := MyRO.EnemyModel[emix].Cap and 3167 (1 shl (mcAlpine - mcFirstNonCap)) <> 0; 3168 end 3169 end; 3170 3171 if CurrentMoveInfo.DoShow then 3172 begin 3173 if Command = cShowCapturing then 3174 Play('MOVE_CAPTURE') 3175 else if EndHealth <= 0 then 3176 Play('MOVE_DIE') 3177 else if Flags and umSpyMission <> 0 then 3178 Play('MOVE_COVERT') 3179 else if Flags and umShipLoading <> 0 then 3180 if ShowMoveDomain = dAir then 3181 Play('MOVE_PLANELANDING') 3182 else 3183 Play('MOVE_LOAD') 3184 else if Flags and umPlaneLoading <> 0 then 3185 Play('MOVE_LOAD') 3186 else if Flags and umShipUnloading <> 0 then 3187 if ShowMoveDomain = dAir then 3188 Play('MOVE_PLANESTART') 3189 else 3190 Play('MOVE_UNLOAD') 3191 else if Flags and umPlaneUnloading <> 0 then 3192 if (MyMap[FromLoc] and fCity = 0) and 3193 (MyMap[FromLoc] and fTerImp <> tiBase) then 3194 Play('MOVE_PARACHUTE') 3195 else 3196 Play('MOVE_UNLOAD') 3197 else if (ShowMoveDomain = dGround) and not IsAlpine and 3198 (MyMap[ToLoc] and fTerrain = fMountains) and 3199 ((MyMap[FromLoc] and (fRoad or fRR or fCity) = 0) or 3200 (MyMap[ToLoc] and (fRoad or fRR or fCity) = 0)) then 3201 Play('MOVE_MOUNTAIN'); 3202 3203 FocusOnLoc(FromLoc, flImmUpdate); 3204 PaintLoc_BeforeMove(FromLoc); 3205 if Command = cShowCapturing then 3206 MoveOnScreen(TShowMove(Data), 1, 32, 32) 3207 else 3208 MoveOnScreen(TShowMove(Data), 1, AnimationSpeed, AnimationSpeed) 3209 end // if CurrentMoveInfo.DoShow 3210 else 3211 MapValid := false; 3212 end 3281 Health := EndHealth; 3282 MoveOnScreen(TShowMove(Data), 10, 0, 16); 3283 end 3284 else if not idle then 3285 Sleep(MoveTime div 2); 3286 MainMap.AttackEnd; 3287 end // if CurrentMoveInfo.DoShow 3288 else 3289 MapValid := false; 3290 end 3291 end; 3292 3293 cShowMissionResult: 3294 if Cardinal(Data) = 0 then 3295 SoundMessageEx(Phrases.Lookup('NOFOREIGNINFO'), '') 3296 else 3297 begin 3298 s := Phrases.Lookup('FOREIGNINFO'); 3299 for p1 := 0 to nPl - 1 do 3300 if 3 shl (p1 * 2) and Cardinal(Data) <> 0 then 3301 s := s + '\' + Tribe[p1].TPhrase('SHORTNAME'); 3302 SoundMessageEx(s, '') 3303 end; 3304 3305 cShowShipChange: 3306 if not IsMultiPlayerGame and (Jump[0] = 0) then 3307 ShowEnemyShipChange(TShowShipChange(Data)); 3308 3309 cShowGreatLibTech: 3310 if not IsMultiPlayerGame and (Jump[0] = 0) then 3311 with MessgExDlg do 3312 begin 3313 MessgText := Format(Phrases.Lookup('GRLIB_GENERAL'), 3314 [Phrases.Lookup('ADVANCES', integer(Data))]); 3315 OpenSound := 'NEWADVANCE_GRLIB'; 3316 Kind := mkOk; 3317 IconKind := mikImp; 3318 IconIndex := woGrLibrary; 3319 ShowModal; 3213 3320 end; 3214 3321 3215 cShowAttacking: 3216 if (idle and (NewPlayer = me) or not idle and not skipped and 3217 (TShowMove(Data).emix <> $FFFF)) and 3218 not((GameMode = cMovie) and (MovieSpeed = 4)) then 3322 cRefreshDebugMap: 3323 begin 3324 if integer(Data) = IsoEngine.pDebugMap then 3219 3325 begin 3220 assert(NewPlayer = me); 3221 if not idle or (GameMode = cMovie) then 3222 Application.ProcessMessages; 3223 with TShowMove(Data) do 3326 MapValid := false; 3327 MainOffscreenPaint; 3328 Update; 3329 end 3330 end; 3331 3332 else 3333 if Command >= cClientEx then 3334 case Command and $FFF0 of 3335 3336 cSetTribe: 3337 with TTribeInfo(Data) do 3224 3338 begin 3225 CurrentMoveInfo.AfterAttackExpeller := -1; 3226 CurrentMoveInfo.DoShow := false; 3227 if idle then 3228 CurrentMoveInfo.DoShow := true // own unit -- always show attacks 3229 else 3230 begin 3231 CurrentMoveInfo.IsAlly := MyRO.Treaty[Owner] = trAlliance; 3232 if CurrentMoveInfo.IsAlly then 3233 CurrentMoveInfo.DoShow := not mAlNoMoves.Checked 3234 else 3235 CurrentMoveInfo.DoShow := not mEnNoMoves.Checked; 3236 end; 3237 if CurrentMoveInfo.DoShow then 3238 begin 3239 ToLoc := dLoc(FromLoc, dx, dy); 3240 if Tribe[Owner].ModelPicture[mix].HGr = 0 then 3241 InitEnemyModel(emix); 3242 3243 if (MyMap[ToLoc] and (fCity or fUnit or fOwned) = fCity or fOwned) 3244 then 3245 begin // tell about bombardment 3246 cix := MyRO.nCity - 1; 3247 while (cix >= 0) and (MyCity[cix].Loc <> ToLoc) do 3248 dec(cix); 3249 if MyCity[cix].Status and csToldBombard = 0 then 3250 begin 3251 if not supervising then 3252 MyCity[cix].Status := MyCity[cix].Status or csToldBombard; 3253 s := CityName(MyCity[cix].ID); 3254 SoundMessageEx(Format(Tribe[Owner].TPhrase('BOMBARD'), 3255 [s]), ''); 3256 Update; // remove message box from screen 3257 end; 3258 end 3259 else if Flags and umExpelling <> 0 then 3260 CurrentMoveInfo.AfterAttackExpeller := Owner; 3261 3262 if Flags and umExpelling <> 0 then 3263 Play('MOVE_EXPEL') 3264 else if Owner = me then 3265 begin 3266 MakeModelInfo(me, mix, MyModel[mix], mi); 3267 Play(AttackSound(ModelCode(mi))); 3268 end 3269 else 3270 Play(AttackSound(ModelCode(MyRO.EnemyModel[emix]))); 3271 3272 FocusOnLoc(FromLoc, flImmUpdate); 3273 3274 // before combat 3275 MainMap.AttackBegin(TShowMove(Data)); 3276 if MyMap[ToLoc] and fCity <> 0 then 3277 PaintLoc(ToLoc); 3278 PaintLoc(FromLoc); 3279 MoveOnScreen(TShowMove(Data), 1, 9, 16); 3280 MoveOnScreen(TShowMove(Data), 17, 12, 32); 3281 MoveOnScreen(TShowMove(Data), 7, 11, 16); 3282 3283 // after combat 3284 MainMap.AttackEffect(TShowMove(Data)); 3285 PaintLoc(ToLoc); 3286 if EndHealth > 0 then 3287 begin 3288 Health := EndHealth; 3289 MoveOnScreen(TShowMove(Data), 10, 0, 16); 3290 end 3291 else if not idle then 3292 Sleep(MoveTime div 2); 3293 MainMap.AttackEnd; 3294 end // if CurrentMoveInfo.DoShow 3295 else 3296 MapValid := false; 3297 end 3298 end; 3299 3300 cShowMissionResult: 3301 if Cardinal(Data) = 0 then 3302 SoundMessageEx(Phrases.Lookup('NOFOREIGNINFO'), '') 3303 else 3304 begin 3305 s := Phrases.Lookup('FOREIGNINFO'); 3306 for p1 := 0 to nPl - 1 do 3307 if 3 shl (p1 * 2) and Cardinal(Data) <> 0 then 3308 s := s + '\' + Tribe[p1].TPhrase('SHORTNAME'); 3309 SoundMessageEx(s, '') 3310 end; 3311 3312 cShowShipChange: 3313 if not IsMultiPlayerGame and (Jump[0] = 0) then 3314 ShowEnemyShipChange(TShowShipChange(Data)); 3315 3316 cShowGreatLibTech: 3317 if not IsMultiPlayerGame and (Jump[0] = 0) then 3318 with MessgExDlg do 3319 begin 3320 MessgText := Format(Phrases.Lookup('GRLIB_GENERAL'), 3321 [Phrases.Lookup('ADVANCES', integer(Data))]); 3322 OpenSound := 'NEWADVANCE_GRLIB'; 3323 Kind := mkOk; 3324 IconKind := mikImp; 3325 IconIndex := woGrLibrary; 3326 ShowModal; 3339 i := UnusedTribeFiles.Count - 1; 3340 while (i >= 0) and 3341 (AnsiCompareFileName(UnusedTribeFiles[i], FileName) <> 0) do 3342 dec(i); 3343 if i >= 0 then 3344 UnusedTribeFiles.Delete(i); 3345 CreateTribe(trix, FileName, true); 3327 3346 end; 3328 3347 3329 cRefreshDebugMap: 3330 begin 3331 if integer(Data) = IsoEngine.pDebugMap then 3332 begin 3333 MapValid := false; 3334 MainOffscreenPaint; 3335 Update; 3336 end 3337 end; 3338 3339 else 3340 if Command >= cClientEx then 3341 case Command and $FFF0 of 3342 3343 cSetTribe: 3344 with TTribeInfo(Data) do 3345 begin 3346 i := UnusedTribeFiles.Count - 1; 3347 while (i >= 0) and 3348 (AnsiCompareFileName(UnusedTribeFiles[i], FileName) <> 0) do 3349 dec(i); 3350 if i >= 0 then 3351 UnusedTribeFiles.Delete(i); 3352 CreateTribe(trix, FileName, true); 3353 end; 3354 3355 cSetNewModelPicture, cSetModelPicture: 3356 if TribeOriginal[TModelPictureInfo(Data).trix] then 3357 Tribe[TModelPictureInfo(Data).trix].SetModelPicture 3358 (TModelPictureInfo(Data), Command and 3359 $FFF0 = cSetNewModelPicture); 3360 3361 cSetSlaveIndex and $FFF0: 3362 Tribe[integer(Data) shr 16].mixSlaves := integer(Data) and $FFFF; 3363 3364 cSetCityName: 3365 with TCityNameInfo(Data) do 3366 if TribeOriginal[ID shr 12] then 3367 Tribe[ID shr 12].SetCityName(ID and $FFF, NewName); 3368 3369 cSetModelName: 3370 with TModelNameInfo(Data) do 3371 if TribeOriginal[NewPlayer] then 3372 Tribe[NewPlayer].ModelName[mix] := NewName; 3373 end 3374 end 3375 end; { <<<client } 3376 3377 { *** main part *** } 3378 3379 procedure TMainScreen.CreateParams(var p: TCreateParams); 3380 var 3381 DefaultOptionChecked: integer; 3382 Reg: TRegistry; 3383 doinit: boolean; 3384 begin 3385 inherited; 3386 3387 // define which menu settings to save 3388 SaveOption[0] := mAlEffectiveMovesOnly.Tag; 3389 SaveOption[1] := mEnMoves.Tag; 3390 SaveOption[2] := mEnAttacks.Tag; 3391 SaveOption[3] := mEnNoMoves.Tag; 3392 SaveOption[4] := mWaitTurn.Tag; 3393 SaveOption[5] := mEffectiveMovesOnly.Tag; 3394 SaveOption[6] := mEnFastMoves.Tag; 3395 SaveOption[7] := mSlowMoves.Tag; 3396 SaveOption[8] := mFastMoves.Tag; 3397 SaveOption[9] := mVeryFastMoves.Tag; 3398 SaveOption[10] := mNames.Tag; 3399 SaveOption[11] := mRepList.Tag; 3400 SaveOption[12] := mRepScreens.Tag; 3401 SaveOption[13] := mSoundOff.Tag; 3402 SaveOption[14] := mSoundOn.Tag; 3403 SaveOption[15] := mSoundOnAlt.Tag; 3404 SaveOption[16] := mScrollSlow.Tag; 3405 SaveOption[17] := mScrollFast.Tag; 3406 SaveOption[18] := mScrollOff.Tag; 3407 SaveOption[19] := mAlSlowMoves.Tag; 3408 SaveOption[20] := mAlFastMoves.Tag; 3409 SaveOption[21] := mAlNoMoves.Tag; 3410 DefaultOptionChecked := 1 shl 1 + 1 shl 7 + 1 shl 10 + 1 shl 12 + 1 shl 14 + 3411 1 shl 18 + 1 shl 19; 3412 3413 Reg := TRegistry.Create; 3414 doinit := true; 3415 if Reg.KeyExists('SOFTWARE\cevo\RegVer9') then 3416 with Reg do begin 3348 cSetNewModelPicture, cSetModelPicture: 3349 if TribeOriginal[TModelPictureInfo(Data).trix] then 3350 Tribe[TModelPictureInfo(Data).trix].SetModelPicture 3351 (TModelPictureInfo(Data), Command and 3352 $FFF0 = cSetNewModelPicture); 3353 3354 cSetSlaveIndex and $FFF0: 3355 Tribe[integer(Data) shr 16].mixSlaves := integer(Data) and $FFFF; 3356 3357 cSetCityName: 3358 with TCityNameInfo(Data) do 3359 if TribeOriginal[ID shr 12] then 3360 Tribe[ID shr 12].SetCityName(ID and $FFF, NewName); 3361 3362 cSetModelName: 3363 with TModelNameInfo(Data) do 3364 if TribeOriginal[NewPlayer] then 3365 Tribe[NewPlayer].ModelName[mix] := NewName; 3366 end 3367 end 3368 end; { <<<client } 3369 3370 { *** main part *** } 3371 3372 procedure TMainScreen.CreateParams(var p: TCreateParams); 3373 var 3374 DefaultOptionChecked: integer; 3375 Reg: TRegistry; 3376 doinit: boolean; 3377 begin 3378 inherited; 3379 3380 // define which menu settings to save 3381 SaveOption[0] := mAlEffectiveMovesOnly.Tag; 3382 SaveOption[1] := mEnMoves.Tag; 3383 SaveOption[2] := mEnAttacks.Tag; 3384 SaveOption[3] := mEnNoMoves.Tag; 3385 SaveOption[4] := mWaitTurn.Tag; 3386 SaveOption[5] := mEffectiveMovesOnly.Tag; 3387 SaveOption[6] := mEnFastMoves.Tag; 3388 SaveOption[7] := mSlowMoves.Tag; 3389 SaveOption[8] := mFastMoves.Tag; 3390 SaveOption[9] := mVeryFastMoves.Tag; 3391 SaveOption[10] := mNames.Tag; 3392 SaveOption[11] := mRepList.Tag; 3393 SaveOption[12] := mRepScreens.Tag; 3394 SaveOption[13] := mSoundOff.Tag; 3395 SaveOption[14] := mSoundOn.Tag; 3396 SaveOption[15] := mSoundOnAlt.Tag; 3397 SaveOption[16] := mScrollSlow.Tag; 3398 SaveOption[17] := mScrollFast.Tag; 3399 SaveOption[18] := mScrollOff.Tag; 3400 SaveOption[19] := mAlSlowMoves.Tag; 3401 SaveOption[20] := mAlFastMoves.Tag; 3402 SaveOption[21] := mAlNoMoves.Tag; 3403 DefaultOptionChecked := 1 shl 1 + 1 shl 7 + 1 shl 10 + 1 shl 12 + 1 shl 14 + 3404 1 shl 18 + 1 shl 19; 3405 3406 Reg := TRegistry.Create; 3407 doinit := true; 3408 if Reg.KeyExists('SOFTWARE\cevo\RegVer9') then 3409 with Reg do 3410 begin 3417 3411 doinit := false; 3418 3412 OpenKey('SOFTWARE\cevo\RegVer9', false); 3419 if ValueExists('TileWidth') then xxt := ReadInteger('TileWidth') div 2 3420 else xxt := 48; 3421 if ValueExists('TileHeight') then yyt := ReadInteger('TileHeight') div 2 3422 else yyt := 24; 3423 if ValueExists('OptionChecked') then OptionChecked := ReadInteger('OptionChecked') 3424 else OptionChecked := DefaultOptionChecked; 3425 if ValueExists('MapOptionChecked') then MapOptionChecked := ReadInteger('MapOptionChecked') 3426 else MapOptionChecked := 1 shl moCityNames; 3427 if ValueExists('CityMapMask') then CityRepMask := Cardinal(ReadInteger('CityReport')) 3428 else CityRepMask := Cardinal(not chPopIncrease and not chNoGrowthWarning and 3429 not chCaptured); 3413 if ValueExists('TileWidth') then 3414 xxt := ReadInteger('TileWidth') div 2 3415 else 3416 xxt := 48; 3417 if ValueExists('TileHeight') then 3418 yyt := ReadInteger('TileHeight') div 2 3419 else 3420 yyt := 24; 3421 if ValueExists('OptionChecked') then 3422 OptionChecked := ReadInteger('OptionChecked') 3423 else 3424 OptionChecked := DefaultOptionChecked; 3425 if ValueExists('MapOptionChecked') then 3426 MapOptionChecked := ReadInteger('MapOptionChecked') 3427 else 3428 MapOptionChecked := 1 shl moCityNames; 3429 if ValueExists('CityMapMask') then 3430 CityRepMask := Cardinal(ReadInteger('CityReport')) 3431 else 3432 CityRepMask := Cardinal(not chPopIncrease and not chNoGrowthWarning and 3433 not chCaptured); 3430 3434 CloseKey; 3431 3435 if OptionChecked and (7 shl 16) = 0 then … … 3433 3437 // old regver with no scrolling 3434 3438 end; 3435 Reg.Free; 3436 3437 if FullScreen then begin 3438 p.Style := $87000000; 3439 BorderStyle := bsNone; 3440 BorderIcons := []; 3441 end; 3442 3443 if 1 shl 13 and OptionChecked <> 0 then 3444 SoundMode := smOff 3445 else if 1 shl 15 and OptionChecked <> 0 then 3446 SoundMode := smOnAlt 3439 Reg.free; 3440 3441 if FullScreen then 3442 begin 3443 p.Style := $87000000; 3444 BorderStyle := bsNone; 3445 BorderIcons := []; 3446 end; 3447 3448 if 1 shl 13 and OptionChecked <> 0 then 3449 SoundMode := smOff 3450 else if 1 shl 15 and OptionChecked <> 0 then 3451 SoundMode := smOnAlt 3452 else 3453 SoundMode := smOn; 3454 end; 3455 3456 procedure TMainScreen.FormCreate(Sender: TObject); 3457 var 3458 i, j: integer; 3459 begin 3460 {$IFDEF WINDOWS}{ TODO } 3461 Screen.Cursors[crImpDrag] := LoadCursor(HInstance, 'DRAG'); 3462 Screen.Cursors[crFlatHand] := LoadCursor(HInstance, 'FLATHAND'); 3463 {$ENDIF} 3464 // tag-controlled language 3465 for i := 0 to ComponentCount - 1 do 3466 if Components[i].Tag and $FF <> 0 then 3467 if Components[i] is TMenuItem then 3468 begin 3469 TMenuItem(Components[i]).Caption := Phrases.Lookup('CONTROLS', 3470 -1 + Components[i].Tag and $FF); 3471 for j := 0 to nSaveOption - 1 do 3472 if Components[i].Tag and $FF = SaveOption[j] then 3473 TMenuItem(Components[i]).Checked := 1 shl j and OptionChecked <> 0; 3474 end 3475 else if Components[i] is TButtonBase then 3476 begin 3477 TButtonBase(Components[i]).Hint := Phrases.Lookup('CONTROLS', 3478 -1 + Components[i].Tag and $FF); 3479 if (Components[i] is TButtonC) and 3480 (TButtonC(Components[i]).ButtonIndex <> 1) then 3481 TButtonC(Components[i]).ButtonIndex := 3482 MapOptionChecked shr (Components[i].Tag shr 8) and 1 + 2 3483 end; 3484 3485 // non-tag-controlled language 3486 mTechTree.Caption := Phrases2.Lookup('MENU_ADVTREE'); 3487 mViewpoint.Caption := Phrases2.Lookup('MENU_VIEWPOINT'); 3488 if not Phrases2FallenBackToEnglish then 3489 begin 3490 MenuArea.Hint := Phrases2.Lookup('BTN_MENU'); 3491 TreasuryArea.Hint := Phrases2.Lookup('TIP_TREASURY'); 3492 ResearchArea.Hint := Phrases.Lookup('SCIENCE'); 3493 ManagementArea.Hint := Phrases2.Lookup('BTN_MANAGE'); 3494 end; 3495 for i := 0 to mRep.Count - 1 do 3496 begin 3497 j := mRep[i].Tag shr 8; 3498 mRep[i].Caption := CityEventName(j); 3499 mRep[i].Checked := CityRepMask and (1 shl j) <> 0; 3500 end; 3501 3502 Mini := TBitmap.Create; 3503 Mini.PixelFormat := pf24bit; 3504 Panel := TBitmap.Create; 3505 Panel.PixelFormat := pf24bit; 3506 Panel.Canvas.Font.Assign(UniFont[ftSmall]); 3507 Panel.Canvas.Brush.Style := bsClear; 3508 TopBar := TBitmap.Create; 3509 TopBar.PixelFormat := pf24bit; 3510 TopBar.Canvas.Font.Assign(UniFont[ftNormal]); 3511 TopBar.Canvas.Brush.Style := bsClear; 3512 Buffer := TBitmap.Create; 3513 Buffer.PixelFormat := pf24bit; 3514 if 2 * lxmax > 3 * xSizeBig then 3515 Buffer.width := 2 * lxmax 3516 else 3517 Buffer.width := 3 * xSizeBig; 3518 if lymax > 3 * ySizeBig then 3519 Buffer.height := lymax 3520 else 3521 Buffer.height := 3 * ySizeBig; 3522 Buffer.Canvas.Font.Assign(UniFont[ftSmall]); 3523 for i := 0 to nPl - 1 do 3524 AILogo[i] := nil; 3525 Canvas.Font.Assign(UniFont[ftSmall]); 3526 InitButtons(); 3527 EOT.Template := Templates; 3528 end; 3529 3530 procedure TMainScreen.FormDestroy(Sender: TObject); 3531 var 3532 i: integer; 3533 begin 3534 TopBar.free; 3535 Mini.free; 3536 Buffer.free; 3537 Panel.free; 3538 for i := 0 to nPl - 1 do 3539 if AILogo[i] <> nil then 3540 AILogo[i].free; 3541 end; 3542 3543 procedure TMainScreen.FormResize(Sender: TObject); 3544 var 3545 MiniFrame, MaxMapWidth: integer; 3546 begin 3547 SmallScreen := ClientWidth < 1024; 3548 MaxMapWidth := (G.lx * 2 - 3) * xxt; 3549 // avoide the same tile being visible left and right 3550 if ClientWidth <= MaxMapWidth then 3551 begin 3552 MapWidth := ClientWidth; 3553 MapOffset := 0; 3554 end 3555 else 3556 begin 3557 MapWidth := MaxMapWidth; 3558 MapOffset := (ClientWidth - MapWidth) div 2; 3559 end; 3560 MapHeight := ClientHeight - TopBarHeight - PanelHeight + overlap; 3561 Panel.width := ClientWidth; 3562 Panel.height := PanelHeight; 3563 TopBar.width := ClientWidth; 3564 TopBar.height := TopBarHeight; 3565 MiniFrame := (lxmax_xxx - G.ly) div 2; 3566 xMidPanel := (G.lx + MiniFrame) * 2 + 1; 3567 xRightPanel := ClientWidth - LeftPanelWidth - 10; 3568 if ClientMode = cEditMap then 3569 TrPitch := 2 * xxt 3570 else 3571 TrPitch := 66; 3572 xMini := MiniFrame - 5; 3573 yMini := (PanelHeight - 26 - lxmax_xxx) div 2 + MiniFrame; 3574 ywmax := (G.ly - MapHeight div yyt + 1) and not 1; 3575 ywcenter := -((MapHeight - yyt * (G.ly - 1)) div (4 * yyt)) * 2; 3576 // only for ywmax<=0 3577 if ywmax <= 0 then 3578 yw := ywcenter 3579 else if yw < 0 then 3580 yw := 0 3581 else if yw > ywmax then 3582 yw := ywmax; 3583 UnitInfoBtn.Top := ClientHeight - 29; 3584 UnitInfoBtn.Left := xMidPanel + 7 + 99; 3585 UnitBtn.Top := ClientHeight - 29; 3586 UnitBtn.Left := xMidPanel + 7 + 99 + 31; 3587 TerrainBtn.Top := ClientHeight - 29; 3588 TerrainBtn.Left := xMidPanel + 7 + 99 + 62; 3589 MovieSpeed1Btn.Top := ClientHeight - 91; 3590 MovieSpeed1Btn.Left := ClientWidth div 2 - 62; 3591 MovieSpeed2Btn.Top := ClientHeight - 91; 3592 MovieSpeed2Btn.Left := ClientWidth div 2 - 62 + 29; 3593 MovieSpeed3Btn.Top := ClientHeight - 91; 3594 MovieSpeed3Btn.Left := ClientWidth div 2 - 62 + 2 * 29; 3595 MovieSpeed4Btn.Top := ClientHeight - 91; 3596 MovieSpeed4Btn.Left := ClientWidth div 2 - 62 + 3 * 29 + 12; 3597 EOT.Top := ClientHeight - 64; 3598 EOT.Left := ClientWidth - 62; 3599 SetWindowPos(sb.h, 0, xRightPanel + 10 - 14 - GetSystemMetrics(SM_CXVSCROLL), 3600 ClientHeight - MidPanelHeight + 8, 0, 0, SWP_NOSIZE or SWP_NOZORDER); 3601 MapBtn0.Left := xMini + G.lx - 44; 3602 MapBtn0.Top := ClientHeight - 15; 3603 MapBtn1.Left := xMini + G.lx - 28; 3604 MapBtn1.Top := ClientHeight - 15; 3605 { MapBtn2.Left:=xMini+G.lx-20; 3606 MapBtn2.Top:=ClientHeight-15; 3607 MapBtn3.Left:=xMini+G.lx-4; 3608 MapBtn3.Top:=ClientHeight-15; } 3609 MapBtn5.Left := xMini + G.lx - 12; 3610 MapBtn5.Top := ClientHeight - 15; 3611 MapBtn4.Left := xMini + G.lx + 20; 3612 MapBtn4.Top := ClientHeight - 15; 3613 MapBtn6.Left := xMini + G.lx + 36; 3614 MapBtn6.Top := ClientHeight - 15; 3615 TreasuryArea.Left := ClientWidth div 2 - 172; 3616 ResearchArea.Left := ClientWidth div 2; 3617 ManagementArea.Left := ClientWidth - xPalace; 3618 ManagementArea.Top := TopBarHeight + MapHeight - overlap + yPalace; 3619 ArrangeMidPanel; 3620 if RepaintOnResize then 3621 begin 3622 RectInvalidate(0, TopBarHeight, ClientWidth, TopBarHeight + MapHeight); 3623 MapValid := false; 3624 PaintAll 3625 end 3626 end; 3627 3628 procedure TMainScreen.FormCloseQuery(Sender: TObject; var CanClose: boolean); 3629 begin 3630 CanClose := Closable; 3631 if not Closable and idle and (me = 0) and (ClientMode < scContact) then 3632 MenuClick(mResign) 3633 end; 3634 3635 procedure TMainScreen.OnScroll(var m: TMessage); 3636 begin 3637 if ProcessPVSB(sb, m) then 3638 begin 3639 PanelPaint; 3640 Update 3641 end 3642 end; 3643 3644 procedure TMainScreen.OnEOT(var Msg: TMessage); 3645 begin 3646 EndTurn 3647 end; 3648 3649 procedure TMainScreen.EOTClick(Sender: TObject); 3650 begin 3651 if GameMode = cMovie then 3652 begin 3653 MessgExDlg.CancelMovie; 3654 Server(sBreak, me, 0, nil^) 3655 end 3656 else if ClientMode < 0 then 3657 skipped := true 3658 else if ClientMode >= scContact then 3659 NegoDlg.ShowNewContent(wmPersistent) 3660 else if Jump[pTurn] > 0 then 3661 begin 3662 Jump[pTurn] := 0; 3663 StartRunning := false 3664 end 3665 else 3666 EndTurn 3667 end; 3668 3669 // set xTerrain, xTroop, and TrRow 3670 procedure TMainScreen.ArrangeMidPanel; 3671 begin 3672 if ClientMode = cEditMap then 3673 xTroop := xMidPanel + 15 3674 else 3675 begin 3676 if supervising then 3677 xTerrain := xMidPanel + 2 * xxt + 14 3678 else if ClientWidth < 1280 then 3679 xTerrain := ClientWidth div 2 + (1280 - ClientWidth) div 3 3447 3680 else 3448 SoundMode := smOn; 3681 xTerrain := ClientWidth div 2; 3682 xTroop := xTerrain + 2 * xxt + 12; 3683 if SmallScreen and not supervising then 3684 xTroop := xRightPanel + 10 - 3 * 66 - 3685 GetSystemMetrics(SM_CXVSCROLL) - 19 - 4; 3686 // not perfect but we assume almost no one is still playing on a 800x600 screen 3449 3687 end; 3450 3451 procedure TMainScreen.FormCreate(Sender: TObject); 3688 TrRow := (xRightPanel + 10 - xTroop - GetSystemMetrics(SM_CXVSCROLL) - 19) 3689 div TrPitch; 3690 end; 3691 3692 function TMainScreen.EndTurn(WasSkipped: boolean): boolean; 3693 3694 function IsResourceUnused(cix, NeedFood, NeedProd: integer): boolean; 3452 3695 var 3453 i, j: integer; 3454 begin 3455 {$IFDEF WINDOWS}{TODO} 3456 Screen.Cursors[crImpDrag] := LoadCursor(HInstance, 'DRAG'); 3457 Screen.Cursors[crFlatHand] := LoadCursor(HInstance, 'FLATHAND'); 3458 {$ENDIF} 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 3696 dx, dy, fix: integer; 3697 CityAreaInfo: TCityAreaInfo; 3698 TileInfo: TTileInfo; 3699 begin 3700 Server(sGetCityAreaInfo, me, cix, CityAreaInfo); 3701 for dy := -3 to 3 do 3702 for dx := -3 to 3 do 3703 if ((dx + dy) and 1 = 0) and (dx * dx * dy * dy < 81) then 3464 3704 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 3705 fix := (dy + 3) shl 2 + (dx + 3) shr 1; 3706 if (MyCity[cix].Tiles and (1 shl fix) = 0) // not used yet 3707 and (CityAreaInfo.Available[fix] = faAvailable) then // usable 3708 begin 3709 TileInfo.ExplCity := cix; 3710 Server(sGetHypoCityTileInfo, me, dLoc(MyCity[cix].Loc, dx, dy), 3711 TileInfo); 3712 if (TileInfo.Food >= NeedFood) and (TileInfo.Prod >= NeedProd) then 3713 begin 3714 result := true; 3715 exit 3716 end; 3717 end 3718 end; 3719 result := false; 3720 end; 3721 3722 var 3723 i, p1, uix, cix, CenterLoc: integer; 3724 MsgItem: string; 3725 CityReport: TCityReport; 3726 PlaneReturnData: TPlaneReturnData; 3727 Zoom: boolean; 3728 begin 3729 result := false; 3730 if ClientMode >= scDipOffer then 3731 exit; 3732 3733 if supervising and (me <> 0) then 3734 begin 3735 for i := 0 to Screen.FormCount - 1 do 3736 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 3737 Screen.Forms[i].Close; // close windows 3738 ItsMeAgain(0); 3739 end; 3740 3741 CityOptimizer_EndOfTurn; 3742 3743 if not WasSkipped then // check warnings 3744 begin 3745 // need to move planes home? 3746 for uix := 0 to MyRO.nUn - 1 do 3747 with MyUn[uix] do 3748 if (Loc >= 0) and (MyModel[mix].Domain = dAir) and 3749 (Status and usToldNoReturn = 0) and (Master < 0) and 3750 (MyMap[Loc] and fCity = 0) and (MyMap[Loc] and fTerImp <> tiBase) then 3473 3751 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 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 3480 3779 end; 3481 3780 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 TopBar.Free; 3532 Mini.Free; 3533 Buffer.Free; 3534 Panel.Free; 3535 for i := 0 to nPl - 1 do 3536 if AILogo[i] <> nil then 3537 AILogo[i].Free; 3538 end; 3539 3540 procedure TMainScreen.FormResize(Sender: TObject); 3541 var 3542 MiniFrame, MaxMapWidth: integer; 3543 begin 3544 SmallScreen := ClientWidth < 1024; 3545 MaxMapWidth := (G.lx * 2 - 3) * xxt; 3546 // avoide the same tile being visible left and right 3547 if ClientWidth <= MaxMapWidth then 3548 begin 3549 MapWidth := ClientWidth; 3550 MapOffset := 0; 3551 end 3552 else 3553 begin 3554 MapWidth := MaxMapWidth; 3555 MapOffset := (ClientWidth - MapWidth) div 2; 3556 end; 3557 MapHeight := ClientHeight - TopBarHeight - PanelHeight + overlap; 3558 Panel.width := ClientWidth; 3559 Panel.height := PanelHeight; 3560 TopBar.width := ClientWidth; 3561 TopBar.height := TopBarHeight; 3562 MiniFrame := (lxmax_xxx - G.ly) div 2; 3563 xMidPanel := (G.lx + MiniFrame) * 2 + 1; 3564 xRightPanel := ClientWidth - LeftPanelWidth - 10; 3565 if ClientMode = cEditMap then 3566 TrPitch := 2 * xxt 3567 else 3568 TrPitch := 66; 3569 xMini := MiniFrame - 5; 3570 yMini := (PanelHeight - 26 - lxmax_xxx) div 2 + MiniFrame; 3571 ywmax := (G.ly - MapHeight div yyt + 1) and not 1; 3572 ywcenter := -((MapHeight - yyt * (G.ly - 1)) div (4 * yyt)) * 2; 3573 // only for ywmax<=0 3574 if ywmax <= 0 then 3575 yw := ywcenter 3576 else if yw < 0 then 3577 yw := 0 3578 else if yw > ywmax then 3579 yw := ywmax; 3580 UnitInfoBtn.Top := ClientHeight - 29; 3581 UnitInfoBtn.Left := xMidPanel + 7 + 99; 3582 UnitBtn.Top := ClientHeight - 29; 3583 UnitBtn.Left := xMidPanel + 7 + 99 + 31; 3584 TerrainBtn.Top := ClientHeight - 29; 3585 TerrainBtn.Left := xMidPanel + 7 + 99 + 62; 3586 MovieSpeed1Btn.Top := ClientHeight - 91; 3587 MovieSpeed1Btn.Left := ClientWidth div 2 - 62; 3588 MovieSpeed2Btn.Top := ClientHeight - 91; 3589 MovieSpeed2Btn.Left := ClientWidth div 2 - 62 + 29; 3590 MovieSpeed3Btn.Top := ClientHeight - 91; 3591 MovieSpeed3Btn.Left := ClientWidth div 2 - 62 + 2 * 29; 3592 MovieSpeed4Btn.Top := ClientHeight - 91; 3593 MovieSpeed4Btn.Left := ClientWidth div 2 - 62 + 3 * 29 + 12; 3594 EOT.Top := ClientHeight - 64; 3595 EOT.Left := ClientWidth - 62; 3596 SetWindowPos(sb.h, 0, xRightPanel + 10 - 14 - 3597 GetSystemMetrics(SM_CXVSCROLL), ClientHeight - MidPanelHeight + 8, 0, 0, 3598 SWP_NOSIZE or SWP_NOZORDER); 3599 MapBtn0.Left := xMini + G.lx - 44; 3600 MapBtn0.Top := ClientHeight - 15; 3601 MapBtn1.Left := xMini + G.lx - 28; 3602 MapBtn1.Top := ClientHeight - 15; 3603 { MapBtn2.Left:=xMini+G.lx-20; 3604 MapBtn2.Top:=ClientHeight-15; 3605 MapBtn3.Left:=xMini+G.lx-4; 3606 MapBtn3.Top:=ClientHeight-15; } 3607 MapBtn5.Left := xMini + G.lx - 12; 3608 MapBtn5.Top := ClientHeight - 15; 3609 MapBtn4.Left := xMini + G.lx + 20; 3610 MapBtn4.Top := ClientHeight - 15; 3611 MapBtn6.Left := xMini + G.lx + 36; 3612 MapBtn6.Top := ClientHeight - 15; 3613 TreasuryArea.Left := ClientWidth div 2 - 172; 3614 ResearchArea.Left := ClientWidth div 2; 3615 ManagementArea.Left := ClientWidth - xPalace; 3616 ManagementArea.Top := TopBarHeight + MapHeight - overlap + yPalace; 3617 ArrangeMidPanel; 3618 if RepaintOnResize then 3619 begin 3620 RectInvalidate(0, TopBarHeight, ClientWidth, TopBarHeight + MapHeight); 3621 MapValid := false; 3622 PaintAll 3623 end 3624 end; 3625 3626 procedure TMainScreen.FormCloseQuery(Sender: TObject; var CanClose: boolean); 3627 begin 3628 CanClose := Closable; 3629 if not Closable and idle and (me = 0) and (ClientMode < scContact) then 3630 MenuClick(mResign) 3631 end; 3632 3633 procedure TMainScreen.OnScroll(var m: TMessage); 3634 begin 3635 if ProcessPVSB(sb, m) then 3636 begin 3637 PanelPaint; 3638 Update 3639 end 3640 end; 3641 3642 procedure TMainScreen.OnEOT(var Msg: TMessage); 3643 begin 3644 EndTurn 3645 end; 3646 3647 procedure TMainScreen.EOTClick(Sender: TObject); 3648 begin 3649 if GameMode = cMovie then 3650 begin 3651 MessgExDlg.CancelMovie; 3652 Server(sBreak, me, 0, nil^) 3653 end 3654 else if ClientMode < 0 then 3655 skipped := true 3656 else if ClientMode >= scContact then 3657 NegoDlg.ShowNewContent(wmPersistent) 3658 else if Jump[pTurn] > 0 then 3659 begin 3660 Jump[pTurn] := 0; 3661 StartRunning := false 3662 end 3663 else 3664 EndTurn 3665 end; 3666 3667 // set xTerrain, xTroop, and TrRow 3668 procedure TMainScreen.ArrangeMidPanel; 3669 begin 3670 if ClientMode = cEditMap then 3671 xTroop := xMidPanel + 15 3672 else 3673 begin 3674 if supervising then 3675 xTerrain := xMidPanel + 2 * xxt + 14 3676 else if ClientWidth < 1280 then 3677 xTerrain := ClientWidth div 2 + (1280 - ClientWidth) div 3 3678 else 3679 xTerrain := ClientWidth div 2; 3680 xTroop := xTerrain + 2 * xxt + 12; 3681 if SmallScreen and not supervising then 3682 xTroop := xRightPanel + 10 - 3 * 66 - 3683 GetSystemMetrics(SM_CXVSCROLL) - 19 - 4; 3684 // not perfect but we assume almost no one is still playing on a 800x600 screen 3685 end; 3686 TrRow := (xRightPanel + 10 - xTroop - GetSystemMetrics(SM_CXVSCROLL) - 19) 3687 div TrPitch; 3688 end; 3689 3690 function TMainScreen.EndTurn(WasSkipped: boolean): boolean; 3691 3692 function IsResourceUnused(cix, NeedFood, NeedProd: integer): boolean; 3693 var 3694 dx, dy, fix: integer; 3695 CityAreaInfo: TCityAreaInfo; 3696 TileInfo: TTileInfo; 3697 begin 3698 Server(sGetCityAreaInfo, me, cix, CityAreaInfo); 3699 for dy := -3 to 3 do 3700 for dx := -3 to 3 do 3701 if ((dx + dy) and 1 = 0) and (dx * dx * dy * dy < 81) then 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 3702 3800 begin 3703 fix := (dy + 3) shl 2 + (dx + 3) shr 1;3704 if (MyCity[cix].Tiles and (1 shl fix) = 0) // not used yet3705 and (CityAreaInfo.Available[fix] = faAvailable) then // usable3706 begin3707 TileInfo.ExplCity := cix;3708 Server(sGetHypoCityTileInfo, me, dLoc(MyCity[cix].Loc, dx, dy), 3709 TileInfo);3710 if (TileInfo.Food >= NeedFood) and (TileInfo.Prod >= NeedProd)3711 then3801 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 3712 3810 begin 3713 result := true; 3714 exit 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; 3715 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 3716 3863 end 3717 3864 end; 3718 result := false; 3719 end; 3720 3721 var 3722 i, p1, uix, cix, CenterLoc: integer; 3723 MsgItem: string; 3724 CityReport: TCityReport; 3725 PlaneReturnData: TPlaneReturnData; 3726 Zoom: boolean; 3727 begin 3728 result := false; 3729 if ClientMode >= scDipOffer then 3730 exit; 3731 3732 if supervising and (me <> 0) then 3733 begin 3734 for i := 0 to Screen.FormCount - 1 do 3735 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 3736 then 3737 Screen.Forms[i].Close; // close windows 3738 ItsMeAgain(0); 3739 end; 3740 3741 CityOptimizer_EndOfTurn; 3742 3743 if not WasSkipped then // check warnings 3744 begin 3745 // need to move planes home? 3746 for uix := 0 to MyRO.nUn - 1 do 3747 with MyUn[uix] do 3748 if (Loc >= 0) and (MyModel[mix].Domain = dAir) and 3749 (Status and usToldNoReturn = 0) and (Master < 0) and 3750 (MyMap[Loc] and fCity = 0) and (MyMap[Loc] and fTerImp <> tiBase) 3751 then 3752 begin 3753 PlaneReturnData.Fuel := Fuel; 3754 PlaneReturnData.Loc := Loc; 3755 PlaneReturnData.Movement := 0; // end turn without further movement? 3756 if Server(sGetPlaneReturn, me, uix, PlaneReturnData) = eNoWay then 3757 begin 3758 CenterLoc := Loc + G.lx * 6; 3759 // centering the unit itself would make it covered by the query dialog 3760 while CenterLoc >= G.lx * G.ly do 3761 dec(CenterLoc, G.lx * 2); 3762 Centre(CenterLoc); 3763 SetTroopLoc(-1); 3764 PaintAll; 3765 3766 if MyModel[mix].Kind = mkSpecial_Glider then 3767 MsgItem := 'LOWFUEL_GLIDER' 3768 else 3769 MsgItem := 'LOWFUEL'; 3770 if SimpleQuery(mkYesNo, Phrases.Lookup(MsgItem), 3771 'WARNING_LOWSUPPORT') <> mrOK then 3772 begin 3773 SetUnFocus(uix); 3774 SetTroopLoc(Loc); 3775 PanelPaint; 3776 exit; 3777 end; 3778 MyUn[uix].Status := MyUn[uix].Status or usToldNoReturn; 3779 end 3780 end; 3781 3782 if not supervising and (MyRO.TestFlags and tfImmImprove = 0) and 3783 (MyRO.Government <> gAnarchy) and (MyRO.Money + TaxSum < 0) and 3784 (MyRO.TaxRate < 100) then // low funds! 3785 with MessgExDlg do 3786 begin 3787 OpenSound := 'WARNING_LOWFUNDS'; 3788 MessgText := Phrases.Lookup('LOWFUNDS'); 3789 Kind := mkYesNo; 3790 IconKind := mikImp; 3791 IconIndex := imTrGoods; 3792 ShowModal; 3793 if ModalResult <> mrOK then 3794 exit 3795 end; 3796 3797 if MyRO.Government <> gAnarchy then 3798 for cix := 0 to MyRO.nCity - 1 do 3799 with MyCity[cix] do 3800 if (Loc >= 0) and (Flags and chCaptured = 0) then 3801 begin 3802 Zoom := false; 3803 CityReport.HypoTiles := -1; 3804 CityReport.HypoTax := -1; 3805 CityReport.HypoLux := -1; 3806 Server(sGetCityReport, me, cix, CityReport); 3807 3808 if (CityReport.Working - CityReport.Happy > Size shr 1) and 3809 (Flags and chCaptured <= $10000) then 3810 with MessgExDlg do 3811 begin 3812 OpenSound := 'WARNING_DISORDER'; 3813 if Status and csResourceWeightsMask = 0 then 3814 MsgItem := 'DISORDER' 3815 else 3816 MsgItem := 'DISORDER_UNREST'; 3817 MessgText := Format(Phrases.Lookup(MsgItem), [CityName(ID)]); 3818 Kind := mkYesNo; 3819 // BigIcon:=29; 3820 ShowModal; 3821 Zoom := ModalResult <> mrOK; 3822 end; 3823 if not Zoom and (Food + CityReport.FoodRep - CityReport.Eaten < 0) 3824 then 3825 with MessgExDlg do 3826 begin 3827 OpenSound := 'WARNING_FAMINE'; 3828 if Status and csResourceWeightsMask = 0 then 3829 MsgItem := 'FAMINE' 3830 else if (CityReport.Deployed <> 0) and 3831 IsResourceUnused(cix, 1, 0) then 3832 MsgItem := 'FAMINE_UNREST' 3833 else 3834 MsgItem := 'FAMINE_TILES'; 3835 MessgText := Format(Phrases.Lookup(MsgItem), [CityName(ID)]); 3836 Kind := mkYesNo; 3837 IconKind := mikImp; 3838 IconIndex := 22; 3839 ShowModal; 3840 Zoom := ModalResult <> mrOK; 3841 end; 3842 if not Zoom and (CityReport.ProdRep < CityReport.Support) then 3843 with MessgExDlg do 3844 begin 3845 OpenSound := 'WARNING_LOWSUPPORT'; 3846 if Status and csResourceWeightsMask = 0 then 3847 MsgItem := 'LOWSUPPORT' 3848 else if (CityReport.Deployed <> 0) and 3849 IsResourceUnused(cix, 0, 1) then 3850 MsgItem := 'LOWSUPPORT_UNREST' 3851 else 3852 MsgItem := 'LOWSUPPORT_TILES'; 3853 MessgText := Format(Phrases.Lookup(MsgItem), [CityName(ID)]); 3854 Kind := mkYesNo; 3855 IconKind := mikImp; 3856 IconIndex := 29; 3857 ShowModal; 3858 Zoom := ModalResult <> mrOK; 3859 end; 3860 if Zoom then 3861 begin // zoom to city 3862 ZoomToCity(Loc); 3863 exit 3864 end 3865 end; 3866 3867 if (MyRO.Happened and phTech <> 0) and (MyRO.ResearchTech < 0) and 3868 (MyData.FarTech <> adNexus) then 3869 if not ChooseResearch then 3870 exit; 3871 end; 3872 3873 RememberPeaceViolation; 3874 3875 SetUnFocus(-1); 3876 for uix := 0 to MyRO.nUn - 1 do 3877 MyUn[uix].Status := MyUn[uix].Status and usPersistent; 3878 3879 CityDlg.CloseAction := None; 3880 if IsMultiPlayerGame then 3881 begin // close windows for next player 3882 for i := 0 to Screen.FormCount - 1 do 3883 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 3884 then 3885 Screen.Forms[i].Close; 3886 end 3887 else 3888 begin 3889 if CityDlg.Visible then 3890 CityDlg.Close; 3891 if UnitStatDlg.Visible then 3892 UnitStatDlg.Close; 3893 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 3894 3881 for i := 0 to Screen.FormCount - 1 do 3895 3882 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 3896 Screen.Forms[i].Enabled := false; 3897 3898 if Server(sTurn, pTurn, 0, nil^) >= rExecuted then 3899 begin 3900 if Jump[pTurn] > 0 then 3901 EOT.Hint := Phrases.Lookup('BTN_STOP') 3902 else 3903 EOT.Hint := Phrases.Lookup('BTN_SKIP'); 3904 result := true; 3905 SetTroopLoc(-1); 3906 pTurn := -1; 3907 pLogo := -1; 3908 UnitInfoBtn.Visible := false; 3909 UnitBtn.Visible := false; 3910 TerrainBtn.Visible := false; 3911 EOT.ButtonIndex := eotCancel; 3912 EOT.Visible := true; 3913 MapValid := false; 3914 PanelPaint; 3915 Update; 3916 ClientMode := -1; 3917 idle := false; 3918 skipped := WasSkipped; 3919 for p1 := 1 to nPl - 1 do 3920 if G.RO[p1] <> nil then 3921 skipped := true; // don't show enemy moves in hotseat mode 3922 end 3883 Screen.Forms[i].Close; 3884 end 3885 else 3886 begin 3887 if CityDlg.Visible then 3888 CityDlg.Close; 3889 if UnitStatDlg.Visible then 3890 UnitStatDlg.Close; 3891 end; 3892 for i := 0 to Screen.FormCount - 1 do 3893 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 3894 Screen.Forms[i].Enabled := false; 3895 3896 if Server(sTurn, pTurn, 0, nil^) >= rExecuted then 3897 begin 3898 if Jump[pTurn] > 0 then 3899 EOT.Hint := Phrases.Lookup('BTN_STOP') 3923 3900 else 3924 PanelPaint 3925 end; // EndTurn 3926 3927 procedure TMainScreen.EndNego; 3928 begin 3929 if NegoDlg.Visible then 3930 NegoDlg.Close; 3931 HaveStrategyAdvice := false; 3932 // AdvisorDlg.HaveStrategyAdvice; 3933 // negotiation might have changed advices 3901 EOT.Hint := Phrases.Lookup('BTN_SKIP'); 3902 result := true; 3903 SetTroopLoc(-1); 3904 pTurn := -1; 3905 pLogo := -1; 3906 UnitInfoBtn.Visible := false; 3907 UnitBtn.Visible := false; 3908 TerrainBtn.Visible := false; 3934 3909 EOT.ButtonIndex := eotCancel; 3935 3910 EOT.Visible := true; 3911 MapValid := false; 3936 3912 PanelPaint; 3937 3913 Update; 3938 3914 ClientMode := -1; 3939 3915 idle := false; 3916 skipped := WasSkipped; 3917 for p1 := 1 to nPl - 1 do 3918 if G.RO[p1] <> nil then 3919 skipped := true; // don't show enemy moves in hotseat mode 3920 end 3921 else 3922 PanelPaint 3923 end; // EndTurn 3924 3925 procedure TMainScreen.EndNego; 3926 begin 3927 if NegoDlg.Visible then 3928 NegoDlg.Close; 3929 HaveStrategyAdvice := false; 3930 // AdvisorDlg.HaveStrategyAdvice; 3931 // negotiation might have changed advices 3932 EOT.ButtonIndex := eotCancel; 3933 EOT.Visible := true; 3934 PanelPaint; 3935 Update; 3936 ClientMode := -1; 3937 idle := false; 3938 end; 3939 3940 procedure TMainScreen.ProcessRect(x0, y0, nx, ny, Options: integer); 3941 var 3942 xs, ys, xl, yl: integer; 3943 begin 3944 xl := nx * xxt + xxt; 3945 yl := ny * yyt + yyt * 2; 3946 xs := (x0 - xw) * (xxt * 2) + y0 and 1 * xxt - G.lx * (xxt * 2); 3947 // |xs+xl/2-MapWidth/2| -> min 3948 while abs(2 * (xs + G.lx * (xxt * 2)) + xl - MapWidth) < 3949 abs(2 * xs + xl - MapWidth) do 3950 inc(xs, G.lx * (xxt * 2)); 3951 ys := (y0 - yw) * yyt - yyt; 3952 if xs + xl > MapWidth then 3953 xl := MapWidth - xs; 3954 if ys + yl > MapHeight then 3955 yl := MapHeight - ys; 3956 if (xl <= 0) or (yl <= 0) then 3957 exit; 3958 if Options and prPaint <> 0 then 3959 begin 3960 if Options and prAutoBounds <> 0 then 3961 MainMap.SetPaintBounds(xs, ys, xs + xl, ys + yl); 3962 MainMap.Paint(xs, ys, x0 + G.lx * y0, nx, ny, -1, -1); 3940 3963 end; 3941 3942 procedure TMainScreen.ProcessRect(x0, y0, nx, ny, Options: integer); 3943 var 3944 xs, ys, xl, yl: integer; 3945 begin 3946 xl := nx * xxt + xxt; 3947 yl := ny * yyt + yyt * 2; 3948 xs := (x0 - xw) * (xxt * 2) + y0 and 1 * xxt - G.lx * (xxt * 2); 3949 // |xs+xl/2-MapWidth/2| -> min 3950 while abs(2 * (xs + G.lx * (xxt * 2)) + xl - MapWidth) < 3951 abs(2 * xs + xl - MapWidth) do 3952 inc(xs, G.lx * (xxt * 2)); 3953 ys := (y0 - yw) * yyt - yyt; 3954 if xs + xl > MapWidth then 3955 xl := MapWidth - xs; 3956 if ys + yl > MapHeight then 3957 yl := MapHeight - ys; 3958 if (xl <= 0) or (yl <= 0) then 3959 exit; 3960 if Options and prPaint <> 0 then 3961 begin 3962 if Options and prAutoBounds <> 0 then 3963 MainMap.SetPaintBounds(xs, ys, xs + xl, ys + yl); 3964 MainMap.Paint(xs, ys, x0 + G.lx * y0, nx, ny, -1, -1); 3965 end; 3966 if Options and prInvalidate <> 0 then 3967 RectInvalidate(MapOffset + xs, TopBarHeight + ys, MapOffset + xs + xl, 3968 TopBarHeight + ys + yl) 3964 if Options and prInvalidate <> 0 then 3965 RectInvalidate(MapOffset + xs, TopBarHeight + ys, MapOffset + xs + xl, 3966 TopBarHeight + ys + yl) 3967 end; 3968 3969 procedure TMainScreen.PaintLoc(Loc: integer; Radius: integer = 0); 3970 var 3971 yLoc, x0: integer; 3972 begin 3973 if MapValid then 3974 begin 3975 yLoc := (Loc + G.lx * 1024) div G.lx - 1024; 3976 x0 := (Loc + (yLoc and 1 - 2 * Radius + G.lx * 1024) div 2) mod G.lx; 3977 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 3978 ProcessRect(x0, yLoc - 2 * Radius, 4 * Radius + 1, 4 * Radius + 1, 3979 prPaint or prAutoBounds or prInvalidate); 3980 Update; 3981 end 3982 end; 3983 3984 procedure TMainScreen.PaintLocTemp(Loc, Style: integer); 3985 var 3986 y0, x0, xMap, yMap: integer; 3987 begin 3988 if not MapValid then 3989 exit; 3990 Buffer.Canvas.Font.Assign(UniFont[ftSmall]); 3991 y0 := Loc div G.lx; 3992 x0 := Loc mod G.lx; 3993 xMap := (x0 - xw) * (xxt * 2) + y0 and 1 * xxt - G.lx * (xxt * 2); 3994 // |xMap+xxt-MapWidth/2| -> min 3995 while abs(2 * (xMap + G.lx * (xxt * 2)) + 2 * xxt - MapWidth) < 3996 abs(2 * xMap + 2 * xxt - MapWidth) do 3997 inc(xMap, G.lx * (xxt * 2)); 3998 yMap := (y0 - yw) * yyt - yyt; 3999 NoMap.SetOutput(Buffer); 4000 NoMap.SetPaintBounds(0, 0, 2 * xxt, 3 * yyt); 4001 NoMap.Paint(0, 0, Loc, 1, 1, -1, -1, Style = pltsBlink); 4002 PaintBufferToScreen(xMap, yMap, 2 * xxt, 3 * yyt); 4003 end; 4004 4005 // paint content of buffer directly to screen instead of offscreen 4006 // panel protusions are added 4007 // NoMap must be set to buffer and bounds before 4008 procedure TMainScreen.PaintBufferToScreen(xMap, yMap, width, height: integer); 4009 begin 4010 if xMap + width > MapWidth then 4011 width := MapWidth - xMap; 4012 if yMap + height > MapHeight then 4013 height := MapHeight - yMap; 4014 if (width <= 0) or (height <= 0) or (width + xMap <= 0) or (height + yMap <= 0) 4015 then 4016 exit; 4017 4018 NoMap.BitBlt(Panel, -xMap - MapOffset, -yMap + MapHeight - overlap, xMidPanel, 4019 overlap, 0, 0, SRCCOPY); 4020 NoMap.BitBlt(Panel, -xMap - MapOffset + xRightPanel, 4021 -yMap + MapHeight - overlap, Panel.width - xRightPanel, overlap, 4022 xRightPanel, 0, SRCCOPY); 4023 if yMap < 0 then 4024 begin 4025 if xMap < 0 then 4026 BitBlt(Canvas.Handle, MapOffset, TopBarHeight, width + xMap, 4027 height + yMap, Buffer.Canvas.Handle, -xMap, -yMap, SRCCOPY) 4028 else 4029 BitBlt(Canvas.Handle, xMap + MapOffset, TopBarHeight, width, 4030 height + yMap, Buffer.Canvas.Handle, 0, -yMap, SRCCOPY) 4031 end 4032 else 4033 begin 4034 if xMap < 0 then 4035 BitBlt(Canvas.Handle, MapOffset, TopBarHeight + yMap, width + xMap, 4036 height, Buffer.Canvas.Handle, -xMap, 0, SRCCOPY) 4037 else 4038 BitBlt(Canvas.Handle, xMap + MapOffset, TopBarHeight + yMap, width, 4039 height, Buffer.Canvas.Handle, 0, 0, SRCCOPY); 4040 end 4041 end; 4042 4043 procedure TMainScreen.PaintLoc_BeforeMove(FromLoc: integer); 4044 var 4045 yLoc, x0: integer; 4046 begin 4047 if MapValid then 4048 begin 4049 yLoc := (FromLoc + G.lx * 1024) div G.lx - 1024; 4050 x0 := (FromLoc + (yLoc and 1 + G.lx * 1024) div 2) mod G.lx; 4051 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 4052 ProcessRect(x0, yLoc, 1, 1, prPaint or prAutoBounds); 4053 end 4054 end; 4055 4056 procedure TMainScreen.PaintDestination; 4057 var 4058 Destination: integer; 4059 begin 4060 if (UnFocus >= 0) and (MyUn[UnFocus].Status and usGoto <> 0) then 4061 begin 4062 Destination := MyUn[UnFocus].Status shr 16; 4063 if (Destination <> $7FFF) and (Destination <> MyUn[UnFocus].Loc) then 4064 PaintLocTemp(Destination, pltsBlink); 3969 4065 end; 3970 3971 procedure TMainScreen.PaintLoc(Loc: integer; Radius: integer = 0); 3972 var 3973 yLoc, x0: integer; 3974 begin 3975 if MapValid then 3976 begin 3977 yLoc := (Loc + G.lx * 1024) div G.lx - 1024; 3978 x0 := (Loc + (yLoc and 1 - 2 * Radius + G.lx * 1024) div 2) mod G.lx; 3979 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 3980 ProcessRect(x0, yLoc - 2 * Radius, 4 * Radius + 1, 4 * Radius + 1, 3981 prPaint or prAutoBounds or prInvalidate); 3982 Update; 3983 end 4066 end; 4067 4068 procedure TMainScreen.MiniPaint; 4069 type 4070 TLine = array [0 .. 99999999, 0 .. 2] of Byte; 4071 var 4072 uix, cix, x, y, Loc, i, hw, xm, cm, cmPolOcean, cmPolNone: integer; 4073 PrevMiniLine, MiniLine: ^TLine; 4074 begin 4075 cmPolOcean := GrExt[HGrSystem].Data.Canvas.Pixels[101, 67]; 4076 cmPolNone := GrExt[HGrSystem].Data.Canvas.Pixels[102, 67]; 4077 hw := MapWidth div (xxt * 2); 4078 with Mini.Canvas do 4079 begin 4080 Brush.Color := $000000; 4081 FillRect(Rect(0, 0, Mini.width, Mini.height)); 3984 4082 end; 3985 3986 procedure TMainScreen.PaintLocTemp(Loc, Style: integer); 3987 var 3988 y0, x0, xMap, yMap: integer; 3989 begin 3990 if not MapValid then 3991 exit; 3992 Buffer.Canvas.Font.Assign(UniFont[ftSmall]); 3993 y0 := Loc div G.lx; 3994 x0 := Loc mod G.lx; 3995 xMap := (x0 - xw) * (xxt * 2) + y0 and 1 * xxt - G.lx * (xxt * 2); 3996 // |xMap+xxt-MapWidth/2| -> min 3997 while abs(2 * (xMap + G.lx * (xxt * 2)) + 2 * xxt - MapWidth) < 3998 abs(2 * xMap + 2 * xxt - MapWidth) do 3999 inc(xMap, G.lx * (xxt * 2)); 4000 yMap := (y0 - yw) * yyt - yyt; 4001 NoMap.SetOutput(Buffer); 4002 NoMap.SetPaintBounds(0, 0, 2 * xxt, 3 * yyt); 4003 NoMap.Paint(0, 0, Loc, 1, 1, -1, -1, Style = pltsBlink); 4004 PaintBufferToScreen(xMap, yMap, 2 * xxt, 3 * yyt); 4005 end; 4006 4007 // paint content of buffer directly to screen instead of offscreen 4008 // panel protusions are added 4009 // NoMap must be set to buffer and bounds before 4010 procedure TMainScreen.PaintBufferToScreen(xMap, yMap, width, height: integer); 4011 begin 4012 if xMap + width > MapWidth then 4013 width := MapWidth - xMap; 4014 if yMap + height > MapHeight then 4015 height := MapHeight - yMap; 4016 if (width <= 0) or (height <= 0) or (width + xMap <= 0) or 4017 (height + yMap <= 0) then 4018 exit; 4019 4020 NoMap.BitBlt(Panel, -xMap - MapOffset, -yMap + MapHeight - overlap, 4021 xMidPanel, overlap, 0, 0, SRCCOPY); 4022 NoMap.BitBlt(Panel, -xMap - MapOffset + xRightPanel, 4023 -yMap + MapHeight - overlap, Panel.width - xRightPanel, overlap, 4024 xRightPanel, 0, SRCCOPY); 4025 if yMap < 0 then 4026 begin 4027 if xMap < 0 then 4028 BitBlt(Canvas.Handle, MapOffset, TopBarHeight, width + xMap, 4029 height + yMap, Buffer.Canvas.Handle, -xMap, -yMap, SRCCOPY) 4030 else 4031 BitBlt(Canvas.Handle, xMap + MapOffset, TopBarHeight, width, 4032 height + yMap, Buffer.Canvas.Handle, 0, -yMap, SRCCOPY) 4033 end 4034 else 4035 begin 4036 if xMap < 0 then 4037 BitBlt(Canvas.Handle, MapOffset, TopBarHeight + yMap, width + xMap, 4038 height, Buffer.Canvas.Handle, -xMap, 0, SRCCOPY) 4039 else 4040 BitBlt(Canvas.Handle, xMap + MapOffset, TopBarHeight + yMap, width, 4041 height, Buffer.Canvas.Handle, 0, 0, SRCCOPY); 4042 end 4043 end; 4044 4045 procedure TMainScreen.PaintLoc_BeforeMove(FromLoc: integer); 4046 var 4047 yLoc, x0: integer; 4048 begin 4049 if MapValid then 4050 begin 4051 yLoc := (FromLoc + G.lx * 1024) div G.lx - 1024; 4052 x0 := (FromLoc + (yLoc and 1 + G.lx * 1024) div 2) mod G.lx; 4053 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 4054 ProcessRect(x0, yLoc, 1, 1, prPaint or prAutoBounds); 4055 end 4056 end; 4057 4058 procedure TMainScreen.PaintDestination; 4059 var 4060 Destination: integer; 4061 begin 4062 if (UnFocus >= 0) and (MyUn[UnFocus].Status and usGoto <> 0) then 4063 begin 4064 Destination := MyUn[UnFocus].Status shr 16; 4065 if (Destination <> $7FFF) and (Destination <> MyUn[UnFocus].Loc) then 4066 PaintLocTemp(Destination, pltsBlink); 4067 end; 4068 end; 4069 4070 procedure TMainScreen.MiniPaint; 4071 type 4072 TLine = array [0 .. 99999999, 0 .. 2] of Byte; 4073 var 4074 uix, cix, x, y, Loc, i, hw, xm, cm, cmPolOcean, cmPolNone: integer; 4075 PrevMiniLine, MiniLine: ^TLine; 4076 begin 4077 cmPolOcean := GrExt[HGrSystem].Data.Canvas.Pixels[101, 67]; 4078 cmPolNone := GrExt[HGrSystem].Data.Canvas.Pixels[102, 67]; 4079 hw := MapWidth div (xxt * 2); 4080 with Mini.Canvas do 4081 begin 4082 Brush.Color := $000000; 4083 FillRect(Rect(0, 0, Mini.width, Mini.height)); 4084 end; 4085 MiniLine := nil; 4086 Mini.BeginUpdate; 4087 for y := 0 to G.ly - 1 do 4088 begin 4089 PrevMiniLine := MiniLine; 4090 MiniLine := Mini.ScanLine[y]; 4091 for x := 0 to G.lx - 1 do 4092 if MyMap[x + G.lx * y] and fTerrain <> fUNKNOWN then 4083 MiniLine := nil; 4084 Mini.BeginUpdate; 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 4093 4094 begin 4094 Loc := x + G.lx * y; 4095 for i := 0 to 1 do 4095 xm := ((x - xwMini) * 2 + i + y and 1 - hw + G.lx * 5) mod (G.lx * 2); 4096 cm := MiniColors[MyMap[Loc] and fTerrain, i]; 4097 if ClientMode = cEditMap then 4096 4098 begin 4097 xm := ((x - xwMini) * 2 + i + y and 1 - hw + G.lx * 5) 4098 mod (G.lx * 2); 4099 cm := MiniColors[MyMap[Loc] and fTerrain, i]; 4100 if ClientMode = cEditMap then 4099 if MyMap[Loc] and (fPrefStartPos or fStartPos) <> 0 then 4100 cm := $FFFFFF; 4101 end 4102 else if MyMap[Loc] and fCity <> 0 then 4103 begin 4104 cix := MyRO.nCity - 1; 4105 while (cix >= 0) and (MyCity[cix].Loc <> Loc) do 4106 dec(cix); 4107 if cix >= 0 then 4108 cm := Tribe[me].Color 4109 else 4101 4110 begin 4102 if MyMap[Loc] and (fPrefStartPos or fStartPos) <> 0 then 4103 cm := $FFFFFF; 4104 end 4105 else if MyMap[Loc] and fCity <> 0 then 4106 begin 4107 cix := MyRO.nCity - 1; 4108 while (cix >= 0) and (MyCity[cix].Loc <> Loc) do 4111 cix := MyRO.nEnemyCity - 1; 4112 while (cix >= 0) and (MyRO.EnemyCity[cix].Loc <> Loc) do 4109 4113 dec(cix); 4110 4114 if cix >= 0 then 4111 cm := Tribe[me].Color 4112 else 4113 begin 4114 cix := MyRO.nEnemyCity - 1; 4115 while (cix >= 0) and (MyRO.EnemyCity[cix].Loc <> Loc) do 4116 dec(cix); 4117 if cix >= 0 then 4118 cm := Tribe[MyRO.EnemyCity[cix].Owner].Color 4119 end; 4120 cm := $808080 or cm shr 1; { increase brightness } 4121 if PrevMiniLine <> nil then 4122 begin // 2x2 city dot covers two scanlines 4123 PrevMiniLine[xm, 0] := cm shr 16; 4124 PrevMiniLine[xm, 1] := cm shr 8 and $FF; 4125 PrevMiniLine[xm, 2] := cm and $FF; 4126 end 4115 cm := Tribe[MyRO.EnemyCity[cix].Owner].Color 4116 end; 4117 cm := $808080 or cm shr 1; { increase brightness } 4118 if PrevMiniLine <> nil then 4119 begin // 2x2 city dot covers two scanlines 4120 PrevMiniLine[xm, 0] := cm shr 16; 4121 PrevMiniLine[xm, 1] := cm shr 8 and $FF; 4122 PrevMiniLine[xm, 2] := cm and $FF; 4127 4123 end 4128 else if (i = 0) and (MyMap[Loc] and fUnit <> 0) then 4124 end 4125 else if (i = 0) and (MyMap[Loc] and fUnit <> 0) then 4126 begin 4127 uix := MyRO.nUn - 1; 4128 while (uix >= 0) and (MyUn[uix].Loc <> Loc) do 4129 dec(uix); 4130 if uix >= 0 then 4131 cm := Tribe[me].Color 4132 else 4129 4133 begin 4130 uix := MyRO.n Un - 1;4131 while (uix >= 0) and (My Un[uix].Loc <> Loc) do4134 uix := MyRO.nEnemyUn - 1; 4135 while (uix >= 0) and (MyRO.EnemyUn[uix].Loc <> Loc) do 4132 4136 dec(uix); 4133 4137 if uix >= 0 then 4134 cm := Tribe[me].Color 4135 else 4136 begin 4137 uix := MyRO.nEnemyUn - 1; 4138 while (uix >= 0) and (MyRO.EnemyUn[uix].Loc <> Loc) do 4139 dec(uix); 4140 if uix >= 0 then 4141 cm := Tribe[MyRO.EnemyUn[uix].Owner].Color 4142 end; 4143 cm := $808080 or cm shr 1; { increase brightness } 4144 end 4145 else if MapOptionChecked and (1 shl moPolitical) <> 0 then 4146 begin 4147 if MyMap[Loc] and fTerrain < fGrass then 4148 cm := cmPolOcean 4149 else if MyRO.Territory[Loc] < 0 then 4150 cm := cmPolNone 4151 else 4152 cm := Tribe[MyRO.Territory[Loc]].Color; 4138 cm := Tribe[MyRO.EnemyUn[uix].Owner].Color 4153 4139 end; 4154 MiniLine[xm, 0] := cm shr 16; 4155 MiniLine[xm, 1] := cm shr 8 and $FF; 4156 MiniLine[xm, 2] := cm and $FF; 4140 cm := $808080 or cm shr 1; { increase brightness } 4141 end 4142 else if MapOptionChecked and (1 shl moPolitical) <> 0 then 4143 begin 4144 if MyMap[Loc] and fTerrain < fGrass then 4145 cm := cmPolOcean 4146 else if MyRO.Territory[Loc] < 0 then 4147 cm := cmPolNone 4148 else 4149 cm := Tribe[MyRO.Territory[Loc]].Color; 4157 4150 end; 4151 MiniLine[xm, 0] := cm shr 16; 4152 MiniLine[xm, 1] := cm shr 8 and $FF; 4153 MiniLine[xm, 2] := cm and $FF; 4158 4154 end; 4155 end; 4156 end; 4157 Mini.EndUpdate; 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 4159 4174 end; 4160 Mini.EndUpdate; 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; 4161 4186 end; 4162 4187 4163 procedure TMainScreen.MainOffscreenPaint; 4164 var 4165 ProcessOptions: integer; 4166 rec: TRect; 4167 DoInvalidate: boolean; 4168 begin 4169 if me < 0 then 4170 with offscreen.Canvas do 4171 begin 4172 Brush.Color := $000000; 4173 FillRect(Rect(0, 0, MapWidth, MapHeight)); 4174 Brush.Style := bsClear; 4175 OffscreenUser := self; 4176 exit 4177 end; 4178 4179 MainMap.SetPaintBounds(0, 0, MapWidth, MapHeight); 4180 if OffscreenUser <> self then 4181 begin 4182 if OffscreenUser <> nil then 4183 OffscreenUser.Update; 4184 // complete working with old owner to prevent rebound 4185 if MapValid and (xwd = xw) and (ywd = yw) then 4186 MainMap.SetPaintBounds(0, 0, UsedOffscreenWidth, UsedOffscreenHeight); 4187 MapValid := false; 4188 OffscreenUser := self; 4189 end; 4190 4191 if xw - xwd > G.lx div 2 then 4192 xwd := xwd + G.lx 4193 else if xwd - xw > G.lx div 2 then 4194 xwd := xwd - G.lx; 4195 if not MapValid or (xw - xwd > MapWidth div (xxt * 2)) or 4196 (xwd - xw > MapWidth div (xxt * 2)) or (yw - ywd > MapHeight div yyt) or 4197 (ywd - yw > MapHeight div yyt) then 4198 begin 4199 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 4200 ProcessRect(xw, yw, MapWidth div xxt, MapHeight div yyt, 4201 prPaint or prInvalidate) 4202 end 4203 else 4204 begin 4205 if (xwd = xw) and (ywd = yw) then 4206 exit; { map window not moved } 4207 offscreen.Canvas.Font.Assign(UniFont[ftSmall]); 4208 rec := Rect(0, 0, MapWidth, MapHeight); 4209 {$IFDEF WINDOWS}{TODO Linux} 4210 ScrollDC(offscreen.Canvas.Handle, (xwd - xw) * (xxt * 2), 4211 (ywd - yw) * yyt, rec, rec, 0, nil); 4212 {$ENDIF} 4213 for DoInvalidate := false to FastScrolling do 4214 begin 4215 if DoInvalidate then 4216 begin 4217 rec.Bottom := MapHeight - overlap; 4218 {$IFDEF WINDOWS}{TODO Linux} 4219 ScrollDC(Canvas.Handle, (xwd - xw) * (xxt * 2), (ywd - yw) * yyt, rec, 4220 rec, 0, nil); 4221 {$ENDIF} 4222 ProcessOptions := prInvalidate; 4223 end 4224 else 4225 ProcessOptions := prPaint or prAutoBounds; 4226 if yw < ywd then 4227 begin 4228 ProcessRect(xw, yw, MapWidth div xxt, ywd - yw - 1, ProcessOptions); 4229 if xw < xwd then 4230 ProcessRect(xw, ywd, (xwd - xw) * 2 - 1, MapHeight div yyt - ywd + 4231 yw, ProcessOptions) 4232 else if xw > xwd then 4233 ProcessRect((xwd + MapWidth div (xxt * 2)) mod G.lx, ywd, 4234 (xw - xwd) * 2 + 1, MapHeight div yyt - ywd + yw, ProcessOptions) 4235 end 4236 else if yw > ywd then 4237 begin 4238 if DoInvalidate then 4239 RectInvalidate(MapOffset, TopBarHeight + MapHeight - overlap - 4240 (yw - ywd) * yyt, MapOffset + MapWidth, TopBarHeight + MapHeight 4241 - overlap) 4242 else 4243 ProcessRect(xw, (ywd + MapHeight div (yyt * 2) * 2), 4244 MapWidth div xxt, yw - ywd + 1, ProcessOptions); 4245 if xw < xwd then 4246 ProcessRect(xw, yw, (xwd - xw) * 2 - 1, MapHeight div yyt - yw + ywd 4247 - 2, ProcessOptions) 4248 else if xw > xwd then 4249 ProcessRect((xwd + MapWidth div (xxt * 2)) mod G.lx, yw, 4250 (xw - xwd) * 2 + 1, MapHeight div yyt - yw + ywd - 2, 4251 ProcessOptions) 4252 end 4253 else if xw < xwd then 4254 ProcessRect(xw, yw, (xwd - xw) * 2 - 1, MapHeight div yyt, 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 {$IFDEF WINDOWS}{ TODO Linux } 4207 ScrollDC(offscreen.Canvas.Handle, (xwd - xw) * (xxt * 2), (ywd - yw) * yyt, 4208 rec, rec, 0, nil); 4209 {$ENDIF} 4210 for DoInvalidate := false to FastScrolling do 4211 begin 4212 if DoInvalidate then 4213 begin 4214 rec.Bottom := MapHeight - overlap; 4215 {$IFDEF WINDOWS}{ TODO Linux } 4216 ScrollDC(Canvas.Handle, (xwd - xw) * (xxt * 2), (ywd - yw) * yyt, rec, 4217 rec, 0, nil); 4218 {$ENDIF} 4219 ProcessOptions := prInvalidate; 4220 end 4221 else 4222 ProcessOptions := prPaint or prAutoBounds; 4223 if yw < ywd then 4224 begin 4225 ProcessRect(xw, yw, MapWidth div xxt, ywd - yw - 1, ProcessOptions); 4226 if xw < xwd then 4227 ProcessRect(xw, ywd, (xwd - xw) * 2 - 1, MapHeight div yyt - ywd + yw, 4255 4228 ProcessOptions) 4256 4229 else if xw > xwd then 4230 ProcessRect((xwd + MapWidth div (xxt * 2)) mod G.lx, ywd, 4231 (xw - xwd) * 2 + 1, MapHeight div yyt - ywd + yw, ProcessOptions) 4232 end 4233 else if yw > ywd then 4234 begin 4235 if DoInvalidate then 4236 RectInvalidate(MapOffset, TopBarHeight + MapHeight - overlap - 4237 (yw - ywd) * yyt, MapOffset + MapWidth, TopBarHeight + MapHeight 4238 - overlap) 4239 else 4240 ProcessRect(xw, (ywd + MapHeight div (yyt * 2) * 2), MapWidth div xxt, 4241 yw - ywd + 1, ProcessOptions); 4242 if xw < xwd then 4243 ProcessRect(xw, yw, (xwd - xw) * 2 - 1, MapHeight div yyt - yw + ywd - 4244 2, ProcessOptions) 4245 else if xw > xwd then 4257 4246 ProcessRect((xwd + MapWidth div (xxt * 2)) mod G.lx, yw, 4258 (xw - xwd) * 2 + 1, MapHeight div yyt, ProcessOptions); 4259 end; 4260 if not FastScrolling then 4261 RectInvalidate(MapOffset, TopBarHeight, MapOffset + MapWidth, 4262 TopBarHeight + MapHeight - overlap); 4263 RectInvalidate(xMidPanel, TopBarHeight + MapHeight - overlap, xRightPanel, 4264 TopBarHeight + MapHeight) 4247 (xw - xwd) * 2 + 1, MapHeight div yyt - yw + ywd - 2, 4248 ProcessOptions) 4249 end 4250 else if xw < xwd then 4251 ProcessRect(xw, yw, (xwd - xw) * 2 - 1, MapHeight div yyt, 4252 ProcessOptions) 4253 else if xw > xwd then 4254 ProcessRect((xwd + MapWidth div (xxt * 2)) mod G.lx, yw, 4255 (xw - xwd) * 2 + 1, MapHeight div yyt, ProcessOptions); 4265 4256 end; 4266 // if (xwd<>xw) or (ywd<>yw)then4267 // Server(sChangeSuperView,me,yw*G.lx+xw,nil^); // for synchronizing client side viewer, not used currently4268 xwd := xw;4269 ywd := yw;4270 MapValid := true;4257 if not FastScrolling then 4258 RectInvalidate(MapOffset, TopBarHeight, MapOffset + MapWidth, 4259 TopBarHeight + MapHeight - overlap); 4260 RectInvalidate(xMidPanel, TopBarHeight + MapHeight - overlap, xRightPanel, 4261 TopBarHeight + MapHeight) 4271 4262 end; 4272 4273 procedure TMainScreen.PaintAll; 4274 begin 4275 MainOffscreenPaint; 4276 xwMini := xw; 4277 ywMini := yw; 4278 MiniPaint; 4279 PanelPaint; 4263 // if (xwd<>xw) or (ywd<>yw) then 4264 // Server(sChangeSuperView,me,yw*G.lx+xw,nil^); // for synchronizing client side viewer, not used currently 4265 xwd := xw; 4266 ywd := yw; 4267 MapValid := true; 4268 end; 4269 4270 procedure TMainScreen.PaintAll; 4271 begin 4272 MainOffscreenPaint; 4273 xwMini := xw; 4274 ywMini := yw; 4275 MiniPaint; 4276 PanelPaint; 4277 end; 4278 4279 procedure TMainScreen.PaintAllMaps; 4280 begin 4281 MainOffscreenPaint; 4282 xwMini := xw; 4283 ywMini := yw; 4284 MiniPaint; 4285 CopyMiniToPanel; 4286 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini + 2, 4287 xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini + 4288 2 + G.ly); 4289 end; 4290 4291 procedure TMainScreen.CopyMiniToPanel; 4292 begin 4293 BitBlt(Panel.Canvas.Handle, xMini + 2, yMini + 2, G.lx * 2, G.ly, 4294 Mini.Canvas.Handle, 0, 0, SRCCOPY); 4295 if MarkCityLoc >= 0 then 4296 Sprite(Panel, HGrSystem, xMini - 2 + (4 * G.lx + 2 * (MarkCityLoc mod G.lx) 4297 + (G.lx - MapWidth div (xxt * 2)) - 2 * xwd) mod (2 * G.lx) + 4298 MarkCityLoc div G.lx and 1, yMini - 3 + MarkCityLoc div G.lx, 10, 4299 10, 77, 47) 4300 else if ywmax <= 0 then 4301 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (xxt * 2), yMini + 2, 4302 xMini + 1 + G.lx + MapWidth div (xxt * 2), yMini + 2 + G.ly - 1, 4303 MainTexture.clMark, MainTexture.clMark) 4304 else 4305 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (xxt * 2), 4306 yMini + 2 + yw, xMini + 1 + G.lx + MapWidth div (xxt * 2), 4307 yMini + yw + MapHeight div yyt, MainTexture.clMark, MainTexture.clMark); 4308 end; 4309 4310 procedure TMainScreen.PanelPaint; 4311 4312 function MovementToString(var Un: TUn): string; 4313 begin 4314 result := ScreenTools.MovementToString(Un.Movement); 4315 if Un.Master >= 0 then 4316 result := '(' + result + ')' 4317 else if (MyModel[Un.mix].Domain = dAir) and 4318 (MyModel[Un.mix].Kind <> mkSpecial_Glider) then 4319 result := Format('%s(%d)', [result, Un.Fuel]); 4280 4320 end; 4281 4321 4282 procedure TMainScreen.PaintAllMaps; 4283 begin 4284 MainOffscreenPaint; 4285 xwMini := xw; 4286 ywMini := yw; 4287 MiniPaint; 4322 var 4323 i, uix, uixDefender, x, xSrc, ySrc, xSrcBase, ySrcBase, CostFactor, Count, 4324 mixShow, xTreasurySection, xResearchSection, JobFocus, TrueMoney, 4325 TrueResearch: integer; 4326 Tile: Cardinal; 4327 s: string; 4328 unx: TUn; 4329 UnitInfo: TUnitInfo; 4330 JobProgressData: TJobProgressData; 4331 Prio: boolean; 4332 begin 4333 with Panel.Canvas do 4334 begin 4335 Fill(Panel.Canvas, 0, 3, xMidPanel + 7 - 10, PanelHeight - 3, 4336 wMainTexture - (xMidPanel + 7 - 10), hMainTexture - PanelHeight); 4337 Fill(Panel.Canvas, xRightPanel + 10 - 7, 3, Panel.width - xRightPanel - 10 + 4338 7, PanelHeight - 3, -(xRightPanel + 10 - 7), hMainTexture - PanelHeight); 4339 FillLarge(Panel.Canvas, xMidPanel - 2, PanelHeight - MidPanelHeight, 4340 xRightPanel + 2, PanelHeight, ClientWidth div 2); 4341 4342 Brush.Style := bsClear; 4343 Pen.Color := $000000; 4344 MoveTo(0, 0); 4345 LineTo(xMidPanel + 7 - 8, 0); 4346 LineTo(xMidPanel + 7 - 8, PanelHeight - MidPanelHeight); 4347 LineTo(xRightPanel, PanelHeight - MidPanelHeight); 4348 LineTo(xRightPanel, 0); 4349 LineTo(ClientWidth, 0); 4350 Pen.Color := MainTexture.clBevelLight; 4351 MoveTo(xMidPanel + 7 - 9, PanelHeight - MidPanelHeight + 2); 4352 LineTo(xRightPanel + 10 - 8, PanelHeight - MidPanelHeight + 2); 4353 Pen.Color := MainTexture.clBevelLight; 4354 MoveTo(0, 1); 4355 LineTo(xMidPanel + 7 - 9, 1); 4356 Pen.Color := MainTexture.clBevelShade; 4357 LineTo(xMidPanel + 7 - 9, PanelHeight - MidPanelHeight + 1); 4358 Pen.Color := MainTexture.clBevelLight; 4359 LineTo(xRightPanel + 10 - 9, PanelHeight - MidPanelHeight + 1); 4360 Pen.Color := MainTexture.clBevelLight; 4361 LineTo(xRightPanel + 10 - 9, 1); 4362 LineTo(ClientWidth, 1); 4363 MoveTo(ClientWidth, 2); 4364 LineTo(xRightPanel + 10 - 8, 2); 4365 LineTo(xRightPanel + 10 - 8, PanelHeight); 4366 MoveTo(0, 2); 4367 LineTo(xMidPanel + 7 - 10, 2); 4368 Pen.Color := MainTexture.clBevelShade; 4369 LineTo(xMidPanel + 7 - 10, PanelHeight); 4370 Corner(Panel.Canvas, xMidPanel + 7 - 16, 1, 1, MainTexture); 4371 Corner(Panel.Canvas, xRightPanel + 10 - 9, 1, 0, MainTexture); 4372 if ClientMode <> cEditMap then 4373 begin 4374 if supervising then 4375 begin 4376 ScreenTools.Frame(Panel.Canvas, ClientWidth - xPalace - 1, yPalace - 1, 4377 ClientWidth - xPalace + xSizeBig, yPalace + ySizeBig, 4378 $B0B0B0, $FFFFFF); 4379 RFrame(Panel.Canvas, ClientWidth - xPalace - 2, yPalace - 2, 4380 ClientWidth - xPalace + xSizeBig + 1, yPalace + ySizeBig + 1, 4381 $FFFFFF, $B0B0B0); 4382 BitBlt(Panel.Canvas.Handle, ClientWidth - xPalace, yPalace, xSizeBig, 4383 ySizeBig, GrExt[HGrSystem2].Data.Canvas.Handle, 70, 123, SRCCOPY); 4384 end 4385 else if MyRO.NatBuilt[imPalace] > 0 then 4386 ImpImage(Panel.Canvas, ClientWidth - xPalace, yPalace, imPalace, -1, 4387 GameMode <> cMovie 4388 { (GameMode<>cMovie) and (MyRO.Government<>gAnarchy) } ) 4389 else 4390 ImpImage(Panel.Canvas, ClientWidth - xPalace, yPalace, 21, -1, 4391 GameMode <> cMovie 4392 { (GameMode<>cMovie) and (MyRO.Government<>gAnarchy) } ); 4393 end; 4394 4395 if GameMode = cMovie then 4396 ScreenTools.Frame(Panel.Canvas, xMini + 1, yMini + 1, 4397 xMini + 2 + G.lx * 2, yMini + 2 + G.ly, $000000, $000000) 4398 else 4399 begin 4400 ScreenTools.Frame(Panel.Canvas, xMini + 1, yMini + 1, 4401 xMini + 2 + G.lx * 2, yMini + 2 + G.ly, $B0B0B0, $FFFFFF); 4402 RFrame(Panel.Canvas, xMini, yMini, xMini + 3 + G.lx * 2, yMini + 3 + G.ly, 4403 $FFFFFF, $B0B0B0); 4404 end; 4288 4405 CopyMiniToPanel; 4289 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini + 2, 4290 xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini + 4291 2 + G.ly); 4292 end; 4293 4294 procedure TMainScreen.CopyMiniToPanel; 4295 begin 4296 BitBlt(Panel.Canvas.Handle, xMini + 2, yMini + 2, G.lx * 2, G.ly, 4297 Mini.Canvas.Handle, 0, 0, SRCCOPY); 4298 if MarkCityLoc >= 0 then 4299 Sprite(Panel, HGrSystem, 4300 xMini - 2 + (4 * G.lx + 2 * (MarkCityLoc mod G.lx) + 4301 (G.lx - MapWidth div (xxt * 2)) - 2 * xwd) mod (2 * G.lx) + 4302 MarkCityLoc div G.lx and 1, yMini - 3 + MarkCityLoc div G.lx, 10, 4303 10, 77, 47) 4304 else if ywmax <= 0 then 4305 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (xxt * 2), yMini + 2, 4306 xMini + 1 + G.lx + MapWidth div (xxt * 2), yMini + 2 + G.ly - 1, 4307 MainTexture.clMark, MainTexture.clMark) 4308 else 4309 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (xxt * 2), 4310 yMini + 2 + yw, xMini + 1 + G.lx + MapWidth div (xxt * 2), 4311 yMini + yw + MapHeight div yyt, MainTexture.clMark, MainTexture.clMark); 4312 end; 4313 4314 procedure TMainScreen.PanelPaint; 4315 4316 function MovementToString(var Un: TUn): string; 4317 begin 4318 result := ScreenTools.MovementToString(Un.Movement); 4319 if Un.Master >= 0 then 4320 result := '(' + result + ')' 4321 else if (MyModel[Un.mix].Domain = dAir) and 4322 (MyModel[Un.mix].Kind <> mkSpecial_Glider) then 4323 result := Format('%s(%d)', [result, Un.Fuel]); 4324 end; 4325 4326 var 4327 i, uix, uixDefender, x, xSrc, ySrc, xSrcBase, ySrcBase, CostFactor, Count, 4328 mixShow, xTreasurySection, xResearchSection, JobFocus, TrueMoney, 4329 TrueResearch: integer; 4330 Tile: Cardinal; 4331 s: string; 4332 unx: TUn; 4333 UnitInfo: TUnitInfo; 4334 JobProgressData: TJobProgressData; 4335 Prio: boolean; 4336 begin 4337 with Panel.Canvas do 4338 begin 4339 Fill(Panel.Canvas, 0, 3, xMidPanel + 7 - 10, PanelHeight - 3, 4340 wMainTexture - (xMidPanel + 7 - 10), hMainTexture - PanelHeight); 4341 Fill(Panel.Canvas, xRightPanel + 10 - 7, 3, Panel.width - xRightPanel - 10 4342 + 7, PanelHeight - 3, -(xRightPanel + 10 - 7), 4343 hMainTexture - PanelHeight); 4344 FillLarge(Panel.Canvas, xMidPanel - 2, PanelHeight - MidPanelHeight, 4345 xRightPanel + 2, PanelHeight, ClientWidth div 2); 4346 4406 if ClientMode <> cEditMap then // MapBtn icons 4407 for i := 0 to 5 do 4408 if i <> 3 then 4409 Dump(Panel, HGrSystem, xMini + G.lx - 42 + 16 * i, PanelHeight - 26, 4410 8, 8, 121 + i * 9, 61); 4411 4412 if ClientMode = cEditMap then 4413 begin 4414 for i := 0 to TrRow - 1 do 4415 trix[i] := -1; 4416 Count := 0; 4417 for i := 0 to nBrushTypes - 1 do 4418 begin // display terrain types 4419 if (Count >= TrRow * sb.si.npos) and (Count < TrRow * (sb.si.npos + 1)) 4420 then 4421 begin 4422 trix[Count - TrRow * sb.si.npos] := BrushTypes[i]; 4423 x := (Count - TrRow * sb.si.npos) * TrPitch; 4424 xSrcBase := -1; 4425 case BrushTypes[i] of 4426 0 .. 8: 4427 begin 4428 xSrc := BrushTypes[i]; 4429 ySrc := 0 4430 end; 4431 9 .. 30: 4432 begin 4433 xSrcBase := 2; 4434 ySrcBase := 2; 4435 xSrc := 0; 4436 ySrc := 2 * integer(BrushTypes[i]) - 15 4437 end; 4438 fRiver: 4439 begin 4440 xSrc := 7; 4441 ySrc := 14 4442 end; 4443 fRoad: 4444 begin 4445 xSrc := 0; 4446 ySrc := 9 4447 end; 4448 fRR: 4449 begin 4450 xSrc := 0; 4451 ySrc := 10 4452 end; 4453 fCanal: 4454 begin 4455 xSrc := 0; 4456 ySrc := 11 4457 end; 4458 fPoll: 4459 begin 4460 xSrc := 6; 4461 ySrc := 12 4462 end; 4463 fDeadLands, fDeadLands or fCobalt, fDeadLands or fUranium, 4464 fDeadLands or fMercury: 4465 begin 4466 xSrcBase := 6; 4467 ySrcBase := 2; 4468 xSrc := 8; 4469 ySrc := 12 + BrushTypes[i] shr 25; 4470 end; 4471 tiIrrigation, tiFarm, tiMine, tiBase: 4472 begin 4473 xSrc := BrushTypes[i] shr 12 - 1; 4474 ySrc := 12 4475 end; 4476 tiFort: 4477 begin 4478 xSrc := 3; 4479 ySrc := 12; 4480 xSrcBase := 7; 4481 ySrcBase := 12 4482 end; 4483 fPrefStartPos: 4484 begin 4485 xSrc := 0; 4486 ySrc := 1 4487 end; 4488 fStartPos: 4489 begin 4490 xSrc := 0; 4491 ySrc := 2 4492 end; 4493 end; 4494 if xSrcBase >= 0 then 4495 Sprite(Panel, HGrTerrain, xTroop + 2 + x, yTroop + 9 - yyt, xxt * 2, 4496 yyt * 3, 1 + xSrcBase * (xxt * 2 + 1), 4497 1 + ySrcBase * (yyt * 3 + 1)); 4498 Sprite(Panel, HGrTerrain, xTroop + 2 + x, yTroop + 9 - yyt, xxt * 2, 4499 yyt * 3, 1 + xSrc * (xxt * 2 + 1), 1 + ySrc * (yyt * 3 + 1)); 4500 if BrushTypes[i] = BrushType then 4501 begin 4502 ScreenTools.Frame(Panel.Canvas, xTroop + 2 + x, 4503 yTroop + 7 - yyt div 2, xTroop + 2 * xxt + x, 4504 yTroop + 2 * yyt + 11, $000000, $000000); 4505 ScreenTools.Frame(Panel.Canvas, xTroop + 1 + x, 4506 yTroop + 6 - yyt div 2, xTroop + 2 * xxt - 1 + x, 4507 yTroop + 2 * yyt + 10, MainTexture.clMark, MainTexture.clMark); 4508 end 4509 end; 4510 inc(Count) 4511 end; 4512 case BrushType of 4513 fDesert, fPrairie, fTundra, fArctic, fSwamp, fHills, fMountains: 4514 s := Phrases.Lookup('TERRAIN', BrushType); 4515 fShore: 4516 s := Format(Phrases.Lookup('TWOTERRAINS'), 4517 [Phrases.Lookup('TERRAIN', fOcean), Phrases.Lookup('TERRAIN', 4518 fShore)]); 4519 fGrass: 4520 s := Format(Phrases.Lookup('TWOTERRAINS'), 4521 [Phrases.Lookup('TERRAIN', fGrass), Phrases.Lookup('TERRAIN', 4522 fGrass + 12)]); 4523 fForest: 4524 s := Format(Phrases.Lookup('TWOTERRAINS'), 4525 [Phrases.Lookup('TERRAIN', fForest), Phrases.Lookup('TERRAIN', 4526 fJungle)]); 4527 fRiver: 4528 s := Phrases.Lookup('RIVER'); 4529 fDeadLands, fDeadLands or fCobalt, fDeadLands or fUranium, 4530 fDeadLands or fMercury: 4531 s := Phrases.Lookup('TERRAIN', 3 * 12 + BrushType shr 25); 4532 fPrefStartPos: 4533 s := Phrases.Lookup('MAP_PREFSTART'); 4534 fStartPos: 4535 s := Phrases.Lookup('MAP_START'); 4536 fPoll: 4537 s := Phrases.Lookup('POLL'); 4538 else // terrain improvements 4539 begin 4540 case BrushType of 4541 fRoad: 4542 i := 1; 4543 fRR: 4544 i := 2; 4545 tiIrrigation: 4546 i := 4; 4547 tiFarm: 4548 i := 5; 4549 tiMine: 4550 i := 7; 4551 fCanal: 4552 i := 8; 4553 tiFort: 4554 i := 10; 4555 tiBase: 4556 i := 12; 4557 end; 4558 s := Phrases.Lookup('JOBRESULT', i); 4559 end 4560 end; 4561 LoweredTextOut(Panel.Canvas, -1, MainTexture, xTroop + 1, 4562 PanelHeight - 19, s); 4563 end 4564 else if TroopLoc >= 0 then 4565 begin 4347 4566 Brush.Style := bsClear; 4348 Pen.Color := $000000; 4349 MoveTo(0, 0); 4350 LineTo(xMidPanel + 7 - 8, 0); 4351 LineTo(xMidPanel + 7 - 8, PanelHeight - MidPanelHeight); 4352 LineTo(xRightPanel, PanelHeight - MidPanelHeight); 4353 LineTo(xRightPanel, 0); 4354 LineTo(ClientWidth, 0); 4355 Pen.Color := MainTexture.clBevelLight; 4356 MoveTo(xMidPanel + 7 - 9, PanelHeight - MidPanelHeight + 2); 4357 LineTo(xRightPanel + 10 - 8, PanelHeight - MidPanelHeight + 2); 4358 Pen.Color := MainTexture.clBevelLight; 4359 MoveTo(0, 1); 4360 LineTo(xMidPanel + 7 - 9, 1); 4361 Pen.Color := MainTexture.clBevelShade; 4362 LineTo(xMidPanel + 7 - 9, PanelHeight - MidPanelHeight + 1); 4363 Pen.Color := MainTexture.clBevelLight; 4364 LineTo(xRightPanel + 10 - 9, PanelHeight - MidPanelHeight + 1); 4365 Pen.Color := MainTexture.clBevelLight; 4366 LineTo(xRightPanel + 10 - 9, 1); 4367 LineTo(ClientWidth, 1); 4368 MoveTo(ClientWidth, 2); 4369 LineTo(xRightPanel + 10 - 8, 2); 4370 LineTo(xRightPanel + 10 - 8, PanelHeight); 4371 MoveTo(0, 2); 4372 LineTo(xMidPanel + 7 - 10, 2); 4373 Pen.Color := MainTexture.clBevelShade; 4374 LineTo(xMidPanel + 7 - 10, PanelHeight); 4375 Corner(Panel.Canvas, xMidPanel + 7 - 16, 1, 1, MainTexture); 4376 Corner(Panel.Canvas, xRightPanel + 10 - 9, 1, 0, MainTexture); 4377 if ClientMode <> cEditMap then 4378 begin 4379 if supervising then 4567 if UnFocus >= 0 then 4568 with MyUn[UnFocus], MyModel[mix] do 4569 begin { display info about selected unit } 4570 if Job = jCity then 4571 mixShow := -1 // building site 4572 else 4573 mixShow := mix; 4574 with Tribe[me].ModelPicture[mixShow] do 4575 begin 4576 Sprite(Panel, HGr, xMidPanel + 7 + 12, yTroop + 1, 64, 48, 4577 pix mod 10 * 65 + 1, pix div 10 * 49 + 1); 4578 if MyUn[UnFocus].Flags and unFortified <> 0 then 4579 Sprite(Panel, HGrStdUnits, xMidPanel + 7 + 12, yTroop + 1, 4580 xxu * 2, yyu * 2, 1 + 6 * (xxu * 2 + 1), 1); 4581 end; 4582 4583 MakeBlue(Panel, xMidPanel + 7 + 12 + 10, yTroop - 13, 44, 12); 4584 s := MovementToString(MyUn[UnFocus]); 4585 RisedTextOut(Panel.Canvas, xMidPanel + 7 + 12 + 32 - 4586 BiColorTextWidth(Panel.Canvas, s) div 2, yTroop - 16, s); 4587 4588 s := IntToStr(Health) + '%'; 4589 LightGradient(Panel.Canvas, xMidPanel + 7 + 12 + 7, PanelHeight - 22, 4590 (Health + 1) div 2, (ColorOfHealth(Health) and $FEFEFE shr 2) * 3); 4591 if Health < 100 then 4592 LightGradient(Panel.Canvas, xMidPanel + 7 + 12 + 7 + (Health + 1) 4593 div 2, PanelHeight - 22, 50 - (Health + 1) div 2, $000000); 4594 RisedTextOut(Panel.Canvas, xMidPanel + 7 + 12 + 32 - 4595 BiColorTextWidth(Panel.Canvas, s) div 2, PanelHeight - 23, s); 4596 4597 FrameImage(Panel.Canvas, GrExt[HGrSystem].Data, 4598 xMidPanel + 7 + xUnitText, yTroop + 15, 12, 14, 4599 121 + Exp div ExpCost * 13, 28); 4600 if Job = jCity then 4601 s := Tribe[me].ModelName[-1] 4602 else 4603 s := Tribe[me].ModelName[mix]; 4604 if Home >= 0 then 4605 begin 4606 LoweredTextOut(Panel.Canvas, -1, MainTexture, 4607 xMidPanel + 7 + xUnitText + 18, yTroop + 5, s); 4608 LoweredTextOut(Panel.Canvas, -1, MainTexture, 4609 xMidPanel + 7 + xUnitText + 18, yTroop + 21, 4610 '(' + CityName(MyCity[Home].ID) + ')'); 4611 end 4612 else 4613 LoweredTextOut(Panel.Canvas, -1, MainTexture, 4614 xMidPanel + 7 + xUnitText + 18, yTroop + 13, s); 4615 end; 4616 4617 if (UnFocus >= 0) and (MyUn[UnFocus].Loc <> TroopLoc) then 4618 begin // divide panel 4619 if SmallScreen and not supervising then 4620 x := xTroop - 8 4621 else 4622 x := xTroop - 152; 4623 Pen.Color := MainTexture.clBevelShade; 4624 MoveTo(x - 1, PanelHeight - MidPanelHeight + 2); 4625 LineTo(x - 1, PanelHeight); 4626 Pen.Color := MainTexture.clBevelLight; 4627 MoveTo(x, PanelHeight - MidPanelHeight + 2); 4628 LineTo(x, PanelHeight); 4629 end; 4630 4631 for i := 0 to 23 do 4632 trix[i] := -1; 4633 if MyMap[TroopLoc] and fUnit <> 0 then 4634 begin 4635 if MyMap[TroopLoc] and fOwned <> 0 then 4380 4636 begin 4381 ScreenTools.Frame(Panel.Canvas, ClientWidth - xPalace - 1, yPalace - 1, 4382 ClientWidth - xPalace + xSizeBig, yPalace + ySizeBig, 4383 $B0B0B0, $FFFFFF); 4384 RFrame(Panel.Canvas, ClientWidth - xPalace - 2, yPalace - 2, 4385 ClientWidth - xPalace + xSizeBig + 1, yPalace + ySizeBig + 1, 4386 $FFFFFF, $B0B0B0); 4387 BitBlt(Panel.Canvas.Handle, ClientWidth - xPalace, yPalace, xSizeBig, 4388 ySizeBig, GrExt[HGrSystem2].Data.Canvas.Handle, 70, 123, SRCCOPY); 4389 end 4390 else if MyRO.NatBuilt[imPalace] > 0 then 4391 ImpImage(Panel.Canvas, ClientWidth - xPalace, yPalace, imPalace, -1, 4392 GameMode <> cMovie 4393 { (GameMode<>cMovie) and (MyRO.Government<>gAnarchy) } ) 4394 else 4395 ImpImage(Panel.Canvas, ClientWidth - xPalace, yPalace, 21, -1, 4396 GameMode <> cMovie 4397 { (GameMode<>cMovie) and (MyRO.Government<>gAnarchy) } ); 4398 end; 4399 4400 if GameMode = cMovie then 4401 ScreenTools.Frame(Panel.Canvas, xMini + 1, yMini + 1, xMini + 2 + G.lx * 2, 4402 yMini + 2 + G.ly, $000000, $000000) 4403 else 4404 begin 4405 ScreenTools.Frame(Panel.Canvas, xMini + 1, yMini + 1, xMini + 2 + G.lx * 2, 4406 yMini + 2 + G.ly, $B0B0B0, $FFFFFF); 4407 RFrame(Panel.Canvas, xMini, yMini, xMini + 3 + G.lx * 2, 4408 yMini + 3 + G.ly, $FFFFFF, $B0B0B0); 4409 end; 4410 CopyMiniToPanel; 4411 if ClientMode <> cEditMap then // MapBtn icons 4412 for i := 0 to 5 do 4413 if i <> 3 then 4414 Dump(Panel, HGrSystem, xMini + G.lx - 42 + 16 * i, PanelHeight - 26, 4415 8, 8, 121 + i * 9, 61); 4416 4417 if ClientMode = cEditMap then 4418 begin 4419 for i := 0 to TrRow - 1 do 4420 trix[i] := -1; 4421 Count := 0; 4422 for i := 0 to nBrushTypes - 1 do 4423 begin // display terrain types 4424 if (Count >= TrRow * sb.si.npos) and (Count < TrRow * (sb.si.npos + 1)) 4637 if (TrCnt > 1) or (UnFocus < 0) or (MyUn[UnFocus].Loc <> TroopLoc) 4425 4638 then 4426 4639 begin 4427 trix[Count - TrRow * sb.si.npos] := BrushTypes[i]; 4428 x := (Count - TrRow * sb.si.npos) * TrPitch; 4429 xSrcBase := -1; 4430 case BrushTypes[i] of 4431 0 .. 8: 4432 begin 4433 xSrc := BrushTypes[i]; 4434 ySrc := 0 4435 end; 4436 9 .. 30: 4437 begin 4438 xSrcBase := 2; 4439 ySrcBase := 2; 4440 xSrc := 0; 4441 ySrc := 2 * integer(BrushTypes[i]) - 15 4442 end; 4443 fRiver: 4444 begin 4445 xSrc := 7; 4446 ySrc := 14 4447 end; 4448 fRoad: 4449 begin 4450 xSrc := 0; 4451 ySrc := 9 4452 end; 4453 fRR: 4454 begin 4455 xSrc := 0; 4456 ySrc := 10 4457 end; 4458 fCanal: 4459 begin 4460 xSrc := 0; 4461 ySrc := 11 4462 end; 4463 fPoll: 4464 begin 4465 xSrc := 6; 4466 ySrc := 12 4467 end; 4468 fDeadLands, fDeadLands or fCobalt, fDeadLands or fUranium, 4469 fDeadLands or fMercury: 4470 begin 4471 xSrcBase := 6; 4472 ySrcBase := 2; 4473 xSrc := 8; 4474 ySrc := 12 + BrushTypes[i] shr 25; 4475 end; 4476 tiIrrigation, tiFarm, tiMine, tiBase: 4477 begin 4478 xSrc := BrushTypes[i] shr 12 - 1; 4479 ySrc := 12 4480 end; 4481 tiFort: 4482 begin 4483 xSrc := 3; 4484 ySrc := 12; 4485 xSrcBase := 7; 4486 ySrcBase := 12 4487 end; 4488 fPrefStartPos: 4489 begin 4490 xSrc := 0; 4491 ySrc := 1 4492 end; 4493 fStartPos: 4494 begin 4495 xSrc := 0; 4496 ySrc := 2 4497 end; 4498 end; 4499 if xSrcBase >= 0 then 4500 Sprite(Panel, HGrTerrain, xTroop + 2 + x, yTroop + 9 - yyt, 4501 xxt * 2, yyt * 3, 1 + xSrcBase * (xxt * 2 + 1), 4502 1 + ySrcBase * (yyt * 3 + 1)); 4503 Sprite(Panel, HGrTerrain, xTroop + 2 + x, yTroop + 9 - yyt, xxt * 2, 4504 yyt * 3, 1 + xSrc * (xxt * 2 + 1), 1 + ySrc * (yyt * 3 + 1)); 4505 if BrushTypes[i] = BrushType then 4506 begin 4507 ScreenTools.Frame(Panel.Canvas, xTroop + 2 + x, yTroop + 7 - yyt div 2, 4508 xTroop + 2 * xxt + x, yTroop + 2 * yyt + 11, $000000, $000000); 4509 ScreenTools.Frame(Panel.Canvas, xTroop + 1 + x, yTroop + 6 - yyt div 2, 4510 xTroop + 2 * xxt - 1 + x, yTroop + 2 * yyt + 10, 4511 MainTexture.clMark, MainTexture.clMark); 4512 end 4513 end; 4514 inc(Count) 4515 end; 4516 case BrushType of 4517 fDesert, fPrairie, fTundra, fArctic, fSwamp, fHills, fMountains: 4518 s := Phrases.Lookup('TERRAIN', BrushType); 4519 fShore: 4520 s := Format(Phrases.Lookup('TWOTERRAINS'), 4521 [Phrases.Lookup('TERRAIN', fOcean), Phrases.Lookup('TERRAIN', 4522 fShore)]); 4523 fGrass: 4524 s := Format(Phrases.Lookup('TWOTERRAINS'), 4525 [Phrases.Lookup('TERRAIN', fGrass), Phrases.Lookup('TERRAIN', 4526 fGrass + 12)]); 4527 fForest: 4528 s := Format(Phrases.Lookup('TWOTERRAINS'), 4529 [Phrases.Lookup('TERRAIN', fForest), Phrases.Lookup('TERRAIN', 4530 fJungle)]); 4531 fRiver: 4532 s := Phrases.Lookup('RIVER'); 4533 fDeadLands, fDeadLands or fCobalt, fDeadLands or fUranium, 4534 fDeadLands or fMercury: 4535 s := Phrases.Lookup('TERRAIN', 3 * 12 + BrushType shr 25); 4536 fPrefStartPos: 4537 s := Phrases.Lookup('MAP_PREFSTART'); 4538 fStartPos: 4539 s := Phrases.Lookup('MAP_START'); 4540 fPoll: 4541 s := Phrases.Lookup('POLL'); 4542 else // terrain improvements 4543 begin 4544 case BrushType of 4545 fRoad: 4546 i := 1; 4547 fRR: 4548 i := 2; 4549 tiIrrigation: 4550 i := 4; 4551 tiFarm: 4552 i := 5; 4553 tiMine: 4554 i := 7; 4555 fCanal: 4556 i := 8; 4557 tiFort: 4558 i := 10; 4559 tiBase: 4560 i := 12; 4561 end; 4562 s := Phrases.Lookup('JOBRESULT', i); 4640 LoweredTextOut(Panel.Canvas, -1, MainTexture, xTroop + 10, 4641 PanelHeight - 24, Phrases.Lookup('PRESENT')); 4642 Server(sGetDefender, me, TroopLoc, uixDefender); 4643 Count := 0; 4644 for Prio := true downto false do 4645 for uix := 0 to MyRO.nUn - 1 do 4646 if (uix = uixDefender) = Prio then 4647 begin // display own units 4648 unx := MyUn[uix]; 4649 if unx.Loc = TroopLoc then 4650 begin 4651 if (Count >= TrRow * sb.si.npos) and 4652 (Count < TrRow * (sb.si.npos + 1)) then 4653 begin 4654 trix[Count - TrRow * sb.si.npos] := uix; 4655 MakeUnitInfo(me, unx, UnitInfo); 4656 x := (Count - TrRow * sb.si.npos) * TrPitch; 4657 if uix = UnFocus then 4658 begin 4659 ScreenTools.Frame(Panel.Canvas, xTroop + 4 + x, 4660 yTroop + 3, xTroop + 64 + x, yTroop + 47, 4661 $000000, $000000); 4662 ScreenTools.Frame(Panel.Canvas, xTroop + 3 + x, 4663 yTroop + 2, xTroop + 63 + x, yTroop + 46, 4664 MainTexture.clMark, MainTexture.clMark); 4665 end 4666 else if (unx.Master >= 0) and (unx.Master = UnFocus) then 4667 begin 4668 CFrame(Panel.Canvas, xTroop + 4 + x, yTroop + 3, 4669 xTroop + 64 + x, yTroop + 47, 8, $000000); 4670 CFrame(Panel.Canvas, xTroop + 3 + x, yTroop + 2, 4671 xTroop + 63 + x, yTroop + 46, 8, MainTexture.clMark); 4672 end; 4673 NoMap.SetOutput(Panel); 4674 NoMap.PaintUnit(xTroop + 2 + x, yTroop + 1, UnitInfo, 4675 unx.Status); 4676 if (ClientMode < scContact) and 4677 ((unx.Job > jNone) or 4678 (unx.Status and (usStay or usRecover or usGoto) <> 0)) 4679 then 4680 Sprite(Panel, HGrSystem, xTroop + 2 + 60 - 20 + x, 4681 yTroop + 35, 20, 20, 81, 25); 4682 4683 if not supervising then 4684 begin 4685 MakeBlue(Panel, xTroop + 2 + 10 + x, 4686 yTroop - 13, 44, 12); 4687 s := MovementToString(unx); 4688 RisedTextOut(Panel.Canvas, 4689 xTroop + x + 34 - BiColorTextWidth(Panel.Canvas, s) 4690 div 2, yTroop - 16, s); 4691 end 4692 end; 4693 inc(Count) 4694 end; 4695 end; // for uix:=0 to MyRO.nUn-1 4696 assert(Count = TrCnt); 4563 4697 end 4564 end;4565 LoweredTextOut(Panel.Canvas, -1, MainTexture, xTroop + 1,4566 PanelHeight - 19, s);4567 end4568 else if TroopLoc >= 0 then4569 begin4570 Brush.Style := bsClear;4571 if UnFocus >= 0 then4572 with MyUn[UnFocus], MyModel[mix] do4573 begin { display info about selected unit }4574 if Job = jCity then4575 mixShow := -1 // building site4576 else4577 mixShow := mix;4578 with Tribe[me].ModelPicture[mixShow] do4579 begin4580 Sprite(Panel, HGr, xMidPanel + 7 + 12, yTroop + 1, 64, 48,4581 pix mod 10 * 65 + 1, pix div 10 * 49 + 1);4582 if MyUn[UnFocus].Flags and unFortified <> 0 then4583 Sprite(Panel, HGrStdUnits, xMidPanel + 7 + 12, yTroop + 1,4584 xxu * 2, yyu * 2, 1 + 6 * (xxu * 2 + 1), 1);4585 end;4586 4587 MakeBlue(Panel, xMidPanel + 7 + 12 + 10, yTroop - 13, 44, 12);4588 s := MovementToString(MyUn[UnFocus]);4589 RisedTextOut(Panel.Canvas, xMidPanel + 7 + 12 + 32 -4590 BiColorTextWidth(Panel.Canvas, s) div 2, yTroop - 16, s);4591 4592 s := IntToStr(Health) + '%';4593 LightGradient(Panel.Canvas, xMidPanel + 7 + 12 + 7,4594 PanelHeight - 22, (Health + 1) div 2,4595 (ColorOfHealth(Health) and $FEFEFE shr 2) * 3);4596 if Health < 100 then4597 LightGradient(Panel.Canvas, xMidPanel + 7 + 12 + 7 + (Health + 1)4598 div 2, PanelHeight - 22, 50 - (Health + 1) div 2, $000000);4599 RisedTextOut(Panel.Canvas, xMidPanel + 7 + 12 + 32 -4600 BiColorTextWidth(Panel.Canvas, s) div 2, PanelHeight - 23, s);4601 4602 FrameImage(Panel.Canvas, GrExt[HGrSystem].Data,4603 xMidPanel + 7 + xUnitText, yTroop + 15, 12, 14,4604 121 + Exp div ExpCost * 13, 28);4605 if Job = jCity then4606 s := Tribe[me].ModelName[-1]4607 else4608 s := Tribe[me].ModelName[mix];4609 if Home >= 0 then4610 begin4611 LoweredTextOut(Panel.Canvas, -1, MainTexture,4612 xMidPanel + 7 + xUnitText + 18, yTroop + 5, s);4613 LoweredTextOut(Panel.Canvas, -1, MainTexture,4614 xMidPanel + 7 + xUnitText + 18, yTroop + 21,4615 '(' + CityName(MyCity[Home].ID) + ')');4616 end4617 else4618 LoweredTextOut(Panel.Canvas, -1, MainTexture,4619 xMidPanel + 7 + xUnitText + 18, yTroop + 13, s);4620 end;4621 4622 if (UnFocus >= 0) and (MyUn[UnFocus].Loc <> TroopLoc) then4623 begin // divide panel4624 if SmallScreen and not supervising then4625 x := xTroop - 84626 else4627 x := xTroop - 152;4628 Pen.Color := MainTexture.clBevelShade;4629 MoveTo(x - 1, PanelHeight - MidPanelHeight + 2);4630 LineTo(x - 1, PanelHeight);4631 Pen.Color := MainTexture.clBevelLight;4632 MoveTo(x, PanelHeight - MidPanelHeight + 2);4633 LineTo(x, PanelHeight);4634 end;4635 4636 for i := 0 to 23 do4637 trix[i] := -1;4638 if MyMap[TroopLoc] and fUnit <> 0 then4639 begin4640 if MyMap[TroopLoc] and fOwned <> 0 then4641 begin4642 if (TrCnt > 1) or (UnFocus < 0) or (MyUn[UnFocus].Loc <> TroopLoc)4643 then4644 begin4645 LoweredTextOut(Panel.Canvas, -1, MainTexture, xTroop + 10,4646 PanelHeight - 24, Phrases.Lookup('PRESENT'));4647 Server(sGetDefender, me, TroopLoc, uixDefender);4648 Count := 0;4649 for Prio := true downto false do4650 for uix := 0 to MyRO.nUn - 1 do4651 if (uix = uixDefender) = Prio then4652 begin // display own units4653 unx := MyUn[uix];4654 if unx.Loc = TroopLoc then4655 begin4656 if (Count >= TrRow * sb.si.npos) and4657 (Count < TrRow * (sb.si.npos + 1)) then4658 begin4659 trix[Count - TrRow * sb.si.npos] := uix;4660 MakeUnitInfo(me, unx, UnitInfo);4661 x := (Count - TrRow * sb.si.npos) * TrPitch;4662 if uix = UnFocus then4663 begin4664 ScreenTools.Frame(Panel.Canvas, xTroop + 4 + x, yTroop + 3,4665 xTroop + 64 + x, yTroop + 47, $000000, $000000);4666 ScreenTools.Frame(Panel.Canvas, xTroop + 3 + x, yTroop + 2,4667 xTroop + 63 + x, yTroop + 46, MainTexture.clMark,4668 MainTexture.clMark);4669 end4670 else if (unx.Master >= 0) and (unx.Master = UnFocus)4671 then4672 begin4673 CFrame(Panel.Canvas, xTroop + 4 + x, yTroop + 3,4674 xTroop + 64 + x, yTroop + 47, 8, $000000);4675 CFrame(Panel.Canvas, xTroop + 3 + x, yTroop + 2,4676 xTroop + 63 + x, yTroop + 46, 8,4677 MainTexture.clMark);4678 end;4679 NoMap.SetOutput(Panel);4680 NoMap.PaintUnit(xTroop + 2 + x, yTroop + 1, UnitInfo,4681 unx.Status);4682 if (ClientMode < scContact) and4683 ((unx.Job > jNone) or4684 (unx.Status and (usStay or usRecover or usGoto) <> 0))4685 then4686 Sprite(Panel, HGrSystem, xTroop + 2 + 60 - 20 + x,4687 yTroop + 35, 20, 20, 81, 25);4688 4689 if not supervising then4690 begin4691 MakeBlue(Panel, xTroop + 2 + 10 + x,4692 yTroop - 13, 44, 12);4693 s := MovementToString(unx);4694 RisedTextOut(Panel.Canvas,4695 xTroop + x + 34 - BiColorTextWidth(Panel.Canvas, s)4696 div 2, yTroop - 16, s);4697 end4698 end;4699 inc(Count)4700 end;4701 end; // for uix:=0 to MyRO.nUn-14702 assert(Count = TrCnt);4703 end4704 end4705 else4706 begin4707 LoweredTextOut(Panel.Canvas, -1, MainTexture, xTroop + 8,4708 PanelHeight - 24, Phrases.Lookup('PRESENT'));4709 Server(sGetUnits, me, TroopLoc, Count);4710 for i := 0 to Count - 1 do4711 if (i >= TrRow * sb.si.npos) and (i < TrRow * (sb.si.npos + 1))4712 then4713 begin // display enemy units4714 trix[i - TrRow * sb.si.npos] := i;4715 x := (i - TrRow * sb.si.npos) * TrPitch;4716 NoMap.SetOutput(Panel);4717 NoMap.PaintUnit(xTroop + 2 + x, yTroop + 1,4718 MyRO.EnemyUn[MyRO.nEnemyUn + i], 0);4719 end;4720 end;4721 end;4722 if not SmallScreen or supervising then4723 begin // show terrain and improvements4724 PaintZoomedTile(Panel, xTerrain - xxt * 2, 110 - yyt * 3, TroopLoc);4725 if (UnFocus >= 0) and (MyUn[UnFocus].Job <> jNone) then4726 begin4727 JobFocus := MyUn[UnFocus].Job;4728 Server(sGetJobProgress, me, MyUn[UnFocus].Loc, JobProgressData);4729 MakeBlue(Panel, xTerrain - 72, 148 - 17, 144, 31);4730 PaintRelativeProgressBar(Panel.Canvas, 3, xTerrain - 68, 148 + 3,4731 63, JobProgressData[JobFocus].Done,4732 JobProgressData[JobFocus].NextTurnPlus,4733 JobProgressData[JobFocus].Required, true, MainTexture);4734 s := Format('%s/%s',4735 [ScreenTools.MovementToString(JobProgressData[JobFocus].Done),4736 ScreenTools.MovementToString(JobProgressData[JobFocus]4737 .Required)]);4738 RisedTextOut(Panel.Canvas, xTerrain + 6, 148 - 3, s);4739 Tile := MyMap[MyUn[UnFocus].Loc];4740 if (JobFocus = jRoad) and (Tile and fRiver <> 0) then4741 JobFocus := nJob + 04742 else if (JobFocus = jRR) and (Tile and fRiver <> 0) then4743 JobFocus := nJob + 14744 else if JobFocus = jClear then4745 begin4746 if Tile and fTerrain = fForest then4747 JobFocus := nJob + 24748 else if Tile and fTerrain = fDesert then4749 JobFocus := nJob + 34750 else4751 JobFocus := nJob + 44752 end;4753 s := Phrases.Lookup('JOBRESULT', JobFocus);4754 RisedTextOut(Panel.Canvas, xTerrain - BiColorTextWidth(Panel.Canvas,4755 s) div 2, 148 - 19, s);4756 end;4757 if MyMap[TroopLoc] and (fTerrain or fSpecial) = fGrass or fSpecial14758 then4759 s := Phrases.Lookup('TERRAIN', fGrass + 12)4760 else if MyMap[TroopLoc] and fDeadLands <> 0 then4761 s := Phrases.Lookup('TERRAIN', 3 * 12)4762 else if (MyMap[TroopLoc] and fTerrain = fForest) and4763 IsJungle(TroopLoc div G.lx) then4764 s := Phrases.Lookup('TERRAIN', fJungle)4765 else4766 s := Phrases.Lookup('TERRAIN', MyMap[TroopLoc] and fTerrain);4767 RisedTextOut(Panel.Canvas, xTerrain - BiColorTextWidth(Panel.Canvas,4768 s) div 2, 99, s);4769 end;4770 4771 if TerrainBtn.Visible then4772 with TerrainBtn do4773 RFrame(Panel.Canvas, Left - 1, Top - self.ClientHeight +4774 (PanelHeight - 1), Left + width, Top + height - self.ClientHeight4775 + PanelHeight, MainTexture.clBevelShade, MainTexture.clBevelLight)4776 end { if TroopLoc>=0 }4777 end;4778 4779 for i := 0 to ControlCount - 1 do4780 if Controls[i] is TButtonB then4781 with TButtonB(Controls[i]) do4782 begin4783 if Visible then4784 begin4785 Dump(Panel, HGrSystem, Left, Top - self.ClientHeight + PanelHeight,4786 25, 25, 169, 243);4787 Sprite(Panel, HGrSystem, Left, Top - self.ClientHeight +4788 PanelHeight, 25, 25, 1 + 26 * ButtonIndex, 337);4789 RFrame(Panel.Canvas, Left - 1, Top - self.ClientHeight +4790 (PanelHeight - 1), Left + width, Top + height - self.ClientHeight4791 + PanelHeight, MainTexture.clBevelShade,4792 MainTexture.clBevelLight);4793 end;4794 end;4795 4796 if ClientMode <> cEditMap then4797 begin4798 for i := 0 to ControlCount - 1 do4799 if Controls[i] is TButtonC then4800 with TButtonC(Controls[i]) do4801 begin4802 Dump(Panel, HGrSystem, Left, Top - self.ClientHeight + PanelHeight,4803 12, 12, 169, 178 + 13 * ButtonIndex);4804 RFrame(Panel.Canvas, Left - 1, Top - self.ClientHeight +4805 (PanelHeight - 1), Left + width, Top + height - self.ClientHeight4806 + PanelHeight, MainTexture.clBevelShade,4807 MainTexture.clBevelLight);4808 end4809 end;4810 EOT.SetBack(Panel.Canvas, EOT.Left, EOT.Top - (ClientHeight - PanelHeight));4811 SmartRectInvalidate(0, ClientHeight - PanelHeight, ClientWidth,4812 ClientHeight);4813 4814 // topbar4815 xTreasurySection := ClientWidth div 2 - 172;4816 xResearchSection := ClientWidth div 2;4817 // ClientWidth div 2+68 = maximum to right4818 FillLarge(TopBar.Canvas, 0, 0, ClientWidth, TopBarHeight - 3,4819 ClientWidth div 2);4820 with TopBar.Canvas do4821 begin4822 Pen.Color := $000000;4823 MoveTo(0, TopBarHeight - 1);4824 LineTo(ClientWidth, TopBarHeight - 1);4825 Pen.Color := MainTexture.clBevelShade;4826 MoveTo(0, TopBarHeight - 2);4827 LineTo(ClientWidth, TopBarHeight - 2);4828 MoveTo(0, TopBarHeight - 3);4829 LineTo(ClientWidth, TopBarHeight - 3);4830 Pen.Color := MainTexture.clBevelLight;4831 ScreenTools.Frame(TopBar.Canvas, 40, -1, xTreasurySection - 1, TopBarHeight - 7,4832 MainTexture.clBevelShade, MainTexture.clBevelLight);4833 ScreenTools.Frame(TopBar.Canvas, xResearchSection + 332, -1, ClientWidth,4834 TopBarHeight - 7, MainTexture.clBevelShade, MainTexture.clBevelLight);4835 end;4836 if GameMode <> cMovie then4837 ImageOp_BCC(TopBar, Templates, 2, 1, 145, 38, 36, 36, $BFBF20, $4040DF);4838 if MyRO.nCity > 0 then4839 begin4840 TrueMoney := MyRO.Money;4841 TrueResearch := MyRO.Research;4842 if supervising then4843 begin // normalize values from after-turn state4844 dec(TrueMoney, TaxSum);4845 if TrueMoney < 0 then4846 TrueMoney := 0; // shouldn't happen4847 dec(TrueResearch, ScienceSum);4848 if TrueResearch < 0 then4849 TrueResearch := 0; // shouldn't happen4850 end;4851 4852 // treasury section4853 ImageOp_BCC(TopBar, Templates, xTreasurySection + 8, 1, 145, 1, 36, 36,4854 $40A040, $4030C0);4855 s := IntToStr(TrueMoney);4856 LoweredTextOut(TopBar.Canvas, -1, MainTexture, xTreasurySection + 48, 0,4857 s + '%c');4858 if MyRO.Government <> gAnarchy then4859 begin4860 ImageOp_BCC(TopBar, Templates, xTreasurySection + 48, 22, 124, 1, 14,4861 14, $0000C0, $0080C0);4862 if TaxSum >= 0 then4863 s := Format(Phrases.Lookup('MONEYGAINPOS'), [TaxSum])4864 else4865 s := Format(Phrases.Lookup('MONEYGAINNEG'), [TaxSum]);4866 LoweredTextOut(TopBar.Canvas, -1, MainTexture,4867 xTreasurySection + 48 + 15, 18, s);4868 end;4869 4870 // research section4871 ImageOp_BCC(TopBar, Templates, xResearchSection + 8, 1, 145, 75, 36, 36,4872 $FF0000, $00FFE0);4873 if MyData.FarTech <> adNexus then4874 begin4875 if MyRO.ResearchTech < 0 then4876 CostFactor := 24877 else if (MyRO.ResearchTech = adMilitary) or4878 (MyRO.Tech[MyRO.ResearchTech] = tsSeen) then4879 CostFactor := 14880 else if MyRO.ResearchTech in FutureTech then4881 if MyRO.Government = gFuture then4882 CostFactor := 44883 else4884 CostFactor := 84885 else4886 CostFactor := 2;4887 Server(sGetTechCost, me, 0, i);4888 CostFactor := CostFactor * 22; // length of progress bar4889 PaintRelativeProgressBar(TopBar.Canvas, 2, xResearchSection + 48 + 1,4890 26, CostFactor, TrueResearch, ScienceSum, i, true, MainTexture);4891 4892 if MyRO.ResearchTech < 0 then4893 s := Phrases.Lookup('SCIENCE')4894 else if MyRO.ResearchTech = adMilitary then4895 s := Phrases.Lookup('INITUNIT')4896 else4897 begin4898 s := Phrases.Lookup('ADVANCES', MyRO.ResearchTech);4899 if MyRO.ResearchTech in FutureTech then4900 if MyRO.Tech[MyRO.ResearchTech] >= 1 then4901 s := s + ' ' + IntToStr(MyRO.Tech[MyRO.ResearchTech] + 1)4902 else4903 s := s + ' 1';4904 end;4905 if ScienceSum > 0 then4906 begin4907 { j:=(i-MyRO.Research-1) div ScienceSum +1;4908 if j<1 then j:=1;4909 if j>1 then4910 s:=Format(Phrases.Lookup('TECHWAIT'),[s,j]); }4911 LoweredTextOut(TopBar.Canvas, -1, MainTexture,4912 xResearchSection + 48, 0, s);4913 end4914 else4915 LoweredTextOut(TopBar.Canvas, -1, MainTexture,4916 xResearchSection + 48, 0, s);4917 end4918 else4919 CostFactor := 0;4920 if (MyData.FarTech <> adNexus) and (ScienceSum > 0) then4921 begin4922 ImageOp_BCC(TopBar, Templates, xResearchSection + 48 + CostFactor + 11,4923 22, 124, 1, 14, 14, $0000C0, $0080C0);4924 s := Format(Phrases.Lookup('TECHGAIN'), [ScienceSum]);4925 LoweredTextOut(TopBar.Canvas, -1, MainTexture, xResearchSection + 48 +4926 CostFactor + 26, 18, s);4927 end4928 end;4929 if ClientMode <> cEditMap then4930 begin4931 TopBar.Canvas.Font.Assign(UniFont[ftCaption]);4932 s := TurnToString(MyRO.Turn);4933 RisedTextOut(TopBar.Canvas,4934 40 + (xTreasurySection - 40 - BiColorTextWidth(TopBar.Canvas, s))4935 div 2, 6, s);4936 TopBar.Canvas.Font.Assign(UniFont[ftNormal]);4937 end;4938 RectInvalidate(0, 0, ClientWidth, TopBarHeight);4939 end; { PanelPaint }4940 4941 procedure TMainScreen.FocusOnLoc(Loc: integer; Options: integer = 0);4942 var4943 dx: integer;4944 Outside, Changed: boolean;4945 begin4946 dx := G.lx + 1 - (xw - Loc + G.lx * 1024 + 1) mod G.lx;4947 Outside := (dx >= (MapWidth + 1) div (xxt * 2) - 2) or (ywmax > 0) and4948 ((yw > 0) and (Loc div G.lx <= yw + 1) or (yw < ywmax) and4949 (Loc div G.lx >= yw + (MapHeight - 1) div yyt - 2));4950 Changed := true;4951 if Outside then4952 begin4953 Centre(Loc);4954 PaintAllMaps4955 end4956 else if not MapValid then4957 PaintAllMaps4958 else4959 Changed := false;4960 if Options and flRepaintPanel <> 0 then4961 PanelPaint;4962 if Changed and (Options and flImmUpdate <> 0) then4963 Update;4964 end;4965 4966 procedure TMainScreen.NextUnit(NearLoc: integer; AutoTurn: boolean);4967 var4968 Dist, TestDist: single;4969 i, uix, NewFocus: integer;4970 GotoOnly: boolean;4971 begin4972 if ClientMode >= scContact then4973 exit;4974 DestinationMarkON := false;4975 PaintDestination;4976 for GotoOnly := GoOnPhase downto false do4977 begin4978 NewFocus := -1;4979 for i := 1 to MyRO.nUn do4980 begin4981 uix := (UnFocus + i) mod MyRO.nUn;4982 if (MyUn[uix].Loc >= 0) and (MyUn[uix].Job = jNone) and4983 (MyUn[uix].Status and (usStay or usRecover or usWaiting) = usWaiting)4984 and (not GotoOnly or (MyUn[uix].Status and usGoto <> 0)) then4985 if NearLoc < 0 then4986 begin4987 NewFocus := uix;4988 Break4989 end4990 else4991 begin4992 TestDist := Distance(NearLoc, MyUn[uix].Loc);4993 if (NewFocus < 0) or (TestDist < Dist) then4994 begin4995 NewFocus := uix;4996 Dist := TestDist4997 end4998 end4999 end;5000 if GotoOnly then5001 if NewFocus < 0 then5002 GoOnPhase := false5003 else5004 Break;5005 end;5006 if NewFocus >= 0 then5007 begin5008 SetUnFocus(NewFocus);5009 SetTroopLoc(MyUn[NewFocus].Loc);5010 FocusOnLoc(TroopLoc, flRepaintPanel)5011 end5012 else if AutoTurn and not mWaitTurn.Checked then5013 begin5014 TurnComplete := true;5015 SetUnFocus(-1);5016 SetTroopLoc(-1);5017 PostMessage(Handle, WM_EOT, 0, 0)5018 end5019 else5020 begin5021 if { (UnFocus>=0) and } not TurnComplete and EOT.Visible then5022 Play('TURNEND');5023 TurnComplete := true;5024 SetUnFocus(-1);5025 SetTroopLoc(-1);5026 PanelPaint;5027 end;5028 end; { NextUnit }5029 5030 procedure TMainScreen.Scroll(dx, dy: integer);5031 begin5032 xw := (xw + G.lx + dx) mod G.lx;5033 if ywmax > 0 then5034 begin5035 yw := yw + 2 * dy;5036 if yw < 0 then5037 yw := 05038 else if yw > ywmax then5039 yw := ywmax;5040 end;5041 MainOffscreenPaint;5042 xwMini := xw;5043 ywMini := yw;5044 MiniPaint;5045 CopyMiniToPanel;5046 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini + 2,5047 xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini +5048 2 + G.ly);5049 Update;5050 end;5051 5052 procedure TMainScreen.Timer1Timer(Sender: TObject);5053 var5054 dx, dy, speed: integer;5055 begin5056 if idle and (me >= 0) and (GameMode <> cMovie) then5057 if (fsModal in Screen.ActiveForm.FormState) or5058 (Screen.ActiveForm is TBufferedDrawDlg) and5059 (TBufferedDrawDlg(Screen.ActiveForm).WindowMode <> wmPersistent) then5060 begin5061 BlinkTime := BlinkOnTime + BlinkOffTime - 1;5062 if not BlinkON then5063 begin5064 BlinkON := true;5065 if UnFocus >= 0 then5066 PaintLocTemp(MyUn[UnFocus].Loc)5067 else if TurnComplete and not supervising then5068 EOT.SetButtonIndexFast(eotBlinkOn)5069 end5070 end5071 else5072 begin5073 if Application.Active and not mScrollOff.Checked then5074 begin5075 if mScrollFast.Checked then5076 speed := 25077 else5078 speed := 1;5079 dx := 0;5080 dy := 0;5081 if Mouse.CursorPos.y < Screen.height - PanelHeight then5082 if Mouse.CursorPos.x = 0 then5083 dx := -speed // scroll left5084 else if Mouse.CursorPos.x = Screen.width - 1 then5085 dx := speed; // scroll right5086 if Mouse.CursorPos.y = 0 then5087 dy := -speed // scroll up5088 else if (Mouse.CursorPos.y = Screen.height - 1) and5089 (Mouse.CursorPos.x >= TerrainBtn.Left + TerrainBtn.width) and5090 (Mouse.CursorPos.x < xRightPanel + 10 - 8) then5091 dy := speed; // scroll down5092 if (dx <> 0) or (dy <> 0) then5093 begin5094 if (Screen.ActiveForm <> MainScreen) and5095 (@Screen.ActiveForm.OnDeactivate <> nil) then5096 Screen.ActiveForm.OnDeactivate(nil);5097 Scroll(dx, dy);5098 end5099 end;5100 5101 BlinkTime := (BlinkTime + 1) mod (BlinkOnTime + BlinkOffTime);5102 BlinkON := BlinkTime >= BlinkOffTime;5103 DestinationMarkON := true;5104 if UnFocus >= 0 then5105 begin5106 if (BlinkTime = 0) or (BlinkTime = BlinkOffTime) then5107 begin5108 PaintLocTemp(MyUn[UnFocus].Loc, pltsBlink);5109 PaintDestination;5110 // if MoveHintToLoc>=0 then5111 // ShowMoveHint(MoveHintToLoc, true);5112 end5113 end5114 else if TurnComplete and not supervising then5115 begin5116 if BlinkTime = 0 then5117 EOT.SetButtonIndexFast(eotBlinkOff)5118 else if BlinkTime = BlinkOffTime then5119 EOT.SetButtonIndexFast(eotBlinkOn)5120 end5121 end5122 end;5123 5124 procedure TMainScreen.Centre(Loc: integer);5125 begin5126 if FastScrolling and MapValid then5127 Update;5128 // necessary because ScrollDC for form canvas is called after5129 xw := (Loc mod G.lx - (MapWidth - xxt * 2 * ((Loc div G.lx) and 1))5130 div (xxt * 4) + G.lx) mod G.lx;5131 if ywmax <= 0 then5132 yw := ywcenter5133 else5134 begin5135 yw := (Loc div G.lx - MapHeight div (yyt * 2) + 1) and not 1;5136 if yw < 0 then5137 yw := 05138 else if yw > ywmax then5139 yw := ywmax;5140 end5141 end;5142 5143 function TMainScreen.ZoomToCity(Loc: integer;5144 NextUnitOnClose: boolean = false; ShowEvent: integer = 0): boolean;5145 begin5146 result := MyMap[Loc] and (fOwned or fSpiedOut) <> 0;5147 if result then5148 with CityDlg do5149 begin5150 if ClientMode >= scContact then5151 begin5152 CloseAction := None;5153 RestoreUnFocus := -1;5154 end5155 else if NextUnitOnClose then5156 begin5157 CloseAction := StepFocus;5158 RestoreUnFocus := -1;5159 end5160 else if not Visible then5161 begin5162 CloseAction := RestoreFocus;5163 RestoreUnFocus := UnFocus;5164 end;5165 SetUnFocus(-1);5166 SetTroopLoc(Loc);5167 MarkCityLoc := Loc;5168 PanelPaint;5169 ShowNewContent(wmPersistent, Loc, ShowEvent);5170 end5171 end;5172 5173 function TMainScreen.LocationOfScreenPixel(x, y: integer): integer;5174 var5175 qx, qy: integer;5176 begin5177 qx := (x * (yyt * 2) + y * (xxt * 2) + xxt * yyt * 2)5178 div (xxt * yyt * 4) - 1;5179 qy := (y * (xxt * 2) - x * (yyt * 2) - xxt * yyt * 2 + 4000 * xxt * yyt)5180 div (xxt * yyt * 4) - 999;5181 result := (xw + (qx - qy + 2048) div 2 - 1024 + G.lx) mod G.lx + G.lx *5182 (yw + qx + qy);5183 end;5184 5185 procedure TMainScreen.MapBoxMouseDown(Sender: TObject; Button: TMouseButton;5186 Shift: TShiftState; x, y: integer);5187 var5188 i, uix, emix, p1, dx, dy, MouseLoc: integer;5189 EditTileData: TEditTileData;5190 m, m2: TMenuItem;5191 MoveAdviceData: TMoveAdviceData;5192 DoCenter: boolean;5193 begin5194 if GameMode = cMovie then5195 exit;5196 5197 if CityDlg.Visible then5198 CityDlg.Close;5199 if UnitStatDlg.Visible then5200 UnitStatDlg.Close;5201 MouseLoc := LocationOfScreenPixel(x, y);5202 if (MouseLoc < 0) or (MouseLoc >= G.lx * G.ly) then5203 exit;5204 if (Button = mbLeft) and not(ssShift in Shift) then5205 begin5206 DoCenter := true;5207 if ClientMode = cEditMap then5208 begin5209 DoCenter := false;5210 EditTileData.Loc := MouseLoc;5211 if ssCtrl in Shift then // toggle special resource5212 case MyMap[MouseLoc] and fTerrain of5213 fOcean:5214 EditTileData.NewTile := MyMap[MouseLoc];5215 fGrass, fArctic:5216 EditTileData.NewTile := MyMap[MouseLoc] and not fSpecial or5217 ((MyMap[MouseLoc] shr 5 and 3 + 1) mod 2 shl 5);5218 else5219 EditTileData.NewTile := MyMap[MouseLoc] and not fSpecial or5220 ((MyMap[MouseLoc] shr 5 and 3 + 1) mod 3 shl 5)5221 end5222 else if BrushType <= fTerrain then5223 EditTileData.NewTile := MyMap[MouseLoc] and not fTerrain or5224 fSpecial or BrushType5225 else if BrushType and fDeadLands <> 0 then5226 if MyMap[MouseLoc] and (fDeadLands or fModern) = BrushType and5227 (fDeadLands or fModern) then5228 EditTileData.NewTile := MyMap[MouseLoc] and5229 not(fDeadLands or fModern)5230 else5231 EditTileData.NewTile := MyMap[MouseLoc] and5232 not(fDeadLands or fModern) or BrushType5233 else if BrushType and fTerImp <> 0 then5234 if MyMap[MouseLoc] and fTerImp = BrushType then5235 EditTileData.NewTile := MyMap[MouseLoc] and not fTerImp5236 else5237 EditTileData.NewTile := MyMap[MouseLoc] and not fTerImp or BrushType5238 else if BrushType and (fPrefStartPos or fStartPos) <> 0 then5239 if MyMap[MouseLoc] and (fPrefStartPos or fStartPos) = BrushType and5240 (fPrefStartPos or fStartPos) then5241 EditTileData.NewTile := MyMap[MouseLoc] and5242 not(fPrefStartPos or fStartPos)5243 else5244 EditTileData.NewTile := MyMap[MouseLoc] and5245 not(fPrefStartPos or fStartPos) or BrushType5246 else5247 EditTileData.NewTile := MyMap[MouseLoc] xor BrushType;5248 Server(sEditTile, me, 0, EditTileData);5249 Edited := true;5250 BrushLoc := MouseLoc;5251 PaintLoc(MouseLoc, 2);5252 MiniPaint;5253 BitBlt(Panel.Canvas.Handle, xMini + 2, yMini + 2, G.lx * 2, G.ly,5254 Mini.Canvas.Handle, 0, 0, SRCCOPY);5255 if ywmax <= 0 then5256 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (2 * xxt),5257 yMini + 2, xMini + 1 + G.lx + MapWidth div (2 * xxt),5258 yMini + 2 + G.ly - 1, MainTexture.clMark, MainTexture.clMark)5259 else5260 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (2 * xxt),5261 yMini + 2 + yw, xMini + 2 + G.lx + MapWidth div (2 * xxt) - 1,5262 yMini + 2 + yw + MapHeight div yyt - 2, MainTexture.clMark,5263 MainTexture.clMark);5264 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini +5265 2, xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini5266 + 2 + G.ly)5267 end5268 else if MyMap[MouseLoc] and fCity <> 0 then { city clicked }5269 begin5270 if MyMap[MouseLoc] and (fOwned or fSpiedOut) <> 0 then5271 begin5272 ZoomToCity(MouseLoc);5273 DoCenter := false;5274 4698 end 5275 4699 else 5276 4700 begin 5277 UnitStatDlg.ShowNewContent_EnemyCity(wmPersistent, MouseLoc); 5278 DoCenter := false; 4701 LoweredTextOut(Panel.Canvas, -1, MainTexture, xTroop + 8, 4702 PanelHeight - 24, Phrases.Lookup('PRESENT')); 4703 Server(sGetUnits, me, TroopLoc, Count); 4704 for i := 0 to Count - 1 do 4705 if (i >= TrRow * sb.si.npos) and (i < TrRow * (sb.si.npos + 1)) 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, 63, 4724 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].Required)]); 4730 RisedTextOut(Panel.Canvas, xTerrain + 6, 148 - 3, s); 4731 Tile := MyMap[MyUn[UnFocus].Loc]; 4732 if (JobFocus = jRoad) and (Tile and fRiver <> 0) then 4733 JobFocus := nJob + 0 4734 else if (JobFocus = jRR) and (Tile and fRiver <> 0) then 4735 JobFocus := nJob + 1 4736 else if JobFocus = jClear then 4737 begin 4738 if Tile and fTerrain = fForest then 4739 JobFocus := nJob + 2 4740 else if Tile and fTerrain = fDesert then 4741 JobFocus := nJob + 3 4742 else 4743 JobFocus := nJob + 4 4744 end; 4745 s := Phrases.Lookup('JOBRESULT', JobFocus); 4746 RisedTextOut(Panel.Canvas, xTerrain - BiColorTextWidth(Panel.Canvas, 4747 s) div 2, 148 - 19, s); 4748 end; 4749 if MyMap[TroopLoc] and (fTerrain or fSpecial) = fGrass or fSpecial1 then 4750 s := Phrases.Lookup('TERRAIN', fGrass + 12) 4751 else if MyMap[TroopLoc] and fDeadLands <> 0 then 4752 s := Phrases.Lookup('TERRAIN', 3 * 12) 4753 else if (MyMap[TroopLoc] and fTerrain = fForest) and 4754 IsJungle(TroopLoc div G.lx) then 4755 s := Phrases.Lookup('TERRAIN', fJungle) 4756 else 4757 s := Phrases.Lookup('TERRAIN', MyMap[TroopLoc] and fTerrain); 4758 RisedTextOut(Panel.Canvas, xTerrain - BiColorTextWidth(Panel.Canvas, s) 4759 div 2, 99, s); 4760 end; 4761 4762 if TerrainBtn.Visible then 4763 with TerrainBtn do 4764 RFrame(Panel.Canvas, Left - 1, Top - self.ClientHeight + 4765 (PanelHeight - 1), Left + width, Top + height - self.ClientHeight + 4766 PanelHeight, MainTexture.clBevelShade, MainTexture.clBevelLight) 4767 end { if TroopLoc>=0 } 4768 end; 4769 4770 for i := 0 to ControlCount - 1 do 4771 if Controls[i] is TButtonB then 4772 with TButtonB(Controls[i]) do 4773 begin 4774 if Visible then 4775 begin 4776 Dump(Panel, HGrSystem, Left, Top - self.ClientHeight + PanelHeight, 4777 25, 25, 169, 243); 4778 Sprite(Panel, HGrSystem, Left, Top - self.ClientHeight + PanelHeight, 4779 25, 25, 1 + 26 * ButtonIndex, 337); 4780 RFrame(Panel.Canvas, Left - 1, Top - self.ClientHeight + 4781 (PanelHeight - 1), Left + width, Top + height - self.ClientHeight + 4782 PanelHeight, MainTexture.clBevelShade, MainTexture.clBevelLight); 4783 end; 4784 end; 4785 4786 if ClientMode <> cEditMap then 4787 begin 4788 for i := 0 to ControlCount - 1 do 4789 if Controls[i] is TButtonC then 4790 with TButtonC(Controls[i]) do 4791 begin 4792 Dump(Panel, HGrSystem, Left, Top - self.ClientHeight + PanelHeight, 4793 12, 12, 169, 178 + 13 * ButtonIndex); 4794 RFrame(Panel.Canvas, Left - 1, Top - self.ClientHeight + 4795 (PanelHeight - 1), Left + width, Top + height - self.ClientHeight + 4796 PanelHeight, MainTexture.clBevelShade, MainTexture.clBevelLight); 5279 4797 end 4798 end; 4799 EOT.SetBack(Panel.Canvas, EOT.Left, EOT.Top - (ClientHeight - PanelHeight)); 4800 SmartRectInvalidate(0, ClientHeight - PanelHeight, ClientWidth, ClientHeight); 4801 4802 // topbar 4803 xTreasurySection := ClientWidth div 2 - 172; 4804 xResearchSection := ClientWidth div 2; 4805 // ClientWidth div 2+68 = maximum to right 4806 FillLarge(TopBar.Canvas, 0, 0, ClientWidth, TopBarHeight - 3, 4807 ClientWidth div 2); 4808 with TopBar.Canvas do 4809 begin 4810 Pen.Color := $000000; 4811 MoveTo(0, TopBarHeight - 1); 4812 LineTo(ClientWidth, TopBarHeight - 1); 4813 Pen.Color := MainTexture.clBevelShade; 4814 MoveTo(0, TopBarHeight - 2); 4815 LineTo(ClientWidth, TopBarHeight - 2); 4816 MoveTo(0, TopBarHeight - 3); 4817 LineTo(ClientWidth, TopBarHeight - 3); 4818 Pen.Color := MainTexture.clBevelLight; 4819 ScreenTools.Frame(TopBar.Canvas, 40, -1, xTreasurySection - 1, 4820 TopBarHeight - 7, MainTexture.clBevelShade, MainTexture.clBevelLight); 4821 ScreenTools.Frame(TopBar.Canvas, xResearchSection + 332, -1, ClientWidth, 4822 TopBarHeight - 7, MainTexture.clBevelShade, MainTexture.clBevelLight); 4823 end; 4824 if GameMode <> cMovie then 4825 ImageOp_BCC(TopBar, Templates, 2, 1, 145, 38, 36, 36, $BFBF20, $4040DF); 4826 if MyRO.nCity > 0 then 4827 begin 4828 TrueMoney := MyRO.Money; 4829 TrueResearch := MyRO.Research; 4830 if supervising then 4831 begin // normalize values from after-turn state 4832 dec(TrueMoney, TaxSum); 4833 if TrueMoney < 0 then 4834 TrueMoney := 0; // shouldn't happen 4835 dec(TrueResearch, ScienceSum); 4836 if TrueResearch < 0 then 4837 TrueResearch := 0; // shouldn't happen 4838 end; 4839 4840 // treasury section 4841 ImageOp_BCC(TopBar, Templates, xTreasurySection + 8, 1, 145, 1, 36, 36, 4842 $40A040, $4030C0); 4843 s := IntToStr(TrueMoney); 4844 LoweredTextOut(TopBar.Canvas, -1, MainTexture, xTreasurySection + 48, 0, 4845 s + '%c'); 4846 if MyRO.Government <> gAnarchy then 4847 begin 4848 ImageOp_BCC(TopBar, Templates, xTreasurySection + 48, 22, 124, 1, 14, 14, 4849 $0000C0, $0080C0); 4850 if TaxSum >= 0 then 4851 s := Format(Phrases.Lookup('MONEYGAINPOS'), [TaxSum]) 4852 else 4853 s := Format(Phrases.Lookup('MONEYGAINNEG'), [TaxSum]); 4854 LoweredTextOut(TopBar.Canvas, -1, MainTexture, xTreasurySection + 48 + 4855 15, 18, s); 4856 end; 4857 4858 // research section 4859 ImageOp_BCC(TopBar, Templates, xResearchSection + 8, 1, 145, 75, 36, 36, 4860 $FF0000, $00FFE0); 4861 if MyData.FarTech <> adNexus then 4862 begin 4863 if MyRO.ResearchTech < 0 then 4864 CostFactor := 2 4865 else if (MyRO.ResearchTech = adMilitary) or 4866 (MyRO.Tech[MyRO.ResearchTech] = tsSeen) then 4867 CostFactor := 1 4868 else if MyRO.ResearchTech in FutureTech then 4869 if MyRO.Government = gFuture then 4870 CostFactor := 4 4871 else 4872 CostFactor := 8 4873 else 4874 CostFactor := 2; 4875 Server(sGetTechCost, me, 0, i); 4876 CostFactor := CostFactor * 22; // length of progress bar 4877 PaintRelativeProgressBar(TopBar.Canvas, 2, xResearchSection + 48 + 1, 26, 4878 CostFactor, TrueResearch, ScienceSum, i, true, MainTexture); 4879 4880 if MyRO.ResearchTech < 0 then 4881 s := Phrases.Lookup('SCIENCE') 4882 else if MyRO.ResearchTech = adMilitary then 4883 s := Phrases.Lookup('INITUNIT') 4884 else 4885 begin 4886 s := Phrases.Lookup('ADVANCES', MyRO.ResearchTech); 4887 if MyRO.ResearchTech in FutureTech then 4888 if MyRO.Tech[MyRO.ResearchTech] >= 1 then 4889 s := s + ' ' + IntToStr(MyRO.Tech[MyRO.ResearchTech] + 1) 4890 else 4891 s := s + ' 1'; 4892 end; 4893 if ScienceSum > 0 then 4894 begin 4895 { j:=(i-MyRO.Research-1) div ScienceSum +1; 4896 if j<1 then j:=1; 4897 if j>1 then 4898 s:=Format(Phrases.Lookup('TECHWAIT'),[s,j]); } 4899 LoweredTextOut(TopBar.Canvas, -1, MainTexture, 4900 xResearchSection + 48, 0, s); 5280 4901 end 5281 else if MyMap[MouseLoc] and fUnit <> 0 then { unit clicked } 5282 if MyMap[MouseLoc] and fOwned <> 0 then 4902 else 4903 LoweredTextOut(TopBar.Canvas, -1, MainTexture, 4904 xResearchSection + 48, 0, s); 4905 end 4906 else 4907 CostFactor := 0; 4908 if (MyData.FarTech <> adNexus) and (ScienceSum > 0) then 4909 begin 4910 ImageOp_BCC(TopBar, Templates, xResearchSection + 48 + CostFactor + 11, 4911 22, 124, 1, 14, 14, $0000C0, $0080C0); 4912 s := Format(Phrases.Lookup('TECHGAIN'), [ScienceSum]); 4913 LoweredTextOut(TopBar.Canvas, -1, MainTexture, xResearchSection + 48 + 4914 CostFactor + 26, 18, s); 4915 end 4916 end; 4917 if ClientMode <> cEditMap then 4918 begin 4919 TopBar.Canvas.Font.Assign(UniFont[ftCaption]); 4920 s := TurnToString(MyRO.Turn); 4921 RisedTextOut(TopBar.Canvas, 4922 40 + (xTreasurySection - 40 - BiColorTextWidth(TopBar.Canvas, s)) 4923 div 2, 6, s); 4924 TopBar.Canvas.Font.Assign(UniFont[ftNormal]); 4925 end; 4926 RectInvalidate(0, 0, ClientWidth, TopBarHeight); 4927 end; { PanelPaint } 4928 4929 procedure TMainScreen.FocusOnLoc(Loc: integer; Options: integer = 0); 4930 var 4931 dx: integer; 4932 Outside, Changed: boolean; 4933 begin 4934 dx := G.lx + 1 - (xw - Loc + G.lx * 1024 + 1) mod G.lx; 4935 Outside := (dx >= (MapWidth + 1) div (xxt * 2) - 2) or (ywmax > 0) and 4936 ((yw > 0) and (Loc div G.lx <= yw + 1) or (yw < ywmax) and 4937 (Loc div G.lx >= yw + (MapHeight - 1) div yyt - 2)); 4938 Changed := true; 4939 if Outside then 4940 begin 4941 Centre(Loc); 4942 PaintAllMaps 4943 end 4944 else if not MapValid then 4945 PaintAllMaps 4946 else 4947 Changed := false; 4948 if Options and flRepaintPanel <> 0 then 4949 PanelPaint; 4950 if Changed and (Options and flImmUpdate <> 0) then 4951 Update; 4952 end; 4953 4954 procedure TMainScreen.NextUnit(NearLoc: integer; AutoTurn: boolean); 4955 var 4956 Dist, TestDist: single; 4957 i, uix, NewFocus: integer; 4958 GotoOnly: boolean; 4959 begin 4960 if ClientMode >= scContact then 4961 exit; 4962 DestinationMarkON := false; 4963 PaintDestination; 4964 for GotoOnly := GoOnPhase downto false do 4965 begin 4966 NewFocus := -1; 4967 for i := 1 to MyRO.nUn do 4968 begin 4969 uix := (UnFocus + i) mod MyRO.nUn; 4970 if (MyUn[uix].Loc >= 0) and (MyUn[uix].Job = jNone) and 4971 (MyUn[uix].Status and (usStay or usRecover or usWaiting) = usWaiting) 4972 and (not GotoOnly or (MyUn[uix].Status and usGoto <> 0)) then 4973 if NearLoc < 0 then 5283 4974 begin 5284 DoCenter := false; 5285 if not supervising and (ClientMode < scContact) then 5286 begin // not in negotiation mode 5287 if (UnFocus >= 0) and (MyUn[UnFocus].Loc = MouseLoc) then 5288 begin // rotate 5289 uix := (UnFocus + 1) mod MyRO.nUn; 5290 i := MyRO.nUn - 1; 5291 while i > 0 do 5292 begin 5293 if (MyUn[uix].Loc = MouseLoc) and (MyUn[uix].Job = jNone) and 5294 (MyUn[uix].Status and (usStay or usRecover or usEnhance or 5295 usWaiting) = usWaiting) then 5296 Break; 5297 dec(i); 5298 uix := (uix + 1) mod MyRO.nUn; 5299 end; 5300 if i = 0 then 5301 uix := UnFocus 5302 end 5303 else 5304 Server(sGetDefender, me, MouseLoc, uix); 5305 if uix <> UnFocus then 5306 SetUnFocus(uix); 5307 TurnComplete := false; 5308 EOT.ButtonIndex := eotGray; 5309 end; 5310 SetTroopLoc(MouseLoc); 5311 PanelPaint; 5312 end // own unit 5313 else if (MyMap[MouseLoc] and fSpiedOut <> 0) and not(ssCtrl in Shift) 5314 then 5315 begin 5316 DoCenter := false; 5317 SetTroopLoc(MouseLoc); 5318 PanelPaint; 4975 NewFocus := uix; 4976 Break 5319 4977 end 5320 4978 else 5321 4979 begin 5322 DoCenter := false; 5323 UnitStatDlg.ShowNewContent_EnemyLoc(wmPersistent, MouseLoc); 5324 end; 5325 if DoCenter then 5326 begin 5327 Centre(MouseLoc); 5328 PaintAllMaps 4980 TestDist := Distance(NearLoc, MyUn[uix].Loc); 4981 if (NewFocus < 0) or (TestDist < Dist) then 4982 begin 4983 NewFocus := uix; 4984 Dist := TestDist 4985 end 4986 end 4987 end; 4988 if GotoOnly then 4989 if NewFocus < 0 then 4990 GoOnPhase := false 4991 else 4992 Break; 4993 end; 4994 if NewFocus >= 0 then 4995 begin 4996 SetUnFocus(NewFocus); 4997 SetTroopLoc(MyUn[NewFocus].Loc); 4998 FocusOnLoc(TroopLoc, flRepaintPanel) 4999 end 5000 else if AutoTurn and not mWaitTurn.Checked then 5001 begin 5002 TurnComplete := true; 5003 SetUnFocus(-1); 5004 SetTroopLoc(-1); 5005 PostMessage(Handle, WM_EOT, 0, 0) 5006 end 5007 else 5008 begin 5009 if { (UnFocus>=0) and } not TurnComplete and EOT.Visible then 5010 Play('TURNEND'); 5011 TurnComplete := true; 5012 SetUnFocus(-1); 5013 SetTroopLoc(-1); 5014 PanelPaint; 5015 end; 5016 end; { NextUnit } 5017 5018 procedure TMainScreen.Scroll(dx, dy: integer); 5019 begin 5020 xw := (xw + G.lx + dx) mod G.lx; 5021 if ywmax > 0 then 5022 begin 5023 yw := yw + 2 * dy; 5024 if yw < 0 then 5025 yw := 0 5026 else if yw > ywmax then 5027 yw := ywmax; 5028 end; 5029 MainOffscreenPaint; 5030 xwMini := xw; 5031 ywMini := yw; 5032 MiniPaint; 5033 CopyMiniToPanel; 5034 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini + 2, 5035 xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini + 5036 2 + G.ly); 5037 Update; 5038 end; 5039 5040 procedure TMainScreen.Timer1Timer(Sender: TObject); 5041 var 5042 dx, dy, speed: integer; 5043 begin 5044 if idle and (me >= 0) and (GameMode <> cMovie) then 5045 if (fsModal in Screen.ActiveForm.FormState) or 5046 (Screen.ActiveForm is TBufferedDrawDlg) and 5047 (TBufferedDrawDlg(Screen.ActiveForm).WindowMode <> wmPersistent) then 5048 begin 5049 BlinkTime := BlinkOnTime + BlinkOffTime - 1; 5050 if not BlinkON then 5051 begin 5052 BlinkON := true; 5053 if UnFocus >= 0 then 5054 PaintLocTemp(MyUn[UnFocus].Loc) 5055 else if TurnComplete and not supervising then 5056 EOT.SetButtonIndexFast(eotBlinkOn) 5329 5057 end 5330 5058 end 5331 else if (ClientMode <> cEditMap) and (Button = mbRight) and 5332 not(ssShift in Shift) then 5333 begin 5334 if supervising then 5335 begin 5336 EditLoc := MouseLoc; 5337 Server(sGetModels, me, 0, nil^); 5338 EmptyMenu(mCreateUnit); 5339 for p1 := 0 to nPl - 1 do 5340 if 1 shl p1 and MyRO.Alive <> 0 then 5341 begin 5342 m := TMenuItem.Create(mCreateUnit); 5343 m.Caption := Tribe[p1].TPhrase('SHORTNAME'); 5344 for emix := MyRO.nEnemyModel - 1 downto 0 do 5345 if (MyRO.EnemyModel[emix].Owner = p1) and 5346 (Server(sCreateUnit - sExecute + p1 shl 4, me, 5347 MyRO.EnemyModel[emix].mix, MouseLoc) >= rExecuted) then 5348 begin 5349 if Tribe[p1].ModelPicture[MyRO.EnemyModel[emix].mix].HGr = 0 5350 then 5351 InitEnemyModel(emix); 5352 m2 := TMenuItem.Create(m); 5353 m2.Caption := Tribe[p1].ModelName[MyRO.EnemyModel[emix].mix]; 5354 m2.Tag := p1 shl 16 + MyRO.EnemyModel[emix].mix; 5355 m2.OnClick := CreateUnitClick; 5356 m.Add(m2); 5357 end; 5358 m.Visible := m.Count > 0; 5359 mCreateUnit.Add(m); 5360 end; 5361 if FullScreen then 5362 EditPopup.Popup(Left + x, Top + y) 5059 else 5060 begin 5061 if Application.Active and not mScrollOff.Checked then 5062 begin 5063 if mScrollFast.Checked then 5064 speed := 2 5363 5065 else 5364 EditPopup.Popup(Left + x + 4, 5365 Top + y + GetSystemMetrics(SM_CYCAPTION) + 4); 5066 speed := 1; 5067 dx := 0; 5068 dy := 0; 5069 if Mouse.CursorPos.y < Screen.height - PanelHeight then 5070 if Mouse.CursorPos.x = 0 then 5071 dx := -speed // scroll left 5072 else if Mouse.CursorPos.x = Screen.width - 1 then 5073 dx := speed; // scroll right 5074 if Mouse.CursorPos.y = 0 then 5075 dy := -speed // scroll up 5076 else if (Mouse.CursorPos.y = Screen.height - 1) and 5077 (Mouse.CursorPos.x >= TerrainBtn.Left + TerrainBtn.width) and 5078 (Mouse.CursorPos.x < xRightPanel + 10 - 8) then 5079 dy := speed; // scroll down 5080 if (dx <> 0) or (dy <> 0) then 5081 begin 5082 if (Screen.ActiveForm <> MainScreen) and 5083 (@Screen.ActiveForm.OnDeactivate <> nil) then 5084 Screen.ActiveForm.OnDeactivate(nil); 5085 Scroll(dx, dy); 5086 end 5087 end; 5088 5089 BlinkTime := (BlinkTime + 1) mod (BlinkOnTime + BlinkOffTime); 5090 BlinkON := BlinkTime >= BlinkOffTime; 5091 DestinationMarkON := true; 5092 if UnFocus >= 0 then 5093 begin 5094 if (BlinkTime = 0) or (BlinkTime = BlinkOffTime) then 5095 begin 5096 PaintLocTemp(MyUn[UnFocus].Loc, pltsBlink); 5097 PaintDestination; 5098 // if MoveHintToLoc>=0 then 5099 // ShowMoveHint(MoveHintToLoc, true); 5100 end 5366 5101 end 5367 else if (UnFocus >= 0) and (MyUn[UnFocus].Loc <> MouseLoc) then 5368 with MyUn[UnFocus] do 5369 begin 5370 dx := ((MouseLoc mod G.lx * 2 + MouseLoc div G.lx and 1) - 5371 (Loc mod G.lx * 2 + Loc div G.lx and 1) + 3 * G.lx) 5372 mod (2 * G.lx) - G.lx; 5373 dy := MouseLoc div G.lx - Loc div G.lx; 5374 if abs(dx) + abs(dy) < 3 then 5375 begin 5376 DestinationMarkON := false; 5377 PaintDestination; 5378 Status := Status and 5379 ($FFFF - usStay - usRecover - usGoto - usEnhance) or usWaiting; 5380 MoveUnit(dx, dy, muAutoNext) { simple move } 5381 end 5382 else if GetMoveAdvice(UnFocus, MouseLoc, MoveAdviceData) >= rExecuted 5383 then 5384 begin 5385 if MyMap[MouseLoc] and (fUnit or fOwned) = fUnit then 5386 begin // check for suicide mission before movement 5387 with MyUn[UnFocus], BattleDlg.Forecast do 5388 begin 5389 pAtt := me; 5390 mixAtt := mix; 5391 HealthAtt := Health; 5392 ExpAtt := Exp; 5393 FlagsAtt := Flags; 5394 end; 5395 BattleDlg.Forecast.Movement := MyUn[UnFocus].Movement; 5396 if (Server(sGetBattleForecastEx, me, MouseLoc, BattleDlg.Forecast) 5397 >= rExecuted) and (BattleDlg.Forecast.EndHealthAtt <= 0) then 5398 begin 5399 BattleDlg.uix := UnFocus; 5400 BattleDlg.ToLoc := MouseLoc; 5401 BattleDlg.IsSuicideQuery := true; 5402 BattleDlg.ShowModal; 5403 if BattleDlg.ModalResult <> mrOK then 5404 exit; 5405 end 5406 end; 5407 DestinationMarkON := false; 5408 PaintDestination; 5409 Status := Status and not(usStay or usRecover or usEnhance) or 5410 usWaiting; 5411 MoveToLoc(MouseLoc, false); { goto } 5412 end 5413 end 5414 end 5415 else if (Button = mbMiddle) and (UnFocus >= 0) and 5416 (MyModel[MyUn[UnFocus].mix].Kind in [mkSettler, mkSlaves]) then 5417 begin 5418 DestinationMarkON := false; 5419 PaintDestination; 5420 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 5421 ($FFFF - usStay - usRecover - usGoto) or usEnhance; 5422 uix := UnFocus; 5423 if MouseLoc <> MyUn[uix].Loc then 5424 MoveToLoc(MouseLoc, true); { goto } 5425 if (UnFocus = uix) and (MyUn[uix].Loc = MouseLoc) then 5426 MenuClick(mEnhance) 5427 end 5428 else if (Button = mbLeft) and (ssShift in Shift) and 5429 (MyMap[MouseLoc] and fTerrain <> fUNKNOWN) then 5430 HelpOnTerrain(MouseLoc, wmPersistent) 5431 else if (ClientMode <= cContinue) and (Button = mbRight) and 5432 (ssShift in Shift) and (UnFocus >= 0) and 5433 (MyMap[MouseLoc] and (fUnit or fOwned) = fUnit) then 5434 begin // battle forecast 5435 with MyUn[UnFocus], BattleDlg.Forecast do 5436 begin 5437 pAtt := me; 5438 mixAtt := mix; 5439 HealthAtt := Health; 5440 ExpAtt := Exp; 5441 FlagsAtt := Flags; 5442 end; 5443 BattleDlg.Forecast.Movement := MyUn[UnFocus].Movement; 5444 if Server(sGetBattleForecastEx, me, MouseLoc, BattleDlg.Forecast) >= rExecuted 5445 then 5446 begin 5447 BattleDlg.uix := UnFocus; 5448 BattleDlg.ToLoc := MouseLoc; 5449 BattleDlg.Left := x - BattleDlg.width div 2; 5450 if BattleDlg.Left < 0 then 5451 BattleDlg.Left := 0 5452 else if BattleDlg.Left + BattleDlg.width > Screen.width then 5453 BattleDlg.Left := Screen.width - BattleDlg.width; 5454 BattleDlg.Top := y - BattleDlg.height div 2; 5455 if BattleDlg.Top < 0 then 5456 BattleDlg.Top := 0 5457 else if BattleDlg.Top + BattleDlg.height > Screen.height then 5458 BattleDlg.Top := Screen.height - BattleDlg.height; 5459 BattleDlg.IsSuicideQuery := false; 5460 BattleDlg.Show; 5102 else if TurnComplete and not supervising then 5103 begin 5104 if BlinkTime = 0 then 5105 EOT.SetButtonIndexFast(eotBlinkOff) 5106 else if BlinkTime = BlinkOffTime then 5107 EOT.SetButtonIndexFast(eotBlinkOn) 5461 5108 end 5462 5109 end 5110 end; 5111 5112 procedure TMainScreen.Centre(Loc: integer); 5113 begin 5114 if FastScrolling and MapValid then 5115 Update; 5116 // necessary because ScrollDC for form canvas is called after 5117 xw := (Loc mod G.lx - (MapWidth - xxt * 2 * ((Loc div G.lx) and 1)) 5118 div (xxt * 4) + G.lx) mod G.lx; 5119 if ywmax <= 0 then 5120 yw := ywcenter 5121 else 5122 begin 5123 yw := (Loc div G.lx - MapHeight div (yyt * 2) + 1) and not 1; 5124 if yw < 0 then 5125 yw := 0 5126 else if yw > ywmax then 5127 yw := ywmax; 5128 end 5129 end; 5130 5131 function TMainScreen.ZoomToCity(Loc: integer; NextUnitOnClose: boolean = false; 5132 ShowEvent: integer = 0): boolean; 5133 begin 5134 result := MyMap[Loc] and (fOwned or fSpiedOut) <> 0; 5135 if result then 5136 with CityDlg do 5137 begin 5138 if ClientMode >= scContact then 5139 begin 5140 CloseAction := None; 5141 RestoreUnFocus := -1; 5142 end 5143 else if NextUnitOnClose then 5144 begin 5145 CloseAction := StepFocus; 5146 RestoreUnFocus := -1; 5147 end 5148 else if not Visible then 5149 begin 5150 CloseAction := RestoreFocus; 5151 RestoreUnFocus := UnFocus; 5152 end; 5153 SetUnFocus(-1); 5154 SetTroopLoc(Loc); 5155 MarkCityLoc := Loc; 5156 PanelPaint; 5157 ShowNewContent(wmPersistent, Loc, ShowEvent); 5158 end 5159 end; 5160 5161 function TMainScreen.LocationOfScreenPixel(x, y: integer): integer; 5162 var 5163 qx, qy: integer; 5164 begin 5165 qx := (x * (yyt * 2) + y * (xxt * 2) + xxt * yyt * 2) div (xxt * yyt * 4) - 1; 5166 qy := (y * (xxt * 2) - x * (yyt * 2) - xxt * yyt * 2 + 4000 * xxt * yyt) 5167 div (xxt * yyt * 4) - 999; 5168 result := (xw + (qx - qy + 2048) div 2 - 1024 + G.lx) mod G.lx + G.lx * 5169 (yw + qx + qy); 5170 end; 5171 5172 procedure TMainScreen.MapBoxMouseDown(Sender: TObject; Button: TMouseButton; 5173 Shift: TShiftState; x, y: integer); 5174 var 5175 i, uix, emix, p1, dx, dy, MouseLoc: integer; 5176 EditTileData: TEditTileData; 5177 m, m2: TMenuItem; 5178 MoveAdviceData: TMoveAdviceData; 5179 DoCenter: boolean; 5180 begin 5181 if GameMode = cMovie then 5182 exit; 5183 5184 if CityDlg.Visible then 5185 CityDlg.Close; 5186 if UnitStatDlg.Visible then 5187 UnitStatDlg.Close; 5188 MouseLoc := LocationOfScreenPixel(x, y); 5189 if (MouseLoc < 0) or (MouseLoc >= G.lx * G.ly) then 5190 exit; 5191 if (Button = mbLeft) and not(ssShift in Shift) then 5192 begin 5193 DoCenter := true; 5194 if ClientMode = cEditMap then 5195 begin 5196 DoCenter := false; 5197 EditTileData.Loc := MouseLoc; 5198 if ssCtrl in Shift then // toggle special resource 5199 case MyMap[MouseLoc] and fTerrain of 5200 fOcean: 5201 EditTileData.NewTile := MyMap[MouseLoc]; 5202 fGrass, fArctic: 5203 EditTileData.NewTile := MyMap[MouseLoc] and not fSpecial or 5204 ((MyMap[MouseLoc] shr 5 and 3 + 1) mod 2 shl 5); 5205 else 5206 EditTileData.NewTile := MyMap[MouseLoc] and not fSpecial or 5207 ((MyMap[MouseLoc] shr 5 and 3 + 1) mod 3 shl 5) 5208 end 5209 else if BrushType <= fTerrain then 5210 EditTileData.NewTile := MyMap[MouseLoc] and not fTerrain or fSpecial or 5211 BrushType 5212 else if BrushType and fDeadLands <> 0 then 5213 if MyMap[MouseLoc] and (fDeadLands or fModern) = BrushType and 5214 (fDeadLands or fModern) then 5215 EditTileData.NewTile := MyMap[MouseLoc] and not(fDeadLands or fModern) 5216 else 5217 EditTileData.NewTile := MyMap[MouseLoc] and not(fDeadLands or fModern) 5218 or BrushType 5219 else if BrushType and fTerImp <> 0 then 5220 if MyMap[MouseLoc] and fTerImp = BrushType then 5221 EditTileData.NewTile := MyMap[MouseLoc] and not fTerImp 5222 else 5223 EditTileData.NewTile := MyMap[MouseLoc] and not fTerImp or BrushType 5224 else if BrushType and (fPrefStartPos or fStartPos) <> 0 then 5225 if MyMap[MouseLoc] and (fPrefStartPos or fStartPos) = BrushType and 5226 (fPrefStartPos or fStartPos) then 5227 EditTileData.NewTile := MyMap[MouseLoc] and 5228 not(fPrefStartPos or fStartPos) 5229 else 5230 EditTileData.NewTile := MyMap[MouseLoc] and 5231 not(fPrefStartPos or fStartPos) or BrushType 5232 else 5233 EditTileData.NewTile := MyMap[MouseLoc] xor BrushType; 5234 Server(sEditTile, me, 0, EditTileData); 5235 Edited := true; 5236 BrushLoc := MouseLoc; 5237 PaintLoc(MouseLoc, 2); 5238 MiniPaint; 5239 BitBlt(Panel.Canvas.Handle, xMini + 2, yMini + 2, G.lx * 2, G.ly, 5240 Mini.Canvas.Handle, 0, 0, SRCCOPY); 5241 if ywmax <= 0 then 5242 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (2 * xxt), 5243 yMini + 2, xMini + 1 + G.lx + MapWidth div (2 * xxt), 5244 yMini + 2 + G.ly - 1, MainTexture.clMark, MainTexture.clMark) 5245 else 5246 Frame(Panel.Canvas, xMini + 2 + G.lx - MapWidth div (2 * xxt), 5247 yMini + 2 + yw, xMini + 2 + G.lx + MapWidth div (2 * xxt) - 1, 5248 yMini + 2 + yw + MapHeight div yyt - 2, MainTexture.clMark, 5249 MainTexture.clMark); 5250 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini + 2, 5251 xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini 5252 + 2 + G.ly) 5253 end 5254 else if MyMap[MouseLoc] and fCity <> 0 then { city clicked } 5255 begin 5256 if MyMap[MouseLoc] and (fOwned or fSpiedOut) <> 0 then 5257 begin 5258 ZoomToCity(MouseLoc); 5259 DoCenter := false; 5260 end 5261 else 5262 begin 5263 UnitStatDlg.ShowNewContent_EnemyCity(wmPersistent, MouseLoc); 5264 DoCenter := false; 5265 end 5266 end 5267 else if MyMap[MouseLoc] and fUnit <> 0 then { unit clicked } 5268 if MyMap[MouseLoc] and fOwned <> 0 then 5269 begin 5270 DoCenter := false; 5271 if not supervising and (ClientMode < scContact) then 5272 begin // not in negotiation mode 5273 if (UnFocus >= 0) and (MyUn[UnFocus].Loc = MouseLoc) then 5274 begin // rotate 5275 uix := (UnFocus + 1) mod MyRO.nUn; 5276 i := MyRO.nUn - 1; 5277 while i > 0 do 5278 begin 5279 if (MyUn[uix].Loc = MouseLoc) and (MyUn[uix].Job = jNone) and 5280 (MyUn[uix].Status and (usStay or usRecover or usEnhance or 5281 usWaiting) = usWaiting) then 5282 Break; 5283 dec(i); 5284 uix := (uix + 1) mod MyRO.nUn; 5285 end; 5286 if i = 0 then 5287 uix := UnFocus 5288 end 5289 else 5290 Server(sGetDefender, me, MouseLoc, uix); 5291 if uix <> UnFocus then 5292 SetUnFocus(uix); 5293 TurnComplete := false; 5294 EOT.ButtonIndex := eotGray; 5295 end; 5296 SetTroopLoc(MouseLoc); 5297 PanelPaint; 5298 end // own unit 5299 else if (MyMap[MouseLoc] and fSpiedOut <> 0) and not(ssCtrl in Shift) then 5300 begin 5301 DoCenter := false; 5302 SetTroopLoc(MouseLoc); 5303 PanelPaint; 5304 end 5305 else 5306 begin 5307 DoCenter := false; 5308 UnitStatDlg.ShowNewContent_EnemyLoc(wmPersistent, MouseLoc); 5309 end; 5310 if DoCenter then 5311 begin 5312 Centre(MouseLoc); 5313 PaintAllMaps 5314 end 5315 end 5316 else if (ClientMode <> cEditMap) and (Button = mbRight) and 5317 not(ssShift in Shift) then 5318 begin 5319 if supervising then 5320 begin 5321 EditLoc := MouseLoc; 5322 Server(sGetModels, me, 0, nil^); 5323 EmptyMenu(mCreateUnit); 5324 for p1 := 0 to nPl - 1 do 5325 if 1 shl p1 and MyRO.Alive <> 0 then 5326 begin 5327 m := TMenuItem.Create(mCreateUnit); 5328 m.Caption := Tribe[p1].TPhrase('SHORTNAME'); 5329 for emix := MyRO.nEnemyModel - 1 downto 0 do 5330 if (MyRO.EnemyModel[emix].Owner = p1) and 5331 (Server(sCreateUnit - sExecute + p1 shl 4, me, 5332 MyRO.EnemyModel[emix].mix, MouseLoc) >= rExecuted) then 5333 begin 5334 if Tribe[p1].ModelPicture[MyRO.EnemyModel[emix].mix].HGr = 0 then 5335 InitEnemyModel(emix); 5336 m2 := TMenuItem.Create(m); 5337 m2.Caption := Tribe[p1].ModelName[MyRO.EnemyModel[emix].mix]; 5338 m2.Tag := p1 shl 16 + MyRO.EnemyModel[emix].mix; 5339 m2.OnClick := CreateUnitClick; 5340 m.Add(m2); 5341 end; 5342 m.Visible := m.Count > 0; 5343 mCreateUnit.Add(m); 5344 end; 5345 if FullScreen then 5346 EditPopup.Popup(Left + x, Top + y) 5347 else 5348 EditPopup.Popup(Left + x + 4, 5349 Top + y + GetSystemMetrics(SM_CYCAPTION) + 4); 5350 end 5351 else if (UnFocus >= 0) and (MyUn[UnFocus].Loc <> MouseLoc) then 5352 with MyUn[UnFocus] do 5353 begin 5354 dx := ((MouseLoc mod G.lx * 2 + MouseLoc div G.lx and 1) - 5355 (Loc mod G.lx * 2 + Loc div G.lx and 1) + 3 * G.lx) 5356 mod (2 * G.lx) - G.lx; 5357 dy := MouseLoc div G.lx - Loc div G.lx; 5358 if abs(dx) + abs(dy) < 3 then 5359 begin 5360 DestinationMarkON := false; 5361 PaintDestination; 5362 Status := Status and ($FFFF - usStay - usRecover - usGoto - usEnhance) 5363 or usWaiting; 5364 MoveUnit(dx, dy, muAutoNext) { simple move } 5365 end 5366 else if GetMoveAdvice(UnFocus, MouseLoc, MoveAdviceData) >= rExecuted 5367 then 5368 begin 5369 if MyMap[MouseLoc] and (fUnit or fOwned) = fUnit then 5370 begin // check for suicide mission before movement 5371 with MyUn[UnFocus], BattleDlg.Forecast do 5372 begin 5373 pAtt := me; 5374 mixAtt := mix; 5375 HealthAtt := Health; 5376 ExpAtt := Exp; 5377 FlagsAtt := Flags; 5378 end; 5379 BattleDlg.Forecast.Movement := MyUn[UnFocus].Movement; 5380 if (Server(sGetBattleForecastEx, me, MouseLoc, BattleDlg.Forecast) 5381 >= rExecuted) and (BattleDlg.Forecast.EndHealthAtt <= 0) then 5382 begin 5383 BattleDlg.uix := UnFocus; 5384 BattleDlg.ToLoc := MouseLoc; 5385 BattleDlg.IsSuicideQuery := true; 5386 BattleDlg.ShowModal; 5387 if BattleDlg.ModalResult <> mrOK then 5388 exit; 5389 end 5390 end; 5391 DestinationMarkON := false; 5392 PaintDestination; 5393 Status := Status and not(usStay or usRecover or usEnhance) or 5394 usWaiting; 5395 MoveToLoc(MouseLoc, false); { goto } 5396 end 5397 end 5398 end 5399 else if (Button = mbMiddle) and (UnFocus >= 0) and 5400 (MyModel[MyUn[UnFocus].mix].Kind in [mkSettler, mkSlaves]) then 5401 begin 5402 DestinationMarkON := false; 5403 PaintDestination; 5404 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 5405 ($FFFF - usStay - usRecover - usGoto) or usEnhance; 5406 uix := UnFocus; 5407 if MouseLoc <> MyUn[uix].Loc then 5408 MoveToLoc(MouseLoc, true); { goto } 5409 if (UnFocus = uix) and (MyUn[uix].Loc = MouseLoc) then 5410 MenuClick(mEnhance) 5411 end 5412 else if (Button = mbLeft) and (ssShift in Shift) and 5413 (MyMap[MouseLoc] and fTerrain <> fUNKNOWN) then 5414 HelpOnTerrain(MouseLoc, wmPersistent) 5415 else if (ClientMode <= cContinue) and (Button = mbRight) and 5416 (ssShift in Shift) and (UnFocus >= 0) and 5417 (MyMap[MouseLoc] and (fUnit or fOwned) = fUnit) then 5418 begin // battle forecast 5419 with MyUn[UnFocus], BattleDlg.Forecast do 5420 begin 5421 pAtt := me; 5422 mixAtt := mix; 5423 HealthAtt := Health; 5424 ExpAtt := Exp; 5425 FlagsAtt := Flags; 5426 end; 5427 BattleDlg.Forecast.Movement := MyUn[UnFocus].Movement; 5428 if Server(sGetBattleForecastEx, me, MouseLoc, BattleDlg.Forecast) >= rExecuted 5429 then 5430 begin 5431 BattleDlg.uix := UnFocus; 5432 BattleDlg.ToLoc := MouseLoc; 5433 BattleDlg.Left := x - BattleDlg.width div 2; 5434 if BattleDlg.Left < 0 then 5435 BattleDlg.Left := 0 5436 else if BattleDlg.Left + BattleDlg.width > Screen.width then 5437 BattleDlg.Left := Screen.width - BattleDlg.width; 5438 BattleDlg.Top := y - BattleDlg.height div 2; 5439 if BattleDlg.Top < 0 then 5440 BattleDlg.Top := 0 5441 else if BattleDlg.Top + BattleDlg.height > Screen.height then 5442 BattleDlg.Top := Screen.height - BattleDlg.height; 5443 BattleDlg.IsSuicideQuery := false; 5444 BattleDlg.Show; 5445 end 5446 end 5447 end; 5448 5449 function TMainScreen.MoveUnit(dx, dy: integer; Options: integer): integer; 5450 // move focused unit to adjacent tile 5451 var 5452 i, cix, uix, euix, FromLoc, ToLoc, DirCode, UnFocus0, Defender, Mission, p1, 5453 NewTiles, cixChanged: integer; 5454 OldToTile: Cardinal; 5455 CityCaptured, IsAttack, OldUnrest, NewUnrest, NeedEcoUpdate, NeedRepaintPanel, 5456 ToTransport, ToShip: boolean; 5457 PlaneReturnData: TPlaneReturnData; 5458 QueryItem: string; 5459 begin 5460 result := eInvalid; 5461 UnFocus0 := UnFocus; 5462 FromLoc := MyUn[UnFocus].Loc; 5463 ToLoc := dLoc(FromLoc, dx, dy); 5464 if (ToLoc < 0) or (ToLoc >= G.lx * G.ly) then 5465 begin 5466 result := eInvalid; 5467 exit; 5463 5468 end; 5464 5465 function TMainScreen.MoveUnit(dx, dy: integer; Options: integer): integer; 5466 // move focused unit to adjacent tile 5467 var 5468 i, cix, uix, euix, FromLoc, ToLoc, DirCode, UnFocus0, Defender, Mission, p1, 5469 NewTiles, cixChanged: integer; 5470 OldToTile: Cardinal; 5471 CityCaptured, IsAttack, OldUnrest, NewUnrest, NeedEcoUpdate, 5472 NeedRepaintPanel, ToTransport, ToShip: boolean; 5473 PlaneReturnData: TPlaneReturnData; 5474 QueryItem: string; 5475 begin 5476 result := eInvalid; 5477 UnFocus0 := UnFocus; 5478 FromLoc := MyUn[UnFocus].Loc; 5479 ToLoc := dLoc(FromLoc, dx, dy); 5480 if (ToLoc < 0) or (ToLoc >= G.lx * G.ly) then 5469 if MyMap[ToLoc] and fStealthUnit <> 0 then 5470 begin 5471 SoundMessage(Phrases.Lookup('ATTACKSTEALTH'), ''); 5472 exit; 5473 end; 5474 if MyMap[ToLoc] and fHiddenUnit <> 0 then 5475 begin 5476 SoundMessage(Phrases.Lookup('ATTACKSUB'), ''); 5477 exit; 5478 end; 5479 5480 if MyMap[ToLoc] and (fUnit or fOwned) = fUnit then 5481 begin // attack -- search enemy unit 5482 if (MyModel[MyUn[UnFocus].mix].Attack = 0) and 5483 not((MyModel[MyUn[UnFocus].mix].Cap[mcBombs] > 0) and 5484 (MyUn[UnFocus].Flags and unBombsLoaded <> 0)) then 5485 begin 5486 SoundMessage(Phrases.Lookup('NOATTACKER'), ''); 5487 exit; 5488 end; 5489 euix := MyRO.nEnemyUn - 1; 5490 while (euix >= 0) and (MyRO.EnemyUn[euix].Loc <> ToLoc) do 5491 dec(euix); 5492 end; 5493 5494 DirCode := dx and 7 shl 4 + dy and 7 shl 7; 5495 result := Server(sMoveUnit - sExecute + DirCode, me, UnFocus, nil^); 5496 if (result < rExecuted) and (MyUn[UnFocus].Job > jNone) then 5497 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 5498 if (result < rExecuted) and (result <> eNoTime_Move) then 5499 begin 5500 case result of 5501 eNoTime_Load: 5502 if MyModel[MyUn[UnFocus].mix].Domain = dAir then 5503 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'), 'NOMOVE_TIME') 5504 else 5505 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 5506 [MovementToString(MyModel[MyUn[UnFocus].mix].speed)]), 5507 'NOMOVE_TIME'); 5508 eNoTime_Bombard: 5509 SoundMessage(Phrases.Lookup('NOTIMEBOMBARD'), 'NOMOVE_TIME'); 5510 eNoTime_Expel: 5511 SoundMessage(Phrases.Lookup('NOTIMEEXPEL'), 'NOMOVE_TIME'); 5512 eNoRoad: 5513 SoundMessage(Phrases.Lookup('NOROAD'), 'NOMOVE_DEFAULT'); 5514 eNoNav: 5515 SoundMessage(Phrases.Lookup('NONAV'), 'NOMOVE_DEFAULT'); 5516 eNoCapturer: 5517 SoundMessage(Phrases.Lookup('NOCAPTURER'), 'NOMOVE_DEFAULT'); 5518 eNoBombarder: 5519 SoundMessage(Phrases.Lookup('NOBOMBARDER'), 'NOMOVE_DEFAULT'); 5520 eZOC: 5521 ContextMessage(Phrases.Lookup('ZOC'), 'NOMOVE_ZOC', hkText, 5522 HelpDlg.TextIndex('MOVEMENT')); 5523 eTreaty: 5524 if MyMap[ToLoc] and (fUnit or fOwned) <> fUnit 5525 then { no enemy unit -- move } 5526 SoundMessage(Tribe[MyRO.Territory[ToLoc]].TPhrase('PEACE_NOMOVE'), 5527 'NOMOVE_TREATY') 5528 else 5529 SoundMessage(Tribe[MyRO.EnemyUn[euix].Owner] 5530 .TPhrase('PEACE_NOATTACK'), 'NOMOVE_TREATY'); 5531 eDomainMismatch: 5532 begin 5533 if (MyModel[MyUn[UnFocus].mix].Domain < dSea) and 5534 (MyMap[ToLoc] and (fUnit or fOwned) = fUnit or fOwned) then 5535 begin // false load attempt 5536 ToShip := false; 5537 ToTransport := false; 5538 for uix := 0 to MyRO.nUn - 1 do 5539 if (MyUn[uix].Loc = ToLoc) and 5540 (MyModel[MyUn[uix].mix].Domain = dSea) then 5541 begin 5542 ToShip := true; 5543 if MyModel[MyUn[uix].mix].Cap[mcSeaTrans] > 0 then 5544 ToTransport := true; 5545 end; 5546 if ToTransport then 5547 SoundMessage(Phrases.Lookup('FULLTRANSPORT'), 'NOMOVE_DEFAULT') 5548 else if ToShip then 5549 SoundMessage(Phrases.Lookup('NOTRANSPORT'), 'NOMOVE_DEFAULT') 5550 else 5551 Play('NOMOVE_DOMAIN'); 5552 end 5553 else 5554 Play('NOMOVE_DOMAIN'); 5555 end 5556 else 5557 Play('NOMOVE_DEFAULT'); 5558 end; 5559 exit; 5560 end; 5561 5562 if ((result = eWon) or (result = eLost) or (result = eBloody)) and 5563 (MyUn[UnFocus].Movement < 100) and 5564 (MyModel[MyUn[UnFocus].mix].Cap[mcWill] = 0) then 5565 begin 5566 if SimpleQuery(mkYesNo, Format(Phrases.Lookup('FASTATTACK'), 5567 [MyUn[UnFocus].Movement]), 'NOMOVE_TIME') <> mrOK then 5481 5568 begin 5482 5569 result := eInvalid; 5483 5570 exit; 5484 5571 end; 5485 if MyMap[ToLoc] and fStealthUnit <> 0 then 5486 begin 5487 SoundMessage(Phrases.Lookup('ATTACKSTEALTH'), ''); 5488 exit; 5489 end; 5490 if MyMap[ToLoc] and fHiddenUnit <> 0 then 5491 begin 5492 SoundMessage(Phrases.Lookup('ATTACKSUB'), ''); 5493 exit; 5494 end; 5495 5496 if MyMap[ToLoc] and (fUnit or fOwned) = fUnit then 5497 begin // attack -- search enemy unit 5498 if (MyModel[MyUn[UnFocus].mix].Attack = 0) and 5499 not((MyModel[MyUn[UnFocus].mix].Cap[mcBombs] > 0) and 5500 (MyUn[UnFocus].Flags and unBombsLoaded <> 0)) then 5501 begin 5502 SoundMessage(Phrases.Lookup('NOATTACKER'), ''); 5503 exit; 5504 end; 5505 euix := MyRO.nEnemyUn - 1; 5506 while (euix >= 0) and (MyRO.EnemyUn[euix].Loc <> ToLoc) do 5507 dec(euix); 5508 end; 5509 5510 DirCode := dx and 7 shl 4 + dy and 7 shl 7; 5511 result := Server(sMoveUnit - sExecute + DirCode, me, UnFocus, nil^); 5512 if (result < rExecuted) and (MyUn[UnFocus].Job > jNone) then 5513 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 5514 if (result < rExecuted) and (result <> eNoTime_Move) then 5515 begin 5516 case result of 5517 eNoTime_Load: 5518 if MyModel[MyUn[UnFocus].mix].Domain = dAir then 5519 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'), 'NOMOVE_TIME') 5520 else 5521 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 5522 [MovementToString(MyModel[MyUn[UnFocus].mix].speed)]), 5523 'NOMOVE_TIME'); 5524 eNoTime_Bombard: 5525 SoundMessage(Phrases.Lookup('NOTIMEBOMBARD'), 'NOMOVE_TIME'); 5526 eNoTime_Expel: 5527 SoundMessage(Phrases.Lookup('NOTIMEEXPEL'), 'NOMOVE_TIME'); 5528 eNoRoad: 5529 SoundMessage(Phrases.Lookup('NOROAD'), 'NOMOVE_DEFAULT'); 5530 eNoNav: 5531 SoundMessage(Phrases.Lookup('NONAV'), 'NOMOVE_DEFAULT'); 5532 eNoCapturer: 5533 SoundMessage(Phrases.Lookup('NOCAPTURER'), 'NOMOVE_DEFAULT'); 5534 eNoBombarder: 5535 SoundMessage(Phrases.Lookup('NOBOMBARDER'), 'NOMOVE_DEFAULT'); 5536 eZOC: 5537 ContextMessage(Phrases.Lookup('ZOC'), 'NOMOVE_ZOC', hkText, 5538 HelpDlg.TextIndex('MOVEMENT')); 5539 eTreaty: 5540 if MyMap[ToLoc] and (fUnit or fOwned) <> fUnit 5541 then { no enemy unit -- move } 5542 SoundMessage(Tribe[MyRO.Territory[ToLoc]].TPhrase('PEACE_NOMOVE'), 5543 'NOMOVE_TREATY') 5544 else 5545 SoundMessage(Tribe[MyRO.EnemyUn[euix].Owner] 5546 .TPhrase('PEACE_NOATTACK'), 'NOMOVE_TREATY'); 5547 eDomainMismatch: 5548 begin 5549 if (MyModel[MyUn[UnFocus].mix].Domain < dSea) and 5550 (MyMap[ToLoc] and (fUnit or fOwned) = fUnit or fOwned) then 5551 begin // false load attempt 5552 ToShip := false; 5553 ToTransport := false; 5554 for uix := 0 to MyRO.nUn - 1 do 5555 if (MyUn[uix].Loc = ToLoc) and 5556 (MyModel[MyUn[uix].mix].Domain = dSea) then 5557 begin 5558 ToShip := true; 5559 if MyModel[MyUn[uix].mix].Cap[mcSeaTrans] > 0 then 5560 ToTransport := true; 5561 end; 5562 if ToTransport then 5563 SoundMessage(Phrases.Lookup('FULLTRANSPORT'), 'NOMOVE_DEFAULT') 5564 else if ToShip then 5565 SoundMessage(Phrases.Lookup('NOTRANSPORT'), 'NOMOVE_DEFAULT') 5566 else 5567 Play('NOMOVE_DOMAIN'); 5568 end 5569 else 5570 Play('NOMOVE_DOMAIN'); 5571 end 5572 Update; // remove message box from screen 5573 end; 5574 5575 OldUnrest := false; 5576 NewUnrest := false; 5577 if (result >= rExecuted) and (result and rUnitRemoved = 0) and 5578 (MyMap[ToLoc] and (fUnit or fOwned) <> fUnit) then 5579 begin 5580 OldUnrest := UnrestAtLoc(UnFocus, FromLoc); 5581 NewUnrest := UnrestAtLoc(UnFocus, ToLoc); 5582 if NewUnrest > OldUnrest then 5583 begin 5584 if MyRO.Government = gDemocracy then 5585 begin 5586 QueryItem := 'UNREST_NOTOWN'; 5587 p1 := me; 5588 end 5572 5589 else 5573 Play('NOMOVE_DEFAULT'); 5574 end; 5575 exit; 5576 end; 5577 5578 if ((result = eWon) or (result = eLost) or (result = eBloody)) and 5579 (MyUn[UnFocus].Movement < 100) and 5580 (MyModel[MyUn[UnFocus].mix].Cap[mcWill] = 0) then 5581 begin 5582 if SimpleQuery(mkYesNo, Format(Phrases.Lookup('FASTATTACK'), 5583 [MyUn[UnFocus].Movement]), 'NOMOVE_TIME') <> mrOK then 5584 begin 5585 result := eInvalid; 5586 exit; 5587 end; 5588 Update; // remove message box from screen 5589 end; 5590 5591 OldUnrest := false; 5592 NewUnrest := false; 5593 if (result >= rExecuted) and (result and rUnitRemoved = 0) and 5594 (MyMap[ToLoc] and (fUnit or fOwned) <> fUnit) then 5595 begin 5596 OldUnrest := UnrestAtLoc(UnFocus, FromLoc); 5597 NewUnrest := UnrestAtLoc(UnFocus, ToLoc); 5598 if NewUnrest > OldUnrest then 5599 begin 5600 if MyRO.Government = gDemocracy then 5601 begin 5602 QueryItem := 'UNREST_NOTOWN'; 5603 p1 := me; 5604 end 5605 else 5606 begin 5607 QueryItem := 'UNREST_FOREIGN'; 5608 p1 := MyRO.Territory[ToLoc]; 5609 end; 5610 with MessgExDlg do 5611 begin 5612 MessgText := Format(Tribe[p1].TPhrase(QueryItem), 5613 [Phrases.Lookup('GOVERNMENT', MyRO.Government)]); 5614 Kind := mkYesNo; 5615 IconKind := mikImp; 5616 IconIndex := imPalace; 5617 ShowModal; 5618 if ModalResult <> mrOK then 5619 begin 5620 result := eInvalid; 5621 exit; 5622 end; 5623 end; 5624 Update; // remove message box from screen 5625 end 5626 end; 5627 5628 if (result >= rExecuted) and (MyModel[MyUn[UnFocus].mix].Domain = dAir) and 5629 (MyUn[UnFocus].Status and usToldNoReturn = 0) then 5630 begin // can plane return? 5631 PlaneReturnData.Fuel := MyUn[UnFocus].Fuel; 5632 if (MyMap[ToLoc] and (fUnit or fOwned) = fUnit) or 5633 (MyMap[ToLoc] and (fCity or fOwned) = fCity) then 5634 begin // attack/expel/bombard -> 100MP 5635 PlaneReturnData.Loc := FromLoc; 5636 PlaneReturnData.Movement := MyUn[UnFocus].Movement - 100; 5637 if PlaneReturnData.Movement < 0 then 5638 PlaneReturnData.Movement := 0; 5639 end 5640 else // move 5641 begin 5642 PlaneReturnData.Loc := ToLoc; 5643 if dx and 1 <> 0 then 5644 PlaneReturnData.Movement := MyUn[UnFocus].Movement - 100 5645 else 5646 PlaneReturnData.Movement := MyUn[UnFocus].Movement - 150; 5647 end; 5648 if Server(sGetPlaneReturn, me, UnFocus, PlaneReturnData) = eNoWay then 5649 begin 5650 if MyModel[MyUn[UnFocus].mix].Kind = mkSpecial_Glider then 5651 QueryItem := 'LOWFUEL_GLIDER' 5652 else 5653 QueryItem := 'LOWFUEL'; 5654 if SimpleQuery(mkYesNo, Phrases.Lookup(QueryItem), 'WARNING_LOWSUPPORT') 5655 <> mrOK then 5590 begin 5591 QueryItem := 'UNREST_FOREIGN'; 5592 p1 := MyRO.Territory[ToLoc]; 5593 end; 5594 with MessgExDlg do 5595 begin 5596 MessgText := Format(Tribe[p1].TPhrase(QueryItem), 5597 [Phrases.Lookup('GOVERNMENT', MyRO.Government)]); 5598 Kind := mkYesNo; 5599 IconKind := mikImp; 5600 IconIndex := imPalace; 5601 ShowModal; 5602 if ModalResult <> mrOK then 5656 5603 begin 5657 5604 result := eInvalid; 5658 5605 exit; 5659 5606 end; 5660 Update; // remove message box from screen 5661 MyUn[UnFocus].Status := MyUn[UnFocus].Status or usToldNoReturn; 5607 end; 5608 Update; // remove message box from screen 5609 end 5610 end; 5611 5612 if (result >= rExecuted) and (MyModel[MyUn[UnFocus].mix].Domain = dAir) and 5613 (MyUn[UnFocus].Status and usToldNoReturn = 0) then 5614 begin // can plane return? 5615 PlaneReturnData.Fuel := MyUn[UnFocus].Fuel; 5616 if (MyMap[ToLoc] and (fUnit or fOwned) = fUnit) or 5617 (MyMap[ToLoc] and (fCity or fOwned) = fCity) then 5618 begin // attack/expel/bombard -> 100MP 5619 PlaneReturnData.Loc := FromLoc; 5620 PlaneReturnData.Movement := MyUn[UnFocus].Movement - 100; 5621 if PlaneReturnData.Movement < 0 then 5622 PlaneReturnData.Movement := 0; 5623 end 5624 else // move 5625 begin 5626 PlaneReturnData.Loc := ToLoc; 5627 if dx and 1 <> 0 then 5628 PlaneReturnData.Movement := MyUn[UnFocus].Movement - 100 5629 else 5630 PlaneReturnData.Movement := MyUn[UnFocus].Movement - 150; 5631 end; 5632 if Server(sGetPlaneReturn, me, UnFocus, PlaneReturnData) = eNoWay then 5633 begin 5634 if MyModel[MyUn[UnFocus].mix].Kind = mkSpecial_Glider then 5635 QueryItem := 'LOWFUEL_GLIDER' 5636 else 5637 QueryItem := 'LOWFUEL'; 5638 if SimpleQuery(mkYesNo, Phrases.Lookup(QueryItem), 'WARNING_LOWSUPPORT') 5639 <> mrOK then 5640 begin 5641 result := eInvalid; 5642 exit; 5643 end; 5644 Update; // remove message box from screen 5645 MyUn[UnFocus].Status := MyUn[UnFocus].Status or usToldNoReturn; 5646 end 5647 end; 5648 5649 if result = eMissionDone then 5650 begin 5651 ModalSelectDlg.ShowNewContent(wmModal, kMission); 5652 Update; // dialog still on screen 5653 Mission := ModalSelectDlg.result; 5654 if Mission < 0 then 5655 exit; 5656 Server(sSetSpyMission + Mission shl 4, me, 0, nil^); 5657 end; 5658 5659 CityCaptured := false; 5660 if result = eNoTime_Move then 5661 Play('NOMOVE_TIME') 5662 else 5663 begin 5664 NeedEcoUpdate := false; 5665 DestinationMarkON := false; 5666 PaintDestination; 5667 if result and rUnitRemoved <> 0 then 5668 CityOptimizer_BeforeRemoveUnit(UnFocus); 5669 IsAttack := (result = eBombarded) or (result <> eMissionDone) and 5670 (MyMap[ToLoc] and (fUnit or fOwned) = fUnit); 5671 if not IsAttack then 5672 begin // move 5673 cix := MyRO.nCity - 1; { look for own city at dest location } 5674 while (cix >= 0) and (MyCity[cix].Loc <> ToLoc) do 5675 dec(cix); 5676 if (result <> eMissionDone) and (MyMap[ToLoc] and fCity <> 0) and (cix < 0) 5677 then 5678 CityCaptured := true; 5679 result := Server(sMoveUnit + DirCode, me, UnFocus, nil^); 5680 case result of 5681 eHiddenUnit: 5682 begin 5683 Play('NOMOVE_SUBMARINE'); 5684 PaintLoc(ToLoc) 5685 end; 5686 eStealthUnit: 5687 begin 5688 Play('NOMOVE_STEALTH'); 5689 PaintLoc(ToLoc) 5690 end; 5691 eZOC_EnemySpotted: 5692 begin 5693 Play('NOMOVE_ZOC'); 5694 PaintLoc(ToLoc, 1) 5695 end; 5696 rExecuted .. maxint: 5697 begin 5698 if result and rUnitRemoved <> 0 then 5699 UnFocus := -1 // unit died 5700 else 5701 begin 5702 assert(UnFocus >= 0); 5703 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 5704 not(usStay or usRecover); 5705 for uix := 0 to MyRO.nUn - 1 do 5706 if MyUn[uix].Master = UnFocus then 5707 MyUn[uix].Status := MyUn[uix].Status and not usWaiting; 5708 if CityCaptured and 5709 (MyRO.Government in [gRepublic, gDemocracy, gFuture]) then 5710 begin // borders have moved, unrest might have changed in any city 5711 CityOptimizer_BeginOfTurn; 5712 NeedEcoUpdate := true; 5713 end 5714 else 5715 begin 5716 if OldUnrest <> NewUnrest then 5717 begin 5718 CityOptimizer_CityChange(MyUn[UnFocus].Home); 5719 for uix := 0 to MyRO.nUn - 1 do 5720 if MyUn[uix].Master = UnFocus then 5721 CityOptimizer_CityChange(MyUn[uix].Home); 5722 NeedEcoUpdate := true; 5723 end; 5724 if (MyRO.Government = gDespotism) and 5725 (MyModel[MyUn[UnFocus].mix].Kind = mkSpecial_TownGuard) then 5726 begin 5727 if MyMap[FromLoc] and fCity <> 0 then 5728 begin // town guard moved out of city in despotism -- reoptimize! 5729 cixChanged := MyRO.nCity - 1; 5730 while (cixChanged >= 0) and 5731 (MyCity[cixChanged].Loc <> FromLoc) do 5732 dec(cixChanged); 5733 assert(cixChanged >= 0); 5734 if cixChanged >= 0 then 5735 begin 5736 CityOptimizer_CityChange(cixChanged); 5737 NeedEcoUpdate := true; 5738 end; 5739 end; 5740 if (MyMap[ToLoc] and fCity <> 0) and not CityCaptured then 5741 begin // town guard moved into city in despotism -- reoptimize! 5742 cixChanged := MyRO.nCity - 1; 5743 while (cixChanged >= 0) and 5744 (MyCity[cixChanged].Loc <> ToLoc) do 5745 dec(cixChanged); 5746 assert(cixChanged >= 0); 5747 if cixChanged >= 0 then 5748 begin 5749 CityOptimizer_CityChange(cixChanged); 5750 NeedEcoUpdate := true; 5751 end; 5752 end; 5753 end; 5754 end; 5755 end; 5756 end; 5757 else 5758 assert(false); 5759 end; 5760 SetTroopLoc(ToLoc); 5761 end 5762 else 5763 begin { enemy unit -- attack } 5764 if result = eBombarded then 5765 Defender := MyRO.Territory[ToLoc] 5766 else 5767 Defender := MyRO.EnemyUn[euix].Owner; 5768 { if MyRO.Treaty[Defender]=trCeaseFire then 5769 if SimpleQuery(mkYesNo,Phrases.Lookup('FRCANCELQUERY_CEASEFIRE'), 5770 'MSG_DEFAULT')<>mrOK then 5771 exit; } 5772 if (Options and muNoSuicideCheck = 0) and (result and rUnitRemoved <> 0) 5773 and (result <> eMissionDone) then 5774 begin // suicide query 5775 with MyUn[UnFocus], BattleDlg.Forecast do 5776 begin 5777 pAtt := me; 5778 mixAtt := mix; 5779 HealthAtt := Health; 5780 ExpAtt := Exp; 5781 FlagsAtt := Flags; 5782 end; 5783 BattleDlg.Forecast.Movement := MyUn[UnFocus].Movement; 5784 Server(sGetBattleForecastEx, me, ToLoc, BattleDlg.Forecast); 5785 BattleDlg.uix := UnFocus; 5786 BattleDlg.ToLoc := ToLoc; 5787 BattleDlg.IsSuicideQuery := true; 5788 BattleDlg.ShowModal; 5789 if BattleDlg.ModalResult <> mrOK then 5790 exit; 5791 end; 5792 5793 cixChanged := -1; 5794 if (result and rUnitRemoved <> 0) and (MyRO.Government = gDespotism) and 5795 (MyModel[MyUn[UnFocus].mix].Kind = mkSpecial_TownGuard) and 5796 (MyMap[FromLoc] and fCity <> 0) then 5797 begin // town guard died in city in despotism -- reoptimize! 5798 cixChanged := MyRO.nCity - 1; 5799 while (cixChanged >= 0) and (MyCity[cixChanged].Loc <> FromLoc) do 5800 dec(cixChanged); 5801 assert(cixChanged >= 0); 5802 end; 5803 5804 for i := 0 to MyRO.nEnemyModel - 1 do 5805 LostArmy[i] := MyRO.EnemyModel[i].Lost; 5806 OldToTile := MyMap[ToLoc]; 5807 result := Server(sMoveUnit + DirCode, me, UnFocus, nil^); 5808 nLostArmy := 0; 5809 for i := 0 to MyRO.nEnemyModel - 1 do 5810 begin 5811 LostArmy[i] := MyRO.EnemyModel[i].Lost - LostArmy[i]; 5812 inc(nLostArmy, LostArmy[i]) 5813 end; 5814 if result and rUnitRemoved <> 0 then 5815 begin 5816 UnFocus := -1; 5817 SetTroopLoc(FromLoc); 5818 end; 5819 if (OldToTile and not MyMap[ToLoc] and fCity <> 0) and 5820 (MyRO.Government in [gRepublic, gDemocracy, gFuture]) then 5821 begin // city was destroyed, borders have moved, unrest might have changed in any city 5822 CityOptimizer_BeginOfTurn; 5823 NeedEcoUpdate := true; 5824 end 5825 else 5826 begin 5827 if cixChanged >= 0 then 5828 begin 5829 CityOptimizer_CityChange(cixChanged); 5830 NeedEcoUpdate := true; 5831 end; 5832 if (result = eWon) or (result = eBloody) or (result = eExpelled) then 5833 begin 5834 CityOptimizer_TileBecomesAvailable(ToLoc); 5835 NeedEcoUpdate := true; 5836 end; 5837 end; 5838 if nLostArmy > 1 then 5839 begin 5840 with MessgExDlg do 5841 begin 5842 Kind := mkOk; 5843 IconKind := mikEnemyArmy; 5844 MessgText := Tribe[Defender].TString(Phrases.Lookup('ARMYLOST', 5845 MyRO.EnemyModel[MyRO.EnemyUn[euix].emix].Domain)); 5846 ShowModal; 5847 end 5662 5848 end 5663 5849 end; 5664 5665 if result = eMissionDone then 5666 begin 5667 ModalSelectDlg.ShowNewContent(wmModal, kMission); 5668 Update; // dialog still on screen 5669 Mission := ModalSelectDlg.result; 5670 if Mission < 0 then 5671 exit; 5672 Server(sSetSpyMission + Mission shl 4, me, 0, nil^); 5850 if result and rUnitRemoved <> 0 then 5851 begin 5852 CityOptimizer_AfterRemoveUnit; 5853 ListDlg.RemoveUnit; 5854 NeedEcoUpdate := true; 5673 5855 end; 5674 5675 CityCaptured := false; 5676 if result = eNoTime_Move then 5677 Play('NOMOVE_TIME') 5856 if NeedEcoUpdate then 5857 begin 5858 UpdateViews(true); 5859 Update 5860 end 5861 end; 5862 5863 if result = eMissionDone then 5864 begin 5865 p1 := MyRO.Territory[ToLoc]; 5866 case Mission of 5867 smStealMap: 5868 begin 5869 MapValid := false; 5870 PaintAllMaps 5871 end; 5872 smStealCivilReport: 5873 TribeMessage(p1, Tribe[p1].TPhrase('DOSSIER_PREPARED'), ''); 5874 smStealMilReport: 5875 ListDlg.ShowNewContent_MilReport(wmPersistent, p1); 5876 end; 5877 end; 5878 5879 if UnFocus >= 0 then 5880 CheckToldNoReturn(UnFocus); 5881 5882 NeedRepaintPanel := false; 5883 if result >= rExecuted then 5884 begin 5885 if CityCaptured and (MyMap[ToLoc] and fCity = 0) then 5886 begin // city destroyed 5887 for i := 0 to 27 do { tell about destroyed wonders } 5888 if (MyRO.Wonder[i].CityID = -2) and (MyData.ToldWonders[i].CityID <> -2) 5889 then 5890 with MessgExDlg do 5891 begin 5892 if WondersDlg.Visible then 5893 WondersDlg.SmartUpdateContent(false); 5894 OpenSound := 'WONDER_DESTROYED'; 5895 MessgText := Format(Phrases.Lookup('WONDERDEST'), 5896 [Phrases.Lookup('IMPROVEMENTS', i)]); 5897 Kind := mkOkHelp; 5898 HelpKind := hkImp; 5899 HelpNo := i; 5900 IconKind := mikImp; 5901 IconIndex := i; 5902 ShowModal; 5903 MyData.ToldWonders[i] := MyRO.Wonder[i]; 5904 end 5905 end; 5906 if CityCaptured and (MyMap[ToLoc] and fCity <> 0) then 5907 begin // city captured 5908 ListDlg.AddCity; 5909 for i := 0 to 27 do { tell about capture of wonders } 5910 if MyRO.City[MyRO.nCity - 1].Built[i] > 0 then 5911 with MessgExDlg do 5912 begin 5913 if WondersDlg.Visible then 5914 WondersDlg.SmartUpdateContent(false); 5915 OpenSound := 'WONDER_CAPTURED'; 5916 MessgText := Format(Tribe[me].TPhrase('WONDERCAPTOWN'), 5917 [Phrases.Lookup('IMPROVEMENTS', i)]); 5918 Kind := mkOkHelp; 5919 HelpKind := hkImp; 5920 HelpNo := i; 5921 IconKind := mikImp; 5922 IconIndex := i; 5923 ShowModal; 5924 MyData.ToldWonders[i] := MyRO.Wonder[i]; 5925 end; 5926 5927 if MyRO.Happened and phStealTech <> 0 then 5928 begin { Temple of Zeus -- choose advance to steal } 5929 ModalSelectDlg.ShowNewContent(wmModal, kStealTech); 5930 Server(sStealTech, me, ModalSelectDlg.result, nil^); 5931 end; 5932 TellNewModels; 5933 5934 cix := MyRO.nCity - 1; 5935 while (cix >= 0) and (MyCity[cix].Loc <> ToLoc) do 5936 dec(cix); 5937 assert(cix >= 0); 5938 MyCity[cix].Status := MyCity[cix].Status and not csResourceWeightsMask or 5939 (3 shl 4); 5940 // captured city, set to maximum growth 5941 NewTiles := 1 shl 13; { exploit central tile only } 5942 Server(sSetCityTiles, me, cix, NewTiles); 5943 end 5678 5944 else 5679 begin 5680 NeedEcoUpdate := false; 5945 NeedRepaintPanel := true; 5946 end; 5947 TellNewContacts; 5948 5949 if (UnFocus >= 0) and (MyUn[UnFocus].Master >= 0) then 5950 with MyUn[MyUn[UnFocus].Master] do 5951 if Status and usStay <> 0 then 5952 begin 5953 Status := Status and not usStay; 5954 if (Movement >= 100) and (Status and (usRecover or usGoto) = 0) then 5955 Status := Status or usWaiting; 5956 end; 5957 if Options and (muAutoNoWait or muAutoNext) <> 0 then 5958 begin 5959 if (UnFocus >= 0) and ((result = eNoTime_Move) or UnitExhausted(UnFocus) or 5960 (MyUn[UnFocus].Master >= 0) or (MyModel[MyUn[UnFocus].mix].Domain = dAir) 5961 and ((MyMap[MyUn[UnFocus].Loc] and fCity <> 0) 5962 { aircrafts stop in cities } 5963 or (MyMap[MyUn[UnFocus].Loc] and fTerImp = tiBase))) then 5964 begin 5965 MyUn[UnFocus].Status := MyUn[UnFocus].Status and not usWaiting; 5966 if Options and muAutoNext <> 0 then 5967 if CityCaptured and (MyMap[ToLoc] and fCity <> 0) then 5968 begin 5969 UnFocus := -1; 5970 PaintLoc(ToLoc); // don't show unit in city if not selected 5971 end 5972 else 5973 NextUnit(UnStartLoc, true) 5974 end 5975 else if (UnFocus < 0) and (Options and muAutoNext <> 0) then 5976 NextUnit(UnStartLoc, result <> eMissionDone); 5977 end; 5978 5979 if NeedRepaintPanel and (UnFocus = UnFocus0) then 5980 if IsAttack then 5981 PanelPaint 5982 else 5983 begin 5984 assert(result <> eMissionDone); 5985 CheckTerrainBtnVisible; 5986 FocusOnLoc(ToLoc, flRepaintPanel or flImmUpdate) 5987 end; 5988 5989 if (result >= rExecuted) and CityCaptured and (MyMap[ToLoc] and fCity <> 0) 5990 then 5991 ZoomToCity(ToLoc, UnFocus < 0, chCaptured); // show captured city 5992 end; // moveunit 5993 5994 procedure TMainScreen.MoveOnScreen(ShowMove: TShowMove; 5995 Step0, Step1, nStep: integer; Restore: boolean = true); 5996 var 5997 ToLoc, xFromLoc, yFromLoc, xToLoc, yToLoc, xFrom, yFrom, xTo, yTo, xMin, yMin, 5998 xRange, yRange, xw1, Step, xMoving, yMoving, yl, SliceCount: integer; 5999 UnitInfo: TUnitInfo; 6000 Ticks0, Ticks: TDateTime; 6001 begin 6002 Timer1.Enabled := false; 6003 Ticks0 := NowPrecise; 6004 with ShowMove do 6005 begin 6006 UnitInfo.Owner := Owner; 6007 UnitInfo.mix := mix; 6008 UnitInfo.Health := Health; 6009 UnitInfo.Job := jNone; 6010 UnitInfo.Flags := Flags; 6011 if Owner <> me then 6012 UnitInfo.emix := emix; 6013 6014 ToLoc := dLoc(FromLoc, dx, dy); 6015 xToLoc := ToLoc mod G.lx; 6016 yToLoc := ToLoc div G.lx; 6017 xFromLoc := FromLoc mod G.lx; 6018 yFromLoc := FromLoc div G.lx; 6019 if xToLoc > xFromLoc + 2 then 6020 xToLoc := xToLoc - G.lx 6021 else if xToLoc < xFromLoc - 2 then 6022 xToLoc := xToLoc + G.lx; 6023 6024 xw1 := xw + G.lx; 6025 // ((xFromLoc-xw1)*2+yFromLoc and 1+1)*xxt+dx*xxt/2-MapWidth/2 -> min 6026 while abs(((xFromLoc - xw1 + G.lx) * 2 + yFromLoc and 1 + 1) * xxt * 2 + dx 6027 * xxt - MapWidth) < abs(((xFromLoc - xw1) * 2 + yFromLoc and 1 + 1) * xxt 6028 * 2 + dx * xxt - MapWidth) do 6029 dec(xw1, G.lx); 6030 6031 xTo := (xToLoc - xw1) * (xxt * 2) + yToLoc and 1 * xxt + (xxt - xxu); 6032 yTo := (yToLoc - yw) * yyt + (yyt - yyu_anchor); 6033 xFrom := (xFromLoc - xw1) * (xxt * 2) + yFromLoc and 1 * xxt + (xxt - xxu); 6034 yFrom := (yFromLoc - yw) * yyt + (yyt - yyu_anchor); 6035 if xFrom < xTo then 6036 begin 6037 xMin := xFrom; 6038 xRange := xTo - xFrom 6039 end 6040 else 6041 begin 6042 xMin := xTo; 6043 xRange := xFrom - xTo 6044 end; 6045 if yFrom < yTo then 6046 begin 6047 yMin := yFrom; 6048 yRange := yTo - yFrom 6049 end 6050 else 6051 begin 6052 yMin := yTo; 6053 yRange := yFrom - yTo 6054 end; 6055 inc(xRange, xxt * 2); 6056 inc(yRange, yyt * 3); 6057 6058 MainOffscreenPaint; 6059 NoMap.SetOutput(Buffer); 6060 NoMap.SetPaintBounds(0, 0, xRange, yRange); 6061 for Step := 0 to abs(Step1 - Step0) do 6062 begin 6063 BitBlt(Buffer.Canvas.Handle, 0, 0, xRange, yRange, 6064 offscreen.Canvas.Handle, xMin, yMin, SRCCOPY); 6065 if Step1 <> Step0 then 6066 begin 6067 xMoving := xFrom + 6068 Round((Step0 + Step * (Step1 - Step0) div abs(Step1 - Step0)) * 6069 (xTo - xFrom) / nStep); 6070 yMoving := yFrom + 6071 Round((Step0 + Step * (Step1 - Step0) div abs(Step1 - Step0)) * 6072 (yTo - yFrom) / nStep); 6073 end 6074 else 6075 begin 6076 xMoving := xFrom; 6077 yMoving := yFrom; 6078 end; 6079 NoMap.PaintUnit(xMoving - xMin, yMoving - yMin, UnitInfo, 0); 6080 PaintBufferToScreen(xMin, yMin, xRange, yRange); 6081 6082 SliceCount := 0; 6083 Ticks := Ticks0; 6084 repeat 6085 if (SliceCount = 0) or 6086 (MillisecondOf(Ticks - Ticks0) * 12 * (SliceCount + 1) div SliceCount 6087 < MoveTime) then 6088 begin 6089 if not idle or (GameMode = cMovie) then 6090 Application.ProcessMessages; 6091 Sleep(1); 6092 inc(SliceCount) 6093 end; 6094 Ticks := NowPrecise; 6095 until (Ticks - Ticks0) / OneMillisecond * 12 >= MoveTime; 6096 Ticks0 := Ticks 6097 end; 6098 end; 6099 if Restore then 6100 begin 6101 BitBlt(Buffer.Canvas.Handle, 0, 0, xRange, yRange, offscreen.Canvas.Handle, 6102 xMin, yMin, SRCCOPY); 6103 PaintBufferToScreen(xMin, yMin, xRange, yRange); 6104 end; 6105 BlinkTime := -1; 6106 Timer1.Enabled := true; 6107 end; 6108 6109 procedure TMainScreen.MoveToLoc(Loc: integer; CheckSuicide: boolean); 6110 // path finder: move focused unit to loc, start multi-turn goto if too far 6111 var 6112 uix, i, MoveOptions, NextLoc, MoveResult: integer; 6113 MoveAdviceData: TMoveAdviceData; 6114 StopReason: (None, Arrived, Dead, NoTime, EnemySpotted, MoveError); 6115 begin 6116 if MyUn[UnFocus].Job > jNone then 6117 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 6118 if GetMoveAdvice(UnFocus, Loc, MoveAdviceData) >= rExecuted then 6119 begin 6120 uix := UnFocus; 6121 StopReason := None; 6122 repeat 6123 for i := 0 to MoveAdviceData.nStep - 1 do 6124 begin 6125 if i = MoveAdviceData.nStep - 1 then 6126 MoveOptions := muAutoNext 6127 else 6128 MoveOptions := 0; 6129 NextLoc := dLoc(MyUn[uix].Loc, MoveAdviceData.dx[i], 6130 MoveAdviceData.dy[i]); 6131 if (NextLoc = Loc) or (Loc = maNextCity) and 6132 (MyMap[NextLoc] and fCity <> 0) then 6133 StopReason := Arrived; 6134 if not CheckSuicide and (NextLoc = Loc) then 6135 MoveOptions := MoveOptions or muNoSuicideCheck; 6136 MoveResult := MoveUnit(MoveAdviceData.dx[i], MoveAdviceData.dy[i], 6137 MoveOptions); 6138 if MoveResult < rExecuted then 6139 StopReason := MoveError 6140 else if MoveResult and rUnitRemoved <> 0 then 6141 StopReason := Dead 6142 else if (StopReason = None) and (MoveResult and rEnemySpotted <> 0) then 6143 StopReason := EnemySpotted; 6144 if StopReason <> None then 6145 Break; 6146 end; 6147 if (StopReason = None) and ((MoveAdviceData.nStep < 25) or 6148 (MyRO.Wonder[woShinkansen].EffectiveOwner <> me)) then 6149 StopReason := NoTime; 6150 if StopReason <> None then 6151 Break; 6152 if GetMoveAdvice(UnFocus, Loc, MoveAdviceData) < rExecuted then 6153 begin 6154 assert(false); 6155 Break 6156 end; 6157 until false; 6158 6159 case StopReason of 6160 None: 6161 assert(false); 6162 Arrived: 6163 MyUn[uix].Status := MyUn[uix].Status and ($FFFF - usGoto); 6164 Dead: 6165 if UnFocus < 0 then 6166 NextUnit(UnStartLoc, false); 6167 else 6168 begin // multi-turn goto 6169 if Loc = maNextCity then 6170 MyUn[uix].Status := MyUn[uix].Status and ($FFFF - usStay - usRecover) 6171 or usGoto + $7FFF shl 16 6172 else 6173 MyUn[uix].Status := MyUn[uix].Status and ($FFFF - usStay - usRecover) 6174 or usGoto + Loc shl 16; 6175 PaintLoc(MyUn[uix].Loc); 6176 if (StopReason = NoTime) and (UnFocus = uix) then 6177 begin 6178 MyUn[uix].Status := MyUn[uix].Status and not usWaiting; 6179 NextUnit(UnStartLoc, true) 6180 end; 6181 end 6182 end 6183 end 6184 end; 6185 6186 procedure TMainScreen.PanelBoxMouseDown(Sender: TObject; Button: TMouseButton; 6187 Shift: TShiftState; x, y: integer); 6188 var 6189 i, xMouse, MouseLoc, p1: integer; 6190 begin 6191 if GameMode = cMovie then 6192 exit; 6193 6194 if Button = mbLeft then 6195 begin 6196 if (x >= xMini + 2) and (y >= yMini + 2) and (x < xMini + 2 + 2 * G.lx) and 6197 (y < yMini + 2 + G.ly) then 6198 if ssShift in Shift then 6199 begin 6200 xMouse := (xwMini + (x - (xMini + 2) + MapWidth div (xxt * 2) + G.lx) 6201 div 2) mod G.lx; 6202 MouseLoc := xMouse + G.lx * (y - (yMini + 2)); 6203 if MyMap[MouseLoc] and fTerrain <> fUNKNOWN then 6204 begin 6205 p1 := MyRO.Territory[MouseLoc]; 6206 if (p1 = me) or (p1 >= 0) and (MyRO.Treaty[p1] >= trNone) then 6207 NatStatDlg.ShowNewContent(wmPersistent, p1); 6208 end 6209 end 6210 else 6211 begin 6212 if CityDlg.Visible then 6213 CityDlg.Close; 6214 if UnitStatDlg.Visible then 6215 UnitStatDlg.Close; 6216 Tracking := true; 6217 PanelBoxMouseMove(Sender, Shift + [ssLeft], x, y); 6218 end 6219 else if (ClientMode <> cEditMap) and (x >= ClientWidth - xPalace) and 6220 (y >= yPalace) and (x < ClientWidth - xPalace + xSizeBig) and 6221 (y < yPalace + ySizeBig) then 6222 begin 6223 InitPopup(StatPopup); 6224 if FullScreen then 6225 StatPopup.Popup(Left + ClientWidth - xPalace + xSizeBig + 2, 6226 Top + ClientHeight - PanelHeight + yPalace - 1) 6227 else 6228 StatPopup.Popup(Left + ClientWidth - xPalace + 6, 6229 Top + ClientHeight - PanelHeight + yPalace + ySizeBig + 6230 GetSystemMetrics(SM_CYCAPTION) + 3) 6231 end 6232 (* else if (x>=xAdvisor-3) and (y>=yAdvisor-3) 6233 and (x<xAdvisor+16+3) and (y<yAdvisor+16+3) and HaveStrategyAdvice then 6234 AdviceBtnClick *) 6235 else if (x >= xTroop + 1) and (y >= yTroop + 1) and 6236 (x < xTroop + TrRow * TrPitch) and (y <= yTroop + 55) then 6237 begin 6238 i := (x - xTroop - 1) div TrPitch; 6239 if trix[i] >= 0 then 6240 if ClientMode = cEditMap then 6241 begin 6242 BrushType := trix[i]; 6243 PanelPaint 6244 end 6245 else if (TroopLoc >= 0) then 6246 if MyMap[TroopLoc] and fOwned <> 0 then 6247 begin 6248 if ssShift in Shift then 6249 UnitStatDlg.ShowNewContent_OwnModel(wmPersistent, 6250 MyUn[trix[i]].mix) 6251 else if not supervising and (ClientMode < scContact) and 6252 (x - xTroop - 1 - i * TrPitch >= 60 - 20) and (y >= yTroop + 35) 6253 and ((MyUn[trix[i]].Job > jNone) or (MyUn[trix[i]].Status and 6254 (usStay or usRecover or usGoto) <> 0)) then 6255 begin // wake up 6256 MyUn[trix[i]].Status := MyUn[trix[i]].Status and 6257 ($FFFF - usStay - usRecover - usGoto - usEnhance) or usWaiting; 6258 if MyUn[trix[i]].Job > jNone then 6259 Server(sStartJob + jNone shl 4, me, trix[i], nil^); 6260 if (UnFocus < 0) and not CityDlg.Visible then 6261 begin 6262 SetUnFocus(trix[i]); 6263 SetTroopLoc(MyUn[trix[i]].Loc); 6264 FocusOnLoc(TroopLoc, flRepaintPanel) 6265 end 6266 else 6267 begin 6268 if CityDlg.Visible and (CityDlg.RestoreUnFocus < 0) then 6269 CityDlg.RestoreUnFocus := trix[i]; 6270 PanelPaint; 6271 end 6272 end 6273 else if (ClientMode < scContact) then 6274 begin 6275 if supervising then 6276 UnitStatDlg.ShowNewContent_OwnUnit(wmPersistent, trix[i]) 6277 else if CityDlg.Visible then 6278 begin 6279 CityDlg.CloseAction := None; 6280 CityDlg.Close; 6281 SumCities(TaxSum, ScienceSum); 6282 SetUnFocus(trix[i]); 6283 end 6284 else 6285 begin 6286 DestinationMarkON := false; 6287 PaintDestination; 6288 UnFocus := trix[i]; 6289 UnStartLoc := TroopLoc; 6290 BlinkTime := 0; 6291 BlinkON := false; 6292 PaintLoc(TroopLoc); 6293 end; 6294 if UnFocus >= 0 then 6295 begin 6296 UnitInfoBtn.Visible := true; 6297 UnitBtn.Visible := true; 6298 TurnComplete := false; 6299 EOT.ButtonIndex := eotGray; 6300 end; 6301 CheckTerrainBtnVisible; 6302 PanelPaint; 6303 end 6304 end 6305 else if Server(sGetUnits, me, TroopLoc, TrCnt) >= rExecuted then 6306 if ssShift in Shift then 6307 UnitStatDlg.ShowNewContent_EnemyModel(wmPersistent, 6308 MyRO.EnemyUn[MyRO.nEnemyUn + trix[i]].emix) // model info 6309 else 6310 UnitStatDlg.ShowNewContent_EnemyUnit(wmPersistent, 6311 MyRO.nEnemyUn + trix[i]); // unit info 6312 end 6313 end 6314 end; 6315 6316 procedure TMainScreen.SetTroopLoc(Loc: integer); 6317 var 6318 trixFocus, uix, uixDefender: integer; 6319 Prio: boolean; 6320 begin 6321 TroopLoc := Loc; 6322 TrRow := (xRightPanel + 10 - xTroop - GetSystemMetrics(SM_CXVSCROLL) - 19) 6323 div TrPitch; 6324 TrCnt := 0; 6325 trixFocus := -1; 6326 if ClientMode = cEditMap then 6327 TrCnt := nBrushTypes 6328 else if (Loc >= 0) and (MyMap[Loc] and fUnit <> 0) then 6329 if MyMap[Loc] and fOwned <> 0 then 6330 begin // count own units here 6331 Server(sGetDefender, me, TroopLoc, uixDefender); 6332 for Prio := true downto false do 6333 for uix := 0 to MyRO.nUn - 1 do 6334 if ((uix = uixDefender) = Prio) and (MyUn[uix].Loc = Loc) then 6335 begin 6336 if uix = UnFocus then 6337 trixFocus := TrCnt; 6338 inc(TrCnt); 6339 end 6340 end 6341 else // count enemy units here 6342 Server(sGetUnits, me, Loc, TrCnt); 6343 if TrCnt = 0 then 6344 InitPVSB(sb, 0, 1) 6345 else 6346 begin 6347 InitPVSB(sb, (TrCnt + TrRow - 1) div TrRow - 1, 1); 6348 with sb.si do 6349 if (nMax >= integer(nPage)) and (trixFocus >= 0) then 6350 begin 6351 sb.si.npos := trixFocus div TrRow; 6352 sb.si.FMask := SIF_POS; 6353 SetScrollInfo(sb.h, SB_CTL, sb.si, true); 6354 end 6355 end 6356 end; 6357 6358 (* procedure TMainScreen.ShowMoveHint(ToLoc: integer; Force: boolean = false); 6359 var 6360 Step,Loc,x0,y0,xs,ys: integer; 6361 Info: string; 6362 InfoSize: TSize; 6363 MoveAdvice: TMoveAdviceData; 6364 begin 6365 if (ToLoc<0) or (ToLoc>=G.lx*G.ly) 6366 or (UnFocus<0) or (MyUn[UnFocus].Loc=ToLoc) then 6367 ToLoc:=-1 6368 else 6369 begin 6370 MoveAdvice.ToLoc:=ToLoc; 6371 MoveAdvice.MoreTurns:=0; 6372 MoveAdvice.MaxHostile_MovementLeft:=MyUn[UnFocus].Health-50; 6373 if Server(sGetMoveAdvice,me,UnFocus,MoveAdvice)<rExecuted then 6374 ToLoc:=-1 6375 end; 6376 if (ToLoc=MoveHintToLoc) and not Force then exit; 6377 if (ToLoc<>MoveHintToLoc) and (MoveHintToLoc>=0) then 6378 begin invalidate; update end; // clear old hint from screen 6379 MoveHintToLoc:=ToLoc; 6380 if ToLoc<0 then exit; 6381 6382 with canvas do 6383 begin 6384 Pen.Color:=$80C0FF; 6385 Pen.Width:=3; 6386 Loc:=MyUn[UnFocus].Loc; 6387 for Step:=0 to MoveAdvice.nStep do 6388 begin 6389 y0:=(Loc+G.lx*1024) div G.lx -1024; 6390 x0:=(Loc+(y0 and 1+G.lx*1024) div 2) mod G.lx; 6391 xs:=(x0-xw)*66+y0 and 1*33-G.lx*66; 6392 while abs(2*(xs+G.lx*66)-MapWidth)<abs(2*xs-MapWidth) do 6393 inc(xs,G.lx*66); 6394 ys:=(y0-yw)*16; 6395 if Step=0 then moveto(xs+33,ys+16) 6396 else lineto(xs+33,ys+16); 6397 if Step<MoveAdvice.nStep then 6398 Loc:=dLoc(Loc,MoveAdvice.dx[Step],MoveAdvice.dy[Step]); 6399 end; 6400 Brush.Color:=$80C0FF; 6401 Info:=' '+inttostr(88)+' '; 6402 InfoSize:=TextExtent(Info); 6403 TextOut(xs+33-InfoSize.cx div 2, ys+16-InfoSize.cy div 2, Info); 6404 Brush.Style:=bsClear; 6405 end 6406 end; *) 6407 6408 procedure TMainScreen.SetDebugMap(p: integer); 6409 begin 6410 IsoEngine.pDebugMap := p; 6411 IsoEngine.Options := IsoEngine.Options and not(1 shl moLocCodes); 6412 mLocCodes.Checked := false; 6413 MapValid := false; 6414 MainOffscreenPaint; 6415 end; 6416 6417 procedure TMainScreen.SetViewpoint(p: integer); 6418 var 6419 i: integer; 6420 begin 6421 if supervising and (G.RO[0].Turn > 0) and 6422 ((p = 0) or (1 shl p and G.RO[0].Alive <> 0)) then 6423 begin 6424 for i := 0 to Screen.FormCount - 1 do 6425 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 6426 Screen.Forms[i].Close; // close windows 6427 ItsMeAgain(p); 6428 SumCities(TaxSum, ScienceSum); 6429 for i := 0 to MyRO.nModel - 1 do 6430 if Tribe[me].ModelPicture[i].HGr = 0 then 6431 InitMyModel(i, true); 6432 6433 SetTroopLoc(-1); 6434 PanelPaint; 6435 MapValid := false; 6436 PaintAllMaps; 6437 end 6438 end; 6439 6440 procedure TMainScreen.FormKeyDown(Sender: TObject; var Key: word; 6441 Shift: TShiftState); 6442 6443 procedure MenuClick_Check(Popup: TPopupMenu; Item: TMenuItem); 6444 begin 6445 InitPopup(Popup); 6446 if Item.Visible and Item.Enabled then 6447 MenuClick(Item); 6448 end; 6449 6450 var 6451 dx, dy: integer; 6452 time0, time1: TDateTime; 6453 begin 6454 if GameMode = cMovie then 6455 begin 6456 case Key of 6457 VK_F4: 6458 MenuClick_Check(StatPopup, mScienceStat); 6459 VK_F6: 6460 MenuClick_Check(StatPopup, mDiagram); 6461 VK_F7: 6462 MenuClick_Check(StatPopup, mWonders); 6463 VK_F8: 6464 MenuClick_Check(StatPopup, mShips); 6465 end; 6466 exit; 6467 end; 6468 6469 if not idle then 6470 exit; 6471 6472 if ClientMode = cEditMap then 6473 begin 6474 if Shift = [ssCtrl] then 6475 case char(Key) of 6476 (* 'A': 6477 begin // auto symmetry 6478 Server($7F0,me,0,nil^); 6479 MapValid:=false; 6480 PaintAll; 6481 end; 6482 'B': 6483 begin // land mass 6484 dy:=0; 6485 for dx:=G.lx to G.lx*(G.ly-1)-1 do 6486 if MyMap[dx] and fTerrain>=fGrass then inc(dy); 6487 dy:=dy 6488 end; *) 6489 'Q': 6490 MenuClick(mResign); 6491 'R': 6492 MenuClick(mRandomMap); 6493 end 6494 else if Shift = [] then 6495 case char(Key) of 6496 char(VK_F1): 6497 MenuClick(mHelp); 6498 end; 6499 exit; 6500 end; 6501 6502 if Shift = [ssAlt] then 6503 case char(Key) of 6504 '0': 6505 SetDebugMap(-1); 6506 '1' .. '9': 6507 SetDebugMap(ord(Key) - 48); 6508 end 6509 else if Shift = [ssCtrl] then 6510 case char(Key) of 6511 'J': 6512 MenuClick(mJump); 6513 'K': 6514 mShowClick(mDebugMap); 6515 'L': 6516 mShowClick(mLocCodes); 6517 'M': 6518 if LogDlg.Visible then 6519 LogDlg.Close 6520 else 6521 LogDlg.Show; 6522 'N': 6523 mNamesClick(mNames); 6524 'Q': 6525 MenuClick_Check(GamePopup, mResign); 6526 'R': 6527 MenuClick(mRun); 6528 '0' .. '9': 6529 begin 6530 if ord(Key) - 48 = me then 6531 SetViewpoint(0) 6532 else 6533 SetViewpoint(ord(Key) - 48); 6534 end; 6535 ' ': 6536 begin // test map repaint time 6537 time0 := NowPrecise; 6538 MapValid := false; 6539 MainOffscreenPaint; 6540 time1 := NowPrecise; 6541 SimpleMessage(Format('Map repaint time: %.3f ms', 6542 [MillisecondOf(time1 - time0)])); 6543 end 6544 end 6545 else if Shift = [] then 6546 case char(Key) of 6547 char(VK_F1): 6548 MenuClick(mHelp); 6549 char(VK_F2): 6550 MenuClick_Check(StatPopup, mUnitStat); 6551 char(VK_F3): 6552 MenuClick_Check(StatPopup, mCityStat); 6553 char(VK_F4): 6554 MenuClick_Check(StatPopup, mScienceStat); 6555 char(VK_F5): 6556 MenuClick_Check(StatPopup, mEUnitStat); 6557 char(VK_F6): 6558 MenuClick_Check(StatPopup, mDiagram); 6559 char(VK_F7): 6560 MenuClick_Check(StatPopup, mWonders); 6561 char(VK_F8): 6562 MenuClick_Check(StatPopup, mShips); 6563 char(VK_F9): 6564 MenuClick_Check(StatPopup, mNations); 6565 char(VK_F10): 6566 MenuClick_Check(StatPopup, mEmpire); 6567 char(VK_ADD): 6568 EndTurn; 6569 '1': 6570 MapBtnClick(MapBtn0); 6571 '2': 6572 MapBtnClick(MapBtn1); 6573 '3': 6574 MapBtnClick(MapBtn4); 6575 '4': 6576 MapBtnClick(MapBtn5); 6577 '5': 6578 MapBtnClick(MapBtn6); 6579 'T': 6580 MenuClick(mTechTree); 6581 'W': 6582 MenuClick(mWait); 6583 end; 6584 6585 if UnFocus >= 0 then 6586 if Shift = [ssCtrl] then 6587 case char(Key) of 6588 'C': 6589 MenuClick_Check(UnitPopup, mCancel); 6590 'D': 6591 MenuClick(mDisband); 6592 'P': 6593 MenuClick_Check(UnitPopup, mPillage); 6594 'T': 6595 MenuClick_Check(UnitPopup, mSelectTransport); 6596 end 6597 else if Shift = [] then 6598 case char(Key) of 6599 ' ': 6600 MenuClick(mNoOrders); 6601 'A': 6602 MenuClick_Check(TerrainPopup, mAirBase); 6603 'B': 6604 MenuClick_Check(UnitPopup, mCity); 6605 'C': 6606 MenuClick(mCentre); 6607 'E': 6608 begin 6609 InitPopup(TerrainPopup); 6610 if mEnhance.Visible and mEnhance.Enabled then 6611 MenuClick(mEnhance) 6612 else 6613 MenuClick(mEnhanceDef) 6614 end; 6615 'F': 6616 MenuClick_Check(TerrainPopup, mFort); 6617 'G': 6618 MenuClick_Check(UnitPopup, mGoOn); 6619 'H': 6620 MenuClick_Check(UnitPopup, mHome); 6621 'I': 6622 if JobTest(UnFocus, jFarm, [eTreaty]) then 6623 MenuClick(mFarm) 6624 else if JobTest(UnFocus, jClear, [eTreaty]) then 6625 MenuClick(mClear) 6626 else 6627 MenuClick_Check(TerrainPopup, mIrrigation); 6628 'L': 6629 MenuClick_Check(UnitPopup, mLoad); 6630 'M': 6631 if JobTest(UnFocus, jAfforest, [eTreaty]) then 6632 MenuClick(mAfforest) 6633 else 6634 MenuClick_Check(TerrainPopup, mMine); 6635 'N': 6636 MenuClick_Check(TerrainPopup, mCanal); 6637 'O': 6638 MenuClick_Check(TerrainPopup, MTrans); 6639 'P': 6640 MenuClick_Check(TerrainPopup, mPollution); 6641 'R': 6642 if JobTest(UnFocus, jRR, [eTreaty]) then 6643 MenuClick(mRR) 6644 else 6645 MenuClick_Check(TerrainPopup, mRoad); 6646 'S': 6647 MenuClick(mStay); 6648 'U': 6649 MenuClick_Check(UnitPopup, mUnload); 6650 'V': 6651 MenuClick_Check(UnitPopup, mRecover); 6652 'Z': 6653 MenuClick_Check(UnitPopup, mUtilize); 6654 #33 .. #40, #97 .. #100, #102 .. #105: 6655 begin { arrow keys } 6656 DestinationMarkON := false; 6657 PaintDestination; 6658 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 6659 ($FFFF - usStay - usRecover - usGoto - usEnhance) or usWaiting; 6660 case Key of 6661 VK_NUMPAD1, VK_END: 6662 begin 6663 dx := -1; 6664 dy := 1 6665 end; 6666 VK_NUMPAD2, VK_DOWN: 6667 begin 6668 dx := 0; 6669 dy := 2 6670 end; 6671 VK_NUMPAD3, VK_NEXT: 6672 begin 6673 dx := 1; 6674 dy := 1 6675 end; 6676 VK_NUMPAD4, VK_LEFT: 6677 begin 6678 dx := -2; 6679 dy := 0 6680 end; 6681 VK_NUMPAD6, VK_RIGHT: 6682 begin 6683 dx := 2; 6684 dy := 0 6685 end; 6686 VK_NUMPAD7, VK_HOME: 6687 begin 6688 dx := -1; 6689 dy := -1 6690 end; 6691 VK_NUMPAD8, VK_UP: 6692 begin 6693 dx := 0; 6694 dy := -2 6695 end; 6696 VK_NUMPAD9, VK_PRIOR: 6697 begin 6698 dx := 1; 6699 dy := -1 6700 end; 6701 end; 6702 MoveUnit(dx, dy, muAutoNext) 6703 end; 6704 end 6705 end; 6706 6707 procedure TMainScreen.MenuClick(Sender: TObject); 6708 6709 function DoJob(j0: integer): integer; 6710 var 6711 Loc0, Movement0: integer; 6712 begin 6713 with MyUn[UnFocus] do 6714 begin 5681 6715 DestinationMarkON := false; 5682 6716 PaintDestination; 5683 if result and rUnitRemoved <> 0 then 5684 CityOptimizer_BeforeRemoveUnit(UnFocus); 5685 IsAttack := (result = eBombarded) or (result <> eMissionDone) and 5686 (MyMap[ToLoc] and (fUnit or fOwned) = fUnit); 5687 if not IsAttack then 5688 begin // move 5689 cix := MyRO.nCity - 1; { look for own city at dest location } 5690 while (cix >= 0) and (MyCity[cix].Loc <> ToLoc) do 5691 dec(cix); 5692 if (result <> eMissionDone) and (MyMap[ToLoc] and fCity <> 0) and 5693 (cix < 0) then 5694 CityCaptured := true; 5695 result := Server(sMoveUnit + DirCode, me, UnFocus, nil^); 5696 case result of 5697 eHiddenUnit: 5698 begin 5699 Play('NOMOVE_SUBMARINE'); 5700 PaintLoc(ToLoc) 5701 end; 5702 eStealthUnit: 5703 begin 5704 Play('NOMOVE_STEALTH'); 5705 PaintLoc(ToLoc) 5706 end; 5707 eZOC_EnemySpotted: 5708 begin 5709 Play('NOMOVE_ZOC'); 5710 PaintLoc(ToLoc, 1) 5711 end; 5712 rExecuted .. maxint: 5713 begin 5714 if result and rUnitRemoved <> 0 then 5715 UnFocus := -1 // unit died 5716 else 5717 begin 5718 assert(UnFocus >= 0); 5719 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 5720 not(usStay or usRecover); 5721 for uix := 0 to MyRO.nUn - 1 do 5722 if MyUn[uix].Master = UnFocus then 5723 MyUn[uix].Status := MyUn[uix].Status and not usWaiting; 5724 if CityCaptured and 5725 (MyRO.Government in [gRepublic, gDemocracy, gFuture]) then 5726 begin // borders have moved, unrest might have changed in any city 5727 CityOptimizer_BeginOfTurn; 5728 NeedEcoUpdate := true; 5729 end 5730 else 5731 begin 5732 if OldUnrest <> NewUnrest then 5733 begin 5734 CityOptimizer_CityChange(MyUn[UnFocus].Home); 5735 for uix := 0 to MyRO.nUn - 1 do 5736 if MyUn[uix].Master = UnFocus then 5737 CityOptimizer_CityChange(MyUn[uix].Home); 5738 NeedEcoUpdate := true; 5739 end; 5740 if (MyRO.Government = gDespotism) and 5741 (MyModel[MyUn[UnFocus].mix].Kind = mkSpecial_TownGuard) then 5742 begin 5743 if MyMap[FromLoc] and fCity <> 0 then 5744 begin // town guard moved out of city in despotism -- reoptimize! 5745 cixChanged := MyRO.nCity - 1; 5746 while (cixChanged >= 0) and 5747 (MyCity[cixChanged].Loc <> FromLoc) do 5748 dec(cixChanged); 5749 assert(cixChanged >= 0); 5750 if cixChanged >= 0 then 5751 begin 5752 CityOptimizer_CityChange(cixChanged); 5753 NeedEcoUpdate := true; 5754 end; 5755 end; 5756 if (MyMap[ToLoc] and fCity <> 0) and not CityCaptured then 5757 begin // town guard moved into city in despotism -- reoptimize! 5758 cixChanged := MyRO.nCity - 1; 5759 while (cixChanged >= 0) and 5760 (MyCity[cixChanged].Loc <> ToLoc) do 5761 dec(cixChanged); 5762 assert(cixChanged >= 0); 5763 if cixChanged >= 0 then 5764 begin 5765 CityOptimizer_CityChange(cixChanged); 5766 NeedEcoUpdate := true; 5767 end 5768 end 5769 end 5770 end 5771 end; 5772 end; 6717 Loc0 := Loc; 6718 Movement0 := Movement; 6719 if j0 < 0 then 6720 result := ProcessEnhancement(UnFocus, MyData.EnhancementJobs) 6721 // terrain enhancement 6722 else 6723 result := Server(sStartJob + j0 shl 4, me, UnFocus, nil^); 6724 if result >= rExecuted then 6725 begin 6726 if result = eDied then 6727 UnFocus := -1; 6728 PaintLoc(Loc0); 6729 if UnFocus >= 0 then 6730 begin 6731 if (j0 < 0) and (result <> eJobDone) then 6732 // multi-turn terrain enhancement 6733 Status := Status and ($FFFF - usStay - usRecover - usGoto) or 6734 usEnhance 6735 else 6736 Status := Status and 6737 ($FFFF - usStay - usRecover - usGoto - usEnhance); 6738 if (Job <> jNone) or (Movement0 < 100) then 6739 begin 6740 Status := Status and not usWaiting; 6741 NextUnit(UnStartLoc, true); 6742 end 6743 else 6744 PanelPaint 6745 end 5773 6746 else 5774 assert(false); 5775 end; 5776 SetTroopLoc(ToLoc); 6747 NextUnit(UnStartLoc, true); 6748 end 6749 end; 6750 case result of 6751 eNoBridgeBuilding: 6752 SoundMessage(Phrases.Lookup('NOBB'), 'INVALID'); 6753 eNoCityTerrain: 6754 SoundMessage(Phrases.Lookup('NOCITY'), 'INVALID'); 6755 eTreaty: 6756 SoundMessage(Tribe[MyRO.Territory[Loc0]].TPhrase('PEACE_NOWORK'), 6757 'NOMOVE_TREATY'); 6758 else 6759 if result < rExecuted then 6760 Play('INVALID') 6761 end 6762 end; 6763 6764 var 6765 i, uix, NewFocus, Loc0, OldMaster, Destination, cix, cixOldHome, 6766 ServerResult: integer; 6767 AltGovs, Changed: boolean; 6768 QueryText: string; 6769 6770 begin 6771 if Sender = mResign then 6772 if ClientMode = cEditMap then 6773 begin 6774 if Edited then 6775 begin 6776 QueryText := Phrases.Lookup('MAP_CLOSE'); 6777 case SimpleQuery(mkYesNoCancel, QueryText, '') of 6778 mrIgnore: 6779 Server(sAbandonMap, me, 0, nil^); 6780 mrOK: 6781 Server(sSaveMap, me, 0, nil^); 6782 end 5777 6783 end 5778 6784 else 5779 begin { enemy unit -- attack } 5780 if result = eBombarded then 5781 Defender := MyRO.Territory[ToLoc] 6785 Server(sAbandonMap, me, 0, nil^) 6786 end 6787 else 6788 begin 6789 if Server(sGetGameChanged, 0, 0, nil^) = eOK then 6790 begin 6791 QueryText := Phrases.Lookup('RESIGN'); 6792 case SimpleQuery(mkYesNoCancel, QueryText, '') of 6793 mrIgnore: 6794 Server(sResign, 0, 0, nil^); 6795 mrOK: 6796 Server(sBreak, 0, 0, nil^) 6797 end 6798 end 6799 else 6800 Server(sResign, 0, 0, nil^) 6801 end 6802 else if Sender = mEmpire then 6803 RatesDlg.ShowNewContent(wmPersistent) 6804 else if Sender = mRevolution then 6805 begin 6806 AltGovs := false; 6807 for i := 2 to nGov - 1 do 6808 if (GovPreq[i] <> preNA) and 6809 ((GovPreq[i] = preNone) or (MyRO.Tech[GovPreq[i]] >= tsApplicable)) then 6810 AltGovs := true; 6811 6812 if not AltGovs then 6813 SoundMessage(Phrases.Lookup('NOALTGOVS'), 'MSG_DEFAULT') 6814 else 6815 begin 6816 Changed := false; 6817 if MyRO.Happened and phChangeGov <> 0 then 6818 begin 6819 ModalSelectDlg.ShowNewContent(wmModal, kGov); 6820 if ModalSelectDlg.result >= 0 then 6821 begin 6822 Play('NEWGOV'); 6823 Server(sSetGovernment, me, ModalSelectDlg.result, nil^); 6824 CityOptimizer_BeginOfTurn; 6825 Changed := true; 6826 end 6827 end 6828 else 6829 // TODO with MessgExDlg do 6830 begin // revolution! 6831 MessgExDlg.MessgText := Tribe[me].TPhrase('REVOLUTION'); 6832 MessgExDlg.Kind := mkYesNo; 6833 MessgExDlg.IconKind := mikPureIcon; 6834 MessgExDlg.IconIndex := 72; // anarchy palace 6835 MessgExDlg.ShowModal; 6836 if ModalResult = mrOK then 6837 begin 6838 Play('REVOLUTION'); 6839 Server(sRevolution, me, 0, nil^); 6840 Changed := true; 6841 if NatStatDlg.Visible then 6842 NatStatDlg.Close; 6843 if CityDlg.Visible then 6844 CityDlg.Close; 6845 end 6846 end; 6847 if Changed then 6848 UpdateViews(true); 6849 end 6850 end 6851 else if Sender = mWebsite then 6852 OpenURL('http://c-evo.org') { *Převedeno z ShellExecute* } 6853 else if Sender = mRandomMap then 6854 begin 6855 if not Edited or (SimpleQuery(mkYesNo, Phrases.Lookup('MAP_RANDOM'), '') 6856 = mrOK) then 6857 begin 6858 Server(sRandomMap, me, 0, nil^); 6859 Edited := true; 6860 MapValid := false; 6861 PaintAllMaps; 6862 end 6863 end 6864 else if Sender = mJump then 6865 begin 6866 if supervising then 6867 Jump[0] := 20 6868 else 6869 Jump[me] := 20; 6870 EndTurn(true); 6871 end 6872 else if Sender = mRun then 6873 begin 6874 if supervising then 6875 Jump[0] := 999999 6876 else 6877 Jump[me] := 999999; 6878 EndTurn(true); 6879 end 6880 else if Sender = mEnhanceDef then 6881 begin 6882 if UnFocus >= 0 then 6883 EnhanceDlg.ShowNewContent(wmPersistent, 6884 MyMap[MyUn[UnFocus].Loc] and fTerrain) 6885 else 6886 EnhanceDlg.ShowNewContent(wmPersistent) 6887 end 6888 else if Sender = mCityTypes then 6889 CityTypeDlg.ShowNewContent(wmModal) 6890 // must be modal because types are not saved before closing 6891 else if Sender = mUnitStat then 6892 begin 6893 if G.Difficulty[me] > 0 then 6894 ListDlg.ShowNewContent_MilReport(wmPersistent, me) 6895 else 6896 begin 6897 i := 1; 6898 while (i < nPl) and (1 shl i and MyRO.Alive = 0) do 6899 inc(i); 6900 if i < nPl then 6901 ListDlg.ShowNewContent_MilReport(wmPersistent, i); 6902 end; 6903 end 6904 else if Sender = mEUnitStat then 6905 begin 6906 if MyRO.nEnemyModel > 0 then 6907 ListDlg.ShowNewContent(wmPersistent, kAllEModels); 6908 end 6909 else if Sender = mCityStat then 6910 ListDlg.ShowNewContent(wmPersistent, kCities) 6911 else if Sender = mScienceStat then 6912 ListDlg.ShowNewContent(wmPersistent, kScience) 6913 else if Sender = mNations then 6914 NatStatDlg.ShowNewContent(wmPersistent) 6915 else if Sender = mHelp then 6916 if ClientMode = cEditMap then 6917 HelpDlg.ShowNewContent(wmPersistent, hkText, HelpDlg.TextIndex('MAPEDIT')) 6918 else 6919 HelpDlg.ShowNewContent(wmPersistent, hkMisc, miscMain) 6920 else if Sender = mTechTree then 6921 TechTreeDlg.ShowModal 6922 else if Sender = mWonders then 6923 WondersDlg.ShowNewContent(wmPersistent) 6924 else if Sender = mDiagram then 6925 DiaDlg.ShowNewContent_Charts(wmPersistent) 6926 else if Sender = mShips then 6927 DiaDlg.ShowNewContent_Ship(wmPersistent) 6928 else if Sender = mWait then 6929 begin 6930 if UnFocus >= 0 then 6931 begin 6932 DestinationMarkON := false; 6933 PaintDestination; 6934 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 6935 ($FFFF - usStay - usRecover - usGoto - usEnhance) or usWaiting; 6936 end; 6937 NextUnit(-1, false); 6938 end 6939 else if UnFocus >= 0 then 6940 with MyUn[UnFocus] do 6941 if Sender = mGoOn then 6942 begin 6943 if Status shr 16 = $7FFF then 6944 Destination := maNextCity 5782 6945 else 5783 De fender := MyRO.EnemyUn[euix].Owner;5784 { if MyRO.Treaty[Defender]=trCeaseFire then5785 if SimpleQuery(mkYesNo,Phrases.Lookup('FRCANCELQUERY_CEASEFIRE'),5786 'MSG_DEFAULT')<>mrOK then5787 exit; }5788 if (Options and muNoSuicideCheck = 0) and (result and rUnitRemoved <> 0)5789 and (result <> eMissionDone) then5790 begin // suicide query5791 with MyUn[UnFocus], BattleDlg.Forecast do6946 Destination := Status shr 16; 6947 Status := Status and not(usStay or usRecover) or usWaiting; 6948 MoveToLoc(Destination, true); 6949 end 6950 else if Sender = mHome then 6951 if MyMap[Loc] and fCity <> 0 then 6952 begin 6953 cixOldHome := Home; 6954 if Server(sSetUnitHome, me, UnFocus, nil^) >= rExecuted then 5792 6955 begin 5793 pAtt := me; 5794 mixAtt := mix; 5795 HealthAtt := Health; 5796 ExpAtt := Exp; 5797 FlagsAtt := Flags; 5798 end; 5799 BattleDlg.Forecast.Movement := MyUn[UnFocus].Movement; 5800 Server(sGetBattleForecastEx, me, ToLoc, BattleDlg.Forecast); 5801 BattleDlg.uix := UnFocus; 5802 BattleDlg.ToLoc := ToLoc; 5803 BattleDlg.IsSuicideQuery := true; 5804 BattleDlg.ShowModal; 5805 if BattleDlg.ModalResult <> mrOK then 5806 exit; 5807 end; 5808 5809 cixChanged := -1; 5810 if (result and rUnitRemoved <> 0) and (MyRO.Government = gDespotism) and 5811 (MyModel[MyUn[UnFocus].mix].Kind = mkSpecial_TownGuard) and 5812 (MyMap[FromLoc] and fCity <> 0) then 5813 begin // town guard died in city in despotism -- reoptimize! 5814 cixChanged := MyRO.nCity - 1; 5815 while (cixChanged >= 0) and (MyCity[cixChanged].Loc <> FromLoc) do 5816 dec(cixChanged); 5817 assert(cixChanged >= 0); 5818 end; 5819 5820 for i := 0 to MyRO.nEnemyModel - 1 do 5821 LostArmy[i] := MyRO.EnemyModel[i].Lost; 5822 OldToTile := MyMap[ToLoc]; 5823 result := Server(sMoveUnit + DirCode, me, UnFocus, nil^); 5824 nLostArmy := 0; 5825 for i := 0 to MyRO.nEnemyModel - 1 do 5826 begin 5827 LostArmy[i] := MyRO.EnemyModel[i].Lost - LostArmy[i]; 5828 inc(nLostArmy, LostArmy[i]) 5829 end; 5830 if result and rUnitRemoved <> 0 then 5831 begin 5832 UnFocus := -1; 5833 SetTroopLoc(FromLoc); 5834 end; 5835 if (OldToTile and not MyMap[ToLoc] and fCity <> 0) and 5836 (MyRO.Government in [gRepublic, gDemocracy, gFuture]) then 5837 begin // city was destroyed, borders have moved, unrest might have changed in any city 5838 CityOptimizer_BeginOfTurn; 5839 NeedEcoUpdate := true; 6956 CityOptimizer_CityChange(cixOldHome); 6957 CityOptimizer_CityChange(Home); 6958 UpdateViews(true); 6959 end 6960 else 6961 Play('INVALID'); 5840 6962 end 5841 6963 else 5842 6964 begin 5843 if cixChanged >= 0 then 5844 begin 5845 CityOptimizer_CityChange(cixChanged); 5846 NeedEcoUpdate := true; 5847 end; 5848 if (result = eWon) or (result = eBloody) or (result = eExpelled) then 5849 begin 5850 CityOptimizer_TileBecomesAvailable(ToLoc); 5851 NeedEcoUpdate := true; 5852 end; 5853 end; 5854 if nLostArmy > 1 then 5855 begin 5856 with MessgExDlg do 5857 begin 5858 Kind := mkOk; 5859 IconKind := mikEnemyArmy; 5860 MessgText := Tribe[Defender].TString(Phrases.Lookup('ARMYLOST', 5861 MyRO.EnemyModel[MyRO.EnemyUn[euix].emix].Domain)); 5862 ShowModal; 5863 end 6965 Status := Status and not(usStay or usRecover or usEnhance); 6966 MoveToLoc(maNextCity, true) 5864 6967 end 5865 end; 5866 if result and rUnitRemoved <> 0 then 5867 begin 5868 CityOptimizer_AfterRemoveUnit; 5869 ListDlg.RemoveUnit; 5870 NeedEcoUpdate := true; 5871 end; 5872 if NeedEcoUpdate then 5873 begin 5874 UpdateViews(true); 5875 Update 6968 else if Sender = mCentre then 6969 begin 6970 Centre(Loc); 6971 PaintAllMaps 5876 6972 end 5877 end; 5878 5879 if result = eMissionDone then 5880 begin 5881 p1 := MyRO.Territory[ToLoc]; 5882 case Mission of 5883 smStealMap: 6973 else if Sender = mCity then 6974 begin 6975 Loc0 := Loc; 6976 if MyMap[Loc] and fCity = 0 then 6977 begin // build city 6978 if DoJob(jCity) = eCity then 5884 6979 begin 5885 6980 MapValid := false; 5886 PaintAllMaps 5887 end; 5888 smStealCivilReport: 5889 TribeMessage(p1, Tribe[p1].TPhrase('DOSSIER_PREPARED'), ''); 5890 smStealMilReport: 5891 ListDlg.ShowNewContent_MilReport(wmPersistent, p1); 5892 end; 5893 end; 5894 5895 if UnFocus >= 0 then 5896 CheckToldNoReturn(UnFocus); 5897 5898 NeedRepaintPanel := false; 5899 if result >= rExecuted then 5900 begin 5901 if CityCaptured and (MyMap[ToLoc] and fCity = 0) then 5902 begin // city destroyed 5903 for i := 0 to 27 do { tell about destroyed wonders } 5904 if (MyRO.Wonder[i].CityID = -2) and 5905 (MyData.ToldWonders[i].CityID <> -2) then 5906 with MessgExDlg do 5907 begin 5908 if WondersDlg.Visible then 5909 WondersDlg.SmartUpdateContent(false); 5910 OpenSound := 'WONDER_DESTROYED'; 5911 MessgText := Format(Phrases.Lookup('WONDERDEST'), 5912 [Phrases.Lookup('IMPROVEMENTS', i)]); 5913 Kind := mkOkHelp; 5914 HelpKind := hkImp; 5915 HelpNo := i; 5916 IconKind := mikImp; 5917 IconIndex := i; 5918 ShowModal; 5919 MyData.ToldWonders[i] := MyRO.Wonder[i]; 5920 end 5921 end; 5922 if CityCaptured and (MyMap[ToLoc] and fCity <> 0) then 5923 begin // city captured 5924 ListDlg.AddCity; 5925 for i := 0 to 27 do { tell about capture of wonders } 5926 if MyRO.City[MyRO.nCity - 1].Built[i] > 0 then 5927 with MessgExDlg do 5928 begin 5929 if WondersDlg.Visible then 5930 WondersDlg.SmartUpdateContent(false); 5931 OpenSound := 'WONDER_CAPTURED'; 5932 MessgText := Format(Tribe[me].TPhrase('WONDERCAPTOWN'), 5933 [Phrases.Lookup('IMPROVEMENTS', i)]); 5934 Kind := mkOkHelp; 5935 HelpKind := hkImp; 5936 HelpNo := i; 5937 IconKind := mikImp; 5938 IconIndex := i; 5939 ShowModal; 5940 MyData.ToldWonders[i] := MyRO.Wonder[i]; 5941 end; 5942 5943 if MyRO.Happened and phStealTech <> 0 then 5944 begin { Temple of Zeus -- choose advance to steal } 5945 ModalSelectDlg.ShowNewContent(wmModal, kStealTech); 5946 Server(sStealTech, me, ModalSelectDlg.result, nil^); 5947 end; 5948 TellNewModels; 5949 5950 cix := MyRO.nCity - 1; 5951 while (cix >= 0) and (MyCity[cix].Loc <> ToLoc) do 5952 dec(cix); 5953 assert(cix >= 0); 5954 MyCity[cix].Status := MyCity[cix].Status and 5955 not csResourceWeightsMask or (3 shl 4); 5956 // captured city, set to maximum growth 5957 NewTiles := 1 shl 13; { exploit central tile only } 5958 Server(sSetCityTiles, me, cix, NewTiles); 5959 end 5960 else 5961 NeedRepaintPanel := true; 5962 end; 5963 TellNewContacts; 5964 5965 if (UnFocus >= 0) and (MyUn[UnFocus].Master >= 0) then 5966 with MyUn[MyUn[UnFocus].Master] do 5967 if Status and usStay <> 0 then 5968 begin 5969 Status := Status and not usStay; 5970 if (Movement >= 100) and (Status and (usRecover or usGoto) = 0) then 5971 Status := Status or usWaiting; 5972 end; 5973 if Options and (muAutoNoWait or muAutoNext) <> 0 then 5974 begin 5975 if (UnFocus >= 0) and ((result = eNoTime_Move) or UnitExhausted(UnFocus) 5976 or (MyUn[UnFocus].Master >= 0) or 5977 (MyModel[MyUn[UnFocus].mix].Domain = dAir) and 5978 ((MyMap[MyUn[UnFocus].Loc] and fCity <> 0) { aircrafts stop in cities } 5979 or (MyMap[MyUn[UnFocus].Loc] and fTerImp = tiBase))) then 5980 begin 5981 MyUn[UnFocus].Status := MyUn[UnFocus].Status and not usWaiting; 5982 if Options and muAutoNext <> 0 then 5983 if CityCaptured and (MyMap[ToLoc] and fCity <> 0) then 5984 begin 5985 UnFocus := -1; 5986 PaintLoc(ToLoc); // don't show unit in city if not selected 6981 PaintAll; 6982 ZoomToCity(Loc0, true, chFounded); 5987 6983 end 5988 else5989 NextUnit(UnStartLoc, true)5990 end5991 else if (UnFocus < 0) and (Options and muAutoNext <> 0) then5992 NextUnit(UnStartLoc, result <> eMissionDone);5993 end;5994 5995 if NeedRepaintPanel and (UnFocus = UnFocus0) then5996 if IsAttack then5997 PanelPaint5998 else5999 begin6000 assert(result <> eMissionDone);6001 CheckTerrainBtnVisible;6002 FocusOnLoc(ToLoc, flRepaintPanel or flImmUpdate)6003 end;6004 6005 if (result >= rExecuted) and CityCaptured and (MyMap[ToLoc] and fCity <> 0)6006 then6007 ZoomToCity(ToLoc, UnFocus < 0, chCaptured); // show captured city6008 end; // moveunit6009 6010 procedure TMainScreen.MoveOnScreen(ShowMove: TShowMove;6011 Step0, Step1, nStep: integer; Restore: boolean = true);6012 var6013 ToLoc, xFromLoc, yFromLoc, xToLoc, yToLoc, xFrom, yFrom, xTo, yTo, xMin,6014 yMin, xRange, yRange, xw1, Step, xMoving, yMoving, yl,6015 SliceCount: integer;6016 UnitInfo: TUnitInfo;6017 Ticks0, Ticks: TDateTime;6018 begin6019 Timer1.Enabled := false;6020 Ticks0 := NowPrecise;6021 with ShowMove do6022 begin6023 UnitInfo.Owner := Owner;6024 UnitInfo.mix := mix;6025 UnitInfo.Health := Health;6026 UnitInfo.Job := jNone;6027 UnitInfo.Flags := Flags;6028 if Owner <> me then6029 UnitInfo.emix := emix;6030 6031 ToLoc := dLoc(FromLoc, dx, dy);6032 xToLoc := ToLoc mod G.lx;6033 yToLoc := ToLoc div G.lx;6034 xFromLoc := FromLoc mod G.lx;6035 yFromLoc := FromLoc div G.lx;6036 if xToLoc > xFromLoc + 2 then6037 xToLoc := xToLoc - G.lx6038 else if xToLoc < xFromLoc - 2 then6039 xToLoc := xToLoc + G.lx;6040 6041 xw1 := xw + G.lx;6042 // ((xFromLoc-xw1)*2+yFromLoc and 1+1)*xxt+dx*xxt/2-MapWidth/2 -> min6043 while abs(((xFromLoc - xw1 + G.lx) * 2 + yFromLoc and 1 + 1) * xxt * 2 +6044 dx * xxt - MapWidth) < abs(((xFromLoc - xw1) * 2 + yFromLoc and 1 + 1) *6045 xxt * 2 + dx * xxt - MapWidth) do6046 dec(xw1, G.lx);6047 6048 xTo := (xToLoc - xw1) * (xxt * 2) + yToLoc and 1 * xxt + (xxt - xxu);6049 yTo := (yToLoc - yw) * yyt + (yyt - yyu_anchor);6050 xFrom := (xFromLoc - xw1) * (xxt * 2) + yFromLoc and 1 * xxt +6051 (xxt - xxu);6052 yFrom := (yFromLoc - yw) * yyt + (yyt - yyu_anchor);6053 if xFrom < xTo then6054 begin6055 xMin := xFrom;6056 xRange := xTo - xFrom6057 end6058 else6059 begin6060 xMin := xTo;6061 xRange := xFrom - xTo6062 end;6063 if yFrom < yTo then6064 begin6065 yMin := yFrom;6066 yRange := yTo - yFrom6067 end6068 else6069 begin6070 yMin := yTo;6071 yRange := yFrom - yTo6072 end;6073 inc(xRange, xxt * 2);6074 inc(yRange, yyt * 3);6075 6076 MainOffscreenPaint;6077 NoMap.SetOutput(Buffer);6078 NoMap.SetPaintBounds(0, 0, xRange, yRange);6079 for Step := 0 to abs(Step1 - Step0) do6080 begin6081 BitBlt(Buffer.Canvas.Handle, 0, 0, xRange, yRange,6082 offscreen.Canvas.Handle, xMin, yMin, SRCCOPY);6083 if Step1 <> Step0 then6084 begin6085 xMoving := xFrom +6086 Round((Step0 + Step * (Step1 - Step0) div abs(Step1 - Step0)) *6087 (xTo - xFrom) / nStep);6088 yMoving := yFrom +6089 Round((Step0 + Step * (Step1 - Step0) div abs(Step1 - Step0)) *6090 (yTo - yFrom) / nStep);6091 6984 end 6092 6985 else 6093 6986 begin 6094 xMoving := xFrom; 6095 yMoving := yFrom; 6096 end; 6097 NoMap.PaintUnit(xMoving - xMin, yMoving - yMin, UnitInfo, 0); 6098 PaintBufferToScreen(xMin, yMin, xRange, yRange); 6099 6100 SliceCount := 0; 6101 Ticks := Ticks0; 6102 repeat 6103 if (SliceCount = 0) or (MillisecondOf(Ticks - Ticks0) * 12 * (SliceCount + 1) 6104 div SliceCount < MoveTime) then 6987 CityOptimizer_BeforeRemoveUnit(UnFocus); 6988 ServerResult := Server(sAddToCity, me, UnFocus, nil^); 6989 if ServerResult >= rExecuted then 6105 6990 begin 6106 if not idle or (GameMode = cMovie) then 6107 Application.ProcessMessages; 6108 Sleep(1); 6109 inc(SliceCount) 6110 end; 6111 Ticks := NowPrecise; 6112 until (Ticks - Ticks0) / OneMillisecond * 12 >= MoveTime; 6113 Ticks0 := Ticks 6114 end; 6115 end; 6116 if Restore then 6117 begin 6118 BitBlt(Buffer.Canvas.Handle, 0, 0, xRange, yRange, 6119 offscreen.Canvas.Handle, xMin, yMin, SRCCOPY); 6120 PaintBufferToScreen(xMin, yMin, xRange, yRange); 6121 end; 6122 BlinkTime := -1; 6123 Timer1.Enabled := true; 6124 end; 6125 6126 procedure TMainScreen.MoveToLoc(Loc: integer; CheckSuicide: boolean); 6127 // path finder: move focused unit to loc, start multi-turn goto if too far 6128 var 6129 uix, i, MoveOptions, NextLoc, MoveResult: integer; 6130 MoveAdviceData: TMoveAdviceData; 6131 StopReason: (None, Arrived, Dead, NoTime, EnemySpotted, MoveError); 6132 begin 6133 if MyUn[UnFocus].Job > jNone then 6134 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 6135 if GetMoveAdvice(UnFocus, Loc, MoveAdviceData) >= rExecuted then 6136 begin 6137 uix := UnFocus; 6138 StopReason := None; 6139 repeat 6140 for i := 0 to MoveAdviceData.nStep - 1 do 6141 begin 6142 if i = MoveAdviceData.nStep - 1 then 6143 MoveOptions := muAutoNext 6144 else 6145 MoveOptions := 0; 6146 NextLoc := dLoc(MyUn[uix].Loc, MoveAdviceData.dx[i], 6147 MoveAdviceData.dy[i]); 6148 if (NextLoc = Loc) or (Loc = maNextCity) and 6149 (MyMap[NextLoc] and fCity <> 0) then 6150 StopReason := Arrived; 6151 if not CheckSuicide and (NextLoc = Loc) then 6152 MoveOptions := MoveOptions or muNoSuicideCheck; 6153 MoveResult := MoveUnit(MoveAdviceData.dx[i], MoveAdviceData.dy[i], 6154 MoveOptions); 6155 if MoveResult < rExecuted then 6156 StopReason := MoveError 6157 else if MoveResult and rUnitRemoved <> 0 then 6158 StopReason := Dead 6159 else if (StopReason = None) and (MoveResult and rEnemySpotted <> 0) 6160 then 6161 StopReason := EnemySpotted; 6162 if StopReason <> None then 6163 Break; 6164 end; 6165 if (StopReason = None) and 6166 ((MoveAdviceData.nStep < 25) or 6167 (MyRO.Wonder[woShinkansen].EffectiveOwner <> me)) then 6168 StopReason := NoTime; 6169 if StopReason <> None then 6170 Break; 6171 if GetMoveAdvice(UnFocus, Loc, MoveAdviceData) < rExecuted then 6172 begin 6173 assert(false); 6174 Break 6175 end 6176 until false; 6177 6178 case StopReason of 6179 None: 6180 assert(false); 6181 Arrived: 6182 MyUn[uix].Status := MyUn[uix].Status and ($FFFF - usGoto); 6183 Dead: 6184 if UnFocus < 0 then 6185 NextUnit(UnStartLoc, false); 6186 else 6187 begin // multi-turn goto 6188 if Loc = maNextCity then 6189 MyUn[uix].Status := MyUn[uix].Status and 6190 ($FFFF - usStay - usRecover) or usGoto + $7FFF shl 16 6191 else 6192 MyUn[uix].Status := MyUn[uix].Status and 6193 ($FFFF - usStay - usRecover) or usGoto + Loc shl 16; 6194 PaintLoc(MyUn[uix].Loc); 6195 if (StopReason = NoTime) and (UnFocus = uix) then 6196 begin 6197 MyUn[uix].Status := MyUn[uix].Status and not usWaiting; 6198 NextUnit(UnStartLoc, true) 6199 end; 6200 end 6201 end 6202 end 6203 end; 6204 6205 procedure TMainScreen.PanelBoxMouseDown(Sender: TObject; 6206 Button: TMouseButton; Shift: TShiftState; x, y: integer); 6207 var 6208 i, xMouse, MouseLoc, p1: integer; 6209 begin 6210 if GameMode = cMovie then 6211 exit; 6212 6213 if Button = mbLeft then 6214 begin 6215 if (x >= xMini + 2) and (y >= yMini + 2) and (x < xMini + 2 + 2 * G.lx) 6216 and (y < yMini + 2 + G.ly) then 6217 if ssShift in Shift then 6218 begin 6219 xMouse := (xwMini + (x - (xMini + 2) + MapWidth div (xxt * 2) + 6220 G.lx) div 2) mod G.lx; 6221 MouseLoc := xMouse + G.lx * (y - (yMini + 2)); 6222 if MyMap[MouseLoc] and fTerrain <> fUNKNOWN then 6223 begin 6224 p1 := MyRO.Territory[MouseLoc]; 6225 if (p1 = me) or (p1 >= 0) and (MyRO.Treaty[p1] >= trNone) then 6226 NatStatDlg.ShowNewContent(wmPersistent, p1); 6227 end 6228 end 6229 else 6230 begin 6231 if CityDlg.Visible then 6232 CityDlg.Close; 6233 if UnitStatDlg.Visible then 6234 UnitStatDlg.Close; 6235 Tracking := true; 6236 PanelBoxMouseMove(Sender, Shift + [ssLeft], x, y); 6237 end 6238 else if (ClientMode <> cEditMap) and (x >= ClientWidth - xPalace) and 6239 (y >= yPalace) and (x < ClientWidth - xPalace + xSizeBig) and 6240 (y < yPalace + ySizeBig) then 6241 begin 6242 InitPopup(StatPopup); 6243 if FullScreen then 6244 StatPopup.Popup(Left + ClientWidth - xPalace + xSizeBig + 2, 6245 Top + ClientHeight - PanelHeight + yPalace - 1) 6246 else 6247 StatPopup.Popup(Left + ClientWidth - xPalace + 6, 6248 Top + ClientHeight - PanelHeight + yPalace + ySizeBig + 6249 GetSystemMetrics(SM_CYCAPTION) + 3) 6250 end 6251 (* else if (x>=xAdvisor-3) and (y>=yAdvisor-3) 6252 and (x<xAdvisor+16+3) and (y<yAdvisor+16+3) and HaveStrategyAdvice then 6253 AdviceBtnClick *) 6254 else if (x >= xTroop + 1) and (y >= yTroop + 1) and 6255 (x < xTroop + TrRow * TrPitch) and (y <= yTroop + 55) then 6256 begin 6257 i := (x - xTroop - 1) div TrPitch; 6258 if trix[i] >= 0 then 6259 if ClientMode = cEditMap then 6260 begin 6261 BrushType := trix[i]; 6262 PanelPaint 6263 end 6264 else if (TroopLoc >= 0) then 6265 if MyMap[TroopLoc] and fOwned <> 0 then 6266 begin 6267 if ssShift in Shift then 6268 UnitStatDlg.ShowNewContent_OwnModel(wmPersistent, 6269 MyUn[trix[i]].mix) 6270 else if not supervising and (ClientMode < scContact) and 6271 (x - xTroop - 1 - i * TrPitch >= 60 - 20) and 6272 (y >= yTroop + 35) and 6273 ((MyUn[trix[i]].Job > jNone) or (MyUn[trix[i]].Status and 6274 (usStay or usRecover or usGoto) <> 0)) then 6275 begin // wake up 6276 MyUn[trix[i]].Status := MyUn[trix[i]].Status and 6277 ($FFFF - usStay - usRecover - usGoto - usEnhance) or 6278 usWaiting; 6279 if MyUn[trix[i]].Job > jNone then 6280 Server(sStartJob + jNone shl 4, me, trix[i], nil^); 6281 if (UnFocus < 0) and not CityDlg.Visible then 6282 begin 6283 SetUnFocus(trix[i]); 6284 SetTroopLoc(MyUn[trix[i]].Loc); 6285 FocusOnLoc(TroopLoc, flRepaintPanel) 6286 end 6287 else 6288 begin 6289 if CityDlg.Visible and (CityDlg.RestoreUnFocus < 0) then 6290 CityDlg.RestoreUnFocus := trix[i]; 6291 PanelPaint; 6292 end 6293 end 6294 else if (ClientMode < scContact) then 6295 begin 6296 if supervising then 6297 UnitStatDlg.ShowNewContent_OwnUnit(wmPersistent, trix[i]) 6298 else if CityDlg.Visible then 6299 begin 6300 CityDlg.CloseAction := None; 6301 CityDlg.Close; 6302 SumCities(TaxSum, ScienceSum); 6303 SetUnFocus(trix[i]); 6304 end 6305 else 6306 begin 6307 DestinationMarkON := false; 6308 PaintDestination; 6309 UnFocus := trix[i]; 6310 UnStartLoc := TroopLoc; 6311 BlinkTime := 0; 6312 BlinkON := false; 6313 PaintLoc(TroopLoc); 6314 end; 6315 if UnFocus >= 0 then 6316 begin 6317 UnitInfoBtn.Visible := true; 6318 UnitBtn.Visible := true; 6319 TurnComplete := false; 6320 EOT.ButtonIndex := eotGray; 6321 end; 6322 CheckTerrainBtnVisible; 6323 PanelPaint; 6324 end 6325 end 6326 else if Server(sGetUnits, me, TroopLoc, TrCnt) >= rExecuted then 6327 if ssShift in Shift then 6328 UnitStatDlg.ShowNewContent_EnemyModel(wmPersistent, 6329 MyRO.EnemyUn[MyRO.nEnemyUn + trix[i]].emix) // model info 6330 else 6331 UnitStatDlg.ShowNewContent_EnemyUnit(wmPersistent, 6332 MyRO.nEnemyUn + trix[i]); // unit info 6333 end 6334 end 6335 end; 6336 6337 procedure TMainScreen.SetTroopLoc(Loc: integer); 6338 var 6339 trixFocus, uix, uixDefender: integer; 6340 Prio: boolean; 6341 begin 6342 TroopLoc := Loc; 6343 TrRow := (xRightPanel + 10 - xTroop - GetSystemMetrics(SM_CXVSCROLL) - 19) 6344 div TrPitch; 6345 TrCnt := 0; 6346 trixFocus := -1; 6347 if ClientMode = cEditMap then 6348 TrCnt := nBrushTypes 6349 else if (Loc >= 0) and (MyMap[Loc] and fUnit <> 0) then 6350 if MyMap[Loc] and fOwned <> 0 then 6351 begin // count own units here 6352 Server(sGetDefender, me, TroopLoc, uixDefender); 6353 for Prio := true downto false do 6354 for uix := 0 to MyRO.nUn - 1 do 6355 if ((uix = uixDefender) = Prio) and (MyUn[uix].Loc = Loc) then 6356 begin 6357 if uix = UnFocus then 6358 trixFocus := TrCnt; 6359 inc(TrCnt); 6360 end 6361 end 6362 else // count enemy units here 6363 Server(sGetUnits, me, Loc, TrCnt); 6364 if TrCnt = 0 then 6365 InitPVSB(sb, 0, 1) 6366 else 6367 begin 6368 InitPVSB(sb, (TrCnt + TrRow - 1) div TrRow - 1, 1); 6369 with sb.si do 6370 if (nMax >= integer(nPage)) and (trixFocus >= 0) then 6371 begin 6372 sb.si.npos := trixFocus div TrRow; 6373 sb.si.FMask := SIF_POS; 6374 SetScrollInfo(sb.h, SB_CTL, sb.si, true); 6375 end 6376 end 6377 end; 6378 6379 (* procedure TMainScreen.ShowMoveHint(ToLoc: integer; Force: boolean = false); 6380 var 6381 Step,Loc,x0,y0,xs,ys: integer; 6382 Info: string; 6383 InfoSize: TSize; 6384 MoveAdvice: TMoveAdviceData; 6385 begin 6386 if (ToLoc<0) or (ToLoc>=G.lx*G.ly) 6387 or (UnFocus<0) or (MyUn[UnFocus].Loc=ToLoc) then 6388 ToLoc:=-1 6389 else 6390 begin 6391 MoveAdvice.ToLoc:=ToLoc; 6392 MoveAdvice.MoreTurns:=0; 6393 MoveAdvice.MaxHostile_MovementLeft:=MyUn[UnFocus].Health-50; 6394 if Server(sGetMoveAdvice,me,UnFocus,MoveAdvice)<rExecuted then 6395 ToLoc:=-1 6396 end; 6397 if (ToLoc=MoveHintToLoc) and not Force then exit; 6398 if (ToLoc<>MoveHintToLoc) and (MoveHintToLoc>=0) then 6399 begin invalidate; update end; // clear old hint from screen 6400 MoveHintToLoc:=ToLoc; 6401 if ToLoc<0 then exit; 6402 6403 with canvas do 6404 begin 6405 Pen.Color:=$80C0FF; 6406 Pen.Width:=3; 6407 Loc:=MyUn[UnFocus].Loc; 6408 for Step:=0 to MoveAdvice.nStep do 6409 begin 6410 y0:=(Loc+G.lx*1024) div G.lx -1024; 6411 x0:=(Loc+(y0 and 1+G.lx*1024) div 2) mod G.lx; 6412 xs:=(x0-xw)*66+y0 and 1*33-G.lx*66; 6413 while abs(2*(xs+G.lx*66)-MapWidth)<abs(2*xs-MapWidth) do 6414 inc(xs,G.lx*66); 6415 ys:=(y0-yw)*16; 6416 if Step=0 then moveto(xs+33,ys+16) 6417 else lineto(xs+33,ys+16); 6418 if Step<MoveAdvice.nStep then 6419 Loc:=dLoc(Loc,MoveAdvice.dx[Step],MoveAdvice.dy[Step]); 6420 end; 6421 Brush.Color:=$80C0FF; 6422 Info:=' '+inttostr(88)+' '; 6423 InfoSize:=TextExtent(Info); 6424 TextOut(xs+33-InfoSize.cx div 2, ys+16-InfoSize.cy div 2, Info); 6425 Brush.Style:=bsClear; 6426 end 6427 end; *) 6428 6429 procedure TMainScreen.SetDebugMap(p: integer); 6430 begin 6431 IsoEngine.pDebugMap := p; 6432 IsoEngine.Options := IsoEngine.Options and not(1 shl moLocCodes); 6433 mLocCodes.Checked := false; 6434 MapValid := false; 6435 MainOffscreenPaint; 6436 end; 6437 6438 procedure TMainScreen.SetViewpoint(p: integer); 6439 var 6440 i: integer; 6441 begin 6442 if supervising and (G.RO[0].Turn > 0) and 6443 ((p = 0) or (1 shl p and G.RO[0].Alive <> 0)) then 6444 begin 6445 for i := 0 to Screen.FormCount - 1 do 6446 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 6447 then 6448 Screen.Forms[i].Close; // close windows 6449 ItsMeAgain(p); 6450 SumCities(TaxSum, ScienceSum); 6451 for i := 0 to MyRO.nModel - 1 do 6452 if Tribe[me].ModelPicture[i].HGr = 0 then 6453 InitMyModel(i, true); 6454 6455 SetTroopLoc(-1); 6456 PanelPaint; 6457 MapValid := false; 6458 PaintAllMaps; 6459 end 6460 end; 6461 6462 procedure TMainScreen.FormKeyDown(Sender: TObject; var Key: word; 6463 Shift: TShiftState); 6464 6465 procedure MenuClick_Check(Popup: TPopupMenu; Item: TMenuItem); 6466 begin 6467 InitPopup(Popup); 6468 if Item.Visible and Item.Enabled then 6469 MenuClick(Item); 6470 end; 6471 6472 var 6473 dx, dy: integer; 6474 time0, time1: TDateTime; 6475 begin 6476 if GameMode = cMovie then 6477 begin 6478 case Key of 6479 VK_F4: 6480 MenuClick_Check(StatPopup, mScienceStat); 6481 VK_F6: 6482 MenuClick_Check(StatPopup, mDiagram); 6483 VK_F7: 6484 MenuClick_Check(StatPopup, mWonders); 6485 VK_F8: 6486 MenuClick_Check(StatPopup, mShips); 6487 end; 6488 exit; 6489 end; 6490 6491 if not idle then 6492 exit; 6493 6494 if ClientMode = cEditMap then 6495 begin 6496 if Shift = [ssCtrl] then 6497 case char(Key) of 6498 (* 'A': 6499 begin // auto symmetry 6500 Server($7F0,me,0,nil^); 6501 MapValid:=false; 6502 PaintAll; 6503 end; 6504 'B': 6505 begin // land mass 6506 dy:=0; 6507 for dx:=G.lx to G.lx*(G.ly-1)-1 do 6508 if MyMap[dx] and fTerrain>=fGrass then inc(dy); 6509 dy:=dy 6510 end; *) 6511 'Q': 6512 MenuClick(mResign); 6513 'R': 6514 MenuClick(mRandomMap); 6515 end 6516 else if Shift = [] then 6517 case char(Key) of 6518 char(VK_F1): 6519 MenuClick(mHelp); 6520 end; 6521 exit; 6522 end; 6523 6524 if Shift = [ssAlt] then 6525 case char(Key) of 6526 '0': 6527 SetDebugMap(-1); 6528 '1' .. '9': 6529 SetDebugMap(ord(Key) - 48); 6530 end 6531 else if Shift = [ssCtrl] then 6532 case char(Key) of 6533 'J': 6534 MenuClick(mJump); 6535 'K': 6536 mShowClick(mDebugMap); 6537 'L': 6538 mShowClick(mLocCodes); 6539 'M': 6540 if LogDlg.Visible then 6541 LogDlg.Close 6542 else 6543 LogDlg.Show; 6544 'N': 6545 mNamesClick(mNames); 6546 'Q': 6547 MenuClick_Check(GamePopup, mResign); 6548 'R': 6549 MenuClick(mRun); 6550 '0' .. '9': 6551 begin 6552 if ord(Key) - 48 = me then 6553 SetViewpoint(0) 6554 else 6555 SetViewpoint(ord(Key) - 48); 6556 end; 6557 ' ': 6558 begin // test map repaint time 6559 time0 := NowPrecise; 6560 MapValid := false; 6561 MainOffscreenPaint; 6562 time1 := NowPrecise; 6563 SimpleMessage(Format('Map repaint time: %.3f ms', 6564 [MillisecondOf(time1 - time0)])); 6565 end 6566 end 6567 else if Shift = [] then 6568 case char(Key) of 6569 char(VK_F1): 6570 MenuClick(mHelp); 6571 char(VK_F2): 6572 MenuClick_Check(StatPopup, mUnitStat); 6573 char(VK_F3): 6574 MenuClick_Check(StatPopup, mCityStat); 6575 char(VK_F4): 6576 MenuClick_Check(StatPopup, mScienceStat); 6577 char(VK_F5): 6578 MenuClick_Check(StatPopup, mEUnitStat); 6579 char(VK_F6): 6580 MenuClick_Check(StatPopup, mDiagram); 6581 char(VK_F7): 6582 MenuClick_Check(StatPopup, mWonders); 6583 char(VK_F8): 6584 MenuClick_Check(StatPopup, mShips); 6585 char(VK_F9): 6586 MenuClick_Check(StatPopup, mNations); 6587 char(VK_F10): 6588 MenuClick_Check(StatPopup, mEmpire); 6589 char(VK_ADD): 6590 EndTurn; 6591 '1': 6592 MapBtnClick(MapBtn0); 6593 '2': 6594 MapBtnClick(MapBtn1); 6595 '3': 6596 MapBtnClick(MapBtn4); 6597 '4': 6598 MapBtnClick(MapBtn5); 6599 '5': 6600 MapBtnClick(MapBtn6); 6601 'T': 6602 MenuClick(mTechTree); 6603 'W': 6604 MenuClick(mWait); 6605 end; 6606 6607 if UnFocus >= 0 then 6608 if Shift = [ssCtrl] then 6609 case char(Key) of 6610 'C': 6611 MenuClick_Check(UnitPopup, mCancel); 6612 'D': 6613 MenuClick(mDisband); 6614 'P': 6615 MenuClick_Check(UnitPopup, mPillage); 6616 'T': 6617 MenuClick_Check(UnitPopup, mSelectTransport); 6618 end 6619 else if Shift = [] then 6620 case char(Key) of 6621 ' ': 6622 MenuClick(mNoOrders); 6623 'A': 6624 MenuClick_Check(TerrainPopup, mAirBase); 6625 'B': 6626 MenuClick_Check(UnitPopup, mCity); 6627 'C': 6628 MenuClick(mCentre); 6629 'E': 6630 begin 6631 InitPopup(TerrainPopup); 6632 if mEnhance.Visible and mEnhance.Enabled then 6633 MenuClick(mEnhance) 6634 else 6635 MenuClick(mEnhanceDef) 6636 end; 6637 'F': 6638 MenuClick_Check(TerrainPopup, mFort); 6639 'G': 6640 MenuClick_Check(UnitPopup, mGoOn); 6641 'H': 6642 MenuClick_Check(UnitPopup, mHome); 6643 'I': 6644 if JobTest(UnFocus, jFarm, [eTreaty]) then 6645 MenuClick(mFarm) 6646 else if JobTest(UnFocus, jClear, [eTreaty]) then 6647 MenuClick(mClear) 6648 else 6649 MenuClick_Check(TerrainPopup, mIrrigation); 6650 'L': 6651 MenuClick_Check(UnitPopup, mLoad); 6652 'M': 6653 if JobTest(UnFocus, jAfforest, [eTreaty]) then 6654 MenuClick(mAfforest) 6655 else 6656 MenuClick_Check(TerrainPopup, mMine); 6657 'N': 6658 MenuClick_Check(TerrainPopup, mCanal); 6659 'O': 6660 MenuClick_Check(TerrainPopup, MTrans); 6661 'P': 6662 MenuClick_Check(TerrainPopup, mPollution); 6663 'R': 6664 if JobTest(UnFocus, jRR, [eTreaty]) then 6665 MenuClick(mRR) 6666 else 6667 MenuClick_Check(TerrainPopup, mRoad); 6668 'S': 6669 MenuClick(mStay); 6670 'U': 6671 MenuClick_Check(UnitPopup, mUnload); 6672 'V': 6673 MenuClick_Check(UnitPopup, mRecover); 6674 'Z': 6675 MenuClick_Check(UnitPopup, mUtilize); 6676 #33 .. #40, #97 .. #100, #102 .. #105: 6677 begin { arrow keys } 6678 DestinationMarkON := false; 6679 PaintDestination; 6680 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 6681 ($FFFF - usStay - usRecover - usGoto - usEnhance) or 6682 usWaiting; 6683 case Key of 6684 VK_NUMPAD1, VK_END: 6685 begin 6686 dx := -1; 6687 dy := 1 6688 end; 6689 VK_NUMPAD2, VK_DOWN: 6690 begin 6691 dx := 0; 6692 dy := 2 6693 end; 6694 VK_NUMPAD3, VK_NEXT: 6695 begin 6696 dx := 1; 6697 dy := 1 6698 end; 6699 VK_NUMPAD4, VK_LEFT: 6700 begin 6701 dx := -2; 6702 dy := 0 6703 end; 6704 VK_NUMPAD6, VK_RIGHT: 6705 begin 6706 dx := 2; 6707 dy := 0 6708 end; 6709 VK_NUMPAD7, VK_HOME: 6710 begin 6711 dx := -1; 6712 dy := -1 6713 end; 6714 VK_NUMPAD8, VK_UP: 6715 begin 6716 dx := 0; 6717 dy := -2 6718 end; 6719 VK_NUMPAD9, VK_PRIOR: 6720 begin 6721 dx := 1; 6722 dy := -1 6723 end; 6724 end; 6725 MoveUnit(dx, dy, muAutoNext) 6726 end; 6727 end 6728 end; 6729 6730 procedure TMainScreen.MenuClick(Sender: TObject); 6731 6732 function DoJob(j0: integer): integer; 6733 var 6734 Loc0, Movement0: integer; 6735 begin 6736 with MyUn[UnFocus] do 6737 begin 6738 DestinationMarkON := false; 6739 PaintDestination; 6740 Loc0 := Loc; 6741 Movement0 := Movement; 6742 if j0 < 0 then 6743 result := ProcessEnhancement(UnFocus, MyData.EnhancementJobs) 6744 // terrain enhancement 6745 else 6746 result := Server(sStartJob + j0 shl 4, me, UnFocus, nil^); 6747 if result >= rExecuted then 6748 begin 6749 if result = eDied then 6750 UnFocus := -1; 6751 PaintLoc(Loc0); 6752 if UnFocus >= 0 then 6753 begin 6754 if (j0 < 0) and (result <> eJobDone) then 6755 // multi-turn terrain enhancement 6756 Status := Status and ($FFFF - usStay - usRecover - usGoto) or 6757 usEnhance 6758 else 6759 Status := Status and 6760 ($FFFF - usStay - usRecover - usGoto - usEnhance); 6761 if (Job <> jNone) or (Movement0 < 100) then 6762 begin 6763 Status := Status and not usWaiting; 6764 NextUnit(UnStartLoc, true); 6765 end 6766 else 6767 PanelPaint 6768 end 6769 else 6770 NextUnit(UnStartLoc, true); 6771 end 6772 end; 6773 case result of 6774 eNoBridgeBuilding: 6775 SoundMessage(Phrases.Lookup('NOBB'), 'INVALID'); 6776 eNoCityTerrain: 6777 SoundMessage(Phrases.Lookup('NOCITY'), 'INVALID'); 6778 eTreaty: 6779 SoundMessage(Tribe[MyRO.Territory[Loc0]].TPhrase('PEACE_NOWORK'), 6780 'NOMOVE_TREATY'); 6781 else 6782 if result < rExecuted then 6783 Play('INVALID') 6784 end 6785 end; 6786 6787 var 6788 i, uix, NewFocus, Loc0, OldMaster, Destination, cix, cixOldHome, 6789 ServerResult: integer; 6790 AltGovs, Changed: boolean; 6791 QueryText: string; 6792 6793 begin 6794 if Sender = mResign then 6795 if ClientMode = cEditMap then 6796 begin 6797 if Edited then 6798 begin 6799 QueryText := Phrases.Lookup('MAP_CLOSE'); 6800 case SimpleQuery(mkYesNoCancel, QueryText, '') of 6801 mrIgnore: 6802 Server(sAbandonMap, me, 0, nil^); 6803 mrOK: 6804 Server(sSaveMap, me, 0, nil^); 6805 end 6806 end 6807 else 6808 Server(sAbandonMap, me, 0, nil^) 6809 end 6810 else 6811 begin 6812 if Server(sGetGameChanged, 0, 0, nil^) = eOK then 6813 begin 6814 QueryText := Phrases.Lookup('RESIGN'); 6815 case SimpleQuery(mkYesNoCancel, QueryText, '') of 6816 mrIgnore: 6817 Server(sResign, 0, 0, nil^); 6818 mrOK: 6819 Server(sBreak, 0, 0, nil^) 6820 end 6821 end 6822 else 6823 Server(sResign, 0, 0, nil^) 6824 end 6825 else if Sender = mEmpire then 6826 RatesDlg.ShowNewContent(wmPersistent) 6827 else if Sender = mRevolution then 6828 begin 6829 AltGovs := false; 6830 for i := 2 to nGov - 1 do 6831 if (GovPreq[i] <> preNA) and 6832 ((GovPreq[i] = preNone) or (MyRO.Tech[GovPreq[i]] >= tsApplicable)) 6833 then 6834 AltGovs := true; 6835 6836 if not AltGovs then 6837 SoundMessage(Phrases.Lookup('NOALTGOVS'), 'MSG_DEFAULT') 6838 else 6839 begin 6840 Changed := false; 6841 if MyRO.Happened and phChangeGov <> 0 then 6842 begin 6843 ModalSelectDlg.ShowNewContent(wmModal, kGov); 6844 if ModalSelectDlg.result >= 0 then 6845 begin 6846 Play('NEWGOV'); 6847 Server(sSetGovernment, me, ModalSelectDlg.result, nil^); 6848 CityOptimizer_BeginOfTurn; 6849 Changed := true; 6850 end 6851 end 6852 else 6853 // TODO with MessgExDlg do 6854 begin // revolution! 6855 MessgExDlg.MessgText := Tribe[me].TPhrase('REVOLUTION'); 6856 MessgExDlg.Kind := mkYesNo; 6857 MessgExDlg.IconKind := mikPureIcon; 6858 MessgExDlg.IconIndex := 72; // anarchy palace 6859 MessgExDlg.ShowModal; 6860 if ModalResult = mrOK then 6861 begin 6862 Play('REVOLUTION'); 6863 Server(sRevolution, me, 0, nil^); 6864 Changed := true; 6865 if NatStatDlg.Visible then 6866 NatStatDlg.Close; 6867 if CityDlg.Visible then 6868 CityDlg.Close; 6869 end 6870 end; 6871 if Changed then 6872 UpdateViews(true); 6873 end 6874 end 6875 else if Sender = mWebsite then 6876 OpenURL('http://c-evo.org'){ *Převedeno z ShellExecute* } 6877 else if Sender = mRandomMap then 6878 begin 6879 if not Edited or (SimpleQuery(mkYesNo, Phrases.Lookup('MAP_RANDOM'), '') 6880 = mrOK) then 6881 begin 6882 Server(sRandomMap, me, 0, nil^); 6883 Edited := true; 6884 MapValid := false; 6885 PaintAllMaps; 6886 end 6887 end 6888 else if Sender = mJump then 6889 begin 6890 if supervising then 6891 Jump[0] := 20 6892 else 6893 Jump[me] := 20; 6894 EndTurn(true); 6895 end 6896 else if Sender = mRun then 6897 begin 6898 if supervising then 6899 Jump[0] := 999999 6900 else 6901 Jump[me] := 999999; 6902 EndTurn(true); 6903 end 6904 else if Sender = mEnhanceDef then 6905 begin 6906 if UnFocus >= 0 then 6907 EnhanceDlg.ShowNewContent(wmPersistent, 6908 MyMap[MyUn[UnFocus].Loc] and fTerrain) 6909 else 6910 EnhanceDlg.ShowNewContent(wmPersistent) 6911 end 6912 else if Sender = mCityTypes then 6913 CityTypeDlg.ShowNewContent(wmModal) 6914 // must be modal because types are not saved before closing 6915 else if Sender = mUnitStat then 6916 begin 6917 if G.Difficulty[me] > 0 then 6918 ListDlg.ShowNewContent_MilReport(wmPersistent, me) 6919 else 6920 begin 6921 i := 1; 6922 while (i < nPl) and (1 shl i and MyRO.Alive = 0) do 6923 inc(i); 6924 if i < nPl then 6925 ListDlg.ShowNewContent_MilReport(wmPersistent, i); 6926 end; 6927 end 6928 else if Sender = mEUnitStat then 6929 begin 6930 if MyRO.nEnemyModel > 0 then 6931 ListDlg.ShowNewContent(wmPersistent, kAllEModels); 6932 end 6933 else if Sender = mCityStat then 6934 ListDlg.ShowNewContent(wmPersistent, kCities) 6935 else if Sender = mScienceStat then 6936 ListDlg.ShowNewContent(wmPersistent, kScience) 6937 else if Sender = mNations then 6938 NatStatDlg.ShowNewContent(wmPersistent) 6939 else if Sender = mHelp then 6940 if ClientMode = cEditMap then 6941 HelpDlg.ShowNewContent(wmPersistent, hkText, 6942 HelpDlg.TextIndex('MAPEDIT')) 6943 else 6944 HelpDlg.ShowNewContent(wmPersistent, hkMisc, miscMain) 6945 else if Sender = mTechTree then 6946 TechTreeDlg.ShowModal 6947 else if Sender = mWonders then 6948 WondersDlg.ShowNewContent(wmPersistent) 6949 else if Sender = mDiagram then 6950 DiaDlg.ShowNewContent_Charts(wmPersistent) 6951 else if Sender = mShips then 6952 DiaDlg.ShowNewContent_Ship(wmPersistent) 6953 else if Sender = mWait then 6954 begin 6955 if UnFocus >= 0 then 6956 begin 6957 DestinationMarkON := false; 6958 PaintDestination; 6959 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 6960 ($FFFF - usStay - usRecover - usGoto - usEnhance) or usWaiting; 6961 end; 6962 NextUnit(-1, false); 6963 end 6964 else if UnFocus >= 0 then 6965 with MyUn[UnFocus] do 6966 if Sender = mGoOn then 6967 begin 6968 if Status shr 16 = $7FFF then 6969 Destination := maNextCity 6970 else 6971 Destination := Status shr 16; 6972 Status := Status and not(usStay or usRecover) or usWaiting; 6973 MoveToLoc(Destination, true); 6974 end 6975 else if Sender = mHome then 6976 if MyMap[Loc] and fCity <> 0 then 6977 begin 6978 cixOldHome := Home; 6979 if Server(sSetUnitHome, me, UnFocus, nil^) >= rExecuted then 6980 begin 6981 CityOptimizer_CityChange(cixOldHome); 6982 CityOptimizer_CityChange(Home); 6983 UpdateViews(true); 6984 end 6985 else 6986 Play('INVALID'); 6987 end 6988 else 6989 begin 6990 Status := Status and not(usStay or usRecover or usEnhance); 6991 MoveToLoc(maNextCity, true) 6992 end 6993 else if Sender = mCentre then 6994 begin 6995 Centre(Loc); 6996 PaintAllMaps 6997 end 6998 else if Sender = mCity then 6999 begin 7000 Loc0 := Loc; 7001 if MyMap[Loc] and fCity = 0 then 7002 begin // build city 7003 if DoJob(jCity) = eCity then 7004 begin 7005 MapValid := false; 7006 PaintAll; 7007 ZoomToCity(Loc0, true, chFounded); 7008 end 7009 end 7010 else 7011 begin 7012 CityOptimizer_BeforeRemoveUnit(UnFocus); 7013 ServerResult := Server(sAddToCity, me, UnFocus, nil^); 7014 if ServerResult >= rExecuted then 7015 begin 7016 cix := MyRO.nCity - 1; 7017 while (cix >= 0) and (MyCity[cix].Loc <> Loc0) do 7018 dec(cix); 7019 assert(cix >= 0); 7020 CityOptimizer_CityChange(cix); 7021 CityOptimizer_AfterRemoveUnit; // does nothing here 7022 SetTroopLoc(Loc0); 7023 UpdateViews(true); 7024 DestinationMarkON := false; 7025 PaintDestination; 7026 UnFocus := -1; 7027 PaintLoc(Loc0); 7028 NextUnit(UnStartLoc, true); 7029 end 7030 else if ServerResult = eMaxSize then 7031 SimpleMessage(Phrases.Lookup('ADDTOMAXSIZE')); 7032 end 7033 end 7034 else if Sender = mRoad then 7035 DoJob(jRoad) 7036 else if Sender = mRR then 7037 DoJob(jRR) 7038 else if Sender = mClear then 7039 DoJob(jClear) 7040 else if Sender = mIrrigation then 7041 DoJob(jIrr) 7042 else if Sender = mFarm then 7043 DoJob(jFarm) 7044 else if Sender = mAfforest then 7045 DoJob(jAfforest) 7046 else if Sender = mMine then 7047 DoJob(jMine) 7048 else if Sender = mCanal then 7049 DoJob(jCanal) 7050 else if Sender = MTrans then 7051 DoJob(jTrans) 7052 else if Sender = mFort then 7053 DoJob(jFort) 7054 else if Sender = mAirBase then 7055 DoJob(jBase) 7056 else if Sender = mPollution then 7057 DoJob(jPoll) 7058 else if Sender = mPillage then 7059 DoJob(jPillage) 7060 else if Sender = mEnhance then 7061 DoJob(-1) 7062 else if Sender = mStay then 7063 begin 7064 DestinationMarkON := false; 7065 PaintDestination; 7066 Status := Status and ($FFFF - usRecover - usGoto - usEnhance) 7067 or usStay; 7068 if Job > jNone then 7069 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 7070 NextUnit(UnStartLoc, true) 7071 end 7072 else if Sender = mRecover then 7073 begin 7074 DestinationMarkON := false; 7075 PaintDestination; 7076 Status := Status and ($FFFF - usStay - usGoto - usEnhance) or 7077 usRecover; 7078 if Job > jNone then 7079 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 7080 NextUnit(UnStartLoc, true) 7081 end 7082 else if Sender = mNoOrders then 7083 begin 7084 Status := Status and not usWaiting; 7085 NextUnit(UnStartLoc, true) 7086 end 7087 else if Sender = mCancel then 7088 begin 7089 DestinationMarkON := false; 7090 PaintDestination; 7091 Status := Status and ($FFFF - usRecover - usGoto - usEnhance); 7092 if Job > jNone then 7093 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 7094 end 7095 else if (Sender = mDisband) or (Sender = mUtilize) then 7096 begin 7097 if (Sender = mUtilize) and 7098 not(Server(sRemoveUnit - sExecute, me, UnFocus, nil^) = eUtilized) 7099 then 7100 begin 7101 SimpleMessage(Phrases2.Lookup('SHIP_UTILIZE')); 7102 // freight for colony ship is the only case in which the command is 7103 // available to player though not valid 7104 exit 7105 end; 7106 if (Sender = mUtilize) and (Health < 100) then 7107 if SimpleQuery(mkYesNo, Phrases.Lookup('DAMAGED_UTILIZE'), '') <> mrOK 7108 then 7109 exit; 7110 Loc0 := Loc; 7111 CityOptimizer_BeforeRemoveUnit(UnFocus); 7112 if Server(sRemoveUnit, me, UnFocus, nil^) = eUtilized then 7113 Play('CITY_UTILIZE') 7114 else 7115 Play('DISBAND'); 7116 CityOptimizer_AfterRemoveUnit; 6991 cix := MyRO.nCity - 1; 6992 while (cix >= 0) and (MyCity[cix].Loc <> Loc0) do 6993 dec(cix); 6994 assert(cix >= 0); 6995 CityOptimizer_CityChange(cix); 6996 CityOptimizer_AfterRemoveUnit; // does nothing here 7117 6997 SetTroopLoc(Loc0); 7118 6998 UpdateViews(true); … … 7123 7003 NextUnit(UnStartLoc, true); 7124 7004 end 7125 else if Sender = mLoad then 7005 else if ServerResult = eMaxSize then 7006 SimpleMessage(Phrases.Lookup('ADDTOMAXSIZE')); 7007 end 7008 end 7009 else if Sender = mRoad then 7010 DoJob(jRoad) 7011 else if Sender = mRR then 7012 DoJob(jRR) 7013 else if Sender = mClear then 7014 DoJob(jClear) 7015 else if Sender = mIrrigation then 7016 DoJob(jIrr) 7017 else if Sender = mFarm then 7018 DoJob(jFarm) 7019 else if Sender = mAfforest then 7020 DoJob(jAfforest) 7021 else if Sender = mMine then 7022 DoJob(jMine) 7023 else if Sender = mCanal then 7024 DoJob(jCanal) 7025 else if Sender = MTrans then 7026 DoJob(jTrans) 7027 else if Sender = mFort then 7028 DoJob(jFort) 7029 else if Sender = mAirBase then 7030 DoJob(jBase) 7031 else if Sender = mPollution then 7032 DoJob(jPoll) 7033 else if Sender = mPillage then 7034 DoJob(jPillage) 7035 else if Sender = mEnhance then 7036 DoJob(-1) 7037 else if Sender = mStay then 7038 begin 7039 DestinationMarkON := false; 7040 PaintDestination; 7041 Status := Status and ($FFFF - usRecover - usGoto - usEnhance) or usStay; 7042 if Job > jNone then 7043 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 7044 NextUnit(UnStartLoc, true) 7045 end 7046 else if Sender = mRecover then 7047 begin 7048 DestinationMarkON := false; 7049 PaintDestination; 7050 Status := Status and ($FFFF - usStay - usGoto - usEnhance) or usRecover; 7051 if Job > jNone then 7052 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 7053 NextUnit(UnStartLoc, true) 7054 end 7055 else if Sender = mNoOrders then 7056 begin 7057 Status := Status and not usWaiting; 7058 NextUnit(UnStartLoc, true) 7059 end 7060 else if Sender = mCancel then 7061 begin 7062 DestinationMarkON := false; 7063 PaintDestination; 7064 Status := Status and ($FFFF - usRecover - usGoto - usEnhance); 7065 if Job > jNone then 7066 Server(sStartJob + jNone shl 4, me, UnFocus, nil^); 7067 end 7068 else if (Sender = mDisband) or (Sender = mUtilize) then 7069 begin 7070 if (Sender = mUtilize) and 7071 not(Server(sRemoveUnit - sExecute, me, UnFocus, nil^) = eUtilized) 7072 then 7073 begin 7074 SimpleMessage(Phrases2.Lookup('SHIP_UTILIZE')); 7075 // freight for colony ship is the only case in which the command is 7076 // available to player though not valid 7077 exit 7078 end; 7079 if (Sender = mUtilize) and (Health < 100) then 7080 if SimpleQuery(mkYesNo, Phrases.Lookup('DAMAGED_UTILIZE'), '') <> mrOK 7081 then 7082 exit; 7083 Loc0 := Loc; 7084 CityOptimizer_BeforeRemoveUnit(UnFocus); 7085 if Server(sRemoveUnit, me, UnFocus, nil^) = eUtilized then 7086 Play('CITY_UTILIZE') 7087 else 7088 Play('DISBAND'); 7089 CityOptimizer_AfterRemoveUnit; 7090 SetTroopLoc(Loc0); 7091 UpdateViews(true); 7092 DestinationMarkON := false; 7093 PaintDestination; 7094 UnFocus := -1; 7095 PaintLoc(Loc0); 7096 NextUnit(UnStartLoc, true); 7097 end 7098 else if Sender = mLoad then 7099 begin 7100 i := Server(sLoadUnit, me, UnFocus, nil^); 7101 if i >= rExecuted then 7102 begin 7103 if MyModel[mix].Domain = dAir then 7104 Play('MOVE_PLANELANDING') 7105 else 7106 Play('MOVE_LOAD'); 7107 DestinationMarkON := false; 7108 PaintDestination; 7109 Status := Status and ($FFFF - usWaiting - usStay - usRecover - usGoto 7110 - usEnhance); 7111 NextUnit(UnStartLoc, true); 7112 end 7113 else if i = eNoTime_Load then 7114 if MyModel[mix].Domain = dAir then 7115 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'), 'NOMOVE_TIME') 7116 else 7117 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 7118 [MovementToString(MyModel[mix].speed)]), 'NOMOVE_TIME'); 7119 end 7120 else if Sender = mUnload then 7121 if Master >= 0 then 7122 begin 7123 OldMaster := Master; 7124 i := Server(sUnloadUnit, me, UnFocus, nil^); 7125 if i >= rExecuted then 7126 7126 begin 7127 i := Server(sLoadUnit, me, UnFocus, nil^); 7128 if i >= rExecuted then 7129 begin 7130 if MyModel[mix].Domain = dAir then 7131 Play('MOVE_PLANELANDING') 7132 else 7133 Play('MOVE_LOAD'); 7134 DestinationMarkON := false; 7135 PaintDestination; 7136 Status := Status and 7137 ($FFFF - usWaiting - usStay - usRecover - usGoto - usEnhance); 7138 NextUnit(UnStartLoc, true); 7139 end 7140 else if i = eNoTime_Load then 7141 if MyModel[mix].Domain = dAir then 7142 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'), 'NOMOVE_TIME') 7143 else 7144 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 7145 [MovementToString(MyModel[mix].speed)]), 'NOMOVE_TIME'); 7127 if MyModel[mix].Domain = dAir then 7128 Play('MOVE_PLANESTART') 7129 else if (MyModel[MyUn[OldMaster].mix].Domain = dAir) and 7130 (MyMap[Loc] and fCity = 0) and (MyMap[Loc] and fTerImp <> tiBase) 7131 then 7132 Play('MOVE_PARACHUTE') 7133 else 7134 Play('MOVE_UNLOAD'); 7135 Status := Status and not usWaiting; 7136 if MyModel[mix].Domain <> dAir then 7137 NextUnit(Loc, true) 7138 else 7139 PanelPaint 7146 7140 end 7147 else if Sender = mUnload then 7148 if Master >= 0 then 7149 begin 7150 OldMaster := Master; 7151 i := Server(sUnloadUnit, me, UnFocus, nil^); 7152 if i >= rExecuted then 7153 begin 7154 if MyModel[mix].Domain = dAir then 7155 Play('MOVE_PLANESTART') 7156 else if (MyModel[MyUn[OldMaster].mix].Domain = dAir) and 7157 (MyMap[Loc] and fCity = 0) and 7158 (MyMap[Loc] and fTerImp <> tiBase) then 7159 Play('MOVE_PARACHUTE') 7160 else 7161 Play('MOVE_UNLOAD'); 7162 Status := Status and not usWaiting; 7163 if MyModel[mix].Domain <> dAir then 7164 NextUnit(Loc, true) 7165 else 7166 PanelPaint 7167 end 7168 else if i = eNoTime_Load then 7169 if MyModel[mix].Domain = dAir then 7170 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'), 'NOMOVE_TIME') 7171 else 7172 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 7173 [MovementToString(MyModel[mix].speed)]), 'NOMOVE_TIME'); 7174 end 7141 else if i = eNoTime_Load then 7142 if MyModel[mix].Domain = dAir then 7143 SoundMessage(Phrases.Lookup('NOTIMELOADAIR'), 'NOMOVE_TIME') 7175 7144 else 7176 begin 7177 NewFocus := -1; 7178 uix := UnFocus; 7179 for i := 1 to MyRO.nUn - 1 do 7180 begin 7181 uix := (uix + MyRO.nUn - 1) mod MyRO.nUn; 7182 if (MyUn[uix].Master = UnFocus) and 7183 (MyUn[uix].Movement = integer(MyModel[MyUn[uix].mix].speed)) 7184 then 7185 begin 7186 MyUn[uix].Status := MyUn[uix].Status or usWaiting; 7187 NewFocus := uix 7188 end; 7189 end; 7190 if NewFocus >= 0 then 7191 begin 7192 SetUnFocus(NewFocus); 7193 SetTroopLoc(Loc); 7194 PanelPaint 7195 end 7196 end 7197 else if Sender = mSelectTransport then 7198 Server(sSelectTransport, me, UnFocus, nil^) 7199 end; 7200 7201 procedure TMainScreen.InitPopup(Popup: TPopupMenu); 7202 var 7203 i, p1, Tile, Test: integer; 7204 NoSuper, extended, Multi, NeedSep, HaveCities: boolean; 7205 LastSep, m: TMenuItem; 7206 mox: ^TModel; 7207 begin 7208 NoSuper := not supervising and (1 shl me and MyRO.Alive <> 0); 7209 HaveCities := false; 7210 for i := 0 to MyRO.nCity - 1 do 7211 if MyCity[i].Loc >= 0 then 7212 begin 7213 HaveCities := true; 7214 Break 7215 end; 7216 if Popup = GamePopup then 7217 begin 7218 mTechTree.Visible := ClientMode <> cEditMap; 7219 mResign.Enabled := supervising or (me = 0) and (ClientMode < scContact); 7220 mRandomMap.Visible := (ClientMode = cEditMap) and 7221 (Server(sMapGeneratorRequest, me, 0, nil^) = eOK); 7222 mOptions.Visible := ClientMode <> cEditMap; 7223 mManip.Visible := ClientMode <> cEditMap; 7224 if ClientMode <> cEditMap then 7225 begin 7226 mWaitTurn.Visible := NoSuper; 7227 mRep.Visible := NoSuper; 7228 mRepList.Visible := NoSuper; 7229 mRepScreens.Visible := NoSuper; 7230 N10.Visible := NoSuper; 7231 mOwnMovement.Visible := NoSuper; 7232 mAllyMovement.Visible := NoSuper; 7233 case SoundMode of 7234 smOff: 7235 mSoundOff.Checked := true; 7236 smOn: 7237 mSoundOn.Checked := true; 7238 smOnAlt: 7239 mSoundOnAlt.Checked := true; 7240 end; 7241 7242 for i := 0 to nTestFlags - 1 do 7243 mManip[i].Checked := MyRO.TestFlags and (1 shl i) <> 0; 7244 mManip.Enabled := supervising or (me = 0); 7245 7246 Multi := false; 7247 for p1 := 1 to nPl - 1 do 7248 if G.RO[p1] <> nil then 7249 Multi := true; 7250 mEnemyMovement.Visible := not Multi; 7251 end; 7252 mMacro.Visible := NoSuper and (ClientMode < scContact); 7253 if NoSuper and (ClientMode < scContact) then 7254 begin 7255 mCityTypes.Enabled := false; 7256 // check if city types already usefull: 7257 if MyRO.nCity > 0 then 7258 for i := 28 to nImp - 1 do 7259 if (i <> imTrGoods) and (Imp[i].Kind = ikCommon) and 7260 (Imp[i].Preq <> preNA) and 7261 ((Imp[i].Preq = preNone) or 7262 (MyRO.Tech[Imp[i].Preq] >= tsApplicable)) then 7263 begin 7264 mCityTypes.Enabled := true; 7265 Break 7266 end; 7267 end; 7268 mViewpoint.Visible := (ClientMode <> cEditMap) and supervising; 7269 mViewpoint.Enabled := G.RO[0].Turn > 0; 7270 if supervising then 7271 begin 7272 EmptyMenu(mViewpoint); 7273 for p1 := 0 to nPl - 1 do 7274 if (p1 = 0) or (1 shl p1 and G.RO[0].Alive <> 0) then 7275 begin 7276 m := TMenuItem.Create(mViewpoint); 7277 if p1 = 0 then 7278 m.Caption := Phrases.Lookup('SUPER') 7279 else 7280 m.Caption := Tribe[p1].TString(Phrases2.Lookup('BELONG')); 7281 m.Tag := p1; 7282 m.OnClick := ViewpointClick; 7283 if p1 < 10 then 7284 m.ShortCut := ShortCut(48 + p1, [ssCtrl]); 7285 m.RadioItem := true; 7286 if p1 = me then 7287 m.Checked := true; 7288 mViewpoint.Add(m); 7289 end 7290 end; 7291 mDebugMap.Visible := (ClientMode <> cEditMap) and supervising; 7292 if supervising then 7293 begin 7294 EmptyMenu(mDebugMap); 7295 for p1 := 0 to nPl - 1 do 7296 if (p1 = 0) or (1 shl p1 and G.RO[0].Alive <> 0) then 7297 begin 7298 m := TMenuItem.Create(mDebugMap); 7299 if p1 = 0 then 7300 m.Caption := Phrases2.Lookup('MENU_DEBUGMAPOFF') 7301 else 7302 m.Caption := Tribe[p1].TString(Phrases2.Lookup('BELONG')); 7303 if p1 = 0 then 7304 m.Tag := -1 7305 else 7306 m.Tag := p1; 7307 m.OnClick := DebugMapClick; 7308 if p1 < 10 then 7309 m.ShortCut := ShortCut(48 + p1, [ssAlt]); 7310 m.RadioItem := true; 7311 if m.Tag = IsoEngine.pDebugMap then 7312 m.Checked := true; 7313 mDebugMap.Add(m); 7314 end 7315 end; 7316 mSmallTiles.Checked := xxt = 33; 7317 mNormalTiles.Checked := xxt = 48; 7318 end 7319 else if Popup = StatPopup then 7320 begin 7321 mEmpire.Visible := NoSuper; 7322 mEmpire.Enabled := MyRO.Government <> gAnarchy; 7323 mRevolution.Visible := NoSuper; 7324 mRevolution.Enabled := (MyRO.Government <> gAnarchy) and 7325 (ClientMode < scContact); 7326 mUnitStat.Enabled := NoSuper or (MyRO.Turn > 0); 7327 mCityStat.Visible := 1 shl me and MyRO.Alive <> 0; 7328 mCityStat.Enabled := HaveCities; 7329 mScienceStat.Visible := true; 7330 mScienceStat.Enabled := not NoSuper or (MyRO.ResearchTech >= 0) or 7331 (MyRO.Happened and phTech <> 0) or (MyRO.Happened and phGameEnd <> 0) 7332 // no researchtech in case just completed 7333 or (MyRO.TestFlags and (tfAllTechs or tfUncover or 7334 tfAllContact) <> 0); 7335 mEUnitStat.Enabled := MyRO.nEnemyModel > 0; 7336 { mWonders.Enabled:= false; 7337 for i:=0 to 27 do if MyRO.Wonder[i].CityID<>-1 then 7338 mWonders.Enabled:=true; } 7339 mDiagram.Enabled := MyRO.Turn >= 2; 7340 mShips.Enabled := false; 7341 for p1 := 0 to nPl - 1 do 7342 if MyRO.Ship[p1].Parts[spComp] + MyRO.Ship[p1].Parts[spPow] + 7343 MyRO.Ship[p1].Parts[spHab] > 0 then 7344 mShips.Enabled := true; 7345 end 7346 else if Popup = UnitPopup then 7347 begin 7348 mox := @MyModel[MyUn[UnFocus].mix]; 7349 Tile := MyMap[MyUn[UnFocus].Loc]; 7350 extended := Tile and fCity = 0; 7351 if extended then 7352 begin 7353 mCity.Caption := Phrases.Lookup('BTN_FOUND'); 7354 mHome.Caption := Phrases.Lookup('BTN_MOVEHOME') 7145 SoundMessage(Format(Phrases.Lookup('NOTIMELOADGROUND'), 7146 [MovementToString(MyModel[mix].speed)]), 'NOMOVE_TIME'); 7355 7147 end 7356 7148 else 7357 7149 begin 7358 mCity.Caption := Phrases.Lookup('BTN_ADD'); 7359 mHome.Caption := Phrases.Lookup('BTN_SETHOME') 7360 end; 7361 7362 extended := extended and 7363 ((mox.Kind = mkSettler) or (mox.Kind = mkSlaves) and 7364 (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)) and 7365 (MyUn[UnFocus].Master < 0) and (Tile and fDeadLands = 0); 7366 if (mox.Kind = mkFreight) and (Tile and fCity <> 0) and 7367 not Phrases2FallenBackToEnglish or 7368 (Server(sRemoveUnit - sExecute, me, UnFocus, nil^) = eUtilized) then 7369 begin 7370 mDisband.Visible := false; 7371 mUtilize.Visible := true; 7372 if mox.Kind = mkFreight then 7373 mUtilize.Caption := Phrases.Lookup('UTILIZE') 7374 else 7375 mUtilize.Caption := Phrases.Lookup('INTEGRATE') 7376 end 7377 else 7378 begin 7379 mDisband.Visible := true; 7380 mUtilize.Visible := false 7381 end; 7382 mGoOn.Visible := MyUn[UnFocus].Status and (usGoto or usWaiting) 7383 = usGoto or usWaiting; 7384 mHome.Visible := HaveCities; 7385 mRecover.Visible := (MyUn[UnFocus].Health < 100) and 7386 (Tile and fTerrain >= fGrass) and 7387 ((MyRO.Wonder[woGardens].EffectiveOwner = me) or 7388 (Tile and fTerrain <> fArctic) and (Tile and fTerrain <> fDesert)) and 7389 not((mox.Domain = dAir) and (Tile and fCity = 0) and 7390 (Tile and fTerImp <> tiBase)); 7391 mStay.Visible := not((mox.Domain = dAir) and (Tile and fCity = 0) and 7392 (Tile and fTerImp <> tiBase)); 7393 mCity.Visible := extended and (mox.Kind = mkSettler) or 7394 (Tile and fCity <> 0) and ((mox.Kind in [mkSettler, mkSlaves]) or 7395 (MyUn[UnFocus].Flags and unConscripts <> 0)); 7396 mPillage.Visible := (Tile and (fRoad or fRR or fCanal or fTerImp) <> 0) 7397 and (MyUn[UnFocus].Master < 0) and (mox.Domain = dGround); 7398 mCancel.Visible := (MyUn[UnFocus].Job > jNone) or 7399 (MyUn[UnFocus].Status and (usRecover or usGoto) <> 0); 7400 7401 Test := Server(sLoadUnit - sExecute, me, UnFocus, nil^); 7402 mLoad.Visible := (Test >= rExecuted) or (Test = eNoTime_Load); 7403 mUnload.Visible := (MyUn[UnFocus].Master >= 0) or 7404 (MyUn[UnFocus].TroopLoad + MyUn[UnFocus].AirLoad > 0); 7405 mSelectTransport.Visible := Server(sSelectTransport - sExecute, me, 7406 UnFocus, nil^) >= rExecuted; 7407 end 7408 else { if Popup=TerrainPopup then } 7409 begin 7410 mox := @MyModel[MyUn[UnFocus].mix]; 7411 Tile := MyMap[MyUn[UnFocus].Loc]; 7412 extended := Tile and fCity = 0; 7413 7414 if (Tile and fRiver <> 0) and 7415 (MyRO.Tech[adBridgeBuilding] >= tsApplicable) then 7416 begin 7417 mRoad.Caption := Phrases.Lookup('BTN_BUILDBRIDGE'); 7418 mRR.Caption := Phrases.Lookup('BTN_BUILDRRBRIDGE'); 7419 end 7420 else 7421 begin 7422 mRoad.Caption := Phrases.Lookup('BTN_BUILDROAD'); 7423 mRR.Caption := Phrases.Lookup('BTN_BUILDRR'); 7424 end; 7425 if Tile and fTerrain = fForest then 7426 mClear.Caption := Phrases.Lookup('BTN_CLEAR') 7427 else if Tile and fTerrain = fDesert then 7428 mClear.Caption := Phrases.Lookup('BTN_UNDESERT') 7429 else 7430 mClear.Caption := Phrases.Lookup('BTN_DRAIN'); 7431 7432 extended := extended and 7433 ((mox.Kind = mkSettler) or (mox.Kind = mkSlaves) and 7434 (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)) and 7435 (MyUn[UnFocus].Master < 0); 7436 if extended then 7437 begin 7438 mRoad.Visible := JobTest(UnFocus, jRoad, 7439 [eNoBridgeBuilding, eTreaty]); 7440 mRR.Visible := JobTest(UnFocus, jRR, [eNoBridgeBuilding, eTreaty]); 7441 mClear.Visible := JobTest(UnFocus, jClear, [eTreaty]); 7442 mIrrigation.Visible := JobTest(UnFocus, jIrr, [eTreaty]); 7443 mFarm.Visible := JobTest(UnFocus, jFarm, [eTreaty]); 7444 mAfforest.Visible := JobTest(UnFocus, jAfforest, [eTreaty]); 7445 mMine.Visible := JobTest(UnFocus, jMine, [eTreaty]); 7446 MTrans.Visible := JobTest(UnFocus, jTrans, [eTreaty]); 7447 mCanal.Visible := JobTest(UnFocus, jCanal, [eTreaty]); 7448 mFort.Visible := JobTest(UnFocus, jFort, [eTreaty]); 7449 mAirBase.Visible := JobTest(UnFocus, jBase, [eTreaty]); 7450 mPollution.Visible := JobTest(UnFocus, jPoll, [eTreaty]); 7451 mEnhance.Visible := (Tile and fDeadLands = 0) and 7452 (MyData.EnhancementJobs[MyMap[MyUn[UnFocus].Loc] and fTerrain, 0] 7453 <> jNone); 7454 end 7455 else 7456 begin 7457 for i := 0 to Popup.Items.Count - 1 do 7458 Popup.Items[i].Visible := false; 7459 end; 7460 end; 7461 7462 // set menu seperators 7463 LastSep := nil; 7464 NeedSep := false; 7465 for i := 0 to Popup.Items.Count - 1 do 7466 if Popup.Items[i].Caption = '-' then 7467 begin 7468 Popup.Items[i].Visible := NeedSep; 7469 if NeedSep then 7470 LastSep := Popup.Items[i]; 7471 NeedSep := false 7472 end 7473 else if Popup.Items[i].Visible then 7474 NeedSep := true; 7475 if (LastSep <> nil) and not NeedSep then 7476 LastSep.Visible := false 7477 end; 7478 7479 procedure TMainScreen.PanelBtnClick(Sender: TObject); 7480 var 7481 Popup: TPopupMenu; 7482 begin 7483 if Sender = UnitBtn then 7484 Popup := UnitPopup 7485 else { if Sender=TerrainBtn then } 7486 Popup := TerrainPopup; 7487 InitPopup(Popup); 7488 if FullScreen then 7489 Popup.Popup(Left + TControl(Sender).Left, Top + TControl(Sender).Top) 7490 else 7491 Popup.Popup(Left + TControl(Sender).Left + 4, Top + TControl(Sender).Top 7492 + GetSystemMetrics(SM_CYCAPTION) + 4); 7493 end; 7494 7495 procedure TMainScreen.CityClosed(Activateuix: integer; StepFocus: boolean; 7496 SelectFocus: boolean); 7497 begin 7498 if supervising then 7499 begin 7500 SetTroopLoc(-1); 7501 PanelPaint 7502 end 7503 else 7504 begin 7505 if Activateuix >= 0 then 7506 begin 7507 SetUnFocus(Activateuix); 7508 SetTroopLoc(MyUn[Activateuix].Loc); 7509 if SelectFocus then 7510 FocusOnLoc(TroopLoc, flRepaintPanel) 7511 else 7150 NewFocus := -1; 7151 uix := UnFocus; 7152 for i := 1 to MyRO.nUn - 1 do 7153 begin 7154 uix := (uix + MyRO.nUn - 1) mod MyRO.nUn; 7155 if (MyUn[uix].Master = UnFocus) and 7156 (MyUn[uix].Movement = integer(MyModel[MyUn[uix].mix].speed)) then 7157 begin 7158 MyUn[uix].Status := MyUn[uix].Status or usWaiting; 7159 NewFocus := uix 7160 end; 7161 end; 7162 if NewFocus >= 0 then 7163 begin 7164 SetUnFocus(NewFocus); 7165 SetTroopLoc(Loc); 7512 7166 PanelPaint 7513 end7514 else if StepFocus then7515 NextUnit(TroopLoc, true)7516 else7517 begin7518 SetTroopLoc(-1);7519 PanelPaint7520 end7521 end7522 end;7523 7524 procedure TMainScreen.Toggle(Sender: TObject);7525 begin7526 TMenuItem(Sender).Checked := not TMenuItem(Sender).Checked7527 end;7528 7529 procedure TMainScreen.PanelBoxMouseMove(Sender: TObject; Shift: TShiftState;7530 x, y: integer);7531 var7532 xCentre, yCentre: integer;7533 begin7534 if Tracking and (ssLeft in Shift) then7535 begin7536 if (x >= xMini + 2) and (y >= yMini + 2) and (x < xMini + 2 + 2 * G.lx)7537 and (y < yMini + 2 + G.ly) then7538 begin7539 xCentre := (xwMini + (x - xMini - 2) div 2 + G.lx div 2 +7540 MapWidth div (xxt * 4)) mod G.lx;7541 yCentre := (y - yMini - 2);7542 xw := (xCentre - MapWidth div (xxt * 4) + G.lx) mod G.lx;7543 if ywmax <= 0 then7544 yw := ywcenter7545 else7546 begin7547 yw := (yCentre - MapHeight div (yyt * 2) + 1) and not 1;7548 if yw < 0 then7549 yw := 07550 else if yw > ywmax then7551 yw := ywmax;7552 end;7553 BitBlt(Buffer.Canvas.Handle, 0, 0, G.lx * 2, G.ly, Mini.Canvas.Handle,7554 0, 0, SRCCOPY);7555 if ywmax <= 0 then7556 Frame(Buffer.Canvas, x - xMini - 2 - MapWidth div (xxt * 2), 0,7557 x - xMini - 2 + MapWidth div (xxt * 2) - 1, G.ly - 1,7558 MainTexture.clMark, MainTexture.clMark)7559 else7560 Frame(Buffer.Canvas, x - xMini - 2 - MapWidth div (xxt * 2), yw,7561 x - xMini - 2 + MapWidth div (xxt * 2) - 1,7562 yw + MapHeight div yyt - 2, MainTexture.clMark,7563 MainTexture.clMark);7564 BitBlt(Panel.Canvas.Handle, xMini + 2, yMini + 2, G.lx * 2, G.ly,7565 Buffer.Canvas.Handle, 0, 0, SRCCOPY);7566 MainOffscreenPaint;7567 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini +7568 2, xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini7569 + 2 + G.ly);7570 Update;7571 end7572 end7573 else7574 Tracking := false7575 end;7576 7577 procedure TMainScreen.PanelBoxMouseUp(Sender: TObject; Button: TMouseButton;7578 Shift: TShiftState; x, y: integer);7579 begin7580 if Tracking then7581 begin7582 Tracking := false;7583 xwMini := xw;7584 ywMini := yw;7585 MiniPaint;7586 PanelPaint;7587 end7588 end;7589 7590 procedure TMainScreen.MapBoxMouseMove(Sender: TObject; Shift: TShiftState;7591 x, y: integer);7592 var7593 MouseLoc: integer;7594 begin7595 xMouse := x;7596 yMouse := y;7597 if (ClientMode = cEditMap) and (ssLeft in Shift) and not Tracking then7598 begin7599 MouseLoc := LocationOfScreenPixel(x, y);7600 if MouseLoc <> BrushLoc then7601 MapBoxMouseDown(nil, mbLeft, Shift, x, y);7602 end7603 (* else if idle and (UnFocus>=0) then7604 begin7605 qx:=(xMouse*32+yMouse*66+16*66) div(32*66)-1;7606 qy:=(yMouse*66-xMouse*32-16*66+2000*33*32) div(32*66)-999;7607 MouseLoc:=(xw+(qx-qy+2048) div 2-1024+G.lx) mod G.lx+G.lx*(yw+qx+qy);7608 ShowMoveHint(MouseLoc);7609 end *)7610 end;7611 7612 procedure TMainScreen.mShowClick(Sender: TObject);7613 begin7614 TMenuItem(Sender).Checked := not TMenuItem(Sender).Checked;7615 SetMapOptions;7616 MapValid := false;7617 PaintAllMaps;7618 end;7619 7620 procedure TMainScreen.mNamesClick(Sender: TObject);7621 var7622 p1: integer;7623 begin7624 mNames.Checked := not mNames.Checked;7625 GenerateNames := mNames.Checked;7626 for p1 := 0 to nPl - 1 do7627 if Tribe[p1] <> nil then7628 if GenerateNames then7629 Tribe[p1].NumberName := -17630 else7631 Tribe[p1].NumberName := p1;7632 MapValid := false;7633 PaintAll;7634 end;7635 7636 function TMainScreen.IsPanelPixel(x, y: integer): boolean;7637 begin7638 result := (y >= TopBarHeight + MapHeight) or7639 (y >= ClientHeight - PanelHeight) and7640 ((x < xMidPanel) or (x >= xRightPanel))7641 end;7642 7643 procedure TMainScreen.FormMouseDown(Sender: TObject; Button: TMouseButton;7644 Shift: TShiftState; x, y: integer);7645 begin7646 if idle then7647 if (x < 40) and (y < 40) then7648 begin7649 if GameMode <> cMovie then7650 begin7651 InitPopup(GamePopup);7652 if FullScreen then7653 GamePopup.Popup(Left, Top + TopBarHeight - 1)7654 else7655 GamePopup.Popup(Left + 4, Top + GetSystemMetrics(SM_CYCAPTION) + 47656 + TopBarHeight - 1);7657 7167 end 7658 7168 end 7659 else if IsPanelPixel(x, y) then 7660 PanelBoxMouseDown(Sender, Button, Shift, x, 7661 y - (ClientHeight - PanelHeight)) 7662 else if (y >= TopBarHeight) and (x >= MapOffset) and 7663 (x < MapOffset + MapWidth) then 7664 MapBoxMouseDown(Sender, Button, Shift, x - MapOffset, 7665 y - TopBarHeight) 7169 else if Sender = mSelectTransport then 7170 Server(sSelectTransport, me, UnFocus, nil^) 7171 end; 7172 7173 procedure TMainScreen.InitPopup(Popup: TPopupMenu); 7174 var 7175 i, p1, Tile, Test: integer; 7176 NoSuper, extended, Multi, NeedSep, HaveCities: boolean; 7177 LastSep, m: TMenuItem; 7178 mox: ^TModel; 7179 begin 7180 NoSuper := not supervising and (1 shl me and MyRO.Alive <> 0); 7181 HaveCities := false; 7182 for i := 0 to MyRO.nCity - 1 do 7183 if MyCity[i].Loc >= 0 then 7184 begin 7185 HaveCities := true; 7186 Break 7666 7187 end; 7667 7668 procedure TMainScreen.FormMouseMove(Sender: TObject; Shift: TShiftState; 7669 x, y: integer); 7670 begin 7671 if idle then 7672 if IsPanelPixel(x, y) then 7673 PanelBoxMouseMove(Sender, Shift, x, y - (ClientHeight - PanelHeight)) 7674 else if (y >= TopBarHeight) and (x >= MapOffset) and 7675 (x < MapOffset + MapWidth) then 7676 MapBoxMouseMove(Sender, Shift, x - MapOffset, y - TopBarHeight); 7188 if Popup = GamePopup then 7189 begin 7190 mTechTree.Visible := ClientMode <> cEditMap; 7191 mResign.Enabled := supervising or (me = 0) and (ClientMode < scContact); 7192 mRandomMap.Visible := (ClientMode = cEditMap) and 7193 (Server(sMapGeneratorRequest, me, 0, nil^) = eOK); 7194 mOptions.Visible := ClientMode <> cEditMap; 7195 mManip.Visible := ClientMode <> cEditMap; 7196 if ClientMode <> cEditMap then 7197 begin 7198 mWaitTurn.Visible := NoSuper; 7199 mRep.Visible := NoSuper; 7200 mRepList.Visible := NoSuper; 7201 mRepScreens.Visible := NoSuper; 7202 N10.Visible := NoSuper; 7203 mOwnMovement.Visible := NoSuper; 7204 mAllyMovement.Visible := NoSuper; 7205 case SoundMode of 7206 smOff: 7207 mSoundOff.Checked := true; 7208 smOn: 7209 mSoundOn.Checked := true; 7210 smOnAlt: 7211 mSoundOnAlt.Checked := true; 7212 end; 7213 7214 for i := 0 to nTestFlags - 1 do 7215 mManip[i].Checked := MyRO.TestFlags and (1 shl i) <> 0; 7216 mManip.Enabled := supervising or (me = 0); 7217 7218 Multi := false; 7219 for p1 := 1 to nPl - 1 do 7220 if G.RO[p1] <> nil then 7221 Multi := true; 7222 mEnemyMovement.Visible := not Multi; 7677 7223 end; 7678 7679 procedure TMainScreen.FormMouseUp(Sender: TObject; Button: TMouseButton; 7680 Shift: TShiftState; x, y: integer); 7681 begin 7682 if idle then 7683 PanelBoxMouseUp(Sender, Button, Shift, x, 7684 y - (ClientHeight - PanelHeight)); 7224 mMacro.Visible := NoSuper and (ClientMode < scContact); 7225 if NoSuper and (ClientMode < scContact) then 7226 begin 7227 mCityTypes.Enabled := false; 7228 // check if city types already usefull: 7229 if MyRO.nCity > 0 then 7230 for i := 28 to nImp - 1 do 7231 if (i <> imTrGoods) and (Imp[i].Kind = ikCommon) and 7232 (Imp[i].Preq <> preNA) and 7233 ((Imp[i].Preq = preNone) or (MyRO.Tech[Imp[i].Preq] >= tsApplicable)) 7234 then 7235 begin 7236 mCityTypes.Enabled := true; 7237 Break 7238 end; 7685 7239 end; 7686 7687 procedure TMainScreen.FormPaint(Sender: TObject); 7688 begin 7240 mViewpoint.Visible := (ClientMode <> cEditMap) and supervising; 7241 mViewpoint.Enabled := G.RO[0].Turn > 0; 7242 if supervising then 7243 begin 7244 EmptyMenu(mViewpoint); 7245 for p1 := 0 to nPl - 1 do 7246 if (p1 = 0) or (1 shl p1 and G.RO[0].Alive <> 0) then 7247 begin 7248 m := TMenuItem.Create(mViewpoint); 7249 if p1 = 0 then 7250 m.Caption := Phrases.Lookup('SUPER') 7251 else 7252 m.Caption := Tribe[p1].TString(Phrases2.Lookup('BELONG')); 7253 m.Tag := p1; 7254 m.OnClick := ViewpointClick; 7255 if p1 < 10 then 7256 m.ShortCut := ShortCut(48 + p1, [ssCtrl]); 7257 m.RadioItem := true; 7258 if p1 = me then 7259 m.Checked := true; 7260 mViewpoint.Add(m); 7261 end 7262 end; 7263 mDebugMap.Visible := (ClientMode <> cEditMap) and supervising; 7264 if supervising then 7265 begin 7266 EmptyMenu(mDebugMap); 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(mDebugMap); 7271 if p1 = 0 then 7272 m.Caption := Phrases2.Lookup('MENU_DEBUGMAPOFF') 7273 else 7274 m.Caption := Tribe[p1].TString(Phrases2.Lookup('BELONG')); 7275 if p1 = 0 then 7276 m.Tag := -1 7277 else 7278 m.Tag := p1; 7279 m.OnClick := DebugMapClick; 7280 if p1 < 10 then 7281 m.ShortCut := ShortCut(48 + p1, [ssAlt]); 7282 m.RadioItem := true; 7283 if m.Tag = IsoEngine.pDebugMap then 7284 m.Checked := true; 7285 mDebugMap.Add(m); 7286 end 7287 end; 7288 mSmallTiles.Checked := xxt = 33; 7289 mNormalTiles.Checked := xxt = 48; 7290 end 7291 else if Popup = StatPopup then 7292 begin 7293 mEmpire.Visible := NoSuper; 7294 mEmpire.Enabled := MyRO.Government <> gAnarchy; 7295 mRevolution.Visible := NoSuper; 7296 mRevolution.Enabled := (MyRO.Government <> gAnarchy) and 7297 (ClientMode < scContact); 7298 mUnitStat.Enabled := NoSuper or (MyRO.Turn > 0); 7299 mCityStat.Visible := 1 shl me and MyRO.Alive <> 0; 7300 mCityStat.Enabled := HaveCities; 7301 mScienceStat.Visible := true; 7302 mScienceStat.Enabled := not NoSuper or (MyRO.ResearchTech >= 0) or 7303 (MyRO.Happened and phTech <> 0) or (MyRO.Happened and phGameEnd <> 0) 7304 // no researchtech in case just completed 7305 or (MyRO.TestFlags and (tfAllTechs or tfUncover or tfAllContact) <> 0); 7306 mEUnitStat.Enabled := MyRO.nEnemyModel > 0; 7307 { mWonders.Enabled:= false; 7308 for i:=0 to 27 do if MyRO.Wonder[i].CityID<>-1 then 7309 mWonders.Enabled:=true; } 7310 mDiagram.Enabled := MyRO.Turn >= 2; 7311 mShips.Enabled := false; 7312 for p1 := 0 to nPl - 1 do 7313 if MyRO.Ship[p1].Parts[spComp] + MyRO.Ship[p1].Parts[spPow] + 7314 MyRO.Ship[p1].Parts[spHab] > 0 then 7315 mShips.Enabled := true; 7316 end 7317 else if Popup = UnitPopup then 7318 begin 7319 mox := @MyModel[MyUn[UnFocus].mix]; 7320 Tile := MyMap[MyUn[UnFocus].Loc]; 7321 extended := Tile and fCity = 0; 7322 if extended then 7323 begin 7324 mCity.Caption := Phrases.Lookup('BTN_FOUND'); 7325 mHome.Caption := Phrases.Lookup('BTN_MOVEHOME') 7326 end 7327 else 7328 begin 7329 mCity.Caption := Phrases.Lookup('BTN_ADD'); 7330 mHome.Caption := Phrases.Lookup('BTN_SETHOME') 7331 end; 7332 7333 extended := extended and ((mox.Kind = mkSettler) or (mox.Kind = mkSlaves) 7334 and (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)) and 7335 (MyUn[UnFocus].Master < 0) and (Tile and fDeadLands = 0); 7336 if (mox.Kind = mkFreight) and (Tile and fCity <> 0) and 7337 not Phrases2FallenBackToEnglish or 7338 (Server(sRemoveUnit - sExecute, me, UnFocus, nil^) = eUtilized) then 7339 begin 7340 mDisband.Visible := false; 7341 mUtilize.Visible := true; 7342 if mox.Kind = mkFreight then 7343 mUtilize.Caption := Phrases.Lookup('UTILIZE') 7344 else 7345 mUtilize.Caption := Phrases.Lookup('INTEGRATE') 7346 end 7347 else 7348 begin 7349 mDisband.Visible := true; 7350 mUtilize.Visible := false 7351 end; 7352 mGoOn.Visible := MyUn[UnFocus].Status and (usGoto or usWaiting) = usGoto or 7353 usWaiting; 7354 mHome.Visible := HaveCities; 7355 mRecover.Visible := (MyUn[UnFocus].Health < 100) and 7356 (Tile and fTerrain >= fGrass) and 7357 ((MyRO.Wonder[woGardens].EffectiveOwner = me) or 7358 (Tile and fTerrain <> fArctic) and (Tile and fTerrain <> fDesert)) and 7359 not((mox.Domain = dAir) and (Tile and fCity = 0) and 7360 (Tile and fTerImp <> tiBase)); 7361 mStay.Visible := not((mox.Domain = dAir) and (Tile and fCity = 0) and 7362 (Tile and fTerImp <> tiBase)); 7363 mCity.Visible := extended and (mox.Kind = mkSettler) or 7364 (Tile and fCity <> 0) and ((mox.Kind in [mkSettler, mkSlaves]) or 7365 (MyUn[UnFocus].Flags and unConscripts <> 0)); 7366 mPillage.Visible := (Tile and (fRoad or fRR or fCanal or fTerImp) <> 0) and 7367 (MyUn[UnFocus].Master < 0) and (mox.Domain = dGround); 7368 mCancel.Visible := (MyUn[UnFocus].Job > jNone) or 7369 (MyUn[UnFocus].Status and (usRecover or usGoto) <> 0); 7370 7371 Test := Server(sLoadUnit - sExecute, me, UnFocus, nil^); 7372 mLoad.Visible := (Test >= rExecuted) or (Test = eNoTime_Load); 7373 mUnload.Visible := (MyUn[UnFocus].Master >= 0) or 7374 (MyUn[UnFocus].TroopLoad + MyUn[UnFocus].AirLoad > 0); 7375 mSelectTransport.Visible := Server(sSelectTransport - sExecute, me, UnFocus, 7376 nil^) >= rExecuted; 7377 end 7378 else { if Popup=TerrainPopup then } 7379 begin 7380 mox := @MyModel[MyUn[UnFocus].mix]; 7381 Tile := MyMap[MyUn[UnFocus].Loc]; 7382 extended := Tile and fCity = 0; 7383 7384 if (Tile and fRiver <> 0) and (MyRO.Tech[adBridgeBuilding] >= tsApplicable) 7385 then 7386 begin 7387 mRoad.Caption := Phrases.Lookup('BTN_BUILDBRIDGE'); 7388 mRR.Caption := Phrases.Lookup('BTN_BUILDRRBRIDGE'); 7389 end 7390 else 7391 begin 7392 mRoad.Caption := Phrases.Lookup('BTN_BUILDROAD'); 7393 mRR.Caption := Phrases.Lookup('BTN_BUILDRR'); 7394 end; 7395 if Tile and fTerrain = fForest then 7396 mClear.Caption := Phrases.Lookup('BTN_CLEAR') 7397 else if Tile and fTerrain = fDesert then 7398 mClear.Caption := Phrases.Lookup('BTN_UNDESERT') 7399 else 7400 mClear.Caption := Phrases.Lookup('BTN_DRAIN'); 7401 7402 extended := extended and ((mox.Kind = mkSettler) or (mox.Kind = mkSlaves) 7403 and (MyRO.Wonder[woPyramids].EffectiveOwner >= 0)) and 7404 (MyUn[UnFocus].Master < 0); 7405 if extended then 7406 begin 7407 mRoad.Visible := JobTest(UnFocus, jRoad, [eNoBridgeBuilding, eTreaty]); 7408 mRR.Visible := JobTest(UnFocus, jRR, [eNoBridgeBuilding, eTreaty]); 7409 mClear.Visible := JobTest(UnFocus, jClear, [eTreaty]); 7410 mIrrigation.Visible := JobTest(UnFocus, jIrr, [eTreaty]); 7411 mFarm.Visible := JobTest(UnFocus, jFarm, [eTreaty]); 7412 mAfforest.Visible := JobTest(UnFocus, jAfforest, [eTreaty]); 7413 mMine.Visible := JobTest(UnFocus, jMine, [eTreaty]); 7414 MTrans.Visible := JobTest(UnFocus, jTrans, [eTreaty]); 7415 mCanal.Visible := JobTest(UnFocus, jCanal, [eTreaty]); 7416 mFort.Visible := JobTest(UnFocus, jFort, [eTreaty]); 7417 mAirBase.Visible := JobTest(UnFocus, jBase, [eTreaty]); 7418 mPollution.Visible := JobTest(UnFocus, jPoll, [eTreaty]); 7419 mEnhance.Visible := (Tile and fDeadLands = 0) and 7420 (MyData.EnhancementJobs[MyMap[MyUn[UnFocus].Loc] and fTerrain, 0] 7421 <> jNone); 7422 end 7423 else 7424 begin 7425 for i := 0 to Popup.Items.Count - 1 do 7426 Popup.Items[i].Visible := false; 7427 end; 7428 end; 7429 7430 // set menu seperators 7431 LastSep := nil; 7432 NeedSep := false; 7433 for i := 0 to Popup.Items.Count - 1 do 7434 if Popup.Items[i].Caption = '-' then 7435 begin 7436 Popup.Items[i].Visible := NeedSep; 7437 if NeedSep then 7438 LastSep := Popup.Items[i]; 7439 NeedSep := false 7440 end 7441 else if Popup.Items[i].Visible then 7442 NeedSep := true; 7443 if (LastSep <> nil) and not NeedSep then 7444 LastSep.Visible := false 7445 end; 7446 7447 procedure TMainScreen.PanelBtnClick(Sender: TObject); 7448 var 7449 Popup: TPopupMenu; 7450 begin 7451 if Sender = UnitBtn then 7452 Popup := UnitPopup 7453 else { if Sender=TerrainBtn then } 7454 Popup := TerrainPopup; 7455 InitPopup(Popup); 7456 if FullScreen then 7457 Popup.Popup(Left + TControl(Sender).Left, Top + TControl(Sender).Top) 7458 else 7459 Popup.Popup(Left + TControl(Sender).Left + 4, Top + TControl(Sender).Top + 7460 GetSystemMetrics(SM_CYCAPTION) + 4); 7461 end; 7462 7463 procedure TMainScreen.CityClosed(Activateuix: integer; StepFocus: boolean; 7464 SelectFocus: boolean); 7465 begin 7466 if supervising then 7467 begin 7468 SetTroopLoc(-1); 7469 PanelPaint 7470 end 7471 else 7472 begin 7473 if Activateuix >= 0 then 7474 begin 7475 SetUnFocus(Activateuix); 7476 SetTroopLoc(MyUn[Activateuix].Loc); 7477 if SelectFocus then 7478 FocusOnLoc(TroopLoc, flRepaintPanel) 7479 else 7480 PanelPaint 7481 end 7482 else if StepFocus then 7483 NextUnit(TroopLoc, true) 7484 else 7485 begin 7486 SetTroopLoc(-1); 7487 PanelPaint 7488 end 7489 end 7490 end; 7491 7492 procedure TMainScreen.Toggle(Sender: TObject); 7493 begin 7494 TMenuItem(Sender).Checked := not TMenuItem(Sender).Checked 7495 end; 7496 7497 procedure TMainScreen.PanelBoxMouseMove(Sender: TObject; Shift: TShiftState; 7498 x, y: integer); 7499 var 7500 xCentre, yCentre: integer; 7501 begin 7502 if Tracking and (ssLeft in Shift) then 7503 begin 7504 if (x >= xMini + 2) and (y >= yMini + 2) and (x < xMini + 2 + 2 * G.lx) and 7505 (y < yMini + 2 + G.ly) then 7506 begin 7507 xCentre := (xwMini + (x - xMini - 2) div 2 + G.lx div 2 + 7508 MapWidth div (xxt * 4)) mod G.lx; 7509 yCentre := (y - yMini - 2); 7510 xw := (xCentre - MapWidth div (xxt * 4) + G.lx) mod G.lx; 7511 if ywmax <= 0 then 7512 yw := ywcenter 7513 else 7514 begin 7515 yw := (yCentre - MapHeight div (yyt * 2) + 1) and not 1; 7516 if yw < 0 then 7517 yw := 0 7518 else if yw > ywmax then 7519 yw := ywmax; 7520 end; 7521 BitBlt(Buffer.Canvas.Handle, 0, 0, G.lx * 2, G.ly, Mini.Canvas.Handle, 0, 7522 0, SRCCOPY); 7523 if ywmax <= 0 then 7524 Frame(Buffer.Canvas, x - xMini - 2 - MapWidth div (xxt * 2), 0, 7525 x - xMini - 2 + MapWidth div (xxt * 2) - 1, G.ly - 1, 7526 MainTexture.clMark, MainTexture.clMark) 7527 else 7528 Frame(Buffer.Canvas, x - xMini - 2 - MapWidth div (xxt * 2), yw, 7529 x - xMini - 2 + MapWidth div (xxt * 2) - 1, yw + MapHeight div yyt - 7530 2, MainTexture.clMark, MainTexture.clMark); 7531 BitBlt(Panel.Canvas.Handle, xMini + 2, yMini + 2, G.lx * 2, G.ly, 7532 Buffer.Canvas.Handle, 0, 0, SRCCOPY); 7689 7533 MainOffscreenPaint; 7690 if (MapOffset > 0) or (MapOffset + MapWidth < ClientWidth) then 7691 with Canvas do 7692 begin // pillarbox, make left and right border black 7693 if me < 0 then 7694 Brush.Color := $000000 7695 else 7696 Brush.Color := EmptySpaceColor; 7697 if xMidPanel > MapOffset then 7698 FillRect(Rect(0, TopBarHeight, MapOffset, TopBarHeight + MapHeight 7699 - overlap)) 7700 else 7701 begin 7702 FillRect(Rect(0, TopBarHeight, xMidPanel, TopBarHeight + MapHeight - 7703 overlap)); 7704 FillRect(Rect(xMidPanel, TopBarHeight, MapOffset, 7705 TopBarHeight + MapHeight)); 7706 end; 7707 if xRightPanel < MapOffset + MapWidth then 7708 FillRect(Rect(MapOffset + MapWidth, TopBarHeight, ClientWidth, 7709 TopBarHeight + MapHeight - overlap)) 7710 else 7711 begin 7712 FillRect(Rect(MapOffset + MapWidth, TopBarHeight, xRightPanel, 7713 TopBarHeight + MapHeight)); 7714 FillRect(Rect(xRightPanel, TopBarHeight, ClientWidth, 7715 TopBarHeight + MapHeight - overlap)); 7716 end; 7717 Brush.Style := bsClear; 7718 end; 7719 BitBlt(Canvas.Handle, MapOffset, TopBarHeight, MapWidth, 7720 MapHeight - overlap, offscreen.Canvas.Handle, 0, 0, SRCCOPY); 7721 BitBlt(Canvas.Handle, 0, 0, ClientWidth, TopBarHeight, 7722 TopBar.Canvas.Handle, 0, 0, SRCCOPY); 7723 if xMidPanel > MapOffset then 7724 BitBlt(Canvas.Handle, xMidPanel, TopBarHeight + MapHeight - overlap, 7725 ClientWidth div 2 - xMidPanel, overlap, offscreen.Canvas.Handle, 7726 xMidPanel - MapOffset, MapHeight - overlap, SRCCOPY) 7534 RectInvalidate(xMini + 2, TopBarHeight + MapHeight - overlap + yMini + 2, 7535 xMini + 2 + G.lx * 2, TopBarHeight + MapHeight - overlap + yMini + 7536 2 + G.ly); 7537 Update; 7538 end 7539 end 7540 else 7541 Tracking := false 7542 end; 7543 7544 procedure TMainScreen.PanelBoxMouseUp(Sender: TObject; Button: TMouseButton; 7545 Shift: TShiftState; x, y: integer); 7546 begin 7547 if Tracking then 7548 begin 7549 Tracking := false; 7550 xwMini := xw; 7551 ywMini := yw; 7552 MiniPaint; 7553 PanelPaint; 7554 end 7555 end; 7556 7557 procedure TMainScreen.MapBoxMouseMove(Sender: TObject; Shift: TShiftState; 7558 x, y: integer); 7559 var 7560 MouseLoc: integer; 7561 begin 7562 xMouse := x; 7563 yMouse := y; 7564 if (ClientMode = cEditMap) and (ssLeft in Shift) and not Tracking then 7565 begin 7566 MouseLoc := LocationOfScreenPixel(x, y); 7567 if MouseLoc <> BrushLoc then 7568 MapBoxMouseDown(nil, mbLeft, Shift, x, y); 7569 end 7570 (* else if idle and (UnFocus>=0) then 7571 begin 7572 qx:=(xMouse*32+yMouse*66+16*66) div(32*66)-1; 7573 qy:=(yMouse*66-xMouse*32-16*66+2000*33*32) div(32*66)-999; 7574 MouseLoc:=(xw+(qx-qy+2048) div 2-1024+G.lx) mod G.lx+G.lx*(yw+qx+qy); 7575 ShowMoveHint(MouseLoc); 7576 end *) 7577 end; 7578 7579 procedure TMainScreen.mShowClick(Sender: TObject); 7580 begin 7581 TMenuItem(Sender).Checked := not TMenuItem(Sender).Checked; 7582 SetMapOptions; 7583 MapValid := false; 7584 PaintAllMaps; 7585 end; 7586 7587 procedure TMainScreen.mNamesClick(Sender: TObject); 7588 var 7589 p1: integer; 7590 begin 7591 mNames.Checked := not mNames.Checked; 7592 GenerateNames := mNames.Checked; 7593 for p1 := 0 to nPl - 1 do 7594 if Tribe[p1] <> nil then 7595 if GenerateNames then 7596 Tribe[p1].NumberName := -1 7727 7597 else 7728 BitBlt(Canvas.Handle, MapOffset, TopBarHeight + MapHeight - overlap, 7729 ClientWidth div 2 - MapOffset, overlap, offscreen.Canvas.Handle, 0, 7730 MapHeight - overlap, SRCCOPY); 7731 if xRightPanel < MapOffset + MapWidth then 7732 BitBlt(Canvas.Handle, ClientWidth div 2, TopBarHeight + MapHeight - 7733 overlap, xRightPanel - ClientWidth div 2, overlap, 7734 offscreen.Canvas.Handle, ClientWidth div 2 - MapOffset, 7735 MapHeight - overlap, SRCCOPY) 7736 else 7737 BitBlt(Canvas.Handle, ClientWidth div 2, TopBarHeight + MapHeight - 7738 overlap, MapOffset + MapWidth - ClientWidth div 2, overlap, 7739 offscreen.Canvas.Handle, ClientWidth div 2 - MapOffset, 7740 MapHeight - overlap, SRCCOPY); 7741 BitBlt(Canvas.Handle, 0, TopBarHeight + MapHeight - overlap, xMidPanel, 7742 overlap, Panel.Canvas.Handle, 0, 0, SRCCOPY); 7743 BitBlt(Canvas.Handle, xRightPanel, TopBarHeight + MapHeight - overlap, 7744 Panel.width - xRightPanel, overlap, Panel.Canvas.Handle, xRightPanel, 7745 0, SRCCOPY); 7746 BitBlt(Canvas.Handle, 0, TopBarHeight + MapHeight, Panel.width, 7747 PanelHeight - overlap, Panel.Canvas.Handle, 0, overlap, SRCCOPY); 7748 if (pLogo >= 0) and (G.RO[pLogo] = nil) and (AILogo[pLogo] <> nil) then 7749 BitBlt(Canvas.Handle, xRightPanel + 10 - (16 + 64), 7750 ClientHeight - PanelHeight, 64, 64, AILogo[pLogo].Canvas.Handle, 0, 0, 7751 SRCCOPY); 7752 end; 7753 7754 procedure TMainScreen.RectInvalidate(Left, Top, Rigth, Bottom: integer); 7755 var 7756 r0: HRgn; 7757 begin 7758 r0 := CreateRectRgn(Left, Top, Rigth, Bottom); 7759 InvalidateRgn(Handle, r0, false); 7760 DeleteObject(r0); 7761 end; 7762 7763 procedure TMainScreen.SmartRectInvalidate(Left, Top, Rigth, 7764 Bottom: integer); 7765 var 7766 i: integer; 7767 r0, r1: HRgn; 7768 begin 7769 r0 := CreateRectRgn(Left, Top, Rigth, Bottom); 7770 for i := 0 to ControlCount - 1 do 7771 if not(Controls[i] is TArea) and Controls[i].Visible then 7772 begin 7773 with Controls[i].BoundsRect do 7774 r1 := CreateRectRgn(Left, Top, Right, Bottom); 7775 CombineRgn(r0, r0, r1, RGN_DIFF); 7776 DeleteObject(r1); 7777 end; 7778 InvalidateRgn(Handle, r0, false); 7779 DeleteObject(r0); 7780 end; 7781 7782 procedure TMainScreen.mRepClicked(Sender: TObject); 7783 begin 7784 with TMenuItem(Sender) do 7785 begin 7786 Checked := not Checked; 7787 if Checked then 7788 CityRepMask := CityRepMask or (1 shl (Tag shr 8)) 7789 else 7790 CityRepMask := CityRepMask and not(1 shl (Tag shr 8)) 7791 end 7792 end; 7793 7794 procedure TMainScreen.mLogClick(Sender: TObject); 7795 begin 7796 LogDlg.Show; 7797 end; 7798 7799 procedure TMainScreen.FormShow(Sender: TObject); 7800 begin 7801 Timer1.Enabled := true; 7802 Left := 0; 7803 Top := 0; 7804 end; 7805 7806 procedure TMainScreen.FormClose(Sender: TObject; var Action: TCloseAction); 7807 begin 7808 Timer1.Enabled := false; 7809 end; 7810 7811 procedure TMainScreen.Radio(Sender: TObject); 7812 begin 7813 TMenuItem(Sender).Checked := true; 7814 end; 7815 7816 procedure TMainScreen.mManipClick(Sender: TObject); 7817 var 7818 Flag: integer; 7819 begin 7820 with TMenuItem(Sender) do 7821 begin 7822 Flag := 1 shl (Tag shr 8); 7823 if Checked then 7824 Server(sClearTestFlag, 0, Flag, nil^) 7825 else 7826 begin 7827 Server(sSetTestFlag, 0, Flag, nil^); 7828 Play('CHEAT'); 7829 end; 7830 if not supervising then 7831 begin 7832 if Flag = tfUncover then 7833 begin 7834 MapValid := false; 7835 PaintAllMaps; 7836 end 7837 else if Flag = tfAllTechs then 7838 TellNewModels 7839 end 7840 end 7841 end; 7842 7843 procedure TMainScreen.MapBtnClick(Sender: TObject); 7844 begin 7845 with TButtonC(Sender) do 7846 begin 7847 MapOptionChecked := MapOptionChecked xor (1 shl (Tag shr 8)); 7848 SetMapOptions; 7849 ButtonIndex := MapOptionChecked shr (Tag shr 8) and 1 + 2 7850 end; 7851 if Sender = MapBtn0 then 7852 begin 7853 MiniPaint; 7854 PanelPaint 7855 end // update mini map only 7856 else 7857 begin 7858 MapValid := false; 7859 PaintAllMaps; 7860 end; // update main map 7861 end; 7862 7863 procedure TMainScreen.GrWallBtnDownChanged(Sender: TObject); 7864 begin 7865 if TButtonBase(Sender).Down then 7866 begin 7867 MapOptionChecked := MapOptionChecked or (1 shl moGreatWall); 7868 TButtonBase(Sender).Hint := ''; 7869 end 7870 else 7871 begin 7872 MapOptionChecked := MapOptionChecked and not(1 shl moGreatWall); 7873 TButtonBase(Sender).Hint := Phrases.Lookup('CONTROLS', 7874 -1 + TButtonBase(Sender).Tag and $FF); 7875 end; 7876 SetMapOptions; 7877 MapValid := false; 7878 PaintAllMaps; 7879 end; 7880 7881 procedure TMainScreen.BareBtnDownChanged(Sender: TObject); 7882 begin 7883 if TButtonBase(Sender).Down then 7884 begin 7885 MapOptionChecked := MapOptionChecked or (1 shl moBareTerrain); 7886 TButtonBase(Sender).Hint := ''; 7887 end 7888 else 7889 begin 7890 MapOptionChecked := MapOptionChecked and not(1 shl moBareTerrain); 7891 TButtonBase(Sender).Hint := Phrases.Lookup('CONTROLS', 7892 -1 + TButtonBase(Sender).Tag and $FF); 7893 end; 7894 SetMapOptions; 7895 MapValid := false; 7896 PaintAllMaps; 7897 end; 7898 7899 procedure TMainScreen.FormKeyUp(Sender: TObject; var Key: word; 7900 Shift: TShiftState); 7901 begin 7902 if idle and (Key = VK_APPS) then 7598 Tribe[p1].NumberName := p1; 7599 MapValid := false; 7600 PaintAll; 7601 end; 7602 7603 function TMainScreen.IsPanelPixel(x, y: integer): boolean; 7604 begin 7605 result := (y >= TopBarHeight + MapHeight) or (y >= ClientHeight - PanelHeight) 7606 and ((x < xMidPanel) or (x >= xRightPanel)) 7607 end; 7608 7609 procedure TMainScreen.FormMouseDown(Sender: TObject; Button: TMouseButton; 7610 Shift: TShiftState; x, y: integer); 7611 begin 7612 if idle then 7613 if (x < 40) and (y < 40) then 7614 begin 7615 if GameMode <> cMovie then 7903 7616 begin 7904 7617 InitPopup(GamePopup); … … 7908 7621 GamePopup.Popup(Left + 4, Top + GetSystemMetrics(SM_CYCAPTION) + 4 + 7909 7622 TopBarHeight - 1); 7910 exit 7911 end // windows menu button calls game menu 7623 end 7624 end 7625 else if IsPanelPixel(x, y) then 7626 PanelBoxMouseDown(Sender, Button, Shift, x, 7627 y - (ClientHeight - PanelHeight)) 7628 else if (y >= TopBarHeight) and (x >= MapOffset) and 7629 (x < MapOffset + MapWidth) then 7630 MapBoxMouseDown(Sender, Button, Shift, x - MapOffset, y - TopBarHeight) 7631 end; 7632 7633 procedure TMainScreen.FormMouseMove(Sender: TObject; Shift: TShiftState; 7634 x, y: integer); 7635 begin 7636 if idle then 7637 if IsPanelPixel(x, y) then 7638 PanelBoxMouseMove(Sender, Shift, x, y - (ClientHeight - PanelHeight)) 7639 else if (y >= TopBarHeight) and (x >= MapOffset) and 7640 (x < MapOffset + MapWidth) then 7641 MapBoxMouseMove(Sender, Shift, x - MapOffset, y - TopBarHeight); 7642 end; 7643 7644 procedure TMainScreen.FormMouseUp(Sender: TObject; Button: TMouseButton; 7645 Shift: TShiftState; x, y: integer); 7646 begin 7647 if idle then 7648 PanelBoxMouseUp(Sender, Button, Shift, x, y - (ClientHeight - PanelHeight)); 7649 end; 7650 7651 procedure TMainScreen.FormPaint(Sender: TObject); 7652 begin 7653 MainOffscreenPaint; 7654 if (MapOffset > 0) or (MapOffset + MapWidth < ClientWidth) then 7655 with Canvas do 7656 begin // pillarbox, make left and right border black 7657 if me < 0 then 7658 Brush.Color := $000000 7659 else 7660 Brush.Color := EmptySpaceColor; 7661 if xMidPanel > MapOffset then 7662 FillRect(Rect(0, TopBarHeight, MapOffset, TopBarHeight + MapHeight 7663 - overlap)) 7664 else 7665 begin 7666 FillRect(Rect(0, TopBarHeight, xMidPanel, TopBarHeight + MapHeight - 7667 overlap)); 7668 FillRect(Rect(xMidPanel, TopBarHeight, MapOffset, 7669 TopBarHeight + MapHeight)); 7670 end; 7671 if xRightPanel < MapOffset + MapWidth then 7672 FillRect(Rect(MapOffset + MapWidth, TopBarHeight, ClientWidth, 7673 TopBarHeight + MapHeight - overlap)) 7674 else 7675 begin 7676 FillRect(Rect(MapOffset + MapWidth, TopBarHeight, xRightPanel, 7677 TopBarHeight + MapHeight)); 7678 FillRect(Rect(xRightPanel, TopBarHeight, ClientWidth, 7679 TopBarHeight + MapHeight - overlap)); 7680 end; 7681 Brush.Style := bsClear; 7912 7682 end; 7913 7914 procedure TMainScreen.CreateUnitClick(Sender: TObject); 7915 var 7916 p1, mix: integer; 7917 begin 7918 p1 := TComponent(Sender).Tag shr 16; 7919 mix := TComponent(Sender).Tag and $FFFF; 7920 if Server(sCreateUnit + p1 shl 4, me, mix, EditLoc) >= rExecuted then 7921 PaintLoc(EditLoc); 7683 BitBlt(Canvas.Handle, MapOffset, TopBarHeight, MapWidth, MapHeight - overlap, 7684 offscreen.Canvas.Handle, 0, 0, SRCCOPY); 7685 BitBlt(Canvas.Handle, 0, 0, ClientWidth, TopBarHeight, TopBar.Canvas.Handle, 7686 0, 0, SRCCOPY); 7687 if xMidPanel > MapOffset then 7688 BitBlt(Canvas.Handle, xMidPanel, TopBarHeight + MapHeight - overlap, 7689 ClientWidth div 2 - xMidPanel, overlap, offscreen.Canvas.Handle, 7690 xMidPanel - MapOffset, MapHeight - overlap, SRCCOPY) 7691 else 7692 BitBlt(Canvas.Handle, MapOffset, TopBarHeight + MapHeight - overlap, 7693 ClientWidth div 2 - MapOffset, overlap, offscreen.Canvas.Handle, 0, 7694 MapHeight - overlap, SRCCOPY); 7695 if xRightPanel < MapOffset + MapWidth then 7696 BitBlt(Canvas.Handle, ClientWidth div 2, TopBarHeight + MapHeight - overlap, 7697 xRightPanel - ClientWidth div 2, overlap, offscreen.Canvas.Handle, 7698 ClientWidth div 2 - MapOffset, MapHeight - overlap, SRCCOPY) 7699 else 7700 BitBlt(Canvas.Handle, ClientWidth div 2, TopBarHeight + MapHeight - overlap, 7701 MapOffset + MapWidth - ClientWidth div 2, overlap, 7702 offscreen.Canvas.Handle, ClientWidth div 2 - MapOffset, 7703 MapHeight - overlap, SRCCOPY); 7704 BitBlt(Canvas.Handle, 0, TopBarHeight + MapHeight - overlap, xMidPanel, 7705 overlap, Panel.Canvas.Handle, 0, 0, SRCCOPY); 7706 BitBlt(Canvas.Handle, xRightPanel, TopBarHeight + MapHeight - overlap, 7707 Panel.width - xRightPanel, overlap, Panel.Canvas.Handle, xRightPanel, 7708 0, SRCCOPY); 7709 BitBlt(Canvas.Handle, 0, TopBarHeight + MapHeight, Panel.width, 7710 PanelHeight - overlap, Panel.Canvas.Handle, 0, overlap, SRCCOPY); 7711 if (pLogo >= 0) and (G.RO[pLogo] = nil) and (AILogo[pLogo] <> nil) then 7712 BitBlt(Canvas.Handle, xRightPanel + 10 - (16 + 64), 7713 ClientHeight - PanelHeight, 64, 64, AILogo[pLogo].Canvas.Handle, 0, 7714 0, SRCCOPY); 7715 end; 7716 7717 procedure TMainScreen.RectInvalidate(Left, Top, Rigth, Bottom: integer); 7718 var 7719 r0: HRgn; 7720 begin 7721 r0 := CreateRectRgn(Left, Top, Rigth, Bottom); 7722 InvalidateRgn(Handle, r0, false); 7723 DeleteObject(r0); 7724 end; 7725 7726 procedure TMainScreen.SmartRectInvalidate(Left, Top, Rigth, Bottom: integer); 7727 var 7728 i: integer; 7729 r0, r1: HRgn; 7730 begin 7731 r0 := CreateRectRgn(Left, Top, Rigth, Bottom); 7732 for i := 0 to ControlCount - 1 do 7733 if not(Controls[i] is TArea) and Controls[i].Visible then 7734 begin 7735 with Controls[i].BoundsRect do 7736 r1 := CreateRectRgn(Left, Top, Right, Bottom); 7737 CombineRgn(r0, r0, r1, RGN_DIFF); 7738 DeleteObject(r1); 7922 7739 end; 7923 7924 procedure TMainScreen.mSoundOffClick(Sender: TObject); 7925 begin 7926 SoundMode := smOff; 7740 InvalidateRgn(Handle, r0, false); 7741 DeleteObject(r0); 7742 end; 7743 7744 procedure TMainScreen.mRepClicked(Sender: TObject); 7745 begin 7746 with TMenuItem(Sender) do 7747 begin 7748 Checked := not Checked; 7749 if Checked then 7750 CityRepMask := CityRepMask or (1 shl (Tag shr 8)) 7751 else 7752 CityRepMask := CityRepMask and not(1 shl (Tag shr 8)) 7753 end 7754 end; 7755 7756 procedure TMainScreen.mLogClick(Sender: TObject); 7757 begin 7758 LogDlg.Show; 7759 end; 7760 7761 procedure TMainScreen.FormShow(Sender: TObject); 7762 begin 7763 Timer1.Enabled := true; 7764 Left := 0; 7765 Top := 0; 7766 end; 7767 7768 procedure TMainScreen.FormClose(Sender: TObject; var Action: TCloseAction); 7769 begin 7770 Timer1.Enabled := false; 7771 end; 7772 7773 procedure TMainScreen.Radio(Sender: TObject); 7774 begin 7775 TMenuItem(Sender).Checked := true; 7776 end; 7777 7778 procedure TMainScreen.mManipClick(Sender: TObject); 7779 var 7780 Flag: integer; 7781 begin 7782 with TMenuItem(Sender) do 7783 begin 7784 Flag := 1 shl (Tag shr 8); 7785 if Checked then 7786 Server(sClearTestFlag, 0, Flag, nil^) 7787 else 7788 begin 7789 Server(sSetTestFlag, 0, Flag, nil^); 7790 Play('CHEAT'); 7927 7791 end; 7928 7929 procedure TMainScreen.mSoundOnClick(Sender: TObject); 7930 begin 7931 SoundMode := smOn; 7932 end; 7933 7934 procedure TMainScreen.mSoundOnAltClick(Sender: TObject); 7935 begin 7936 SoundMode := smOnAlt; 7937 end; 7938 7939 { procedure TMainScreen.AdviceBtnClick; 7940 var 7941 OldAdviceLoc: integer; 7942 begin 7943 DestinationMarkON:=false; 7944 PaintDestination; 7945 AdvisorDlg.GiveStrategyAdvice; 7946 OldAdviceLoc:=MainMap.AdviceLoc; 7947 MainMap.AdviceLoc:=-1; 7948 PaintLoc(OldAdviceLoc); 7949 end; } 7950 7951 { procedure TMainScreen.SetAdviceLoc(Loc: integer; AvoidRect: TRect); 7952 var 7953 OldAdviceLoc,x,y: integer; 7954 begin 7955 if Loc<>MainMap.AdviceLoc then 7956 begin 7957 if Loc>=0 then 7958 begin // center 7959 y:=Loc div G.lx; 7960 x:=(Loc+G.lx - AvoidRect.Right div (2*66)) mod G.lx; 7961 Centre(y*G.lx+x); 7962 PaintAllMaps; 7963 end; 7964 OldAdviceLoc:=MainMap.AdviceLoc; 7965 MainMap.AdviceLoc:=Loc; 7966 PaintLoc(OldAdviceLoc); 7967 PaintLoc(MainMap.AdviceLoc); 7968 end; 7969 end; } 7970 7971 procedure TMainScreen.UnitInfoBtnClick(Sender: TObject); 7972 begin 7973 if UnFocus >= 0 then 7974 UnitStatDlg.ShowNewContent_OwnModel(wmPersistent, MyUn[UnFocus].mix) 7975 end; 7976 7977 procedure TMainScreen.ViewpointClick(Sender: TObject); 7978 begin 7979 SetViewpoint(TMenuItem(Sender).Tag); 7980 end; 7981 7982 procedure TMainScreen.DebugMapClick(Sender: TObject); 7983 begin 7984 SetDebugMap(TMenuItem(Sender).Tag); 7985 end; 7986 7987 procedure TMainScreen.mSmallTilesClick(Sender: TObject); 7988 begin 7989 SetTileSize(33, 16); 7990 end; 7991 7992 procedure TMainScreen.mNormalTilesClick(Sender: TObject); 7993 begin 7994 SetTileSize(48, 24); 7995 end; 7996 7997 procedure TMainScreen.SetTileSize(x, y: integer); 7998 var 7999 i, CenterLoc: integer; 8000 begin 8001 CenterLoc := (xw + MapWidth div (xxt * 4)) mod G.lx + 8002 (yw + MapHeight div (yyt * 2)) * G.lx; 8003 IsoEngine.ApplyTileSize(x, y); 8004 FormResize(nil); 8005 Centre(CenterLoc); 8006 PaintAllMaps; 8007 for i := 0 to Screen.FormCount - 1 do 8008 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) 8009 then 8010 TBufferedDrawDlg(Screen.Forms[i]).SmartUpdateContent(false); 8011 end; 8012 8013 procedure TMainScreen.SaveSettings; 8014 var 8015 i, j: integer; 8016 Reg: TRegistry; 8017 begin 8018 OptionChecked := OptionChecked and soExtraMask; 8019 for i := 0 to ComponentCount - 1 do 8020 if Components[i] is TMenuItem then 8021 for j := 0 to nSaveOption - 1 do 8022 if TMenuItem(Components[i]).Checked and 8023 (TMenuItem(Components[i]).Tag = SaveOption[j]) then 8024 inc(OptionChecked, 1 shl j); 8025 8026 Reg := TRegistry.Create; 8027 Reg.OpenKey('SOFTWARE\cevo\RegVer9', true); 8028 Reg.WriteInteger('TileWidth', xxt * 2); 8029 Reg.WriteInteger('TileHeight', yyt * 2); 8030 Reg.WriteInteger('OptionChecked', OptionChecked); 8031 Reg.WriteInteger('MapOptionChecked', MapOptionChecked); 8032 Reg.WriteInteger('CityReport', integer(CityRepMask)); 8033 Reg.closekey; 8034 Reg.free; 8035 end; 8036 8037 procedure TMainScreen.MovieSpeedBtnClick(Sender: TObject); 8038 begin 8039 MovieSpeed := TButtonB(Sender).Tag shr 8; 8040 CheckMovieSpeedBtnState; 8041 end; 7792 if not supervising then 7793 begin 7794 if Flag = tfUncover then 7795 begin 7796 MapValid := false; 7797 PaintAllMaps; 7798 end 7799 else if Flag = tfAllTechs then 7800 TellNewModels 7801 end 7802 end 7803 end; 7804 7805 procedure TMainScreen.MapBtnClick(Sender: TObject); 7806 begin 7807 with TButtonC(Sender) do 7808 begin 7809 MapOptionChecked := MapOptionChecked xor (1 shl (Tag shr 8)); 7810 SetMapOptions; 7811 ButtonIndex := MapOptionChecked shr (Tag shr 8) and 1 + 2 7812 end; 7813 if Sender = MapBtn0 then 7814 begin 7815 MiniPaint; 7816 PanelPaint 7817 end // update mini map only 7818 else 7819 begin 7820 MapValid := false; 7821 PaintAllMaps; 7822 end; // update main map 7823 end; 7824 7825 procedure TMainScreen.GrWallBtnDownChanged(Sender: TObject); 7826 begin 7827 if TButtonBase(Sender).Down then 7828 begin 7829 MapOptionChecked := MapOptionChecked or (1 shl moGreatWall); 7830 TButtonBase(Sender).Hint := ''; 7831 end 7832 else 7833 begin 7834 MapOptionChecked := MapOptionChecked and not(1 shl moGreatWall); 7835 TButtonBase(Sender).Hint := Phrases.Lookup('CONTROLS', 7836 -1 + TButtonBase(Sender).Tag and $FF); 7837 end; 7838 SetMapOptions; 7839 MapValid := false; 7840 PaintAllMaps; 7841 end; 7842 7843 procedure TMainScreen.BareBtnDownChanged(Sender: TObject); 7844 begin 7845 if TButtonBase(Sender).Down then 7846 begin 7847 MapOptionChecked := MapOptionChecked or (1 shl moBareTerrain); 7848 TButtonBase(Sender).Hint := ''; 7849 end 7850 else 7851 begin 7852 MapOptionChecked := MapOptionChecked and not(1 shl moBareTerrain); 7853 TButtonBase(Sender).Hint := Phrases.Lookup('CONTROLS', 7854 -1 + TButtonBase(Sender).Tag and $FF); 7855 end; 7856 SetMapOptions; 7857 MapValid := false; 7858 PaintAllMaps; 7859 end; 7860 7861 procedure TMainScreen.FormKeyUp(Sender: TObject; var Key: word; 7862 Shift: TShiftState); 7863 begin 7864 if idle and (Key = VK_APPS) then 7865 begin 7866 InitPopup(GamePopup); 7867 if FullScreen then 7868 GamePopup.Popup(Left, Top + TopBarHeight - 1) 7869 else 7870 GamePopup.Popup(Left + 4, Top + GetSystemMetrics(SM_CYCAPTION) + 4 + 7871 TopBarHeight - 1); 7872 exit 7873 end // windows menu button calls game menu 7874 end; 7875 7876 procedure TMainScreen.CreateUnitClick(Sender: TObject); 7877 var 7878 p1, mix: integer; 7879 begin 7880 p1 := TComponent(Sender).Tag shr 16; 7881 mix := TComponent(Sender).Tag and $FFFF; 7882 if Server(sCreateUnit + p1 shl 4, me, mix, EditLoc) >= rExecuted then 7883 PaintLoc(EditLoc); 7884 end; 7885 7886 procedure TMainScreen.mSoundOffClick(Sender: TObject); 7887 begin 7888 SoundMode := smOff; 7889 end; 7890 7891 procedure TMainScreen.mSoundOnClick(Sender: TObject); 7892 begin 7893 SoundMode := smOn; 7894 end; 7895 7896 procedure TMainScreen.mSoundOnAltClick(Sender: TObject); 7897 begin 7898 SoundMode := smOnAlt; 7899 end; 7900 7901 { procedure TMainScreen.AdviceBtnClick; 7902 var 7903 OldAdviceLoc: integer; 7904 begin 7905 DestinationMarkON:=false; 7906 PaintDestination; 7907 AdvisorDlg.GiveStrategyAdvice; 7908 OldAdviceLoc:=MainMap.AdviceLoc; 7909 MainMap.AdviceLoc:=-1; 7910 PaintLoc(OldAdviceLoc); 7911 end; } 7912 7913 { procedure TMainScreen.SetAdviceLoc(Loc: integer; AvoidRect: TRect); 7914 var 7915 OldAdviceLoc,x,y: integer; 7916 begin 7917 if Loc<>MainMap.AdviceLoc then 7918 begin 7919 if Loc>=0 then 7920 begin // center 7921 y:=Loc div G.lx; 7922 x:=(Loc+G.lx - AvoidRect.Right div (2*66)) mod G.lx; 7923 Centre(y*G.lx+x); 7924 PaintAllMaps; 7925 end; 7926 OldAdviceLoc:=MainMap.AdviceLoc; 7927 MainMap.AdviceLoc:=Loc; 7928 PaintLoc(OldAdviceLoc); 7929 PaintLoc(MainMap.AdviceLoc); 7930 end; 7931 end; } 7932 7933 procedure TMainScreen.UnitInfoBtnClick(Sender: TObject); 7934 begin 7935 if UnFocus >= 0 then 7936 UnitStatDlg.ShowNewContent_OwnModel(wmPersistent, MyUn[UnFocus].mix) 7937 end; 7938 7939 procedure TMainScreen.ViewpointClick(Sender: TObject); 7940 begin 7941 SetViewpoint(TMenuItem(Sender).Tag); 7942 end; 7943 7944 procedure TMainScreen.DebugMapClick(Sender: TObject); 7945 begin 7946 SetDebugMap(TMenuItem(Sender).Tag); 7947 end; 7948 7949 procedure TMainScreen.mSmallTilesClick(Sender: TObject); 7950 begin 7951 SetTileSize(33, 16); 7952 end; 7953 7954 procedure TMainScreen.mNormalTilesClick(Sender: TObject); 7955 begin 7956 SetTileSize(48, 24); 7957 end; 7958 7959 procedure TMainScreen.SetTileSize(x, y: integer); 7960 var 7961 i, CenterLoc: integer; 7962 begin 7963 CenterLoc := (xw + MapWidth div (xxt * 4)) mod G.lx + 7964 (yw + MapHeight div (yyt * 2)) * G.lx; 7965 IsoEngine.ApplyTileSize(x, y); 7966 FormResize(nil); 7967 Centre(CenterLoc); 7968 PaintAllMaps; 7969 for i := 0 to Screen.FormCount - 1 do 7970 if Screen.Forms[i].Visible and (Screen.Forms[i] is TBufferedDrawDlg) then 7971 TBufferedDrawDlg(Screen.Forms[i]).SmartUpdateContent(false); 7972 end; 7973 7974 procedure TMainScreen.SaveSettings; 7975 var 7976 i, j: integer; 7977 Reg: TRegistry; 7978 begin 7979 OptionChecked := OptionChecked and soExtraMask; 7980 for i := 0 to ComponentCount - 1 do 7981 if Components[i] is TMenuItem then 7982 for j := 0 to nSaveOption - 1 do 7983 if TMenuItem(Components[i]).Checked and 7984 (TMenuItem(Components[i]).Tag = SaveOption[j]) then 7985 inc(OptionChecked, 1 shl j); 7986 7987 Reg := TRegistry.Create; 7988 Reg.OpenKey('SOFTWARE\cevo\RegVer9', true); 7989 Reg.WriteInteger('TileWidth', xxt * 2); 7990 Reg.WriteInteger('TileHeight', yyt * 2); 7991 Reg.WriteInteger('OptionChecked', OptionChecked); 7992 Reg.WriteInteger('MapOptionChecked', MapOptionChecked); 7993 Reg.WriteInteger('CityReport', integer(CityRepMask)); 7994 Reg.CloseKey; 7995 Reg.free; 7996 end; 7997 7998 procedure TMainScreen.MovieSpeedBtnClick(Sender: TObject); 7999 begin 8000 MovieSpeed := TButtonB(Sender).Tag shr 8; 8001 CheckMovieSpeedBtnState; 8002 end; 8042 8003 8043 8004 initialization
Note:
See TracChangeset
for help on using the changeset viewer.