#include "AngelScriptScript.hpp" #include "AngelScriptResolver.hpp" #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().c_str() << "', line " << ctx->GetExceptionLineNumber() \ << ". Message: '" << ctx->GetExceptionString() << "'."; \ if (newContext) { \ _ctxPool->ReturnContextToPool(ctx); \ } else { \ ctx->PopState(); \ } \ throw ArbUt::Exception(err.str()); \ } \ if (newContext) { \ _ctxPool->ReturnContextToPool(ctx); \ } else { \ ctx->PopState(); \ } \ throw ArbUt::Exception("Script didn't finish properly; message " + std::to_string(scriptResult)); \ } \ if (newContext) { \ _ctxPool->ReturnContextToPool(ctx); \ } else { \ ctx->PopState(); \ } CScriptArray* AngelScriptScript::GetEffectParameters(const ArbUt::List& ls) { asITypeInfo* t = _resolver->GetBaseType("array"_cnc); CScriptArray* arr = CScriptArray::Create(t, ls.Count()); for (size_t i = 0; i < ls.Count(); i++) { arr->SetValue(i, (void**)&ls[i]); } return arr; } void AngelScriptScript::OnInitialize(const ArbUt::List& parameters) { CScriptArray* arr = nullptr; CALL_HOOK(OnInitialize, { arr = GetEffectParameters(parameters); ctx->SetArgAddress(0, arr); }) if (arr != nullptr) { arr->Release(); } } void AngelScriptScript::Stack() { CALL_HOOK(Stack, ); } void AngelScriptScript::OnRemove() { CALL_HOOK(OnRemove, ); } void AngelScriptScript::OnBeforeTurn(const CreatureLib::Battling::BaseTurnChoice* choice) { CALL_HOOK(OnBeforeTurn, { ctx->SetArgObject(0, (void*)choice); }) } void AngelScriptScript::ChangeAttack(CreatureLib::Battling::AttackTurnChoice* choice, ArbUt::StringView* outAttack) { CALL_HOOK(ChangeAttack, { ctx->SetArgObject(0, (void*)choice); ctx->SetArgAddress(0, outAttack); }) } void AngelScriptScript::PreventAttack(CreatureLib::Battling::ExecutingAttack* attack, bool* outResult) { CALL_HOOK(PreventAttack, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgAddress(1, outResult); }) } void AngelScriptScript::FailAttack(CreatureLib::Battling::ExecutingAttack* attack, bool* outFailed) { CALL_HOOK(FailAttack, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgAddress(1, outFailed); }) } void AngelScriptScript::StopBeforeAttack(CreatureLib::Battling::ExecutingAttack* attack, bool* outResult) { CALL_HOOK(StopBeforeAttack, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgAddress(1, outResult); }) } void AngelScriptScript::OnBeforeAttack(CreatureLib::Battling::ExecutingAttack* attack) { CALL_HOOK(OnBeforeAttack, { ctx->SetArgObject(0, (void*)attack); }) } void AngelScriptScript::FailIncomingAttack(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, bool* outResult) { CALL_HOOK(FailIncomingAttack, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgAddress(2, outResult); }) } void AngelScriptScript::IsInvulnerable(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, bool* outResult) { CALL_HOOK(IsInvulnerable, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgAddress(2, outResult); }) } void AngelScriptScript::OnAttackMiss(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target) { CALL_HOOK(OnAttackMiss, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); }) } void AngelScriptScript::ChangeAttackType(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitNumber, uint8_t* outType) { CALL_HOOK(ChangeAttackType, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitNumber); ctx->SetArgAddress(3, outType); }) } void AngelScriptScript::ChangeEffectiveness(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitNumber, float* effectiveness) { CALL_HOOK(ChangeEffectiveness, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitNumber); ctx->SetArgAddress(3, effectiveness); }) } void AngelScriptScript::PreventSecondaryEffects(const CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitNumber, bool* outResult) { CALL_HOOK(PreventSecondaryEffects, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitNumber); ctx->SetArgAddress(3, outResult); }) } void AngelScriptScript::OnSecondaryEffect(const CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitNumber) { CALL_HOOK(OnSecondaryEffect, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitNumber); }) } void AngelScriptScript::OnAfterHits(const CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target) { CALL_HOOK(OnAfterHits, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); }) } void AngelScriptScript::PreventSelfSwitch(const CreatureLib::Battling::SwitchTurnChoice* choice, bool* outResult) { CALL_HOOK(PreventSelfSwitch, { ctx->SetArgObject(0, (void*)choice); ctx->SetArgAddress(1, outResult); }) } void AngelScriptScript::ModifyEffectChance(const CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, float* chance) { CALL_HOOK(ModifyEffectChance, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgAddress(2, chance); }) } void AngelScriptScript::ModifyIncomingEffectChance(const CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, float* chance) { CALL_HOOK(ModifyIncomingEffectChance, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgAddress(2, chance); }) } void AngelScriptScript::OverrideBasePower(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitIndex, uint8_t* basePower) { CALL_HOOK(OverrideBasePower, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitIndex); ctx->SetArgAddress(3, basePower); }) } void AngelScriptScript::ChangeDamageStatsUser(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitIndex, CreatureLib::Battling::Creature** statsUser) { CALL_HOOK(ChangeDamageStatsUser, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitIndex); ctx->SetArgAddress(3, statsUser); }) } void AngelScriptScript::BypassDefensiveStat(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitIndex, bool* bypass) { CALL_HOOK(BypassDefensiveStat, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitIndex); ctx->SetArgAddress(3, bypass); }) } void AngelScriptScript::BypassOffensiveStat(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitIndex, bool* bypass) { CALL_HOOK(BypassOffensiveStat, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitIndex); ctx->SetArgAddress(3, bypass); }) } void AngelScriptScript::ModifyStatModifier(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitIndex, float* modifier) { CALL_HOOK(ModifyStatModifier, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitIndex); ctx->SetArgAddress(3, modifier); }) } void AngelScriptScript::ModifyDamageModifier(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitIndex, float* modifier) { CALL_HOOK(ModifyDamageModifier, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitIndex); ctx->SetArgAddress(3, modifier); }) } void AngelScriptScript::OverrideDamage(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitIndex, uint32_t* damage) { CALL_HOOK(OverrideDamage, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitIndex); ctx->SetArgAddress(3, damage); }) } void AngelScriptScript::ModifyCriticalStage(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hit, uint8_t* critStage) { CALL_HOOK(ModifyCriticalStage, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hit); ctx->SetArgAddress(3, critStage); }) } void AngelScriptScript::ModifyExperienceGain(CreatureLib::Battling::Creature* faintedMon, CreatureLib::Battling::Creature* winningMon, uint32_t* experienceGain) { CALL_HOOK(ModifyExperienceGain, { ctx->SetArgObject(0, (void*)faintedMon); ctx->SetArgObject(1, (void*)winningMon); ctx->SetArgAddress(2, experienceGain); }) } void AngelScriptScript::DoesShareExperience(CreatureLib::Battling::Creature* faintedMon, CreatureLib::Battling::Creature* winningMon, bool* shareExperience) { CALL_HOOK(DoesShareExperience, { ctx->SetArgObject(0, (void*)faintedMon); ctx->SetArgObject(1, (void*)winningMon); ctx->SetArgAddress(2, shareExperience); }) } void AngelScriptScript::OverrideCriticalModifier(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hit, float* critModifier) { CALL_HOOK(OverrideCriticalModifier, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hit); ctx->SetArgAddress(3, critModifier); }) } void AngelScriptScript::OverrideSTABModifier(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hit, float* stabModifier) { CALL_HOOK(OverrideSTABModifier, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hit); ctx->SetArgAddress(3, stabModifier); }) }