Overhaul memory model to new Arbutils memory.
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
Signed-off-by: Deukhoofd <Deukhoofd@gmail.com>
This commit is contained in:
parent
1dc3aafd33
commit
5c39694f19
|
@ -31,7 +31,7 @@ export uint8_t CreatureLib_Battle_CreatureInField(bool& out, const Battle* p, Cr
|
||||||
Try(out = p->CreatureInField(c);)
|
Try(out = p->CreatureInField(c);)
|
||||||
}
|
}
|
||||||
export uint8_t CreatureLib_Battle_GetCreature(Creature*& out, const Battle* p, uint8_t side, uint8_t target) {
|
export uint8_t CreatureLib_Battle_GetCreature(Creature*& out, const Battle* p, uint8_t side, uint8_t target) {
|
||||||
Try(out = p->GetCreature(side, target).GetRaw();)
|
Try(out = p->GetCreature(side, target).GetValue();)
|
||||||
}
|
}
|
||||||
|
|
||||||
export uint8_t CreatureLib_Battle_ForceRecall(Battle* p, uint8_t side, uint8_t target) {
|
export uint8_t CreatureLib_Battle_ForceRecall(Battle* p, uint8_t side, uint8_t target) {
|
||||||
|
@ -58,7 +58,11 @@ export BattleParty* const* CreatureLib_Battle_GetParties(const Battle* p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export Script* CreatureLib_Battle_GetVolatileScript(Battle* p, const char* key) {
|
export Script* CreatureLib_Battle_GetVolatileScript(Battle* p, const char* key) {
|
||||||
return p->GetVolatileScript(ArbUt::StringView::CalculateHash(key)).GetRaw();
|
auto v = p->GetVolatileScript(ArbUt::StringView::CalculateHash(key));
|
||||||
|
if (!v.has_value()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return v.value();
|
||||||
}
|
}
|
||||||
export uint8_t CreatureLib_Battle_AddVolatileScriptByName(Battle* p, const char* key) {
|
export uint8_t CreatureLib_Battle_AddVolatileScriptByName(Battle* p, const char* key) {
|
||||||
Try(p->AddVolatileScript(ArbUt::StringView(key));)
|
Try(p->AddVolatileScript(ArbUt::StringView(key));)
|
||||||
|
|
|
@ -23,7 +23,7 @@ export uint8_t CreatureLib_BattleSide_SetCreature(BattleSide* p, Creature* creat
|
||||||
}
|
}
|
||||||
|
|
||||||
export uint8_t CreatureLib_BattleSide_GetCreature(Creature*& out, BattleSide* p, uint8_t index) {
|
export uint8_t CreatureLib_BattleSide_GetCreature(Creature*& out, BattleSide* p, uint8_t index) {
|
||||||
Try(out = p->GetCreature(index).GetRaw());
|
Try(out = p->GetCreature(index).GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
export uint8_t CreatureLib_BattleSide_GetSideIndex(BattleSide* p) { return p->GetSideIndex(); }
|
export uint8_t CreatureLib_BattleSide_GetSideIndex(BattleSide* p) { return p->GetSideIndex(); }
|
||||||
|
|
|
@ -51,8 +51,8 @@ export void CreatureLib_Creature_SetHeldItemFromItem(Creature* p, const Creature
|
||||||
return p->SetHeldItem(ArbUt::BorrowedPtr<const CreatureLib::Library::Item>(item));
|
return p->SetHeldItem(ArbUt::BorrowedPtr<const CreatureLib::Library::Item>(item));
|
||||||
}
|
}
|
||||||
SIMPLE_GET_FUNC(Creature, GetCurrentHealth, uint32_t);
|
SIMPLE_GET_FUNC(Creature, GetCurrentHealth, uint32_t);
|
||||||
BORROWED_GET_FUNC(Creature, GetBattle, Battle*);
|
OPTIONAL_GET_FUNC(Creature, GetBattle, Battle*);
|
||||||
BORROWED_GET_FUNC(Creature, GetBattleSide, BattleSide*);
|
OPTIONAL_GET_FUNC(Creature, GetBattleSide, BattleSide*);
|
||||||
SIMPLE_GET_FUNC(Creature, IsOnBattleField, bool);
|
SIMPLE_GET_FUNC(Creature, IsOnBattleField, bool);
|
||||||
export const char* CreatureLib_Creature_GetNickname(Creature* p) { return p->GetNickname().data(); }
|
export const char* CreatureLib_Creature_GetNickname(Creature* p) { return p->GetNickname().data(); }
|
||||||
export bool CreatureLib_Creature_HasType(Creature* p, uint8_t type) { return p->HasType(type); }
|
export bool CreatureLib_Creature_HasType(Creature* p, uint8_t type) { return p->HasType(type); }
|
||||||
|
@ -101,8 +101,8 @@ export LearnedAttack* const* CreatureLib_Creature_GetAttacks(Creature* p) { retu
|
||||||
export bool CreatureLib_Creature_HasAttack(Creature* p, const char* scriptName) {
|
export bool CreatureLib_Creature_HasAttack(Creature* p, const char* scriptName) {
|
||||||
return p->HasAttack(ArbUt::StringView(scriptName));
|
return p->HasAttack(ArbUt::StringView(scriptName));
|
||||||
}
|
}
|
||||||
BORROWED_GET_FUNC(Creature, GetDisplaySpecies, const CreatureLib::Library::CreatureSpecies*);
|
OPTIONAL_GET_FUNC(Creature, GetDisplaySpecies, const CreatureLib::Library::CreatureSpecies*);
|
||||||
BORROWED_GET_FUNC(Creature, GetDisplayVariant, const CreatureLib::Library::SpeciesVariant*);
|
OPTIONAL_GET_FUNC(Creature, GetDisplayVariant, const CreatureLib::Library::SpeciesVariant*);
|
||||||
export void CreatureLib_Creature_SetDisplaySpecies(Creature* p, const CreatureLib::Library::CreatureSpecies* species) {
|
export void CreatureLib_Creature_SetDisplaySpecies(Creature* p, const CreatureLib::Library::CreatureSpecies* species) {
|
||||||
return p->SetDisplaySpecies(ArbUt::BorrowedPtr<const CreatureLib::Library::CreatureSpecies>(species));
|
return p->SetDisplaySpecies(ArbUt::BorrowedPtr<const CreatureLib::Library::CreatureSpecies>(species));
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ export CreatureParty* CreatureLib_CreatureParty_ConstructFromArray(Creature* cre
|
||||||
export void CreatureLib_CreatureParty_Destruct(const CreatureParty* p) { delete p; }
|
export void CreatureLib_CreatureParty_Destruct(const CreatureParty* p) { delete p; }
|
||||||
|
|
||||||
export uint8_t CreatureLib_CreatureParty_GetAtIndex(Creature*& out, const CreatureParty* p, size_t index) {
|
export uint8_t CreatureLib_CreatureParty_GetAtIndex(Creature*& out, const CreatureParty* p, size_t index) {
|
||||||
Try(out = p->GetAtIndex(index).GetRaw();)
|
Try(out = p->GetAtIndex(index).GetValue();)
|
||||||
}
|
}
|
||||||
|
|
||||||
export uint8_t CreatureLib_CreatureParty_Switch(CreatureParty* p, size_t a, size_t b) { Try(p->Switch(a, b);) }
|
export uint8_t CreatureLib_CreatureParty_Switch(CreatureParty* p, size_t a, size_t b) { Try(p->Switch(a, b);) }
|
||||||
|
|
|
@ -5,7 +5,7 @@ using namespace CreatureLib::Battling;
|
||||||
export uint8_t CreatureLib_ExecutingAttack_Construct(ExecutingAttack*& out, Creature* const* targets,
|
export uint8_t CreatureLib_ExecutingAttack_Construct(ExecutingAttack*& out, Creature* const* targets,
|
||||||
size_t targetCount, uint8_t numberHits, Creature* user,
|
size_t targetCount, uint8_t numberHits, Creature* user,
|
||||||
LearnedAttack* attack, Script* script) {
|
LearnedAttack* attack, Script* script) {
|
||||||
Try(auto ls = ArbUt::List<ArbUt::BorrowedPtr<Creature>>(targetCount);
|
Try(auto ls = ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>(targetCount);
|
||||||
for (size_t i = 0; i < targetCount; i++) { ls.Append(targets[i]); } auto s = std::unique_ptr<Script>(script);
|
for (size_t i = 0; i < targetCount; i++) { ls.Append(targets[i]); } auto s = std::unique_ptr<Script>(script);
|
||||||
out = new ExecutingAttack(ls, numberHits, user, attack, s);)
|
out = new ExecutingAttack(ls, numberHits, user, attack, s);)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,11 @@ export const HistoryElement* CreatureLib_HistoryHandler_GetTopElement(const Hist
|
||||||
return p->GetTopElement().GetRaw();
|
return p->GetTopElement().GetRaw();
|
||||||
}
|
}
|
||||||
export const HistoryElement* CreatureLib_HistoryHandler_GetLastUsedAttack(const HistoryHolder* p) {
|
export const HistoryElement* CreatureLib_HistoryHandler_GetLastUsedAttack(const HistoryHolder* p) {
|
||||||
return p->GetLastUsedAttack().GetRaw();
|
auto res = p->GetLastUsedAttack();
|
||||||
|
if (res.has_value()) {
|
||||||
|
return res.value();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
export HistoryElementKind CreatureLib_HistoryElement_GetKind(const HistoryElement* p) { return p->GetKind(); }
|
export HistoryElementKind CreatureLib_HistoryElement_GetKind(const HistoryElement* p) { return p->GetKind(); }
|
||||||
|
|
|
@ -37,4 +37,4 @@ export uint8_t CreatureLib_AttackTurnChoice_GetTargetCreatureIndex(const AttackT
|
||||||
return p->GetTarget().GetCreatureIndex();
|
return p->GetTarget().GetCreatureIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
BORROWED_GET_FUNC(SwitchTurnChoice, GetNewCreature, Creature*)
|
OPTIONAL_GET_FUNC(SwitchTurnChoice, GetNewCreature, Creature*)
|
|
@ -50,6 +50,12 @@ public:
|
||||||
export returnType CreatureLib_##type##_##name(const type* p) { return p->name(); }
|
export returnType CreatureLib_##type##_##name(const type* p) { return p->name(); }
|
||||||
#define BORROWED_GET_FUNC(type, name, returnType) \
|
#define BORROWED_GET_FUNC(type, name, returnType) \
|
||||||
export returnType CreatureLib_##type##_##name(const type* p) { return p->name().GetRaw(); }
|
export returnType CreatureLib_##type##_##name(const type* p) { return p->name().GetRaw(); }
|
||||||
|
#define OPTIONAL_GET_FUNC(type, name, returnType) \
|
||||||
|
export returnType CreatureLib_##type##_##name(const type* p) { \
|
||||||
|
if (p->name().HasValue()) \
|
||||||
|
return p->name().GetValue(); \
|
||||||
|
return nullptr; \
|
||||||
|
}
|
||||||
#define SMART_GET_FUNC(type, name, returnType) \
|
#define SMART_GET_FUNC(type, name, returnType) \
|
||||||
export returnType CreatureLib_##type##_##name(const type* p) { return p->name().get(); }
|
export returnType CreatureLib_##type##_##name(const type* p) { return p->name().get(); }
|
||||||
#define DESTRUCTOR(type) \
|
#define DESTRUCTOR(type) \
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
if (_offset + sizeof(T) >= _capacity) {
|
if (_offset + sizeof(T) >= _capacity) {
|
||||||
_capacity += stepSize;
|
_capacity += stepSize;
|
||||||
auto newPtr = realloc(_memory, _capacity);
|
auto* newPtr = realloc(_memory, _capacity);
|
||||||
if (newPtr == nullptr) {
|
if (newPtr == nullptr) {
|
||||||
THROW("Out of memory.");
|
THROW("Out of memory.");
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ namespace CreatureLib::Battling {
|
||||||
uint8_t* ptr = _memory + _offset;
|
uint8_t* ptr = _memory + _offset;
|
||||||
T* event = new (ptr) T(args...);
|
T* event = new (ptr) T(args...);
|
||||||
_offset += sizeof(T);
|
_offset += sizeof(T);
|
||||||
for (auto listener : _listeners) {
|
for (const auto& listener : _listeners) {
|
||||||
try_creature(listener(event), "Exception in event listener");
|
try_creature(listener(event), "Exception in event listener");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@ namespace CreatureLib::Battling {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ArbUt::List<ArbUt::BorrowedPtr<Creature>> ResolveTargets(const CreatureIndex& index,
|
static ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>
|
||||||
CreatureLib::Library::AttackTarget target,
|
ResolveTargets(const CreatureIndex& index, CreatureLib::Library::AttackTarget target,
|
||||||
const ArbUt::BorrowedPtr<Battle>& battle) {
|
const ArbUt::BorrowedPtr<Battle>& battle) {
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case CreatureLib::Library::AttackTarget::Adjacent: {
|
case CreatureLib::Library::AttackTarget::Adjacent: {
|
||||||
return {battle->GetCreature(index)};
|
return {battle->GetCreature(index)};
|
||||||
|
@ -32,14 +32,15 @@ namespace CreatureLib::Battling {
|
||||||
return {battle->GetCreature(index)};
|
return {battle->GetCreature(index)};
|
||||||
};
|
};
|
||||||
case CreatureLib::Library::AttackTarget::All: {
|
case CreatureLib::Library::AttackTarget::All: {
|
||||||
ArbUt::BorrowedPtr<Creature> arr[battle->GetCreaturesPerSide() * battle->GetSides().Count()];
|
ArbUt::OptionalBorrowedPtr<Creature>
|
||||||
|
arr[battle->GetCreaturesPerSide() * battle->GetSides().Count()];
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (auto side : battle->GetSides()) {
|
for (auto side : battle->GetSides()) {
|
||||||
for (auto mon : side->GetCreatures()) {
|
for (auto mon : side->GetCreatures()) {
|
||||||
arr[i++] = mon;
|
arr[i++] = mon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ArbUt::List<ArbUt::BorrowedPtr<Creature>>(arr, arr + i);
|
return ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>(arr, arr + i);
|
||||||
}
|
}
|
||||||
case CreatureLib::Library::AttackTarget::AllAdjacent: {
|
case CreatureLib::Library::AttackTarget::AllAdjacent: {
|
||||||
auto left = index.GetCreatureIndex() - 1;
|
auto left = index.GetCreatureIndex() - 1;
|
||||||
|
@ -77,20 +78,20 @@ namespace CreatureLib::Battling {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case CreatureLib::Library::AttackTarget::AllAlly: {
|
case CreatureLib::Library::AttackTarget::AllAlly: {
|
||||||
ArbUt::BorrowedPtr<Creature> arr[battle->GetCreaturesPerSide()];
|
ArbUt::OptionalBorrowedPtr<Creature> arr[battle->GetCreaturesPerSide()];
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (auto mon : battle->GetSides()[index.GetSideIndex()]->GetCreatures()) {
|
for (auto mon : battle->GetSides()[index.GetSideIndex()]->GetCreatures()) {
|
||||||
arr[i++] = mon;
|
arr[i++] = mon;
|
||||||
}
|
}
|
||||||
return ArbUt::List<ArbUt::BorrowedPtr<Creature>>(arr, arr + i);
|
return ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>(arr, arr + i);
|
||||||
};
|
};
|
||||||
case CreatureLib::Library::AttackTarget::AllOpponent: {
|
case CreatureLib::Library::AttackTarget::AllOpponent: {
|
||||||
ArbUt::BorrowedPtr<Creature> arr[battle->GetCreaturesPerSide()];
|
ArbUt::OptionalBorrowedPtr<Creature> arr[battle->GetCreaturesPerSide()];
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (auto mon : battle->GetSides()[index.GetSideIndex()]->GetCreatures()) {
|
for (auto mon : battle->GetSides()[index.GetSideIndex()]->GetCreatures()) {
|
||||||
arr[i++] = mon;
|
arr[i++] = mon;
|
||||||
}
|
}
|
||||||
return ArbUt::List<ArbUt::BorrowedPtr<Creature>>(arr, arr + i);
|
return ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>(arr, arr + i);
|
||||||
};
|
};
|
||||||
case CreatureLib::Library::AttackTarget::Any: {
|
case CreatureLib::Library::AttackTarget::Any: {
|
||||||
return {battle->GetCreature(index)};
|
return {battle->GetCreature(index)};
|
||||||
|
|
|
@ -15,14 +15,14 @@ void TurnHandler::RunTurn(ArbUt::BorrowedPtr<ChoiceQueue> queue) {
|
||||||
auto item = queue->Dequeue();
|
auto item = queue->Dequeue();
|
||||||
AssertNotNull(item)
|
AssertNotNull(item)
|
||||||
AssertNotNull(item->GetUser())
|
AssertNotNull(item->GetUser())
|
||||||
AssertNotNull(item->GetUser()->GetBattle())
|
Assert(item->GetUser()->GetBattle().HasValue())
|
||||||
AssertNotNull(item->GetUser()->GetBattleSide())
|
Assert(item->GetUser()->GetBattleSide().HasValue())
|
||||||
auto index = (uint32_t)item->GetUser()->GetBattleSide()->GetCreatureIndex(item->GetUser());
|
auto index = (uint32_t)item->GetUser()->GetBattleSide().GetValue()->GetCreatureIndex(item->GetUser());
|
||||||
|
|
||||||
try_creature(ExecuteChoice(item.get()),
|
try_creature(ExecuteChoice(item.get()),
|
||||||
"Executing choice failed for choice by mon on side "
|
"Executing choice failed for choice by mon on side "
|
||||||
<< ((uint32_t)item->GetUser()->GetBattleSide()->GetSideIndex()) << " and index " << index
|
<< ((uint32_t)item->GetUser()->GetBattleSide().GetValue()->GetSideIndex()) << " and index "
|
||||||
<< ". Choice had choice kind "
|
<< index << ". Choice had choice kind "
|
||||||
<< CreatureLib::Battling::TurnChoiceKindHelper::ToString(item->GetKind()) << " "
|
<< CreatureLib::Battling::TurnChoiceKindHelper::ToString(item->GetKind()) << " "
|
||||||
<< " with message");
|
<< " with message");
|
||||||
}
|
}
|
||||||
|
@ -37,14 +37,15 @@ void TurnHandler::ExecuteChoice(ArbUt::BorrowedPtr<BaseTurnChoice> choice) {
|
||||||
}
|
}
|
||||||
auto user = choice->GetUser();
|
auto user = choice->GetUser();
|
||||||
AssertNotNull(user)
|
AssertNotNull(user)
|
||||||
if (user->GetBattle()->HasEnded())
|
if (!user->GetBattle().HasValue())
|
||||||
|
return;
|
||||||
|
auto battle = user->GetBattle().GetValue();
|
||||||
|
if (battle->HasEnded())
|
||||||
return;
|
return;
|
||||||
// If the user is fainted, we don't want to execute its choice.
|
// If the user is fainted, we don't want to execute its choice.
|
||||||
if (user->IsFainted()) {
|
if (user->IsFainted()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto battle = user->GetBattle();
|
|
||||||
AssertNotNull(battle)
|
|
||||||
// If the user is not in the field, we don't want to execute its choice.
|
// If the user is not in the field, we don't want to execute its choice.
|
||||||
if (!user->IsOnBattleField()) {
|
if (!user->IsOnBattleField()) {
|
||||||
return;
|
return;
|
||||||
|
@ -76,8 +77,9 @@ void TurnHandler::ExecuteAttackChoice(const ArbUt::BorrowedPtr<AttackTurnChoice>
|
||||||
}
|
}
|
||||||
|
|
||||||
auto targetType = choice->GetAttack()->GetAttack()->GetTarget();
|
auto targetType = choice->GetAttack()->GetAttack()->GetTarget();
|
||||||
ArbUt::List<ArbUt::BorrowedPtr<Creature>> targets;
|
ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>> targets;
|
||||||
try_creature(targets = TargetResolver::ResolveTargets(choice->GetTarget(), targetType, battle);
|
Assert(battle.HasValue());
|
||||||
|
try_creature(targets = TargetResolver::ResolveTargets(choice->GetTarget(), targetType, battle.GetValue());
|
||||||
, "Exception during target determination");
|
, "Exception during target determination");
|
||||||
|
|
||||||
auto attack = new ExecutingAttack(targets, 1, choice->GetUser(), choice->GetAttack(), choice->GetAttackScript());
|
auto attack = new ExecutingAttack(targets, 1, choice->GetUser(), choice->GetAttack(), choice->GetAttackScript());
|
||||||
|
@ -94,8 +96,8 @@ void TurnHandler::ExecuteAttackChoice(const ArbUt::BorrowedPtr<AttackTurnChoice>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
battle->TriggerEventListener<AttackUseEvent>(attack);
|
battle.GetValue()->TriggerEventListener<AttackUseEvent>(attack);
|
||||||
battle->RegisterHistoryElement<AttackUseHistory>(attack);
|
battle.GetValue()->RegisterHistoryElement<AttackUseHistory>(attack);
|
||||||
|
|
||||||
// HOOK: check if attack fails
|
// HOOK: check if attack fails
|
||||||
bool fail = false;
|
bool fail = false;
|
||||||
|
@ -114,7 +116,10 @@ void TurnHandler::ExecuteAttackChoice(const ArbUt::BorrowedPtr<AttackTurnChoice>
|
||||||
|
|
||||||
for (uint8_t i = 0; i < attack->GetTargetCount(); i++) {
|
for (uint8_t i = 0; i < attack->GetTargetCount(); i++) {
|
||||||
auto target = attack->GetTargets()[i];
|
auto target = attack->GetTargets()[i];
|
||||||
try_creature(HandleAttackForTarget(attack, target), "Exception occurred during handling attack for target");
|
if (target.HasValue()) {
|
||||||
|
try_creature(HandleAttackForTarget(attack, target.GetValue()), "Exception occurred during handling attack "
|
||||||
|
"for target");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,8 +129,8 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
|
||||||
AssertNotNull(user)
|
AssertNotNull(user)
|
||||||
AssertNotNull(target)
|
AssertNotNull(target)
|
||||||
auto& battle = user->GetBattle();
|
auto& battle = user->GetBattle();
|
||||||
AssertNotNull(battle)
|
Assert(battle.HasValue())
|
||||||
if (battle->HasEnded())
|
if (battle.GetValue()->HasEnded())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool fail = false;
|
bool fail = false;
|
||||||
|
@ -145,7 +150,7 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
|
||||||
auto numberOfHits = attack->GetNumberOfHits();
|
auto numberOfHits = attack->GetNumberOfHits();
|
||||||
if (numberOfHits == 0) {
|
if (numberOfHits == 0) {
|
||||||
HOOK(OnAttackMiss, target, attack, target.GetRaw());
|
HOOK(OnAttackMiss, target, attack, target.GetRaw());
|
||||||
battle->TriggerEventListener<MissEvent>(user);
|
battle.GetValue()->TriggerEventListener<MissEvent>(user);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +159,7 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
|
||||||
auto& attackData = learnedAttack->GetAttack();
|
auto& attackData = learnedAttack->GetAttack();
|
||||||
AssertNotNull(attackData);
|
AssertNotNull(attackData);
|
||||||
|
|
||||||
auto& library = battle->GetLibrary();
|
auto& library = battle.GetValue()->GetLibrary();
|
||||||
AssertNotNull(library)
|
AssertNotNull(library)
|
||||||
auto& dmgLibrary = library->GetDamageLibrary();
|
auto& dmgLibrary = library->GetDamageLibrary();
|
||||||
auto& typeLibrary = library->GetTypeLibrary();
|
auto& typeLibrary = library->GetTypeLibrary();
|
||||||
|
@ -165,7 +170,7 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
|
||||||
|
|
||||||
auto hitIterator = attack->GetTargetIteratorBegin(target);
|
auto hitIterator = attack->GetTargetIteratorBegin(target);
|
||||||
for (uint8_t hitIndex = 0; hitIndex < numberOfHits; hitIndex++) {
|
for (uint8_t hitIndex = 0; hitIndex < numberOfHits; hitIndex++) {
|
||||||
if (battle->HasEnded())
|
if (battle.GetValue()->HasEnded())
|
||||||
return;
|
return;
|
||||||
if (user->IsFainted()) {
|
if (user->IsFainted()) {
|
||||||
break;
|
break;
|
||||||
|
@ -193,7 +198,7 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
|
||||||
hasSecondaryEffect = true;
|
hasSecondaryEffect = true;
|
||||||
} else {
|
} else {
|
||||||
hasSecondaryEffect =
|
hasSecondaryEffect =
|
||||||
battle->GetRandom()->EffectChance(effect->GetChance(), attack, target.GetRaw());
|
battle.GetValue()->GetRandom()->EffectChance(effect->GetChance(), attack, target.GetRaw());
|
||||||
}
|
}
|
||||||
if (hasSecondaryEffect) {
|
if (hasSecondaryEffect) {
|
||||||
HOOK(OnSecondaryEffect, user, attack, target.GetRaw(), hitIndex);
|
HOOK(OnSecondaryEffect, user, attack, target.GetRaw(), hitIndex);
|
||||||
|
@ -223,7 +228,7 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
|
||||||
if (effect->GetChance() == -1) {
|
if (effect->GetChance() == -1) {
|
||||||
hasSecondaryEffect = true;
|
hasSecondaryEffect = true;
|
||||||
} else {
|
} else {
|
||||||
auto random = battle->GetRandom();
|
auto random = battle.GetValue()->GetRandom();
|
||||||
AssertNotNull(random);
|
AssertNotNull(random);
|
||||||
hasSecondaryEffect = random->EffectChance(effect->GetChance(), attack, target.GetRaw());
|
hasSecondaryEffect = random->EffectChance(effect->GetChance(), attack, target.GetRaw());
|
||||||
}
|
}
|
||||||
|
@ -257,20 +262,24 @@ void TurnHandler::ExecuteSwitchChoice(ArbUt::BorrowedPtr<SwitchTurnChoice> choic
|
||||||
auto user = choice->GetUser();
|
auto user = choice->GetUser();
|
||||||
user->ClearVolatileScripts();
|
user->ClearVolatileScripts();
|
||||||
auto userSide = user->GetBattleSide();
|
auto userSide = user->GetBattleSide();
|
||||||
auto userIndex = userSide->GetCreatureIndex(user);
|
if (userSide.HasValue()) {
|
||||||
userSide->SetCreature(choice->GetNewCreature(), userIndex);
|
auto userIndex = userSide.GetValue()->GetCreatureIndex(user);
|
||||||
|
userSide.GetValue()->SetCreature(choice->GetNewCreature(), userIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void TurnHandler::ExecuteFleeChoice(ArbUt::BorrowedPtr<FleeTurnChoice> choice) {
|
void TurnHandler::ExecuteFleeChoice(ArbUt::BorrowedPtr<FleeTurnChoice> choice) {
|
||||||
auto user = choice->GetUser();
|
auto user = choice->GetUser();
|
||||||
auto battle = user->GetBattle();
|
auto battle = user->GetBattle();
|
||||||
if (!battle->CanFlee()) {
|
if (!battle.HasValue() || !battle.GetValue()->CanFlee()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: If any of the creatures on the users side has a script that prevents it from running, block.
|
// TODO: If any of the creatures on the users side has a script that prevents it from running, block.
|
||||||
// TODO: If any of the creatures on any other side has a script that prevents this side from running, block.
|
// TODO: If any of the creatures on any other side has a script that prevents this side from running, block.
|
||||||
|
|
||||||
if (battle->GetLibrary()->GetMiscLibrary()->CanFlee(choice.GetRaw())) {
|
if (battle.GetValue()->GetLibrary()->GetMiscLibrary()->CanFlee(choice.GetRaw())) {
|
||||||
user->GetBattleSide()->MarkAsFled();
|
if (user->GetBattleSide().HasValue()) {
|
||||||
battle->ValidateBattleState();
|
user->GetBattleSide().GetValue()->MarkAsFled();
|
||||||
|
}
|
||||||
|
battle.GetValue()->ValidateBattleState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,14 +51,14 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<const HistoryElement> GetTopElement() const noexcept { return _top; }
|
ArbUt::BorrowedPtr<const HistoryElement> GetTopElement() const noexcept { return _top; }
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<const HistoryElement> GetLastUsedAttack() const noexcept {
|
std::optional<ArbUt::BorrowedPtr<const HistoryElement>> GetLastUsedAttack() const noexcept {
|
||||||
const auto* c = _top;
|
const auto* c = _top;
|
||||||
while (c != nullptr) {
|
while (c != nullptr) {
|
||||||
if (c->GetKind() == HistoryElementKind::AttackUse)
|
if (c->GetKind() == HistoryElementKind::AttackUse)
|
||||||
return c;
|
return c;
|
||||||
c = c->_previous;
|
c = c->_previous;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@ bool CreatureLib::Battling::MiscLibrary::IsCritical([[maybe_unused]] CreatureLib
|
||||||
CreatureLib::Battling::Creature* target,
|
CreatureLib::Battling::Creature* target,
|
||||||
[[maybe_unused]] uint8_t hit) const {
|
[[maybe_unused]] uint8_t hit) const {
|
||||||
AssertNotNull(target)
|
AssertNotNull(target)
|
||||||
auto rand = target->GetBattle()->GetRandom();
|
Assert(target->GetBattle().HasValue())
|
||||||
|
auto rand = target->GetBattle().GetValue()->GetRandom();
|
||||||
return rand->Get(10) <= 0;
|
return rand->Get(10) <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,10 +36,11 @@ bool CreatureLib::Battling::MiscLibrary::CanFlee([[maybe_unused]] FleeTurnChoice
|
||||||
CreatureLib::Battling::BaseTurnChoice*
|
CreatureLib::Battling::BaseTurnChoice*
|
||||||
CreatureLib::Battling::MiscLibrary::ReplacementAttack(Creature* user, [[maybe_unused]] CreatureIndex target) const {
|
CreatureLib::Battling::MiscLibrary::ReplacementAttack(Creature* user, [[maybe_unused]] CreatureIndex target) const {
|
||||||
AssertNotNull(user)
|
AssertNotNull(user)
|
||||||
|
Assert(user->GetBattleSide().HasValue())
|
||||||
auto sideTarget = 0;
|
auto sideTarget = 0;
|
||||||
if (user->GetBattleSide()->GetSideIndex() == 0)
|
if (user->GetBattleSide().GetValue()->GetSideIndex() == 0)
|
||||||
sideTarget = 1;
|
sideTarget = 1;
|
||||||
auto side = user->GetBattle()->GetSides()[sideTarget];
|
auto side = user->GetBattle().GetValue()->GetSides()[sideTarget];
|
||||||
auto random_mon = side->GetRandomCreatureIndex();
|
auto random_mon = side->GetRandomCreatureIndex();
|
||||||
return new AttackTurnChoice(user, GetReplacementAttack(), CreatureIndex(side->GetSideIndex(), random_mon));
|
return new AttackTurnChoice(user, GetReplacementAttack(), CreatureIndex(side->GetSideIndex(), random_mon));
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,8 @@ bool Battle::TrySetChoice(BaseTurnChoice* choice) {
|
||||||
AssertNotNull(choice)
|
AssertNotNull(choice)
|
||||||
if (!CanUse(choice))
|
if (!CanUse(choice))
|
||||||
return false;
|
return false;
|
||||||
choice->GetUser()->GetBattleSide()->SetChoice(choice);
|
Assert(choice->GetUser()->GetBattleSide().HasValue())
|
||||||
|
choice->GetUser()->GetBattleSide().GetValue()->SetChoice(choice);
|
||||||
CheckChoicesSetAndRun();
|
CheckChoicesSetAndRun();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -155,15 +156,15 @@ void Battle::ValidateBattleState() {
|
||||||
}
|
}
|
||||||
void Battle::AddVolatileScript(const ArbUt::StringView& key) {
|
void Battle::AddVolatileScript(const ArbUt::StringView& key) {
|
||||||
auto script = _volatile.Get(key);
|
auto script = _volatile.Get(key);
|
||||||
if (script != nullptr) {
|
if (script.has_value()) {
|
||||||
script->Stack();
|
script.value()->Stack();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
script = _library->LoadScript(ScriptCategory::Battle, key);
|
script = _library->LoadScript(ScriptCategory::Battle, key);
|
||||||
if (script == nullptr) {
|
if (!script.has_value()) {
|
||||||
THROW("Invalid volatile script requested for battle: '" << key.c_str() << "'.");
|
THROW("Invalid volatile script requested for battle: '" << key.c_str() << "'.");
|
||||||
}
|
}
|
||||||
return _volatile.Add(script.GetRaw());
|
return _volatile.Add(script.value().GetRaw());
|
||||||
}
|
}
|
||||||
void Battle::AddVolatileScript(Script* script) { return _volatile.Add(script); }
|
void Battle::AddVolatileScript(Script* script) { return _volatile.Add(script); }
|
||||||
void Battle::RemoveVolatileScript(Script* script) { _volatile.Remove(script->GetName()); }
|
void Battle::RemoveVolatileScript(Script* script) { _volatile.Remove(script->GetName()); }
|
||||||
|
|
|
@ -41,7 +41,6 @@ namespace CreatureLib::Battling {
|
||||||
.count())
|
.count())
|
||||||
: _library(library), _parties(parties.GetStdList()), _canFlee(canFlee), _numberOfSides(numberOfSides),
|
: _library(library), _parties(parties.GetStdList()), _canFlee(canFlee), _numberOfSides(numberOfSides),
|
||||||
_creaturesPerSide(creaturesPerSide), _sides(numberOfSides), _random(randomSeed) {
|
_creaturesPerSide(creaturesPerSide), _sides(numberOfSides), _random(randomSeed) {
|
||||||
AssertNotNull(_library);
|
|
||||||
AssertAllNotNull(parties);
|
AssertAllNotNull(parties);
|
||||||
|
|
||||||
for (size_t i = 0; i < numberOfSides; i++) {
|
for (size_t i = 0; i < numberOfSides; i++) {
|
||||||
|
@ -67,10 +66,10 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
bool CreatureInField(ArbUt::BorrowedPtr<Creature> creature) const;
|
bool CreatureInField(ArbUt::BorrowedPtr<Creature> creature) const;
|
||||||
|
|
||||||
const ArbUt::BorrowedPtr<Creature>& GetCreature(const CreatureIndex& target) const {
|
const ArbUt::OptionalBorrowedPtr<Creature>& GetCreature(const CreatureIndex& target) const {
|
||||||
return _sides[target.GetSideIndex()]->GetCreature(target.GetCreatureIndex());
|
return _sides[target.GetSideIndex()]->GetCreature(target.GetCreatureIndex());
|
||||||
}
|
}
|
||||||
const ArbUt::BorrowedPtr<Creature>& GetCreature(uint8_t side, uint8_t target) const {
|
const ArbUt::OptionalBorrowedPtr<Creature>& GetCreature(uint8_t side, uint8_t target) const {
|
||||||
return _sides[side]->GetCreature(target);
|
return _sides[side]->GetCreature(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,8 +86,12 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
const ArbUt::UniquePtrList<BattleParty>& GetParties() const noexcept { return _parties; }
|
const ArbUt::UniquePtrList<BattleParty>& GetParties() const noexcept { return _parties; }
|
||||||
const ArbUt::UniquePtrList<BattleSide>& GetSides() const noexcept { return _sides; }
|
const ArbUt::UniquePtrList<BattleSide>& GetSides() const noexcept { return _sides; }
|
||||||
ArbUt::BorrowedPtr<Script> GetVolatileScript(const ArbUt::StringView& key) const { return _volatile.Get(key); }
|
std::optional<ArbUt::BorrowedPtr<Script>> GetVolatileScript(const ArbUt::StringView& key) const {
|
||||||
ArbUt::BorrowedPtr<Script> GetVolatileScript(uint32_t keyHash) const noexcept { return _volatile.Get(keyHash); }
|
return _volatile.Get(key);
|
||||||
|
}
|
||||||
|
std::optional<ArbUt::BorrowedPtr<Script>> GetVolatileScript(uint32_t keyHash) const noexcept {
|
||||||
|
return _volatile.Get(keyHash);
|
||||||
|
}
|
||||||
void AddVolatileScript(const ArbUt::StringView& key);
|
void AddVolatileScript(const ArbUt::StringView& key);
|
||||||
void AddVolatileScript(Script* script);
|
void AddVolatileScript(Script* script);
|
||||||
void RemoveVolatileScript(const ArbUt::BasicStringView& name) { _volatile.Remove(name); }
|
void RemoveVolatileScript(const ArbUt::BasicStringView& name) { _volatile.Remove(name); }
|
||||||
|
|
|
@ -11,7 +11,7 @@ bool BattleSide::AllPossibleSlotsFilled() const {
|
||||||
try {
|
try {
|
||||||
for (size_t i = 0; i < _creatures.Count(); i++) {
|
for (size_t i = 0; i < _creatures.Count(); i++) {
|
||||||
auto c = _creatures[i];
|
auto c = _creatures[i];
|
||||||
if (c == nullptr || c->IsFainted()) {
|
if (!c.HasValue() || c.GetValue()->IsFainted()) {
|
||||||
if (_battle->CanSlotBeFilled(_index, i))
|
if (_battle->CanSlotBeFilled(_index, i))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,10 @@ void BattleSide::SetChoice(BaseTurnChoice* choice) {
|
||||||
try {
|
try {
|
||||||
for (size_t i = 0; i < _creatures.Count(); i++) {
|
for (size_t i = 0; i < _creatures.Count(); i++) {
|
||||||
auto& c = _creatures[i];
|
auto& c = _creatures[i];
|
||||||
if (c == choice->GetUser()) {
|
if (!c.HasValue()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c.GetValue() == choice->GetUser()) {
|
||||||
_choices[i] = std::shared_ptr<BaseTurnChoice>(choice);
|
_choices[i] = std::shared_ptr<BaseTurnChoice>(choice);
|
||||||
_choicesSet++;
|
_choicesSet++;
|
||||||
return;
|
return;
|
||||||
|
@ -46,37 +49,39 @@ void BattleSide::SetChoice(BaseTurnChoice* choice) {
|
||||||
THROW("User not found");
|
THROW("User not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleSide::SetCreature(ArbUt::BorrowedPtr<Creature> creature, uint8_t index) {
|
void BattleSide::SetCreature(ArbUt::OptionalBorrowedPtr<Creature> creature, uint8_t index) {
|
||||||
auto old = _creatures[index];
|
auto old = _creatures[index];
|
||||||
if (old != nullptr) {
|
if (old.HasValue()) {
|
||||||
old->SetOnBattleField(false);
|
old.GetValue()->SetOnBattleField(false);
|
||||||
}
|
}
|
||||||
_creatures[index] = creature;
|
_creatures[index] = creature.GetValue();
|
||||||
if (creature != nullptr) {
|
if (!creature.HasValue()) {
|
||||||
creature->SetBattleData(_battle, this);
|
|
||||||
creature->SetOnBattleField(true);
|
|
||||||
}
|
|
||||||
if (_battle == nullptr)
|
|
||||||
return;
|
return;
|
||||||
for (auto side : _battle->GetSides()) {
|
}
|
||||||
if (side == this)
|
creature.GetValue()->SetBattleData(_battle, this);
|
||||||
|
creature.GetValue()->SetOnBattleField(true);
|
||||||
|
if (_battle == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (auto* side : _battle->GetSides()) {
|
||||||
|
if (side == this) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
for (const auto& c : side->GetCreatures()) {
|
for (const auto& c : side->GetCreatures()) {
|
||||||
if (c != nullptr) {
|
if (c.HasValue()) {
|
||||||
c->MarkOpponentAsSeen(creature);
|
c.GetValue()->MarkOpponentAsSeen(creature.GetValue());
|
||||||
creature->MarkOpponentAsSeen(c.GetRaw());
|
creature.GetValue()->MarkOpponentAsSeen(c.GetValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_battle->TriggerEventListener<SwitchEvent>(CreatureIndex(this->_index, index), creature);
|
_battle->TriggerEventListener<SwitchEvent>(CreatureIndex(this->_index, index), creature.GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BattleSide::CreatureOnSide(const ArbUt::BorrowedPtr<Creature>& creature) const {
|
bool BattleSide::CreatureOnSide(const ArbUt::BorrowedPtr<Creature>& creature) const {
|
||||||
AssertNotNull(creature)
|
return std::find(_creatures.begin(), _creatures.end(), creature.GetRaw()) != _creatures.end();
|
||||||
return std::find(_creatures.begin(), _creatures.end(), creature) != _creatures.end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ArbUt::BorrowedPtr<Creature>& BattleSide::GetCreature(uint8_t index) const { return _creatures[index]; }
|
const ArbUt::OptionalBorrowedPtr<Creature>& BattleSide::GetCreature(uint8_t index) const { return _creatures[index]; }
|
||||||
|
|
||||||
void BattleSide::GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) {
|
void BattleSide::GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) {
|
||||||
scripts.Append(ScriptWrapper::FromSet(&_volatile));
|
scripts.Append(ScriptWrapper::FromSet(&_volatile));
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace CreatureLib::Battling {
|
||||||
class BattleSide : public ScriptSource {
|
class BattleSide : public ScriptSource {
|
||||||
uint8_t _index;
|
uint8_t _index;
|
||||||
uint8_t _creaturesPerSide;
|
uint8_t _creaturesPerSide;
|
||||||
ArbUt::List<ArbUt::BorrowedPtr<Creature>> _creatures;
|
ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>> _creatures;
|
||||||
ArbUt::List<std::shared_ptr<BaseTurnChoice>> _choices;
|
ArbUt::List<std::shared_ptr<BaseTurnChoice>> _choices;
|
||||||
ArbUt::List<bool> _fillableSlots;
|
ArbUt::List<bool> _fillableSlots;
|
||||||
uint8_t _choicesSet = 0;
|
uint8_t _choicesSet = 0;
|
||||||
|
@ -40,20 +40,22 @@ namespace CreatureLib::Battling {
|
||||||
void SetChoice(BaseTurnChoice* choice);
|
void SetChoice(BaseTurnChoice* choice);
|
||||||
void ResetChoices() noexcept;
|
void ResetChoices() noexcept;
|
||||||
|
|
||||||
void SetCreature(ArbUt::BorrowedPtr<Creature> creature, uint8_t index);
|
void SetCreature(ArbUt::OptionalBorrowedPtr<Creature> creature, uint8_t index);
|
||||||
|
|
||||||
const ArbUt::BorrowedPtr<Creature>& GetCreature(uint8_t index) const;
|
const ArbUt::OptionalBorrowedPtr<Creature>& GetCreature(uint8_t index) const;
|
||||||
bool CreatureOnSide(const ArbUt::BorrowedPtr<Creature>& creature) const;
|
bool CreatureOnSide(const ArbUt::BorrowedPtr<Creature>& creature) const;
|
||||||
|
|
||||||
size_t ScriptCount() const override;
|
size_t ScriptCount() const override;
|
||||||
void GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) override;
|
void GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) override;
|
||||||
|
|
||||||
const ArbUt::List<ArbUt::BorrowedPtr<Creature>>& GetCreatures() { return _creatures; }
|
const ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>& GetCreatures() { return _creatures; }
|
||||||
|
|
||||||
uint8_t GetSideIndex() noexcept { return _index; }
|
uint8_t GetSideIndex() noexcept { return _index; }
|
||||||
uint8_t GetCreatureIndex(const ArbUt::BorrowedPtr<Creature>& c) {
|
uint8_t GetCreatureIndex(const ArbUt::BorrowedPtr<Creature>& c) {
|
||||||
for (size_t i = 0; i < _creatures.Count(); i++) {
|
for (size_t i = 0; i < _creatures.Count(); i++) {
|
||||||
if (_creatures[i] == c)
|
if (!_creatures[i].HasValue())
|
||||||
|
continue;
|
||||||
|
if (_creatures[i].GetValue() == c.GetRaw())
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
THROW("Unable to find creature on field.");
|
THROW("Unable to find creature on field.");
|
||||||
|
@ -61,7 +63,9 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
void MarkSlotAsUnfillable(const ArbUt::BorrowedPtr<Creature>& creature) noexcept {
|
void MarkSlotAsUnfillable(const ArbUt::BorrowedPtr<Creature>& creature) noexcept {
|
||||||
for (uint8_t i = 0; i < _creaturesPerSide; i++) {
|
for (uint8_t i = 0; i < _creaturesPerSide; i++) {
|
||||||
if (_creatures[i] == creature) {
|
if (!_creatures[i].HasValue())
|
||||||
|
continue;
|
||||||
|
if (_creatures[i].GetValue() == creature) {
|
||||||
_fillableSlots.At(i) = false;
|
_fillableSlots.At(i) = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,6 @@ namespace CreatureLib::Battling {
|
||||||
_uniqueIdentifier(uid), _gender(gender), _coloring(coloring), _heldItem(heldItem),
|
_uniqueIdentifier(uid), _gender(gender), _coloring(coloring), _heldItem(heldItem),
|
||||||
_nickname(std::move(nickname)), _talentIndex(talent), _hasOverridenTalent(false), _attacks(attacks),
|
_nickname(std::move(nickname)), _talentIndex(talent), _hasOverridenTalent(false), _attacks(attacks),
|
||||||
_allowedExperienceGain(allowedExperienceGain) {
|
_allowedExperienceGain(allowedExperienceGain) {
|
||||||
AssertNotNull(library)
|
|
||||||
AssertNotNull(species)
|
|
||||||
AssertNotNull(variant)
|
|
||||||
|
|
||||||
_activeTalent = std::unique_ptr<Script>(_library->LoadScript(ScriptCategory::Talent, GetActiveTalent()));
|
_activeTalent = std::unique_ptr<Script>(_library->LoadScript(ScriptCategory::Talent, GetActiveTalent()));
|
||||||
for (auto t : _variant->GetTypes()) {
|
for (auto t : _variant->GetTypes()) {
|
||||||
_types.push_back(t);
|
_types.push_back(t);
|
||||||
|
@ -36,8 +32,8 @@ namespace CreatureLib::Battling {
|
||||||
// If the creature is genderless, but it's new species is not, we want to set its gender
|
// If the creature is genderless, but it's new species is not, we want to set its gender
|
||||||
if (_gender != CreatureLib::Library::Gender::Genderless && _species->GetGenderRate() != -1) {
|
if (_gender != CreatureLib::Library::Gender::Genderless && _species->GetGenderRate() != -1) {
|
||||||
// If we are currently in battle, use the battle random so we can get predictable events.
|
// If we are currently in battle, use the battle random so we can get predictable events.
|
||||||
if (!_battle.IsNull()) {
|
if (_battle.HasValue()) {
|
||||||
_gender = _species->GetRandomGender(_battle->GetRandom()->GetRNG());
|
_gender = _species->GetRandomGender(_battle.GetValue()->GetRandom()->GetRNG());
|
||||||
}
|
}
|
||||||
// Else create a new random.
|
// Else create a new random.
|
||||||
else {
|
else {
|
||||||
|
@ -48,8 +44,8 @@ namespace CreatureLib::Battling {
|
||||||
else if (_species->GetGenderRate() == -1 && _gender != CreatureLib::Library::Gender::Genderless) {
|
else if (_species->GetGenderRate() == -1 && _gender != CreatureLib::Library::Gender::Genderless) {
|
||||||
_gender = CreatureLib::Library::Gender::Genderless;
|
_gender = CreatureLib::Library::Gender::Genderless;
|
||||||
}
|
}
|
||||||
if (_battle != nullptr) {
|
if (_battle.HasValue()) {
|
||||||
_battle->TriggerEventListener<ChangeSpeciesEvent>(this, _species);
|
_battle.GetValue()->TriggerEventListener<ChangeSpeciesEvent>(this, _species);
|
||||||
}
|
}
|
||||||
ChangeVariant(variant);
|
ChangeVariant(variant);
|
||||||
}
|
}
|
||||||
|
@ -79,8 +75,8 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
// TODO: consider variant specific attacks?
|
// TODO: consider variant specific attacks?
|
||||||
|
|
||||||
if (_battle != nullptr) {
|
if (_battle.HasValue()) {
|
||||||
_battle->TriggerEventListener<ChangeVariantEvent>(this, _variant);
|
_battle.GetValue()->TriggerEventListener<ChangeVariantEvent>(this, _variant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,9 +98,9 @@ namespace CreatureLib::Battling {
|
||||||
return _variant->GetTalent(_talentIndex);
|
return _variant->GetTalent(_talentIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Creature::SetBattleData(ArbUt::BorrowedPtr<Battle> battle, ArbUt::BorrowedPtr<BattleSide> side) {
|
void Creature::SetBattleData(const ArbUt::BorrowedPtr<Battle>& battle, const ArbUt::BorrowedPtr<BattleSide>& side) {
|
||||||
_battle = battle;
|
_battle = battle.GetRaw();
|
||||||
_side = side;
|
_side = side.GetRaw();
|
||||||
this->ResetActiveScripts();
|
this->ResetActiveScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,9 +138,9 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
const ArbUt::BorrowedPtr<Battle>& Creature::GetBattle() const { return _battle; }
|
const ArbUt::OptionalBorrowedPtr<Battle>& Creature::GetBattle() const { return _battle; }
|
||||||
|
|
||||||
const ArbUt::BorrowedPtr<BattleSide>& Creature::GetBattleSide() const { return _side; }
|
const ArbUt::OptionalBorrowedPtr<BattleSide>& Creature::GetBattleSide() const { return _side; }
|
||||||
|
|
||||||
bool Creature::IsFainted() const noexcept { return this->_currentHealth == 0; }
|
bool Creature::IsFainted() const noexcept { return this->_currentHealth == 0; }
|
||||||
|
|
||||||
|
@ -152,15 +148,17 @@ namespace CreatureLib::Battling {
|
||||||
AssertNotNull(_battle)
|
AssertNotNull(_battle)
|
||||||
AssertNotNull(_side)
|
AssertNotNull(_side)
|
||||||
// HOOK: On Faint
|
// HOOK: On Faint
|
||||||
if (_battle != nullptr) {
|
if (_battle.HasValue()) {
|
||||||
_battle->TriggerEventListener<FaintEvent>(this);
|
_battle.GetValue()->TriggerEventListener<FaintEvent>(this);
|
||||||
}
|
}
|
||||||
_library->GetExperienceLibrary()->HandleExperienceGain(this, _seenOpponents);
|
_library->GetExperienceLibrary()->HandleExperienceGain(this, _seenOpponents);
|
||||||
auto sideIndex = _side->GetCreatureIndex(this);
|
if (_battle.HasValue() && _side.HasValue()) {
|
||||||
if (!_battle->CanSlotBeFilled(_side->GetSideIndex(), sideIndex)) {
|
auto sideIndex = _side.GetValue()->GetCreatureIndex(this);
|
||||||
_side->MarkSlotAsUnfillable(this);
|
if (!_battle.GetValue()->CanSlotBeFilled(_side.GetValue()->GetSideIndex(), sideIndex)) {
|
||||||
|
_side.GetValue()->MarkSlotAsUnfillable(this);
|
||||||
|
}
|
||||||
|
_battle.GetValue()->ValidateBattleState();
|
||||||
}
|
}
|
||||||
_battle->ValidateBattleState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Creature::Damage(uint32_t damage, DamageSource source) {
|
void Creature::Damage(uint32_t damage, DamageSource source) {
|
||||||
|
@ -172,8 +170,8 @@ namespace CreatureLib::Battling {
|
||||||
// HOOK: On Damage
|
// HOOK: On Damage
|
||||||
auto newHealth = _currentHealth - damage;
|
auto newHealth = _currentHealth - damage;
|
||||||
auto battle = this->GetBattle();
|
auto battle = this->GetBattle();
|
||||||
if (battle != nullptr) {
|
if (battle.HasValue()) {
|
||||||
battle->TriggerEventListener<DamageEvent>(this, source, _currentHealth, newHealth);
|
battle.GetValue()->TriggerEventListener<DamageEvent>(this, source, _currentHealth, newHealth);
|
||||||
}
|
}
|
||||||
_currentHealth = newHealth;
|
_currentHealth = newHealth;
|
||||||
|
|
||||||
|
@ -192,8 +190,8 @@ namespace CreatureLib::Battling {
|
||||||
// HOOK: On Heal
|
// HOOK: On Heal
|
||||||
auto newHealth = _currentHealth + amount;
|
auto newHealth = _currentHealth + amount;
|
||||||
auto battle = this->GetBattle();
|
auto battle = this->GetBattle();
|
||||||
if (battle != nullptr) {
|
if (battle.HasValue()) {
|
||||||
battle->TriggerEventListener<HealEvent>(this, _currentHealth, newHealth);
|
battle.GetValue()->TriggerEventListener<HealEvent>(this, _currentHealth, newHealth);
|
||||||
}
|
}
|
||||||
_currentHealth = newHealth;
|
_currentHealth = newHealth;
|
||||||
}
|
}
|
||||||
|
@ -223,8 +221,8 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
size_t Creature::ScriptCount() const {
|
size_t Creature::ScriptCount() const {
|
||||||
auto c = 3;
|
auto c = 3;
|
||||||
if (_side != nullptr) {
|
if (_side.HasValue()) {
|
||||||
c += _side->ScriptCount();
|
c += _side.GetValue()->ScriptCount();
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -233,8 +231,8 @@ namespace CreatureLib::Battling {
|
||||||
scripts.Append(ScriptWrapper::FromScript(&_activeTalent));
|
scripts.Append(ScriptWrapper::FromScript(&_activeTalent));
|
||||||
scripts.Append(ScriptWrapper::FromScript(&_status));
|
scripts.Append(ScriptWrapper::FromScript(&_status));
|
||||||
scripts.Append(ScriptWrapper::FromSet(&_volatile));
|
scripts.Append(ScriptWrapper::FromSet(&_volatile));
|
||||||
if (_side != nullptr) {
|
if (_side.HasValue()) {
|
||||||
_side->GetActiveScripts(scripts);
|
_side.GetValue()->GetActiveScripts(scripts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Creature::ClearVolatileScripts() { _volatile.Clear(); }
|
void Creature::ClearVolatileScripts() { _volatile.Clear(); }
|
||||||
|
@ -248,22 +246,22 @@ namespace CreatureLib::Battling {
|
||||||
if (level >= maxLevel) {
|
if (level >= maxLevel) {
|
||||||
exp = _library->GetGrowthRateLibrary()->CalculateExperience(this->GetSpecies()->GetGrowthRate(), maxLevel);
|
exp = _library->GetGrowthRateLibrary()->CalculateExperience(this->GetSpecies()->GetGrowthRate(), maxLevel);
|
||||||
}
|
}
|
||||||
if (_battle != nullptr) {
|
if (_battle.HasValue()) {
|
||||||
_battle->TriggerEventListener<ExperienceGainEvent>(this, _experience, exp);
|
_battle.GetValue()->TriggerEventListener<ExperienceGainEvent>(this, _experience, exp);
|
||||||
}
|
}
|
||||||
_experience = exp;
|
_experience = exp;
|
||||||
_level = level;
|
_level = level;
|
||||||
}
|
}
|
||||||
ArbUt::BorrowedPtr<const Library::CreatureSpecies> Creature::GetDisplaySpecies() const noexcept {
|
ArbUt::OptionalBorrowedPtr<const Library::CreatureSpecies> Creature::GetDisplaySpecies() const noexcept {
|
||||||
auto species = _displaySpecies;
|
auto species = _displaySpecies;
|
||||||
if (species == nullptr)
|
if (!species.HasValue())
|
||||||
species = _species;
|
species = _species.GetRaw();
|
||||||
return species;
|
return species;
|
||||||
}
|
}
|
||||||
ArbUt::BorrowedPtr<const Library::SpeciesVariant> Creature::GetDisplayVariant() const noexcept {
|
ArbUt::OptionalBorrowedPtr<const Library::SpeciesVariant> Creature::GetDisplayVariant() const noexcept {
|
||||||
auto variant = _displayVariant;
|
auto variant = _displayVariant;
|
||||||
if (variant == nullptr)
|
if (!variant.HasValue())
|
||||||
variant = _variant;
|
variant = _variant.GetRaw();
|
||||||
return variant;
|
return variant;
|
||||||
}
|
}
|
||||||
void Creature::SetHeldItem(const ArbUt::BasicStringView& itemName) {
|
void Creature::SetHeldItem(const ArbUt::BasicStringView& itemName) {
|
||||||
|
@ -283,15 +281,15 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
void Creature::AddVolatileScript(const ArbUt::StringView& name) {
|
void Creature::AddVolatileScript(const ArbUt::StringView& name) {
|
||||||
auto script = _volatile.Get(name);
|
auto script = _volatile.Get(name);
|
||||||
if (script != nullptr) {
|
if (script.has_value()) {
|
||||||
script->Stack();
|
script.value()->Stack();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
script = this->_library->LoadScript(ScriptCategory::Creature, name);
|
script = this->_library->LoadScript(ScriptCategory::Creature, name);
|
||||||
if (script == nullptr) {
|
if (!script.has_value()) {
|
||||||
THROW("Invalid volatile script requested for creature: '" << name.c_str() << "'.");
|
THROW("Invalid volatile script requested for creature: '" << name.c_str() << "'.");
|
||||||
}
|
}
|
||||||
_volatile.Add(script.GetRaw());
|
_volatile.Add(script.value().GetRaw());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Creature::AddVolatileScript(Script* script) { _volatile.Add(script); }
|
void Creature::AddVolatileScript(Script* script) { _volatile.Add(script); }
|
||||||
|
|
|
@ -24,8 +24,8 @@ namespace CreatureLib::Battling {
|
||||||
ArbUt::BorrowedPtr<const Library::CreatureSpecies> _species;
|
ArbUt::BorrowedPtr<const Library::CreatureSpecies> _species;
|
||||||
ArbUt::BorrowedPtr<const Library::SpeciesVariant> _variant;
|
ArbUt::BorrowedPtr<const Library::SpeciesVariant> _variant;
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<const Library::CreatureSpecies> _displaySpecies = nullptr;
|
ArbUt::OptionalBorrowedPtr<const Library::CreatureSpecies> _displaySpecies = nullptr;
|
||||||
ArbUt::BorrowedPtr<const Library::SpeciesVariant> _displayVariant = nullptr;
|
ArbUt::OptionalBorrowedPtr<const Library::SpeciesVariant> _displayVariant = nullptr;
|
||||||
|
|
||||||
level_int_t _level;
|
level_int_t _level;
|
||||||
uint32_t _experience;
|
uint32_t _experience;
|
||||||
|
@ -39,8 +39,8 @@ namespace CreatureLib::Battling {
|
||||||
Library::StatisticSet<uint32_t> _flatStats;
|
Library::StatisticSet<uint32_t> _flatStats;
|
||||||
Library::StatisticSet<uint32_t> _boostedStats;
|
Library::StatisticSet<uint32_t> _boostedStats;
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<Battle> _battle = nullptr;
|
ArbUt::OptionalBorrowedPtr<Battle> _battle = nullptr;
|
||||||
ArbUt::BorrowedPtr<BattleSide> _side = nullptr;
|
ArbUt::OptionalBorrowedPtr<BattleSide> _side = nullptr;
|
||||||
bool _onBattleField = false;
|
bool _onBattleField = false;
|
||||||
|
|
||||||
std::string _nickname = "";
|
std::string _nickname = "";
|
||||||
|
@ -104,9 +104,9 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; }
|
inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; }
|
||||||
|
|
||||||
void SetBattleData(ArbUt::BorrowedPtr<Battle> battle, ArbUt::BorrowedPtr<BattleSide> side);
|
void SetBattleData(const ArbUt::BorrowedPtr<Battle>& battle, const ArbUt::BorrowedPtr<BattleSide>& side);
|
||||||
const ArbUt::BorrowedPtr<Battle>& GetBattle() const;
|
const ArbUt::OptionalBorrowedPtr<Battle>& GetBattle() const;
|
||||||
const ArbUt::BorrowedPtr<BattleSide>& GetBattleSide() const;
|
const ArbUt::OptionalBorrowedPtr<BattleSide>& GetBattleSide() const;
|
||||||
inline void SetOnBattleField(bool value) { _onBattleField = value; }
|
inline void SetOnBattleField(bool value) { _onBattleField = value; }
|
||||||
inline bool IsOnBattleField() const { return _onBattleField; }
|
inline bool IsOnBattleField() const { return _onBattleField; }
|
||||||
|
|
||||||
|
@ -149,14 +149,14 @@ namespace CreatureLib::Battling {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<const Library::CreatureSpecies> GetDisplaySpecies() const noexcept;
|
ArbUt::OptionalBorrowedPtr<const Library::CreatureSpecies> GetDisplaySpecies() const noexcept;
|
||||||
ArbUt::BorrowedPtr<const Library::SpeciesVariant> GetDisplayVariant() const noexcept;
|
ArbUt::OptionalBorrowedPtr<const Library::SpeciesVariant> GetDisplayVariant() const noexcept;
|
||||||
|
|
||||||
void SetDisplaySpecies(const ArbUt::BorrowedPtr<const Library::CreatureSpecies>& species) noexcept {
|
void SetDisplaySpecies(const ArbUt::BorrowedPtr<const Library::CreatureSpecies>& species) noexcept {
|
||||||
_displaySpecies = species;
|
_displaySpecies = species.GetRaw();
|
||||||
}
|
}
|
||||||
void SetDisplayVariant(ArbUt::BorrowedPtr<const Library::SpeciesVariant> variant) noexcept {
|
void SetDisplayVariant(ArbUt::BorrowedPtr<const Library::SpeciesVariant> variant) noexcept {
|
||||||
_displayVariant = variant;
|
_displayVariant = variant.GetRaw();
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool AllowedExperienceGain() const noexcept { return _allowedExperienceGain; }
|
inline bool AllowedExperienceGain() const noexcept { return _allowedExperienceGain; }
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
namespace CreatureLib::Battling {
|
namespace CreatureLib::Battling {
|
||||||
class CreatureParty {
|
class CreatureParty {
|
||||||
ArbUt::UniquePtrList<Creature> _party;
|
ArbUt::OptionalUniquePtrList<Creature> _party;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CreatureParty(size_t size) noexcept : _party(size) {
|
CreatureParty(size_t size) noexcept : _party(size) {
|
||||||
|
@ -18,7 +18,7 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
virtual ~CreatureParty() = default;
|
virtual ~CreatureParty() = default;
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<Creature> GetAtIndex(size_t index) const noexcept { return _party[index]; }
|
ArbUt::OptionalBorrowedPtr<Creature> GetAtIndex(size_t index) const noexcept { return _party[index]; }
|
||||||
|
|
||||||
void Switch(size_t a, size_t b) noexcept { _party.Swap(a, b); }
|
void Switch(size_t a, size_t b) noexcept { _party.Swap(a, b); }
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ namespace CreatureLib::Battling {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArbUt::UniquePtrList<Creature>& GetParty() noexcept { return _party; }
|
ArbUt::OptionalUniquePtrList<Creature>& GetParty() noexcept { return _party; }
|
||||||
const ArbUt::UniquePtrList<Creature>& GetParty() const noexcept { return _party; }
|
const ArbUt::OptionalUniquePtrList<Creature>& GetParty() const noexcept { return _party; }
|
||||||
|
|
||||||
size_t GetLength() const noexcept { return _party.Count(); }
|
size_t GetLength() const noexcept { return _party.Count(); }
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,10 @@ namespace CreatureLib::Battling {
|
||||||
ArbUt::BorrowedPtr<Creature> _user;
|
ArbUt::BorrowedPtr<Creature> _user;
|
||||||
ArbUt::BorrowedPtr<LearnedAttack> _attack;
|
ArbUt::BorrowedPtr<LearnedAttack> _attack;
|
||||||
std::unique_ptr<Script> _script = nullptr;
|
std::unique_ptr<Script> _script = nullptr;
|
||||||
ArbUt::List<ArbUt::BorrowedPtr<Creature>> _targets;
|
ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>> _targets;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ExecutingAttack(const ArbUt::List<ArbUt::BorrowedPtr<Creature>>& targets, uint8_t numberHits,
|
ExecutingAttack(const ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>& targets, uint8_t numberHits,
|
||||||
ArbUt::BorrowedPtr<Creature> user, const ArbUt::BorrowedPtr<LearnedAttack>& attack,
|
ArbUt::BorrowedPtr<Creature> user, const ArbUt::BorrowedPtr<LearnedAttack>& attack,
|
||||||
const std::unique_ptr<Script>& script)
|
const std::unique_ptr<Script>& script)
|
||||||
: _numberHits(numberHits), _hits(std::make_unique<HitData[]>(targets.Count() * numberHits)), _user(user),
|
: _numberHits(numberHits), _hits(std::make_unique<HitData[]>(targets.Count() * numberHits)), _user(user),
|
||||||
|
@ -55,7 +55,10 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
HitData& GetHitData(ArbUt::BorrowedPtr<Creature> creature, uint8_t hit) {
|
HitData& GetHitData(ArbUt::BorrowedPtr<Creature> creature, uint8_t hit) {
|
||||||
for (uint8_t i = 0; i < _targets.Count(); i++) {
|
for (uint8_t i = 0; i < _targets.Count(); i++) {
|
||||||
if (_targets[i] == creature) {
|
if (!_targets[i].HasValue()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_targets[i].GetValue() == creature) {
|
||||||
return _hits[i * _numberHits + hit];
|
return _hits[i * _numberHits + hit];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +67,10 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
HitData* GetTargetIteratorBegin(ArbUt::BorrowedPtr<Creature> creature) {
|
HitData* GetTargetIteratorBegin(ArbUt::BorrowedPtr<Creature> creature) {
|
||||||
for (uint8_t i = 0; i < _targets.Count(); i++) {
|
for (uint8_t i = 0; i < _targets.Count(); i++) {
|
||||||
if (_targets[i] == creature) {
|
if (!_targets[i].HasValue()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_targets[i].GetValue() == creature) {
|
||||||
return &_hits[i * _numberHits];
|
return &_hits[i * _numberHits];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +79,10 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
bool IsCreatureTarget(ArbUt::BorrowedPtr<Creature> creature) noexcept {
|
bool IsCreatureTarget(ArbUt::BorrowedPtr<Creature> creature) noexcept {
|
||||||
for (uint8_t i = 0; i < _targets.Count(); i++) {
|
for (uint8_t i = 0; i < _targets.Count(); i++) {
|
||||||
if (_targets[i] == creature) {
|
if (!_targets[i].HasValue()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_targets[i].GetValue() == creature) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +91,7 @@ namespace CreatureLib::Battling {
|
||||||
|
|
||||||
inline uint8_t GetTargetCount() const noexcept { return _targets.Count(); }
|
inline uint8_t GetTargetCount() const noexcept { return _targets.Count(); }
|
||||||
|
|
||||||
inline const ArbUt::List<ArbUt::BorrowedPtr<Creature>>& GetTargets() const noexcept { return _targets; }
|
inline const ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>& GetTargets() const noexcept { return _targets; }
|
||||||
inline uint8_t GetNumberOfHits() const noexcept { return _numberHits; }
|
inline uint8_t GetNumberOfHits() const noexcept { return _numberHits; }
|
||||||
|
|
||||||
inline const ArbUt::BorrowedPtr<Creature>& GetUser() noexcept { return _user; }
|
inline const ArbUt::BorrowedPtr<Creature>& GetUser() noexcept { return _user; }
|
||||||
|
|
|
@ -45,14 +45,14 @@ namespace CreatureLib::Battling {
|
||||||
}
|
}
|
||||||
inline bool HasNext() { return _index < _size; }
|
inline bool HasNext() { return _index < _size; }
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<Script> GetNextNotNull() {
|
std::optional<ArbUt::BorrowedPtr<Script>> GetNextNotNull() {
|
||||||
while (HasNext()) {
|
while (HasNext()) {
|
||||||
auto s = GetNext();
|
auto s = GetNext();
|
||||||
if (s != nullptr) {
|
if (s != nullptr) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<Script> GetNext() {
|
ArbUt::BorrowedPtr<Script> GetNext() {
|
||||||
|
|
|
@ -27,14 +27,16 @@ namespace CreatureLib::Battling {
|
||||||
_lookup.Insert(script->GetName(), _scripts.Count() - 1);
|
_lookup.Insert(script->GetName(), _scripts.Count() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<Script> Get(const ArbUt::BasicStringView& key) const { return Get(key.GetHash()); }
|
std::optional<ArbUt::BorrowedPtr<Script>> Get(const ArbUt::BasicStringView& key) const {
|
||||||
|
return Get(key.GetHash());
|
||||||
|
}
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<Script> Get(uint32_t keyHash) const noexcept {
|
std::optional<ArbUt::BorrowedPtr<Script>> Get(uint32_t keyHash) const noexcept {
|
||||||
size_t v;
|
size_t v;
|
||||||
if (_lookup.TryGet(keyHash, v)) {
|
if (_lookup.TryGet(keyHash, v)) {
|
||||||
return _scripts[v];
|
return _scripts[v];
|
||||||
}
|
}
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Remove(const ArbUt::BasicStringView& key) { Remove(key.GetHash()); }
|
void Remove(const ArbUt::BasicStringView& key) { Remove(key.GetHash()); }
|
||||||
|
|
|
@ -22,9 +22,9 @@ namespace CreatureLib::Battling {
|
||||||
if (user == nullptr)
|
if (user == nullptr)
|
||||||
return;
|
return;
|
||||||
auto battle = user->GetBattle();
|
auto battle = user->GetBattle();
|
||||||
if (battle != nullptr) {
|
if (battle.HasValue()) {
|
||||||
if (_attack->GetAttack()->HasSecondaryEffect()) {
|
if (_attack->GetAttack()->HasSecondaryEffect()) {
|
||||||
auto library = battle->GetLibrary();
|
auto library = battle.GetValue()->GetLibrary();
|
||||||
auto& effect = _attack->GetAttack()->GetSecondaryEffect();
|
auto& effect = _attack->GetAttack()->GetSecondaryEffect();
|
||||||
_attackScript =
|
_attackScript =
|
||||||
std::unique_ptr<Script>(library->LoadScript(ScriptCategory::Attack, effect->GetEffectName()));
|
std::unique_ptr<Script>(library->LoadScript(ScriptCategory::Attack, effect->GetEffectName()));
|
||||||
|
|
|
@ -4,15 +4,15 @@
|
||||||
#include "BaseTurnChoice.hpp"
|
#include "BaseTurnChoice.hpp"
|
||||||
namespace CreatureLib::Battling {
|
namespace CreatureLib::Battling {
|
||||||
class SwitchTurnChoice : public BaseTurnChoice {
|
class SwitchTurnChoice : public BaseTurnChoice {
|
||||||
ArbUt::BorrowedPtr<Creature> _newCreature;
|
ArbUt::OptionalBorrowedPtr<Creature> _newCreature;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SwitchTurnChoice(ArbUt::BorrowedPtr<Creature> user, ArbUt::BorrowedPtr<Creature> newCreature) noexcept
|
SwitchTurnChoice(ArbUt::BorrowedPtr<Creature> user, ArbUt::OptionalBorrowedPtr<Creature> newCreature) noexcept
|
||||||
: BaseTurnChoice(user), _newCreature(newCreature) {}
|
: BaseTurnChoice(user), _newCreature(newCreature) {}
|
||||||
|
|
||||||
TurnChoiceKind GetKind() const noexcept final { return TurnChoiceKind::Switch; }
|
TurnChoiceKind GetKind() const noexcept final { return TurnChoiceKind::Switch; }
|
||||||
|
|
||||||
inline const ArbUt::BorrowedPtr<Creature>& GetNewCreature() const noexcept { return _newCreature; }
|
inline const ArbUt::OptionalBorrowedPtr<Creature>& GetNewCreature() const noexcept { return _newCreature; }
|
||||||
size_t ScriptCount() const override { return GetUser()->ScriptCount(); }
|
size_t ScriptCount() const override { return GetUser()->ScriptCount(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -36,9 +36,9 @@ namespace CreatureLib::Library {
|
||||||
return _distinctLevelAttacks;
|
return _distinctLevelAttacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<const AttackData> GetRandomAttack(ArbUt::Random& rand) const {
|
std::optional<ArbUt::BorrowedPtr<const AttackData>> GetRandomAttack(ArbUt::Random& rand) const {
|
||||||
if (_distinctLevelAttacks.Count() == 0) {
|
if (_distinctLevelAttacks.Count() == 0) {
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
auto val = rand.Get(_distinctLevelAttacks.Count());
|
auto val = rand.Get(_distinctLevelAttacks.Count());
|
||||||
auto it = _distinctLevelAttacks.begin();
|
auto it = _distinctLevelAttacks.begin();
|
||||||
|
@ -64,7 +64,7 @@ namespace CreatureLib::Library {
|
||||||
LearnableAttacks::GetDistinctLevelAttacks() const noexcept {
|
LearnableAttacks::GetDistinctLevelAttacks() const noexcept {
|
||||||
return _impl->GetDistinctLevelAttacks();
|
return _impl->GetDistinctLevelAttacks();
|
||||||
}
|
}
|
||||||
ArbUt::BorrowedPtr<const AttackData> LearnableAttacks::GetRandomAttack(ArbUt::Random& rand) const {
|
std::optional<ArbUt::BorrowedPtr<const AttackData>> LearnableAttacks::GetRandomAttack(ArbUt::Random& rand) const {
|
||||||
return _impl->GetRandomAttack(rand);
|
return _impl->GetRandomAttack(rand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace CreatureLib::Library {
|
||||||
/// @brief Returns a random attack that can be learned.
|
/// @brief Returns a random attack that can be learned.
|
||||||
/// @param rand A random number generator.
|
/// @param rand A random number generator.
|
||||||
/// @return A random attack that can be learned.
|
/// @return A random attack that can be learned.
|
||||||
virtual ArbUt::BorrowedPtr<const AttackData> GetRandomAttack(ArbUt::Random& rand) const;
|
virtual std::optional<ArbUt::BorrowedPtr<const AttackData>> GetRandomAttack(ArbUt::Random& rand) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,7 @@
|
||||||
#include <Arbutils/Collections/List.hpp>
|
#include <Arbutils/Collections/List.hpp>
|
||||||
#include <Arbutils/Enum.hpp>
|
#include <Arbutils/Enum.hpp>
|
||||||
#include <Arbutils/Exception.hpp>
|
#include <Arbutils/Exception.hpp>
|
||||||
#include <Arbutils/Memory/BorrowedPtr.hpp>
|
#include <Arbutils/Memory/Memory.hpp>
|
||||||
#include <Arbutils/Memory/UniquePtrList.hpp>
|
|
||||||
#include <Arbutils/Precompiled.hxx>
|
#include <Arbutils/Precompiled.hxx>
|
||||||
#include <Arbutils/StringView.hpp>
|
#include <Arbutils/StringView.hpp>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifdef TESTS_BUILD
|
#ifdef TESTS_BUILD
|
||||||
|
|
||||||
#include "../../extern/doctest.hpp"
|
#include "../../extern/doctest.hpp"
|
||||||
|
#include "../../src/Battling/Models/Battle.hpp"
|
||||||
#include "../../src/Battling/Models/BattleSide.hpp"
|
#include "../../src/Battling/Models/BattleSide.hpp"
|
||||||
#include "../../src/Battling/Models/CreateCreature.hpp"
|
#include "../../src/Battling/Models/CreateCreature.hpp"
|
||||||
#include "../../src/Battling/TurnChoices/PassTurnChoice.hpp"
|
#include "../../src/Battling/TurnChoices/PassTurnChoice.hpp"
|
||||||
|
@ -9,7 +10,9 @@
|
||||||
using namespace CreatureLib::Battling;
|
using namespace CreatureLib::Battling;
|
||||||
|
|
||||||
TEST_CASE("Set Choice one-sized side") {
|
TEST_CASE("Set Choice one-sized side") {
|
||||||
auto side = BattleSide(0, nullptr, 1);
|
auto lib = TestLibrary::Get();
|
||||||
|
auto battle = Battle(lib, {});
|
||||||
|
auto side = BattleSide(0, &battle, 1);
|
||||||
auto c = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
auto c = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
||||||
side.SetCreature(c, 0);
|
side.SetCreature(c, 0);
|
||||||
auto choice = new PassTurnChoice(c);
|
auto choice = new PassTurnChoice(c);
|
||||||
|
@ -18,7 +21,9 @@ TEST_CASE("Set Choice one-sized side") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Set Choice one-sized side, validate all choices set") {
|
TEST_CASE("Set Choice one-sized side, validate all choices set") {
|
||||||
auto side = BattleSide(0, nullptr, 1);
|
auto lib = TestLibrary::Get();
|
||||||
|
auto battle = Battle(lib, {});
|
||||||
|
auto side = BattleSide(0, &battle, 1);
|
||||||
auto c = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
auto c = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
||||||
side.SetCreature(c, 0);
|
side.SetCreature(c, 0);
|
||||||
auto choice = new PassTurnChoice(c);
|
auto choice = new PassTurnChoice(c);
|
||||||
|
@ -29,7 +34,9 @@ TEST_CASE("Set Choice one-sized side, validate all choices set") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Set Choice two-sized side") {
|
TEST_CASE("Set Choice two-sized side") {
|
||||||
auto side = BattleSide(0, nullptr, 2);
|
auto lib = TestLibrary::Get();
|
||||||
|
auto battle = Battle(lib, {});
|
||||||
|
auto side = BattleSide(0, &battle, 2);
|
||||||
auto c1 = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
auto c1 = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
||||||
auto c2 = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
auto c2 = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
||||||
side.SetCreature(c1, 0);
|
side.SetCreature(c1, 0);
|
||||||
|
@ -43,7 +50,9 @@ TEST_CASE("Set Choice two-sized side") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Set Choice two-sized side, validate all choices set") {
|
TEST_CASE("Set Choice two-sized side, validate all choices set") {
|
||||||
auto side = BattleSide(0, nullptr, 2);
|
auto lib = TestLibrary::Get();
|
||||||
|
auto battle = Battle(lib, {});
|
||||||
|
auto side = BattleSide(0, &battle, 2);
|
||||||
auto c1 = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
auto c1 = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
||||||
auto c2 = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
auto c2 = CreateCreature(TestLibrary::Get(), "testSpecies1"_cnc, 5).Create();
|
||||||
side.SetCreature(c1, 0);
|
side.SetCreature(c1, 0);
|
||||||
|
|
|
@ -12,7 +12,7 @@ TEST_CASE("Build and use event hook") {
|
||||||
std::vector<const EventData*> events;
|
std::vector<const EventData*> events;
|
||||||
eventHook.RegisterListener([&](const EventData* evt) mutable -> void { events.push_back(evt); });
|
eventHook.RegisterListener([&](const EventData* evt) mutable -> void { events.push_back(evt); });
|
||||||
for (size_t i = 0; i < 10; i++) {
|
for (size_t i = 0; i < 10; i++) {
|
||||||
eventHook.Trigger<DamageEvent>(nullptr, DamageSource::AttackDamage, 0, 0);
|
eventHook.Trigger<DamageEvent>((Creature*)1, DamageSource::AttackDamage, 0, 0);
|
||||||
}
|
}
|
||||||
REQUIRE(events.size() == 10);
|
REQUIRE(events.size() == 10);
|
||||||
REQUIRE(events[0]->GetKind() == EventDataKind::Damage);
|
REQUIRE(events[0]->GetKind() == EventDataKind::Damage);
|
||||||
|
@ -23,7 +23,7 @@ TEST_CASE("Build and use event hook a lot") {
|
||||||
std::vector<const EventData*> events;
|
std::vector<const EventData*> events;
|
||||||
eventHook.RegisterListener([&](const EventData* evt) mutable -> void { events.push_back(evt); });
|
eventHook.RegisterListener([&](const EventData* evt) mutable -> void { events.push_back(evt); });
|
||||||
for (size_t i = 0; i < 10000; i++) {
|
for (size_t i = 0; i < 10000; i++) {
|
||||||
eventHook.Trigger<DamageEvent>(nullptr, DamageSource::AttackDamage, 0, 0);
|
eventHook.Trigger<DamageEvent>((Creature*)1, DamageSource::AttackDamage, 0, 0);
|
||||||
}
|
}
|
||||||
REQUIRE(events.size() == 10000);
|
REQUIRE(events.size() == 10000);
|
||||||
}
|
}
|
||||||
|
@ -32,13 +32,13 @@ TEST_CASE("Build and use event hook with different types") {
|
||||||
auto eventHook = EventHook();
|
auto eventHook = EventHook();
|
||||||
std::vector<const EventData*> events;
|
std::vector<const EventData*> events;
|
||||||
eventHook.RegisterListener([&](const EventData* evt) mutable -> void { events.push_back(evt); });
|
eventHook.RegisterListener([&](const EventData* evt) mutable -> void { events.push_back(evt); });
|
||||||
eventHook.Trigger<DamageEvent>(nullptr, DamageSource::AttackDamage, 0, 0);
|
eventHook.Trigger<DamageEvent>((Creature*)1, DamageSource::AttackDamage, 0, 0);
|
||||||
eventHook.Trigger<FaintEvent>(nullptr);
|
eventHook.Trigger<FaintEvent>((Creature*)1);
|
||||||
eventHook.Trigger<DamageEvent>(nullptr, DamageSource::AttackDamage, 0, 0);
|
eventHook.Trigger<DamageEvent>((Creature*)1, DamageSource::AttackDamage, 0, 0);
|
||||||
eventHook.Trigger<FaintEvent>(nullptr);
|
eventHook.Trigger<FaintEvent>((Creature*)1);
|
||||||
eventHook.Trigger<DamageEvent>(nullptr, DamageSource::AttackDamage, 0, 0);
|
eventHook.Trigger<DamageEvent>((Creature*)1, DamageSource::AttackDamage, 0, 0);
|
||||||
eventHook.Trigger<FaintEvent>(nullptr);
|
eventHook.Trigger<FaintEvent>((Creature*)1);
|
||||||
eventHook.Trigger<DamageEvent>(nullptr, DamageSource::AttackDamage, 0, 0);
|
eventHook.Trigger<DamageEvent>((Creature*)1, DamageSource::AttackDamage, 0, 0);
|
||||||
eventHook.Trigger<FaintEvent>(nullptr);
|
eventHook.Trigger<FaintEvent>((Creature*)1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
|
@ -26,7 +26,6 @@ TEST_CASE("Script Aggregator properly iterates containing script.") {
|
||||||
auto aggr = ScriptAggregator(vec);
|
auto aggr = ScriptAggregator(vec);
|
||||||
while (aggr.HasNext()) {
|
while (aggr.HasNext()) {
|
||||||
auto next = aggr.GetNext();
|
auto next = aggr.GetNext();
|
||||||
REQUIRE(next != nullptr);
|
|
||||||
next.As<TestScript>()->TestMethod(ran);
|
next.As<TestScript>()->TestMethod(ran);
|
||||||
}
|
}
|
||||||
CHECK(ran == 1);
|
CHECK(ran == 1);
|
||||||
|
@ -44,7 +43,6 @@ TEST_CASE("Script Aggregator properly iterates multiple scripts.") {
|
||||||
auto aggr = ScriptAggregator(vec);
|
auto aggr = ScriptAggregator(vec);
|
||||||
while (aggr.HasNext()) {
|
while (aggr.HasNext()) {
|
||||||
auto next = aggr.GetNext();
|
auto next = aggr.GetNext();
|
||||||
REQUIRE(next != nullptr);
|
|
||||||
next.As<TestScript>()->TestMethod(ran);
|
next.As<TestScript>()->TestMethod(ran);
|
||||||
}
|
}
|
||||||
CHECK(ran == 3);
|
CHECK(ran == 3);
|
||||||
|
@ -63,8 +61,7 @@ TEST_CASE("Script Aggregator properly iterates Script Set.") {
|
||||||
auto aggr = ScriptAggregator(vec);
|
auto aggr = ScriptAggregator(vec);
|
||||||
while (aggr.HasNext()) {
|
while (aggr.HasNext()) {
|
||||||
auto next = aggr.GetNextNotNull();
|
auto next = aggr.GetNextNotNull();
|
||||||
REQUIRE(next != nullptr);
|
next.value().As<TestScript>()->TestMethod(ran);
|
||||||
next.As<TestScript>()->TestMethod(ran);
|
|
||||||
}
|
}
|
||||||
CHECK(ran == 3);
|
CHECK(ran == 3);
|
||||||
}
|
}
|
||||||
|
@ -82,8 +79,7 @@ TEST_CASE("Script Aggregator properly iterates data of Script Set and Script.")
|
||||||
auto aggr = ScriptAggregator(vec);
|
auto aggr = ScriptAggregator(vec);
|
||||||
while (aggr.HasNext()) {
|
while (aggr.HasNext()) {
|
||||||
auto next = aggr.GetNextNotNull();
|
auto next = aggr.GetNextNotNull();
|
||||||
REQUIRE(next != nullptr);
|
next.value().As<TestScript>()->TestMethod(ran);
|
||||||
next.As<TestScript>()->TestMethod(ran);
|
|
||||||
}
|
}
|
||||||
CHECK(ran == 3);
|
CHECK(ran == 3);
|
||||||
}
|
}
|
||||||
|
@ -101,8 +97,7 @@ TEST_CASE("Script Aggregator properly iterates data of Script and Script Set.")
|
||||||
auto aggr = ScriptAggregator(vec);
|
auto aggr = ScriptAggregator(vec);
|
||||||
while (aggr.HasNext()) {
|
while (aggr.HasNext()) {
|
||||||
auto next = aggr.GetNextNotNull();
|
auto next = aggr.GetNextNotNull();
|
||||||
REQUIRE(next != nullptr);
|
next.value().As<TestScript>()->TestMethod(ran);
|
||||||
next.As<TestScript>()->TestMethod(ran);
|
|
||||||
}
|
}
|
||||||
CHECK(ran == 3);
|
CHECK(ran == 3);
|
||||||
}
|
}
|
||||||
|
@ -122,8 +117,7 @@ TEST_CASE("Script Aggregator properly iterates data of Script, Script Set and Sc
|
||||||
auto aggr = ScriptAggregator(vec);
|
auto aggr = ScriptAggregator(vec);
|
||||||
while (aggr.HasNext()) {
|
while (aggr.HasNext()) {
|
||||||
auto next = aggr.GetNextNotNull();
|
auto next = aggr.GetNextNotNull();
|
||||||
REQUIRE(next != nullptr);
|
next.value().As<TestScript>()->TestMethod(ran);
|
||||||
next.As<TestScript>()->TestMethod(ran);
|
|
||||||
}
|
}
|
||||||
CHECK(ran == 4);
|
CHECK(ran == 4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,8 +76,8 @@ TEST_CASE("Script source with single item script set.") {
|
||||||
source.Set.Add(s);
|
source.Set.Add(s);
|
||||||
auto scripts = source.GetScriptIterator();
|
auto scripts = source.GetScriptIterator();
|
||||||
auto first = scripts.GetNextNotNull();
|
auto first = scripts.GetNextNotNull();
|
||||||
CHECK(first != nullptr);
|
REQUIRE(first.has_value());
|
||||||
CHECK(first->GetName() == "foobar");
|
CHECK(first.value()->GetName() == "foobar");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Script source with multiple item script set.") {
|
TEST_CASE("Script source with multiple item script set.") {
|
||||||
|
@ -88,11 +88,11 @@ TEST_CASE("Script source with multiple item script set.") {
|
||||||
source.Set.Add(s2);
|
source.Set.Add(s2);
|
||||||
auto scripts = source.GetScriptIterator();
|
auto scripts = source.GetScriptIterator();
|
||||||
auto first = scripts.GetNextNotNull();
|
auto first = scripts.GetNextNotNull();
|
||||||
REQUIRE(first != nullptr);
|
REQUIRE(first.has_value());
|
||||||
CHECK(first->GetName() == "foobar");
|
CHECK(first.value()->GetName() == "foobar");
|
||||||
auto second = scripts.GetNextNotNull();
|
auto second = scripts.GetNextNotNull();
|
||||||
REQUIRE(second != nullptr);
|
REQUIRE(second.has_value());
|
||||||
CHECK(second->GetName() == "foobar2");
|
CHECK(second.value()->GetName() == "foobar2");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "../../extern/doctest.hpp"
|
#include "../../extern/doctest.hpp"
|
||||||
#include "../../src/Battling/Flow/TurnOrdering.hpp"
|
#include "../../src/Battling/Flow/TurnOrdering.hpp"
|
||||||
|
#include "../../src/Battling/Models/CreateCreature.hpp"
|
||||||
#include "../../src/Battling/TurnChoices/AttackTurnChoice.hpp"
|
#include "../../src/Battling/TurnChoices/AttackTurnChoice.hpp"
|
||||||
#include "../../src/Battling/TurnChoices/PassTurnChoice.hpp"
|
#include "../../src/Battling/TurnChoices/PassTurnChoice.hpp"
|
||||||
#include "../TestLibrary/TestLibrary.hpp"
|
#include "../TestLibrary/TestLibrary.hpp"
|
||||||
|
@ -13,8 +14,10 @@ TEST_CASE("Turn ordering: Attack before pass") {
|
||||||
auto lib = TestLibrary::Get();
|
auto lib = TestLibrary::Get();
|
||||||
auto learnedAttack =
|
auto learnedAttack =
|
||||||
LearnedAttack(lib->GetAttackLibrary()->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
LearnedAttack(lib->GetAttackLibrary()->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
||||||
auto choice1 = std::make_shared<PassTurnChoice>(nullptr);
|
auto creature = CreateCreature(lib, "testSpecies1"_cnc, 1).Create();
|
||||||
auto choice2 = std::make_shared<AttackTurnChoice>(nullptr, &learnedAttack, CreatureIndex(0, 0));
|
|
||||||
|
auto choice1 = std::make_shared<PassTurnChoice>(creature);
|
||||||
|
auto choice2 = std::make_shared<AttackTurnChoice>(creature, &learnedAttack, CreatureIndex(0, 0));
|
||||||
auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
|
auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
|
||||||
TurnOrdering::OrderChoices(vec);
|
TurnOrdering::OrderChoices(vec);
|
||||||
CHECK(vec[0] == choice2);
|
CHECK(vec[0] == choice2);
|
||||||
|
@ -23,14 +26,18 @@ TEST_CASE("Turn ordering: Attack before pass") {
|
||||||
TurnOrdering::OrderChoices(vec);
|
TurnOrdering::OrderChoices(vec);
|
||||||
CHECK(vec[0] == choice2);
|
CHECK(vec[0] == choice2);
|
||||||
CHECK(vec[1] == choice1);
|
CHECK(vec[1] == choice1);
|
||||||
|
delete creature;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Turn ordering: High priority goes before no priority") {
|
TEST_CASE("Turn ordering: High priority goes before no priority") {
|
||||||
const auto& l = TestLibrary::Get()->GetAttackLibrary();
|
auto lib = TestLibrary::Get();
|
||||||
|
const auto& l = lib->GetAttackLibrary();
|
||||||
auto a1 = new LearnedAttack(l->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
auto a1 = new LearnedAttack(l->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
||||||
auto a2 = new LearnedAttack(l->Get("highPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
auto a2 = new LearnedAttack(l->Get("highPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
||||||
auto choice1 = std::make_shared<AttackTurnChoice>(nullptr, a1, CreatureIndex(0, 0));
|
auto creature = CreateCreature(lib, "testSpecies1"_cnc, 1).Create();
|
||||||
auto choice2 = std::make_shared<AttackTurnChoice>(nullptr, a2, CreatureIndex(0, 0));
|
|
||||||
|
auto choice1 = std::make_shared<AttackTurnChoice>(creature, a1, CreatureIndex(0, 0));
|
||||||
|
auto choice2 = std::make_shared<AttackTurnChoice>(creature, a2, CreatureIndex(0, 0));
|
||||||
auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
|
auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
|
||||||
TurnOrdering::OrderChoices(vec);
|
TurnOrdering::OrderChoices(vec);
|
||||||
CHECK(vec[0] == choice2);
|
CHECK(vec[0] == choice2);
|
||||||
|
@ -42,14 +49,17 @@ TEST_CASE("Turn ordering: High priority goes before no priority") {
|
||||||
|
|
||||||
delete a1;
|
delete a1;
|
||||||
delete a2;
|
delete a2;
|
||||||
|
delete creature;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Turn ordering: Higher priority goes before high priority") {
|
TEST_CASE("Turn ordering: Higher priority goes before high priority") {
|
||||||
const auto& l = TestLibrary::Get()->GetAttackLibrary();
|
auto lib = TestLibrary::Get();
|
||||||
|
const auto& l = lib->GetAttackLibrary();
|
||||||
auto a1 = new LearnedAttack(l->Get("highPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
auto a1 = new LearnedAttack(l->Get("highPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
||||||
auto a2 = new LearnedAttack(l->Get("higherPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
auto a2 = new LearnedAttack(l->Get("higherPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
||||||
auto choice1 = std::make_shared<AttackTurnChoice>(nullptr, a1, CreatureIndex(0, 0));
|
auto creature = CreateCreature(lib, "testSpecies1"_cnc, 1).Create();
|
||||||
auto choice2 = std::make_shared<AttackTurnChoice>(nullptr, a2, CreatureIndex(0, 0));
|
auto choice1 = std::make_shared<AttackTurnChoice>(creature, a1, CreatureIndex(0, 0));
|
||||||
|
auto choice2 = std::make_shared<AttackTurnChoice>(creature, a2, CreatureIndex(0, 0));
|
||||||
auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
|
auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
|
||||||
TurnOrdering::OrderChoices(vec);
|
TurnOrdering::OrderChoices(vec);
|
||||||
CHECK(vec[0] == choice2);
|
CHECK(vec[0] == choice2);
|
||||||
|
@ -60,14 +70,18 @@ TEST_CASE("Turn ordering: Higher priority goes before high priority") {
|
||||||
CHECK(vec[1] == choice1);
|
CHECK(vec[1] == choice1);
|
||||||
delete a1;
|
delete a1;
|
||||||
delete a2;
|
delete a2;
|
||||||
|
delete creature;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Turn ordering: High priority goes before low priority") {
|
TEST_CASE("Turn ordering: High priority goes before low priority") {
|
||||||
const auto& l = TestLibrary::Get()->GetAttackLibrary();
|
auto lib = TestLibrary::Get();
|
||||||
|
const auto& l = lib->GetAttackLibrary();
|
||||||
auto a1 = new LearnedAttack(l->Get("lowPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
auto a1 = new LearnedAttack(l->Get("lowPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
||||||
auto a2 = new LearnedAttack(l->Get("higherPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
auto a2 = new LearnedAttack(l->Get("higherPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
||||||
auto choice1 = std::make_shared<AttackTurnChoice>(nullptr, a1, CreatureIndex(0, 0));
|
auto creature = CreateCreature(lib, "testSpecies1"_cnc, 1).Create();
|
||||||
auto choice2 = std::make_shared<AttackTurnChoice>(nullptr, a2, CreatureIndex(0, 0));
|
|
||||||
|
auto choice1 = std::make_shared<AttackTurnChoice>(creature, a1, CreatureIndex(0, 0));
|
||||||
|
auto choice2 = std::make_shared<AttackTurnChoice>(creature, a2, CreatureIndex(0, 0));
|
||||||
auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
|
auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
|
||||||
TurnOrdering::OrderChoices(vec);
|
TurnOrdering::OrderChoices(vec);
|
||||||
CHECK(vec[0] == choice2);
|
CHECK(vec[0] == choice2);
|
||||||
|
@ -79,14 +93,17 @@ TEST_CASE("Turn ordering: High priority goes before low priority") {
|
||||||
|
|
||||||
delete a1;
|
delete a1;
|
||||||
delete a2;
|
delete a2;
|
||||||
|
delete creature;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Turn ordering: No priority goes before low priority") {
|
TEST_CASE("Turn ordering: No priority goes before low priority") {
|
||||||
const auto& l = TestLibrary::Get()->GetAttackLibrary();
|
auto lib = TestLibrary::Get();
|
||||||
|
const auto& l = lib->GetAttackLibrary();
|
||||||
auto a1 = new LearnedAttack(l->Get("lowPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
auto a1 = new LearnedAttack(l->Get("lowPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
||||||
auto a2 = new LearnedAttack(l->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
auto a2 = new LearnedAttack(l->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown);
|
||||||
auto choice1 = std::make_shared<AttackTurnChoice>(nullptr, a1, CreatureIndex(0, 0));
|
auto creature = CreateCreature(lib, "testSpecies1"_cnc, 1).Create();
|
||||||
auto choice2 = std::make_shared<AttackTurnChoice>(nullptr, a2, CreatureIndex(0, 0));
|
auto choice1 = std::make_shared<AttackTurnChoice>(creature, a1, CreatureIndex(0, 0));
|
||||||
|
auto choice2 = std::make_shared<AttackTurnChoice>(creature, a2, CreatureIndex(0, 0));
|
||||||
auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
|
auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
|
||||||
TurnOrdering::OrderChoices(vec);
|
TurnOrdering::OrderChoices(vec);
|
||||||
CHECK(vec[0] == choice2);
|
CHECK(vec[0] == choice2);
|
||||||
|
@ -98,6 +115,7 @@ TEST_CASE("Turn ordering: No priority goes before low priority") {
|
||||||
|
|
||||||
delete a1;
|
delete a1;
|
||||||
delete a2;
|
delete a2;
|
||||||
|
delete creature;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue