3 /** @file newgrf_industries.cpp */ |
3 /** @file newgrf_industries.cpp */ |
4 |
4 |
5 #include "stdafx.h" |
5 #include "stdafx.h" |
6 #include "openttd.h" |
6 #include "openttd.h" |
7 #include "debug.h" |
7 #include "debug.h" |
8 #include "functions.h" |
|
9 #include "macros.h" |
|
10 #include "variables.h" |
8 #include "variables.h" |
11 #include "landscape.h" |
9 #include "landscape.h" |
12 #include "table/strings.h" |
|
13 #include "industry.h" |
10 #include "industry.h" |
14 #include "industry_map.h" |
11 #include "industry_map.h" |
15 #include "newgrf.h" |
12 #include "newgrf.h" |
16 #include "newgrf_callbacks.h" |
13 #include "newgrf_callbacks.h" |
17 #include "newgrf_spritegroup.h" |
14 #include "newgrf_spritegroup.h" |
18 #include "newgrf_industries.h" |
15 #include "newgrf_industries.h" |
19 #include "newgrf_industrytiles.h" |
16 #include "newgrf_industrytiles.h" |
20 #include "newgrf_commons.h" |
17 #include "newgrf_commons.h" |
21 #include "newgrf_text.h" |
18 #include "newgrf_text.h" |
22 #include "newgrf_town.h" |
19 #include "newgrf_town.h" |
23 #include "date.h" |
20 #include "window_func.h" |
|
21 #include "town.h" |
|
22 #include "player_func.h" |
|
23 #include "player_base.h" |
|
24 #include "command_func.h" |
|
25 |
|
26 #include "table/strings.h" |
24 |
27 |
25 /* Since the industry IDs defined by the GRF file don't necessarily correlate |
28 /* Since the industry IDs defined by the GRF file don't necessarily correlate |
26 * to those used by the game, the IDs used for overriding old industries must be |
29 * to those used by the game, the IDs used for overriding old industries must be |
27 * translated when the idustry spec is set. */ |
30 * translated when the idustry spec is set. */ |
28 IndustryOverrideManager _industry_mngr(NEW_INDUSTRYOFFSET, NUM_INDUSTRYTYPES, INVALID_INDUSTRYTYPE); |
31 IndustryOverrideManager _industry_mngr(NEW_INDUSTRYOFFSET, NUM_INDUSTRYTYPES, INVALID_INDUSTRYTYPE); |
32 { |
35 { |
33 if (grf_type == IT_INVALID) return IT_INVALID; |
36 if (grf_type == IT_INVALID) return IT_INVALID; |
34 if (!HasBit(grf_type, 7)) return GB(grf_type, 0, 6); |
37 if (!HasBit(grf_type, 7)) return GB(grf_type, 0, 6); |
35 |
38 |
36 return _industry_mngr.GetID(GB(grf_type, 0, 6), grf_id); |
39 return _industry_mngr.GetID(GB(grf_type, 0, 6), grf_id); |
|
40 } |
|
41 |
|
42 static uint32 GetGRFParameter(IndustryType ind_id, byte parameter) |
|
43 { |
|
44 const IndustrySpec *indspec = GetIndustrySpec(ind_id); |
|
45 const GRFFile *file = indspec->grf_prop.grffile; |
|
46 |
|
47 if (parameter >= file->param_end) return 0; |
|
48 return file->param[parameter]; |
37 } |
49 } |
38 |
50 |
39 /** |
51 /** |
40 * Finds the distance for the closest tile with water/land given a tile |
52 * Finds the distance for the closest tile with water/land given a tile |
41 * @param tile the tile to find the distance too |
53 * @param tile the tile to find the distance too |
191 * @return the value stored in the corresponding variable*/ |
203 * @return the value stored in the corresponding variable*/ |
192 uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) |
204 uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) |
193 { |
205 { |
194 const Industry *industry = object->u.industry.ind; |
206 const Industry *industry = object->u.industry.ind; |
195 TileIndex tile = object->u.industry.tile; |
207 TileIndex tile = object->u.industry.tile; |
196 const IndustrySpec *indspec = GetIndustrySpec(industry->type); |
208 IndustryType type = object->u.industry.type; |
|
209 const IndustrySpec *indspec = GetIndustrySpec(type); |
|
210 |
|
211 if (industry == NULL) { |
|
212 /* industry does not exist, only use those variables that are "safe" */ |
|
213 switch (variable) { |
|
214 /* Read GRF parameter */ |
|
215 case 0x7F: return GetGRFParameter(type, parameter); |
|
216 /* Manhattan distance of closes dry/water tile */ |
|
217 case 0x43: return GetClosestWaterDistance(tile, (indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) == 0); |
|
218 } |
|
219 |
|
220 DEBUG(grf, 1, "Unhandled property 0x%X (no available industry) in callback 0x%x", variable, object->callback); |
|
221 |
|
222 *available = false; |
|
223 return UINT_MAX; |
|
224 } |
197 |
225 |
198 switch (variable) { |
226 switch (variable) { |
199 case 0x40: |
227 case 0x40: |
200 case 0x41: |
228 case 0x41: |
201 case 0x42: { // waiting cargo, but only if those two callback flags are set |
229 case 0x42: { // waiting cargo, but only if those two callback flags are set |
266 case 0x67: |
294 case 0x67: |
267 case 0x68: return GetCountAndDistanceOfClosestInstance(parameter, variable == 0x68 ? GB(GetRegister(0x101), 0, 8) : 0, industry); |
295 case 0x68: return GetCountAndDistanceOfClosestInstance(parameter, variable == 0x68 ? GB(GetRegister(0x101), 0, 8) : 0, industry); |
268 |
296 |
269 /* Get a variable from the persistent storage */ |
297 /* Get a variable from the persistent storage */ |
270 case 0x7C: return industry->psa.Get(parameter); |
298 case 0x7C: return industry->psa.Get(parameter); |
|
299 |
|
300 /* Read GRF parameter */ |
|
301 case 0x7F: return GetGRFParameter(type, parameter); |
271 |
302 |
272 /* Industry structure access*/ |
303 /* Industry structure access*/ |
273 case 0x80: return industry->xy; |
304 case 0x80: return industry->xy; |
274 case 0x81: return GB(industry->xy, 8, 8); |
305 case 0x81: return GB(industry->xy, 8, 8); |
275 /* Pointer to the town the industry is associated with */ |
306 /* Pointer to the town the industry is associated with */ |
317 case 0xA5: return GB(industry->last_month_transported[0], 8, 8); |
348 case 0xA5: return GB(industry->last_month_transported[0], 8, 8); |
318 |
349 |
319 case 0xA6: return industry->type; |
350 case 0xA6: return industry->type; |
320 case 0xA7: return industry->founder; |
351 case 0xA7: return industry->founder; |
321 case 0xA8: return industry->random_color; |
352 case 0xA8: return industry->random_color; |
322 case 0xA9: return Clamp(0, industry->last_prod_year - 1920, 255); |
353 case 0xA9: return Clamp(0, industry->last_prod_year - ORIGINAL_BASE_YEAR, 255); |
323 case 0xAA: return industry->counter; |
354 case 0xAA: return industry->counter; |
324 case 0xAB: return GB(industry->counter, 8, 8); |
355 case 0xAB: return GB(industry->counter, 8, 8); |
325 case 0xAC: return industry->was_cargo_delivered; |
356 case 0xAC: return industry->was_cargo_delivered; |
326 |
357 |
327 case 0xB0: return Clamp(0, industry->construction_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 65535); // Date when built since 1920 (in days) |
358 case 0xB0: return Clamp(0, industry->construction_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 65535); // Date when built since 1920 (in days) |
355 { |
386 { |
356 if (object->u.industry.ind == NULL) return; |
387 if (object->u.industry.ind == NULL) return; |
357 object->u.industry.ind->random_triggers = triggers; |
388 object->u.industry.ind->random_triggers = triggers; |
358 } |
389 } |
359 |
390 |
360 static void NewIndustryResolver(ResolverObject *res, TileIndex tile, Industry *indus) |
391 static void NewIndustryResolver(ResolverObject *res, TileIndex tile, Industry *indus, IndustryType type) |
361 { |
392 { |
362 res->GetRandomBits = IndustryGetRandomBits; |
393 res->GetRandomBits = IndustryGetRandomBits; |
363 res->GetTriggers = IndustryGetTriggers; |
394 res->GetTriggers = IndustryGetTriggers; |
364 res->SetTriggers = IndustrySetTriggers; |
395 res->SetTriggers = IndustrySetTriggers; |
365 res->GetVariable = IndustryGetVariable; |
396 res->GetVariable = IndustryGetVariable; |
367 |
398 |
368 res->psa = &indus->psa; |
399 res->psa = &indus->psa; |
369 res->u.industry.tile = tile; |
400 res->u.industry.tile = tile; |
370 res->u.industry.ind = indus; |
401 res->u.industry.ind = indus; |
371 res->u.industry.gfx = INVALID_INDUSTRYTILE; |
402 res->u.industry.gfx = INVALID_INDUSTRYTILE; |
|
403 res->u.industry.type = type; |
372 |
404 |
373 res->callback = CBID_NO_CALLBACK; |
405 res->callback = CBID_NO_CALLBACK; |
374 res->callback_param1 = 0; |
406 res->callback_param1 = 0; |
375 res->callback_param2 = 0; |
407 res->callback_param2 = 0; |
376 res->last_value = 0; |
408 res->last_value = 0; |
381 uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile) |
413 uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile) |
382 { |
414 { |
383 ResolverObject object; |
415 ResolverObject object; |
384 const SpriteGroup *group; |
416 const SpriteGroup *group; |
385 |
417 |
386 NewIndustryResolver(&object, tile, industry); |
418 NewIndustryResolver(&object, tile, industry, type); |
387 object.callback = callback; |
419 object.callback = callback; |
388 object.callback_param1 = param1; |
420 object.callback_param1 = param1; |
389 object.callback_param2 = param2; |
421 object.callback_param2 = param2; |
390 |
422 |
391 group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); |
423 group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); |
452 ind.width = 0; |
484 ind.width = 0; |
453 ind.type = type; |
485 ind.type = type; |
454 ind.selected_layout = itspec_index; |
486 ind.selected_layout = itspec_index; |
455 ind.town = ClosestTownFromTile(tile, (uint)-1); |
487 ind.town = ClosestTownFromTile(tile, (uint)-1); |
456 |
488 |
457 NewIndustryResolver(&object, tile, &ind); |
489 NewIndustryResolver(&object, tile, &ind, type); |
458 object.GetVariable = IndustryLocationGetVariable; |
490 object.GetVariable = IndustryLocationGetVariable; |
459 object.callback = CBID_INDUSTRY_LOCATION; |
491 object.callback = CBID_INDUSTRY_LOCATION; |
460 |
492 |
461 group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); |
493 group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); |
462 |
494 |
505 */ |
537 */ |
506 void IndustryProductionCallback(Industry *ind, int reason) |
538 void IndustryProductionCallback(Industry *ind, int reason) |
507 { |
539 { |
508 const IndustrySpec *spec = GetIndustrySpec(ind->type); |
540 const IndustrySpec *spec = GetIndustrySpec(ind->type); |
509 ResolverObject object; |
541 ResolverObject object; |
510 NewIndustryResolver(&object, ind->xy, ind); |
542 NewIndustryResolver(&object, ind->xy, ind, ind->type); |
511 if ((spec->behaviour & INDUSTRYBEH_PRODCALLBACK_RANDOM) != 0) object.callback_param1 = Random(); |
543 if ((spec->behaviour & INDUSTRYBEH_PRODCALLBACK_RANDOM) != 0) object.callback_param1 = Random(); |
512 int multiplier = 1; |
544 int multiplier = 1; |
513 if ((spec->behaviour & INDUSTRYBEH_PROD_MULTI_HNDLING) != 0) multiplier = ind->prod_level; |
545 if ((spec->behaviour & INDUSTRYBEH_PROD_MULTI_HNDLING) != 0) multiplier = ind->prod_level; |
514 object.callback_param2 = reason; |
546 object.callback_param2 = reason; |
515 |
547 |
533 SB(object.callback_param2, 24, 8, again); |
565 SB(object.callback_param2, 24, 8, again); |
534 } |
566 } |
535 |
567 |
536 InvalidateWindow(WC_INDUSTRY_VIEW, ind->index); |
568 InvalidateWindow(WC_INDUSTRY_VIEW, ind->index); |
537 } |
569 } |
538 |
|
539 void DoTriggerIndustry(Industry *ind, IndustryTileTrigger trigger) |
|
540 { |
|
541 ResolverObject object; |
|
542 |
|
543 NewIndustryResolver(&object, ind->xy, ind); |
|
544 object.callback = CBID_RANDOM_TRIGGER; |
|
545 object.trigger = trigger; |
|
546 |
|
547 const SpriteGroup *group = Resolve(GetIndustrySpec(ind->type)->grf_prop.spritegroup, &object); |
|
548 if (group == NULL) return; |
|
549 |
|
550 byte new_random_bits = Random(); |
|
551 ind->random &= ~object.reseed; |
|
552 ind->random |= new_random_bits & object.reseed; |
|
553 } |
|