Merge pull request #5286 from Zzooouhh/Zzooouhh-ugl

Implemented Unglued cards
This commit is contained in:
L_J 2018-09-30 14:13:19 +02:00 committed by GitHub
commit 494b51eb9b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 1214 additions and 0 deletions

View file

@ -0,0 +1,119 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyIfConditionIsTrueAbility;
import mage.abilities.common.SpellCastAllTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.filter.FilterSpell;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
/**
*
* @author L_J
*/
public final class ChecksAndBalances extends CardImpl {
public ChecksAndBalances(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}");
// Cast this spell only if there are three or more players in the game.
this.addAbility(new CastOnlyIfConditionIsTrueAbility(ChecksAndBalancesCondition.instance, "Cast this spell only if there are three or more players in the game"));
// Whenever a player casts a spell, each of that players opponents may discard a card. If they do, counter that spell.
this.addAbility(new SpellCastAllTriggeredAbility(new ChecksAndBalancesEffect(), new FilterSpell("a spell"), false, SetTargetPointer.SPELL));
}
public ChecksAndBalances(final ChecksAndBalances card) {
super(card);
}
@Override
public ChecksAndBalances copy() {
return new ChecksAndBalances(this);
}
}
enum ChecksAndBalancesCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
return game.getPlayerList().size() >= 3;
}
@Override
public String toString() {
return "there are three or more players in the game";
}
}
class ChecksAndBalancesEffect extends OneShotEffect {
public ChecksAndBalancesEffect() {
super(Outcome.Detriment);
staticText = "each of that players opponents may discard a card. If they do, counter that spell";
}
public ChecksAndBalancesEffect(final ChecksAndBalancesEffect effect) {
super(effect);
}
@Override
public ChecksAndBalancesEffect copy() {
return new ChecksAndBalancesEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getStack().getSpell(this.getTargetPointer().getFirst(game, source));
if (spell != null) {
for (UUID uuid : game.getOpponents(spell.getControllerId())) {
Player player = game.getPlayer(uuid);
if (player != null) {
if (player.getHand().isEmpty()) {
game.informPlayers(player.getLogName() + " doesn't have a card in hand to discard to counter " + spell.getLogName() + ", effect aborted.");
return true;
}
}
}
for (UUID uuid : game.getOpponents(spell.getControllerId())) {
Player player = game.getPlayer(uuid);
if (player != null) {
if (!player.chooseUse(outcome, "Do you wish to discard a card to counter " + spell.getLogName() + '?', source, game)) {
game.informPlayers(player.getLogName() + " refuses to discard a card to counter " + spell.getLogName());
return true;
} else {
game.informPlayers(player.getLogName() + " agrees to discard a card to counter " + spell.getLogName());
}
}
}
for (UUID uuid : game.getOpponents(spell.getControllerId())) {
Player player = game.getPlayer(uuid);
if (player != null && !player.getHand().isEmpty()) {
TargetCardInHand target = new TargetCardInHand();
if (player.choose(Outcome.Discard, target, source.getSourceId(), game)) {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
player.discard(card, source, game);
}
}
}
}
game.getStack().counter(spell.getId(), source.getSourceId(), game);
return true;
}
return false;
}
}

View file

@ -0,0 +1,92 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
/**
*
* @author L_J
*/
public final class ClamIAm extends CardImpl {
public ClamIAm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.CLAMFOLK);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// If you roll a 3 on a six-sided die, you may reroll that die.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ClamIAmEffect()));
}
public ClamIAm(final ClamIAm card) {
super(card);
}
@Override
public ClamIAm copy() {
return new ClamIAm(this);
}
}
class ClamIAmEffect extends ReplacementEffectImpl {
ClamIAmEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "If you roll a 3 on a six-sided die, you may reroll that die";
}
ClamIAmEffect(final ClamIAmEffect effect) {
super(effect);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player player = game.getPlayer(event.getPlayerId());
if (player != null) {
String data = event.getData();
int numSides = Integer.parseInt(data);
if (numSides == 6 && event.getAmount() == 3) {
if (player.chooseUse(outcome, "Reroll the die?", source, game)) {
game.informPlayers(player.getLogName() + " chose to reroll the die.");
event.setAmount(player.rollDice(game, 6));
}
}
}
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ROLL_DICE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return source.getControllerId().equals(event.getPlayerId());
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public ClamIAmEffect copy() {
return new ClamIAmEffect(this);
}
}

