diff --git a/src/Battling/Library/MiscLibrary.cpp b/src/Battling/Library/MiscLibrary.cpp new file mode 100644 index 0000000..3b397d4 --- /dev/null +++ b/src/Battling/Library/MiscLibrary.cpp @@ -0,0 +1,20 @@ +#include "MiscLibrary.hpp" +#include +#include "../PkmnScriptHook.hpp" + +bool PkmnLib::Battling::MiscLibrary::IsCritical(CreatureLib::Battling::ExecutingAttack* attack, + CreatureLib::Battling::Creature* target, uint8_t hit) const { + uint8_t critStage = 0; + PKMN_HOOK(ModifyCriticalStage, attack, attack, target, hit, &critStage); + auto rand = target->GetBattle()->GetRandom(); + switch (critStage){ + case 0: return rand->Get(24) == 0; + case 1: return rand->Get(8) == 0; + case 2: return rand->Get(2) == 0; + default: return true; + } +} + +bool PkmnLib::Battling::MiscLibrary::CanFlee(CreatureLib::Battling::FleeTurnChoice* switchChoice) const { + return CreatureLib::Battling::MiscLibrary::CanFlee(switchChoice); +} diff --git a/src/Battling/Library/MiscLibrary.hpp b/src/Battling/Library/MiscLibrary.hpp new file mode 100644 index 0000000..7cbd06a --- /dev/null +++ b/src/Battling/Library/MiscLibrary.hpp @@ -0,0 +1,15 @@ +#ifndef PKMNLIB_MISCLIBRARY_HPP +#define PKMNLIB_MISCLIBRARY_HPP + +#include + +namespace PkmnLib::Battling{ + class MiscLibrary : CreatureLib::Battling::MiscLibrary { + ~MiscLibrary() override = default; + bool IsCritical(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target, + uint8_t hit) const override; + bool CanFlee(CreatureLib::Battling::FleeTurnChoice* switchChoice) const override; + }; +} + +#endif // PKMNLIB_MISCLIBRARY_HPP diff --git a/src/Battling/PkmnScript.hpp b/src/Battling/PkmnScript.hpp new file mode 100644 index 0000000..8f3e3b6 --- /dev/null +++ b/src/Battling/PkmnScript.hpp @@ -0,0 +1,16 @@ +#ifndef PKMNLIB_PKMNSCRIPT_HPP +#define PKMNLIB_PKMNSCRIPT_HPP +#include +#include "Pokemon/Pokemon.hpp" + +namespace PkmnLib::Battling{ + class PkmnScript : public CreatureLib::Battling::Script{ + public: + PkmnScript(const std::string& name) : Script(name) {} + + virtual void ModifyCriticalStage(CreatureLib::Battling::ExecutingAttack* attack, + CreatureLib::Battling::Creature* target, uint8_t hit, uint8_t* critStage){}; + }; +} + +#endif // PKMNLIB_PKMNSCRIPT_HPP diff --git a/src/Battling/PkmnScriptHook.hpp b/src/Battling/PkmnScriptHook.hpp new file mode 100644 index 0000000..3e6831d --- /dev/null +++ b/src/Battling/PkmnScriptHook.hpp @@ -0,0 +1,13 @@ +#include "PkmnScript.hpp" + +#define PKMN_HOOK(hookName, source, ...) \ + { \ + auto aggregator = source->GetScriptIterator(); \ + while (aggregator.HasNext()) { \ + auto next = aggregator.GetNext(); \ + if (next == nullptr) \ + continue; \ + auto castNext = dynamic_cast(next); \ + castNext->hookName(__VA_ARGS__); \ + } \ + } diff --git a/src/ScriptResolving/AngelScript/AngelScriptScript.hpp b/src/ScriptResolving/AngelScript/AngelScriptScript.hpp index 397e683..c1314d1 100644 --- a/src/ScriptResolving/AngelScript/AngelScriptScript.hpp +++ b/src/ScriptResolving/AngelScript/AngelScriptScript.hpp @@ -4,10 +4,11 @@ #define ANGELSCRIPT_DLL_LIBRARY_IMPORT #include #include +#include "../../Battling/PkmnScript.hpp" #include "AngelScriptTypeInfo.hpp" #include "ContextPool.hpp" -class AngelScriptScript : public CreatureLib::Battling::Script { +class AngelScriptScript : public PkmnLib::Battling::PkmnScript { private: AngelScriptTypeInfo* _type = nullptr; ContextPool* _ctxPool = nullptr; @@ -16,7 +17,7 @@ private: public: AngelScriptScript(const std::string& name, AngelScriptTypeInfo* type, asIScriptObject* obj, ContextPool* ctxPool) - : CreatureLib::Battling::Script(name), _type(type), _ctxPool(ctxPool), _obj(obj) {} + : PkmnLib::Battling::PkmnScript(name), _type(type), _ctxPool(ctxPool), _obj(obj) {} ~AngelScriptScript() override { _obj->Release(); } @@ -251,6 +252,20 @@ public: 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 diff --git a/src/ScriptResolving/AngelScript/AngelScriptTypeInfo.hpp b/src/ScriptResolving/AngelScript/AngelScriptTypeInfo.hpp index 6eaf1b2..8dfe6b4 100644 --- a/src/ScriptResolving/AngelScript/AngelScriptTypeInfo.hpp +++ b/src/ScriptResolving/AngelScript/AngelScriptTypeInfo.hpp @@ -90,24 +90,29 @@ public: SCRIPT_HOOK_FUNCTION(OnAfterHits, "void OnAfterHits(ExecutingMove@ attack, Pokemon@ target)"); SCRIPT_HOOK_FUNCTION(ModifyEffectChance, "void ModifyEffectChance(ExecutingMove@ attack, Pokemon@ target, float& chance)"); -SCRIPT_HOOK_FUNCTION(ModifyIncomingEffectChance, - "void ModifyIncomingEffectChance(ExecutingMove@ attack, Pokemon@ target, float& chance)"); + SCRIPT_HOOK_FUNCTION(ModifyIncomingEffectChance, + "void ModifyIncomingEffectChance(ExecutingMove@ attack, Pokemon@ target, float& chance)"); -SCRIPT_HOOK_FUNCTION(OverrideBasePower, - "void OverrideBasePower(ExecutingMove@ attack, Pokemon@ target, uint8 hit, uint8& chance)"); -SCRIPT_HOOK_FUNCTION(ChangeDamageStatsUser, - "void ChangeDamageStatsUser(ExecutingMove@ attack, Pokemon@ target, uint8 hit, Pokemon@& user)"); -SCRIPT_HOOK_FUNCTION(BypassDefensiveStat, - "void BypassDefensiveStat(ExecutingMove@ attack, Pokemon@ target, uint8 hit, bool& bypass)"); -SCRIPT_HOOK_FUNCTION(BypassOffensiveStat, - "void BypassOffensiveStat(ExecutingMove@ attack, Pokemon@ target, uint8 hit, bool& bypass)"); -SCRIPT_HOOK_FUNCTION(ModifyStatModifier, - "void ModifyStatModifier(ExecutingMove@ attack, Pokemon@ target, uint8 hit, float& modifier)"); -SCRIPT_HOOK_FUNCTION(ModifyDamageModifier, - "void ModifyDamageModifier(ExecutingMove@ attack, Pokemon@ target, uint8 hit, float& modifier)"); -SCRIPT_HOOK_FUNCTION(OverrideDamage, - "void OverrideDamage(ExecutingMove@ attack, Pokemon@ target, uint8 hit, int& damage)"); + SCRIPT_HOOK_FUNCTION(OverrideBasePower, + "void OverrideBasePower(ExecutingMove@ attack, Pokemon@ target, uint8 hit, uint8& chance)"); + SCRIPT_HOOK_FUNCTION( + ChangeDamageStatsUser, + "void ChangeDamageStatsUser(ExecutingMove@ attack, Pokemon@ target, uint8 hit, Pokemon@& user)"); + SCRIPT_HOOK_FUNCTION(BypassDefensiveStat, + "void BypassDefensiveStat(ExecutingMove@ attack, Pokemon@ target, uint8 hit, bool& bypass)"); + SCRIPT_HOOK_FUNCTION(BypassOffensiveStat, + "void BypassOffensiveStat(ExecutingMove@ attack, Pokemon@ target, uint8 hit, bool& bypass)"); + SCRIPT_HOOK_FUNCTION(ModifyStatModifier, + "void ModifyStatModifier(ExecutingMove@ attack, Pokemon@ target, uint8 hit, float& modifier)"); + SCRIPT_HOOK_FUNCTION( + ModifyDamageModifier, + "void ModifyDamageModifier(ExecutingMove@ attack, Pokemon@ target, uint8 hit, float& modifier)"); + SCRIPT_HOOK_FUNCTION(OverrideDamage, + "void OverrideDamage(ExecutingMove@ attack, Pokemon@ target, uint8 hit, int& damage)"); + SCRIPT_HOOK_FUNCTION( + ModifyCriticalStage, + "void ModifyCriticalStage(ExecutingMove@ attack, Pokemon@ target, uint8 hit, uint8& critStage)"); }; #undef SCRIPT_HOOK_FUNCTION diff --git a/src/ScriptResolving/AngelScript/TypeRegistry/BasicScriptClass.cpp b/src/ScriptResolving/AngelScript/TypeRegistry/BasicScriptClass.cpp index 327743c..a0ff8d5 100644 --- a/src/ScriptResolving/AngelScript/TypeRegistry/BasicScriptClass.cpp +++ b/src/ScriptResolving/AngelScript/TypeRegistry/BasicScriptClass.cpp @@ -6,6 +6,7 @@ void BasicScriptClass::Register(asIScriptEngine* engine) { // registry interface. As such, we just create it from string. [[maybe_unused]] int r = engine->GetModuleByIndex(0)->AddScriptSection("PkmnScript", R"( shared abstract class PkmnScript { +// CreatureLib methods void Stack(){}; void OnRemove(){}; void PreventAttack(ExecutingMove@ attack, bool& result){}; @@ -31,6 +32,9 @@ shared abstract class PkmnScript { void ModifyStatModifier(ExecutingMove@ attack, Pokemon@ target, uint8 hit, float& modifier){}; void ModifyDamageModifier(ExecutingMove@ attack, Pokemon@ target, uint8 hit, float& modifier){}; void OverrideDamage(ExecutingMove@ attack, Pokemon@ target, uint8 hit, int& damage){}; + +// PkmnLib methods + void ModifyCriticalStage(ExecutingMove@ attack, Pokemon@ target, uint8 hit, uint8& critStage){}; } )"); assert(r >= 0);