forked from External/mage
Reworked cost adjuster logic for better support of X and cost modification effects:
Improves: * refactor: split CostAdjuster logic in multiple parts - prepare X, prepare cost, increase cost, reduce cost; * refactor: improved VariableManaCost to support min/max values, playable and AI calculations, test framework; * refactor: improved EarlyTargetCost to support mana costs too (related to #13023); * refactor: migrated some cards with CostAdjuster and X to EarlyTargetCost (Knollspine Invocation, etc - related to #13023); * refactor: added shared code for "As an additional cost to cast this spell, discard X creature cards"; * refactor: added shared code for "X is the converted mana cost of the exiled card"; * tests: added dozens tests with cost adjusters; Bug fixes: * game: fixed that some cards with CostAdjuster ignore min/max limits for X (allow to choose any X, example: Scorched Earth, Open The Way); * game: fixed that some cards ask to announce already defined X values (example: Bargaining Table); * game: fixed that some cards with CostAdjuster do not support combo with other cost modification effects; * game, gui: fixed missing game logs about predefined X values; * game, gui: fixed wrong X icon for predefined X values; Test framework: * test framework: added X min/max check for wrong values; * test framework: added X min/max info in miss X value announce; * test framework: added check to find duplicated effect bugs (see assertNoDuplicatedEffects); Cards: * Open The Way - fixed that it allow to choose any X without limits (close #12810); * Unbound Flourishing - improved combo support for activated abilities with predefined X mana costs like Bargaining Table;
This commit is contained in:
parent
13a832ae00
commit
bae3089abb
100 changed files with 1519 additions and 449 deletions
|
|
@ -1,24 +1,86 @@
|
|||
package mage.abilities.costs;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.CostModificationType;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
* Dynamic costs implementation to control {X} or other costs, can be used in spells and abilities
|
||||
* <p>
|
||||
* Possible use cases:
|
||||
* - define {X} costs like X cards to discard (mana and non-mana values);
|
||||
* - define {X} limits before announce (to help in UX and AI logic)
|
||||
* - define any dynamic costs
|
||||
* - use as simple cost increase/reduce effect
|
||||
* <p>
|
||||
* Calls order by game engine:
|
||||
* - ... early cost target selection for EarlyTargetCost ...
|
||||
* - prepareX
|
||||
* - ... x announce ...
|
||||
* - prepareCost
|
||||
* - increaseCost
|
||||
* - reduceCost
|
||||
* - ... normal target selection and payment ...
|
||||
*
|
||||
* @author TheElk801, JayDi85
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface CostAdjuster extends Serializable {
|
||||
|
||||
/**
|
||||
* Must check playable and real cast states.
|
||||
* Example: if it need stack related info (like real targets) then must check two states (game.inCheckPlayableState):
|
||||
* 1. In playable state it must check all possible use cases (e.g. allow to reduce on any available target and modes)
|
||||
* 2. In real cast state it must check current use case (e.g. real selected targets and modes)
|
||||
*
|
||||
* @param ability
|
||||
* @param game
|
||||
* Prepare {X} costs settings or define auto-announced mana values
|
||||
* <p>
|
||||
* Usage example:
|
||||
* - define auto-announced mana value {X} by ability.setVariableCostsValue
|
||||
* - define possible {X} settings by ability.setVariableCostsMinMax
|
||||
*/
|
||||
void adjustCosts(Ability ability, Game game);
|
||||
default void prepareX(Ability ability, Game game) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare any dynamic costs
|
||||
* <p>
|
||||
* Usage example:
|
||||
* - add real cost after {X} mana value announce by CardUtil.getSourceCostsTagX
|
||||
* - add dynamic cost from game data
|
||||
*/
|
||||
default void prepareCost(Ability ability, Game game) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple cost reduction effect
|
||||
*/
|
||||
default void reduceCost(Ability ability, Game game) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple cost increase effect
|
||||
*/
|
||||
default void increaseCost(Ability ability, Game game) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation. Override reduceCost or increaseCost instead
|
||||
* TODO: make it private after java 9+ migrate
|
||||
*/
|
||||
default void modifyCost(Ability ability, Game game, CostModificationType costModificationType) {
|
||||
switch (costModificationType) {
|
||||
case REDUCE_COST:
|
||||
reduceCost(ability, game);
|
||||
break;
|
||||
case INCREASE_COST:
|
||||
increaseCost(ability, game);
|
||||
break;
|
||||
case SET_COST:
|
||||
// do nothing
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown mod type: " + costModificationType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue