PkmnLib/src/ScriptResolving/AngelScript/AngelScriptScript.hpp

273 lines
13 KiB
C++

#ifndef PKMNLIB_ANGELSCRIPTSCRIPT_HPP
#define PKMNLIB_ANGELSCRIPTSCRIPT_HPP
#include <CreatureLib/Battling/ScriptHandling/Script.hpp>
#define ANGELSCRIPT_DLL_LIBRARY_IMPORT
#include <CreatureLib/Core/Exceptions/NotImplementedException.hpp>
#include <angelscript.h>
#include "../../Battling/PkmnScript.hpp"
#include "AngelScriptTypeInfo.hpp"
#include "ContextPool.hpp"
class AngelScriptScript : public PkmnLib::Battling::PkmnScript {
private:
AngelScriptTypeInfo* _type = nullptr;
ContextPool* _ctxPool = nullptr;
asIScriptObject* _obj = nullptr;
public:
AngelScriptScript(const std::string& name, AngelScriptTypeInfo* type, asIScriptObject* obj, ContextPool* ctxPool)
: PkmnLib::Battling::PkmnScript(name), _type(type), _ctxPool(ctxPool), _obj(obj) {}
~AngelScriptScript() override { _obj->Release(); }
asIScriptFunction* PrepareMethod(const char* name, asIScriptContext* ctx) {
auto func = _type->GetFunction(name);
ctx->Prepare(func);
ctx->SetObject(_obj);
return func;
}
ContextPool* GetContextPool() { return _ctxPool; }
#define CALL_HOOK(name, setup) \
auto s = _type->Get##name(); \
if (!s.Exists) \
return; \
auto ctx = asGetActiveContext(); \
bool newContext = false; \
if (ctx == nullptr) { \
ctx = _ctxPool->RequestContext(); \
newContext = true; \
} else { \
ctx->PushState(); \
} \
ctx->Prepare(s.Function); \
ctx->SetObject(_obj); \
setup; \
auto scriptResult = ctx->Execute(); \
if (scriptResult != asEXECUTION_FINISHED) { \
if (scriptResult == asEXECUTION_EXCEPTION) { \
std::stringstream err; \
err << "Script exception in script '" << GetName() << "', line " << ctx->GetExceptionLineNumber() \
<< ". Message: '" << ctx->GetExceptionString() << "'."; \
throw CreatureException(err.str()); \
} \
throw CreatureException("Script didn't finish properly; message " + std::to_string(scriptResult)); \
} \
if (newContext) { \
_ctxPool->ReturnContextToPool(ctx); \
} else { \
ctx->PopState(); \
}
void Stack() override { CALL_HOOK(Stack, ); }
void OnRemove() override { CALL_HOOK(OnRemove, ); }
void OnBeforeTurn(const CreatureLib::Battling::BaseTurnChoice* choice) override {
throw NotImplementedException(); // TODO
}
void ChangeAttack(CreatureLib::Battling::AttackTurnChoice* choice, std::string* outAttack) override {
throw NotImplementedException(); // TODO
}
void PreventAttack(CreatureLib::Battling::ExecutingAttack* attack, bool* outResult) override {
CALL_HOOK(PreventAttack, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgAddress(1, outResult);
})
}
void FailAttack(CreatureLib::Battling::ExecutingAttack* attack, bool* outFailed) override {
CALL_HOOK(FailAttack, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgAddress(1, outFailed);
})
}
void StopBeforeAttack(CreatureLib::Battling::ExecutingAttack* attack, bool* outResult) override {
CALL_HOOK(StopBeforeAttack, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgAddress(1, outResult);
})
}
void OnBeforeAttack(CreatureLib::Battling::ExecutingAttack* attack) override {
CALL_HOOK(OnBeforeAttack, { ctx->SetArgObject(0, (void*)attack); })
}
void FailIncomingAttack(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
bool* outResult) override {
CALL_HOOK(FailIncomingAttack, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgAddress(2, outResult);
})
}
void IsInvulnerable(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
bool* outResult) override {
CALL_HOOK(IsInvulnerable, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgAddress(2, outResult);
})
}
void OnAttackMiss(CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target) override {
CALL_HOOK(OnAttackMiss, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
})
}
void ChangeAttackType(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitNumber, uint8_t* outType) override {
CALL_HOOK(ChangeAttackType, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hitNumber);
ctx->SetArgAddress(3, outType);
})
}
void OnStatusMove(const CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitNumber) override {
CALL_HOOK(OnStatusMove, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hitNumber);
})
}
void PreventSecondaryEffects(const CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target, uint8_t hitNumber, bool* outResult) override {
CALL_HOOK(PreventSecondaryEffects, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hitNumber);
ctx->SetArgAddress(3, outResult);
})
}
void OnSecondaryEffect(const CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target, uint8_t hitNumber) override {
CALL_HOOK(OnSecondaryEffect, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hitNumber);
})
}
void OnAfterHits(const CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target) override {
CALL_HOOK(OnAfterHits, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
})
}
void PreventSelfSwitch(const CreatureLib::Battling::SwitchTurnChoice* choice, bool* outResult) override {
throw NotImplementedException(); // TODO
}
void ModifyEffectChance(const CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target, float* chance) override {
CALL_HOOK(ModifyEffectChance, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgAddress(2, chance);
})
}
void ModifyIncomingEffectChance(const CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target, float* chance) override {
CALL_HOOK(ModifyIncomingEffectChance, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgAddress(2, chance);
})
}
void OverrideBasePower(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitIndex, uint8_t* basePower) override {
CALL_HOOK(OverrideBasePower, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hitIndex);
ctx->SetArgAddress(3, basePower);
})
}
void ChangeDamageStatsUser(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitIndex, CreatureLib::Battling::Creature** statsUser) override {
CALL_HOOK(ChangeDamageStatsUser, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hitIndex);
ctx->SetArgAddress(3, statsUser);
})
}
void BypassDefensiveStat(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitIndex, bool* bypass) override {
CALL_HOOK(BypassDefensiveStat, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hitIndex);
ctx->SetArgAddress(3, bypass);
})
}
void BypassOffensiveStat(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitIndex, bool* bypass) override {
CALL_HOOK(BypassOffensiveStat, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hitIndex);
ctx->SetArgAddress(3, bypass);
})
}
void ModifyStatModifier(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitIndex, float* modifier) override {
CALL_HOOK(ModifyStatModifier, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hitIndex);
ctx->SetArgAddress(3, modifier);
})
}
void ModifyDamageModifier(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitIndex, float* modifier) override {
CALL_HOOK(ModifyDamageModifier, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hitIndex);
ctx->SetArgAddress(3, modifier);
})
}
void OverrideDamage(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitIndex, int32_t* damage) override {
CALL_HOOK(OverrideDamage, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hitIndex);
ctx->SetArgAddress(3, damage);
})
}
////////////////////
// PkmnLib methods//
////////////////////
void ModifyCriticalStage(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hit, uint8_t* critStage) override {
CALL_HOOK(ModifyCriticalStage, {
ctx->SetArgObject(0, (void*)attack);
ctx->SetArgObject(1, (void*)target);
ctx->SetArgByte(2, hit);
ctx->SetArgAddress(3, critStage);
})
}
};
#undef CALL_HOOK
#endif // PKMNLIB_ANGELSCRIPTSCRIPT_HPP