1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-08 01:01:04 -09:00

added missing Planeswalker damage redirection effect + some fixes

This commit is contained in:
BetaSteward 2010-11-21 03:35:04 +00:00
parent 120de78d97
commit 06b7e63843
37 changed files with 347 additions and 75 deletions

View file

@ -137,7 +137,7 @@ public class ProteanHydra extends CardImpl<ProteanHydra> {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
boolean retValue = false;
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), event.getAmount());
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), event.getAmount(), false);
int damage = event.getAmount();
if (!game.replaceEvent(preventEvent)) {
event.setAmount(0);

View file

@ -40,6 +40,7 @@ import mage.Constants.Zone;
import mage.abilities.Ability;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.common.OnEventTriggeredAbility;
import mage.abilities.common.PutIntoGraveFromBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
@ -117,7 +118,7 @@ class NecroticPlagueEffect extends ContinuousEffectImpl<NecroticPlagueEffect> {
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
creature.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new SacrificeSourceEffect()));
creature.addAbility(new LeavesBattlefieldTriggeredAbility(new NecroticPlagueEffect2(source.getSourceId()), false));
creature.addAbility(new PutIntoGraveFromBattlefieldTriggeredAbility(new NecroticPlagueEffect2(source.getSourceId()), false));
}
break;
}
@ -187,4 +188,9 @@ class NecroticPlagueEffect2 extends OneShotEffect<NecroticPlagueEffect2> {
return new NecroticPlagueEffect2(this);
}
@Override
public String getText(Ability source) {
return "its controller chooses target creature one of his or her opponents controls. Return Necrotic Plague from its owner's graveyard to the battlefield attached to that creature.";
}
}

View file

