mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Untap: cant untap turns Effect
This commit is contained in:
@@ -30,6 +30,7 @@ public enum ApiType {
|
||||
Block (BlockEffect.class),
|
||||
Bond (BondEffect.class),
|
||||
Branch (BranchEffect.class),
|
||||
CantUntapTurn (CantUntapTurnEffect.class),
|
||||
ChangeCombatants (ChangeCombatantsEffect.class),
|
||||
ChangeTargets (ChangeTargetsEffect.class),
|
||||
ChangeText (ChangeTextEffect.class),
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
public class CantUntapTurnEffect extends SpellAbilityEffect {
|
||||
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
final Card host = sa.getHostCard();
|
||||
final Game game = host.getGame();
|
||||
final long timestamp = game.getNextTimestamp();
|
||||
|
||||
final int n = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("Turns", "1"), sa);
|
||||
|
||||
List<Card> cards = getTargetCards(sa);
|
||||
|
||||
for (final Card tgtC : cards) {
|
||||
if (sa.usesTargeting() && !tgtC.canBeTargetedBy(sa)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tgtC.addCantUntapTurn(timestamp, n);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3634,20 +3634,67 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
return !isExertedBy(p);
|
||||
}
|
||||
|
||||
public boolean isCantUntap() {
|
||||
return !cantUntap.isEmpty();
|
||||
}
|
||||
|
||||
public final boolean addCantUntap(final long timestamp) {
|
||||
return cantUntap.add(timestamp);
|
||||
boolean result = cantUntap.add(timestamp);
|
||||
getView().updateCantUntap(this);
|
||||
return result;
|
||||
}
|
||||
|
||||
public final boolean removeCantUntap(final long timestamp) {
|
||||
return cantUntap.remove(timestamp);
|
||||
boolean result = cantUntap.remove(timestamp);
|
||||
getView().updateCantUntap(this);
|
||||
return result;
|
||||
}
|
||||
|
||||
public final void addCantUntapTurn(final long timestamp, final int value) {
|
||||
cantUntapTurns.put(timestamp, value);
|
||||
getView().updateCantUntap(this);
|
||||
}
|
||||
|
||||
public final void removeCantUntapTurn(final long timestamp) {
|
||||
cantUntapTurns.remove(timestamp);
|
||||
getView().updateCantUntap(this);
|
||||
}
|
||||
|
||||
public final void removeCantUntapTurn() {
|
||||
// reduce by one each turn
|
||||
|
||||
List<Long> toRemove = Lists.newArrayList();
|
||||
for (final Map.Entry<Long, Integer> e : cantUntapTurns.entrySet()) {
|
||||
e.setValue(e.getValue() - 1);
|
||||
if (e.getValue() <= 0) {
|
||||
toRemove.add(e.getKey());
|
||||
}
|
||||
}
|
||||
for (final long l : toRemove) {
|
||||
cantUntapTurns.remove(l);
|
||||
}
|
||||
getView().updateCantUntap(this);
|
||||
}
|
||||
|
||||
public final int getCantUntapTurnValue() {
|
||||
if (cantUntapTurns.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return Collections.max(cantUntapTurns.values());
|
||||
}
|
||||
|
||||
public final void addCantUntapPlayer(final Player p, final long timestamp) {
|
||||
cantUntapPlayer.put(timestamp, p);
|
||||
getView().updateCantUntap(this);
|
||||
}
|
||||
|
||||
public final void removeCantUntapPlayer(final long timestamp) {
|
||||
cantUntapPlayer.remove(timestamp);
|
||||
getView().updateCantUntap(this);
|
||||
}
|
||||
|
||||
public final Collection<Player> getCantUntapPlayer() {
|
||||
return cantUntapPlayer.values();
|
||||
}
|
||||
|
||||
public final void untap() {
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.game.card;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ImageKeys;
|
||||
import forge.card.*;
|
||||
import forge.card.mana.ManaCost;
|
||||
@@ -22,6 +24,7 @@ import forge.util.Lang;
|
||||
import forge.util.collect.FCollectionView;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -604,7 +607,7 @@ public class CardView extends GameEntityView {
|
||||
sb.append("\r\n\r\n").append("(").append(taltname).append(") ").append(taltoracle);
|
||||
}
|
||||
|
||||
String nonAbilityText = get(TrackableProperty.NonAbilityText);
|
||||
String nonAbilityText = getNonAbilityText();
|
||||
if (!nonAbilityText.isEmpty()) {
|
||||
sb.append("\r\n \r\nNon ability features: \r\n");
|
||||
sb.append(nonAbilityText.replaceAll("CARDNAME", getName()));
|
||||
@@ -632,22 +635,6 @@ public class CardView extends GameEntityView {
|
||||
sb.append("\r\n");
|
||||
}
|
||||
|
||||
if (getCanBlockAny()) {
|
||||
sb.append("\r\n\r\n");
|
||||
sb.append("CARDNAME can block any number of creatures.".replaceAll("CARDNAME", getName()));
|
||||
sb.append("\r\n");
|
||||
} else {
|
||||
int i = getBlockAdditional();
|
||||
if (i > 0) {
|
||||
sb.append("\r\n\r\n");
|
||||
sb.append("CARDNAME can block an additional ".replaceAll("CARDNAME", getName()));
|
||||
sb.append(i == 1 ? "creature" : Lang.nounWithNumeral(i, "creature"));
|
||||
sb.append(" each combat.");
|
||||
sb.append("\r\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String cloner = get(TrackableProperty.Cloner);
|
||||
if (!cloner.isEmpty()) {
|
||||
sb.append("\r\nCloned by: ").append(cloner);
|
||||
@@ -656,6 +643,57 @@ public class CardView extends GameEntityView {
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
public String getNonAbilityText() {
|
||||
StringBuilder sb = new StringBuilder(get(TrackableProperty.NonAbilityText));
|
||||
|
||||
if (getCanBlockAny()) {
|
||||
sb.append("\r\n");
|
||||
sb.append("CARDNAME can block any number of creatures.");
|
||||
sb.append("\r\n");
|
||||
} else {
|
||||
int i = getBlockAdditional();
|
||||
if (i > 0) {
|
||||
sb.append("\r\n");
|
||||
sb.append("CARDNAME can block an additional ");
|
||||
sb.append(i == 1 ? "creature" : Lang.nounWithNumeral(i, "creature"));
|
||||
sb.append(" each combat.");
|
||||
sb.append("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (getCantUntap()) {
|
||||
String msg = "CARDNAME doesn’t untap during its controller’s untap step.";
|
||||
sb.append("\r\n");
|
||||
sb.append(msg);
|
||||
sb.append("\r\n");
|
||||
} else {
|
||||
int i = this.getCantUntapTurn();
|
||||
if (i == 1) {
|
||||
String msg = "CARDNAME doesn’t untap during its controller’s next untap step.";
|
||||
sb.append("\r\n");
|
||||
sb.append(msg);
|
||||
sb.append("\r\n");
|
||||
} else if (i > 1) {
|
||||
String str = Lang.nounWithNumeral(i, "untap step");
|
||||
String msg = ("CARDNAME doesn’t untap during its controller’s next " + str + ".");
|
||||
sb.append("\r\n");
|
||||
sb.append(msg);
|
||||
sb.append("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
FCollectionView<PlayerView> untapList = getCantUntapPlayer();
|
||||
if (untapList != null && !untapList.isEmpty()) {
|
||||
String p = Lang.joinHomogenous(Lists.newArrayList(untapList), null, "or");
|
||||
String msg = "CARDNAME doesn’t untap during " + p + " untap step.";
|
||||
sb.append("\r\n");
|
||||
sb.append(msg);
|
||||
sb.append("\r\n");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public CardStateView getCurrentState() {
|
||||
return get(TrackableProperty.CurrentState);
|
||||
}
|
||||
@@ -767,6 +805,39 @@ public class CardView extends GameEntityView {
|
||||
set(TrackableProperty.BlockAny, c.canBlockAny());
|
||||
}
|
||||
|
||||
boolean getCantUntap() {
|
||||
return get(TrackableProperty.CantUntapAny);
|
||||
}
|
||||
int getCantUntapTurn() {
|
||||
return get(TrackableProperty.CantUntapTurns);
|
||||
}
|
||||
|
||||
FCollectionView<PlayerView> getCantUntapPlayer() {
|
||||
return get(TrackableProperty.CantUntapPlayer);
|
||||
}
|
||||
|
||||
void updateCantUntap(Card c) {
|
||||
set(TrackableProperty.CantUntapAny, c.isCantUntap());
|
||||
set(TrackableProperty.CantUntapTurns, c.getCantUntapTurnValue());
|
||||
|
||||
Collection<Player> list = c.getCantUntapPlayer();
|
||||
if (list.isEmpty()) {
|
||||
set(TrackableProperty.CantUntapPlayer, null);
|
||||
} else {
|
||||
TrackableCollection<PlayerView> prop = get(TrackableProperty.CantUntapPlayer);
|
||||
if (prop == null) {
|
||||
prop = new TrackableCollection<>();
|
||||
} else {
|
||||
prop.clear();
|
||||
}
|
||||
for (Player p : list) {
|
||||
prop.add(p.getView());
|
||||
}
|
||||
|
||||
set(TrackableProperty.CantUntapPlayer, prop);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getName();
|
||||
|
||||
@@ -65,7 +65,7 @@ public class Untap extends Phase {
|
||||
*/
|
||||
@Override
|
||||
public void executeAt() {
|
||||
this.execute(this.at);
|
||||
super.executeAt();
|
||||
|
||||
final Player turn = game.getPhaseHandler().getPlayerTurn();
|
||||
Untap.doPhasing(turn);
|
||||
@@ -84,8 +84,7 @@ public class Untap extends Phase {
|
||||
*/
|
||||
public static boolean canUntap(final Card c) {
|
||||
|
||||
if (c.hasKeyword("This card doesn't untap during your next untap step.")
|
||||
|| c.hasKeyword("This card doesn't untap during your next two untap steps.")) {
|
||||
if (c.hasKeyword("This card doesn't untap during your next untap step.")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -199,11 +198,9 @@ public class Untap extends Phase {
|
||||
|
||||
// Remove temporary keywords
|
||||
for (final Card c : player.getCardsIn(ZoneType.Battlefield)) {
|
||||
c.removeCantUntapTurn();
|
||||
|
||||
c.removeHiddenExtrinsicKeyword("This card doesn't untap during your next untap step.");
|
||||
if (c.hasKeyword("This card doesn't untap during your next two untap steps.")) {
|
||||
c.removeHiddenExtrinsicKeyword("This card doesn't untap during your next two untap steps.");
|
||||
c.addHiddenExtrinsicKeyword("This card doesn't untap during your next untap step.");
|
||||
}
|
||||
}
|
||||
|
||||
// remove exerted flags from all things in play
|
||||
|
||||
@@ -113,6 +113,9 @@ public enum TrackableProperty {
|
||||
OpponentMayLook(TrackableTypes.BooleanType),
|
||||
BlockAdditional(TrackableTypes.IntegerType),
|
||||
BlockAny(TrackableTypes.BooleanType),
|
||||
CantUntapTurns(TrackableTypes.IntegerType),
|
||||
CantUntapPlayer(TrackableTypes.PlayerViewCollectionType),
|
||||
CantUntapAny(TrackableTypes.BooleanType),
|
||||
AbilityText(TrackableTypes.StringType),
|
||||
NonAbilityText(TrackableTypes.StringType),
|
||||
FoilIndex(TrackableTypes.IntegerType),
|
||||
|
||||
Reference in New Issue
Block a user