Initial support for item use scripts in angelscript.
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2021-03-07 17:09:30 +01:00
parent 18cebe842a
commit 27dd8a8202
17 changed files with 405 additions and 97 deletions

View File

@@ -127,7 +127,7 @@ void AngelScriptResolver::MessageCallback(const asSMessageInfo* msg, void*) {
}
CreatureLib::Battling::BattleScript* AngelScriptResolver::LoadScript(ScriptCategory category,
const ArbUt::StringView& scriptName) {
const ArbUt::StringView& scriptName) {
ArbUt::Dictionary<ArbUt::StringView, AngelScriptTypeInfo*> innerDb;
auto v = _typeDatabase.TryGet(category);
if (!v.has_value()) {
@@ -150,6 +150,36 @@ CreatureLib::Battling::BattleScript* AngelScriptResolver::LoadScript(ScriptCateg
_contextPool->ReturnContextToPool(ctx);
return new AngelScriptScript(this, t.value(), obj, _contextPool);
}
CreatureLib::Battling::ItemUseScript* AngelScriptResolver::LoadItemScript(const CreatureLib::Library::Item* item) {
auto v = this->_itemUseScripts.TryGet(item);
if (v.has_value()) {
return v.value();
}
if (!item->GetEffect().HasValue()) {
return nullptr;
}
auto typeInfoOption = _itemUseTypes.TryGet(item->GetEffect().GetValue()->GetEffectName());
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 AngelScriptItemUseScript(obj, this);
_itemUseScripts.Insert(item, scriptObject);
_contextPool->ReturnContextToPool(ctx);
return scriptObject;
}
void AngelScriptResolver::FinalizeModule() {
int r = _builder.BuildModule();
if (r < 0)
@@ -159,62 +189,85 @@ void AngelScriptResolver::FinalizeModule() {
std::regex variableMatcher(R"(\s*(\w+)=(\w+))", std::regex_constants::icase);
std::smatch base_match;
auto pkmnScriptType = _mainModule->GetTypeInfoByName("PkmnScript");
auto itemUseScriptType = _mainModule->GetTypeInfoByName("ItemUseScript");
for (asUINT n = 0; n < count; n++) {
auto typeInfo = _mainModule->GetObjectTypeByIndex(n);
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());
if (typeInfo->DerivesFrom(pkmnScriptType)) {
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());
}
}
RegisterScriptType(typeInfo, metadataKind, effectName);
}
if (effectName.IsEmpty()) {
continue;
}
switch (metadataKind) {
case "Move"_cnc:
_typeDatabase[ScriptCategory::Attack].Insert(effectName,
new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Pokemon"_cnc:
_typeDatabase[ScriptCategory::Creature].Insert(effectName,
new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Ability"_cnc:
_typeDatabase[ScriptCategory::Talent].Insert(effectName,
new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Status"_cnc:
_typeDatabase[ScriptCategory::Status].Insert(effectName,
new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Battle"_cnc:
_typeDatabase[ScriptCategory::Battle].Insert(effectName,
new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Side"_cnc:
_typeDatabase[ScriptCategory::Side].Insert(effectName,
new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Weather"_cnc:
_typeDatabase[static_cast<ScriptCategory>(PkmnScriptCategory::Weather)].Insert(
effectName, new AngelScriptTypeInfo(effectName, typeInfo));
break;
}
} else if (typeInfo->DerivesFrom(itemUseScriptType)) {
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());
}
}
_itemUseTypes.Insert(effectName, typeInfo);
}
}
}
}
}
void AngelScriptResolver::RegisterScriptType(asITypeInfo* typeInfo, const ArbUt::StringView& metadataKind,
const ArbUt::StringView& effectName) {
if (effectName.IsEmpty()) {
return;
}
switch (metadataKind) {
case "Move"_cnc:
_typeDatabase[ScriptCategory::Attack].Insert(effectName, new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Pokemon"_cnc:
_typeDatabase[ScriptCategory::Creature].Insert(effectName, new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Ability"_cnc:
_typeDatabase[ScriptCategory::Talent].Insert(effectName, new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Status"_cnc:
_typeDatabase[ScriptCategory::Status].Insert(effectName, new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Battle"_cnc:
_typeDatabase[ScriptCategory::Battle].Insert(effectName, new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Side"_cnc:
_typeDatabase[ScriptCategory::Side].Insert(effectName, new AngelScriptTypeInfo(effectName, typeInfo));
break;
case "Weather"_cnc:
_typeDatabase[static_cast<ScriptCategory>(PkmnScriptCategory::Weather)].Insert(
effectName, new AngelScriptTypeInfo(effectName, typeInfo));
break;
}
}
void AngelScriptResolver::CreateScript(const char* name, const char* script) {
_builder.AddSectionFromMemory(name, script);
}
@@ -325,4 +378,4 @@ void AngelScriptResolver::InitializeByteCode(
typeDatabase.Set(innerDb.first, newInnerDb);
}
_typeDatabase = typeDatabase;
}
}