Merge branch 'master' into add-minimum-rating-option

This commit is contained in:
LevelX2 2018-11-26 17:18:35 +01:00 committed by GitHub
commit e7d129a074
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
568 changed files with 21414 additions and 6453 deletions

View file

@ -12,6 +12,9 @@ public interface Controllable {
UUID getId();
default boolean isControlledBy(UUID controllerID){
if(getControllerId() == null){
return false;
}
return getControllerId().equals(controllerID);
}
}

View file

@ -1026,6 +1026,7 @@ public abstract class GameImpl implements Game, Serializable {
watchers.add(new BlockedAttackerWatcher());
watchers.add(new DamageDoneWatcher());
watchers.add(new PlanarRollWatcher());
watchers.add(new PlayersAttackedThisTurnWatcher());
//20100716 - 103.5
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
@ -1527,7 +1528,7 @@ public abstract class GameImpl implements Game, Serializable {
@Override
public void addEffect(ContinuousEffect continuousEffect, Ability source) {
Ability newAbility = source.copy();
newAbility.setSourceObject(null, this); // Update the source object to the currently existing Object
newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(source.getSourceId()));
ContinuousEffect newEffect = continuousEffect.copy();
newEffect.newId();
@ -1698,11 +1699,17 @@ public abstract class GameImpl implements Game, Serializable {
if (ability instanceof TriggeredManaAbility || ability instanceof DelayedTriggeredManaAbility) {
// 20110715 - 605.4
Ability manaAbiltiy = ability.copy();
if (manaAbiltiy.getSourceObjectZoneChangeCounter() == 0) {
manaAbiltiy.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(ability.getSourceId()));
}
manaAbiltiy.activate(this, false);
manaAbiltiy.resolve(this);
} else {
TriggeredAbility newAbility = ability.copy();
newAbility.newId();
if (newAbility.getSourceObjectZoneChangeCounter() == 0) {
newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(ability.getSourceId()));
}
state.addTriggeredAbility(newAbility);
}
}
@ -1711,10 +1718,10 @@ public abstract class GameImpl implements Game, Serializable {
public UUID addDelayedTriggeredAbility(DelayedTriggeredAbility delayedAbility, Ability source) {
delayedAbility.setSourceId(source.getSourceId());
delayedAbility.setControllerId(source.getControllerId());
delayedAbility.setSourceObject(source.getSourceObject(this), this);
// return addDelayedTriggeredAbility(delayedAbility);
DelayedTriggeredAbility newAbility = delayedAbility.copy();
newAbility.newId();
newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(source.getSourceId()));
newAbility.initOnAdding(this);
// ability.init is called as the ability triggeres not now.
// If a FixedTarget pointer is already set from the effect setting up this delayed ability
@ -2594,7 +2601,7 @@ public abstract class GameImpl implements Game, Serializable {
boolean addPlaneAgain = false;
for (Iterator<CommandObject> it = this.getState().getCommand().iterator(); it.hasNext();) {
CommandObject obj = it.next();
if (obj.getControllerId().equals(playerId)) {
if (obj.isControlledBy(playerId)) {
if (obj instanceof Emblem) {
((Emblem) obj).discardEffects();// This may not be the best fix but it works
}

View file

@ -1,4 +1,3 @@
package mage.game.combat;
import mage.MageObject;
@ -6,6 +5,7 @@ import mage.abilities.Ability;
import mage.abilities.effects.RequirementEffect;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.keyword.BandingAbility;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.abilities.keyword.special.JohanVigilanceAbility;
import mage.constants.Outcome;
@ -14,8 +14,12 @@ import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreatureForCombatBlock;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.filter.predicate.permanent.AttackingSameNotBandedPredicate;
import mage.filter.predicate.permanent.PermanentIdPredicate;
import mage.game.Game;
@ -103,8 +107,8 @@ public class Combat implements Serializable, Copyable<Combat> {
}
/**
* Get all possible defender (players and plainwalkers) That does not mean
* neccessarly mean that they are really attacked
* Get all possible defender (players and planeswalkers) That does not mean
* necessarily mean that they are really attacked
*
* @return
*/
@ -246,11 +250,14 @@ public class Combat implements Serializable, Copyable<Combat> {
game.getCombat().checkAttackRequirements(player, game);
boolean firstTime = true;
do {
if (!firstTime || !game.getPlayer(game.getActivePlayerId()).getAvailableAttackers(game).isEmpty()) {
if (!firstTime
|| !game.getPlayer(game.getActivePlayerId()).getAvailableAttackers(game).isEmpty()) {
player.selectAttackers(game, attackingPlayerId);
}
firstTime = false;
if (game.isPaused() || game.checkIfGameIsOver() || game.executingRollback()) {
if (game.isPaused()
|| game.checkIfGameIsOver()
|| game.executingRollback()) {
return;
}
// because of possible undo during declare attackers it's neccassary to call here the methods with "game.getCombat()." to get the current combat object!!!
@ -293,53 +300,115 @@ public class Combat implements Serializable, Copyable<Combat> {
Permanent attacker = game.getPermanent(creatureId);
if (attacker != null && player != null) {
CombatGroup combatGroup = findGroup(attacker.getId());
if (combatGroup != null && attacker.getAbilities().containsKey(BandingAbility.getInstance().getId()) && attacker.getBandedCards().isEmpty() && getAttackers().size() > 1) {
boolean isBanded = false;
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature to band with " + attacker.getLogName());
filter.add(Predicates.not(new PermanentIdPredicate(creatureId)));
filter.add(new AttackingSameNotBandedPredicate(combatGroup.getDefenderId())); // creature that isn't already banded, and is attacking the same player or planeswalker
while (player.canRespond()) {
TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true);
target.setRequired(false);
if (!target.canChoose(attackingPlayerId, game)
|| game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, attackingPlayerId, attackingPlayerId))
|| !player.chooseUse(Outcome.Benefit, "Do you wish to " + (isBanded ? "band " + attacker.getLogName() + " with another " : "form a band with " + attacker.getLogName() + " and an ") + "attacking creature?", null, game)) {
break;
}
if (target.choose(Outcome.Benefit, attackingPlayerId, null, game)) {
isBanded = true;
for (UUID targetId : target.getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
for (UUID bandedId : attacker.getBandedCards()) {
permanent.addBandedCard(bandedId);
Permanent banded = game.getPermanent(bandedId);
if (banded != null) {
banded.addBandedCard(targetId);
}
}
permanent.addBandedCard(creatureId);
attacker.addBandedCard(targetId);
if (!permanent.getAbilities().containsKey(BandingAbility.getInstance().getId())) {
filter.add(new AbilityPredicate(BandingAbility.class));
}
}
}
if (combatGroup != null && attacker.getBandedCards().isEmpty() && getAttackers().size() > 1) {
boolean canBand = attacker.getAbilities().containsKey(BandingAbility.getInstance().getId());
List<Ability> bandsWithOther = new ArrayList<>();
for (Ability ability : attacker.getAbilities()) {
if (ability.getClass().equals(BandsWithOtherAbility.class)) {
bandsWithOther.add(ability);
}
}
if (isBanded) {
StringBuilder sb = new StringBuilder(player.getLogName()).append(" formed a band with ").append((attacker.getBandedCards().size() + 1) + " creatures: ");
sb.append(attacker.getLogName());
for (UUID id : attacker.getBandedCards()) {
sb.append(", ");
Permanent permanent = game.getPermanent(id);
if (permanent != null) {
sb.append(permanent.getLogName());
boolean canBandWithOther = !bandsWithOther.isEmpty();
if (canBand || canBandWithOther) {
boolean isBanded = false;
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature to band with " + attacker.getLogName());
filter.add(Predicates.not(new PermanentIdPredicate(creatureId)));
filter.add(new AttackingSameNotBandedPredicate(combatGroup.getDefenderId())); // creature that isn't already banded, and is attacking the same player or planeswalker
List<Predicate<MageObject>> predicates = new ArrayList<>();
if (!canBand && canBandWithOther) {
for (Ability ab : bandsWithOther) {
BandsWithOtherAbility ability = (BandsWithOtherAbility) ab;
if (ability.getSubtype() != null) {
predicates.add(new SubtypePredicate(ability.getSubtype()));
}
if (ability.getSupertype() != null) {
predicates.add(new SupertypePredicate(ability.getSupertype()));
}
if (ability.getName() != null) {
predicates.add(new NamePredicate(ability.getName()));
}
}
filter.add(Predicates.or(predicates));
}
while (player.canRespond()) {
TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true);
target.setRequired(false);
canBand &= target.canChoose(attackingPlayerId, game);
canBandWithOther &= target.canChoose(attackingPlayerId, game);
if (game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, attackingPlayerId, attackingPlayerId))
|| (!canBand && !canBandWithOther)
|| !player.chooseUse(Outcome.Benefit, "Do you wish to " + (isBanded ? "band " + attacker.getLogName() + " with another " : "form a band with " + attacker.getLogName() + " and an ") + "attacking creature?", null, game)) {
break;
}
if (canBand && canBandWithOther) {
if (player.chooseUse(Outcome.Detriment, "Choose type of banding ability to apply:", attacker.getLogName(), "Banding", "Bands with other", null, game)) {
canBandWithOther = false;
} else {
canBand = false;
for (Ability ab : bandsWithOther) {
BandsWithOtherAbility ability = (BandsWithOtherAbility) ab;
if (ability.getSubtype() != null) {
predicates.add(new SubtypePredicate(ability.getSubtype()));
}
if (ability.getSupertype() != null) {
predicates.add(new SupertypePredicate(ability.getSupertype()));
}
if (ability.getName() != null) {
predicates.add(new NamePredicate(ability.getName()));
}
}
filter.add(Predicates.or(predicates));
}
}
if (target.choose(Outcome.Benefit, attackingPlayerId, null, game)) {
isBanded = true;
for (UUID targetId : target.getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
for (UUID bandedId : attacker.getBandedCards()) {
permanent.addBandedCard(bandedId);
Permanent banded = game.getPermanent(bandedId);
if (banded != null) {
banded.addBandedCard(targetId);
}
}
permanent.addBandedCard(creatureId);
attacker.addBandedCard(targetId);
if (canBand) {
if (!permanent.getAbilities().containsKey(BandingAbility.getInstance().getId())) {
filter.add(new AbilityPredicate(BandingAbility.class));
canBandWithOther = false;
}
} else if (canBandWithOther) {
List<Predicate<MageObject>> newPredicates = new ArrayList<>();
for (Predicate<MageObject> predicate : predicates) {
if (predicate.apply(permanent, game)) {
newPredicates.add(predicate);
}
}
filter.add(Predicates.or(newPredicates));
canBand = false;
}
}
}
}
}
game.informPlayers(sb.toString());
if (isBanded) {
StringBuilder sb = new StringBuilder(player.getLogName()).append(" formed a band with ").append((attacker.getBandedCards().size() + 1) + " creatures: ");
sb.append(attacker.getLogName());
for (UUID id : attacker.getBandedCards()) {
sb.append(", ");
Permanent permanent = game.getPermanent(id);
if (permanent != null) {
sb.append(permanent.getLogName());
}
}
game.informPlayers(sb.toString());
}
}
}
}
@ -387,11 +456,16 @@ public class Combat implements Serializable, Copyable<Combat> {
if (defenders.size() == 1) {
player.declareAttacker(creature.getId(), defenders.iterator().next(), game, false);
} else {
TargetDefender target = new TargetDefender(defenders, creature.getId());
target.setRequired(true);
target.setTargetName("planeswalker or player for " + creature.getLogName() + " to attack");
if (player.chooseTarget(Outcome.Damage, target, null, game)) {
player.declareAttacker(creature.getId(), target.getFirstTarget(), game, false);
if (!player.isHuman()) { // computer only for multiple defenders
player.declareAttacker(creature.getId(), defenders.iterator().next(), game, false);
} else { // human players only for multiple defenders
TargetDefender target = new TargetDefender(defenders, creature.getId());
target.setRequired(true);
target.setTargetName("planeswalker or player for " + creature.getLogName() + " to attack");
if (player.chooseTarget(Outcome.Damage, target, null, game)) {
System.out.println("The player " + player.getName() + " declares an attacker here. " + creature.getName());
player.declareAttacker(creature.getId(), target.getFirstTarget(), game, false);
}
}
}
} else {
@ -483,7 +557,7 @@ public class Combat implements Serializable, Copyable<Combat> {
* Handle the blocker selection process
*
* @param blockController player that controlls how to block, if null the
* defender is the controller
* defender is the controller
* @param game
*/
public void selectBlockers(Player blockController, Game game) {
@ -1275,10 +1349,10 @@ public class Combat implements Serializable, Copyable<Combat> {
if (defenderAttackedBy.size() >= defendingPlayer.getMaxAttackedBy()) {
Player attackingPlayer = game.getPlayer(game.getControllerId(attackerId));
if (attackingPlayer != null && !game.isSimulation()) {
game.informPlayer(attackingPlayer, "No more than " +
CardUtil.numberToText(defendingPlayer.getMaxAttackedBy()) +
" creatures can attack " +
defendingPlayer.getLogName());
game.informPlayer(attackingPlayer, "No more than "
+ CardUtil.numberToText(defendingPlayer.getMaxAttackedBy())
+ " creatures can attack "
+ defendingPlayer.getLogName());
}
return false;
}
@ -1308,7 +1382,7 @@ public class Combat implements Serializable, Copyable<Combat> {
* @param playerId
* @param game
* @param solveBanding check whether also add creatures banded with
* attackerId
* attackerId
*/
public void addBlockingGroup(UUID blockerId, UUID attackerId, UUID playerId, Game game, boolean solveBanding) {
Permanent blocker = game.getPermanent(blockerId);

View file

@ -5,10 +5,12 @@ import java.io.Serializable;
import java.util.*;
import java.util.stream.Stream;
import mage.abilities.Ability;
import mage.abilities.common.ControllerAssignCombatDamageToBlockersAbility;
import mage.abilities.common.ControllerDivideCombatDamageAbility;
import mage.abilities.common.DamageAsThoughNotBlockedAbility;
import mage.abilities.keyword.BandingAbility;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.abilities.keyword.CantBlockAloneAbility;
import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.DoubleStrikeAbility;
@ -110,6 +112,56 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
return perm.getAbilities().containsKey(BandingAbility.getInstance().getId());
}
private boolean appliesBandsWithOther(List<UUID> creatureIds, Game game) {
for (UUID creatureId : creatureIds) {
Permanent perm = game.getPermanent(creatureId);
if (perm != null && perm.getBandedCards() != null) {
for (Ability ab : perm.getAbilities()) {
if (ab.getClass().equals(BandsWithOtherAbility.class)) {
BandsWithOtherAbility ability = (BandsWithOtherAbility) ab;
if (ability.getSubtype() != null) {
if (perm.hasSubtype(ability.getSubtype(), game)) {
for (UUID bandedId : creatureIds) {
if (!bandedId.equals(creatureId)) {
Permanent banded = game.getPermanent(bandedId);
if (banded != null && banded.hasSubtype(ability.getSubtype(), game)) {
return true;
}
}
}
}
}
if (ability.getSupertype() != null) {
if (perm.getSuperType().contains(ability.getSupertype())) {
for (UUID bandedId : creatureIds) {
if (!bandedId.equals(creatureId)) {
Permanent banded = game.getPermanent(bandedId);
if (banded != null && banded.getSuperType().contains(ability.getSupertype())) {
return true;
}
}
}
}
}
if (ability.getName() != null) {
if (perm.getName().equals(ability.getName())) {
for (UUID bandedId : creatureIds) {
if (!bandedId.equals(creatureId)) {
Permanent banded = game.getPermanent(bandedId);
if (banded != null && banded.getName().equals(ability.getName())) {
return true;
}
}
}
}
}
}
}
}
}
return false;
}
public void assignDamageToBlockers(boolean first, Game game) {
if (!attackers.isEmpty() && (!first || hasFirstOrDoubleStrike(game))) {
Permanent attacker = game.getPermanent(attackers.get(0));
@ -837,6 +889,9 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
}
}
}
if (appliesBandsWithOther(attackers, game)) { // 702.21k - both a [quality] creature with bands with other [quality] and another [quality] creature (...)
return true;
}
return false;
}
@ -855,6 +910,9 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
}
}
}
if (appliesBandsWithOther(blockers, game)) { // 702.21j - both a [quality] creature with bands with other [quality] and another [quality] creature (...)
return true;
}
for (Permanent defensiveFormation : game.getBattlefield().getAllActivePermanents(defendingPlayerId)) {
if (defensiveFormation.getAbilities().containsKey(ControllerAssignCombatDamageToBlockersAbility.getInstance().getId())) {
return true;

View file

@ -3,17 +3,16 @@ package mage.game.command;
import java.util.UUID;
import mage.MageObject;
import mage.game.Controllable;
/**
*
* @author Viserion, nantuko
*/
public interface CommandObject extends MageObject {
public interface CommandObject extends MageObject, Controllable {
UUID getSourceId();
UUID getControllerId();
void assignNewId();
MageObject getSourceObject();

View file

@ -1,4 +1,3 @@
package mage.game.command;
import java.util.EnumSet;

View file

@ -1,7 +1,5 @@
package mage.game.command;
import static java.lang.Math.log;
import java.lang.reflect.Constructor;
import java.util.EnumSet;
import java.util.List;
@ -289,7 +287,7 @@ public class Plane implements CommandObject {
if (plane instanceof Plane) {
return (Plane) plane;
}
} catch (Exception ex) {
} catch (Exception ex) {
}
return null;
}

View file

@ -3,11 +3,11 @@ package mage.game.command.emblems;
import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
import mage.abilities.effects.common.LoseGameTargetPlayerEffect;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.command.Emblem;
/**
*
* @author TheElk801
*/
public final class VraskaGolgariQueenEmblem extends Emblem {
@ -17,9 +17,9 @@ public final class VraskaGolgariQueenEmblem extends Emblem {
this.setName("Emblem Vraska");
this.setExpansionSetCodeForImage("GRN");
this.getAbilities().add(new DealsDamageToAPlayerAllTriggeredAbility(
new LoseGameTargetPlayerEffect(),
Zone.COMMAND, new LoseGameTargetPlayerEffect(),
StaticFilters.FILTER_CONTROLLED_A_CREATURE,
false, SetTargetPointer.PLAYER, true
false, SetTargetPointer.NONE, true, true
));
}
}

View file

@ -147,7 +147,8 @@ public abstract class DraftImpl implements Draft {
@Override
public void autoPick(UUID playerId) {
this.addPick(playerId, players.get(playerId).getBooster().get(0).getId(), null);
List<Card> booster = players.get(playerId).getBooster();
this.addPick(playerId, booster.get(booster.size()-1).getId(), null);
}
protected void passLeft() {

View file

@ -1,18 +1,17 @@
package mage.game.permanent.token;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.MageInt;
import mage.abilities.keyword.VigilanceAbility;
import mage.constants.CardType;
import mage.constants.SubType;
/**
*
* @author TheElk801
*/
public final class ElfKnightToken extends TokenImpl {
public ElfKnightToken() {
super("Knight Ally", "2/2 green and white Elf Knight creature token with vigilance");
super("Elf Knight", "2/2 green and white Elf Knight creature token with vigilance");
this.setExpansionSetCodeForImage("GRN");
cardType.add(CardType.CREATURE);
color.setGreen(true);

View file

@ -0,0 +1,29 @@
package mage.game.permanent.token;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.MageInt;
/**
*
* @author L_J
*/
public final class ExpansionSymbolToken extends TokenImpl {
public ExpansionSymbolToken() {
super("Expansion-Symbol", "1/1 colorless Expansion-Symbol creature token");
cardType.add(CardType.CREATURE);
subtype.add(SubType.EXPANSION_SYMBOL);
power = new MageInt(1);
toughness = new MageInt(1);
}
public ExpansionSymbolToken(final ExpansionSymbolToken token) {
super(token);
}
public ExpansionSymbolToken copy() {
return new ExpansionSymbolToken(this);
}
}

View file

@ -20,7 +20,7 @@ public final class GoblinToken extends TokenImpl {
static {
tokenImageSets.addAll(Arrays.asList("10E", "ALA", "SOM", "M10", "NPH", "M13", "RTR",
"MMA", "M15", "C14", "KTK", "EVG", "DTK", "ORI", "DDG", "DDN", "DD3EVG", "MM2",
"MM3", "EMA", "C16", "DOM"));
"MM3", "EMA", "C16", "DOM", "ANA"));
}
public GoblinToken(boolean withHaste) {

View file

@ -10,7 +10,6 @@ import mage.constants.SubType;
import mage.target.TargetPermanent;
/**
*
* @author TheElk801
*/
public final class MaskToken extends TokenImpl {
@ -18,8 +17,8 @@ public final class MaskToken extends TokenImpl {
public MaskToken() {
super(
"Mask", "white Aura enchantment token named Mask "
+ "attached to another target permanent. "
+ "The token has enchant permanent and totem armor."
+ "attached to another target permanent. "
+ "The token has enchant permanent and totem armor."
);
cardType.add(CardType.ENCHANTMENT);
color.setWhite(true);
@ -31,6 +30,7 @@ public final class MaskToken extends TokenImpl {
ability.addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(ability);
// Totem armor
this.addAbility(new TotemArmorAbility());
}

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

View file

@ -17,7 +17,7 @@ public final class SpiritWhiteToken extends TokenImpl {
final static private List<String> tokenImageSets = new ArrayList<>();
static {
tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CNS", "DDC", "DDK", "FRF", "ISD", "KTK", "M15", "MM2", "SHM", "SOI", "EMA", "C16", "MM3", "CMA", "E01"));
tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CNS", "DDC", "DDK", "FRF", "ISD", "KTK", "M15", "MM2", "SHM", "SOI", "EMA", "C16", "MM3", "CMA", "E01", "ANA"));
}
public SpiritWhiteToken() {

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 UktabiKongApeToken extends TokenImpl {
public UktabiKongApeToken() {
super("Ape", "1/1 green Ape creature token");
cardType.add(CardType.CREATURE);
subtype.add(SubType.APE);
color.setGreen(true);
power = new MageInt(1);
toughness = new MageInt(1);
}
public UktabiKongApeToken(final UktabiKongApeToken token) {
super(token);
}
public UktabiKongApeToken copy() {
return new UktabiKongApeToken(this);
}
}

View file

@ -0,0 +1,32 @@
package mage.game.permanent.token;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.MageInt;
import mage.abilities.keyword.BandsWithOtherAbility;
/**
*
* @author L_J
*/
public final class WolvesOfTheHuntToken extends TokenImpl {
public WolvesOfTheHuntToken() {
super("Wolves of the Hunt", "1/1 green Wolf creature token named Wolves of the Hunt");
cardType.add(CardType.CREATURE);
subtype.add(SubType.WOLF);
color.setGreen(true);
power = new MageInt(1);
toughness = new MageInt(1);
this.addAbility(new BandsWithOtherAbility("Wolves of the Hunt"));
}
public WolvesOfTheHuntToken(final WolvesOfTheHuntToken token) {
super(token);
}
public WolvesOfTheHuntToken copy() {
return new WolvesOfTheHuntToken(this);
}
}

View file

@ -518,14 +518,19 @@ public class StackAbility extends StackObjImpl implements Ability {
return this.ability.getSourcePermanentIfItStillExists(game);
}
@Override
public void setSourceObjectZoneChangeCounter(int zoneChangeCounter) {
ability.setSourceObjectZoneChangeCounter(zoneChangeCounter);
}
@Override
public int getSourceObjectZoneChangeCounter() {
return ability.getSourceObjectZoneChangeCounter();
}
@Override
public void setSourceObject(MageObject sourceObject, Game game) {
throw new UnsupportedOperationException("Not supported.");
public Permanent getSourcePermanentOrLKI(Game game) {
return ability.getSourcePermanentOrLKI(game);
}
@Override