MKM: a_killer_among_us.txt + support (#4574)

This commit is contained in:
Northmoc
2024-01-21 22:30:24 -05:00
committed by GitHub
parent b274ead986
commit 804977e1b5
13 changed files with 79 additions and 28 deletions

View File

@@ -498,7 +498,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
}
@Override
public PaymentDecision visit(CostRevealChosenPlayer cost) {
public PaymentDecision visit(CostRevealChosen cost) {
return PaymentDecision.number(1);
}

View File

@@ -1,5 +1,6 @@
package forge.game.ability.effects;
import forge.game.Game;
import forge.game.GameLogEntryType;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
@@ -27,12 +28,15 @@ public class ChoosePlayerEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
final Card card = sa.getHostCard();
final Game game = card.getGame();
final FCollectionView<Player> choices = sa.hasParam("Choices") ? AbilityUtils.getDefinedPlayers(
card, sa.getParam("Choices"), sa) : sa.getActivatingPlayer().getGame().getPlayersInTurnOrder();
card, sa.getParam("Choices"), sa) : game.getPlayersInTurnOrder();
final String choiceDesc = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : Localizer.getInstance().getMessage("lblChoosePlayer");
final String choiceDesc = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") :
Localizer.getInstance().getMessage("lblChoosePlayer");
final boolean random = sa.hasParam("Random");
final boolean secret = sa.hasParam("Secretly");
for (final Player p : getTargetPlayers(sa)) {
if (!p.isInGame()) {
@@ -45,7 +49,7 @@ public class ChoosePlayerEffect extends SpellAbilityEffect {
chosen = choices.isEmpty() ? null : p.getController().chooseSingleEntityForEffect(choices, sa, choiceDesc, sa.hasParam("Optional"), null);
}
if (null != chosen) {
if (sa.hasParam("Secretly")) {
if (secret) {
card.setSecretChosenPlayer(chosen);
} else if (sa.hasParam("Protect")) {
card.setProtectingPlayer(chosen);
@@ -58,11 +62,10 @@ public class ChoosePlayerEffect extends SpellAbilityEffect {
if (sa.hasParam("RememberChosen")) {
card.addRemembered(chosen);
}
if (sa.hasParam("DontNotify")) { //ie Shared Fate
//log the chosen player
p.getGame().getGameLog().add(GameLogEntryType.INFORMATION, Localizer.getInstance().getMessage("lblPlayerPickedChosen", sa.getActivatingPlayer(), chosen));
} else {
p.getGame().getAction().notifyOfValue(sa, p, Localizer.getInstance().getMessage("lblPlayerPickedChosen", sa.getActivatingPlayer(), chosen), null);
if (!secret) {
//ie Shared Fate log the chosen player
if (sa.hasParam("DontNotify")) game.getGameLog().add(GameLogEntryType.INFORMATION, Localizer.getInstance().getMessage("lblPlayerPickedChosen", sa.getActivatingPlayer(), chosen));
else game.getAction().notifyOfValue(sa, p, Localizer.getInstance().getMessage("lblPlayerPickedChosen", sa.getActivatingPlayer(), chosen), null);
}
// SubAbility that only fires if a player is chosen
SpellAbility chosenSA = sa.getAdditionalAbility("ChooseSubAbility");

View File

@@ -41,6 +41,7 @@ public class ChooseTypeEffect extends SpellAbilityEffect {
final List<String> invalidTypes = sa.hasParam("InvalidTypes") ? Arrays.asList(sa.getParam("InvalidTypes").split(",")) : new ArrayList<>();
final List<String> validTypes = new ArrayList<>();
final List<Player> tgtPlayers = getTargetPlayers(sa);
final boolean secret = sa.hasParam("Secretly");
if (sa.hasParam("ValidTypes")) {
validTypes.addAll(Arrays.asList(sa.getParam("ValidTypes").split(",")));
@@ -131,7 +132,7 @@ public class ChooseTypeEffect extends SpellAbilityEffect {
choice = p.getController().chooseSomeType(type, sa, validTypes, invalidTypes);
}
p.getGame().getAction().notifyOfValue(sa, p, choice, noNotify);
if (!secret) p.getGame().getAction().notifyOfValue(sa, p, choice, noNotify);
if (sa.hasParam("Note")) {
card.addNotedType(choice);
@@ -142,7 +143,8 @@ public class ChooseTypeEffect extends SpellAbilityEffect {
if (sa.hasParam("ChooseType2")) {
card.setChosenType2(choice);
} else {
card.setChosenType(choice);
if (secret) card.setSecretChosenType(choice);
else card.setChosenType(choice);
}
}
} else {

View File

@@ -1877,6 +1877,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
return chosenType != null && !chosenType.isEmpty();
}
public final void setSecretChosenType(final String s) {
chosenType = s;
}
public final void revealChosenType() {
view.updateChosenType(this);
}
// used by card Illusionary Terrain
public final String getChosenType2() {
return chosenType2;

View File

@@ -543,8 +543,9 @@ public class Cost implements Serializable {
return new CostEnlist(splitStr[0], splitStr[1], description);
}
if (parse.equals("RevealChosenPlayer")) {
return new CostRevealChosenPlayer();
if (parse.startsWith("RevealChosen<")) {
final String[] splitStr = abCostParse(parse, 2);
return new CostRevealChosen(splitStr[0], splitStr.length > 1 ? splitStr[1] : null);
}
// These won't show up with multiples

View File

@@ -20,12 +20,18 @@ package forge.game.cost;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.util.Localizer;
public class CostRevealChosenPlayer extends CostPart {
public class CostRevealChosen extends CostPart {
private static final long serialVersionUID = 1L;
public CostRevealChosenPlayer() { }
public CostRevealChosen(final String type, final String desc) {
super("1", type, desc);
}
@Override
public int paymentOrder() { return 20; }
/*
* (non-Javadoc)
@@ -34,19 +40,39 @@ public class CostRevealChosenPlayer extends CostPart {
*/
@Override
public final String toString() {
return "Reveal the player you chose";
if (getType().equals("Player")) {
return "Reveal the player you chose";
} else if (getType().equals("Type")) {
return "Reveal the chosen " + getDescriptiveType().toLowerCase();
}
return "Update CostRevealChosen.java";
}
@Override
public final boolean canPay(final SpellAbility ability, final Player activator, final boolean effect) {
final Card source = ability.getHostCard();
return source.hasChosenPlayer() && source.getTurnInController().equals(activator);
if (getType().equals("Player")) {
return source.hasChosenPlayer() && source.getTurnInController().equals(activator);
} else if (getType().equals("Type")) {
return source.hasChosenType() && source.getTurnInController().equals(activator);
}
return false;
}
@Override
public boolean payAsDecided(Player ai, PaymentDecision decision, SpellAbility ability, final boolean effect) {
ability.getHostCard().revealChosenPlayer();
Card host = ability.getHostCard();
String o = "";
if (getType().equals("Player")) {
o = host.getChosenPlayer().toString();
host.revealChosenPlayer();
} else if (getType().equals("Type")) {
o = host.getChosenType();
host.revealChosenType();
}
final String message = Localizer.getInstance().getMessage("lblPlayerReveals", ai, o);
ai.getGame().getAction().notifyOfValue(ability, host, message, ai);
return true;
}

View File

@@ -26,7 +26,7 @@ public interface ICostVisitor<T> {
T visit(CostSacrifice cost);
T visit(CostReturn cost);
T visit(CostReveal cost);
T visit(CostRevealChosenPlayer cost);
T visit(CostRevealChosen cost);
T visit(CostRemoveAnyCounter cost);
T visit(CostRemoveCounter cost);
T visit(CostPutCounter cost);
@@ -159,7 +159,7 @@ public interface ICostVisitor<T> {
}
@Override
public T visit(CostRevealChosenPlayer cost) {
public T visit(CostRevealChosen cost) {
return null;
}

View File

@@ -5,6 +5,6 @@ PT:6/5
K:Flying
K:Haste
K:ETBReplacement:Other:ChooseP
SVar:ChooseP:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | ChoiceTitle$ Choose an opponent | Secretly$ True | SpellDescription$ As CARDNAME enters the battlefield, secretly choose an opponent.
A:AB$ ChangeTargets | Cost$ RevealChosenPlayer | TargetType$ Spell,Activated,Triggered | ValidTgts$ Card,Emblem | ConditionTargetValidTargeting$ Permanent.YouCtrl+inRealZoneBattlefield,You | ConditionPlayerDefined$ TargetedController | ConditionPlayerContains$ Player.Chosen | GameActivationLimit$ 1 | SpellDescription$ Choose new targets for target spell or ability if it's controlled by the chosen player and if it targets you or a permanent you control. Activate only once.
SVar:ChooseP:DB$ ChoosePlayer | Defined$ You | Choices$ Opponent | ChoiceTitle$ Choose an opponent | Secretly$ True | SpellDescription$ As CARDNAME enters the battlefield, secretly choose an opponent.
A:AB$ ChangeTargets | Cost$ RevealChosen<Player> | TargetType$ Spell,Activated,Triggered | ValidTgts$ Card,Emblem | ConditionTargetValidTargeting$ Permanent.YouCtrl+inRealZoneBattlefield,You | ConditionPlayerDefined$ TargetedController | ConditionPlayerContains$ Player.Chosen | GameActivationLimit$ 1 | SpellDescription$ Choose new targets for target spell or ability if it's controlled by the chosen player and if it targets you or a permanent you control. Activate only once.
Oracle:Flying, haste\nAs Emissary of Grudges enters the battlefield, secretly choose an opponent.\nReveal the player you chose: Choose new targets for target spell or ability if it's controlled by the chosen player and if it targets you or a permanent you control. Activate only once.

View File

@@ -4,7 +4,7 @@ Types:Creature Archon
PT:5/5
K:Flying
K:ETBReplacement:Other:ChooseP
SVar:ChooseP:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | ChoiceTitle$ Choose an opponent | Secretly$ True | SpellDescription$ As CARDNAME enters the battlefield, secretly choose an opponent.
A:AB$ Pump | Cost$ RevealChosenPlayer | Defined$ You | KW$ Protection:Player.PlayerUID_ChosenPlayerUID:ChosenPlayerName | DefinedKW$ ChosenPlayer | SubAbility$ DBPump | GameActivationLimit$ 1 | StackDescription$ {p:You} and | SpellDescription$ You and target permanent you control each gain protection from the chosen player until end of turn. Activate only once.
SVar:DBPump:DB$ Pump | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target permanent you control | KW$ Protection:Player.PlayerUID_ChosenPlayerUID:ChosenPlayerName | DefinedKW$ ChosenPlayer | StackDescription$ {c:Targeted} each gain protection from {p:ChosenPlayer} until end of turn. Activate only once.
SVar:ChooseP:DB$ ChoosePlayer | Defined$ You | Choices$ Opponent | ChoiceTitle$ Choose an opponent | Secretly$ True | SpellDescription$ As CARDNAME enters the battlefield, secretly choose an opponent.
A:AB$ Pump | Cost$ RevealChosen<Player> | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target permanent you control | KW$ Protection:Player.PlayerUID_ChosenPlayerUID:ChosenPlayerName | DefinedKW$ ChosenPlayer | GameActivationLimit$ 1 | SubAbility$ DBPump | StackDescription$ {p:You} and {c:Targeted} each gain protection from {p:ChosenPlayer} until end of turn. | SpellDescription$ You and target permanent you control each gain protection from the chosen player until end of turn. Activate only once.
SVar:DBPump:DB$ Pump | Defined$ You | KW$ Protection:Player.PlayerUID_ChosenPlayerUID:ChosenPlayerName | DefinedKW$ ChosenPlayer | StackDescription$ None
Oracle:Flying\nAs Guardian Archon enters the battlefield, secretly choose an opponent.\nReveal the player you chose: You and target permanent you control each gain protection from the chosen player until end of turn. Activate only once.

View File

@@ -3,6 +3,6 @@ ManaCost:2 W
Types:Creature Cat Archer
PT:3/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChooseOpp | TriggerDescription$ When CARDNAME enters the battlefield, secretly choose an opponent.
SVar:TrigChooseOpp:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | Secretly$ True
A:AB$ ChangeZone | Cost$ RevealChosenPlayer | ValidTgts$ Creature.attackingYou | TgtPrompt$ Select target creature that's attacking you. | Origin$ Battlefield | Destination$ Exile | ConditionDefined$ Targeted | ConditionPresent$ Card.ChosenCtrl | GameActivationLimit$ 1 | SpellDescription$ Exile target creature that's attacking you if it's controlled by the chosen player. Activate only once.
SVar:TrigChooseOpp:DB$ ChoosePlayer | Defined$ You | Choices$ Opponent | Secretly$ True
A:AB$ ChangeZone | Cost$ RevealChosen<Player> | ValidTgts$ Creature.attackingYou | TgtPrompt$ Select target creature that's attacking you | Origin$ Battlefield | Destination$ Exile | ConditionDefined$ Targeted | ConditionPresent$ Card.ChosenCtrl | GameActivationLimit$ 1 | SpellDescription$ Exile target creature that's attacking you if it's controlled by the chosen player. Activate only once.
Oracle:When Stalking Leonin enters the battlefield, secretly choose an opponent.\nReveal the player you chose: Exile target creature that's attacking you if it's controlled by the chosen player. Activate only once.

View File

@@ -0,0 +1,10 @@
Name:A Killer Among Us
ManaCost:4 G
Types:Enchantment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a 1/1 white Human creature token, a 1/1 blue Merfolk creature token, and a 1/1 red Goblin creature token. Then secretly choose Human, Merfolk, or Goblin.
SVar:TrigToken:DB$ Token | TokenScript$ w_1_1_human,u_1_1_merfolk,r_1_1_goblin | SubAbility$ DBChooseType
SVar:DBChooseType:DB$ ChooseType | Type$ Creature | ValidTypes$ Human,Merfolk,Goblin | Secretly$ True
A:AB$ PutCounter | Cost$ Sac<1/CARDNAME> RevealChosen<Type/creature type> | ValidTgts$ Creature.token+attacking | TgtPrompt$ Select target attacking creature token | AITgts$ Creature.token+attacking+ChosenType | Defined$ Targeted.ChosenType | CounterType$ P1P1 | CounterNum$ 3 | SubAbility$ DBPump | StackDescription$ REP target attacking creature token_{c:Targeted} | SpellDescription$ If target attacking creature token is the chosen type, put three +1/+1 counters on it
SVar:DBPump:DB$ Pump | Defined$ Targeted.ChosenType | KW$ Deathtouch | StackDescription$ SpellDescription | SpellDescription$ and it gains deathtouch until end of turn.
DeckHas:Ability$Token|Sacrifice & Type$Human|Merfolk|Goblin & Color$White|Blue|Red
Oracle:When A Killer Among Us enters the battlefield, create a 1/1 white Human creature token, a 1/1 blue Merfolk creature token, and a 1/1 red Goblin creature token. Then secretly choose Human, Merfolk, or Goblin.\nSacrifice A Killer Among Us, Reveal the chosen creature type: If target attacking creature token is the chosen type, put three +1/+1 counters on it and it gains deathtouch until end of turn.

View File

@@ -2433,6 +2433,8 @@ lblThisPlaneHasNoDesc=This plane has no description.
#ConquestUtil.java
lblHistoriiansWillRecallYourConquestAs=Historians will recall your conquest as:
lblConquestName=Conquest Name
#CostRevealChosen.java
lblPlayerReveals={0} reveals {1}
#HumanCostDecision.java
lblChooseXValueForCard={0} - Choose a Value for X
lblSelectOneSameNameCardToDiscardAlreadyChosen=Select one of the cards with the same name to discard. Already chosen:

View File

@@ -851,7 +851,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
}
@Override
public PaymentDecision visit(final CostRevealChosenPlayer cost) {
public PaymentDecision visit(final CostRevealChosen cost) {
return PaymentDecision.number(1);
}