From d3d1402fbbd0266e62b7957d7cf70465459ece8d Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 17 Sep 2016 00:45:33 +0200 Subject: [PATCH] [KLD] Added 9 white cards. --- .../java/mage/server/game/GameController.java | 244 ++++++++-------- .../src/mage/sets/kaladesh/BuiltToLast.java | 69 +++++ .../sets/kaladesh/ConsulsShieldguard.java | 88 ++++++ .../src/mage/sets/kaladesh/EddytrailHawk.java | 88 ++++++ .../src/mage/sets/kaladesh/GearshiftAce.java | 112 ++++++++ .../mage/sets/kaladesh/HeraldOfTheFair.java | 69 +++++ .../src/mage/sets/kaladesh/MakeObsolete.java | 7 +- .../mage/sets/kaladesh/NinthBridgePatrol.java | 77 +++++ .../mage/sets/kaladesh/RevokePrivilege.java | 125 ++++++++ .../mage/sets/kaladesh/ServoExhibition.java | 62 ++++ .../mage/sets/kaladesh/TrustyCompanion.java | 65 +++++ .../common/TargetHasCardTypeCondition.java | 36 +++ .../mage/abilities/keyword/CrewAbility.java | 271 +++++++++--------- .../main/java/mage/game/events/GameEvent.java | 6 + 14 files changed, 1058 insertions(+), 261 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/kaladesh/BuiltToLast.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/ConsulsShieldguard.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/EddytrailHawk.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/GearshiftAce.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/HeraldOfTheFair.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/NinthBridgePatrol.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/RevokePrivilege.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/ServoExhibition.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/TrustyCompanion.java create mode 100644 Mage/src/main/java/mage/abilities/condition/common/TargetHasCardTypeCondition.java diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index 009b959d0d..26ddefecde 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -156,123 +156,123 @@ public class GameController implements GameCallback { private void init() { game.addTableEventListener( new Listener() { - @Override - public void event(TableEvent event) { - try { - PriorityTimer timer; - UUID playerId; - switch (event.getEventType()) { - case UPDATE: - updateGame(); - break; - case INFO: - ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, ChatMessage.MessageType.GAME); - logger.trace(game.getId() + " " + event.getMessage()); - break; - case STATUS: - ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), ChatMessage.MessageType.GAME); - logger.trace(game.getId() + " " + event.getMessage()); - break; - case ERROR: - error(event.getMessage(), event.getException()); - break; - case END_GAME_INFO: - endGameInfo(); - break; - case INIT_TIMER: - final UUID initPlayerId = event.getPlayerId(); - if (initPlayerId == null) { - throw new MageException("INIT_TIMER: playerId can't be null"); - } - createPlayerTimer(event.getPlayerId(), game.getPriorityTime()); - break; - case RESUME_TIMER: - playerId = event.getPlayerId(); - if (playerId == null) { - throw new MageException("RESUME_TIMER: playerId can't be null"); - } - timer = timers.get(playerId); - if (timer == null) { - Player player = game.getState().getPlayer(playerId); - if (player != null) { - timer = createPlayerTimer(event.getPlayerId(), player.getPriorityTimeLeft()); - } else { - throw new MageException("RESUME_TIMER: player can't be null"); - } - } - timer.resume(); - break; - case PAUSE_TIMER: - playerId = event.getPlayerId(); - if (playerId == null) { - throw new MageException("PAUSE_TIMER: playerId can't be null"); - } - timer = timers.get(playerId); - if (timer == null) { - throw new MageException("PAUSE_TIMER: couldn't find timer for player: " + playerId); - } - timer.pause(); - break; + @Override + public void event(TableEvent event) { + try { + PriorityTimer timer; + UUID playerId; + switch (event.getEventType()) { + case UPDATE: + updateGame(); + break; + case INFO: + ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, ChatMessage.MessageType.GAME); + logger.trace(game.getId() + " " + event.getMessage()); + break; + case STATUS: + ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), ChatMessage.MessageType.GAME); + logger.trace(game.getId() + " " + event.getMessage()); + break; + case ERROR: + error(event.getMessage(), event.getException()); + break; + case END_GAME_INFO: + endGameInfo(); + break; + case INIT_TIMER: + final UUID initPlayerId = event.getPlayerId(); + if (initPlayerId == null) { + throw new MageException("INIT_TIMER: playerId can't be null"); } - } catch (MageException ex) { - logger.fatal("Table event listener error ", ex); - } + createPlayerTimer(event.getPlayerId(), game.getPriorityTime()); + break; + case RESUME_TIMER: + playerId = event.getPlayerId(); + if (playerId == null) { + throw new MageException("RESUME_TIMER: playerId can't be null"); + } + timer = timers.get(playerId); + if (timer == null) { + Player player = game.getState().getPlayer(playerId); + if (player != null) { + timer = createPlayerTimer(event.getPlayerId(), player.getPriorityTimeLeft()); + } else { + throw new MageException("RESUME_TIMER: player can't be null"); + } + } + timer.resume(); + break; + case PAUSE_TIMER: + playerId = event.getPlayerId(); + if (playerId == null) { + throw new MageException("PAUSE_TIMER: playerId can't be null"); + } + timer = timers.get(playerId); + if (timer == null) { + throw new MageException("PAUSE_TIMER: couldn't find timer for player: " + playerId); + } + timer.pause(); + break; } + } catch (MageException ex) { + logger.fatal("Table event listener error ", ex); } + } + } ); game.addPlayerQueryEventListener( new Listener() { - @Override - public void event(PlayerQueryEvent event) { - logger.trace(new StringBuilder(event.getPlayerId().toString()).append("--").append(event.getQueryType()).append("--").append(event.getMessage()).toString()); - try { - switch (event.getQueryType()) { - case ASK: - ask(event.getPlayerId(), event.getMessage(), event.getOptions()); - break; - case PICK_TARGET: - target(event.getPlayerId(), event.getMessage(), event.getCards(), event.getPerms(), event.getTargets(), event.isRequired(), event.getOptions()); - break; - case PICK_ABILITY: - target(event.getPlayerId(), event.getMessage(), event.getAbilities(), event.isRequired(), event.getOptions()); - break; - case SELECT: - select(event.getPlayerId(), event.getMessage(), event.getOptions()); - break; - case PLAY_MANA: - playMana(event.getPlayerId(), event.getMessage(), event.getOptions()); - break; - case PLAY_X_MANA: - playXMana(event.getPlayerId(), event.getMessage()); - break; - case CHOOSE_ABILITY: - String objectName = null; - if (event.getChoices() != null && event.getChoices().size() > 0) { - objectName = event.getChoices().iterator().next(); - } - chooseAbility(event.getPlayerId(), objectName, event.getAbilities()); - break; - case CHOOSE_PILE: - choosePile(event.getPlayerId(), event.getMessage(), event.getPile1(), event.getPile2()); - break; - case CHOOSE_MODE: - chooseMode(event.getPlayerId(), event.getModes()); - break; - case CHOOSE_CHOICE: - chooseChoice(event.getPlayerId(), event.getChoice()); - break; - case AMOUNT: - amount(event.getPlayerId(), event.getMessage(), event.getMin(), event.getMax()); - break; - case PERSONAL_MESSAGE: - informPersonal(event.getPlayerId(), event.getMessage()); - break; + @Override + public void event(PlayerQueryEvent event) { + logger.trace(new StringBuilder(event.getPlayerId().toString()).append("--").append(event.getQueryType()).append("--").append(event.getMessage()).toString()); + try { + switch (event.getQueryType()) { + case ASK: + ask(event.getPlayerId(), event.getMessage(), event.getOptions()); + break; + case PICK_TARGET: + target(event.getPlayerId(), event.getMessage(), event.getCards(), event.getPerms(), event.getTargets(), event.isRequired(), event.getOptions()); + break; + case PICK_ABILITY: + target(event.getPlayerId(), event.getMessage(), event.getAbilities(), event.isRequired(), event.getOptions()); + break; + case SELECT: + select(event.getPlayerId(), event.getMessage(), event.getOptions()); + break; + case PLAY_MANA: + playMana(event.getPlayerId(), event.getMessage(), event.getOptions()); + break; + case PLAY_X_MANA: + playXMana(event.getPlayerId(), event.getMessage()); + break; + case CHOOSE_ABILITY: + String objectName = null; + if (event.getChoices() != null && event.getChoices().size() > 0) { + objectName = event.getChoices().iterator().next(); } - } catch (MageException ex) { - logger.fatal("Player event listener error ", ex); - } + chooseAbility(event.getPlayerId(), objectName, event.getAbilities()); + break; + case CHOOSE_PILE: + choosePile(event.getPlayerId(), event.getMessage(), event.getPile1(), event.getPile2()); + break; + case CHOOSE_MODE: + chooseMode(event.getPlayerId(), event.getModes()); + break; + case CHOOSE_CHOICE: + chooseChoice(event.getPlayerId(), event.getChoice()); + break; + case AMOUNT: + amount(event.getPlayerId(), event.getMessage(), event.getMin(), event.getMax()); + break; + case PERSONAL_MESSAGE: + informPersonal(event.getPlayerId(), event.getMessage()); + break; } + } catch (MageException ex) { + logger.fatal("Player event listener error ", ex); } + } + } ); joinWaitingExecutor.scheduleAtFixedRate(new Runnable() { @Override @@ -380,11 +380,9 @@ public class GameController implements GameCallback { } } - } else { - if (!player.hasLeft()) { - logger.debug("Player " + player.getName() + " canceled game (no user) gameId: " + game.getId()); - player.leave(); - } + } else if (!player.hasLeft()) { + logger.debug("Player " + player.getName() + " canceled game (no user) gameId: " + game.getId()); + player.leave(); } } } @@ -405,11 +403,11 @@ public class GameController implements GameCallback { joinWaitingExecutor.shutdownNow(); ThreadExecutor.getInstance().getCallExecutor().execute( new Runnable() { - @Override - public void run() { - startGame(); - } - }); + @Override + public void run() { + startGame(); + } + }); } } @@ -1077,11 +1075,11 @@ public class GameController implements GameCallback { cancelTimeout(); futureTimeout = timeoutIdleExecutor.schedule( new Runnable() { - @Override - public void run() { - idleTimeout(playerId); - } - }, + @Override + public void run() { + idleTimeout(playerId); + } + }, Main.isTestMode() ? 3600 : ConfigSettings.getInstance().getMaxSecondsIdle(), TimeUnit.SECONDS ); diff --git a/Mage.Sets/src/mage/sets/kaladesh/BuiltToLast.java b/Mage.Sets/src/mage/sets/kaladesh/BuiltToLast.java new file mode 100644 index 0000000000..e0fb62cdb2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/BuiltToLast.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.condition.common.TargetHasCardTypeCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class BuiltToLast extends CardImpl { + + public BuiltToLast(UUID ownerId) { + super(ownerId, 7, "Built to Last", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{W}"); + this.expansionSetCode = "KLD"; + + // Target creature gets +2/+2 until end of turn. If its an artifact creature, it gains indestructible until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new ConditionalContinuousEffect( + new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), new TargetHasCardTypeCondition(CardType.ARTIFACT), + "If its an artifact creature, it gains indestructible until end of turn")); + + } + + public BuiltToLast(final BuiltToLast card) { + super(card); + } + + @Override + public BuiltToLast copy() { + return new BuiltToLast(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/ConsulsShieldguard.java b/Mage.Sets/src/mage/sets/kaladesh/ConsulsShieldguard.java new file mode 100644 index 0000000000..5194bdac8f --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/ConsulsShieldguard.java @@ -0,0 +1,88 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.PayEnergyCost; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterAttackingCreature; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class ConsulsShieldguard extends CardImpl { + + private final static FilterAttackingCreature filter = new FilterAttackingCreature(); + + static { + filter.add(new AnotherPredicate()); + } + + public ConsulsShieldguard(UUID ownerId) { + super(ownerId, 11, "Consul's Shieldguard", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Dwarf"); + this.subtype.add("Soldier"); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // When Consul's Shieldguard enters the battlefield, you get {E}{E}. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GetEnergyCountersControllerEffect(2))); + + // Whenever Consul's Shiedguard attacks, you may pay {E}. If you do, another target attacking creature gets indestructible until end of turn. + DoIfCostPaid doIfCostPaidEffect = new DoIfCostPaid(new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), new PayEnergyCost(1)); + Ability ability = new AttacksTriggeredAbility(doIfCostPaidEffect, false, + "Whenever {this} attacks you may pay {E}. If you do, another target attacking creature gets indestructible until end of turn."); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + + } + + public ConsulsShieldguard(final ConsulsShieldguard card) { + super(card); + } + + @Override + public ConsulsShieldguard copy() { + return new ConsulsShieldguard(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/EddytrailHawk.java b/Mage.Sets/src/mage/sets/kaladesh/EddytrailHawk.java new file mode 100644 index 0000000000..68837ef08e --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/EddytrailHawk.java @@ -0,0 +1,88 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.PayEnergyCost; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterAttackingCreature; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class EddytrailHawk extends CardImpl { + + private final static FilterAttackingCreature filter = new FilterAttackingCreature(); + + static { + filter.add(new AnotherPredicate()); + } + + public EddytrailHawk(UUID ownerId) { + super(ownerId, 12, "Eddytrail Hawk", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Bird"); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // When Eddytail Hawk enters the battlefield, you get {E}{E}. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GetEnergyCountersControllerEffect(2))); + // When Eddytail Hawk attacks you pay {E}. If you do, another target attacking creature gains flying until end of turn. + DoIfCostPaid doIfCostPaidEffect = new DoIfCostPaid(new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), new PayEnergyCost(1), null, false); + Ability ability = new AttacksTriggeredAbility(doIfCostPaidEffect, false, + "Whenever {this} attacks you pay {E}. If you do, another target attacking creature gets indestructible until end of turn."); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + public EddytrailHawk(final EddytrailHawk card) { + super(card); + } + + @Override + public EddytrailHawk copy() { + return new EddytrailHawk(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/GearshiftAce.java b/Mage.Sets/src/mage/sets/kaladesh/GearshiftAce.java new file mode 100644 index 0000000000..f07d2bab7f --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/GearshiftAce.java @@ -0,0 +1,112 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class GearshiftAce extends CardImpl { + + public GearshiftAce(UUID ownerId) { + super(ownerId, 16, "Gearshift Ace", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Dwarf"); + this.subtype.add("Pilot"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // First Strike + this.addAbility(FirstStrikeAbility.getInstance()); + // Whenever Gearshift Ace crews a Vehicle, that Vehicle gains first strike until the end of turn. + this.addAbility(new CrewsVehicleSourceTriggeredAbility(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, + "that Vehicle gains first strike until end of turn"))); + } + + public GearshiftAce(final GearshiftAce card) { + super(card); + } + + @Override + public GearshiftAce copy() { + return new GearshiftAce(this); + } +} + +class GearshiftAceTriggeredAbility extends TriggeredAbilityImpl { + + public GearshiftAceTriggeredAbility(Effect effect) { + super(Zone.BATTLEFIELD, effect, false); + } + + public GearshiftAceTriggeredAbility(final GearshiftAceTriggeredAbility ability) { + super(ability); + } + + @Override + public GearshiftAceTriggeredAbility copy() { + return new GearshiftAceTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CREWED_VEHICLE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getTargetId().equals(getSourceId())) { + for (Effect effect : getEffects()) { + // set the vehicle id as target + effect.setTargetPointer(new FixedTarget(event.getSourceId())); + } + return true; + } + return false; + } + + @Override + public String getRule() { + return "When {this} crews a Vehicle, " + super.getRule(); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/HeraldOfTheFair.java b/Mage.Sets/src/mage/sets/kaladesh/HeraldOfTheFair.java new file mode 100644 index 0000000000..0307288540 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/HeraldOfTheFair.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class HeraldOfTheFair extends CardImpl { + + public HeraldOfTheFair(UUID ownerId) { + super(ownerId, 18, "Herald of the Fair", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Human"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // When Herald of the Fair enters the battlefield, target creature you control gets +1/+1 until end of turn. + Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn), false); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + + } + + public HeraldOfTheFair(final HeraldOfTheFair card) { + super(card); + } + + @Override + public HeraldOfTheFair copy() { + return new HeraldOfTheFair(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/MakeObsolete.java b/Mage.Sets/src/mage/sets/kaladesh/MakeObsolete.java index 453396ab24..5ca3da296e 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/MakeObsolete.java +++ b/Mage.Sets/src/mage/sets/kaladesh/MakeObsolete.java @@ -1,27 +1,26 @@ package mage.sets.kaladesh; +import java.util.UUID; import mage.abilities.effects.common.continuous.BoostOpponentsEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Rarity; -import java.util.UUID; - /** * @author royk */ public class MakeObsolete extends CardImpl { public MakeObsolete(UUID ownerId) { - super(ownerId, 89, "Make Obsolete", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "(2)(B)"); + super(ownerId, 89, "Make Obsolete", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{B}"); this.expansionSetCode = "KLD"; // Creatures your opponents control get -1/-1 until end of turn this.getSpellAbility().addEffect(new BoostOpponentsEffect(-1, -1, Duration.EndOfTurn)); } - public MakeObsolete(final MakeObsolete card) { + public MakeObsolete(final MakeObsolete card) { super(card); } diff --git a/Mage.Sets/src/mage/sets/kaladesh/NinthBridgePatrol.java b/Mage.Sets/src/mage/sets/kaladesh/NinthBridgePatrol.java new file mode 100644 index 0000000000..a3f2698238 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/NinthBridgePatrol.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.ZoneChangeAllTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; + +/** + * + * @author LevelX2 + */ +public class NinthBridgePatrol extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public NinthBridgePatrol(UUID ownerId) { + super(ownerId, 22, "Ninth Bridge Patrol", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Dwarf"); + this.subtype.add("Soldier"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Whenever another creature you control leaves the battlefield, put a +1/+1 counter on Ninth Bridge Patrol. + this.addAbility(new ZoneChangeAllTriggeredAbility(Zone.BATTLEFIELD, Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter, + "Whenever another creature you control leaves the battlefield, ", false)); + } + + public NinthBridgePatrol(final NinthBridgePatrol card) { + super(card); + } + + @Override + public NinthBridgePatrol copy() { + return new NinthBridgePatrol(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/RevokePrivilege.java b/Mage.Sets/src/mage/sets/kaladesh/RevokePrivilege.java new file mode 100644 index 0000000000..481cf2c028 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/RevokePrivilege.java @@ -0,0 +1,125 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class RevokePrivilege extends CardImpl { + + public RevokePrivilege(UUID ownerId) { + super(ownerId, 26, "Revoke Privilege", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Aura"); + + // Enchant creature. + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature can't attack, block, or crew Vehicles. + Effect effect = new CantAttackBlockAttachedEffect(AttachmentType.AURA); + effect.setText("Enchanted creature can't attack, block"); + ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); + ability.addEffect(new RevokePrivilegeCantCrewEffect()); + this.addAbility(ability); + + } + + public RevokePrivilege(final RevokePrivilege card) { + super(card); + } + + @Override + public RevokePrivilege copy() { + return new RevokePrivilege(this); + } +} + +class RevokePrivilegeCantCrewEffect extends ContinuousRuleModifyingEffectImpl { + + public RevokePrivilegeCantCrewEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = ", or crew Vehicles"; + } + + public RevokePrivilegeCantCrewEffect(final RevokePrivilegeCantCrewEffect effect) { + super(effect); + } + + @Override + public RevokePrivilegeCantCrewEffect copy() { + return new RevokePrivilegeCantCrewEffect(this); + } + + @Override + public String getInfoMessage(Ability source, GameEvent event, Game game) { + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null) { + return "The creature enchanted by " + mageObject.getIdName() + " can't crew vehicles."; + } + return null; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.CREW_VEHICLE; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent enchantment = game.getPermanent(source.getSourceId()); + return enchantment != null && event.getTargetId().equals(enchantment.getAttachedTo()); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/ServoExhibition.java b/Mage.Sets/src/mage/sets/kaladesh/ServoExhibition.java new file mode 100644 index 0000000000..05e8f4b15f --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/ServoExhibition.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.game.permanent.token.ServoToken; + +/** + * + * @author LevelX2 + */ +public class ServoExhibition extends CardImpl { + + public ServoExhibition(UUID ownerId) { + super(ownerId, 27, "Servo Exhibition", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{W}"); + this.expansionSetCode = "KLD"; + + // Create two 1/1 colorless Servo artifact creature tokens. + Effect effect = new CreateTokenEffect(new ServoToken(), 2); + effect.setText("Create two 1/1 colorless Servo artifact creature tokens"); + this.getSpellAbility().addEffect(effect); + } + + public ServoExhibition(final ServoExhibition card) { + super(card); + } + + @Override + public ServoExhibition copy() { + return new ServoExhibition(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/TrustyCompanion.java b/Mage.Sets/src/mage/sets/kaladesh/TrustyCompanion.java new file mode 100644 index 0000000000..18f238312d --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/TrustyCompanion.java @@ -0,0 +1,65 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.CantAttackAloneAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class TrustyCompanion extends CardImpl { + + public TrustyCompanion(UUID ownerId) { + super(ownerId, 33, "Trusty Companion", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Hyena"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + // Trusty Companion can't attack alone. + this.addAbility(new CantAttackAloneAbility()); + } + + public TrustyCompanion(final TrustyCompanion card) { + super(card); + } + + @Override + public TrustyCompanion copy() { + return new TrustyCompanion(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/condition/common/TargetHasCardTypeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/TargetHasCardTypeCondition.java new file mode 100644 index 0000000000..d1f0bb30af --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/TargetHasCardTypeCondition.java @@ -0,0 +1,36 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.condition.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.constants.CardType; +import mage.game.Game; + +/** + * + * @author LevelX2 + */ +public class TargetHasCardTypeCondition implements Condition { + + private final CardType cardType; + + public TargetHasCardTypeCondition(CardType cardType) { + this.cardType = cardType; + } + + @Override + public boolean apply(Game game, Ability source) { + if (!source.getTargets().isEmpty()) { + MageObject mageObject = game.getObject(source.getFirstTarget()); + if (mageObject != null) { + return mageObject.getCardType().contains(cardType); + } + } + return false; + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java index d1f7c63fc4..dc48b5baaa 100644 --- a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java @@ -1,134 +1,137 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.abilities.keyword; - -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.Cost; -import mage.abilities.costs.CostImpl; -import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; - -/** - * @author emerald000 - */ -public class CrewAbility extends SimpleActivatedAbility { - - private final int value; - - public CrewAbility(int value) { - super(Zone.BATTLEFIELD, new AddCardTypeSourceEffect(CardType.ARTIFACT, Duration.EndOfTurn), new CrewCost(value)); - this.addEffect(new AddCardTypeSourceEffect(CardType.CREATURE, Duration.EndOfTurn)); - this.value = value; - } - - public CrewAbility(final CrewAbility ability) { - super(ability); - this.value = ability.value; - } - - @Override - public CrewAbility copy() { - return new CrewAbility(this); - } - - @Override - public String getRule() { - return "Crew " + value + " (Tap any number of creatures you control with total power " + value + " or more: This Vehicle becomes an artifact creature until end of turn.)"; - } -} - -class CrewCost extends CostImpl { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); - - static { - filter.add(Predicates.not(new TappedPredicate())); - } - - private final int value; - - CrewCost(int value) { - this.value = value; - } - - CrewCost(final CrewCost cost) { - super(cost); - this.value = cost.value; - } - - @Override - public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { - Target target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true); - if (target.choose(Outcome.Tap, controllerId, sourceId, game)) { - int sumPower = 0; - for (UUID targetId : target.getTargets()) { - Permanent permanent = game.getPermanent(targetId); - if (permanent != null && permanent.tap(game)) { - sumPower += permanent.getPower().getValue(); - } - } - paid = sumPower >= value; - if (paid) { - for (UUID targetId : target.getTargets()) { - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREWED_VEHICLE, targetId, sourceId, controllerId)); - } - } - } - return paid; - } - - @Override - public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { - int sumPower = 0; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) { - sumPower += permanent.getPower().getValue(); - if (sumPower >= value) { - return true; - } - } - return false; - } - - @Override - public CrewCost copy() { - return new CrewCost(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.keyword; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.Target; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * @author emerald000 + */ +public class CrewAbility extends SimpleActivatedAbility { + + private final int value; + + public CrewAbility(int value) { + super(Zone.BATTLEFIELD, new AddCardTypeSourceEffect(CardType.ARTIFACT, Duration.EndOfTurn), new CrewCost(value)); + this.addEffect(new AddCardTypeSourceEffect(CardType.CREATURE, Duration.EndOfTurn)); + this.value = value; + } + + public CrewAbility(final CrewAbility ability) { + super(ability); + this.value = ability.value; + } + + @Override + public CrewAbility copy() { + return new CrewAbility(this); + } + + @Override + public String getRule() { + return "Crew " + value + " (Tap any number of creatures you control with total power " + value + " or more: This Vehicle becomes an artifact creature until end of turn.)"; + } +} + +class CrewCost extends CostImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + private final int value; + + CrewCost(int value) { + this.value = value; + } + + CrewCost(final CrewCost cost) { + super(cost); + this.value = cost.value; + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { + Target target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true); + if (target.choose(Outcome.Tap, controllerId, sourceId, game)) { + int sumPower = 0; + for (UUID targetId : target.getTargets()) { + GameEvent event = new GameEvent(GameEvent.EventType.CREW_VEHICLE, targetId, sourceId, controllerId); + if (!game.replaceEvent(event)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null && permanent.tap(game)) { + sumPower += permanent.getPower().getValue(); + } + } + } + paid = sumPower >= value; + if (paid) { + for (UUID targetId : target.getTargets()) { + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREWED_VEHICLE, targetId, sourceId, controllerId)); + } + } + } + return paid; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + int sumPower = 0; + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) { + sumPower += permanent.getPower().getValue(); + if (sumPower >= value) { + return true; + } + } + return false; + } + + @Override + public CrewCost copy() { + return new CrewCost(this); + } +} diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java index aeda747014..a984f80cba 100644 --- a/Mage/src/main/java/mage/game/events/GameEvent.java +++ b/Mage/src/main/java/mage/game/events/GameEvent.java @@ -109,6 +109,12 @@ public class GameEvent implements Serializable { GAIN_LIFE, GAINED_LIFE, LOSE_LIFE, LOST_LIFE, PLAY_LAND, LAND_PLAYED, + CREW_VEHICLE, + /* CREW_VEHICLE + targetId the id of the creature that crewed a vehicle + sourceId sourceId of the vehicle + playerId the id of the controlling player + */ CREWED_VEHICLE, /* CREWED_VEHICLE targetId the id of the creature that crewed a vehicle