mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-12 00:38:44 +00:00
Ghostly Dancers and support
This commit is contained in:
@@ -155,7 +155,7 @@ public class SetStateAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
// non-permanent facedown can't be turned face up
|
||||
if (!card.getRules().getType().isPermanent()) {
|
||||
if (!card.getRules().getType().isPermanent() || !card.canBeTurnedFaceUp()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -285,7 +285,16 @@ public final class AbilityFactory {
|
||||
final String key = "Choices";
|
||||
if (mapParams.containsKey(key)) {
|
||||
List<String> names = Lists.newArrayList(mapParams.get(key).split(","));
|
||||
spellAbility.setAdditionalAbilityList(key, Lists.transform(names, input -> getSubAbility(state, input, sVarHolder)));
|
||||
spellAbility.setAdditionalAbilityList(key, Lists.transform(names, input -> {
|
||||
AbilitySub sub = getSubAbility(state, input, sVarHolder);
|
||||
if (api == ApiType.GenericChoice) {
|
||||
// support scripters adding restrictions to filter illegal choices
|
||||
sub.setRestrictions(new SpellAbilityRestriction());
|
||||
makeRestrictions(sub);
|
||||
}
|
||||
return sub;
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,15 +21,6 @@ public class VillainousChoiceEffect extends SpellAbilityEffect {
|
||||
for (Player p : getDefinedPlayersOrTargeted(sa)) {
|
||||
int choiceAmount = p.getAdditionalVillainousChoices() + 1;
|
||||
|
||||
List<SpellAbility> saToRemove = Lists.newArrayList();
|
||||
|
||||
for (SpellAbility saChoice : abilities) {
|
||||
if (saChoice.getRestrictions() != null && !saChoice.getRestrictions().checkOtherRestrictions(sa.getHostCard(), saChoice, sa.getActivatingPlayer())) {
|
||||
saToRemove.add(saChoice);
|
||||
}
|
||||
}
|
||||
abilities.removeAll(saToRemove);
|
||||
|
||||
// For the AI chooseSAForEffect really should take the least good ability. Currently it just takes the first
|
||||
List<SpellAbility> chosenSAs = Lists.newArrayList();
|
||||
for(int i = 0; i < choiceAmount; i++) {
|
||||
|
||||
@@ -805,6 +805,11 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|
||||
return setState(CardStateName.FaceDown, false);
|
||||
}
|
||||
|
||||
public boolean canBeTurnedFaceUp() {
|
||||
Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(this);
|
||||
return !getGame().getReplacementHandler().cantHappenCheck(ReplacementType.TurnFaceUp, repParams);
|
||||
}
|
||||
|
||||
public void forceTurnFaceUp() {
|
||||
turnFaceUp(false, null);
|
||||
}
|
||||
@@ -813,14 +818,10 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|
||||
return turnFaceUp(true, cause);
|
||||
}
|
||||
public boolean turnFaceUp(boolean runTriggers, SpellAbility cause) {
|
||||
if (!isFaceDown()) {
|
||||
if (!isFaceDown() || !canBeTurnedFaceUp()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check replacement effects
|
||||
Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(this);
|
||||
if (game.getReplacementHandler().cantHappenCheck(ReplacementType.TurnFaceUp, repParams)) return false;
|
||||
|
||||
CardCollectionView cards = hasMergedCard() ? getMergedCards() : new CardCollection(this);
|
||||
boolean retResult = false;
|
||||
long ts = game.getNextTimestamp();
|
||||
@@ -855,10 +856,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|
||||
triggerHandler.registerActiveTrigger(this, false);
|
||||
}
|
||||
if (runTriggers) {
|
||||
// Run replacement effects
|
||||
Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(this);
|
||||
game.getReplacementHandler().run(ReplacementType.TurnFaceUp, repParams);
|
||||
|
||||
// Run triggers
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(this);
|
||||
runParams.put(AbilityKey.Cause, cause);
|
||||
|
||||
|
||||
@@ -1924,6 +1924,18 @@ public class CardProperty {
|
||||
if (!card.isGoaded()) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("FullyUnlocked")) {
|
||||
if (card.getUnlockedRooms().size() < 2) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("canReceiveCounters")) {
|
||||
if (!card.canReceiveCounters(CounterType.getType(property.split(" ")[1]))) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("canBeTurnedFaceUp")) {
|
||||
if (!card.canBeTurnedFaceUp()) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("NoAbilities")) {
|
||||
if (!card.hasNoAbilities()) {
|
||||
return false;
|
||||
|
||||
@@ -18,12 +18,8 @@
|
||||
package forge.game.spellability;
|
||||
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.replacement.ReplacementType;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -58,9 +54,8 @@ public abstract class AbilityStatic extends Ability implements Cloneable {
|
||||
|
||||
// Check if ability can't be attempted because of replacement effect
|
||||
// Initial usage is Karlov Watchdog preventing disguise/morph/cloak/manifest turning face up
|
||||
if (this.isTurnFaceUp()) {
|
||||
Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(c);
|
||||
if (c.getGame().getReplacementHandler().cantHappenCheck(ReplacementType.TurnFaceUp, repParams)) return false;
|
||||
if (this.isTurnFaceUp() && !c.canBeTurnedFaceUp()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getRestrictions().canPlay(c, this);
|
||||
|
||||
13
forge-gui/res/cardsfolder/upcoming/ghostly_dancers.txt
Normal file
13
forge-gui/res/cardsfolder/upcoming/ghostly_dancers.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Name:Ghostly Dancers
|
||||
ManaCost:3 W W
|
||||
Types:Creature Spirit
|
||||
PT:2/5
|
||||
K:Flying
|
||||
T:Mode$ ChangesZone | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigChoice | TriggerDescription$ When CARDNAME enters, return an enchantment card from your graveyard to your hand or unlock a locked door of a Room you control.
|
||||
SVar:TrigChoice:DB$ GenericChoice | Choices$ DBReturn,DBUnlock
|
||||
SVar:DBReturn:DB$ ChangeZone | Hidden$ True | Mandatory$ True | ChangeType$ Enchantment.YouOwn | Origin$ Graveyard | Destination$ Hand | IsPresent$ Enchantment.YouOwn | PresentZone$ Graveyard | SpellDescription$ Return an enchantment card from your graveyard to your hand
|
||||
SVar:DBUnlock:DB$ UnlockDoor | Mode$ Unlock | Choices$ Room.YouCtrl+!FullyUnlocked | IsPresent$ Room.YouCtrl+!FullyUnlocked | SpellDescription$ Unlock a locked door of a Room you control
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, create a 3/1 white Spirit creature token with flying.
|
||||
T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, create a 3/1 white Spirit creature token with flying.
|
||||
SVar:TrigToken:DB$ Token | TokenScript$ w_3_1_spirit_flying
|
||||
Oracle:Flying\nWhen Ghostly Dancers enters, return an enchantment card from your graveyard to your hand or unlock a locked door of a Room you control.\nEerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, create a 3/1 white Spirit creature token with flying.
|
||||
7
forge-gui/res/tokenscripts/w_3_1_spirit_flying.txt
Normal file
7
forge-gui/res/tokenscripts/w_3_1_spirit_flying.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
Name:Spirit Token
|
||||
ManaCost:no cost
|
||||
Types:Creature Spirit
|
||||
Colors:white
|
||||
PT:3/1
|
||||
K:Flying
|
||||
Oracle:Flying
|
||||
Reference in New Issue
Block a user