forked from External/mage
[BLB] Implement Season of Gathering and Pawprints mechanic (#12617)
* Add skeleton * Implement Pawprints modal functionality * Implement Seasons of Gathering * remove unused imports * Add Pawprints test * use withPawPRintValue() instead of setter * use 0 for non-pawprint mode and modes classes and move mode validation to addMode * Use GreatestPowerAmongControlledCreaturesValue * Fix pawprints check * calcualte sleected pawprint count based on selected modes * move max pawprints check to getAvailableModes * fix max pawprints checks
This commit is contained in:
parent
d5c76489ac
commit
e976920e2d
6 changed files with 449 additions and 8 deletions
|
|
@ -2578,20 +2578,38 @@ public class HumanPlayer extends PlayerImpl {
|
|||
if (!modeText.isEmpty()) {
|
||||
modeText = Character.toUpperCase(modeText.charAt(0)) + modeText.substring(1);
|
||||
}
|
||||
modeMap.put(mode.getId(), modeIndex + ". " + modeText);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (mode.getPawPrintValue() > 0){
|
||||
for (int i = 0; i < mode.getPawPrintValue(); ++i){
|
||||
sb.append("{P}");
|
||||
}
|
||||
sb.append(": ");
|
||||
} else {
|
||||
sb.append(modeIndex).append(". ");
|
||||
}
|
||||
modeMap.put(mode.getId(), sb.append(modeText).toString());
|
||||
}
|
||||
}
|
||||
|
||||
// done button for "for up" choices only
|
||||
boolean canEndChoice = modes.getSelectedModes().size() >= modes.getMinModes() || modes.isMayChooseNone();
|
||||
boolean canEndChoice = (modes.getSelectedModes().size() >= modes.getMinModes() && modes.getMaxPawPrints() == 0) ||
|
||||
(modes.getSelectedPawPrints() >= modes.getMaxPawPrints() && modes.getMaxPawPrints() > 0) ||
|
||||
modes.isMayChooseNone();
|
||||
if (canEndChoice) {
|
||||
modeMap.put(Modes.CHOOSE_OPTION_DONE_ID, "Done");
|
||||
}
|
||||
modeMap.put(Modes.CHOOSE_OPTION_CANCEL_ID, "Cancel");
|
||||
|
||||
// prepare dialog
|
||||
String message = "Choose mode (selected " + modes.getSelectedModes().size() + " of " + modes.getMaxModes(game, source)
|
||||
+ ", min " + modes.getMinModes() + ")";
|
||||
String message;
|
||||
if (modes.getMaxPawPrints() == 0){
|
||||
message = "Choose mode (selected " + modes.getSelectedModes().size() + " of " + modes.getMaxModes(game, source)
|
||||
+ ", min " + modes.getMinModes() + ")";
|
||||
} else {
|
||||
message = "Choose mode (selected " + modes.getSelectedPawPrints() + " of " + modes.getMaxPawPrints()
|
||||
+ " {P})";
|
||||
}
|
||||
|
||||
if (obj != null) {
|
||||
message = message + "<br>" + obj.getLogName();
|
||||
}
|
||||
|
|
|
|||
162
Mage.Sets/src/mage/cards/s/SeasonOfGathering.java
Normal file
162
Mage.Sets/src/mage/cards/s/SeasonOfGathering.java
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.*;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jimga150
|
||||
*/
|
||||
public final class SeasonOfGathering extends CardImpl {
|
||||
|
||||
public SeasonOfGathering(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}{G}");
|
||||
|
||||
// Choose up to five {P} worth of modes. You may choose the same mode more than once.
|
||||
this.getSpellAbility().getModes().setMaxPawPrints(5);
|
||||
this.getSpellAbility().getModes().setMinModes(0);
|
||||
this.getSpellAbility().getModes().setMaxModes(5);
|
||||
this.getSpellAbility().getModes().setMayChooseSameModeMoreThanOnce(true);
|
||||
|
||||
// {P} -- Put a +1/+1 counter on a creature you control. It gains vigilance and trample until end of turn.
|
||||
this.getSpellAbility().addEffect(new SeasonOfGatheringCounterEffect());
|
||||
this.spellAbility.getModes().getMode().withPawPrintValue(1);
|
||||
|
||||
// {P}{P} -- Choose artifact or enchantment. Destroy all permanents of the chosen type.
|
||||
Mode mode2 = new Mode(new SeasonOfGatheringRemovalEffect());
|
||||
this.getSpellAbility().addMode(mode2.withPawPrintValue(2));
|
||||
|
||||
// {P}{P}{P} -- Draw cards equal to the greatest power among creatures you control.
|
||||
Mode mode3 = new Mode(
|
||||
new DrawCardSourceControllerEffect(GreatestPowerAmongControlledCreaturesValue.instance)
|
||||
.setText("Draw cards equal to the greatest power among creatures you control.")
|
||||
);
|
||||
this.getSpellAbility().addMode(mode3.withPawPrintValue(3));
|
||||
}
|
||||
|
||||
private SeasonOfGathering(final SeasonOfGathering card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeasonOfGathering copy() {
|
||||
return new SeasonOfGathering(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Based on KaylasCommandCounterEffect
|
||||
class SeasonOfGatheringCounterEffect extends OneShotEffect {
|
||||
|
||||
SeasonOfGatheringCounterEffect() {
|
||||
super(Outcome.BoostCreature);
|
||||
this.staticText = "Put a +1/+1 counter on a creature you control. It gains vigilance and trample until end of turn.";
|
||||
}
|
||||
|
||||
private SeasonOfGatheringCounterEffect(final SeasonOfGatheringCounterEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeasonOfGatheringCounterEffect copy() {
|
||||
return new SeasonOfGatheringCounterEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent();
|
||||
target.withNotTarget(true);
|
||||
controller.chooseTarget(outcome, target, source, game);
|
||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
permanent.addCounters(CounterType.P1P1.createInstance(), source, game);
|
||||
GainAbilityTargetEffect effect = new GainAbilityTargetEffect(VigilanceAbility.getInstance());
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
game.addEffect(effect, source);
|
||||
GainAbilityTargetEffect effect2 = new GainAbilityTargetEffect(TrampleAbility.getInstance());
|
||||
effect2.setTargetPointer(new FixedTarget(permanent, game));
|
||||
game.addEffect(effect2, source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Based on KindredDominanceEffect and TurnaboutEffect
|
||||
class SeasonOfGatheringRemovalEffect extends OneShotEffect {
|
||||
|
||||
private static final Set<String> choice = new HashSet<>();
|
||||
|
||||
static {
|
||||
choice.add(CardType.ARTIFACT.toString());
|
||||
choice.add(CardType.ENCHANTMENT.toString());
|
||||
}
|
||||
|
||||
SeasonOfGatheringRemovalEffect() {
|
||||
super(Outcome.DestroyPermanent);
|
||||
this.staticText = "Choose artifact or enchantment. Destroy all permanents of the chosen type.";
|
||||
}
|
||||
|
||||
private SeasonOfGatheringRemovalEffect(final SeasonOfGatheringRemovalEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeasonOfGatheringRemovalEffect copy() {
|
||||
return new SeasonOfGatheringRemovalEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Choice choiceImpl = new ChoiceImpl(true);
|
||||
choiceImpl.setMessage("Choose card type to destroy");
|
||||
choiceImpl.setChoices(choice);
|
||||
if (!controller.choose(Outcome.Neutral, choiceImpl, game)) {
|
||||
return false;
|
||||
}
|
||||
FilterPermanent filter;
|
||||
switch (choiceImpl.getChoice()) {
|
||||
case "Artifact":
|
||||
filter = StaticFilters.FILTER_PERMANENT_ARTIFACT;
|
||||
break;
|
||||
case "Enchantment":
|
||||
filter = StaticFilters.FILTER_PERMANENT_ENCHANTMENT;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Choice is required");
|
||||
}
|
||||
game.informPlayers(controller.getLogName() + " has chosen " + choiceImpl.getChoiceKey());
|
||||
return new DestroyAllEffect(filter).apply(game, source);
|
||||
}
|
||||
}
|
||||
|
|
@ -203,6 +203,7 @@ public final class Bloomburrow extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Scales of Shale", 110, Rarity.COMMON, mage.cards.s.ScalesOfShale.class));
|
||||
cards.add(new SetCardInfo("Scavenger's Talent", 111, Rarity.RARE, mage.cards.s.ScavengersTalent.class));
|
||||
cards.add(new SetCardInfo("Scrapshooter", 191, Rarity.RARE, mage.cards.s.Scrapshooter.class));
|
||||
cards.add(new SetCardInfo("Season of Gathering", 192, Rarity.MYTHIC, mage.cards.s.SeasonOfGathering.class));
|
||||
cards.add(new SetCardInfo("Seasoned Warrenguard", 30, Rarity.UNCOMMON, mage.cards.s.SeasonedWarrenguard.class));
|
||||
cards.add(new SetCardInfo("Seedglaive Mentor", 231, Rarity.UNCOMMON, mage.cards.s.SeedglaiveMentor.class));
|
||||
cards.add(new SetCardInfo("Seedpod Squire", 232, Rarity.COMMON, mage.cards.s.SeedpodSquire.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,218 @@
|
|||
package org.mage.test.cards.modal;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author jimga150
|
||||
*/
|
||||
public class PawPrintsTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_Choose113() {
|
||||
// Test that draw effect sees power affected by counter effect
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 6);
|
||||
// Choose up to five {P} worth of modes. You may choose the same mode more than once.
|
||||
// {P} -- Put a +1/+1 counter on a creature you control. It gains vigilance and trample until end of turn.
|
||||
// {P}{P} -- Choose artifact or enchantment. Destroy all permanents of the chosen type.
|
||||
// {P}{P}{P} -- Draw cards equal to the greatest power among creatures you control.
|
||||
addCard(Zone.HAND, playerA, "Season of Gathering"); // Instant {4}{G}{G}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Season of Gathering");
|
||||
setModeChoice(playerA, "1");
|
||||
setModeChoice(playerA, "1");
|
||||
setModeChoice(playerA, "3");
|
||||
addTarget(playerA, "Memnite"); // for 1
|
||||
addTarget(playerA, "Memnite");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertHandCount(playerA, 3);
|
||||
|
||||
assertPowerToughness(playerA, "Memnite", 3, 3);
|
||||
assertCounterCount("Memnite", CounterType.P1P1, 2);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Choose123() {
|
||||
// Test that 1, 2, and 3 cannot all be selected (and that 1 and 2 will fire in that order)
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 6);
|
||||
// Choose up to five {P} worth of modes. You may choose the same mode more than once.
|
||||
// {P} -- Put a +1/+1 counter on a creature you control. It gains vigilance and trample until end of turn.
|
||||
// {P}{P} -- Choose artifact or enchantment. Destroy all permanents of the chosen type.
|
||||
// {P}{P}{P} -- Draw cards equal to the greatest power among creatures you control.
|
||||
addCard(Zone.HAND, playerA, "Season of Gathering"); // Instant {4}{G}{G}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
|
||||
// If one or more +1/+1 counters would be put on a creature you control, that many plus one +1/+1 counters are put on it instead.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Hardened Scales");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Season of Gathering");
|
||||
setModeChoice(playerA, "1");
|
||||
setModeChoice(playerA, "2");
|
||||
setModeChoice(playerA, "3"); // Will be unused
|
||||
addTarget(playerA, "Memnite"); // for 1
|
||||
setChoice(playerA, "Enchantment");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
// Add one more counter from Hardened Scales, which was still on the battlefield when the counter placing effect triggered
|
||||
assertPowerToughness(playerA, "Memnite", 3, 3);
|
||||
assertCounterCount("Memnite", CounterType.P1P1, 2);
|
||||
|
||||
// But not anymore...
|
||||
assertPermanentCount(playerA, "Hardened Scales", 0);
|
||||
assertGraveyardCount(playerA, "Hardened Scales", 1);
|
||||
|
||||
// Draw effect didnt trigger
|
||||
assertHandCount(playerA, 0);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Choose2111() {
|
||||
// Test that 1 and 2 will fire in that order when choices are made in reverse
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 6);
|
||||
// Choose up to five {P} worth of modes. You may choose the same mode more than once.
|
||||
// {P} -- Put a +1/+1 counter on a creature you control. It gains vigilance and trample until end of turn.
|
||||
// {P}{P} -- Choose artifact or enchantment. Destroy all permanents of the chosen type.
|
||||
// {P}{P}{P} -- Draw cards equal to the greatest power among creatures you control.
|
||||
addCard(Zone.HAND, playerA, "Season of Gathering"); // Instant {4}{G}{G}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
|
||||
// If one or more +1/+1 counters would be put on a creature you control, that many plus one +1/+1 counters are put on it instead.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Hardened Scales");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Season of Gathering");
|
||||
setModeChoice(playerA, "2");
|
||||
setModeChoice(playerA, "1");
|
||||
setModeChoice(playerA, "1");
|
||||
setModeChoice(playerA, "1");
|
||||
addTarget(playerA, "Memnite"); // for 1
|
||||
addTarget(playerA, "Memnite"); // for 1
|
||||
addTarget(playerA, "Memnite"); // for 1
|
||||
setChoice(playerA, "Enchantment");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
// Add one more counter per choice from Hardened Scales, which was still on the battlefield when the counter placing effect triggered
|
||||
assertPowerToughness(playerA, "Memnite", 7, 7);
|
||||
assertCounterCount("Memnite", CounterType.P1P1, 6);
|
||||
|
||||
// But not anymore...
|
||||
assertPermanentCount(playerA, "Hardened Scales", 0);
|
||||
assertGraveyardCount(playerA, "Hardened Scales", 1);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Choose1x5() {
|
||||
// Test that max amount of modes can be chosen
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 6);
|
||||
// Choose up to five {P} worth of modes. You may choose the same mode more than once.
|
||||
// {P} -- Put a +1/+1 counter on a creature you control. It gains vigilance and trample until end of turn.
|
||||
// {P}{P} -- Choose artifact or enchantment. Destroy all permanents of the chosen type.
|
||||
// {P}{P}{P} -- Draw cards equal to the greatest power among creatures you control.
|
||||
addCard(Zone.HAND, playerA, "Season of Gathering"); // Instant {4}{G}{G}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Season of Gathering");
|
||||
for (int i = 0; i < 5; ++i){
|
||||
setModeChoice(playerA, "1");
|
||||
addTarget(playerA, "Memnite");
|
||||
}
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPowerToughness(playerA, "Memnite", 6, 6);
|
||||
assertCounterCount("Memnite", CounterType.P1P1, 5);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Choose23() {
|
||||
// Test that 2 and 3 fire in that order
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 6);
|
||||
// Choose up to five {P} worth of modes. You may choose the same mode more than once.
|
||||
// {P} -- Put a +1/+1 counter on a creature you control. It gains vigilance and trample until end of turn.
|
||||
// {P}{P} -- Choose artifact or enchantment. Destroy all permanents of the chosen type.
|
||||
// {P}{P}{P} -- Draw cards equal to the greatest power among creatures you control.
|
||||
addCard(Zone.HAND, playerA, "Season of Gathering"); // Instant {4}{G}{G}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
|
||||
// If one or more +1/+1 counters would be put on a creature you control, that many plus one +1/+1 counters are put on it instead.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Hardened Scales");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Season of Gathering");
|
||||
setModeChoice(playerA, "3");
|
||||
setModeChoice(playerA, "2");
|
||||
setChoice(playerA, "Artifact");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Hardened Scales", 1);
|
||||
assertGraveyardCount(playerA, "Memnite", 1);
|
||||
|
||||
// Draw effect saw no creatures, so no cards
|
||||
assertHandCount(playerA, 0);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Choose122() {
|
||||
// Test destroying both artifacts and enchantments
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 6);
|
||||
// Choose up to five {P} worth of modes. You may choose the same mode more than once.
|
||||
// {P} -- Put a +1/+1 counter on a creature you control. It gains vigilance and trample until end of turn.
|
||||
// {P}{P} -- Choose artifact or enchantment. Destroy all permanents of the chosen type.
|
||||
// {P}{P}{P} -- Draw cards equal to the greatest power among creatures you control.
|
||||
addCard(Zone.HAND, playerA, "Season of Gathering"); // Instant {4}{G}{G}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
|
||||
// If one or more +1/+1 counters would be put on a creature you control, that many plus one +1/+1 counters are put on it instead.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Hardened Scales");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Season of Gathering");
|
||||
setModeChoice(playerA, "1");
|
||||
setModeChoice(playerA, "2");
|
||||
setModeChoice(playerA, "2");
|
||||
addTarget(playerA, "Memnite");
|
||||
setChoice(playerA, "Artifact");
|
||||
setChoice(playerA, "Enchantment");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Hardened Scales", 1);
|
||||
assertGraveyardCount(playerA, "Memnite", 1);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ public class Mode implements Serializable {
|
|||
protected final Effects effects;
|
||||
protected String flavorWord;
|
||||
protected Cost cost = null;
|
||||
protected int pawPrintValue = 0; //0 = does not use pawprints
|
||||
/**
|
||||
* Optional Tag to distinguish this mode from others.
|
||||
* In the case of modes that players can only choose once,
|
||||
|
|
@ -42,6 +43,7 @@ public class Mode implements Serializable {
|
|||
this.flavorWord = mode.flavorWord;
|
||||
this.modeTag = mode.modeTag;
|
||||
this.cost = mode.cost != null ? mode.cost.copy() : null;
|
||||
this.pawPrintValue = mode.pawPrintValue;
|
||||
}
|
||||
|
||||
public UUID setRandomId() {
|
||||
|
|
@ -119,4 +121,13 @@ public class Mode implements Serializable {
|
|||
public Cost getCost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
public Mode withPawPrintValue(int pawPrintValue) {
|
||||
this.pawPrintValue = pawPrintValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getPawPrintValue() {
|
||||
return pawPrintValue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> implements Copyable<Modes>
|
|||
|
||||
private int minModes;
|
||||
private int maxModes;
|
||||
private int maxPawPrints;
|
||||
private Filter maxModesFilter; // calculates the max number of available modes
|
||||
private Condition moreCondition; // allows multiple modes choose (example: choose one... if condition, you may choose both)
|
||||
|
||||
|
|
@ -53,6 +54,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> implements Copyable<Modes>
|
|||
this.put(currentMode.getId(), currentMode);
|
||||
this.minModes = 1;
|
||||
this.maxModes = 1;
|
||||
this.maxPawPrints = 0; // 0 = does not use pawprints
|
||||
this.addSelectedMode(currentMode.getId());
|
||||
this.chooseController = TargetController.YOU;
|
||||
}
|
||||
|
|
@ -68,6 +70,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> implements Copyable<Modes>
|
|||
|
||||
this.minModes = modes.minModes;
|
||||
this.maxModes = modes.maxModes;
|
||||
this.maxPawPrints = modes.maxPawPrints;
|
||||
this.maxModesFilter = modes.maxModesFilter; // can't change so no copy needed
|
||||
this.moreCondition = modes.moreCondition;
|
||||
|
||||
|
|
@ -194,6 +197,12 @@ public class Modes extends LinkedHashMap<UUID, Mode> implements Copyable<Modes>
|
|||
return count;
|
||||
}
|
||||
|
||||
public int getSelectedPawPrints(){
|
||||
return this.selectedModes.stream()
|
||||
.mapToInt(modeID -> get(modeID).getPawPrintValue())
|
||||
.sum();
|
||||
}
|
||||
|
||||
public void setMinModes(int minModes) {
|
||||
this.minModes = minModes;
|
||||
}
|
||||
|
|
@ -256,6 +265,14 @@ public class Modes extends LinkedHashMap<UUID, Mode> implements Copyable<Modes>
|
|||
return realMaxModes;
|
||||
}
|
||||
|
||||
public void setMaxPawPrints(int maxPawPrints) {
|
||||
this.maxPawPrints = maxPawPrints;
|
||||
}
|
||||
|
||||
public int getMaxPawPrints() {
|
||||
return this.maxPawPrints;
|
||||
}
|
||||
|
||||
public void setChooseController(TargetController chooseController) {
|
||||
this.chooseController = chooseController;
|
||||
}
|
||||
|
|
@ -275,6 +292,12 @@ public class Modes extends LinkedHashMap<UUID, Mode> implements Copyable<Modes>
|
|||
}
|
||||
|
||||
public void addMode(Mode mode) {
|
||||
if (this.maxPawPrints > 0 && mode.getPawPrintValue() == 0){
|
||||
throw new IllegalArgumentException("Mode must have nonzero pawprints value in a pawprints mode set.");
|
||||
}
|
||||
if (this.maxPawPrints == 0 && mode.getPawPrintValue() > 0){
|
||||
throw new IllegalArgumentException("Cannot add pawprints mode to non-pawprints mode set.");
|
||||
}
|
||||
this.put(mode.getId(), mode);
|
||||
}
|
||||
|
||||
|
|
@ -317,7 +340,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> implements Copyable<Modes>
|
|||
return isSelectedValid(source, game);
|
||||
}
|
||||
|
||||
// modal spells must show choose dialog even for 1 option, so check this.size instead evailableModes.size here
|
||||
// modal spells must show choose dialog even for 1 option, so check this.size instead availableModes.size here
|
||||
if (this.size() > 1) {
|
||||
// multiple modes
|
||||
|
||||
|
|
@ -375,7 +398,8 @@ public class Modes extends LinkedHashMap<UUID, Mode> implements Copyable<Modes>
|
|||
this.currentMode = null;
|
||||
int currentMaxModes = this.getMaxModes(game, source);
|
||||
|
||||
while (this.selectedModes.size() < currentMaxModes) {
|
||||
while ((this.selectedModes.size() < currentMaxModes && maxPawPrints == 0) ||
|
||||
(this.getSelectedPawPrints() < maxPawPrints && maxPawPrints > 0)) {
|
||||
Mode choice = player.chooseMode(this, source, game);
|
||||
if (choice == null) {
|
||||
// user press cancel/stop in choose dialog or nothing to choose
|
||||
|
|
@ -437,8 +461,10 @@ public class Modes extends LinkedHashMap<UUID, Mode> implements Copyable<Modes>
|
|||
throw new IllegalArgumentException("Unknown modeId to select");
|
||||
}
|
||||
|
||||
Mode mode = get(modeId);
|
||||
|
||||
if (selectedModes.contains(modeId) && mayChooseSameModeMoreThanOnce) {
|
||||
Mode duplicateMode = get(modeId).copy();
|
||||
Mode duplicateMode = mode.copy();
|
||||
UUID originalId = modeId;
|
||||
duplicateMode.setRandomId();
|
||||
modeId = duplicateMode.getId();
|
||||
|
|
@ -526,6 +552,9 @@ public class Modes extends LinkedHashMap<UUID, Mode> implements Copyable<Modes>
|
|||
if (isLimitUsageByOnce() && nonAvailableModes.contains(mode.getId())) {
|
||||
continue;
|
||||
}
|
||||
if (getMaxPawPrints() > 0 && getSelectedPawPrints() + mode.getPawPrintValue() > getMaxPawPrints()){
|
||||
continue;
|
||||
}
|
||||
availableModes.add(mode);
|
||||
}
|
||||
return availableModes;
|
||||
|
|
@ -545,7 +574,9 @@ public class Modes extends LinkedHashMap<UUID, Mode> implements Copyable<Modes>
|
|||
}
|
||||
sb.append("choose ");
|
||||
}
|
||||
if (this.getMinModes() == 0 && this.getMaxModes(null, null) == 1) {
|
||||
if (this.getMaxPawPrints() > 0){
|
||||
sb.append("up to ").append(CardUtil.numberToText(this.getMaxPawPrints())).append(" {P} worth of modes");
|
||||
} else if (this.getMinModes() == 0 && this.getMaxModes(null, null) == 1) {
|
||||
sb.append("up to one");
|
||||
} else if (this.getMinModes() == 0 && this.getMaxModes(null, null) > 2) {
|
||||
sb.append("any number");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue