Index: src/lang/english.txt =================================================================== --- src/lang/english.txt (revision 15954) +++ src/lang/english.txt (working copy) @@ -3129,6 +3129,7 @@ STR_NEWGRF_ERROR_INVALID_ID :Attempt to use invalid ID. STR_NEWGRF_ERROR_CORRUPT_SPRITE :{YELLOW}{RAW_STRING} contains a corrupt sprite. All corrupt sprites will be shown as a red question mark (?). STR_NEWGRF_ERROR_MULTIPLE_ACTION_8 :Contains multiple Action 8 entries. +STR_NEWGRF_ERROR_ENDLESS_LOOP_IN_INDUSTRY_PRODUCTION_CALLBACK :{BLACK}{RAW_STRING} caused an endless loop in IndustryProductionCallback, local_id was {NUM}. STR_NEWGRF_PRESET_LIST_TIP :{BLACK}Load the selected preset STR_NEWGRF_PRESET_SAVE :{BLACK}Save preset Index: src/newgrf_industries.cpp =================================================================== --- src/newgrf_industries.cpp (revision 15954) +++ src/newgrf_industries.cpp (working copy) @@ -17,6 +17,8 @@ #include "town.h" #include "company_base.h" #include "command_func.h" +#include "gui.h" +#include "strings_func.h" #include "table/strings.h" @@ -570,6 +572,16 @@ object.callback_param2 = reason; for (uint loop = 0;; loop++) { + if (loop >= 0x10000) { + /* display error message */ + SetDParamStr(0, spec->grf_prop.grffile->filename); + SetDParam(1, spec->grf_prop.local_id); + ShowErrorMessage(STR_NEWGRF_ERROR_ENDLESS_LOOP_IN_INDUSTRY_PRODUCTION_CALLBACK, STR_EMPTY, 0, 0); + + /* abort the function early, this error isn't critical and will allow the game to continue to run */ + break; + } + SB(object.callback_param2, 8, 16, loop); const SpriteGroup *group = Resolve(spec->grf_prop.spritegroup, &object); if (group == NULL || group->type != SGT_INDUSTRY_PRODUCTION) break;