Adds a bunch of helpers for evolution, as well as custom script evolution methods.
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2021-07-09 13:54:42 +02:00
parent 8fc29d925b
commit 9424a209ec
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
16 changed files with 281 additions and 86 deletions

View File

@ -17,6 +17,13 @@ export uint8_t PkmnLib_AngelScriptResolver_LoadScript(CreatureLib::Battling::Bat
ScriptCategory category, const char* scriptName) { ScriptCategory category, const char* scriptName) {
Try(out = p->LoadScript(category, ArbUt::StringView(scriptName));) Try(out = p->LoadScript(category, ArbUt::StringView(scriptName));)
} }
export uint8_t PkmnLib_AngelScriptResolver_LoadEvolutionScript(PkmnLib::Battling::EvolutionScript const*& out,
AngelScriptResolver* p, const char* scriptName) {
Try(
auto s = p->LoadEvolutionScript(ArbUt::StringView(scriptName));
if (!s.HasValue()) { out = nullptr; } else { out = s.GetValue(); })
}
export uint8_t PkmnLib_AngelScriptResolver_WriteByteCodeToFile(AngelScriptResolver* p, const char* file, export uint8_t PkmnLib_AngelScriptResolver_WriteByteCodeToFile(AngelScriptResolver* p, const char* file,
bool stripDebugInfo) { bool stripDebugInfo) {
Try(p->WriteByteCodeToFile(file, stripDebugInfo);) Try(p->WriteByteCodeToFile(file, stripDebugInfo);)

View File

@ -0,0 +1,13 @@
#ifndef PKMNLIB_EVOLUTIONSCRIPT_HPP
#define PKMNLIB_EVOLUTIONSCRIPT_HPP
namespace PkmnLib::Battling {
class EvolutionScript {
public:
virtual void DoesEvolveFromLevelUp(const ArbUt::BorrowedPtr<const PkmnLib::Library::EvolutionData>& evolution,
const ArbUt::BorrowedPtr<const PkmnLib::Battling::Pokemon>& pokemon,
bool* out) const = 0;
};
}
#endif // PKMNLIB_EVOLUTIONSCRIPT_HPP

View File

@ -66,7 +66,16 @@ bool PkmnLib::Battling::MiscLibrary::CanEvolveFromLevelUp(
return pokemon->GetLevel() >= evolution->GetData(1)->AsInt() && return pokemon->GetLevel() >= evolution->GetData(1)->AsInt() &&
pokemon->GetGender() == (CreatureLib::Library::Gender)evolution->GetData(0)->AsInt(); pokemon->GetGender() == (CreatureLib::Library::Gender)evolution->GetData(0)->AsInt();
case Library::EvolutionMethod::Custom: case Library::EvolutionMethod::Custom:
// TODO {
auto script = dynamic_cast<ScriptResolver*>(pokemon->GetLibrary()->GetScriptResolver().get())
->LoadEvolutionScript(evolution->GetData(0)->AsString());
if (!script.HasValue()) {
return false;
}
auto v = false;
script.GetValue()->DoesEvolveFromLevelUp(evolution, pokemon, &v);
return v;
}
case Library::EvolutionMethod::EvolutionItemUse: case Library::EvolutionMethod::EvolutionItemUse:
case Library::EvolutionMethod::EvolutionItemUseWithGender: case Library::EvolutionMethod::EvolutionItemUseWithGender:
case Library::EvolutionMethod::Trade: case Library::EvolutionMethod::Trade:

View File

@ -1,9 +1,14 @@
#ifndef PKMNLIB_SCRIPTRESOLVER_HPP #ifndef PKMNLIB_SCRIPTRESOLVER_HPP
#define PKMNLIB_SCRIPTRESOLVER_HPP #define PKMNLIB_SCRIPTRESOLVER_HPP
#include "../EvolutionScript.hpp"
namespace PkmnLib::Battling { namespace PkmnLib::Battling {
class ScriptResolver : public CreatureLib::Battling::ScriptResolver { class ScriptResolver : public CreatureLib::Battling::ScriptResolver {
public: public:
virtual ArbUt::OptionalBorrowedPtr<const EvolutionScript> LoadEvolutionScript(const ArbUt::StringView&) {
return nullptr;
};
}; };
} }

View File

@ -2,7 +2,7 @@
#define PKMNLIB_MOVECATEGORY_HPP #define PKMNLIB_MOVECATEGORY_HPP
namespace PkmnLib::Library { namespace PkmnLib::Library {
enum class MoveCategory : uint8_t { Physical, Special, Status }; ENUM(MoveCategory, u8, Physical, Special, Status)
} }
#endif // PKMNLIB_MOVECATEGORY_HPP #endif // PKMNLIB_MOVECATEGORY_HPP

View File

@ -0,0 +1,18 @@
#include "AngelScriptEvolutionScript.hpp"
#include "AngelScriptResolver.hpp"
void AngelScriptEvolutionScript::DoesEvolveFromLevelUp(
const ArbUt::BorrowedPtr<const PkmnLib::Library::EvolutionData>& evolution,
const ArbUt::BorrowedPtr<const PkmnLib::Battling::Pokemon>& pokemon, bool* out) const {
if (!__DoesEvolveFromLevelUp.Exists) {
return;
}
AngelScriptUtils::AngelscriptFunctionCall(
__DoesEvolveFromLevelUp.Function, _resolver->GetContextPool(), _scriptObject, ""_cnc,
[&]([[maybe_unused]] asIScriptContext* ctx) {
ctx->SetArgObject(0, (void*)evolution.GetRaw());
ctx->SetArgObject(1, (void*)pokemon.GetRaw());
ctx->SetArgObject(2, out);
},
[&]([[maybe_unused]] asIScriptContext* ctx) {});
}

View File

@ -0,0 +1,47 @@
#ifndef PKMNLIB_ANGELSCRIPTEVOLUTIONSCRIPT_HPP
#define PKMNLIB_ANGELSCRIPTEVOLUTIONSCRIPT_HPP
#include "../../Battling/Pokemon/Pokemon.hpp"
#include "../../Library/Evolutions/EvolutionData.hpp"
#include "AngelScriptFunctionCall.hpp"
class AngelScriptResolver;
class AngelScriptEvolutionScript final : public PkmnLib::Battling::EvolutionScript {
asIScriptObject* _scriptObject;
AngelScriptResolver* _resolver;
struct FunctionInfo {
bool Exists = false;
asIScriptFunction* Function = nullptr;
};
#define EVO_SCRIPT_HOOK_FUNCTION(name, decl) FunctionInfo __##name = Initialize(decl);
FunctionInfo Initialize(const std::string& decl) {
auto val = _scriptObject->GetObjectType()->GetMethodByDecl(decl.c_str(), false);
if (val == nullptr) {
return FunctionInfo{.Exists = false, .Function = nullptr};
}
return FunctionInfo{.Exists = true, .Function = val};
}
EVO_SCRIPT_HOOK_FUNCTION(DoesEvolveFromLevelUp,
"void DoesEvolveFromLevelUp(bool& out, const EvolutionData@ evoData,"
"const Pokemon@ pokemon)");
public:
AngelScriptEvolutionScript(asIScriptObject* scriptObject, AngelScriptResolver* resolver)
: _scriptObject(scriptObject), _resolver(resolver) {}
~AngelScriptEvolutionScript() {
if (_scriptObject != nullptr) {
_scriptObject->Release();
}
}
void DoesEvolveFromLevelUp(const ArbUt::BorrowedPtr<const PkmnLib::Library::EvolutionData>& evolution,
const ArbUt::BorrowedPtr<const PkmnLib::Battling::Pokemon>& pokemon,
bool* out) const override;
};
#endif // PKMNLIB_ANGELSCRIPTEVOLUTIONSCRIPT_HPP

View File

@ -107,13 +107,13 @@ void AngelScriptResolver::Initialize(CreatureLib::Battling::BattleLibrary* arg,
void AngelScriptResolver::RegisterTypes() { void AngelScriptResolver::RegisterTypes() {
// Register static library types // Register static library types
RegisterEffectParameter::Register(_engine);
RegisterSpeciesTypes::Register(_engine); RegisterSpeciesTypes::Register(_engine);
RegisterItemTypes::Register(_engine); RegisterItemTypes::Register(_engine);
RegisterMoveTypes::Register(_engine); RegisterMoveTypes::Register(_engine);
RegisterGrowthRateTypes::Register(_engine); RegisterGrowthRateTypes::Register(_engine);
RegisterTypeLibrary::Register(_engine); RegisterTypeLibrary::Register(_engine);
RegisterStaticLibraryTypes::Register(_engine); RegisterStaticLibraryTypes::Register(_engine);
RegisterEffectParameter::Register(_engine);
// Register battle types // Register battle types
// Predeclare these two types, and declare their implementation later. // Predeclare these two types, and declare their implementation later.
@ -197,6 +197,31 @@ CreatureLib::Battling::ItemUseScript* AngelScriptResolver::LoadItemScript(const
return scriptObject; return scriptObject;
} }
ArbUt::OptionalBorrowedPtr<const PkmnLib::Battling::EvolutionScript>
AngelScriptResolver::LoadEvolutionScript(const ArbUt::StringView& view) {
auto v = this->_evolutionScripts.TryGet(view);
if (v.has_value()) {
return v.value().get();
}
auto typeInfoOption = _evolutionTypes.TryGet(view);
if (!typeInfoOption.has_value()) {
return nullptr;
}
auto* ctx = _contextPool->RequestContext();
auto* factory = typeInfoOption.value().get()->GetFactoryByIndex(0);
ctx->Prepare(factory);
auto result = ctx->Execute();
if (result != asEXECUTION_FINISHED) {
throw ArbUt::Exception("Instantiation failed.");
}
asIScriptObject* obj = *(asIScriptObject**)ctx->GetAddressOfReturnValue();
obj->AddRef();
auto* scriptObject = new AngelScriptEvolutionScript(obj, this);
_evolutionScripts.Insert(view, scriptObject);
_contextPool->ReturnContextToPool(ctx);
return scriptObject;
}
void AngelScriptResolver::FinalizeModule() { void AngelScriptResolver::FinalizeModule() {
int r = _builder.BuildModule(); int r = _builder.BuildModule();
if (r < 0) if (r < 0)
@ -208,6 +233,7 @@ void AngelScriptResolver::FinalizeModule() {
auto pkmnScriptType = _mainModule->GetTypeInfoByName("PkmnScript"); auto pkmnScriptType = _mainModule->GetTypeInfoByName("PkmnScript");
auto itemUseScriptType = _mainModule->GetTypeInfoByName("ItemUseScript"); auto itemUseScriptType = _mainModule->GetTypeInfoByName("ItemUseScript");
auto evolutionScriptType = _mainModule->GetTypeInfoByName("EvolutionScript");
for (asUINT n = 0; n < count; n++) { for (asUINT n = 0; n < count; n++) {
auto typeInfo = _mainModule->GetObjectTypeByIndex(n); auto typeInfo = _mainModule->GetObjectTypeByIndex(n);
if (typeInfo->DerivesFrom(pkmnScriptType)) { if (typeInfo->DerivesFrom(pkmnScriptType)) {
@ -252,6 +278,27 @@ void AngelScriptResolver::FinalizeModule() {
_itemUseTypes.Insert(effectName, typeInfo); _itemUseTypes.Insert(effectName, typeInfo);
} }
} }
} else if (typeInfo->DerivesFrom(evolutionScriptType)) {
auto metadata = _builder.GetMetadataForType(typeInfo->GetTypeId());
for (size_t m = 0; m < metadata.size(); m++) {
auto data = metadata[m];
if (std::regex_match(data, base_match, metadataMatcher)) {
auto mt = base_match[1].str();
auto metadataKind = ArbUt::StringView(mt.c_str(), mt.length());
auto metadataVariables = base_match[2].str();
if (!std::regex_match(metadataVariables, base_match, variableMatcher)) {
continue;
}
ArbUt::StringView effectName;
for (size_t variableIndex = 1; variableIndex < base_match.size(); variableIndex += 2) {
if (ArbUt::StringView::CalculateHash(base_match[variableIndex].str().c_str()) == "effect"_cnc) {
auto val = base_match[variableIndex + 1].str();
effectName = ArbUt::StringView(val.c_str(), val.length());
}
}
_evolutionTypes.Insert(effectName, typeInfo);
}
}
} }
} }
} }
@ -309,7 +356,7 @@ void AngelScriptResolver::WriteByteCodeToFile(const char* file, bool stripDebugI
// We grab the current position of the written file. This is the position the types will be written on. So we need // We grab the current position of the written file. This is the position the types will be written on. So we need
// to know this. // to know this.
uint64_t bytecodeSize = (uint64_t)ftell(wFile); uint64_t bytecodeSize = (uint64_t)ftell(wFile);
stream->WriteTypes(_typeDatabase, _itemUseTypes); stream->WriteTypes(_typeDatabase, _itemUseTypes, _evolutionTypes);
// Go back to the start of the file // Go back to the start of the file
fsetpos(wFile, &startPos); fsetpos(wFile, &startPos);
@ -351,7 +398,7 @@ uint8_t* AngelScriptResolver::WriteByteCodeToMemory(size_t& size, bool stripDebu
auto result = _mainModule->SaveByteCode(stream, stripDebugInfo); auto result = _mainModule->SaveByteCode(stream, stripDebugInfo);
Ensure(result == asSUCCESS); Ensure(result == asSUCCESS);
byteCodeSize[0] = (uint64_t)stream->GetWrittenSize(); byteCodeSize[0] = (uint64_t)stream->GetWrittenSize();
stream->WriteTypes(_typeDatabase, _itemUseTypes); stream->WriteTypes(_typeDatabase, _itemUseTypes, _evolutionTypes);
stream->WriteToPosition(byteCodeSize, sizeof(uint64_t), 0); stream->WriteToPosition(byteCodeSize, sizeof(uint64_t), 0);
auto arr = stream->GetOut(); auto arr = stream->GetOut();
size = stream->GetWrittenSize(); size = stream->GetWrittenSize();
@ -376,7 +423,7 @@ void AngelScriptResolver::LoadByteCodeFromMemory(uint8_t* byte, size_t size) {
delete stream; delete stream;
} }
void AngelScriptResolver::InitializeByteCode( void AngelScriptResolver::InitializeByteCode(
const ArbUt::Dictionary<ScriptCategory, ArbUt::Dictionary<ArbUt::StringView, uint32_t>>& types) { const ArbUt::Dictionary<i16, ArbUt::Dictionary<ArbUt::StringView, uint32_t>>& types) {
auto typeCount = _mainModule->GetObjectTypeCount(); auto typeCount = _mainModule->GetObjectTypeCount();
ArbUt::Dictionary<uint32_t, asITypeInfo*> objectTypes; ArbUt::Dictionary<uint32_t, asITypeInfo*> objectTypes;
@ -386,20 +433,30 @@ void AngelScriptResolver::InitializeByteCode(
} }
ArbUt::Dictionary<ScriptCategory, ArbUt::Dictionary<ArbUt::StringView, AngelScriptTypeInfo*>> typeDatabase; ArbUt::Dictionary<ScriptCategory, ArbUt::Dictionary<ArbUt::StringView, AngelScriptTypeInfo*>> typeDatabase;
for (const auto& innerDb : types) { for (const auto& innerDb : types) {
if (innerDb.first != (ScriptCategory)-1) { if (innerDb.first >= 0 && innerDb.first <= 255) {
ArbUt::Dictionary<ArbUt::StringView, AngelScriptTypeInfo*> newInnerDb; ArbUt::Dictionary<ArbUt::StringView, AngelScriptTypeInfo*> newInnerDb;
for (const auto& val : innerDb.second) { for (const auto& val : innerDb.second) {
auto decl = val.second; auto decl = val.second;
auto type = objectTypes[decl]; auto type = objectTypes[decl];
newInnerDb.Set(val.first, new AngelScriptTypeInfo(val.first, type)); newInnerDb.Set(val.first, new AngelScriptTypeInfo(val.first, type));
} }
typeDatabase.Set(innerDb.first, newInnerDb); typeDatabase.Set((ScriptCategory)innerDb.first, newInnerDb);
} else { } else {
if (innerDb.first == -1) {
for (const auto& val : innerDb.second) { for (const auto& val : innerDb.second) {
auto decl = val.second; auto decl = val.second;
auto type = objectTypes[decl]; auto type = objectTypes[decl];
_itemUseTypes.Set(val.first, type); _itemUseTypes.Set(val.first, type);
} }
} else if (innerDb.first == -2) {
for (const auto& val : innerDb.second) {
auto decl = val.second;
auto type = objectTypes[decl];
_evolutionTypes.Set(val.first, type);
}
} else {
THROW("Resolving unknown script category value: " << innerDb.first);
}
} }
} }
_typeDatabase = typeDatabase; _typeDatabase = typeDatabase;

View File

@ -4,6 +4,7 @@
#include <CreatureLib/Battling/ScriptHandling/ScriptResolver.hpp> #include <CreatureLib/Battling/ScriptHandling/ScriptResolver.hpp>
#include "../../../extern/angelscript_addons/scriptbuilder/scriptbuilder.h" #include "../../../extern/angelscript_addons/scriptbuilder/scriptbuilder.h"
#include "../../Battling/Library/BattleLibrary.hpp" #include "../../Battling/Library/BattleLibrary.hpp"
#include "AngelScriptEvolutionScript.hpp"
#define ANGELSCRIPT_DLL_LIBRARY_IMPORT #define ANGELSCRIPT_DLL_LIBRARY_IMPORT
#include <Arbutils/StringView.hpp> #include <Arbutils/StringView.hpp>
@ -23,18 +24,18 @@ private:
ArbUt::Dictionary<ScriptCategory, ArbUt::Dictionary<ArbUt::StringView, AngelScriptTypeInfo*>> _typeDatabase; ArbUt::Dictionary<ScriptCategory, ArbUt::Dictionary<ArbUt::StringView, AngelScriptTypeInfo*>> _typeDatabase;
ArbUt::Dictionary<ArbUt::StringView, asITypeInfo*> _baseTypes; ArbUt::Dictionary<ArbUt::StringView, asITypeInfo*> _baseTypes;
ArbUt::Dictionary<ArbUt::StringView, asITypeInfo*> _itemUseTypes; ArbUt::Dictionary<ArbUt::StringView, asITypeInfo*> _itemUseTypes;
ArbUt::Dictionary<ArbUt::StringView, asITypeInfo*> _evolutionTypes;
ArbUt::Dictionary<const CreatureLib::Library::Item*, AngelScriptItemUseScript*> _itemUseScripts; ArbUt::Dictionary<const CreatureLib::Library::Item*, AngelScriptItemUseScript*> _itemUseScripts;
ArbUt::Dictionary<ArbUt::StringView, AngelScriptEvolutionScript*> _evolutionScripts;
static void MessageCallback(const asSMessageInfo* msg, void* param); static void MessageCallback(const asSMessageInfo* msg, void* param);
static void Print(const std::string& str) { std::cout << str << std::endl; } static void Print(const std::string& str) { std::cout << str << std::endl; }
static void PrintConst(const ArbUt::StringView& str) { Print(std::string(str.std_str())); } static void PrintConst(const ArbUt::StringView& str) { Print(std::string(str.std_str())); }
static i32 IncludeCallback(const char *include, const char *from, CScriptBuilder *builder, void *userParam); static i32 IncludeCallback(const char* include, const char* from, CScriptBuilder* builder, void* userParam);
void RegisterTypes(); void RegisterTypes();
void void
InitializeByteCode(const ArbUt::Dictionary<ScriptCategory, ArbUt::Dictionary<ArbUt::StringView, uint32_t>>& types); InitializeByteCode(const ArbUt::Dictionary<i16, ArbUt::Dictionary<ArbUt::StringView, uint32_t>>& types);
void RegisterScriptType(asITypeInfo* typeInfo, const ArbUt::StringView& metadataKind, void RegisterScriptType(asITypeInfo* typeInfo, const ArbUt::StringView& metadataKind,
const ArbUt::StringView& effectName); const ArbUt::StringView& effectName);
@ -64,6 +65,9 @@ public:
const ArbUt::StringView& scriptName) override; const ArbUt::StringView& scriptName) override;
CreatureLib::Battling::ItemUseScript* LoadItemScript(const CreatureLib::Library::Item* item) override; CreatureLib::Battling::ItemUseScript* LoadItemScript(const CreatureLib::Library::Item* item) override;
ArbUt::OptionalBorrowedPtr<const PkmnLib::Battling::EvolutionScript>
LoadEvolutionScript(const ArbUt::StringView& view) override;
void WriteByteCodeToFile(const char* file, bool stripDebugInfo = false); void WriteByteCodeToFile(const char* file, bool stripDebugInfo = false);
void LoadByteCodeFromFile(const char* file); void LoadByteCodeFromFile(const char* file);
uint8_t* WriteByteCodeToMemory(size_t& size, bool stripDebugInfo = false); uint8_t* WriteByteCodeToMemory(size_t& size, bool stripDebugInfo = false);

View File

@ -15,7 +15,8 @@ protected:
public: public:
virtual void WriteTypes( virtual void WriteTypes(
const ArbUt::Dictionary<ScriptCategory, ArbUt::Dictionary<ArbUt::StringView, AngelScriptTypeInfo*>>& types, const ArbUt::Dictionary<ScriptCategory, ArbUt::Dictionary<ArbUt::StringView, AngelScriptTypeInfo*>>& types,
const ArbUt::Dictionary<ArbUt::StringView, asITypeInfo*> itemUseTypes) { const ArbUt::Dictionary<ArbUt::StringView, asITypeInfo*>& itemUseTypes,
const ArbUt::Dictionary<ArbUt::StringView, asITypeInfo*>& evolutionTypes) {
// We serialize our types in the format // We serialize our types in the format
// "[category(byte)][name(str)]\2[decl(str)]\2[name(str)]\2[decl(str)]\1[category(byte)]...." // "[category(byte)][name(str)]\2[decl(str)]\2[name(str)]\2[decl(str)]\1[category(byte)]...."
@ -23,7 +24,7 @@ public:
for (const auto& dic : types) { for (const auto& dic : types) {
// Write the category // Write the category
categoryArr[0] = dic.first; categoryArr[0] = dic.first;
Write(categoryArr, sizeof(ScriptCategory)); Write(categoryArr, sizeof(i16));
for (const auto& inner : dic.second) { for (const auto& inner : dic.second) {
// Write the script name // Write the script name
Write(inner.first.c_str(), sizeof(char) * inner.first.Length()); Write(inner.first.c_str(), sizeof(char) * inner.first.Length());
@ -40,7 +41,7 @@ public:
} }
categoryArr[0] = (ScriptCategory)-1; categoryArr[0] = (ScriptCategory)-1;
Write(categoryArr, sizeof(ScriptCategory)); Write(categoryArr, sizeof(i16));
for (const auto& inner : itemUseTypes) { for (const auto& inner : itemUseTypes) {
// Write the script name // Write the script name
Write(inner.first.c_str(), sizeof(char) * inner.first.Length()); Write(inner.first.c_str(), sizeof(char) * inner.first.Length());
@ -54,15 +55,31 @@ public:
} }
// Write the divider between categories. // Write the divider between categories.
Write("\1", sizeof(char)); Write("\1", sizeof(char));
categoryArr[0] = (ScriptCategory)-2;
Write(categoryArr, sizeof(i16));
for (const auto& inner : evolutionTypes) {
// Write the script name
Write(inner.first.c_str(), sizeof(char) * inner.first.Length());
// Write the divider
Write("\2", sizeof(char));
// Write the declaration of the script
auto decl = inner.second->GetName();
Write(decl, sizeof(char) * strlen(decl));
// Write another divider.
Write("\2", sizeof(char));
}
// Write the divider between categories.
Write("\1", sizeof(char));
} }
virtual ArbUt::Dictionary<ScriptCategory, ArbUt::Dictionary<ArbUt::StringView, uint32_t>> ReadTypes() { virtual ArbUt::Dictionary<i16, ArbUt::Dictionary<ArbUt::StringView, uint32_t>> ReadTypes() {
_angelScriptBound = SIZE_MAX; _angelScriptBound = SIZE_MAX;
ArbUt::Dictionary<ScriptCategory, ArbUt::Dictionary<ArbUt::StringView, uint32_t>> types; ArbUt::Dictionary<i16, ArbUt::Dictionary<ArbUt::StringView, uint32_t>> types;
ScriptCategory categoryArr[1]; i16 categoryArr[1];
while (true) { while (true) {
// Every inner database starts with the category, of known size. Read that. // Every inner database starts with the category, of known size. Read that.
auto read = Read(categoryArr, sizeof(ScriptCategory)); auto read = Read(categoryArr, sizeof(i16));
// If we haven't read anything, we are finished. // If we haven't read anything, we are finished.
if (read == 0) { if (read == 0) {
break; break;

View File

@ -70,4 +70,11 @@ shared abstract class ItemUseScript {
} }
)"); )");
Ensure(r >= 0); Ensure(r >= 0);
r = engine->GetModuleByIndex(0)->AddScriptSection("EvolutionScript", R"(
shared abstract class EvolutionScript {
void DoesEvolveFromLevelUp(bool& out, const EvolutionData@ evoData, const Pokemon@ pokemon) { };
}
)");
Ensure(r >= 0);
} }

View File

@ -8,10 +8,6 @@
#include "../../AngelScriptScript.hpp" #include "../../AngelScriptScript.hpp"
#include "../HelperFile.hpp" #include "../HelperFile.hpp"
// Hack to handle AngelScript not recognizing different sized enums on fields, and returning invalid values due to it.
#define ENUM__SIZE_WRAPPER(name, type, func) \
int32_t name(type* obj) { return static_cast<int32_t>(obj->func()); }
void RegisterPokemonClass::Register(asIScriptEngine* engine) { void RegisterPokemonClass::Register(asIScriptEngine* engine) {
RegisterDamageSource(engine); RegisterDamageSource(engine);
RegisterMoveLearnMethod(engine); RegisterMoveLearnMethod(engine);

View File

@ -4,3 +4,16 @@
static returns* funcName##Wrapper(o* obj) { return obj->funcName().GetValue(); } static returns* funcName##Wrapper(o* obj) { return obj->funcName().GetValue(); }
#define UNIQUE_PTR_GETTER_FUNC(o, returns, funcName) \ #define UNIQUE_PTR_GETTER_FUNC(o, returns, funcName) \
static returns* funcName##Wrapper(o* obj) { return obj->funcName().get(); } static returns* funcName##Wrapper(o* obj) { return obj->funcName().get(); }
#define REGISTER_ENUM(enumName, asName) \
{ \
auto __r = engine->RegisterEnum(asName); \
Ensure(__r >= 0); \
for (auto val : enumName##Helper::GetValues()) { \
__r = engine->RegisterEnumValue(asName, enumName##Helper::ToString(val).c_str(), (i32)val); \
Ensure(__r >= 0); \
} \
}
// Hack to handle AngelScript not recognizing different sized enums on fields, and returning invalid values due to it.
#define ENUM__SIZE_WRAPPER(name, type, func) \
int32_t name(type* obj) { return static_cast<int32_t>(obj->func()); }

View File

@ -1,6 +1,7 @@
#include "RegisterMoveTypes.hpp" #include "RegisterMoveTypes.hpp"
#include "../../../../Library/Moves/MoveData.hpp" #include "../../../../Library/Moves/MoveData.hpp"
#include "../../../../Library/Moves/MoveLibrary.hpp" #include "../../../../Library/Moves/MoveLibrary.hpp"
#include "../HelperFile.hpp"
void RegisterMoveTypes::Register(asIScriptEngine* engine) { void RegisterMoveTypes::Register(asIScriptEngine* engine) {
RegisterMoveCategory(engine); RegisterMoveCategory(engine);
@ -9,33 +10,12 @@ void RegisterMoveTypes::Register(asIScriptEngine* engine) {
RegisterMoveLibrary(engine); RegisterMoveLibrary(engine);
} }
#define REGISTER_ENUM_VALUE(asName, cName, valueName) \
r = engine->RegisterEnumValue(#asName, #valueName, (int)cName::valueName); \
Ensure(r >= 0);
void RegisterMoveTypes::RegisterMoveCategory(asIScriptEngine* engine) { void RegisterMoveTypes::RegisterMoveCategory(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterEnum("MoveCategory"); REGISTER_ENUM(PkmnLib::Library::MoveCategory, "MoveCategory");
Ensure(r >= 0);
REGISTER_ENUM_VALUE(MoveCategory, PkmnLib::Library::MoveCategory, Physical)
REGISTER_ENUM_VALUE(MoveCategory, PkmnLib::Library::MoveCategory, Special)
REGISTER_ENUM_VALUE(MoveCategory, PkmnLib::Library::MoveCategory, Status)
} }
void RegisterMoveTypes::RegisterMoveTarget(asIScriptEngine* engine) { void RegisterMoveTypes::RegisterMoveTarget(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterEnum("MoveTarget"); REGISTER_ENUM(CreatureLib::Library::AttackTarget, "MoveTarget");
Ensure(r >= 0);
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, Adjacent)
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, AdjacentAlly)
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, AdjacentAllySelf)
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, AdjacentOpponent)
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, All)
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, AllAdjacent)
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, AllAdjacentOpponent)
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, AllAlly)
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, AllOpponent)
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, Any)
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, RandomOpponent)
REGISTER_ENUM_VALUE(MoveTarget, CreatureLib::Library::AttackTarget, Self)
} }
// Hack to handle AngelScript not recognizing different sized enums on fields, and returning invalid values due to it. // Hack to handle AngelScript not recognizing different sized enums on fields, and returning invalid values due to it.