View file

@ -0,0 +1,102 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetControlledPermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public final class Clambassadors extends CardImpl {
public Clambassadors(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add(SubType.CLAMFOLK);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Whenever Clambassadors deals damage to a player, choose an artifact, creature, or land you control. That player gains control of that permanent.
this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new ClambassadorsEffect(), false, true));
}
public Clambassadors(final Clambassadors card) {
super(card);
}
@Override
public Clambassadors copy() {
return new Clambassadors(this);
}
}
class ClambassadorsEffect extends OneShotEffect {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("artifact, creature, or land you control");
static {
filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT),
new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.LAND)));
}
static {
filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.LAND)));
}
public ClambassadorsEffect() {
super(Outcome.Detriment);
this.staticText = "choose an artifact, creature, or land you control. That player gains control of that permanent";
}
public ClambassadorsEffect(final ClambassadorsEffect effect) {
super(effect);
}
@Override
public ClambassadorsEffect copy() {
return new ClambassadorsEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Target target = new TargetControlledPermanent(1, 1, filter, true);
if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
while (!target.isChosen() && target.canChoose(controller.getId(), game) && controller.canRespond()) {
controller.chooseTarget(outcome, target, source, game);
}
}
Permanent permanent = game.getPermanent(target.getFirstTarget());
Player opponent = game.getPlayer(this.getTargetPointer().getFirst(game, source));
if (permanent != null && opponent != null) {
ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, true, opponent.getId());
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
game.informPlayers(opponent.getLogName() + " has gained control of " + permanent.getLogName());
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,80 @@
package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
import mage.game.stack.Spell;
import mage.target.TargetSpell;
/**
*
* @author L_J
*/
public final class Denied extends CardImpl {
public Denied(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}");
// Choose a card name, then target spell's controller reveals their hand. If a card with the chosen name is revealed this way, counter that spell.
this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL));
this.getSpellAbility().addEffect(new DeniedEffect());
this.getSpellAbility().addTarget(new TargetSpell());
}
public Denied(final Denied card) {
super(card);
}
@Override
public Denied copy() {
return new Denied(this);
}
}
class DeniedEffect extends OneShotEffect {
public DeniedEffect() {
super(Outcome.Detriment);
staticText = "Choose a card name, then target spell's controller reveals their hand. If a card with the chosen name is revealed this way, counter that spell";
}
public DeniedEffect(final DeniedEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Spell targetSpell = game.getStack().getSpell(source.getFirstTarget());
if (targetSpell == null) {
return true;
}
Player player = game.getPlayer(targetSpell.getControllerId());
Object object = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
if (player != null && object instanceof String) {
player.revealCards("Denied!", player.getHand(), game, true);
String namedCard = (String) object;
for (Card card : player.getHand().getCards(game)) {
if (card != null && card.getName().equals(namedCard)) {
game.getStack().counter(targetSpell.getId(), source.getSourceId(), game);
break;
}
}
return true;
}
return false;
}
@Override
public DeniedEffect copy() {
return new DeniedEffect(this);
}
}

View file

@ -0,0 +1,71 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.token.RabidSheepToken;
import mage.players.Player;
/**
*
* @author L_J
*/
public class FlockOfRabidSheep extends CardImpl {
public FlockOfRabidSheep(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{G}{G}");
// Flip X coins. For each flip you win, create a 2/2 green Sheep creature token named Rabid Sheep.
this.getSpellAbility().addEffect(new FlockOfRabidSheepEffect());
}
public FlockOfRabidSheep(final FlockOfRabidSheep card) {
super(card);
}
@Override
public FlockOfRabidSheep copy() {
return new FlockOfRabidSheep(this);
}
}
class FlockOfRabidSheepEffect extends OneShotEffect {
public FlockOfRabidSheepEffect() {
super(Outcome.LoseLife);
this.staticText = "Flip X coins. For each flip you win, create a 2/2 green Sheep creature token named Rabid Sheep";
}
public FlockOfRabidSheepEffect(final FlockOfRabidSheepEffect effect) {
super(effect);
}
@Override
public FlockOfRabidSheepEffect copy() {
return new FlockOfRabidSheepEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int repeat = source.getManaCostsToPay().getX();
int wonCount = 0;
for (int i = 1; i <= repeat; i++) {
if (controller.flipCoin(game)) {
wonCount++;
}
}
new CreateTokenEffect(new RabidSheepToken(), wonCount).apply(game, source);
return true;
}
return false;
}
}

