mirror of
https://github.com/magefree/mage.git
synced 2025-12-25 13:02:06 -08:00
Merge branch 'master' of github.com:rsypen/mage into fix_tests_not_passing
This commit is contained in:
commit
29a889b236
58 changed files with 2327 additions and 150 deletions
|
|
@ -27,11 +27,12 @@
|
|||
*/
|
||||
package mage.abilities.common;
|
||||
|
||||
import mage.constants.Zone;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.EntersTheBattlefieldEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
@ -51,7 +52,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
|
|||
/**
|
||||
* optional = false<br>
|
||||
* opponentController = false
|
||||
*
|
||||
*
|
||||
* @param effect
|
||||
*/
|
||||
public CreatureEntersBattlefieldTriggeredAbility(Effect effect) {
|
||||
|
|
@ -60,7 +61,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
|
|||
|
||||
/**
|
||||
* opponentController = false
|
||||
*
|
||||
*
|
||||
* @param effect
|
||||
* @param optional
|
||||
*/
|
||||
|
|
@ -69,7 +70,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param effect
|
||||
* @param optional
|
||||
* @param opponentController
|
||||
|
|
@ -78,7 +79,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
|
|||
this(Zone.BATTLEFIELD, effect, optional, opponentController);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param zone
|
||||
* @param effect
|
||||
|
|
@ -104,7 +105,6 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public CreatureEntersBattlefieldTriggeredAbility(CreatureEntersBattlefieldTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.opponentController = ability.opponentController;
|
||||
|
|
@ -118,7 +118,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
|
|||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
|
||||
if (filter.match(permanent, sourceId, controllerId, game)
|
||||
&& (permanent.getControllerId().equals(this.controllerId) ^ opponentController)) {
|
||||
if (!this.getTargets().isEmpty()) {
|
||||
|
|
@ -137,7 +137,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever a " + filter.getMessage() +" enters the battlefield under "
|
||||
return "Whenever a " + filter.getMessage() + " enters the battlefield under "
|
||||
+ (opponentController ? "an opponent's control, " : "your control, ")
|
||||
+ super.getRule();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,9 @@ public class DoIfCostPaid extends OneShotEffect {
|
|||
|
||||
public DoIfCostPaid(Effect effect, Cost cost, String chooseUseText, boolean optional) {
|
||||
super(Outcome.Benefit);
|
||||
this.executingEffects.add(effect);
|
||||
if (effect != null) {
|
||||
this.executingEffects.add(effect);
|
||||
}
|
||||
this.cost = cost;
|
||||
this.chooseUseText = chooseUseText;
|
||||
this.optional = optional;
|
||||
|
|
@ -74,10 +76,9 @@ public class DoIfCostPaid extends OneShotEffect {
|
|||
message = CardUtil.replaceSourceName(message, mageObject.getLogName());
|
||||
boolean result = true;
|
||||
if (cost.canPay(source, source.getSourceId(), player.getId(), game)
|
||||
&& (!optional || player.chooseUse(executingEffects.get(0).getOutcome(), message, source, game))) {
|
||||
&& executingEffects.size() > 0 && (!optional || player.chooseUse(executingEffects.get(0).getOutcome(), message, source, game))) {
|
||||
cost.clearPaid();
|
||||
if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) {
|
||||
game.applyEffects(); // To end effects e.g. of sacrificed permanents
|
||||
for (Effect effect : executingEffects) {
|
||||
effect.setTargetPointer(this.targetPointer);
|
||||
if (effect instanceof OneShotEffect) {
|
||||
|
|
@ -87,7 +88,8 @@ public class DoIfCostPaid extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
player.resetStoredBookmark(game); // otherwise you can e.g. undo card drawn with Mentor of the Meek
|
||||
} else if (!otherwiseEffects.isEmpty()) {
|
||||
}
|
||||
else if (!otherwiseEffects.isEmpty()) {
|
||||
for (Effect effect : otherwiseEffects) {
|
||||
effect.setTargetPointer(this.targetPointer);
|
||||
if (effect instanceof OneShotEffect) {
|
||||
|
|
@ -97,7 +99,8 @@ public class DoIfCostPaid extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (!otherwiseEffects.isEmpty()) {
|
||||
}
|
||||
else if (!otherwiseEffects.isEmpty()) {
|
||||
for (Effect effect : otherwiseEffects) {
|
||||
effect.setTargetPointer(this.targetPointer);
|
||||
if (effect instanceof OneShotEffect) {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public enum CardRepository {
|
|||
// raise this if db structure was changed
|
||||
private static final long CARD_DB_VERSION = 51;
|
||||
// raise this if new cards were added to the server
|
||||
private static final long CARD_CONTENT_VERSION = 99;
|
||||
private static final long CARD_CONTENT_VERSION = 100;
|
||||
private Dao<CardInfo, Object> cardDao;
|
||||
private Set<String> classNames;
|
||||
|
||||
|
|
|
|||
|
|
@ -85,12 +85,14 @@ public enum SubType {
|
|||
CENTAUR("Centaur", SubTypeSet.CreatureType),
|
||||
CEREAN("Cerean", SubTypeSet.CreatureType, true), // Star Wars
|
||||
CEPHALID("Cephalid", SubTypeSet.CreatureType),
|
||||
CHICKEN("Chicken", SubTypeSet.CreatureType, true), // Unglued
|
||||
CHIMERA("Chimera", SubTypeSet.CreatureType),
|
||||
CHISS("Chiss", SubTypeSet.CreatureType, true),
|
||||
CITIZEN("Citizen", SubTypeSet.CreatureType),
|
||||
CLERIC("Cleric", SubTypeSet.CreatureType),
|
||||
COCKATRICE("Cockatrice", SubTypeSet.CreatureType),
|
||||
CONSTRUCT("Construct", SubTypeSet.CreatureType),
|
||||
COW("Cow", SubTypeSet.CreatureType, true), // Unglued
|
||||
COWARD("Coward", SubTypeSet.CreatureType),
|
||||
CRAB("Crab", SubTypeSet.CreatureType),
|
||||
CROCODILE("Crocodile", SubTypeSet.CreatureType),
|
||||
|
|
@ -114,6 +116,7 @@ public enum SubType {
|
|||
DWARF("Dwarf", SubTypeSet.CreatureType),
|
||||
// E
|
||||
EFREET("Efreet", SubTypeSet.CreatureType),
|
||||
EGG("Egg", SubTypeSet.CreatureType),
|
||||
ELDER("Elder", SubTypeSet.CreatureType),
|
||||
ELDRAZI("Eldrazi", SubTypeSet.CreatureType),
|
||||
ELEMENTAL("Elemental", SubTypeSet.CreatureType),
|
||||
|
|
@ -131,6 +134,7 @@ public enum SubType {
|
|||
FROG("Frog", SubTypeSet.CreatureType),
|
||||
FUNGUS("Fungus", SubTypeSet.CreatureType),
|
||||
// G
|
||||
GAMER("Gamer", SubTypeSet.CreatureType, true), // Un-sets
|
||||
GAMORREAN("Gamorrean", SubTypeSet.CreatureType, true), // Star Wars
|
||||
GAND("Gand", SubTypeSet.CreatureType, true), // Star Wars
|
||||
GARGOYLE("Gargoyle", SubTypeSet.CreatureType),
|
||||
|
|
@ -194,6 +198,7 @@ public enum SubType {
|
|||
LHURGOYF("Lhurgoyf", SubTypeSet.CreatureType),
|
||||
LICID("Licid", SubTypeSet.CreatureType),
|
||||
LIZARD("Lizard", SubTypeSet.CreatureType),
|
||||
LOBSTER("Lobster", SubTypeSet.CreatureType, true), // Unglued
|
||||
// M
|
||||
MANTELLIAN("Mantellian", SubTypeSet.CreatureType, true), // Star Wars
|
||||
MANTICORE("Manticore", SubTypeSet.CreatureType),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.filter.predicate.permanent;
|
||||
|
||||
import java.util.List;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author L_J
|
||||
*/
|
||||
public class PermanentInListPredicate implements Predicate<Permanent> {
|
||||
|
||||
private final List<Permanent> permanents;
|
||||
|
||||
public PermanentInListPredicate(List<Permanent> permanents) {
|
||||
this.permanents = permanents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
return permanents.contains(input);
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +38,6 @@ import mage.abilities.keyword.special.JohanVigilanceAbility;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.common.FilterCreatureForCombatBlock;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
|
|
@ -655,7 +654,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
Map<UUID, Set<UUID>> mustBeBlockedByAtLeastOne = new HashMap<>();
|
||||
|
||||
// check mustBlock requirements of creatures from opponents of attacking player
|
||||
for (Permanent creature : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), player.getId(), game)) {
|
||||
for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED, player.getId(), game)) {
|
||||
// creature is controlled by an opponent of the attacker
|
||||
if (opponents.contains(creature.getControllerId())) {
|
||||
|
||||
|
|
@ -1180,6 +1179,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
//TODO: handle banding
|
||||
blockingGroups.get(blockerId).attackers.add(attackerId);
|
||||
}
|
||||
// "blocker.setBlocking(blocker.getBlocking() + 1)" is handled by the attacking combat group
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1392,6 +1392,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
|
||||
public void removeBlockerGromGroup(UUID blockerId, CombatGroup groupToUnblock, Game game) {
|
||||
// Manual player action for undoing one declared blocker (used for multi-blocker creatures)
|
||||
Permanent creature = game.getPermanent(blockerId);
|
||||
if (creature != null) {
|
||||
for (CombatGroup group : groups) {
|
||||
|
|
@ -1404,7 +1405,26 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
if (creature.getBlocking() > 0) {
|
||||
creature.setBlocking(creature.getBlocking() - 1);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Tryinging creature to unblock, but blocking number value of creature < 1");
|
||||
throw new UnsupportedOperationException("Trying to unblock creature, but blocking number value of creature < 1");
|
||||
}
|
||||
boolean canRemove = false;
|
||||
for (CombatGroup blockGroup : getBlockingGroups()) {
|
||||
if (blockGroup.blockers.contains(blockerId)) {
|
||||
for (UUID attackerId : group.getAttackers()) {
|
||||
blockGroup.attackers.remove(attackerId);
|
||||
blockGroup.attackerOrder.remove(attackerId);
|
||||
}
|
||||
if (creature.getBlocking() == 0) {
|
||||
blockGroup.blockers.remove(blockerId);
|
||||
blockGroup.attackerOrder.clear();
|
||||
}
|
||||
}
|
||||
if (blockGroup.blockers.isEmpty()) {
|
||||
canRemove = true;
|
||||
}
|
||||
}
|
||||
if (canRemove) {
|
||||
blockingGroups.remove(blockerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1412,6 +1432,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
|
||||
public void removeBlocker(UUID blockerId, Game game) {
|
||||
// Manual player action for undoing all declared blockers (used for single-blocker creatures and multi-blockers exceeding blocking limit)
|
||||
for (CombatGroup group : groups) {
|
||||
if (group.blockers.contains(blockerId)) {
|
||||
group.blockers.remove(blockerId);
|
||||
|
|
|
|||
|
|
@ -60,12 +60,15 @@ import mage.target.TargetCard;
|
|||
import mage.util.CardUtil;
|
||||
import mage.util.GameLog;
|
||||
import mage.util.ThreadLocalStringBuilder;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public abstract class PermanentImpl extends CardImpl implements Permanent {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(PermanentImpl.class);
|
||||
|
||||
public class MarkedDamageInfo {
|
||||
|
||||
public MarkedDamageInfo(Counter counter, MageObject sourceObject) {
|
||||
|
|
@ -699,6 +702,10 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (getSpellAbility() == null) {
|
||||
logger.info("FATAL : no spell ability for attach to permanent: " + getName());
|
||||
return;
|
||||
}
|
||||
if (!getSpellAbility().getTargets().isEmpty() && (getSpellAbility().getTargets().get(0) instanceof TargetCard)) {
|
||||
Card attachedToCard = game.getCard(this.getAttachedTo());
|
||||
if (attachedToCard != null) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ciaccona007
|
||||
*/
|
||||
|
||||
public class GiantChickenToken extends Token {
|
||||
|
||||
public GiantChickenToken() {
|
||||
super("Giant Chicken", "4/4 red Giant Chicken creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setRed(true);
|
||||
subtype.add(SubType.GIANT);
|
||||
subtype.add(SubType.CHICKEN);
|
||||
power = new MageInt(4);
|
||||
toughness = new MageInt(4);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue