Index: src/ai/ai_scanner.cpp =================================================================== --- src/ai/ai_scanner.cpp (revision 27586) +++ src/ai/ai_scanner.cpp (working copy) @@ -104,7 +104,7 @@ AIInfo *info = NULL; int version = -1; - if (versionParam == -1) { + if (versionParam <= -1) { /* We want to load the latest version of this AI; so find it */ if (this->info_single_list.find(ai_name) != this->info_single_list.end()) return static_cast(this->info_single_list[ai_name]); @@ -113,7 +113,8 @@ if (e == NULL) return NULL; *e = '\0'; e++; - versionParam = atoi(e); + /* We may still want to load the latest available version of this AI */ + if (versionParam == -1) versionParam = atoi(e); /* FALL THROUGH, like we were calling this function with a version. */ } @@ -125,17 +126,46 @@ if (this->info_list.find(ai_name_tmp) != this->info_list.end()) return static_cast(this->info_list[ai_name_tmp]); } - /* See if there is a compatible AI which goes by that name, with the highest - * version which allows loading the requested version */ - ScriptInfoList::iterator it = this->info_list.begin(); - for (; it != this->info_list.end(); it++) { - AIInfo *i = static_cast((*it).second); - if (strcasecmp(ai_name, i->GetName()) == 0 && i->CanLoadFromVersion(versionParam) && (version == -1 || i->GetVersion() > version)) { - version = (*it).second->GetVersion(); - info = i; + if (versionParam != -2) { + /* See if there is a compatible AI which goes by that name, with the highest + * version which allows loading the requested version */ + ScriptInfoList::iterator it = this->info_list.begin(); + for (; it != this->info_list.end(); it++) { + AIInfo *i = static_cast((*it).second); + if (strcasecmp(ai_name, i->GetName()) == 0 && i->CanLoadFromVersion(versionParam) && (version == -1 || i->GetVersion() > version)) { + version = (*it).second->GetVersion(); + info = i; + } } } + if (info == NULL && !force_exact_match && versionParam != -1) { + if (versionParam != -2) { + /* If we didn't find a match AI, maybe the user included a version */ + char *e = strrchr(ai_name, '.'); + if (e == NULL) return NULL; + *e = '\0'; + e++; + versionParam = atoi(e); + /* Try to find a direct 'name.version' match */ + char ai_name_tmp[1024]; + seprintf(ai_name_tmp, lastof(ai_name_tmp), "%s.%d", ai_name, versionParam); + strtolower(ai_name_tmp); + if (this->info_list.find(ai_name_tmp) != this->info_list.end()) return static_cast(this->info_list[ai_name_tmp]); + } + /* See if there is a compatible AI which goes by that name, with the highest + * version which allows loading the requested version */ + ScriptInfoList::iterator it = this->info_list.begin(); + if (versionParam == -2) versionParam = -1; + for (; it != this->info_list.end(); it++) { + AIInfo *i = static_cast((*it).second); + if (strcasecmp(ai_name, i->GetName()) == 0 && i->CanLoadFromVersion(versionParam) && (version == -1 || i->GetVersion() > version)) { + version = (*it).second->GetVersion(); + info = i; + } + } + } + return info; } Index: src/game/game_scanner.cpp =================================================================== --- src/game/game_scanner.cpp (revision 27586) +++ src/game/game_scanner.cpp (working copy) @@ -45,7 +45,7 @@ GameInfo *info = NULL; int version = -1; - if (versionParam == -1) { + if (versionParam <= -1) { /* We want to load the latest version of this Game script; so find it */ if (this->info_single_list.find(game_name) != this->info_single_list.end()) return static_cast(this->info_single_list[game_name]); @@ -54,7 +54,8 @@ if (e == NULL) return NULL; *e = '\0'; e++; - versionParam = atoi(e); + /* We may still want to load the latest available version of this Game script */ + if (versionParam == -1) versionParam = atoi(e); /* FALL THROUGH, like we were calling this function with a version. */ } @@ -66,17 +67,46 @@ if (this->info_list.find(game_name_tmp) != this->info_list.end()) return static_cast(this->info_list[game_name_tmp]); } - /* See if there is a compatible Game script which goes by that name, with the highest - * version which allows loading the requested version */ - ScriptInfoList::iterator it = this->info_list.begin(); - for (; it != this->info_list.end(); it++) { - GameInfo *i = static_cast((*it).second); - if (strcasecmp(game_name, i->GetName()) == 0 && i->CanLoadFromVersion(versionParam) && (version == -1 || i->GetVersion() > version)) { - version = (*it).second->GetVersion(); - info = i; + if (versionParam != -2) { + /* See if there is a compatible Game script which goes by that name, with the highest + * version which allows loading the requested version */ + ScriptInfoList::iterator it = this->info_list.begin(); + for (; it != this->info_list.end(); it++) { + GameInfo *i = static_cast((*it).second); + if (strcasecmp(game_name, i->GetName()) == 0 && i->CanLoadFromVersion(versionParam) && (version == -1 || i->GetVersion() > version)) { + version = (*it).second->GetVersion(); + info = i; + } } } + if (info == NULL && !force_exact_match && versionParam != -1) { + if (versionParam != -2) { + /* If we didn't find a match Game script, maybe the user included a version */ + char *e = strrchr(game_name, '.'); + if (e == NULL) return NULL; + *e = '\0'; + e++; + versionParam = atoi(e); + /* Try to find a direct 'name.version' match */ + char game_name_tmp[1024]; + seprintf(game_name_tmp, lastof(game_name_tmp), "%s.%d", game_name, versionParam); + strtolower(game_name_tmp); + if (this->info_list.find(game_name_tmp) != this->info_list.end()) return static_cast(this->info_list[game_name_tmp]); + } + /* See if there is a compatible Game script which goes by that name, with the highest + * version which allows loading the requested version */ + ScriptInfoList::iterator it = this->info_list.begin(); + if (versionParam == -2) versionParam = -1; + for (; it != this->info_list.end(); it++) { + GameInfo *i = static_cast((*it).second); + if (strcasecmp(game_name, i->GetName()) == 0 && i->CanLoadFromVersion(versionParam) && (version == -1 || i->GetVersion() > version)) { + version = (*it).second->GetVersion(); + info = i; + } + } + } + return info; } Index: src/saveload/ai_sl.cpp =================================================================== --- src/saveload/ai_sl.cpp (revision 27586) +++ src/saveload/ai_sl.cpp (working copy) @@ -87,7 +87,7 @@ if (!config->HasScript()) { /* No version of the AI available that can load the data. Try to load the * latest version of the AI instead. */ - config->Change(_ai_saveload_name, -1, false, _ai_saveload_is_random); + config->Change(_ai_saveload_name, -2, false, _ai_saveload_is_random); if (!config->HasScript()) { if (strcmp(_ai_saveload_name, "%_dummy") != 0) { DEBUG(script, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name, _ai_saveload_version); Index: src/saveload/game_sl.cpp =================================================================== --- src/saveload/game_sl.cpp (revision 27586) +++ src/saveload/game_sl.cpp (working copy) @@ -79,10 +79,10 @@ if (!config->HasScript()) { /* No version of the GameScript available that can load the data. Try to load the * latest version of the GameScript instead. */ - config->Change(_game_saveload_name, -1, false, _game_saveload_is_random); + config->Change(_game_saveload_name, -2, false, _game_saveload_is_random); if (!config->HasScript()) { if (strcmp(_game_saveload_name, "%_dummy") != 0) { - DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name, _game_saveload_version); + DEBUG(script, 0, "The savegame has a GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name, _game_saveload_version); DEBUG(script, 0, "This game will continue to run without GameScript."); } else { DEBUG(script, 0, "The savegame had no GameScript available at the time of saving."); @@ -89,7 +89,7 @@ DEBUG(script, 0, "This game will continue to run without GameScript."); } } else { - DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name, _game_saveload_version); + DEBUG(script, 0, "The savegame has a GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name, _game_saveload_version); DEBUG(script, 0, "The latest version of that GameScript has been loaded instead, but it'll not get the savegame data as it's incompatible."); } /* Make sure the GameScript doesn't get the saveload data, as he was not the Index: src/script/script_config.cpp =================================================================== --- src/script/script_config.cpp (revision 27586) +++ src/script/script_config.cpp (working copy) @@ -24,6 +24,18 @@ this->name = (name == NULL) ? NULL : stredup(name); this->info = (name == NULL) ? NULL : this->FindInfo(this->name, version, force_exact_match); this->version = (info == NULL) ? -1 : info->GetVersion(); + if (this->name != NULL && info != NULL && strcasecmp(this->name, this->info->GetName()) != 0 && this->version > -1) { + char script_name[1024]; + strecpy(script_name, this->name, lastof(script_name)); + strtolower(script_name); + char *e = strrchr(script_name, '.'); + if (e != NULL) { + *e = '\0'; + e++; + int versionParam = atoi(e); + if (this->version != versionParam) this->name = stredup(GetInfo()->GetName()); + } + } this->is_random = is_random; if (this->config_list != NULL) delete this->config_list; this->config_list = (info == NULL) ? NULL : new ScriptConfigItemList();