magarena/src/magic/model/action/DealDamageAction.java

130 lines
4.8 KiB
Java

package magic.model.action;
import magic.model.MagicAbility;
import magic.model.MagicCounterType;
import magic.model.MagicDamage;
import magic.model.MagicGame;
import magic.model.MagicPermanent;
import magic.model.MagicPermanentState;
import magic.model.MagicPlayer;
import magic.model.MagicPlayerState;
import magic.model.MagicSource;
import magic.model.MagicType;
import magic.model.event.MagicRedirectDamageEvent;
import magic.model.target.MagicTarget;
import magic.model.trigger.MagicTriggerType;
public class DealDamageAction extends MagicAction {
private static final int UNINIT = Integer.MIN_VALUE;
private final MagicDamage damage;
private MagicTarget target;
private int oldDamage = UNINIT;
public DealDamageAction(final MagicSource source, MagicTarget target, final int amt) {
this(new MagicDamage(source, target, amt), null);
}
public DealDamageAction(final MagicDamage damage) {
this(damage, null);
}
public static final DealDamageAction NoRedirect(final MagicDamage damage) {
return new DealDamageAction(damage, damage.getTarget());
}
private DealDamageAction(final MagicDamage aDamage, final MagicTarget aTarget) {
damage = aDamage;
target = aTarget;
}
@Override
public void doAction(final MagicGame game) {
game.executeTrigger(MagicTriggerType.IfDamageWouldBeDealt,damage);
/*
306.7. If damage would be dealt to a player by a source
controlled by an opponent, that opponent may have that source deal that
damage to a planeswalker the first player controls instead.
*/
// in immediate mode, always deal damage to player
if (!game.isImmediate() &&
target == null &&
damage.getTarget().isPlayer() &&
damage.getSource().getController() != damage.getTarget() &&
damage.getTarget().getController().controlsPermanent(MagicType.Planeswalker)) {
game.addEvent(new MagicRedirectDamageEvent(damage));
return;
}
target = damage.getTarget();
/*
119.1. Objects can deal damage to creatures, planeswalkers, and players.
*/
if (!target.isCreaturePermanent() &&
!target.isPlaneswalkerPermanent() &&
!target.isPlayer()) {
return;
}
damage.setDealtAmount(0);
final int dealtAmount=damage.getAmount();
if (dealtAmount <= 0) {
return;
}
final MagicSource source=damage.getSource();
if (target.isPlaneswalkerPermanent()) {
final MagicPermanent targetPermanent=(MagicPermanent)target;
game.doAction(new ChangeCountersAction(damage.getSource().getController(),targetPermanent,MagicCounterType.Loyalty,-dealtAmount));
}
if (target.isCreaturePermanent()) {
final MagicPermanent targetPermanent=(MagicPermanent)target;
if (damage.hasNoRegeneration()) {
game.doAction(ChangeStateAction.Set(targetPermanent,MagicPermanentState.CannotBeRegenerated));
}
if (source.hasAbility(MagicAbility.Wither)||source.hasAbility(MagicAbility.Infect)) {
game.doAction(new ChangeCountersAction(damage.getSource().getController(),targetPermanent,MagicCounterType.MinusOne,dealtAmount));
} else {
oldDamage=targetPermanent.getDamage();
targetPermanent.setDamage(oldDamage+dealtAmount);
}
if (source.hasAbility(MagicAbility.Deathtouch)) {
game.doAction(ChangeStateAction.Set(targetPermanent,MagicPermanentState.Destroyed));
}
game.doAction(ChangeStateAction.Set(targetPermanent,MagicPermanentState.WasDealtDamage));
}
if (target.isPlayer()) {
final MagicPlayer targetPlayer = (MagicPlayer)target;
if (source.hasAbility(MagicAbility.Infect)) {
game.doAction(new ChangeCountersAction(damage.getSource().getController(),targetPlayer, MagicCounterType.Poison, dealtAmount));
} else {
game.doAction(new ChangeLifeAction(targetPlayer,-dealtAmount,true));
}
game.doAction(new ChangePlayerStateAction(targetPlayer,MagicPlayerState.WasDealtDamage));
}
damage.setDealtAmount(dealtAmount);
if (source.hasAbility(MagicAbility.Lifelink)) {
game.doAction(new ChangeLifeAction(source.getController(),dealtAmount));
}
game.executeTrigger(MagicTriggerType.WhenDamageIsDealt,damage);
game.setStateCheckRequired();
}
@Override
public void undoAction(final MagicGame game) {
if (oldDamage!=UNINIT) {
final MagicPermanent targetPermanent=(MagicPermanent)target;
targetPermanent.setDamage(oldDamage);
}
}
}