Implements creature switching as turn choice.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
2ee181bca7
commit
c25d7b865e
|
@ -43,8 +43,9 @@ void TurnHandler::ExecuteChoice(BaseTurnChoice* choice) {
|
||||||
switch (choiceKind) {
|
switch (choiceKind) {
|
||||||
case TurnChoiceKind::Pass: throw NotReachableException();
|
case TurnChoiceKind::Pass: throw NotReachableException();
|
||||||
case TurnChoiceKind::Attack: return ExecuteAttackChoice(dynamic_cast<AttackTurnChoice*>(choice));
|
case TurnChoiceKind::Attack: return ExecuteAttackChoice(dynamic_cast<AttackTurnChoice*>(choice));
|
||||||
|
case TurnChoiceKind::Switch: return ExecuteSwitchChoice(dynamic_cast<SwitchTurnChoice*>(choice));
|
||||||
|
|
||||||
case TurnChoiceKind::Item:
|
case TurnChoiceKind::Item:
|
||||||
case TurnChoiceKind::Switch:
|
|
||||||
case TurnChoiceKind::RunAway: throw NotImplementedException();
|
case TurnChoiceKind::RunAway: throw NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,3 +166,18 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, Creature* targe
|
||||||
HOOK(OnAfterHits, userSource, attack, target);
|
HOOK(OnAfterHits, userSource, attack, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TurnHandler::ExecuteSwitchChoice(CreatureLib::Battling::SwitchTurnChoice* choice) {
|
||||||
|
bool preventSwitch = false;
|
||||||
|
HOOK(PreventSelfSwitch, choice, choice, preventSwitch);
|
||||||
|
if (preventSwitch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// HOOK: PreventOpponentSwitch for each opponent.
|
||||||
|
|
||||||
|
auto user = choice->GetUser();
|
||||||
|
user->ClearVolatileScripts();
|
||||||
|
auto userSide = user->GetBattleSide();
|
||||||
|
auto userIndex = userSide->GetCreatureIndex(user);
|
||||||
|
userSide->SetCreature(choice->GetNewCreature(), userIndex);
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "../Models/ExecutingAttack.hpp"
|
#include "../Models/ExecutingAttack.hpp"
|
||||||
#include "../TurnChoices/AttackTurnChoice.hpp"
|
#include "../TurnChoices/AttackTurnChoice.hpp"
|
||||||
|
#include "../TurnChoices/SwitchTurnChoice.hpp"
|
||||||
#include "ChoiceQueue.hpp"
|
#include "ChoiceQueue.hpp"
|
||||||
|
|
||||||
namespace CreatureLib::Battling {
|
namespace CreatureLib::Battling {
|
||||||
|
@ -15,6 +16,8 @@ namespace CreatureLib::Battling {
|
||||||
static void HandleAttackForTarget(ExecutingAttack* attack, Creature* target,
|
static void HandleAttackForTarget(ExecutingAttack* attack, Creature* target,
|
||||||
ExecutingAttack::TargetData* targetData);
|
ExecutingAttack::TargetData* targetData);
|
||||||
|
|
||||||
|
static void ExecuteSwitchChoice(SwitchTurnChoice* choice);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void RunTurn(Battle* battle, ChoiceQueue* queue);
|
static void RunTurn(Battle* battle, ChoiceQueue* queue);
|
||||||
};
|
};
|
||||||
|
|
|
@ -129,3 +129,4 @@ void Battling::Creature::GetActiveScripts(std::vector<ScriptWrapper>& scripts) {
|
||||||
scripts.emplace_back(&_volatile);
|
scripts.emplace_back(&_volatile);
|
||||||
_side->GetActiveScripts(scripts);
|
_side->GetActiveScripts(scripts);
|
||||||
}
|
}
|
||||||
|
void Battling::Creature::ClearVolatileScripts() { _volatile.Clear(); }
|
||||||
|
|
|
@ -84,6 +84,7 @@ namespace CreatureLib::Battling {
|
||||||
void OverrideActiveTalent(const std::string& talent);
|
void OverrideActiveTalent(const std::string& talent);
|
||||||
|
|
||||||
void GetActiveScripts(std::vector<ScriptWrapper>& scripts) override;
|
void GetActiveScripts(std::vector<ScriptWrapper>& scripts) override;
|
||||||
|
void ClearVolatileScripts();
|
||||||
|
|
||||||
std::vector<LearnedAttack*>& GetAttacks() { return _attacks; }
|
std::vector<LearnedAttack*>& GetAttacks() { return _attacks; }
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
namespace CreatureLib::Battling {
|
namespace CreatureLib::Battling {
|
||||||
class BaseTurnChoice;
|
class BaseTurnChoice;
|
||||||
class AttackTurnChoice;
|
class AttackTurnChoice;
|
||||||
|
class SwitchTurnChoice;
|
||||||
class ExecutingAttack;
|
class ExecutingAttack;
|
||||||
class Creature;
|
class Creature;
|
||||||
|
|
||||||
|
@ -41,6 +42,8 @@ namespace CreatureLib::Battling {
|
||||||
virtual void OnSecondaryEffect(const ExecutingAttack* attack, Creature* target, uint8_t hitNumber){};
|
virtual void OnSecondaryEffect(const ExecutingAttack* attack, Creature* target, uint8_t hitNumber){};
|
||||||
|
|
||||||
virtual void OnAfterHits(const ExecutingAttack* attack, Creature* target){};
|
virtual void OnAfterHits(const ExecutingAttack* attack, Creature* target){};
|
||||||
|
|
||||||
|
virtual void PreventSelfSwitch(const SwitchTurnChoice* choice, bool& result){};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,11 @@ namespace CreatureLib::Battling {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Clear() {
|
||||||
|
_scripts.clear();
|
||||||
|
_lookup.clear();
|
||||||
|
}
|
||||||
|
|
||||||
size_t Count() const { return _scripts.size(); }
|
size_t Count() const { return _scripts.size(); }
|
||||||
|
|
||||||
const std::vector<Script*>* GetIterator() const { return &_scripts; }
|
const std::vector<Script*>* GetIterator() const { return &_scripts; }
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef CREATURELIB_SWITCHTURNCHOICE_HPP
|
||||||
|
#define CREATURELIB_SWITCHTURNCHOICE_HPP
|
||||||
|
|
||||||
|
#include "BaseTurnChoice.hpp"
|
||||||
|
namespace CreatureLib::Battling {
|
||||||
|
class SwitchTurnChoice : public BaseTurnChoice {
|
||||||
|
Creature* _newCreature;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SwitchTurnChoice(Creature* user, Creature* newCreature) : BaseTurnChoice(user), _newCreature(newCreature) {}
|
||||||
|
|
||||||
|
TurnChoiceKind GetKind() const final { return TurnChoiceKind::Switch; }
|
||||||
|
|
||||||
|
inline Creature* GetNewCreature() const { return _newCreature; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void GetActiveScripts(std::vector<ScriptWrapper>& scripts) override { GetUser()->GetActiveScripts(scripts); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CREATURELIB_SWITCHTURNCHOICE_HPP
|
|
@ -5,6 +5,7 @@
|
||||||
#include "../../src/Battling/Models/CreateCreature.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 "../../src/Battling/TurnChoices/SwitchTurnChoice.hpp"
|
||||||
#include "../TestLibrary/TestLibrary.hpp"
|
#include "../TestLibrary/TestLibrary.hpp"
|
||||||
|
|
||||||
using namespace CreatureLib;
|
using namespace CreatureLib;
|
||||||
|
@ -139,4 +140,49 @@ TEST_CASE("When another creature is available on faint, make sure the battle has
|
||||||
REQUIRE(battle.GetResult() == 0);
|
REQUIRE(battle.GetResult() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Switch Creature in", "[Integrations]") {
|
||||||
|
auto library = TestLibrary::Get();
|
||||||
|
auto c1 = CreateCreature(library, "testSpecies1", 100).WithAttack("standard", AttackLearnMethod::Unknown)->Create();
|
||||||
|
auto c2 = CreateCreature(library, "testSpecies1", 1).WithAttack("standard", AttackLearnMethod::Unknown)->Create();
|
||||||
|
CreatureParty party1{c1, c2};
|
||||||
|
auto battleParty1 = BattleParty(&party1, {CreatureIndex(0, 0)});
|
||||||
|
auto c3 = CreateCreature(library, "testSpecies1", 1).WithAttack("standard", AttackLearnMethod::Unknown)->Create();
|
||||||
|
CreatureParty party2{c3};
|
||||||
|
auto battleParty2 = BattleParty(&party2, {CreatureIndex(1, 0)});
|
||||||
|
|
||||||
|
auto battle = Battle(library, {battleParty1, battleParty2});
|
||||||
|
|
||||||
|
battle.SwitchCreature(0, 0, c1);
|
||||||
|
battle.SwitchCreature(1, 0, c3);
|
||||||
|
|
||||||
|
REQUIRE(battle.GetTarget(CreatureIndex(0, 0)) == c1);
|
||||||
|
|
||||||
|
battle.TrySetChoice(new SwitchTurnChoice(c1, c2));
|
||||||
|
battle.TrySetChoice(new PassTurnChoice(c3));
|
||||||
|
|
||||||
|
REQUIRE(battle.GetTarget(CreatureIndex(0, 0)) == c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Switch Creature in, but have attack aimed at it. Attack should hit new creature", "[Integrations]") {
|
||||||
|
auto library = TestLibrary::Get();
|
||||||
|
auto c1 = CreateCreature(library, "testSpecies1", 50).WithAttack("standard", AttackLearnMethod::Unknown)->Create();
|
||||||
|
auto c2 = CreateCreature(library, "testSpecies1", 50).WithAttack("standard", AttackLearnMethod::Unknown)->Create();
|
||||||
|
CreatureParty party1{c1, c2};
|
||||||
|
auto battleParty1 = BattleParty(&party1, {CreatureIndex(0, 0)});
|
||||||
|
auto c3 = CreateCreature(library, "testSpecies1", 50).WithAttack("standard", AttackLearnMethod::Unknown)->Create();
|
||||||
|
CreatureParty party2{c3};
|
||||||
|
auto battleParty2 = BattleParty(&party2, {CreatureIndex(1, 0)});
|
||||||
|
|
||||||
|
auto battle = Battle(library, {battleParty1, battleParty2});
|
||||||
|
|
||||||
|
battle.SwitchCreature(0, 0, c1);
|
||||||
|
battle.SwitchCreature(1, 0, c3);
|
||||||
|
|
||||||
|
battle.TrySetChoice(new SwitchTurnChoice(c1, c2));
|
||||||
|
battle.TrySetChoice(new AttackTurnChoice(c3, c3->GetAttacks()[0], CreatureIndex(0, 0)));
|
||||||
|
|
||||||
|
REQUIRE(c2->GetCurrentHealth() < c2->GetBoostedStat(Core::Statistic::Health));
|
||||||
|
REQUIRE(c1->GetCurrentHealth() == c1->GetBoostedStat(Core::Statistic::Health));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue