Skip to content

Commit

Permalink
LCI: the_millennium_calendar.txt and support (TriggerUntapAll)
Browse files Browse the repository at this point in the history
  • Loading branch information
Northmoc committed Nov 15, 2023
1 parent 4c84acd commit 14205e0
Show file tree
Hide file tree
Showing 15 changed files with 240 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import com.google.common.collect.Lists;

import com.google.common.collect.Maps;
import forge.GameCommand;
import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.event.GameEventCardStatsChanged;
import forge.game.event.GameEventCombatChanged;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.CardTranslation;
import forge.util.Localizer;
Expand Down Expand Up @@ -145,6 +150,7 @@ public void resolve(SpellAbility sa) {
}

boolean combatChanged = false;
CardCollection untapped = new CardCollection();
for (Card tgtC : tgtCards) {
if (!tgtC.isInPlay() || !tgtC.canBeControlledBy(newController)) {
continue;
Expand All @@ -167,7 +173,7 @@ public void resolve(SpellAbility sa) {
tgtC.addTempController(newController, tStamp);

if (bUntap) {
tgtC.untap(true);
if (tgtC.untap(true)) untapped.add(tgtC);
}

final List<String> kws = Lists.newArrayList();
Expand Down Expand Up @@ -251,6 +257,13 @@ public void run() {
combatChanged = true;
}
} // end foreach target
if (!untapped.isEmpty()) {
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
final Map<Player, CardCollection> map = Maps.newHashMap();
map.put(activator, untapped);
runParams.put(AbilityKey.Map, map);
game.getTriggerHandler().runTrigger(TriggerType.UntapAll, runParams, false);
}

if (combatChanged) {
game.updateCombatForView();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package forge.game.ability.effects;


import com.google.common.collect.Maps;
import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
Expand Down Expand Up @@ -66,21 +67,29 @@ public void resolve(SpellAbility sa) {
toTap = sa.getActivatingPlayer().getController().chooseBinary(sa, sb.toString(), PlayerController.BinaryChoiceType.TapOrUntap);

CardCollection tapped = new CardCollection();
CardCollection untapped = new CardCollection();
for (final Card tgtC : validCards) {
if (!tgtC.isInPlay()) {
continue;
}
if (toTap) {
if (tgtC.tap(true, sa, activator)) tapped.add(tgtC);
} else {
tgtC.untap(true);
if (tgtC.untap(true)) untapped.add(tgtC);
}
}
if (!tapped.isEmpty()) {
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put(AbilityKey.Cards, tapped);
game.getTriggerHandler().runTrigger(TriggerType.TapAll, runParams, false);
}
if (!untapped.isEmpty()) {
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
final Map<Player, CardCollection> map = Maps.newHashMap();
map.put(activator, untapped);
runParams.put(AbilityKey.Map, map);
game.getTriggerHandler().runTrigger(TriggerType.UntapAll, runParams, false);
}
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package forge.game.ability.effects;

import com.google.common.collect.Maps;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
Expand Down Expand Up @@ -38,6 +39,7 @@ public void resolve(SpellAbility sa) {
PlayerController pc = activator.getController();

CardCollection tapped = new CardCollection();
final Map<Player, CardCollection> untapMap = Maps.newHashMap();
for (final Card tgtC : getTargetCards(sa)) {
if (!tgtC.isInPlay()) {
continue;
Expand All @@ -50,16 +52,17 @@ public void resolve(SpellAbility sa) {
boolean tap = pc.chooseBinary(sa, Localizer.getInstance().getMessage("lblTapOrUntapTarget", CardTranslation.getTranslatedName(tgtC.getName())), PlayerController.BinaryChoiceType.TapOrUntap,
!tgtC.getController().equals(activator) );

if (tap) {
Player tapper = activator;
if (sa.hasParam("Tapper")) {
tapper = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Tapper"), sa).getFirst();
}

if (tgtC.tap(true, sa, tapper)) tapped.add(tgtC);
} else {
tgtC.untap(true);
Player tapper = activator;
if (sa.hasParam("Tapper")) {
tapper = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Tapper"), sa).getFirst();
}
if (tgtC.tap(true, sa, tapper)) tapped.add(tgtC);
else if (tgtC.untap(true)) untapMap.computeIfAbsent(tapper, i -> new CardCollection()).add(tgtC);
}
if (!untapMap.isEmpty()) {
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put(AbilityKey.Map, untapMap);
activator.getGame().getTriggerHandler().runTrigger(TriggerType.UntapAll, runParams, false);
}
if (!tapped.isEmpty()) {
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package forge.game.ability.effects;

import com.google.common.collect.Maps;
import forge.game.ability.AbilityKey;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollectionView;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.player.Player;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;

import java.util.Map;

public class UntapAllEffect extends SpellAbilityEffect {
@Override
protected String getStackDescription(SpellAbility sa) {
Expand All @@ -20,22 +26,23 @@ protected String getStackDescription(SpellAbility sa) {
@Override
public void resolve(SpellAbility sa) {
final Card card = sa.getHostCard();
CardCollectionView list;
final Player activator = sa.getActivatingPlayer();
final String valid = sa.getParamOrDefault("ValidCards", "");
Map<Player, CardCollection> untapMap = Maps.newHashMap();

if (!sa.usesTargeting() && !sa.hasParam("Defined")) {
list = sa.getActivatingPlayer().getGame().getCardsIn(ZoneType.Battlefield);
} else {
list = getTargetPlayers(sa).getCardsIn(ZoneType.Battlefield);
for (Player p : getTargetPlayers(sa)) {
for (Card c : CardLists.getValidCards(p.getCardsIn(ZoneType.Battlefield), valid, activator, card, sa)) {
if (c.untap(true)) {
untapMap.computeIfAbsent(p, i -> new CardCollection()).add(c);
if (sa.hasParam("RememberUntapped")) card.addRemembered(c);
}
}
}
list = CardLists.getValidCards(list, valid, sa.getActivatingPlayer(), card, sa);

boolean remember = sa.hasParam("RememberUntapped");
for (Card c : list) {
c.untap(true);
if (remember) {
card.addRemembered(c);
}
if (!untapMap.isEmpty()) {
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put(AbilityKey.Map, untapMap);
activator.getGame().getTriggerHandler().runTrigger(TriggerType.UntapAll, runParams, false);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package forge.game.ability.effects;

import com.google.common.collect.Maps;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
Expand All @@ -10,10 +12,13 @@
import forge.game.card.CardPredicates.Presets;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.Lang;
import forge.util.Localizer;

import java.util.Map;

public class UntapEffect extends SpellAbilityEffect {

/* (non-Javadoc)
Expand All @@ -38,6 +43,9 @@ protected String getStackDescription(SpellAbility sa) {

@Override
public void resolve(SpellAbility sa) {
final Player activator = sa.getActivatingPlayer();
final boolean ETB = sa.hasParam("ETB");

if (sa.hasParam("UntapUpTo")) {
untapChoose(sa, false);
} else if (sa.hasParam("UntapExactly")) {
Expand All @@ -46,18 +54,26 @@ public void resolve(SpellAbility sa) {
final CardCollection affectedCards = getTargetCards(sa);
affectedCards.addAll(CardUtil.getRadiance(sa));

CardCollection untapped = new CardCollection();
for (final Card tgtC : affectedCards) {
if (tgtC.isPhasedOut()) {
continue;
}
if (tgtC.isInPlay()) {
tgtC.untap(true);
if (tgtC.untap(true)) untapped.add(tgtC);
}
if (sa.hasParam("ETB")) {
if (ETB) {
// do not fire triggers
tgtC.setTapped(false);
}
}
if (!untapped.isEmpty() && !ETB) {
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
final Map<Player, CardCollection> map = Maps.newHashMap();
map.put(activator, untapped);
runParams.put(AbilityKey.Map, map);
activator.getGame().getTriggerHandler().runTrigger(TriggerType.UntapAll, runParams, false);
}
}
}

Expand All @@ -72,10 +88,12 @@ public void resolve(SpellAbility sa) {
* whether the untapping is mandatory.
*/
private static void untapChoose(final SpellAbility sa, final boolean mandatory) {
final Map<Player, CardCollection> map = Maps.newHashMap();
final int num = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Amount"), sa);
final String valid = sa.getParam("UntapType");

for (final Player p : AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Defined"), sa)) {
CardCollection untapped = new CardCollection();
if (!p.isInGame()) {
continue;
}
Expand All @@ -90,9 +108,18 @@ private static void untapChoose(final SpellAbility sa, final boolean mandatory)
final CardCollectionView selected = p.getController().chooseCardsForEffect(list, sa, Localizer.getInstance().getMessage("lblSelectCardToUntap"), mandatory ? num : 0, num, !mandatory, null);
if (selected != null) {
for (final Card c : selected) {
c.untap(true);
if (c.untap(true)) untapped.add(c);
}
}
if (!untapped.isEmpty()) {
map.put(p, untapped);
}
}
if (!map.isEmpty()) {
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put(AbilityKey.Map, map);
sa.getActivatingPlayer().getGame().getTriggerHandler()
.runTrigger(TriggerType.UntapAll, runParams, false);
}
}

Expand Down
7 changes: 4 additions & 3 deletions forge-game/src/main/java/forge/game/card/Card.java
Original file line number Diff line number Diff line change
Expand Up @@ -4461,12 +4461,12 @@ public final boolean tap(boolean attacker, boolean tapAnimation, SpellAbility ca
return true;
}

public final void untap(boolean untapAnimation) {
if (!tapped) { return; }
public final boolean untap(boolean untapAnimation) {
if (!tapped) { return false; }

// Run Replacement effects
if (getGame().getReplacementHandler().run(ReplacementType.Untap, AbilityKey.mapFromAffected(this)) != ReplacementResult.NotReplaced) {
return;
return false;
}

// Run triggers
Expand All @@ -4476,6 +4476,7 @@ public final void untap(boolean untapAnimation) {
setTapped(false);
view.updateNeedsUntapAnimation(untapAnimation);
getGame().fireEvent(new GameEventCardTapped(this, false));
return true;
}

public final Table<Long, Long, CardTraitChanges> getChangedCardTraitsByText() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@
*/
package forge.game.cost;

import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardUtil;
import forge.game.card.CardZoneTable;
import forge.game.card.*;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.Zone;
Expand Down
15 changes: 14 additions & 1 deletion forge-game/src/main/java/forge/game/cost/CostUntap.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@
*/
package forge.game.cost;

import com.google.common.collect.Maps;
import forge.game.ability.AbilityKey;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType;

import java.util.Map;

/**
* The Class CostUntap.
Expand Down Expand Up @@ -77,7 +83,14 @@ public final boolean canPay(final SpellAbility ability, final Player payer, fina

@Override
public boolean payAsDecided(Player ai, PaymentDecision decision, SpellAbility ability, final boolean effect) {
ability.getHostCard().untap(true);
final Card c = ability.getHostCard();
if (c.untap(true)) {
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
final Map<Player, CardCollection> map = Maps.newHashMap();
map.put(ai, new CardCollection(c));
runParams.put(AbilityKey.Map, map);
ai.getGame().getTriggerHandler().runTrigger(TriggerType.UntapAll, runParams, false);
}
return true;
}

Expand Down
Loading

0 comments on commit 14205e0

Please sign in to comment.