mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 18:28:00 +00:00
Merge branch 'goad' into 'master'
Goad doesn't stack See merge request core-developers/forge!6074
This commit is contained in:
@@ -624,7 +624,7 @@ public class AiAttackController {
|
|||||||
|
|
||||||
// Attempt to see if there's a defined entity that must be attacked strictly this turn...
|
// Attempt to see if there's a defined entity that must be attacked strictly this turn...
|
||||||
GameEntity entity = ai.getMustAttackEntityThisTurn();
|
GameEntity entity = ai.getMustAttackEntityThisTurn();
|
||||||
if (entity == null) {
|
if (nextTurn || entity == null) {
|
||||||
// ...or during the attacking creature controller's turn
|
// ...or during the attacking creature controller's turn
|
||||||
entity = ai.getMustAttackEntity();
|
entity = ai.getMustAttackEntity();
|
||||||
}
|
}
|
||||||
@@ -720,6 +720,7 @@ public class AiAttackController {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
boolean mustAttack = false;
|
boolean mustAttack = false;
|
||||||
|
// TODO for nextTurn check if it was temporary
|
||||||
if (attacker.isGoaded()) {
|
if (attacker.isGoaded()) {
|
||||||
mustAttack = true;
|
mustAttack = true;
|
||||||
} else if (attacker.getSVar("MustAttack").equals("True")) {
|
} else if (attacker.getSVar("MustAttack").equals("True")) {
|
||||||
@@ -736,7 +737,7 @@ public class AiAttackController {
|
|||||||
mustAttack = true;
|
mustAttack = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mustAttack || attacker.getController().getMustAttackEntity() != null || attacker.getController().getMustAttackEntityThisTurn() != null) {
|
if (mustAttack || (attacker.getController().getMustAttackEntity() != null && nextTurn) || (attacker.getController().getMustAttackEntityThisTurn() != null && !nextTurn)) {
|
||||||
combat.addAttacker(attacker, defender);
|
combat.addAttacker(attacker, defender);
|
||||||
attackersLeft.remove(attacker);
|
attackersLeft.remove(attacker);
|
||||||
numForcedAttackers++;
|
numForcedAttackers++;
|
||||||
|
|||||||
@@ -3040,11 +3040,11 @@ public class ComputerUtil {
|
|||||||
public static boolean aiLifeInDanger(Player ai, boolean serious, int payment) {
|
public static boolean aiLifeInDanger(Player ai, boolean serious, int payment) {
|
||||||
// TODO should also consider them as teams
|
// TODO should also consider them as teams
|
||||||
for (Player opponent: ai.getOpponents()) {
|
for (Player opponent: ai.getOpponents()) {
|
||||||
// test whether the human can kill the ai next turn
|
|
||||||
Combat combat = new Combat(opponent);
|
Combat combat = new Combat(opponent);
|
||||||
boolean containsAttacker = false;
|
boolean containsAttacker = false;
|
||||||
|
boolean thisCombat = ai.getGame().getPhaseHandler().isPlayerTurn(opponent) && ai.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_BEGIN);
|
||||||
for (Card att : opponent.getCreaturesInPlay()) {
|
for (Card att : opponent.getCreaturesInPlay()) {
|
||||||
if (ComputerUtilCombat.canAttackNextTurn(att, ai)) {
|
if ((thisCombat && CombatUtil.canAttack(att, ai)) || (!thisCombat && ComputerUtilCombat.canAttackNextTurn(att, ai))) {
|
||||||
combat.addAttacker(att, ai);
|
combat.addAttacker(att, ai);
|
||||||
containsAttacker = true;
|
containsAttacker = true;
|
||||||
}
|
}
|
||||||
@@ -3052,6 +3052,8 @@ public class ComputerUtil {
|
|||||||
if (!containsAttacker) {
|
if (!containsAttacker) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO if it's next turn ignore mustBlockCards
|
||||||
AiBlockController block = new AiBlockController(ai, false);
|
AiBlockController block = new AiBlockController(ai, false);
|
||||||
block.assignBlockersForCombat(combat);
|
block.assignBlockersForCombat(combat);
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ public class GoadAi extends SpellAbilityAi {
|
|||||||
if (ComputerUtilCard.isUselessCreature(ai, c)) {
|
if (ComputerUtilCard.isUselessCreature(ai, c)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// useless
|
||||||
|
if (c.isGoadedBy(ai)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// select creatures which can attack an Opponent other than ai
|
// select creatures which can attack an Opponent other than ai
|
||||||
for (Player o : ai.getOpponents()) {
|
for (Player o : ai.getOpponents()) {
|
||||||
if (ComputerUtilCombat.canAttackNextTurn(c, o)) {
|
if (ComputerUtilCombat.canAttackNextTurn(c, o)) {
|
||||||
@@ -64,6 +68,10 @@ public class GoadAi extends SpellAbilityAi {
|
|||||||
if (ComputerUtilCard.isUselessCreature(ai, c)) {
|
if (ComputerUtilCard.isUselessCreature(ai, c)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// useless
|
||||||
|
if (c.isGoadedBy(ai)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// select only creatures AI can block
|
// select only creatures AI can block
|
||||||
return ComputerUtilCard.canBeBlockedProfitably(ai, c, false);
|
return ComputerUtilCard.canBeBlockedProfitably(ai, c, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ public class GoadEffect extends SpellAbilityEffect {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 701.38d
|
||||||
|
if (tgtC.isGoadedBy(player)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// if pump is a target, make sure we can still target now
|
// if pump is a target, make sure we can still target now
|
||||||
if (sa.usesTargeting() && !sa.getTargetRestrictions().canTgtPlayer() && !tgtC.canBeTargetedBy(sa)) {
|
if (sa.usesTargeting() && !sa.getTargetRestrictions().canTgtPlayer() && !tgtC.canBeTargetedBy(sa)) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class MustAttackEffect extends SpellAbilityEffect {
|
|||||||
// TODO these should not override but add another requirement
|
// TODO these should not override but add another requirement
|
||||||
for (final Player p : tgtPlayers) {
|
for (final Player p : tgtPlayers) {
|
||||||
if ((tgt == null) || p.canBeTargetedBy(sa)) {
|
if ((tgt == null) || p.canBeTargetedBy(sa)) {
|
||||||
if (thisTurn) {
|
if (thisTurn || !p.getGame().getPhaseHandler().isPlayerTurn(p)) {
|
||||||
p.setMustAttackEntityThisTurn(entity);
|
p.setMustAttackEntityThisTurn(entity);
|
||||||
} else {
|
} else {
|
||||||
p.setMustAttackEntity(entity);
|
p.setMustAttackEntity(entity);
|
||||||
|
|||||||
@@ -35,10 +35,6 @@ public class AttackRequirement {
|
|||||||
|
|
||||||
this.causesToAttack = causesToAttack;
|
this.causesToAttack = causesToAttack;
|
||||||
|
|
||||||
final GameEntity mustAttack = attacker.getController().getMustAttackEntity();
|
|
||||||
if (mustAttack != null) {
|
|
||||||
defenderSpecific.add(mustAttack);
|
|
||||||
}
|
|
||||||
final GameEntity mustAttackThisTurn = attacker.getController().getMustAttackEntityThisTurn();
|
final GameEntity mustAttackThisTurn = attacker.getController().getMustAttackEntityThisTurn();
|
||||||
if (mustAttackThisTurn != null) {
|
if (mustAttackThisTurn != null) {
|
||||||
defenderSpecific.add(mustAttackThisTurn);
|
defenderSpecific.add(mustAttackThisTurn);
|
||||||
@@ -47,6 +43,7 @@ public class AttackRequirement {
|
|||||||
int nAttackAnything = 0;
|
int nAttackAnything = 0;
|
||||||
|
|
||||||
if (attacker.isGoaded()) {
|
if (attacker.isGoaded()) {
|
||||||
|
// Goad has two requirements but the other is handled by CombatUtil currently
|
||||||
nAttackAnything += attacker.getGoaded().size();
|
nAttackAnything += attacker.getGoaded().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,11 +67,7 @@ public class AttackRequirement {
|
|||||||
nAttackAnything++;
|
nAttackAnything++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final GameEntity mustAttack3 = attacker.getMustAttackEntity();
|
|
||||||
if (mustAttack3 != null) {
|
|
||||||
defenderSpecific.add(mustAttack3);
|
|
||||||
}
|
|
||||||
final GameEntity mustAttackThisTurn3 = attacker.getMustAttackEntityThisTurn();
|
final GameEntity mustAttackThisTurn3 = attacker.getMustAttackEntityThisTurn();
|
||||||
if (mustAttackThisTurn3 != null) {
|
if (mustAttackThisTurn3 != null) {
|
||||||
defenderSpecific.add(mustAttackThisTurn3);
|
defenderSpecific.add(mustAttackThisTurn3);
|
||||||
|
|||||||
@@ -825,6 +825,7 @@ public class PhaseHandler implements java.io.Serializable {
|
|||||||
private Player handleNextTurn() {
|
private Player handleNextTurn() {
|
||||||
game.getStack().onNextTurn();
|
game.getStack().onNextTurn();
|
||||||
// reset mustAttackEntity
|
// reset mustAttackEntity
|
||||||
|
playerTurn.setMustAttackEntityThisTurn(playerTurn.getMustAttackEntity());
|
||||||
playerTurn.setMustAttackEntity(null);
|
playerTurn.setMustAttackEntity(null);
|
||||||
|
|
||||||
game.getTriggerHandler().clearThisTurnDelayedTrigger();
|
game.getTriggerHandler().clearThisTurnDelayedTrigger();
|
||||||
|
|||||||
@@ -906,7 +906,7 @@ public final class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add Types
|
// add Types
|
||||||
if ((addTypes != null) || (removeTypes != null) || addAllCreatureTypes
|
if (addTypes != null || removeTypes != null || addAllCreatureTypes
|
||||||
|| removeSuperTypes || removeCardTypes || removeLandTypes || removeCreatureTypes || removeArtifactTypes || removeEnchantmentTypes) {
|
|| removeSuperTypes || removeCardTypes || removeLandTypes || removeCreatureTypes || removeArtifactTypes || removeEnchantmentTypes) {
|
||||||
affectedCard.addChangedCardTypes(addTypes, removeTypes, addAllCreatureTypes, removeSuperTypes, removeCardTypes, removeSubTypes,
|
affectedCard.addChangedCardTypes(addTypes, removeTypes, addAllCreatureTypes, removeSuperTypes, removeCardTypes, removeSubTypes,
|
||||||
removeLandTypes, removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes,
|
removeLandTypes, removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes,
|
||||||
@@ -919,7 +919,7 @@ public final class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (layer == StaticAbilityLayer.RULES) {
|
if (layer == StaticAbilityLayer.RULES) {
|
||||||
if (params.containsKey("Goad")) {
|
if (params.containsKey("Goad") && !affectedCard.isGoadedBy(hostCard.getController())) {
|
||||||
affectedCard.addGoad(se.getTimestamp(), hostCard.getController());
|
affectedCard.addGoad(se.getTimestamp(), hostCard.getController());
|
||||||
}
|
}
|
||||||
if (params.containsKey("CanBlockAny")) {
|
if (params.containsKey("CanBlockAny")) {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ Name:Avalanche Tusker
|
|||||||
ManaCost:2 G U R
|
ManaCost:2 G U R
|
||||||
Types:Creature Elephant Warrior
|
Types:Creature Elephant Warrior
|
||||||
PT:6/4
|
PT:6/4
|
||||||
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigCantBlock | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, target creature defending player controls blocks this combat if able.
|
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigCantBlock | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, target creature defending player controls blocks it this combat if able.
|
||||||
SVar:TrigCantBlock:DB$ MustBlock | ValidTgts$ Creature.DefenderCtrl | TgtPrompt$ Select target creature | SpellDescription$ Target creature blocks CARDNAME this turn if able.
|
SVar:TrigCantBlock:DB$ MustBlock | ValidTgts$ Creature.DefenderCtrl | TgtPrompt$ Select target creature
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/avalanche_tusker.jpg
|
|
||||||
Oracle:Whenever Avalanche Tusker attacks, target creature defending player controls blocks it this combat if able.
|
Oracle:Whenever Avalanche Tusker attacks, target creature defending player controls blocks it this combat if able.
|
||||||
|
|||||||
@@ -5,10 +5,9 @@ PT:6/1
|
|||||||
K:Haste
|
K:Haste
|
||||||
K:Trample
|
K:Trample
|
||||||
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigProvoke | TriggerDescription$ When CARDNAME attacks, up to one target creature defending player controls blocks it this combat if able.
|
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigProvoke | TriggerDescription$ When CARDNAME attacks, up to one target creature defending player controls blocks it this combat if able.
|
||||||
SVar:TrigProvoke:DB$ MustBlock | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature.DefenderCtrl | Duration$ UntilEndOfCombat | TgtPrompt$ Select up to one target creature defending player controls
|
SVar:TrigProvoke:DB$ MustBlock | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature.DefenderCtrl | TgtPrompt$ Select up to one target creature defending player controls
|
||||||
T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | Execute$ TrigSac | TriggerDescription$ At the beginning of the end step, sacrifice CARDNAME.
|
T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | Execute$ TrigSac | TriggerDescription$ At the beginning of the end step, sacrifice CARDNAME.
|
||||||
SVar:TrigSac:DB$ Sacrifice | SacValid$ Self
|
SVar:TrigSac:DB$ Sacrifice | SacValid$ Self
|
||||||
SVar:EndOfTurnLeavePlay:True
|
SVar:EndOfTurnLeavePlay:True
|
||||||
SVar:PlayMain1:TRUE
|
SVar:PlayMain1:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/impetuous_devils.jpg
|
|
||||||
Oracle:Trample, haste\nWhen Impetuous Devils attacks, up to one target creature defending player controls blocks it this combat if able.\nAt the beginning of the end step, sacrifice Impetuous Devils.
|
Oracle:Trample, haste\nWhen Impetuous Devils attacks, up to one target creature defending player controls blocks it this combat if able.\nAt the beginning of the end step, sacrifice Impetuous Devils.
|
||||||
|
|||||||
Reference in New Issue
Block a user