Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
SD - Inferno Guard Invoker (#3774)
Browse files Browse the repository at this point in the history
* tests and implementation for Inferno Guard Invoker

* Fix lint errors

* - Rework implementation
- Add tests for multiple delayed effects and province breaking by other means

* Fix lint error
  • Loading branch information
The-Outcast authored and marcsoiferman-cm committed Dec 9, 2019
1 parent 6ead51c commit 6dca84c
Show file tree
Hide file tree
Showing 2 changed files with 227 additions and 0 deletions.
50 changes: 50 additions & 0 deletions server/game/cards/09.6-SD/InfernoGuardInvoker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const { EventNames } = require('../../Constants.js');
const EventRegistrar = require('../../eventregistrar.js');
const DrawCard = require('../../drawcard.js');
const { CardTypes, Durations, Players } = require('../../Constants');
const AbilityDsl = require('../../abilitydsl');

class InfernoGuardInvoker extends DrawCard {
setupCardAbilities() {
this.provinceBroken = false;
this.eventRegistrar = new EventRegistrar(this.game, this);
this.eventRegistrar.register([EventNames.OnBreakProvince, EventNames.OnConflictDeclared]);

this.action({
title: 'honor this character',
condition: context => context.game.isDuringConflict('military'),
target: {
cardType: CardTypes.Character,
controller: Players.Self,
cardCondition: card => card.isParticipating()
},
gameAction: AbilityDsl.actions.multiple([
AbilityDsl.actions.honor(context => ({ target: context.target})),
AbilityDsl.actions.cardLastingEffect(context => ({
duration: Durations.UntilEndOfPhase,
target: context.target,
effect: AbilityDsl.effects.delayedEffect({
when: {
onConflictFinished: () => this.provinceBroken
},
message: '{1} is discarded, burned to a pile of ash due to the delayed effect of {0}',
messageArgs: [context.source, context.target],
gameAction: AbilityDsl.actions.sacrifice({ target: context.target })
})
}))
])
});
}

onBreakProvince() {
this.provinceBroken = true;
}

onConflictDeclared() {
this.provinceBroken = false;
}
}

InfernoGuardInvoker.id = 'inferno-guard-invoker';

module.exports = InfernoGuardInvoker;
177 changes: 177 additions & 0 deletions test/server/cards/09.6-SD/InfernoGuardInvoker.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
describe('Inferno Guard Invoker', function() {
integration(function() {
describe('Inferno Guard Invoker\'s action ability', function() {
beforeEach(function() {
this.setupTest({
phase: 'conflict',
player1: {
inPlay: ['inferno-guard-invoker', 'serene-warrior'],
dynastyDiscard: ['akodo-toturi'],
hand: ['forebearer-s-echoes']
},
player2: {
inPlay: ['solemn-scholar', 'fushicho'],
provinces: ['shameful-display', 'endless-plains']
}
});

this.player1.player.optionSettings.orderForcedAbilities = true;

this.infernoGuardInvoker = this.player1.findCardByName('inferno-guard-invoker');
this.sereneWarrior = this.player1.findCardByName('serene-warrior');
this.akodoToturi = this.player1.findCardByName('akodo-toturi');
this.echoes = this.player1.findCardByName('forebearer-s-echoes');

this.solemnScholar = this.player2.findCardByName('solemn-scholar');
this.fushicho = this.player2.findCardByName('fushicho');
this.endlessPlains = this.player2.findCardByName('endless-plains', 'province 2');

this.noMoreActions();
});

it('should not be triggerable during a political conflict', function() {
this.initiateConflict({
type: 'political',
attackers: [this.sereneWarrior],
defenders: [this.solemnScholar]
});

this.player2.pass();

this.player1.clickCard(this.infernoGuardInvoker);
expect(this.player1).toHavePrompt('Conflict Action Window');
});

it('should be able to honor a participating character you control during a military conflict', function() {
this.initiateConflict({
type: 'military',
attackers: [this.sereneWarrior],
defenders: [this.solemnScholar]
});

this.player2.pass();

this.player1.clickCard(this.infernoGuardInvoker);
expect(this.player1).toBeAbleToSelect(this.sereneWarrior);
expect(this.player1).not.toBeAbleToSelect(this.solemnScholar);
expect(this.player1).not.toBeAbleToSelect(this.infernoGuardInvoker);
expect(this.player1).not.toBeAbleToSelect(this.fushicho);

this.player1.clickCard(this.sereneWarrior);
expect(this.sereneWarrior.isHonored).toBe(true);
});

it('should sacrifice the targeted character at the end of the conflict if the province breaks this conflict', function() {
this.initiateConflict({
type: 'military',
attackers: [this.sereneWarrior],
defenders: [this.solemnScholar]
});

this.player2.pass();

this.player1.clickCard(this.infernoGuardInvoker);
expect(this.player1).toBeAbleToSelect(this.sereneWarrior);
expect(this.player1).not.toBeAbleToSelect(this.solemnScholar);
expect(this.player1).not.toBeAbleToSelect(this.infernoGuardInvoker);

this.player1.clickCard(this.sereneWarrior);
expect(this.sereneWarrior.isHonored).toBe(true);

this.player2.pass();
this.player1.pass();

this.player1.clickPrompt('No');
this.player1.clickPrompt('Don\'t resolve');
expect(this.player1).toHavePrompt('Action Window');
expect(this.getChatLogs(5)).toContain('Serene Warrior is discarded, burned to a pile of ash due to the delayed effect of Inferno Guard Invoker');
expect(this.sereneWarrior.location).toBe('dynasty discard pile');
});

it('should not discard the targeted character if the province doesn\'t break this conflict', function() {
this.initiateConflict({
type: 'military',
attackers: [this.sereneWarrior],
defenders: [this.fushicho]
});

this.player2.pass();

this.player1.clickCard(this.infernoGuardInvoker);
this.player1.clickCard(this.sereneWarrior);
expect(this.sereneWarrior.isHonored).toBe(true);

this.player2.pass();
this.player1.pass();

expect(this.getChatLogs(5)).not.toContain('Serene Warrior is discarded, burned to a pile of ash due to the delayed effect of Inferno Guard Invoker');
this.player1.clickPrompt('Don\'t Resolve');

expect(this.sereneWarrior.location).toBe('play area');
expect(this.player1).toHavePrompt('Action Window');
});

it('should let first player pick the order when multiple delayed effects fire (Inferno Guard Invoker + Forebearer\'s Echoes)', function() {
this.initiateConflict({
type: 'military',
attackers: [this.sereneWarrior],
defenders: [this.fushicho]
});

this.player2.pass();

this.player1.clickCard(this.echoes);
this.player1.clickCard(this.akodoToturi);
this.player2.pass();
this.player1.clickCard(this.infernoGuardInvoker);
this.player1.clickCard(this.akodoToturi);
expect(this.akodoToturi.isHonored).toBe(true);

this.player2.pass();
this.player1.pass();

this.player1.clickPrompt('No');
this.player1.clickPrompt('Don\'t Resolve');
this.player1.clickPrompt('Pass');

expect(this.player1).toHavePrompt('Order Simultaneous effects');
expect(this.player1).toHavePromptButton('Forebearer\'s Echoes\'s effect on Akodo Toturi');
expect(this.player1).toHavePromptButton('Inferno Guard Invoker\'s effect on Akodo Toturi');

this.player1.clickPrompt('Inferno Guard Invoker\'s effect on Akodo Toturi');
expect(this.getChatLogs(5)).toContain('Akodo Toturi is discarded, burned to a pile of ash due to the delayed effect of Inferno Guard Invoker');
expect(this.akodoToturi.location).toBe('dynasty discard pile');
expect(this.player1).toHavePrompt('Action Window');
});

it('should discard the target of Inferno Guard Invoker if the province was broken by other means (e.g: Endless Plains)', function() {
this.initiateConflict({
type: 'military',
attackers: [this.sereneWarrior, this.infernoGuardInvoker],
province: this.endlessPlains
});
this.player2.clickCard(this.endlessPlains);
this.player1.clickPrompt('No');
this.player1.clickCard(this.sereneWarrior);


this.player2.clickPrompt('Pass');
this.player2.clickCard(this.fushicho);
this.player2.clickPrompt('Done');

this.player2.pass();
this.player1.clickCard(this.infernoGuardInvoker);
this.player1.clickCard(this.infernoGuardInvoker);

this.player2.pass();
this.player1.pass();

this.player1.clickPrompt('Don\'t Resolve');
expect(this.getChatLogs(5)).toContain('Inferno Guard Invoker is discarded, burned to a pile of ash due to the delayed effect of Inferno Guard Invoker');

expect(this.infernoGuardInvoker.location).toBe('dynasty discard pile');
expect(this.player1).toHavePrompt('Action Window');
});
});
});
});

0 comments on commit 6dca84c

Please sign in to comment.