mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
- ChangeCombatantsEffect: attempt to account for the new rule for Ulamog, the Ceaseless Hunger + Portal Mage interaction in multiplayer games. Currently achieved by rigging the triggering info on the stack instance, which may not be optimal. Feel free to propose a better solution.
This commit is contained in:
@@ -7,7 +7,9 @@ import forge.game.card.Card;
|
||||
import forge.game.combat.AttackingBand;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.event.GameEventCombatChanged;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.util.collect.FCollectionView;
|
||||
|
||||
@@ -38,17 +40,29 @@ public class ChangeCombatantsEffect extends SpellAbilityEffect {
|
||||
for (final Card c : getTargetCards(sa)) {
|
||||
if ((tgt == null) || c.canBeTargetedBy(sa)) {
|
||||
final Combat combat = game.getCombat();
|
||||
final GameEntity orginalDefender = combat.getDefenderByAttacker(c);
|
||||
final GameEntity originalDefender = combat.getDefenderByAttacker(c);
|
||||
final FCollectionView<GameEntity> defs = combat.getDefenders();
|
||||
final GameEntity defender = sa.getActivatingPlayer().getController().chooseSingleEntityForEffect(defs, sa,
|
||||
"Choose which defender to attack with " + c, false);
|
||||
if (orginalDefender != null && !orginalDefender.equals(defender)) {
|
||||
if (originalDefender != null && !originalDefender.equals(defender)) {
|
||||
AttackingBand ab = combat.getBandOfAttacker(c);
|
||||
if (ab != null) {
|
||||
combat.unregisterAttacker(c, ab);
|
||||
ab.removeAttacker(c);
|
||||
}
|
||||
combat.addAttacker(c, defender);
|
||||
// retarget triggers to the new defender (e.g. Ulamog, Ceaseless Hunger + Portal Mage)
|
||||
for (SpellAbilityStackInstance si : game.getStack()) {
|
||||
if (si.isTrigger() && c.equals(si.getSourceCard())
|
||||
&& si.getTriggeringObject("Attacker") != null) {
|
||||
si.addTriggeringObject("OriginalDefender", originalDefender);
|
||||
if (defender instanceof Player) {
|
||||
si.updateTriggeringObject("DefendingPlayer", defender);
|
||||
} else if (defender instanceof Card) {
|
||||
si.updateTriggeringObject("DefendingPlayer", ((Card)defender).getController());
|
||||
}
|
||||
}
|
||||
}
|
||||
isCombatChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
@@ -541,6 +543,24 @@ public class Combat {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// restore the original defender in case it was changed before the creature was
|
||||
// removed from combat but before the trigger resolved (e.g. Ulamog, the Ceaseless
|
||||
// Hunger + Portal Mage + Unsummon)
|
||||
Game game = c.getGame();
|
||||
for (SpellAbilityStackInstance si : game.getStack()) {
|
||||
if (si.isTrigger() && c.equals(si.getSourceCard())) {
|
||||
GameEntity origDefender = (GameEntity)si.getTriggeringObject("OriginalDefender");
|
||||
if (origDefender != null) {
|
||||
si.updateTriggeringObject("Defender", origDefender);
|
||||
if (origDefender instanceof Player) {
|
||||
si.updateTriggeringObject("DefendingPlayer", origDefender);
|
||||
} else if (origDefender instanceof Card) {
|
||||
si.updateTriggeringObject("DefendingPlayer", ((Card)origDefender).getController());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// removes references to this defender from all indices and orders
|
||||
|
||||
@@ -356,6 +356,29 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addTriggeringObject(String trigObj, Object value) {
|
||||
if (!triggeringObjects.containsKey(trigObj)) {
|
||||
triggeringObjects.put(trigObj, value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean updateTriggeringObject(String trigObj, Object value) {
|
||||
if (triggeringObjects.containsKey(trigObj)) {
|
||||
triggeringObjects.replace(trigObj, value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object getTriggeringObject(String trigObj) {
|
||||
if (triggeringObjects.containsKey(trigObj)) {
|
||||
return triggeringObjects.get(trigObj);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean compareToSpellAbility(SpellAbility sa) {
|
||||
// Compare my target choices to the SA passed in
|
||||
// TODO? Compare other data points in the SI to the passed SpellAbility for confirmation
|
||||
|
||||
Reference in New Issue
Block a user