Changeset 303 for branches/highdpi/LocalPlayer
- Timestamp:
- Mar 9, 2021, 9:19:49 AM (4 years ago)
- Location:
- branches/highdpi/LocalPlayer
- Files:
-
- 1 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/highdpi/LocalPlayer/CityScreen.pas
r246 r303 216 216 Template := TDpiBitmap.Create; 217 217 Template.PixelFormat := pf24bit; 218 LoadGraphicFile(Template, GetGraphicsDir + DirectorySeparator + 'City.png', gfNoGamma); 218 LoadGraphicFile(Template, GetGraphicsDir + DirectorySeparator + 'City.png', 219 [gfNoGamma]); 219 220 CityMapTemplate := TDpiBitmap.Create; 220 221 CityMapTemplate.PixelFormat := pf24bit; 221 LoadGraphicFile(CityMapTemplate, GetGraphicsDir + DirectorySeparator + 'BigCityMap.png', gfNoGamma); 222 LoadGraphicFile(CityMapTemplate, GetGraphicsDir + DirectorySeparator + 'BigCityMap.png', 223 [gfNoGamma]); 222 224 SmallCityMapTemplate := TDpiBitmap.Create; 223 225 SmallCityMapTemplate.PixelFormat := pf24bit; 224 226 LoadGraphicFile(SmallCityMapTemplate, GetGraphicsDir + DirectorySeparator + 'SmallCityMap.png', 225 gfNoGamma);227 [gfNoGamma]); 226 228 SmallCityMap := TDpiBitmap.Create; 227 229 SmallCityMap.PixelFormat := pf24bit; … … 1397 1399 1398 1400 procedure TCityDlg.ChooseProject; 1399 const 1400 ptSelect = 0; 1401 ptTrGoods = 1; 1402 ptUn = 2; 1403 ptCaravan = 3; 1404 ptImp = 4; 1405 ptWonder = 6; 1406 ptShip = 7; 1407 ptInvalid = 8; 1408 1409 function ProjectType(Project: integer): integer; 1401 type 1402 TProjectType = ( 1403 ptSelect = 0, 1404 ptTrGoods = 1, 1405 ptUn = 2, 1406 ptCaravan = 3, 1407 ptImp = 4, 1408 ptWonder = 6, 1409 ptShip = 7, 1410 ptInvalid = 8 1411 ); 1412 1413 function ProjectType(Project: integer): TProjectType; 1410 1414 begin 1411 1415 if Project and cpCompleted <> 0 then 1412 result := ptSelect1416 Result := ptSelect 1413 1417 else if Project and (cpImp + cpIndex) = cpImp + imTrGoods then 1414 result := ptTrGoods1415 else if Project and cpImp = 0 then 1418 Result := ptTrGoods 1419 else if Project and cpImp = 0 then begin 1416 1420 if MyModel[Project and cpIndex].Kind = mkCaravan then 1417 result := ptCaravan1418 else 1419 result := ptUn1421 Result := ptCaravan 1422 else Result := ptUn; 1423 end 1420 1424 else if Project and cpIndex >= nImp then 1421 result := ptInvalid1425 Result := ptInvalid 1422 1426 else if Imp[Project and cpIndex].Kind = ikWonder then 1423 result := ptWonder1427 Result := ptWonder 1424 1428 else if Imp[Project and cpIndex].Kind = ikShipPart then 1425 result := ptShip1426 else 1427 result := ptImp1429 Result := ptShip 1430 else 1431 Result := ptImp; 1428 1432 end; 1429 1433 1430 1434 var 1431 NewProject, OldMoney, pt0, pt1, cix1: integer; 1435 NewProject, OldMoney, cix1: integer; 1436 pt0, pt1: TProjectType; 1432 1437 QueryOk: boolean; 1433 1438 begin 1434 assert(not supervising);1439 Assert(not supervising); 1435 1440 ModalSelectDlg.ShowNewContent_CityProject(wmModal, cix); 1436 1441 if ModalSelectDlg.result <> -1 then … … 1444 1449 else 1445 1450 begin 1446 NewProject := ModalSelectDlg. result;1447 QueryOk := true;1451 NewProject := ModalSelectDlg.Result; 1452 QueryOk := True; 1448 1453 if (NewProject and cpImp <> 0) and (NewProject and cpIndex >= 28) and 1449 1454 (MyRO.NatBuilt[NewProject and cpIndex] > 0) then … … 1453 1458 while (cix1 >= 0) and 1454 1459 (MyCity[cix1].Built[NewProject and cpIndex] = 0) do 1455 dec(cix1);1460 Dec(cix1); 1456 1461 MessgText := Format(Phrases.Lookup('DOUBLESTATEIMP'), 1457 1462 [Phrases.Lookup('IMPROVEMENTS', NewProject and cpIndex), … … 1465 1470 end; 1466 1471 if not QueryOk then 1467 exit;1472 Exit; 1468 1473 1469 1474 if (MyCity[cix].Prod > 0) then … … 1476 1481 (cpImp or cpIndex) then 1477 1482 begin // loss of material -- do query 1483 DpiApplication.ProcessMessages; // TODO: Needed for Gtk2, Lazarus gtk2 bug? 1478 1484 if (pt1 = ptTrGoods) or (pt1 = ptShip) or (pt1 <> pt0) and 1479 (pt0 <> ptCaravan) then 1485 (pt0 <> ptCaravan) then begin 1480 1486 QueryOk := SimpleQuery(mkOkCancel, 1481 1487 Format(Phrases.Lookup('LOSEMAT'), [MyCity[cix].Prod0, 1482 1488 MyCity[cix].Prod0]), 'MSG_DEFAULT') = mrOK 1483 else if MyCity[cix].Project and (cpImp or cpIndex) = MyCity[cix] 1484 .Project0 and (cpImp or cpIndex) then 1485 QueryOk := SimpleQuery(mkOkCancel, Phrases.Lookup('LOSEMAT3'), 1486 'MSG_DEFAULT') = mrOK 1489 end else 1490 if MyCity[cix].Project and (cpImp or cpIndex) = MyCity[cix] 1491 .Project0 and (cpImp or cpIndex) then begin 1492 QueryOk := SimpleQuery(mkOkCancel, Phrases.Lookup('LOSEMAT3'), 1493 'MSG_DEFAULT') = mrOK; 1494 end; 1487 1495 end; 1488 1496 end; 1489 1497 end; 1490 1498 if not QueryOk then 1491 exit;1499 Exit; 1492 1500 1493 1501 OldMoney := MyRO.Money; -
branches/highdpi/LocalPlayer/ClientTools.pas
r210 r303 13 13 14 14 type 15 TImpOrder = array [0 .. (nImp + 4) div 4 * 4 - 1] of ShortInt;16 TEnhancementJobs = array [0 .. 11, 0 .. 7] of Byte;15 TImpOrder = array [0 .. (nImp + 4) div 4 * 4 - 1] of shortint; 16 TEnhancementJobs = array [0 .. 11, 0 .. 7] of byte; 17 17 JobResultSet = set of 0 .. 39; 18 18 … … 42 42 function CutCityFoodSurplus(FoodSurplus: integer; IsCityAlive: boolean; 43 43 gov, size: integer): integer; 44 function CityTaxBalance(cix: integer; const CityReport: TCityReportNew) 45 : integer; 44 function CityTaxBalance(cix: integer; const CityReport: TCityReportNew): integer; 46 45 procedure SumCities(var TaxSum, ScienceSum: integer); 47 46 function JobTest(uix, Job: integer; IgnoreResults: JobResultSet = []): boolean; … … 50 49 function UnitExhausted(uix: integer): boolean; 51 50 function ModelHash(const ModelInfo: TModelInfo): integer; 52 function ProcessEnhancement(uix: integer; const Jobs: TEnhancementJobs) 53 : integer; 51 function ProcessEnhancement(uix: integer; const Jobs: TEnhancementJobs): integer; 54 52 function AutoBuild(cix: integer; const ImpOrder: TImpOrder): boolean; 55 53 procedure DebugMessage(Level: integer; Text: string); … … 62 60 procedure CityOptimizer_EndOfTurn; 63 61 62 64 63 implementation 65 64 … … 72 71 begin 73 72 y0 := (Loc + G.lx * 1024) div G.lx - 1024; 74 result := (Loc + (dx + y0 and 1 + G.lx * 1024) shr 1) mod G.lx + G.lx 75 * (y0 + dy) 73 Result := (Loc + (dx + y0 and 1 + G.lx * 1024) shr 1) mod G.lx + G.lx * (y0 + dy); 76 74 end; 77 75 … … 80 78 dx, dy: integer; 81 79 begin 82 inc(Loc0, G.lx * 1024);83 inc(Loc1, G.lx * 1024);84 dx := abs(((Loc1 mod G.lx * 2 + Loc1 div G.lx and 1) - (Loc0 mod G.lx * 2 +85 Loc0 div G.lx and 1) + 3 * G.lx) mod (2 * G.lx) - G.lx);80 Inc(Loc0, G.lx * 1024); 81 Inc(Loc1, G.lx * 1024); 82 dx := abs(((Loc1 mod G.lx * 2 + Loc1 div G.lx and 1) - 83 (Loc0 mod G.lx * 2 + Loc0 div G.lx and 1) + 3 * G.lx) mod (2 * G.lx) - G.lx); 86 84 dy := abs(Loc1 div G.lx - Loc0 div G.lx); 87 result := dx + dy + abs(dx - dy) shr 1;85 Result := dx + dy + abs(dx - dy) shr 1; 88 86 end; 89 87 … … 92 90 uix1: integer; 93 91 begin 94 result := false;92 Result := False; 95 93 if MyModel[MyUn[uix].mix].Flags and mdCivil = 0 then 96 94 case MyRO.Government of 97 95 gRepublic, gFuture: 98 result := (MyRO.Territory[Loc] >= 0) and (MyRO.Territory[Loc] <> me) and96 Result := (MyRO.Territory[Loc] >= 0) and (MyRO.Territory[Loc] <> me) and 99 97 (MyRO.Treaty[MyRO.Territory[Loc]] < trAlliance); 100 98 gDemocracy: 101 result := (MyRO.Territory[Loc] < 0) or (MyRO.Territory[Loc] <> me) and99 Result := (MyRO.Territory[Loc] < 0) or (MyRO.Territory[Loc] <> me) and 102 100 (MyRO.Treaty[MyRO.Territory[Loc]] < trAlliance); 103 101 end; … … 106 104 for uix1 := 0 to MyRO.nUn - 1 do // check transported units too 107 105 if (MyUn[uix1].Loc >= 0) and (MyUn[uix1].Master = uix) then 108 result := result or UnrestAtLoc(uix1, Loc);106 Result := Result or UnrestAtLoc(uix1, Loc); 109 107 end; 110 108 … … 124 122 MoveAdviceData.MoreTurns := 999; 125 123 MoveAdviceData.MaxHostile_MovementLeft := MyUn[uix].Health - MinEndHealth; 126 result := Server(sGetMoveAdvice, me, uix, MoveAdviceData);127 if (MinEndHealth <= 1) or ( result <> eNoWay) then124 Result := Server(sGetMoveAdvice, me, uix, MoveAdviceData); 125 if (MinEndHealth <= 1) or (Result <> eNoWay) then 128 126 exit; 129 127 end; … … 135 133 25: 136 134 MinEndHealth := 12; 135 else 136 MinEndHealth := 1 137 end; 138 until False; 139 end; 140 141 function ColorOfHealth(Health: integer): integer; 142 var 143 red, green: integer; 144 begin 145 green := 400 * Health div 100; 146 if green > 200 then 147 green := 200; 148 red := 510 * (100 - Health) div 100; 149 if red > 255 then 150 red := 255; 151 Result := green shl 8 + red; 152 end; 153 154 function IsMultiPlayerGame: boolean; 155 var 156 p1: integer; 157 begin 158 Result := False; 159 for p1 := 1 to nPl - 1 do 160 if G.RO[p1] <> nil then 161 Result := True; 162 end; 163 164 procedure ItsMeAgain(p: integer); 165 begin 166 if G.RO[p] <> nil then 167 MyRO := pointer(G.RO[p]) 168 else if G.SuperVisorRO[p] <> nil then 169 MyRO := pointer(G.SuperVisorRO[p]) 170 else 171 exit; 172 me := p; 173 MyMap := pointer(MyRO.Map); 174 MyUn := pointer(MyRO.Un); 175 MyCity := pointer(MyRO.City); 176 MyModel := pointer(MyRO.Model); 177 end; 178 179 function GetAge(p: integer): integer; 180 var 181 i: integer; 182 begin 183 if p = me then 184 begin 185 Result := 0; 186 for i := 1 to 3 do 187 if MyRO.Tech[AgePreq[i]] >= tsApplicable then 188 Result := i; 189 end 190 else 191 begin 192 Result := 0; 193 for i := 1 to 3 do 194 if MyRO.EnemyReport[p].Tech[AgePreq[i]] >= tsApplicable then 195 Result := i; 196 end; 197 end; 198 199 function IsCivilReportNew(Enemy: integer): boolean; 200 var 201 i: integer; 202 begin 203 assert(Enemy <> me); 204 i := MyRO.EnemyReport[Enemy].TurnOfCivilReport; 205 Result := (i = MyRO.Turn) or (i = MyRO.Turn - 1) and (Enemy > me); 206 end; 207 208 function IsMilReportNew(Enemy: integer): boolean; 209 var 210 i: integer; 211 begin 212 assert(Enemy <> me); 213 i := MyRO.EnemyReport[Enemy].TurnOfMilReport; 214 Result := (i = MyRO.Turn) or (i = MyRO.Turn - 1) and (Enemy > me); 215 end; 216 217 function CutCityFoodSurplus(FoodSurplus: integer; IsCityAlive: boolean; 218 gov, size: integer): integer; 219 begin 220 Result := FoodSurplus; 221 if not IsCityAlive or (Result > 0) and ((gov = gFuture) or 222 (size >= NeedAqueductSize) and (Result < 2)) then 223 Result := 0; { no growth } 224 end; 225 226 function CityTaxBalance(cix: integer; const CityReport: TCityReportNew): integer; 227 var 228 i: integer; 229 begin 230 Result := 0; 231 if (CityReport.HappinessBalance >= 0) { no disorder } and 232 (MyCity[cix].Flags and chCaptured = 0) then // not captured 233 begin 234 Inc(Result, CityReport.Tax); 235 if (MyCity[cix].Project and (cpImp + cpIndex) = cpImp + imTrGoods) and 236 (CityReport.Production > 0) then 237 Inc(Result, CityReport.Production); 238 if ((MyRO.Government = gFuture) or (MyCity[cix].size >= 239 NeedAqueductSize) and (CityReport.FoodSurplus < 2)) and 240 (CityReport.FoodSurplus > 0) then 241 Inc(Result, CityReport.FoodSurplus); 242 end; 243 for i := 28 to nImp - 1 do 244 if MyCity[cix].Built[i] > 0 then 245 Dec(Result, Imp[i].Maint); 246 end; 247 248 procedure SumCities(var TaxSum, ScienceSum: integer); 249 var 250 cix: integer; 251 CityReport: TCityReportNew; 252 begin 253 TaxSum := MyRO.OracleIncome; 254 ScienceSum := 0; 255 if MyRO.Government = gAnarchy then 256 exit; 257 for cix := 0 to MyRO.nCity - 1 do 258 if MyCity[cix].Loc >= 0 then 259 begin 260 CityReport.HypoTiles := -1; 261 CityReport.HypoTaxRate := -1; 262 CityReport.HypoLuxuryRate := -1; 263 Server(sGetCityReportNew, me, cix, CityReport); 264 if (CityReport.HappinessBalance >= 0) { no disorder } and 265 (MyCity[cix].Flags and chCaptured = 0) then // not captured 266 ScienceSum := ScienceSum + CityReport.Science; 267 TaxSum := TaxSum + CityTaxBalance(cix, CityReport); 268 end; 269 end; 270 271 function JobTest(uix, Job: integer; IgnoreResults: JobResultSet): boolean; 272 var 273 Test: integer; 274 begin 275 Test := Server(sStartJob + Job shl 4 - sExecute, me, uix, nil^); 276 Result := (Test >= rExecuted) or (Test in IgnoreResults); 277 end; 278 279 procedure GetUnitInfo(Loc: integer; var uix: integer; var UnitInfo: TUnitInfo); 280 var 281 i, Cnt: integer; 282 begin 283 if MyMap[Loc] and fOwned <> 0 then 284 begin 285 Server(sGetDefender, me, Loc, uix); 286 Cnt := 0; 287 for i := 0 to MyRO.nUn - 1 do 288 if MyUn[i].Loc = Loc then 289 Inc(Cnt); 290 MakeUnitInfo(me, MyUn[uix], UnitInfo); 291 if Cnt > 1 then 292 UnitInfo.Flags := UnitInfo.Flags or unMulti; 293 end 294 else 295 begin 296 uix := MyRO.nEnemyUn - 1; 297 while (uix >= 0) and (MyRO.EnemyUn[uix].Loc <> Loc) do 298 Dec(uix); 299 UnitInfo := MyRO.EnemyUn[uix]; 300 end; 301 end; { GetUnitInfo } 302 303 procedure GetCityInfo(Loc: integer; var cix: integer; var CityInfo: TCityInfo); 304 begin 305 if MyMap[Loc] and fOwned <> 0 then 306 begin 307 CityInfo.Loc := Loc; 308 cix := MyRO.nCity - 1; 309 while (cix >= 0) and (MyCity[cix].Loc <> Loc) do 310 Dec(cix); 311 with CityInfo do 312 begin 313 Owner := me; 314 ID := MyCity[cix].ID; 315 size := MyCity[cix].size; 316 Flags := 0; 317 if MyCity[cix].Built[imPalace] > 0 then 318 Inc(Flags, ciCapital); 319 if (MyCity[cix].Built[imWalls] > 0) or 320 (MyMap[MyCity[cix].Loc] and fGrWall <> 0) then 321 Inc(Flags, ciWalled); 322 if MyCity[cix].Built[imCoastalFort] > 0 then 323 Inc(Flags, ciCoastalFort); 324 if MyCity[cix].Built[imMissileBat] > 0 then 325 Inc(Flags, ciMissileBat); 326 if MyCity[cix].Built[imBunker] > 0 then 327 Inc(Flags, ciBunker); 328 if MyCity[cix].Built[imSpacePort] > 0 then 329 Inc(Flags, ciSpacePort); 330 end; 331 end 332 else 333 begin 334 cix := MyRO.nEnemyCity - 1; 335 while (cix >= 0) and (MyRO.EnemyCity[cix].Loc <> Loc) do 336 Dec(cix); 337 CityInfo := MyRO.EnemyCity[cix]; 338 end; 339 end; 340 341 function UnitExhausted(uix: integer): boolean; 342 // check if another move of this unit is still possible 343 var 344 dx, dy: integer; 345 begin 346 Result := True; 347 if (MyUn[uix].Movement > 0) or 348 (MyRO.Wonder[woShinkansen].EffectiveOwner = me) then 349 if (MyUn[uix].Movement >= 100) or 350 ((MyModel[MyUn[uix].mix].Kind = mkCaravan) and 351 (MyMap[MyUn[uix].Loc] and fCity <> 0)) then 352 Result := False 137 353 else 138 MinEndHealth := 1 139 end; 140 until false end; 141 142 function ColorOfHealth(Health: integer): integer; 143 var 144 red, green: integer; 145 begin 146 green := 400 * Health div 100; 147 if green > 200 then 148 green := 200; 149 red := 510 * (100 - Health) div 100; 150 if red > 255 then 151 red := 255; 152 result := green shl 8 + red 153 end; 154 155 function IsMultiPlayerGame: boolean; 156 var 157 p1: integer; 158 begin 159 result := false; 160 for p1 := 1 to nPl - 1 do 161 if G.RO[p1] <> nil then 162 result := true; 163 end; 164 165 procedure ItsMeAgain(p: integer); 166 begin 167 if G.RO[p] <> nil then 168 MyRO := pointer(G.RO[p]) 169 else if G.SuperVisorRO[p] <> nil then 170 MyRO := pointer(G.SuperVisorRO[p]) 171 else 172 exit; 173 me := p; 174 MyMap := pointer(MyRO.Map); 175 MyUn := pointer(MyRO.Un); 176 MyCity := pointer(MyRO.City); 177 MyModel := pointer(MyRO.Model); 178 end; 179 180 function GetAge(p: integer): integer; 181 var 182 i: integer; 183 begin 184 if p = me then 185 begin 186 result := 0; 187 for i := 1 to 3 do 188 if MyRO.Tech[AgePreq[i]] >= tsApplicable then 189 result := i; 190 end 354 for dx := -2 to 2 do 355 for dy := -2 to 2 do 356 if abs(dx) + abs(dy) = 2 then 357 if Server(sMoveUnit - sExecute + dx and 7 shl 4 + dy and 358 7 shl 7, me, uix, nil^) >= rExecuted then 359 Result := False; 360 end; 361 362 function ModelHash(const ModelInfo: TModelInfo): integer; 363 var 364 i, FeatureCode, Hash1, Hash2, Hash2r, d: cardinal; 365 begin 366 with ModelInfo do 367 if Kind > mkEnemyDeveloped then 368 Result := integer($C0000000 + Speed div 50 + Kind shl 8) 191 369 else 192 370 begin 193 result := 0; 194 for i := 1 to 3 do 195 if MyRO.EnemyReport[p].Tech[AgePreq[i]] >= tsApplicable then 196 result := i; 197 end 198 end; 199 200 function IsCivilReportNew(Enemy: integer): boolean; 201 var 202 i: integer; 203 begin 204 assert(Enemy <> me); 205 i := MyRO.EnemyReport[Enemy].TurnOfCivilReport; 206 result := (i = MyRO.Turn) or (i = MyRO.Turn - 1) and (Enemy > me); 207 end; 208 209 function IsMilReportNew(Enemy: integer): boolean; 210 var 211 i: integer; 212 begin 213 assert(Enemy <> me); 214 i := MyRO.EnemyReport[Enemy].TurnOfMilReport; 215 result := (i = MyRO.Turn) or (i = MyRO.Turn - 1) and (Enemy > me); 216 end; 217 218 function CutCityFoodSurplus(FoodSurplus: integer; IsCityAlive: boolean; 219 gov, size: integer): integer; 220 begin 221 result := FoodSurplus; 222 if not IsCityAlive or (result > 0) and 223 ((gov = gFuture) or (size >= NeedAqueductSize) and (result < 2)) then 224 result := 0; { no growth } 225 end; 226 227 function CityTaxBalance(cix: integer; 228 const CityReport: TCityReportNew): integer; 229 var 230 i: integer; 231 begin 232 result := 0; 233 if (CityReport.HappinessBalance >= 0) { no disorder } 234 and (MyCity[cix].Flags and chCaptured = 0) then // not captured 235 begin 236 inc(result, CityReport.Tax); 237 if (MyCity[cix].Project and (cpImp + cpIndex) = cpImp + imTrGoods) and 238 (CityReport.Production > 0) then 239 inc(result, CityReport.Production); 240 if ((MyRO.Government = gFuture) or (MyCity[cix].size >= NeedAqueductSize) 241 and (CityReport.FoodSurplus < 2)) and (CityReport.FoodSurplus > 0) then 242 inc(result, CityReport.FoodSurplus); 371 FeatureCode := 0; 372 for i := mcFirstNonCap to nFeature - 1 do 373 if 1 shl Domain and Feature[i].Domains <> 0 then 374 begin 375 FeatureCode := FeatureCode * 2; 376 if 1 shl (i - mcFirstNonCap) <> 0 then 377 Inc(FeatureCode); 378 end; 379 case Domain of 380 dGround: 381 begin 382 assert(FeatureCode < 1 shl 8); 383 assert(Attack < 5113); 384 assert(Defense < 2273); 385 assert(Cost < 1611); 386 Hash1 := (Attack * 2273 + Defense) * 9 + (Speed - 150) div 50; 387 Hash2 := FeatureCode * 1611 + Cost; 388 end; 389 dSea: 390 begin 391 assert(FeatureCode < 1 shl 9); 392 assert(Attack < 12193); 393 assert(Defense < 6097); 394 assert(Cost < 4381); 395 Hash1 := ((Attack * 6097 + Defense) * 5 + 396 (Speed - 350) div 100) * 2; 397 if Weight >= 6 then 398 Inc(Hash1); 399 Hash2 := ((TTrans * 17 + ATrans_Fuel) shl 9 + FeatureCode) * 400 4381 + Cost; 401 end; 402 dAir: 403 begin 404 assert(FeatureCode < 1 shl 5); 405 assert(Attack < 2407); 406 assert(Defense < 1605); 407 assert(Bombs < 4813); 408 assert(Cost < 2089); 409 Hash1 := (Attack * 1605 + Defense) shl 5 + FeatureCode; 410 Hash2 := ((Bombs * 7 + ATrans_Fuel) * 4 + TTrans) * 2089 + Cost; 411 end; 412 end; 413 Hash2r := 0; 414 for i := 0 to 7 do 415 begin 416 Hash2r := Hash2r * 13; 417 d := Hash2 div 13; 418 Inc(Hash2r, Hash2 - d * 13); 419 Hash2 := d; 420 end; 421 Result := integer(Domain shl 30 + Hash1 xor Hash2r); 243 422 end; 244 for i := 28 to nImp - 1 do 245 if MyCity[cix].Built[i] > 0 then 246 dec(result, Imp[i].Maint); 247 end; 248 249 procedure SumCities(var TaxSum, ScienceSum: integer); 250 var 251 cix: integer; 252 CityReport: TCityReportNew; 253 begin 254 TaxSum := MyRO.OracleIncome; 255 ScienceSum := 0; 256 if MyRO.Government = gAnarchy then 257 exit; 258 for cix := 0 to MyRO.nCity - 1 do 259 if MyCity[cix].Loc >= 0 then 260 begin 261 CityReport.HypoTiles := -1; 262 CityReport.HypoTaxRate := -1; 263 CityReport.HypoLuxuryRate := -1; 264 Server(sGetCityReportNew, me, cix, CityReport); 265 if (CityReport.HappinessBalance >= 0) { no disorder } 266 and (MyCity[cix].Flags and chCaptured = 0) then // not captured 267 ScienceSum := ScienceSum + CityReport.Science; 268 TaxSum := TaxSum + CityTaxBalance(cix, CityReport); 269 end; 270 end; 271 272 function JobTest(uix, Job: integer; IgnoreResults: JobResultSet): boolean; 273 var 274 Test: integer; 275 begin 276 Test := Server(sStartJob + Job shl 4 - sExecute, me, uix, nil^); 277 result := (Test >= rExecuted) or (Test in IgnoreResults); 278 end; 279 280 procedure GetUnitInfo(Loc: integer; var uix: integer; 281 var UnitInfo: TUnitInfo); 282 var 283 i, Cnt: integer; 284 begin 285 if MyMap[Loc] and fOwned <> 0 then 286 begin 287 Server(sGetDefender, me, Loc, uix); 288 Cnt := 0; 289 for i := 0 to MyRO.nUn - 1 do 290 if MyUn[i].Loc = Loc then 291 inc(Cnt); 292 MakeUnitInfo(me, MyUn[uix], UnitInfo); 293 if Cnt > 1 then 294 UnitInfo.Flags := UnitInfo.Flags or unMulti; 295 end 296 else 297 begin 298 uix := MyRO.nEnemyUn - 1; 299 while (uix >= 0) and (MyRO.EnemyUn[uix].Loc <> Loc) do 300 dec(uix); 301 UnitInfo := MyRO.EnemyUn[uix]; 302 end 303 end; { GetUnitInfo } 304 305 procedure GetCityInfo(Loc: integer; var cix: integer; 306 var CityInfo: TCityInfo); 307 begin 308 if MyMap[Loc] and fOwned <> 0 then 309 begin 310 CityInfo.Loc := Loc; 311 cix := MyRO.nCity - 1; 312 while (cix >= 0) and (MyCity[cix].Loc <> Loc) do 313 dec(cix); 314 with CityInfo do 315 begin 316 Owner := me; 317 ID := MyCity[cix].ID; 318 size := MyCity[cix].size; 319 Flags := 0; 320 if MyCity[cix].Built[imPalace] > 0 then 321 inc(Flags, ciCapital); 322 if (MyCity[cix].Built[imWalls] > 0) or 323 (MyMap[MyCity[cix].Loc] and fGrWall <> 0) then 324 inc(Flags, ciWalled); 325 if MyCity[cix].Built[imCoastalFort] > 0 then 326 inc(Flags, ciCoastalFort); 327 if MyCity[cix].Built[imMissileBat] > 0 then 328 inc(Flags, ciMissileBat); 329 if MyCity[cix].Built[imBunker] > 0 then 330 inc(Flags, ciBunker); 331 if MyCity[cix].Built[imSpacePort] > 0 then 332 inc(Flags, ciSpacePort); 333 end 334 end 335 else 336 begin 337 cix := MyRO.nEnemyCity - 1; 338 while (cix >= 0) and (MyRO.EnemyCity[cix].Loc <> Loc) do 339 dec(cix); 340 CityInfo := MyRO.EnemyCity[cix]; 341 end 342 end; 343 344 function UnitExhausted(uix: integer): boolean; 345 // check if another move of this unit is still possible 346 var 347 dx, dy: integer; 348 begin 349 result := true; 350 if (MyUn[uix].Movement > 0) or 351 (MyRO.Wonder[woShinkansen].EffectiveOwner = me) then 352 if (MyUn[uix].Movement >= 100) or 353 ((MyModel[MyUn[uix].mix].Kind = mkCaravan) and 354 (MyMap[MyUn[uix].Loc] and fCity <> 0)) then 355 result := false 356 else 357 for dx := -2 to 2 do 358 for dy := -2 to 2 do 359 if abs(dx) + abs(dy) = 2 then 360 if Server(sMoveUnit - sExecute + dx and 7 shl 4 + dy and 7 shl 7, 361 me, uix, nil^) >= rExecuted then 362 result := false; 363 end; 364 365 function ModelHash(const ModelInfo: TModelInfo): integer; 366 var 367 i, FeatureCode, Hash1, Hash2, Hash2r, d: cardinal; 368 begin 369 with ModelInfo do 370 if Kind > mkEnemyDeveloped then 371 result := integer($C0000000 + Speed div 50 + Kind shl 8) 372 else 373 begin 374 FeatureCode := 0; 375 for i := mcFirstNonCap to nFeature - 1 do 376 if 1 shl Domain and Feature[i].Domains <> 0 then 377 begin 378 FeatureCode := FeatureCode * 2; 379 if 1 shl (i - mcFirstNonCap) <> 0 then 380 inc(FeatureCode); 381 end; 382 case Domain of 383 dGround: 384 begin 385 assert(FeatureCode < 1 shl 8); 386 assert(Attack < 5113); 387 assert(Defense < 2273); 388 assert(Cost < 1611); 389 Hash1 := (Attack * 2273 + Defense) * 9 + (Speed - 150) div 50; 390 Hash2 := FeatureCode * 1611 + Cost; 391 end; 392 dSea: 393 begin 394 assert(FeatureCode < 1 shl 9); 395 assert(Attack < 12193); 396 assert(Defense < 6097); 397 assert(Cost < 4381); 398 Hash1 := ((Attack * 6097 + Defense) * 5 + (Speed - 350) 399 div 100) * 2; 400 if Weight >= 6 then 401 inc(Hash1); 402 Hash2 := ((TTrans * 17 + ATrans_Fuel) shl 9 + FeatureCode) * 403 4381 + Cost; 404 end; 405 dAir: 406 begin 407 assert(FeatureCode < 1 shl 5); 408 assert(Attack < 2407); 409 assert(Defense < 1605); 410 assert(Bombs < 4813); 411 assert(Cost < 2089); 412 Hash1 := (Attack * 1605 + Defense) shl 5 + FeatureCode; 413 Hash2 := ((Bombs * 7 + ATrans_Fuel) * 4 + TTrans) * 2089 + Cost; 414 end; 415 end; 416 Hash2r := 0; 417 for i := 0 to 7 do 418 begin 419 Hash2r := Hash2r * 13; 420 d := Hash2 div 13; 421 inc(Hash2r, Hash2 - d * 13); 422 Hash2 := d 423 end; 424 result := integer(Domain shl 30 + Hash1 xor Hash2r) 425 end 426 end; 427 428 function ProcessEnhancement(uix: integer; 429 const Jobs: TEnhancementJobs): integer; 423 end; 424 425 function ProcessEnhancement(uix: integer; const Jobs: TEnhancementJobs): integer; 430 426 { return values: 431 427 eJobDone - all applicable jobs done 432 428 eOK - enhancement not complete 433 429 eDied - job done and died (thurst) } 434 var 435 stage, NextJob, Tile: integer; 436 Done: Set of jNone .. jPoll; 437 begin 438 Done := []; 439 Tile := MyMap[MyUn[uix].Loc]; 440 if Tile and fRoad <> 0 then 441 include(Done, jRoad); 442 if Tile and fRR <> 0 then 443 include(Done, jRR); 444 if (Tile and fTerImp = tiIrrigation) or (Tile and fTerImp = tiFarm) then 445 include(Done, jIrr); 446 if Tile and fTerImp = tiFarm then 447 include(Done, jFarm); 448 if Tile and fTerImp = tiMine then 449 include(Done, jMine); 450 if Tile and fPoll = 0 then 451 include(Done, jPoll); 452 453 if MyUn[uix].Job = jNone then 454 result := eJobDone 455 else 456 result := eOK; 457 while (result <> eOK) and (result <> eDied) do 430 var 431 stage, NextJob, Tile: integer; 432 Done: set of jNone .. jPoll; 433 begin 434 Done := []; 435 Tile := MyMap[MyUn[uix].Loc]; 436 if Tile and fRoad <> 0 then 437 include(Done, jRoad); 438 if Tile and fRR <> 0 then 439 include(Done, jRR); 440 if (Tile and fTerImp = tiIrrigation) or (Tile and fTerImp = tiFarm) then 441 include(Done, jIrr); 442 if Tile and fTerImp = tiFarm then 443 include(Done, jFarm); 444 if Tile and fTerImp = tiMine then 445 include(Done, jMine); 446 if Tile and fPoll = 0 then 447 include(Done, jPoll); 448 449 if MyUn[uix].Job = jNone then 450 Result := eJobDone 451 else 452 Result := eOK; 453 while (Result <> eOK) and (Result <> eDied) do 454 begin 455 stage := -1; 456 repeat 457 if stage = -1 then 458 NextJob := jPoll 459 else 460 NextJob := Jobs[Tile and fTerrain, stage]; 461 if (NextJob = jNone) or not (NextJob in Done) then 462 Break; 463 Inc(stage); 464 until stage = 5; 465 if (stage = 5) or (NextJob = jNone) then 458 466 begin 459 stage := -1; 460 repeat 461 if stage = -1 then 462 NextJob := jPoll 463 else 464 NextJob := Jobs[Tile and fTerrain, stage]; 465 if (NextJob = jNone) or not(NextJob in Done) then 466 Break; 467 inc(stage); 468 until stage = 5; 469 if (stage = 5) or (NextJob = jNone) then 467 Result := eJobDone; 468 Break; 469 end; // tile enhancement complete 470 Result := Server(sStartJob + NextJob shl 4, me, uix, nil^); 471 include(Done, NextJob); 472 end; 473 end; 474 475 function AutoBuild(cix: integer; const ImpOrder: TImpOrder): boolean; 476 var 477 i, NewProject: integer; 478 begin 479 Result := False; 480 if (MyCity[cix].Project and (cpImp + cpIndex) = cpImp + imTrGoods) or 481 (MyCity[cix].Flags and chProduction <> 0) then 482 begin 483 i := 0; 484 repeat 485 while (ImpOrder[i] >= 0) and (MyCity[cix].Built[ImpOrder[i]] > 0) do 486 Inc(i); 487 if ImpOrder[i] < 0 then 488 Break; 489 assert(i < nImp); 490 NewProject := cpImp + ImpOrder[i]; 491 if Server(sSetCityProject, me, cix, NewProject) >= rExecuted then 470 492 begin 471 result := eJobDone; 493 Result := True; 494 CityOptimizer_CityChange(cix); 472 495 Break; 473 end; // tile enhancement complete 474 result := Server(sStartJob + NextJob shl 4, me, uix, nil^); 475 include(Done, NextJob) 496 end; 497 Inc(i); 498 until False; 499 end; 500 end; 501 502 procedure CalculateAdvValues; 503 var 504 i, j: integer; 505 known: array [0 .. nAdv - 1] of integer; 506 507 procedure MarkPreqs(i: integer); 508 begin 509 if known[i] = 0 then 510 begin 511 known[i] := 1; 512 if (i <> adScience) and (i <> adMassProduction) then 513 begin 514 if (AdvPreq[i, 0] >= 0) then 515 MarkPreqs(AdvPreq[i, 0]); 516 if (AdvPreq[i, 1] >= 0) then 517 MarkPreqs(AdvPreq[i, 1]); 518 end; 476 519 end; 477 520 end; 478 521 479 function AutoBuild(cix: integer; const ImpOrder: TImpOrder): boolean; 480 var 481 i, NewProject: integer; 482 begin 483 result := false; 484 if (MyCity[cix].Project and (cpImp + cpIndex) = cpImp + imTrGoods) or 485 (MyCity[cix].Flags and chProduction <> 0) then 522 begin 523 FillChar(AdvValue, SizeOf(AdvValue), 0); 524 for i := 0 to nAdv - 1 do 525 begin 526 FillChar(known, SizeOf(known), 0); 527 MarkPreqs(i); 528 for j := 0 to nAdv - 1 do 529 if known[j] > 0 then 530 Inc(AdvValue[i]); 531 if i in FutureTech then 532 Inc(AdvValue[i], 3000) 533 else if known[adMassProduction] > 0 then 534 Inc(AdvValue[i], 2000) 535 else if known[adScience] > 0 then 536 Inc(AdvValue[i], 1000); 537 end; 538 end; 539 540 procedure DebugMessage(Level: integer; Text: string); 541 begin 542 Server(sMessage, me, Level, PChar(Text)^); 543 end; 544 545 function MarkCitiesAround(Loc, cixExcept: integer): boolean; 546 // return whether a city was marked 547 var 548 cix: integer; 549 begin 550 Result := False; 551 for cix := 0 to MyRO.nCity - 1 do 552 if (cix <> cixExcept) and (MyCity[cix].Loc >= 0) and 553 (MyCity[cix].Flags and chCaptured = 0) and 554 (Distance(MyCity[cix].Loc, Loc) <= 5) then 486 555 begin 487 i := 0; 488 repeat 489 while (ImpOrder[i] >= 0) and (MyCity[cix].Built[ImpOrder[i]] > 0) do 490 inc(i); 491 if ImpOrder[i] < 0 then 492 Break; 493 assert(i < nImp); 494 NewProject := cpImp + ImpOrder[i]; 495 if Server(sSetCityProject, me, cix, NewProject) >= rExecuted then 556 CityNeedsOptimize[cix] := True; 557 Result := True; 558 end; 559 end; 560 561 procedure OptimizeCities(CheckOnly: boolean); 562 var 563 cix, fix, dx, dy, Loc1, OptiType: integer; 564 Done: boolean; 565 Advice: TCityTileAdviceData; 566 begin 567 repeat 568 Done := True; 569 for cix := 0 to MyRO.nCity - 1 do 570 if CityNeedsOptimize[cix] then 571 begin 572 OptiType := (MyCity[cix].Status shr 4) and $0F; 573 if OptiType <> 0 then 496 574 begin 497 result := true; 498 CityOptimizer_CityChange(cix); 499 Break; 575 Advice.ResourceWeights := OfferedResourceWeights[OptiType]; 576 Server(sGetCityTileAdvice, me, cix, Advice); 577 if Advice.Tiles <> MyCity[cix].Tiles then 578 if CheckOnly then 579 begin 580 // TODO: What is this assert for? 581 // Need to optimize city tiles but CheckOnly true? 582 //assert(false) 583 end 584 else 585 begin 586 for fix := 1 to 26 do 587 if MyCity[cix].Tiles and not Advice.Tiles and 588 (1 shl fix) <> 0 then 589 begin // tile no longer used by this city -- check using it by another 590 dy := fix shr 2 - 3; 591 dx := fix and 3 shl 1 - 3 + (dy + 3) and 1; 592 Loc1 := dLoc(MyCity[cix].Loc, dx, dy); 593 if MarkCitiesAround(Loc1, cix) then 594 Done := False; 595 end; 596 Server(sSetCityTiles, me, cix, Advice.Tiles); 597 end; 500 598 end; 501 inc(i); 502 until false end end; 503 504 procedure CalculateAdvValues; 505 var 506 i, j: integer; 507 known: array [0 .. nAdv - 1] of integer; 508 509 procedure MarkPreqs(i: integer); 510 begin 511 if known[i] = 0 then 512 begin 513 known[i] := 1; 514 if (i <> adScience) and (i <> adMassProduction) then 515 begin 516 if (AdvPreq[i, 0] >= 0) then 517 MarkPreqs(AdvPreq[i, 0]); 518 if (AdvPreq[i, 1] >= 0) then 519 MarkPreqs(AdvPreq[i, 1]); 520 end 521 end 522 end; 523 599 CityNeedsOptimize[cix] := False; 600 end; 601 until Done; 602 end; 603 604 procedure CityOptimizer_BeginOfTurn; 605 var 606 cix: integer; 607 begin 608 FillChar(CityNeedsOptimize, MyRO.nCity - 1, 0); // false 609 if MyRO.Government <> gAnarchy then 610 begin 611 for cix := 0 to MyRO.nCity - 1 do 612 if (MyCity[cix].Loc >= 0) and (MyCity[cix].Flags and chCaptured = 0) 613 then 614 CityNeedsOptimize[cix] := True; 615 OptimizeCities(False); // optimize all cities 616 end; 617 end; 618 619 procedure CityOptimizer_CityChange(cix: integer); 620 begin 621 if (MyRO.Government <> gAnarchy) and (MyCity[cix].Flags and 622 chCaptured = 0) then 623 begin 624 CityNeedsOptimize[cix] := True; 625 OptimizeCities(False); 626 end; 627 end; 628 629 procedure CityOptimizer_TileBecomesAvailable(Loc: integer); 630 begin 631 if (MyRO.Government <> gAnarchy) and MarkCitiesAround(Loc, -1) then 632 OptimizeCities(False); 633 end; 634 635 procedure CityOptimizer_ReleaseCityTiles(cix, ReleasedTiles: integer); 636 var 637 fix, dx, dy, Loc1: integer; 638 Done: boolean; 639 begin 640 if (MyRO.Government <> gAnarchy) and (ReleasedTiles <> 0) then 641 begin 642 Done := True; 643 for fix := 1 to 26 do 644 if ReleasedTiles and (1 shl fix) <> 0 then 524 645 begin 525 FillChar(AdvValue, SizeOf(AdvValue), 0); 526 for i := 0 to nAdv - 1 do 527 begin 528 FillChar(known, SizeOf(known), 0); 529 MarkPreqs(i); 530 for j := 0 to nAdv - 1 do 531 if known[j] > 0 then 532 inc(AdvValue[i]); 533 if i in FutureTech then 534 inc(AdvValue[i], 3000) 535 else if known[adMassProduction] > 0 then 536 inc(AdvValue[i], 2000) 537 else if known[adScience] > 0 then 538 inc(AdvValue[i], 1000) 539 end; 646 dy := fix shr 2 - 3; 647 dx := fix and 3 shl 1 - 3 + (dy + 3) and 1; 648 Loc1 := dLoc(MyCity[cix].Loc, dx, dy); 649 if MarkCitiesAround(Loc1, cix) then 650 Done := False; 540 651 end; 541 542 procedure DebugMessage(Level: integer; Text: string); 543 begin 544 Server(sMessage, me, Level, pchar(Text)^) 545 end; 546 547 function MarkCitiesAround(Loc, cixExcept: integer): boolean; 548 // return whether a city was marked 549 var 550 cix: integer; 551 begin 552 result := false; 553 for cix := 0 to MyRO.nCity - 1 do 554 if (cix <> cixExcept) and (MyCity[cix].Loc >= 0) and 555 (MyCity[cix].Flags and chCaptured = 0) and 556 (Distance(MyCity[cix].Loc, Loc) <= 5) then 557 begin 558 CityNeedsOptimize[cix] := true; 559 result := true; 560 end 561 end; 562 563 procedure OptimizeCities(CheckOnly: boolean); 564 var 565 cix, fix, dx, dy, Loc1, OptiType: integer; 566 Done: boolean; 567 Advice: TCityTileAdviceData; 568 begin 569 repeat 570 Done := true; 571 for cix := 0 to MyRO.nCity - 1 do 572 if CityNeedsOptimize[cix] then begin 573 OptiType := (MyCity[cix].Status shr 4) and $0F; 574 if OptiType <> 0 then begin 575 Advice.ResourceWeights := OfferedResourceWeights[OptiType]; 576 Server(sGetCityTileAdvice, me, cix, Advice); 577 if Advice.Tiles <> MyCity[cix].Tiles then 578 if CheckOnly then begin 579 // TODO: What is this assert for? 580 // Need to optimize city tiles but CheckOnly true? 581 //assert(false) 582 end else begin 583 for fix := 1 to 26 do 584 if MyCity[cix].Tiles and not Advice.Tiles and 585 (1 shl fix) <> 0 then 586 begin // tile no longer used by this city -- check using it by another 587 dy := fix shr 2 - 3; 588 dx := fix and 3 shl 1 - 3 + (dy + 3) and 1; 589 Loc1 := dLoc(MyCity[cix].Loc, dx, dy); 590 if MarkCitiesAround(Loc1, cix) then 591 Done := false; 592 end; 593 Server(sSetCityTiles, me, cix, Advice.Tiles); 594 end; 595 end; 596 CityNeedsOptimize[cix] := false; 597 end; 598 until Done; 599 end; 600 601 procedure CityOptimizer_BeginOfTurn; 602 var 603 cix: integer; 604 begin 605 FillChar(CityNeedsOptimize, MyRO.nCity - 1, 0); // false 606 if MyRO.Government <> gAnarchy then 607 begin 608 for cix := 0 to MyRO.nCity - 1 do 609 if (MyCity[cix].Loc >= 0) and (MyCity[cix].Flags and chCaptured = 0) 610 then 611 CityNeedsOptimize[cix] := true; 612 OptimizeCities(false); // optimize all cities 613 end 614 end; 615 616 procedure CityOptimizer_CityChange(cix: integer); 617 begin 618 if (MyRO.Government <> gAnarchy) and 619 (MyCity[cix].Flags and chCaptured = 0) then 620 begin 621 CityNeedsOptimize[cix] := true; 622 OptimizeCities(false); 623 end 624 end; 625 626 procedure CityOptimizer_TileBecomesAvailable(Loc: integer); 627 begin 628 if (MyRO.Government <> gAnarchy) and MarkCitiesAround(Loc, -1) then 629 OptimizeCities(false); 630 end; 631 632 procedure CityOptimizer_ReleaseCityTiles(cix, ReleasedTiles: integer); 633 var 634 fix, dx, dy, Loc1: integer; 635 Done: boolean; 636 begin 637 if (MyRO.Government <> gAnarchy) and (ReleasedTiles <> 0) then 638 begin 639 Done := true; 640 for fix := 1 to 26 do 641 if ReleasedTiles and (1 shl fix) <> 0 then 642 begin 643 dy := fix shr 2 - 3; 644 dx := fix and 3 shl 1 - 3 + (dy + 3) and 1; 645 Loc1 := dLoc(MyCity[cix].Loc, dx, dy); 646 if MarkCitiesAround(Loc1, cix) then 647 Done := false; 648 end; 649 if not Done then 650 OptimizeCities(false); 651 end 652 end; 653 654 procedure CityOptimizer_BeforeRemoveUnit(uix: integer); 655 var 656 uix1: integer; 657 begin 658 if MyRO.Government <> gAnarchy then 659 begin 660 if MyUn[uix].Home >= 0 then 661 CityNeedsOptimize[MyUn[uix].Home] := true; 662 663 // transported units are also removed 664 for uix1 := 0 to MyRO.nUn - 1 do 665 if (MyUn[uix1].Loc >= 0) and (MyUn[uix1].Master = uix) and 666 (MyUn[uix1].Home >= 0) then 667 CityNeedsOptimize[MyUn[uix1].Home] := true; 668 end 669 end; 670 671 procedure CityOptimizer_AfterRemoveUnit; 672 begin 673 if MyRO.Government <> gAnarchy then 674 OptimizeCities(false); 675 end; 676 677 procedure CityOptimizer_EndOfTurn; 678 // all cities should already be optimized here -- only check this 679 var 680 cix: integer; 681 begin 652 if not Done then 653 OptimizeCities(False); 654 end; 655 end; 656 657 procedure CityOptimizer_BeforeRemoveUnit(uix: integer); 658 var 659 uix1: integer; 660 begin 661 if MyRO.Government <> gAnarchy then 662 begin 663 if MyUn[uix].Home >= 0 then 664 CityNeedsOptimize[MyUn[uix].Home] := True; 665 666 // transported units are also removed 667 for uix1 := 0 to MyRO.nUn - 1 do 668 if (MyUn[uix1].Loc >= 0) and (MyUn[uix1].Master = uix) and 669 (MyUn[uix1].Home >= 0) then 670 CityNeedsOptimize[MyUn[uix1].Home] := True; 671 end; 672 end; 673 674 procedure CityOptimizer_AfterRemoveUnit; 675 begin 676 if MyRO.Government <> gAnarchy then 677 OptimizeCities(False); 678 end; 679 680 procedure CityOptimizer_EndOfTurn; 681 // all cities should already be optimized here -- only check this 682 var 683 cix: integer; 684 begin 682 685 {$IFOPT O-} 683 684 685 686 687 688 689 CityNeedsOptimize[cix] := true;690 OptimizeCities(true); // check all cities691 686 if MyRO.Government <> gAnarchy then 687 begin 688 FillChar(CityNeedsOptimize, MyRO.nCity - 1, 0); // false 689 for cix := 0 to MyRO.nCity - 1 do 690 if (MyCity[cix].Loc >= 0) and (MyCity[cix].Flags and chCaptured = 0) 691 then 692 CityNeedsOptimize[cix] := True; 693 OptimizeCities(True); // check all cities 694 end; 692 695 {$ENDIF} 693 696 end; 694 697 695 698 initialization 696 699 697 Assert(nImp < 128);698 CalculateAdvValues;700 Assert(nImp < 128); 701 CalculateAdvValues; 699 702 700 703 end. -
branches/highdpi/LocalPlayer/Draft.pas
r210 r303 92 92 Template := TDpiBitmap.Create; 93 93 Template.PixelFormat := pf24bit; 94 LoadGraphicFile(Template, GetGraphicsDir + DirectorySeparator + 'MiliRes.png', gfNoGamma); 94 LoadGraphicFile(Template, GetGraphicsDir + DirectorySeparator + 'MiliRes.png', 95 [gfNoGamma]); 95 96 end; 96 97 -
branches/highdpi/LocalPlayer/Enhance.pas
r244 r303 366 366 Shift: TShiftState); 367 367 begin 368 if Key = VK_ESCAPE then 369 Close 370 else if Key = VK_F1 then 368 if Key = VK_F1 then 371 369 HelpDlg.ShowNewContent(FWindowMode or wmPersistent, hkText, 372 370 HelpDlg.TextIndex('MACRO')) -
branches/highdpi/LocalPlayer/Help.pas
r265 r303 127 127 128 128 uses 129 Directories, ClientTools, Term, Tribes, Inp, Messg, UPixelPointer, Global; 129 Directories, ClientTools, Term, Tribes, Inp, Messg, UPixelPointer, Global, 130 UKeyBindings; 130 131 131 132 {$R *.lfm} … … 207 208 destructor THyperText.Destroy; 208 209 begin 209 inherited Destroy;210 inherited; 210 211 end; 211 212 … … 1242 1243 until FindNext(sr) <> 0; 1243 1244 FindClose(sr); 1244 Plus.Free;1245 FreeAndNil(Plus); 1245 1246 1246 1247 List.Sort; … … 1259 1260 MainText.AddLine(s); 1260 1261 end; 1261 List.Free;1262 FreeAndNil(List); 1262 1263 end; 1263 1264 … … 1277 1278 MainText.AddLine(s); 1278 1279 end; 1279 List.Free;1280 FreeAndNil(List); 1280 1281 end; 1281 1282 … … 1439 1440 AppendList(List); 1440 1441 end; 1441 List.Free;1442 FreeAndNil(List); 1442 1443 end 1443 1444 else // single advance … … 1538 1539 List.Sort; 1539 1540 AppendList(List); 1540 List.Free;1541 FreeAndNil(List); 1541 1542 end 1542 1543 else if no = 201 then … … 1827 1828 AppendList(List); 1828 1829 end; 1829 List.Free;1830 FreeAndNil(List); 1830 1831 end 1831 1832 else … … 1988 1989 OffscreenPaint; 1989 1990 Invalidate; 1990 HistItem.Free;1991 FreeAndNil(HistItem); 1991 1992 end; 1992 1993 end; … … 2016 2017 Shift: TShiftState); 2017 2018 begin 2018 if Key = VK_F1then // my key2019 if KeyToShortCut(Key, Shift) = BHelp.ShortCut then // my key 2019 2020 else 2020 inherited 2021 inherited; 2021 2022 end; 2022 2023 -
branches/highdpi/LocalPlayer/IsoEngine.pas
r265 r303 133 133 OnInitEnemyModel := InitEnemyModelHandler; 134 134 if NoMap <> nil then 135 NoMap.Free;135 FreeAndNil(NoMap); 136 136 NoMap := TIsoMap.Create; 137 137 end; … … 168 168 { prepare dithered ground tiles } 169 169 if LandPatch <> nil then 170 LandPatch.Free;170 FreeAndNil(LandPatch); 171 171 LandPatch := TDpiBitmap.Create; 172 172 LandPatch.PixelFormat := pf24bit; … … 175 175 LandPatch.Canvas.FillRect(0, 0, LandPatch.Width, LandPatch.Height); 176 176 if OceanPatch <> nil then 177 OceanPatch.Free;177 FreeAndNil(OceanPatch); 178 178 OceanPatch := TDpiBitmap.Create; 179 179 OceanPatch.PixelFormat := pf24bit; … … 363 363 DitherMask.Canvas, 0, 0, SRCAND); 364 364 365 LandMore.Free;366 OceanMore.Free;367 DitherMask.Free;365 FreeAndNil(LandMore); 366 FreeAndNil(OceanMore); 367 FreeAndNil(DitherMask); 368 368 369 369 // reduce size of terrain icons … … 417 417 end; 418 418 Mask24.EndUpdate; 419 Mask24.Free;419 FreeAndNil(Mask24); 420 420 421 421 if Borders <> nil then 422 Borders.Free;422 FreeAndNil(Borders); 423 423 Borders := TDpiBitmap.Create; 424 424 Borders.PixelFormat := pf24bit; … … 702 702 end; 703 703 Textout(xShield + 2, yShield - 1, LabelTextColor, s); 704 end 704 end; 705 705 end; { PaintCity } 706 706 … … 1078 1078 if not(FoW and (Tile and fObserved = 0)) then 1079 1079 PaintBorder; 1080 1080 1081 if (Loc >= 0) and (Loc < G.lx * G.ly) and (Loc = FAdviceLoc) then 1081 1082 TSprite(x, y, spPlain); … … 1287 1288 i: integer; 1288 1289 begin 1289 FOutput.Canvas.pen.Color := $000000; // $FF shl (8*random(3));1290 1290 FOutput.Canvas.pen.Color := $000000; // $FF shl (8*random(3)); 1291 1291 for i := 0 to nx div 2 do -
branches/highdpi/LocalPlayer/MessgEx.pas
r253 r303 218 218 end 219 219 else 220 result := inherited ShowModal;220 result := inherited; 221 221 end; 222 222 -
branches/highdpi/LocalPlayer/NatStat.pas
r244 r303 93 93 Template := TDpiBitmap.Create; 94 94 Template.PixelFormat := pf24bit; 95 LoadGraphicFile(Template, GetGraphicsDir + DirectorySeparator + 'Nation.png', gfNoGamma); 95 LoadGraphicFile(Template, GetGraphicsDir + DirectorySeparator + 'Nation.png', 96 [gfNoGamma]); 96 97 end; 97 98 98 99 procedure TNatStatDlg.FormDestroy(Sender: TObject); 99 100 begin 100 ReportText.Free;101 FreeAndNil(ReportText); 101 102 FreeMem(SelfReport); 102 Template.Free;103 Back.Free;103 FreeAndNil(Template); 104 FreeAndNil(Back); 104 105 end; 105 106 -
branches/highdpi/LocalPlayer/Select.pas
r273 r303 1605 1605 CaptionRight := CloseBtn.Left; 1606 1606 { TODO: 1607 SetWindowPos(sb.ScrollBar.Handle, 0, SideFrame + InnerWidth - GetSystemMetrics(SM_CXVSCROLL),1607 SetWindowPos(sb.ScrollBar.Handle, 0, SideFrame + InnerWidth - DpiGetSystemMetrics(SM_CXVSCROLL), 1608 1608 TitleHeight, DpiGetSystemMetrics(SM_CXVSCROLL), LineDistance * DispLines + 48, 1609 1609 SWP_NOZORDER or SWP_NOREDRAW); -
branches/highdpi/LocalPlayer/TechTree.pas
r246 r303 23 23 Shift: TShiftState; X, Y: Integer); 24 24 procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); 25 procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);26 25 procedure CloseBtnClick(Sender: TObject); 27 26 private … … 133 132 NewHeight: Integer; 134 133 const 135 TransparentColor = $7F007F;134 TransparentColor: Cardinal = $7F007F; 136 135 begin 137 136 if Image = nil then begin 138 137 Image := TDpiBitmap.Create; 139 138 Image.PixelFormat := pf24bit; 140 LoadGraphicFile(Image, HomeDir + 'Help' + DirectorySeparator + 'AdvTree.png', gfNoGamma); 139 LoadGraphicFile(Image, HomeDir + 'Help' + DirectorySeparator + 'AdvTree.png', 140 [gfNoGamma]); 141 141 142 142 with Image.Canvas do begin … … 228 228 end; 229 229 230 procedure TTechTreeDlg.FormKeyDown(Sender: TObject; var Key: Word;231 Shift: TShiftState);232 begin233 if Key = VK_ESCAPE then234 Close;235 end;236 237 230 procedure TTechTreeDlg.CloseBtnClick(Sender: TObject); 238 231 begin -
branches/highdpi/LocalPlayer/Term.pas
r265 r303 235 235 Closable, RepaintOnResize, Tracking, TurnComplete, Edited, GoOnPhase, 236 236 HaveStrategyAdvice, FirstMovieTurn: boolean; 237 PrevWindowState: TWindowState; 238 CurrentWindowState: TWindowState; 237 239 function ChooseUnusedTribe: integer; 238 240 procedure GetTribeList; … … 283 285 procedure OnEOT(var Msg: TMessage); message WM_EOT; 284 286 procedure SoundPreload(Check: integer); 287 procedure UpdateKeyShortcuts; 288 procedure SetFullScreen(Active: Boolean); 285 289 public 286 290 UsedOffscreenWidth, UsedOffscreenHeight: integer; … … 307 311 FileName: ShortString; 308 312 end; 309 310 313 TCityNameInfo = record 311 314 ID: integer; 312 NewName: ShortString end; 313 TModelNameInfo = record mix: integer; 314 NewName: ShortString end; 315 TPriceSet = Set of $00 .. $FF; 315 NewName: ShortString; 316 end; 317 TModelNameInfo = record 318 mix: integer; 319 NewName: ShortString; 320 end; 321 TPriceSet = Set of $00 .. $FF; 316 322 317 323 const … … 481 487 Directories, IsoEngine, CityScreen, Draft, MessgEx, Select, CityType, Help, 482 488 UnitStat, Log, Diagram, NatStat, Wonders, Enhance, Nego, UPixelPointer, Sound, 483 Battle, Rates, TechTree, Registry, Global ;489 Battle, Rates, TechTree, Registry, Global, UKeyBindings; 484 490 485 491 {$R *.lfm} … … 531 537 SmallScreen, GameOK, MapValid, skipped, idle: boolean; 532 538 533 SaveOption: array [0 ..nSaveOption - 1] of integer;534 MiniColors: array [0 .. $1f, 0 ..1] of TColor;539 SaveOption: array [0..nSaveOption - 1] of integer; 540 MiniColors: array [0..11, 0..1] of TColor; 535 541 MainMap: TIsoMap; 536 542 CurrentMoveInfo: record AfterMovePaintRadius, AfterAttackExpeller: integer; … … 551 557 procedure InitSmallImp; 552 558 const 553 cut = 4;559 Cut = 4; 554 560 Sharpen = 80; 555 561 type … … 742 748 ChooseModelPicture(Owner, mix, ModelCode(MyRO.EnemyModel[emix]), 743 749 ModelHash(MyRO.EnemyModel[emix]), MyRO.Turn, false, true); 744 result := true 750 result := true; 745 751 end; 746 752 … … 786 792 function CreateTribe(p: integer; FileName: string; Original: boolean): boolean; 787 793 begin 788 if not FileExists(LocalizedFilePath('Tribes' + DirectorySeparator + FileName + 789 '.tribe.txt')) then 790 begin 791 result := false; 792 exit 794 FileName := LocalizedFilePath('Tribes' + DirectorySeparator + FileName + 795 CevoTribeExt); 796 if not FileExists(FileName) then 797 begin 798 Result := False; 799 Exit; 793 800 end; 794 801 … … 879 886 MyModel[mix].Status := MyModel[mix].Status or msObsolete; 880 887 end; 881 inc(MyData.ToldModels) 888 inc(MyData.ToldModels); 882 889 end; 883 890 end; … … 1123 1130 if UnitStatDlg.Visible then 1124 1131 UnitStatDlg.Close; 1125 end 1126 end 1132 end; 1133 end; 1127 1134 end; 1128 1135 … … 1151 1158 if UnitStatDlg.Visible then 1152 1159 UnitStatDlg.Close; 1153 end 1154 end 1160 end; 1161 end; 1155 1162 end; 1156 1163 … … 1175 1182 UnFocus := -1; 1176 1183 PaintLoc(Loc0); 1177 end 1184 end; 1178 1185 end; 1179 1186 UnFocus := uix; … … 1220 1227 MovieSpeed3Btn.Visible := false; 1221 1228 MovieSpeed4Btn.Visible := false; 1222 end 1229 end; 1223 1230 end; 1224 1231 … … 1248 1255 if AILogo[p] <> nil then 1249 1256 begin 1250 AILogo[p].free; 1251 AILogo[p] := nil 1252 end 1257 FreeAndNil(AILogo[p]); 1258 end; 1253 1259 end 1254 1260 else … … 1256 1262 if AILogo[p] = nil then 1257 1263 AILogo[p] := TDpiBitmap.Create; 1258 if not LoadGraphicFile(AILogo[p], HomeDir + Name + '.png', gfNoError) then 1259 begin 1260 AILogo[p].free; 1261 AILogo[p] := nil 1262 end 1263 end 1264 if not LoadGraphicFile(AILogo[p], HomeDir + Name + '.png', [gfNoError]) then 1265 begin 1266 FreeAndNil(AILogo[p]); 1267 end; 1268 end; 1264 1269 end; 1265 1270 … … 1296 1301 MapValid := false; 1297 1302 PaintAllMaps; 1298 end 1299 end 1303 end; 1304 end; 1300 1305 end; 1301 1306 … … 1415 1420 begin 1416 1421 UnusedTribeFiles.Clear; 1417 ok := FindFirst(LocalizedFilePath('Tribes') + DirectorySeparator + '* .tribe.txt',1422 ok := FindFirst(LocalizedFilePath('Tribes') + DirectorySeparator + '*' + CevoTribeExt, 1418 1423 faArchive + faReadOnly, SearchRec) = 0; 1419 1424 if not ok then 1420 1425 begin 1421 1426 FindClose(SearchRec); 1422 ok := FindFirst(LocalizedFilePath('Tribes' + DirectorySeparator + '* .tribe.txt'),1427 ok := FindFirst(LocalizedFilePath('Tribes' + DirectorySeparator + '*' + CevoTribeExt), 1423 1428 faArchive + faReadOnly, SearchRec) = 0; 1424 1429 end; 1425 1430 if ok then 1426 1431 repeat 1427 SearchRec.Name := Copy(SearchRec.Name, 1, Length(SearchRec.Name) - 10);1432 SearchRec.Name := Copy(SearchRec.Name, 1, Length(SearchRec.Name) - Length(CevoTribeExt)); 1428 1433 if GetTribeInfo(SearchRec.Name, Name, Color) then 1429 1434 UnusedTribeFiles.AddObject(SearchRec.Name, TObject(Color)); … … 1434 1439 function TMainScreen.ChooseUnusedTribe: integer; 1435 1440 var 1436 i, j, ColorDistance, BestColorDistance, TestColorDistance, 1437 CountBest: integer; 1441 i: Integer; 1442 j: Integer; 1443 ColorDistance: Integer; 1444 BestColorDistance: Integer; 1445 TestColorDistance: Integer; 1446 CountBest: Integer; 1438 1447 begin 1439 1448 assert(UnusedTribeFiles.Count > 0); … … 1465 1474 if DelphiRandom(CountBest) = 0 then 1466 1475 result := j 1467 end 1476 end; 1468 1477 end; 1469 1478 end; … … 1523 1532 IconKind := mikShip; 1524 1533 IconIndex := Ship2Owner; 1525 end 1534 end; 1526 1535 end; 1527 1536 … … 1536 1545 MostCost := TestCost; 1537 1546 IconIndex := imShipComp + i 1538 end 1547 end; 1539 1548 end; 1540 1549 end; … … 1619 1628 sb := TPVScrollbar.Create(Self); 1620 1629 sb.OnUpdate := ScrollBarUpdate; 1621 end; { InitModule }1630 end; 1622 1631 1623 1632 procedure TMainScreen.InitTurn(NewPlayer: integer); … … 2237 2246 Flags and CityRepMask); 2238 2247 UpdatePanel := true; 2239 end 2248 end; 2240 2249 end 2241 2250 else { if mRepList.Checked then } … … 2243 2252 if Flags and CityRepMask <> 0 then 2244 2253 ShowCityList := true 2245 end 2246 end 2254 end; 2255 end; 2247 2256 end; { city loop } 2248 2257 end; // ClientMode=cTurn … … 2263 2272 Play('REVOLUTION'); 2264 2273 Server(sRevolution, me, 0, nil^); 2265 end 2274 end; 2266 2275 end; 2267 2276 end; // ClientMode=cTurn … … 2382 2391 else 2383 2392 Status := Status and not usWaiting; 2384 end 2393 end; 2385 2394 end; 2386 2395 end; // ClientMode=cTurn … … 2480 2489 opAllModel: 2481 2490 s := s + 'All models'; 2482 end 2491 end; 2483 2492 end; 2484 2493 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(s)); … … 2488 2497 s := s + '--- ACCEPTED! ---'; 2489 2498 LogDlg.Add(NewPlayer, G.RO[0].Turn, pchar(s)); 2490 end 2499 end; 2491 2500 end; 2492 2501 … … 2502 2511 cReleaseModule: 2503 2512 begin 2504 SmallImp.free;2505 UnusedTribeFiles.free;2506 TribeNames.free;2507 MainMap.free;2513 FreeAndNil(SmallImp); 2514 FreeAndNil(UnusedTribeFiles); 2515 FreeAndNil(TribeNames); 2516 FreeAndNil(MainMap); 2508 2517 IsoEngine.Done; 2509 2518 // AdvisorDlg.DeInit; … … 2703 2712 for p1 := 0 to nPl - 1 do 2704 2713 if Tribe[p1] <> nil then 2705 Tribe[p1].free;2714 FreeAndNil(Tribe[p1]); 2706 2715 Tribes.Done; 2707 2716 RepaintOnResize := false; … … 2844 2853 // this break will ensure speed of fast forward does not depend on cpu speed 2845 2854 DpiApplication.ProcessMessages; 2846 end 2855 end; 2847 2856 end; 2848 2857 … … 2923 2932 DipCall(scReject); 2924 2933 EndNego 2925 end 2926 end 2934 end; 2935 end; 2927 2936 end; 2928 2937 end; … … 3410 3419 i, j: integer; 3411 3420 begin 3421 KeyBindings.LoadFromRegistry(HKEY_CURRENT_USER, AppRegistryKey + '\KeyBindings'); 3422 UpdateKeyShortcuts; 3423 3412 3424 MainFormKeyDown := FormKeyDown; 3413 3425 BaseWin.CreateOffscreen(Offscreen); … … 3512 3524 I: Integer; 3513 3525 begin 3526 KeyBindings.SaveToRegistry(HKEY_CURRENT_USER, AppRegistryKey + '\KeyBindings'); 3514 3527 MainFormKeyDown := nil; 3515 3528 FreeAndNil(sb); … … 3615 3628 RectInvalidate(0, TopBarHeight, ClientWidth, TopBarHeight + MapHeight); 3616 3629 MapValid := false; 3617 PaintAll 3618 end 3630 PaintAll; 3631 end; 3619 3632 end; 3620 3633 … … 3623 3636 CanClose := Closable; 3624 3637 if not Closable and idle and (me = 0) and (ClientMode < scContact) then 3625 MenuClick(mResign) 3638 MenuClick(mResign); 3626 3639 end; 3627 3640 … … 4061 4074 var 4062 4075 uix, cix, x, y, Loc, i, hw, xm, cm, cmPolOcean, cmPolNone: integer; 4063 PrevMiniPixel, MiniPixel: TPixelPointer; 4076 PrevMiniPixel: TPixelPointer; 4077 MiniPixel: TPixelPointer; 4078 TerrainTile: Cardinal; 4064 4079 begin 4065 4080 cmPolOcean := GrExt[HGrSystem].Data.Canvas.Pixels[101, 67]; … … 4085 4100 ScaleToNative(G.lx) * 5) mod (ScaleToNative(G.lx) * 2); 4086 4101 MiniPixel.SetXY(xm, y); 4087 cm := MiniColors[MyMap[Loc] and fTerrain, i]; 4102 TerrainTile := MyMap[Loc] and fTerrain; 4103 if TerrainTile > 11 then TerrainTile := 0; 4104 cm := MiniColors[TerrainTile, i]; 4088 4105 if ClientMode = cEditMap then 4089 4106 begin … … 6422 6439 MapValid := false; 6423 6440 PaintAllMaps; 6424 end 6441 end; 6442 end; 6443 6444 procedure TMainScreen.UpdateKeyShortcuts; 6445 begin 6446 mHelp.ShortCut := BHelp.ShortCut; 6447 mUnitStat.ShortCut := BUnitStat.ShortCut; 6448 mCityStat.ShortCut := BCityStat.ShortCut; 6449 mScienceStat.ShortCut := BScienceStat.ShortCut; 6450 mEUnitStat.ShortCut := BEUnitStat.ShortCut;; 6451 mDiagram.ShortCut := BDiagram.ShortCut; 6452 mWonders.ShortCut := BWonders.ShortCut; 6453 mShips.ShortCut := BShips.ShortCut; 6454 mNations.ShortCut := BNations.ShortCut; 6455 mEmpire.ShortCut := BEmpire.ShortCut; 6456 mResign.ShortCut := BResign.ShortCut; 6457 mRandomMap.ShortCut := BRandomMap.ShortCut; 6458 mDisband.ShortCut := BDisbandUnit.ShortCut; 6459 mFort.ShortCut := BFortify.ShortCut; 6460 mCentre.ShortCut := BCenterUnit.ShortCut; 6461 mStay.ShortCut := BStay.ShortCut; 6462 mNoOrders.ShortCut := BNoOrders.ShortCut; 6463 mCancel.ShortCut := BCancel.ShortCut; 6464 mPillage.ShortCut := BPillage.ShortCut; 6465 mTechTree.ShortCut := BTechTree.ShortCut; 6466 mWait.ShortCut := BWait.ShortCut; 6467 mJump.ShortCut := BJump.ShortCut;; 6468 mDebugMap.ShortCut := BDebugMap.ShortCut; 6469 mLocCodes.ShortCut := BLocCodes.ShortCut; 6470 mNames.ShortCut := BNames.ShortCut; 6471 mRun.ShortCut := BRun.ShortCut; 6472 mAirBase.ShortCut := BAirBase.ShortCut; 6473 mCity.ShortCut := BBuildCity.ShortCut; 6474 mEnhance.ShortCut := BEnhance.ShortCut; 6475 mGoOn.ShortCut := BGoOn.ShortCut; 6476 mHome.ShortCut := BHome.ShortCut; 6477 mFarm.ShortCut := BFarmClearIrrigation.ShortCut; 6478 mClear.ShortCut := BFarmClearIrrigation.ShortCut; 6479 mIrrigation.ShortCut := BFarmClearIrrigation.ShortCut; 6480 mLoad.ShortCut := BLoad.ShortCut; 6481 mAfforest.ShortCut := BAfforestMine.ShortCut; 6482 mMine.ShortCut := BAfforestMine.ShortCut; 6483 mCanal.ShortCut := BCanal.ShortCut; 6484 MTrans.ShortCut := BTrans.ShortCut; 6485 mPollution.ShortCut := BPollution.ShortCut; 6486 mRR.ShortCut := BRailRoad.ShortCut; 6487 mRoad.ShortCut := BRailRoad.ShortCut; 6488 mUnload.ShortCut := BUnload.ShortCut; 6489 mRecover.ShortCut := BRecover.ShortCut; 6490 mUtilize.ShortCut := BUtilize.ShortCut; 6491 end; 6492 6493 procedure TMainScreen.SetFullScreen(Active: Boolean); 6494 begin 6495 if Active and (CurrentWindowState <> wsFullScreen) then begin 6496 PrevWindowState := WindowState; 6497 CurrentWindowState := wsFullScreen; 6498 WindowState := CurrentWindowState; 6499 {$IFDEF WINDOWS} 6500 BorderStyle := bsNone; 6501 {$ENDIF} 6502 BorderIcons := []; 6503 end else 6504 if not Active and (CurrentWindowState = wsFullScreen) then begin 6505 if PrevWindowState = wsMaximized then begin 6506 CurrentWindowState := wsMaximized; 6507 WindowState := CurrentWindowState; 6508 end else begin 6509 CurrentWindowState := wsNormal; 6510 WindowState := CurrentWindowState; 6511 WindowState := wsFullScreen; 6512 WindowState := CurrentWindowState; 6513 end; 6514 {$IFDEF WINDOWS} 6515 BorderStyle := bsSizeable; 6516 {$ENDIF} 6517 BorderIcons := [biSystemMenu, biMinimize, biMaximize]; 6518 end; 6425 6519 end; 6426 6520 … … 6435 6529 end; 6436 6530 6531 procedure SetViewpointMe(p: Integer); 6532 begin 6533 if p = me then SetViewpoint(p) 6534 else SetViewpoint(p); 6535 end; 6536 6537 procedure DoMoveUnit(X, Y: Integer); 6538 begin 6539 DestinationMarkON := False; 6540 PaintDestination; 6541 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 6542 ($FFFF - usStay - usRecover - usGoto - usEnhance) or usWaiting; 6543 MoveUnit(X, Y, muAutoNext); 6544 end; 6545 6437 6546 var 6438 dx, dy: integer; 6439 time0, time1: TDateTime; 6440 begin 6441 if GameMode = cMovie then 6442 begin 6443 case Key of 6444 VK_F4: 6445 MenuClick_Check(StatPopup, mScienceStat); 6446 VK_F6: 6447 MenuClick_Check(StatPopup, mDiagram); 6448 VK_F7: 6449 MenuClick_Check(StatPopup, mWonders); 6450 VK_F8: 6451 MenuClick_Check(StatPopup, mShips); 6452 end; 6453 exit; 6454 end; 6455 6456 if not idle then 6457 exit; 6458 6459 if ClientMode = cEditMap then 6460 begin 6461 if Shift = [ssCtrl] then 6547 Time0, Time1: TDateTime; 6548 ShortCut: TShortCut; 6549 begin 6550 ShortCut := KeyToShortCut(Key, Shift); 6551 6552 if GameMode = cMovie then begin 6553 if BScienceStat.Test(ShortCut) then MenuClick_Check(StatPopup, mScienceStat) 6554 else if BDiagram.Test(ShortCut) then MenuClick_Check(StatPopup, mDiagram) 6555 else if BWonders.Test(ShortCut) then MenuClick_Check(StatPopup, mWonders) 6556 else if BShips.Test(ShortCut) then MenuClick_Check(StatPopup, mShips); 6557 Exit; 6558 end; 6559 6560 if not Idle then Exit; 6561 6562 if ClientMode = cEditMap then begin 6563 if BResign.Test(ShortCut) then MenuClick(mResign) 6564 else if BRandomMap.Test(ShortCut) then MenuClick(mRandomMap) 6565 else if BHelp.Test(ShortCut) then MenuClick(mHelp); 6566 (*if Shift = [ssCtrl] then 6462 6567 case char(Key) of 6463 (*'A':6568 'A': 6464 6569 begin // auto symmetry 6465 6570 Server($7F0,me,0,nil^); … … 6473 6578 if MyMap[dx] and fTerrain>=fGrass then inc(dy); 6474 6579 dy:=dy 6475 end; *) 6476 'Q': 6477 MenuClick(mResign); 6478 'R': 6479 MenuClick(mRandomMap); 6480 end 6481 else if Shift = [] then 6482 case char(Key) of 6483 char(VK_F1): 6484 MenuClick(mHelp); 6580 end; 6485 6581 end; 6486 exit; 6487 end; 6488 6489 if Shift = [ssAlt] then 6490 case char(Key) of 6491 '0': 6492 SetDebugMap(-1); 6493 '1' .. '9': 6494 SetDebugMap(ord(Key) - 48); 6582 *) 6583 Exit; 6584 end; 6585 6586 if BEndTurn.Test(ShortCut) then EndTurn 6587 else if BFullScreen.Test(ShortCut) then begin 6588 FullScreen := not FullScreen; 6589 SetFullScreen(FullScreen); 6590 end 6591 else if BHelp.Test(ShortCut) then MenuClick(mHelp) 6592 else if BUnitStat.Test(ShortCut) then MenuClick_Check(StatPopup, mUnitStat) 6593 else if BCityStat.Test(ShortCut) then MenuClick_Check(StatPopup, mCityStat) 6594 else if BScienceStat.Test(ShortCut) then MenuClick_Check(StatPopup, mScienceStat) 6595 else if BEUnitStat.Test(ShortCut) then MenuClick_Check(StatPopup, mEUnitStat) 6596 else if BDiagram.Test(ShortCut) then MenuClick_Check(StatPopup, mDiagram) 6597 else if BWonders.Test(ShortCut) then MenuClick_Check(StatPopup, mWonders) 6598 else if BShips.Test(ShortCut) then MenuClick_Check(StatPopup, mShips) 6599 else if BNations.Test(ShortCut) then MenuClick_Check(StatPopup, mNations) 6600 else if BEmpire.Test(ShortCut) then MenuClick_Check(StatPopup, mEmpire) 6601 6602 else if BSetDebugMap0.Test(ShortCut) then SetDebugMap(-1) 6603 else if BSetDebugMap1.Test(ShortCut) then SetDebugMap(1) 6604 else if BSetDebugMap2.Test(ShortCut) then SetDebugMap(2) 6605 else if BSetDebugMap3.Test(ShortCut) then SetDebugMap(3) 6606 else if BSetDebugMap4.Test(ShortCut) then SetDebugMap(4) 6607 else if BSetDebugMap5.Test(ShortCut) then SetDebugMap(5) 6608 else if BSetDebugMap6.Test(ShortCut) then SetDebugMap(6) 6609 else if BSetDebugMap7.Test(ShortCut) then SetDebugMap(7) 6610 else if BSetDebugMap8.Test(ShortCut) then SetDebugMap(8) 6611 else if BSetDebugMap9.Test(ShortCut) then SetDebugMap(9) 6612 6613 else if BJump.Test(ShortCut) then MenuClick(mJump) 6614 else if BDebugMap.Test(ShortCut) then mShowClick(mDebugMap) 6615 else if BLocCodes.Test(ShortCut) then mShowClick(mLocCodes) 6616 else if BLogDlg.Test(ShortCut) then begin 6617 if LogDlg.Visible then LogDlg.Close 6618 else LogDlg.Show; 6619 end 6620 else if BNames.Test(ShortCut) then mNamesClick(mNames) 6621 else if BResign.Test(ShortCut) then MenuClick_Check(GamePopup, mResign) 6622 else if BRun.Test(ShortCut) then MenuClick(mRun) 6623 else if BTestMapRepaint.Test(ShortCut) then begin // test map repaint time 6624 Time0 := NowPrecise; 6625 MapValid := False; 6626 MainOffscreenPaint; 6627 Time1 := NowPrecise; 6628 SimpleMessage(Format('Map repaint time: %.3f ms', 6629 [(Time1 - Time0) / OneMillisecond])); 6630 end 6631 else if BSetViewpoint0.Test(ShortCut) then SetViewpointMe(0) 6632 else if BSetViewpoint1.Test(ShortCut) then SetViewpointMe(1) 6633 else if BSetViewpoint2.Test(ShortCut) then SetViewpointMe(2) 6634 else if BSetViewpoint3.Test(ShortCut) then SetViewpointMe(3) 6635 else if BSetViewpoint4.Test(ShortCut) then SetViewpointMe(4) 6636 else if BSetViewpoint5.Test(ShortCut) then SetViewpointMe(5) 6637 else if BSetViewpoint6.Test(ShortCut) then SetViewpointMe(6) 6638 else if BSetViewpoint7.Test(ShortCut) then SetViewpointMe(7) 6639 else if BSetViewpoint8.Test(ShortCut) then SetViewpointMe(8) 6640 else if BSetViewpoint9.Test(ShortCut) then SetViewpointMe(9) 6641 6642 else if BMapBtn0.Test(ShortCut) then MapBtnClick(MapBtn0) 6643 else if BMapBtn1.Test(ShortCut) then MapBtnClick(MapBtn1) 6644 else if BMapBtn4.Test(ShortCut) then MapBtnClick(MapBtn4) 6645 else if BMapBtn5.Test(ShortCut) then MapBtnClick(MapBtn5) 6646 else if BMapBtn6.Test(ShortCut) then MapBtnClick(MapBtn6) 6647 else if BTechTree.Test(ShortCut) then MenuClick(mTechTree) 6648 else if BWait.Test(ShortCut) then MenuClick(mWait); 6649 6650 if UnFocus >= 0 then begin 6651 if BDisbandUnit.Test(ShortCut) then MenuClick(mDisband) 6652 else if BFortify.Test(ShortCut) then MenuClick_Check(TerrainPopup, mFort) 6653 else if BCenterUnit.Test(ShortCut) then MenuClick(mCentre) 6654 else if BStay.Test(ShortCut) then MenuClick(mStay) 6655 else if BNoOrders.Test(ShortCut) then MenuClick(mNoOrders) 6656 else if BCancel.Test(ShortCut) then MenuClick_Check(UnitPopup, mCancel) 6657 else if BPillage.Test(ShortCut) then MenuClick_Check(UnitPopup, mPillage) 6658 else if BSelectTransport.Test(ShortCut) then MenuClick_Check(UnitPopup, mSelectTransport) 6659 else if BAirBase.Test(ShortCut) then MenuClick_Check(TerrainPopup, mAirBase) 6660 else if BBuildCity.Test(ShortCut) then MenuClick_Check(UnitPopup, mCity) 6661 else if BEnhance.Test(ShortCut) then begin 6662 InitPopup(TerrainPopup); 6663 if mEnhance.Visible and mEnhance.Enabled then MenuClick(mEnhance) 6664 else MenuClick(mEnhanceDef) 6495 6665 end 6496 else if Shift = [ssCtrl] then 6497 case char(Key) of 6498 'J': 6499 MenuClick(mJump); 6500 'K': 6501 mShowClick(mDebugMap); 6502 'L': 6503 mShowClick(mLocCodes); 6504 'M': 6505 if LogDlg.Visible then 6506 LogDlg.Close 6507 else 6508 LogDlg.Show; 6509 'N': 6510 mNamesClick(mNames); 6511 'Q': 6512 MenuClick_Check(GamePopup, mResign); 6513 'R': 6514 MenuClick(mRun); 6515 '0' .. '9': 6516 begin 6517 if ord(Key) - 48 = me then 6518 SetViewpoint(0) 6519 else 6520 SetViewpoint(ord(Key) - 48); 6521 end; 6522 ' ': 6523 begin // test map repaint time 6524 time0 := NowPrecise; 6525 MapValid := false; 6526 MainOffscreenPaint; 6527 time1 := NowPrecise; 6528 SimpleMessage(Format('Map repaint time: %.3f ms', 6529 [(time1 - time0) / OneMillisecond])); 6530 end 6666 else if BGoOn.Test(ShortCut) then MenuClick_Check(UnitPopup, mGoOn) 6667 else if BHome.Test(ShortCut) then MenuClick_Check(UnitPopup, mHome) 6668 else if BFarmClearIrrigation.Test(ShortCut) then begin 6669 if JobTest(UnFocus, jFarm, [eTreaty]) then 6670 MenuClick(mFarm) 6671 else if JobTest(UnFocus, jClear, [eTreaty]) then 6672 MenuClick(mClear) 6673 else MenuClick_Check(TerrainPopup, mIrrigation); 6531 6674 end 6532 else if Shift = [] then 6533 case char(Key) of 6534 char(VK_F1): 6535 MenuClick(mHelp); 6536 char(VK_F2): 6537 MenuClick_Check(StatPopup, mUnitStat); 6538 char(VK_F3): 6539 MenuClick_Check(StatPopup, mCityStat); 6540 char(VK_F4): 6541 MenuClick_Check(StatPopup, mScienceStat); 6542 char(VK_F5): 6543 MenuClick_Check(StatPopup, mEUnitStat); 6544 char(VK_F6): 6545 MenuClick_Check(StatPopup, mDiagram); 6546 char(VK_F7): 6547 MenuClick_Check(StatPopup, mWonders); 6548 char(VK_F8): 6549 MenuClick_Check(StatPopup, mShips); 6550 char(VK_F9): 6551 MenuClick_Check(StatPopup, mNations); 6552 char(VK_F10): 6553 MenuClick_Check(StatPopup, mEmpire); 6554 char(VK_ADD): 6555 EndTurn; 6556 '1': 6557 MapBtnClick(MapBtn0); 6558 '2': 6559 MapBtnClick(MapBtn1); 6560 '3': 6561 MapBtnClick(MapBtn4); 6562 '4': 6563 MapBtnClick(MapBtn5); 6564 '5': 6565 MapBtnClick(MapBtn6); 6566 'T': 6567 MenuClick(mTechTree); 6568 'W': 6569 MenuClick(mWait); 6570 end; 6571 6572 if UnFocus >= 0 then 6573 if Shift = [ssCtrl] then 6574 case char(Key) of 6575 'C': 6576 MenuClick_Check(UnitPopup, mCancel); 6577 'D': 6578 MenuClick(mDisband); 6579 'P': 6580 MenuClick_Check(UnitPopup, mPillage); 6581 'T': 6582 MenuClick_Check(UnitPopup, mSelectTransport); 6583 end 6584 else if Shift = [] then 6585 case char(Key) of 6586 ' ': 6587 MenuClick(mNoOrders); 6588 'A': 6589 MenuClick_Check(TerrainPopup, mAirBase); 6590 'B': 6591 MenuClick_Check(UnitPopup, mCity); 6592 'C': 6593 MenuClick(mCentre); 6594 'E': 6595 begin 6596 InitPopup(TerrainPopup); 6597 if mEnhance.Visible and mEnhance.Enabled then 6598 MenuClick(mEnhance) 6599 else 6600 MenuClick(mEnhanceDef) 6601 end; 6602 'F': 6603 MenuClick_Check(TerrainPopup, mFort); 6604 'G': 6605 MenuClick_Check(UnitPopup, mGoOn); 6606 'H': 6607 MenuClick_Check(UnitPopup, mHome); 6608 'I': 6609 if JobTest(UnFocus, jFarm, [eTreaty]) then 6610 MenuClick(mFarm) 6611 else if JobTest(UnFocus, jClear, [eTreaty]) then 6612 MenuClick(mClear) 6613 else 6614 MenuClick_Check(TerrainPopup, mIrrigation); 6615 'L': 6616 MenuClick_Check(UnitPopup, mLoad); 6617 'M': 6618 if JobTest(UnFocus, jAfforest, [eTreaty]) then 6619 MenuClick(mAfforest) 6620 else 6621 MenuClick_Check(TerrainPopup, mMine); 6622 'N': 6623 MenuClick_Check(TerrainPopup, mCanal); 6624 'O': 6625 MenuClick_Check(TerrainPopup, MTrans); 6626 'P': 6627 MenuClick_Check(TerrainPopup, mPollution); 6628 'R': 6629 if JobTest(UnFocus, jRR, [eTreaty]) then 6630 MenuClick(mRR) 6631 else 6632 MenuClick_Check(TerrainPopup, mRoad); 6633 'S': 6634 MenuClick(mStay); 6635 'U': 6636 MenuClick_Check(UnitPopup, mUnload); 6637 'V': 6638 MenuClick_Check(UnitPopup, mRecover); 6639 'Z': 6640 MenuClick_Check(UnitPopup, mUtilize); 6641 #33 .. #40, #97 .. #100, #102 .. #105: 6642 begin { arrow keys } 6643 DestinationMarkON := false; 6644 PaintDestination; 6645 MyUn[UnFocus].Status := MyUn[UnFocus].Status and 6646 ($FFFF - usStay - usRecover - usGoto - usEnhance) or usWaiting; 6647 case Key of 6648 VK_NUMPAD1, VK_END: 6649 begin 6650 dx := -1; 6651 dy := 1 6652 end; 6653 VK_NUMPAD2, VK_DOWN: 6654 begin 6655 dx := 0; 6656 dy := 2 6657 end; 6658 VK_NUMPAD3, VK_NEXT: 6659 begin 6660 dx := 1; 6661 dy := 1 6662 end; 6663 VK_NUMPAD4, VK_LEFT: 6664 begin 6665 dx := -2; 6666 dy := 0 6667 end; 6668 VK_NUMPAD6, VK_RIGHT: 6669 begin 6670 dx := 2; 6671 dy := 0 6672 end; 6673 VK_NUMPAD7, VK_HOME: 6674 begin 6675 dx := -1; 6676 dy := -1 6677 end; 6678 VK_NUMPAD8, VK_UP: 6679 begin 6680 dx := 0; 6681 dy := -2 6682 end; 6683 VK_NUMPAD9, VK_PRIOR: 6684 begin 6685 dx := 1; 6686 dy := -1 6687 end; 6688 end; 6689 MoveUnit(dx, dy, muAutoNext) 6690 end; 6691 end 6675 else if BLoad.Test(ShortCut) then MenuClick_Check(UnitPopup, mLoad) 6676 else if BAfforestMine.Test(ShortCut) then begin 6677 if JobTest(UnFocus, jAfforest, [eTreaty]) then MenuClick(mAfforest) 6678 else MenuClick_Check(TerrainPopup, mMine); 6679 end 6680 else if BCanal.Test(ShortCut) then MenuClick_Check(TerrainPopup, mCanal) 6681 else if BTrans.Test(ShortCut) then MenuClick_Check(TerrainPopup, MTrans) 6682 else if BPollution.Test(ShortCut) then MenuClick_Check(TerrainPopup, mPollution) 6683 else if BRailRoad.Test(ShortCut) then begin 6684 if JobTest(UnFocus, jRR, [eTreaty]) then MenuClick(mRR) 6685 else MenuClick_Check(TerrainPopup, mRoad); 6686 end 6687 else if BUnload.Test(ShortCut) then MenuClick_Check(UnitPopup, mUnload) 6688 else if BRecover.Test(ShortCut) then MenuClick_Check(UnitPopup, mRecover) 6689 else if BUtilize.Test(ShortCut) then MenuClick_Check(UnitPopup, mUtilize) 6690 else if BMoveLeftDown.Test(ShortCut) then DoMoveUnit(-1, 1) 6691 else if BMoveDown.Test(ShortCut) then DoMoveUnit(0, 2) 6692 else if BMoveRightDown.Test(ShortCut) then DoMoveUnit(1, 1) 6693 else if BMoveLeft.Test(ShortCut) then DoMoveUnit(-2, 0) 6694 else if BMoveRight.Test(ShortCut) then DoMoveUnit(2, 0) 6695 else if BMoveLeftUp.Test(ShortCut) then DoMoveUnit(-1, -1) 6696 else if BMoveUp.Test(ShortCut) then DoMoveUnit(0, -2) 6697 else if BMoveRightUp.Test(ShortCut) then DoMoveUnit(1, -1); 6698 end; 6692 6699 end; 6693 6700 … … 7152 7159 SetTroopLoc(Loc); 7153 7160 PanelPaint 7154 end 7161 end; 7155 7162 end 7156 7163 else if Sender = mSelectTransport then … … 7171 7178 begin 7172 7179 HaveCities := true; 7173 Break 7180 Break; 7174 7181 end; 7175 7182 if Popup = GamePopup then … … 7271 7278 m.Checked := true; 7272 7279 mDebugMap.Add(m); 7273 end 7280 end; 7274 7281 end; 7275 7282 mSmallTiles.Checked := xxt = 33; … … 7455 7462 begin 7456 7463 SetTroopLoc(-1); 7457 PanelPaint 7464 PanelPaint; 7458 7465 end 7459 7466 else … … 7474 7481 SetTroopLoc(-1); 7475 7482 PanelPaint 7476 end 7477 end 7483 end; 7484 end; 7478 7485 end; 7479 7486 … … 7523 7530 2 + G.ly); 7524 7531 Update; 7525 end 7532 end; 7526 7533 end 7527 7534 else … … 7539 7546 MiniPaint; 7540 7547 PanelPaint; 7541 end 7548 end; 7542 7549 end; 7543 7550 … … 7591 7598 begin 7592 7599 result := (y >= TopBarHeight + MapHeight) or (y >= ClientHeight - PanelHeight) 7593 and ((x < xMidPanel) or (x >= xRightPanel)) 7600 and ((x < xMidPanel) or (x >= xRightPanel)); 7594 7601 end; 7595 7602 … … 7608 7615 GamePopup.Popup(Left + 4, Top + DpiGetSystemMetrics(SM_CYCAPTION) + 4 + 7609 7616 TopBarHeight - 1); 7610 end 7617 end; 7611 7618 end 7612 7619 else if IsPanelPixel(x, y) then … … 7771 7778 CityRepMask := CityRepMask or (1 shl (Tag shr 8)) 7772 7779 else 7773 CityRepMask := CityRepMask and not(1 shl (Tag shr 8)) 7774 end 7780 CityRepMask := CityRepMask and not(1 shl (Tag shr 8)); 7781 end; 7775 7782 end; 7776 7783 … … 7782 7789 procedure TMainScreen.FormShow(Sender: TObject); 7783 7790 begin 7784 if FullScreen then begin 7785 WindowState := wsFullScreen; 7786 BorderStyle := bsNone; 7787 BorderIcons := []; 7788 end else begin 7789 WindowState := wsMaximized; 7790 BorderStyle := bsSizeable; 7791 BorderIcons := [biSystemMenu, biMinimize, biMaximize]; 7792 end; 7791 SetFullScreen(FullScreen); 7793 7792 Timer1.Enabled := True; 7794 7793 end; … … 7827 7826 else if Flag = tfAllTechs then 7828 7827 TellNewModels 7829 end 7830 end 7828 end; 7829 end; 7831 7830 end; 7832 7831 … … 7898 7897 GamePopup.Popup(Left + 4, Top + DpiGetSystemMetrics(SM_CYCAPTION) + 4 + 7899 7898 TopBarHeight - 1); 7900 exit 7901 end // windows menu button calls game menu7899 exit; 7900 end; // windows menu button calls game menu 7902 7901 end; 7903 7902 -
branches/highdpi/LocalPlayer/Tribes.pas
r210 r303 5 5 6 6 uses 7 Protocol, ScreenTools, LazFileUtils, 8 Classes, Graphics, SysUtils; 7 Protocol, ScreenTools, LazFileUtils, Classes, Graphics, SysUtils, Global; 9 8 10 9 type 11 10 TCityPicture = record 12 xShield, yShield: integer; 11 xShield: Integer; 12 yShield: Integer; 13 13 end; 14 14 15 15 TModelPicture = record 16 HGr, pix, xShield, yShield: integer; 16 HGr: Integer; 17 pix: Integer; 18 xShield: Integer; 19 yShield: Integer; 17 20 end; 18 21 19 22 TModelPictureInfo = record 20 trix, mix, pix, Hash: integer; 23 trix: Integer; 24 mix: Integer; 25 pix: Integer; 26 Hash: Integer; 21 27 GrName: ShortString; 22 28 end; 23 29 24 30 TTribe = class 25 symHGr, sympix, faceHGr, facepix, cHGr, cpix, 31 symHGr: Integer; 32 sympix: Integer; 33 faceHGr: Integer; 34 facepix: Integer; 35 cHGr: Integer; 36 cpix: Integer; 26 37 // symbol and city graphics 27 cAge, mixSlaves: integer; 38 cAge: Integer; 39 mixSlaves: Integer; 28 40 Color: TColor; 29 NumberName: integer;41 NumberName: Integer; 30 42 CityPicture: array [0 .. 3] of TCityPicture; 31 43 ModelPicture: array [-1 .. 256] of TModelPicture; // -1 is building site … … 33 45 constructor Create(FileName: string); 34 46 destructor Destroy; override; 35 function GetCityName(i: integer): string;36 {$IFNDEF SCR} procedure SetCityName(i: integer; NewName: string); {$ENDIF}47 function GetCityName(i: Integer): string; 48 {$IFNDEF SCR} procedure SetCityName(i: Integer; NewName: string); {$ENDIF} 37 49 {$IFNDEF SCR} function TString(Template: string): string; 38 50 function TPhrase(Item: string): string; {$ENDIF} 39 procedure SetModelPicture(const Info: TModelPictureInfo; IsNew: boolean);51 procedure SetModelPicture(const Info: TModelPictureInfo; IsNew: Boolean); 40 52 function ChooseModelPicture(var Picture: TModelPictureInfo; 41 code, Turn: integer; ForceNew: boolean): boolean;42 procedure InitAge(Age: integer);53 Code, Turn: Integer; ForceNew: Boolean): Boolean; 54 procedure InitAge(Age: Integer); 43 55 protected 44 CityLine0, nCityLines: integer; 56 CityLine0: Integer; 57 nCityLines: Integer; 45 58 Name: array ['a' .. 'z'] of string; 46 Script: tstringlist;59 Script: TStringList; 47 60 end; 48 61 49 62 var 50 63 Tribe: array [0 .. nPl - 1] of TTribe; 51 HGrStdUnits: integer;64 HGrStdUnits: Integer; 52 65 53 66 procedure Init; 54 67 procedure Done; 55 function CityName(Founder: integer): string; 56 function ModelCode(const ModelInfo: TModelInfo): integer; 57 procedure FindStdModelPicture(code: integer; var pix: integer; 58 var Name: string); 59 function GetTribeInfo(FileName: string; var Name: string; 60 var Color: TColor): boolean; 61 procedure FindPosition(HGr, x, y, xmax, ymax: integer; Mark: TColor; 62 var xp, yp: integer); 68 function CityName(Founder: Integer): string; 69 function ModelCode(const ModelInfo: TModelInfo): Integer; 70 procedure FindStdModelPicture(Code: Integer; var pix: Integer; var Name: string); 71 function GetTribeInfo(FileName: string; var Name: string; var Color: TColor): Boolean; 72 procedure FindPosition(HGr, x, y, xmax, ymax: Integer; Mark: TColor; 73 var xp, yp: Integer); 74 63 75 64 76 implementation … … 69 81 type 70 82 TChosenModelPictureInfo = record 71 Hash, HGr, pix: integer; 72 ModelName: ShortString end; 73 74 TPictureList = array [0 .. 99999] of TChosenModelPictureInfo; 75 76 var 77 StdUnitScript: tstringlist; 78 PictureList: ^TPictureList; 79 nPictureList: integer; 80 81 procedure Init; 82 begin 83 StdUnitScript := tstringlist.Create; 84 StdUnitScript.LoadFromFile(LocalizedFilePath('Tribes' + DirectorySeparator + 'StdUnits.txt')); 85 nPictureList := 0; 86 PictureList := nil; 83 Hash: Integer; 84 HGr: Integer; 85 pix: Integer; 86 ModelName: ShortString; 87 end; 88 89 TPictureList = array [0 .. 99999] of TChosenModelPictureInfo; 90 91 var 92 StdUnitScript: TStringList; 93 PictureList: ^TPictureList; 94 nPictureList: Integer; 95 96 procedure Init; 97 begin 98 StdUnitScript := TStringList.Create; 99 StdUnitScript.LoadFromFile(LocalizedFilePath('Tribes' + 100 DirectorySeparator + 'StdUnits.txt')); 101 nPictureList := 0; 102 PictureList := nil; 103 end; 104 105 procedure Done; 106 begin 107 ReallocMem(PictureList, 0); 108 FreeAndNil(StdUnitScript); 109 end; 110 111 function CityName(Founder: Integer): string; 112 begin 113 if not GenerateNames then 114 Result := Format('%d.%d', [Founder shr 12, Founder and $FFF]) 115 else 116 Result := Tribe[Founder shr 12].GetCityName(Founder and $FFF); 117 end; 118 119 function ModelCode(const ModelInfo: TModelInfo): Integer; 120 begin 121 with ModelInfo do 122 begin 123 case Kind of 124 mkSelfDeveloped, mkEnemyDeveloped: 125 case Domain of { age determination } 126 dGround: 127 if (Attack >= Defense * 4) or (Attack > 0) and 128 (MaxUpgrade < 10) and 129 (Cap and (1 shl (mcArtillery - mcFirstNonCap)) <> 0) then 130 begin 131 Result := 170; 132 if MaxUpgrade >= 12 then 133 Inc(Result, 3) 134 else if (MaxUpgrade >= 10) or (Weight > 7) then 135 Inc(Result, 2) 136 else if MaxUpgrade >= 4 then 137 Inc(Result, 1); 138 end 139 else 140 begin 141 Result := 100; 142 if MaxUpgrade >= 12 then 143 Inc(Result, 6) 144 else if (MaxUpgrade >= 10) or (Weight > 7) then 145 Inc(Result, 5) 146 else if MaxUpgrade >= 6 then 147 Inc(Result, 4) 148 else if MaxUpgrade >= 4 then 149 Inc(Result, 3) 150 else if MaxUpgrade >= 2 then 151 Inc(Result, 2) 152 else if MaxUpgrade >= 1 then 153 Inc(Result, 1); 154 if Speed >= 250 then 155 if (Result >= 105) and (Attack <= Defense) then 156 Result := 110 157 else 158 Inc(Result, 30); 159 end; 160 dSea: 161 begin 162 Result := 200; 163 if MaxUpgrade >= 8 then 164 Inc(Result, 3) 165 else if MaxUpgrade >= 6 then 166 Inc(Result, 2) 167 else if MaxUpgrade >= 3 then 168 Inc(Result, 1); 169 if Cap and (1 shl (mcSub - mcFirstNonCap)) <> 0 then 170 Result := 240 171 else if ATrans_Fuel > 0 then 172 Result := 220 173 else if (Result >= 202) and (Attack = 0) and (TTrans > 0) then 174 Result := 210; 175 end; 176 dAir: 177 begin 178 Result := 300; 179 if (Bombs > 0) or (TTrans > 0) then 180 Inc(Result, 10); 181 if Speed > 850 then 182 Inc(Result, 1); 183 end; 184 end; 185 mkSpecial_TownGuard: 186 Result := 41; 187 mkSpecial_Boat: 188 Result := 64; 189 mkSpecial_SubCabin: 190 Result := 71; 191 mkSpecial_Glider: 192 Result := 73; 193 mkSlaves: 194 Result := 74; 195 mkSettler: 196 if Speed > 150 then 197 Result := 11 198 else 199 Result := 10; 200 mkDiplomat: 201 Result := 21; 202 mkCaravan: 203 Result := 30; 87 204 end; 88 89 procedure Done; 90 begin 91 ReallocMem(PictureList, 0); 92 StdUnitScript.Free; 205 end; 206 end; 207 208 var 209 Input: string; 210 211 function Get: string; 212 var 213 p: Integer; 214 begin 215 while (Input <> '') and ((Input[1] = ' ') or (Input[1] = #9)) do 216 Delete(Input, 1, 1); 217 p := Pos(',', Input); 218 if p = 0 then 219 p := Length(Input) + 1; 220 Result := Copy(Input, 1, p - 1); 221 Delete(Input, 1, p); 222 end; 223 224 function GetNum: Integer; 225 var 226 i: Integer; 227 begin 228 Val(Get, Result, i); 229 if i <> 0 then 230 Result := 0; 231 end; 232 233 procedure FindStdModelPicture(Code: Integer; var pix: Integer; var Name: string); 234 var 235 i: Integer; 236 begin 237 for i := 0 to StdUnitScript.Count - 1 do 238 begin // look through StdUnits 239 Input := StdUnitScript[i]; 240 pix := GetNum; 241 if Code = GetNum then 242 begin 243 Name := Get; 244 Exit; 93 245 end; 94 95 function CityName(Founder: integer): string; 96 begin 97 if not GenerateNames then 98 result := Format('%d.%d', [Founder shr 12, Founder and $FFF]) 246 end; 247 pix := -1; 248 end; 249 250 function GetTribeInfo(FileName: string; var Name: string; 251 var Color: TColor): Boolean; 252 var 253 Found: Integer; 254 TribeScript: TextFile; 255 begin 256 Name := ''; 257 Color := $FFFFFF; 258 Found := 0; 259 AssignFile(TribeScript, LocalizedFilePath('Tribes' + DirectorySeparator + 260 FileName + CevoTribeExt)); 261 Reset(TribeScript); 262 while not EOF(TribeScript) do 263 begin 264 ReadLn(TribeScript, Input); 265 if Copy(Input, 1, 7) = '#CHOOSE' then 266 begin 267 Name := Copy(Input, 9, 255); 268 Found := Found or 1; 269 if Found = 3 then 270 Break; 271 end 272 else if Copy(Input, 1, 6) = '#COLOR' then 273 begin 274 Color := HexStringToColor(Copy(Input, 7, 255)); 275 Found := Found or 2; 276 if Found = 3 then 277 Break; 278 end; 279 end; 280 CloseFile(TribeScript); 281 Result := Found = 3; 282 end; 283 284 constructor TTribe.Create(FileName: string); 285 var 286 Line: Integer; 287 Variant: Char; 288 Item: string; 289 begin 290 inherited Create; 291 for Variant := 'a' to 'z' do 292 Name[Variant] := ''; 293 Script := TStringList.Create; 294 Script.LoadFromFile(FileName); 295 CityLine0 := 0; 296 nCityLines := 0; 297 for Line := 0 to Script.Count - 1 do 298 begin 299 Input := Script[Line]; 300 if (CityLine0 > 0) and (nCityLines = 0) and 301 ((Input = '') or (Input[1] = '#')) then 302 nCityLines := Line - CityLine0; 303 if (Length(Input) >= 3) and (Input[1] = '#') and 304 (Input[2] in ['a' .. 'z']) and (Input[3] = ' ') then 305 Name[Input[2]] := Copy(Input, 4, 255) 306 else if Copy(Input, 1, 6) = '#COLOR' then 307 Color := HexStringToColor(Copy(Input, 7, 255)) 308 else if Copy(Input, 1, 7) = '#CITIES' then 309 CityLine0 := Line + 1 310 else if Copy(Input, 1, 8) = '#SYMBOLS' then 311 begin 312 Delete(Input, 1, 9); 313 Item := Get; 314 sympix := GetNum; 315 symHGr := LoadGraphicSet(Item + '.png'); 316 end; 317 end; 318 FillChar(ModelPicture, SizeOf(ModelPicture), 0); 319 NumberName := -1; 320 cAge := -1; 321 mixSlaves := -1; 322 end; 323 324 destructor TTribe.Destroy; 325 begin 326 FreeAndNil(Script); 327 inherited; 328 end; 329 330 procedure FindPosition(HGr, x, y, xmax, ymax: Integer; Mark: TColor; 331 var xp, yp: Integer); 332 begin 333 xp := 0; 334 while (xp < xmax) and (GrExt[HGr].Data.Canvas.Pixels[x + 1 + xp, y] <> Mark) do 335 Inc(xp); 336 yp := 0; 337 while (yp < ymax) and (GrExt[HGr].Data.Canvas.Pixels[x, y + 1 + yp] <> Mark) do 338 Inc(yp); 339 end; 340 341 function TTribe.GetCityName(i: Integer): string; 342 begin 343 Result := ''; 344 if nCityLines > i then 345 begin 346 Result := Script[CityLine0 + i]; 347 while (Result <> '') and ((Result[1] = ' ') or (Result[1] = #9)) do 348 Delete(Result, 1, 1); 349 end 350 {$IFNDEF SCR} 351 else 352 Result := Format(TPhrase('GENCITY'), [i + 1]); 353 {$ENDIF} 354 end; 355 356 {$IFNDEF SCR} 357 procedure TTribe.SetCityName(i: Integer; NewName: string); 358 begin 359 while nCityLines <= i do 360 begin 361 Script.Insert(CityLine0 + nCityLines, Format(TPhrase('GENCITY'), 362 [nCityLines + 1])); 363 Inc(nCityLines); 364 end; 365 Script[CityLine0 + i] := NewName; 366 end; 367 368 function TTribe.TString(Template: string): string; 369 var 370 p: Integer; 371 Variant: Char; 372 CaseUp: Boolean; 373 begin 374 repeat 375 p := pos('#', Template); 376 if (p = 0) or (p = Length(Template)) then 377 Break; 378 Variant := Template[p + 1]; 379 CaseUp := Variant in ['A' .. 'Z']; 380 if CaseUp then 381 Inc(Variant, 32); 382 Delete(Template, p, 2); 383 if Variant in ['a' .. 'z'] then 384 begin 385 if NumberName < 0 then 386 Insert(Name[Variant], Template, p) 99 387 else 100 result := Tribe[Founder shr 12].GetCityName(Founder and $FFF); 101 end; 102 103 function ModelCode(const ModelInfo: TModelInfo): integer; 104 begin 105 with ModelInfo do 106 begin 107 case Kind of 108 mkSelfDeveloped, mkEnemyDeveloped: 109 case Domain of { age determination } 110 dGround: 111 if (Attack >= Defense * 4) or (Attack > 0) and (MaxUpgrade < 10) 112 and (Cap and (1 shl (mcArtillery - mcFirstNonCap)) <> 0) then 113 begin 114 result := 170; 115 if MaxUpgrade >= 12 then 116 inc(result, 3) 117 else if (MaxUpgrade >= 10) or (Weight > 7) then 118 inc(result, 2) 119 else if MaxUpgrade >= 4 then 120 inc(result, 1) 121 end 122 else 123 begin 124 result := 100; 125 if MaxUpgrade >= 12 then 126 inc(result, 6) 127 else if (MaxUpgrade >= 10) or (Weight > 7) then 128 inc(result, 5) 129 else if MaxUpgrade >= 6 then 130 inc(result, 4) 131 else if MaxUpgrade >= 4 then 132 inc(result, 3) 133 else if MaxUpgrade >= 2 then 134 inc(result, 2) 135 else if MaxUpgrade >= 1 then 136 inc(result, 1); 137 if Speed >= 250 then 138 if (result >= 105) and (Attack <= Defense) then 139 result := 110 140 else 141 inc(result, 30) 142 end; 143 dSea: 144 begin 145 result := 200; 146 if MaxUpgrade >= 8 then 147 inc(result, 3) 148 else if MaxUpgrade >= 6 then 149 inc(result, 2) 150 else if MaxUpgrade >= 3 then 151 inc(result, 1); 152 if Cap and (1 shl (mcSub - mcFirstNonCap)) <> 0 then 153 result := 240 154 else if ATrans_Fuel > 0 then 155 result := 220 156 else if (result >= 202) and (Attack = 0) and (TTrans > 0) then 157 result := 210; 158 end; 159 dAir: 160 begin 161 result := 300; 162 if (Bombs > 0) or (TTrans > 0) then 163 inc(result, 10); 164 if Speed > 850 then 165 inc(result, 1) 166 end; 167 end; 168 mkSpecial_TownGuard: 169 result := 41; 170 mkSpecial_Boat: 171 result := 64; 172 mkSpecial_SubCabin: 173 result := 71; 174 mkSpecial_Glider: 175 result := 73; 176 mkSlaves: 177 result := 74; 178 mkSettler: 179 if Speed > 150 then 180 result := 11 181 else 182 result := 10; 183 mkDiplomat: 184 result := 21; 185 mkCaravan: 186 result := 30; 187 end; 188 end; 189 end; 190 191 var 192 Input: string; 193 194 function Get: string; 195 196 var 197 p: integer; 198 begin 199 while (Input <> '') and ((Input[1] = ' ') or (Input[1] = #9)) do 200 Delete(Input, 1, 1); 201 p := pos(',', Input); 202 if p = 0 then 203 p := Length(Input) + 1; 204 result := Copy(Input, 1, p - 1); 205 Delete(Input, 1, p) 206 end; 207 208 function GetNum: integer; 209 210 var 211 i: integer; 212 begin 213 val(Get, result, i); 214 if i <> 0 then 215 result := 0 216 end; 217 218 procedure FindStdModelPicture(code: integer; var pix: integer; 219 var Name: string); 220 221 var 222 i: integer; 223 begin 224 for i := 0 to StdUnitScript.Count - 1 do 225 begin // look through StdUnits 226 Input := StdUnitScript[i]; 227 pix := GetNum; 228 if code = GetNum then 229 begin 230 Name := Get; 231 exit; 232 end 233 end; 234 pix := -1 235 end; 236 237 function GetTribeInfo(FileName: string; var Name: string; 238 var Color: TColor): boolean; 239 240 var 241 found: integer; 242 TribeScript: TextFile; 243 begin 244 Name := ''; 245 Color := $FFFFFF; 246 found := 0; 247 AssignFile(TribeScript, LocalizedFilePath('Tribes' + DirectorySeparator + FileName + 248 '.tribe.txt')); 249 Reset(TribeScript); 250 while not EOF(TribeScript) do 251 begin 252 ReadLn(TribeScript, Input); 253 if Copy(Input, 1, 7) = '#CHOOSE' then 254 begin 255 Name := Copy(Input, 9, 255); 256 found := found or 1; 257 if found = 3 then 258 break 259 end 260 else if Copy(Input, 1, 6) = '#COLOR' then 261 begin 262 Color := HexStringToColor(Copy(Input, 7, 255)); 263 found := found or 2; 264 if found = 3 then 265 break 266 end 267 end; 268 CloseFile(TribeScript); 269 result := found = 3; 270 end; 271 272 constructor TTribe.Create(FileName: string); 273 274 var 275 line: integer; 276 variant: char; 277 Item: string; 278 begin 279 inherited Create; 280 for variant := 'a' to 'z' do 281 Name[variant] := ''; 282 Script := tstringlist.Create; 283 Script.LoadFromFile(LocalizedFilePath('Tribes' + DirectorySeparator + FileName + '.tribe.txt')); 284 CityLine0 := 0; 285 nCityLines := 0; 286 for line := 0 to Script.Count - 1 do 287 begin 288 Input := Script[line]; 289 if (CityLine0 > 0) and (nCityLines = 0) and 290 ((Input = '') or (Input[1] = '#')) then 291 nCityLines := line - CityLine0; 292 if (Length(Input) >= 3) and (Input[1] = '#') and (Input[2] in ['a' .. 'z'] 293 ) and (Input[3] = ' ') then 294 Name[Input[2]] := Copy(Input, 4, 255) 295 else if Copy(Input, 1, 6) = '#COLOR' then 296 Color := HexStringToColor(Copy(Input, 7, 255)) 297 else if Copy(Input, 1, 7) = '#CITIES' then 298 CityLine0 := line + 1 299 else if Copy(Input, 1, 8) = '#SYMBOLS' then 300 begin 301 Delete(Input, 1, 9); 302 Item := Get; 303 sympix := GetNum; 304 symHGr := LoadGraphicSet(Item + '.png'); 305 end 306 end; 307 FillChar(ModelPicture, SizeOf(ModelPicture), 0); 308 NumberName := -1; 309 cAge := -1; 310 mixSlaves := -1; 311 end; 312 313 destructor TTribe.Destroy; 314 begin 315 Script.Free; 316 inherited Destroy; 317 end; 318 319 procedure FindPosition(HGr, x, y, xmax, ymax: integer; Mark: TColor; 320 var xp, yp: integer); 321 begin 322 xp := 0; 323 while (xp < xmax) and (GrExt[HGr].Data.Canvas.Pixels[x + 1 + xp, y] 324 <> Mark) do 325 inc(xp); 326 yp := 0; 327 while (yp < ymax) and (GrExt[HGr].Data.Canvas.Pixels[x, y + 1 + yp] 328 <> Mark) do 329 inc(yp); 330 end; 331 332 function TTribe.GetCityName(i: integer): string; 333 begin 334 result := ''; 335 if nCityLines > i then 336 begin 337 result := Script[CityLine0 + i]; 338 while (result <> '') and ((result[1] = ' ') or (result[1] = #9)) do 339 Delete(result, 1, 1); 388 Insert(Format('P%d', [NumberName]), Template, p); 389 if CaseUp and (Length(Template) >= p) and 390 (Template[p] in ['a' .. 'z', #$E0 .. #$FF]) then 391 Dec(Template[p], 32); 340 392 end 341 {$IFNDEF SCR} else 342 result := Format(TPhrase('GENCITY'), [i + 1]){$ENDIF} 343 end; 344 345 {$IFNDEF SCR} 346 procedure TTribe.SetCityName(i: integer; NewName: string); 347 begin 348 while nCityLines <= i do 349 begin 350 Script.Insert(CityLine0 + nCityLines, Format(TPhrase('GENCITY'), 351 [nCityLines + 1])); 352 inc(nCityLines); 353 end; 354 Script[CityLine0 + i] := NewName; 355 end; 356 357 function TTribe.TString(Template: string): string; 358 359 var 360 p: integer; 361 variant: char; 362 CaseUp: boolean; 363 begin 364 repeat 365 p := pos('#', Template); 366 if (p = 0) or (p = Length(Template)) then 367 break; 368 variant := Template[p + 1]; 369 CaseUp := variant in ['A' .. 'Z']; 370 if CaseUp then 371 inc(variant, 32); 372 Delete(Template, p, 2); 373 if variant in ['a' .. 'z'] then 374 begin 375 if NumberName < 0 then 376 Insert(Name[variant], Template, p) 377 else 378 Insert(Format('P%d', [NumberName]), Template, p); 379 if CaseUp and (Length(Template) >= p) and 380 (Template[p] in ['a' .. 'z', #$E0 .. #$FF]) then 381 dec(Template[p], 32); 382 end 383 until false; 384 result := Template; 385 end; 386 387 function TTribe.TPhrase(Item: string): string; 388 begin 389 result := TString(Phrases.Lookup(Item)); 390 end; 393 until False; 394 Result := Template; 395 end; 396 397 function TTribe.TPhrase(Item: string): string; 398 begin 399 Result := TString(Phrases.Lookup(Item)); 400 end; 401 391 402 {$ENDIF} 392 403 393 procedure TTribe.InitAge(Age: integer); 394 type 395 TLine = array [0 .. 649, 0 .. 2] of Byte; 396 var 397 i, x, gray: integer; 398 Item: string; 399 begin 400 if Age = cAge then 401 exit; 402 cAge := Age; 403 with Script do 404 begin 405 i := 0; 406 while (i < Count) and 407 (Copy(Strings[i], 1, 6) <> '#AGE' + char(48 + Age) + ' ') do 408 inc(i); 409 if i < Count then 410 begin 411 Input := Strings[i]; 412 system.Delete(Input, 1, 6); 413 Item := Get; 414 cpix := GetNum; 415 // init city graphics 416 if Age < 2 then 417 begin 418 if CompareText(Item, 'stdcities') = 0 then 419 case cpix of 420 3: 421 cpix := 0; 422 6: 423 begin 424 cpix := 0; 425 Item := 'Nation2'; 426 end 427 end; 428 cHGr := LoadGraphicSet(Item + '.png'); 429 for x := 0 to 3 do 430 with CityPicture[x] do 431 begin 432 FindPosition(cHGr, x * 65, cpix * 49, 63, 47, $00FFFF, 433 xShield, yShield); 434 // FindPosition(cHGr,x*65,cpix*49,$FFFFFF,xf,yf); 435 end 436 end 437 else 438 cHGr := -1; 439 440 {$IFNDEF SCR} 441 Get; 442 GetNum; 443 Item := Get; 444 if Item = '' then 445 faceHGr := -1 446 else 447 begin 448 faceHGr := LoadGraphicSet(Item + '.png'); 449 facepix := GetNum; 450 if GrExt[faceHGr].Data.Canvas.Pixels[facepix mod 10 * 65, 451 facepix div 10 * 49 + 48] = $00FFFF then 452 begin // generate shield picture 453 GrExt[faceHGr].Data.Canvas.Pixels[facepix mod 10 * 65, 454 facepix div 10 * 49 + 48] := $000000; 455 gray := $B8B8B8; 456 ImageOp_BCC(GrExt[faceHGr].Data, Templates, 457 facepix mod 10 * 65 + 1, facepix div 10 * 49 + 1, 1, 25, 64, 48, 458 gray, Color); 404 procedure TTribe.InitAge(Age: Integer); 405 type 406 TLine = array [0 .. 649, 0 .. 2] of Byte; 407 var 408 i, x, Gray: Integer; 409 Item: string; 410 begin 411 if Age = cAge then 412 Exit; 413 cAge := Age; 414 with Script do 415 begin 416 i := 0; 417 while (i < Count) and (Copy(Strings[i], 1, 6) <> 418 '#AGE' + char(48 + Age) + ' ') do 419 Inc(i); 420 if i < Count then 421 begin 422 Input := Strings[i]; 423 system.Delete(Input, 1, 6); 424 Item := Get; 425 cpix := GetNum; 426 // init city graphics 427 if Age < 2 then 428 begin 429 if CompareText(Item, 'stdcities') = 0 then 430 case cpix of 431 3: 432 cpix := 0; 433 6: 434 begin 435 cpix := 0; 436 Item := 'Nation2'; 459 437 end 460 438 end; 439 cHGr := LoadGraphicSet(Item + '.png'); 440 for x := 0 to 3 do 441 with CityPicture[x] do 442 begin 443 FindPosition(cHGr, x * 65, cpix * 49, 63, 47, $00FFFF, 444 xShield, yShield); 445 // FindPosition(cHGr,x*65,cpix*49,$FFFFFF,xf,yf); 446 end; 447 end 448 else 449 cHGr := -1; 450 451 {$IFNDEF SCR} 452 Get; 453 GetNum; 454 Item := Get; 455 if Item = '' then 456 faceHGr := -1 457 else 458 begin 459 faceHGr := LoadGraphicSet(Item + '.png'); 460 facepix := GetNum; 461 if GrExt[faceHGr].Data.Canvas.Pixels[facepix mod 10 * 65, 462 facepix div 10 * 49 + 48] = $00FFFF then 463 begin // generate shield picture 464 GrExt[faceHGr].Data.Canvas.Pixels[facepix mod 10 * 65, 465 facepix div 10 * 49 + 48] := $000000; 466 Gray := $B8B8B8; 467 ImageOp_BCC(GrExt[faceHGr].Data, Templates, 468 facepix mod 10 * 65 + 1, facepix div 10 * 49 + 1, 1, 25, 64, 48, 469 Gray, Color); 470 end; 471 end; 461 472 {$ENDIF} 462 end463 end464 473 end; 465 466 procedure TTribe.SetModelPicture(const Info: TModelPictureInfo; 467 IsNew: boolean); 468 var 469 i: integer; 470 ok: boolean; 471 begin 472 with Info do 473 begin 474 if not IsNew then 474 end; 475 end; 476 477 procedure TTribe.SetModelPicture(const Info: TModelPictureInfo; IsNew: Boolean); 478 var 479 i: Integer; 480 ok: Boolean; 481 begin 482 with Info do 483 begin 484 if not IsNew then 485 begin 486 i := nPictureList - 1; 487 while (i >= 0) and (PictureList[i].Hash <> Info.Hash) do 488 Dec(i); 489 assert(i >= 0); 490 assert(PictureList[i].HGr = LoadGraphicSet(GrName)); 491 assert(PictureList[i].pix = pix); 492 ModelPicture[mix].HGr := PictureList[i].HGr; 493 ModelPicture[mix].pix := PictureList[i].pix; 494 ModelName[mix] := PictureList[i].ModelName; 495 end 496 else 497 begin 498 with ModelPicture[mix] do 499 begin 500 HGr := LoadGraphicSet(GrName); 501 pix := Info.pix; 502 Inc(GrExt[HGr].pixUsed[pix]); 503 end; 504 ModelName[mix] := ''; 505 506 // read model name from tribe script 507 ok := False; 508 for i := 0 to Script.Count - 1 do 509 begin 510 Input := Script[i]; 511 if Input = '#UNITS ' + ExtractFileNameOnly(GrName) then 512 ok := True 513 else if (Input <> '') and (Input[1] = '#') then 514 ok := False 515 else if ok and (GetNum = pix) then 475 516 begin 476 i := nPictureList - 1; 477 while (i >= 0) and (PictureList[i].Hash <> Info.Hash) do 478 dec(i); 479 assert(i >= 0); 480 assert(PictureList[i].HGr = LoadGraphicSet(GrName)); 481 assert(PictureList[i].pix = pix); 482 ModelPicture[mix].HGr := PictureList[i].HGr; 483 ModelPicture[mix].pix := PictureList[i].pix; 484 ModelName[mix] := PictureList[i].ModelName; 485 end 486 else 517 Get; 518 ModelName[mix] := Get; 519 end; 520 end; 521 522 if ModelName[mix] = '' then 523 begin // read model name from StdUnits.txt 524 for i := 0 to StdUnitScript.Count - 1 do 487 525 begin 488 with ModelPicture[mix] do 526 Input := StdUnitScript[i]; 527 if GetNum = pix then 489 528 begin 490 HGr := LoadGraphicSet(GrName); 491 pix := Info.pix; 492 inc(GrExt[HGr].pixUsed[pix]); 529 Get; 530 ModelName[mix] := Get; 493 531 end; 494 ModelName[mix] := '';495 496 // read model name from tribe script497 ok := false;498 for i := 0 to Script.Count - 1 do499 begin500 Input := Script[i];501 if Input = '#UNITS ' + ExtractFileNameOnly(GrName) then502 ok := true503 else if (Input <> '') and (Input[1] = '#') then504 ok := false505 else if ok and (GetNum = pix) then506 begin507 Get;508 ModelName[mix] := Get509 end510 end;511 512 if ModelName[mix] = '' then513 begin // read model name from StdUnits.txt514 for i := 0 to StdUnitScript.Count - 1 do515 begin516 Input := StdUnitScript[i];517 if GetNum = pix then518 begin519 Get;520 ModelName[mix] := Get521 end522 end523 end;524 525 if Hash <> 0 then526 begin527 if nPictureList = 0 then528 ReallocMem(PictureList, 64 * SizeOf(TChosenModelPictureInfo))529 else if (nPictureList >= 64) and530 (nPictureList and (nPictureList - 1) = 0) then531 ReallocMem(PictureList,532 nPictureList * (2 * SizeOf(TChosenModelPictureInfo)));533 PictureList[nPictureList].Hash := Info.Hash;534 PictureList[nPictureList].HGr := ModelPicture[mix].HGr;535 PictureList[nPictureList].pix := Info.pix;536 PictureList[nPictureList].ModelName := ModelName[mix];537 inc(nPictureList);538 end539 532 end; 540 541 with ModelPicture[mix] do 542 FindPosition(HGr, pix mod 10 * 65, pix div 10 * 49, 63, 47, $FFFFFF, 543 xShield, yShield); 533 end; 534 535 if Hash <> 0 then 536 begin 537 if nPictureList = 0 then 538 ReallocMem(PictureList, 64 * SizeOf(TChosenModelPictureInfo)) 539 else if (nPictureList >= 64) and (nPictureList and 540 (nPictureList - 1) = 0) then 541 ReallocMem(PictureList, 542 nPictureList * (2 * SizeOf(TChosenModelPictureInfo))); 543 PictureList[nPictureList].Hash := Info.Hash; 544 PictureList[nPictureList].HGr := ModelPicture[mix].HGr; 545 PictureList[nPictureList].pix := Info.pix; 546 PictureList[nPictureList].ModelName := ModelName[mix]; 547 Inc(nPictureList); 544 548 end; 545 549 end; 546 550 547 function TTribe.ChooseModelPicture(var Picture: TModelPictureInfo; 548 code, Turn: integer; ForceNew: boolean): boolean; 549 var 550 i, Cnt, HGr, used, LeastUsed: integer; 551 TestPic: TModelPictureInfo; 552 ok: boolean; 553 554 procedure check; 555 begin 556 TestPic.pix := GetNum; 557 if code = GetNum then 558 begin 559 if ForceNew or (HGr < 0) then 560 used := 0 561 else 562 begin 563 used := 4 * GrExt[HGr].pixUsed[TestPic.pix]; 564 if HGr = HGrStdUnits then 565 inc(used, 2); // prefer units not from StdUnits 566 end; 567 if used < LeastUsed then 568 begin 569 Cnt := 0; 570 LeastUsed := used 571 end; 572 if used = LeastUsed then 573 begin 574 inc(Cnt); 575 if Turn mod Cnt = 0 then 576 Picture := TestPic 577 end; 578 end 579 end; 580 581 begin 582 // look for identical model to assign same picture again 583 if not ForceNew and (Picture.Hash > 0) then 584 begin 585 for i := 0 to nPictureList - 1 do 586 if PictureList[i].Hash = Picture.Hash then 587 begin 588 Picture.GrName := GrExt[PictureList[i].HGr].Name; 589 Picture.pix := PictureList[i].pix; 590 result := false; 591 exit; 592 end 593 end; 594 595 Picture.pix := 0; 596 TestPic := Picture; 597 LeastUsed := MaxInt; 598 599 TestPic.GrName := 'StdUnits.png'; 600 HGr := HGrStdUnits; 601 for i := 0 to StdUnitScript.Count - 1 do 602 begin // look through StdUnits 603 Input := StdUnitScript[i]; 604 check; 605 end; 606 607 ok := false; 608 for i := 0 to Script.Count - 1 do 609 begin // look through units defined in tribe script 610 Input := Script[i]; 611 if Copy(Input, 1, 6) = '#UNITS' then 612 begin 613 ok := true; 614 TestPic.GrName := Copy(Input, 8, 255) + '.png'; 615 HGr := nGrExt - 1; 616 while (HGr >= 0) and (GrExt[HGr].Name <> TestPic.GrName) do 617 dec(HGr); 618 end 619 else if (Input <> '') and (Input[1] = '#') then 620 ok := false 621 else if ok then 622 check; 623 end; 624 result := true; 551 with ModelPicture[mix] do 552 FindPosition(HGr, pix mod 10 * 65, pix div 10 * 49, 63, 47, $FFFFFF, 553 xShield, yShield); 554 end; 555 end; 556 557 function TTribe.ChooseModelPicture(var Picture: TModelPictureInfo; 558 Code, Turn: Integer; ForceNew: Boolean): Boolean; 559 var 560 i, Cnt, HGr, Used, LeastUsed: Integer; 561 TestPic: TModelPictureInfo; 562 ok: Boolean; 563 564 procedure Check; 565 begin 566 TestPic.pix := GetNum; 567 if Code = GetNum then 568 begin 569 if ForceNew or (HGr < 0) then 570 Used := 0 571 else 572 begin 573 Used := 4 * GrExt[HGr].pixUsed[TestPic.pix]; 574 if HGr = HGrStdUnits then 575 Inc(Used, 2); // prefer units not from StdUnits 576 end; 577 if Used < LeastUsed then 578 begin 579 Cnt := 0; 580 LeastUsed := Used; 581 end; 582 if Used = LeastUsed then 583 begin 584 Inc(Cnt); 585 if Turn mod Cnt = 0 then 586 Picture := TestPic; 587 end; 625 588 end; 589 end; 590 591 begin 592 // look for identical model to assign same picture again 593 if not ForceNew and (Picture.Hash > 0) then 594 begin 595 for i := 0 to nPictureList - 1 do 596 if PictureList[i].Hash = Picture.Hash then 597 begin 598 Picture.GrName := GrExt[PictureList[i].HGr].Name; 599 Picture.pix := PictureList[i].pix; 600 Result := False; 601 Exit; 602 end; 603 end; 604 605 Picture.pix := 0; 606 TestPic := Picture; 607 LeastUsed := MaxInt; 608 609 TestPic.GrName := 'StdUnits.png'; 610 HGr := HGrStdUnits; 611 for i := 0 to StdUnitScript.Count - 1 do 612 begin // look through StdUnits 613 Input := StdUnitScript[i]; 614 Check; 615 end; 616 617 ok := False; 618 for i := 0 to Script.Count - 1 do 619 begin // look through units defined in tribe script 620 Input := Script[i]; 621 if Copy(Input, 1, 6) = '#UNITS' then 622 begin 623 ok := True; 624 TestPic.GrName := Copy(Input, 8, 255) + '.png'; 625 HGr := nGrExt - 1; 626 while (HGr >= 0) and (GrExt[HGr].Name <> TestPic.GrName) do 627 Dec(HGr); 628 end 629 else if (Input <> '') and (Input[1] = '#') then 630 ok := False 631 else if ok then 632 Check; 633 end; 634 Result := True; 635 end; 626 636 627 637 end. -
branches/highdpi/LocalPlayer/UnitStat.pas
r210 r303 83 83 Template := TDpiBitmap.Create; 84 84 Template.PixelFormat := pf24bit; 85 LoadGraphicFile(Template, GetGraphicsDir + DirectorySeparator + 'Unit.png', gfNoGamma); 85 LoadGraphicFile(Template, GetGraphicsDir + DirectorySeparator + 'Unit.png', 86 [gfNoGamma]); 86 87 end; 87 88 88 89 procedure TUnitStatDlg.FormDestroy(Sender: TObject); 89 90 begin 90 Template.Free;91 Back.Free;91 FreeAndNil(Template); 92 FreeAndNil(Back); 92 93 end; 93 94 … … 276 277 procedure TUnitStatDlg.CloseBtnClick(Sender: TObject); 277 278 begin 278 Close 279 Close; 279 280 end; 280 281 … … 363 364 inc(dx, 15) 364 365 end; 365 end 366 end 366 end; 367 end; 367 368 end; { featurebar } 368 369
Note:
See TracChangeset
for help on using the changeset viewer.