View file

@ -0,0 +1,144 @@
package mage.cards.f;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.ExileZone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author L_J
*/
public final class FreeForAll extends CardImpl {
public FreeForAll(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{U}");
// When Free-for-All enters the battlefield, exile all creatures face down.
this.addAbility(new EntersBattlefieldTriggeredAbility(new FreeForAllExileAllEffect()));
// At the beginning of each player's upkeep, that player chooses a card exiled with Free-for-All at random and puts it onto the battlefield.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new FreeForAllReturnFromExileEffect(), TargetController.ANY, false, true));
// When Free-for-All leaves the battlefield, put all cards exiled with it into their owners' graveyards.
this.addAbility(new LeavesBattlefieldTriggeredAbility(new FreeForAllLeavesBattlefieldEffect(), false));
}
public FreeForAll(final FreeForAll card) {
super(card);
}
@Override
public FreeForAll copy() {
return new FreeForAll(this);
}
}
class FreeForAllExileAllEffect extends OneShotEffect {
public FreeForAllExileAllEffect() {
super(Outcome.Exile);
staticText = "exile all creatures face down";
}
public FreeForAllExileAllEffect(final FreeForAllExileAllEffect effect) {
super(effect);
}
@Override
public FreeForAllExileAllEffect copy() {
return new FreeForAllExileAllEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game);
for (Permanent permanent : permanents) {
Card card = game.getCard(permanent.getId());
permanent.moveToExile(source.getSourceId(), "Free-for-All", source.getSourceId(), game);
if (card != null) {
card.setFaceDown(true, game);
}
}
return true;
}
}
class FreeForAllReturnFromExileEffect extends OneShotEffect {
public FreeForAllReturnFromExileEffect() {
super(Outcome.PutCardInPlay);
staticText = "that player chooses a card exiled with Free-for-All at random and puts it onto the battlefield";
}
public FreeForAllReturnFromExileEffect(final FreeForAllReturnFromExileEffect effect) {
super(effect);
}
@Override
public FreeForAllReturnFromExileEffect copy() {
return new FreeForAllReturnFromExileEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
if (player != null) {
ExileZone exZone = game.getExile().getExileZone(source.getSourceId());
if (exZone != null) {
Cards exiledCards = new CardsImpl(exZone.getCards(game));
return player.moveCards(exiledCards.getRandom(game), Zone.BATTLEFIELD, source, game);
}
return true;
}
return false;
}
}
class FreeForAllLeavesBattlefieldEffect extends OneShotEffect {
public FreeForAllLeavesBattlefieldEffect() {
super(Outcome.Detriment);
this.staticText = "put all cards exiled with it into their owners' graveyards";
}
public FreeForAllLeavesBattlefieldEffect(final FreeForAllLeavesBattlefieldEffect effect) {
super(effect);
}
@Override
public FreeForAllLeavesBattlefieldEffect copy() {
return new FreeForAllLeavesBattlefieldEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
ExileZone exZone = game.getExile().getExileZone(source.getSourceId());
if (exZone != null) {
return controller.moveCards(exZone.getCards(game), Zone.GRAVEYARD, source, game, false, false, true, null);
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,135 @@
package mage.cards.f;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.watchers.Watcher;
/**
*
* @author L_J
*/
public final class FreeRangeChicken extends CardImpl {
public FreeRangeChicken(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
this.subtype.add(SubType.CHICKEN);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// {1}{G}: Roll two six-sided dice. If both results are the same, Free-Range Chicken gets +X/+X until end of turn, where X is that result. If the total of those results is equal to any other total you have rolled this turn for Free-Range Chicken, sacrifice it. (For example, if you roll two 3s, Free-Range Chicken gets +3/+3. If you roll a total of 6 for Free-Range Chicken later that turn, sacrifice it.)
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new FreeRangeChickenEffect(), new ManaCostsImpl("{1}{G}")), new FreeRangeChickenWatcher());
}
public FreeRangeChicken(final FreeRangeChicken card) {
super(card);
}
@Override
public FreeRangeChicken copy() {
return new FreeRangeChicken(this);
}
}
class FreeRangeChickenEffect extends OneShotEffect {
public FreeRangeChickenEffect() {
super(Outcome.BoostCreature);
this.staticText = "Roll two six-sided dice. If both results are the same, Free-Range Chicken gets +X/+X until end of turn, where X is that result. If the total of those results is equal to any other total you have rolled this turn for Free-Range Chicken, sacrifice it";
}
public FreeRangeChickenEffect(final FreeRangeChickenEffect effect) {
super(effect);
}
@Override
public FreeRangeChickenEffect copy() {
return new FreeRangeChickenEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int firstRoll = controller.rollDice(game, 6);
int secondRoll = controller.rollDice(game, 6);
if (firstRoll == secondRoll) {
game.addEffect(new BoostSourceEffect(firstRoll, firstRoll, Duration.EndOfTurn), source);
}
FreeRangeChickenWatcher watcher = (FreeRangeChickenWatcher) game.getState().getWatchers().get(FreeRangeChickenWatcher.class.getSimpleName());
if (watcher != null) {
int totalRoll = firstRoll + secondRoll;
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null) {
if (watcher.rolledThisTurn(sourcePermanent.getId(), totalRoll)) {
sourcePermanent.sacrifice(source.getSourceId(), game);
} else {
watcher.addRoll(sourcePermanent.getId(), totalRoll);
}
}
}
return true;
}
return false;
}
}
class FreeRangeChickenWatcher extends Watcher {
private final Map<UUID, Integer> totalRolls = new HashMap<>();
public FreeRangeChickenWatcher() {
super(FreeRangeChickenWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public FreeRangeChickenWatcher(final FreeRangeChickenWatcher watcher) {
super(watcher);
for (Map.Entry<UUID, Integer> entry : watcher.totalRolls.entrySet()) {
this.totalRolls.put(entry.getKey(), entry.getValue());
}
}
@Override
public void watch(GameEvent event, Game game) {
}
@Override
public void reset() {
totalRolls.clear();
}
@Override
public FreeRangeChickenWatcher copy() {
return new FreeRangeChickenWatcher(this);
}
public void addRoll(UUID sourceId, int roll) {
totalRolls.put(sourceId, roll);
}
public boolean rolledThisTurn(UUID sourceId, int roll) {
if (totalRolls.get(sourceId) != null) {
return totalRolls.get(sourceId) == roll;
}
return false;
}
}

View file

@ -0,0 +1,110 @@
package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
/**
*
* @author L_J
*/
public final class GoblinBowlingTeam extends CardImpl {
public GoblinBowlingTeam(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}");
this.subtype.add(SubType.GOBLIN);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// If Goblin Bowling Team would deal damage to a permanent or player, it deals that much damage plus the result of a six-sided die roll to that permanent or player instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GoblinBowlingTeamEffect()));
}
public GoblinBowlingTeam(final GoblinBowlingTeam card) {
super(card);
}
@Override
public GoblinBowlingTeam copy() {
return new GoblinBowlingTeam(this);
}
}
class GoblinBowlingTeamEffect extends ReplacementEffectImpl {
public GoblinBowlingTeamEffect() {
super(Duration.WhileOnBattlefield, Outcome.Damage);
staticText = "If {this} would deal damage to a permanent or player, it deals that much damage plus the result of a six-sided die roll to that permanent or player instead";
}
public GoblinBowlingTeamEffect(final GoblinBowlingTeamEffect effect) {
super(effect);
}
@Override
public GoblinBowlingTeamEffect copy() {
return new GoblinBowlingTeamEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
switch (event.getType()) {
case DAMAGE_CREATURE:
case DAMAGE_PLAYER:
case DAMAGE_PLANESWALKER:
return true;
default:
return false;
}
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return event.getSourceId().equals(source.getSourceId());
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
DamageEvent damageEvent = (DamageEvent) event;
if (damageEvent.getType() == EventType.DAMAGE_PLAYER) {
Player targetPlayer = game.getPlayer(event.getTargetId());
if (targetPlayer != null) {
targetPlayer.damage(CardUtil.addWithOverflowCheck(damageEvent.getAmount(), controller.rollDice(game, 6)), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
return true;
}
} else {
Permanent targetPermanent = game.getPermanent(event.getTargetId());
if (targetPermanent != null) {
targetPermanent.damage(CardUtil.addWithOverflowCheck(damageEvent.getAmount(), controller.rollDice(game, 6)), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
return true;
}
}
}
return false;
}
}

View file

@ -0,0 +1,154 @@
package mage.cards.r;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.SpellCastAllTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.filter.FilterSpell;
import mage.filter.predicate.ObjectPlayer;
import mage.filter.predicate.ObjectPlayerPredicate;
import mage.filter.predicate.mageobject.NumberOfTargetsPredicate;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.Target;
import mage.target.Targets;
import mage.util.TargetAddress;
/**
*
* @author L_J
*/
public final class Ricochet extends CardImpl {
protected static final FilterSpell filter = new FilterSpell("a spell that targets a single player");
static {
filter.add(new NumberOfTargetsPredicate(1));
filter.add(new SpellWithOnlyPlayerTargetsPredicate());
}
public Ricochet(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{R}");
// Whenever a player casts a spell that targets a single player, each player rolls a six-sided die. Change the target of that spell to the player with the lowest result. Reroll to break ties, if necessary.
this.addAbility(new SpellCastAllTriggeredAbility(new RicochetEffect(), filter, false, SetTargetPointer.SPELL));
}
public Ricochet(final Ricochet card) {
super(card);
}
@Override
public Ricochet copy() {
return new Ricochet(this);
}
}
class SpellWithOnlyPlayerTargetsPredicate implements ObjectPlayerPredicate<ObjectPlayer<Spell>> {
@Override
public boolean apply(ObjectPlayer<Spell> input, Game game) {
Spell spell = input.getObject();
if (spell == null) {
return false;
}
for (TargetAddress addr : TargetAddress.walk(spell)) {
Target targetInstance = addr.getTarget(spell);
for (UUID targetId : targetInstance.getTargets()) {
if (game.getPlayer(targetId) == null) {
return false;
}
}
}
return true;
}
}
class RicochetEffect extends OneShotEffect {
public RicochetEffect() {
super(Outcome.Detriment);
staticText = "each player rolls a six-sided die. Change the target of that spell to the player with the lowest result. Reroll to break ties, if necessary";
}
public RicochetEffect(final RicochetEffect effect) {
super(effect);
}
@Override
public RicochetEffect copy() {
return new RicochetEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getStack().getSpell(this.getTargetPointer().getFirst(game, source));
if (spell != null) {
Targets targets = new Targets();
Ability sourceAbility = spell.getSpellAbility();
for (UUID modeId : sourceAbility.getModes().getSelectedModes()) {
Mode mode = sourceAbility.getModes().get(modeId);
targets.addAll(mode.getTargets());
}
if (targets.size() != 1 || targets.get(0).getTargets().size() != 1) {
return false;
}
Map<Player, Integer> playerRolls = new HashMap<>();
for (UUID playerId : game.getPlayerList().copy()) {
Player player = game.getPlayer(playerId);
if (player != null) {
playerRolls.put(player, 7);
}
}
do {
for (Player player : playerRolls.keySet()) {
playerRolls.put(player, player.rollDice(game, 6));
}
int minValueInMap = Collections.min(playerRolls.values());
for (Map.Entry<Player, Integer> mapEntry : new HashSet<>(playerRolls.entrySet())) {
if (mapEntry.getValue() > minValueInMap) {
playerRolls.remove(mapEntry.getKey());
}
}
} while (playerRolls.size() > 1);
if (playerRolls.size() == 1) {
Player loser = (Player) playerRolls.keySet().toArray()[0];
UUID loserId = loser.getId();
Target target = targets.get(0);
if (target.getFirstTarget().equals(loserId)) {
return true;
}
String oldTargetName = null;
if (target.canTarget(spell.getControllerId(), loserId, sourceAbility, game)) {
Player oldPlayer = game.getPlayer(targets.getFirstTarget());
if (oldPlayer != null) {
oldTargetName = oldPlayer.getLogName();
}
target.clearChosen();
target.addTarget(loserId, sourceAbility, game);
}
MageObject sourceObject = game.getObject(source.getSourceId());
if (oldTargetName != null && sourceObject != null) {
game.informPlayers(sourceObject.getLogName() + ": Changed target of " + spell.getLogName() + " from " + oldTargetName + " to " + loser.getLogName());
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,56 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.common.FilterPermanentCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.filter.predicate.other.ExpansionSetPredicate;
/**
*
* @author L_J
*/
public final class SpatulaOfTheAges extends CardImpl {
private static final FilterPermanentCard filter = new FilterPermanentCard("a silver-bordered permanent card");
static {
filter.add(Predicates.and(
Predicates.not(new SupertypePredicate(SuperType.BASIC)), // all Un-set basic lands are black bordered cards, and thus illegal choices
Predicates.not(new NamePredicate("Steamflogger Boss")), // printed in Unstable with a black border
Predicates.or(new ExpansionSetPredicate("UGL"), new ExpansionSetPredicate("UNH"), new ExpansionSetPredicate("UST"))
));
}
public SpatulaOfTheAges(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
// {4}, {T}, Sacrifice Spatula of the Ages: You may put a silver-bordered permanent card from your hand onto the battlefield.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutCardFromHandOntoBattlefieldEffect(filter), new ManaCostsImpl("{4}"));
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
}
public SpatulaOfTheAges(final SpatulaOfTheAges card) {
super(card);
}
@Override
public SpatulaOfTheAges copy() {
return new SpatulaOfTheAges(this);
}
}

View file

@ -0,0 +1,107 @@
package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author L_J
*/
public final class TempOfTheDamned extends CardImpl {
public TempOfTheDamned(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// As Temp of the Damned enters the battlefield, roll a six-sided die. Temp of the Damned enters the battlefield with a number of funk counters on it equal to the result.
this.addAbility(new AsEntersBattlefieldAbility(new TempOfTheDamnedEffect()));
// At the beginning of your upkeep, remove a funk counter from Temp of the Damned. If you can't, sacrifice it.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TempOfTheDamnedUpkeepEffect(), TargetController.YOU, false));
}
public TempOfTheDamned(final TempOfTheDamned card) {
super(card);
}
@Override
public TempOfTheDamned copy() {
return new TempOfTheDamned(this);
}
}
class TempOfTheDamnedEffect extends OneShotEffect {
public TempOfTheDamnedEffect() {
super(Outcome.Neutral);
staticText = "roll a six-sided die. {this} enters the battlefield with a number of funk counters on it equal to the result";
}
public TempOfTheDamnedEffect(final TempOfTheDamnedEffect effect) {
super(effect);
}
@Override
public TempOfTheDamnedEffect copy() {
return new TempOfTheDamnedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
return new AddCountersSourceEffect(CounterType.FUNK.createInstance(controller.rollDice(game, 6))).apply(game, source);
}
return false;
}
}
class TempOfTheDamnedUpkeepEffect extends OneShotEffect {
TempOfTheDamnedUpkeepEffect() {
super(Outcome.Sacrifice);
staticText = "remove a funk counter from {this}. If you can't, sacrifice it";
}
TempOfTheDamnedUpkeepEffect(final TempOfTheDamnedUpkeepEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
int amount = permanent.getCounters(game).getCount(CounterType.FUNK);
if (amount > 0) {
permanent.removeCounters(CounterType.FUNK.createInstance(), game);
} else {
permanent.sacrifice(source.getSourceId(), game);
}
return true;
}
return false;
}
@Override
public TempOfTheDamnedUpkeepEffect copy() {
return new TempOfTheDamnedUpkeepEffect(this);
}
}

View file

@ -22,12 +22,21 @@ public final class Unglued extends ExpansionSet {
super("Unglued", "UGL", ExpansionSet.buildDate(1998, 8, 11), SetType.JOKESET);
cards.add(new SetCardInfo("Burning Cinder Fury of Crimson Chaos Fire", 40, Rarity.RARE, mage.cards.b.BurningCinderFuryOfCrimsonChaosFire.class));
cards.add(new SetCardInfo("Checks and Balances", 16, Rarity.UNCOMMON, mage.cards.c.ChecksAndBalances.class));
cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class));
cards.add(new SetCardInfo("Chicken a la King", 17, Rarity.RARE, mage.cards.c.ChickenALaKing.class));
cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class));
cards.add(new SetCardInfo("Clambassadors", 18, Rarity.COMMON, mage.cards.c.Clambassadors.class));
cards.add(new SetCardInfo("Clam-I-Am", 19, Rarity.COMMON, mage.cards.c.ClamIAm.class));
cards.add(new SetCardInfo("Denied!", 22, Rarity.COMMON, mage.cards.d.Denied.class));
cards.add(new SetCardInfo("Elvish Impersonators", 56, Rarity.COMMON, mage.cards.e.ElvishImpersonators.class));
cards.add(new SetCardInfo("Flock of Rabid Sheep", 57, Rarity.UNCOMMON, mage.cards.f.FlockOfRabidSheep.class));
cards.add(new SetCardInfo("Forest", 88, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Fowl Play", 24, Rarity.COMMON, mage.cards.f.FowlPlay.class));
cards.add(new SetCardInfo("Free-for-All", 25, Rarity.RARE, mage.cards.f.FreeForAll.class));
cards.add(new SetCardInfo("Free-Range Chicken", 58, Rarity.COMMON, mage.cards.f.FreeRangeChicken.class));
cards.add(new SetCardInfo("Gerrymandering", 59, Rarity.UNCOMMON, mage.cards.g.Gerrymandering.class));
cards.add(new SetCardInfo("Goblin Bowling Team", 44, Rarity.COMMON, mage.cards.g.GoblinBowlingTeam.class));
cards.add(new SetCardInfo("Goblin Tutor", 45, Rarity.UNCOMMON, mage.cards.g.GoblinTutor.class));
cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class));
cards.add(new SetCardInfo("Hungry Hungry Heifer", 63, Rarity.UNCOMMON, mage.cards.h.HungryHungryHeifer.class));
@ -43,11 +52,14 @@ public final class Unglued extends ExpansionSet {
cards.add(new SetCardInfo("Paper Tiger", 78, Rarity.COMMON, mage.cards.p.PaperTiger.class));
cards.add(new SetCardInfo("Plains", 84, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Poultrygeist", 37, Rarity.COMMON, mage.cards.p.Poultrygeist.class));
cards.add(new SetCardInfo("Ricochet", 50, Rarity.UNCOMMON, mage.cards.r.Ricochet.class));
cards.add(new SetCardInfo("Rock Lobster", 79, Rarity.COMMON, mage.cards.r.RockLobster.class));
cards.add(new SetCardInfo("Scissors Lizard", 80, Rarity.COMMON, mage.cards.s.ScissorsLizard.class));
cards.add(new SetCardInfo("Spark Fiend", 51, Rarity.RARE, mage.cards.s.SparkFiend.class));
cards.add(new SetCardInfo("Spatula of the Ages", 81, Rarity.UNCOMMON, mage.cards.s.SpatulaOfTheAges.class));
cards.add(new SetCardInfo("Strategy, Schmategy", 52, Rarity.RARE, mage.cards.s.StrategySchmategy.class));
cards.add(new SetCardInfo("Swamp", 86, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Temp of the Damned", 38, Rarity.COMMON, mage.cards.t.TempOfTheDamned.class));
cards.add(new SetCardInfo("The Cheese Stands Alone", 2, Rarity.RARE, mage.cards.t.TheCheeseStandsAlone.class));
cards.add(new SetCardInfo("Timmy, Power Gamer", 68, Rarity.RARE, mage.cards.t.TimmyPowerGamer.class));
cards.add(new SetCardInfo("Urza's Science Fair Project", 83, Rarity.UNCOMMON, mage.cards.u.UrzasScienceFairProject.class));

View file

@ -93,6 +93,7 @@ public enum SubType {
CHIMERA("Chimera", SubTypeSet.CreatureType),
CHISS("Chiss", SubTypeSet.CreatureType, true),
CITIZEN("Citizen", SubTypeSet.CreatureType),
CLAMFOLK("Clamfolk", SubTypeSet.CreatureType, true), // Unglued
CLERIC("Cleric", SubTypeSet.CreatureType),
COCKATRICE("Cockatrice", SubTypeSet.CreatureType),
CONSTRUCT("Construct", SubTypeSet.CreatureType),

View file

@ -44,6 +44,7 @@ public enum CounterType {
FEATHER("feather"),
FILIBUSTER("filibuster"),
FLOOD("flood"),
FUNK("funk"),
FURY("fury"),
FUNGUS("fungus"),
FUSE("fuse"),

View file

@ -0,0 +1,30 @@
package mage.game.permanent.token;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.MageInt;
/**
*
* @author L_J
*/
public final class RabidSheepToken extends TokenImpl {
public RabidSheepToken() {
super("Rabid Sheep", "2/2 green Sheep creature token named Rabid Sheep");
cardType.add(CardType.CREATURE);
subtype.add(SubType.SHEEP);
color.setGreen(true);
power = new MageInt(2);
toughness = new MageInt(2);
}
public RabidSheepToken(final RabidSheepToken token) {
super(token);
}
public RabidSheepToken copy() {
return new RabidSheepToken(this);
}
}