mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
- DelayedTriggerAi: port over AILogic NarsetRebound and SpellCopy (the latter doesn't quite work yet and the spell somehow magically fizzles with no trace).
This commit is contained in:
committed by
Michael Kamensky
parent
d5639f5395
commit
9b040b063b
@@ -38,7 +38,6 @@ import forge.game.player.Player;
|
||||
import forge.game.player.PlayerController;
|
||||
import forge.game.spellability.*;
|
||||
import forge.game.zone.Zone;
|
||||
import forge.util.collect.FCollection;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -151,7 +150,7 @@ public class HumanPlaySpellAbility {
|
||||
// is only executed or evaluated if the first argument does not suffice to determine the value of the expression
|
||||
final boolean prerequisitesMet = announceValuesLikeX()
|
||||
&& announceType()
|
||||
&& (!mayChooseTargets || setupTargets()) // if you can choose targets, then do choose them.
|
||||
&& (!mayChooseTargets || ability.setupTargets()) // if you can choose targets, then do choose them.
|
||||
&& (isFree || payment.payCost(new HumanCostDecision(controller, human, ability, ability.getHostCard())));
|
||||
|
||||
if (!prerequisitesMet) {
|
||||
@@ -190,7 +189,7 @@ public class HumanPlaySpellAbility {
|
||||
// no worries here. The same thread must resolve, and by this moment ability will have been resolved already
|
||||
// Triggers haven't resolved yet ??
|
||||
if (mayChooseTargets) {
|
||||
clearTargets(ability);
|
||||
ability.clearTargets();
|
||||
}
|
||||
if (manaTypeConversion || manaColorConversion || keywordColor) {
|
||||
manapool.restoreColorReplacements();
|
||||
@@ -199,47 +198,6 @@ public class HumanPlaySpellAbility {
|
||||
return true;
|
||||
}
|
||||
|
||||
private final boolean setupTargets() {
|
||||
// Skip to paying if parent ability doesn't target and has no subAbilities.
|
||||
// (or trigger case where its already targeted)
|
||||
SpellAbility currentAbility = ability;
|
||||
final Card source = ability.getHostCard();
|
||||
do {
|
||||
final TargetRestrictions tgt = currentAbility.getTargetRestrictions();
|
||||
if (tgt != null && tgt.doesTarget()) {
|
||||
clearTargets(currentAbility);
|
||||
Player targetingPlayer;
|
||||
if (currentAbility.hasParam("TargetingPlayer")) {
|
||||
final FCollection<Player> candidates = AbilityUtils.getDefinedPlayers(source, currentAbility.getParam("TargetingPlayer"), currentAbility);
|
||||
// activator chooses targeting player
|
||||
targetingPlayer = ability.getActivatingPlayer().getController().chooseSingleEntityForEffect(
|
||||
candidates, currentAbility, "Choose the targeting player", null);
|
||||
} else {
|
||||
targetingPlayer = ability.getActivatingPlayer();
|
||||
}
|
||||
currentAbility.setTargetingPlayer(targetingPlayer);
|
||||
if (!targetingPlayer.getController().chooseTargetsFor(currentAbility)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
final AbilitySub subAbility = currentAbility.getSubAbility();
|
||||
if (subAbility != null) {
|
||||
// This is necessary for "TargetsWithDefinedController$ ParentTarget"
|
||||
subAbility.setParent(currentAbility);
|
||||
}
|
||||
currentAbility = subAbility;
|
||||
} while (currentAbility != null);
|
||||
return true;
|
||||
}
|
||||
|
||||
public final void clearTargets(final SpellAbility ability) {
|
||||
final TargetRestrictions tg = ability.getTargetRestrictions();
|
||||
if (tg != null) {
|
||||
ability.resetTargets();
|
||||
tg.calculateStillToDivide(ability.getParam("DividedAsYouChoose"), ability.getHostCard(), ability);
|
||||
}
|
||||
}
|
||||
|
||||
private void rollbackAbility(final Zone fromZone, final int zonePosition, CostPayment payment) {
|
||||
// cancel ability during target choosing
|
||||
final Game game = ability.getActivatingPlayer().getGame();
|
||||
@@ -251,7 +209,7 @@ public class HumanPlaySpellAbility {
|
||||
game.getAction().moveTo(fromZone, ability.getHostCard(), zonePosition >= 0 ? Integer.valueOf(zonePosition) : null, null);
|
||||
}
|
||||
|
||||
clearTargets(ability);
|
||||
ability.clearTargets();
|
||||
|
||||
ability.resetOnceResolved();
|
||||
payment.refundPayment();
|
||||
|
||||
@@ -1671,7 +1671,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
List<SpellAbility> orderedSAs = activePlayerSAs;
|
||||
if (activePlayerSAs.size() > 1) {
|
||||
final String firstStr = activePlayerSAs.get(0).toString();
|
||||
boolean needPrompt = false;
|
||||
boolean needPrompt = !activePlayerSAs.get(0).isTrigger();
|
||||
|
||||
// for the purpose of pre-ordering, no need for extra granularity
|
||||
Integer idxAdditionalInfo = firstStr.indexOf(" [");
|
||||
@@ -1682,6 +1682,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
SpellAbility currentSa = activePlayerSAs.get(i);
|
||||
String saStr = currentSa.toString();
|
||||
|
||||
// if current SA isn't a trigger and it uses Targeting, try to show prompt
|
||||
if (!currentSa.isTrigger() && currentSa.usesTargeting()) {
|
||||
needPrompt = true;
|
||||
}
|
||||
if (!needPrompt && !saStr.equals(firstStr)) {
|
||||
needPrompt = true; // prompt by default unless all abilities
|
||||
// are the same
|
||||
@@ -1738,6 +1742,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
if (next.isTrigger()) {
|
||||
HumanPlay.playSpellAbility(this, player, next);
|
||||
} else {
|
||||
if (next.isCopied()) {
|
||||
// copied spell always add to stack
|
||||
player.getGame().getStackZone().add(next.getHostCard());
|
||||
// TODO check if static abilities needs to be run for things affecting the copy?
|
||||
if (next.isMayChooseNewTargets() && !next.setupTargets()) {
|
||||
// if targets can't be done, remove copy from existence
|
||||
next.getHostCard().ceaseToExist();
|
||||
}
|
||||
}
|
||||
player.getGame().getStack().add(next);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user