mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
AI: Fix counters calculation for Wildborn Preserver activation (#3119)
* - Remove legacy hacky code that's apparently not needed anymore. * - Fix imports. * - Restore the original code but tweak it to hopefully accomodate for Wildborn Preserver. * - Clean up / clarify. * Remove fake SVar --------- Co-authored-by: tool4EvEr <tool4EvEr@192.168.0.59>
This commit is contained in:
@@ -1,43 +1,18 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import forge.ai.*;
|
||||||
import forge.ai.AiCardMemory;
|
|
||||||
import forge.ai.AiProps;
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilAbility;
|
|
||||||
import forge.ai.ComputerUtilCard;
|
|
||||||
import forge.ai.ComputerUtilCombat;
|
|
||||||
import forge.ai.ComputerUtilCost;
|
|
||||||
import forge.ai.PlayerControllerAi;
|
|
||||||
import forge.ai.SpecialAiLogic;
|
|
||||||
import forge.ai.SpecialCardAi;
|
|
||||||
import forge.ai.SpellAbilityAi;
|
|
||||||
import forge.card.CardStateName;
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPredicates;
|
|
||||||
import forge.game.card.CounterEnumType;
|
|
||||||
import forge.game.card.CounterType;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.*;
|
||||||
import forge.game.cost.CostPart;
|
|
||||||
import forge.game.cost.CostPutCounter;
|
|
||||||
import forge.game.cost.CostRemoveCounter;
|
|
||||||
import forge.game.cost.CostSacrifice;
|
|
||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
@@ -54,6 +29,10 @@ import forge.game.zone.ZoneType;
|
|||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class CountersPutAi extends CountersAi {
|
public class CountersPutAi extends CountersAi {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -774,38 +753,17 @@ public class CountersPutAi extends CountersAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!sa.usesTargeting()) {
|
if (!sa.usesTargeting()) {
|
||||||
// No target. So must be defined
|
// No target. So must be defined. (Unused at the moment)
|
||||||
list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
|
// list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
|
||||||
|
|
||||||
if (amountStr.equals("X")
|
if (amountStr.equals("X")
|
||||||
&& root.getXManaCostPaid() == null
|
&& root.getXManaCostPaid() == null
|
||||||
&& source.getXManaCostPaid() == 0 /* SubAbility on something that already had set PayX, e.g. Endless One ETB counters */
|
&& source.getXManaCostPaid() == 0 // SubAbility on something that already had set PayX, e.g. Endless One ETB counters
|
||||||
|
&& amount == 0 // And counter amount wasn't set previously by something (e.g. Wildborn Preserver)
|
||||||
&& sa.hasSVar(amountStr) && sa.getSVar(amountStr).equals("Count$xPaid")) {
|
&& sa.hasSVar(amountStr) && sa.getSVar(amountStr).equals("Count$xPaid")) {
|
||||||
|
|
||||||
// detect if there's more than one X in the cost (Hangarback Walker, Walking Ballista, etc.)
|
|
||||||
SpellAbility testSa = sa;
|
|
||||||
int countX = 0;
|
|
||||||
int nonXGlyphs = 0;
|
|
||||||
while (testSa != null && countX == 0) {
|
|
||||||
countX = testSa.getPayCosts().getTotalMana().countX();
|
|
||||||
nonXGlyphs = testSa.getPayCosts().getTotalMana().getGlyphCount() - countX;
|
|
||||||
testSa = testSa.getSubAbility();
|
|
||||||
}
|
|
||||||
if (countX == 0) {
|
|
||||||
// try determining it from the card itself if neither SA has "X" in the cost
|
|
||||||
countX = source.getState(CardStateName.Original).getManaCost().countX();
|
|
||||||
nonXGlyphs = source.getState(CardStateName.Original).getManaCost().getGlyphCount() - countX;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spend all remaining mana to add X counters (eg. Hero of Leina Tower)
|
// Spend all remaining mana to add X counters (eg. Hero of Leina Tower)
|
||||||
int payX = ComputerUtilCost.getMaxXValue(sa, ai, true);
|
int payX = ComputerUtilCost.getMaxXValue(sa, ai, true);
|
||||||
|
|
||||||
// Account for the possible presence of additional glyphs in cost (e.g. Mikaeus, the Lunarch; Primordial Hydra)
|
|
||||||
payX -= nonXGlyphs;
|
|
||||||
|
|
||||||
// Account for the multiple X in cost
|
|
||||||
if (countX > 1) { payX /= countX; }
|
|
||||||
|
|
||||||
root.setXManaCostPaid(payX);
|
root.setXManaCostPaid(payX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,17 +36,11 @@ public class ImmediateTriggerAi extends SpellAbilityAi {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String logic = sa.getParamOrDefault("AILogic", "");
|
|
||||||
|
|
||||||
SpellAbility trigsa = sa.getAdditionalAbility("Execute");
|
SpellAbility trigsa = sa.getAdditionalAbility("Execute");
|
||||||
if (trigsa == null) {
|
if (trigsa == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logic.equals("MaxX")) {
|
|
||||||
sa.setXManaCostPaid(ComputerUtilCost.getMaxXValue(sa, ai, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
||||||
trigsa.setActivatingPlayer(ai, true);
|
trigsa.setActivatingPlayer(ai, true);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,5 @@ Types:Sorcery
|
|||||||
A:SP$ Token | Cost$ X W B | TokenAmount$ X | TokenScript$ wb_2_1_inkling_flying | TokenTapped$ True | SubAbility$ BlotDestroy | SpellDescription$ Create X tapped 2/1 white and black Inkling creature tokens with flying. If X is 6 or more, destroy all noncreature, nonland permanents.
|
A:SP$ Token | Cost$ X W B | TokenAmount$ X | TokenScript$ wb_2_1_inkling_flying | TokenTapped$ True | SubAbility$ BlotDestroy | SpellDescription$ Create X tapped 2/1 white and black Inkling creature tokens with flying. If X is 6 or more, destroy all noncreature, nonland permanents.
|
||||||
SVar:BlotDestroy:DB$ DestroyAll | ValidCards$ Permanent.nonCreature+nonLand | ConditionCheckSVar$ X | ConditionSVarCompare$ GE6
|
SVar:BlotDestroy:DB$ DestroyAll | ValidCards$ Permanent.nonCreature+nonLand | ConditionCheckSVar$ X | ConditionSVarCompare$ GE6
|
||||||
SVar:X:Count$xPaid
|
SVar:X:Count$xPaid
|
||||||
SVar:PayX:6
|
|
||||||
DeckHas:Ability$Token
|
DeckHas:Ability$Token
|
||||||
Oracle:Create X tapped 2/1 white and black Inkling creature tokens with flying. If X is 6 or more, destroy all noncreature, nonland permanents.
|
Oracle:Create X tapped 2/1 white and black Inkling creature tokens with flying. If X is 6 or more, destroy all noncreature, nonland permanents.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ Types:Enchantment Creature Dragon Spirit
|
|||||||
PT:2/2
|
PT:2/2
|
||||||
K:Flying
|
K:Flying
|
||||||
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Creature.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigImmediateTrig | TriggerDescription$ Whenever another creature enters the battlefield under your control, you may pay {X}. When you do, put X +1/+1 counters on that creature.
|
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Creature.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigImmediateTrig | TriggerDescription$ Whenever another creature enters the battlefield under your control, you may pay {X}. When you do, put X +1/+1 counters on that creature.
|
||||||
SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ X | Execute$ TrigPutCounter | RememberObjects$ TriggeredCardLKICopy | AILogic$ MaxX | TriggerDescription$ When you do, put X +1/+1 counters on that creature.
|
SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ X | Execute$ TrigPutCounter | RememberObjects$ TriggeredCardLKICopy | TriggerDescription$ When you do, put X +1/+1 counters on that creature.
|
||||||
SVar:TrigPutCounter:DB$ PutCounter | Defined$ DelayTriggerRememberedLKI | CounterType$ P1P1 | CounterNum$ X
|
SVar:TrigPutCounter:DB$ PutCounter | Defined$ DelayTriggerRememberedLKI | CounterType$ P1P1 | CounterNum$ X
|
||||||
S:Mode$ Continuous | IsPresent$ Creature.modified+YouCtrl | PresentCompare$ GE5 | Affected$ Card.Self | AddPower$ 5 | AddToughness$ 5 | AddKeyword$ Trample | Description$ As long as you control five or more modified creatures, CARDNAME gets +5/+5 and has trample.
|
S:Mode$ Continuous | IsPresent$ Creature.modified+YouCtrl | PresentCompare$ GE5 | Affected$ Card.Self | AddPower$ 5 | AddToughness$ 5 | AddKeyword$ Trample | Description$ As long as you control five or more modified creatures, CARDNAME gets +5/+5 and has trample.
|
||||||
SVar:X:Count$xPaid
|
SVar:X:Count$xPaid
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ A:SP$ Token | Cost$ X W W | TokenAmount$ X | TokenScript$ w_1_1_soldier | Rememb
|
|||||||
SVar:CoupDestroy:DB$ DestroyAll | ValidCards$ Creature.IsNotRemembered | ConditionCheckSVar$ X | ConditionSVarCompare$ GE5 | SubAbility$ DBCleanup
|
SVar:CoupDestroy:DB$ DestroyAll | ValidCards$ Creature.IsNotRemembered | ConditionCheckSVar$ X | ConditionSVarCompare$ GE5 | SubAbility$ DBCleanup
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
SVar:X:Count$xPaid
|
SVar:X:Count$xPaid
|
||||||
SVar:PayX:5
|
|
||||||
SVar:NeedsToPlayVar:OwnCreats LEOppCreats
|
SVar:NeedsToPlayVar:OwnCreats LEOppCreats
|
||||||
SVar:OwnCreats:Count$SumPower_Creature.YouCtrl
|
SVar:OwnCreats:Count$SumPower_Creature.YouCtrl
|
||||||
SVar:OppCreats:Count$SumPower_Creature.OppCtrl
|
SVar:OppCreats:Count$SumPower_Creature.OppCtrl
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ PT:2/2
|
|||||||
K:Flash
|
K:Flash
|
||||||
K:Reach
|
K:Reach
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.nonHuman+Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigImmediateTrig | TriggerDescription$ Whenever another non-Human creature enters the battlefield under your control, you may pay {X}. When you do, put X +1/+1 counters on CARDNAME.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.nonHuman+Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigImmediateTrig | TriggerDescription$ Whenever another non-Human creature enters the battlefield under your control, you may pay {X}. When you do, put X +1/+1 counters on CARDNAME.
|
||||||
SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ X | Execute$ TrigPutCounter | AILogic$ MaxX | TriggerDescription$ When you do, put X +1/+1 counters on CARDNAME.
|
SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ X | Execute$ TrigPutCounter | TriggerDescription$ When you do, put X +1/+1 counters on CARDNAME.
|
||||||
SVar:X:Count$xPaid
|
SVar:X:Count$xPaid
|
||||||
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ X
|
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ X
|
||||||
DeckHas:Ability$Counters
|
DeckHas:Ability$Counters
|
||||||
|
|||||||
Reference in New Issue
Block a user