#include "AngelScriptScript.hpp" #include "AngelScriptFunctionCall.hpp" #include "AngelScriptResolver.hpp" #define CALL_HOOK(name, setup) \ auto s = _type->Get##name(); \ if (!s.Exists) \ return; \ AngelScriptUtils::AngelscriptFunctionCall( \ s.Function, _ctxPool, _obj, _resolver, GetName(), [&]([[maybe_unused]] asIScriptContext* ctx) { setup }, \ [&]([[maybe_unused]] asIScriptContext* ctx) {}); NativeArray>* AngelScriptScript::GetEffectParameters(const ArbUt::List& ls) { return new NativeArray>(&ls); } AngelScriptScript::AngelScriptScript(const ArbUt::OptionalBorrowedPtr& owner, asITypeInfo* ownerType, AngelScriptResolver* resolver, AngelScriptTypeInfo* type, asIScriptObject* obj, ContextPool* ctxPool) : PkmnLib::Battling::PkmnScript(owner), _resolver(resolver), _type(type), _ctxPool(ctxPool), _obj(obj) { if (_type->GetGetOwner().Exists && owner.HasValue()) { if (ownerType == nullptr) { THROW("Script was created with owner value, but with unknown owner type.") } auto* handle = GetAngelscriptOwner(); handle->Set(owner.GetValue(), ownerType); } } CScriptHandle* AngelScriptScript::GetAngelscriptOwner() { CScriptHandle* handle = nullptr; AngelScriptUtils::AngelscriptFunctionCall( _type->GetGetOwner().Function, _ctxPool, _obj, _resolver, GetName(), [&](asIScriptContext*) {}, [&](asIScriptContext* ctx) { handle = (CScriptHandle*)ctx->GetReturnAddress(); }); return handle; } void AngelScriptScript::OnInitialize(const CreatureLib::Battling::BattleLibrary* library, const ArbUt::List& parameters) { CALL_HOOK(OnInitialize, { auto arr = GetEffectParameters(parameters); ctx->SetArgObject(0, (void*)library); ctx->SetArgAddress(1, arr); }) } 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(1, 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::BlockCritical(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitNumber, bool* blockCritical) { CALL_HOOK(BlockCritical, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitNumber); ctx->SetArgAddress(3, blockCritical); }) } void AngelScriptScript::PreventStatBoostChange(CreatureLib::Battling::Creature* target, CreatureLib::Library::Statistic stat, int8_t diffAmount, bool* prevent) { CALL_HOOK(PreventStatBoostChange, { ctx->SetArgObject(0, (void*)target); ctx->SetArgDWord(1, (i32)stat); ctx->SetArgByte(2, diffAmount); ctx->SetArgAddress(3, prevent); }) } void AngelScriptScript::ModifyStatBoostChange(CreatureLib::Battling::Creature* target, CreatureLib::Library::Statistic stat, int8_t* diffAmount) { CALL_HOOK(ModifyStatBoostChange, { ctx->SetArgObject(0, (void*)target); ctx->SetArgDWord(1, (i32)stat); ctx->SetArgAddress(2, diffAmount); }) } 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::OverrideIncomingDamage(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitIndex, uint32_t* damage) { CALL_HOOK(OverrideIncomingDamage, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitIndex); ctx->SetArgAddress(3, damage); }) } void AngelScriptScript::PreventIncomingCritical(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hit, bool* preventCrit) { CALL_HOOK(PreventIncomingCritical, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hit); ctx->SetArgAddress(3, preventCrit); }) } 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); }) } void AngelScriptScript::ChangePriority(CreatureLib::Battling::AttackTurnChoice* choice, int8_t* priority) { CALL_HOOK(ChangePriority, { ctx->SetArgObject(0, (void*)choice); ctx->SetArgAddress(1, priority); }) } void AngelScriptScript::OnFail(CreatureLib::Battling::Creature* target) { CALL_HOOK(OnFail, { ctx->SetArgObject(0, (void*)target); }) } void AngelScriptScript::OnOpponentFail(CreatureLib::Battling::Creature* target) { CALL_HOOK(OnOpponentFail, { ctx->SetArgObject(0, (void*)target); }) } void AngelScriptScript::PreventRunAway(const CreatureLib::Battling::FleeTurnChoice* choice, bool* result) { CALL_HOOK(PreventRunAway, { ctx->SetArgObject(0, (void*)choice); ctx->SetArgAddress(1, result); }) } void AngelScriptScript::PreventOpponentRunAway(const CreatureLib::Battling::FleeTurnChoice* choice, bool* result) { CALL_HOOK(PreventOpponentRunAway, { ctx->SetArgObject(0, (void*)choice); ctx->SetArgAddress(1, result); }) } void AngelScriptScript::PreventOpponentSwitch(const CreatureLib::Battling::SwitchTurnChoice* choice, bool* outResult) { CALL_HOOK(PreventOpponentSwitch, { ctx->SetArgObject(0, (void*)choice); ctx->SetArgAddress(1, outResult); }) } void AngelScriptScript::OnEndTurn() { CALL_HOOK(OnEndTurn, {}) } void AngelScriptScript::ModifyNumberOfHits(CreatureLib::Battling::AttackTurnChoice* choice, u8* numberOfHits){CALL_HOOK(ModifyNumberOfHits, { ctx->SetArgObject(0, (void*)choice); ctx->SetArgAddress(1, numberOfHits); })} CreatureLib::Battling::BattleScript* AngelScriptScript::Clone(const ArbUt::OptionalBorrowedPtr& owner) { auto* ctx = _ctxPool->RequestContext(); auto* obj = _type->Instantiate(ctx); if (_obj != nullptr) { obj->CopyFrom(_obj); } _ctxPool->ReturnContextToPool(ctx); return new AngelScriptScript(owner, GetAngelscriptOwner()->GetType(), _resolver, _type, obj, _ctxPool); } void AngelScriptScript::OnDamage(CreatureLib::Battling::Creature* creature, CreatureLib::Battling::DamageSource source, [[maybe_unused]] u32 oldHealth, [[maybe_unused]] u32 newHealth) { CALL_HOOK(OnDamage, { ctx->SetArgObject(0, (void*)creature); ctx->SetArgDWord(1, (i32)source); ctx->SetArgDWord(2, oldHealth); ctx->SetArgDWord(3, newHealth); }) } void AngelScriptScript::OnFaint(CreatureLib::Battling::Creature* creature, CreatureLib::Battling::DamageSource source) { CALL_HOOK(OnFaint, { ctx->SetArgObject(0, (void*)creature); ctx->SetArgDWord(1, (i32)source); }) } void AngelScriptScript::BlockWeather(CreatureLib::Battling::Battle* battle, bool* blockWeather) { CALL_HOOK(BlockWeather, { ctx->SetArgObject(0, (void*)battle); ctx->SetArgAddress(1, blockWeather); }) } void AngelScriptScript::OnSwitchIn(CreatureLib::Battling::Creature* creature) { CALL_HOOK(OnSwitchIn, { ctx->SetArgObject(0, (void*)creature); }) } void AngelScriptScript::OnIncomingHit(const CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, uint8_t hitNumber) { CALL_HOOK(OnIncomingHit, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitNumber); }) } void AngelScriptScript::OnFaintingOpponent(const CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, u8 hitNumber) { CALL_HOOK(OnFaintingOpponent, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitNumber); }) } void AngelScriptScript::ModifyOffensiveStatValue(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, u8 hitIndex, float* modifier) { CALL_HOOK(ModifyOffensiveStatValue, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitIndex); ctx->SetArgAddress(3, modifier); }) } void AngelScriptScript::ModifyDefensiveStatValue(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, u8 hitIndex, float* modifier) { CALL_HOOK(ModifyDefensiveStatValue, { ctx->SetArgObject(0, (void*)attack); ctx->SetArgObject(1, (void*)target); ctx->SetArgByte(2, hitIndex); ctx->SetArgAddress(3, modifier); }) } void AngelScriptScript::OnAfterHeldItemConsume(CreatureLib::Battling::Creature* creature, const CreatureLib::Library::Item* item) { CALL_HOOK(OnAfterHeldItemConsume, { ctx->SetArgObject(0, (void*)creature); ctx->SetArgObject(1, (void*)item); }); }