@ -112,7 +112,7 @@ class VengefulArchonEffect extends PreventionEffectImpl<VengefulArchonEffect> {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getControllerId(), source.getId(), source.getControllerId(), event.getAmount());
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getControllerId(), source.getId(), source.getControllerId(), event.getAmount(), false);
if (!game.replaceEvent(preventEvent)) {
Player player = game.getPlayer(source.getFirstTarget());
if (player != null) {

View file

@ -74,20 +74,23 @@ public class BraveTheElements extends CardImpl<BraveTheElements> {
class BraveTheElementsEffect extends GainAbilityControlledEffect {
FilterCreaturePermanent filter1 = new FilterCreaturePermanent();
private static FilterCreaturePermanent filter1 = new FilterCreaturePermanent();
static {
filter1.setUseColor(true);
filter1.getColor().setWhite(true);
}
FilterCard filter2;
public BraveTheElementsEffect() {
super(new ProtectionAbility(new FilterCard()), Duration.EndOfTurn);
filter1.setUseColor(true);
filter1.getColor().setWhite(true);
super(new ProtectionAbility(new FilterCard()), Duration.EndOfTurn, filter1);
filter2 = (FilterCard)((ProtectionAbility)ability).getFilter();
filter2.setUseColor(true);
}
public BraveTheElementsEffect(final BraveTheElementsEffect effect) {
super(effect);
this.filter1 = effect.filter1.copy();
this.filter2 = effect.filter2.copy();
}
@ -101,10 +104,8 @@ class BraveTheElementsEffect extends GainAbilityControlledEffect {
ChoiceColor choice = (ChoiceColor) source.getChoices().get(0);
filter2.setColor(choice.getColor());
filter2.setMessage(choice.getChoice());
for (Permanent perm: game.getBattlefield().getAllActivePermanents(filter1, source.getControllerId())) {
perm.addAbility(ability);
}
return true;
ability = new ProtectionAbility(new FilterCard(filter2));
return super.apply(game, source);
}
@Override

View file

@ -281,6 +281,7 @@ public final class Constants {
PutManaInPool(true),
Regenerate(true),
PreventDamage(true),
RedirectDamage(true),
Tap(false),
Untap(true),
Win(true),

View file

@ -59,13 +59,16 @@ public class ContinuousEffects implements Serializable {
private final Map<PreventionEffect, Ability> preventionEffects = new HashMap<PreventionEffect, Ability>();
private final Map<AsThoughEffect, Ability> asThoughEffects = new HashMap<AsThoughEffect, Ability>();
private final ApplyCountersEffect applyCounters;
private final PlaneswalkerRedirectionEffect planeswalkerRedirectionEffect;
public ContinuousEffects() {
applyCounters = new ApplyCountersEffect();
planeswalkerRedirectionEffect = new PlaneswalkerRedirectionEffect();
}
public ContinuousEffects(final ContinuousEffects effect) {
this.applyCounters = effect.applyCounters.copy();
this.planeswalkerRedirectionEffect = effect.planeswalkerRedirectionEffect.copy();
for (Entry<ContinuousEffect, Ability> entry: effect.layeredEffects.entrySet()) {
layeredEffects.put((ContinuousEffect)entry.getKey().copy(), entry.getValue().copy());
}
@ -158,10 +161,12 @@ public class ContinuousEffects implements Serializable {
private List<ReplacementEffect> getApplicableReplacementEffects(GameEvent event, Game game) {
List<ReplacementEffect> replaceEffects = new ArrayList<ReplacementEffect>();
if (planeswalkerRedirectionEffect.applies(event, null, game))
replaceEffects.add(planeswalkerRedirectionEffect);
for (ReplacementEffect effect: replacementEffects.keySet()) {
if (effect.applies(event, replacementEffects.get(effect), game)) {
if (effect.getDuration() != Duration.OneUse || !effect.isUsed())
replaceEffects.add((ReplacementEffect)effect);
replaceEffects.add(effect);
}
}
return replaceEffects;

View file

@ -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.abilities.effects;
import java.util.UUID;
import mage.Constants.Duration;
import mage.Constants.Outcome;
import mage.abilities.Ability;
import mage.filter.common.FilterPlaneswalkerPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.TargetPermanent;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class PlaneswalkerRedirectionEffect extends RedirectionEffect<PlaneswalkerRedirectionEffect> {
private static FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent();
public PlaneswalkerRedirectionEffect() {
super(Duration.EndOfGame);
}
public PlaneswalkerRedirectionEffect(final PlaneswalkerRedirectionEffect effect) {
super(effect);
}
@Override
public PlaneswalkerRedirectionEffect copy() {
return new PlaneswalkerRedirectionEffect(this);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == EventType.DAMAGE_PLAYER) {
UUID playerId = getSourceControllerId(event.getSourceId(), game);
if (game.getOpponents(event.getTargetId()).contains(playerId)) {
Player target = game.getPlayer(event.getTargetId());
Player player = game.getPlayer(playerId);
if (target != null) {
int numPlaneswalkers = game.getBattlefield().countAll(filter, target.getId());
if (numPlaneswalkers > 0 && player.chooseUse(outcome, "Redirect damage to planeswalker?", game)) {
redirectTarget = new TargetPermanent(filter);
if (numPlaneswalkers == 1) {
redirectTarget.add(game.getBattlefield().getAllActivePermanents(filter, target.getId()).get(0).getId(), game);
}
else {
player.choose(Outcome.Damage, redirectTarget, game);
}
return true;
}
}
}
}
return false;
}
private UUID getSourceControllerId(UUID sourceId, Game game) {
StackObject source = game.getStack().getStackObject(sourceId);
if (source != null)
return source.getControllerId();
Permanent permanent = game.getBattlefield().getPermanent(sourceId);
if (permanent != null)
return permanent.getControllerId();
return null;
}
}

View file

@ -55,7 +55,7 @@ public abstract class PreventionEffectImpl<T extends PreventionEffectImpl<T>> ex
case DAMAGE_CREATURE:
case DAMAGE_PLAYER:
case DAMAGE_PLANESWALKER:
return true;
return event.getFlag();
default:
return false;
}

View file

@ -0,0 +1,93 @@
/*
* 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;
import java.util.UUID;
import mage.Constants.Duration;
import mage.Constants.Outcome;
import mage.abilities.Ability;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.game.stack.StackAbility;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.TargetPermanent;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public abstract class RedirectionEffect<T extends RedirectionEffect<T>> extends ReplacementEffectImpl<T> {
protected TargetPermanent redirectTarget;
public RedirectionEffect(Duration duration) {
super(duration, Outcome.RedirectDamage);
}
public RedirectionEffect(final RedirectionEffect effect) {
super(effect);
this.redirectTarget = effect.redirectTarget;
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent permanent = game.getPermanent(redirectTarget.getFirstTarget());
Ability damageSource = getSource(event.getSourceId(), game);
if (permanent != null) {
permanent.damage(event.getAmount(), damageSource.getId(), game, event.getFlag());
return true;
}
Player player = game.getPlayer(redirectTarget.getFirstTarget());
if (player != null) {
player.damage(event.getAmount(), damageSource.getId(), game, false, event.getFlag());
return true;
}
return false;
}
protected Ability getSource(UUID sourceId, Game game) {
StackObject source = game.getStack().getStackObject(sourceId);
if (source != null) {
if (source instanceof StackAbility)
return (StackAbility)source;
if (source instanceof Spell)
return ((Spell)source).getSpellAbility();
}
return null;
}
}

View file

@ -64,7 +64,7 @@ public class DamageAllControlledTargetEffect extends OneShotEffect<DamageAllCont
@Override
public boolean apply(Game game, Ability source) {
for (Permanent permanent: game.getBattlefield().getAllActivePermanents(filter, source.getFirstTarget())) {
permanent.damage(amount, source.getSourceId(), game, true);
permanent.damage(amount, source.getId(), game, true);
}
return true;
}

View file

@ -64,7 +64,7 @@ public class DamageAllEffect extends OneShotEffect<DamageAllEffect> {
@Override
public boolean apply(Game game, Ability source) {
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
permanent.damage(amount, source.getSourceId(), game, true);
permanent.damage(amount, source.getId(), game, true);
}
return true;
}

View file

@ -72,7 +72,7 @@ public class DamageControllerEffect extends OneShotEffect<DamageControllerEffect
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.damage(amount, source.getSourceId(), game, false, preventable);
player.damage(amount, source.getId(), game, false, preventable);
return true;
}
return false;

View file

@ -70,12 +70,12 @@ public class DamageMultiEffect extends OneShotEffect<DamageMultiEffect> {
for (UUID target: multiTarget.getTargets()) {
Permanent permanent = game.getPermanent(target);
if (permanent != null) {
permanent.damage(multiTarget.getTargetAmount(target), source.getSourceId(), game, true);
permanent.damage(multiTarget.getTargetAmount(target), source.getId(), game, true);
}
else {
Player player = game.getPlayer(target);
if (player != null) {
player.damage(multiTarget.getTargetAmount(target), source.getSourceId(), game, false, true);
player.damage(multiTarget.getTargetAmount(target), source.getId(), game, false, true);
}
}
}

View file

@ -73,12 +73,12 @@ public class DamageTargetEffect extends OneShotEffect<DamageTargetEffect> {
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
permanent.damage(amount, source.getSourceId(), game, preventable);
permanent.damage(amount, source.getId(), game, preventable);
return true;
}
Player player = game.getPlayer(source.getFirstTarget());
if (player != null) {
player.damage(amount, source.getSourceId(), game, false, preventable);
player.damage(amount, source.getId(), game, false, preventable);
return true;
}
return false;

View file

@ -59,12 +59,12 @@ public class DamageXTargetEffect extends OneShotEffect<DamageXTargetEffect> {
int amount = source.getCosts().getVariableCosts().get(0).getAmount();
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
permanent.damage(amount, source.getSourceId(), game, true);
permanent.damage(amount, source.getId(), game, true);
return true;
}
Player player = game.getPlayer(source.getFirstTarget());
if (player != null) {
player.damage(amount, source.getSourceId(), game, false, true);
player.damage(amount, source.getId(), game, false, true);
return true;
}
return false;

View file

@ -61,7 +61,7 @@ public class DestroyAllControlledTargetEffect extends OneShotEffect<DestroyAllCo
@Override
public boolean apply(Game game, Ability source) {
for (Permanent permanent: game.getBattlefield().getAllActivePermanents(filter, source.getFirstTarget())) {
permanent.destroy(source.getSourceId(), game, false);
permanent.destroy(source.getId(), game, false);
}
return true;
}

View file

@ -61,7 +61,7 @@ public class DestroyAllEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
permanent.destroy(source.getSourceId(), game, false);
permanent.destroy(source.getId(), game, false);
}
return true;
}

View file

@ -61,7 +61,7 @@ public class DestroyAllNamedPermanentsEffect extends OneShotEffect<DestroyAllNam
permanent.destroy(source.getSourceId(), game, false);
for (Permanent perm: game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
if (perm.getName().equals(name))
perm.destroy(source.getSourceId(), game, false);
perm.destroy(source.getId(), game, false);
}
return true;

View file

@ -56,7 +56,7 @@ public class DestroyNoRegenTargetEffect extends OneShotEffect<DestroyNoRegenTarg
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
permanent.destroy(source.getSourceId(), game, true);
permanent.destroy(source.getId(), game, true);
return true;
}

View file

@ -65,7 +65,7 @@ public class DestroySourceEffect extends OneShotEffect<DestroySourceEffect> {
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
permanent.destroy(source.getSourceId(), game, noRegen);
permanent.destroy(source.getId(), game, noRegen);
return true;
}
return false;

View file

@ -65,7 +65,7 @@ public class DestroyTargetEffect extends OneShotEffect<DestroyTargetEffect> {
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
permanent.destroy(source.getSourceId(), game, noRegen);
permanent.destroy(source.getId(), game, noRegen);
return true;
}
return false;

View file

@ -45,7 +45,7 @@ import mage.game.permanent.Permanent;
public class GainAbilityControlledEffect extends ContinuousEffectImpl<GainAbilityControlledEffect> {
protected Ability ability;
protected boolean excludeSource;
protected boolean excludeSource;
protected FilterPermanent permanentFilter;
public GainAbilityControlledEffect(Ability ability, Duration duration) {
@ -56,18 +56,18 @@ public class GainAbilityControlledEffect extends ContinuousEffectImpl<GainAbilit
this(ability, duration, filter, false);
}
public GainAbilityControlledEffect(Ability ability, Duration duration, FilterPermanent filter, boolean excludeSource) {
public GainAbilityControlledEffect(Ability ability, Duration duration, FilterPermanent filter, boolean excludeSource) {
super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
this.ability = ability;
this.permanentFilter = filter;
this.excludeSource = excludeSource;
this.excludeSource = excludeSource;
}
public GainAbilityControlledEffect(final GainAbilityControlledEffect effect) {
super(effect);
this.ability = effect.ability.copy();
this.permanentFilter = effect.permanentFilter.copy();
this.excludeSource = effect.excludeSource;
this.excludeSource = effect.excludeSource;
}
@Override
@ -78,9 +78,9 @@ public class GainAbilityControlledEffect extends ContinuousEffectImpl<GainAbilit
@Override
public boolean apply(Game game, Ability source) {
for (Permanent perm: game.getBattlefield().getAllActivePermanents(permanentFilter, source.getControllerId())) {
if (!(excludeSource && perm.getId().equals(source.getSourceId()))) {
perm.addAbility(ability.copy());
}
if (!(excludeSource && perm.getId().equals(source.getSourceId()))) {
perm.addAbility(ability.copy());
}
}
return true;
}
@ -88,7 +88,7 @@ public class GainAbilityControlledEffect extends ContinuousEffectImpl<GainAbilit
@Override
public String getText(Ability source) {
StringBuilder sb = new StringBuilder();
if (excludeSource)
if (excludeSource)
sb.append("Other ");
sb.append(permanentFilter.getMessage()).append(" you control gain ").append(ability.getRule());
sb.append(" ").append(duration.toString());

View file

@ -61,7 +61,7 @@ public class PreventAllCombatDamageEffect extends PreventionEffectImpl<PreventAl
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), event.getAmount());
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), event.getAmount(), false);
if (!game.replaceEvent(preventEvent)) {
int damage = event.getAmount();
event.setAmount(0);

View file

@ -61,7 +61,7 @@ public class PreventAllDamageSourceEffect extends PreventionEffectImpl<PreventAl
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), event.getAmount());
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), event.getAmount(), false);
if (!game.replaceEvent(preventEvent)) {
int damage = event.getAmount();
event.setAmount(0);

View file

@ -67,7 +67,7 @@ public class PreventAllDamageToEffect extends PreventionEffectImpl<PreventAllDam
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), event.getAmount());
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), event.getAmount(), false);
if (!game.replaceEvent(preventEvent)) {
int damage = event.getAmount();
event.setAmount(0);

View file

@ -64,7 +64,7 @@ public class PreventDamageTargetEffect extends PreventionEffectImpl<PreventDamag
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), event.getAmount());
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), event.getAmount(), false);
if (!game.replaceEvent(preventEvent)) {
if (event.getAmount() >= this.amount) {
int damage = event.getAmount();

View file

@ -35,12 +35,10 @@ import mage.Constants.Outcome;
import mage.Constants.TargetController;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledPermanent;
/**

View file

@ -97,7 +97,6 @@ class CascadeEffect extends OneShotEffect<CascadeEffect> {
if (card == null)
break;
card.moveToExile(exile.getId(), exile.getName(), game);
// exile.add(card);
} while (card.getCardType().contains(CardType.LAND) || card.getManaCost().convertedManaCost() >= sourceCost);
if (card != null) {
@ -111,7 +110,6 @@ class CascadeEffect extends OneShotEffect<CascadeEffect> {
card = exile.getRandom(game);
exile.remove(card.getId());
card.moveToZone(Zone.LIBRARY, game, false);
// player.getLibrary().putOnBottom(card, game);
}
return true;

View file

@ -184,7 +184,7 @@ public abstract class CardImpl<T extends CardImpl<T>> extends MageObjectImpl<T>
public boolean moveToZone(Zone toZone, UUID controllerId, Game game, boolean flag) {
Zone fromZone = zone;
ZoneChangeEvent event = new ZoneChangeEvent(this.getId(), controllerId, fromZone, toZone);
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, controllerId, fromZone, toZone);
if (!game.replaceEvent(event)) {
switch (event.getToZone()) {
case GRAVEYARD:
@ -226,7 +226,7 @@ public abstract class CardImpl<T extends CardImpl<T>> extends MageObjectImpl<T>
@Override
public boolean moveToExile(UUID exileId, String name, Game game) {
Zone fromZone = zone;
ZoneChangeEvent event = new ZoneChangeEvent(this.getId(), ownerId, fromZone, Zone.EXILED);
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, ownerId, fromZone, Zone.EXILED);
if (!game.replaceEvent(event)) {
if (exileId == null) {
game.getExile().getPermanentExile().add(this);
@ -235,7 +235,7 @@ public abstract class CardImpl<T extends CardImpl<T>> extends MageObjectImpl<T>
game.getExile().createZone(exileId, name).add(this);
}
zone = event.getToZone();
game.fireEvent(new ZoneChangeEvent(this.getId(), ownerId, fromZone, Zone.EXILED));
game.fireEvent(new ZoneChangeEvent(this.objectId, ownerId, fromZone, Zone.EXILED));
return true;
}
return false;
@ -248,7 +248,7 @@ public abstract class CardImpl<T extends CardImpl<T>> extends MageObjectImpl<T>
zone = Zone.BATTLEFIELD;
permanent.entersBattlefield(game);
game.applyEffects();
game.fireEvent(new ZoneChangeEvent(permanent.getId(), controllerId, fromZone, Zone.BATTLEFIELD));
game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD));
return true;
}

View file

@ -44,6 +44,8 @@ import mage.abilities.TriggeredAbilities;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffects;
import mage.game.combat.Combat;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Battlefield;
import mage.game.permanent.Permanent;
import mage.game.stack.StackObject;
@ -295,14 +297,20 @@ public class GameState implements Serializable, Copyable<GameState> {
public void handleEvent(GameEvent event, Game game) {
watchers.watch(event, game);
if (!replaceEvent(event, game)) {
if (event.getType() == EventType.ZONE_CHANGE) {
ZoneChangeEvent zEvent = (ZoneChangeEvent)event;
if (zEvent.getFromZone() == Zone.BATTLEFIELD) {
zEvent.getTarget().checkTriggers(zEvent.getToZone(), event, game);
}
}
for (Player player: players.values()) {
player.checkTriggers(event, game);
}
battlefield.checkTriggers(event, game);
stack.checkTriggers(event, game);
delayed.checkTriggers(event, game);
exile.checkTriggers(event, game);
}
battlefield.checkTriggers(event, game);
stack.checkTriggers(event, game);
delayed.checkTriggers(event, game);
exile.checkTriggers(event, game);
}
public boolean replaceEvent(GameEvent event, Game game) {

View file

@ -41,6 +41,7 @@ public class GameEvent {
private UUID sourceId;
private UUID playerId;
private int amount;
private boolean flag;
private String data;
public enum EventType {
@ -119,19 +120,20 @@ public class GameEvent {
}
public GameEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId) {
this(type, targetId, sourceId, playerId, 0);
this(type, targetId, sourceId, playerId, 0, false);
}
public GameEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, int amount) {
public GameEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, int amount, boolean flag) {
this.type = type;
this.targetId = targetId;
this.sourceId = sourceId;
this.amount = amount;
this.playerId = playerId;
this.flag = flag;
}
public static GameEvent getEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, int amount) {
return new GameEvent(type, targetId, sourceId, playerId, amount);
return new GameEvent(type, targetId, sourceId, playerId, amount, false);
}
public static GameEvent getEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId) {
@ -162,6 +164,10 @@ public class GameEvent {
return amount;
}
public boolean getFlag() {
return flag;
}
public void setAmount(int amount) {
this.amount = amount;
}

View file

@ -30,6 +30,7 @@ package mage.game.events;
import java.util.UUID;
import mage.Constants.Zone;
import mage.game.permanent.Permanent;
/**
*
@ -39,6 +40,14 @@ public class ZoneChangeEvent extends GameEvent {
private Zone fromZone;
private Zone toZone;
private Permanent target;
public ZoneChangeEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone) {
super(EventType.ZONE_CHANGE, target.getId(), sourceId, playerId);
this.fromZone = fromZone;
this.toZone = toZone;
this.target = target;
}
public ZoneChangeEvent(UUID targetId, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone) {
super(EventType.ZONE_CHANGE, targetId, sourceId, playerId);
@ -46,6 +55,10 @@ public class ZoneChangeEvent extends GameEvent {
this.toZone = toZone;
}
public ZoneChangeEvent(Permanent target, UUID playerId, Zone fromZone, Zone toZone) {
this(target, null, playerId, fromZone, toZone);
}
public ZoneChangeEvent(UUID targetId, UUID playerId, Zone fromZone, Zone toZone) {
this(targetId, null, playerId, fromZone, toZone);
}
@ -61,4 +74,8 @@ public class ZoneChangeEvent extends GameEvent {
public void setToZone(Zone toZone) {
this.toZone = toZone;
}
public Permanent getTarget() {
return target;
}
}

View file

@ -37,10 +37,10 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.keyword.LevelAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.LevelerCard;
import mage.game.Game;
import mage.game.events.ZoneChangeEvent;
import mage.players.Player;
/**
*
@ -112,18 +112,58 @@ public class PermanentCard extends PermanentImpl<PermanentCard> {
this.cardNumber = card.getCardNumber();
}
// @Override
// public boolean moveToZone(Zone zone, Game game, boolean flag) {
// ZoneChangeEvent event = new ZoneChangeEvent(this.getId(), this.getControllerId(), Zone.BATTLEFIELD, zone);
// if (!game.replaceEvent(event)) {
// if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) {
// CardImpl card = (CardImpl) game.getCard(objectId);
// return card.moveToZone(event.getToZone(), controllerId, game, flag);
// }
// }
// return false;
// }
@Override
public boolean moveToZone(Zone zone, Game game, boolean flag) {
ZoneChangeEvent event = new ZoneChangeEvent(this.getId(), this.getControllerId(), Zone.BATTLEFIELD, zone);
public boolean moveToZone(Zone toZone, Game game, boolean flag) {
Zone fromZone = zone;
ZoneChangeEvent event = new ZoneChangeEvent(this, controllerId, fromZone, toZone);
if (!game.replaceEvent(event)) {
if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) {
CardImpl card = (CardImpl) game.getCard(objectId);
return card.moveToZone(event.getToZone(), controllerId, game, flag);
Player controller = game.getPlayer(controllerId);
if (controller != null && controller.removeFromBattlefield(this, game)) {
Card card = game.getCard(objectId);
Player owner = game.getPlayer(ownerId);
if (owner != null) {
switch (event.getToZone()) {
case GRAVEYARD:
owner.putInGraveyard(card, game, !flag);
break;
case HAND:
owner.getHand().add(card);
break;
case EXILED:
game.getExile().getPermanentExile().add(card);
break;
case LIBRARY:
if (flag)
owner.getLibrary().putOnTop(card, game);
else
owner.getLibrary().putOnBottom(card, game);
break;
case BATTLEFIELD:
//should never happen
break;
}
zone = event.getToZone();
game.fireEvent(event);
return zone == toZone;
}
}
}
return false;
}
@Override
public boolean moveToExile(UUID exileId, String name, Game game) {
if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) {

View file

@ -438,8 +438,8 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
}
protected int damagePlaneswalker(int damage, UUID sourceId, Game game, boolean preventable) {
GameEvent event = new GameEvent(GameEvent.EventType.DAMAGE_PLANESWALKER, objectId, sourceId, controllerId, damage);
if (!preventable || !game.replaceEvent(event)) {
GameEvent event = new GameEvent(GameEvent.EventType.DAMAGE_PLANESWALKER, objectId, sourceId, controllerId, damage, preventable);
if (!game.replaceEvent(event)) {
int actualDamage = event.getAmount();
if (actualDamage > 0) {
if (event.getAmount() > this.loyalty.getValue()) {
@ -454,8 +454,8 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
}
protected int damageCreature(int damage, UUID sourceId, Game game, boolean preventable) {
GameEvent event = new GameEvent(GameEvent.EventType.DAMAGE_CREATURE, objectId, sourceId, controllerId, damage);
if (!preventable || !game.replaceEvent(event)) {
GameEvent event = new GameEvent(GameEvent.EventType.DAMAGE_CREATURE, objectId, sourceId, controllerId, damage, preventable);
if (!game.replaceEvent(event)) {
int actualDamage = event.getAmount();
if (actualDamage > 0) {
if (this.damage + event.getAmount() > this.toughness.getValue()) {

View file

@ -76,9 +76,9 @@ public class PermanentToken extends PermanentImpl<PermanentToken> {
@Override
public boolean moveToZone(Zone zone, Game game, boolean flag) {
if (!game.replaceEvent(new ZoneChangeEvent(this.getId(), this.getControllerId(), Zone.BATTLEFIELD, zone))) {
if (!game.replaceEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, zone))) {
if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) {
game.fireEvent(new ZoneChangeEvent(this.getId(), this.getControllerId(), Zone.BATTLEFIELD, zone));
game.fireEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, zone));
return true;
}
}
@ -87,9 +87,9 @@ public class PermanentToken extends PermanentImpl<PermanentToken> {
@Override
public boolean moveToExile(UUID exileId, String name, Game game) {
if (!game.replaceEvent(new ZoneChangeEvent(this.getId(), this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED))) {
if (!game.replaceEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED))) {
if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) {
game.fireEvent(new ZoneChangeEvent(this.getId(), this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED));
game.fireEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED));
return true;
}
}

View file

@ -85,7 +85,7 @@ public class Token extends MageObjectImpl<Token> {
game.getBattlefield().addPermanent(permanent);
permanent.entersBattlefield(game);
game.applyEffects();
game.fireEvent(new ZoneChangeEvent(permanent.getId(), controllerId, Zone.OUTSIDE, Zone.BATTLEFIELD));
game.fireEvent(new ZoneChangeEvent(permanent, controllerId, Zone.OUTSIDE, Zone.BATTLEFIELD));
return true;
}

View file

@ -593,7 +593,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
@Override
public int loseLife(int amount, Game game) {
GameEvent event = new GameEvent(GameEvent.EventType.LOSE_LIFE, playerId, playerId, playerId, amount);
GameEvent event = new GameEvent(GameEvent.EventType.LOSE_LIFE, playerId, playerId, playerId, amount, false);
if (!game.replaceEvent(event)) {
setLife(this.life - amount, game);
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LOST_LIFE, playerId, playerId, playerId, amount));
@ -604,7 +604,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
@Override
public void gainLife(int amount, Game game) {
GameEvent event = new GameEvent(GameEvent.EventType.GAIN_LIFE, playerId, playerId, playerId, amount);
GameEvent event = new GameEvent(GameEvent.EventType.GAIN_LIFE, playerId, playerId, playerId, amount, false);
if (!game.replaceEvent(event)) {
setLife(this.life + amount, game);
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.GAINED_LIFE, playerId, playerId, playerId, amount));
@ -614,8 +614,8 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
@Override
public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable) {
if (damage > 0 && canDamage(game.getObject(sourceId))) {
GameEvent event = new GameEvent(GameEvent.EventType.DAMAGE_PLAYER, playerId, sourceId, playerId, damage);
if (!preventable || !game.replaceEvent(event)) {
GameEvent event = new GameEvent(GameEvent.EventType.DAMAGE_PLAYER, playerId, sourceId, playerId, damage, preventable);
if (!game.replaceEvent(event)) {
int actualDamage = event.getAmount();
if (actualDamage > 0) {
actualDamage = this.loseLife(actualDamage, game);