foul-magics/Mage/src/main/java/mage/abilities/keyword/SoulbondAbility.java
2018-06-02 17:59:49 +02:00

271 lines
10 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package mage.abilities.keyword;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
import mage.util.GameLog;
/**
* 702.94. Soulbond
*
* 702.94a Soulbond is a keyword that represents two triggered abilities.
* “Soulbond” means “When this creature enters the battlefield, if you control
* both this creature and another creature and both are unpaired, you may pair
* this creature with another unpaired creature you control for as long as both
* remain creatures on the battlefield under your control” and “Whenever another
* creature enters the battlefield under your control, if you control both that
* creature and this one and both are unpaired, you may pair that creature with
* this creature for as long as both remain creatures on the battlefield under
* your control.”
*
* 702.94b A creature becomes “paired” with another as the result of a soulbond
* ability. Abilities may refer to a paired creature, the creature another
* creature is paired with, or whether a creature is paired. An “unpaired”
* creature is one that is not paired.
*
* 702.94c When the soulbond ability resolves, if either object that would be
* paired is no longer a creature, no longer on the battlefield, or no longer
* under the control of the player who controls the soulbond ability, neither
* object becomes paired.
*
* 702.94d A creature can be paired with only one other creature.
*
* 702.94e A paired creature becomes unpaired if any of the following occur:
* another player gains control of it or the creature its paired with; it or
* the creature its paired with stops being a creature; or it or the creature
* its paired with leaves the battlefield.
*
* @author LevelX2
*/
public class SoulbondAbility extends EntersBattlefieldTriggeredAbility {
public SoulbondAbility() {
super(new SoulboundEntersSelfEffect(), true);
this.addSubAbility(new SoulbondEntersOtherAbility());
}
public SoulbondAbility(SoulbondAbility ability) {
super(ability);
}
@Override
public String getRule() {
return "Soulbond <i>(You may pair this creature with another unpaired creature when either enters the battlefield. They remain paired for as long as you control both of them.)</i>";
}
@Override
public boolean checkInterveningIfClause(Game game) {
// if you control both this creature and another creature and both are unpaired
boolean self = false;
boolean other = false;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(getControllerId())) {
if (permanent.isCreature()) {
if (permanent.getId().equals(getSourceId())) {
if (permanent.getControllerId().equals(getControllerId())) {
self = true;
if (other) {
return true;
}
} else {
return false;
}
} else if (permanent.getPairedCard() == null) {
other = true;
if (self) {
return true;
}
}
}
}
return false;
}
@Override
public SoulbondAbility copy() {
return new SoulbondAbility(this);
}
}
// When this creature enters the battlefield, if you control both this creature and another creature and both are unpaired, you may pair
// this creature with another unpaired creature you control for as long as both remain creatures on the battlefield under your control
class SoulboundEntersSelfEffect extends OneShotEffect {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another not paired creature you control");
static {
filter.add(new AnotherPredicate());
filter.add(Predicates.not(new PairedPredicate()));
}
public SoulboundEntersSelfEffect() {
super(Outcome.Benefit);
}
public SoulboundEntersSelfEffect(final SoulboundEntersSelfEffect effect) {
super(effect);
}
@Override
public SoulboundEntersSelfEffect copy() {
return new SoulboundEntersSelfEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null && permanent.isCreature()) {
Player controller = game.getPlayer(permanent.getControllerId());
if (controller != null) {
TargetControlledPermanent target = new TargetControlledPermanent(filter);
target.setNotTarget(true);
if (target.canChoose(permanent.getId(), controller.getId(), game)) {
if (controller.choose(Outcome.Benefit, target, permanent.getId(), game)) {
Permanent chosen = game.getPermanent(target.getFirstTarget());
if (chosen != null) {
chosen.setPairedCard(new MageObjectReference(permanent, game));
chosen.addInfo("soulbond", "Soulbond to " + GameLog.getColoredObjectIdNameForTooltip(permanent), game);
permanent.setPairedCard(new MageObjectReference(chosen, game));
permanent.addInfo("soulbond", "Soulbond to " + GameLog.getColoredObjectIdNameForTooltip(chosen), game);
if (!game.isSimulation()) {
game.informPlayers(controller.getLogName() + " soulbonds " + permanent.getLogName() + " with " + chosen.getLogName());
}
}
}
}
}
return true;
}
return false;
}
}
/**
* “Whenever another creature enters the battlefield under your control, if you
* control both that creature and this one and both are unpaired, you may pair
* that creature with this creature for as long as both remain creatures on the
* battlefield under your control.”
*
*/
class SoulbondEntersOtherAbility extends EntersBattlefieldAllTriggeredAbility {
private final static FilterCreaturePermanent soulbondFilter = new FilterCreaturePermanent();
static {
soulbondFilter.add(Predicates.not(new PairedPredicate()));
soulbondFilter.add(new ControllerPredicate(TargetController.YOU));
soulbondFilter.add(new AnotherPredicate());
}
public SoulbondEntersOtherAbility() {
super(Zone.BATTLEFIELD, new SoulboundEntersOtherEffect(), soulbondFilter, true, SetTargetPointer.PERMANENT, "");
setRuleVisible(false);
}
public SoulbondEntersOtherAbility(SoulbondEntersOtherAbility ability) {
super(ability);
}
@Override
public String getRule() {
return "Soulbond <i>(You may pair this creature with another unpaired creature when either enters the battlefield. They remain paired for as long as you control both of them.)</i>";
}
@Override
public boolean checkInterveningIfClause(Game game) {
// if you control both this creature and another creature and both are unpaired
if (game.getBattlefield().countAll(filter, getControllerId(), game) > 0) {
Permanent sourcePermanent = game.getPermanent(getSourceId());
if (sourcePermanent != null && sourcePermanent.getControllerId().equals(getControllerId()) && sourcePermanent.getPairedCard() == null) {
return true;
}
}
return false;
}
@Override
public SoulbondEntersOtherAbility copy() {
return new SoulbondEntersOtherAbility(this);
}
}
class SoulboundEntersOtherEffect extends OneShotEffect {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another not paired creature you control");
static {
filter.add(new AnotherPredicate());
filter.add(Predicates.not(new PairedPredicate()));
}
public SoulboundEntersOtherEffect() {
super(Outcome.Benefit);
}
public SoulboundEntersOtherEffect(final SoulboundEntersOtherEffect effect) {
super(effect);
}
@Override
public SoulboundEntersOtherEffect copy() {
return new SoulboundEntersOtherEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null && permanent.getPairedCard() == null
&& permanent.isCreature()) {
Player controller = game.getPlayer(permanent.getControllerId());
if (controller != null) {
Permanent enteringPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (enteringPermanent != null && enteringPermanent.isCreature() && enteringPermanent.getPairedCard() == null) {
enteringPermanent.setPairedCard(new MageObjectReference(permanent, game));
permanent.setPairedCard(new MageObjectReference(enteringPermanent, game));
if (!game.isSimulation()) {
game.informPlayers(controller.getLogName() + " soulbonds " + permanent.getLogName() + " with " + enteringPermanent.getLogName());
}
}
}
return true;
}
return false;
}
}
class PairedPredicate implements Predicate<Permanent> {
@Override
public boolean apply(Permanent input, Game game) {
return input.getPairedCard() != null;
}
@Override
public String toString() {
return "Paired";
}
}