|
1 #include "stdafx.h" |
|
2 #include "ttd.h" |
|
3 #include "vehicle.h" |
|
4 #include "gfx.h" |
|
5 #include "assert.h" |
|
6 #include "saveload.h" |
|
7 |
|
8 extern void StartupEconomy(); |
|
9 extern void InitNewsItemStructs(); |
|
10 |
|
11 static uint32 _random_seed_3, _random_seed_4; |
|
12 |
|
13 byte _name_array[512][32]; |
|
14 |
|
15 static INLINE uint32 ROR(uint32 x, int n) |
|
16 { |
|
17 return (x >> n) + (x << ((sizeof(x)*8)-n)); |
|
18 } |
|
19 |
|
20 |
|
21 uint32 Random() |
|
22 { |
|
23 uint32 t = _random_seed_2; |
|
24 uint32 s = _random_seed_1; |
|
25 _random_seed_1 = s + ROR(t ^ 0x1234567F, 7); |
|
26 return _random_seed_2 = ROR(s, 3); |
|
27 } |
|
28 |
|
29 uint RandomRange(uint max) |
|
30 { |
|
31 return (uint16)Random() * max >> 16; |
|
32 } |
|
33 |
|
34 uint32 InteractiveRandom() |
|
35 { |
|
36 uint32 t = _random_seed_4; |
|
37 uint32 s = _random_seed_3; |
|
38 _random_seed_3 = s + ROR(t ^ 0x1234567F, 7); |
|
39 return _random_seed_4 = ROR(s, 3); |
|
40 } |
|
41 |
|
42 void memswap(void *a, void *b, size_t size) { |
|
43 void *c = alloca(size); |
|
44 memcpy(c, a, size); |
|
45 memcpy(a, b, size); |
|
46 memcpy(b, c, size); |
|
47 } |
|
48 |
|
49 void SetDate(uint date) |
|
50 { |
|
51 YearMonthDay ymd; |
|
52 ConvertDayToYMD(&ymd, _date = date); |
|
53 _cur_year = ymd.year; |
|
54 _cur_month = ymd.month; |
|
55 } |
|
56 |
|
57 void InitializeClearLand(); |
|
58 void InitializeRail(); |
|
59 void InitializeRailGui(); |
|
60 void InitializeRoad(); |
|
61 void InitializeRoadGui(); |
|
62 void InitializeAirportGui(); |
|
63 void InitializeDock(); |
|
64 void InitializeDockGui(); |
|
65 void InitializeIndustries(); |
|
66 void InitializeLandscape(); |
|
67 void InitializeTowns(); |
|
68 void InitializeTrees(); |
|
69 void InitializeStations(); |
|
70 void InitializeNameMgr(); |
|
71 void InitializePlayers(); |
|
72 void InitializeCheats(); |
|
73 |
|
74 void GenerateLandscape(); |
|
75 void GenerateClearTile(); |
|
76 |
|
77 void GenerateIndustries(); |
|
78 void GenerateUnmovables(); |
|
79 void GenerateTowns(); |
|
80 |
|
81 void StartupPlayers(); |
|
82 void StartupEngines(); |
|
83 void StartupDisasters(); |
|
84 void GenerateTrees(); |
|
85 |
|
86 void ConvertGroundTilesIntoWaterTiles(); |
|
87 |
|
88 void InitializeGame() |
|
89 { |
|
90 SetObjectToPlace(1, 0, 0, 0); |
|
91 |
|
92 _pause = 0; |
|
93 _fast_forward = 0; |
|
94 _tick_counter = 0; |
|
95 _date_fract = 0; |
|
96 _cur_tileloop_tile = 0; |
|
97 _vehicle_id_ctr_day = 0; |
|
98 |
|
99 { |
|
100 uint starting = ConvertIntDate(_patches.starting_date); |
|
101 if ( starting == (uint)-1) starting = 10958; |
|
102 SetDate(starting); |
|
103 } |
|
104 |
|
105 InitializeVehicles(); |
|
106 _backup_orders_tile = 0; |
|
107 |
|
108 InitNewsItemStructs(); |
|
109 InitializeLandscape(); |
|
110 InitializeClearLand(); |
|
111 InitializeRail(); |
|
112 InitializeRailGui(); |
|
113 InitializeRoad(); |
|
114 InitializeRoadGui(); |
|
115 InitializeAirportGui(); |
|
116 InitializeDock(); |
|
117 InitializeDockGui(); |
|
118 InitializeTowns(); |
|
119 InitializeTrees(); |
|
120 InitializeStations(); |
|
121 InitializeIndustries(); |
|
122 |
|
123 InitializeNameMgr(); |
|
124 InitializeTrains(); |
|
125 |
|
126 InitializePlayers(); |
|
127 InitializeCheats(); |
|
128 |
|
129 InitTextEffects(); |
|
130 InitializeAnimatedTiles(); |
|
131 |
|
132 InitializeLandscapeVariables(false); |
|
133 |
|
134 ResetObjectToPlace(); |
|
135 } |
|
136 |
|
137 void GenerateWorld(int mode) |
|
138 { |
|
139 int i; |
|
140 |
|
141 _generating_world = true; |
|
142 InitializeGame(); |
|
143 SetObjectToPlace(1, 0, 0, 0); |
|
144 |
|
145 // Must start economy early because of the costs. |
|
146 StartupEconomy(); |
|
147 |
|
148 // Don't generate landscape items when in the scenario editor. |
|
149 if (mode == 1) { |
|
150 // empty world in scenario editor |
|
151 ConvertGroundTilesIntoWaterTiles(); |
|
152 } else { |
|
153 GenerateLandscape(); |
|
154 GenerateClearTile(); |
|
155 |
|
156 // only generate towns, tree and industries in newgame mode. |
|
157 if (mode == 0) { |
|
158 GenerateTowns(); |
|
159 GenerateTrees(); |
|
160 GenerateIndustries(); |
|
161 GenerateUnmovables(); |
|
162 } |
|
163 } |
|
164 |
|
165 // These are probably pointless when inside the scenario editor. |
|
166 StartupPlayers(); |
|
167 StartupEngines(); |
|
168 StartupDisasters(); |
|
169 _generating_world = false; |
|
170 |
|
171 // No need to run the tile loop in the scenario editor. |
|
172 if (mode != 1) { |
|
173 for(i=0x500; i!=0; i--) |
|
174 RunTileLoop(); |
|
175 } |
|
176 |
|
177 ResetObjectToPlace(); |
|
178 } |
|
179 |
|
180 void DeleteName(StringID id) |
|
181 { |
|
182 if ((id & 0xF800) == 0x7800) { |
|
183 memset(_name_array[id & 0x1FF], 0, sizeof(_name_array[id & 0x1FF])); |
|
184 } |
|
185 } |
|
186 |
|
187 byte *GetName(int id, byte *buff) |
|
188 { |
|
189 byte *b; |
|
190 |
|
191 if (id & 0x600) { |
|
192 if (id & 0x200) { |
|
193 if (id & 0x400) { |
|
194 GetParamInt32(); |
|
195 GetParamUint16(); |
|
196 } else { |
|
197 GetParamUint16(); |
|
198 } |
|
199 } else { |
|
200 GetParamInt32(); |
|
201 } |
|
202 } |
|
203 |
|
204 b = _name_array[(id&~0x600)]; |
|
205 while ((*buff++ = *b++) != 0); |
|
206 |
|
207 return buff - 1; |
|
208 } |
|
209 |
|
210 |
|
211 void InitializeCheats() |
|
212 { |
|
213 memset(&_cheats, 0, sizeof(Cheats)); |
|
214 } |
|
215 |
|
216 |
|
217 void InitializeNameMgr() |
|
218 { |
|
219 memset(_name_array, 0, sizeof(_name_array)); |
|
220 } |
|
221 |
|
222 StringID AllocateName(const byte *name, byte skip) |
|
223 { |
|
224 int free_item = -1; |
|
225 const byte *names; |
|
226 byte *dst; |
|
227 int i; |
|
228 |
|
229 names = &_name_array[0][0]; |
|
230 |
|
231 for(i=0; i!=512; i++,names+=sizeof(_name_array[0])) { |
|
232 if (names[0] == 0) { |
|
233 if (free_item == -1) |
|
234 free_item = i; |
|
235 } else { |
|
236 if (str_eq(names, name)) { |
|
237 _error_message = STR_0132_CHOSEN_NAME_IN_USE_ALREADY; |
|
238 return 0; |
|
239 } |
|
240 } |
|
241 } |
|
242 |
|
243 if (free_item < 0) { |
|
244 _error_message = STR_0131_TOO_MANY_NAMES_DEFINED; |
|
245 return 0; |
|
246 } |
|
247 |
|
248 dst=_name_array[free_item]; |
|
249 |
|
250 for(i=0; (dst[i] = name[i]) != 0 && ++i != 32; ) {} |
|
251 dst[31] = 0; |
|
252 |
|
253 return free_item | 0x7800 | (skip << 8); |
|
254 } |
|
255 |
|
256 const TileIndexDiff _tileoffs_by_dir[4] = { |
|
257 TILE_XY(-1, 0), |
|
258 TILE_XY(0, 1), |
|
259 TILE_XY(1, 0), |
|
260 TILE_XY(0, -1), |
|
261 }; |
|
262 |
|
263 |
|
264 #define M(a,b) ((a<<5)|b) |
|
265 static const uint16 _month_date_from_year_day[] = { |
|
266 M(0,1),M(0,2),M(0,3),M(0,4),M(0,5),M(0,6),M(0,7),M(0,8),M(0,9),M(0,10),M(0,11),M(0,12),M(0,13),M(0,14),M(0,15),M(0,16),M(0,17),M(0,18),M(0,19),M(0,20),M(0,21),M(0,22),M(0,23),M(0,24),M(0,25),M(0,26),M(0,27),M(0,28),M(0,29),M(0,30),M(0,31), |
|
267 M(1,1),M(1,2),M(1,3),M(1,4),M(1,5),M(1,6),M(1,7),M(1,8),M(1,9),M(1,10),M(1,11),M(1,12),M(1,13),M(1,14),M(1,15),M(1,16),M(1,17),M(1,18),M(1,19),M(1,20),M(1,21),M(1,22),M(1,23),M(1,24),M(1,25),M(1,26),M(1,27),M(1,28),M(1,29), |
|
268 M(2,1),M(2,2),M(2,3),M(2,4),M(2,5),M(2,6),M(2,7),M(2,8),M(2,9),M(2,10),M(2,11),M(2,12),M(2,13),M(2,14),M(2,15),M(2,16),M(2,17),M(2,18),M(2,19),M(2,20),M(2,21),M(2,22),M(2,23),M(2,24),M(2,25),M(2,26),M(2,27),M(2,28),M(2,29),M(2,30),M(2,31), |
|
269 M(3,1),M(3,2),M(3,3),M(3,4),M(3,5),M(3,6),M(3,7),M(3,8),M(3,9),M(3,10),M(3,11),M(3,12),M(3,13),M(3,14),M(3,15),M(3,16),M(3,17),M(3,18),M(3,19),M(3,20),M(3,21),M(3,22),M(3,23),M(3,24),M(3,25),M(3,26),M(3,27),M(3,28),M(3,29),M(3,30), |
|
270 M(4,1),M(4,2),M(4,3),M(4,4),M(4,5),M(4,6),M(4,7),M(4,8),M(4,9),M(4,10),M(4,11),M(4,12),M(4,13),M(4,14),M(4,15),M(4,16),M(4,17),M(4,18),M(4,19),M(4,20),M(4,21),M(4,22),M(4,23),M(4,24),M(4,25),M(4,26),M(4,27),M(4,28),M(4,29),M(4,30),M(4,31), |
|
271 M(5,1),M(5,2),M(5,3),M(5,4),M(5,5),M(5,6),M(5,7),M(5,8),M(5,9),M(5,10),M(5,11),M(5,12),M(5,13),M(5,14),M(5,15),M(5,16),M(5,17),M(5,18),M(5,19),M(5,20),M(5,21),M(5,22),M(5,23),M(5,24),M(5,25),M(5,26),M(5,27),M(5,28),M(5,29),M(5,30), |
|
272 M(6,1),M(6,2),M(6,3),M(6,4),M(6,5),M(6,6),M(6,7),M(6,8),M(6,9),M(6,10),M(6,11),M(6,12),M(6,13),M(6,14),M(6,15),M(6,16),M(6,17),M(6,18),M(6,19),M(6,20),M(6,21),M(6,22),M(6,23),M(6,24),M(6,25),M(6,26),M(6,27),M(6,28),M(6,29),M(6,30),M(6,31), |
|
273 M(7,1),M(7,2),M(7,3),M(7,4),M(7,5),M(7,6),M(7,7),M(7,8),M(7,9),M(7,10),M(7,11),M(7,12),M(7,13),M(7,14),M(7,15),M(7,16),M(7,17),M(7,18),M(7,19),M(7,20),M(7,21),M(7,22),M(7,23),M(7,24),M(7,25),M(7,26),M(7,27),M(7,28),M(7,29),M(7,30),M(7,31), |
|
274 M(8,1),M(8,2),M(8,3),M(8,4),M(8,5),M(8,6),M(8,7),M(8,8),M(8,9),M(8,10),M(8,11),M(8,12),M(8,13),M(8,14),M(8,15),M(8,16),M(8,17),M(8,18),M(8,19),M(8,20),M(8,21),M(8,22),M(8,23),M(8,24),M(8,25),M(8,26),M(8,27),M(8,28),M(8,29),M(8,30), |
|
275 M(9,1),M(9,2),M(9,3),M(9,4),M(9,5),M(9,6),M(9,7),M(9,8),M(9,9),M(9,10),M(9,11),M(9,12),M(9,13),M(9,14),M(9,15),M(9,16),M(9,17),M(9,18),M(9,19),M(9,20),M(9,21),M(9,22),M(9,23),M(9,24),M(9,25),M(9,26),M(9,27),M(9,28),M(9,29),M(9,30),M(9,31), |
|
276 M(10,1),M(10,2),M(10,3),M(10,4),M(10,5),M(10,6),M(10,7),M(10,8),M(10,9),M(10,10),M(10,11),M(10,12),M(10,13),M(10,14),M(10,15),M(10,16),M(10,17),M(10,18),M(10,19),M(10,20),M(10,21),M(10,22),M(10,23),M(10,24),M(10,25),M(10,26),M(10,27),M(10,28),M(10,29),M(10,30), |
|
277 M(11,1),M(11,2),M(11,3),M(11,4),M(11,5),M(11,6),M(11,7),M(11,8),M(11,9),M(11,10),M(11,11),M(11,12),M(11,13),M(11,14),M(11,15),M(11,16),M(11,17),M(11,18),M(11,19),M(11,20),M(11,21),M(11,22),M(11,23),M(11,24),M(11,25),M(11,26),M(11,27),M(11,28),M(11,29),M(11,30),M(11,31), |
|
278 }; |
|
279 #undef M |
|
280 |
|
281 enum { |
|
282 ACCUM_JAN = 0, |
|
283 ACCUM_FEB = ACCUM_JAN + 31, |
|
284 ACCUM_MAR = ACCUM_FEB + 29, |
|
285 ACCUM_APR = ACCUM_MAR + 31, |
|
286 ACCUM_MAY = ACCUM_APR + 30, |
|
287 ACCUM_JUN = ACCUM_MAY + 31, |
|
288 ACCUM_JUL = ACCUM_JUN + 30, |
|
289 ACCUM_AUG = ACCUM_JUL + 31, |
|
290 ACCUM_SEP = ACCUM_AUG + 31, |
|
291 ACCUM_OCT = ACCUM_SEP + 30, |
|
292 ACCUM_NOV = ACCUM_OCT + 31, |
|
293 ACCUM_DEC = ACCUM_NOV + 30, |
|
294 }; |
|
295 |
|
296 static const uint16 _accum_days_for_month[] = { |
|
297 ACCUM_JAN,ACCUM_FEB,ACCUM_MAR,ACCUM_APR, |
|
298 ACCUM_MAY,ACCUM_JUN,ACCUM_JUL,ACCUM_AUG, |
|
299 ACCUM_SEP,ACCUM_OCT,ACCUM_NOV,ACCUM_DEC, |
|
300 }; |
|
301 |
|
302 |
|
303 void ConvertDayToYMD(YearMonthDay *ymd, uint16 date) |
|
304 { |
|
305 uint yr = date / (365+365+365+366); |
|
306 uint rem = date % (365+365+365+366); |
|
307 uint x; |
|
308 |
|
309 yr *= 4; |
|
310 |
|
311 if (rem >= 366) { |
|
312 rem--; |
|
313 do { |
|
314 rem -= 365; |
|
315 yr++; |
|
316 } while (rem >= 365); |
|
317 if (rem >= 31+28) rem++; |
|
318 } |
|
319 |
|
320 ymd->year = yr; |
|
321 |
|
322 x = _month_date_from_year_day[rem]; |
|
323 ymd->month = x >> 5; |
|
324 ymd->day = x & 0x1F; |
|
325 } |
|
326 |
|
327 // year is a number between 0..? |
|
328 // month is a number between 0..11 |
|
329 // day is a number between 1..31 |
|
330 uint ConvertYMDToDay(uint year, uint month, uint day) |
|
331 { |
|
332 uint rem; |
|
333 |
|
334 // day in the year |
|
335 rem = _accum_days_for_month[month] + day - 1; |
|
336 |
|
337 // remove feb 29 from year 1,2,3 |
|
338 if (year & 3) rem += (year & 3) * 365 + (rem < 31+29); |
|
339 |
|
340 // base date. |
|
341 return (year >> 2) * (365+365+365+366) + rem; |
|
342 } |
|
343 |
|
344 // convert a date on the form |
|
345 // 1920 - 2090 |
|
346 // 192001 - 209012 |
|
347 // 19200101 - 20901231 |
|
348 // or if > 2090 and below 65536, treat it as a daycount |
|
349 // returns -1 if no conversion was possible |
|
350 uint ConvertIntDate(uint date) |
|
351 { |
|
352 uint year, month = 0, day = 1; |
|
353 |
|
354 if (IS_INT_INSIDE(date, 1920, 2090 + 1)) { |
|
355 year = date - 1920; |
|
356 } else if (IS_INT_INSIDE(date, 192001, 209012+1)) { |
|
357 month = date % 100 - 1; |
|
358 year = date / 100 - 1920; |
|
359 } else if (IS_INT_INSIDE(date, 19200101, 20901231+1)) { |
|
360 day = date % 100; date /= 100; |
|
361 month = date % 100 - 1; |
|
362 year = date / 100 - 1920; |
|
363 } else if (IS_INT_INSIDE(date, 2091, 65536)) |
|
364 return date; |
|
365 else |
|
366 return (uint)-1; |
|
367 |
|
368 // invalid ranges? |
|
369 if (month >= 12 || !IS_INT_INSIDE(day, 1, 31+1)) return (uint)-1; |
|
370 |
|
371 return ConvertYMDToDay(year, month, day); |
|
372 } |
|
373 |
|
374 typedef struct LandscapePredefVar { |
|
375 StringID names[NUM_CARGO]; |
|
376 byte weights[NUM_CARGO]; |
|
377 StringID sprites[NUM_CARGO]; |
|
378 |
|
379 uint16 initial_cargo_payment[NUM_CARGO]; |
|
380 byte transit_days_table_1[NUM_CARGO]; |
|
381 byte transit_days_table_2[NUM_CARGO]; |
|
382 |
|
383 byte railwagon_by_cargo[3][NUM_CARGO]; |
|
384 |
|
385 byte road_veh_by_cargo_start[NUM_CARGO]; |
|
386 byte road_veh_by_cargo_count[NUM_CARGO]; |
|
387 } LandscapePredefVar; |
|
388 |
|
389 #include "table/landscape_const.h" |
|
390 |
|
391 |
|
392 // Calculate constants that depend on the landscape type. |
|
393 void InitializeLandscapeVariables(bool only_constants) |
|
394 { |
|
395 const LandscapePredefVar *lpd; |
|
396 int i; |
|
397 StringID str; |
|
398 |
|
399 lpd = &_landscape_predef_var[_opt.landscape]; |
|
400 |
|
401 memcpy(_cargoc.ai_railwagon, lpd->railwagon_by_cargo, sizeof(lpd->railwagon_by_cargo)); |
|
402 memcpy(_cargoc.ai_roadveh_start, lpd->road_veh_by_cargo_start,sizeof(lpd->road_veh_by_cargo_start)); |
|
403 memcpy(_cargoc.ai_roadveh_count, lpd->road_veh_by_cargo_count,sizeof(lpd->road_veh_by_cargo_count)); |
|
404 |
|
405 for(i=0; i!=NUM_CARGO; i++) { |
|
406 _cargoc.sprites[i] = lpd->sprites[i]; |
|
407 |
|
408 str = lpd->names[i]; |
|
409 _cargoc.names_s[i] = str; |
|
410 _cargoc.names_p[i] = (str += 0x20); |
|
411 _cargoc.names_long_s[i] = (str += 0x20); |
|
412 _cargoc.names_long_p[i] = (str += 0x20); |
|
413 _cargoc.names_short[i] = (str += 0x20); |
|
414 _cargoc.weights[i] = lpd->weights[i]; |
|
415 |
|
416 if (!only_constants) { |
|
417 _cargo_payment_rates[i] = lpd->initial_cargo_payment[i]; |
|
418 _cargo_payment_rates_frac[i] = 0; |
|
419 } |
|
420 |
|
421 _cargoc.transit_days_1[i] = lpd->transit_days_table_1[i]; |
|
422 _cargoc.transit_days_2[i] = lpd->transit_days_table_2[i]; |
|
423 } |
|
424 } |
|
425 |
|
426 // distance in Manhattan metric |
|
427 uint GetTileDist(TileIndex xy1, TileIndex xy2) |
|
428 { |
|
429 return myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2)) + |
|
430 myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2)); |
|
431 } |
|
432 |
|
433 // maximum distance in x _or_ y |
|
434 uint GetTileDist1D(TileIndex xy1, TileIndex xy2) |
|
435 { |
|
436 return max(myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2)), |
|
437 myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2))); |
|
438 } |
|
439 |
|
440 uint GetTileDist1Db(TileIndex xy1, TileIndex xy2) |
|
441 { |
|
442 int a = myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2)); |
|
443 int b = myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2)); |
|
444 |
|
445 if (a > b) |
|
446 return a*2+b; |
|
447 else |
|
448 return b*2+a; |
|
449 } |
|
450 |
|
451 uint GetTileDistAdv(TileIndex xy1, TileIndex xy2) |
|
452 { |
|
453 uint a = myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2)); |
|
454 uint b = myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2)); |
|
455 return a*a+b*b; |
|
456 } |
|
457 |
|
458 bool CheckDistanceFromEdge(TileIndex tile, uint distance) |
|
459 { |
|
460 return IS_INT_INSIDE(GET_TILE_X(tile), distance, TILE_X_MAX + 1 - distance) && |
|
461 IS_INT_INSIDE(GET_TILE_Y(tile), distance, TILE_Y_MAX + 1 - distance); |
|
462 } |
|
463 |
|
464 void OnNewDay_Train(Vehicle *v); |
|
465 void OnNewDay_RoadVeh(Vehicle *v); |
|
466 void OnNewDay_Aircraft(Vehicle *v); |
|
467 void OnNewDay_Ship(Vehicle *v); |
|
468 void OnNewDay_EffectVehicle(Vehicle *v) { /* empty */ } |
|
469 void OnNewDay_DisasterVehicle(Vehicle *v); |
|
470 |
|
471 typedef void OnNewVehicleDayProc(Vehicle *v); |
|
472 |
|
473 static OnNewVehicleDayProc * _on_new_vehicle_day_proc[] = { |
|
474 OnNewDay_Train, |
|
475 OnNewDay_RoadVeh, |
|
476 OnNewDay_Ship, |
|
477 OnNewDay_Aircraft, |
|
478 OnNewDay_EffectVehicle, |
|
479 OnNewDay_DisasterVehicle, |
|
480 }; |
|
481 |
|
482 void EnginesDailyLoop(); |
|
483 void DisasterDailyLoop(); |
|
484 void PlayersMonthlyLoop(); |
|
485 void EnginesMonthlyLoop(); |
|
486 void TownsMonthlyLoop(); |
|
487 void IndustryMonthlyLoop(); |
|
488 void StationMonthlyLoop(); |
|
489 |
|
490 void PlayersYearlyLoop(); |
|
491 void TrainsYearlyLoop(); |
|
492 void RoadVehiclesYearlyLoop(); |
|
493 void AircraftYearlyLoop(); |
|
494 void ShipsYearlyLoop(); |
|
495 |
|
496 void CheckpointsDailyLoop(); |
|
497 |
|
498 |
|
499 static const uint16 _autosave_months[] = { |
|
500 0, // never |
|
501 0xFFF, // every month |
|
502 0x249, // every 3 months |
|
503 0x041, // every 6 months |
|
504 0x001, // every 12 months |
|
505 }; |
|
506 |
|
507 void IncreaseDate() |
|
508 { |
|
509 int i,ctr,t; |
|
510 YearMonthDay ymd; |
|
511 |
|
512 if (_game_mode == GM_MENU) { |
|
513 _tick_counter++; |
|
514 return; |
|
515 } |
|
516 |
|
517 /*if the day changed, call the vehicle event but only update a part of the vehicles |
|
518 old max was i!= 12. But with that and a bigger number of vehicles (2560), per day only |
|
519 a part of it could be done, namely: function called max_size date_fract (uint16) / 885 x 12 ==> |
|
520 65536 / 885 = 74; 74x12 = 888. So max 888. Any vehicles above that were not _on_new_vehicle_day_proc'd |
|
521 eg. aged. |
|
522 So new code updates it for max vehicles. |
|
523 (NUM_VEHICLES / maximum number of times ctr is incremented before reset ) + 1 (to get last vehicles too) |
|
524 max size of _date_fract / 885 (added each tick) is number of times before ctr is reset. |
|
525 Calculation might look complicated, but compiler just replaces it with 35, so that's ok |
|
526 */ |
|
527 |
|
528 ctr = _vehicle_id_ctr_day; |
|
529 for(i=0; i!=(NUM_VEHICLES / ((1<<sizeof(_date_fract)*8) / 885)) + 1 && ctr != lengthof(_vehicles); i++) { |
|
530 Vehicle *v = &_vehicles[ctr++]; |
|
531 if ((t=v->type) != 0) |
|
532 _on_new_vehicle_day_proc[t - 0x10](v); |
|
533 } |
|
534 _vehicle_id_ctr_day = ctr; |
|
535 |
|
536 /* increase day, and check if a new day is there? */ |
|
537 _tick_counter++; |
|
538 |
|
539 if ( (_date_fract += 885) >= 885) |
|
540 return; |
|
541 |
|
542 /* yeah, increse day counter and call various daily loops */ |
|
543 _date++; |
|
544 |
|
545 _vehicle_id_ctr_day = 0; |
|
546 |
|
547 DisasterDailyLoop(); |
|
548 CheckpointsDailyLoop(); |
|
549 |
|
550 if (_game_mode != GM_MENU) { |
|
551 InvalidateWindowWidget(WC_STATUS_BAR, 0, 0); |
|
552 EnginesDailyLoop(); |
|
553 } |
|
554 |
|
555 /* check if we entered a new month? */ |
|
556 ConvertDayToYMD(&ymd, _date); |
|
557 if ((byte)ymd.month == _cur_month) |
|
558 return; |
|
559 _cur_month = ymd.month; |
|
560 |
|
561 // printf("Month %d, %X\n", ymd.month, _random_seed_1); |
|
562 |
|
563 /* yes, call various monthly loops */ |
|
564 if (_game_mode != GM_MENU) { |
|
565 if (HASBIT(_autosave_months[_opt.autosave], _cur_month)) { |
|
566 _do_autosave = true; |
|
567 RedrawAutosave(); |
|
568 } |
|
569 |
|
570 PlayersMonthlyLoop(); |
|
571 EnginesMonthlyLoop(); |
|
572 TownsMonthlyLoop(); |
|
573 IndustryMonthlyLoop(); |
|
574 StationMonthlyLoop(); |
|
575 } |
|
576 |
|
577 /* check if we entered a new year? */ |
|
578 if ((byte)ymd.year == _cur_year) |
|
579 return; |
|
580 _cur_year = ymd.year; |
|
581 |
|
582 /* yes, call various yearly loops */ |
|
583 |
|
584 PlayersYearlyLoop(); |
|
585 TrainsYearlyLoop(); |
|
586 RoadVehiclesYearlyLoop(); |
|
587 AircraftYearlyLoop(); |
|
588 ShipsYearlyLoop(); |
|
589 |
|
590 /* check if we reached 2090, that's the maximum year. */ |
|
591 if (_cur_year == 171) { |
|
592 _cur_year = 170; |
|
593 _date = 62093; |
|
594 } |
|
595 |
|
596 if (_patches.auto_euro) |
|
597 CheckSwitchToEuro(); |
|
598 |
|
599 /* XXX: check if year 2050 was reached */ |
|
600 } |
|
601 |
|
602 int FindFirstBit(uint32 x) |
|
603 { |
|
604 int i = 0; |
|
605 assert(x != 0); |
|
606 for(;!(x&1);i++,x>>=1); |
|
607 return i; |
|
608 } |
|
609 |
|
610 |
|
611 extern uint SafeTileAdd(uint tile, int add, const char *exp, const char *file, int line) |
|
612 { |
|
613 int x = GET_TILE_X(tile) + (signed char)(add & 0xFF); |
|
614 int y = GET_TILE_Y(tile) + ((((0x8080 + add)>>8) & 0xFF) - 0x80); |
|
615 |
|
616 if (x < 0 || y < 0 || x >= TILES_X || y >= TILES_Y) { |
|
617 char buf[512]; |
|
618 |
|
619 sprintf(buf, "TILE_ADD(%s) when adding 0x%.4X and %d failed", exp, tile, add); |
|
620 #if !defined(_DEBUG) || !defined(_MSC_VER) |
|
621 printf("%s\n", buf); |
|
622 #else |
|
623 _assert(buf, (char*)file, line); |
|
624 #endif |
|
625 } |
|
626 |
|
627 assert(TILE_XY(x,y) == TILE_MASK(tile + add)); |
|
628 |
|
629 return TILE_XY(x,y); |
|
630 } |
|
631 |
|
632 static void Save_NAME() |
|
633 { |
|
634 int i; |
|
635 byte *b = _name_array[0]; |
|
636 |
|
637 for(i=0; i!=lengthof(_name_array); i++,b+=sizeof(_name_array[0])) { |
|
638 if (*b) { |
|
639 SlSetArrayIndex(i); |
|
640 SlArray(b, strlen(b), SLE_UINT8); |
|
641 } |
|
642 } |
|
643 } |
|
644 |
|
645 static void Load_NAME() |
|
646 { |
|
647 int index; |
|
648 |
|
649 while ((index = SlIterateArray()) != -1) { |
|
650 SlArray(_name_array[index],SlGetFieldLength(),SLE_UINT8); |
|
651 } |
|
652 } |
|
653 |
|
654 static const byte _game_opt_desc[] = { |
|
655 // added a new difficulty option (town attitude) in version 4 |
|
656 SLE_CONDARR(GameOptions,diff, SLE_FILE_I16 | SLE_VAR_I32, 17, 0, 3), |
|
657 SLE_CONDARR(GameOptions,diff, SLE_FILE_I16 | SLE_VAR_I32, 18, 4, 255), |
|
658 SLE_VAR(GameOptions,diff_level, SLE_UINT8), |
|
659 SLE_VAR(GameOptions,currency, SLE_UINT8), |
|
660 SLE_VAR(GameOptions,kilometers, SLE_UINT8), |
|
661 SLE_VAR(GameOptions,town_name, SLE_UINT8), |
|
662 SLE_VAR(GameOptions,landscape, SLE_UINT8), |
|
663 SLE_VAR(GameOptions,snow_line, SLE_UINT8), |
|
664 SLE_VAR(GameOptions,autosave, SLE_UINT8), |
|
665 SLE_VAR(GameOptions,road_side, SLE_UINT8), |
|
666 SLE_END() |
|
667 }; |
|
668 |
|
669 // Save load game options |
|
670 static void SaveLoad_OPTS() |
|
671 { |
|
672 SlObject(&_opt, _game_opt_desc); |
|
673 } |
|
674 |
|
675 |
|
676 static const SaveLoadGlobVarList _date_desc[] = { |
|
677 {&_date, SLE_UINT16, 0, 255}, |
|
678 {&_date_fract, SLE_UINT16, 0, 255}, |
|
679 {&_tick_counter, SLE_UINT16, 0, 255}, |
|
680 {&_vehicle_id_ctr_day, SLE_UINT16, 0, 255}, |
|
681 {&_age_cargo_skip_counter, SLE_UINT8, 0, 255}, |
|
682 {&_avail_aircraft, SLE_UINT8, 0, 255}, |
|
683 {&_cur_tileloop_tile, SLE_UINT16, 0, 255}, |
|
684 {&_disaster_delay, SLE_UINT16, 0, 255}, |
|
685 {&_station_tick_ctr, SLE_UINT16, 0, 255}, |
|
686 {&_random_seed_1, SLE_UINT32, 0, 255}, |
|
687 {&_random_seed_2, SLE_UINT32, 0, 255}, |
|
688 {&_cur_town_ctr, SLE_UINT8, 0, 255}, |
|
689 {&_cur_player_tick_index, SLE_FILE_U8 | SLE_VAR_UINT, 0, 255}, |
|
690 {&_next_competitor_start, SLE_FILE_U16 | SLE_VAR_UINT, 0, 255}, |
|
691 {&_trees_tick_ctr, SLE_UINT8, 0, 255}, |
|
692 {&_pause, SLE_UINT8, 4, 255}, |
|
693 {NULL,0} |
|
694 }; |
|
695 |
|
696 // Save load date related variables as well as persistent tick counters |
|
697 // XXX: currently some unrelated stuff is just put here |
|
698 static void SaveLoad_DATE() |
|
699 { |
|
700 SlGlobList(_date_desc); |
|
701 } |
|
702 |
|
703 |
|
704 static const SaveLoadGlobVarList _view_desc[] = { |
|
705 {&_saved_scrollpos_x, SLE_FILE_I16 | SLE_VAR_INT, 0, 255}, |
|
706 {&_saved_scrollpos_y, SLE_FILE_I16 | SLE_VAR_INT, 0, 255}, |
|
707 {&_saved_scrollpos_zoom, SLE_UINT8, 0, 255}, |
|
708 {NULL,0} |
|
709 }; |
|
710 |
|
711 static void SaveLoad_VIEW() |
|
712 { |
|
713 SlGlobList(_view_desc); |
|
714 } |
|
715 |
|
716 static void SaveLoad_MAPT() { |
|
717 SlArray(_map_type_and_height, lengthof(_map_type_and_height), SLE_UINT8); |
|
718 } |
|
719 |
|
720 static void SaveLoad_MAP2() { |
|
721 SlArray(_map2, lengthof(_map2), SLE_UINT8); |
|
722 } |
|
723 |
|
724 static void SaveLoad_M3LO() { |
|
725 SlArray(_map3_lo, lengthof(_map3_lo), SLE_UINT8); |
|
726 } |
|
727 |
|
728 static void SaveLoad_M3HI() { |
|
729 SlArray(_map3_hi, lengthof(_map3_hi), SLE_UINT8); |
|
730 } |
|
731 |
|
732 static void SaveLoad_MAPO() { |
|
733 SlArray(_map_owner, lengthof(_map_owner), SLE_UINT8); |
|
734 } |
|
735 |
|
736 static void SaveLoad_MAP5() { |
|
737 SlArray(_map5, lengthof(_map5), SLE_UINT8); |
|
738 } |
|
739 |
|
740 static void SaveLoad_MAPE() { |
|
741 SlArray(_map_extra_bits, lengthof(_map_extra_bits), SLE_UINT8); |
|
742 } |
|
743 |
|
744 |
|
745 static void Save_CHTS() |
|
746 { |
|
747 byte count = sizeof(_cheats)/sizeof(Cheat); |
|
748 Cheat* cht = (Cheat*) &_cheats; |
|
749 Cheat* cht_last = &cht[count]; |
|
750 |
|
751 SlSetLength(count*2); |
|
752 for(; cht != cht_last; cht++) { |
|
753 SlWriteByte(cht->been_used); |
|
754 SlWriteByte(cht->value); |
|
755 } |
|
756 } |
|
757 |
|
758 static void Load_CHTS() |
|
759 { |
|
760 Cheat* cht = (Cheat*) &_cheats; |
|
761 |
|
762 uint count = SlGetFieldLength()/2; |
|
763 for(; count; count--, cht++) |
|
764 { |
|
765 cht->been_used = (byte)SlReadByte(); |
|
766 cht->value = (byte)SlReadByte(); |
|
767 } |
|
768 } |
|
769 |
|
770 |
|
771 const ChunkHandler _misc_chunk_handlers[] = { |
|
772 { 'MAPT', SaveLoad_MAPT, SaveLoad_MAPT, CH_RIFF }, |
|
773 { 'MAP2', SaveLoad_MAP2, SaveLoad_MAP2, CH_RIFF }, |
|
774 { 'M3LO', SaveLoad_M3LO, SaveLoad_M3LO, CH_RIFF }, |
|
775 { 'M3HI', SaveLoad_M3HI, SaveLoad_M3HI, CH_RIFF }, |
|
776 { 'MAPO', SaveLoad_MAPO, SaveLoad_MAPO, CH_RIFF }, |
|
777 { 'MAP5', SaveLoad_MAP5, SaveLoad_MAP5, CH_RIFF }, |
|
778 { 'MAPE', SaveLoad_MAPE, SaveLoad_MAPE, CH_RIFF }, |
|
779 |
|
780 { 'NAME', Save_NAME, Load_NAME, CH_ARRAY}, |
|
781 { 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF}, |
|
782 { 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF}, |
|
783 { 'OPTS', SaveLoad_OPTS, SaveLoad_OPTS, CH_RIFF}, |
|
784 { 'CHTS', Save_CHTS, Load_CHTS, CH_RIFF | CH_LAST} |
|
785 }; |