[KLD] Added 9 white cards.

This commit is contained in:
LevelX2 2016-09-17 00:45:33 +02:00
parent cf568fd41d
commit d3d1402fbb
14 changed files with 1058 additions and 261 deletions

View file

@ -156,123 +156,123 @@ public class GameController implements GameCallback {
private void init() { private void init() {
game.addTableEventListener( game.addTableEventListener(
new Listener<TableEvent>() { new Listener<TableEvent>() {
@Override @Override
public void event(TableEvent event) { public void event(TableEvent event) {
try { try {
PriorityTimer timer; PriorityTimer timer;
UUID playerId; UUID playerId;
switch (event.getEventType()) { switch (event.getEventType()) {
case UPDATE: case UPDATE:
updateGame(); updateGame();
break; break;
case INFO: case INFO:
ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, ChatMessage.MessageType.GAME); ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, ChatMessage.MessageType.GAME);
logger.trace(game.getId() + " " + event.getMessage()); logger.trace(game.getId() + " " + event.getMessage());
break; break;
case STATUS: case STATUS:
ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), ChatMessage.MessageType.GAME); ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), ChatMessage.MessageType.GAME);
logger.trace(game.getId() + " " + event.getMessage()); logger.trace(game.getId() + " " + event.getMessage());
break; break;
case ERROR: case ERROR:
error(event.getMessage(), event.getException()); error(event.getMessage(), event.getException());
break; break;
case END_GAME_INFO: case END_GAME_INFO:
endGameInfo(); endGameInfo();
break; break;
case INIT_TIMER: case INIT_TIMER:
final UUID initPlayerId = event.getPlayerId(); final UUID initPlayerId = event.getPlayerId();
if (initPlayerId == null) { if (initPlayerId == null) {
throw new MageException("INIT_TIMER: playerId can't be 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;
} }
} catch (MageException ex) { createPlayerTimer(event.getPlayerId(), game.getPriorityTime());
logger.fatal("Table event listener error ", ex); 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( game.addPlayerQueryEventListener(
new Listener<PlayerQueryEvent>() { new Listener<PlayerQueryEvent>() {
@Override @Override
public void event(PlayerQueryEvent event) { public void event(PlayerQueryEvent event) {
logger.trace(new StringBuilder(event.getPlayerId().toString()).append("--").append(event.getQueryType()).append("--").append(event.getMessage()).toString()); logger.trace(new StringBuilder(event.getPlayerId().toString()).append("--").append(event.getQueryType()).append("--").append(event.getMessage()).toString());
try { try {
switch (event.getQueryType()) { switch (event.getQueryType()) {
case ASK: case ASK:
ask(event.getPlayerId(), event.getMessage(), event.getOptions()); ask(event.getPlayerId(), event.getMessage(), event.getOptions());
break; break;
case PICK_TARGET: case PICK_TARGET:
target(event.getPlayerId(), event.getMessage(), event.getCards(), event.getPerms(), event.getTargets(), event.isRequired(), event.getOptions()); target(event.getPlayerId(), event.getMessage(), event.getCards(), event.getPerms(), event.getTargets(), event.isRequired(), event.getOptions());
break; break;
case PICK_ABILITY: case PICK_ABILITY:
target(event.getPlayerId(), event.getMessage(), event.getAbilities(), event.isRequired(), event.getOptions()); target(event.getPlayerId(), event.getMessage(), event.getAbilities(), event.isRequired(), event.getOptions());
break; break;
case SELECT: case SELECT:
select(event.getPlayerId(), event.getMessage(), event.getOptions()); select(event.getPlayerId(), event.getMessage(), event.getOptions());
break; break;
case PLAY_MANA: case PLAY_MANA:
playMana(event.getPlayerId(), event.getMessage(), event.getOptions()); playMana(event.getPlayerId(), event.getMessage(), event.getOptions());
break; break;
case PLAY_X_MANA: case PLAY_X_MANA:
playXMana(event.getPlayerId(), event.getMessage()); playXMana(event.getPlayerId(), event.getMessage());
break; break;
case CHOOSE_ABILITY: case CHOOSE_ABILITY:
String objectName = null; String objectName = null;
if (event.getChoices() != null && event.getChoices().size() > 0) { if (event.getChoices() != null && event.getChoices().size() > 0) {
objectName = event.getChoices().iterator().next(); 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;
} }
} catch (MageException ex) { chooseAbility(event.getPlayerId(), objectName, event.getAbilities());
logger.fatal("Player event listener error ", ex); 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() { joinWaitingExecutor.scheduleAtFixedRate(new Runnable() {
@Override @Override
@ -380,11 +380,9 @@ public class GameController implements GameCallback {
} }
} }
} else { } else if (!player.hasLeft()) {
if (!player.hasLeft()) { logger.debug("Player " + player.getName() + " canceled game (no user) gameId: " + game.getId());
logger.debug("Player " + player.getName() + " canceled game (no user) gameId: " + game.getId()); player.leave();
player.leave();
}
} }
} }
} }
@ -405,11 +403,11 @@ public class GameController implements GameCallback {
joinWaitingExecutor.shutdownNow(); joinWaitingExecutor.shutdownNow();
ThreadExecutor.getInstance().getCallExecutor().execute( ThreadExecutor.getInstance().getCallExecutor().execute(
new Runnable() { new Runnable() {
@Override @Override
public void run() { public void run() {
startGame(); startGame();
} }
}); });
} }
} }
@ -1077,11 +1075,11 @@ public class GameController implements GameCallback {
cancelTimeout(); cancelTimeout();
futureTimeout = timeoutIdleExecutor.schedule( futureTimeout = timeoutIdleExecutor.schedule(
new Runnable() { new Runnable() {
@Override @Override
public void run() { public void run() {
idleTimeout(playerId); idleTimeout(playerId);
} }
}, },
Main.isTestMode() ? 3600 : ConfigSettings.getInstance().getMaxSecondsIdle(), Main.isTestMode() ? 3600 : ConfigSettings.getInstance().getMaxSecondsIdle(),
TimeUnit.SECONDS TimeUnit.SECONDS
); );

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -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);
}
}

View file

@ -1,27 +1,26 @@
package mage.sets.kaladesh; package mage.sets.kaladesh;
import java.util.UUID;
import mage.abilities.effects.common.continuous.BoostOpponentsEffect; import mage.abilities.effects.common.continuous.BoostOpponentsEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Rarity; import mage.constants.Rarity;
import java.util.UUID;
/** /**
* @author royk * @author royk
*/ */
public class MakeObsolete extends CardImpl { public class MakeObsolete extends CardImpl {
public MakeObsolete(UUID ownerId) { 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"; this.expansionSetCode = "KLD";
// Creatures your opponents control get -1/-1 until end of turn // Creatures your opponents control get -1/-1 until end of turn
this.getSpellAbility().addEffect(new BoostOpponentsEffect(-1, -1, Duration.EndOfTurn)); this.getSpellAbility().addEffect(new BoostOpponentsEffect(-1, -1, Duration.EndOfTurn));
} }
public MakeObsolete(final MakeObsolete card) { public MakeObsolete(final MakeObsolete card) {
super(card); super(card);
} }

View file

@ -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);
}
}

View file

@ -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());
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -1,134 +1,137 @@
/* /*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, are * Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met: * permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, this list of * 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer. * conditions and the following disclaimer.
* *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list * 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 * of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution. * provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * 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 * 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 * 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 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 * 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 * 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 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* The views and conclusions contained in the software and documentation are those of the * 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 * authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com. * or implied, of BetaSteward_at_googlemail.com.
*/ */
package mage.abilities.keyword; package mage.abilities.keyword;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost; import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl; import mage.abilities.costs.CostImpl;
import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect; import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TappedPredicate; import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.Target; import mage.target.Target;
import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent;
/** /**
* @author emerald000 * @author emerald000
*/ */
public class CrewAbility extends SimpleActivatedAbility { public class CrewAbility extends SimpleActivatedAbility {
private final int value; private final int value;
public CrewAbility(int value) { public CrewAbility(int value) {
super(Zone.BATTLEFIELD, new AddCardTypeSourceEffect(CardType.ARTIFACT, Duration.EndOfTurn), new CrewCost(value)); super(Zone.BATTLEFIELD, new AddCardTypeSourceEffect(CardType.ARTIFACT, Duration.EndOfTurn), new CrewCost(value));
this.addEffect(new AddCardTypeSourceEffect(CardType.CREATURE, Duration.EndOfTurn)); this.addEffect(new AddCardTypeSourceEffect(CardType.CREATURE, Duration.EndOfTurn));
this.value = value; this.value = value;
} }
public CrewAbility(final CrewAbility ability) { public CrewAbility(final CrewAbility ability) {
super(ability); super(ability);
this.value = ability.value; this.value = ability.value;
} }
@Override @Override
public CrewAbility copy() { public CrewAbility copy() {
return new CrewAbility(this); return new CrewAbility(this);
} }
@Override @Override
public String getRule() { public String getRule() {
return "Crew " + value + " <i>(Tap any number of creatures you control with total power " + value + " or more: This Vehicle becomes an artifact creature until end of turn.)</i>"; return "Crew " + value + " <i>(Tap any number of creatures you control with total power " + value + " or more: This Vehicle becomes an artifact creature until end of turn.)</i>";
} }
} }
class CrewCost extends CostImpl { class CrewCost extends CostImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control");
static { static {
filter.add(Predicates.not(new TappedPredicate())); filter.add(Predicates.not(new TappedPredicate()));
} }
private final int value; private final int value;
CrewCost(int value) { CrewCost(int value) {
this.value = value; this.value = value;
} }
CrewCost(final CrewCost cost) { CrewCost(final CrewCost cost) {
super(cost); super(cost);
this.value = cost.value; this.value = cost.value;
} }
@Override @Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { 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); Target target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true);
if (target.choose(Outcome.Tap, controllerId, sourceId, game)) { if (target.choose(Outcome.Tap, controllerId, sourceId, game)) {
int sumPower = 0; int sumPower = 0;
for (UUID targetId : target.getTargets()) { for (UUID targetId : target.getTargets()) {
Permanent permanent = game.getPermanent(targetId); GameEvent event = new GameEvent(GameEvent.EventType.CREW_VEHICLE, targetId, sourceId, controllerId);
if (permanent != null && permanent.tap(game)) { if (!game.replaceEvent(event)) {
sumPower += permanent.getPower().getValue(); 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)); paid = sumPower >= value;
} if (paid) {
} for (UUID targetId : target.getTargets()) {
} game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREWED_VEHICLE, targetId, sourceId, controllerId));
return paid; }
} }
}
@Override return paid;
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { }
int sumPower = 0;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) { @Override
sumPower += permanent.getPower().getValue(); public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
if (sumPower >= value) { int sumPower = 0;
return true; for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) {
} sumPower += permanent.getPower().getValue();
} if (sumPower >= value) {
return false; return true;
} }
}
@Override return false;
public CrewCost copy() { }
return new CrewCost(this);
} @Override
} public CrewCost copy() {
return new CrewCost(this);
}
}

View file

@ -109,6 +109,12 @@ public class GameEvent implements Serializable {
GAIN_LIFE, GAINED_LIFE, GAIN_LIFE, GAINED_LIFE,
LOSE_LIFE, LOST_LIFE, LOSE_LIFE, LOST_LIFE,
PLAY_LAND, LAND_PLAYED, 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,
/* CREWED_VEHICLE /* CREWED_VEHICLE
targetId the id of the creature that crewed a vehicle targetId the id of the creature that crewed a vehicle