Initial work on attack fail handling.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: Deukhoofd <Deukhoofd@gmail.com>
This commit is contained in:
@@ -63,6 +63,13 @@ void TurnHandler::ExecuteChoice(ArbUt::BorrowedPtr<BaseTurnChoice> choice) {
|
||||
}
|
||||
}
|
||||
|
||||
#define FAIL_HANDLING(source, user, target) \
|
||||
battle.GetValue()->TriggerEventListener<FailEvent>(user); \
|
||||
HOOK(OnFail, source, user) \
|
||||
if ((target) != (void*)0) { \
|
||||
HOOK(OnOpponentFail, (target), user) \
|
||||
}
|
||||
|
||||
void TurnHandler::ExecuteAttackChoice(const ArbUt::BorrowedPtr<AttackTurnChoice>& choice) {
|
||||
auto battle = choice->GetUser()->GetBattle();
|
||||
auto attackName = choice->GetAttack()->GetAttack()->GetName();
|
||||
@@ -77,20 +84,20 @@ void TurnHandler::ExecuteAttackChoice(const ArbUt::BorrowedPtr<AttackTurnChoice>
|
||||
try_creature(targets = TargetResolver::ResolveTargets(choice->GetTarget(), targetType, battle.GetValue());
|
||||
, "Exception during target determination");
|
||||
|
||||
auto attack = new ExecutingAttack(targets, 1, choice->GetUser(), choice->GetAttack(), choice->GetAttackScript());
|
||||
auto attackScoped = ArbUt::ScopedPtr<ExecutingAttack>(
|
||||
new ExecutingAttack(targets, 1, choice->GetUser(), choice->GetAttack(), choice->GetAttackScript()));
|
||||
bool prevented = false;
|
||||
HOOK(PreventAttack, attack, attack, &prevented);
|
||||
HOOK(PreventAttack, attackScoped, attackScoped, &prevented);
|
||||
if (prevented) {
|
||||
delete attack;
|
||||
return;
|
||||
}
|
||||
|
||||
// HOOK: override targets
|
||||
if (!choice->GetAttack()->TryUse(1)) {
|
||||
delete attack;
|
||||
return;
|
||||
}
|
||||
|
||||
auto* attack = attackScoped.TakeOwnership();
|
||||
battle.GetValue()->TriggerEventListener<AttackUseEvent>(attack);
|
||||
battle.GetValue()->RegisterHistoryElement<AttackUseHistory>(attack);
|
||||
|
||||
@@ -98,7 +105,7 @@ void TurnHandler::ExecuteAttackChoice(const ArbUt::BorrowedPtr<AttackTurnChoice>
|
||||
bool fail = false;
|
||||
HOOK(FailAttack, attack, attack, &fail);
|
||||
if (fail) {
|
||||
// TODO: Fail handling.
|
||||
FAIL_HANDLING(attack, choice->GetUser(), (ScriptSource*)nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -120,16 +127,17 @@ void TurnHandler::ExecuteAttackChoice(const ArbUt::BorrowedPtr<AttackTurnChoice>
|
||||
|
||||
void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::BorrowedPtr<Creature>& target) {
|
||||
EnsureNotNull(attack)
|
||||
auto& user = attack->GetUser();
|
||||
auto& battle = user->GetBattle();
|
||||
const auto& user = attack->GetUser();
|
||||
const auto& battle = user->GetBattle();
|
||||
Ensure(battle.HasValue())
|
||||
if (battle.GetValue()->HasEnded())
|
||||
if (battle.GetValue()->HasEnded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool fail = false;
|
||||
HOOK(FailIncomingAttack, target, attack, target.GetRaw(), &fail);
|
||||
if (fail) {
|
||||
// TODO: Fail handling.
|
||||
FAIL_HANDLING(attack, user, target);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -147,21 +155,22 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
|
||||
return;
|
||||
}
|
||||
|
||||
auto& learnedAttack = attack->GetAttack();
|
||||
auto& attackData = learnedAttack->GetAttack();
|
||||
const auto& learnedAttack = attack->GetAttack();
|
||||
const auto& attackData = learnedAttack->GetAttack();
|
||||
|
||||
auto& library = battle.GetValue()->GetLibrary();
|
||||
auto& dmgLibrary = library->GetDamageLibrary();
|
||||
auto& typeLibrary = library->GetTypeLibrary();
|
||||
auto& miscLibrary = library->GetMiscLibrary();
|
||||
const auto& library = battle.GetValue()->GetLibrary();
|
||||
const auto& dmgLibrary = library->GetDamageLibrary();
|
||||
const auto& typeLibrary = library->GetTypeLibrary();
|
||||
const auto& miscLibrary = library->GetMiscLibrary();
|
||||
EnsureNotNull(dmgLibrary)
|
||||
EnsureNotNull(typeLibrary)
|
||||
EnsureNotNull(miscLibrary)
|
||||
|
||||
auto hitIterator = attack->GetTargetIteratorBegin(target);
|
||||
auto* hitIterator = attack->GetTargetIteratorBegin(target);
|
||||
for (uint8_t hitIndex = 0; hitIndex < numberOfHits; hitIndex++) {
|
||||
if (battle.GetValue()->HasEnded())
|
||||
if (battle.GetValue()->HasEnded()) {
|
||||
return;
|
||||
}
|
||||
if (user->IsFainted()) {
|
||||
break;
|
||||
}
|
||||
@@ -182,16 +191,15 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
|
||||
if (attackData->GetCategory() == Library::AttackCategory::Status) {
|
||||
if (attackData->HasSecondaryEffect()) {
|
||||
try {
|
||||
auto& effect = attackData->GetSecondaryEffect();
|
||||
bool hasSecondaryEffect;
|
||||
if (effect->GetChance() == -1) {
|
||||
hasSecondaryEffect = true;
|
||||
} else {
|
||||
hasSecondaryEffect =
|
||||
battle.GetValue()->GetRandom()->EffectChance(effect->GetChance(), attack, target.GetRaw());
|
||||
}
|
||||
const auto& effect = attackData->GetSecondaryEffect();
|
||||
bool hasSecondaryEffect =
|
||||
effect->GetChance() == -1 ||
|
||||
battle.GetValue()->GetRandom()->EffectChance(effect->GetChance(), attack, target.GetRaw());
|
||||
if (hasSecondaryEffect) {
|
||||
HOOK(OnSecondaryEffect, attack, attack, target.GetRaw(), hitIndex);
|
||||
if (hit.HasFailed()) {
|
||||
FAIL_HANDLING(attack, user, target);
|
||||
}
|
||||
}
|
||||
} catch (const ArbUt::Exception& e) {
|
||||
throw e;
|
||||
@@ -213,17 +221,16 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
|
||||
HOOK(PreventSecondaryEffects, target, attack, target.GetRaw(), hitIndex, &preventSecondary);
|
||||
if (!preventSecondary) {
|
||||
try {
|
||||
auto& effect = attackData->GetSecondaryEffect();
|
||||
bool hasSecondaryEffect;
|
||||
if (effect->GetChance() == -1) {
|
||||
hasSecondaryEffect = true;
|
||||
} else {
|
||||
auto random = battle.GetValue()->GetRandom();
|
||||
EnsureNotNull(random);
|
||||
hasSecondaryEffect = random->EffectChance(effect->GetChance(), attack, target.GetRaw());
|
||||
}
|
||||
const auto& effect = attackData->GetSecondaryEffect();
|
||||
bool hasSecondaryEffect =
|
||||
effect->GetChance() == -1 || battle.GetValue()->GetRandom()->EffectChance(
|
||||
effect->GetChance(), attack, target.GetRaw());
|
||||
if (hasSecondaryEffect) {
|
||||
HOOK(OnSecondaryEffect, attack, attack, target.GetRaw(), hitIndex);
|
||||
if (hit.HasFailed()) {
|
||||
battle.GetValue()->TriggerEventListener<FailEvent>(user);
|
||||
FAIL_HANDLING(attack, user, target);
|
||||
}
|
||||
}
|
||||
} catch (const ArbUt::Exception& e) {
|
||||
throw e;
|
||||
|
||||
Reference in New Issue
Block a user