#include "AngelScripResolver.hpp" #include #include #include "../../../extern/angelscript_addons/scriptarray/scriptarray.h" #include "../../../extern/angelscript_addons/scripthandle/scripthandle.h" #include "../../../extern/angelscript_addons/scripthelper/scripthelper.h" #include "../../../extern/angelscript_addons/scriptstdstring/scriptstdstring.h" #include "TypeRegistry/BasicScriptClass.hpp" #include "TypeRegistry/Battling/RegisterBattleClass.hpp" #include "TypeRegistry/Battling/RegisterBattleLibrary.hpp" #include "TypeRegistry/Battling/RegisterExecutingAttack.hpp" #include "TypeRegistry/Battling/RegisterPokemonClass.hpp" #include "TypeRegistry/Battling/RegisterTurnChoices.hpp" #include "TypeRegistry/Library/RegisterGrowthRateTypes.hpp" #include "TypeRegistry/Library/RegisterItemTypes.hpp" #include "TypeRegistry/Library/RegisterMoveTypes.hpp" #include "TypeRegistry/Library/RegisterSpeciesTypes.hpp" #include "TypeRegistry/Library/RegisterStaticLibraryTypes.hpp" #include "TypeRegistry/Library/RegisterTypeLibrary.hpp" CreatureLib::Battling::ScriptResolver* PkmnLib::Battling::BattleLibrary::CreateScriptResolver() { return new AngelScripResolver(); } void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* arg) { auto library = (PkmnLib::Battling::BattleLibrary*)arg; _engine = asCreateScriptEngine(); int32_t r = _engine->SetMessageCallback(asFUNCTION(MessageCallback), nullptr, asCALL_CDECL); if (r < 0) throw CreatureException("Registering message callback failed."); _engine->SetEngineProperty(asEP_DISALLOW_EMPTY_LIST_ELEMENTS, true); _engine->SetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE, false); _engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, true); _engine->SetEngineProperty(asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT, true); _engine->SetEngineProperty(asEP_AUTO_GARBAGE_COLLECT, false); _engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, true); _engine->SetEngineProperty(asEP_PROPERTY_ACCESSOR_MODE, 2); _engine->SetEngineProperty(asEP_COMPILER_WARNINGS, 2); RegisterStdString(_engine); // Register Script Array type RegisterScriptArray(_engine, true); r = _engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(Print), asCALL_CDECL); if (r < 0) throw CreatureException("Registering print function failed."); RegisterScriptHandle(_engine); _builder.StartNewModule(_engine, "pkmn"); _mainModule = _builder.GetModule(); RegisterTypes(); RegisterExceptionRoutines(_engine); auto staticLib = library->GetStaticLib(); _engine->RegisterGlobalProperty("const StaticLibrary@ StaticLib", &staticLib); _contextPool = new ContextPool(_engine); } void AngelScripResolver::RegisterTypes() { // Register static library types RegisterSpeciesTypes::Register(_engine); RegisterItemTypes::Register(_engine); RegisterMoveTypes::Register(_engine); RegisterGrowthRateTypes::Register(_engine); RegisterTypeLibrary::Register(_engine); RegisterStaticLibraryTypes::Register(_engine); // Register battle types RegisterPokemonClass::Register(_engine); RegisterExecutingAttack::Register(_engine); RegisterTurnChoices::Register(_engine); RegisterBattleLibrary::Register(_engine); RegisterBattleClass::Register(_engine); [[maybe_unused]] int r = _engine->RegisterObjectMethod("Pokemon", "const Battle@ get_Battle() const property", asMETHOD(CreatureLib::Battling::Creature, GetBattle), asCALL_THISCALL); assert(r >= 0); // Register base script BasicScriptClass::Register(_engine); } AngelScriptTypeInfo* AngelScripResolver::GetTypeInfo(const ConstString& name, const std::string& decl) { auto find = _types.find(name); if (find != _types.end()) { return find->second; } auto type = _mainModule->GetTypeInfoByDecl(decl.c_str()); if (type == nullptr) { _types.insert({name, nullptr}); return nullptr; } auto typeinfo = new AngelScriptTypeInfo(name, type); _types.insert({name, typeinfo}); return typeinfo; } void AngelScripResolver::MessageCallback(const asSMessageInfo* msg, void* param) { const char* type = "ERR "; if (msg->type == asMSGTYPE_WARNING) type = "WARN"; else if (msg->type == asMSGTYPE_INFORMATION) type = "INFO"; printf("%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message); } static constexpr const char* GetCategoryNamespace(ScriptCategory category) { switch (category) { case ScriptCategory::Attack: return "Moves"; case ScriptCategory::Talent: return "Abilities"; case ScriptCategory::Status: return "Status"; case ScriptCategory::Creature: return "Pokemon"; case ScriptCategory::Battle: return "Battle"; case ScriptCategory::Side: return "Side"; default: throw CreatureException("Unknown script category"); } } CreatureLib::Battling::Script* AngelScripResolver::LoadScript(ScriptCategory category, const ConstString& scriptName) { std::stringstream decl; decl << GetCategoryNamespace(category) << "::" << scriptName.c_str(); auto typeInfo = GetTypeInfo(scriptName, decl.str()); if (typeInfo == nullptr) return nullptr; auto ctx = _contextPool->RequestContext(); auto obj = typeInfo->Instantiate(ctx); _contextPool->ReturnContextToPool(ctx); return new AngelScriptScript(typeInfo, obj, _contextPool); } void AngelScripResolver::FinalizeModule() { int r = _builder.BuildModule(); if (r < 0) throw CreatureException("Building Script Module failed."); } void AngelScripResolver::CreateScript(const char* name, const char* script) { _builder.AddSectionFromMemory(name, script); }