# HG changeset patch # User glx # Date 1191709824 0 # Node ID 197cb8c6ae1753eef8e7d2bed348dbd5b69d685e # Parent d2a6acdbd665a1696eb0a5aaa716e40c09d9b44b (svn r11221) [NoAI] -Sync: with trunk r11145:11220 diff -r d2a6acdbd665 -r 197cb8c6ae17 Makefile.in --- a/Makefile.in Sun Sep 23 07:37:38 2007 +0000 +++ b/Makefile.in Sat Oct 06 22:30:24 2007 +0000 @@ -23,8 +23,6 @@ INSTALL_ICON_DIR = "$(INSTALL_DIR)/"!!ICON_DIR!! INSTALL_DATA_DIR = "$(INSTALL_DIR)/"!!DATA_DIR!! INSTALL_PERSONAL_DIR = !!PERSONAL_DIR!! -# TODO: ENABLE_INSTALL should be removed when the search path patch has been applied -ENABLE_INSTALL = !!ENABLE_INSTALL!! TTD = !!TTD!! TTDS = $(SRC_DIRS:%=%/$(TTD)) OS = !!OS!! @@ -221,6 +219,9 @@ ifeq ($(shell if test -n "`ls -l \"$(BIN_DIR)/scenario/heightmaps/\"* 2>/dev/null`"; then echo 1; fi), 1) $(Q)cp "$(BIN_DIR)/scenario/heightmaps/"* "$(BUNDLE_DIR)/scenario/heightmap/" endif +ifeq ($(TTD), openttd.exe) + $(Q)unix2dos "$(BUNDLE_DIR)/docs/"* "$(BUNDLE_DIR)/readme.txt" "$(BUNDLE_DIR)/COPYING" +endif ### Packing the current bundle into several compressed file formats ### # diff -r d2a6acdbd665 -r 197cb8c6ae17 Makefile.src.in --- a/Makefile.src.in Sun Sep 23 07:37:38 2007 +0000 +++ b/Makefile.src.in Sat Oct 06 22:30:24 2007 +0000 @@ -102,8 +102,14 @@ else # Are we a git dir? ifeq ($(shell if test -d $(SRC_DIR)/../.git; then echo 1; fi), 1) -# Find the revision like: rXXXXM -REV := g$(shell if head=`git rev-parse --verify HEAD 2>/dev/null`; then echo "$$head" | cut -c1-8; fi)$(shell if git diff-index HEAD | read dummy; then echo M; fi)$(shell git branch|grep '[*]'|sed 's/\* /-/;s/^-master$$//') +# Find the revision like: gXXXXM-branch +REV := g$(shell if head=`LC_ALL=C git rev-parse --verify HEAD 2>/dev/null`; then echo "$$head" | cut -c1-8; fi)$(shell if git diff-index HEAD | read dummy; then echo M; fi)$(shell git branch|grep '[*]' | sed 's/\* /-/;s/^-master$$//') +else +# Are we a hg (Mercurial) dir? +ifeq ($(shell if test -d $(SRC_DIR)/../.hg; then echo 1; fi), 1) +# Find the revision like: hXXXXM-branch +REV := h$(shell if head=`LC_ALL=C hg tip 2>/dev/null`; then echo "$$head" | head -n 1 | cut -c19-26; fi)$(shell if hg status | grep -v '^?' | read dummy; then echo M; fi)$(shell hg branch | sed 's/^/-/;s/^-default$$//') +endif endif endif endif diff -r d2a6acdbd665 -r 197cb8c6ae17 bin/ai/regression/regression.txt --- a/bin/ai/regression/regression.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/bin/ai/regression/regression.txt Sat Oct 06 22:30:24 2007 +0000 @@ -9,21 +9,21 @@ abs( 21): 21 --AIBase-- - Rand(): 438016824 - Rand(): 1155512394 - Rand(): -1230912451 + Rand(): -1692638405 + Rand(): -1170386787 + Rand(): 190814891 RandRange(0): 0 RandRange(0): 0 RandRange(0): 0 RandRange(1): 0 RandRange(1): 0 RandRange(1): 0 - RandRange(2): 1 RandRange(2): 0 RandRange(2): 0 - RandRange(9): 0 - RandRange(9): 1 - RandRange(9): 7 + RandRange(2): 0 + RandRange(9): 4 + RandRange(9): 6 + RandRange(9): 2 Chance(1, 2): true Chance(1, 2): true Chance(1, 2): false @@ -137,144 +137,144 @@ 1098 => 1098 1099 => 1099 Randomize ListDump: - 1 => 12862691 - 2 => -1917812707 - 1000 => 1421163554 - 1001 => -312664745 - 1002 => -2068922958 - 1003 => 1861130245 - 1004 => 1649688256 - 1005 => 15955316 - 1006 => 1355779470 - 1007 => 865353559 - 1008 => 803536462 - 1009 => -1712495000 - 1010 => -1505961326 - 1011 => -870330146 - 1012 => 126669570 - 1013 => -805020189 - 1014 => 793365509 - 1015 => 913987592 - 1016 => -720783506 - 1017 => 1926417138 - 1018 => -683369878 - 1019 => 446485522 - 1020 => 537800773 - 1021 => -615490971 - 1022 => 1776085247 - 1023 => -1869659646 - 1024 => 1353595954 - 1025 => 1880025847 - 1026 => 56594834 - 1027 => 1165500481 - 1028 => 1086094131 - 1029 => -263041456 - 1030 => 1130819676 - 1031 => 1868532194 - 1032 => 406052492 - 1033 => 529742212 - 1034 => 1549122406 - 1035 => 1528374594 - 1036 => -1586709059 - 1037 => -1866528486 - 1038 => -2123636907 - 1039 => 2060223021 - 1040 => -982427121 - 1041 => -99903420 - 1042 => 373385608 - 1043 => -1522828933 - 1044 => -1560504629 - 1045 => -2077599081 - 1046 => -782857017 - 1047 => 192681035 - 1048 => -642978559 - 1049 => 1723023122 - 1051 => 1181099329 - 1052 => -1581037797 - 1053 => -1856480328 - 1054 => -360359556 - 1055 => 2087072896 - 1056 => 1566859460 - 1057 => 490730845 - 1058 => -871118486 - 1059 => -1265136557 - 1060 => -1710287301 - 1061 => 624475954 - 1062 => 1448791554 - 1063 => -1448570564 - 1064 => -923161374 - 1065 => -1175940076 - 1066 => 1633634195 - 1067 => 474627780 - 1068 => -1754850936 - 1069 => -970278622 - 1070 => -1005842954 - 1071 => -1149168206 - 1072 => -1107909687 - 1073 => -1319038694 - 1074 => 1057817048 - 1075 => 410375978 - 1076 => 37823872 - 1077 => 2005120480 - 1078 => 2001195837 - 1079 => 2132885814 - 1080 => -809853417 - 1081 => -1575623843 - 1082 => -598915313 - 1083 => 620318589 - 1084 => -2127761983 - 1085 => -507862777 - 1086 => -245405898 - 1087 => -811840780 - 1088 => 571811265 - 1089 => 1695322056 - 1090 => 1956157477 - 1091 => -495557029 - 1092 => -1727000177 - 1093 => -1572068837 - 1094 => -1100027091 - 1095 => -677705398 - 1096 => 742793210 - 1097 => 431459282 - 1098 => -1694029724 - 1099 => 105515356 + 1 => 581150761 + 2 => 780195416 + 1000 => -1005781929 + 1001 => -304338569 + 1002 => -1743669342 + 1003 => 2052174274 + 1004 => -239846598 + 1005 => -519154508 + 1006 => 1384592592 + 1007 => 92537681 + 1008 => -783011799 + 1009 => 1020927039 + 1010 => -762645416 + 1011 => 1654042603 + 1012 => 210165652 + 1013 => -1851586478 + 1014 => 208319733 + 1015 => -1211393332 + 1016 => 2052272773 + 1017 => -1489194376 + 1018 => -438907823 + 1019 => 130289291 + 1020 => -1283324111 + 1021 => -259554489 + 1022 => 1143992540 + 1023 => -1301766703 + 1024 => 2067670203 + 1025 => 1726364654 + 1026 => 939556491 + 1027 => -1134709978 + 1028 => -110608336 + 1029 => 1339284138 + 1030 => -472993361 + 1031 => 958802835 + 1032 => 761440845 + 1033 => -1469223188 + 1034 => -721599317 + 1035 => 434887418 + 1036 => -820146882 + 1037 => 274760994 + 1038 => -522727528 + 1039 => -669489971 + 1040 => 1377115572 + 1041 => 516401345 + 1042 => 295153940 + 1043 => -1055199725 + 1044 => -1143220467 + 1045 => -686775621 + 1046 => 867901084 + 1047 => 1693214681 + 1048 => -1112224853 + 1049 => 659718584 + 1051 => -1132568097 + 1052 => -1370768491 + 1053 => -1233695197 + 1054 => 824602143 + 1055 => 1213169381 + 1056 => 1616397171 + 1057 => -1494293955 + 1058 => 168525123 + 1059 => 985183216 + 1060 => 163496891 + 1061 => -1920407820 + 1062 => 512739738 + 1063 => 1098365126 + 1064 => 1522198446 + 1065 => 152025258 + 1066 => -1654530986 + 1067 => 1386785618 + 1068 => -49512268 + 1069 => 1214031860 + 1070 => 458782250 + 1071 => -1641082778 + 1072 => -1284412562 + 1073 => 1507095104 + 1074 => -1103314033 + 1075 => -837829736 + 1076 => 1245363646 + 1077 => -1003369287 + 1078 => -729296780 + 1079 => -2042801701 + 1080 => 690945725 + 1081 => 844366079 + 1082 => 1659029417 + 1083 => 585818047 + 1084 => -1199106717 + 1085 => 680742150 + 1086 => 264108503 + 1087 => -301161571 + 1088 => -132905463 + 1089 => 1892881479 + 1090 => -1903322021 + 1091 => 1017533996 + 1092 => -976386914 + 1093 => -90625762 + 1094 => -1290852461 + 1095 => -1953934605 + 1096 => 112304592 + 1097 => 1238896913 + 1098 => 1436365455 + 1099 => 825503137 KeepTop(10): - 1 => 12862691 - 2 => -1917812707 - 1000 => 1421163554 - 1001 => -312664745 - 1002 => -2068922958 - 1003 => 1861130245 - 1004 => 1649688256 - 1005 => 15955316 - 1006 => 1355779470 - 1007 => 865353559 + 1 => 581150761 + 2 => 780195416 + 1000 => -1005781929 + 1001 => -304338569 + 1002 => -1743669342 + 1003 => 2052174274 + 1004 => -239846598 + 1005 => -519154508 + 1006 => 1384592592 + 1007 => 92537681 KeepBottom(8): - 1000 => 1421163554 - 1001 => -312664745 - 1002 => -2068922958 - 1003 => 1861130245 - 1004 => 1649688256 - 1005 => 15955316 - 1006 => 1355779470 - 1007 => 865353559 + 1000 => -1005781929 + 1001 => -304338569 + 1002 => -1743669342 + 1003 => 2052174274 + 1004 => -239846598 + 1005 => -519154508 + 1006 => 1384592592 + 1007 => 92537681 RemoveBottom(2): - 1000 => 1421163554 - 1001 => -312664745 - 1002 => -2068922958 - 1003 => 1861130245 - 1004 => 1649688256 - 1005 => 15955316 + 1000 => -1005781929 + 1001 => -304338569 + 1002 => -1743669342 + 1003 => 2052174274 + 1004 => -239846598 + 1005 => -519154508 RemoveTop(2): - 1002 => -2068922958 - 1003 => 1861130245 - 1004 => 1649688256 - 1005 => 15955316 + 1002 => -1743669342 + 1003 => 2052174274 + 1004 => -239846598 + 1005 => -519154508 RemoveList({1003, 1004}): - 1002 => -2068922958 - 1005 => 15955316 + 1002 => -1743669342 + 1005 => -519154508 KeepList({1003, 1004, 1005}): - 1005 => 15955316 + 1005 => -519154508 IsEmpty(): true --AIAirport-- @@ -332,11 +332,11 @@ GetHangarOfAirport(): 32119 IsHangarTile(): true IsAirportTile(): true - GetBankBalance(): 90100 + GetBankBalance(): 90052 RemoveAirport(): true IsHangarTile(): false IsAirportTile(): false - GetBankBalance(): 89836 + GetBankBalance(): 89788 BuildAirport(): true --AICargo-- @@ -378,7 +378,7 @@ IsFreight(): true GetCargoIncome(0, 0): 0 GetCargoIncome(10, 10): 5 - GetCargoIncome(100, 10): 53 + GetCargoIncome(100, 10): 54 GetCargoIncome(10, 100): 3 Cargo 4 IsValidCargo(): true @@ -410,7 +410,7 @@ IsFreight(): true GetCargoIncome(0, 0): 0 GetCargoIncome(10, 10): 6 - GetCargoIncome(100, 10): 60 + GetCargoIncome(100, 10): 61 GetCargoIncome(10, 100): 4 Cargo 8 IsValidCargo(): true @@ -475,11 +475,11 @@ SetCompanyName(): true SetCompanyName(): false GetCompanyName(): Regression - GetPresidentName(): L. Parker + GetPresidentName(): I. Gribble SetPresidentName(): true GetPresidentName(): Regression AI GetCompanyValue(): 0 - GetBankBalance(): 84436 + GetBankBalance(): 84364 GetCompanyName(): (null : 0x00000000) GetLoanAmount(): 100000 GetMaxLoanAmount(): 300000 @@ -487,13 +487,13 @@ SetLoanAmount(1): false SetLoanAmount(100): false SetLoanAmount(10000): false - GetBankBalance(): 84436 + GetBankBalance(): 84364 GetLoanAmount(): 100000 SetMinimumLoanAmount(31337): true - GetBankBalance(): 24436 + GetBankBalance(): 24364 GetLoanAmount(): 40000 SetLoanAmount(10000): true - GetBankBalance(): 284436 + GetBankBalance(): 284364 GetLoanAmount(): 300000 --Event-- @@ -1022,15 +1022,8 @@ 62 => 569 47 => 488 KeepAboveValue(50): done - Count(): 7 + Count(): 0 Production ListDump: - 17 => 80 - 15 => 72 - 20 => 68 - 18 => 68 - 22 => 57 - 16 => 56 - 21 => 52 --Map-- GetMapSize(): 65536 @@ -1065,7 +1058,7 @@ IsBuoyTile(): false IsLockTile(): false IsCanalTile(): false - GetBankBalance(): 284108 + GetBankBalance(): 284034 BuildWaterDepot(): true BuildDock(): true BuildBuoy(): true @@ -1076,7 +1069,7 @@ IsBuoyTile(): true IsLockTile(): true IsCanalTile(): true - GetBankBalance(): 254559 + GetBankBalance(): 254295 RemoveWaterDepot(): true RemoveDock(): true RemoveBuoy(): true @@ -1087,7 +1080,7 @@ IsBuoyTile(): false IsLockTile(): false IsCanalTile(): false - GetBankBalance(): 231914 + GetBankBalance(): 231503 BuildWaterDepot(): true BuildDock(): true @@ -1501,27 +1494,27 @@ Town 0 IsValidTown(): true GetName(): Planfield - GetPopulation(): 538 + GetPopulation(): 754 GetLocation(): 15508 Town 1 IsValidTown(): true GetName(): Trenningville - GetPopulation(): 236 + GetPopulation(): 226 GetLocation(): 46751 Town 2 IsValidTown(): true GetName(): Tondston - GetPopulation(): 253 + GetPopulation(): 320 GetLocation(): 28365 Town 3 IsValidTown(): true GetName(): Tunford - GetPopulation(): 206 + GetPopulation(): 211 GetLocation(): 41895 Town 4 IsValidTown(): true GetName(): Wrundtown - GetPopulation(): 414 + GetPopulation(): 396 GetLocation(): 41450 Town 5 IsValidTown(): true @@ -1531,22 +1524,22 @@ Town 6 IsValidTown(): true GetName(): Muningville - GetPopulation(): 566 + GetPopulation(): 579 GetLocation(): 38200 Town 7 IsValidTown(): true GetName(): Hutfingford - GetPopulation(): 652 + GetPopulation(): 777 GetLocation(): 59234 Town 8 IsValidTown(): true GetName(): Sadtown - GetPopulation(): 292 + GetPopulation(): 290 GetLocation(): 51267 Town 9 IsValidTown(): true GetName(): Frindinghattan - GetPopulation(): 447 + GetPopulation(): 459 GetLocation(): 5825 Town 10 IsValidTown(): true @@ -1556,12 +1549,12 @@ Town 11 IsValidTown(): true GetName(): Fort Frindston - GetPopulation(): 156 + GetPopulation(): 197 GetLocation(): 14935 Town 12 IsValidTown(): true GetName(): Ginborough - GetPopulation(): 766 + GetPopulation(): 853 GetLocation(): 32740 Town 13 IsValidTown(): true @@ -1571,22 +1564,22 @@ Town 14 IsValidTown(): true GetName(): Prundinghall - GetPopulation(): 316 + GetPopulation(): 336 GetLocation(): 51298 Town 15 IsValidTown(): true GetName(): Benville - GetPopulation(): 699 + GetPopulation(): 776 GetLocation(): 42338 Town 16 IsValidTown(): true GetName(): Kennville - GetPopulation(): 659 + GetPopulation(): 717 GetLocation(): 17345 Town 17 IsValidTown(): true GetName(): Quartfingfield - GetPopulation(): 185 + GetPopulation(): 170 GetLocation(): 24252 Town 18 IsValidTown(): true @@ -1596,7 +1589,7 @@ Town 19 IsValidTown(): true GetName(): Mendingston - GetPopulation(): 221 + GetPopulation(): 226 GetLocation(): 6511 Town 20 IsValidTown(): true @@ -1606,22 +1599,22 @@ Town 21 IsValidTown(): true GetName(): Franinghead - GetPopulation(): 598 + GetPopulation(): 780 GetLocation(): 9634 Town 22 IsValidTown(): true GetName(): Naborough - GetPopulation(): 174 + GetPopulation(): 191 GetLocation(): 51891 Town 23 IsValidTown(): true GetName(): Lardborough - GetPopulation(): 657 + GetPopulation(): 669 GetLocation(): 59622 Town 24 IsValidTown(): true GetName(): Little Fruford - GetPopulation(): 624 + GetPopulation(): 636 GetLocation(): 19596 Town 25 IsValidTown(): true @@ -1631,12 +1624,12 @@ Town 26 IsValidTown(): true GetName(): Bedburg - GetPopulation(): 336 + GetPopulation(): 349 GetLocation(): 39505 Town 27 IsValidTown(): true GetName(): Fudinghattan - GetPopulation(): 382 + GetPopulation(): 412 GetLocation(): 45525 Town 28 IsValidTown(): false @@ -1753,17 +1746,17 @@ KeepAboveValue(500): done Count(): 11 Population ListDump: - 12 => 766 + 12 => 853 + 21 => 780 + 7 => 777 + 15 => 776 + 0 => 754 + 16 => 717 10 => 702 - 15 => 699 - 16 => 659 - 23 => 657 - 7 => 652 - 24 => 624 - 21 => 598 - 6 => 566 + 23 => 669 + 24 => 636 + 6 => 579 25 => 548 - 0 => 538 --Vehicle-- Engine -1 @@ -2530,20 +2523,20 @@ BuildVehicle(): 0 IsValidVehicle(11): false --Transaction-- - GetCosts(): 5945 + GetCosts(): 5985 Execute(): true IsValidVehicle(11): true CloneVehicle(): 12 --Accounting-- - GetCosts(): 11890 - Should be: 11890 + GetCosts(): 11970 + Should be: 11970 ResetCosts(): (null : 0x00000000) SellVehicle(12): true StartStopVehicle(): true SendVehicleToDepot(): true --Accounting-- - GetCosts(): -5945 - Should be: -5945 + GetCosts(): -5985 + Should be: -5985 GetName(): Road Vehicle 1 SetName(): true GetName(): MyVehicleName @@ -2552,10 +2545,10 @@ GetLocation(): 33417 GetEngineType(): 153 GetUnitNumber(): 1 - GetAge(): 0 + GetAge(): 1 GetMaxAge(): 5490 - GetAgeLeft(): 5490 - GetProfitThisYear(): 0 + GetAgeLeft(): 5489 + GetProfitThisYear(): -1 GetProfitLastYear(): 0 GetVehicleType(): 1 BuildVehicle(): 13 @@ -2582,18 +2575,18 @@ 13 => 1 11 => 1 Age ListDump: - 15 => 1 - 13 => 1 12 => 1 11 => 1 + 15 => 0 + 13 => 0 MaxAge ListDump: 15 => 10980 13 => 10980 12 => 5490 11 => 5490 AgeLeft ListDump: - 15 => 10979 - 13 => 10979 + 15 => 10980 + 13 => 10980 12 => 5489 11 => 5489 ProfitThisYear ListDump: diff -r d2a6acdbd665 -r 197cb8c6ae17 bin/ai/regression/run.sh --- a/bin/ai/regression/run.sh Sun Sep 23 07:37:38 2007 +0000 +++ b/bin/ai/regression/run.sh Sat Oct 06 22:30:24 2007 +0000 @@ -10,7 +10,7 @@ params="" gdb="" if [ "$1" != "-r" ]; then - params="-snull -mnull -vnull:ticks=2000" + params="-snull -mnull -vnull:ticks=10000" fi if [ "$1" = "-g" ]; then gdb="gdb --ex run --args " diff -r d2a6acdbd665 -r 197cb8c6ae17 config.lib --- a/config.lib Sun Sep 23 07:37:38 2007 +0000 +++ b/config.lib Sat Oct 06 22:30:24 2007 +0000 @@ -702,6 +702,9 @@ elif [ -d "$ROOT_DIR/.git" ] && [ -n "`git help`" ]; then revision="" log 1 "checking revision... git detection" + elif [ -d "$ROOT_DIR/.hg" ] && [ -n "`hg help`" ]; then + revision="" + log 1 "checking revision... hg detection" else revision="" log 1 "checking revision... no detection" @@ -2143,6 +2146,8 @@ echo " --enable-translator enable extra output for translators" echo " --enable-universal enable universal builds (OSX ONLY)" echo " --enable-osx-g5 enables optimalizations for G5 (OSX ONLY)" + echo " --disable-unicode disable unicode support to build win9x" + echo " version (Win32 ONLY)" echo " --disable-network disable network support" echo " --disable-assert disable asserts (continue on errors)" echo " --disable-strip disable any possible stripping" diff -r d2a6acdbd665 -r 197cb8c6ae17 docs/landscape.html --- a/docs/landscape.html Sun Sep 23 07:37:38 2007 +0000 +++ b/docs/landscape.html Sat Oct 06 22:30:24 2007 +0000 @@ -973,7 +973,7 @@
  • m2: index into the array of industries
  • -
  • m5: type:
    +
  • m5: type (plus m6 bit 2):
    (note: this is not the same as the industry type, which is stored in the array of industries) @@ -1272,9 +1272,17 @@
    + + AF..1FF  + NewGRF industries industry +
  • m6 bits 1..0 : Tropic zone definition
  • +
  • m3: animation state
  • +
  • m4: animation loop
  • +
  • m6 bits 3..5: random triggers (NewGRF)
  • +
  • m7: random bits (NewGRF)
  • diff -r d2a6acdbd665 -r 197cb8c6ae17 docs/landscape_grid.html --- a/docs/landscape_grid.html Sun Sep 23 07:37:38 2007 +0000 +++ b/docs/landscape_grid.html Sat Oct 06 22:30:24 2007 +0000 @@ -200,41 +200,17 @@ OOOO OOOO - 8 + 8 industry XXXX XXXX XOOX XXXX XXXX XXXX XXXX XXXX - OOOO OOOO - OOOO OOOO - XXXX XXXX - OOOO OOXX - OOOO OOOO - - - bubble/sugar/toffee,
    - gold/copper/coal,
    - oil wells, power station - -inherit- - XOOO OOOO - -inherit- - XXXX XXXX - OOOO OOOO - -inherit- - -inherit- - OOOO OOOO - - - toy factory - -inherit- - XOOO OOOO - -inherit- XXXX XXXX XXXX XXXX - -inherit- - -inherit- - OOOO OOOO + XXXX XXXX + OOXX XXXX + XXXX XXXX 9 diff -r d2a6acdbd665 -r 197cb8c6ae17 projects/openttd.vcproj --- a/projects/openttd.vcproj Sun Sep 23 07:37:38 2007 +0000 +++ b/projects/openttd.vcproj Sat Oct 06 22:30:24 2007 +0000 @@ -327,6 +327,9 @@ RelativePath=".\..\src\rev.cpp"> + + + RelativePath=".\..\src\blitter\32bpp_optimized.cpp"> + RelativePath=".\..\src\blitter\32bpp_optimized.hpp"> diff -r d2a6acdbd665 -r 197cb8c6ae17 projects/openttd_vs80.vcproj --- a/projects/openttd_vs80.vcproj Sun Sep 23 07:37:38 2007 +0000 +++ b/projects/openttd_vs80.vcproj Sat Oct 06 22:30:24 2007 +0000 @@ -668,6 +668,10 @@ > + + @@ -1996,14 +2000,14 @@ > + + - - diff -r d2a6acdbd665 -r 197cb8c6ae17 readme.txt --- a/readme.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/readme.txt Sat Oct 06 22:30:24 2007 +0000 @@ -10,7 +10,7 @@ 2.0) Contacting * 2.1 Reporting Bugs 3.0) Supported Platforms -4.0) Running OpenTTD +4.0) Installing and running OpenTTD 5.0) OpenTTD features 6.0) Configuration File 7.0) Compiling @@ -80,12 +80,19 @@ Windows - Win32 GDI (faster) or SDL -4.0) Running OpenTTD: ----- ---------------- +4.0) Installing and running OpenTTD: +---- ------------------------------- + +Installing OpenTTD is fairly straightforward. Either you have downloaded an +archive which you have to extract to a directory where you want OpenTTD to +be installed, or you have downloaded an installer, which will automatically +extract OpenTTD in the given directory. Before you run OpenTTD, you need to put the game's datafiles into the data/ subdirectory. You need the following files from the original version -of TTD as OpenTTD makes use of the original TTD artwork. +of TTD as OpenTTD makes use of the original TTD artwork. The Windows +installer optionally can copy these files from your Transport Tycoon Deluxe +CD-ROM. List of the required files: sample.cat @@ -103,9 +110,6 @@ If you want music you need to copy the gm/ folder from Windows TTD into your OpenTTD folder, not your data folder. -You can change the data path (which contains savegames as well) in -Makefile.config by setting DATA_DIR_PREFIX and USE_HOMEDIR. - 5.0) OpenTTD features: ---- ----------------- @@ -119,7 +123,6 @@ Several important non-standard controls: * Use Ctrl to place semaphore signals -* Ctrl-D toggles double mode in the Windows version * Ingame console. More information at http://wiki.openttd.org/index.php/Console @@ -210,10 +213,6 @@ * Please contact the development team before beginning the translation process! This avoids double work, as someone else may have already started translating to the same language. - * Translators must use the character set ISO 8859-15. - Otherwise, some characters will not display correctly in the game. - * Currently it is not possible to translate into character sets other than - Latin. 8.2) Translation: ---- ------------------- @@ -306,7 +305,6 @@ Thanks to: Josef Drexler - For his great work on TTDPatch. Marcin Grzegorczyk - For his TTDPatch work and documentation of TTD internals and graphics (signals and track foundations) - Matthijs Kooijman (blathijs) - For his many patches, suggestions and major work on maprewrite Petr Baudis (pasky) - Many patches, newgrf support, etc. Simon Sasburg (HackyKid) - For the many bugfixes he has blessed us with (and future PBS) Stefan Meißner (sign_de) - For his work on the console diff -r d2a6acdbd665 -r 197cb8c6ae17 source.list --- a/source.list Sun Sep 23 07:37:38 2007 +0000 +++ b/source.list Sat Oct 06 22:30:24 2007 +0000 @@ -58,6 +58,7 @@ queue.cpp rail.cpp rev.cpp +road.cpp saveload.cpp screenshot.cpp #if SDL @@ -418,8 +419,8 @@ blitter/32bpp_anim.hpp blitter/32bpp_base.cpp blitter/32bpp_base.hpp +blitter/32bpp_optimized.cpp blitter/32bpp_optimized.hpp -blitter/32bpp_optimized.cpp blitter/32bpp_simple.cpp blitter/32bpp_simple.hpp blitter/8bpp_base.cpp diff -r d2a6acdbd665 -r 197cb8c6ae17 src/aircraft.h --- a/src/aircraft.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/aircraft.h Sat Oct 06 22:30:24 2007 +0000 @@ -33,20 +33,29 @@ return v->subtype <= AIR_AIRCRAFT; } -/** Checks if an aircraft is buildable at the tile in question +/** Checks if an aircraft can use the station in question * @param engine The engine to test - * @param tile The tile where the hangar is - * @return true if the aircraft can be build + * @param st The station + * @return true if the aircraft can use the station */ -static inline bool IsAircraftBuildableAtStation(EngineID engine, TileIndex tile) +static inline bool CanAircraftUseStation(EngineID engine, const Station *st) { - const Station *st = GetStationByTile(tile); const AirportFTAClass *apc = st->Airport(); const AircraftVehicleInfo *avi = AircraftVehInfo(engine); return (apc->flags & (avi->subtype & AIR_CTOL ? AirportFTAClass::AIRPLANES : AirportFTAClass::HELICOPTERS)) != 0; } +/** Checks if an aircraft can use the station at the tile in question + * @param engine The engine to test + * @param tile The tile where the station is + * @return true if the aircraft can use the station + */ +static inline bool CanAircraftUseStation(EngineID engine, TileIndex tile) +{ + return CanAircraftUseStation(engine, GetStationByTile(tile)); +} + /** * Calculates cargo capacity based on an aircraft's passenger * and mail capacities. diff -r d2a6acdbd665 -r 197cb8c6ae17 src/aircraft_cmd.cpp --- a/src/aircraft_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/aircraft_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -283,7 +283,7 @@ SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); /* Prevent building aircraft types at places which can't handle them */ - if (!IsAircraftBuildableAtStation(p1, tile)) return CMD_ERROR; + if (!CanAircraftUseStation(p1, tile)) return CMD_ERROR; /* Allocate 2 or 3 vehicle structs, depending on type * vl[0] = aircraft, vl[1] = shadow, [vl[2] = rotor] */ @@ -365,7 +365,7 @@ v->cargo_type = cargo; - if (HASBIT(EngInfo(p1)->callbackmask, CBM_REFIT_CAPACITY)) { + if (HASBIT(EngInfo(p1)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) { callback = GetVehicleCallback(CBID_VEHICLE_REFIT_CAPACITY, 0, 0, v->engine_type, v); } @@ -646,7 +646,7 @@ /* Check the refit capacity callback */ uint16 callback = CALLBACK_FAILED; - if (HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_REFIT_CAPACITY)) { + if (HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) { /* Back up the existing cargo type */ CargoID temp_cid = v->cargo_type; byte temp_subtype = v->cargo_subtype; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/aircraft_gui.cpp --- a/src/aircraft_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/aircraft_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -95,7 +95,7 @@ if (v->tile == _backup_orders_tile) { _backup_orders_tile = 0; - RestoreVehicleOrders(v, _backup_orders_data); + RestoreVehicleOrders(v); } ShowVehicleViewWindow(v); } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/articulated_vehicles.cpp --- a/src/articulated_vehicles.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/articulated_vehicles.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -17,7 +17,7 @@ uint CountArticulatedParts(EngineID engine_type, bool purchase_window) { - if (!HASBIT(EngInfo(engine_type)->callbackmask, CBM_ARTIC_ENGINE)) return 0; + if (!HASBIT(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return 0; Vehicle *v = NULL;; if (!purchase_window) { @@ -41,7 +41,7 @@ const Vehicle *v = vl[0]; Vehicle *u = vl[0]; - if (!HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_ARTIC_ENGINE)) return; + if (!HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return; for (uint i = 1; i < MAX_UVALUE(EngineID); i++) { uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, v->engine_type, v); diff -r d2a6acdbd665 -r 197cb8c6ae17 src/autoslope.h --- a/src/autoslope.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/autoslope.h Sat Oct 06 22:30:24 2007 +0000 @@ -36,7 +36,9 @@ */ static inline bool AutoslopeEnabled() { - return (_patches.autoslope && IsValidPlayer(_current_player)); + return (_patches.autoslope && + (IsValidPlayer(_current_player) || + (_current_player == OWNER_NONE && _game_mode == GM_EDITOR) #define )); } #endif /* AUTOSLOPE_H */ diff -r d2a6acdbd665 -r 197cb8c6ae17 src/blitter/32bpp_base.cpp --- a/src/blitter/32bpp_base.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/blitter/32bpp_base.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -56,7 +56,7 @@ stepx = 1; } - if (x > 0 && y > 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); + if (x >= 0 && y >= 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); if (dx > dy) { frac = dy - (dx / 2); while (x != x2) { @@ -66,7 +66,7 @@ } x += stepx; frac += dy; - if (x > 0 && y > 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); + if (x >= 0 && y >= 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); } } else { frac = dx - (dy / 2); @@ -77,7 +77,7 @@ } y += stepy; frac += dx; - if (x > 0 && y > 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); + if (x >= 0 && y >= 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); } } } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/blitter/8bpp_base.cpp --- a/src/blitter/8bpp_base.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/blitter/8bpp_base.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -60,7 +60,7 @@ stepx = 1; } - if (x > 0 && y > 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); + if (x >= 0 && y >= 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); if (dx > dy) { frac = dy - (dx / 2); while (x != x2) { @@ -70,7 +70,7 @@ } x += stepx; frac += dy; - if (x > 0 && y > 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); + if (x >= 0 && y >= 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); } } else { frac = dx - (dy / 2); @@ -81,7 +81,7 @@ } y += stepy; frac += dx; - if (x > 0 && y > 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); + if (x >= 0 && y >= 0 && x < screen_width && y < screen_height) this->SetPixel(video, x, y, color); } } } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/build_vehicle_gui.cpp --- a/src/build_vehicle_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/build_vehicle_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -765,7 +765,7 @@ for (eid = AIRCRAFT_ENGINES_INDEX; eid < AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES; eid++) { if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_player)) continue; /* First VEH_END window_numbers are fake to allow a window open for all different types at once */ - if (w->window_number > VEH_END && !IsAircraftBuildableAtStation(eid, w->window_number)) continue; + if (w->window_number > VEH_END && !CanAircraftUseStation(eid, w->window_number)) continue; EngList_Add(&bv->eng_list, eid); if (eid == bv->sel_engine) sel_id = eid; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/clear_cmd.cpp --- a/src/clear_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/clear_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -314,7 +314,7 @@ return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE); } /* Check tiletype-specific things, and add extra-cost */ - CommandCost cost = _tile_type_procs[GetTileType(tile)]->terraform_tile_proc(tile, flags, z_min * TILE_HEIGHT, (Slope) tileh); + CommandCost cost = _tile_type_procs[GetTileType(tile)]->terraform_tile_proc(tile, flags | DC_AUTO, z_min * TILE_HEIGHT, (Slope) tileh); if (CmdFailed(cost)) { _terraform_err_tile = tile; return cost; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/depot_gui.cpp --- a/src/depot_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/depot_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -928,7 +928,7 @@ if (is_engine) { _backup_orders_tile = v->tile; - BackupVehicleOrders(v, _backup_orders_data); + BackupVehicleOrders(v); } switch (v->type) { diff -r d2a6acdbd665 -r 197cb8c6ae17 src/direction.h --- a/src/direction.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/direction.h Sat Oct 06 22:30:24 2007 +0000 @@ -165,6 +165,9 @@ DIAGDIRDIFF_90LEFT = 3 ///< 90 degrees left }; +/** Allow incrementing of DiagDirDiff variables */ +DECLARE_POSTFIX_INCREMENT(DiagDirDiff); + /** * Applies a difference on a DiagDirection * diff -r d2a6acdbd665 -r 197cb8c6ae17 src/economy.cpp --- a/src/economy.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/economy.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -972,7 +972,6 @@ static void FindSubsidyCargoRoute(FoundRoute *fr) { Industry *i; - const IndustrySpec *ind; int trans, total; CargoID cargo; @@ -980,15 +979,14 @@ fr->from = i = GetRandomIndustry(); if (i == NULL) return; - ind = GetIndustrySpec(i->type); /* Randomize cargo type */ - if (HASBIT(Random(), 0) && ind->produced_cargo[1] != CT_INVALID) { - cargo = ind->produced_cargo[1]; + if (HASBIT(Random(), 0) && i->produced_cargo[1] != CT_INVALID) { + cargo = i->produced_cargo[1]; trans = i->last_month_pct_transported[1]; total = i->last_month_production[1]; } else { - cargo = ind->produced_cargo[0]; + cargo = i->produced_cargo[0]; trans = i->last_month_pct_transported[0]; total = i->last_month_production[0]; } @@ -1015,17 +1013,12 @@ } else { /* The destination is an industry */ Industry *i2 = GetRandomIndustry(); - if (i2 == NULL) { - return; - } - - ind = GetIndustrySpec(i2->type); /* The industry must accept the cargo */ - if (i == i2 || - (cargo != ind->accepts_cargo[0] && - cargo != ind->accepts_cargo[1] && - cargo != ind->accepts_cargo[2])) { + if (i2 == NULL || i == i2 || + (cargo != i2->accepts_cargo[0] && + cargo != i2->accepts_cargo[1] && + cargo != i2->accepts_cargo[2])) { return; } fr->distance = DistanceManhattan(i->xy, i2->xy); @@ -1226,12 +1219,12 @@ indspec = GetIndustrySpec(ind->type); uint i; - for (i = 0; i < lengthof(indspec->accepts_cargo); i++) { - if (cargo_type == indspec->accepts_cargo[i]) break; + for (i = 0; i < lengthof(ind->accepts_cargo); i++) { + if (cargo_type == ind->accepts_cargo[i]) break; } /* Check if matching cargo has been found */ - if (i == lengthof(indspec->accepts_cargo)) continue; + if (i == lengthof(ind->accepts_cargo)) continue; if (HASBIT(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) { uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO, 0, GetReverseCargoTranslation(cargo_type, indspec->grf_prop.grffile), ind, ind->type, ind->xy); @@ -1529,7 +1522,7 @@ if (v->cargo_cap == 0) continue; byte load_amount = EngInfo(v->engine_type)->load_amount; - if (_patches.gradual_loading && HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_LOAD_AMOUNT)) { + if (_patches.gradual_loading && HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) { uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v); if (cb_load_amount != CALLBACK_FAILED) load_amount = cb_load_amount & 0xFF; } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/fileio.cpp --- a/src/fileio.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/fileio.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -296,6 +296,10 @@ snprintf(buf, lengthof(buf), "%s%s%s", _searchpaths[sp], _subdirs[subdir], filename); } +#if defined(WIN32) + if (mode[0] == 'r' && GetFileAttributes(OTTD2FS(buf)) == INVALID_FILE_ATTRIBUTES) return NULL; +#endif + f = fopen(buf, mode); #if !defined(WIN32) if (f == NULL) { diff -r d2a6acdbd665 -r 197cb8c6ae17 src/functions.h --- a/src/functions.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/functions.h Sat Oct 06 22:30:24 2007 +0000 @@ -132,7 +132,6 @@ bool ScrollMainWindowToTile(TileIndex tile, bool instant = false); bool ScrollMainWindowTo(int x, int y, bool instant = false); -void DrawSprite(SpriteID img, SpriteID pal, int x, int y); bool EnsureNoVehicle(TileIndex tile); bool EnsureNoVehicleOnGround(TileIndex tile); diff -r d2a6acdbd665 -r 197cb8c6ae17 src/gfx.cpp --- a/src/gfx.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/gfx.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -43,7 +43,7 @@ Colour _cur_palette[256]; byte _stringwidth_table[FS_END][224]; -static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode); +static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = NULL); FontSize _cur_fontsize; static FontSize _last_fontsize; @@ -139,6 +139,71 @@ blitter->DrawLine(dpi->dst_ptr, x, y, x2, y2, dpi->width, dpi->height, color); } +void GfxDrawLineUnscaled(int x, int y, int x2, int y2, int color) +{ + Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter(); + DrawPixelInfo *dpi = _cur_dpi; + + x -= dpi->left; + x2 -= dpi->left; + y -= dpi->top; + y2 -= dpi->top; + + /* Check clipping */ + if (x < 0 && x2 < 0) return; + if (y < 0 && y2 < 0) return; + if (x > dpi->width && x2 > dpi->width) return; + if (y > dpi->height && y2 > dpi->height) return; + + blitter->DrawLine(dpi->dst_ptr, UnScaleByZoom(x, dpi->zoom), UnScaleByZoom(y, dpi->zoom), + UnScaleByZoom(x2, dpi->zoom), UnScaleByZoom(y2, dpi->zoom), + UnScaleByZoom(dpi->width, dpi->zoom), UnScaleByZoom(dpi->height, dpi->zoom), color); +} + +/** + * Draws the projection of a parallelepiped. + * This can be used to draw boxes in world coordinates. + * + * @param x Screen X-coordinate of top front corner. + * @param y Screen Y-coordinate of top front corner. + * @param dx1 Screen X-length of first edge. + * @param dy1 Screen Y-length of first edge. + * @param dx2 Screen X-length of second edge. + * @param dy2 Screen Y-length of second edge. + * @param dx3 Screen X-length of third edge. + * @param dy3 Screen Y-length of third edge. + */ +void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3) +{ + /* .... + * .. .... + * .. .... + * .. ^ + * <--__(dx1,dy1) /(dx2,dy2) + * : --__ / : + * : --__ / : + * : *(x,y) : + * : | : + * : | .. + * .... |(dx3,dy3) + * .... | .. + * ....V. + */ + + static const byte color = 255; + + GfxDrawLineUnscaled(x, y, x + dx1, y + dy1, color); + GfxDrawLineUnscaled(x, y, x + dx2, y + dy2, color); + GfxDrawLineUnscaled(x, y, x + dx3, y + dy3, color); + + GfxDrawLineUnscaled(x + dx1, y + dy1, x + dx1 + dx2, y + dy1 + dy2, color); + GfxDrawLineUnscaled(x + dx1, y + dy1, x + dx1 + dx3, y + dy1 + dy3, color); + GfxDrawLineUnscaled(x + dx2, y + dy2, x + dx2 + dx1, y + dy2 + dy1, color); + GfxDrawLineUnscaled(x + dx2, y + dy2, x + dx2 + dx3, y + dy2 + dy3, color); + GfxDrawLineUnscaled(x + dx3, y + dy3, x + dx3 + dx1, y + dy3 + dy1, color); + GfxDrawLineUnscaled(x + dx3, y + dy3, x + dx3 + dx2, y + dy3 + dy2, color); +} + /** Truncate a given string to a maximum width if neccessary. * If the string is truncated, add three dots ('...') to show this. @@ -587,24 +652,33 @@ return DoDrawString(buffer, x, y, color); } -void DrawSprite(SpriteID img, SpriteID pal, int x, int y) +void DrawSprite(SpriteID img, SpriteID pal, int x, int y, const SubSprite *sub) { if (HASBIT(img, PALETTE_MODIFIER_TRANSPARENT)) { _color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1; - GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_TRANSPARENT); + GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_TRANSPARENT, sub); } else if (pal != PAL_NONE) { _color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1; - GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_COLOUR_REMAP); + GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_COLOUR_REMAP, sub); } else { - GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_NORMAL); + GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_NORMAL, sub); } } -static inline void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode) +static inline void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub) { const DrawPixelInfo *dpi = _cur_dpi; Blitter::BlitterParams bp; + /* Amount of pixels to clip from the source sprite */ + int clip_left = (sub != NULL ? max(0, -sprite->x_offs + sub->left ) : 0); + int clip_top = (sub != NULL ? max(0, -sprite->y_offs + sub->top ) : 0); + int clip_right = (sub != NULL ? max(0, sprite->width - (-sprite->x_offs + sub->right + 1)) : 0); + int clip_bottom = (sub != NULL ? max(0, sprite->height - (-sprite->y_offs + sub->bottom + 1)) : 0); + + if (clip_left + clip_right >= sprite->width) return; + if (clip_top + clip_bottom >= sprite->height) return; + /* Move to the correct offset */ x += sprite->x_offs; y += sprite->y_offs; @@ -613,12 +687,16 @@ bp.sprite = sprite->data; bp.sprite_width = sprite->width; bp.sprite_height = sprite->height; - bp.width = UnScaleByZoom(sprite->width, dpi->zoom); - bp.height = UnScaleByZoom(sprite->height, dpi->zoom); + bp.width = UnScaleByZoom(sprite->width - clip_left - clip_right, dpi->zoom); + bp.height = UnScaleByZoom(sprite->height - clip_top - clip_bottom, dpi->zoom); bp.top = 0; bp.left = 0; - bp.skip_left = 0; - bp.skip_top = 0; + bp.skip_left = UnScaleByZoom(clip_left, dpi->zoom); + bp.skip_top = UnScaleByZoom(clip_top, dpi->zoom); + + x += ScaleByZoom(bp.skip_left, dpi->zoom); + y += ScaleByZoom(bp.skip_top, dpi->zoom); + bp.dst = dpi->dst_ptr; bp.pitch = dpi->pitch; bp.remap = _color_remap_ptr; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/gfx.h --- a/src/gfx.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/gfx.h Sat Oct 06 22:30:24 2007 +0000 @@ -242,6 +242,16 @@ void RedrawScreenRect(int left, int top, int right, int bottom); void GfxScroll(int left, int top, int width, int height, int xo, int yo); +/** + * Used to only draw a part of the sprite. + * Draw the subsprite in the rect (sprite_x_offset + left, sprite_y_offset + top) to (sprite_x_offset + right, sprite_y_offset + bottom). + * Both corners are included in the drawing area. + */ +struct SubSprite { + int left, top, right, bottom; +}; + +void DrawSprite(SpriteID img, SpriteID pal, int x, int y, const SubSprite *sub = NULL); /* XXX doesn't really belong here, but the only * consumers always use it in conjunction with DoDrawString() */ @@ -268,6 +278,7 @@ void GfxFillRect(int left, int top, int right, int bottom, int color); void GfxDrawLine(int left, int top, int right, int bottom, int color); +void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3); BoundingRect GetStringBoundingBox(const char *str); uint32 FormatStringLinebreaks(char *str, int maxw); diff -r d2a6acdbd665 -r 197cb8c6ae17 src/industry.h --- a/src/industry.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/industry.h Sat Oct 06 22:30:24 2007 +0000 @@ -9,17 +9,17 @@ #include "helpers.hpp" #include "newgrf_storage.h" -typedef byte IndustryGfx; +typedef uint16 IndustryGfx; typedef uint8 IndustryType; enum { INVALID_INDUSTRY = 0xFFFF, NEW_INDUSTRYOFFSET = 37, ///< original number of industries - NUM_INDUSTRYTYPES = 37, ///< total number of industries, new and old + NUM_INDUSTRYTYPES = 64, ///< total number of industries, new and old INDUSTRYTILE_NOANIM = 0xFF, ///< flag to mark industry tiles as having no animation NEW_INDUSTRYTILEOFFSET = 175, ///< original number of tiles INVALID_INDUSTRYTYPE = NUM_INDUSTRYTYPES, ///< one above amount is considered invalid - NUM_INDUSTRYTILES = NEW_INDUSTRYTILEOFFSET, ///< total number of industry tiles, new and old + NUM_INDUSTRYTILES = 512, ///< total number of industry tiles, new and old INVALID_INDUSTRYTILE = NUM_INDUSTRYTILES, ///< one above amount is considered invalid INDUSTRY_COMPLETED = 3, ///< final stage of industry construction. }; @@ -105,10 +105,12 @@ byte width; byte height; const Town *town; ///< Nearest town + CargoID produced_cargo[2]; ///< 2 production cargo slots uint16 produced_cargo_waiting[2]; ///< amount of cargo produced per cargo uint16 incoming_cargo_waiting[3]; ///< incoming cargo waiting to be processed byte production_rate[2]; ///< production rate for each cargo byte prod_level; ///< general production level + CargoID accepts_cargo[3]; ///< 3 input cargo slots uint16 this_month_production[2]; ///< stats of this month's production per cargo uint16 this_month_transported[2]; ///< stats of this month's transport per cargo byte last_month_pct_transported[2]; ///< percentage transported per cargo in the last full month diff -r d2a6acdbd665 -r 197cb8c6ae17 src/industry_cmd.cpp --- a/src/industry_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/industry_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -65,11 +65,16 @@ /* once performed, enable only the current climate industries */ for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) { - _industry_specs[i].enabled = HASBIT(_origin_industry_specs[i].climate_availability, _opt.landscape); + _industry_specs[i].enabled = i < NEW_INDUSTRYOFFSET && + HASBIT(_origin_industry_specs[i].climate_availability, _opt.landscape); } memset(&_industry_tile_specs, 0, sizeof(_industry_tile_specs)); memcpy(&_industry_tile_specs, &_origin_industry_tile_specs, sizeof(_origin_industry_tile_specs)); + + /* Reset any overrides that have been set. */ + _industile_mngr.ResetOverride(); + _industry_mngr.ResetOverride(); } void ResetIndustryCreationProbility(IndustryType type) @@ -357,7 +362,8 @@ for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) { CargoID a = accepts_cargo[i]; - if (a != CT_INVALID) ac[a] = acceptance[i]; + /* Only set the value once. */ + if (a != CT_INVALID && ac[a] == 0) ac[a] = acceptance[i]; } } @@ -385,6 +391,7 @@ */ if ((_current_player != OWNER_WATER && _game_mode != GM_EDITOR && !_cheats.magic_bulldozer.value) || + ((flags & DC_AUTO) != 0) || (_current_player == OWNER_WATER && (indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER))) { SetDParam(0, indspec->name); return_cmd_error(STR_4800_IN_THE_WAY); @@ -409,7 +416,7 @@ i->this_month_production[0] += cw; - am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[0], cw); + am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[0], cw); i->this_month_transported[0] += am; if (am != 0 && !StartStopIndustryTileAnimation(i, IAT_INDUSTRY_DISTRIBUTES_CARGO)) { uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production; @@ -431,7 +438,7 @@ i->this_month_production[1] += cw; - am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[1], cw); + am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[1], cw); i->this_month_transported[1] += am; } } @@ -819,7 +826,7 @@ static void GetProducedCargo_Industry(TileIndex tile, CargoID *b) { - const IndustrySpec *i = GetIndustrySpec(GetIndustryByTile(tile)->type); + const Industry *i = GetIndustryByTile(tile); b[0] = i->produced_cargo[0]; b[1] = i->produced_cargo[1]; @@ -1176,9 +1183,27 @@ return t; } -static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, int type, bool *custom_shape_check = NULL) +bool IsSlopeRefused(Slope current, Slope refused) +{ + if (current != SLOPE_FLAT) { + if (refused & SLOPE_STEEP) return true; + + Slope t = ComplementSlope(current); + + if (refused & 1 && (t & SLOPE_NW)) return false; + if (refused & 2 && (t & SLOPE_NE)) return false; + if (refused & 4 && (t & SLOPE_SW)) return false; + if (refused & 8 && (t & SLOPE_SE)) return false; + } + + return false; +} + +static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, uint itspec_index, int type, bool *custom_shape_check = NULL) { _error_message = STR_0239_SITE_UNSUITABLE; + bool refused_slope = false; + bool custom_shape = false; do { IndustryGfx gfx = GetTranslatedIndustryTileID(it->gfx); @@ -1203,8 +1228,8 @@ IndustyBehaviour ind_behav = GetIndustrySpec(type)->behaviour; if (HASBIT(its->callback_flags, CBM_INDT_SHAPE_CHECK)) { - if (custom_shape_check != NULL) *custom_shape_check = true; - if (!PerformIndustryTileSlopeCheck(cur_tile, its, type, gfx)) return false; + custom_shape = true; + if (!PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, itspec_index)) return false; } else { if (ind_behav & INDUSTRYBEH_BUILT_ONWATER) { /* As soon as the tile is not water, bail out. @@ -1219,24 +1244,7 @@ tileh = GetTileSlope(cur_tile, NULL); if (IsSteepSlope(tileh)) return false; - if (_patches.land_generator != LG_TERRAGENESIS || !_generating_world) { - /* It is almost impossible to have a fully flat land in TG, so what we - * do is that we check if we can make the land flat later on. See - * CheckIfCanLevelIndustryPlatform(). */ - if (tileh != SLOPE_FLAT) { - Slope t; - byte bits = its->slopes_refused; - - if (bits & 0x10) return false; - - t = ComplementSlope(tileh); - - if (bits & 1 && (t & SLOPE_NW)) return false; - if (bits & 2 && (t & SLOPE_NE)) return false; - if (bits & 4 && (t & SLOPE_SW)) return false; - if (bits & 8 && (t & SLOPE_SE)) return false; - } - } + refused_slope |= IsSlopeRefused(tileh, its->slopes_refused); } } @@ -1252,7 +1260,12 @@ } } while ((++it)->ti.x != -0x80); - return true; + if (custom_shape_check != NULL) *custom_shape_check = custom_shape; + + /* It is almost impossible to have a fully flat land in TG, so what we + * do is that we check if we can make the land flat later on. See + * CheckIfCanLevelIndustryPlatform(). */ + return !refused_slope || (_patches.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape); } static bool CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t) @@ -1318,6 +1331,7 @@ /* Finds dimensions of largest variant of this industry */ do { + if (it->gfx == 0xFF) continue; // FF been a marquer for a check on clear water, skip it if (it->ti.x > max_x) max_x = it->ti.x; if (it->ti.y > max_y) max_y = it->ti.y; } while ((++it)->ti.x != MKEND); @@ -1334,15 +1348,26 @@ /* Check if we don't leave the map */ if (TileX(cur_tile) == 0 || TileY(cur_tile) == 0 || TileX(cur_tile) + size_x >= MapMaxX() || TileY(cur_tile) + size_y >= MapMaxY()) return false; + /* _current_player is OWNER_NONE for randomly generated industries and in editor, or the player who funded or prospected the industry. + * Perform terraforming as OWNER_TOWN to disable autoslope. */ + PlayerID old_player = _current_player; + _current_player = OWNER_TOWN; + BEGIN_TILE_LOOP(tile_walk, size_x, size_y, cur_tile) { curh = TileHeight(tile_walk); if (curh != h) { /* This tile needs terraforming. Check if we can do that without * damaging the surroundings too much. */ - if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) return false; + if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) { + _current_player = old_player; + return false; + } /* This is not 100% correct check, but the best we can do without modifying the map. * What is missing, is if the difference in height is more than 1.. */ - if (CmdFailed(DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND))) return false; + if (CmdFailed(DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND))) { + _current_player = old_player; + return false; + } } } END_TILE_LOOP(tile_walk, size_x, size_y, cur_tile) @@ -1360,6 +1385,7 @@ } END_TILE_LOOP(tile_walk, size_x, size_y, cur_tile) } + _current_player = old_player; return true; } @@ -1377,7 +1403,7 @@ /* check if an industry that accepts the same goods is nearby */ if (DistanceMax(tile, i->xy) <= 14 && indspec->accepts_cargo[0] != CT_INVALID && - indspec->accepts_cargo[0] == GetIndustrySpec(i->type)->accepts_cargo[0] && ( + indspec->accepts_cargo[0] == i->accepts_cargo[0] && ( _game_mode != GM_EDITOR || !_patches.same_industry_close || !_patches.multiple_industry_per_town @@ -1400,17 +1426,23 @@ { const IndustrySpec *indspec = GetIndustrySpec(type); uint32 r; - int j; + uint j; i->xy = tile; i->width = i->height = 0; i->type = type; IncIndustryTypeCount(type); + i->produced_cargo[0] = indspec->produced_cargo[0]; + i->produced_cargo[1] = indspec->produced_cargo[1]; + i->accepts_cargo[0] = indspec->accepts_cargo[0]; + i->accepts_cargo[1] = indspec->accepts_cargo[1]; + i->accepts_cargo[2] = indspec->accepts_cargo[2]; i->production_rate[0] = indspec->production_rate[0]; i->production_rate[1] = indspec->production_rate[1]; - if (_patches.smooth_economy) { + /* don't use smooth economy for industries using production callbacks */ + if (_patches.smooth_economy && !(HASBIT(indspec->callback_flags, CBM_IND_PRODUCTION_256_TICKS) || HASBIT(indspec->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL))) { i->production_rate[0] = min((RandomRange(256) + 128) * i->production_rate[0] >> 8 , 255); i->production_rate[1] = min((RandomRange(256) + 128) * i->production_rate[1] >> 8 , 255); } @@ -1439,6 +1471,30 @@ i->last_month_production[0] = i->production_rate[0] * 8; i->last_month_production[1] = i->production_rate[1] * 8; i->founder = _current_player; + + if (HASBIT(indspec->callback_flags, CBM_IND_DECIDE_COLOUR)) { + uint16 res = GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR, 0, 0, i, type, INVALID_TILE); + if (res != CALLBACK_FAILED) i->random_color = GB(res, 0, 4); + } + + if (HASBIT(indspec->callback_flags, CBM_IND_INPUT_CARGO_TYPES)) { + for (j = 0; j < lengthof(i->accepts_cargo); j++) i->accepts_cargo[j] = CT_INVALID; + for (j = 0; j < lengthof(i->accepts_cargo); j++) { + uint16 res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE); + if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break; + i->accepts_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile); + } + } + + if (HASBIT(indspec->callback_flags, CBM_IND_OUTPUT_CARGO_TYPES)) { + for (j = 0; j < lengthof(i->produced_cargo); j++) i->produced_cargo[j] = CT_INVALID; + for (j = 0; j < lengthof(i->produced_cargo); j++) { + uint16 res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE); + if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break; + i->produced_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile); + } + } + i->construction_date = _date; i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR : (_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY); @@ -1496,7 +1552,7 @@ const IndustryTileTable *it = indspec->table[itspec_index]; bool custom_shape_check = false; - if (!CheckIfIndustryTilesAreFree(tile, it, type, &custom_shape_check)) return NULL; + if (!CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, &custom_shape_check)) return NULL; if (HASBIT(GetIndustrySpec(type)->callback_flags, CBM_IND_LOCATION)) { if (!CheckIfCallBackAllowsCreation(tile, type, itspec_index)) return NULL; @@ -1537,7 +1593,6 @@ { int num; const IndustryTileTable * const *itt; - const IndustryTileTable *it; const IndustrySpec *indspec; SET_EXPENSES_TYPE(EXPENSES_OTHER); @@ -1581,7 +1636,7 @@ do { if (--num < 0) return_cmd_error(STR_0239_SITE_UNSUITABLE); - } while (!CheckIfIndustryTilesAreFree(tile, it = itt[num], p1)); + } while (!CheckIfIndustryTilesAreFree(tile, itt[num], num, p1)); if (CreateNewIndustryHelper(tile, p1, flags, indspec, num) == NULL) return CMD_ERROR; } @@ -1699,10 +1754,9 @@ { byte pct; bool refresh = false; - const IndustrySpec *indsp = GetIndustrySpec(i->type); - for (byte j = 0; j < lengthof(indsp->produced_cargo); j++) { - if (indsp->produced_cargo[j] != CT_INVALID) { + for (byte j = 0; j < lengthof(i->produced_cargo); j++) { + if (i->produced_cargo[j] != CT_INVALID) { pct = 0; if (i->this_month_production[j] != 0) { i->last_prod_year = _cur_year; @@ -1809,6 +1863,8 @@ const IndustrySpec *indspec = GetIndustrySpec(i->type); bool standard = true; bool suppress_message = false; + /* don't use smooth economy for industries using production callbacks */ + bool smooth_economy = _patches.smooth_economy && !(HASBIT(indspec->callback_flags, CBM_IND_PRODUCTION_256_TICKS) || HASBIT(indspec->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL)); byte div = 0; byte mul = 0; @@ -1835,7 +1891,7 @@ } } - if (standard && monthly != _patches.smooth_economy) return; + if (standard && monthly != smooth_economy) return; if (standard && indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return; @@ -1843,9 +1899,9 @@ /* decrease or increase */ bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _opt.landscape == LT_TEMPERATE; - if (_patches.smooth_economy) { + if (smooth_economy) { closeit = true; - for (byte j = 0; j < 2 && indspec->produced_cargo[j] != CT_INVALID; j++){ + for (byte j = 0; j < 2 && i->produced_cargo[j] != CT_INVALID; j++){ uint32 r = Random(); int old_prod, new_prod, percent; int mag; @@ -1874,7 +1930,7 @@ mag = abs(percent); if (mag >= 10) { SetDParam(2, mag); - SetDParam(0, GetCargo(indspec->produced_cargo[j])->name); + SetDParam(0, GetCargo(i->produced_cargo[j])->name); SetDParam(1, i->index); AddNewsItem( percent >= 0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN, @@ -1896,7 +1952,7 @@ } if (standard && indspec->life_type & INDUSTRYLIFE_PROCESSING) { - if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1, _patches.smooth_economy ? 180 : 2)) { + if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1, smooth_economy ? 180 : 2)) { closeit = true; } } @@ -2018,7 +2074,7 @@ } } } - return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); // funny magic bulldozer + return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); } extern const TileTypeProcs _tile_type_industry_procs = { @@ -2045,10 +2101,12 @@ SLE_VAR(Industry, height, SLE_UINT8), SLE_REF(Industry, town, REF_TOWN), SLE_CONDNULL( 2, 2, 60), ///< used to be industry's produced_cargo + SLE_CONDARR(Industry, produced_cargo, SLE_UINT8, 2, 78, SL_MAX_VERSION), SLE_CONDARR(Industry, incoming_cargo_waiting, SLE_UINT16, 3, 70, SL_MAX_VERSION), SLE_ARR(Industry, produced_cargo_waiting, SLE_UINT16, 2), SLE_ARR(Industry, production_rate, SLE_UINT8, 2), SLE_CONDNULL( 3, 2, 60), ///< used to be industry's accepts_cargo + SLE_CONDARR(Industry, accepts_cargo, SLE_UINT8, 3, 78, SL_MAX_VERSION), SLE_VAR(Industry, prod_level, SLE_UINT8), SLE_ARR(Industry, this_month_production, SLE_UINT16, 2), SLE_ARR(Industry, this_month_transported, SLE_UINT16, 2), diff -r d2a6acdbd665 -r 197cb8c6ae17 src/industry_gui.cpp --- a/src/industry_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/industry_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -118,7 +118,7 @@ indsp = GetIndustrySpec(ind); if (indsp->enabled && (!indsp->IsRawIndustry() || _game_mode == GM_EDITOR)) { _fund_gui.index[_fund_gui.count] = ind; - _fund_gui.enabled[_fund_gui.count] = CheckIfCallBackAllowsAvailability(ind, IACT_USERCREATION); + _fund_gui.enabled[_fund_gui.count] = (_game_mode == GM_EDITOR) || CheckIfCallBackAllowsAvailability(ind, IACT_USERCREATION); _fund_gui.count++; } } @@ -128,7 +128,7 @@ indsp = GetIndustrySpec(ind); if (indsp->enabled && indsp->IsRawIndustry()) { _fund_gui.index[_fund_gui.count] = ind; - _fund_gui.enabled[_fund_gui.count] = CheckIfCallBackAllowsAvailability(ind, IACT_USERCREATION); + _fund_gui.enabled[_fund_gui.count] = (_game_mode == GM_EDITOR) || CheckIfCallBackAllowsAvailability(ind, IACT_USERCREATION); _fund_gui.count++; } } @@ -390,9 +390,8 @@ static inline bool IsProductionAlterable(const Industry *i) { - const IndustrySpec *ind = GetIndustrySpec(i->type); return ((_game_mode == GM_EDITOR || _cheats.setup_prod.value) && - (ind->accepts_cargo[0] == CT_INVALID || ind->accepts_cargo[0] == CT_VALUABLES)); + (i->accepts_cargo[0] == CT_INVALID || i->accepts_cargo[0] == CT_VALUABLES)); } /** Information to store about the industry window */ @@ -410,21 +409,22 @@ switch (e->event) { case WE_CREATE: { /* Count the number of lines that we need to resize the GUI with */ - const IndustrySpec *ind = GetIndustrySpec(GetIndustry(w->window_number)->type); + const Industry *i = GetIndustry(w->window_number); + const IndustrySpec *ind = GetIndustrySpec(i->type); int lines = -3; if (HASBIT(ind->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HASBIT(ind->callback_flags, CBM_IND_PRODUCTION_256_TICKS)) { - for (uint j = 0; j < 3 && ind->accepts_cargo[j] != CT_INVALID; j++) { + for (uint j = 0; j < lengthof(i->accepts_cargo) && i->accepts_cargo[j] != CT_INVALID; j++) { if (j == 0) lines++; lines++; } - } else if (ind->accepts_cargo[0] != CT_INVALID) { + } else if (i->accepts_cargo[0] != CT_INVALID) { lines++; } - for (uint j = 0; j < 2 && ind->produced_cargo[j] != CT_INVALID; j++) { + for (uint j = 0; j < lengthof(i->produced_cargo) && i->produced_cargo[j] != CT_INVALID; j++) { if (j == 0) { - if (ind->accepts_cargo[0] != CT_INVALID) lines++; + if (i->accepts_cargo[0] != CT_INVALID) lines++; lines++; } lines++; @@ -448,26 +448,26 @@ DrawWindowWidgets(w); if (HASBIT(ind->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HASBIT(ind->callback_flags, CBM_IND_PRODUCTION_256_TICKS)) { - for (uint j = 0; j < 3 && ind->accepts_cargo[j] != CT_INVALID; j++) { + for (uint j = 0; j < lengthof(i->accepts_cargo) && i->accepts_cargo[j] != CT_INVALID; j++) { if (j == 0) { DrawString(2, y, STR_INDUSTRY_WINDOW_WAITING_FOR_PROCESSING, 0); y += 10; } - SetDParam(0, ind->accepts_cargo[j]); + SetDParam(0, i->accepts_cargo[j]); SetDParam(1, i->incoming_cargo_waiting[j]); DrawString(4, y, STR_INDUSTRY_WINDOW_WAITING_STOCKPILE_CARGO, 0); y += 10; } - } else if (ind->accepts_cargo[0] != CT_INVALID) { + } else if (i->accepts_cargo[0] != CT_INVALID) { StringID str; - SetDParam(0, GetCargo(ind->accepts_cargo[0])->name); + SetDParam(0, GetCargo(i->accepts_cargo[0])->name); str = STR_4827_REQUIRES; - if (ind->accepts_cargo[1] != CT_INVALID) { - SetDParam(1, GetCargo(ind->accepts_cargo[1])->name); + if (i->accepts_cargo[1] != CT_INVALID) { + SetDParam(1, GetCargo(i->accepts_cargo[1])->name); str = STR_4828_REQUIRES; - if (ind->accepts_cargo[2] != CT_INVALID) { - SetDParam(2, GetCargo(ind->accepts_cargo[2])->name); + if (i->accepts_cargo[2] != CT_INVALID) { + SetDParam(2, GetCargo(i->accepts_cargo[2])->name); str = STR_4829_REQUIRES; } } @@ -475,15 +475,15 @@ y += 10; } - for (uint j = 0; j < 2 && ind->produced_cargo[j] != CT_INVALID; j++) { + for (uint j = 0; j < lengthof(i->produced_cargo) && i->produced_cargo[j] != CT_INVALID; j++) { if (j == 0) { - if (ind->accepts_cargo[0] != CT_INVALID) y += 10; + if (i->accepts_cargo[0] != CT_INVALID) y += 10; DrawString(2, y, STR_482A_PRODUCTION_LAST_MONTH, 0); y += 10; WP(w, indview_d).production_offset_y = y; } - SetDParam(0, ind->produced_cargo[j]); + SetDParam(0, i->produced_cargo[j]); SetDParam(1, i->last_month_production[j]); SetDParam(2, i->last_month_pct_transported[j] * 100 >> 8); @@ -527,8 +527,7 @@ if (!IsProductionAlterable(i)) return; x = e->we.click.pt.x; line = (e->we.click.pt.y - WP(w, indview_d).production_offset_y) / 10; - if (e->we.click.pt.y >= WP(w, indview_d).production_offset_y && IS_INT_INSIDE(line, 0, 2) && - GetIndustrySpec(i->type)->produced_cargo[line] != CT_INVALID) { + if (e->we.click.pt.y >= WP(w, indview_d).production_offset_y && IS_INT_INSIDE(line, 0, 2) && i->produced_cargo[line] != CT_INVALID) { if (IS_INT_INSIDE(x, 5, 25) ) { /* Clicked buttons, decrease or increase production */ if (x < 15) { @@ -579,10 +578,8 @@ static void UpdateIndustryProduction(Industry *i) { - const IndustrySpec *ind = GetIndustrySpec(i->type); - - for (byte j = 0; j < lengthof(ind->produced_cargo); j++) { - if (ind->produced_cargo[j] != CT_INVALID) { + for (byte j = 0; j < lengthof(i->produced_cargo); j++) { + if (i->produced_cargo[j] != CT_INVALID) { i->last_month_production[j] = 8 * i->production_rate[j]; } } @@ -655,8 +652,6 @@ { const Industry* i = *(const Industry**)a; const Industry* j = *(const Industry**)b; - const IndustrySpec *ind_i = GetIndustrySpec(i->type); - const IndustrySpec *ind_j = GetIndustrySpec(j->type); int r; switch (_industry_sort_order >> 1) { @@ -670,10 +665,10 @@ break; case 2: /* Sort by Production */ - if (ind_i->produced_cargo[0] == CT_INVALID) { - r = (ind_j->produced_cargo[0] == CT_INVALID ? 0 : -1); + if (i->produced_cargo[0] == CT_INVALID) { + r = (j->produced_cargo[0] == CT_INVALID ? 0 : -1); } else { - if (ind_j->produced_cargo[0] == CT_INVALID) { + if (j->produced_cargo[0] == CT_INVALID) { r = 1; } else { r = @@ -684,23 +679,23 @@ break; case 3: /* Sort by transported fraction */ - if (ind_i->produced_cargo[0] == CT_INVALID) { - r = (ind_j->produced_cargo[0] == CT_INVALID ? 0 : -1); + if (i->produced_cargo[0] == CT_INVALID) { + r = (j->produced_cargo[0] == CT_INVALID ? 0 : -1); } else { - if (ind_j->produced_cargo[0] == CT_INVALID) { + if (j->produced_cargo[0] == CT_INVALID) { r = 1; } else { int pi; int pj; pi = i->last_month_pct_transported[0] * 100 >> 8; - if (ind_i->produced_cargo[1] != CT_INVALID) { + if (i->produced_cargo[1] != CT_INVALID) { int p = i->last_month_pct_transported[1] * 100 >> 8; if (p < pi) pi = p; } pj = j->last_month_pct_transported[0] * 100 >> 8; - if (ind_j->produced_cargo[1] != CT_INVALID) { + if (j->produced_cargo[1] != CT_INVALID) { int p = j->last_month_pct_transported[1] * 100 >> 8; if (p < pj) pj = p; } @@ -781,15 +776,14 @@ while (p < _num_industry_sort) { const Industry* i = _industry_sort[p]; - const IndustrySpec *ind = GetIndustrySpec(i->type); SetDParam(0, i->index); - if (ind->produced_cargo[0] != CT_INVALID) { - SetDParam(1, ind->produced_cargo[0]); + if (i->produced_cargo[0] != CT_INVALID) { + SetDParam(1, i->produced_cargo[0]); SetDParam(2, i->last_month_production[0]); - if (ind->produced_cargo[1] != CT_INVALID) { - SetDParam(3, ind->produced_cargo[1]); + if (i->produced_cargo[1] != CT_INVALID) { + SetDParam(3, i->produced_cargo[1]); SetDParam(4, i->last_month_production[1]); SetDParam(5, i->last_month_pct_transported[0] * 100 >> 8); SetDParam(6, i->last_month_pct_transported[1] * 100 >> 8); diff -r d2a6acdbd665 -r 197cb8c6ae17 src/industry_map.h --- a/src/industry_map.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/industry_map.h Sat Oct 06 22:30:24 2007 +0000 @@ -109,7 +109,7 @@ static inline byte GetIndustryConstructionStage(TileIndex tile) { assert(IsTileType(tile, MP_INDUSTRY)); - return GB(_m[tile].m1, 0, 2); + return IsIndustryCompleted(tile) ? (byte)INDUSTRY_COMPLETED : GB(_m[tile].m1, 0, 2); } /** @@ -124,6 +124,12 @@ SB(_m[tile].m1, 0, 2, value); } +static inline IndustryGfx GetCleanIndustryGfx(TileIndex t) +{ + assert(IsTileType(t, MP_INDUSTRY)); + return _m[t].m5 | (GB(_m[t].m6, 2, 1) << 8); +} + /** * Get the industry graphics ID for the given industry tile * @param t the tile to get the gfx for @@ -133,7 +139,7 @@ static inline IndustryGfx GetIndustryGfx(TileIndex t) { assert(IsTileType(t, MP_INDUSTRY)); - return GetTranslatedIndustryTileID(_m[t].m5 | (GB(_m[t].m6, 2, 1) << 8)); + return GetTranslatedIndustryTileID(GetCleanIndustryGfx(t)); } /** @@ -145,7 +151,8 @@ static inline void SetIndustryGfx(TileIndex t, IndustryGfx gfx) { assert(IsTileType(t, MP_INDUSTRY)); - _m[t].m5 = gfx; + _m[t].m5 = GB(gfx, 0, 8); + SB(_m[t].m6, 2, 1, GB(gfx, 8, 1)); } /** @@ -253,12 +260,24 @@ * @param tile TileIndex of the tile to query * @pre IsTileType(tile, MP_INDUSTRY) * @return requested bits - * @todo implement the storage in map array */ static inline byte GetIndustryRandomBits(TileIndex tile) { assert(IsTileType(tile, MP_INDUSTRY)); - return 0; + return _me[tile].m7; +} + +/** + * Set the random bits for this tile. + * Used for grf callbacks + * @param tile TileIndex of the tile to query + * @param bits the random bits + * @pre IsTileType(tile, MP_INDUSTRY) + */ +static inline byte GetIndustryRandomBits(TileIndex tile, byte bits) +{ + assert(IsTileType(tile, MP_INDUSTRY)); + _me[tile].m7 = bits; } /** @@ -267,12 +286,11 @@ * @param tile TileIndex of the tile to query * @pre IsTileType(tile, MP_INDUSTRY) * @return requested triggers - * @todo implement the storage in map array */ static inline byte GetIndustryTriggers(TileIndex tile) { assert(IsTileType(tile, MP_INDUSTRY)); - return 0; + return GB(_m[tile].m6, 3, 3); } @@ -280,12 +298,13 @@ * Set the activated triggers bits for this industry tile * Used for grf callbacks * @param tile TileIndex of the tile to query + * @param triggers the triggers to set * @pre IsTileType(tile, MP_INDUSTRY) - * @todo implement the storage in map array */ static inline void SetIndustryTriggers(TileIndex tile, byte triggers) { assert(IsTileType(tile, MP_INDUSTRY)); + SB(_m[tile].m6, 3, 3, triggers); } #endif /* INDUSTRY_MAP_H */ diff -r d2a6acdbd665 -r 197cb8c6ae17 src/landscape.cpp --- a/src/landscape.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/landscape.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -77,23 +77,23 @@ } uint dz = IsSteepSlope(*s) ? TILE_HEIGHT : 0; - byte highest_corner = GetHighestSlopeCorner(*s); + Corner highest_corner = GetHighestSlopeCorner(*s); switch (f) { case FOUNDATION_INCLINED_X: - *s = (highest_corner <= 1 ? SLOPE_SW : SLOPE_NE); + *s = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? SLOPE_SW : SLOPE_NE); break; case FOUNDATION_INCLINED_Y: - *s = (((highest_corner == 1) || (highest_corner == 2)) ? SLOPE_SE : SLOPE_NW); + *s = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? SLOPE_SE : SLOPE_NW); break; case FOUNDATION_STEEP_LOWER: - *s = (Slope) (1 << highest_corner); + *s = SlopeWithOneCornerRaised(highest_corner); break; case FOUNDATION_STEEP_HIGHER: - *s = (Slope) (*s & ~SLOPE_STEEP); + *s = SlopeWithThreeCornersRaised(OppositeCorner(highest_corner)); break; default: NOT_REACHED(); @@ -271,7 +271,7 @@ lower_base + (ti->tileh & ~SLOPE_STEEP), PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z ); - byte highest_corner = GetHighestSlopeCorner(ti->tileh); + Corner highest_corner = GetHighestSlopeCorner(ti->tileh); ti->z += ApplyFoundationToSlope(f, &ti->tileh); if (IsInclinedFoundation(f)) { diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/american.txt --- a/src/lang/american.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/american.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2017,7 +2017,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Must demolish tunnel first STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Must demolish bridge first STR_5008_CANNOT_START_AND_END_ON :{WHITE}Cannot start and end on same position -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Level land or water required under bridge STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Start and end must be in line STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Site unsuitable for tunnel entrance STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/brazilian_portuguese.txt --- a/src/lang/brazilian_portuguese.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/brazilian_portuguese.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2021,7 +2021,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Necessário demolir o túnel primeiro STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Necessário demolir a ponte primeiro STR_5008_CANNOT_START_AND_END_ON :{WHITE}Impossível iniciar e terminar no mesmo ponto -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Debaixo da ponte é necessário um terreno plano ou água STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Inicio e fim necessitam estar alinhados STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}O local não é adequado para a entrada do túnel STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/bulgarian.txt --- a/src/lang/bulgarian.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/bulgarian.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2008,7 +2008,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Първо разрушете тунела STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Първо трябва да разрушите моста STR_5008_CANNOT_START_AND_END_ON :{WHITE}Не може да започва и да свърша на едно и също място -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Равна земя или вода е необходима под моста STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Началото и краят трябва да са на една линия STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Мястото е неподходящо за вход на тунел STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/catalan.txt --- a/src/lang/catalan.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/catalan.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2017,7 +2017,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Primer has d'enderrocar el túnel STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Primer has d'enderrocar el pont STR_5008_CANNOT_START_AND_END_ON :{WHITE}No es pot començar i acabar a la mateixa posició -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Es necessita una certa elevació sobre el terreny o aigua sota el pont STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Inici i final han d'estar en línia recta STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Lloc inadequat per l'entrada del túnel STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/croatian.txt --- a/src/lang/croatian.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/croatian.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2019,7 +2019,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Najprije moraš srušiti tunel STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Najprije moraš srušiti most STR_5008_CANNOT_START_AND_END_ON :{WHITE}Početak i kraj ne mogu biti na istom mjestu -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Ispod mosta mora biti ravna zemlja ili voda STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Početak i kraj moraju biti u ravnini STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Neprikladan teren za ulaz u tunel STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/czech.txt --- a/src/lang/czech.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/czech.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2075,7 +2075,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Nutno nejprve zničit tunel STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Nutno nejprve zničit most STR_5008_CANNOT_START_AND_END_ON :{WHITE}Nelze začít a skončit na stejném místě -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Pod mostem je nutná rovná země nebo voda STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Začátek a konec musí být ve stejné výšce STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Místo nevhodné pro vjezd do tunelu STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/danish.txt --- a/src/lang/danish.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/danish.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2017,7 +2017,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Det er nødvendigt at rive tunnelen ned først STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Det er nødvendigt at rive broen ned først STR_5008_CANNOT_START_AND_END_ON :{WHITE}Kan ikke starte og slutte på samme position -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Der skal være fladt land eller vand under broen STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Start- og slutposition skal være på linje STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Dette sted er ikke brugbart til starten af en tunnel STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/dutch.txt --- a/src/lang/dutch.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/dutch.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2017,7 +2017,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Tunnel moet eerst afgebroken worden STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Brug moet eerst afgebroken worden STR_5008_CANNOT_START_AND_END_ON :{WHITE}Kan niet beginnen en eindigen op dezelfde plaats -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Vlak land of water vereist onder brug STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Begin en einde moeten op een lijn staan STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Locatie ongeschikt voor ingang tunnel STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/english.txt --- a/src/lang/english.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/english.txt Sat Oct 06 22:30:24 2007 +0000 @@ -1047,6 +1047,8 @@ STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Road vehicle queueing (with quantum effects): {ORANGE}{STRING1} STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Pan window when mouse is at the edge: {ORANGE}{STRING1} STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Allow bribing of the local authority: {ORANGE}{STRING1} +STR_CONFIG_PATCHES_ALLOW_EXCLUSIVE :{LTBLUE}Allow buying exclusive transport rights: {ORANGE}{STRING1} +STR_CONFIG_PATCHES_ALLOW_GIVE_MONEY :{LTBLUE}Allow sending money to other companies: {ORANGE}{STRING1} STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Nonuniform stations: {ORANGE}{STRING1} STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL :{LTBLUE}New global pathfinding (NPF, overrides NTP): {ORANGE}{STRING1} STR_CONFIG_PATCHES_FREIGHT_TRAINS :{LTBLUE}Weight multiplier for freight to simulate heavy trains: {ORANGE}{STRING} @@ -1187,6 +1189,7 @@ STR_CONFIG_PATCHES_LARGER_TOWNS :{LTBLUE}Proportion of towns that will become cities: {ORANGE}1 in {STRING1} STR_CONFIG_PATCHES_LARGER_TOWNS_DISABLED :{LTBLUE}Proportion of towns that will become cities: {ORANGE}None STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER :{LTBLUE}Initial city size multiplier: {ORANGE}{STRING1} +STR_CONFIG_MODIFIED_ROAD_REBUILD :{LTBLUE}Remove absurd road-elements during the road construction STR_CONFIG_PATCHES_GUI :{BLACK}Interface STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Construction @@ -2017,7 +2020,8 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Must demolish tunnel first STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Must demolish bridge first STR_5008_CANNOT_START_AND_END_ON :{WHITE}Cannot start and end in the same spot -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Level land or water required under bridge +STR_BRIDGEHEADS_NOT_SAME_HEIGHT :{WHITE}Bridge heads not at the same level +STR_BRIDGE_TOO_LOW_FOR_TERRAIN :{WHITE}Bridge is too low for the terrain STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Start and end must be in line STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Site unsuitable for tunnel entrance STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/esperanto.txt --- a/src/lang/esperanto.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/esperanto.txt Sat Oct 06 22:30:24 2007 +0000 @@ -1910,7 +1910,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Antaŭe forigu tunelon STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Antaŭe forigu ponton STR_5008_CANNOT_START_AND_END_ON :{WHITE}Ne povas komenci kaj fini en la sama loko -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Ebena lando aŭ akvo necesas sub la ponto STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Komenco kaj fino devas esti samliniaj STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Nekonvena loko por tunelkomenco STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/estonian.txt --- a/src/lang/estonian.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/estonian.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2117,7 +2117,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Enne tuleb tunnel hävitada STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Enne tuleb sild hävitada STR_5008_CANNOT_START_AND_END_ON :{WHITE}Ei saa alata ja lõppeda samas kohas -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Silla otsade kõrgus peab sama olema STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Algus ja lõpp peavad samal joonel olema STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Koht ei sobi tunneli sissekäiguks STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/finnish.txt --- a/src/lang/finnish.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/finnish.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2016,7 +2016,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Tunneli pitää tuhota ensin. STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Silta pitää tuhota ensin. STR_5008_CANNOT_START_AND_END_ON :{WHITE}Ei voi aloittaa ja lopettaa samasta paikkasta. -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Sillan alla pitää olla tasaista maata tai vettä. STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Alku- ja päätepisteen pitää olla linjassa. STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Tontti on sopimaton tunnelinsuulle. STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/french.txt --- a/src/lang/french.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/french.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2018,7 +2018,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Vous devez d'abord démolir le tunnel STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Vous devez d'abord démolir le pont STR_5008_CANNOT_START_AND_END_ON :{WHITE}Impossible de commencer et de terminer au même endroit -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Crevasse ou eau requise sous le pont STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Le début et la fin doivent être alignés STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Le site pour l'entrée du tunnel ne convient pas STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/galician.txt --- a/src/lang/galician.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/galician.txt Sat Oct 06 22:30:24 2007 +0000 @@ -1856,7 +1856,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Debes demole-lo túnel primeiro STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Debes demole-la ponte primeiro STR_5008_CANNOT_START_AND_END_ON :{WHITE}Non pode empezar e rematar na mesma posición -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Necesítase terreo nivelado ou auga baixo a ponte STR_500A_START_AND_END_MUST_BE_IN :{WHITE}O inicio e o final deben estar aliñados STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Emprazamento inadecuado para a entrada do túnel STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/german.txt --- a/src/lang/german.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/german.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2017,7 +2017,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Der Tunnel muss zuerst abgerissen werden STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Die Brücke muss erst abgerissen werden STR_5008_CANNOT_START_AND_END_ON :{WHITE}Anfang und Ende können nicht im selben Feld liegen -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Unter der Brücke ist ebenes Land oder Wasser erforderlich STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Anfang und Ende müssen auf einer Ebene liegen STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Platz ist nicht für einen Tunnel geeignet STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/hungarian.txt --- a/src/lang/hungarian.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/hungarian.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2120,7 +2120,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Előbb le kell rombolnod az alagutat STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Előbb le kell rombolnod a hidat STR_5008_CANNOT_START_AND_END_ON :{WHITE}Nem kezdődhet és végződhet ugyanott -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Sima talaj vagy víz kell, hogy legyen a híd alatt STR_500A_START_AND_END_MUST_BE_IN :{WHITE}A kezdetének és a végének egy vonalban kell lennie STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Nem alkalmas a hely alagút bejáratának STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/icelandic.txt --- a/src/lang/icelandic.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/icelandic.txt Sat Oct 06 22:30:24 2007 +0000 @@ -1877,7 +1877,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Verður að eyða göngum fyrst STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Verður að eyða brú fyrst STR_5008_CANNOT_START_AND_END_ON :{WHITE}Getur ekki byrjað og endað á sama stað -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Sléttlendi eða vatn nauðsynlegt undir brú STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Verður að byrja og enda í sömu línu STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Óhentug staðsetning fyrir enda gangnanna STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/italian.txt --- a/src/lang/italian.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/italian.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2019,7 +2019,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Bisogna demolire il tunnel prima STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Bisogna demolire il ponte prima STR_5008_CANNOT_START_AND_END_ON :{WHITE}Impossibile partire e finire nello stesso punto -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Sotto un ponte è richiesto terreno livellato o acqua STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Inizio e fine devono essere allineati STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Sito inadatto per l'entrata del tunnel STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/japanese.txt --- a/src/lang/japanese.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/japanese.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2016,7 +2016,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}先にトンネルを破壊しなければなりません STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}先に橋を破壊しなければなりません STR_5008_CANNOT_START_AND_END_ON :{WHITE}開始点と終了点が同じ位置に建設できません -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}橋下に平地もしくは水がなければなりません STR_500A_START_AND_END_MUST_BE_IN :{WHITE}一直線の橋しか建設できません STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}この土地はトンネルの入り口に不適当です STR_500D :{GOLD}{STRING}、{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/korean.txt --- a/src/lang/korean.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/korean.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2011,7 +2011,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}터널을 먼저 제거하십시오 STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}다리를 먼저 제거하십시오 STR_5008_CANNOT_START_AND_END_ON :{WHITE}같은 위치에서 시작하고 끝낼 수 없습니다 -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}다리 아래에는 평평한 땅이나 물이 있어야 합니다! STR_500A_START_AND_END_MUST_BE_IN :{WHITE}시작과 끝은 한 줄 위에 있어야 합니다 STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}터널 입구에 알맞지 않은 장소입니다 STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/lithuanian.txt --- a/src/lang/lithuanian.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/lithuanian.txt Sat Oct 06 22:30:24 2007 +0000 @@ -1907,7 +1907,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Pirmiau reikia pasalinti tuneli STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Pirmiau reikia pasalinti tilta STR_5008_CANNOT_START_AND_END_ON :{WHITE}Negalima pradeti ir baigti tuo paciu metu -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Po tiltu turi buti lygi zeme arba vanduo STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Pradzia ir pabaiga turi buti vienoje linijoje STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Vieta netinkama įvaziavimui į tunelį STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/norwegian_bokmal.txt --- a/src/lang/norwegian_bokmal.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/norwegian_bokmal.txt Sat Oct 06 22:30:24 2007 +0000 @@ -1931,7 +1931,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Må rive tunnel først STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Må rive bro først STR_5008_CANNOT_START_AND_END_ON :{WHITE}Kan ikke starte og slutte på samme felt -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Flatt land eller vann trengs under broen STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Start og slutt må være på linje STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Feltet er upassende for tunnelinngang STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/norwegian_nynorsk.txt --- a/src/lang/norwegian_nynorsk.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/norwegian_nynorsk.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2017,7 +2017,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Må rive tunnel først STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Må rive bru først STR_5008_CANNOT_START_AND_END_ON :{WHITE}Kan ikkje starte og slutte på same felt -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Flatt land eller vatn trengst under brua STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Start og slutt må vere på linje STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Feltet er uhøveleg for tunnelinngang STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/piglatin.txt --- a/src/lang/piglatin.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/piglatin.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2016,7 +2016,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Ustmay emolishday unneltay irstfay STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Ustmay emolishday idgebray irstfay STR_5008_CANNOT_START_AND_END_ON :{WHITE}Annotcay artstay andway endway inway ethay amesay otspay -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Evellay andlay orway aterway equiredray underway idgebray STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Artstay andway endway ustmay ebay inway inelay STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Itesay unsuitableway orfay unneltay entranceway STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/polish.txt --- a/src/lang/polish.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/polish.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2127,7 +2127,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Należy najpierw usunąć tunel STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Należy najpierw usunąć most STR_5008_CANNOT_START_AND_END_ON :{WHITE}Nie można zaczynać i kończyć w tym samym miejscu -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Wymagany równy ląd lub woda pod mostem STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Początek i koniec muszą być w jednej linii STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Nieodpowiednie miejsce na wejście tunelu STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/portuguese.txt --- a/src/lang/portuguese.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/portuguese.txt Sat Oct 06 22:30:24 2007 +0000 @@ -1999,7 +1999,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Deverá demolir o túnel primeiro STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Deverá demolir a ponte primeiro STR_5008_CANNOT_START_AND_END_ON :{WHITE}Não é posível iniciar e finalizar no mesmo ponto -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Debaixo da ponte é necessário terreno plano ou água STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Inicio e fim devem estar alinhados STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}O sítio não é adequado para a entrada do túnel STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/romanian.txt --- a/src/lang/romanian.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/romanian.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2017,7 +2017,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Mai întâi trebuie demolat tunelul STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Mai întâi trebuie demolat podul STR_5008_CANNOT_START_AND_END_ON :{WHITE}Cele două capete nu se pot situa în acelaşi loc -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Sub pod trebuie să existe teren plat sau apă STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Cele două capete trebuie să se situeze în linie STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Loc nepotrivit pentru intrarea într-un tunel STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/russian.txt --- a/src/lang/russian.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/russian.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2018,7 +2018,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Сначала удалите туннель STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Сначала удалите мост STR_5008_CANNOT_START_AND_END_ON :{WHITE}Не может начинаться и заканчиваться в той же точке -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Более низкий уровень земли или воды должен быть под мостом STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Начало и конец должны быть на одной линии STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Неподходящее место для строительства туннеля STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/simplified_chinese.txt --- a/src/lang/simplified_chinese.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/simplified_chinese.txt Sat Oct 06 22:30:24 2007 +0000 @@ -1900,7 +1900,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}必须先拆除隧道 STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}必须先拆除桥梁 STR_5008_CANNOT_START_AND_END_ON :{WHITE}起止点不能相同 -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}桥下必须有不平整的地面或水面 STR_500A_START_AND_END_MUST_BE_IN :{WHITE}起止两端必须在一条线上 STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}此处不适合作为隧道入口 STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/slovak.txt --- a/src/lang/slovak.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/slovak.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2081,7 +2081,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Tunel musi byt najskor zburany STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Most musi byt najskor zburany STR_5008_CANNOT_START_AND_END_ON :{WHITE}Nemozno zacat a skoncit na tom istom mieste -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Pod mostom je potrebná voda alebo údolie STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Zaciatok a koniec musi byt v rovine STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}To miesto je nepouzitelne ako vstup do tunela STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/slovenian.txt --- a/src/lang/slovenian.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/slovenian.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2097,7 +2097,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Najprej moraš porušiti predor STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Najprej moraš porušiti most STR_5008_CANNOT_START_AND_END_ON :{WHITE}Ni mogoče začeti in končati v isti točki -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Raven teren ali vodovje zahtevano pod mostom STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Začetek in konec morata biti na isti višini STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Lokacija neprimerna za vhod v predor STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/spanish.txt --- a/src/lang/spanish.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/spanish.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2018,7 +2018,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Primero debe demolerse el túnel STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Primero debe demolerse el puente STR_5008_CANNOT_START_AND_END_ON :{WHITE}No se puede comenzar y acabar en la misma posición -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Se requiere tierra a nivel o agua bajo el puente STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Comienzo y final deben estar en línea STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Lugar inapropiado para entrada de túnel STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/swedish.txt --- a/src/lang/swedish.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/swedish.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2016,7 +2016,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Måste riva tunnel först STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Måste riva bro först STR_5008_CANNOT_START_AND_END_ON :{WHITE}Kan inte börja och sluta på samma plats -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Platt land eller vatten krävs under bro STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Start- och slutpunkt måste ligga i linje STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Platsen passar inte för tunnelentré STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/traditional_chinese.txt --- a/src/lang/traditional_chinese.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/traditional_chinese.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2017,7 +2017,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}必須先摧毀隧道 STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}必須先摧毀橋樑 STR_5008_CANNOT_START_AND_END_ON :{WHITE}不能結束在開始地點 -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}橋樑下需要平地或水面 STR_500A_START_AND_END_MUST_BE_IN :{WHITE}開始與結束地點必須位在同一直線 STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}隧道入口地點不適合 STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/turkish.txt --- a/src/lang/turkish.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/turkish.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2012,7 +2012,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Önce tünel yıkılmalı STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Önce köprü yıkılmalı STR_5008_CANNOT_START_AND_END_ON :{WHITE}Aynı noktada başlayıp bitemez -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Köprü altınin düz olması gerekiyor STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Başlangıç ve bitiş aynı çizgi üzerinde olmalı STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Yer tünel girişi için uygun değil STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/ukrainian.txt --- a/src/lang/ukrainian.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/ukrainian.txt Sat Oct 06 22:30:24 2007 +0000 @@ -2178,7 +2178,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Спочатку зруйнуйте тунель STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Спочатку зруйнуйте міст STR_5008_CANNOT_START_AND_END_ON :{WHITE}Початок та кінець не можуть бути в одному місці -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Рівна земля чи вода має бути під мостом STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Початок та кінець мають бути на одній лінії STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Невідповідне місце для початку тунеля STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/unfinished/afrikaans.txt --- a/src/lang/unfinished/afrikaans.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/unfinished/afrikaans.txt Sat Oct 06 22:30:24 2007 +0000 @@ -1808,7 +1808,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Moet eers tonnel afbreek STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Moet eers brug afbreek STR_5008_CANNOT_START_AND_END_ON :{WHITE}Kan nie in die selfde plek begin en eindig nie -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Platte land of water benooding onder brug STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Begin en einde moet in lyn wees STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Plek ongeskik vir tonnel ingang STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/lang/unfinished/greek.txt --- a/src/lang/unfinished/greek.txt Sun Sep 23 07:37:38 2007 +0000 +++ b/src/lang/unfinished/greek.txt Sat Oct 06 22:30:24 2007 +0000 @@ -1640,7 +1640,6 @@ STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Πρέπει πρώτα να καταστραφεί το τούνελ STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Πρέπει πρώτα να καταστραφεί η γέφυρα STR_5008_CANNOT_START_AND_END_ON :{WHITE}Δεν γίνεται να ξεκινάει και να τελειώνει στο ίδιο σημείο -STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Απαιτείται επίπεδο έδαφος ή νερό κάτω από τη γέφυρα STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Η αρχή και το τέλος πρέπει να είναι σε ευθεία STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Ακατάλληλη τοποθεσία για είσοδο τούνελ STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/macros.h --- a/src/macros.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/macros.h Sat Oct 06 22:30:24 2007 +0000 @@ -341,6 +341,15 @@ #define GENERAL_SPRITE_COLOR(color) ((color) + PALETTE_RECOLOR_START) #define PLAYER_SPRITE_COLOR(owner) (GENERAL_SPRITE_COLOR(_player_colors[owner])) +/** + * Whether a sprite comes from the original graphics files or a new grf file + * (either supplied by OpenTTD or supplied by the user). + * + * @param sprite The sprite to check + * @return True if it is a new sprite, or false if it is original. + */ +#define IS_CUSTOM_SPRITE(sprite) ((sprite) >= SPR_SIGNALS_BASE) + extern const byte _ffb_64[128]; /** diff -r d2a6acdbd665 -r 197cb8c6ae17 src/main_gui.cpp --- a/src/main_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/main_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -59,11 +59,13 @@ extern void GenerateIndustries(); extern bool GenerateTowns(); +bool _draw_bounding_boxes = false; + void CcGiveMoney(bool success, TileIndex tile, uint32 p1, uint32 p2) { #ifdef ENABLE_NETWORK - if (!success) return; + if (!success || !_patches.give_money) return; char msg[20]; /* Inform the player of this action */ @@ -2208,6 +2210,13 @@ break; } + if (e->we.keypress.keycode == ('B' | WKC_CTRL)) { + e->we.keypress.cont = false; + _draw_bounding_boxes = !_draw_bounding_boxes; + MarkWholeScreenDirty(); + break; + } + if (_game_mode == GM_MENU) break; switch (e->we.keypress.keycode) { diff -r d2a6acdbd665 -r 197cb8c6ae17 src/map.h --- a/src/map.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/map.h Sat Oct 06 22:30:24 2007 +0000 @@ -390,6 +390,18 @@ } /** + * Adds a DiagDir to a tile. + * + * @param tile The current tile + * @param dir The direction in which we want to step + * @return the moved tile + */ +static inline TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir) +{ + return TILE_ADD(tile, TileOffsByDiagDir(dir)); +} + +/** * A callback function type for searching tiles. * * @param tile The tile to test diff -r d2a6acdbd665 -r 197cb8c6ae17 src/misc.cpp --- a/src/misc.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/misc.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -41,7 +41,7 @@ #ifdef RANDOM_DEBUG if (_networking && (DEREF_CLIENT(0)->status != STATUS_INACTIVE || !_network_server)) - printf("Random [%d/%d] %s:%d\n",_frame_counter, _current_player, file, line); + printf("Random [%d/%d] %s:%d\n",_frame_counter, (byte)_current_player, file, line); #endif s = _random_seeds[0][0]; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/misc_cmd.cpp --- a/src/misc_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/misc_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -351,6 +351,8 @@ */ CommandCost CmdGiveMoney(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { + if (!_patches.give_money) return CMD_ERROR; + const Player *p = GetPlayer(_current_player); CommandCost amount(min((Money)p1, (Money)20000000LL)); diff -r d2a6acdbd665 -r 197cb8c6ae17 src/music/win32_m.cpp --- a/src/music/win32_m.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/music/win32_m.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -142,7 +142,11 @@ } if (NULL == (_midi.wait_obj = CreateEvent(NULL, FALSE, FALSE, NULL))) return "Failed to create event"; - if (NULL == (_midi.thread = CreateThread(NULL, 8192, MidiThread, 0, 0, NULL))) return "Failed to create thread"; + + /* The lpThreadId parameter of CreateThread (the last parameter) + * may NOT be NULL on Windows 95, 98 and ME. */ + DWORD threadId; + if (NULL == (_midi.thread = CreateThread(NULL, 8192, MidiThread, 0, 0, &threadId))) return "Failed to create thread"; return NULL; } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/network/network_gui.cpp --- a/src/network/network_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/network/network_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -1264,8 +1264,8 @@ _clientlist_proc[i++] = &ClientList_SpeakToAll; if (_network_own_client_index != ci->client_index) { - /* We are no spectator and the player we want to give money to is no spectator */ - if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas)) { + /* We are no spectator and the player we want to give money to is no spectator and money gifts are allowed */ + if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas) && _patches.give_money) { GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(_clientlist_action[i])); _clientlist_proc[i++] = &ClientList_GiveMoney; } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf.cpp --- a/src/newgrf.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -1206,9 +1206,6 @@ /* Allocate house specs if they haven't been allocated already. */ if (_cur_grffile->housespec == NULL) { _cur_grffile->housespec = CallocT(HOUSE_MAX); - - /* Reset any overrides that have been set. */ - _house_mngr.ResetOverride(); } for (int i = 0; i < numinfo; i++) { @@ -1702,8 +1699,6 @@ static bool IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, byte **bufp, int len) { - if (!HASBIT(_ttdpatch_flags[3], 0x07)) return true; - byte *buf = *bufp; bool ret = false; @@ -1715,9 +1710,6 @@ /* Allocate industry tile specs if they haven't been allocated already. */ if (_cur_grffile->indtspec == NULL) { _cur_grffile->indtspec = CallocT(NUM_INDUSTRYTILES); - - /* Reset any overrides that have been set. */ - _industile_mngr.ResetOverride(); } for (int i = 0; i < numinfo; i++) { @@ -1772,7 +1764,7 @@ case 0x0C: { uint16 acctp = grf_load_word(&buf); tsp->accepts_cargo[prop - 0x0A] = GetCargoTranslation(GB(acctp, 0, 8), _cur_grffile); - tsp->acceptance[prop - 0x0A] = GetCargoTranslation(GB(acctp, 8, 8), _cur_grffile); + tsp->acceptance[prop - 0x0A] = GB(acctp, 8, 8); } break; case 0x0D: // Land shape flags @@ -1811,8 +1803,6 @@ static bool IndustriesChangeInfo(uint indid, int numinfo, int prop, byte **bufp, int len) { - if (!HASBIT(_ttdpatch_flags[3], 0x07)) return true; - byte *buf = *bufp; bool ret = false; @@ -1826,9 +1816,6 @@ /* Allocate industry specs if they haven't been allocated already. */ if (_cur_grffile->industryspec == NULL) { _cur_grffile->industryspec = CallocT(NUM_INDUSTRYTYPES); - - /* Reset any overrides that have been set. */ - _industry_mngr.ResetOverride(); } for (int i = 0; i < numinfo; i++) { @@ -1938,6 +1925,9 @@ size = k + 1; copy_from = itt; } + } else if (itt[k].gfx == 0xFF) { + itt[k].ti.x = (int8)GB(itt[k].ti.x, 0, 8); + itt[k].ti.y = (int8)GB(itt[k].ti.y, 0, 8); } } tile_table[j] = CallocT(size); @@ -2005,11 +1995,11 @@ break; case 0x17: // Probability in random game - indsp->appear_ingame[_opt.landscape] = grf_load_byte(&buf); + indsp->appear_creation[_opt.landscape] = grf_load_byte(&buf); break; case 0x18: // Probability during gameplay - indsp->appear_creation[_opt.landscape] = grf_load_byte(&buf); + indsp->appear_ingame[_opt.landscape] = grf_load_byte(&buf); break; case 0x19: // Map color @@ -2943,8 +2933,6 @@ static void IndustryMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount) { - if (!HASBIT(_ttdpatch_flags[3], 0x07)) return; - byte *bp = &buf[4 + idcount + cidcount * 3]; uint16 groupid = grf_load_word(&bp); @@ -2969,8 +2957,6 @@ static void IndustrytileMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount) { - if (!HASBIT(_ttdpatch_flags[3], 0x07)) return; - byte *bp = &buf[4 + idcount + cidcount * 3]; uint16 groupid = grf_load_word(&bp); @@ -3056,8 +3042,8 @@ grfmsg(6, "FeatureMapSpriteGroup: Feature %d, %d ids, %d cids, wagon override %d", feature, idcount, cidcount, wagover); - if (_cur_grffile->spriteset_start == 0 || _cur_grffile->spritegroups == 0) { - grfmsg(1, "FeatureMapSpriteGroup: No sprite set to work on! Skipping"); + if (_cur_grffile->spritegroups == 0) { + grfmsg(1, "FeatureMapSpriteGroup: No sprite groups to work on! Skipping"); return; } @@ -3393,8 +3379,8 @@ case 0x8B: { // TTDPatch version uint major = 2; uint minor = 6; - uint revision = 0; // special case: 2.0.1 is 2.0.10 - uint build = 1210; + uint revision = 1; // special case: 2.0.1 is 2.0.10 + uint build = 1382; return (major << 24) | (minor << 20) | (revision << 16) | build; } @@ -4730,7 +4716,7 @@ | (0 << 0x04) // aichoosechance | (1 << 0x05) // resolutionwidth | (1 << 0x06) // resolutionheight - | (0 << 0x07) // newindustries + | (1 << 0x07) // newindustries | ((_patches.improved_load ? 1 : 0) << 0x08) // fifoloading | (0 << 0x09) // townroadbranchprob | (0 << 0x0A) // tempsnowline @@ -4971,7 +4957,7 @@ _loaded_newgrf_features.has_2CC = false; _loaded_newgrf_features.has_newhouses = false; - _loaded_newgrf_features.has_newindustries = false, + _loaded_newgrf_features.has_newindustries = false; _signal_base = 0; _coast_base = 0; @@ -5492,7 +5478,7 @@ /* Load newgrf sprites * in each loading stage, (try to) open each file specified in the config * and load information from it. */ - for (GrfLoadingStage stage = GLS_LABELSCAN; stage <= GLS_ACTIVATION; stage++) { + for (GrfLoadingStage stage = GLS_LABELSCAN; stage < GLS_ACTIVATION; stage++) { uint slot = file_index; _cur_stage = stage; @@ -5505,13 +5491,17 @@ if (!FioCheckFileExists(c->filename)) error("NewGRF file is missing '%s'", c->filename); if (stage == GLS_LABELSCAN) InitNewGRFFile(c, _cur_spriteid); - LoadNewGRFFile(c, slot++, stage); + LoadNewGRFFile(c, slot, stage); if (stage == GLS_RESERVE) { if (c->status == GCS_ACTIVATED) c->status = GCS_INITIALISED; - } else if (stage == GLS_ACTIVATION) { + _cur_stage = GLS_ACTIVATION; + LoadNewGRFFile(c, slot++, GLS_ACTIVATION); + _cur_stage = stage; ClearTemporaryNewGRFData(); BuildCargoTranslationMap(); DEBUG(sprite, 2, "LoadNewGRF: Currently %i sprites are loaded", _cur_spriteid); + } else { + slot++; } } } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_callbacks.h --- a/src/newgrf_callbacks.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_callbacks.h Sat Oct 06 22:30:24 2007 +0000 @@ -24,6 +24,8 @@ /** Set when calling a randomizing trigger (almost undocumented). */ CBID_RANDOM_TRIGGER = 0x01, + /* There are no callbacks 0x02 - 0x0F. */ + /** Powered wagons, if the result is lower as 0x40 then the wagon is powered * @todo : interpret the rest of the result, aka "visual effects". */ CBID_TRAIN_WAGON_POWER = 0x10, @@ -69,7 +71,7 @@ CBID_TRAIN_ALLOW_WAGON_ATTACH = 0x1D, /** Called to determine the colour of a town building. */ - CBID_BUILDING_COLOUR = 0x1E, + CBID_HOUSE_COLOUR = 0x1E, /** Called to decide how much cargo a town building can accept. */ CBID_HOUSE_CARGO_ACCEPTANCE = 0x1F, @@ -168,6 +170,8 @@ /** Called to determine if the industry can still accept or refuse more cargo arrival */ CBID_INDUSTRY_REFUSE_CARGO = 0x3D, + /* There are no callbacks 0x3E - 0x142. */ + /** Called to determine whether a town building can be destroyed. */ CBID_HOUSE_DENY_DESTRUCTION = 0x143, @@ -182,6 +186,20 @@ /** Add an offset to the default sprite numbers to show another sprite. */ CBID_CANALS_SPRITE_OFFSET = 0x147, // not implemented + + /* There is no callback 0x148.*/ + + /** Callback done for each tile of a station to check the slope. */ + CBID_STATION_LAND_SLOPE_CHECK = 0x149, // not implemented + + /** Called to determine the color of an industry. */ + CBID_INDUSTRY_DECIDE_COLOUR = 0x14A, + + /** Customize the input cargo types of a newly build industry. */ + CBID_INDUSTRY_INPUT_CARGO_TYPES = 0x14B, + + /** Customize the output cargo types of a newly build industry. */ + CBID_INDUSTRY_OUTPUT_CARGO_TYPES = 0x14C, }; /** @@ -189,64 +207,70 @@ * Some callbacks are always used and don't have a mask. */ enum VehicleCallbackMask { - CBM_WAGON_POWER = 0, ///< Powered wagons (trains only) - CBM_VEHICLE_LENGTH = 1, ///< Vehicle length (trains only) - CBM_LOAD_AMOUNT = 2, ///< Load amount - CBM_REFIT_CAPACITY = 3, ///< Cargo capacity after refit - CBM_ARTIC_ENGINE = 4, ///< Add articulated engines (trains only) - CBM_CARGO_SUFFIX = 5, ///< Show suffix after cargo name - CBM_COLOUR_REMAP = 6, ///< Change colour mapping of vehicle - CBM_SOUND_EFFECT = 7, ///< Vehicle uses custom sound effects + CBM_TRAIN_WAGON_POWER = 0, ///< Powered wagons (trains only) + CBM_VEHICLE_LENGTH = 1, ///< Vehicle length (trains and road vehicles) + CBM_VEHICLE_LOAD_AMOUNT = 2, ///< Load amount + CBM_VEHICLE_REFIT_CAPACITY = 3, ///< Cargo capacity after refit + CBM_VEHICLE_ARTIC_ENGINE = 4, ///< Add articulated engines (trains only) + CBM_VEHICLE_CARGO_SUFFIX = 5, ///< Show suffix after cargo name + CBM_VEHICLE_COLOUR_REMAP = 6, ///< Change colour mapping of vehicle + CBM_VEHICLE_SOUND_EFFECT = 7, ///< Vehicle uses custom sound effects }; /** * Callback masks for stations. */ enum StationCallbackMask { - CBM_STATION_AVAIL = 0, ///< Availability of station in construction window - CBM_CUSTOM_LAYOUT = 1, ///< Use callback to select a tile layout to use + CBM_STATION_AVAIL = 0, ///< Availability of station in construction window + CBM_STATION_SPRITE_LAYOUT = 1, ///< Use callback to select a sprite layout to use + CBM_STATION_ANIMATION_NEXT_FRAME = 2, ///< Use a custom next frame callback + CBM_STATION_ANIMATION_SPEED = 3, ///< Customize the animation speed of the station + CBM_STATION_SLOPE_CHECK = 4, ///< Check slope of new station tiles }; /** * Callback masks for houses. */ enum HouseCallbackMask { - CBM_HOUSE_ALLOW_CONSTRUCTION = 0, - CBM_ANIMATION_NEXT_FRAME = 1, - CBM_ANIMATION_START_STOP = 2, - CBM_CONSTRUCTION_STATE_CHANGE = 3, - CBM_BUILDING_COLOUR = 4, - CBM_CARGO_ACCEPTANCE = 5, - CBM_ANIMATION_SPEED = 6, - CBM_HOUSE_DESTRUCTION = 7, - CBM_HOUSE_ACCEPT_CARGO = 8, - CBM_HOUSE_PRODUCE_CARGO = 9, - CBM_HOUSE_DENY_DESTRUCTION = 10, + CBM_HOUSE_ALLOW_CONSTRUCTION = 0, + CBM_HOUSE_ANIMATION_NEXT_FRAME = 1, + CBM_HOUSE_ANIMATION_START_STOP = 2, + CBM_HOUSE_CONSTRUCTION_STATE_CHANGE = 3, + CBM_HOUSE_COLOUR = 4, + CBM_HOUSE_CARGO_ACCEPTANCE = 5, + CBM_HOUSE_ANIMATION_SPEED = 6, + CBM_HOUSE_DESTRUCTION = 7, + CBM_HOUSE_ACCEPT_CARGO = 8, + CBM_HOUSE_PRODUCE_CARGO = 9, + CBM_HOUSE_DENY_DESTRUCTION = 10, }; /** * Callback masks for cargos. */ enum CargoCallbackMask { - CBM_CARGO_PROFIT_CALC = 0, - CBM_CARGO_STATION_RATING_CALC = 1, + CBM_CARGO_PROFIT_CALC = 0, ///< custom profit calculation + CBM_CARGO_STATION_RATING_CALC = 1, ///< custom station rating for this cargo type }; /** * Callback masks for Industries */ enum IndustryCallbackMask { - CBM_IND_AVAILABLE = 0, ///< industry availability callback - CBM_IND_PRODUCTION_CARGO_ARRIVAL = 1, ///< call production callback when cargo arrives at the industry - CBM_IND_PRODUCTION_256_TICKS = 2, ///< call production callback every 256 ticks - CBM_IND_LOCATION = 3, ///< check industry construction on given area - CBM_IND_PRODUCTION_CHANGE = 4, ///< controls random production change - CBM_IND_MONTHLYPROD_CHANGE = 5, ///< controls monthly random production change - CBM_IND_CARGO_SUFFIX = 6, ///< cargo sub-type display - CBM_IND_FUND_MORE_TEXT = 7, ///< additional text in fund window - CBM_IND_WINDOW_MORE_TEXT = 8, ///< additional text in industry window - CBM_IND_SPECIAL_EFFECT = 9, ///< control special effects + CBM_IND_AVAILABLE = 0, ///< industry availability callback + CBM_IND_PRODUCTION_CARGO_ARRIVAL = 1, ///< call production callback when cargo arrives at the industry + CBM_IND_PRODUCTION_256_TICKS = 2, ///< call production callback every 256 ticks + CBM_IND_LOCATION = 3, ///< check industry construction on given area + CBM_IND_PRODUCTION_CHANGE = 4, ///< controls random production change + CBM_IND_MONTHLYPROD_CHANGE = 5, ///< controls monthly random production change + CBM_IND_CARGO_SUFFIX = 6, ///< cargo sub-type display + CBM_IND_FUND_MORE_TEXT = 7, ///< additional text in fund window + CBM_IND_WINDOW_MORE_TEXT = 8, ///< additional text in industry window + CBM_IND_SPECIAL_EFFECT = 9, ///< control special effects CBM_IND_REFUSE_CARGO = 10, ///< option out of accepting cargo + CBM_IND_DECIDE_COLOUR = 11, ///< give a custom colour to newly build industries + CBM_IND_INPUT_CARGO_TYPES = 12, ///< customize the cargos the industry requires + CBM_IND_OUTPUT_CARGO_TYPES = 13, ///< customize the cargos the industry produces }; /** diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_commons.cpp --- a/src/newgrf_commons.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_commons.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -105,7 +105,7 @@ for (id = max_offset; id < max_new_entities; id++) { map = &mapping_ID[id]; - if (map->entity_id == 0 && map->grfid == 0) { + if (CheckValidNewID(id) && map->entity_id == 0 && map->grfid == 0) { map->entity_id = grf_local_id; map->grfid = grfid; map->substitute_id = substitute_id; @@ -188,7 +188,7 @@ * checking what is available * @param inds Industryspec that comes from the grf decoding process */ -void IndustryOverrideManager::SetEntitySpec(const IndustrySpec *inds) +void IndustryOverrideManager::SetEntitySpec(IndustrySpec *inds) { /* First step : We need to find if this industry is already specified in the savegame data */ IndustryType ind_id = this->GetID(inds->grf_prop.local_id, inds->grf_prop.grffile->grfid); @@ -206,6 +206,7 @@ * Or it is a simple substitute. * In both case, we need to find a free available slot */ ind_id = this->AddEntityID(inds->grf_prop.local_id, inds->grf_prop.grffile->grfid, inds->grf_prop.subst_id); + inds->grf_prop.override = invalid_ID; // make sure it will not be detected as overriden } } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_commons.h --- a/src/newgrf_commons.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_commons.h Sat Oct 06 22:30:24 2007 +0000 @@ -33,6 +33,7 @@ uint16 max_new_entities; ///< what is the amount of entities, old and new summed uint16 invalid_ID; ///< ID used to dected invalid entities; + virtual bool CheckValidNewID(uint16 testid) { return true; } public: EntityIDMapping *mapping_ID; ///< mapping of ids from grf files. Public out of convenience @@ -70,12 +71,14 @@ OverrideManagerBase(offset, maximum, invalid) {} virtual uint16 AddEntityID(byte grf_local_id, uint32 grfid, byte substitute_id); - void SetEntitySpec(const IndustrySpec *inds); + void SetEntitySpec(IndustrySpec *inds); }; struct IndustryTileSpec; class IndustryTileOverrideManager : public OverrideManagerBase { +protected: + virtual bool CheckValidNewID(uint16 testid) { return testid != 0xFF; } public: IndustryTileOverrideManager(uint16 offset, uint16 maximum, uint16 invalid) : OverrideManagerBase(offset, maximum, invalid) {} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_config.cpp --- a/src/newgrf_config.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_config.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -371,6 +371,21 @@ return num; } +/** + * Simple sorter for GRFS + * @param p1 the first GRFConfig * + * @param p2 the second GRFConfig * + * @return the same strcmp would return for the name of the NewGRF. + */ +static int CDECL GRFSorter(const void *p1, const void *p2) +{ + const GRFConfig *c1 = *(const GRFConfig **)p1; + const GRFConfig *c2 = *(const GRFConfig **)p2; + + return strcmp(c1->name != NULL ? c1->name : c1->filename, + c2->name != NULL ? c2->name : c2->filename); +} + /* Scan for all NewGRFs */ void ScanNewGRFFiles() { @@ -389,7 +404,30 @@ FOR_ALL_TARS(tar) { num += ScanTar(tar); } + DEBUG(grf, 1, "Scan complete, found %d files", num); + if (num == 0 || _all_grfs == NULL) return; + + /* Sort the linked list using quicksort. + * For that we first have to make an array, the qsort and + * then remake the linked list. */ + GRFConfig **to_sort = MallocT(num); + if (to_sort == NULL) return; // No memory, then don't sort + + uint i = 0; + for (GRFConfig *p = _all_grfs; p != NULL; p = p->next, i++) { + to_sort[i] = p; + } + /* Number of files is not necessarily right */ + num = i; + + qsort(to_sort, num, sizeof(GRFConfig*), GRFSorter); + + for (i = 1; i < num; i++) { + to_sort[i - 1]->next = to_sort[i]; + } + to_sort[num - 1]->next = NULL; + _all_grfs = to_sort[0]; } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_gui.cpp --- a/src/newgrf_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -515,6 +515,7 @@ case WE_RESIZE: w->vscroll.cap += e->we.sizing.diff.y / 14; w->widget[SNGRFS_FILE_LIST].data = (w->vscroll.cap << 8) + 1; + SetupNewGRFWindow(w); break; } } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_house.cpp --- a/src/newgrf_house.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_house.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -308,19 +308,23 @@ SpriteID image = dts->ground_sprite; SpriteID pal = dts->ground_pal; + if (IS_CUSTOM_SPRITE(image)) image += stage; + if (GB(image, 0, SPRITE_WIDTH) != 0) DrawGroundSprite(image, pal); foreach_draw_tile_seq(dtss, dts->seq) { if (GB(dtss->image, 0, SPRITE_WIDTH) == 0) continue; - image = dtss->image + stage; + image = dtss->image; pal = dtss->pal; + if (IS_CUSTOM_SPRITE(image)) image += stage; + if ((HASBIT(image, SPRITE_MODIFIER_OPAQUE) || !HASBIT(_transparent_opt, TO_HOUSES)) && HASBIT(image, PALETTE_MODIFIER_COLOR)) { if (pal == 0) { const HouseSpec *hs = GetHouseSpecs(house_id); - if (HASBIT(hs->callback_mask, CBM_BUILDING_COLOUR)) { - uint16 callback = GetHouseCallback(CBID_BUILDING_COLOUR, 0, 0, house_id, GetTownByTile(ti->tile), ti->tile); + if (HASBIT(hs->callback_mask, CBM_HOUSE_COLOUR)) { + uint16 callback = GetHouseCallback(CBID_HOUSE_COLOUR, 0, 0, house_id, GetTownByTile(ti->tile), ti->tile); if (callback != CALLBACK_FAILED) { /* If bit 14 is set, we should use a 2cc colour map, else use the callback value. */ pal = HASBIT(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback; @@ -342,7 +346,7 @@ HASBIT(_transparent_opt, TO_HOUSES) ); } else { - AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y); + AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y, HASBIT(_transparent_opt, TO_HOUSES)); } } } @@ -375,7 +379,7 @@ byte animation_speed = hs->animation_speed; bool frame_set_by_callback = false; - if (HASBIT(hs->callback_mask, CBM_ANIMATION_SPEED)) { + if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_SPEED)) { uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_SPEED, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); if (callback_res != CALLBACK_FAILED) animation_speed = clamp(callback_res & 0xFF, 2, 16); } @@ -389,7 +393,7 @@ byte frame = GetHouseAnimationFrame(tile); byte num_frames = GB(hs->animation_frames, 0, 7); - if (HASBIT(hs->callback_mask, CBM_ANIMATION_NEXT_FRAME)) { + if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_NEXT_FRAME)) { uint32 param = (hs->extra_flags & CALLBACK_1A_RANDOM_BITS) ? Random() : 0; uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_NEXT_FRAME, param, 0, GetHouseType(tile), GetTownByTile(tile), tile); @@ -468,7 +472,7 @@ { const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile)); - if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) { + if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) { uint32 param = (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) ? (GB(Random(), 0, 16) | random_bits << 16) : Random(); uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_START_STOP, param, 0, GetHouseType(tile), GetTownByTile(tile), tile); @@ -491,7 +495,7 @@ * MarkTileDirtyByTile(tile); */ - if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) { + if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) { /* If this house is marked as having a synchronised callback, all the * tiles will have the callback called at once, rather than when the * tile loop reaches them. This should only be enabled for the northern diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_industries.cpp --- a/src/newgrf_industries.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_industries.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -78,47 +78,44 @@ /** Make an analysis of a tile and check for its belonging to the same * industry, and/or the same grf file - * @param new_tile TileIndex of the tile to query - * @param old_tile TileIndex of the reference tile - * @param i Industry to which old_tile belongs to + * @param tile TileIndex of the tile to query + * @param i Industry to which to compare the tile to * @return value encoded as per NFO specs */ -uint32 GetIndustryIDAtOffset(TileIndex new_tile, TileIndex old_tile, const Industry *i) +uint32 GetIndustryIDAtOffset(TileIndex tile, const Industry *i) { - if (IsTileType(new_tile, MP_INDUSTRY)) { // Is this an industry tile? - - if (GetIndustryIndex(new_tile) == i->index) { // Does it belong to the same industry? - IndustryGfx gfx = GetIndustryGfx(new_tile); - const IndustryTileSpec *indtsp = GetIndustryTileSpec(gfx); - const IndustryTileSpec *indold = GetIndustryTileSpec(GetIndustryGfx(old_tile)); + if (!IsTileType(tile, MP_INDUSTRY) || GetIndustryIndex(tile) == i->index) { + /* No industry and/or the tile does not have the same industry as the one we match it with */ + return 0xFFFF; + } - if (gfx < NEW_INDUSTRYOFFSET) { // Does it belongs to an old type? - /* It is an old tile. We have to see if it's been overriden */ - if (indtsp->grf_prop.override == INVALID_INDUSTRYTILE) { // has it been overridden? - return 0xFF << 8 | gfx; // no. Tag FF + the gfx id of that tile - } else { // yes. FInd out if it is from the same grf file or not - const IndustryTileSpec *old_tile_ovr = GetIndustryTileSpec(indtsp->grf_prop.override); + IndustryGfx gfx = GetCleanIndustryGfx(tile); + const IndustryTileSpec *indtsp = GetIndustryTileSpec(gfx); + const IndustrySpec *indold = GetIndustrySpec(i->type); - if (old_tile_ovr->grf_prop.grffile->grfid == indold->grf_prop.grffile->grfid) { - return old_tile_ovr->grf_prop.local_id; // same grf file - } else { - return 0xFFFE; // not the same grf file - } - } - } else { - if (indtsp->grf_prop.spritegroup != NULL) { // tile has a spritegroup ? - if (indtsp->grf_prop.grffile->grfid == indold->grf_prop.grffile->grfid) { // same industry, same grf ? - return indtsp->grf_prop.local_id; - } else { - return 0xFFFE; // Defined in another grf file - } - } else { // tile has no spritegroup - return 0xFF << 8 | indtsp->grf_prop.subst_id; // so just give him the substitute - } - } + if (gfx < NEW_INDUSTRYOFFSET) { // Does it belongs to an old type? + /* It is an old tile. We have to see if it's been overriden */ + if (indtsp->grf_prop.override == INVALID_INDUSTRYTILE) { // has it been overridden? + return 0xFF << 8 | gfx; // no. Tag FF + the gfx id of that tile + } + /* Not overriden */ + const IndustryTileSpec *tile_ovr = GetIndustryTileSpec(indtsp->grf_prop.override); + + if (tile_ovr->grf_prop.grffile->grfid == indold->grf_prop.grffile->grfid) { + return tile_ovr->grf_prop.local_id; // same grf file + } else { + return 0xFFFE; // not the same grf file } } - - return 0xFFFF; // tile is not an industry one or does not belong to the current industry + /* Not an 'old type' tile */ + if (indtsp->grf_prop.spritegroup != NULL) { // tile has a spritegroup ? + if (indtsp->grf_prop.grffile->grfid == indold->grf_prop.grffile->grfid) { // same industry, same grf ? + return indtsp->grf_prop.local_id; + } else { + return 0xFFFE; // Defined in another grf file + } + } + /* The tile has no spritegroup */ + return 0xFF << 8 | indtsp->grf_prop.subst_id; // so just give him the substitute } static uint32 GetClosestIndustry(TileIndex tile, IndustryType type, const Industry *current) @@ -156,8 +153,8 @@ break; case 0xFFFFFFFF: // current grf - ind_index = GetIndustrySpec(current->type)->grf_prop.grffile->grfid; - /*Fall through*/ + GrfID = GetIndustrySpec(current->type)->grf_prop.grffile->grfid; + /* Fall through */ default: //use the grfid specified in register 100h ind_index = MapNewGRFIndustryType(param_setID, GrfID); @@ -209,27 +206,47 @@ } /* Manhattan distance of closes dry/water tile */ - case 0x43: return GetClosestWaterDistance(tile, (object->u.industry_location.spec->behaviour & INDUSTRYBEH_BUILT_ONWATER) == 0); + case 0x43: return GetClosestWaterDistance(tile, (indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) == 0); /* Layout number */ case 0x44: return industry->selected_layout; + /* player info */ + case 0x45: { + byte colours; + bool is_ai = false; + + if (IsValidPlayer(industry->founder)) { + const Player *p = GetPlayer(industry->founder); + const Livery *l = &p->livery[LS_DEFAULT]; + + is_ai = p->is_ai; + colours = l->colour1 + l->colour2 * 16; + } else { + colours = GB(Random(), 0, 8); + } + + return industry->founder | (is_ai ? 0x10000 : 0) | (colours << 24); + } + /* Get industry ID at offset param */ - case 0x60: return GetIndustryIDAtOffset(GetNearbyTile(parameter, industry->xy), tile, industry); + case 0x60: return GetIndustryIDAtOffset(GetNearbyTile(parameter, industry->xy), industry); - case 0x61: return 0; // Get random tile bits at offset param + /* Get random tile bits at offset param */ + case 0x61: + tile = GetNearbyTile(parameter, tile); + return (IsTileType(tile, MP_INDUSTRY) && GetIndustryByTile(tile) == industry) ? GetIndustryRandomBits(tile) : 0; /* Land info of nearby tiles */ case 0x62: return GetNearbyIndustryTileInformation(parameter, tile, INVALID_INDUSTRY); /* Animation stage of nearby tiles */ - case 0x63: { + case 0x63: tile = GetNearbyTile(parameter, tile); if (IsTileType(tile, MP_INDUSTRY) && GetIndustryByTile(tile) == industry) { return GetIndustryAnimationState(tile); } return 0xFFFFFFFF; - } /* Distance of nearest industry of given type */ case 0x64: return GetClosestIndustry(tile, MapNewGRFIndustryType(parameter, indspec->grf_prop.grffile->grfid), industry); @@ -258,7 +275,7 @@ case 0x87: return industry->height;// xy dimensions /* */ case 0x88: - case 0x89: return indspec->produced_cargo[variable - 0x88]; + case 0x89: return industry->produced_cargo[variable - 0x88]; case 0x8A: return industry->produced_cargo_waiting[0]; case 0x8B: return GB(industry->produced_cargo_waiting[0], 8, 8); case 0x8C: return industry->produced_cargo_waiting[1]; @@ -267,7 +284,7 @@ case 0x8F: return industry->production_rate[variable - 0x8E]; case 0x90: case 0x91: - case 0x92: return indspec->accepts_cargo[variable - 0x90]; + case 0x92: return industry->accepts_cargo[variable - 0x90]; case 0x93: return industry->prod_level; /* amount of cargo produced so far THIS month. */ case 0x94: return industry->this_month_production[0]; @@ -318,11 +335,27 @@ return NULL; } +static uint32 IndustryGetRandomBits(const ResolverObject *object) +{ + return object->u.industry.ind == NULL ? 0 : 0; //object->u.industry.ind->random_bits; +} + +static uint32 IndustryGetTriggers(const ResolverObject *object) +{ + return object->u.industry.ind == NULL ? 0 : 0; //object->u.industry.ind->triggers; +} + +static void IndustrySetTriggers(const ResolverObject *object, int triggers) +{ + if (object->u.industry.ind == NULL) return; + //object->u.industry.ind->triggers = triggers; +} + static void NewIndustryResolver(ResolverObject *res, TileIndex tile, Industry *indus) { - res->GetRandomBits = IndustryTileGetRandomBits; - res->GetTriggers = IndustryTileGetTriggers; - res->SetTriggers = IndustryTileSetTriggers; + res->GetRandomBits = IndustryGetRandomBits; + res->GetTriggers = IndustryGetTriggers; + res->SetTriggers = IndustrySetTriggers; res->GetVariable = IndustryGetVariable; res->ResolveReal = IndustryResolveReal; @@ -357,55 +390,47 @@ uint32 IndustryLocationGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) { - TileIndex tile = object->u.industry_location.tile; + const Industry *industry = object->u.industry.ind; + TileIndex tile = object->u.industry.tile; if (object->scope == VSG_SCOPE_PARENT) { - return TownGetVariable(variable, parameter, available, ClosestTownFromTile(tile, (uint)-1)); + return TownGetVariable(variable, parameter, available, industry->town); } switch (variable) { - /* Land info of nearby tiles */ - case 0x62: return GetNearbyIndustryTileInformation(parameter, tile, INVALID_INDUSTRY); - - /* Distance of nearest industry of given type */ - case 0x64: return GetClosestIndustry(tile, MapNewGRFIndustryType(parameter, object->u.industry_location.spec->grf_prop.grffile->grfid), NULL); - - /* Location where to build the industry */ case 0x80: return tile; case 0x81: return GB(tile, 8, 8); /* Pointer to the town the industry is associated with */ - case 0x82: return ClosestTownFromTile(tile, (uint)-1)->index; + case 0x82: return industry->town->index; case 0x83: case 0x84: case 0x85: DEBUG(grf, 0, "NewGRFs shouldn't be doing pointer magic"); break; // not supported /* Number of the layout */ - case 0x86: return object->u.industry_location.itspec_index; + case 0x86: return industry->selected_layout; /* Ground type */ case 0x87: return GetTerrainType(tile); /* Town zone */ - case 0x88: return GetTownRadiusGroup(ClosestTownFromTile(tile, (uint)-1), tile); + case 0x88: return GetTownRadiusGroup(industry->town, tile); /* Manhattan distance of the closest town */ - case 0x89: return min(DistanceManhattan(ClosestTownFromTile(tile, (uint)-1)->xy, tile), 255); + case 0x89: return min(DistanceManhattan(industry->town->xy, tile), 255); /* Lowest height of the tile */ case 0x8A: return GetTileZ(tile); /* Distance to the nearest water/land tile */ - case 0x8B: return GetClosestWaterDistance(tile, (object->u.industry_location.spec->behaviour & INDUSTRYBEH_BUILT_ONWATER) == 0); + case 0x8B: return GetClosestWaterDistance(tile, (GetIndustrySpec(industry->type)->behaviour & INDUSTRYBEH_BUILT_ONWATER) == 0); /* Square of Euclidian distance from town */ - case 0x8D: return min(DistanceSquare(ClosestTownFromTile(tile, (uint)-1)->xy, tile), 65535); + case 0x8D: return min(DistanceSquare(industry->town->xy, tile), 65535); } - DEBUG(grf, 1, "Unhandled location industry property 0x%X", variable); - - *available = false; - return (uint32)-1; + /* None of the special ones, so try the general ones */ + return IndustryGetVariable(object, variable, parameter, available); } bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspec_index) @@ -415,16 +440,23 @@ ResolverObject object; const SpriteGroup *group; - NewIndustryResolver(&object, tile, NULL); + Industry ind; + ind.index = INVALID_INDUSTRY; + ind.xy = tile; + ind.width = 0; + ind.type = type; + ind.selected_layout = itspec_index; + ind.town = ClosestTownFromTile(tile, (uint)-1); + + NewIndustryResolver(&object, tile, &ind); object.GetVariable = IndustryLocationGetVariable; object.callback = CBID_INDUSTRY_LOCATION; - object.u.industry_location.tile = tile; - object.u.industry_location.spec = indspec; - object.u.industry_location.itspec_index = itspec_index; group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); - if (group == NULL || group->type != SGT_CALLBACK) return false; + /* Unlike the "normal" cases, not having a valid result means we allow + * the building of the industry, as that's how it's done in TTDP. */ + if (group == NULL || group->type != SGT_CALLBACK) return true; switch (group->g.callback.result) { case 0x400: return true; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_industries.h --- a/src/newgrf_industries.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_industries.h Sat Oct 06 22:30:24 2007 +0000 @@ -8,10 +8,20 @@ #include "industry.h" #include "newgrf_spritegroup.h" +/** When should the industry(tile) be triggered for random bits? */ +enum IndustryTrigger { + /** Triggered each tile loop */ + INDUSTRY_TRIGGER_TILELOOP_PROCESS = 1, + /** Triggered (whole industry) each 256 ticks */ + INDUSTRY_TRIGGER_256_TICKS = 2, + /** Triggered on cargo delivery */ + INDUSTRY_TRIGGER_CARGO_DELIVERY = 4, +}; + /* in newgrf_industry.cpp */ uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available); uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile); -uint32 GetIndustryIDAtOffset(TileIndex new_tile, TileIndex old_tile, const Industry *i); +uint32 GetIndustryIDAtOffset(TileIndex new_tile, const Industry *i); void IndustryProductionCallback(Industry *ind, int reason); bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspec_index); bool CheckIfCallBackAllowsAvailability(IndustryType type, IndustryAvailabilityCallType creation_type); @@ -19,10 +29,6 @@ IndustryType MapNewGRFIndustryType(IndustryType grf_type, uint32 grf_id); /* in newgrf_industrytiles.cpp*/ -uint32 IndustryTileGetRandomBits(const ResolverObject *object); -uint32 IndustryTileGetTriggers(const ResolverObject *object); -void IndustryTileSetTriggers(const ResolverObject *object, int triggers); - uint32 GetNearbyIndustryTileInformation(byte parameter, TileIndex tile, IndustryID index); #endif /* NEWGRF_INDUSTRIES_H */ diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_industrytiles.cpp --- a/src/newgrf_industrytiles.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_industrytiles.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -99,7 +99,7 @@ } /* Get industry tile ID at offset */ - case 0x62 : return GetIndustryIDAtOffset(GetNearbyTile(parameter, tile), tile, inds); + case 0x62 : return GetIndustryIDAtOffset(GetNearbyTile(parameter, tile), inds); } DEBUG(grf, 1, "Unhandled industry tile property 0x%X", variable); @@ -114,22 +114,30 @@ return NULL; } -uint32 IndustryTileGetRandomBits(const ResolverObject *object) +static uint32 IndustryTileGetRandomBits(const ResolverObject *object) { const TileIndex tile = object->u.industry.tile; - return (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) ? 0 : GetIndustryRandomBits(tile); + if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0; + return (object->scope == VSG_SCOPE_SELF) ? GetIndustryRandomBits(tile) : 0; //GetIndustryByTile(tile)->random_bits; } -uint32 IndustryTileGetTriggers(const ResolverObject *object) +static uint32 IndustryTileGetTriggers(const ResolverObject *object) { const TileIndex tile = object->u.industry.tile; - return (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) ? 0 : GetIndustryTriggers(tile); + if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0; + return (object->scope == VSG_SCOPE_SELF) ? GetIndustryTriggers(tile) : 0; //GetIndustryByTile(tile)->triggers; } -void IndustryTileSetTriggers(const ResolverObject *object, int triggers) +static void IndustryTileSetTriggers(const ResolverObject *object, int triggers) { const TileIndex tile = object->u.industry.tile; - if (IsTileType(tile, MP_INDUSTRY)) SetIndustryTriggers(tile, triggers); + if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return; + + if (object->scope != VSG_SCOPE_SELF) { + SetIndustryTriggers(tile, triggers); + } else { + //GetIndustryByTile(tile)->triggers = triggers; + } } static void NewIndustryTileResolver(ResolverObject *res, IndustryGfx gfx, TileIndex tile, Industry *indus) @@ -161,14 +169,18 @@ SpriteID image = dts->ground_sprite; SpriteID pal = dts->ground_pal; + if (IS_CUSTOM_SPRITE(image)) image += stage; + if (GB(image, 0, SPRITE_WIDTH) != 0) DrawGroundSprite(image, pal); foreach_draw_tile_seq(dtss, dts->seq) { if (GB(dtss->image, 0, SPRITE_WIDTH) == 0) continue; - image = dtss->image + stage; + image = dtss->image; pal = dtss->pal; + if (IS_CUSTOM_SPRITE(image)) image += stage; + if (HASBIT(image, PALETTE_MODIFIER_COLOR)) { pal = GENERAL_SPRITE_COLOR(rnd_color); } else { @@ -184,7 +196,7 @@ !HASBIT(image, SPRITE_MODIFIER_OPAQUE) && HASBIT(_transparent_opt, TO_INDUSTRIES) ); } else { - AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y); + AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y, HASBIT(_transparent_opt, TO_INDUSTRIES)); } } } @@ -235,18 +247,23 @@ } } -bool PerformIndustryTileSlopeCheck(TileIndex tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx) +extern bool IsSlopeRefused(Slope current, Slope refused); + +bool PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind_tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx, uint itspec_index) { Industry ind; - ind.xy = 0; + ind.index = INVALID_INDUSTRY; + ind.xy = ind_base_tile; ind.width = 0; ind.type = type; - uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_SHAPE_CHECK, 0, 0, gfx, &ind, tile); + uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_SHAPE_CHECK, 0, itspec_index, gfx, &ind, ind_tile); + if (callback_res == CALLBACK_FAILED) { + return !IsSlopeRefused(GetTileSlope(ind_tile, NULL), its->slopes_refused); + } if (its->grf_prop.grffile->grf_version < 7) { return callback_res != 0; } - if (callback_res == CALLBACK_FAILED) return false; switch (callback_res) { case 0x400: return true; @@ -350,8 +367,11 @@ uint32 random = Random(); BEGIN_TILE_LOOP(tile, ind->width, ind->height, ind->xy) if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == ind->index) { - ret &= StartStopIndustryTileAnimation(tile, iat, random); - SB(random, 0, 16, Random()); + if (StartStopIndustryTileAnimation(tile, iat, random)) { + SB(random, 0, 16, Random()); + } else { + ret = false; + } } END_TILE_LOOP(tile, ind->width, ind->height, ind->xy) diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_industrytiles.h --- a/src/newgrf_industrytiles.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_industrytiles.h Sat Oct 06 22:30:24 2007 +0000 @@ -15,7 +15,7 @@ bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const IndustryTileSpec *inds); uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2, IndustryGfx gfx_id, Industry *industry, TileIndex tile); -bool PerformIndustryTileSlopeCheck(TileIndex tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx); +bool PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind_tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx, uint itspec_index); void AnimateNewIndustryTile(TileIndex tile); bool StartStopIndustryTileAnimation(TileIndex tile, IndustryAnimationTrigger iat, uint32 random = Random()); diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_sound.cpp --- a/src/newgrf_sound.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_sound.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -59,7 +59,7 @@ if (file == NULL) return false; /* Check that the vehicle type uses the sound effect callback */ - if (!HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_SOUND_EFFECT)) return false; + if (!HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_SOUND_EFFECT)) return false; callback = GetVehicleCallback(CBID_VEHICLE_SOUND_EFFECT, event, 0, v->engine_type, v); if (callback == CALLBACK_FAILED) return false; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_spritegroup.cpp --- a/src/newgrf_spritegroup.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_spritegroup.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -212,7 +212,7 @@ switch (object->callback) { /* All these functions are 15 bit callbacks */ case CBID_VEHICLE_REFIT_CAPACITY: - case CBID_BUILDING_COLOUR: + case CBID_HOUSE_COLOUR: case CBID_HOUSE_CARGO_ACCEPTANCE: case CBID_INDUSTRY_LOCATION: case CBID_INDTILE_CARGO_ACCEPTANCE: diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_spritegroup.h --- a/src/newgrf_spritegroup.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_spritegroup.h Sat Oct 06 22:30:24 2007 +0000 @@ -231,11 +231,6 @@ IndustryGfx gfx; } industry; struct { - TileIndex tile; - const IndustrySpec *spec; - uint itspec_index; - } industry_location; - struct { const struct CargoSpec *cs; } cargo; } u; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/newgrf_station.cpp --- a/src/newgrf_station.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/newgrf_station.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -751,7 +751,7 @@ relocation = GetCustomStationRelocation(statspec, NULL, INVALID_TILE); - if (HASBIT(statspec->callbackmask, CBM_CUSTOM_LAYOUT)) { + if (HASBIT(statspec->callbackmask, CBM_STATION_SPRITE_LAYOUT)) { uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0x2110000, 0, statspec, NULL, INVALID_TILE); if (callback != CALLBACK_FAILED) tile = callback; } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/openttd.cpp --- a/src/openttd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/openttd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -2191,6 +2191,19 @@ } } + if (CheckSavegameVersion(78)) { + Industry *i; + uint j; + FOR_ALL_INDUSTRIES(i) { + const IndustrySpec *indsp = GetIndustrySpec(i->type); + for (j = 0; j < lengthof(i->produced_cargo); j++) { + i->produced_cargo[j] = indsp->produced_cargo[j]; + } + for (j = 0; j < lengthof(i->accepts_cargo); j++) { + i->accepts_cargo[j] = indsp->accepts_cargo[j]; + } + } + } return true; } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/order.h --- a/src/order.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/order.h Sat Oct 06 22:30:24 2007 +0000 @@ -116,18 +116,18 @@ void FreeChain(); }; -#define MAX_BACKUP_ORDER_COUNT 40 +struct BackuppedOrders { + BackuppedOrders() : order(NULL) { } -struct BackuppedOrders { VehicleID clone; VehicleOrderID orderindex; - Order order[MAX_BACKUP_ORDER_COUNT + 1]; + Order *order; uint16 service_interval; char name[32]; }; VARDEF TileIndex _backup_orders_tile; -VARDEF BackuppedOrders _backup_orders_data[1]; +VARDEF BackuppedOrders _backup_orders_data; static inline VehicleOrderID GetMaxOrderIndex() { @@ -200,8 +200,8 @@ } /* Functions */ -void BackupVehicleOrders(const Vehicle *v, BackuppedOrders *order); -void RestoreVehicleOrders(const Vehicle* v, const BackuppedOrders* order); +void BackupVehicleOrders(const Vehicle *v, BackuppedOrders *order = &_backup_orders_data); +void RestoreVehicleOrders(const Vehicle *v, const BackuppedOrders *order = &_backup_orders_data); void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination); void InvalidateVehicleOrder(const Vehicle *v); bool VehicleHasDepotOrders(const Vehicle *v); diff -r d2a6acdbd665 -r 197cb8c6ae17 src/order_cmd.cpp --- a/src/order_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/order_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -19,6 +19,7 @@ #include "vehicle_gui.h" #include "cargotype.h" #include "strings.h" +#include "aircraft.h" DEFINE_OLD_POOL_GENERIC(Order, Order) @@ -198,7 +199,9 @@ break; case VEH_AIRCRAFT: - if (!(st->facilities & FACIL_AIRPORT)) return CMD_ERROR; + if (!(st->facilities & FACIL_AIRPORT) || !CanAircraftUseStation(v->engine_type, st)) { + return CMD_ERROR; + } break; default: return CMD_ERROR; @@ -239,7 +242,8 @@ if (!CheckOwnership(st->owner) || !(st->facilities & FACIL_AIRPORT) || - st->Airport()->nof_depots == 0) { + st->Airport()->nof_depots == 0 || + !CanAircraftUseStation(v->engine_type, st)) { return CMD_ERROR; } } else { @@ -317,10 +321,6 @@ if (!HasOrderPoolFree(1)) return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS); - /* XXX - This limit is only here because the backuppedorders can't - * handle any more then this.. */ - if (v->num_orders >= MAX_BACKUP_ORDER_COUNT) return_cmd_error(STR_8832_TOO_MANY_ORDERS); - if (v->type == VEH_SHIP && IsHumanPlayer(v->owner) && !_patches.new_pathfinding_all) { @@ -920,6 +920,10 @@ */ void BackupVehicleOrders(const Vehicle *v, BackuppedOrders *bak) { + /* Make sure we always have freed the stuff */ + free(bak->order); + bak->order = NULL; + /* Save general info */ bak->orderindex = v->cur_order_index; bak->service_interval = v->service_interval; @@ -939,13 +943,21 @@ bak->clone = u->index; } else { /* Else copy the orders */ - Order *order, *dest; - - dest = bak->order; /* We do not have shared orders */ bak->clone = INVALID_VEHICLE; + + /* Count the number of orders */ + uint cnt = 0; + const Order *order; + FOR_VEHICLE_ORDERS(v, order) cnt++; + + /* Allocate memory for the orders plus an end-of-orders marker */ + bak->order = MallocT(cnt + 1); + + Order *dest = bak->order; + /* Copy the orders */ FOR_VEHICLE_ORDERS(v, order) { *dest = *order; @@ -961,12 +973,10 @@ * Restore vehicle orders that are backupped via BackupVehicleOrders * */ -void RestoreVehicleOrders(const Vehicle* v, const BackuppedOrders* bak) +void RestoreVehicleOrders(const Vehicle *v, const BackuppedOrders *bak) { - uint i; - /* If we have a custom name, process that */ - if (bak->name[0] != 0) { + if (!StrEmpty(bak->name)) { _cmd_text = bak->name; DoCommandP(0, v->index, 0, NULL, CMD_NAME_VEHICLE); } @@ -981,7 +991,7 @@ * order number is one more than the current amount of orders, and because * in network the commands are queued before send, the second insert always * fails in test mode. By bypassing the test-mode, that no longer is a problem. */ - for (i = 0; bak->order[i].IsValid(); i++) { + for (uint i = 0; bak->order[i].IsValid(); i++) { if (!DoCommandP(0, v->index + (i << 16), PackOrder(&bak->order[i]), NULL, CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK)) break; } @@ -1032,7 +1042,7 @@ switch (v->type) { default: NOT_REACHED(); case VEH_TRAIN: return st->train_tile; - case VEH_AIRCRAFT: return st->airport_tile; + case VEH_AIRCRAFT: return CanAircraftUseStation(v->engine_type, st) ? st->airport_tile : 0; case VEH_SHIP: return st->dock_tile; case VEH_ROAD: if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) { diff -r d2a6acdbd665 -r 197cb8c6ae17 src/rail_cmd.cpp --- a/src/rail_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/rail_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -1065,6 +1065,7 @@ if (IsTileDepotType(tile, TRANSPORT_RAIL)) { /* Update build vehicle window related to this depot */ + InvalidateWindowData(WC_VEHICLE_DEPOT, tile); InvalidateWindowData(WC_BUILD_VEHICLE, tile); } @@ -1516,7 +1517,7 @@ const Station* st = ComposeWaypointStation(ti->tile); uint gfx = 2; - if (HASBIT(statspec->callbackmask, CBM_CUSTOM_LAYOUT)) { + if (HASBIT(statspec->callbackmask, CBM_STATION_SPRITE_LAYOUT)) { uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile); if (callback != CALLBACK_FAILED) gfx = callback; } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/road.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/road.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -0,0 +1,69 @@ +#include "stdafx.h" +#include "openttd.h" +#include "functions.h" +#include "rail_map.h" +#include "road.h" +#include "road_map.h" +#include "water_map.h" +#include "macros.h" + +bool IsPossibleCrossing(const TileIndex tile, Axis ax) +{ + return (IsTileType(tile, MP_RAILWAY) && + !HasSignals(tile) && + GetTrackBits(tile) == (ax == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X) && + GetTileSlope(tile, NULL) == SLOPE_FLAT); +} + +RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb) +{ + for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) { + const TileIndex neighbor_tile = TileAddByDiagDir(tile, dir); + + /* Get the Roadbit pointing to the neighbor_tile */ + const RoadBits target_rb = DiagDirToRoadBits(dir); + + /* If the roadbit is in the current plan */ + if (org_rb & target_rb) { + bool connective = false; + const RoadBits mirrored_rb = MirrorRoadBits(target_rb); + + switch (GetTileType(neighbor_tile)) { + /* Allways connective ones */ + case MP_CLEAR: case MP_TREES: + connective = true; + break; + + /* The conditionaly connective ones */ + case MP_TUNNELBRIDGE: + case MP_STATION: + case MP_ROAD: { + const RoadBits neighbor_rb = GetAnyRoadBits(neighbor_tile, ROADTYPE_ROAD) | GetAnyRoadBits(neighbor_tile, ROADTYPE_TRAM); + + /* Accept only connective tiles */ + connective = (neighbor_rb & mirrored_rb) || // Neighbor has got the fitting RoadBit + COUNTBITS(neighbor_rb) == 1; // Neighbor has got only one Roadbit + + } break; + + case MP_RAILWAY: + connective = IsPossibleCrossing(neighbor_tile, DiagDirToAxis(dir)); + break; + + case MP_WATER: + /* Check for real water tile */ + connective = !IsWater(neighbor_tile); + break; + + /* The defentetly not connective ones */ + default: break; + } + + /* If the neighbor tile is inconnective remove the planed road connection to it */ + if (!connective) org_rb ^= target_rb; + + } + } + + return org_rb; +} diff -r d2a6acdbd665 -r 197cb8c6ae17 src/road.h --- a/src/road.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/road.h Sat Oct 06 22:30:24 2007 +0000 @@ -116,6 +116,36 @@ } /** + * Calculate the mirrored RoadBits + * + * Simply move the bits to their new position. + * + * @param r The given RoadBits value + * @return the mirrored + */ +static inline RoadBits MirrorRoadBits(RoadBits r) +{ + return (RoadBits)(GB(r, 0, 2) << 2 | GB(r, 2, 2)); +} + +/** + * Calculate rotated RoadBits + * + * Move the Roadbits clockwise til they are in their final position. + * + * @param r The given RoadBits value + * @param rot The given Rotation angle + * @return the rotated + */ +static inline RoadBits RotateRoadBits(RoadBits r, DiagDirDiff rot) +{ + for (; rot > (DiagDirDiff)0; rot--){ + r = (RoadBits)(GB(r, 0, 1) << 3 | GB(r, 1, 3)); + } + return r; +} + +/** * Create the road-part which belongs to the given DiagDirection * * This function returns a RoadBits value which belongs to @@ -130,6 +160,16 @@ } /** + * Return if the tile is a valid tile for a crossing. + * + * @note function is overloaded + * @param tile the curent tile + * @param ax the axis of the road over the rail + * @return true if it is a valid tile + */ +bool IsPossibleCrossing(const TileIndex tile, Axis ax); + +/** * Checks whether the trackdir means that we are reversing. * @param dir the trackdir to check * @return true if it is a reversing road trackdir @@ -150,6 +190,14 @@ } /** + * Clean up unneccesary RoadBits of a planed tile. + * @param tile current tile + * @param org_rb planed RoadBits + * @return optimised RoadBits + */ +RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb); + +/** * Is it allowed to remove the given road bits from the given tile? * @param tile the tile to remove the road from * @param remove the roadbits that are going to be removed diff -r d2a6acdbd665 -r 197cb8c6ae17 src/road_cmd.cpp --- a/src/road_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/road_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -259,70 +259,121 @@ static const RoadBits _valid_tileh_slopes_road[][15] = { /* set of normal ones */ { - ROAD_ALL, ROAD_NONE, ROAD_NONE, - ROAD_X, ROAD_NONE, ROAD_NONE, // 3, 4, 5 - ROAD_Y, ROAD_NONE, ROAD_NONE, - ROAD_Y, ROAD_NONE, ROAD_NONE, // 9, 10, 11 - ROAD_X, ROAD_NONE, ROAD_NONE + ROAD_ALL, // SLOPE_FLAT + ROAD_NONE, // SLOPE_W + ROAD_NONE, // SLOPE_S + + ROAD_X, // SLOPE_SW + ROAD_NONE, // SLOPE_E + ROAD_NONE, // SLOPE_EW + + ROAD_Y, // SLOPE_SE + ROAD_NONE, // SLOPE_WSE + ROAD_NONE, // SLOPE_N + + ROAD_Y, // SLOPE_NW + ROAD_NONE, // SLOPE_NS + ROAD_NONE, // SLOPE_NE + + ROAD_X, // SLOPE_ENW + ROAD_NONE, // SLOPE_SEN + ROAD_NONE // SLOPE_ELEVATED }, /* allowed road for an evenly raised platform */ { - ROAD_NONE, - ROAD_SW | ROAD_NW, - ROAD_SW | ROAD_SE, - ROAD_Y | ROAD_SW, + ROAD_NONE, // SLOPE_FLAT + ROAD_SW | ROAD_NW, // SLOPE_W + ROAD_SW | ROAD_SE, // SLOPE_S - ROAD_SE | ROAD_NE, // 4 - ROAD_ALL, - ROAD_X | ROAD_SE, - ROAD_ALL, + ROAD_Y | ROAD_SW, // SLOPE_SW + ROAD_SE | ROAD_NE, // SLOPE_E + ROAD_ALL, // SLOPE_EW - ROAD_NW | ROAD_NE, // 8 - ROAD_X | ROAD_NW, - ROAD_ALL, - ROAD_ALL, + ROAD_X | ROAD_SE, // SLOPE_SE + ROAD_ALL, // SLOPE_WSE + ROAD_NW | ROAD_NE, // SLOPE_N - ROAD_Y | ROAD_NE, // 12 - ROAD_ALL, - ROAD_ALL + ROAD_X | ROAD_NW, // SLOPE_NW + ROAD_ALL, // SLOPE_NS + ROAD_ALL, // SLOPE_NE + + ROAD_Y | ROAD_NE, // SLOPE_ENW + ROAD_ALL, // SLOPE_SEN + ROAD_ALL // SLOPE_ELEVATED + }, + /* Singe bits on slopes */ + { + ROAD_ALL, // SLOPE_FLAT + ROAD_NE | ROAD_SE, // SLOPE_W + ROAD_NE | ROAD_NW, // SLOPE_S + + ROAD_NE, // SLOPE_SW + ROAD_NW | ROAD_SW, // SLOPE_E + ROAD_ALL, // SLOPE_EW + + ROAD_NW, // SLOPE_SE + ROAD_ALL, // SLOPE_WSE + ROAD_SE | ROAD_SW, // SLOPE_N + + ROAD_SE, // SLOPE_NW + ROAD_ALL, // SLOPE_NS + ROAD_ALL, // SLOPE_NE + + ROAD_SW, // SLOPE_ENW + ROAD_ALL, // SLOPE_SEN + ROAD_ALL, // SLOPE_ELEVATED }, }; - +/** + * Calculate the costs for roads on slopes + * Aside modify the RoadBits to fit on the slopes + * + * @note The RoadBits are modified too! + * @param tileh The current slope + * @param pieces The RoadBits we want to add + * @param existing The existent RoadBits + * @return The costs for these RoadBits on this slope + */ static CommandCost CheckRoadSlope(Slope tileh, RoadBits* pieces, RoadBits existing) { - RoadBits road_bits; - if (IsSteepSlope(tileh)) { - /* force full pieces. */ - *pieces |= (RoadBits)((*pieces & 0xC) >> 2); - *pieces |= (RoadBits)((*pieces & 0x3) << 2); + /* Force straight roads. */ + *pieces |= MirrorRoadBits(*pieces); - if (existing == 0 || existing == *pieces) { + if (existing == ROAD_NONE || existing == *pieces) { if (*pieces == ROAD_X || *pieces == ROAD_Y) return _price.terraform; } return CMD_ERROR; } - road_bits = *pieces | existing; + + RoadBits road_bits = *pieces | existing; + + /* Single bits on slopes. + * We check for the roads that need at least 2 bits */ + if (_patches.build_on_slopes && + existing == ROAD_NONE && COUNTBITS(*pieces) == 1 && + (_valid_tileh_slopes_road[2][tileh] & *pieces) == ROAD_NONE) { + return CommandCost(_price.terraform); + } /* no special foundation */ - if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == 0) { + if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == ROAD_NONE) { /* force that all bits are set when we have slopes */ if (tileh != SLOPE_FLAT) *pieces |= _valid_tileh_slopes_road[0][tileh]; return CommandCost(); // no extra cost } /* foundation is used. Whole tile is leveled up */ - if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == 0) { - return CommandCost(existing != 0 ? 0 : _price.terraform); + if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == ROAD_NONE) { + return CommandCost(existing != ROAD_NONE ? 0 : _price.terraform); } - *pieces |= (RoadBits)((*pieces & 0xC) >> 2); - *pieces |= (RoadBits)((*pieces & 0x3) << 2); + /* Force straight roads. */ + *pieces |= MirrorRoadBits(*pieces); /* partly leveled up tile, only if there's no road on that tile */ - if ((existing == 0 || existing == *pieces) && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) { - /* force full pieces. */ + if ((existing == ROAD_NONE || existing == *pieces) && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) { if (*pieces == ROAD_X || *pieces == ROAD_Y) return _price.terraform; } return CMD_ERROR; @@ -602,7 +653,7 @@ /* On the X-axis, we have to swap the initial bits, so they * will be interpreted correctly in the GTTS. Futhermore * when you just 'click' on one tile to build them. */ - if (HASBIT(p2, 2) == (start_tile == end_tile)) drd ^= DRD_BOTH; + if (HASBIT(p2, 2) == (start_tile == end_tile && HASBIT(p2, 0) == HASBIT(p2, 1))) drd ^= DRD_BOTH; /* No disallowed direction bits have to be toggled */ if (!HASBIT(p2, 5)) drd = DRD_NONE; @@ -785,10 +836,11 @@ case ROAD_TILE_NORMAL: { RoadBits b = GetAllRoadBits(tile); -#define M(x) (1 << (x)) /* Clear the road if only one piece is on the tile OR the AI tries * to clear town road OR we are not using the DC_AUTO flag */ - if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) || !(flags & DC_AUTO)) { + if ((COUNTBITS(b) == 1 && GetRoadBits(tile, ROADTYPE_TRAM) == ROAD_NONE) || + IsTileOwner(tile, OWNER_TOWN) || !(flags & DC_AUTO) + ) { RoadTypes rts = GetRoadTypes(tile); CommandCost ret; for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { @@ -802,7 +854,6 @@ } return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); } -#undef M case ROAD_TILE_CROSSING: { RoadTypes rts = GetRoadTypes(tile); @@ -1179,8 +1230,8 @@ if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) return; + const Town* t = ClosestTownFromTile(tile, (uint)-1); if (!HasRoadWorks(tile)) { - const Town* t = ClosestTownFromTile(tile, (uint)-1); int grp = 0; if (t != NULL) { @@ -1189,8 +1240,8 @@ /* Show an animation to indicate road work */ if (t->road_build_months != 0 && (DistanceManhattan(t->xy, tile) < 8 || grp != 0) && - GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetAllRoadBits(tile) == ROAD_X || GetAllRoadBits(tile) == ROAD_Y)) { - if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) { + GetRoadTileType(tile) == ROAD_TILE_NORMAL && COUNTBITS(GetAllRoadBits(tile)) > 1 ) { + if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 40)) { StartRoadWorks(tile); SndPlayTileFx(SND_21_JACKHAMMER, tile); @@ -1228,6 +1279,17 @@ } } else if (IncreaseRoadWorksCounter(tile)) { TerminateRoadWorks(tile); + + if (_patches.mod_road_rebuild) { + /* Generate a nicer town surface */ + const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD); + const RoadBits new_rb = CleanUpRoadBits(tile, old_rb); + + if (old_rb != new_rb) { + DoCommand(tile, (old_rb ^ new_rb), t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_REMOVE_ROAD); + } + } + MarkTileDirtyByTile(tile); } } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/roadveh_cmd.cpp --- a/src/roadveh_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/roadveh_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -1001,7 +1001,7 @@ const Vehicle* u; const Vehicle* v; TileIndex tile; - byte tilebits; + uint16 tilebits; }; static void* EnumFindVehToOvertake(Vehicle* v, void* data) @@ -1017,9 +1017,10 @@ { uint32 bits; - bits = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, od->v->u.road.compatible_roadtypes) & 0x3F; + bits = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, od->v->u.road.compatible_roadtypes); + bits |= bits >> 8; - if (!(od->tilebits & bits) || (bits & 0x3C) || (bits & 0x3F3F0000)) + if (!(od->tilebits & bits) || (bits & 0x3C3C) || (bits & 0x3F3F0000)) return true; return VehicleFromPos(od->tile, od, EnumFindVehToOvertake) != NULL; } @@ -1027,7 +1028,7 @@ static void RoadVehCheckOvertake(Vehicle *v, Vehicle *u) { OvertakeData od; - byte tt; + uint16 tt; od.v = v; od.u = u; @@ -1041,6 +1042,9 @@ /* Trams can't overtake other trams */ if (v->u.road.roadtype == ROADTYPE_TRAM) return; + /* Don't overtake in stations */ + if (IsTileType(v->tile, MP_STATION)) return; + /* For now, articulated road vehicles can't overtake anything. */ if (RoadVehHasArticPart(v)) return; @@ -1049,7 +1053,10 @@ /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */ if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return; - tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes) & 0x3F; + tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes); + tt |= tt >> 8; + tt &= 0x3F; + if ((tt & 3) == 0) return; if ((tt & 0x3C) != 0) return; @@ -1650,9 +1657,9 @@ Vehicle* u = RoadVehFindCloseTo(v, x, y, new_dir); if (u != NULL) { - v->cur_speed = u->cur_speed; /* There is a vehicle in front overtake it if possible */ if (v->u.road.overtaking == 0) RoadVehCheckOvertake(v, u); + if (v->u.road.overtaking == 0) v->cur_speed = u->cur_speed; return false; } } @@ -2026,7 +2033,7 @@ if (v->cargo_cap == 0) continue; - if (HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_REFIT_CAPACITY)) { + if (HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) { /* Back up the cargo type */ CargoID temp_cid = v->cargo_type; byte temp_subtype = v->cargo_subtype; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/roadveh_gui.cpp --- a/src/roadveh_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/roadveh_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -128,7 +128,7 @@ v = GetVehicle(_new_vehicle_id); if (v->tile == _backup_orders_tile) { _backup_orders_tile = 0; - RestoreVehicleOrders(v, _backup_orders_data); + RestoreVehicleOrders(v); } ShowVehicleViewWindow(v); } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/saveload.cpp --- a/src/saveload.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/saveload.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -29,7 +29,7 @@ #include "strings.h" #include -extern const uint16 SAVEGAME_VERSION = 76; +extern const uint16 SAVEGAME_VERSION = 79; uint16 _sl_version; ///< the major savegame version identifier byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! diff -r d2a6acdbd665 -r 197cb8c6ae17 src/settings.cpp --- a/src/settings.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/settings.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -1423,6 +1423,8 @@ SDT_BOOL(Patches, multiple_industry_per_town, 0, 0, false, STR_CONFIG_PATCHES_MULTIPINDTOWN, NULL), SDT_BOOL(Patches, same_industry_close, 0, 0, false, STR_CONFIG_PATCHES_SAMEINDCLOSE, NULL), SDT_BOOL(Patches, bribe, 0, 0, true, STR_CONFIG_PATCHES_BRIBE, NULL), + SDT_CONDBOOL(Patches, exclusive_rights, 79, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_ALLOW_EXCLUSIVE, NULL), + SDT_CONDBOOL(Patches, give_money, 79, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_ALLOW_GIVE_MONEY, NULL), SDT_VAR(Patches, snow_line_height,SLE_UINT8, 0, 0, 7, 2, 13, 0, STR_CONFIG_PATCHES_SNOWLINE_HEIGHT, NULL), SDT_VAR(Patches, colored_news_year,SLE_INT32, 0,NC, 2000, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_COLORED_NEWS_YEAR,NULL), SDT_VAR(Patches, starting_year, SLE_INT32, 0,NC, 1950, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_STARTING_YEAR,NULL), @@ -1432,6 +1434,7 @@ SDT_CONDVAR(Patches, town_growth_rate, SLE_UINT8, 54, SL_MAX_VERSION, 0, MS, 2, 0, 4, 0, STR_CONFIG_PATCHES_TOWN_GROWTH, NULL), SDT_CONDVAR(Patches, larger_towns, SLE_UINT8, 54, SL_MAX_VERSION, 0, D0, 4, 0, 255, 1, STR_CONFIG_PATCHES_LARGER_TOWNS, NULL), SDT_CONDVAR(Patches, initial_city_size, SLE_UINT8, 56, SL_MAX_VERSION, 0, 0, 2, 1, 10, 1, STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER, NULL), + SDT_CONDBOOL(Patches, mod_road_rebuild, 77, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_MODIFIED_ROAD_REBUILD, NULL), /***************************************************************************/ /* AI section of the GUI-configure patches window */ diff -r d2a6acdbd665 -r 197cb8c6ae17 src/settings_gui.cpp --- a/src/settings_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/settings_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -672,7 +672,6 @@ "drag_signals_density", "oil_refinery_limit", "semaphore_build_before", - "town_layout", }; static const char *_patches_stations[] = { @@ -696,10 +695,14 @@ "multiple_industry_per_town", "same_industry_close", "bribe", + "exclusive_rights", + "give_money", "colored_news_year", "ending_year", "smooth_economy", "allow_shares", + "town_layout", + "mod_road_rebuild", "town_growth_rate", "larger_towns", "initial_city_size", diff -r d2a6acdbd665 -r 197cb8c6ae17 src/ship_cmd.cpp --- a/src/ship_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/ship_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -1079,7 +1079,7 @@ SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN); /* Check the refit capacity callback */ - if (HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_REFIT_CAPACITY)) { + if (HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) { /* Back up the existing cargo type */ CargoID temp_cid = v->cargo_type; byte temp_subtype = v->cargo_subtype; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/ship_gui.cpp --- a/src/ship_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/ship_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -35,7 +35,7 @@ v = GetVehicle(_new_vehicle_id); if (v->tile == _backup_orders_tile) { _backup_orders_tile = 0; - RestoreVehicleOrders(v, _backup_orders_data); + RestoreVehicleOrders(v); } ShowVehicleViewWindow(v); } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/slope.h --- a/src/slope.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/slope.h Sat Oct 06 22:30:24 2007 +0000 @@ -41,6 +41,16 @@ }; /** + * Enumeration of tile corners + */ +enum Corner { + CORNER_W = 0, + CORNER_S = 1, + CORNER_E = 2, + CORNER_N = 3, +}; + +/** * Checks if a slope is steep. * * @param s The given #Slope. @@ -73,19 +83,19 @@ * * @pre The slope must be a slope with one corner raised or a steep slope. * @param s The #Slope. - * @return Number of the highest corner. (0 west, 1 south, 2 east, 3 north) + * @return Highest corner. */ -static inline byte GetHighestSlopeCorner(Slope s) +static inline Corner GetHighestSlopeCorner(Slope s) { switch (s) { case SLOPE_W: - case SLOPE_STEEP_W: return 0; + case SLOPE_STEEP_W: return CORNER_W; case SLOPE_S: - case SLOPE_STEEP_S: return 1; + case SLOPE_STEEP_S: return CORNER_S; case SLOPE_E: - case SLOPE_STEEP_E: return 2; + case SLOPE_STEEP_E: return CORNER_E; case SLOPE_N: - case SLOPE_STEEP_N: return 3; + case SLOPE_STEEP_N: return CORNER_N; default: NOT_REACHED(); } } @@ -103,6 +113,40 @@ return TILE_HEIGHT; } +/** + * Returns the opposite corner. + * + * @param corner A #Corner. + * @return The opposite corner to "corner". + */ +static inline Corner OppositeCorner(Corner corner) +{ + return (Corner)(corner ^ 2); +} + +/** + * Returns the slope with a specific corner raised. + * + * @param corner The #Corner. + * @return The #Slope with corner "corner" raised. + */ +static inline Slope SlopeWithOneCornerRaised(Corner corner) +{ + assert(IS_INT_INSIDE(corner, 0, 4)); + return (Slope)(1 << corner); +} + +/** + * Returns the slope with all except one corner raised. + * + * @param corner The #Corner. + * @return The #Slope with all corners but "corner" raised. + */ +static inline Slope SlopeWithThreeCornersRaised(Corner corner) +{ + return ComplementSlope(SlopeWithOneCornerRaised(corner)); +} + /** * Enumeration for Foundations. diff -r d2a6acdbd665 -r 197cb8c6ae17 src/station_cmd.cpp --- a/src/station_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/station_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -165,14 +165,14 @@ /* No industry */ if (!IsTileType(tile, MP_INDUSTRY)) return false; - const IndustrySpec *indsp = GetIndustrySpec(GetIndustryByTile(tile)->type); + const Industry *ind = GetIndustryByTile(tile); /* No extractive industry */ - if ((indsp->life_type & INDUSTRYLIFE_EXTRACTIVE) == 0) return false; - - for (uint i = 0; i < lengthof(indsp->produced_cargo); i++) { + if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_EXTRACTIVE) == 0) return false; + + for (uint i = 0; i < lengthof(ind->produced_cargo); i++) { /* The industry extracts something non-liquid, i.e. no oil or plastic, so it is a mine */ - if (indsp->produced_cargo[i] != CT_INVALID && (GetCargo(indsp->produced_cargo[i])->classes & CC_LIQUID) == 0) return true; + if (ind->produced_cargo[i] != CT_INVALID && (GetCargo(ind->produced_cargo[i])->classes & CC_LIQUID) == 0) return true; } return false; @@ -208,14 +208,14 @@ /* No industry */ if (!IsTileType(tile, MP_INDUSTRY)) return false; - const IndustrySpec *indsp = GetIndustrySpec(GetIndustryByTile(tile)->type); + const Industry *ind = GetIndustryByTile(tile); /* No extractive industry */ - if ((indsp->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false; - - for (uint i = 0; i < lengthof(indsp->produced_cargo); i++) { + if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false; + + for (uint i = 0; i < lengthof(ind->produced_cargo); i++) { /* The industry produces wood. */ - if (indsp->produced_cargo[i] != CT_INVALID && GetCargo(indsp->produced_cargo[i])->label == 'WOOD') return true; + if (ind->produced_cargo[i] != CT_INVALID && GetCargo(ind->produced_cargo[i])->label == 'WOOD') return true; } return false; @@ -1732,7 +1732,7 @@ } BEGIN_TILE_LOOP(tile_cur, w, h, tile) { - if (!EnsureNoVehicle(tile_cur)) return CMD_ERROR; + if (!EnsureNoVehicleOnGround(tile_cur)) return CMD_ERROR; if (flags & DC_EXEC) { DeleteAnimatedTile(tile_cur); @@ -2054,7 +2054,7 @@ relocation = GetCustomStationRelocation(statspec, st, ti->tile); - if (HASBIT(statspec->callbackmask, CBM_CUSTOM_LAYOUT)) { + if (HASBIT(statspec->callbackmask, CBM_STATION_SPRITE_LAYOUT)) { uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile); if (callback != CALLBACK_FAILED) tile = (callback & ~1) + GetRailStationAxis(ti->tile); } @@ -2115,7 +2115,7 @@ HASBIT(_transparent_opt, TO_BUILDINGS) ); } else { - AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y); + AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y, HASBIT(_transparent_opt, TO_BUILDINGS)); } } } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/town_cmd.cpp --- a/src/town_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/town_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -98,6 +98,13 @@ // Local static int _grow_town_result; +/* Describe the possible states */ +enum TownGrowthResult { + GROWTH_SUCCEED = -1, + GROWTH_SEARCH_STOPPED = 0 +// GROWTH_SEARCH_RUNNING >= 1 +}; + static bool BuildTownHouse(Town *t, TileIndex tile); static void DoBuildTownHouse(Town *t, TileIndex tile); @@ -133,18 +140,6 @@ } /** - * Move a TileIndex into a diagonal direction. - * - * @param tile The current tile - * @param dir The direction in which we want to step - * @return the moved tile - */ -static inline TileIndex AddDiagDirToTileIndex(TileIndex tile, DiagDirection dir) -{ - return TILE_ADD(tile, TileOffsByDiagDir(dir)); -} - -/** * House Tile drawing handler. * Part of the tile loop process * @param ti TileInfo of the tile to draw @@ -359,7 +354,7 @@ if (GetHouseConstructionTick(tile) != 0) return; /* Check and/or */ - if (HASBIT(GetHouseSpecs(GetHouseType(tile))->callback_mask, CBM_CONSTRUCTION_STATE_CHANGE)) { + if (HASBIT(GetHouseSpecs(GetHouseType(tile))->callback_mask, CBM_HOUSE_CONSTRUCTION_STATE_CHANGE)) { uint16 callback_res = GetHouseCallback(CBID_HOUSE_CONSTRUCTION_STATE_CHANGE, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res); } @@ -547,7 +542,7 @@ } /* Check for custom cargo acceptance */ - if (HASBIT(hs->callback_mask, CBM_CARGO_ACCEPTANCE)) { + if (HASBIT(hs->callback_mask, CBM_HOUSE_CARGO_ACCEPTANCE)) { uint16 callback = GetHouseCallback(CBID_HOUSE_CARGO_ACCEPTANCE, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); if (callback != CALLBACK_FAILED) { if (accepts[0] != CT_INVALID) ac[accepts[0]] = GB(callback, 0, 4); @@ -661,7 +656,7 @@ */ static bool IsNeighborRoadTile(TileIndex tile, DiagDirection dir, uint dist_multi) { - static TileIndexDiff tid_lt[3]; ///< lookup table for the used diff values + static TileIndexDiff tid_lt[3]; // lookup table for the used diff values tid_lt[0] = TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90RIGHT)); tid_lt[1] = TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90LEFT)); tid_lt[2] = TileOffsByDiagDir(ReverseDiagDir(dir)); @@ -681,7 +676,7 @@ cur += tid_lt[(pos & 1) ? 0 : 1]; if (pos & 2) cur += tid_lt[2]; - cur = (uint)(pos / 4) * cur; ///< Multiply for the fitting distance + cur = (uint)(pos / 4) * cur; // Multiply for the fitting distance if (GetTownRoadBits(TILE_ADD(tile, cur)) & DiagDirToRoadBits((pos & 2) ? dir : ReverseDiagDir(dir))) return true; } return false; @@ -797,7 +792,7 @@ static RoadBits GetTownRoadGridElement(Town* t, TileIndex tile, DiagDirection dir) { /* align the grid to the downtown */ - TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); ///< Vector from downtown to the tile + TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); // Vector from downtown to the tile RoadBits rcmd = ROAD_NONE; switch (_patches.town_layout) { @@ -849,32 +844,110 @@ } /** - * Check there are enough neighbor house tiles next to the current tile + * Grows the town with an extra house. + * Check if there are enough neighbor house tiles + * next to the current tile. If there are enough + * add another house. * - * @param tile current tile - * @return true if there are more than 2 house tiles next - * to the current one + * @param t The current town + * @param tile The target tile for the extra house + * @return true if an extra house has been added */ -static bool AreNeighborsHouseTiles(TileIndex tile) +static bool GrowTownWithExtraHouse(Town *t, TileIndex tile) { - uint counter = 0; ///< counts the house neighbor tiles - /* We can't look further than that. */ - if (TileX(tile) < 1 || TileY(tile) < 1) { - return false; + if (TileX(tile) < 2 || TileY(tile) < 2 || MapMaxX() <= TileX(tile) || MapMaxY() <= TileY(tile)) return false; + + uint counter = 0; // counts the house neighbor tiles + + /* Check the tiles E,N,W and S of the current tile for houses */ + for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) { + + if (IsTileType(TileAddByDiagDir(tile, dir), MP_HOUSE)) counter++; + + /* If there are enough neighbors stop here */ + if (counter >= 3) { + if (BuildTownHouse(t, tile)) { + _grow_town_result = GROWTH_SUCCEED; + return true; + } + return false; + } } - - /* Check the tiles E,N,W and S of the current tile. */ - for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) { - if (IsTileType(AddDiagDirToTileIndex(tile, i), MP_HOUSE)) { - counter++; + return false; +} + +/** + * Grows the town with a road piece. + * + * @param t The current town + * @param tile The current tile + * @param rcmd The RoadBits we want to build on the tile + * @return true if the RoadBits have been added else false + */ +static bool GrowTownWithRoad(const Town *t, TileIndex tile, RoadBits rcmd) +{ + if (CmdSucceeded(DoCommand(tile, rcmd, t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD))) { + _grow_town_result = GROWTH_SUCCEED; + return true; + } + return false; +} + +/** + * Grows the town with a bridge. + * At first we check if a bridge is reasonable. + * If so we check if we are able to build it. + * + * @param t The current town + * @param tile The current tile + * @param rcmd The RoadBits which are possible on this tile + * @return true if a bridge has been build else false + */ +static bool GrowTownWithBridge(const Town *t, TileIndex tile, RoadBits rcmd) +{ + DiagDirection bridge_dir; // The direction of a bridge we maybe want to build + + /* Determine direction of slope, + * and build a road if not a special slope. */ + switch (GetTileSlope(tile, NULL)) { + case SLOPE_SW: bridge_dir = DIAGDIR_NE; break; + case SLOPE_SE: bridge_dir = DIAGDIR_NW; break; + case SLOPE_NW: bridge_dir = DIAGDIR_SE; break; + case SLOPE_NE: bridge_dir = DIAGDIR_SW; break; + + default: return false; + } + + /* Check if the bridge will be compatible to the RoadBits */ + if (!(rcmd & DiagDirToRoadBits(ReverseDiagDir(bridge_dir)))) return false; + + /* We are in the right direction */ + uint32 bridge_length = 0; // This value stores the length of the possible bridge + TileIndex bridge_tile = tile; // Used to store the other waterside + + do { + if (bridge_length++ >= 11) { + /* Max 11 tile long bridges */ + return false; } - - /* If there are enougth neighbor's stop it here */ - if (counter >= 3) { + bridge_tile = TILE_MASK(bridge_tile + TileOffsByDiagDir(bridge_dir)); + } while (IsClearWaterTile(bridge_tile)); + + /* no water tiles in between? */ + if (bridge_length == 1) return false; + + for (uint8 times = 0; times <= 22; times++) { + byte bridge_type = RandomRange(MAX_BRIDGES - 1); + + /* Can we actually build the bridge? */ + if (CmdSucceeded(DoCommand(tile, bridge_tile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO, CMD_BUILD_BRIDGE))) { + DoCommand(tile, bridge_tile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_EXEC | DC_AUTO, CMD_BUILD_BRIDGE); + _grow_town_result = GROWTH_SUCCEED; return true; } } + /* Quit if it selecting an appropiate bridge type fails a large number of times. */ return false; } @@ -882,32 +955,31 @@ * Grows the given town. * There are at the moment 3 possible way's for * the town expansion: - * @li Generate a random tile and check if there is a road allowed - * @li TL_ORIGINAL - * @li TL_BETTER_ROADS - * @li Check if the town geometry allows a road and which one - * @li TL_2X2_GRID - * @li TL_3X3_GRID - * @li Forbid roads, only build houses - * @li TL_NO_ROADS + * @li Generate a random tile and check if there is a road allowed + * @li TL_ORIGINAL + * @li TL_BETTER_ROADS + * @li Check if the town geometry allows a road and which one + * @li TL_2X2_GRID + * @li TL_3X3_GRID + * @li Forbid roads, only build houses + * @li TL_NO_ROADS * * @param tile_ptr The current tile * @param cur_rb The current tiles RoadBits * @param target_dir The target road dir * @param t1 The current town */ -static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection target_dir, Town* t1) +static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection target_dir, Town *t1) { - RoadBits rcmd = ROAD_NONE; ///< RoadBits for the road construction command - TileIndex tmptile; ///< Dummy tile for various things - TileIndex tile = *tile_ptr; ///< The main tile on which we base our growth + RoadBits rcmd = ROAD_NONE; // RoadBits for the road construction command + TileIndex tile = *tile_ptr; // The main tile on which we base our growth TILE_ASSERT(tile); if (cur_rb == ROAD_NONE) { /* Tile has no road. First reset the status counter * to say that this is the last iteration. */ - _grow_town_result = 0; + _grow_town_result = GROWTH_SEARCH_STOPPED; /* Remove hills etc */ LevelTownLand(tile); @@ -936,14 +1008,14 @@ do target_dir = RandomDiagDir(); while (target_dir == source_dir); } - if (!IsRoadAllowedHere(AddDiagDirToTileIndex(tile, target_dir), target_dir)) { + if (!IsRoadAllowedHere(TileAddByDiagDir(tile, target_dir), target_dir)) { /* A road is not allowed to continue the randomized road, * return if the road we're trying to build is curved. */ if (target_dir != ReverseDiagDir(source_dir)) return; /* Return if neither side of the new road is a house */ - if (!IsTileType(AddDiagDirToTileIndex(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90RIGHT)), MP_HOUSE) && - !IsTileType(AddDiagDirToTileIndex(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90LEFT)), MP_HOUSE)) { + if (!IsTileType(TileAddByDiagDir(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90RIGHT)), MP_HOUSE) && + !IsTileType(TileAddByDiagDir(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90LEFT)), MP_HOUSE)) { return; } @@ -955,11 +1027,11 @@ break; } - } else if (target_dir < (DiagDirection)5 && !(cur_rb & DiagDirToRoadBits(ReverseDiagDir(target_dir)))) { + } else if (target_dir < DIAGDIR_END && !(cur_rb & DiagDirToRoadBits(ReverseDiagDir(target_dir)))) { /* Continue building on a partial road. * Should be allways OK, so we only generate * the fitting RoadBits */ - _grow_town_result = 0; + _grow_town_result = GROWTH_SEARCH_STOPPED; switch (_patches.town_layout) { default: NOT_REACHED(); @@ -978,8 +1050,7 @@ break; } } else { - bool allow_house = false; ///< Value which decides if we want to construct a house - TileIndex tmptile2; ///< Yet another dummy tile + bool allow_house = false; // Value which decides if we want to construct a house /* Reached a tunnel/bridge? Then continue at the other side of it. */ if (IsTileType(tile, MP_TUNNELBRIDGE)) { @@ -997,10 +1068,10 @@ if (cur_rb & DiagDirToRoadBits(target_dir)) return; /* This is the tile we will reach if we extend to this direction. */ - tmptile = AddDiagDirToTileIndex(tile, target_dir); + TileIndex house_tile = TileAddByDiagDir(tile, target_dir); // position of a possible house /* Don't walk into water. */ - if (IsClearWaterTile(tmptile)) return; + if (IsClearWaterTile(house_tile)) return; switch (_patches.town_layout) { default: NOT_REACHED(); @@ -1010,98 +1081,54 @@ break; case TL_3X3_GRID: /* Use 2x2 grid afterwards! */ - /* Fill gap if house has enougth neighbors */ - tmptile2 = AddDiagDirToTileIndex(tmptile, target_dir); - if (AreNeighborsHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) { - _grow_town_result = -1; - } + GrowTownWithExtraHouse(t1, TileAddByDiagDir(house_tile, target_dir)); + /* FALL THROUGH */ case TL_2X2_GRID: - rcmd = GetTownRoadGridElement(t1, tmptile, target_dir); + rcmd = GetTownRoadGridElement(t1, house_tile, target_dir); allow_house = (rcmd == ROAD_NONE); break; case TL_BETTER_ROADS: /* Use original afterwards! */ - /* Fill gap if house has enougth neighbors */ - tmptile2 = AddDiagDirToTileIndex(tmptile, target_dir); - if (AreNeighborsHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) { - _grow_town_result = -1; - } + GrowTownWithExtraHouse(t1, TileAddByDiagDir(house_tile, target_dir)); + /* FALL THROUGH */ case TL_ORIGINAL: /* Allow a house at the edge. 60% chance or * always ok if no road allowed. */ rcmd = DiagDirToRoadBits(target_dir); - allow_house = (!IsRoadAllowedHere(tmptile, target_dir) || CHANCE16(6, 10)); + allow_house = (!IsRoadAllowedHere(house_tile, target_dir) || CHANCE16(6, 10)); break; } if (allow_house) { /* Build a house, but not if there already is a house there. */ - if (!IsTileType(tmptile, MP_HOUSE)) { + if (!IsTileType(house_tile, MP_HOUSE)) { /* Level the land if possible */ - LevelTownLand(tmptile); + LevelTownLand(house_tile); /* And build a house. * Set result to -1 if we managed to build it. */ - if (BuildTownHouse(t1, tmptile)) { - _grow_town_result = -1; + if (BuildTownHouse(t1, house_tile)) { + _grow_town_result = GROWTH_SUCCEED; } } return; } - _grow_town_result = 0; + _grow_town_result = GROWTH_SEARCH_STOPPED; } /* Return if a water tile */ if (IsClearWaterTile(tile)) return; - DiagDirection bridge_dir; ///< The direction of a bridge we maybe want to build - /* Determine direction of slope, - * and build a road if not a special slope. */ - switch (GetTileSlope(tile, NULL)) { - case SLOPE_SW: bridge_dir = DIAGDIR_NE; break; - case SLOPE_SE: bridge_dir = DIAGDIR_NW; break; - case SLOPE_NW: bridge_dir = DIAGDIR_SE; break; - case SLOPE_NE: bridge_dir = DIAGDIR_SW; break; - - default: -build_road_and_exit: - if (CmdSucceeded(DoCommand(tile, rcmd, t1->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD))) { - _grow_town_result = -1; - } - return; - } - - /* Check if the bridge is in the right direction */ - if (!(rcmd & DiagDirToRoadBits(bridge_dir))) goto build_road_and_exit; - - /* We are in the right direction */ - uint32 bridge_length = 0; ///< This value stores the length of the possible bridge - tmptile = tile; ///< Now we use this dummy to store the other waterside - do { - if (bridge_length++ >= 11) { - /* Max 11 tile long bridges */ - goto build_road_and_exit; - } - tmptile = TILE_MASK(tmptile + TileOffsByDiagDir(bridge_dir)); - } while (IsClearWaterTile(tmptile)); - - /* no water tiles in between? */ - if (bridge_length == 1) goto build_road_and_exit; - - for (uint times = 0; times <= 22; times++) { - byte bridge_type = RandomRange(MAX_BRIDGES - 1); - - /* Can we actually build the bridge? */ - if (CmdSucceeded(DoCommand(tile, tmptile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO, CMD_BUILD_BRIDGE))) { - DoCommand(tile, tmptile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_EXEC | DC_AUTO, CMD_BUILD_BRIDGE); - _grow_town_result = -1; - return; - } - } - /* Quit if it selecting an appropiate bridge type fails a large number of times. */ + /* Make the roads look nicer */ + rcmd = CleanUpRoadBits(tile, rcmd); + if (rcmd == ROAD_NONE) return; + + if (GrowTownWithBridge(t1, tile, rcmd)) return; + + GrowTownWithRoad(t1, tile, rcmd); } /** Returns "growth" if a house was built, or no if the build failed. @@ -1114,7 +1141,7 @@ /* Special case. * @see GrowTownInTile Check the else if */ - DiagDirection target_dir = (DiagDirection)5; ///< The direction in which we want to extend the town + DiagDirection target_dir = DIAGDIR_END; // The direction in which we want to extend the town TILE_ASSERT(tile); @@ -1137,7 +1164,7 @@ } do { - RoadBits cur_rb = GetTownRoadBits(tile); ///< The RoadBits of the current tile + RoadBits cur_rb = GetTownRoadBits(tile); // The RoadBits of the current tile /* Try to grow the town from this point */ GrowTownInTile(&tile, cur_rb, target_dir, t); @@ -1151,12 +1178,12 @@ /* Select a random bit from the blockmask, walk a step * and continue the search from there. */ do target_dir = RandomDiagDir(); while (!(cur_rb & DiagDirToRoadBits(target_dir))); - tile = AddDiagDirToTileIndex(tile, target_dir); + tile = TileAddByDiagDir(tile, target_dir); if (IsTileType(tile, MP_ROAD)) { /* Don't allow building over roads of other cities */ if (IsTileOwner(tile, OWNER_TOWN) && GetTownByTile(tile) != t) { - _grow_town_result = -1; + _grow_town_result = GROWTH_SUCCEED; } else if (_game_mode == GM_EDITOR) { /* If we are in the SE, and this road-piece has no town owner yet, it just found an * owner :) (happy happy happy road now) */ @@ -1220,7 +1247,7 @@ PlayerID old_player = _current_player; _current_player = OWNER_TOWN; - TileIndex tile = t->xy; ///< The tile we are working with ATM + TileIndex tile = t->xy; // The tile we are working with ATM /* Find a road that we can base the construction on. */ for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) { @@ -1994,6 +2021,9 @@ static void TownActionBuyRights(Town* t) { + /* Check if it's allowed to by the rights */ + if (!_patches.exclusive_rights) return; + t->exclusive_counter = 12; t->exclusivity = _current_player; @@ -2110,8 +2140,8 @@ /** Towns are processed every TOWN_GROWTH_FREQUENCY ticks, and this is the * number of times towns are processed before a new building is built. */ static const uint16 _grow_count_values[2][6] = { - { 120, 120, 120, 100, 80, 60 }, ///< Fund new buildings has been activated - { 320, 420, 300, 220, 160, 100 } ///< Normal values + { 120, 120, 120, 100, 80, 60 }, // Fund new buildings has been activated + { 320, 420, 300, 220, 160, 100 } // Normal values }; if (t->fund_buildings_months != 0) { @@ -2252,9 +2282,9 @@ /* penalty for removing town-owned stuff */ static const int _default_rating_settings [3][3] = { /* ROAD_REMOVE, TUNNELBRIDGE_REMOVE, INDUSTRY_REMOVE */ - { 0, 128, 384}, ///< Permissive - { 48, 192, 480}, ///< Neutral - { 96, 384, 768}, ///< Hostile + { 0, 128, 384}, // Permissive + { 48, 192, 480}, // Neutral + { 96, 384, 768}, // Hostile }; bool CheckforTownRating(uint32 flags, Town *t, byte type) @@ -2499,4 +2529,7 @@ { memset(&_house_specs, 0, sizeof(_house_specs)); memcpy(&_house_specs, &_original_house_specs, sizeof(_original_house_specs)); + + /* Reset any overrides that have been set. */ + _house_mngr.ResetOverride(); } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/town_gui.cpp --- a/src/town_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/town_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -20,19 +20,49 @@ #include "variables.h" #include "helpers.hpp" +enum TownAuthorityWidget { + TWA_CLOSEBOX = 0, + TWA_CAPTION, + TWA_RATING_INFO, + TWA_COMMAND_LIST, + TWA_SCROLLBAR, + TWA_ACTION_INFO, + TWA_EXECUTE, +}; + static const Widget _town_authority_widgets[] = { -{ WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, RESIZE_NONE, 13, 11, 316, 0, 13, STR_2022_LOCAL_AUTHORITY, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PANEL, RESIZE_NONE, 13, 0, 316, 14, 105, 0x0, STR_NULL}, -{ WWT_PANEL, RESIZE_NONE, 13, 0, 304, 106, 157, 0x0, STR_2043_LIST_OF_THINGS_TO_DO_AT}, -{ WWT_SCROLLBAR, RESIZE_NONE, 13, 305, 316, 106, 157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -{ WWT_PANEL, RESIZE_NONE, 13, 0, 316, 158, 209, 0x0, STR_NULL}, -{ WWT_PUSHTXTBTN, RESIZE_NONE, 13, 0, 316, 210, 221, STR_2042_DO_IT, STR_2044_CARRY_OUT_THE_HIGHLIGHTED}, +{ WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // TWA_CLOSEBOX +{ WWT_CAPTION, RESIZE_NONE, 13, 11, 316, 0, 13, STR_2022_LOCAL_AUTHORITY, STR_018C_WINDOW_TITLE_DRAG_THIS}, // TWA_CAPTION +{ WWT_PANEL, RESIZE_NONE, 13, 0, 316, 14, 105, 0x0, STR_NULL}, // TWA_RATING_INFO +{ WWT_PANEL, RESIZE_NONE, 13, 0, 304, 106, 157, 0x0, STR_2043_LIST_OF_THINGS_TO_DO_AT}, // TWA_COMMAND_LIST +{ WWT_SCROLLBAR, RESIZE_NONE, 13, 305, 316, 106, 157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // TWA_SCROLLBAR +{ WWT_PANEL, RESIZE_NONE, 13, 0, 316, 158, 209, 0x0, STR_NULL}, // TWA_ACTION_INFO +{ WWT_PUSHTXTBTN, RESIZE_NONE, 13, 0, 316, 210, 221, STR_2042_DO_IT, STR_2044_CARRY_OUT_THE_HIGHLIGHTED}, // TWA_EXECUTE { WIDGETS_END}, }; extern const byte _town_action_costs[8]; +enum TownActions { + TACT_NONE = 0x00, + + TACT_ADVERTISE_SMALL = 0x01, + TACT_ADVERTISE_MEDIUM = 0x02, + TACT_ADVERTISE_LARGE = 0x04, + TACT_ROAD_REBUILD = 0x08, + TACT_BUILD_STATUE = 0x10, + TACT_FOUND_BUILDINGS = 0x20, + TACT_BUY_RIGHTS = 0x40, + TACT_BRIBE = 0x80, + + TACT_ADVERTISE = TACT_ADVERTISE_SMALL | TACT_ADVERTISE_MEDIUM | TACT_ADVERTISE_LARGE, + TACT_CONSTRUCTION = TACT_ROAD_REBUILD | TACT_BUILD_STATUE | TACT_FOUND_BUILDINGS, + TACT_FUNDS = TACT_BUY_RIGHTS | TACT_BRIBE, + TACT_ALL = TACT_ADVERTISE | TACT_CONSTRUCTION | TACT_FUNDS, +}; + +DECLARE_ENUM_AS_BIT_SET(TownActions); + /** Get a list of available actions to do at a town. * @param nump if not NULL add put the number of available actions in it * @param pid the player that is querying the town @@ -41,41 +71,38 @@ */ uint GetMaskOfTownActions(int *nump, PlayerID pid, const Town *t) { - Money avail, ref; int num = 0; - uint avail_buttons = 0x7F; // by default all buttons except bribe are enabled. - uint buttons = 0; - - if (pid != PLAYER_SPECTATOR) { - uint i; + TownActions buttons = TACT_NONE; - /* bribe option enabled? */ - if (_patches.bribe) { - /* if unwanted, disable everything. */ - if (t->unwanted[pid]) { - avail_buttons = 0; - } else if (t->ratings[pid] < RATING_BRIBE_MAXIMUM) { - SETBIT(avail_buttons, 7); // Allow bribing - } - } + /* Spectators and unwanted have no options */ + if (pid != PLAYER_SPECTATOR && !(_patches.bribe && t->unwanted[pid])) { /* Things worth more than this are not shown */ - avail = GetPlayer(pid)->player_money + _price.station_value * 200; - ref = _price.build_industry >> 8; + Money avail = GetPlayer(pid)->player_money + _price.station_value * 200; + Money ref = _price.build_industry >> 8; - for (i = 0; i != lengthof(_town_action_costs); i++, avail_buttons >>= 1) { - if (HASBIT(avail_buttons, 0) && avail >= _town_action_costs[i] * ref) { - SETBIT(buttons, i); + /* Check the action bits for validity and + * if they are valid add them */ + for (uint i = 0; i != lengthof(_town_action_costs); i++) { + const TownActions cur = (TownActions)(1 << i); + + /* Is the player not able to bribe ? */ + if (cur == TACT_BRIBE && (!_patches.bribe || t->ratings[pid] >= RATING_BRIBE_MAXIMUM)) + continue; + + /* Is the player not able to buy exclusive rights ? */ + if (cur == TACT_BUY_RIGHTS && !_patches.exclusive_rights) + continue; + + /* Is the player not able to build a statue ? */ + if (cur == TACT_BUILD_STATUE && HASBIT(t->statues, pid)) + continue; + + if (avail >= _town_action_costs[i] * ref) { + buttons |= cur; num++; } } - - /* Disable build statue if already built */ - if (HASBIT(t->statues, pid)) { - CLRBIT(buttons, 4); - num--; - } - } if (nump != NULL) *nump = num; @@ -161,9 +188,9 @@ y += 10; } for (i = 0; buttons; i++, buttons >>= 1) { - if (pos <= -5) break; + if (pos <= -5) break; ///< Draw only the 5 fitting lines - if (buttons&1 && --pos < 0) { + if ((buttons & 1) && --pos < 0) { DrawString(3, y, STR_2046_SMALL_ADVERTISING_CAMPAIGN + i, 6); y += 10; } @@ -185,7 +212,7 @@ case WE_DOUBLE_CLICK: case WE_CLICK: switch (e->we.click.widget) { - case 3: { /* listbox */ + case TWA_COMMAND_LIST: { const Town *t = GetTown(w->window_number); int y = (e->we.click.pt.y - 0x6B) / 10; @@ -200,7 +227,7 @@ if (e->event != WE_DOUBLE_CLICK || y < 0) break; } - case 6: { /* carry out the action */ + case TWA_EXECUTE: { DoCommandP(GetTown(w->window_number)->xy, w->window_number, WP(w,def_d).data_1, NULL, CMD_DO_TOWN_ACTION | CMD_MSG(STR_00B4_CAN_T_DO_THIS)); break; } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/train_cmd.cpp --- a/src/train_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/train_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -194,7 +194,7 @@ if (!IsArticulatedPart(u)) { /* Check powered wagon / visual effect callback */ - if (HASBIT(EngInfo(u->engine_type)->callbackmask, CBM_WAGON_POWER)) { + if (HASBIT(EngInfo(u->engine_type)->callbackmask, CBM_TRAIN_WAGON_POWER)) { uint16 callback = GetVehicleCallback(CBID_TRAIN_WAGON_POWER, 0, 0, u->engine_type, u); if (callback != CALLBACK_FAILED) u->u.rail.cached_vis_effect = callback; @@ -1626,7 +1626,7 @@ if (p2) { /* turn a single unit around */ - if (IsMultiheaded(v) || HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_ARTIC_ENGINE)) { + if (IsMultiheaded(v) || HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) { return_cmd_error(STR_ONLY_TURN_SINGLE_UNIT); } @@ -1717,7 +1717,7 @@ if (v->cargo_cap != 0) { uint16 amount = CALLBACK_FAILED; - if (HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_REFIT_CAPACITY)) { + if (HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) { /* Back up the vehicle's cargo type */ CargoID temp_cid = v->cargo_type; byte temp_subtype = v->cargo_subtype; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/train_gui.cpp --- a/src/train_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/train_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -54,7 +54,7 @@ v = GetVehicle(_new_vehicle_id); if (tile == _backup_orders_tile) { _backup_orders_tile = 0; - RestoreVehicleOrders(v, _backup_orders_data); + RestoreVehicleOrders(v); } ShowVehicleViewWindow(v); } diff -r d2a6acdbd665 -r 197cb8c6ae17 src/tunnelbridge_cmd.cpp --- a/src/tunnelbridge_cmd.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/tunnelbridge_cmd.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -256,7 +256,7 @@ if (IsSteepSlope(tileh_end)) z_end += TILE_HEIGHT; if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh_end)) z_end += TILE_HEIGHT; - if (z_start != z_end) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED); + if (z_start != z_end) return_cmd_error(STR_BRIDGEHEADS_NOT_SAME_HEIGHT); /* Towns are not allowed to use bridges on slopes. */ allow_on_slopes = ( _current_player != OWNER_TOWN && _patches.build_on_slopes); @@ -366,7 +366,7 @@ for (tile = tile_start + delta; tile != tile_end; tile += delta) { uint z; - if (GetTileSlope(tile, &z) != SLOPE_FLAT && z >= z_start) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED); + if (GetTileSlope(tile, &z) != SLOPE_FLAT && z >= z_start) return_cmd_error(STR_BRIDGE_TOO_LOW_FOR_TERRAIN); if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile) && !replace_bridge) { /* Disallow crossing bridges for the time being */ @@ -531,29 +531,12 @@ /* slope of end tile must be complementary to the slope of the start tile */ if (end_tileh != ComplementSlope(start_tileh)) { - /* - * A lot of things can be autosloped, but then there is still a structure with - * on top of a tunnel entrance which is bad. Therefor we disallow those. - * Furthermore half road bits (not tram bits) can always be removed, so we - * need to preserve that behaviour here too. - */ - switch (GetTileType(end_tile)) { - default: return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); + /* Check if there is a structure on the terraformed tile. Do not add the cost, that will be done by the terraforming */ + ret = DoCommand(end_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR); + if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); - /* Tiles that can be (safely) "auto" terraformed for tunnels */ - case MP_ROAD: - if (GetRoadTileType(end_tile) != ROAD_TILE_NORMAL || // Depots and crossings can't be removed - (GetRoadTypes(end_tile) & ROADTYPES_TRAMHWAY) != 0 || // Half tram bits must not be removed - COUNTBITS(GetRoadBits(end_tile, ROADTYPE_ROAD)) > 1) { // Non-half road bits must not be removed either - return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); - } - /* FALL THROUGH */ - case MP_CLEAR: - case MP_TREES: - ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); - if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); - break; - } + ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); + if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); } else { ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (CmdFailed(ret)) return ret; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/variables.h --- a/src/variables.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/variables.h Sat Oct 06 22:30:24 2007 +0000 @@ -241,6 +241,11 @@ bool timetable_in_ticks; ///< Whether to show the timetable in ticks rather than days. bool autoslope; ///< Allow terraforming under things. + + bool mod_road_rebuild; ///< Roadworks remove unneccesary RoadBits + + bool exclusive_rights; ///< allow buying exclusive rights + bool give_money; ///< allow giving other players money }; VARDEF Patches _patches; @@ -334,6 +339,8 @@ extern const TileTypeProcs * const _tile_type_procs[16]; +extern bool _draw_bounding_boxes; + /* misc */ VARDEF char _screenshot_name[128]; VARDEF byte _vehicle_design_names; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/vehicle.cpp --- a/src/vehicle.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/vehicle.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -2619,7 +2619,7 @@ SpriteID map = PAL_NONE; /* Check if we should use the colour map callback */ - if (HASBIT(EngInfo(engine_type)->callbackmask, CBM_COLOUR_REMAP)) { + if (HASBIT(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_COLOUR_REMAP)) { uint16 callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v); /* A return value of 0xC000 is stated to "use the default two-color * maps" which happens to be the failure action too... */ diff -r d2a6acdbd665 -r 197cb8c6ae17 src/vehicle_gui.cpp --- a/src/vehicle_gui.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/vehicle_gui.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -208,7 +208,7 @@ if (!HASBIT(cmask, cid)) continue; /* Check the vehicle's callback mask for cargo suffixes */ - if (HASBIT(callbackmask, CBM_CARGO_SUFFIX)) { + if (HASBIT(callbackmask, CBM_VEHICLE_CARGO_SUFFIX)) { /* Make a note of the original cargo type. It has to be * changed to test the cargo & subtype... */ CargoID temp_cargo = u->cargo_type; diff -r d2a6acdbd665 -r 197cb8c6ae17 src/viewport.cpp --- a/src/viewport.cpp Sun Sep 23 07:37:38 2007 +0000 +++ b/src/viewport.cpp Sat Oct 06 22:30:24 2007 +0000 @@ -66,6 +66,7 @@ struct TileSpriteToDraw { SpriteID image; SpriteID pal; + const SubSprite *sub; ///< only draw a rectangular part of the sprite TileSpriteToDraw *next; int32 x; int32 y; @@ -75,6 +76,7 @@ struct ChildScreenSpriteToDraw { SpriteID image; SpriteID pal; + const SubSprite *sub; ///< only draw a rectangular part of the sprite int32 x; int32 y; ChildScreenSpriteToDraw *next; @@ -83,6 +85,7 @@ struct ParentSpriteToDraw { SpriteID image; ///< sprite to draw SpriteID pal; ///< palette to use + const SubSprite *sub; ///< only draw a rectangular part of the sprite int32 x; ///< screen X coordinate of sprite int32 y; ///< screen Y coordinate of sprite @@ -428,7 +431,18 @@ InvalidateWidget(w, widget_zoom_out); } -void DrawGroundSpriteAt(SpriteID image, SpriteID pal, int32 x, int32 y, byte z) +/** + * Draws a ground sprite at a specific world-coordinate. + * + * @param image the image to draw. + * @param pal the provided palette. + * @param x position x of the sprite. + * @param y position y of the sprite. + * @param z position z of the sprite. + * @param sub Only draw a part of the sprite. + * + */ +void DrawGroundSpriteAt(SpriteID image, SpriteID pal, int32 x, int32 y, byte z, const SubSprite *sub) { ViewportDrawer *vd = _cur_vd; TileSpriteToDraw *ts; @@ -445,6 +459,7 @@ ts->image = image; ts->pal = pal; + ts->sub = sub; ts->next = NULL; ts->x = x; ts->y = y; @@ -453,14 +468,22 @@ vd->last_tile = &ts->next; } -void DrawGroundSprite(SpriteID image, SpriteID pal) +/** + * Draws a ground sprite for the current tile. + * If the current tile is drawn on top of a foundation the sprite is added as child sprite to the "foundation"-ParentSprite. + * + * @param image the image to draw. + * @param pal the provided palette. + * @param sub Only draw a part of the sprite. + */ +void DrawGroundSprite(SpriteID image, SpriteID pal, const SubSprite *sub) { if (_offset_ground_sprites) { /* offset ground sprite because of foundation? */ - AddChildSpriteScreen(image, pal, _cur_vd->offs_x, _cur_vd->offs_y); + AddChildSpriteScreen(image, pal, _cur_vd->offs_x, _cur_vd->offs_y, false, sub); } else { _added_tile_sprite = true; - DrawGroundSpriteAt(image, pal, _cur_ti->x, _cur_ti->y, _cur_ti->z); + DrawGroundSpriteAt(image, pal, _cur_ti->x, _cur_ti->y, _cur_ti->z, sub); } } @@ -472,7 +495,18 @@ _offset_ground_sprites = true; } -static void AddCombinedSprite(SpriteID image, SpriteID pal, int x, int y, byte z) +/** + * Adds a child sprite to a parent sprite. + * In contrast to "AddChildSpriteScreen()" the sprite position is in world coordinates + * + * @param image the image to draw. + * @param pal the provided palette. + * @param x position x of the sprite. + * @param y position y of the sprite. + * @param z position z of the sprite. + * @param sub Only draw a part of the sprite. + */ +static void AddCombinedSprite(SpriteID image, SpriteID pal, int x, int y, byte z, const SubSprite *sub) { const ViewportDrawer *vd = _cur_vd; Point pt = RemapCoords(x, y, z); @@ -484,17 +518,18 @@ pt.y + spr->y_offs + spr->height <= vd->dpi.top) return; - AddChildSpriteScreen(image, pal, pt.x - vd->parent_list[-1]->left, pt.y - vd->parent_list[-1]->top); + AddChildSpriteScreen(image, pal, pt.x - vd->parent_list[-1]->left, pt.y - vd->parent_list[-1]->top, false, sub); } /** Draw a (transparent) sprite at given coordinates with a given bounding box. * The bounding box extends from (x + bb_offset_x, y + bb_offset_y, z + bb_offset_z) to (x + w - 1, y + h - 1, z + dz - 1), both corners included. + * Bounding boxes with bb_offset_x == w or bb_offset_y == h or bb_offset_z == dz are allowed and produce thin slices. * * @note Bounding boxes are normally specified with bb_offset_x = bb_offset_y = bb_offset_z = 0. The extent of the bounding box in negative direction is * defined by the sprite offset in the grf file. * However if modifying the sprite offsets is not suitable (e.g. when using existing graphics), the bounding box can be tuned by bb_offset. * - * @pre w > bb_offset_x, h > bb_offset_y, dz > bb_offset_z. Else w, h or dz are ignored. + * @pre w >= bb_offset_x, h >= bb_offset_y, dz >= bb_offset_z. Else w, h or dz are ignored. * * @param image the image to combine and draw, * @param pal the provided palette, @@ -508,13 +543,14 @@ * @param bb_offset_x bounding box extent towards negative X (world), * @param bb_offset_y bounding box extent towards negative Y (world), * @param bb_offset_z bounding box extent towards negative Z (world) + * @param sub Only draw a part of the sprite. */ -void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z) +void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z, const SubSprite *sub) { ViewportDrawer *vd = _cur_vd; ParentSpriteToDraw *ps; Point pt; - int32 right, bottom; + int32 left, right, top, bottom; assert((image & SPRITE_MASK) < MAX_SPRITES); @@ -525,7 +561,7 @@ } if (vd->combine_sprites == 2) { - AddCombinedSprite(image, pal, x, y, z); + AddCombinedSprite(image, pal, x, y, z, sub); return; } @@ -551,22 +587,32 @@ pt = RemapCoords(x, y, z); ps->x = pt.x; ps->y = pt.y; + + /* Compute screen extents of sprite */ if (image == SPR_EMPTY_BOUNDING_BOX) { - ps->left = RemapCoords(x + w , y + bb_offset_y, z + bb_offset_z).x; - right = RemapCoords(x + bb_offset_x, y + h , z + bb_offset_z).x; - ps->top = RemapCoords(x + bb_offset_x, y + bb_offset_y, z + dz ).y; - bottom = RemapCoords(x + w , y + h , z + bb_offset_z).y; + left = ps->left = RemapCoords(x + w , y + bb_offset_y, z + bb_offset_z).x; + right = RemapCoords(x + bb_offset_x, y + h , z + bb_offset_z).x + 1; + top = ps->top = RemapCoords(x + bb_offset_x, y + bb_offset_y, z + dz ).y; + bottom = RemapCoords(x + w , y + h , z + bb_offset_z).y + 1; } else { const Sprite *spr = GetSprite(image & SPRITE_MASK); - ps->left = (pt.x += spr->x_offs); - right = (pt.x + spr->width ); - ps->top = (pt.y += spr->y_offs); - bottom = (pt.y + spr->height); + left = ps->left = (pt.x += spr->x_offs); + right = (pt.x + spr->width ); + top = ps->top = (pt.y += spr->y_offs); + bottom = (pt.y + spr->height); } - if (ps->left >= vd->dpi.left + vd->dpi.width || - right <= vd->dpi.left || - ps->top >= vd->dpi.top + vd->dpi.height || - bottom <= vd->dpi.top) { + if (_draw_bounding_boxes && (image != SPR_EMPTY_BOUNDING_BOX)) { + /* Compute maximal extents of sprite and it's bounding box */ + left = min(left , RemapCoords(x + w , y + bb_offset_y, z + bb_offset_z).x); + right = max(right , RemapCoords(x + bb_offset_x, y + h , z + bb_offset_z).x + 1); + top = min(top , RemapCoords(x + bb_offset_x, y + bb_offset_y, z + dz ).y); + bottom = max(bottom, RemapCoords(x + w , y + h , z + bb_offset_z).y + 1); + } + /* Do not add the sprite to the viewport, if it is outside */ + if (left >= vd->dpi.left + vd->dpi.width || + right <= vd->dpi.left || + top >= vd->dpi.top + vd->dpi.height || + bottom <= vd->dpi.top) { return; } @@ -574,14 +620,15 @@ ps->image = image; ps->pal = pal; + ps->sub = sub; ps->xmin = x + bb_offset_x; - ps->xmax = x + max(bb_offset_x, w - 1); + ps->xmax = x + max(bb_offset_x, w) - 1; ps->ymin = y + bb_offset_y; - ps->ymax = y + max(bb_offset_y, h - 1); + ps->ymax = y + max(bb_offset_y, h) - 1; ps->zmin = z + bb_offset_z; - ps->zmax = z + max(bb_offset_z, dz - 1); + ps->zmax = z + max(bb_offset_z, dz) - 1; ps->comparison_done = false; ps->child = NULL; @@ -602,19 +649,36 @@ _cur_vd->combine_sprites = 0; } -void AddChildSpriteScreen(SpriteID image, SpriteID pal, int x, int y) +/** + * Add a child sprite to a parent sprite. + * + * @param image the image to draw. + * @param pal the provided palette. + * @param x sprite x-offset (screen coordinates) relative to parent sprite. + * @param y sprite y-offset (screen coordinates) relative to parent sprite. + * @param transparent if true, switch the palette between the provided palette and the transparent palette, + * @param sub Only draw a part of the sprite. + */ +void AddChildSpriteScreen(SpriteID image, SpriteID pal, int x, int y, bool transparent, const SubSprite *sub) { ViewportDrawer *vd = _cur_vd; ChildScreenSpriteToDraw *cs; assert((image & SPRITE_MASK) < MAX_SPRITES); + /* make the sprites transparent with the right palette */ + if (transparent) { + SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); + pal = PALETTE_TO_TRANSPARENT; + } + if (vd->spritelist_mem >= vd->eof_spritelist_mem) { DEBUG(sprite, 0, "Out of sprite memory"); return; } cs = (ChildScreenSpriteToDraw*)vd->spritelist_mem; + /* If the ParentSprite was clipped by the viewport bounds, do not draw the ChildSprites either */ if (vd->last_child == NULL) return; vd->spritelist_mem += sizeof(ChildScreenSpriteToDraw); @@ -624,6 +688,7 @@ cs->image = image; cs->pal = pal; + cs->sub = sub; cs->x = x; cs->y = y; cs->next = NULL; @@ -667,6 +732,17 @@ } } +/** + * Draws a selection rectangle on a tile. + * + * @param ti TileInfo Tile that is being drawn + * @param pal Palette to apply. + */ +static void DrawTileSelectionRect(const TileInfo *ti, SpriteID pal) +{ + DrawSelectionSprite(SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh], pal, ti); +} + static bool IsPartOfAutoLine(int px, int py) { px -= _thd.selstart.x; @@ -700,17 +776,38 @@ #include "table/autorail.h" /** + * Draws autorail highlights. + * + * @param *ti TileInfo Tile that is being drawn + * @param autorail_type Offset into _AutorailTilehSprite[][] + */ +static void DrawAutorailSelection(const TileInfo *ti, uint autorail_type) +{ + SpriteID image; + SpriteID pal; + int offset; + + offset = _AutorailTilehSprite[ti->tileh][autorail_type]; + if (offset >= 0) { + image = SPR_AUTORAIL_BASE + offset; + pal = PAL_NONE; + } else { + image = SPR_AUTORAIL_BASE - offset; + pal = PALETTE_SEL_TILE_RED; + } + + DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : pal, ti); +} + +/** * Checks if the specified tile is selected and if so draws selection using correct selectionstyle. * @param *ti TileInfo Tile that is being drawn */ static void DrawTileSelection(const TileInfo *ti) { - SpriteID image; - SpriteID pal; - /* Draw a red error square? */ if (_thd.redsq != 0 && _thd.redsq == ti->tile) { - DrawSelectionSprite(SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh], PALETTE_TILE_RED_PULSATING, ti); + DrawTileSelectionRect(ti, PALETTE_TILE_RED_PULSATING); return; } @@ -721,8 +818,7 @@ if (IS_INSIDE_1D(ti->x, _thd.pos.x, _thd.size.x) && IS_INSIDE_1D(ti->y, _thd.pos.y, _thd.size.y)) { if (_thd.drawstyle & HT_RECT) { - image = SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh]; - DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : PAL_NONE, ti); + DrawTileSelectionRect(ti, _thd.make_square_red ? PALETTE_SEL_TILE_RED : PAL_NONE); } else if (_thd.drawstyle & HT_POINT) { /* Figure out the Z coordinate for the single dot. */ byte z = ti->z; @@ -734,25 +830,12 @@ } else if (_thd.drawstyle & HT_RAIL /*&& _thd.place_mode == VHM_RAIL*/) { /* autorail highlight piece under cursor */ uint type = _thd.drawstyle & 0xF; - int offset; - assert(type <= 5); - - offset = _AutorailTilehSprite[ti->tileh][_AutorailType[type][0]]; - if (offset >= 0) { - image = SPR_AUTORAIL_BASE + offset; - pal = PAL_NONE; - } else { - image = SPR_AUTORAIL_BASE - offset; - pal = PALETTE_TO_RED; - } - - DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : pal, ti); + DrawAutorailSelection(ti, _AutorailType[type][0]); } else if (IsPartOfAutoLine(ti->x, ti->y)) { /* autorail highlighting long line */ int dir = _thd.drawstyle & ~0xF0; - int offset; uint side; if (dir < 2) { @@ -762,16 +845,7 @@ side = delta(delta(TileX(start), TileX(ti->tile)), delta(TileY(start), TileY(ti->tile))); } - offset = _AutorailTilehSprite[ti->tileh][_AutorailType[dir][side]]; - if (offset >= 0) { - image = SPR_AUTORAIL_BASE + offset; - pal = PAL_NONE; - } else { - image = SPR_AUTORAIL_BASE - offset; - pal = PALETTE_TO_RED; - } - - DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : pal, ti); + DrawAutorailSelection(ti, _AutorailType[dir][side]); } return; } @@ -782,7 +856,7 @@ IS_INSIDE_1D(ti->x, _thd.pos.x + _thd.offs.x, _thd.size.x + _thd.outersize.x) && IS_INSIDE_1D(ti->y, _thd.pos.y + _thd.offs.y, _thd.size.y + _thd.outersize.y)) { /* Draw a blue rect. */ - DrawSelectionSprite(SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh], PALETTE_SEL_TILE_BLUE, ti); + DrawTileSelectionRect(ti, PALETTE_SEL_TILE_BLUE); return; } } @@ -1152,7 +1226,7 @@ { do { Point pt = RemapCoords(ts->x, ts->y, ts->z); - DrawSprite(ts->image, ts->pal, pt.x, pt.y); + DrawSprite(ts->image, ts->pal, pt.x, pt.y, ts->sub); ts = ts->next; } while (ts != NULL); } @@ -1223,14 +1297,34 @@ const ParentSpriteToDraw* ps = *psd; const ChildScreenSpriteToDraw* cs; - if (ps->image != SPR_EMPTY_BOUNDING_BOX) DrawSprite(ps->image, ps->pal, ps->x, ps->y); + if (ps->image != SPR_EMPTY_BOUNDING_BOX) DrawSprite(ps->image, ps->pal, ps->x, ps->y, ps->sub); for (cs = ps->child; cs != NULL; cs = cs->next) { - DrawSprite(cs->image, cs->pal, ps->left + cs->x, ps->top + cs->y); + DrawSprite(cs->image, cs->pal, ps->left + cs->x, ps->top + cs->y, cs->sub); } } } +/** + * Draws the bounding boxes of all ParentSprites + * @param psd Array of ParentSprites + */ +static void ViewportDrawBoundingBoxes(ParentSpriteToDraw *psd[]) +{ + for (; *psd != NULL; psd++) { + const ParentSpriteToDraw* ps = *psd; + Point pt1 = RemapCoords(ps->xmax + 1, ps->ymax + 1, ps->zmax + 1); // top front corner + Point pt2 = RemapCoords(ps->xmin , ps->ymax + 1, ps->zmax + 1); // top left corner + Point pt3 = RemapCoords(ps->xmax + 1, ps->ymin , ps->zmax + 1); // top right corner + Point pt4 = RemapCoords(ps->xmax + 1, ps->ymax + 1, ps->zmin ); // bottom front corner + + DrawBox( pt1.x, pt1.y, + pt2.x - pt1.x, pt2.y - pt1.y, + pt3.x - pt1.x, pt3.y - pt1.y, + pt4.x - pt1.x, pt4.y - pt1.y); + } +} + static void ViewportDrawStrings(DrawPixelInfo *dpi, const StringSpriteToDraw *ss) { DrawPixelInfo dp; @@ -1354,6 +1448,7 @@ ViewportSortParentSprites(parent_list); ViewportDrawParentSprites(parent_list); + if (_draw_bounding_boxes) ViewportDrawBoundingBoxes(parent_list); if (vd.first_string != NULL) ViewportDrawStrings(&vd.dpi, vd.first_string); diff -r d2a6acdbd665 -r 197cb8c6ae17 src/viewport.h --- a/src/viewport.h Sun Sep 23 07:37:38 2007 +0000 +++ b/src/viewport.h Sat Oct 06 22:30:24 2007 +0000 @@ -57,11 +57,11 @@ void OffsetGroundSprite(int x, int y); -void DrawGroundSprite(SpriteID image, SpriteID pal); -void DrawGroundSpriteAt(SpriteID image, SpriteID pal, int32 x, int32 y, byte z); -void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, int dz, int z, bool transparent = false, int bb_offset_x = 0, int bb_offset_y = 0, int bb_offset_z = 0); +void DrawGroundSprite(SpriteID image, SpriteID pal, const SubSprite *sub = NULL); +void DrawGroundSpriteAt(SpriteID image, SpriteID pal, int32 x, int32 y, byte z, const SubSprite *sub = NULL); +void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, int dz, int z, bool transparent = false, int bb_offset_x = 0, int bb_offset_y = 0, int bb_offset_z = 0, const SubSprite *sub = NULL); void *AddStringToDraw(int x, int y, StringID string, uint64 params_1, uint64 params_2); -void AddChildSpriteScreen(SpriteID image, SpriteID pal, int x, int y); +void AddChildSpriteScreen(SpriteID image, SpriteID pal, int x, int y, bool transparent = false, const SubSprite *sub = NULL); void StartSpriteCombine();