mirror of
https://github.com/magefree/mage.git
synced 2025-12-26 13:32:06 -08:00
[AFR] Implementing Class enchantments (ready for review) (#7992)
* [AFR] Implemented Druid Class * [AFR] Implemented Wizard Class * [AFR] Implemented Cleric Class * [AFR] Implemented Fighter Class * reworked class ability implementation * fixed an error with setting class level * small reworking of class triggers * added class level hint * added tests * small change * added common class for reminder text
This commit is contained in:
parent
d00765c2d5
commit
5b88484cb6
17 changed files with 884 additions and 5 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package mage.abilities.common;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.Zone;
|
||||
|
|
@ -64,6 +65,7 @@ public class AttacksCreatureYouControlTriggeredAbility extends TriggeredAbilityI
|
|||
if (setTargetPointer) {
|
||||
this.getEffects().setTargetPointer(new FixedTarget(event.getSourceId(), game));
|
||||
}
|
||||
this.getEffects().setValue("attackerRef", new MageObjectReference(sourcePermanent, game));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class BecomesClassLevelTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private final int level;
|
||||
|
||||
public BecomesClassLevelTriggeredAbility(Effect effect, int level) {
|
||||
super(Zone.BATTLEFIELD, effect);
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
private BecomesClassLevelTriggeredAbility(final BecomesClassLevelTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.level = ability.level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.GAINS_CLASS_LEVEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
return event.getAmount() == level && event.getSourceId().equals(getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomesClassLevelTriggeredAbility copy() {
|
||||
return new BecomesClassLevelTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When this Class becomes level " + level + ", " + super.getRule();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class GainClassAbilitySourceEffect extends ContinuousEffectImpl implements SourceEffect {
|
||||
|
||||
private final Ability ability;
|
||||
private final int level;
|
||||
|
||||
public GainClassAbilitySourceEffect(Effect effect, int level) {
|
||||
this(new SimpleStaticAbility(effect), level);
|
||||
}
|
||||
|
||||
public GainClassAbilitySourceEffect(Ability ability, int level) {
|
||||
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
|
||||
staticText = ability.getRule();
|
||||
this.ability = ability;
|
||||
this.level = level;
|
||||
this.ability.setRuleVisible(false);
|
||||
generateGainAbilityDependencies(ability, null);
|
||||
}
|
||||
|
||||
private GainClassAbilitySourceEffect(final GainClassAbilitySourceEffect effect) {
|
||||
super(effect);
|
||||
this.level = effect.level;
|
||||
this.ability = effect.ability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (permanent == null || permanent.getClassLevel() < level) {
|
||||
return false;
|
||||
}
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GainClassAbilitySourceEffect copy() {
|
||||
return new GainClassAbilitySourceEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package mage.abilities.effects.common.cost;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.constants.CostModificationType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
|
|
@ -8,22 +9,28 @@ import mage.game.Game;
|
|||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Styxo
|
||||
*/
|
||||
public class AbilitiesCostReductionControllerEffect extends CostModificationEffectImpl {
|
||||
|
||||
private final Class activatedAbility;
|
||||
private final Class<? extends ActivatedAbility> activatedAbility;
|
||||
private final int amount;
|
||||
|
||||
public AbilitiesCostReductionControllerEffect(Class activatedAbility, String activatedAbilityName) {
|
||||
public AbilitiesCostReductionControllerEffect(Class<? extends ActivatedAbility> activatedAbility, String activatedAbilityName) {
|
||||
this(activatedAbility, activatedAbilityName, 1);
|
||||
}
|
||||
|
||||
public AbilitiesCostReductionControllerEffect(Class<? extends ActivatedAbility> activatedAbility, String activatedAbilityName, int amount) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
this.activatedAbility = activatedAbility;
|
||||
staticText = activatedAbilityName + " costs you pay cost {1} less";
|
||||
staticText = activatedAbilityName + " costs you pay cost {" + amount + "} less";
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public AbilitiesCostReductionControllerEffect(AbilitiesCostReductionControllerEffect effect) {
|
||||
super(effect);
|
||||
this.activatedAbility = effect.activatedAbility;
|
||||
this.amount = effect.amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -33,7 +40,7 @@ public class AbilitiesCostReductionControllerEffect extends CostModificationEffe
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
CardUtil.reduceCost(abilityToModify, 1);
|
||||
CardUtil.reduceCost(abilityToModify, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package mage.abilities.hint.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public enum ClassLevelHint implements Hint {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public String getText(Game game, Ability ability) {
|
||||
Permanent permanent = ability.getSourcePermanentIfItStillExists(game);
|
||||
if (permanent == null) {
|
||||
return null;
|
||||
}
|
||||
return "Class level: " + permanent.getClassLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLevelHint copy() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbilityImpl;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class ClassLevelAbility extends ActivatedAbilityImpl {
|
||||
|
||||
private final int level;
|
||||
private final String manaString;
|
||||
|
||||
public ClassLevelAbility(int level, String manaString) {
|
||||
super(Zone.BATTLEFIELD, new SetClassLevelEffect(level), new ManaCostsImpl<>(manaString));
|
||||
this.level = level;
|
||||
this.manaString = manaString;
|
||||
setTiming(TimingRule.SORCERY);
|
||||
}
|
||||
|
||||
private ClassLevelAbility(final ClassLevelAbility ability) {
|
||||
super(ability);
|
||||
this.level = ability.level;
|
||||
this.manaString = ability.manaString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLevelAbility copy() {
|
||||
return new ClassLevelAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return manaString + ": Level " + level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivationStatus canActivate(UUID playerId, Game game) {
|
||||
Permanent permanent = getSourcePermanentIfItStillExists(game);
|
||||
if (permanent != null && permanent.getClassLevel() == level - 1) {
|
||||
return super.canActivate(playerId, game);
|
||||
}
|
||||
return ActivationStatus.getFalse();
|
||||
}
|
||||
}
|
||||
|
||||
class SetClassLevelEffect extends OneShotEffect {
|
||||
|
||||
private final int level;
|
||||
|
||||
SetClassLevelEffect(int level) {
|
||||
super(Outcome.Benefit);
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
private SetClassLevelEffect(final SetClassLevelEffect effect) {
|
||||
super(effect);
|
||||
this.level = effect.level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SetClassLevelEffect copy() {
|
||||
return new SetClassLevelEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (permanent == null || !permanent.setClassLevel(level)) {
|
||||
return false;
|
||||
}
|
||||
game.fireEvent(GameEvent.getEvent(
|
||||
GameEvent.EventType.GAINS_CLASS_LEVEL, source.getSourceId(),
|
||||
source, source.getControllerId(), level
|
||||
));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.hint.common.ClassLevelHint;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class ClassReminderAbility extends StaticAbility {
|
||||
|
||||
public ClassReminderAbility() {
|
||||
super(Zone.ALL, null);
|
||||
this.addHint(ClassLevelHint.instance);
|
||||
}
|
||||
|
||||
private ClassReminderAbility(final ClassReminderAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassReminderAbility copy() {
|
||||
return new ClassReminderAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "<i>(Gain the next level as a sorcery to add its ability.)</i>";
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ public enum SubType {
|
|||
// 205.3h Enchantments have their own unique set of subtypes; these subtypes are called enchantment types.
|
||||
AURA("Aura", SubTypeSet.EnchantmentType),
|
||||
CARTOUCHE("Cartouche", SubTypeSet.EnchantmentType),
|
||||
CLASS("Class", SubTypeSet.EnchantmentType),
|
||||
CURSE("Curse", SubTypeSet.EnchantmentType),
|
||||
RUNE("Rune", SubTypeSet.EnchantmentType),
|
||||
SAGA("Saga", SubTypeSet.EnchantmentType),
|
||||
|
|
|
|||
|
|
@ -340,6 +340,7 @@ public class GameEvent implements Serializable {
|
|||
*/
|
||||
BECOMES_EXERTED,
|
||||
BECOMES_RENOWNED,
|
||||
GAINS_CLASS_LEVEL,
|
||||
/* BECOMES_MONARCH
|
||||
targetId playerId of the player that becomes the monarch
|
||||
sourceId id of the source object that created that effect, if no effect exist it's null
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
void setRenowned(boolean value);
|
||||
|
||||
int getClassLevel();
|
||||
|
||||
boolean setClassLevel(int classLevel);
|
||||
|
||||
void setCardNumber(String cid);
|
||||
|
||||
void setExpansionSetCode(String expansionSetCode);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
protected boolean renowned;
|
||||
protected boolean manifested = false;
|
||||
protected boolean morphed = false;
|
||||
protected int classLevel = 1;
|
||||
protected UUID originalControllerId;
|
||||
protected UUID controllerId;
|
||||
protected UUID beforeResetControllerId;
|
||||
|
|
@ -163,6 +164,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
this.transformed = permanent.transformed;
|
||||
this.monstrous = permanent.monstrous;
|
||||
this.renowned = permanent.renowned;
|
||||
this.classLevel = permanent.classLevel;
|
||||
this.pairedPermanent = permanent.pairedPermanent;
|
||||
this.bandedCards.addAll(permanent.bandedCards);
|
||||
this.timesLoyaltyUsed = permanent.timesLoyaltyUsed;
|
||||
|
|
@ -1519,6 +1521,20 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
this.renowned = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClassLevel() {
|
||||
return classLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setClassLevel(int classLevel) {
|
||||
if (this.classLevel == classLevel - 1) {
|
||||
this.classLevel = classLevel;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPairedCard(MageObjectReference pairedCard) {
|
||||
this.pairedPermanent = pairedCard;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue