@Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { PreventionEffectData preventionResult = preventDamageAction(event, source, game); if (preventionResult.getPreventedDamage() > 0) { Permanent redirectTo = game.getPermanent(getTargetPointer().getFirst(game, source)); if (redirectTo != null) { game.informPlayers( "Dealing " + preventionResult.getPreventedDamage() + " to " + redirectTo.getLogName() + " instead."); DamageEvent damageEvent = (DamageEvent) event; redirectTo.damage( preventionResult.getPreventedDamage(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects()); } discard(); // (only once) } return false; }
@Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { DamageEvent damageEvent = (DamageEvent) event; Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (sourcePermanent != null) { // get name of old target Permanent targetPermanent = game.getPermanent(event.getTargetId()); StringBuilder message = new StringBuilder(); message.append(sourcePermanent.getName()).append(": gets "); message.append(damageEvent.getAmount()).append(" damage redirected from "); if (targetPermanent != null) { message.append(targetPermanent.getName()); } else { Player targetPlayer = game.getPlayer(event.getTargetId()); if (targetPlayer != null) { message.append(targetPlayer.getName()); } else { message.append("unknown"); } } game.informPlayers(message.toString()); // redirect damage this.used = true; sourcePermanent.damage( damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isPreventable(), damageEvent.isCombatDamage(), event.getAppliedEffects()); return true; } return false; }
public boolean replaceEvent(GameEvent event, Game game) { boolean caught = false; HashMap<UUID, HashSet<UUID>> consumed = new HashMap<>(); do { HashMap<ReplacementEffect, HashSet<Ability>> rEffects = getApplicableReplacementEffects(event, game); // Remove all consumed effects (ability dependant) for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext(); ) { ReplacementEffect entry = it1.next(); if (consumed.containsKey(entry.getId())) { HashSet<UUID> consumedAbilitiesIds = consumed.get(entry.getId()); if (rEffects.get(entry) == null || consumedAbilitiesIds.size() == rEffects.get(entry).size()) { it1.remove(); } else { Iterator it = rEffects.get(entry).iterator(); while (it.hasNext()) { Ability ability = (Ability) it.next(); if (consumedAbilitiesIds.contains(ability.getId())) { it.remove(); } } } } } // no effects left, quit if (rEffects.isEmpty()) { break; } int index; boolean onlyOne = false; if (rEffects.size() == 1) { ReplacementEffect effect = rEffects.keySet().iterator().next(); HashSet<Ability> abilities; if (effect.getEffectType().equals(EffectType.REPLACEMENT)) { abilities = replacementEffects.getAbility(effect.getId()); } else { abilities = preventionEffects.getAbility(effect.getId()); } if (abilities == null || abilities.size() == 1) { onlyOne = true; } } if (onlyOne) { index = 0; } else { // 20100716 - 616.1c Player player = game.getPlayer(event.getPlayerId()); index = player.chooseReplacementEffect(getReplacementEffectsTexts(rEffects, game), game); } // get the selected effect int checked = 0; ReplacementEffect rEffect = null; Ability rAbility = null; for (Map.Entry<ReplacementEffect, HashSet<Ability>> entry : rEffects.entrySet()) { if (entry.getValue() == null) { if (checked == index) { rEffect = entry.getKey(); break; } else { checked++; } } else { HashSet<Ability> abilities = entry.getValue(); int size = abilities.size(); if (index > (checked + size - 1)) { checked += size; } else { rEffect = entry.getKey(); Iterator it = abilities.iterator(); while (it.hasNext() && rAbility == null) { if (checked == index) { rAbility = (Ability) it.next(); } else { it.next(); checked++; } } break; } } } if (rEffect != null) { event.getAppliedEffects().add(rEffect.getId()); caught = rEffect.replaceEvent(event, rAbility, game); } if (caught) { // Event was completely replaced -> stop applying effects to it break; } // add the applied effect to the consumed effects if (rEffect != null) { if (consumed.containsKey(rEffect.getId())) { HashSet<UUID> set = consumed.get(rEffect.getId()); if (rAbility != null) { if (!set.contains(rAbility.getId())) { set.add(rAbility.getId()); } } } else { HashSet<UUID> set = new HashSet<>(); if (rAbility != null) { // in case of AuraReplacementEffect or PlaneswalkerReplacementEffect there // is no Ability set.add(rAbility.getId()); } consumed.put(rEffect.getId(), set); } } // Must be called here for some effects to be able to work correctly // TODO: add info which effects need that call game.applyEffects(); } while (true); return caught; }
/** * @param event * @param game * @return a list of all {@link ReplacementEffect} that apply to the current event */ private HashMap<ReplacementEffect, HashSet<Ability>> getApplicableReplacementEffects( GameEvent event, Game game) { HashMap<ReplacementEffect, HashSet<Ability>> replaceEffects = new HashMap<>(); if (planeswalkerRedirectionEffect.checksEventType(event, game) && planeswalkerRedirectionEffect.applies(event, null, game)) { replaceEffects.put(planeswalkerRedirectionEffect, null); } if (auraReplacementEffect.checksEventType(event, game) && auraReplacementEffect.applies(event, null, game)) { replaceEffects.put(auraReplacementEffect, null); } // boolean checkLKI = event.getType().equals(EventType.ZONE_CHANGE) || // event.getType().equals(EventType.DESTROYED_PERMANENT); // get all applicable transient Replacement effects for (ReplacementEffect effect : replacementEffects) { if (!effect.checksEventType(event, game)) { continue; } if (event.getAppliedEffects() != null && event.getAppliedEffects().contains(effect.getId())) { // Effect already applied to this event, ignore it // TODO: Handle also gained effect that are connected to different abilities. continue; } HashSet<Ability> abilities = replacementEffects.getAbility(effect.getId()); HashSet<Ability> applicableAbilities = new HashSet<>(); for (Ability ability : abilities) { // for replacment effects of static abilities do not use LKI to check if to apply if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { if (!game.getScopeRelevant() || effect.hasSelfScope() || !event.getTargetId().equals(ability.getSourceId())) { if (effect.applies(event, ability, game)) { applicableAbilities.add(ability); } } } } } if (!applicableAbilities.isEmpty()) { replaceEffects.put(effect, applicableAbilities); } } for (PreventionEffect effect : preventionEffects) { if (!effect.checksEventType(event, game)) { continue; } if (event.getAppliedEffects() != null && event.getAppliedEffects().contains(effect.getId())) { // Effect already applied to this event, ignore it // TODO: Handle also gained effect that are connected to different abilities. continue; } HashSet<Ability> abilities = preventionEffects.getAbility(effect.getId()); HashSet<Ability> applicableAbilities = new HashSet<>(); for (Ability ability : abilities) { if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { if (effect.applies(event, ability, game)) { applicableAbilities.add(ability); } } } } if (!applicableAbilities.isEmpty()) { replaceEffects.put((ReplacementEffect) effect, applicableAbilities); } } return replaceEffects; }