View File

@ -9,35 +9,36 @@ void RegisterSpeciesTypes::Register(asIScriptEngine* engine) {
RegisterStatisticEnum(engine); RegisterStatisticEnum(engine);
RegisterFormeType(engine); RegisterFormeType(engine);
RegisterSpeciesType(engine); RegisterSpeciesType(engine);
RegisterEvolutionData(engine);
RegisterSpeciesLibrary(engine); RegisterSpeciesLibrary(engine);
} }
void RegisterSpeciesTypes::RegisterGenderEnum(asIScriptEngine* engine) { void RegisterSpeciesTypes::RegisterGenderEnum(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterEnum("Gender"); int r = engine->RegisterEnum("Gender");
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterEnumValue("Gender", "Male", (int)CreatureLib::Library::Gender::Male); r = engine->RegisterEnumValue("Gender", "Male", (int)CreatureLib::Library::Gender::Male);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterEnumValue("Gender", "Female", (int)CreatureLib::Library::Gender::Female); r = engine->RegisterEnumValue("Gender", "Female", (int)CreatureLib::Library::Gender::Female);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterEnumValue("Gender", "Genderless", (int)CreatureLib::Library::Gender::Genderless); r = engine->RegisterEnumValue("Gender", "Genderless", (int)CreatureLib::Library::Gender::Genderless);
assert(r >= 0); Ensure(r >= 0);
} }
void RegisterSpeciesTypes::RegisterStatisticEnum(asIScriptEngine* engine) { void RegisterSpeciesTypes::RegisterStatisticEnum(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterEnum("Statistic"); int r = engine->RegisterEnum("Statistic");
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterEnumValue("Statistic", "HP", (int)PkmnLib::Library::Statistic::HealthPoints); r = engine->RegisterEnumValue("Statistic", "HP", (int)PkmnLib::Library::Statistic::HealthPoints);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterEnumValue("Statistic", "Attack", (int)PkmnLib::Library::Statistic::PhysicalAttack); r = engine->RegisterEnumValue("Statistic", "Attack", (int)PkmnLib::Library::Statistic::PhysicalAttack);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterEnumValue("Statistic", "Defense", (int)PkmnLib::Library::Statistic::PhysicalDefense); r = engine->RegisterEnumValue("Statistic", "Defense", (int)PkmnLib::Library::Statistic::PhysicalDefense);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterEnumValue("Statistic", "SpecialAttack", (int)PkmnLib::Library::Statistic::SpecialAttack); r = engine->RegisterEnumValue("Statistic", "SpecialAttack", (int)PkmnLib::Library::Statistic::SpecialAttack);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterEnumValue("Statistic", "SpecialDefense", (int)PkmnLib::Library::Statistic::SpecialDefense); r = engine->RegisterEnumValue("Statistic", "SpecialDefense", (int)PkmnLib::Library::Statistic::SpecialDefense);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterEnumValue("Statistic", "Speed", (int)PkmnLib::Library::Statistic::Speed); r = engine->RegisterEnumValue("Statistic", "Speed", (int)PkmnLib::Library::Statistic::Speed);
assert(r >= 0); Ensure(r >= 0);
} }
static const PkmnLib::Library::PokemonForme* GetFormeWrapper(const std::string& s, static const PkmnLib::Library::PokemonForme* GetFormeWrapper(const std::string& s,
@ -49,29 +50,29 @@ static const PkmnLib::Library::PokemonForme* GetFormeWrapper(const std::string&
BORROWED_PTR_GETTER_FUNC(PkmnLib::Library::PokemonSpecies, const PkmnLib::Library::PokemonForme, GetDefaultForme); BORROWED_PTR_GETTER_FUNC(PkmnLib::Library::PokemonSpecies, const PkmnLib::Library::PokemonForme, GetDefaultForme);
void RegisterSpeciesTypes::RegisterSpeciesType(asIScriptEngine* engine) { void RegisterSpeciesTypes::RegisterSpeciesType(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterObjectType("Species", 0, asOBJ_REF | asOBJ_NOCOUNT); int r = engine->RegisterObjectType("Species", 0, asOBJ_REF | asOBJ_NOCOUNT);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Species", "const constString& get_Name() const property", r = engine->RegisterObjectMethod("Species", "const constString& get_Name() const property",
asMETHOD(PkmnLib::Library::PokemonSpecies, GetName), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonSpecies, GetName), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Species", "uint16 get_Id() const property", r = engine->RegisterObjectMethod("Species", "uint16 get_Id() const property",
asMETHOD(PkmnLib::Library::PokemonSpecies, GetId), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonSpecies, GetId), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Species", "float get_GenderRate() const property", r = engine->RegisterObjectMethod("Species", "float get_GenderRate() const property",
asMETHOD(PkmnLib::Library::PokemonSpecies, GetGenderRate), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonSpecies, GetGenderRate), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Species", "uint8 get_CaptureRate() const property", r = engine->RegisterObjectMethod("Species", "uint8 get_CaptureRate() const property",
asMETHOD(PkmnLib::Library::PokemonSpecies, GetCaptureRate), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonSpecies, GetCaptureRate), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Species", "Gender GetRandomGender() const", r = engine->RegisterObjectMethod("Species", "Gender GetRandomGender() const",
asMETHOD(PkmnLib::Library::PokemonSpecies, GetRandomGender), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonSpecies, GetRandomGender), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Species", "const Forme@ GetForme(string key) const", asFUNCTION(GetFormeWrapper), r = engine->RegisterObjectMethod("Species", "const Forme@ GetForme(string key) const", asFUNCTION(GetFormeWrapper),
asCALL_CDECL_OBJLAST); asCALL_CDECL_OBJLAST);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Species", "const Forme@ get_DefaultForme() const property", r = engine->RegisterObjectMethod("Species", "const Forme@ get_DefaultForme() const property",
asFUNCTION(GetDefaultFormeWrapper), asCALL_CDECL_OBJLAST); asFUNCTION(GetDefaultFormeWrapper), asCALL_CDECL_OBJLAST);
assert(r >= 0); Ensure(r >= 0);
} }
const ArbUt::StringView& GetAbility(PkmnLib::Library::PokemonForme* p, bool hidden, uint8_t index) { const ArbUt::StringView& GetAbility(PkmnLib::Library::PokemonForme* p, bool hidden, uint8_t index) {
@ -79,40 +80,60 @@ const ArbUt::StringView& GetAbility(PkmnLib::Library::PokemonForme* p, bool hidd
} }
void RegisterSpeciesTypes::RegisterFormeType(asIScriptEngine* engine) { void RegisterSpeciesTypes::RegisterFormeType(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterObjectType("Forme", 0, asOBJ_REF | asOBJ_NOCOUNT); int r = engine->RegisterObjectType("Forme", 0, asOBJ_REF | asOBJ_NOCOUNT);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Forme", "const constString& get_Name() const property", r = engine->RegisterObjectMethod("Forme", "const constString& get_Name() const property",
asMETHOD(PkmnLib::Library::PokemonForme, GetName), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonForme, GetName), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Forme", "float get_Weight() const property", r = engine->RegisterObjectMethod("Forme", "float get_Weight() const property",
asMETHOD(PkmnLib::Library::PokemonForme, GetWeight), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonForme, GetWeight), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Forme", "float get_Height() const property", r = engine->RegisterObjectMethod("Forme", "float get_Height() const property",
asMETHOD(PkmnLib::Library::PokemonForme, GetHeight), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonForme, GetHeight), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Forme", "uint get_BaseExperience() const property", r = engine->RegisterObjectMethod("Forme", "uint get_BaseExperience() const property",
asMETHOD(PkmnLib::Library::PokemonForme, GetBaseExperience), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonForme, GetBaseExperience), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Forme", "int get_TypeCount() const property", r = engine->RegisterObjectMethod("Forme", "int get_TypeCount() const property",
asMETHOD(PkmnLib::Library::PokemonForme, GetTypeCount), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonForme, GetTypeCount), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Forme", "uint8 GetType(int index) const", r = engine->RegisterObjectMethod("Forme", "uint8 GetType(int index) const",
asMETHOD(PkmnLib::Library::PokemonForme, GetType), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonForme, GetType), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Forme", "uint GetStatistic(Statistic stat) const", r = engine->RegisterObjectMethod("Forme", "uint GetStatistic(Statistic stat) const",
asMETHOD(PkmnLib::Library::PokemonForme, GetStatistic), asCALL_THISCALL); asMETHOD(PkmnLib::Library::PokemonForme, GetStatistic), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("Forme", "const constString& GetAbility(bool hidden, uint8 index) const", r = engine->RegisterObjectMethod("Forme", "const constString& GetAbility(bool hidden, uint8 index) const",
asFUNCTIONPR(GetAbility, asFUNCTIONPR(GetAbility,
(PkmnLib::Library::PokemonForme * p, bool hidden, uint8_t index), (PkmnLib::Library::PokemonForme * p, bool hidden, uint8_t index),
const ArbUt::StringView&), const ArbUt::StringView&),
asCALL_CDECL_OBJFIRST); asCALL_CDECL_OBJFIRST);
assert(r >= 0); Ensure(r >= 0);
} }
ENUM__SIZE_WRAPPER(EvolutionData_GetMethodWrapper, PkmnLib::Library::EvolutionData, GetMethod);
void RegisterSpeciesTypes::RegisterEvolutionData(asIScriptEngine* engine) {
int r = engine->RegisterObjectType("EvolutionData", 0, asOBJ_REF | asOBJ_NOCOUNT);
Ensure(r >= 0);
r = engine->RegisterObjectMethod("EvolutionData", "const Species& get_NewSpecies() const property",
asMETHOD(PkmnLib::Library::EvolutionData, GetNewSpecies), asCALL_THISCALL);
Ensure(r >= 0);
REGISTER_ENUM(PkmnLib::Library::EvolutionMethod, "EvolutionMethod");
r = engine->RegisterObjectMethod("EvolutionData", "EvolutionMethod get_Method() const property",
asFUNCTION(EvolutionData_GetMethodWrapper), asCALL_CDECL_OBJLAST);
Ensure(r >= 0);
r = engine->RegisterObjectMethod("EvolutionData", "uint64 get_DataCount() const property",
asMETHOD(PkmnLib::Library::EvolutionData, GetDataCount), asCALL_THISCALL);
Ensure(r >= 0);
r = engine->RegisterObjectMethod("EvolutionData", "EffectParameter@ GetData(uint64 index) const",
asMETHOD(PkmnLib::Library::EvolutionData, GetData), asCALL_THISCALL);
Ensure(r >= 0);
}
void RegisterSpeciesTypes::RegisterSpeciesLibrary(asIScriptEngine* engine) { void RegisterSpeciesTypes::RegisterSpeciesLibrary(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterObjectType("SpeciesLibrary", 0, asOBJ_REF | asOBJ_NOCOUNT); int r = engine->RegisterObjectType("SpeciesLibrary", 0, asOBJ_REF | asOBJ_NOCOUNT);
assert(r >= 0); Ensure(r >= 0);
r = engine->RegisterObjectMethod("SpeciesLibrary", "const Species@ Get(const constString &in name) const", r = engine->RegisterObjectMethod("SpeciesLibrary", "const Species@ Get(const constString &in name) const",
asMETHOD(PkmnLib::Library::SpeciesLibrary, Get), asCALL_THISCALL); asMETHOD(PkmnLib::Library::SpeciesLibrary, Get), asCALL_THISCALL);
assert(r >= 0); Ensure(r >= 0);
} }

View File

@ -12,6 +12,7 @@ private:
static void RegisterStatisticEnum(asIScriptEngine* engine); static void RegisterStatisticEnum(asIScriptEngine* engine);
static void RegisterSpeciesType(asIScriptEngine* engine); static void RegisterSpeciesType(asIScriptEngine* engine);
static void RegisterFormeType(asIScriptEngine* engine); static void RegisterFormeType(asIScriptEngine* engine);
static void RegisterEvolutionData(asIScriptEngine* engine);
static void RegisterSpeciesLibrary(asIScriptEngine* engine); static void RegisterSpeciesLibrary(asIScriptEngine* engine);
}; };