1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-04 01:06:04 -09:00

[ONC] Implement Staff of the Storyteller

This commit is contained in:
theelk801 2023-04-28 19:25:34 -04:00
parent 753452d8a0
commit 4757356bc2
6 changed files with 137 additions and 1 deletions
Mage.Sets/src/mage
Mage/src/main/java/mage

View file

@ -0,0 +1,85 @@
package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.CreatedTokensEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.token.SpiritWhiteToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class StaffOfTheStoryteller extends CardImpl {
public StaffOfTheStoryteller(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{W}");
// When Staff of the Storyteller enters the battlefield, create a 1/1 white Spirit creature token with flying.
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken())));
// Whenever you create one or more creature tokens, put a story counter on Staff of the Storyteller.
this.addAbility(new StaffOfTheStorytellerTriggeredAbility());
// {W}, {T}, Remove a story counter from Staff of the Storyteller: Draw a card.
Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{W}"));
ability.addCost(new TapSourceCost());
ability.addCost(new RemoveCountersSourceCost(CounterType.STORY.createInstance()));
this.addAbility(ability);
}
private StaffOfTheStoryteller(final StaffOfTheStoryteller card) {
super(card);
}
@Override
public StaffOfTheStoryteller copy() {
return new StaffOfTheStoryteller(this);
}
}
class StaffOfTheStorytellerTriggeredAbility extends TriggeredAbilityImpl {
StaffOfTheStorytellerTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORY.createInstance()));
setTriggerPhrase("Whenever you create one or more creature tokens, ");
}
private StaffOfTheStorytellerTriggeredAbility(final StaffOfTheStorytellerTriggeredAbility ability) {
super(ability);
}
@Override
public StaffOfTheStorytellerTriggeredAbility copy() {
return new StaffOfTheStorytellerTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.CREATED_TOKENS;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return isControlledBy(event.getPlayerId())
&& ((CreatedTokensEvent) event)
.getCreatedTokens()
.stream()
.anyMatch(p -> p.isCreature(game));
}
}

View file

