mirror of
https://github.com/magefree/mage.git
synced 2025-12-25 13:02:06 -08:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
4a2e1c5063
82 changed files with 4468 additions and 688 deletions
|
|
@ -32,7 +32,7 @@ import mage.util.Copyable;
|
|||
|
||||
public class MageInt implements Serializable, Copyable<MageInt> {
|
||||
|
||||
public static MageInt EmptyMageInt = new MageInt(Integer.MIN_VALUE, null) {
|
||||
public static MageInt EmptyMageInt = new MageInt(Integer.MIN_VALUE, "") {
|
||||
|
||||
private static final String exceptionMessage = "MageInt.EmptyMageInt can't be modified.";
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import mage.MageObject;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Zone;
|
||||
import mage.designations.Designation;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.NumberOfTriggersEvent;
|
||||
|
|
@ -146,6 +147,8 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
|
|||
public void add(TriggeredAbility ability, UUID sourceId, MageObject attachedTo) {
|
||||
if (sourceId == null) {
|
||||
add(ability, attachedTo);
|
||||
} else if (attachedTo == null) {
|
||||
this.put(ability.getId() + "_" + sourceId, ability);
|
||||
} else {
|
||||
this.add(ability, attachedTo);
|
||||
List<UUID> uuidList = new LinkedList<>();
|
||||
|
|
@ -190,8 +193,14 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
|
|||
public void removeAbilitiesOfNonExistingSources(Game game) {
|
||||
// e.g. Token that had triggered abilities
|
||||
List<String> keysToRemove = new ArrayList<>();
|
||||
Abilities:
|
||||
for (Entry<String, TriggeredAbility> entry : this.entrySet()) {
|
||||
if (game.getObject(entry.getValue().getSourceId()) == null) {
|
||||
for (Designation designation : game.getState().getDesignations()) {
|
||||
if (designation.getId().equals(entry.getValue().getSourceId())) {
|
||||
continue Abilities;
|
||||
}
|
||||
}
|
||||
keysToRemove.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ package mage.abilities.common;
|
|||
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedPlayerEvent;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,29 @@
|
|||
/*
|
||||
* 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.
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class BecomesMonarchTargetEffect extends OneShotEffect {
|
||||
|
||||
public BecomesMonarchTargetEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "target player becomes the monarch";
|
||||
}
|
||||
|
||||
public BecomesMonarchTargetEffect(final BecomesMonarchTargetEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomesMonarchTargetEffect copy() {
|
||||
return new BecomesMonarchTargetEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (targetPlayer != null) {
|
||||
game.setMonarchId(source, targetPlayer.getId());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Library;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Styxo
|
||||
*/
|
||||
public class RevealCardsFromLibraryUntilEffect extends OneShotEffect {
|
||||
|
||||
private FilterCard filter;
|
||||
|
||||
public RevealCardsFromLibraryUntilEffect(FilterCard filter) {
|
||||
super(Outcome.ReturnToHand);
|
||||
this.filter = filter;
|
||||
this.staticText = "reveal cards from the top of your library until you reveal a " + filter.getMessage() + ". Put that card into your hand and the rest on the bottom of your library in a random order";
|
||||
}
|
||||
|
||||
public RevealCardsFromLibraryUntilEffect(final RevealCardsFromLibraryUntilEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RevealCardsFromLibraryUntilEffect copy() {
|
||||
return new RevealCardsFromLibraryUntilEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (controller != null && controller.getLibrary().size() > 0) {
|
||||
Cards cards = new CardsImpl();
|
||||
Library library = controller.getLibrary();
|
||||
Card card = null;
|
||||
do {
|
||||
card = library.removeFromTop(game);
|
||||
if (card != null) {
|
||||
cards.add(card);
|
||||
}
|
||||
} while (library.size() > 0 && card != null && !filter.match(card, game));
|
||||
// reveal cards
|
||||
if (!cards.isEmpty()) {
|
||||
controller.revealCards(sourceObject.getIdName(), cards, game);
|
||||
if (filter.match(card, game)) {
|
||||
// put creature card in hand
|
||||
controller.moveCards(card, Zone.HAND, source, game);
|
||||
// remove it from revealed card list
|
||||
cards.remove(card);
|
||||
}
|
||||
// Put the rest on the bottom of your library in a random order
|
||||
Cards randomOrder = new CardsImpl();
|
||||
while (cards.size() > 0) {
|
||||
card = cards.getRandom(game);
|
||||
if (card != null) {
|
||||
cards.remove(card);
|
||||
randomOrder.add(card);
|
||||
controller.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.HAND, false, false);
|
||||
}
|
||||
}
|
||||
controller.putCardsOnBottomOfLibrary(randomOrder, game, source, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
* @author JRHerlehy
|
||||
*/
|
||||
public class SwordsToPlowsharesEffect extends OneShotEffect {
|
||||
|
||||
public SwordsToPlowsharesEffect() {
|
||||
super(Outcome.GainLife);
|
||||
staticText = "Its controller gains life equal to its power";
|
||||
}
|
||||
|
||||
public SwordsToPlowsharesEffect(final SwordsToPlowsharesEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SwordsToPlowsharesEffect copy() {
|
||||
return new SwordsToPlowsharesEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source));
|
||||
if (permanent != null) {
|
||||
Player player = game.getPlayer(permanent.getControllerId());
|
||||
if (player != null) {
|
||||
player.gainLife(permanent.getPower().getValue(), game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -14,27 +14,22 @@ public enum FrameStyle {
|
|||
* The default card frame, normal M15 card frames
|
||||
*/
|
||||
M15_NORMAL(BorderType.M15, false),
|
||||
|
||||
/**
|
||||
* Battle for Zendkiar full art basic lands
|
||||
*/
|
||||
BFZ_FULL_ART_BASIC(BorderType.M15, true),
|
||||
|
||||
/**
|
||||
* Kaladesh block Inventions
|
||||
*/
|
||||
KLD_INVENTION(BorderType.M15, false),
|
||||
|
||||
/**
|
||||
* Zenkikar full art lands
|
||||
*/
|
||||
ZEN_FULL_ART_BASIC(BorderType.MOD, true),
|
||||
|
||||
/**
|
||||
* Unhinged full art lands
|
||||
*/
|
||||
UNH_FULL_ART_BASIC(BorderType.SPC, true),
|
||||
|
||||
/**
|
||||
* Unglued full art lands
|
||||
*/
|
||||
|
|
@ -45,30 +40,26 @@ public enum FrameStyle {
|
|||
*/
|
||||
public enum BorderType {
|
||||
/**
|
||||
* Various specialty borders
|
||||
* EG: Unhinged, Unglued
|
||||
* Various specialty borders EG: Unhinged, Unglued
|
||||
*/
|
||||
SPC,
|
||||
|
||||
/**
|
||||
* Old border cards
|
||||
*/
|
||||
OLD,
|
||||
|
||||
/**
|
||||
* Modern border cards (8th -> Theros)
|
||||
*/
|
||||
MOD,
|
||||
|
||||
/**
|
||||
* M15 border cards (M14 -> current)
|
||||
*/
|
||||
M15
|
||||
}
|
||||
|
||||
private BorderType borderType;
|
||||
private boolean isFullArt;
|
||||
|
||||
|
||||
private final BorderType borderType;
|
||||
private final boolean isFullArt;
|
||||
|
||||
public BorderType getBorderType() {
|
||||
return borderType;
|
||||
}
|
||||
|
|
@ -76,7 +67,7 @@ public enum FrameStyle {
|
|||
public boolean isFullArt() {
|
||||
return isFullArt;
|
||||
}
|
||||
|
||||
|
||||
FrameStyle(BorderType borderType, boolean isFullArt) {
|
||||
this.borderType = borderType;
|
||||
this.isFullArt = isFullArt;
|
||||
|
|
|
|||
212
Mage/src/main/java/mage/designations/Designation.java
Normal file
212
Mage/src/main/java/mage/designations/Designation.java
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* 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.designations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.cards.FrameStyle;
|
||||
import mage.constants.CardType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.util.GameLog;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public abstract class Designation implements MageObject {
|
||||
|
||||
private static List emptyList = new ArrayList();
|
||||
private static ObjectColor emptyColor = new ObjectColor();
|
||||
private static ManaCosts emptyCost = new ManaCostsImpl();
|
||||
|
||||
private String name;
|
||||
private UUID id;
|
||||
private FrameStyle frameStyle;
|
||||
private Abilities<Ability> abilites = new AbilitiesImpl<>();
|
||||
private String expansionSetCodeForImage;
|
||||
|
||||
public Designation(String name, String expansionSetCode) {
|
||||
this.name = name;
|
||||
this.id = UUID.randomUUID();
|
||||
this.frameStyle = FrameStyle.M15_NORMAL;
|
||||
this.expansionSetCodeForImage = expansionSetCode;
|
||||
}
|
||||
|
||||
public Designation(final Designation designation) {
|
||||
this.id = designation.id;
|
||||
this.name = designation.name;
|
||||
this.frameStyle = designation.frameStyle;
|
||||
this.abilites = designation.abilites.copy();
|
||||
}
|
||||
|
||||
public abstract void start(Game game, UUID controllerId);
|
||||
|
||||
@Override
|
||||
public FrameStyle getFrameStyle() {
|
||||
return frameStyle;
|
||||
}
|
||||
|
||||
public void assignNewId() {
|
||||
this.id = UUID.randomUUID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdName() {
|
||||
return getName() + " [" + getId().toString().substring(0, 3) + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImageName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void addAbility(Ability ability) {
|
||||
ability.setSourceId(id);
|
||||
abilites.add(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities() {
|
||||
return abilites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectColor getFrameColor(Game game) {
|
||||
return emptyColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setExpansionSetCodeForImage(String expansionSetCodeForImage) {
|
||||
this.expansionSetCodeForImage = expansionSetCodeForImage;
|
||||
}
|
||||
|
||||
public String getExpansionSetCodeForImage() {
|
||||
return expansionSetCodeForImage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogName() {
|
||||
return GameLog.getColoredObjectIdName(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CardType> getCardType() {
|
||||
return emptyList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSubtype(Game game) {
|
||||
return emptyList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSubtype(String subtype, Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSupertype() {
|
||||
return emptyList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAbility(UUID abilityId, Game game) {
|
||||
return abilites.containsKey(abilityId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectColor getColor(Game game) {
|
||||
return emptyColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManaCosts<ManaCost> getManaCost() {
|
||||
return emptyCost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getConvertedManaCost() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MageInt getPower() {
|
||||
return MageInt.EmptyMageInt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MageInt getToughness() {
|
||||
return MageInt.EmptyMageInt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartingLoyalty() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCopy(boolean isCopy) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCopy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Designation copy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZoneChangeCounter(Game game) {
|
||||
return 1; // Emblems can't move zones until now so return always 1
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateZoneChangeCounter(Game game, ZoneChangeEvent event) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZoneChangeCounter(int value, Game game) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
}
|
||||
152
Mage/src/main/java/mage/designations/Monarch.java
Normal file
152
Mage/src/main/java/mage/designations/Monarch.java
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* 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.designations;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.abilities.effects.common.BecomesMonarchTargetEffect;
|
||||
import mage.abilities.effects.common.DrawCardTargetEffect;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedPlayerEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class Monarch extends Designation {
|
||||
|
||||
public Monarch() {
|
||||
super("The Monarch", "CN2");
|
||||
addAbility(new MonarchDrawTriggeredAbility());
|
||||
addAbility(new MonarchDealsCombatDamageToAPlayerTriggeredAbility());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param game
|
||||
* @param controllerId
|
||||
*/
|
||||
@Override
|
||||
public void start(Game game, UUID controllerId) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// At the beginning of the monarch’s end step, that player draws a card
|
||||
class MonarchDrawTriggeredAbility extends BeginningOfEndStepTriggeredAbility {
|
||||
|
||||
public MonarchDrawTriggeredAbility() {
|
||||
super(Zone.ALL, new DrawCardTargetEffect(1), TargetController.ANY, null, false);
|
||||
}
|
||||
|
||||
public MonarchDrawTriggeredAbility(final MonarchDrawTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (game.getMonarchId() != null && event.getPlayerId().equals(game.getMonarchId())) {
|
||||
setControllerId(game.getMonarchId());
|
||||
getEffects().get(0).setTargetPointer(new FixedTarget(game.getMonarchId()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MonarchDrawTriggeredAbility copy() {
|
||||
return new MonarchDrawTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "At the beginning of the monarch’s end step, that player draws a card.";
|
||||
}
|
||||
}
|
||||
|
||||
// Whenever a creature deals combat damage to the monarch, its controller becomes the monarch.
|
||||
class MonarchDealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public MonarchDealsCombatDamageToAPlayerTriggeredAbility() {
|
||||
super(Zone.ALL, new BecomesMonarchTargetEffect(), false);
|
||||
}
|
||||
|
||||
public MonarchDealsCombatDamageToAPlayerTriggeredAbility(final MonarchDealsCombatDamageToAPlayerTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (((DamagedPlayerEvent) event).isCombatDamage()) {
|
||||
MageObject damagingObject = game.getObject(event.getSourceId());
|
||||
if (damagingObject != null
|
||||
&& damagingObject instanceof Permanent
|
||||
&& damagingObject.getCardType().contains(CardType.CREATURE)
|
||||
&& event.getTargetId().equals(game.getMonarchId())) {
|
||||
setControllerId(event.getPlayerId());
|
||||
getEffects().get(0).setTargetPointer(new FixedTarget(((Permanent) damagingObject).getControllerId()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MonarchDealsCombatDamageToAPlayerTriggeredAbility copy() {
|
||||
return new MonarchDealsCombatDamageToAPlayerTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever a creature deals combat damage to the monarch, its controller becomes the monarch.";
|
||||
}
|
||||
}
|
||||
|
|
@ -81,6 +81,8 @@ import mage.constants.SpellAbilityType;
|
|||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.counters.Counters;
|
||||
import mage.designations.Designation;
|
||||
import mage.designations.Monarch;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
|
|
@ -385,11 +387,11 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
object = getCard(objectId);
|
||||
|
||||
if (object == null) {
|
||||
// for (CommandObject commandObject : state.getCommand()) {
|
||||
// if (commandObject.getId().equals(objectId)) {
|
||||
// return commandObject;
|
||||
// }
|
||||
// }
|
||||
for (Designation designation : state.getDesignations()) {
|
||||
if (designation.getId().equals(objectId)) {
|
||||
return designation;
|
||||
}
|
||||
}
|
||||
// can be an ability of a sacrificed Token trying to get it's source object
|
||||
object = getLastKnownInformation(objectId, Zone.BATTLEFIELD);
|
||||
}
|
||||
|
|
@ -2916,6 +2918,9 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
@Override
|
||||
public void setMonarchId(Ability source, UUID monarchId) {
|
||||
Player newMonarch = getPlayer(monarchId);
|
||||
if (getMonarchId() == null) {
|
||||
getState().addDesignation(new Monarch(), this, monarchId);
|
||||
}
|
||||
if (newMonarch != null) {
|
||||
getState().setMonarchId(monarchId);
|
||||
informPlayers(newMonarch.getLogName() + " is the monarch");
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ import mage.abilities.effects.Effect;
|
|||
import mage.cards.Card;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.Zone;
|
||||
import mage.designations.Designation;
|
||||
import mage.game.combat.Combat;
|
||||
import mage.game.combat.CombatGroup;
|
||||
import mage.game.command.Command;
|
||||
|
|
@ -113,6 +114,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
private UUID monarchId; // player that is the monarch
|
||||
private SpellStack stack;
|
||||
private Command command;
|
||||
private List<Designation> designations = new ArrayList<>();
|
||||
private Exile exile;
|
||||
private Battlefield battlefield;
|
||||
private int turnNum = 1;
|
||||
|
|
@ -170,6 +172,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
|
||||
this.stack = state.stack.copy();
|
||||
this.command = state.command.copy();
|
||||
this.designations.addAll(state.designations);
|
||||
this.exile = state.exile.copy();
|
||||
this.battlefield = state.battlefield.copy();
|
||||
this.turnNum = state.turnNum;
|
||||
|
|
@ -219,6 +222,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
this.monarchId = state.monarchId;
|
||||
this.stack = state.stack;
|
||||
this.command = state.command;
|
||||
this.designations = state.designations;
|
||||
this.exile = state.exile;
|
||||
this.battlefield = state.battlefield;
|
||||
this.turnNum = state.turnNum;
|
||||
|
|
@ -461,6 +465,10 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
return exile;
|
||||
}
|
||||
|
||||
public List<Designation> getDesignations() {
|
||||
return designations;
|
||||
}
|
||||
|
||||
public Command getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
|
@ -859,6 +867,14 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
}
|
||||
|
||||
public void addDesignation(Designation designation, Game game, UUID controllerId) {
|
||||
getDesignations().add(designation);
|
||||
for (Ability ability : designation.getAbilities()) {
|
||||
ability.setControllerId(controllerId);
|
||||
addAbility(ability, designation.getId(), null);
|
||||
}
|
||||
}
|
||||
|
||||
public void addCommandObject(CommandObject commandObject) {
|
||||
getCommand().add(commandObject);
|
||||
setZone(commandObject.getId(), Zone.COMMAND);
|
||||
|
|
@ -1026,6 +1042,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
stack.clear();
|
||||
exile.clear();
|
||||
command.clear();
|
||||
designations.clear();
|
||||
revealed.clear();
|
||||
lookedAt.clear();
|
||||
turnNum = 0;
|
||||
|
|
|
|||
|
|
@ -339,8 +339,17 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
// No need to attack a special defender
|
||||
if (defendersForcedToAttack.isEmpty()) {
|
||||
if (defendersForcedToAttack.isEmpty()) {
|
||||
if (defendersCostlessAttackable.size() == 1) {
|
||||
player.declareAttacker(creature.getId(), defenders.iterator().next(), game, false);
|
||||
if (defendersCostlessAttackable.size() >= 1) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TargetDefender target = new TargetDefender(defendersCostlessAttackable, creature.getId());
|
||||
|
|
|
|||
|
|
@ -1231,14 +1231,14 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean triggerAbility(TriggeredAbility source, Game game) {
|
||||
if (source == null) {
|
||||
public boolean triggerAbility(TriggeredAbility triggeredAbility, Game game) {
|
||||
if (triggeredAbility == null) {
|
||||
logger.warn("Null source in triggerAbility method");
|
||||
throw new IllegalArgumentException("source TriggeredAbility must not be null");
|
||||
}
|
||||
//20091005 - 603.3c, 603.3d
|
||||
int bookmark = game.bookmarkState();
|
||||
TriggeredAbility ability = source.copy();
|
||||
TriggeredAbility ability = triggeredAbility.copy();
|
||||
MageObject sourceObject = ability.getSourceObject(game);
|
||||
if (sourceObject != null) {
|
||||
sourceObject.adjustTargets(ability, game);
|
||||
|
|
@ -1260,7 +1260,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
restoreState(bookmark, source.getRule(), game); // why restore is needed here? (to remove the triggered ability from the stack)
|
||||
restoreState(bookmark, triggeredAbility.getRule(), game); // why restore is needed here? (to remove the triggered ability from the stack)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1829,9 +1829,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (sourceAbilities != null && sourceAbilities.containsKey(InfectAbility.getInstance().getId())) {
|
||||
addCounters(CounterType.POISON.createInstance(actualDamage), game);
|
||||
} else {
|
||||
if (getId().equals(game.getMonarchId()) && sourceControllerId != null) {
|
||||
game.setMonarchId(null, sourceControllerId);
|
||||
}
|
||||
GameEvent damageToLifeLossEvent = new GameEvent(EventType.DAMAGE_CAUSES_LIFE_LOSS, playerId, sourceId, playerId, actualDamage, combatDamage);
|
||||
if (!game.replaceEvent(damageToLifeLossEvent)) {
|
||||
this.loseLife(damageToLifeLossEvent.getAmount(), game, combatDamage);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue