mirror of
https://github.com/magefree/mage.git
synced 2025-12-26 05:22:02 -08:00
[MH1] added Unbound Flourishing
This commit is contained in:
parent
3599d6343c
commit
12fc854777
16 changed files with 457 additions and 51 deletions
|
|
@ -254,6 +254,8 @@ public abstract class AbilityImpl implements Ability {
|
|||
int xValue = this.getManaCostsToPay().getX();
|
||||
this.getManaCostsToPay().clear();
|
||||
VariableManaCost xCosts = new VariableManaCost();
|
||||
// no x events - rules from Unbound Flourishing:
|
||||
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
|
||||
xCosts.setAmount(xValue);
|
||||
this.getManaCostsToPay().add(xCosts);
|
||||
} else {
|
||||
|
|
@ -288,11 +290,13 @@ public abstract class AbilityImpl implements Ability {
|
|||
if (getAbilityType() == AbilityType.SPELL && (getManaCostsToPay().isEmpty() && getCosts().isEmpty()) && !noMana) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 20121001 - 601.2b
|
||||
// If the spell has a variable cost that will be paid as it's being cast (such as an {X} in
|
||||
// its mana cost; see rule 107.3), the player announces the value of that variable.
|
||||
VariableManaCost variableManaCost = handleManaXCosts(game, noMana, controller);
|
||||
String announceString = handleOtherXCosts(game, controller);
|
||||
|
||||
// For effects from cards like Void Winnower x costs have to be set
|
||||
if (this.getAbilityType() == AbilityType.SPELL
|
||||
&& game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL_LATE, getId(), getSourceId(), getControllerId()), this)) {
|
||||
|
|
@ -499,7 +503,9 @@ public abstract class AbilityImpl implements Ability {
|
|||
costs.add(fixedCost);
|
||||
}
|
||||
// set the xcosts to paid
|
||||
variableCost.setAmount(xValue);
|
||||
// no x events - rules from Unbound Flourishing:
|
||||
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
|
||||
variableCost.setAmount(xValue); //
|
||||
((Cost) variableCost).setPaid();
|
||||
String message = controller.getLogName() + " announces a value of " + xValue + " (" + variableCost.getActionText() + ')';
|
||||
announceString.append(message);
|
||||
|
|
@ -530,6 +536,13 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
}
|
||||
|
||||
public int handleManaXMultiplier(Game game, int value) {
|
||||
// some spells can change X value without new pays (Unbound Flourishing doubles X)
|
||||
GameEvent xEvent = GameEvent.getEvent(GameEvent.EventType.X_MANA_ANNOUNCE, getId(), getSourceId(), getControllerId(), value);
|
||||
game.replaceEvent(xEvent, this);
|
||||
return xEvent.getAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles X mana costs and sets manaCostsToPay.
|
||||
*
|
||||
|
|
@ -546,15 +559,21 @@ public abstract class AbilityImpl implements Ability {
|
|||
VariableManaCost variableManaCost = null;
|
||||
for (ManaCost cost : manaCostsToPay) {
|
||||
if (cost instanceof VariableManaCost) {
|
||||
variableManaCost = (VariableManaCost) cost;
|
||||
break; // only one VariableManCost per spell (or is it possible to have more?)
|
||||
if (variableManaCost == null) {
|
||||
variableManaCost = (VariableManaCost) cost;
|
||||
} else {
|
||||
// only one VariableManCost per spell (or is it possible to have more?)
|
||||
logger.error("Variable mana cost allowes only in one instance per ability: " + this);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (variableManaCost != null) {
|
||||
int xValue;
|
||||
if (!variableManaCost.isPaid()) { // should only happen for human players
|
||||
int xValue;
|
||||
int xValueMultiplier = handleManaXMultiplier(game, 1);
|
||||
if (!noMana) {
|
||||
xValue = controller.announceXMana(variableManaCost.getMinX(), variableManaCost.getMaxX(), "Announce the value for " + variableManaCost.getText(), game, this);
|
||||
xValue = controller.announceXMana(variableManaCost.getMinX(), variableManaCost.getMaxX(), xValueMultiplier,
|
||||
"Announce the value for " + variableManaCost.getText(), game, this);
|
||||
int amountMana = xValue * variableManaCost.getMultiplier();
|
||||
StringBuilder manaString = threadLocalBuilder.get();
|
||||
if (variableManaCost.getFilter() == null || variableManaCost.getFilter().isGeneric()) {
|
||||
|
|
@ -584,7 +603,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
}
|
||||
manaCostsToPay.add(new ManaCostsImpl(manaString.toString()));
|
||||
manaCostsToPay.setX(amountMana);
|
||||
manaCostsToPay.setX(xValue, xValueMultiplier);
|
||||
}
|
||||
variableManaCost.setPaid();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
package mage.abilities.costs.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
|
|
@ -16,8 +13,11 @@ import mage.game.Game;
|
|||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ExileFromHandCost extends CostImpl {
|
||||
|
|
@ -30,10 +30,9 @@ public class ExileFromHandCost extends CostImpl {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param target
|
||||
* @param setXFromCMC the spells X value on the stack is set to the
|
||||
* converted mana costs of the exiled card
|
||||
* converted mana costs of the exiled card
|
||||
*/
|
||||
public ExileFromHandCost(TargetCardInHand target, boolean setXFromCMC) {
|
||||
this.addTarget(target);
|
||||
|
|
@ -68,6 +67,8 @@ public class ExileFromHandCost extends CostImpl {
|
|||
paid = true;
|
||||
if (setXFromCMC) {
|
||||
VariableManaCost vmc = new VariableManaCost();
|
||||
// no x events - rules from Unbound Flourishing:
|
||||
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
|
||||
vmc.setAmount(cmc);
|
||||
vmc.setPaid();
|
||||
ability.getManaCostsToPay().add(vmc);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.abilities.costs.mana;
|
||||
|
||||
import mage.Mana;
|
||||
|
|
@ -11,9 +10,8 @@ import java.util.UUID;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @param <T>
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public interface ManaCosts<T extends ManaCost> extends List<T>, ManaCost {
|
||||
|
||||
|
|
@ -21,9 +19,15 @@ public interface ManaCosts<T extends ManaCost> extends List<T>, ManaCost {
|
|||
|
||||
List<VariableCost> getVariableCosts();
|
||||
|
||||
boolean containsX();
|
||||
|
||||
int getX();
|
||||
|
||||
void setX(int x);
|
||||
/**
|
||||
* @param xValue announced X value
|
||||
* @param xMultiplier special X multiplier to change announced X value without pay increase, see Unbound Flourishing
|
||||
*/
|
||||
void setX(int xValue, int xMultiplier);
|
||||
|
||||
void load(String mana);
|
||||
|
||||
|
|
@ -41,7 +45,7 @@ public interface ManaCosts<T extends ManaCost> extends List<T>, ManaCost {
|
|||
static ManaCosts<ManaCost> removeVariableManaCost(ManaCosts<ManaCost> m) {
|
||||
return m.stream()
|
||||
.filter(mc -> !(mc instanceof VariableManaCost))
|
||||
.collect(Collectors.toCollection(ManaCostsImpl<ManaCost>::new));
|
||||
.collect(Collectors.toCollection(ManaCostsImpl::new));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.abilities.costs.mana;
|
||||
|
||||
import java.util.*;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
|
|
@ -20,9 +18,11 @@ import mage.players.Player;
|
|||
import mage.target.Targets;
|
||||
import mage.util.ManaUtil;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @param <T>
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements ManaCosts<T> {
|
||||
|
||||
|
|
@ -213,6 +213,11 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
|||
return variableCosts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsX() {
|
||||
return !getVariableCosts().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
int amount = 0;
|
||||
|
|
@ -224,10 +229,10 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setX(int x) {
|
||||
public void setX(int xValue, int xMultiplier) {
|
||||
List<VariableCost> variableCosts = getVariableCosts();
|
||||
if (!variableCosts.isEmpty()) {
|
||||
variableCosts.get(0).setAmount(x);
|
||||
variableCosts.get(0).setAmount(xValue * xMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -339,7 +344,7 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
|||
if (player != null) {
|
||||
game.undo(playerId);
|
||||
this.clearPaid();
|
||||
this.setX(referenceCosts.getX());
|
||||
this.setX(referenceCosts.getX(), 1); // TODO: checks Word of Command with Unbound Flourishing's X multiplier
|
||||
player.getManaPool().restoreMana(pool.getPoolBookmark());
|
||||
game.bookmarkState();
|
||||
}
|
||||
|
|
@ -378,15 +383,15 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
|||
} else if (!symbol.equals("X")) {
|
||||
this.add(new ColoredManaCost(ColoredManaSymbol.lookup(symbol.charAt(0))));
|
||||
} else // check X wasn't added before
|
||||
if (modifierForX == 0) {
|
||||
// count X occurence
|
||||
for (String s : symbols) {
|
||||
if (s.equals("X")) {
|
||||
modifierForX++;
|
||||
if (modifierForX == 0) {
|
||||
// count X occurence
|
||||
for (String s : symbols) {
|
||||
if (s.equals("X")) {
|
||||
modifierForX++;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.add(new VariableManaCost(modifierForX));
|
||||
} //TODO: handle multiple {X} and/or {Y} symbols
|
||||
this.add(new VariableManaCost(modifierForX));
|
||||
} //TODO: handle multiple {X} and/or {Y} symbols
|
||||
} else if (Character.isDigit(symbol.charAt(0))) {
|
||||
this.add(new MonoHybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(2))));
|
||||
} else if (symbol.contains("P")) {
|
||||
|
|
|
|||
|
|
@ -124,6 +124,13 @@ public class GameEvent implements Serializable {
|
|||
sourceId sourceId of the vehicle
|
||||
playerId the id of the controlling player
|
||||
*/
|
||||
X_MANA_ANNOUNCE,
|
||||
/* X_MANA_ANNOUNCE
|
||||
mana x-costs announced by players (X value can be changed by replace events like Unbound Flourishing)
|
||||
targetId id of the spell that's cast
|
||||
playerId player that casts the spell
|
||||
amount X multiplier to change X value, default 1
|
||||
*/
|
||||
CAST_SPELL,
|
||||
/* SPELL_CAST
|
||||
x-Costs are already defined
|
||||
|
|
|
|||
|
|
@ -564,7 +564,11 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
boolean putCardsOnTopOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder);
|
||||
|
||||
// set the value for X mana spells and abilities
|
||||
int announceXMana(int min, int max, String message, Game game, Ability ability);
|
||||
default int announceXMana(int min, int max, String message, Game game, Ability ability) {
|
||||
return announceXMana(min, max, 1, message, game, ability);
|
||||
}
|
||||
|
||||
int announceXMana(int min, int max, int multilier, String message, Game game, Ability ability);
|
||||
|
||||
// set the value for non mana X costs
|
||||
int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost);
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ public class StubPlayer extends PlayerImpl implements Player {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
|
||||
public int announceXMana(int min, int max, int multilier, String message, Game game, Ability ability) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue