mirror of
https://github.com/magefree/mage.git
synced 2025-12-24 20:41:58 -08:00
Merge origin/master
This commit is contained in:
commit
7ff31fb12e
92 changed files with 2894 additions and 775 deletions
|
|
@ -1167,6 +1167,9 @@ public abstract class AbilityImpl implements Ability {
|
|||
public MageObject getSourceObjectIfItStillExists(Game game) {
|
||||
MageObject currentObject = game.getObject(getSourceId());
|
||||
if (currentObject != null) {
|
||||
if (sourceObject == null) {
|
||||
setSourceObject(currentObject, game);
|
||||
}
|
||||
MageObjectReference mor = new MageObjectReference(currentObject, game);
|
||||
if (mor.getZoneChangeCounter() == getSourceObjectZoneChangeCounter()) {
|
||||
// source object has meanwhile not changed zone
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ public class BeginningOfEndStepTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
private String generateConditionString() {
|
||||
if (interveningIfClauseCondition != null) {
|
||||
return new StringBuilder(interveningIfClauseCondition.toString()).append(", ").toString();
|
||||
return "if {this} is " + interveningIfClauseCondition.toString() + ", ";
|
||||
}
|
||||
switch (getZone()) {
|
||||
case GRAVEYARD:
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.constants.CardType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
|
|
@ -38,15 +38,15 @@ import mage.game.permanent.Permanent;
|
|||
*
|
||||
* @author North
|
||||
*/
|
||||
public class EnchantedCondition implements Condition {
|
||||
public class EnchantedSourceCondition implements Condition {
|
||||
|
||||
private int numberOfEnchantments;
|
||||
|
||||
public EnchantedCondition() {
|
||||
public EnchantedSourceCondition() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public EnchantedCondition(int numberOfEnchantments) {
|
||||
public EnchantedSourceCondition(int numberOfEnchantments) {
|
||||
this.numberOfEnchantments = numberOfEnchantments;
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ public class EnchantedCondition implements Condition {
|
|||
for (UUID uuid : permanent.getAttachments()) {
|
||||
Permanent attached = game.getBattlefield().getPermanent(uuid);
|
||||
if (attached != null && attached.getCardType().contains(CardType.ENCHANTMENT)) {
|
||||
if (++numberOfFoundEnchantments >= numberOfEnchantments) {
|
||||
if (++numberOfFoundEnchantments >= numberOfEnchantments) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -66,4 +66,9 @@ public class EnchantedCondition implements Condition {
|
|||
}
|
||||
return (numberOfFoundEnchantments >= numberOfEnchantments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "enchanted";
|
||||
}
|
||||
}
|
||||
|
|
@ -38,9 +38,9 @@ import mage.game.permanent.Permanent;
|
|||
*
|
||||
* @author nantuko
|
||||
*/
|
||||
public class EquippedCondition implements Condition {
|
||||
public class EquippedSourceCondition implements Condition {
|
||||
|
||||
private static final EquippedCondition fInstance = new EquippedCondition();
|
||||
private static final EquippedSourceCondition fInstance = new EquippedSourceCondition();
|
||||
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
|
|
@ -59,4 +59,10 @@ public class EquippedCondition implements Condition {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "equipped";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -67,7 +67,7 @@ public class DiscardTargetCost extends CostImpl {
|
|||
@Override
|
||||
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
this.cards.clear();
|
||||
this.targets.clearChosen();;
|
||||
this.targets.clearChosen();
|
||||
Player player = game.getPlayer(controllerId);
|
||||
if (player == null) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import mage.MageObject;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.keyword.TransformAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
|
|
@ -90,6 +91,10 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
UUID sourceId = event.getSourceId();
|
||||
UUID controllerId = event.getPlayerId();
|
||||
|
||||
if (game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()) != null) {
|
||||
card = card.getSecondCardFace();
|
||||
}
|
||||
|
||||
// Aura cards that go to battlefield face down (Manifest) don't have to select targets
|
||||
if (card.isFaceDown(game)) {
|
||||
return false;
|
||||
|
|
@ -167,6 +172,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
Player targetPlayer = game.getPlayer(targetId);
|
||||
if (targetCard != null || targetPermanent != null || targetPlayer != null) {
|
||||
card = game.getCard(event.getTargetId());
|
||||
card.removeFromZone(game, fromZone, sourceId);
|
||||
card.updateZoneChangeCounter(game);
|
||||
PermanentCard permanent = new PermanentCard(card, (controllingPlayer == null ? card.getOwnerId() : controllingPlayer.getId()), game);
|
||||
|
|
@ -200,7 +206,12 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
if (((ZoneChangeEvent) event).getToZone().equals(Zone.BATTLEFIELD)
|
||||
&& !(((ZoneChangeEvent) event).getFromZone().equals(Zone.STACK))) {
|
||||
Card card = game.getCard(event.getTargetId());
|
||||
if (card != null && card.getCardType().contains(CardType.ENCHANTMENT) && card.hasSubtype("Aura")) {
|
||||
if (card != null && (card.getCardType().contains(CardType.ENCHANTMENT) && card.hasSubtype("Aura")
|
||||
|| // in case of transformable enchantments
|
||||
(game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()) != null
|
||||
&& card.getSecondCardFace() != null
|
||||
&& card.getSecondCardFace().getCardType().contains(CardType.ENCHANTMENT)
|
||||
&& card.getSecondCardFace().hasSubtype("Aura")))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,10 @@ public class DoIfCostPaid extends OneShotEffect {
|
|||
return game.getPlayer(source.getControllerId());
|
||||
}
|
||||
|
||||
public Cost getCost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
if (!staticText.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import java.util.UUID;
|
|||
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;
|
||||
|
|
@ -78,20 +79,30 @@ public class ReturnToBattlefieldUnderOwnerControlTargetEffect extends OneShotEff
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Card card = null;
|
||||
Cards cardsToMove = new CardsImpl();
|
||||
if (fromExileZone) {
|
||||
UUID exilZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
if (exilZoneId != null) {
|
||||
ExileZone exileZone = game.getExile().getExileZone(exilZoneId);
|
||||
if (exileZone != null && getTargetPointer().getFirst(game, source) != null) {
|
||||
card = exileZone.get(getTargetPointer().getFirst(game, source), game);
|
||||
if (exileZone != null) {
|
||||
for (UUID cardId : getTargetPointer().getTargets(game, source)) {
|
||||
Card card = exileZone.get(cardId, game);
|
||||
if (card != null) {
|
||||
cardsToMove.add(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
card = game.getCard(getTargetPointer().getFirst(game, source));
|
||||
for (UUID cardId : getTargetPointer().getTargets(game, source)) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (card != null) {
|
||||
cardsToMove.add(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (card != null) {
|
||||
controller.moveCards(new CardsImpl(card).getCards(game),
|
||||
if (!cardsToMove.isEmpty()) {
|
||||
controller.moveCards(cardsToMove.getCards(game),
|
||||
Zone.BATTLEFIELD, source, game, tapped, false, true, null);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ public enum PlayerAction {
|
|||
MANA_AUTO_PAYMENT_OFF,
|
||||
MANA_AUTO_PAYMENT_RESTRICTED_ON,
|
||||
MANA_AUTO_PAYMENT_RESTRICTED_OFF,
|
||||
USE_FIRST_MANA_ABILITY_ON,
|
||||
USE_FIRST_MANA_ABILITY_OFF,
|
||||
RESET_AUTO_SELECT_REPLACEMENT_EFFECTS,
|
||||
REVOKE_PERMISSIONS_TO_SEE_HAND_CARDS,
|
||||
REQUEST_PERMISSION_TO_SEE_HAND_CARDS,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
package mage.constants;
|
||||
|
||||
/**
|
||||
* Allows user to either tap a land for the first mode directly (shortcut)
|
||||
* or have the normal method which pops up a menu
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public enum UseFirstManaAbilityMode {
|
||||
|
||||
NORMAL, FIRST
|
||||
}
|
||||
|
|
@ -348,6 +348,8 @@ public interface Game extends MageItem, Serializable {
|
|||
void setManaPaymentMode(UUID playerId, boolean autoPayment);
|
||||
|
||||
void setManaPaymentModeRestricted(UUID playerId, boolean autoPaymentRestricted);
|
||||
|
||||
void setUseFirstManaAbility(UUID playerId, boolean useFirstManaAbility);
|
||||
|
||||
void undo(UUID playerId);
|
||||
|
||||
|
|
|
|||
|
|
@ -1238,6 +1238,14 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setUseFirstManaAbility(UUID playerId, boolean useFirstManaAbility) {
|
||||
Player player = state.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
player.getUserData().setUseFirstManaAbility(useFirstManaAbility);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playPriority(UUID activePlayerId, boolean resuming) {
|
||||
int errorContinueCounter = 0;
|
||||
|
|
|
|||
|
|
@ -32,8 +32,12 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Abilities;
|
||||
|
|
@ -59,6 +63,8 @@ import mage.game.combat.CombatGroup;
|
|||
import mage.game.command.Command;
|
||||
import mage.game.command.CommandObject;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.events.ZoneChangeGroupEvent;
|
||||
import mage.game.permanent.Battlefield;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.SpellStack;
|
||||
|
|
@ -655,7 +661,9 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
if (!simultaneousEvents.isEmpty() && !getTurn().isEndTurnRequested()) {
|
||||
// it can happen, that the events add new simultaneous events, so copy the list before
|
||||
List<GameEvent> eventsToHandle = new ArrayList<>();
|
||||
List<GameEvent> eventGroups = createEventGroups(simultaneousEvents, game);
|
||||
eventsToHandle.addAll(simultaneousEvents);
|
||||
eventsToHandle.addAll(eventGroups);
|
||||
simultaneousEvents.clear();
|
||||
for (GameEvent event : eventsToHandle) {
|
||||
this.handleEvent(event, game);
|
||||
|
|
@ -684,6 +692,76 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
return effects.replaceEvent(event, game);
|
||||
}
|
||||
|
||||
public List<GameEvent> createEventGroups(List<GameEvent> events, Game game) {
|
||||
|
||||
class ZoneChangeData {
|
||||
|
||||
private final Zone fromZone;
|
||||
private final Zone toZone;
|
||||
private final UUID sourceId;
|
||||
private final UUID playerId;
|
||||
|
||||
public ZoneChangeData(UUID sourceId, UUID playerId, Zone fromZone, Zone toZone) {
|
||||
this.sourceId = sourceId;
|
||||
this.playerId = playerId;
|
||||
this.fromZone = fromZone;
|
||||
this.toZone = toZone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (this.fromZone.ordinal() + 1) * 1
|
||||
+ (this.toZone.ordinal() + 1) * 10
|
||||
+ (this.sourceId != null ? this.sourceId.hashCode() : 0)
|
||||
+ (this.playerId != null ? this.playerId.hashCode() : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ZoneChangeData) {
|
||||
ZoneChangeData data = (ZoneChangeData) obj;
|
||||
return this.fromZone == data.fromZone
|
||||
&& this.toZone == data.toZone
|
||||
&& this.sourceId == data.sourceId
|
||||
&& this.playerId == data.playerId;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Map<ZoneChangeData, List<GameEvent>> eventsByKey = new HashMap<>();
|
||||
List<GameEvent> groupEvents = new LinkedList<>();
|
||||
for (GameEvent event : events) {
|
||||
if (event instanceof ZoneChangeEvent) {
|
||||
ZoneChangeEvent castEvent = (ZoneChangeEvent) event;
|
||||
ZoneChangeData key = new ZoneChangeData(castEvent.getSourceId(), castEvent.getPlayerId(), castEvent.getFromZone(), castEvent.getToZone());
|
||||
if (eventsByKey.containsKey(key)) {
|
||||
eventsByKey.get(key).add(event);
|
||||
} else {
|
||||
List<GameEvent> list = new LinkedList<>();
|
||||
list.add(event);
|
||||
eventsByKey.put(key, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<ZoneChangeData, List<GameEvent>> entry : eventsByKey.entrySet()) {
|
||||
Set<Card> movedCards = new LinkedHashSet<>();
|
||||
for (Iterator<GameEvent> it = entry.getValue().iterator(); it.hasNext();) {
|
||||
GameEvent event = it.next();
|
||||
ZoneChangeEvent castEvent = (ZoneChangeEvent) event;
|
||||
UUID targetId = castEvent.getTargetId();
|
||||
Card card = game.getCard(targetId);
|
||||
movedCards.add(card);
|
||||
}
|
||||
ZoneChangeData eventData = entry.getKey();
|
||||
if (!movedCards.isEmpty()) {
|
||||
ZoneChangeGroupEvent event = new ZoneChangeGroupEvent(movedCards, eventData.sourceId, eventData.playerId, eventData.fromZone, eventData.toZone);
|
||||
groupEvents.add(event);
|
||||
}
|
||||
}
|
||||
return groupEvents;
|
||||
}
|
||||
|
||||
public void addCard(Card card) {
|
||||
setZone(card.getId(), Zone.OUTSIDE);
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
|
|
|
|||
|
|
@ -512,7 +512,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
if (canTransform) {
|
||||
if (!replaceEvent(EventType.TRANSFORM, game)) {
|
||||
setTransformed(!transformed);
|
||||
fireEvent(EventType.TRANSFORMED, game);
|
||||
game.applyEffects();
|
||||
game.addSimultaneousEvent(GameEvent.getEvent(EventType.TRANSFORMED, getId(), getControllerId()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,6 @@ import mage.game.events.DamagedPlayerEvent;
|
|||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.events.ZoneChangeGroupEvent;
|
||||
import mage.game.match.MatchPlayer;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
|
|
@ -3249,9 +3248,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
default:
|
||||
throw new UnsupportedOperationException("to Zone" + toZone.toString() + " not supported yet");
|
||||
}
|
||||
if (!successfulMovedCards.isEmpty()) {
|
||||
game.fireEvent(new ZoneChangeGroupEvent(successfulMovedCards, source == null ? null : source.getSourceId(), this.getId(), fromZone, toZone));
|
||||
}
|
||||
return successfulMovedCards.size() > 0;
|
||||
}
|
||||
|
||||
|
|
@ -3267,7 +3263,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (cards.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
game.fireEvent(new ZoneChangeGroupEvent(cards, source == null ? null : source.getSourceId(), this.getId(), null, Zone.EXILED));
|
||||
boolean result = false;
|
||||
for (Card card : cards) {
|
||||
Zone fromZone = game.getState().getZone(card.getId());
|
||||
|
|
@ -3368,7 +3363,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
game.fireEvent(new ZoneChangeGroupEvent(movedCards, source == null ? null : source.getSourceId(), this.getId(), fromZone, Zone.GRAVEYARD));
|
||||
return movedCards;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ public class UserData implements Serializable {
|
|||
protected boolean passPriorityCast;
|
||||
protected boolean passPriorityActivation;
|
||||
protected boolean autoOrderTrigger;
|
||||
protected boolean useFirstManaAbility;
|
||||
|
||||
protected String matchHistory;
|
||||
protected int matchQuitRatio;
|
||||
|
|
@ -31,7 +32,7 @@ public class UserData implements Serializable {
|
|||
public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced,
|
||||
boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps,
|
||||
String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted,
|
||||
boolean passPriorityCast, boolean passPriorityActivation, boolean autoOrderTrigger) {
|
||||
boolean passPriorityCast, boolean passPriorityActivation, boolean autoOrderTrigger, boolean useFirstManaAbility) {
|
||||
this.groupId = userGroup.getGroupId();
|
||||
this.avatarId = avatarId;
|
||||
this.showAbilityPickerForced = showAbilityPickerForced;
|
||||
|
|
@ -45,6 +46,7 @@ public class UserData implements Serializable {
|
|||
this.passPriorityCast = passPriorityCast;
|
||||
this.passPriorityActivation = passPriorityActivation;
|
||||
this.autoOrderTrigger = autoOrderTrigger;
|
||||
this.useFirstManaAbility = useFirstManaAbility;
|
||||
this.matchHistory = "";
|
||||
this.matchQuitRatio = 0;
|
||||
this.tourneyHistory = "";
|
||||
|
|
@ -65,10 +67,11 @@ public class UserData implements Serializable {
|
|||
this.passPriorityCast = userData.passPriorityCast;
|
||||
this.passPriorityActivation = userData.passPriorityActivation;
|
||||
this.autoOrderTrigger = userData.autoOrderTrigger;
|
||||
this.useFirstManaAbility = userData.useFirstManaAbility;
|
||||
}
|
||||
|
||||
public static UserData getDefaultUserDataView() {
|
||||
return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, getDefaultFlagName(), false, true, true, false, false, false);
|
||||
return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, getDefaultFlagName(), false, true, true, false, false, false, false);
|
||||
}
|
||||
|
||||
public void setGroupId(int groupId) {
|
||||
|
|
@ -175,6 +178,14 @@ public class UserData implements Serializable {
|
|||
this.autoOrderTrigger = autoOrderTrigger;
|
||||
}
|
||||
|
||||
public boolean isUseFirstManaAbility() {
|
||||
return useFirstManaAbility;
|
||||
}
|
||||
|
||||
public void setUseFirstManaAbility(boolean useFirstManaAbility) {
|
||||
this.useFirstManaAbility = useFirstManaAbility;
|
||||
}
|
||||
|
||||
public String getHistory() {
|
||||
if (UserGroup.COMPUTER.equals(this.groupId)) {
|
||||
return "";
|
||||
|
|
|
|||
|
|
@ -78,11 +78,11 @@ public class CardUtil {
|
|||
// Enchantment subtypes
|
||||
"Aura", "Curse", "Shrine",
|
||||
// Artifact subtypes
|
||||
"Equipment", "Fortification", "Contraption",
|
||||
"Clue", "Equipment", "Fortification", "Contraption",
|
||||
// Land subtypes
|
||||
"Desert", "Gate", "Lair", "Locus", "Urza's", "Mine", "Power-Plant", "Tower",
|
||||
// Planeswalker subtypes
|
||||
"Ajani", "Ashiok", "Bolas", "Chandra", "Dack", "Daretti", "Domri", "Elspeth", "Freyalise", "Garruk", "Gideon", "Jace",
|
||||
"Ajani", "Arlinn", "Ashiok", "Bolas", "Chandra", "Dack", "Daretti", "Domri", "Elspeth", "Freyalise", "Garruk", "Gideon", "Jace",
|
||||
"Karn", "Kiora", "Koth", "Liliana", "Nahiri", "Nissa", "Narset", "Nixilis", "Ral", "Sarkhan", "Sorin", "Tamiyo", "Teferi",
|
||||
"Tezzeret", "Tibalt", "Ugin", "Venser", "Vraska", "Xenagos",
|
||||
// Instant sorcery subtypes
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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.watchers.common;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CastFromGraveyardWatcher extends Watcher {
|
||||
|
||||
// holds which spell with witch zone change counter was cast from graveyard
|
||||
private final Map<UUID, HashSet<Integer>> spellsCastFromGraveyard = new HashMap<>();
|
||||
|
||||
public CastFromGraveyardWatcher() {
|
||||
super(CastFromGraveyardWatcher.class.getName(), WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public CastFromGraveyardWatcher(final CastFromGraveyardWatcher watcher) {
|
||||
super(watcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
/**
|
||||
* This does still not handle if a spell is cast from hand and comes to
|
||||
* play from other zones during the same step. But at least the state is
|
||||
* reset if the game comes to a new step
|
||||
*/
|
||||
if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getZone().equals(Zone.GRAVEYARD)) {
|
||||
Spell spell = (Spell) game.getObject(event.getTargetId());
|
||||
if (spell != null) {
|
||||
HashSet<Integer> zcc = spellsCastFromGraveyard.get(spell.getSourceId());
|
||||
if (zcc == null) {
|
||||
zcc = new HashSet<>();
|
||||
spellsCastFromGraveyard.put(spell.getSourceId(), zcc);
|
||||
}
|
||||
zcc.add(spell.getZoneChangeCounter(game));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public boolean spellWasCastFromGraveyard(UUID sourceId, int zcc) {
|
||||
Set zccSet = spellsCastFromGraveyard.get(sourceId);
|
||||
if (zccSet != null) {
|
||||
return zccSet.contains(zcc);
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
spellsCastFromGraveyard.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CastFromGraveyardWatcher copy() {
|
||||
return new CastFromGraveyardWatcher(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package mage.watchers.common;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import static mage.game.events.GameEvent.EventType.CAST_SPELL;
|
||||
import static mage.game.events.GameEvent.EventType.SPELL_CAST;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth
|
||||
**/
|
||||
public class FirstSpellCastThisTurnWatcher extends Watcher {
|
||||
|
||||
private final Map<UUID, UUID> playerFirstSpellCast = new HashMap<>();
|
||||
private final Map<UUID, UUID> playerFirstCastSpell = new HashMap<>();
|
||||
|
||||
public FirstSpellCastThisTurnWatcher() {
|
||||
super("FirstSpellCastThisTurn", WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public FirstSpellCastThisTurnWatcher(final FirstSpellCastThisTurnWatcher watcher) {
|
||||
super(watcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
switch (event.getType()) {
|
||||
case SPELL_CAST:
|
||||
case CAST_SPELL:
|
||||
Spell spell = (Spell) game.getObject(event.getTargetId());
|
||||
if (spell != null && !playerFirstSpellCast.containsKey(spell.getControllerId())) {
|
||||
if (event.getType().equals(EventType.SPELL_CAST)) {
|
||||
playerFirstSpellCast.put(spell.getControllerId(), spell.getId());
|
||||
} else if (event.getType().equals(EventType.CAST_SPELL)) {
|
||||
playerFirstCastSpell.put(spell.getControllerId(), spell.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FirstSpellCastThisTurnWatcher copy() {
|
||||
return new FirstSpellCastThisTurnWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
playerFirstSpellCast.clear();
|
||||
playerFirstCastSpell.clear();
|
||||
}
|
||||
|
||||
public UUID getIdOfFirstCastSpell(UUID playerId) {
|
||||
if (playerFirstSpellCast.get(playerId) == null) {
|
||||
return playerFirstCastSpell.get(playerId);
|
||||
} else {
|
||||
return playerFirstSpellCast.get(playerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue