18 #include "newgrf_commons.h" |
17 #include "newgrf_commons.h" |
19 #include "newgrf_text.h" |
18 #include "newgrf_text.h" |
20 #include "newgrf_town.h" |
19 #include "newgrf_town.h" |
21 #include "window_func.h" |
20 #include "window_func.h" |
22 #include "town.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" |
|
27 |
|
28 static Randomizer _industry_creation_randomizer; |
23 |
29 |
24 /* Since the industry IDs defined by the GRF file don't necessarily correlate |
30 /* Since the industry IDs defined by the GRF file don't necessarily correlate |
25 * to those used by the game, the IDs used for overriding old industries must be |
31 * to those used by the game, the IDs used for overriding old industries must be |
26 * translated when the idustry spec is set. */ |
32 * translated when the idustry spec is set. */ |
27 IndustryOverrideManager _industry_mngr(NEW_INDUSTRYOFFSET, NUM_INDUSTRYTYPES, INVALID_INDUSTRYTYPE); |
33 IndustryOverrideManager _industry_mngr(NEW_INDUSTRYOFFSET, NUM_INDUSTRYTYPES, INVALID_INDUSTRYTYPE); |
199 * @return the value stored in the corresponding variable*/ |
205 * @return the value stored in the corresponding variable*/ |
200 uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) |
206 uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) |
201 { |
207 { |
202 const Industry *industry = object->u.industry.ind; |
208 const Industry *industry = object->u.industry.ind; |
203 TileIndex tile = object->u.industry.tile; |
209 TileIndex tile = object->u.industry.tile; |
204 const IndustrySpec *indspec = GetIndustrySpec(industry->type); |
210 IndustryType type = object->u.industry.type; |
|
211 const IndustrySpec *indspec = GetIndustrySpec(type); |
|
212 |
|
213 if (industry == NULL) { |
|
214 /* industry does not exist, only use those variables that are "safe" */ |
|
215 switch (variable) { |
|
216 /* Read GRF parameter */ |
|
217 case 0x7F: return GetGRFParameter(type, parameter); |
|
218 /* Manhattan distance of closes dry/water tile */ |
|
219 case 0x43: return GetClosestWaterDistance(tile, (indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) == 0); |
|
220 } |
|
221 |
|
222 DEBUG(grf, 1, "Unhandled property 0x%X (no available industry) in callback 0x%x", variable, object->callback); |
|
223 |
|
224 *available = false; |
|
225 return UINT_MAX; |
|
226 } |
205 |
227 |
206 switch (variable) { |
228 switch (variable) { |
207 case 0x40: |
229 case 0x40: |
208 case 0x41: |
230 case 0x41: |
209 case 0x42: { // waiting cargo, but only if those two callback flags are set |
231 case 0x42: { // waiting cargo, but only if those two callback flags are set |
276 |
298 |
277 /* Get a variable from the persistent storage */ |
299 /* Get a variable from the persistent storage */ |
278 case 0x7C: return industry->psa.Get(parameter); |
300 case 0x7C: return industry->psa.Get(parameter); |
279 |
301 |
280 /* Read GRF parameter */ |
302 /* Read GRF parameter */ |
281 case 0x7F: return GetGRFParameter(industry->type, parameter); |
303 case 0x7F: return GetGRFParameter(type, parameter); |
282 |
304 |
283 /* Industry structure access*/ |
305 /* Industry structure access*/ |
284 case 0x80: return industry->xy; |
306 case 0x80: return industry->xy; |
285 case 0x81: return GB(industry->xy, 8, 8); |
307 case 0x81: return GB(industry->xy, 8, 8); |
286 /* Pointer to the town the industry is associated with */ |
308 /* Pointer to the town the industry is associated with */ |
366 { |
388 { |
367 if (object->u.industry.ind == NULL) return; |
389 if (object->u.industry.ind == NULL) return; |
368 object->u.industry.ind->random_triggers = triggers; |
390 object->u.industry.ind->random_triggers = triggers; |
369 } |
391 } |
370 |
392 |
371 static void NewIndustryResolver(ResolverObject *res, TileIndex tile, Industry *indus) |
393 static void NewIndustryResolver(ResolverObject *res, TileIndex tile, Industry *indus, IndustryType type) |
372 { |
394 { |
373 res->GetRandomBits = IndustryGetRandomBits; |
395 res->GetRandomBits = IndustryGetRandomBits; |
374 res->GetTriggers = IndustryGetTriggers; |
396 res->GetTriggers = IndustryGetTriggers; |
375 res->SetTriggers = IndustrySetTriggers; |
397 res->SetTriggers = IndustrySetTriggers; |
376 res->GetVariable = IndustryGetVariable; |
398 res->GetVariable = IndustryGetVariable; |
378 |
400 |
379 res->psa = &indus->psa; |
401 res->psa = &indus->psa; |
380 res->u.industry.tile = tile; |
402 res->u.industry.tile = tile; |
381 res->u.industry.ind = indus; |
403 res->u.industry.ind = indus; |
382 res->u.industry.gfx = INVALID_INDUSTRYTILE; |
404 res->u.industry.gfx = INVALID_INDUSTRYTILE; |
|
405 res->u.industry.type = type; |
383 |
406 |
384 res->callback = CBID_NO_CALLBACK; |
407 res->callback = CBID_NO_CALLBACK; |
385 res->callback_param1 = 0; |
408 res->callback_param1 = 0; |
386 res->callback_param2 = 0; |
409 res->callback_param2 = 0; |
387 res->last_value = 0; |
410 res->last_value = 0; |
392 uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile) |
415 uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile) |
393 { |
416 { |
394 ResolverObject object; |
417 ResolverObject object; |
395 const SpriteGroup *group; |
418 const SpriteGroup *group; |
396 |
419 |
397 NewIndustryResolver(&object, tile, industry); |
420 NewIndustryResolver(&object, tile, industry, type); |
398 object.callback = callback; |
421 object.callback = callback; |
399 object.callback_param1 = param1; |
422 object.callback_param1 = param1; |
400 object.callback_param2 = param2; |
423 object.callback_param2 = param2; |
401 |
424 |
402 group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); |
425 group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); |
442 /* Distance to the nearest water/land tile */ |
465 /* Distance to the nearest water/land tile */ |
443 case 0x8B: return GetClosestWaterDistance(tile, (GetIndustrySpec(industry->type)->behaviour & INDUSTRYBEH_BUILT_ONWATER) == 0); |
466 case 0x8B: return GetClosestWaterDistance(tile, (GetIndustrySpec(industry->type)->behaviour & INDUSTRYBEH_BUILT_ONWATER) == 0); |
444 |
467 |
445 /* Square of Euclidian distance from town */ |
468 /* Square of Euclidian distance from town */ |
446 case 0x8D: return min(DistanceSquare(industry->town->xy, tile), 65535); |
469 case 0x8D: return min(DistanceSquare(industry->town->xy, tile), 65535); |
|
470 |
|
471 /* 32 random bits */ |
|
472 case 0x8F: return _industry_creation_randomizer.Next(); |
447 } |
473 } |
448 |
474 |
449 /* None of the special ones, so try the general ones */ |
475 /* None of the special ones, so try the general ones */ |
450 return IndustryGetVariable(object, variable, parameter, available); |
476 return IndustryGetVariable(object, variable, parameter, available); |
451 } |
477 } |
452 |
478 |
453 bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspec_index) |
479 bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspec_index, uint32 seed) |
454 { |
480 { |
455 const IndustrySpec *indspec = GetIndustrySpec(type); |
481 const IndustrySpec *indspec = GetIndustrySpec(type); |
456 |
482 |
457 ResolverObject object; |
483 ResolverObject object; |
458 const SpriteGroup *group; |
484 const SpriteGroup *group; |
463 ind.width = 0; |
489 ind.width = 0; |
464 ind.type = type; |
490 ind.type = type; |
465 ind.selected_layout = itspec_index; |
491 ind.selected_layout = itspec_index; |
466 ind.town = ClosestTownFromTile(tile, (uint)-1); |
492 ind.town = ClosestTownFromTile(tile, (uint)-1); |
467 |
493 |
468 NewIndustryResolver(&object, tile, &ind); |
494 NewIndustryResolver(&object, tile, &ind, type); |
469 object.GetVariable = IndustryLocationGetVariable; |
495 object.GetVariable = IndustryLocationGetVariable; |
470 object.callback = CBID_INDUSTRY_LOCATION; |
496 object.callback = CBID_INDUSTRY_LOCATION; |
|
497 _industry_creation_randomizer.SetSeed(seed); |
471 |
498 |
472 group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); |
499 group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); |
473 |
500 |
474 /* Unlike the "normal" cases, not having a valid result means we allow |
501 /* Unlike the "normal" cases, not having a valid result means we allow |
475 * the building of the industry, as that's how it's done in TTDP. */ |
502 * the building of the industry, as that's how it's done in TTDP. */ |
516 */ |
543 */ |
517 void IndustryProductionCallback(Industry *ind, int reason) |
544 void IndustryProductionCallback(Industry *ind, int reason) |
518 { |
545 { |
519 const IndustrySpec *spec = GetIndustrySpec(ind->type); |
546 const IndustrySpec *spec = GetIndustrySpec(ind->type); |
520 ResolverObject object; |
547 ResolverObject object; |
521 NewIndustryResolver(&object, ind->xy, ind); |
548 NewIndustryResolver(&object, ind->xy, ind, ind->type); |
522 if ((spec->behaviour & INDUSTRYBEH_PRODCALLBACK_RANDOM) != 0) object.callback_param1 = Random(); |
549 if ((spec->behaviour & INDUSTRYBEH_PRODCALLBACK_RANDOM) != 0) object.callback_param1 = Random(); |
523 int multiplier = 1; |
550 int multiplier = 1; |
524 if ((spec->behaviour & INDUSTRYBEH_PROD_MULTI_HNDLING) != 0) multiplier = ind->prod_level; |
551 if ((spec->behaviour & INDUSTRYBEH_PROD_MULTI_HNDLING) != 0) multiplier = ind->prod_level; |
525 object.callback_param2 = reason; |
552 object.callback_param2 = reason; |
526 |
553 |