mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
Merge branch 'season_of_the_witch' into 'master'
Add Season of the Witch See merge request core-developers/forge!4173
This commit is contained in:
@@ -682,6 +682,8 @@ public class AiAttackController {
|
||||
final boolean bAssault = this.doAssault(ai);
|
||||
// TODO: detect Lightmine Field by presence of a card with a specific trigger
|
||||
final boolean lightmineField = ComputerUtilCard.isPresentOnBattlefield(ai.getGame(), "Lightmine Field");
|
||||
// TODO: detect Season of the Witch by presence of a card with a specific trigger
|
||||
final boolean seasonOfTheWitch = ComputerUtilCard.isPresentOnBattlefield(ai.getGame(), "Season of the Witch");
|
||||
|
||||
// Determine who will be attacked
|
||||
GameEntity defender = this.chooseDefender(combat, bAssault);
|
||||
@@ -715,6 +717,9 @@ public class AiAttackController {
|
||||
} else if (attacker.hasSVar("EndOfTurnLeavePlay")
|
||||
&& isEffectiveAttacker(ai, attacker, combat)) {
|
||||
mustAttack = true;
|
||||
} else if (seasonOfTheWitch) {
|
||||
// TODO: if there are other ways to tap this creature (like mana creature), then don't need to attack
|
||||
mustAttack = true;
|
||||
} else {
|
||||
for (KeywordInterface inst : attacker.getKeywords()) {
|
||||
String s = inst.getOriginal();
|
||||
|
||||
@@ -17,6 +17,7 @@ import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.combat.AttackingBand;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.mana.Mana;
|
||||
import forge.game.player.Player;
|
||||
@@ -1622,6 +1623,9 @@ public class CardProperty {
|
||||
if (band == null || !band.getAttackers().contains(card)) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("couldAttackButNotAttacking")) {
|
||||
if (!game.getPhaseHandler().isPlayerTurn(controller)) return false;
|
||||
return CombatUtil.couldAttackButNotAttacking(combat, card);
|
||||
} else if (property.startsWith("kicked")) {
|
||||
if (property.equals("kicked")) {
|
||||
if (card.getKickerMagnitude() == 0) {
|
||||
|
||||
@@ -45,6 +45,7 @@ import forge.util.collect.FCollectionView;
|
||||
import forge.util.maps.MapToAmount;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -82,6 +83,38 @@ public class CombatUtil {
|
||||
return myViolations <= bestAttack.getRight().intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if attacker could attack without violating any constraints.
|
||||
*/
|
||||
public static boolean couldAttackButNotAttacking(Combat combat, final Card attacker) {
|
||||
// If the player didn't declare attackers, combat here will be null
|
||||
if (combat == null) {
|
||||
combat = new Combat(attacker.getController());
|
||||
} else if (combat.isAttacking(attacker)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final AttackConstraints constraints = combat.getAttackConstraints();
|
||||
final Pair<Map<Card, GameEntity>, Integer> bestAttack = constraints.getLegalAttackers();
|
||||
final Map<Card, GameEntity> attackers = new HashMap<>(combat.getAttackersAndDefenders());
|
||||
final Game game = attacker.getGame();
|
||||
|
||||
return Iterables.any(getAllPossibleDefenders(attacker.getController()), new Predicate<GameEntity>() {
|
||||
@Override
|
||||
public boolean apply(final GameEntity defender) {
|
||||
if (!canAttack(attacker, defender) || getAttackCost(game, attacker, defender) != null) {
|
||||
return false;
|
||||
}
|
||||
attackers.put(attacker, defender);
|
||||
final int myViolations = constraints.countViolations(attackers);
|
||||
if (myViolations == -1) {
|
||||
return false;
|
||||
}
|
||||
return myViolations <= bestAttack.getRight().intValue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Check whether a player should be given the chance to attack this combat.
|
||||
|
||||
13
forge-gui/res/cardsfolder/s/season_of_the_witch.txt
Normal file
13
forge-gui/res/cardsfolder/s/season_of_the_witch.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Name:Season of the Witch
|
||||
ManaCost:B B B
|
||||
Types:Enchantment
|
||||
K:UpkeepCost:PayLife<2>
|
||||
T:Mode$ Phase | Mode$ Phase | Phase$ Declare Attackers | Execute$ TrigMarkCouldAttack | Static$ True
|
||||
SVar:TrigMarkCouldAttack:DB$ PumpAll | ValidCards$ Creature.couldAttackButNotAttacking | RememberAllPumped$ True
|
||||
T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | Execute$ TrigDestroyAll | TriggerDescription$ At the beginning of the end step, destroy all untapped creatures that didn't attack this turn, except for creatures that couldn't attack.
|
||||
SVar:TrigDestroyAll:DB$ DestroyAll | ValidCards$ Creature.untapped+IsRemembered
|
||||
T:Mode$ Phase | Phase$ Cleanup | Execute$ TrigCleanup | Static$ True
|
||||
SVar:TrigCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
SVar:NonStackingEffect:True
|
||||
AI:RemoveDeck:Random
|
||||
Oracle:At the beginning of your upkeep, sacrifice Season of the Witch unless you pay 2 life.\nAt the beginning of the end step, destroy all untapped creatures that didn't attack this turn, except for creatures that couldn't attack.
|
||||
Reference in New Issue
Block a user