mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
Merge branch 'master' of https://git.cardforge.org/core-developers/forge
This commit is contained in:
@@ -8,7 +8,6 @@ import forge.game.GameEntity;
|
|||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.ability.effects.TokenEffect;
|
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
@@ -61,20 +60,9 @@ public class TokenAi extends SpellAbilityAi {
|
|||||||
private void readParameters(final SpellAbility mapParams) {
|
private void readParameters(final SpellAbility mapParams) {
|
||||||
this.tokenAmount = mapParams.getParamOrDefault("TokenAmount", "1");
|
this.tokenAmount = mapParams.getParamOrDefault("TokenAmount", "1");
|
||||||
|
|
||||||
TokenEffect effect = new TokenEffect();
|
this.actualToken = TokenInfo.getProtoType(mapParams.getParam("TokenScript"), mapParams);
|
||||||
|
|
||||||
this.actualToken = effect.loadTokenPrototype(mapParams);
|
|
||||||
|
|
||||||
if (actualToken == null) {
|
if (actualToken == null) {
|
||||||
String[] keywords;
|
|
||||||
|
|
||||||
if (mapParams.hasParam("TokenKeywords")) {
|
|
||||||
// TODO: Change this Split to a semicolon or something else
|
|
||||||
keywords = mapParams.getParam("TokenKeywords").split("<>");
|
|
||||||
} else {
|
|
||||||
keywords = new String[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tokenPower = mapParams.getParam("TokenPower");
|
this.tokenPower = mapParams.getParam("TokenPower");
|
||||||
this.tokenToughness = mapParams.getParam("TokenToughness");
|
this.tokenToughness = mapParams.getParam("TokenToughness");
|
||||||
} else {
|
} else {
|
||||||
@@ -394,6 +382,7 @@ public class TokenAi extends SpellAbilityAi {
|
|||||||
* @param sa Token SpellAbility
|
* @param sa Token SpellAbility
|
||||||
* @return token creature created by ability
|
* @return token creature created by ability
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static Card spawnToken(Player ai, SpellAbility sa) {
|
public static Card spawnToken(Player ai, SpellAbility sa) {
|
||||||
return spawnToken(ai, sa, false);
|
return spawnToken(ai, sa, false);
|
||||||
}
|
}
|
||||||
@@ -406,9 +395,17 @@ public class TokenAi extends SpellAbilityAi {
|
|||||||
* @return token creature created by ability
|
* @return token creature created by ability
|
||||||
*/
|
*/
|
||||||
// TODO Is this just completely copied from TokenEffect? Let's just call that thing
|
// TODO Is this just completely copied from TokenEffect? Let's just call that thing
|
||||||
|
@Deprecated
|
||||||
public static Card spawnToken(Player ai, SpellAbility sa, boolean notNull) {
|
public static Card spawnToken(Player ai, SpellAbility sa, boolean notNull) {
|
||||||
final Card host = sa.getHostCard();
|
final Card host = sa.getHostCard();
|
||||||
|
|
||||||
|
Card result = TokenInfo.getProtoType(sa.getParam("TokenScript"), sa);
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
result.setController(ai, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
String[] tokenKeywords = sa.hasParam("TokenKeywords") ? sa.getParam("TokenKeywords").split("<>") : new String[0];
|
String[] tokenKeywords = sa.hasParam("TokenKeywords") ? sa.getParam("TokenKeywords").split("<>") : new String[0];
|
||||||
String tokenPower = sa.getParam("TokenPower");
|
String tokenPower = sa.getParam("TokenPower");
|
||||||
String tokenToughness = sa.getParam("TokenToughness");
|
String tokenToughness = sa.getParam("TokenToughness");
|
||||||
|
|||||||
@@ -147,13 +147,6 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cards returned from exile face-down must be reset to their original state, otherwise
|
|
||||||
// all sort of funky shenanigans may happen later (e.g. their ETB replacement effects are set
|
|
||||||
// up on the wrong card state etc.).
|
|
||||||
if (wasFacedown && (fromBattlefield || (toHand && zoneFrom.is(ZoneType.Exile)))) {
|
|
||||||
c.setState(CardStateName.Original, true);
|
|
||||||
c.runFaceupCommands();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up the temporary Dash SVar when the Dashed card leaves the battlefield
|
// Clean up the temporary Dash SVar when the Dashed card leaves the battlefield
|
||||||
// Clean up the temporary AtEOT SVar
|
// Clean up the temporary AtEOT SVar
|
||||||
@@ -191,6 +184,14 @@ public class GameAction {
|
|||||||
lastKnownInfo = CardUtil.getLKICopy(c);
|
lastKnownInfo = CardUtil.getLKICopy(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cards returned from exile face-down must be reset to their original state, otherwise
|
||||||
|
// all sort of funky shenanigans may happen later (e.g. their ETB replacement effects are set
|
||||||
|
// up on the wrong card state etc.).
|
||||||
|
if (wasFacedown && (fromBattlefield || (toHand && zoneFrom.is(ZoneType.Exile)))) {
|
||||||
|
c.setState(CardStateName.Original, true);
|
||||||
|
c.runFaceupCommands();
|
||||||
|
}
|
||||||
|
|
||||||
if (!c.isToken()) {
|
if (!c.isToken()) {
|
||||||
if (c.isCloned()) {
|
if (c.isCloned()) {
|
||||||
c.switchStates(CardStateName.Original, CardStateName.Cloner, false);
|
c.switchStates(CardStateName.Original, CardStateName.Cloner, false);
|
||||||
@@ -215,15 +216,15 @@ public class GameAction {
|
|||||||
c.updateStateForView();
|
c.updateStateForView();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fromBattlefield && c.getCurrentStateName() != CardStateName.Original) {
|
copied = CardFactory.copyCard(c, false);
|
||||||
|
|
||||||
|
if (fromBattlefield && copied.getCurrentStateName() != CardStateName.Original) {
|
||||||
// when a card leaves the battlefield, ensure it's in its original state
|
// when a card leaves the battlefield, ensure it's in its original state
|
||||||
// (we need to do this on the object before copying it, or it won't work correctly e.g.
|
// (we need to do this on the object before copying it, or it won't work correctly e.g.
|
||||||
// on Transformed objects)
|
// on Transformed objects)
|
||||||
c.setState(CardStateName.Original, false);
|
copied.setState(CardStateName.Original, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
copied = CardFactory.copyCard(c, false);
|
|
||||||
|
|
||||||
copied.setUnearthed(c.isUnearthed());
|
copied.setUnearthed(c.isUnearthed());
|
||||||
copied.setTapped(false);
|
copied.setTapped(false);
|
||||||
|
|
||||||
@@ -250,11 +251,10 @@ public class GameAction {
|
|||||||
// special rule for Worms of the Earth
|
// special rule for Worms of the Earth
|
||||||
if (toBattlefield && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noLandBattlefield)) {
|
if (toBattlefield && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noLandBattlefield)) {
|
||||||
// something that is already a Land cant enter the battlefield
|
// something that is already a Land cant enter the battlefield
|
||||||
if (c.isLand()) {
|
Card noLandLKI = c;
|
||||||
return c;
|
if (!c.isLand()) {
|
||||||
}
|
|
||||||
// check if something would be a land
|
// check if something would be a land
|
||||||
Card noLandLKI = CardUtil.getLKICopy(c);
|
noLandLKI = CardUtil.getLKICopy(c);
|
||||||
// this check needs to check if this card would be on the battlefield
|
// this check needs to check if this card would be on the battlefield
|
||||||
noLandLKI.setLastKnownZone(zoneTo);
|
noLandLKI.setLastKnownZone(zoneTo);
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ public class GameAction {
|
|||||||
checkStaticAbilities(false, Sets.newHashSet(noLandLKI), preList);
|
checkStaticAbilities(false, Sets.newHashSet(noLandLKI), preList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(noLandLKI.isLand()) {
|
if(noLandLKI.isLand()) {
|
||||||
// if it isn't on the Stack, it stays in that Zone
|
// if it isn't on the Stack, it stays in that Zone
|
||||||
if (!c.getZone().is(ZoneType.Stack)) {
|
if (!c.getZone().is(ZoneType.Stack)) {
|
||||||
@@ -278,6 +278,7 @@ public class GameAction {
|
|||||||
// if something would only be a land when entering the battlefield and not before
|
// if something would only be a land when entering the battlefield and not before
|
||||||
// put it into the graveyard instead
|
// put it into the graveyard instead
|
||||||
zoneTo = c.getOwner().getZone(ZoneType.Graveyard);
|
zoneTo = c.getOwner().getZone(ZoneType.Graveyard);
|
||||||
|
|
||||||
// reset facedown
|
// reset facedown
|
||||||
copied.setState(CardStateName.Original, false);
|
copied.setState(CardStateName.Original, false);
|
||||||
copied.setManifested(false);
|
copied.setManifested(false);
|
||||||
@@ -285,6 +286,26 @@ public class GameAction {
|
|||||||
|
|
||||||
// not to battlefield anymore!
|
// not to battlefield anymore!
|
||||||
toBattlefield = false;
|
toBattlefield = false;
|
||||||
|
|
||||||
|
if (copied.isCloned()) {
|
||||||
|
copied.switchStates(CardStateName.Original, CardStateName.Cloner, false);
|
||||||
|
copied.setState(CardStateName.Original, false);
|
||||||
|
copied.clearStates(CardStateName.Cloner, false);
|
||||||
|
if (copied.isFlipCard()) {
|
||||||
|
copied.clearStates(CardStateName.Flipped, false);
|
||||||
|
}
|
||||||
|
if (copied.getStates().contains(CardStateName.OriginalText)) {
|
||||||
|
copied.clearStates(CardStateName.OriginalText, false);
|
||||||
|
copied.removeSVar("GainingTextFrom");
|
||||||
|
copied.removeSVar("GainingTextFromTimestamp");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copied.getCurrentStateName() != CardStateName.Original) {
|
||||||
|
copied.setState(CardStateName.Original, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
copied.updateStateForView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -226,6 +226,10 @@ public class TokenInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static public Card getProtoType(final String script, final SpellAbility sa) {
|
static public Card getProtoType(final String script, final SpellAbility sa) {
|
||||||
|
// script might be null, or sa might be null
|
||||||
|
if (script == null || sa == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final Card host = sa.getHostCard();
|
final Card host = sa.getHostCard();
|
||||||
final Game game = host.getGame();
|
final Game game = host.getGame();
|
||||||
|
|
||||||
|
|||||||
@@ -100,8 +100,8 @@ public class TriggerChangesZone extends Trigger {
|
|||||||
if (hasParam("ValidCard")) {
|
if (hasParam("ValidCard")) {
|
||||||
Card moved = (Card) runParams2.get("Card");
|
Card moved = (Card) runParams2.get("Card");
|
||||||
final Game game = getHostCard().getGame();
|
final Game game = getHostCard().getGame();
|
||||||
boolean isDiesTrig = "Battlefield".equals(getParam("Origin"))
|
boolean leavesBattlefield = "Battlefield".equals(getParam("Origin"));
|
||||||
&& "Graveyard".equals(getParam("Destination"));
|
boolean isDiesTrig = leavesBattlefield && "Graveyard".equals(getParam("Destination"));
|
||||||
|
|
||||||
if (isDiesTrig) {
|
if (isDiesTrig) {
|
||||||
moved = game.getChangeZoneLKIInfo(moved);
|
moved = game.getChangeZoneLKIInfo(moved);
|
||||||
@@ -111,6 +111,11 @@ public class TriggerChangesZone extends Trigger {
|
|||||||
getHostCard(), null)) {
|
getHostCard(), null)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if it is a die trigger, and the hostcard is the moved one, but it doesn't has the trigger
|
||||||
|
if (leavesBattlefield && moved.equals(getHostCard()) && !moved.hasTrigger(this)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasParam("ValidCause")) {
|
if (hasParam("ValidCause")) {
|
||||||
|
|||||||
Reference in New Issue
Block a user