Register many battle classes in AngelScript.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2020-01-26 15:18:04 +01:00
parent af9fa61245
commit cade351bc2
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
15 changed files with 376 additions and 15 deletions

View File

@ -40,7 +40,7 @@ class PkmnLibConan(ConanFile):
self.options["AngelScript"].link_std_statically = True self.options["AngelScript"].link_std_statically = True
def requirements(self): def requirements(self):
self.requires("CreatureLib/15523a18a556dedf5b27212264a871260608abb6@creaturelib/master") self.requires("CreatureLib/7e0a1ec033f476dba24a7d091df997f31e2ac076@creaturelib/master")
if self.options.script_handler == "angelscript": if self.options.script_handler == "angelscript":
self.requires("AngelScript/2.34@AngelScript/Deukhoofd") self.requires("AngelScript/2.34@AngelScript/Deukhoofd")
else: else:

View File

@ -1,6 +1,11 @@
#include "AngelScripResolver.hpp" #include "AngelScripResolver.hpp"
#define AS_USE_ACCESSORS
#include "../../extern/angelscript_addons/scriptarray/scriptarray.h"
#undef AS_USE_ACCESSORS
#include "../../extern/angelscript_addons/scripthelper/scripthelper.h" #include "../../extern/angelscript_addons/scripthelper/scripthelper.h"
#include "../../extern/angelscript_addons/scriptstdstring/scriptstdstring.h" #include "../../extern/angelscript_addons/scriptstdstring/scriptstdstring.h"
#include "TypeRegistry/Battling/RegisterExecutingAttack.hpp"
#include "TypeRegistry/Battling/RegisterPokemonClass.hpp"
#include "TypeRegistry/Library/RegisterGrowthRateTypes.hpp" #include "TypeRegistry/Library/RegisterGrowthRateTypes.hpp"
#include "TypeRegistry/Library/RegisterItemTypes.hpp" #include "TypeRegistry/Library/RegisterItemTypes.hpp"
#include "TypeRegistry/Library/RegisterMoveTypes.hpp" #include "TypeRegistry/Library/RegisterMoveTypes.hpp"
@ -15,23 +20,35 @@ CreatureLib::Battling::ScriptResolver* PkmnLib::Battling::BattleLibrary::CreateS
void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* library) { void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* library) {
_engine = asCreateScriptEngine(); _engine = asCreateScriptEngine();
int32_t r = _engine->SetMessageCallback(asFUNCTION(MessageCallback), nullptr, asCALL_CDECL);
if (r < 0)
throw CreatureException("Registering message callback failed.");
_engine->SetEngineProperty(asEP_DISALLOW_EMPTY_LIST_ELEMENTS, true); _engine->SetEngineProperty(asEP_DISALLOW_EMPTY_LIST_ELEMENTS, true);
_engine->SetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE, true); _engine->SetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE, true);
_engine->SetEngineProperty(asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT, true); _engine->SetEngineProperty(asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT, true);
_engine->SetEngineProperty(asEP_AUTO_GARBAGE_COLLECT, false); _engine->SetEngineProperty(asEP_AUTO_GARBAGE_COLLECT, false);
_engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, true); _engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, true);
int32_t r = _engine->SetMessageCallback(asFUNCTION(MessageCallback), nullptr, asCALL_CDECL);
if (r < 0)
throw CreatureException("Registering message callback failed.");
RegisterStdString(_engine); RegisterStdString(_engine);
// Register Script Array type
RegisterScriptArray(_engine, true);
r = _engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(Print), asCALL_CDECL); r = _engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(Print), asCALL_CDECL);
if (r < 0) if (r < 0)
throw CreatureException("Registering print function failed."); throw CreatureException("Registering print function failed.");
RegisterTypes();
RegisterExceptionRoutines(_engine); RegisterExceptionRoutines(_engine);
_mainModule = _engine->GetModule("pkmn", asGM_ALWAYS_CREATE);
_contextPool = new ContextPool(_engine);
}
void AngelScripResolver::RegisterTypes() {
// Register static library types
RegisterSpeciesTypes::Register(_engine); RegisterSpeciesTypes::Register(_engine);
RegisterItemTypes::Register(_engine); RegisterItemTypes::Register(_engine);
RegisterMoveTypes::Register(_engine); RegisterMoveTypes::Register(_engine);
@ -39,10 +56,11 @@ void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* librar
RegisterTypeLibrary::Register(_engine); RegisterTypeLibrary::Register(_engine);
RegisterStaticLibraryTypes::Register(_engine); RegisterStaticLibraryTypes::Register(_engine);
_mainModule = _engine->GetModule("pkmn", asGM_ALWAYS_CREATE); // Register battle types
RegisterPokemonClass::Register(_engine);
_contextPool = new ContextPool(_engine); RegisterExecutingAttack::Register(_engine);
} }
AngelScriptTypeInfo* AngelScripResolver::GetTypeInfo(const std::string& name) { AngelScriptTypeInfo* AngelScripResolver::GetTypeInfo(const std::string& name) {
auto find = _types.find(name); auto find = _types.find(name);
if (find != _types.end()) { if (find != _types.end()) {

View File

@ -22,6 +22,8 @@ private:
static void Print(const std::string& str) { std::cout << str << std::endl; } static void Print(const std::string& str) { std::cout << str << std::endl; }
AngelScriptTypeInfo* GetTypeInfo(const std::string& name); AngelScriptTypeInfo* GetTypeInfo(const std::string& name);
void RegisterTypes();
public: public:
~AngelScripResolver() override { ~AngelScripResolver() override {
delete _contextPool; delete _contextPool;

View File

@ -0,0 +1,14 @@
#include "RegisterBattleLibrary.hpp"
#include <cassert>
#include "../../../Battling/Library/DamageLibrary.hpp"
void RegisterBattleLibrary::Register(asIScriptEngine* engine) {
RegisterDamageLibrary(engine);
}
void RegisterBattleLibrary::RegisterDamageLibrary(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterObjectType("DamageLibrary", 0, asOBJ_REF | asOBJ_NOCOUNT);
assert(r >= 0);
r = engine->RegisterObjectMethod("DamageLibrary", "int GetDamage() const",
asMETHOD(PkmnLib::Battling::DamageLibrary, GetDamage), asCALL_THISCALL);
assert(r >= 0);
}

View File

@ -0,0 +1,11 @@
#ifndef PKMNLIB_REGISTERBATTLELIBRARY_HPP
#define PKMNLIB_REGISTERBATTLELIBRARY_HPP
#include <angelscript.h>
class RegisterBattleLibrary {
static void RegisterDamageLibrary(asIScriptEngine* engine);
public:
static void Register(asIScriptEngine* engine);
};
#endif // PKMNLIB_REGISTERBATTLELIBRARY_HPP

View File

@ -0,0 +1,71 @@
#include "RegisterExecutingAttack.hpp"
#include <Battling/Models/ExecutingAttack.hpp>
#include <cassert>
void RegisterExecutingAttack::Register(asIScriptEngine* engine) {
RegisterHitData(engine);
RegisterTargetData(engine);
RegisterExecutingAttackType(engine);
}
void RegisterExecutingAttack::RegisterHitData(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterObjectType("HitData", 0, asOBJ_REF | asOBJ_NOCOUNT);
assert(r >= 0);
r = engine->RegisterObjectMethod("HitData", "bool get_IsCritical() const property",
asMETHOD(CreatureLib::Battling::ExecutingAttack::HitData, IsCritical),
asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("HitData", "uint8 get_BasePower() const property",
asMETHOD(CreatureLib::Battling::ExecutingAttack::HitData, GetBasePower),
asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("HitData", "float get_Effectiveness() const property",
asMETHOD(CreatureLib::Battling::ExecutingAttack::HitData, GetEffectiveness),
asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("HitData", "float get_Damage() const property",
asMETHOD(CreatureLib::Battling::ExecutingAttack::HitData, GetDamage),
asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("HitData", "uint8 get_Type() const property",
asMETHOD(CreatureLib::Battling::ExecutingAttack::HitData, GetType),
asCALL_THISCALL);
assert(r >= 0);
}
void RegisterExecutingAttack::RegisterTargetData(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterObjectType("TargetData", 0, asOBJ_REF | asOBJ_NOCOUNT);
assert(r >= 0);
r = engine->RegisterObjectMethod("TargetData", "uint8 get_NumberOfHits() const property",
asMETHOD(CreatureLib::Battling::ExecutingAttack::TargetData, GetNumberOfHits),
asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("TargetData", "bool get_IsHit() const property",
asMETHOD(CreatureLib::Battling::ExecutingAttack::TargetData, IsHit),
asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("TargetData", "HitData@ GetHit(uint8 index) const",
asMETHOD(CreatureLib::Battling::ExecutingAttack::TargetData, GetHit),
asCALL_THISCALL);
assert(r >= 0);
}
void RegisterExecutingAttack::RegisterExecutingAttackType(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterObjectType("ExecutingMove", 0, asOBJ_REF | asOBJ_NOCOUNT);
assert(r >= 0);
r = engine->RegisterObjectMethod("ExecutingMove", "TargetData& GetAttackDataForTarget(Pokemon@ pkmn) const",
asMETHOD(CreatureLib::Battling::ExecutingAttack, GetAttackDataForTarget),
asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("ExecutingMove", "bool IsPokemonTarget(Pokemon@ pkmn) const",
asMETHOD(CreatureLib::Battling::ExecutingAttack, IsCreatureTarget),
asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("ExecutingMove", "Pokemon@ get_User() const property",
asMETHOD(CreatureLib::Battling::ExecutingAttack, GetUser),
asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("ExecutingMove", "LearnedMove@ get_Move() const property",
asMETHOD(CreatureLib::Battling::ExecutingAttack, GetAttack),
asCALL_THISCALL);
assert(r >= 0);
}

View File

@ -0,0 +1,14 @@
#ifndef PKMNLIB_REGISTEREXECUTINGATTACK_HPP
#define PKMNLIB_REGISTEREXECUTINGATTACK_HPP
#include <angelscript.h>
class RegisterExecutingAttack {
static void RegisterHitData(asIScriptEngine* engine);
static void RegisterTargetData(asIScriptEngine* engine);
static void RegisterExecutingAttackType(asIScriptEngine* engine);
public:
static void Register(asIScriptEngine* engine);
};
#endif // PKMNLIB_REGISTEREXECUTINGATTACK_HPP

View File

@ -0,0 +1,124 @@
#include "RegisterPokemonClass.hpp"
#include <Battling/Models/LearnedAttack.hpp>
#include <cassert>
#include "../../../Battling/Pokemon/Pokemon.hpp"
// Hack to handle AngelScript not recognizing different sized enums on fields, and returning invalid values due to it.
#define ENUM__SIZE_WRAPPER(name, type, func) \
int32_t name(type* obj) { return static_cast<int32_t>(obj->func()); }
void RegisterPokemonClass::Register(asIScriptEngine* engine) {
RegisterDamageSource(engine);
RegisterMoveLearnMethod(engine);
RegisterLearnedAttack(engine);
RegisterPokemonType(engine);
}
void RegisterPokemonClass::RegisterDamageSource(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterEnum("DamageSource");
assert(r >= 0);
r = engine->RegisterEnumValue("DamageSource", "AttackDamage",
(int)CreatureLib::Battling::DamageSource::AttackDamage);
assert(r >= 0);
}
void RegisterPokemonClass::RegisterMoveLearnMethod(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterEnum("MoveLearnMethod");
assert(r >= 0);
r = engine->RegisterEnumValue("MoveLearnMethod", "Unknown", (int)CreatureLib::Battling::AttackLearnMethod::Unknown);
assert(r >= 0);
r = engine->RegisterEnumValue("MoveLearnMethod", "Level", (int)CreatureLib::Battling::AttackLearnMethod::Level);
assert(r >= 0);
}
ENUM__SIZE_WRAPPER(LearnedMove_LearnMethodWrapper, CreatureLib::Battling::LearnedAttack, GetLearnMethod)
void RegisterPokemonClass::RegisterLearnedAttack(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterObjectType("LearnedMove", 0, asOBJ_REF | asOBJ_NOCOUNT);
assert(r >= 0);
r = engine->RegisterObjectMethod("LearnedMove", "const MoveData@ get_MoveData() const property",
asMETHOD(CreatureLib::Battling::LearnedAttack, GetAttack), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("LearnedMove", "uint8 get_MaxUses() const property",
asMETHOD(CreatureLib::Battling::LearnedAttack, GetMaxUses), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("LearnedMove", "uint8 get_RemainingUses() const property",
asMETHOD(CreatureLib::Battling::LearnedAttack, GetRemainingUses), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("LearnedMove", "Gender get_LearnMethod() const property",
asFUNCTION(LearnedMove_LearnMethodWrapper), asCALL_CDECL_OBJLAST);
assert(r >= 0);
}
ENUM__SIZE_WRAPPER(Pkmn_GenderWrapper, PkmnLib::Battling::Pokemon, GetGender)
void RegisterPokemonClass::RegisterPokemonType(asIScriptEngine* engine) {
[[maybe_unused]]int r = engine->RegisterObjectType("Pokemon", 0, asOBJ_REF | asOBJ_NOCOUNT);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "const Species@ get_Species() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetSpecies), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "const Forme@ get_Forme() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetForme), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "uint8 get_Level() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetLevel), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "uint32 get_Experience() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetExperience), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "Gender get_Gender() const property", asFUNCTION(Pkmn_GenderWrapper),
asCALL_CDECL_OBJLAST);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "uint8 get_Coloring() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetColoring), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "const Item@ get_HeldItem() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetHeldItem), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "uint32 get_CurrentHealth() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetCurrentHealth), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "const string& get_Nickname() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetNickname), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "const string& get_ActiveAbility() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetActiveTalent), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "bool get_IsFainted() const property",
asMETHOD(PkmnLib::Battling::Pokemon, IsFainted), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "uint8[]@ GetTypes() const",
asMETHOD(PkmnLib::Battling::Pokemon, GetTypes), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "bool HasType(uint8 type) const",
asMETHOD(PkmnLib::Battling::Pokemon, HasType), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "void Damage(uint32 type, DamageSource source)",
asMETHOD(PkmnLib::Battling::Pokemon, Damage), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "void OverrideActiveAbility(const string &in ability)",
asMETHOD(PkmnLib::Battling::Pokemon, OverrideActiveTalent), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "LearnedMove@[]@ get_Moves() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetAttacks), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "const Species@ get_DisplaySpecies() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetDisplaySpecies), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "const Species@ get_DisplayForme() const property",
asMETHOD(PkmnLib::Battling::Pokemon, GetDisplayVariant), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "uint32 GetFlatStat(Statistic stat) const",
asMETHOD(PkmnLib::Battling::Pokemon, GetFlatStat), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "uint32 GetBoostedStat(Statistic stat) const",
asMETHOD(PkmnLib::Battling::Pokemon, GetBoostedStat), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "uint32 GetBaseStat(Statistic stat) const",
asMETHOD(PkmnLib::Battling::Pokemon, GetBaseStat), asCALL_THISCALL);
assert(r >= 0);
r = engine->RegisterObjectMethod("Pokemon", "int8 GetStatBoost(Statistic stat) const",
asMETHOD(PkmnLib::Battling::Pokemon, GetStatBoost), asCALL_THISCALL);
assert(r >= 0);
}

View File

@ -0,0 +1,14 @@
#ifndef PKMNLIB_REGISTERPOKEMONCLASS_HPP
#define PKMNLIB_REGISTERPOKEMONCLASS_HPP
#include <angelscript.h>
class RegisterPokemonClass {
static void RegisterDamageSource(asIScriptEngine* engine);
static void RegisterMoveLearnMethod(asIScriptEngine* engine);
static void RegisterLearnedAttack(asIScriptEngine* engine);
static void RegisterPokemonType(asIScriptEngine* engine);
public:
static void Register(asIScriptEngine* engine);
};
#endif // PKMNLIB_REGISTERPOKEMONCLASS_HPP

View File

@ -3,13 +3,14 @@
#include <Battling/Library/BattleLibrary.hpp> #include <Battling/Library/BattleLibrary.hpp>
#include "../../Library/PokemonLibrary.hpp" #include "../../Library/PokemonLibrary.hpp"
#include "DamageLibrary.hpp"
#include "StatCalculator.hpp" #include "StatCalculator.hpp"
namespace PkmnLib::Battling { namespace PkmnLib::Battling {
class BattleLibrary : public CreatureLib::Battling::BattleLibrary { class BattleLibrary : public CreatureLib::Battling::BattleLibrary {
public: public:
BattleLibrary(Library::PokemonLibrary* staticLib, StatCalculator* statCalculator, BattleLibrary(Library::PokemonLibrary* staticLib, StatCalculator* statCalculator,
CreatureLib::Battling::DamageLibrary* damageLibrary, DamageLibrary* damageLibrary,
CreatureLib::Battling::ExperienceLibrary* experienceLibrary, CreatureLib::Battling::ExperienceLibrary* experienceLibrary,
CreatureLib::Battling::ScriptResolver* scriptResolver, CreatureLib::Battling::ScriptResolver* scriptResolver,
CreatureLib::Battling::MiscLibrary* miscLibrary) CreatureLib::Battling::MiscLibrary* miscLibrary)

View File

@ -0,0 +1,68 @@
#include "DamageLibrary.hpp"
#include "../Pokemon/Pokemon.hpp"
int PkmnLib::Battling::DamageLibrary::GetDamage(CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target, uint8_t hitIndex) const {
auto levelMod = static_cast<float>(2 * attack->GetUser()->GetLevel());
auto hit = attack->GetAttackDataForTarget(target).GetHit(hitIndex);
auto bp = hit->GetBasePower();
auto statMod = GetStatModifier(attack, target, hitIndex);
// HOOK: Modify stat modifier
int damage = static_cast<int>((((levelMod * static_cast<float>(bp) * statMod) / 50) + 2) *
GetDamageModifier(attack, target, hitIndex));
// HOOK: Override damage
return damage;
}
int PkmnLib::Battling::DamageLibrary::GetBasePower(CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target, uint8_t hitIndex) const {
auto bp = attack->GetAttack()->GetAttack()->GetBasePower();
// HOOK: modify base power.
return bp;
}
float PkmnLib::Battling::DamageLibrary::GetStatModifier(CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target,
uint8_t hitIndex) const {
auto user = attack->GetUser();
// HOOK: allow overriding for which users stat we use.
auto hit = attack->GetAttackDataForTarget(target).GetHit(hitIndex);
CreatureLib::Core::Statistic offensiveStat;
CreatureLib::Core::Statistic defensiveStat;
auto learnedMove = dynamic_cast<LearnedMove*>(attack->GetAttack());
auto moveData = learnedMove->GetMoveData();
if (moveData->GetCategory() == Library::MoveCategory::Physical) {
offensiveStat = Library::Statistic::PhysicalAttack;
defensiveStat = Library::Statistic::PhysicalDefense;
} else {
offensiveStat = Library::Statistic::SpecialAttack;
defensiveStat = Library::Statistic::SpecialDefense;
}
auto bypassDefensive = hit->IsCritical() && target->GetStatBoost(defensiveStat) > 0;
// HOOK: allow bypassing defensive stat modifiers.
auto bypassOffensive = hit->IsCritical() && user->GetStatBoost(offensiveStat) < 0;
// HOOK: Allow bypassing offensive stat modifiers.
float offensiveValue;
float defensiveValue;
if (bypassOffensive) {
offensiveValue = user->GetFlatStat(offensiveStat);
} else {
offensiveValue = user->GetBoostedStat(offensiveStat);
}
if (bypassDefensive) {
defensiveValue = target->GetFlatStat(defensiveStat);
} else {
defensiveValue = target->GetBoostedStat(defensiveStat);
}
return offensiveValue / defensiveValue;
}
float PkmnLib::Battling::DamageLibrary::GetDamageModifier(CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target,
uint8_t hitIndex) const {
float mod = 1;
auto hit = attack->GetAttackDataForTarget(target).GetHit(hitIndex);
mod *= hit->GetEffectiveness();
// HOOK: Modify damage modifier.
return mod;
}

View File

@ -0,0 +1,20 @@
#ifndef PKMNLIB_DAMAGELIBRARY_HPP
#define PKMNLIB_DAMAGELIBRARY_HPP
#include <Battling/Library/DamageLibrary.hpp>
namespace PkmnLib::Battling {
class DamageLibrary : public CreatureLib::Battling::DamageLibrary {
public:
int GetDamage(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitIndex) const override;
int GetBasePower(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitIndex) const override;
float GetStatModifier(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitIndex) const override;
float GetDamageModifier(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hitIndex) const override;
};
}
#endif // PKMNLIB_DAMAGELIBRARY_HPP

View File

@ -8,6 +8,8 @@ namespace PkmnLib::Battling {
public: public:
LearnedMove(const Library::MoveData* move, CreatureLib::Battling::AttackLearnMethod learnMethod) LearnedMove(const Library::MoveData* move, CreatureLib::Battling::AttackLearnMethod learnMethod)
: CreatureLib::Battling::LearnedAttack(move, learnMethod) {} : CreatureLib::Battling::LearnedAttack(move, learnMethod) {}
const Library::MoveData* GetMoveData() const { return dynamic_cast<const Library::MoveData*>(GetAttack()); }
}; };
} }

View File

@ -29,10 +29,12 @@ namespace PkmnLib::Battling {
heldItem, nickname, talent, std::move(moves)), heldItem, nickname, talent, std::move(moves)),
_individualValues(individualValues), _effortValues(effortValues), _nature(nature) {} _individualValues(individualValues), _effortValues(effortValues), _nature(nature) {}
const Library::Nature& GetNature() const; const Library::PokemonForme* GetForme() const {
uint8_t GetIndividualValue(CreatureLib::Core::Statistic stat) const { return dynamic_cast<const Library::PokemonForme*>(GetVariant());
return _individualValues.GetStat(stat);
} }
const Library::Nature& GetNature() const;
uint8_t GetIndividualValue(CreatureLib::Core::Statistic stat) const { return _individualValues.GetStat(stat); }
uint8_t GetEffortValue(CreatureLib::Core::Statistic stat) const { return _effortValues.GetStat(stat); } uint8_t GetEffortValue(CreatureLib::Core::Statistic stat) const { return _effortValues.GetStat(stat); }
}; };
} }

View File

@ -23,7 +23,7 @@ public:
auto statCalc = new PkmnLib::Battling::StatCalculator(); auto statCalc = new PkmnLib::Battling::StatCalculator();
auto scriptResolver = PkmnLib::Battling::BattleLibrary::CreateScriptResolver(); auto scriptResolver = PkmnLib::Battling::BattleLibrary::CreateScriptResolver();
auto lib = new PkmnLib::Battling::BattleLibrary( auto lib = new PkmnLib::Battling::BattleLibrary(
BuildStaticLibrary(), statCalc, new CreatureLib::Battling::DamageLibrary(), BuildStaticLibrary(), statCalc, new PkmnLib::Battling::DamageLibrary(),
new CreatureLib::Battling::ExperienceLibrary(), scriptResolver, new CreatureLib::Battling::ExperienceLibrary(), scriptResolver,
new CreatureLib::Battling::MiscLibrary()); new CreatureLib::Battling::MiscLibrary());
scriptResolver->Initialize(lib); scriptResolver->Initialize(lib);