Files
@ r19056:723de07a18e9
Branch filter:
Location: cpp/openttd-patchpack/source/src/ai/ai_scanner.cpp
r19056:723de07a18e9
4.9 KiB
text/x-c
(svn r23924) -Fix [FS#5054]: [NoGo] "Some" news messages would cause an assertion to be triggered due to a missing proper location for the viewport of the news message, so only allow building when valid data for the viewport is provided or no viewport is used
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | /* $Id$ */
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ai_scanner.cpp allows scanning AI scripts */
#include "../stdafx.h"
#include "../debug.h"
#include "../network/network.h"
#include "../core/random_func.hpp"
#include "../script/squirrel_class.hpp"
#include "ai_info.hpp"
#include "ai_scanner.hpp"
AIScannerInfo::AIScannerInfo() :
ScriptScanner(),
info_dummy(NULL)
{
}
void AIScannerInfo::Initialize()
{
ScriptScanner::Initialize("AIScanner");
/* Create the dummy AI */
free(this->main_script);
this->main_script = strdup("%_dummy");
extern void Script_CreateDummyInfo(HSQUIRRELVM vm, const char *type, const char *dir);
Script_CreateDummyInfo(this->engine->GetVM(), "AI", "ai");
}
void AIScannerInfo::SetDummyAI(class AIInfo *info)
{
this->info_dummy = info;
}
AIScannerInfo::~AIScannerInfo()
{
delete this->info_dummy;
}
void AIScannerInfo::GetScriptName(ScriptInfo *info, char *name, int len)
{
snprintf(name, len, "%s", info->GetName());
}
void AIScannerInfo::RegisterAPI(class Squirrel *engine)
{
AIInfo::RegisterAPI(engine);
}
AIInfo *AIScannerInfo::SelectRandomAI() const
{
uint num_random_ais = 0;
for (ScriptInfoList::const_iterator it = this->info_single_list.begin(); it != this->info_single_list.end(); it++) {
AIInfo *i = static_cast<AIInfo *>((*it).second);
if (i->UseAsRandomAI()) num_random_ais++;
}
if (num_random_ais == 0) {
DEBUG(script, 0, "No suitable AI found, loading 'dummy' AI.");
return this->info_dummy;
}
/* Find a random AI */
uint pos;
if (_networking) {
pos = InteractiveRandomRange(num_random_ais);
} else {
pos = RandomRange(num_random_ais);
}
/* Find the Nth item from the array */
ScriptInfoList::const_iterator it = this->info_single_list.begin();
#define GetAIInfo(it) static_cast<AIInfo *>((*it).second)
while (!GetAIInfo(it)->UseAsRandomAI()) it++;
for (; pos > 0; pos--) {
it++;
while (!GetAIInfo(it)->UseAsRandomAI()) it++;
}
return GetAIInfo(it);
#undef GetAIInfo
}
AIInfo *AIScannerInfo::FindInfo(const char *nameParam, int versionParam, bool force_exact_match)
{
if (this->info_list.size() == 0) return NULL;
if (nameParam == NULL) return NULL;
char ai_name[1024];
ttd_strlcpy(ai_name, nameParam, sizeof(ai_name));
strtolower(ai_name);
AIInfo *info = NULL;
int version = -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<AIInfo *>(this->info_single_list[ai_name]);
/* 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);
/* FALL THROUGH, like we were calling this function with a version. */
}
if (force_exact_match) {
/* Try to find a direct 'name.version' match */
char ai_name_tmp[1024];
snprintf(ai_name_tmp, sizeof(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<AIInfo *>(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<AIInfo *>((*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;
}
void AIScannerLibrary::Initialize()
{
ScriptScanner::Initialize("AIScanner");
}
void AIScannerLibrary::GetScriptName(ScriptInfo *info, char *name, int len)
{
AILibrary *library = static_cast<AILibrary *>(info);
snprintf(name, len, "%s.%s", library->GetCategory(), library->GetInstanceName());
}
void AIScannerLibrary::RegisterAPI(class Squirrel *engine)
{
AILibrary::RegisterAPI(engine);
}
AILibrary *AIScannerLibrary::FindLibrary(const char *library, int version)
{
/* Internally we store libraries as 'library.version' */
char library_name[1024];
snprintf(library_name, sizeof(library_name), "%s.%d", library, version);
strtolower(library_name);
/* Check if the library + version exists */
ScriptInfoList::iterator iter = this->info_list.find(library_name);
if (iter == this->info_list.end()) return NULL;
return static_cast<AILibrary *>((*iter).second);
}
|