Questing Beast - fixed rollback error on damage prevent (#6116);

This commit is contained in:
Oleg Agafonov 2019-12-24 10:53:51 +04:00
parent 5cb040607e
commit 9cf1ee2f42
32 changed files with 260 additions and 223 deletions

View file

@ -1,8 +1,5 @@
package mage.abilities.effects.common;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
@ -10,14 +7,19 @@ import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.PreventionEffectImpl;
import mage.constants.Duration;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.events.PreventDamageEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetAmount;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public class PreventDamageToTargetMultiAmountEffect extends PreventionEffectImpl {
@ -77,7 +79,7 @@ public class PreventDamageToTargetMultiAmountEffect extends PreventionEffectImpl
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
int targetAmount = targetAmountMap.get(event.getTargetId());
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, event.getTargetId(), source.getSourceId(), source.getControllerId(), event.getAmount(), false);
GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage());
if (!game.replaceEvent(preventEvent)) {
if (event.getAmount() >= targetAmount) {
int damage = targetAmount;

View file

@ -2638,7 +2638,7 @@ public abstract class GameImpl implements Game, Serializable {
return result;
}
DamageEvent damageEvent = (DamageEvent) event;
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, damageEvent.getTargetId(), damageEvent.getSourceId(), source.getControllerId(), damageEvent.getAmount(), false);
GameEvent preventEvent = new PreventDamageEvent(damageEvent.getTargetId(), damageEvent.getSourceId(), source.getControllerId(), damageEvent.getAmount(), damageEvent.isCombatDamage());
if (game.replaceEvent(preventEvent)) {
result.setReplaced(true);
return result;

View file

@ -22,6 +22,7 @@ public class GameEvent implements Serializable {
// for counters: event is result of effect (+1 from planeswalkers is cost, not effect)
// for combat damage: event is preventable damage
// for discard: event is result of effect (1) or result of cost (0)
// for prevent damage: try to prevent combat damage (1) or other damage (0)
protected boolean flag;
protected String data;
protected Zone zone;

View file

@ -0,0 +1,17 @@
package mage.game.events;
import java.util.UUID;
/**
* @author JayDi85
*/
public class PreventDamageEvent extends GameEvent {
public PreventDamageEvent(UUID targetId, UUID sourceId, UUID playerId, int damageToPrevent, boolean isCombatDamage) {
super(EventType.PREVENT_DAMAGE, targetId, sourceId, playerId, damageToPrevent, isCombatDamage);
}
public boolean isCombatDamage() {
return flag;
}
}

View file

@ -1,6 +1,5 @@
package mage.game.permanent;
import java.util.*;
import mage.MageObject;
import mage.MageObjectReference;
import mage.ObjectColor;
@ -38,6 +37,8 @@ import mage.util.GameLog;
import mage.util.ThreadLocalStringBuilder;
import org.apache.log4j.Logger;
import java.util.*;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -761,7 +762,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
this.attachedTo = attachToObjectId;
this.attachedToZoneChangeCounter = game.getState().getZoneChangeCounter(attachToObjectId);
for (Ability ability : this.getAbilities()) {
for (Iterator<Effect> ite = ability.getEffects(game, EffectType.CONTINUOUS).iterator(); ite.hasNext();) {
for (Iterator<Effect> ite = ability.getEffects(game, EffectType.CONTINUOUS).iterator(); ite.hasNext(); ) {
ContinuousEffect effect = (ContinuousEffect) ite.next();
game.getContinuousEffects().setOrder(effect);
// It's important to update the timestamp of the copied effect in ContinuousEffects because it does the action
@ -816,8 +817,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
* @param game
* @param preventable
* @param combat
* @param markDamage If true, damage will be dealt later in applyDamage
* method
* @param markDamage If true, damage will be dealt later in applyDamage
* method
* @return
*/
private int damage(int damageAmount, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
@ -969,7 +970,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
private int checkProtectionAbilities(GameEvent event, UUID sourceId, Game game) {
MageObject source = game.getObject(sourceId);
if (source != null && hasProtectionFrom(source, game)) {
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, this.objectId, sourceId, this.controllerId, event.getAmount(), false);
GameEvent preventEvent = new PreventDamageEvent(this.objectId, sourceId, this.controllerId, event.getAmount(), ((DamageEvent) event).isCombatDamage());
if (!game.replaceEvent(preventEvent)) {
int preventedDamage = event.getAmount();
event.setAmount(0);