(svn r17302) [0.7] -Backport from trunk:

- Fix: [NoAI] Reloading an AI started a new AI in the first available company slot causing other AIs to be started [FS#3153] (r17298)
- Fix: Crash after upgrading base graphics set when opening the game options menu and you were using the upgraded set [FS#3147] (r17291)
- Fix: [Squirrel] Stack was not always cleared properly with tail recursion (r17284)
- Fix: [Squirrel] Calling a function that has default parameters with not enough parameters can cause a crash (r17273)
- Change: Mention the MD5 checksum of the original NewGRF in the "saveload failed horribly"-error message and make it more clear that the filename is of the current NewGRF [FS#3139] (r17267)
This commit is contained in:
rubidium 2009-08-28 17:17:08 +00:00
parent ca66a61cc9
commit 47ae295ee1
8 changed files with 53 additions and 15 deletions

View File

@ -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: {

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -88,6 +88,7 @@ public:
case CONTENT_TYPE_BASE_GRAPHICS:
FindGraphicsSets();
InvalidateWindow(WC_GAME_OPTIONS, 0);
break;
case CONTENT_TYPE_NEWGRF:

View File

@ -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();

View File

@ -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 <signal.h>
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);
}
}