@ -152,6 +152,7 @@ public final class PhyrexiaAllWillBeOneCommander extends ExpansionSet {
cards.add(new SetCardInfo("Sol Ring", 140, Rarity.UNCOMMON, mage.cards.s.SolRing.class)); cards.add(new SetCardInfo("Sol Ring", 140, Rarity.UNCOMMON, mage.cards.s.SolRing.class));
cards.add(new SetCardInfo("Solemn Simulacrum", 141, Rarity.RARE, mage.cards.s.SolemnSimulacrum.class)); cards.add(new SetCardInfo("Solemn Simulacrum", 141, Rarity.RARE, mage.cards.s.SolemnSimulacrum.class));
cards.add(new SetCardInfo("Soul-Guide Lantern", 142, Rarity.UNCOMMON, mage.cards.s.SoulGuideLantern.class)); cards.add(new SetCardInfo("Soul-Guide Lantern", 142, Rarity.UNCOMMON, mage.cards.s.SoulGuideLantern.class));
cards.add(new SetCardInfo("Staff of the Storyteller", 10, Rarity.RARE, mage.cards.s.StaffOfTheStoryteller.class));
cards.add(new SetCardInfo("Sungrass Prairie", 166, Rarity.RARE, mage.cards.s.SungrassPrairie.class)); cards.add(new SetCardInfo("Sungrass Prairie", 166, Rarity.RARE, mage.cards.s.SungrassPrairie.class));
cards.add(new SetCardInfo("Swords to Plowshares", 89, Rarity.UNCOMMON, mage.cards.s.SwordsToPlowshares.class)); cards.add(new SetCardInfo("Swords to Plowshares", 89, Rarity.UNCOMMON, mage.cards.s.SwordsToPlowshares.class));
cards.add(new SetCardInfo("Synthesis Pod", 23, Rarity.RARE, mage.cards.s.SynthesisPod.class)); cards.add(new SetCardInfo("Synthesis Pod", 23, Rarity.RARE, mage.cards.s.SynthesisPod.class));

View file

@ -180,6 +180,7 @@ public enum CounterType {
SPORE("spore"), SPORE("spore"),
STASH("stash"), STASH("stash"),
STORAGE("storage"), STORAGE("storage"),
STORY("story"),
STRIFE("strife"), STRIFE("strife"),
STUDY("study"), STUDY("study"),
STUN("stun"), STUN("stun"),

View file

@ -0,0 +1,44 @@
package mage.game.events;
import com.google.common.collect.Sets;
import mage.abilities.Ability;
import mage.game.Controllable;
import mage.game.Game;
import mage.game.permanent.PermanentToken;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author TheElk801
*/
public class CreatedTokensEvent extends GameEvent {
private final Set<PermanentToken> createdTokens = new HashSet<>();
private CreatedTokensEvent(UUID playerId, Set<PermanentToken> createdTokens, Ability source) {
super(EventType.CREATED_TOKENS, playerId, source, playerId);
this.createdTokens.addAll(createdTokens);
}
public static void addEvents(Set<PermanentToken> allAddedTokens, Ability source, Game game) {
allAddedTokens
.stream()
.collect(Collectors.toMap(
Controllable::getControllerId,
Collections::singleton,
Sets::union
))
.entrySet()
.stream()
.map(entry -> new CreatedTokensEvent(entry.getKey(), entry.getValue(), source))
.forEach(game::addSimultaneousEvent);
}
public Set<PermanentToken> getCreatedTokens() {
return createdTokens;
}
}

View file

@ -462,7 +462,7 @@ public class GameEvent implements Serializable {
flag not used for this event flag not used for this event
*/ */
GAINED_CONTROL, GAINED_CONTROL,
CREATE_TOKEN, CREATED_TOKEN, CREATE_TOKEN, CREATED_TOKEN, CREATED_TOKENS,
/* REGENERATE /* REGENERATE
targetId id of the creature to regenerate targetId id of the creature to regenerate
sourceId sourceId of the effect doing the regeneration sourceId sourceId of the effect doing the regeneration

View file

@ -18,6 +18,7 @@ import mage.game.Game;
import mage.game.command.CommandObject; import mage.game.command.CommandObject;
import mage.game.events.CreateTokenEvent; import mage.game.events.CreateTokenEvent;
import mage.game.events.CreatedTokenEvent; import mage.game.events.CreatedTokenEvent;
import mage.game.events.CreatedTokensEvent;
import mage.game.events.ZoneChangeEvent; import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken; import mage.game.permanent.PermanentToken;
@ -249,6 +250,7 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
return; return;
} }
Set<PermanentToken> allAddedTokens = new HashSet<>();
for (Map.Entry<Token, Integer> entry : event.getTokens().entrySet()) { for (Map.Entry<Token, Integer> entry : event.getTokens().entrySet()) {
Token token = entry.getKey(); Token token = entry.getKey();
int amount = entry.getValue(); int amount = entry.getValue();
@ -306,6 +308,7 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
game.addSimultaneousEvent(zccEvent); game.addSimultaneousEvent(zccEvent);
if (permanent instanceof PermanentToken && created) { if (permanent instanceof PermanentToken && created) {
game.addSimultaneousEvent(new CreatedTokenEvent(source, (PermanentToken) permanent)); game.addSimultaneousEvent(new CreatedTokenEvent(source, (PermanentToken) permanent));
allAddedTokens.add((PermanentToken) permanent);
} }
// if token was created (not a spell copy) handle auras coming into the battlefield // if token was created (not a spell copy) handle auras coming into the battlefield
@ -382,6 +385,8 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
} }
} }
} }
CreatedTokensEvent.addEvents(allAddedTokens, source, game);
game.getState().applyEffects(game); // Needed to do it here without LKIReset i.e. do get SwordOfTheMeekTest running correctly. game.getState().applyEffects(game); // Needed to do it here without LKIReset i.e. do get SwordOfTheMeekTest running correctly.
} }