--- 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 ###
#
--- 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
--- 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:
--- 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 "
--- 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"
--- 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 @@
</ul>
</li>
<li>m2: index into the array of industries</li>
- <li>m5: type:<br>
+ <li>m5: type (plus m6 bit 2):<br>
<small>(note: this is not the same as the industry type, which is stored in the array of industries)</small>
<table>
@@ -1272,9 +1272,17 @@
</table>
</td>
</tr>
+ <tr>
+ <td nowrap valign=top><tt>AF</tt>..<tt>1FF</tt> </td>
+ <td align=left>NewGRF industries industry</td>
+ </tr>
</table>
</li>
<li>m6 bits 1..0 : <a href="#tropic_zone">Tropic zone definition</a></li>
+ <li>m3: animation state</li>
+ <li>m4: animation loop</li>
+ <li>m6 bits 3..5: random triggers (NewGRF)</li>
+ <li>m7: random bits (NewGRF)</li>
</ul>
</td>
</tr>
--- 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 @@
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
- <td rowspan=3>8</td>
+ <td>8</td>
<td class="caption">industry</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="abuse">X</span><span class="free">OO</span><span class="abuse">X
XXXX</span></td>
<td class="bits">XXXX XXXX XXXX XXXX</td>
- <td class="bits"><span class="free">OOOO OOOO</span></td>
- <td class="bits"><span class="free">OOOO OOOO</span></td>
- <td class="bits">XXXX XXXX</td>
- <td class="bits"><span class="free">OOOO OO</span>XX</td>
- <td class="bits"><span class="free">OOOO OOOO</span></td>
- </tr>
- <tr>
- <td>bubble/sugar/toffee,<BR>
- gold/copper/coal,<BR>
- oil wells, power station</td>
- <td class="bits">-inherit-</td>
- <td class="bits"><span class="abuse">X</span><span class="free">OOO OOOO</span></td>
- <td class="bits">-inherit-</td>
- <td class="bits">XXXX XXXX</td>
- <td class="bits"><span class="free">OOOO OOOO</span></td>
- <td class="bits">-inherit-</td>
- <td class="bits">-inherit-</td>
- <td class="bits"><span class="free">OOOO OOOO</span></td>
- </tr>
- <tr>
- <td>toy factory</td>
- <td class="bits">-inherit-</td>
- <td class="bits"><span class="abuse">X</span><span class="free">OOO OOOO</span></td>
- <td class="bits">-inherit-</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
- <td class="bits">-inherit-</td>
- <td class="bits">-inherit-</td>
- <td class="bits"><span class="free">OOOO OOOO</span></td>
+ <td class="bits">XXXX XXXX</td>
+ <td class="bits"><span class="free">OO</span>XX XXXX</td>
+ <td class="bits">XXXX XXXX</td>
</tr>
<tr>
<td rowspan=2>9</td>
--- 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">
</File>
<File
+ RelativePath=".\..\src\road.cpp">
+ </File>
+ <File
RelativePath=".\..\src\saveload.cpp">
</File>
<File
@@ -1333,10 +1336,10 @@
RelativePath=".\..\src\blitter\32bpp_base.hpp">
</File>
<File
- RelativePath=".\..\src\blitter\32bpp_optimized.hpp">
+ RelativePath=".\..\src\blitter\32bpp_optimized.cpp">
</File>
<File
- RelativePath=".\..\src\blitter\32bpp_optimized.cpp">
+ RelativePath=".\..\src\blitter\32bpp_optimized.hpp">
</File>
<File
RelativePath=".\..\src\blitter\32bpp_simple.cpp">
--- 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 @@
>
</File>
<File
+ RelativePath=".\..\src\road.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\saveload.cpp"
>
</File>
@@ -1996,14 +2000,14 @@
>
</File>
<File
+ RelativePath=".\..\src\blitter\32bpp_optimized.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\blitter\32bpp_optimized.hpp"
>
</File>
<File
- RelativePath=".\..\src\blitter\32bpp_optimized.cpp"
- >
- </File>
- <File
RelativePath=".\..\src\blitter\32bpp_simple.cpp"
>
</File>
--- 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
--- 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
--- 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.
--- 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;
--- 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);
}
--- 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);
--- 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 */
--- 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);
}
}
}
--- 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);
}
}
}
--- 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;
--- 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;
--- 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) {
--- 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
*
--- 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;
}
--- 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) {
--- 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);
--- 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;
--- 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);
--- 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
--- 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),
--- 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);
--- 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 */
--- 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)) {
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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}
--- 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];
/**
--- 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) {
--- 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
--- 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];
--- 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));
--- 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;
}
--- 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;
}
--- 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<HouseSpec*>(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<IndustryTileSpec*>(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<IndustrySpec*>(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<IndustryTileTable>(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++;
}
}
}
--- 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
};
/**
--- 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
}
}
--- 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) {}
--- 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<GRFConfig*>(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];
}
--- 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;
}
}
--- 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
--- 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;
--- 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 */
--- 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)
--- 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());
--- 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;
--- 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:
--- 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;
--- 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;
}
--- 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;
}
--- 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);
--- 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<Order>(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)) {
--- 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;
}
--- /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;
+}
--- 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
--- 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);
}
}
--- 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;
--- 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);
}
--- 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 <list>
-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!
--- 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 */
--- 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",
--- 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;
--- 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);
}
--- 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.
--- 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));
}
}
}
--- 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();
}
--- 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;
}
--- 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;
--- 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);
}
--- 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;
--- 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;
--- 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... */
--- 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;
--- 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);
--- 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();