mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 02:08:00 +00:00
CanBlockAny: rewrite for 'can block an additional' and 'can block any number'
This commit is contained in:
@@ -547,8 +547,7 @@ public class AiAttackController {
|
|||||||
remainingAttackers.removeAll(unblockedAttackers);
|
remainingAttackers.removeAll(unblockedAttackers);
|
||||||
|
|
||||||
for (Card blocker : this.blockers) {
|
for (Card blocker : this.blockers) {
|
||||||
if (blocker.hasKeyword("CARDNAME can block any number of creatures.")
|
if (blocker.canBlockAny()) {
|
||||||
|| blocker.hasKeyword("CARDNAME can block an additional ninety-nine creatures each combat.")) {
|
|
||||||
for (Card attacker : this.attackers) {
|
for (Card attacker : this.attackers) {
|
||||||
if (CombatUtil.canBlock(attacker, blocker)) {
|
if (CombatUtil.canBlock(attacker, blocker)) {
|
||||||
remainingAttackers.remove(attacker);
|
remainingAttackers.remove(attacker);
|
||||||
@@ -564,6 +563,7 @@ public class AiAttackController {
|
|||||||
if (remainingAttackers.isEmpty() || maxBlockersAfterCrew == 0) {
|
if (remainingAttackers.isEmpty() || maxBlockersAfterCrew == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// TODO replace with better amount
|
||||||
if (blocker.hasKeyword("CARDNAME can block an additional creature each combat.")) {
|
if (blocker.hasKeyword("CARDNAME can block an additional creature each combat.")) {
|
||||||
blockedAttackers.add(remainingAttackers.get(0));
|
blockedAttackers.add(remainingAttackers.get(0));
|
||||||
remainingAttackers.remove(0);
|
remainingAttackers.remove(0);
|
||||||
@@ -884,7 +884,7 @@ public class AiAttackController {
|
|||||||
final int outNumber = computerForces - humanForces;
|
final int outNumber = computerForces - humanForces;
|
||||||
|
|
||||||
for (Card blocker : this.blockers) {
|
for (Card blocker : this.blockers) {
|
||||||
if (blocker.hasKeyword("CARDNAME can block any number of creatures.")) {
|
if (blocker.canBlockAny()) {
|
||||||
aiLifeToPlayerDamageRatio--;
|
aiLifeToPlayerDamageRatio--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1581,9 +1581,6 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
&& CombatUtil.canBlock(card, true);
|
&& CombatUtil.canBlock(card, true);
|
||||||
} else if (keyword.equals("Reach")) {
|
} else if (keyword.equals("Reach")) {
|
||||||
return !card.hasKeyword(Keyword.FLYING) && CombatUtil.canBlock(card, true);
|
return !card.hasKeyword(Keyword.FLYING) && CombatUtil.canBlock(card, true);
|
||||||
} else if (keyword.endsWith("CARDNAME can block an additional creature each combat.")) {
|
|
||||||
return CombatUtil.canBlock(card, true) && !card.hasKeyword("CARDNAME can block any number of creatures.")
|
|
||||||
&& !card.hasKeyword("CARDNAME can block an additional ninety-nine creatures each combat.");
|
|
||||||
} else if (keyword.equals("CARDNAME can attack as though it didn't have defender.")) {
|
} else if (keyword.equals("CARDNAME can attack as though it didn't have defender.")) {
|
||||||
return card.hasKeyword(Keyword.DEFENDER) && card.getNetCombatDamage() + powerBonus > 0;
|
return card.hasKeyword(Keyword.DEFENDER) && card.getNetCombatDamage() + powerBonus > 0;
|
||||||
} else if (keyword.equals("Shroud") || keyword.equals("Hexproof")) {
|
} else if (keyword.equals("Shroud") || keyword.equals("Hexproof")) {
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else if (keyword.equals("Bushido")) {
|
} else if (keyword.startsWith("Bushido")) {
|
||||||
return !ph.isPlayerTurn(opp) && (CombatUtil.canAttack(card, opp) || (combat != null && combat.isAttacking(card)))
|
return !ph.isPlayerTurn(opp) && (CombatUtil.canAttack(card, opp) || (combat != null && combat.isAttacking(card)))
|
||||||
&& !ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)
|
&& !ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)
|
||||||
&& !opp.getCreaturesInPlay().isEmpty()
|
&& !opp.getCreaturesInPlay().isEmpty()
|
||||||
@@ -335,22 +335,6 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|
|||||||
&& !CardLists.getKeyword(game.getCombat().getAttackers(), Keyword.FLYING).isEmpty()
|
&& !CardLists.getKeyword(game.getCombat().getAttackers(), Keyword.FLYING).isEmpty()
|
||||||
&& !card.hasKeyword(Keyword.FLYING)
|
&& !card.hasKeyword(Keyword.FLYING)
|
||||||
&& CombatUtil.canBlock(card);
|
&& CombatUtil.canBlock(card);
|
||||||
} else if (keyword.endsWith("CARDNAME can block an additional creature each combat.")) {
|
|
||||||
if (ph.isPlayerTurn(ai)
|
|
||||||
|| !ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int canBlockNum = 1 + CombatUtil.numberOfAdditionalCreaturesCanBlock(card);
|
|
||||||
int possibleBlockNum = 0;
|
|
||||||
for (Card attacker : game.getCombat().getAttackers()) {
|
|
||||||
if (CombatUtil.canBlock(attacker, card)) {
|
|
||||||
possibleBlockNum++;
|
|
||||||
if (possibleBlockNum > canBlockNum) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return possibleBlockNum > canBlockNum;
|
|
||||||
} else if (keyword.equals("Shroud") || keyword.equals("Hexproof")) {
|
} else if (keyword.equals("Shroud") || keyword.equals("Hexproof")) {
|
||||||
return ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa).contains(card);
|
return ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa).contains(card);
|
||||||
} else if (keyword.equals("Persist")) {
|
} else if (keyword.equals("Persist")) {
|
||||||
|
|||||||
@@ -47,11 +47,8 @@ public class StaticEffect {
|
|||||||
|
|
||||||
private final Card source;
|
private final Card source;
|
||||||
private StaticAbility ability;
|
private StaticAbility ability;
|
||||||
private int keywordNumber = 0;
|
|
||||||
private CardCollectionView affectedCards = new CardCollection();
|
private CardCollectionView affectedCards = new CardCollection();
|
||||||
private List<Player> affectedPlayers = Lists.newArrayList();
|
private List<Player> affectedPlayers = Lists.newArrayList();
|
||||||
private int xValue = 0;
|
|
||||||
private int yValue = 0;
|
|
||||||
private long timestamp = -1;
|
private long timestamp = -1;
|
||||||
|
|
||||||
private String chosenType;
|
private String chosenType;
|
||||||
@@ -88,11 +85,8 @@ public class StaticEffect {
|
|||||||
private StaticEffect makeMappedCopy(GameObjectMap map) {
|
private StaticEffect makeMappedCopy(GameObjectMap map) {
|
||||||
StaticEffect copy = new StaticEffect(map.map(this.source));
|
StaticEffect copy = new StaticEffect(map.map(this.source));
|
||||||
copy.ability = this.ability;
|
copy.ability = this.ability;
|
||||||
copy.keywordNumber = this.keywordNumber;
|
|
||||||
copy.affectedCards = map.mapCollection(this.affectedCards);
|
copy.affectedCards = map.mapCollection(this.affectedCards);
|
||||||
copy.affectedPlayers = map.mapList(this.affectedPlayers);
|
copy.affectedPlayers = map.mapList(this.affectedPlayers);
|
||||||
copy.xValue = this.xValue;
|
|
||||||
copy.yValue = this.yValue;
|
|
||||||
copy.timestamp = this.timestamp;
|
copy.timestamp = this.timestamp;
|
||||||
copy.chosenType = this.chosenType;
|
copy.chosenType = this.chosenType;
|
||||||
copy.mapParams = this.mapParams;
|
copy.mapParams = this.mapParams;
|
||||||
@@ -627,29 +621,6 @@ public class StaticEffect {
|
|||||||
return this.source;
|
return this.source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Setter for the field <code>keywordNumber</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param i
|
|
||||||
* a int.
|
|
||||||
*/
|
|
||||||
public final void setKeywordNumber(final int i) {
|
|
||||||
this.keywordNumber = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Getter for the field <code>keywordNumber</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a int.
|
|
||||||
*/
|
|
||||||
public final int getKeywordNumber() {
|
|
||||||
return this.keywordNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Getter for the field <code>affectedCards</code>.
|
* Getter for the field <code>affectedCards</code>.
|
||||||
@@ -692,52 +663,6 @@ public class StaticEffect {
|
|||||||
this.affectedPlayers = list;
|
this.affectedPlayers = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Setter for the field <code>xValue</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param x
|
|
||||||
* a int.
|
|
||||||
*/
|
|
||||||
public final void setXValue(final int x) {
|
|
||||||
this.xValue = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Getter for the field <code>xValue</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a int.
|
|
||||||
*/
|
|
||||||
public final int getXValue() {
|
|
||||||
return this.xValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Setter for the field <code>yValue</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param y
|
|
||||||
* a int.
|
|
||||||
*/
|
|
||||||
public final void setYValue(final int y) {
|
|
||||||
this.yValue = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Getter for the field <code>yValue</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a int.
|
|
||||||
*/
|
|
||||||
public final int getYValue() {
|
|
||||||
return this.yValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* setParams. TODO Write javadoc for this method.
|
* setParams. TODO Write javadoc for this method.
|
||||||
*
|
*
|
||||||
@@ -788,7 +713,6 @@ public class StaticEffect {
|
|||||||
|
|
||||||
String changeColorWordsTo = null;
|
String changeColorWordsTo = null;
|
||||||
|
|
||||||
int keywordMultiplier = 1;
|
|
||||||
boolean setPT = false;
|
boolean setPT = false;
|
||||||
String[] addHiddenKeywords = null;
|
String[] addHiddenKeywords = null;
|
||||||
String addColors = null;
|
String addColors = null;
|
||||||
@@ -805,15 +729,6 @@ public class StaticEffect {
|
|||||||
setPT = true;
|
setPT = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("KeywordMultiplier")) {
|
|
||||||
String multiplier = params.get("KeywordMultiplier");
|
|
||||||
if (multiplier.equals("X")) {
|
|
||||||
keywordMultiplier = getXValue();
|
|
||||||
} else {
|
|
||||||
keywordMultiplier = Integer.valueOf(multiplier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("AddHiddenKeyword")) {
|
if (params.containsKey("AddHiddenKeyword")) {
|
||||||
addHiddenKeywords = params.get("AddHiddenKeyword").split(" & ");
|
addHiddenKeywords = params.get("AddHiddenKeyword").split(" & ");
|
||||||
}
|
}
|
||||||
@@ -906,9 +821,7 @@ public class StaticEffect {
|
|||||||
|
|
||||||
if (addHiddenKeywords != null) {
|
if (addHiddenKeywords != null) {
|
||||||
for (final String k : addHiddenKeywords) {
|
for (final String k : addHiddenKeywords) {
|
||||||
for (int j = 0; j < keywordMultiplier; j++) {
|
affectedCard.removeHiddenExtrinsicKeyword(k);
|
||||||
affectedCard.removeHiddenExtrinsicKeyword(k);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -949,6 +862,13 @@ public class StaticEffect {
|
|||||||
affectedCard.removeGoad(getTimestamp());
|
affectedCard.removeGoad(getTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("CanBlockAny")) {
|
||||||
|
affectedCard.removeCanBlockAny(getTimestamp());
|
||||||
|
}
|
||||||
|
if (params.containsKey("CanBlockAmount")) {
|
||||||
|
affectedCard.removeCanBlockAdditional(getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
affectedCard.updateAbilityTextForView(); // only update keywords and text for view to avoid flickering
|
affectedCard.updateAbilityTextForView(); // only update keywords and text for view to avoid flickering
|
||||||
}
|
}
|
||||||
return affectedCards;
|
return affectedCards;
|
||||||
|
|||||||
@@ -64,7 +64,15 @@ public class PumpEffect extends SpellAbilityEffect {
|
|||||||
if (redrawPT) {
|
if (redrawPT) {
|
||||||
gameCard.updatePowerToughnessForView();
|
gameCard.updatePowerToughnessForView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sa.hasParam("CanBlockAny")) {
|
||||||
|
gameCard.addCanBlockAny(timestamp);
|
||||||
|
}
|
||||||
|
if (sa.hasParam("CanBlockAmount")) {
|
||||||
|
int v = AbilityUtils.calculateAmount(host, sa.getParam("CanBlockAmount"), sa, true);
|
||||||
|
gameCard.addCanBlockAdditional(v, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
if (sa.hasParam("LeaveBattlefield")) {
|
if (sa.hasParam("LeaveBattlefield")) {
|
||||||
addLeaveBattlefieldReplacement(gameCard, sa, sa.getParam("LeaveBattlefield"));
|
addLeaveBattlefieldReplacement(gameCard, sa, sa.getParam("LeaveBattlefield"));
|
||||||
}
|
}
|
||||||
@@ -77,6 +85,9 @@ public class PumpEffect extends SpellAbilityEffect {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
gameCard.removePTBoost(timestamp);
|
gameCard.removePTBoost(timestamp);
|
||||||
|
boolean updateText = false;
|
||||||
|
updateText = gameCard.removeCanBlockAny(timestamp) || updateText;
|
||||||
|
updateText = gameCard.removeCanBlockAdditional(timestamp) || updateText;
|
||||||
|
|
||||||
if (keywords.size() > 0) {
|
if (keywords.size() > 0) {
|
||||||
|
|
||||||
@@ -88,6 +99,9 @@ public class PumpEffect extends SpellAbilityEffect {
|
|||||||
gameCard.removeChangedCardKeywords(timestamp);
|
gameCard.removeChangedCardKeywords(timestamp);
|
||||||
}
|
}
|
||||||
gameCard.updatePowerToughnessForView();
|
gameCard.updatePowerToughnessForView();
|
||||||
|
if (updateText) {
|
||||||
|
gameCard.updateAbilityTextForView();
|
||||||
|
}
|
||||||
|
|
||||||
game.fireEvent(new GameEventCardStatsChanged(gameCard));
|
game.fireEvent(new GameEventCardStatsChanged(gameCard));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,6 +123,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private final NavigableMap<Long, CardCloneStates> clonedStates = Maps.newTreeMap();
|
private final NavigableMap<Long, CardCloneStates> clonedStates = Maps.newTreeMap();
|
||||||
private final NavigableMap<Long, CardCloneStates> textChangeStates = Maps.newTreeMap();
|
private final NavigableMap<Long, CardCloneStates> textChangeStates = Maps.newTreeMap();
|
||||||
|
|
||||||
|
private final Map<Long, Integer> canBlockAdditional = Maps.newTreeMap();
|
||||||
|
private final Set<Long> canBlockAny = Sets.newHashSet();
|
||||||
|
|
||||||
// changes that say "replace each instance of one [color,type] by another - timestamp is the key of maps
|
// changes that say "replace each instance of one [color,type] by another - timestamp is the key of maps
|
||||||
private final CardChangedWords changedTextColors = new CardChangedWords();
|
private final CardChangedWords changedTextColors = new CardChangedWords();
|
||||||
@@ -2045,6 +2047,17 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
sb.append("is goaded by: ").append(Lang.joinHomogenous(getGoaded()));
|
sb.append("is goaded by: ").append(Lang.joinHomogenous(getGoaded()));
|
||||||
sb.append("\r\n");
|
sb.append("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// maybe move to CardView for better output
|
||||||
|
if (canBlockAny()) {
|
||||||
|
sb.append("CARDNAME can block any number of creatures.");
|
||||||
|
sb.append("\r\n");
|
||||||
|
} else if (!canBlockAdditional.isEmpty()){
|
||||||
|
sb.append("CARDNAME can block an additional ");
|
||||||
|
sb.append(Lang.nounWithNumeral(canBlockAdditional(), "creature"));
|
||||||
|
sb.append(" creatures each combat.");
|
||||||
|
sb.append("\r\n");
|
||||||
|
}
|
||||||
// replace triple line feeds with double line feeds
|
// replace triple line feeds with double line feeds
|
||||||
int start;
|
int start;
|
||||||
final String s = "\r\n\r\n\r\n";
|
final String s = "\r\n\r\n\r\n";
|
||||||
@@ -6224,4 +6237,35 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
numberTurnActivations.clear();
|
numberTurnActivations.clear();
|
||||||
numberTurnActivationsStatic.clear();
|
numberTurnActivationsStatic.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addCanBlockAdditional(int n, long timestamp) {
|
||||||
|
if (n <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
canBlockAdditional.put(timestamp, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeCanBlockAdditional(long timestamp) {
|
||||||
|
return canBlockAdditional.remove(timestamp) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int canBlockAdditional() {
|
||||||
|
int result = 0;
|
||||||
|
for (Integer v : canBlockAdditional.values()) {
|
||||||
|
result += v;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCanBlockAny(long timestamp) {
|
||||||
|
canBlockAny.add(timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeCanBlockAny(long timestamp) {
|
||||||
|
return canBlockAny.remove(timestamp) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canBlockAny() {
|
||||||
|
return !canBlockAny.isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -581,16 +581,6 @@ public class CardView extends GameEntityView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String nonAbilityText = get(TrackableProperty.NonAbilityText);
|
String nonAbilityText = get(TrackableProperty.NonAbilityText);
|
||||||
int blockAdditional = state.getBlockAdditional();
|
|
||||||
if (blockAdditional > 1) {
|
|
||||||
final StringBuilder ab = new StringBuilder();
|
|
||||||
ab.append("CARDNAME can block an additional ");
|
|
||||||
ab.append(blockAdditional);
|
|
||||||
ab.append(" creatures each combat.");
|
|
||||||
nonAbilityText = nonAbilityText.replaceFirst("CARDNAME can block an additional creature each combat.", ab.toString());
|
|
||||||
nonAbilityText = nonAbilityText.replaceAll("CARDNAME can block an additional creature each combat.", "");
|
|
||||||
nonAbilityText = nonAbilityText.replaceAll("\r\n\r\n\r\n", "");
|
|
||||||
}
|
|
||||||
if (!nonAbilityText.isEmpty()) {
|
if (!nonAbilityText.isEmpty()) {
|
||||||
sb.append("\r\n \r\nNon ability features: \r\n");
|
sb.append("\r\n \r\nNon ability features: \r\n");
|
||||||
sb.append(nonAbilityText.replaceAll("CARDNAME", getName()));
|
sb.append(nonAbilityText.replaceAll("CARDNAME", getName()));
|
||||||
@@ -989,9 +979,6 @@ public class CardView extends GameEntityView {
|
|||||||
return get(TrackableProperty.HasTrample);
|
return get(TrackableProperty.HasTrample);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBlockAdditional() {
|
|
||||||
return get(TrackableProperty.BlockAdditional);
|
|
||||||
}
|
|
||||||
public String getAbilityText() {
|
public String getAbilityText() {
|
||||||
return get(TrackableProperty.AbilityText);
|
return get(TrackableProperty.AbilityText);
|
||||||
}
|
}
|
||||||
@@ -1005,7 +992,6 @@ public class CardView extends GameEntityView {
|
|||||||
set(TrackableProperty.HasInfect, c.hasKeyword(Keyword.INFECT, state));
|
set(TrackableProperty.HasInfect, c.hasKeyword(Keyword.INFECT, state));
|
||||||
set(TrackableProperty.HasStorm, c.hasKeyword(Keyword.STORM, state));
|
set(TrackableProperty.HasStorm, c.hasKeyword(Keyword.STORM, state));
|
||||||
set(TrackableProperty.HasTrample, c.hasKeyword(Keyword.TRAMPLE, state));
|
set(TrackableProperty.HasTrample, c.hasKeyword(Keyword.TRAMPLE, state));
|
||||||
set(TrackableProperty.BlockAdditional, c.getAmountOfKeyword("CARDNAME can block an additional creature each combat.", state));
|
|
||||||
updateAbilityText(c, state);
|
updateAbilityText(c, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -430,20 +430,13 @@ public class CombatUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canBlockMoreCreatures(final Card blocker, final CardCollectionView blockedBy) {
|
public static boolean canBlockMoreCreatures(final Card blocker, final CardCollectionView blockedBy) {
|
||||||
if (blockedBy.isEmpty() || blocker.hasKeyword("CARDNAME can block any number of creatures.")) {
|
if (blockedBy.isEmpty() || blocker.canBlockAny()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int canBlockMore = numberOfAdditionalCreaturesCanBlock(blocker);
|
int canBlockMore = blocker.canBlockAdditional();
|
||||||
return canBlockMore >= blockedBy.size();
|
return canBlockMore >= blockedBy.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int numberOfAdditionalCreaturesCanBlock(final Card blocker) {
|
|
||||||
// If Wizards makes a few more of these, we should really just make a generic version
|
|
||||||
return blocker.getAmountOfKeyword("CARDNAME can block an additional creature each combat.") +
|
|
||||||
blocker.getAmountOfKeyword("CARDNAME can block an additional ninety-nine creatures.") * 99 +
|
|
||||||
blocker.getAmountOfKeyword("CARDNAME can block an additional seven creatures each combat.") * 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
// can the attacker be blocked at all?
|
// can the attacker be blocked at all?
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ public class StaticAbility extends CardTraitBase implements Comparable<StaticAbi
|
|||||||
layers.add(StaticAbilityLayer.RULES);
|
layers.add(StaticAbilityLayer.RULES);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasParam("IgnoreEffectCost") || hasParam("Goad")) {
|
if (hasParam("IgnoreEffectCost") || hasParam("Goad") || hasParam("CanBlockAny") || hasParam("CanBlockAmount")) {
|
||||||
layers.add(StaticAbilityLayer.RULES);
|
layers.add(StaticAbilityLayer.RULES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,6 @@ public final class StaticAbilityContinuous {
|
|||||||
int setPower = Integer.MAX_VALUE;
|
int setPower = Integer.MAX_VALUE;
|
||||||
String setT = "";
|
String setT = "";
|
||||||
int setToughness = Integer.MAX_VALUE;
|
int setToughness = Integer.MAX_VALUE;
|
||||||
int keywordMultiplier = 1;
|
|
||||||
|
|
||||||
String[] addKeywords = null;
|
String[] addKeywords = null;
|
||||||
List<String> addHiddenKeywords = Lists.newArrayList();
|
List<String> addHiddenKeywords = Lists.newArrayList();
|
||||||
@@ -186,16 +185,6 @@ public final class StaticAbilityContinuous {
|
|||||||
toughnessBonus = AbilityUtils.calculateAmount(hostCard, addT, stAb, true);
|
toughnessBonus = AbilityUtils.calculateAmount(hostCard, addT, stAb, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("KeywordMultiplier")) {
|
|
||||||
final String multiplier = params.get("KeywordMultiplier");
|
|
||||||
if (multiplier.equals("X")) {
|
|
||||||
keywordMultiplier = AbilityUtils.calculateAmount(hostCard, "X", stAb);
|
|
||||||
se.setXValue(keywordMultiplier);
|
|
||||||
} else {
|
|
||||||
keywordMultiplier = Integer.valueOf(multiplier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (layer == StaticAbilityLayer.ABILITIES2 && params.containsKey("AddKeyword")) {
|
if (layer == StaticAbilityLayer.ABILITIES2 && params.containsKey("AddKeyword")) {
|
||||||
addKeywords = params.get("AddKeyword").split(" & ");
|
addKeywords = params.get("AddKeyword").split(" & ");
|
||||||
final Iterable<String> chosencolors = hostCard.getChosenColors();
|
final Iterable<String> chosencolors = hostCard.getChosenColors();
|
||||||
@@ -448,9 +437,7 @@ public final class StaticAbilityContinuous {
|
|||||||
|
|
||||||
// add keywords
|
// add keywords
|
||||||
if (addKeywords != null) {
|
if (addKeywords != null) {
|
||||||
for (int i = 0; i < keywordMultiplier; i++) {
|
p.addChangedKeywords(addKeywords, removeKeywords == null ? new String[0] : removeKeywords, se.getTimestamp());
|
||||||
p.addChangedKeywords(addKeywords, removeKeywords == null ? new String[0] : removeKeywords, se.getTimestamp());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add static abilities
|
// add static abilities
|
||||||
@@ -577,9 +564,7 @@ public final class StaticAbilityContinuous {
|
|||||||
// add HIDDEN keywords
|
// add HIDDEN keywords
|
||||||
if (!addHiddenKeywords.isEmpty()) {
|
if (!addHiddenKeywords.isEmpty()) {
|
||||||
for (final String k : addHiddenKeywords) {
|
for (final String k : addHiddenKeywords) {
|
||||||
for (int j = 0; j < keywordMultiplier; j++) {
|
affectedCard.addHiddenExtrinsicKeyword(k);
|
||||||
affectedCard.addHiddenExtrinsicKeyword(k);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -718,8 +703,17 @@ public final class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layer == StaticAbilityLayer.RULES && params.containsKey("Goad")) {
|
if (layer == StaticAbilityLayer.RULES) {
|
||||||
affectedCard.addGoad(se.getTimestamp(), hostCard.getController());
|
if (params.containsKey("Goad")) {
|
||||||
|
affectedCard.addGoad(se.getTimestamp(), hostCard.getController());
|
||||||
|
}
|
||||||
|
if (params.containsKey("CanBlockAny")) {
|
||||||
|
affectedCard.addCanBlockAny(se.getTimestamp());
|
||||||
|
}
|
||||||
|
if (params.containsKey("CanBlockAmount")) {
|
||||||
|
int v = AbilityUtils.calculateAmount(hostCard, params.get("CanBlockAmount"), stAb, true);
|
||||||
|
affectedCard.addCanBlockAdditional(v, se.getTimestamp());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mayLookAt != null) {
|
if (mayLookAt != null) {
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ public enum TrackableProperty {
|
|||||||
HasTrample(TrackableTypes.BooleanType),
|
HasTrample(TrackableTypes.BooleanType),
|
||||||
YouMayLook(TrackableTypes.BooleanType),
|
YouMayLook(TrackableTypes.BooleanType),
|
||||||
OpponentMayLook(TrackableTypes.BooleanType),
|
OpponentMayLook(TrackableTypes.BooleanType),
|
||||||
BlockAdditional(TrackableTypes.IntegerType),
|
|
||||||
AbilityText(TrackableTypes.StringType),
|
AbilityText(TrackableTypes.StringType),
|
||||||
NonAbilityText(TrackableTypes.StringType),
|
NonAbilityText(TrackableTypes.StringType),
|
||||||
FoilIndex(TrackableTypes.IntegerType),
|
FoilIndex(TrackableTypes.IntegerType),
|
||||||
|
|||||||
Reference in New Issue
Block a user