mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 03:08:02 +00:00
Merge branch 'new-cards-2' into 'master'
Combat Calligrapher Closes #1795 See merge request core-developers/forge!4462
This commit is contained in:
@@ -3,23 +3,12 @@ package forge.ai;
|
|||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
|
import com.google.common.collect.*;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
|
|
||||||
import forge.StaticData;
|
import forge.StaticData;
|
||||||
import forge.card.CardStateName;
|
import forge.card.CardStateName;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
@@ -769,23 +758,10 @@ public abstract class GameState {
|
|||||||
}
|
}
|
||||||
game.fireEvent(new GameEventAttackersDeclared(attackingPlayer, attackersMap));
|
game.fireEvent(new GameEventAttackersDeclared(attackingPlayer, attackersMap));
|
||||||
|
|
||||||
if (!combat.getAttackers().isEmpty()) {
|
|
||||||
List<GameEntity> attackedTarget = Lists.newArrayList();
|
|
||||||
for (final Card c : combat.getAttackers()) {
|
for (final Card c : combat.getAttackers()) {
|
||||||
attackedTarget.add(combat.getDefenderByAttacker(c));
|
CombatUtil.checkDeclaredAttacker(game, c, combat, false);
|
||||||
}
|
|
||||||
final Map<AbilityKey, Object> runParams = Maps.newEnumMap(AbilityKey.class);
|
|
||||||
runParams.put(AbilityKey.Attackers, combat.getAttackers());
|
|
||||||
runParams.put(AbilityKey.AttackingPlayer, combat.getAttackingPlayer());
|
|
||||||
runParams.put(AbilityKey.AttackedTarget, attackedTarget);
|
|
||||||
game.getTriggerHandler().runTrigger(TriggerType.AttackersDeclared, runParams, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final Card c : combat.getAttackers()) {
|
|
||||||
CombatUtil.checkDeclaredAttacker(game, c, combat);
|
|
||||||
}
|
|
||||||
|
|
||||||
game.getTriggerHandler().resetActiveTriggers();
|
|
||||||
game.updateCombatForView();
|
game.updateCombatForView();
|
||||||
game.fireEvent(new GameEventCombatChanged());
|
game.fireEvent(new GameEventCombatChanged());
|
||||||
|
|
||||||
|
|||||||
@@ -352,8 +352,9 @@ public class CombatUtil {
|
|||||||
* @param c
|
* @param c
|
||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
*/
|
*/
|
||||||
public static void checkDeclaredAttacker(final Game game, final Card c, final Combat combat) {
|
public static void checkDeclaredAttacker(final Game game, final Card c, final Combat combat, boolean triggers) {
|
||||||
// Run triggers
|
// Run triggers
|
||||||
|
if (triggers) {
|
||||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||||
runParams.put(AbilityKey.Attacker, c);
|
runParams.put(AbilityKey.Attacker, c);
|
||||||
final List<Card> otherAttackers = combat.getAttackers();
|
final List<Card> otherAttackers = combat.getAttackers();
|
||||||
@@ -363,6 +364,7 @@ public class CombatUtil {
|
|||||||
runParams.put(AbilityKey.DefendingPlayer, combat.getDefenderPlayerByAttacker(c));
|
runParams.put(AbilityKey.DefendingPlayer, combat.getDefenderPlayerByAttacker(c));
|
||||||
runParams.put(AbilityKey.Defenders, combat.getDefenders());
|
runParams.put(AbilityKey.Defenders, combat.getDefenders());
|
||||||
game.getTriggerHandler().runTrigger(TriggerType.Attacks, runParams, false);
|
game.getTriggerHandler().runTrigger(TriggerType.Attacks, runParams, false);
|
||||||
|
}
|
||||||
|
|
||||||
c.getDamageHistory().setCreatureAttackedThisCombat(true);
|
c.getDamageHistory().setCreatureAttackedThisCombat(true);
|
||||||
c.getDamageHistory().clearNotAttackedSinceLastUpkeepOf();
|
c.getDamageHistory().clearNotAttackedSinceLastUpkeepOf();
|
||||||
|
|||||||
@@ -17,19 +17,11 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.phase;
|
package forge.game.phase;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
|
import com.google.common.collect.*;
|
||||||
import org.apache.commons.lang3.time.StopWatch;
|
import org.apache.commons.lang3.time.StopWatch;
|
||||||
|
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
|
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
@@ -621,9 +613,16 @@ public class PhaseHandler implements java.io.Serializable {
|
|||||||
|
|
||||||
// fire AttackersDeclared trigger
|
// fire AttackersDeclared trigger
|
||||||
if (!combat.getAttackers().isEmpty()) {
|
if (!combat.getAttackers().isEmpty()) {
|
||||||
List<GameEntity> attackedTarget = Lists.newArrayList();
|
List<GameEntity> attackedTarget = new ArrayList<>();
|
||||||
for (final Card c : combat.getAttackers()) {
|
for (GameEntity ge : combat.getDefenders()) {
|
||||||
attackedTarget.add(combat.getDefenderByAttacker(c));
|
if (!combat.getAttackersOf(ge).isEmpty()) {
|
||||||
|
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||||
|
runParams.put(AbilityKey.Attackers, combat.getAttackersOf(ge));
|
||||||
|
runParams.put(AbilityKey.AttackingPlayer, combat.getAttackingPlayer());
|
||||||
|
runParams.put(AbilityKey.AttackedTarget, ge);
|
||||||
|
attackedTarget.add(ge);
|
||||||
|
game.getTriggerHandler().runTrigger(TriggerType.AttackersDeclaredOneTarget, runParams, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||||
runParams.put(AbilityKey.Attackers, combat.getAttackers());
|
runParams.put(AbilityKey.Attackers, combat.getAttackers());
|
||||||
@@ -633,7 +632,7 @@ public class PhaseHandler implements java.io.Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final Card c : combat.getAttackers()) {
|
for (final Card c : combat.getAttackers()) {
|
||||||
CombatUtil.checkDeclaredAttacker(game, c, combat);
|
CombatUtil.checkDeclaredAttacker(game, c, combat, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
game.getTriggerHandler().resetActiveTriggers();
|
game.getTriggerHandler().resetActiveTriggers();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public enum TriggerType {
|
|||||||
AttackerBlockedOnce(TriggerAttackerBlockedOnce.class),
|
AttackerBlockedOnce(TriggerAttackerBlockedOnce.class),
|
||||||
AttackerBlockedByCreature(TriggerAttackerBlockedByCreature.class),
|
AttackerBlockedByCreature(TriggerAttackerBlockedByCreature.class),
|
||||||
AttackersDeclared(TriggerAttackersDeclared.class),
|
AttackersDeclared(TriggerAttackersDeclared.class),
|
||||||
|
AttackersDeclaredOneTarget(TriggerAttackersDeclared.class),
|
||||||
AttackerUnblocked(TriggerAttackerUnblocked.class),
|
AttackerUnblocked(TriggerAttackerUnblocked.class),
|
||||||
AttackerUnblockedOnce(TriggerAttackerUnblockedOnce.class),
|
AttackerUnblockedOnce(TriggerAttackerUnblockedOnce.class),
|
||||||
Attacks(TriggerAttacks.class),
|
Attacks(TriggerAttacks.class),
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ManaCost:1 W
|
|||||||
Types:Artifact Equipment
|
Types:Artifact Equipment
|
||||||
S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 2 | AddToughness$ 2 | Description$ Equipped creature gets +2/+2.
|
S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 2 | AddToughness$ 2 | Description$ Equipped creature gets +2/+2.
|
||||||
T:Mode$ Attacks | ValidCard$ Card.AttachedBy | Attacked$ Player.withMostLife | Execute$ TrigToken | TriggerDescription$ Whenever equipped creature attacks the player with the most life or tied for most life, create a 4/4 white Angel creature token with flying that's tapped and attacking that player.
|
T:Mode$ Attacks | ValidCard$ Card.AttachedBy | Attacked$ Player.withMostLife | Execute$ TrigToken | TriggerDescription$ Whenever equipped creature attacks the player with the most life or tied for most life, create a 4/4 white Angel creature token with flying that's tapped and attacking that player.
|
||||||
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_4_4_angel_flying | TokenOwner$ You | TokenTapped$ True | TokenAttacking$ True
|
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_4_4_angel_flying | TokenOwner$ You | TokenTapped$ True | TokenAttacking$ TriggeredDefender
|
||||||
SVar:HasAttackEffect:TRUE
|
SVar:HasAttackEffect:TRUE
|
||||||
K:Equip:4
|
K:Equip:4
|
||||||
DeckHas:Ability$Token
|
DeckHas:Ability$Token
|
||||||
|
|||||||
10
forge-gui/res/cardsfolder/upcoming/combat_calligrapher.txt
Normal file
10
forge-gui/res/cardsfolder/upcoming/combat_calligrapher.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Name:Combat Calligrapher
|
||||||
|
ManaCost:3 W
|
||||||
|
Types:Creature Bird Cleric
|
||||||
|
PT:3/3
|
||||||
|
K:Flying
|
||||||
|
S:Mode$ CantAttack | ValidCard$ Creature.Inkling | Target$ You,Planeswalker.YouCtrl | Description$ Inklings can't attack you or planeswalkers you control.
|
||||||
|
T:Mode$ AttackersDeclaredOneTarget | AttackedTarget$ Opponent | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever a player attacks one of your opponents, that attacking player creates a tapped 2/1 white and black Inkling creature token with flying that's attacking that opponent.
|
||||||
|
SVar:TrigToken:DB$ Token | TokenScript$ wb_2_1_inkling_flying | TokenOwner$ TriggeredAttackingPlayer | TokenTapped$ True | TokenAttacking$ TriggeredAttackedTarget
|
||||||
|
DeckHas:Ability$Token
|
||||||
|
Oracle:Flying\nInklings can't attack you or planeswalkers you control.\nWhenever a player attacks one of your opponents, that attacking player creates a tapped 2/1 white and black Inkling creature token with flying that's attacking that opponent.
|
||||||
Reference in New Issue
Block a user