mirror of https://github.com/OpenTTD/OpenTTD.git
(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:
parent
ca66a61cc9
commit
47ae295ee1
|
@ -323,6 +323,10 @@ bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQIntege
|
||||||
SQInteger ndef = func->_ndefaultparams;
|
SQInteger ndef = func->_ndefaultparams;
|
||||||
if(ndef && nargs < paramssize) {
|
if(ndef && nargs < paramssize) {
|
||||||
SQInteger diff = paramssize - nargs;
|
SQInteger diff = paramssize - nargs;
|
||||||
|
if (diff > ndef) {
|
||||||
|
Raise_Error(_SC("wrong number of parameters"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
for(SQInteger n = ndef - diff; n < ndef; n++) {
|
for(SQInteger n = ndef - diff; n < ndef; n++) {
|
||||||
_stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n];
|
_stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n];
|
||||||
}
|
}
|
||||||
|
@ -745,9 +749,8 @@ common_call:
|
||||||
_GUARD(gen->Yield(this));
|
_GUARD(gen->Yield(this));
|
||||||
Return(1, ct_target, clo);
|
Return(1, ct_target, clo);
|
||||||
STK(ct_target) = gen;
|
STK(ct_target) = gen;
|
||||||
while (last_top >= _top) _stack._vals[last_top--].Null();
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
while (last_top >= _top) _stack._vals[last_top--].Null();
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
case OT_NATIVECLOSURE: {
|
case OT_NATIVECLOSURE: {
|
||||||
|
|
|
@ -742,7 +742,7 @@ struct AIDebugWindow : public Window {
|
||||||
if (widget == AID_WIDGET_RELOAD_TOGGLE && !this->IsWidgetDisabled(widget)) {
|
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 */
|
/* 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, 2, ai_debug_company, CMD_COMPANY_CTRL);
|
||||||
DoCommandP(0, 1, 0, CMD_COMPANY_CTRL);
|
DoCommandP(0, 1, ai_debug_company, CMD_COMPANY_CTRL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -420,16 +420,23 @@ void ResetCompanyLivery(Company *c)
|
||||||
* Create a new company and sets all company variables default values
|
* Create a new company and sets all company variables default values
|
||||||
*
|
*
|
||||||
* @param is_ai is a ai company?
|
* @param is_ai is a ai company?
|
||||||
|
* @param company CompanyID to use for the new company
|
||||||
* @return the company struct
|
* @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;
|
if (ActiveCompanyCount() == MAX_COMPANIES || !Company::CanAllocateItem()) return NULL;
|
||||||
|
|
||||||
/* we have to generate colour before this company is valid */
|
/* we have to generate colour before this company is valid */
|
||||||
Colours colour = GenerateCompanyColour();
|
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;
|
c->colour = colour;
|
||||||
|
|
||||||
|
@ -486,7 +493,7 @@ static void MaybeStartNewCompany()
|
||||||
if (n < (uint)_settings_game.difficulty.max_no_competitors) {
|
if (n < (uint)_settings_game.difficulty.max_no_competitors) {
|
||||||
/* Send a command to all clients to start up a new AI.
|
/* Send a command to all clients to start up a new AI.
|
||||||
* Works fine for Multiplayer and Singleplayer */
|
* 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
|
* - p1 = 3 - merge two companies together. merge #1 with #2. Identified by p2
|
||||||
* @param p2 various functionality, dictated by p1
|
* @param p2 various functionality, dictated by p1
|
||||||
* - p1 = 0 - ClientID of the newly created client
|
* - 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 = 2 - CompanyID of the that is getting deleted
|
||||||
* - p1 = 3 - #1 p2 = (bit 0-15) - company to merge (p2 & 0xFFFF)
|
* - 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)
|
* - #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
|
case 1: // Make a new AI company
|
||||||
if (!(flags & DC_EXEC)) return CommandCost();
|
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;
|
break;
|
||||||
|
|
||||||
case 2: { // Delete a company
|
case 2: { // Delete a company
|
||||||
|
|
|
@ -1018,7 +1018,7 @@ DEF_CONSOLE_CMD(ConStartAI)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start a new AI company */
|
/* Start a new AI company */
|
||||||
DoCommandP(0, 1, 0, CMD_COMPANY_CTRL);
|
DoCommandP(0, 1, INVALID_COMPANY, CMD_COMPANY_CTRL);
|
||||||
|
|
||||||
return true;
|
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 */
|
/* 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, 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.");
|
IConsolePrint(CC_DEFAULT, "AI reloaded.");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -493,6 +493,11 @@ bool OBGFileScanner::AddFile(const char *filename, size_t basepath_length)
|
||||||
/* don't allow recursive delete of all remaining items */
|
/* don't allow recursive delete of all remaining items */
|
||||||
duplicate->next = NULL;
|
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);
|
DEBUG(grf, 1, "Removing %s (%i) as base graphics set (duplicate)", duplicate->name, duplicate->version);
|
||||||
delete duplicate;
|
delete duplicate;
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
|
@ -88,6 +88,7 @@ public:
|
||||||
|
|
||||||
case CONTENT_TYPE_BASE_GRAPHICS:
|
case CONTENT_TYPE_BASE_GRAPHICS:
|
||||||
FindGraphicsSets();
|
FindGraphicsSets();
|
||||||
|
InvalidateWindow(WC_GAME_OPTIONS, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONTENT_TYPE_NEWGRF:
|
case CONTENT_TYPE_NEWGRF:
|
||||||
|
|
|
@ -71,7 +71,7 @@ void ProcessAsyncSaveFinish();
|
||||||
void CallWindowTickEvent();
|
void CallWindowTickEvent();
|
||||||
|
|
||||||
extern void SetDifficultyLevel(int mode, DifficultySettings *gm_opt);
|
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 ShowOSErrorBox(const char *buf, bool system);
|
||||||
extern void InitializeRailGUI();
|
extern void InitializeRailGUI();
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "../roadveh.h"
|
#include "../roadveh.h"
|
||||||
#include "../string_func.h"
|
#include "../string_func.h"
|
||||||
#include "../gamelog.h"
|
#include "../gamelog.h"
|
||||||
|
#include "../gamelog_internal.h"
|
||||||
#include "../network/network.h"
|
#include "../network/network.h"
|
||||||
#include "../gfxinit.h"
|
#include "../gfxinit.h"
|
||||||
#include "../functions.h"
|
#include "../functions.h"
|
||||||
|
@ -38,7 +39,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
extern StringID _switch_mode_errorstr;
|
extern StringID _switch_mode_errorstr;
|
||||||
extern Company *DoStartupNewCompany(bool is_ai);
|
extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY);
|
||||||
extern void InitializeRailGUI();
|
extern void InitializeRailGUI();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -266,6 +267,24 @@ static void ResetSignalHandlers()
|
||||||
signal(SIGFPE, _prev_fpe);
|
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
|
* 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
|
* 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"
|
"savegame still crashes when all NewGRFs are found you should file a\n"
|
||||||
"bug report. The missing NewGRFs are:\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)) {
|
if (HasBit(c->flags, GCF_COMPATIBLE)) {
|
||||||
|
const GRFIdentifier *replaced = GetOverriddenIdentifier(c);
|
||||||
char buf[40];
|
char buf[40];
|
||||||
md5sumToString(buf, lastof(buf), c->md5sum);
|
md5sumToString(buf, lastof(buf), replaced->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);
|
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) {
|
if (c->status == GCS_NOT_FOUND) {
|
||||||
char buf[40];
|
char buf[40];
|
||||||
md5sumToString(buf, lastof(buf), c->md5sum);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue