diff --git a/src/3rdparty/squirrel/squirrel/sqvm.cpp b/src/3rdparty/squirrel/squirrel/sqvm.cpp index ed9d81f42a..036016cd19 100644 --- a/src/3rdparty/squirrel/squirrel/sqvm.cpp +++ b/src/3rdparty/squirrel/squirrel/sqvm.cpp @@ -323,6 +323,10 @@ bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQIntege SQInteger ndef = func->_ndefaultparams; if(ndef && nargs < paramssize) { SQInteger diff = paramssize - nargs; + if (diff > ndef) { + Raise_Error(_SC("wrong number of parameters")); + return false; + } for(SQInteger n = ndef - diff; n < ndef; n++) { _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n]; } @@ -745,9 +749,8 @@ common_call: _GUARD(gen->Yield(this)); Return(1, ct_target, clo); STK(ct_target) = gen; - while (last_top >= _top) _stack._vals[last_top--].Null(); - continue; } + while (last_top >= _top) _stack._vals[last_top--].Null(); } continue; case OT_NATIVECLOSURE: { diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp index f405cbd4f1..a0fe785dc4 100644 --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -742,7 +742,7 @@ struct AIDebugWindow : public Window { if (widget == AID_WIDGET_RELOAD_TOGGLE && !this->IsWidgetDisabled(widget)) { /* First kill the company of the AI, then start a new one. This should start the current AI again */ DoCommandP(0, 2, ai_debug_company, CMD_COMPANY_CTRL); - DoCommandP(0, 1, 0, CMD_COMPANY_CTRL); + DoCommandP(0, 1, ai_debug_company, CMD_COMPANY_CTRL); } } diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index f9daab2fe6..e67df3bec0 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -420,16 +420,23 @@ void ResetCompanyLivery(Company *c) * Create a new company and sets all company variables default values * * @param is_ai is a ai company? + * @param company CompanyID to use for the new company * @return the company struct */ -Company *DoStartupNewCompany(bool is_ai) +Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY) { if (ActiveCompanyCount() == MAX_COMPANIES || !Company::CanAllocateItem()) return NULL; /* we have to generate colour before this company is valid */ Colours colour = GenerateCompanyColour(); - Company *c = new Company(STR_SV_UNNAMED, is_ai); + Company *c; + if (company == INVALID_COMPANY) { + c = new Company(STR_SV_UNNAMED, is_ai); + } else { + if (IsValidCompanyID(company)) return NULL; + c = new (company) Company(STR_SV_UNNAMED, is_ai); + } c->colour = colour; @@ -486,7 +493,7 @@ static void MaybeStartNewCompany() if (n < (uint)_settings_game.difficulty.max_no_competitors) { /* Send a command to all clients to start up a new AI. * Works fine for Multiplayer and Singleplayer */ - DoCommandP(0, 1, 0, CMD_COMPANY_CTRL); + DoCommandP(0, 1, INVALID_COMPANY, CMD_COMPANY_CTRL); } } @@ -700,6 +707,7 @@ void CompanyNewsInformation::FillData(const Company *c, const Company *other) * - p1 = 3 - merge two companies together. merge #1 with #2. Identified by p2 * @param p2 various functionality, dictated by p1 * - p1 = 0 - ClientID of the newly created client + * - p1 = 1 - CompanyID to start AI (INVALID_COMPANY for first available) * - p1 = 2 - CompanyID of the that is getting deleted * - p1 = 3 - #1 p2 = (bit 0-15) - company to merge (p2 & 0xFFFF) * - #2 p2 = (bit 16-31) - company to be merged into ((p2>>16)&0xFFFF) @@ -815,7 +823,8 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 case 1: // Make a new AI company if (!(flags & DC_EXEC)) return CommandCost(); - DoStartupNewCompany(true); + if (p2 != INVALID_COMPANY && (p2 >= MAX_COMPANIES || IsValidCompanyID((CompanyID)p2))) return CMD_ERROR; + DoStartupNewCompany(true, (CompanyID)p2); break; case 2: { // Delete a company diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 55686a1fae..283a23024a 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1018,7 +1018,7 @@ DEF_CONSOLE_CMD(ConStartAI) } /* Start a new AI company */ - DoCommandP(0, 1, 0, CMD_COMPANY_CTRL); + DoCommandP(0, 1, INVALID_COMPANY, CMD_COMPANY_CTRL); return true; } @@ -1054,7 +1054,7 @@ DEF_CONSOLE_CMD(ConReloadAI) /* First kill the company of the AI, then start a new one. This should start the current AI again */ DoCommandP(0, 2, company_id, CMD_COMPANY_CTRL); - DoCommandP(0, 1, 0, CMD_COMPANY_CTRL); + DoCommandP(0, 1, company_id, CMD_COMPANY_CTRL); IConsolePrint(CC_DEFAULT, "AI reloaded."); return true; diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 17bb6a928a..347d6ece61 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -493,6 +493,11 @@ bool OBGFileScanner::AddFile(const char *filename, size_t basepath_length) /* don't allow recursive delete of all remaining items */ duplicate->next = NULL; + /* If the duplicate set is currently used (due to rescanning this can happen) + * update the currently used set to the new one. This will 'lie' about the + * version number until a new game is started which isn't a big problem */ + if (_used_graphics_set == duplicate) _used_graphics_set = graphics; + DEBUG(grf, 1, "Removing %s (%i) as base graphics set (duplicate)", duplicate->name, duplicate->version); delete duplicate; ret = true; diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index badb5a44d3..3fc7635597 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -88,6 +88,7 @@ public: case CONTENT_TYPE_BASE_GRAPHICS: FindGraphicsSets(); + InvalidateWindow(WC_GAME_OPTIONS, 0); break; case CONTENT_TYPE_NEWGRF: diff --git a/src/openttd.cpp b/src/openttd.cpp index b0d847dfe7..70525cdee1 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -71,7 +71,7 @@ void ProcessAsyncSaveFinish(); void CallWindowTickEvent(); extern void SetDifficultyLevel(int mode, DifficultySettings *gm_opt); -extern Company *DoStartupNewCompany(bool is_ai); +extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY); extern void ShowOSErrorBox(const char *buf, bool system); extern void InitializeRailGUI(); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index cdc1295b2c..cc89dfb7c2 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -11,6 +11,7 @@ #include "../roadveh.h" #include "../string_func.h" #include "../gamelog.h" +#include "../gamelog_internal.h" #include "../network/network.h" #include "../gfxinit.h" #include "../functions.h" @@ -38,7 +39,7 @@ #include extern StringID _switch_mode_errorstr; -extern Company *DoStartupNewCompany(bool is_ai); +extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY); extern void InitializeRailGUI(); /** @@ -266,6 +267,24 @@ static void ResetSignalHandlers() signal(SIGFPE, _prev_fpe); } +/** + * Try to find the overridden GRF identifier of the given GRF. + * @param c the GRF to get the 'previous' version of. + * @return the GRF identifier or \a c if none could be found. + */ +static const GRFIdentifier *GetOverriddenIdentifier(const GRFConfig *c) +{ + const LoggedAction *la = &_gamelog_action[_gamelog_actions - 1]; + if (la->at != GLAT_LOAD) return c; + + const LoggedChange *lcend = &la->change[la->changes]; + for (const LoggedChange *lc = la->change; lc != lcend; lc++) { + if (lc->ct == GLCT_GRFCOMPAT && lc->grfcompat.grfid == c->grfid) return &lc->grfcompat; + } + + return c; +} + /** * Signal handler used to give a user a more useful report for crashes during * the savegame loading process; especially when there's problems with the @@ -291,16 +310,17 @@ static void CDECL HandleSavegameLoadCrash(int signum) "savegame still crashes when all NewGRFs are found you should file a\n" "bug report. The missing NewGRFs are:\n"); - for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) { + for (const GRFConfig *c = _grfconfig; c != NULL; c = c->next) { if (HasBit(c->flags, GCF_COMPATIBLE)) { + const GRFIdentifier *replaced = GetOverriddenIdentifier(c); char buf[40]; - md5sumToString(buf, lastof(buf), c->md5sum); - p += seprintf(p, lastof(buffer), "NewGRF %08X (%s) not found; checksum %s. Tried another NewGRF with same GRF ID\n", BSWAP32(c->grfid), c->filename, buf); + md5sumToString(buf, lastof(buf), replaced->md5sum); + p += seprintf(p, lastof(buffer), "NewGRF %08X (checksum %s) not found.\n Loaded NewGRF \"%s\" with same GRF ID instead.\n", BSWAP32(c->grfid), buf, c->filename); } if (c->status == GCS_NOT_FOUND) { char buf[40]; md5sumToString(buf, lastof(buf), c->md5sum); - p += seprintf(p, lastof(buffer), "NewGRF %08X (%s) not found; checksum %s\n", BSWAP32(c->grfid), c->filename, buf); + p += seprintf(p, lastof(buffer), "NewGRF %08X (%s) not found; checksum %s.\n", BSWAP32(c->grfid), c->filename, buf); } }