Merge pull request #903 from kevlahnota/master

KLD & AER support
This commit is contained in:
Anthony Calosa
2017-01-27 06:00:58 +08:00
committed by GitHub
40 changed files with 3671 additions and 637 deletions
@@ -68,12 +68,6 @@ mana={4}{G}
type=Sorcery
[/card]
[card]
name=Oath of Nissa
text=When Oath of Nissa enters the battlefield, look at the top three cards of your library. You may reveal a creature, land, or planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in any order. -- You may spend mana as though it were mana of any color to cast planeswalker spells.
mana={G}
type=Legendary Enchantment
[/card]
[card]
name=Reality Smasher
text=({C} represents colorless mana.) -- Trample, haste -- Whenever Reality Smasher becomes the target of a spell an opponent controls, counter that spell unless its controller discards a card.
mana={4}{C}
File diff suppressed because it is too large Load Diff
+231
View File
@@ -0,0 +1,231 @@
[meta]
author=Wagic Team
name=Zendikar Expeditions
year=2016
total=45
[/meta]
[card]
primitive=Ancient Tomb
id=409567
rarity=M
[/card]
[card]
primitive=Arid Mesa
id=405092
rarity=M
[/card]
[card]
primitive=Blood Crypt
id=405093
rarity=M
[/card]
[card]
primitive=Bloodstained Mire
id=405094
rarity=M
[/card]
[card]
primitive=Breeding Pool
id=405095
rarity=M
[/card]
[card]
primitive=Canopy Vista
id=405096
rarity=M
[/card]
[card]
primitive=Cascade Bluffs
id=409563
rarity=M
[/card]
[card]
primitive=Cinder Glade
id=405097
rarity=M
[/card]
[card]
primitive=Dust Bowl
id=409568
rarity=M
[/card]
[card]
primitive=Eye of Ugin
id=409569
rarity=M
[/card]
[card]
primitive=Fetid Heath
id=409562
rarity=M
[/card]
[card]
primitive=Fire-Lit Thicket
id=409560
rarity=M
[/card]
[card]
primitive=Flooded Grove
id=409566
rarity=M
[/card]
[card]
primitive=Flooded Strand
id=405098
rarity=M
[/card]
[card]
primitive=Forbidden Orchard
id=409570
rarity=M
[/card]
[card]
primitive=Godless Shrine
id=405099
rarity=M
[/card]
[card]
primitive=Graven Cairns
id=409559
rarity=M
[/card]
[card]
primitive=Hallowed Fountain
id=405100
rarity=M
[/card]
[card]
primitive=Horizon Canopy
id=409571
rarity=M
[/card]
[card]
primitive=Kor Haven
id=409572
rarity=M
[/card]
[card]
primitive=Mana Confluence
id=409573
rarity=M
[/card]
[card]
primitive=Marsh Flats
id=405101
rarity=M
[/card]
[card]
primitive=Misty Rainforest
id=405102
rarity=M
[/card]
[card]
primitive=Mystic Gate
id=409557
rarity=M
[/card]
[card]
primitive=Overgrown Tomb
id=405103
rarity=M
[/card]
[card]
primitive=Polluted Delta
id=405104
rarity=M
[/card]
[card]
primitive=Prairie Stream
id=405105
rarity=M
[/card]
[card]
primitive=Rugged Prairie
id=409565
rarity=M
[/card]
[card]
primitive=Sacred Foundry
id=405106
rarity=M
[/card]
[card]
primitive=Scalding Tarn
id=405107
rarity=M
[/card]
[card]
primitive=Smoldering Marsh
id=405108
rarity=M
[/card]
[card]
primitive=Steam Vents
id=405109
rarity=M
[/card]
[card]
primitive=Stomping Ground
id=405110
rarity=M
[/card]
[card]
primitive=Strip Mine
id=409574
rarity=M
[/card]
[card]
primitive=Sunken Hollow
id=405111
rarity=M
[/card]
[card]
primitive=Sunken Ruins
id=409558
rarity=M
[/card]
[card]
primitive=Tectonic Edge
id=409575
rarity=M
[/card]
[card]
primitive=Temple Garden
id=405112
rarity=M
[/card]
[card]
primitive=Twilight Mire
id=409564
rarity=M
[/card]
[card]
primitive=Verdant Catacombs
id=405113
rarity=M
[/card]
[card]
primitive=Wasteland
id=409576
rarity=M
[/card]
[card]
primitive=Watery Grave
id=405114
rarity=M
[/card]
[card]
primitive=Windswept Heath
id=405115
rarity=M
[/card]
[card]
primitive=Wooded Bastion
id=409561
rarity=M
[/card]
[card]
primitive=Wooded Foothills
id=405116
rarity=M
[/card]
@@ -12,3 +12,6 @@
# Basic Landcycling
#AUTO_DEFINE __BASIC_LANDCYCLING__($cost) $cost{cycle}:name(basic landcycling) moveTo(myhand) target(land[basic]|mylibrary)
# Fabricate
#AUTO_DEFINE _FABRICATE_($c) transforms((,newability[choice counter(1/1.$c)],newability[choice makecardt(Servo:Artifact Creature Servo:1/1)*$c])) ueot
@@ -1,5 +1,17 @@
grade=borderline
[card]
name=Akiri, Line-Slinger
abilities=first strike,vigilance
auto=type:artifact:mybattlefield/0 nonstatic
#wagic don't support commander atm
text=First strike, vigilance -- Akiri, Line-Slinger gets +1/+0 for each artifact you control. -- Partner (You can have two commanders if both have partner.)
mana={R}{W}
type=Legendary Creature
subtype=Kor Soldier Ally
power=0
toughness=3
[/card]
[card]
name=Angelic Field Marshal
abilities=flying
#wagic doesnt have commander zone
@@ -68,6 +80,18 @@ mana={3}{U}
type=Instant
[/card]
[card]
name=Bruse Tarl, Boorish Herder
#wagic don't support commander atm
auto=name(double strike & lifelink) target(creature|mybattlefield) transforms((,newability[double strike],newability[lifelink])) ueot
auto=@combat(attacking) source(this):name(double strike & lifelink) target(creature|mybattlefield) transforms((,newability[double strike],newability[lifelink])) ueot
text=Whenever Bruse Tarl, Boorish Herder enters the battlefield or attacks, target creature you control gains double strike and lifelink until end of turn. -- Partner (You can have two commanders if both have partner.)
mana={2}{R}{W}
type=Legendary Creature
subtype=Human Ally
power=3
toughness=3
[/card]
[card]
name=Cemetery Puca
text=Whenever a creature is put into a graveyard from the battlefield, you may pay {1}. If you do, Cemetery Puca becomes a copy of that creature and gains this ability.
auto=@movedto(creature|graveyard) from(battlefield):all(trigger[from]) pay[[{1}]] copy
@@ -266,6 +290,18 @@ text=Suspend 3
type=Sorcery
[/card]
[card]
name=Ikra Shidiqi, the Usurper
abilities=menace
#wagic don't support commander atm
auto=@combatdamaged(player) from(creature|mybattlefield):all(trigger[from]) dynamicability<!mytgt toughnesslifegain targetcontroller!>
text=Menace -- Whenever a creature you control deals combat damage to a player, you gain life equal to that creature's toughness. -- Partner (You can have two commanders if both have partner.)
mana={3}{B}{G}
type=Legendary Creature
subtype=Naga Wizard
power=3
toughness=7
[/card]
[card]
name=Intellectual Offering
#wagic only supports single opponent
auto=draw:3 all(player)
@@ -275,6 +311,18 @@ mana={4}{U}
type=Instant
[/card]
[card]
name=Ishai, Ojutai Dragonspeaker
abilities=flying
#wagic don't support commander atm
auto=@movedto(*|opponentstack):counter(1/1,1)
text=Flying -- Whenever an opponent casts a spell, put a +1/+1 counter on Ishai, Ojutai Dragonspeaker. -- Partner (You can have two commanders if both have partner.)
mana={2}{W}{U}
type=Legendary Creature
subtype=Bird Monk
power=1
toughness=1
[/card]
[card]
name=Ivy Seer
auto={2}{G}{T}:foreach(*[green]|myhand) 1/1 target(creature)
text={2}{G}, {T}: Reveal any number of green cards in your hand. Target creature gets +X/+X until end of turn, where X is the number of cards revealed this way.
@@ -295,6 +343,41 @@ power=1
toughness=1
[/card]
[card]
name=Kraum, Ludevic's Opus
abilities=flying,haste
#wagic don't support commander atm
auto=@movedto(*|opponentstack) restriction{thisturn(*|opponentstack)~equalto~1}:draw:1 controller
text=Flying, haste -- Whenever an opponent casts his or her second spell each turn, draw a card. -- Partner (You can have two commanders if both have partner.)
mana={3}{U}{R}
type=Legendary Creature
subtype=Zombie Horror
power=4
toughness=4
[/card]
[card]
name=Kydele, Chosen of Kruphix
#wagic don't support commander atm
auto={T}:thisforeach(variable{pdrewcount}>0) add{C}
text={T}: Add {C} to your mana pool for each card you've drawn this turn. -- Partner (You can have two commanders if both have partner.)
mana={2}{G}{U}
type=Legendary Creature
subtype=Human Wizard
power=2
toughness=3
[/card]
[card]
name=Ludevic, Necro-Alchemist
#wagic don't support commander atm
auto=@each my end restriction{compare(oplifelost)~morethan~0}:may draw:1 controller
auto=@each opponent end restriction{compare(oplifelost)~morethan~0}:may draw:1 controller
text=At the beginning of each player's end step, that player may draw a card if a player other than you lost life this turn. -- Partner (You can have two commanders if both have partner.)
mana={1}{U}{R}
type=Legendary Creature
subtype=Human Wizard
power=1
toughness=4
[/card]
[card]
name=Maralen of the Mornsong
auto=replacedraw ability$!name(skip draw) donothing!$ controller
auto=opponentreplacedraw ability$!name(skip draw) donothing!$ opponent
@@ -423,6 +506,19 @@ power=2
toughness=6
[/card]
[card]
name=Ravos, Soultender
abilities=flying
#wagic don't support commander atm
auto=lord(other creature|mybattlefield) 1/1
auto=@each my upkeep restriction{type(creature|mygraveyard)~morethan~0}:may target(creature|mygraveyard) moveto(myhand)
text=Flying -- Other creatures you control get +1/+1. -- At the beginning of your upkeep, you may return target creature card from your graveyard to your hand. -- Partner (You can have two commanders if both have partner.)
mana={3}{W}{B}
type=Legendary Creature
subtype=Human Cleric
power=2
toughness=2
[/card]
[card]
name=Rayne, Academy Chancellor
#missing parser for player/controller/opponent
auto=this(auras >= 1) transforms((,newability[@targeted(*|mybattlefield) from(*|opponentzones):draw:2]))
@@ -534,6 +630,30 @@ mana={3}{G}
type=Sorcery
[/card]
[card]
name=Sidar Kondo of Jamuraa
abilities=flanking
#wagic don't support commander atm
auto=lord(creature[-flying;-reach]|opponentbattlefield) cantbeblockerof(creature[power<=2])
text=Flanking (Whenever a creature without flanking blocks this creature, the blocking creature gets -1/-1 until end of turn.) -- Creatures your opponents control without flying or reach can't block creatures with power 2 or less. -- Partner (You can have two commanders if both have partner.)
mana={2}{G}{W}
type=Legendary Creature
subtype=Human Knight
power=2
toughness=5
[/card]
[card]
name=Silas Renn, Seeker Adept
abilities=deathtouch
#wagic don't support commander atm
auto=@combatdamaged(player) from(this):target(artifact|mygraveyard) canplayfromgraveyard ueot
text=Deathtouch -- Whenever Silas Renn, Seeker Adept deals combat damage to a player, choose target artifact card in your graveyard. You may cast that card this turn. -- Partner (You can have two commanders if both have partner.)
mana={1}{U}{B}
type=Legendary Artifact Creature
subtype=Human
power=2
toughness=2
[/card]
[card]
name=Silvergill Adept
otherrestriction=type(*[merfolk]|myhand)~lessthan~2
other={4}{U}
@@ -618,6 +738,18 @@ mana={X}{G}
type=Sorcery
[/card]
[card]
name=Tana, the Bloodsower
abilities=trample
#wagic don't support commander atm
auto=@combatdamaged(player) from(this):makecardt(Saproling:Creature Saproling:1/1:green)*thatmuch
text=Trample -- Whenever Tana, the Bloodsower deals combat damage to a player, create that many 1/1 green Saproling creature tokens. -- Partner (You can have two commanders if both have partner.)
mana={2}{R}{G}
type=Legendary Creature
subtype=Elf Druid
power=2
toughness=2
[/card]
[card]
name=Teferi, Mage of Zhalfir
abilities=flash
auto=lord(creature|mycastingzone) flash
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -2,6 +2,7 @@
[INIT]
FIRSTMAIN
[PLAYER1]
inplay:Mirror Gallery
graveyard:Krosan Cloudscraper, Dragonlord Kolaghan, Clone
hand:Living Death
manapool:{2}{B}{B}{B}
@@ -26,8 +27,8 @@ eot
[ASSERT]
UNTAP
[PLAYER1]
inplay:Krosan Cloudscraper, Clone
graveyard:Dragonlord Kolaghan, Living Death
inplay:Krosan Cloudscraper, Dragonlord Kolaghan, Clone, Mirror Gallery
graveyard:Living Death
[PLAYER2]
life:1
[END]
@@ -10,6 +10,8 @@ graveyard:White Knight,Glorious Anthem
library:White Knight,Glorious Anthem,Grizzly Bears
[DO]
Haunting Echoes
choice 0
p2
next
goto firstmain
[ASSERT]
+58
View File
@@ -552,6 +552,14 @@ private:
intValue +=1;
}
}
else if (s == "penergy")
{
intValue = card->controller()->energyCount;
}
else if (s == "oenergy")
{
intValue = card->controller()->opponent()->energyCount;
}
else if (s == "praidcount")
{
intValue = card->controller()->raidcount;
@@ -560,6 +568,14 @@ private:
{
intValue = card->controller()->opponent()->raidcount;
}
else if (s == "pstormcount")
{
intValue = card->controller()->game->stack->seenThisTurn("*", Constants::CAST_ALL);
}
else if (s == "ostormcount")
{
intValue = card->controller()->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL);
}
else if (s == "countallspell")
{
intValue = card->controller()->game->stack->seenThisTurn("*", Constants::CAST_ALL) + card->controller()->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL);
@@ -1448,6 +1464,34 @@ public:
return NEW TrCombatTrigger(*this);
}
};
class TrplayerEnergized: public Trigger
{
public:
bool thiscontroller, thisopponent;
TrplayerEnergized(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc,bool once = false, bool thiscontroller = false, bool thisopponent = false) :
Trigger(observer, id, source,once, tc),thiscontroller(thiscontroller),thisopponent(thisopponent)
{
}
int triggerOnEventImpl(WEvent * event)
{
WEventplayerEnergized * e = dynamic_cast<WEventplayerEnergized *> (event);
if (!e) return 0;
if (!tc->canTarget(e->player)) return 0;
if(thiscontroller)
if(e->player != source->controller())
return 0;
if(thisopponent)
if(e->player == source->controller())
return 0;
return 1;
}
TrplayerEnergized * clone() const
{
return NEW TrplayerEnergized(*this);
}
};
class TrcardDrawn: public Trigger
{
@@ -2001,6 +2045,7 @@ class AALibraryBottom: public ActivatedAbility
{
public:
AALibraryBottom(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target = NULL, ManaCost * _cost = NULL);
MTGAbility * andAbility;
int resolve();
const string getMenuText();
AALibraryBottom * clone() const;
@@ -4514,6 +4559,19 @@ public:
AAAlterPoison * clone() const;
~AAAlterPoison();
};
//Energy Counter
class AAAlterEnergy: public ActivatedAbilityTP
{
public:
int energy;
AAAlterEnergy(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int energy, ManaCost * _cost = NULL,
int who = TargetChooser::UNSET);
int resolve();
const string getMenuText();
AAAlterEnergy * clone() const;
~AAAlterEnergy();
};
/* Standard Damager, can choose a NEW target each time the price is paid */
class TADamager: public TargetAbility
{
+3
View File
@@ -71,6 +71,9 @@ public:
string doubleFaced;
void setdoubleFaced(const string& value);
const string& getdoubleFaced() const;
string AICustomCode;
void setAICustomCode(const string& value);
const string& getAICustomCode() const;
vector<int>types;
CardPrimitive();
+23
View File
@@ -216,6 +216,19 @@ public:
virtual SnowCost * clone() const;
};
//Energy cost
class EnergyCost : public ExtraCost
{
private:
int enc;
public:
EnergyCost(int enc = 0);
virtual int canPay();
virtual int doPay();
virtual EnergyCost * clone() const;
};
//untap cost
class UnTapCost : public ExtraCost
{
@@ -295,6 +308,16 @@ public:
virtual int doPay();
virtual Delve * clone() const;
};
//improvise
class Improvise : public ExtraCost
{
public:
Improvise(TargetChooser *_tc = NULL);
virtual int canPay();
virtual int isPaymentSet();
virtual int doPay();
virtual Improvise * clone() const;
};
//offering cost
class Offering : public ExtraCost
{
+2
View File
@@ -125,6 +125,8 @@ class GameObserver{
void enchantmentStatus();
void Affinity();
bool AffinityNeedsUpdate;
bool foundlegendrule;
void checkLegendary(MTGCardInstance * card);
void addObserver(MTGAbility * observer);
bool removeObserver(ActionElement * observer);
void startGame(GameType, Rules * rules);
+2
View File
@@ -64,6 +64,7 @@ public:
int equipment;
int auras;
bool wasDealtDamage;
bool combatdamageToOpponent;
bool damageToOpponent;
bool damageToController;
bool damageToCreature;
@@ -266,6 +267,7 @@ public:
int myconvertedcost;
ManaCost * computeNewCost(MTGCardInstance * card,ManaCost * oldCost, ManaCost * refCost,bool noTrinisphere = false);
int countTrini;
bool anymanareplacement;
vector<MTGCardInstance*>imprintedCards;
int attackCost;
int attackCostBackup;
+4 -1
View File
@@ -262,7 +262,10 @@ class Constants
CONDUITED = 140,
CANBLOCKTAPPED = 141,
OPPNOMAXHAND = 142,
NB_BASIC_ABILITIES = 143,
CANTCREW = 143,
HIDDENFACE = 144,
ANYTYPEOFMANA = 145,
NB_BASIC_ABILITIES = 146,
RARITY_S = 'S', //Special Rarity
RARITY_M = 'M', //Mythics
+4 -2
View File
@@ -73,6 +73,8 @@ public:
class MTGPutInPlayRule: public PermanentAbility
{
protected:
string defaultPlayName;
public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
int reactToClick(MTGCardInstance * card);
@@ -80,8 +82,8 @@ public:
MTGPutInPlayRule(GameObserver* observer, int _id);
const string getMenuText()
{
if(game && game->gameType() == GAME_TYPE_MOMIR)
return "Play Land";
if(defaultPlayName.size())
return defaultPlayName.c_str();
return "Cast Card Normally";
}
virtual MTGPutInPlayRule * clone() const;
+2
View File
@@ -42,8 +42,10 @@ public:
int skippingTurn;
int extraTurn;
int drawCounter;
int energyCount;
int epic;
int forcefield;
int dealsdamagebycombat;
int initLife;
int raidcount;
int handmodifier;
+9
View File
@@ -306,6 +306,15 @@ struct WEventCardTransforms : public WEventCardUpdate {
virtual Targetable * getTarget(int target);
};
//alterenergy event
struct WEventplayerEnergized : public WEvent {
WEventplayerEnergized(Player * player,int nb_count);
Player * player;
int nb_count;
using WEvent::getTarget;
virtual Targetable * getTarget(Player * player);
};
std::ostream& operator<<(std::ostream&, const WEvent&);
#endif
+1
View File
@@ -80,6 +80,7 @@ public:
}
};
virtual JQuadPtr RetrieveCard(MTGCard * card, int style = RETRIEVE_NORMAL,int submode = CACHE_NORMAL) = 0;
virtual JQuadPtr RetrieveCardToken(MTGCard * card, int style = RETRIEVE_NORMAL,int submode = CACHE_NORMAL, int tId = 0) = 0;
virtual JSample * RetrieveSample(const string& filename, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL) = 0;
virtual JTexture * RetrieveTexture(const string& filename, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL) = 0;
virtual JQuadPtr RetrieveQuad(const string& filename, float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f, string resname="", int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL, int id = 0) = 0;
@@ -141,6 +141,7 @@ public:
bool IsThreaded();
JQuadPtr RetrieveCard(MTGCard * card, int style = RETRIEVE_NORMAL,int submode = CACHE_NORMAL);
JQuadPtr RetrieveCardToken(MTGCard * card, int style = RETRIEVE_NORMAL,int submode = CACHE_NORMAL, int tId = 0);
JSample * RetrieveSample(const string& filename, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL);
JTexture * RetrieveTexture(const string& filename, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL);
JQuadPtr RetrieveQuad(const string& filename, float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f, string resname="", int style = RETRIEVE_LOCK, int submode = CACHE_NORMAL, int id = 0);
+7
View File
@@ -595,6 +595,13 @@ int OrderedAIAction::getEfficiency()
efficiency = 90;
}
}
else if (dynamic_cast<AAAlterEnergy *>(a))
{
if (playerAbilityTarget && playerAbilityTarget == p)
{
efficiency = 90;
}
}
else if (ATokenCreator * atc = dynamic_cast<ATokenCreator *>(a))
{
efficiency = 80;
+80 -14
View File
@@ -1010,6 +1010,47 @@ AAAlterPoison::~AAAlterPoison()
{
}
//AA Energy Counters
AAAlterEnergy::AAAlterEnergy(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int energy, ManaCost * _cost,
int who) :
ActivatedAbilityTP(observer, _id, _source, _target, _cost, who), energy(energy)
{
}
int AAAlterEnergy::resolve()
{
Damageable * _target = (Damageable *) getTarget();
if (_target)
{
Player * pTarget = (Player*)_target;
if(pTarget)
{
pTarget->energyCount += energy;
if(energy > 0)
{
WEvent * e = NEW WEventplayerEnergized(pTarget, energy);
game->receiveEvent(e);
}//todo loses enegy event
}
}
return 0;
}
const string AAAlterEnergy::getMenuText()
{
WParsedInt parsedNum(energy);
return _(parsedNum.getStringValue() + " Energy ").c_str();
}
AAAlterEnergy * AAAlterEnergy::clone() const
{
return NEW AAAlterEnergy(*this);
}
AAAlterEnergy::~AAAlterEnergy()
{
}
//Damage Prevent
AADamagePrevent::AADamagePrevent(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int preventing, ManaCost * _cost,
int who) :
@@ -1443,6 +1484,7 @@ AALibraryBottom::AALibraryBottom(GameObserver* observer, int _id, MTGCardInstanc
ActivatedAbility(observer, _id, _source, _cost, 0)
{
target = _target;
andAbility = NULL;
}
int AALibraryBottom::resolve()
@@ -1462,6 +1504,20 @@ int AALibraryBottom::resolve()
newOrder.push_back(rearranged);
}
library->cards = newOrder;
if(andAbility)
{
MTGAbility * andAbilityClone = andAbility->clone();
andAbilityClone->target = _target;
if(andAbility->oneShot)
{
andAbilityClone->resolve();
SAFE_DELETE(andAbilityClone);
}
else
{
andAbilityClone->addToGame();
}
}
return 1;
}
return 0;
@@ -2011,6 +2067,12 @@ int AAProliferate::resolve()
a->oneShot = true;
pcounters.push_back(a);
}
else if(pTarget && pTarget->energyCount && pTarget == source->controller())
{
MTGAbility * a = NEW AAAlterEnergy(game, game->mLayers->actionLayer()->getMaxId(), source, target, 1, NULL);
a->oneShot = true;
pcounters.push_back(a);
}
else if (cTarget && cTarget->counters)
{
Counters * counters = cTarget->counters;
@@ -7733,7 +7795,7 @@ const string AEquip::getMenuText()
int AEquip::testDestroy()
{
if (source->target && !game->isInPlay(source->target))
unequip();
//unequip();//testfix for equipment when the card it equip moves to other battlefield
if (!game->connectRule)
{
if (source->target && TargetAbility::tc && !TargetAbility::tc->canTarget((Targetable *)source->target,true))
@@ -7909,17 +7971,9 @@ int AACastCard::resolveSpell()
}
if (_target)
{
if (_target->isLand())
{
MTGCardInstance * copy = _target->controller()->game->putInZone(_target, _target->currentZone, source->controller()->game->temp,noEvent);
copy->changeController(source->controller(),true);
Spell * spell = NEW Spell(game, 0,copy,NULL,NULL, 1);
spell->resolve();
delete spell;
}
else
{
putinplay = true;
Spell * spell = NULL;
MTGCardInstance * copy = NULL;
if ((normal || asNormalMadness)||(!_target->hasType(Subtypes::TYPE_INSTANT) && !_target->hasType(Subtypes::TYPE_SORCERY)))
@@ -7943,12 +7997,24 @@ int AACastCard::resolveSpell()
if (game->targetChooser)
{
game->targetChooser->Owner = source->controller();
spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, NULL, 1, 0);
if(putinplay)
{
spell = NEW Spell(game, 0,copy,game->targetChooser,NULL, 1);
spell->resolve();
}
else
spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, NULL, 1, 0);
game->targetChooser = NULL;
}
else
{
spell = game->mLayers->stackLayer()->addSpell(copy, NULL, NULL, 1, 0);
if(putinplay)
{
spell = NEW Spell(game, 0,copy,NULL,NULL, 1);
spell->resolve();
}
else
spell = game->mLayers->stackLayer()->addSpell(copy, NULL, NULL, 1, 0);
}
if (copy->has(Constants::STORM))
@@ -7980,7 +8046,7 @@ int AACastCard::resolveSpell()
andAbilityClone->addToGame();
}
}
}
this->forceDestroy = true;
processed = true;
return 1;
+8 -1
View File
@@ -388,7 +388,14 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card)
}
//Counters
if (anyCounter)
if (anyCounter == -1)
{
if (card->counters->mCount)
{
match = NULL;
}
}
else if (anyCounter)
{
if (!(card->counters->mCount))
{
+20
View File
@@ -148,6 +148,11 @@ void CardGui::Render()
MTGCard * fcard = MTGCollection()->getCardByName(card->name);
quad = game->getResourceManager()->RetrieveCard(fcard, CACHE_THUMB);
}
if (game && card->hasCopiedToken && !quad.get())
{
MTGCard * tcard = MTGCollection()->getCardById(abs(card->copiedID));
quad = game->getResourceManager()->RetrieveCardToken(tcard, CACHE_THUMB, 1, abs(card->copiedID));
}
if (quad.get())
alternate = false;
else
@@ -533,6 +538,7 @@ void CardGui::AlternateRender(MTGCard * card, const Pos& pos)
// Draw the "unknown" card model
JRenderer * renderer = JRenderer::GetInstance();
JQuadPtr q;
MTGCardInstance * thiscard = dynamic_cast<MTGCardInstance*> (card);
float x = pos.actX;
@@ -553,6 +559,14 @@ void CardGui::AlternateRender(MTGCard * card, const Pos& pos)
items.clear();
if (q.get() && q->mTex)
{
//test
//draw black border ingame only
if(thiscard && thiscard->getObserver())
{
renderer->FillRoundRect((pos.actX - (pos.actZ * 84.f))-11.5f,(pos.actY - (pos.actZ * 119.7f))-14.f,pos.actZ * 168.f + 6.5f,pos.actZ * 239.4f + 12.f,8.f,ARGB(255,5,5,5));
renderer->DrawRoundRect((pos.actX - (pos.actZ * 84.f))-11.5f,(pos.actY - (pos.actZ * 119.7f))-14.f,pos.actZ * 168.f + 6.5f,pos.actZ * 239.4f + 12.f,8.f,ARGB(50,240,240,240));
}
q->SetHotSpot(static_cast<float> (q->mTex->mWidth / 2), static_cast<float> (q->mTex->mHeight / 2));
float scale = pos.actZ * 250 / q->mHeight;
@@ -1135,6 +1149,12 @@ void CardGui::RenderBig(MTGCard* card, const Pos& pos, bool thumb, bool noborder
MTGCard * fcard = MTGCollection()->getCardByName(kcard->name);
quad = WResourceManager::Instance()->RetrieveCard(fcard);
}
if (kcard && kcard->hasCopiedToken)
{
MTGCard * tcard = MTGCollection()->getCardById(abs(kcard->copiedID));
quad = thumb ? WResourceManager::Instance()->RetrieveCardToken(tcard, RETRIEVE_THUMB, 1, abs(kcard->copiedID))
: WResourceManager::Instance()->RetrieveCardToken(tcard, RETRIEVE_NORMAL, 1, abs(kcard->copiedID));
}
if (quad.get())
{
if (quad->mHeight < quad->mWidth)
+11
View File
@@ -57,6 +57,7 @@ CardPrimitive::CardPrimitive(CardPrimitive * source)
setName(source->name);
setdoubleFaced(source->doubleFaced);
setAICustomCode(source->AICustomCode);
power = source->power;
toughness = source->toughness;
restrictions = source->restrictions ? source->restrictions->clone() : NULL;
@@ -341,6 +342,16 @@ const string& CardPrimitive::getdoubleFaced() const
return doubleFaced;
}
void CardPrimitive::setAICustomCode(const string& value)
{
std::transform(AICustomCode.begin(), AICustomCode.end(), AICustomCode.begin(), ::tolower);
AICustomCode = value;
}
const string& CardPrimitive::getAICustomCode() const
{
return AICustomCode;
}
void CardPrimitive::setName(const string& value)
{
+2
View File
@@ -260,6 +260,8 @@ int Damage::resolve()
target->lifeLostThisTurn += damage;
if ( typeOfDamage == 1 && target == source->controller()->opponent() )//add vector prowledtypes.
{
source->controller()->dealsdamagebycombat = 1; // for restriction check
((MTGCardInstance*)source)->combatdamageToOpponent = true; //check
vector<string> values = MTGAllCards::getCreatureValuesById();//getting a weird crash here. rarely.
for (size_t i = 0; i < values.size(); ++i)
{
+99
View File
@@ -232,6 +232,37 @@ int SnowCost::doPay()
return 0;
}
//Energy Cost
EnergyCost * EnergyCost::clone() const
{
EnergyCost * ec = NEW EnergyCost(*this);
return ec;
}
EnergyCost::EnergyCost(int enc) :
ExtraCost("Energy Cost"),enc(enc)
{
}
int EnergyCost::canPay()
{
if(source->controller()->energyCount >= enc)
{
return 1;
}
return 0;
}
int EnergyCost::doPay()
{
if(source->controller()->energyCount)
{
source->controller()->energyCount -= enc;
return 1;
}
return 0;
}
//life cost
LifeCost * LifeCost::clone() const
{
@@ -1118,6 +1149,74 @@ int Delve::doPay()
return 0;
}
//IMPROVISE
Improvise * Improvise::clone() const
{
Improvise * ec = NEW Improvise(*this);
if (tc)
ec->tc = tc->clone();
return ec;
}
Improvise::Improvise(TargetChooser *_tc) :
ExtraCost("Select Artifacts To Tap", _tc)
{
}
int Improvise::canPay()
{
return isPaymentSet();
}
int Improvise::isPaymentSet()
{
ManaCost * toReduce = NEW ManaCost(source->getManaCost());
tc->maxtargets = source->getManaCost()->getCost(Constants::MTG_COLOR_ARTIFACT);
if (tc->getNbTargets())
{
toReduce->remove(Constants::MTG_COLOR_ARTIFACT, tc->getNbTargets());
}
if (target && (!source->controller()->getManaPool()->canAfford(toReduce)))
{
target = NULL;
SAFE_DELETE(toReduce);
return 0;
}
if (target && (source->controller()->getManaPool()->canAfford(toReduce)))
{
/*if (target->getObserver()->guiOpenDisplay)
target->getObserver()->ButtonPressed(target->getObserver()->guiOpenDisplay);*/
SAFE_DELETE(toReduce);
return 1;
}
SAFE_DELETE(toReduce);
return 0;
}
int Improvise::doPay()
{
if (target && tc->getNbTargets())
{
ManaCost * toReduce = NEW ManaCost(source->getManaCost());
toReduce->remove(Constants::MTG_COLOR_ARTIFACT, tc->getNbTargets());
target->controller()->getManaPool()->pay(toReduce);
SAFE_DELETE(toReduce);
vector<Targetable*>targetlist = tc->getTargetsFrom();
for (vector<Targetable*>::iterator it = targetlist.begin(); it != targetlist.end(); it++)
{
MTGCardInstance * targetCard = dynamic_cast<MTGCardInstance*>(*it);
source->storedCard = targetCard->createSnapShot();
targetCard->tap();
}
if (tc)
tc->initTargets();
return 1;
}
return 0;
}
///////////////
//Sacrifice target as cost for Offering
Offering * Offering::clone() const
+88 -12
View File
@@ -110,6 +110,7 @@ GameObserver::GameObserver(WResourceManager *output, JGE* input)
mLayers = NULL;
mTrash = new Trash();
mDeckManager = new DeckManager();
foundlegendrule = false;
}
GamePhase GameObserver::getCurrentGamePhase()
@@ -213,6 +214,7 @@ void GameObserver::nextGamePhase()
currentPlayer->nonCombatDamage = 0;
currentPlayer->drawCounter = 0;
currentPlayer->raidcount = 0;
currentPlayer->dealsdamagebycombat = 0; //clear check for restriction
currentPlayer->opponent()->raidcount = 0;
currentPlayer->prowledTypes.clear();
currentPlayer->opponent()->damageCount = 0; //added to clear odcount
@@ -712,19 +714,20 @@ void GameObserver::gameStateBasedEffects()
///set basic land mana objects canproduce
for (size_t gg = 0; gg < mLayers->actionLayer()->manaObjects.size(); gg++)
{
if (dynamic_cast<AManaProducer*> (((MTGAbility *) mLayers->actionLayer()->manaObjects[gg])) &&
(dynamic_cast<AManaProducer*> (((MTGAbility *) mLayers->actionLayer()->manaObjects[gg])))->source->isLand() &&
(dynamic_cast<AManaProducer*> (((MTGAbility *) mLayers->actionLayer()->manaObjects[gg])))->source == card)
MTGAbility * aa = ((MTGAbility *) mLayers->actionLayer()->manaObjects[gg]);
//AManaProducer * amp = dynamic_cast<AManaProducer*> (aa);
if (dynamic_cast<AManaProducer*> (aa) && (dynamic_cast<AManaProducer*> (aa))->source->isLand() && (dynamic_cast<AManaProducer*> (aa))->source == card)
{
if (card->hasType("forest") && (dynamic_cast<AManaProducer*> (((MTGAbility *) mLayers->actionLayer()->manaObjects[gg])))->output->hasColor(Constants::MTG_COLOR_GREEN))
if (card->hasType("forest") && ((AManaProducer*)aa)->output->hasColor(Constants::MTG_COLOR_GREEN))
card->canproduceG = 1;
if (card->hasType("island") && (dynamic_cast<AManaProducer*> (((MTGAbility *) mLayers->actionLayer()->manaObjects[gg])))->output->hasColor(Constants::MTG_COLOR_BLUE))
if (card->hasType("island") && ((AManaProducer*)aa)->output->hasColor(Constants::MTG_COLOR_BLUE))
card->canproduceU = 1;
if (card->hasType("mountain") && (dynamic_cast<AManaProducer*> (((MTGAbility *) mLayers->actionLayer()->manaObjects[gg])))->output->hasColor(Constants::MTG_COLOR_RED))
if (card->hasType("mountain") && ((AManaProducer*)aa)->output->hasColor(Constants::MTG_COLOR_RED))
card->canproduceR = 1;
if (card->hasType("swamp") && (dynamic_cast<AManaProducer*> (((MTGAbility *) mLayers->actionLayer()->manaObjects[gg])))->output->hasColor(Constants::MTG_COLOR_BLACK))
if (card->hasType("swamp") && ((AManaProducer*)aa)->output->hasColor(Constants::MTG_COLOR_BLACK))
card->canproduceB = 1;
if (card->hasType("plains") && (dynamic_cast<AManaProducer*> (((MTGAbility *) mLayers->actionLayer()->manaObjects[gg])))->output->hasColor(Constants::MTG_COLOR_WHITE))
if (card->hasType("plains") && ((AManaProducer*)aa)->output->hasColor(Constants::MTG_COLOR_WHITE))
card->canproduceW = 1;
}
}
@@ -771,9 +774,9 @@ void GameObserver::gameStateBasedEffects()
////////////////////////////////////////////////////
//Unattach Equipments that dont have valid targets//
////////////////////////////////////////////////////
if ((card->target) && card->hasType(Subtypes::TYPE_EQUIPMENT))
if (card->hasType(Subtypes::TYPE_EQUIPMENT))
{
if(card->target && isInPlay(card->target) && (card->target)->protectedAgainst(card))//protection from quality
if(isInPlay(card))
{
for (size_t i = 1; i < mLayers->actionLayer()->mObjects.size(); i++)
{
@@ -781,7 +784,14 @@ void GameObserver::gameStateBasedEffects()
AEquip * eq = dynamic_cast<AEquip*> (a);
if (eq && eq->source == card)
{
((AEquip*)a)->unequip();
if(card->target)//unattach equipments from cards that has protection from quality ex. protection from artifacts
{
if((card->target)->protectedAgainst(card)||card->isCreature())
((AEquip*)a)->unequip();
}
if(card->controller())
((AEquip*)a)->getActionTc()->Owner = card->controller();
//fix for equip ability when the equipment changed controller...
}
}
}
@@ -879,6 +889,7 @@ void GameObserver::gameStateBasedEffects()
if(card->life < 1 && !card->has(Constants::INDESTRUCTIBLE))
card->destroy();//manor gargoyle... recheck
}
checkLegendary(card); //legendary rule as state based effect
}
if(card->childrenCards.size())
@@ -934,7 +945,6 @@ void GameObserver::gameStateBasedEffects()
p->nomaxhandsize = true;
else
p->nomaxhandsize = false;
/////////////////////////////////////////////////
//handle end of turn effects while we're at it.//
/////////////////////////////////////////////////
@@ -959,6 +969,7 @@ void GameObserver::gameStateBasedEffects()
c->wasDealtDamage = false;
c->damageToController = false;
c->damageToOpponent = false;
c->combatdamageToOpponent = false;
c->damageToCreature = false;
c->isAttacking = NULL;
}
@@ -1054,6 +1065,51 @@ void GameObserver::gameStateBasedEffects()
}
}
void GameObserver::checkLegendary(MTGCardInstance * card)
{
if(!foundlegendrule)
return;
if(card->has(Constants::NOLEGEND)||card->controller()->opponent()->inPlay()->hasAbility(Constants::NOLEGENDRULE)||card->controller()->inPlay()->hasAbility(Constants::NOLEGENDRULE))
return;
int destroy = 0;
vector<MTGCardInstance*>oldCards;
MTGGameZone * z = card->controller()->game->inPlay;
int nbcards = z->nb_cards-1;
for (int r = 0; r < nbcards; r++)
{
MTGCardInstance * comparison = z->cards[r];
if (comparison != card && comparison->hasType("legendary") && !(comparison->getName().compare(card->getName())))
{
oldCards.push_back(comparison);
destroy = 1;
}
}
if(destroy)
{
vector<MTGAbility*>selection;
MultiAbility * multi = NEW MultiAbility(this, this->mLayers->actionLayer()->getMaxId(), card, card, NULL);
for(unsigned int i = 0;i < oldCards.size();i++)
{
AAMover *a = NEW AAMover(this, this->mLayers->actionLayer()->getMaxId(), card, oldCards[i],"ownergraveyard","Keep New");
a->oneShot = true;
multi->Add(a);
}
multi->oneShot = 1;
MTGAbility * a1 = multi;
selection.push_back(a1);
AAMover *b = NEW AAMover(this, this->mLayers->actionLayer()->getMaxId(), card, card,"ownergraveyard","Keep Old");
b->oneShot = true;
MTGAbility * b1 = b;
selection.push_back(b1);
MTGAbility * menuChoice = NEW MenuAbility(this, this->mLayers->actionLayer()->getMaxId(), card, card,true,selection,card->controller(),"Legendary Rule");
menuChoice->addToGame();
}
return;
}
void GameObserver::enchantmentStatus()
{
for (int i = 0; i < 2; i++)
@@ -1118,6 +1174,26 @@ void GameObserver::Affinity()
///we handle trisnisphere seperately because its a desaster.
if(card->getManaCost())//make sure we check, abiliy$!/token dont have a mancost object.
{
//change cost to colorless for anytypeofmana ability
if(card->has(Constants::ANYTYPEOFMANA))
{
card->anymanareplacement = true;
int convertedC = card->getManaCost()->getConvertedCost();
card->getManaCost()->changeCostTo( NEW ManaCost(ManaCost::parseManaCost("{0}", NULL, card)) );
for (int jj = 0; jj < convertedC; jj++)
{
card->getManaCost()->add(Constants::MTG_COLOR_ARTIFACT, 1);
}
}
else
{
if (card->anymanareplacement)
{
card->getManaCost()->changeCostTo( card->model->data->getManaCost() );
card->anymanareplacement = false;
}
}
if (card->has(Constants::TRINISPHERE))
{
for (int jj = card->getManaCost()->getConvertedCost(); jj < 3; jj++)
+4 -6
View File
@@ -151,12 +151,10 @@ void GuiPhaseBar::Render()
sprintf(buf, _("(%s%s) %s").c_str(), currentP.c_str(), interrupt.c_str(),phaseNameToTranslate.c_str());
#if !defined (PSP)
if(phaseinfo.get())
{
phaseinfo->mWidth = font->GetStringWidth(buf)+12.f;
phaseinfo->SetHotSpot(phaseinfo->mWidth -4, 0);
//phaseinfo->mHeight = font->GetHeight()+5.f;
JRenderer::GetInstance()->RenderQuad(phaseinfo.get(),SCREEN_WIDTH_F,0,0,2.2f, SCREEN_HEIGHT_F / phaseinfo->mHeight);
{//fix phaseinfo graphics... should look nice now...
float testW = ((font->GetStringWidth(buf))*2) - SCREEN_WIDTH_F;
phaseinfo->SetHotSpot(testW+40.f, 0);
JRenderer::GetInstance()->RenderQuad(phaseinfo.get(),0,0,0,SCREEN_WIDTH_F / phaseinfo->mWidth, SCREEN_HEIGHT_F / phaseinfo->mHeight);
}
#endif
font->DrawString(buf, SCREEN_WIDTH - 5, 2, JGETEXT_RIGHT);
+22 -4
View File
@@ -31,6 +31,7 @@ void GuiAvatar::Render()
JRenderer * r = JRenderer::GetInstance();
int life = player->life;
int poisonCount = player->poisonCount;
int energyCount = player->energyCount;
WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
mFont->SetScale(DEFAULT_MAIN_FONT_SCALE);
//Avatar
@@ -108,10 +109,10 @@ void GuiAvatar::Render()
{
case TOP_LEFT:
mFont->SetColor(ARGB((int)actA / 4, 0, 0, 0));
mFont->DrawString(buffer, actX + 2, actY + 2);
mFont->DrawString(buffer, actX + 2, actY - 2);
mFont->SetScale(1.3f);
mFont->SetColor(ARGB((int)actA, lx, ly, lz));
mFont->DrawString(buffer, actX + 1, actY + 1);
mFont->DrawString(buffer, actX + 1, actY - 1);
mFont->SetScale(1);
break;
case BOTTOM_RIGHT:
@@ -122,8 +123,8 @@ void GuiAvatar::Render()
break;
}
//poison
char poison[5];
if (poisonCount > 0)
char poison[10];
if (poisonCount >= 0)
{
sprintf(poison, "%i", poisonCount);
switch (corner)
@@ -138,6 +139,23 @@ void GuiAvatar::Render()
break;
}
}
//energy
char energy[15];
if (energyCount >= 0)
{
sprintf(energy, "%i", energyCount);
switch (corner)
{
case TOP_LEFT:
mFont->SetColor(ARGB((int)actA / 1, 255, 255, 0));
mFont->DrawString(energy, actX + 2, actY + 17);
break;
case BOTTOM_RIGHT:
mFont->SetColor(ARGB((int)actA / 1 ,255, 255, 0));
mFont->DrawString(energy, actX, actY - 27, JGETEXT_RIGHT);
break;
}
}
PlayGuiObject::Render();
}
+96 -2
View File
@@ -329,6 +329,37 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
if(!count)
return 0;
}
check = restriction[i].find("revolt");
if(check != string::npos)
{
int count = 0;
for(unsigned int k = 0; k < player->game->hand->cardsSeenThisTurn.size(); k++)
{
MTGCardInstance * tCard = player->game->hand->cardsSeenThisTurn[k];
if(tCard && tCard->previousZone == card->controller()->game->battlefield)
count++;
}
for(unsigned int k = 0; k < player->game->exile->cardsSeenThisTurn.size(); k++)
{
MTGCardInstance * tCard = player->game->exile->cardsSeenThisTurn[k];
if(tCard && tCard->previousZone == card->controller()->game->battlefield)
count++;
}
for(unsigned int k = 0; k < player->game->library->cardsSeenThisTurn.size(); k++)
{
MTGCardInstance * tCard = player->game->library->cardsSeenThisTurn[k];
if(tCard && tCard->previousZone == card->controller()->game->battlefield)
count++;
}
for(unsigned int k = 0; k < player->game->graveyard->cardsSeenThisTurn.size(); k++)
{
MTGCardInstance * tCard = player->game->graveyard->cardsSeenThisTurn[k];
if(tCard && tCard->previousZone == card->controller()->game->battlefield)
count++;
}
if(!count)
return 0;
}
check = restriction[i].find("morbid");
if(check != string::npos)
{
@@ -510,6 +541,22 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
return 0;
}
check = restriction[i].find("opponentdamagedbycombat");
if(check != string::npos)
{
if(card->controller()->dealsdamagebycombat < 1)
return 0;
}
check = restriction[i].find("outnumbered");//opponent controls atleast 4 or more creatures than you
if(check != string::npos)
{
bool isoutnumbered = (card->controller()->opponent()->inPlay()->countByType("creature") - card->controller()->inPlay()->countByType("creature"))>3;
if(!isoutnumbered)
return 0;
}
check = restriction[i].find("hasdefender");
if(check != string::npos)
{
@@ -531,6 +578,13 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
return 0;
}
check = restriction[i].find("didcombatdamagetofoe");
if(check != string::npos)
{
if(!card->combatdamageToOpponent)
return 0;
}
check = restriction[i].find("ownerscontrol");
if(check != string::npos)
{
@@ -936,6 +990,14 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell
}
//energized player - controller of card
if (TargetChooser * tc = parseSimpleTC(s, "energizedof", card))
return NEW TrplayerEnergized(observer, id, card, tc,once,true,false);
//energized player - opponent of card controller
if (TargetChooser * tc = parseSimpleTC(s, "energizedfoeof", card))
return NEW TrplayerEnergized(observer, id, card, tc,once,false,true);
//drawn player - controller of card - dynamic version drawof(player) -> returns current controller even with exchange of card controller
if (TargetChooser * tc = parseSimpleTC(s, "drawof", card))
return NEW TrcardDrawn(observer, id, card, tc,once,true,false);
@@ -1331,7 +1393,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
found = s.find("legendrule");
if(found != string::npos)
{
observer->addObserver(NEW MTGLegendRule(observer, -1));
//I replaced this rule since it broke cards with copy effects and with andability and other
//complex cards. So I moved it to gameobserver state based effects, if there are no more
//abilities that needs resolving then trigger this legend check... example bug:
//cast Phantasmal Image, then copy Vendilion Clique in play, after you choose target player
//there will be infinite menu for legendary rule that conflicts with Phantasmal andAbility
//observer->addObserver(NEW MTGLegendRule(observer, -1));
observer->foundlegendrule = true;
return NULL;
}
//this handles the planeswalker named legend rule which is dramatically different from above.
@@ -2678,6 +2746,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
{
MTGAbility * a = NEW AALibraryBottom(observer, id, card, target);
a->oneShot = 1;
//andability
if(storedAndAbility.size())
{
string stored = storedAndAbility;
storedAndAbility.clear();
((AALibraryBottom*)a)->andAbility = parseMagicLine(stored, id, spell, card);
}
return a;
}
@@ -2949,6 +3024,17 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a;
}
//alter energy
vector<string> splitEnergy = parseBetween(s, "alterenergy:", " ", false);
if (splitEnergy.size())
{
int energy = atoi(splitEnergy[1].c_str());
Targetable * t = spell ? spell->getNextTarget() : NULL;
MTGAbility * a = NEW AAAlterEnergy(observer, id, card, t, energy, NULL, who);
a->oneShot = 1;
return a;
}
//prevent next damage
vector<string> splitPrevent = parseBetween(s, "prevent:", " ", false);
if (splitPrevent.size())
@@ -3487,7 +3573,15 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
a->oneShot = 1;
a->canBeInterrupted = false;
a->named = newName;
return a;
if(card->getAICustomCode().size() && card->controller()->isAI())
{
MTGAbility * a3 = parseMagicLine(card->getAICustomCode(), id, spell, card);
a3->oneShot = 1;
a3->canBeInterrupted = false;
return a3;
}
else
return a;
}
//scry:x (activate aility)
+9 -2
View File
@@ -130,6 +130,7 @@ void MTGCardInstance::copy(MTGCardInstance * card)
alias = data->alias;
copiedID = card->copiedID;
doubleFaced = data->doubleFaced;
AICustomCode = data->AICustomCode;
origpower = card->origpower;//for flip
origtoughness = card->origtoughness;//for flip
@@ -217,6 +218,7 @@ void MTGCardInstance::initMTGCI()
sunburst = 0;
equipment = 0;
auras = 0;
combatdamageToOpponent = false;
damageToOpponent = false;
damageToController = false;
damageToCreature = false;
@@ -241,6 +243,7 @@ void MTGCardInstance::initMTGCI()
miracle = false;
hasCopiedToken = false;
countTrini = 0;
anymanareplacement = false;
imprintedCards.clear();
attackCost = 0;
attackCostBackup = 0;
@@ -806,14 +809,18 @@ void MTGCardInstance::switchPT(bool apply)
int MTGCardInstance::getCurrentPower()
{
if(!isInPlay(observer))
if(observer && !isCreature())
return 0;
if(observer && !isInPlay(observer))
return LKIpower;
return power;
}
int MTGCardInstance::getCurrentToughness()
{
if(!isInPlay(observer))
if(observer && !isCreature())
return 0;
if(observer && !isInPlay(observer))
return LKItoughness;
return toughness;
}
+6 -1
View File
@@ -58,7 +58,12 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi
switch (key[0])
{
case 'a':
if (key == "auto")
if (key == "aicode")//replacement code for AI. for reveal:number basic version only
{
if (!primitive) primitive = NEW CardPrimitive();
primitive->setAICustomCode(val);
}
else if (key == "auto")
{
if (!primitive) primitive = NEW CardPrimitive();
primitive->addMagicText(val);
+4 -1
View File
@@ -173,7 +173,10 @@ const char* Constants::MTGBasicAbilities[] = {
"asflash",
"conduited",
"canblocktapped",
"oppnomaxhand"
"oppnomaxhand",
"cantcrew",
"hiddenface",//test for facedown
"anytypeofmana"
};
map<string,int> Constants::MTGBasicAbilitiesMap;
+6
View File
@@ -296,11 +296,13 @@ MTGPutInPlayRule::MTGPutInPlayRule(GameObserver* observer, int _id) :
PermanentAbility(observer, _id)
{
aType = MTGAbility::PUT_INTO_PLAY;
defaultPlayName = "";
}
int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
{
int cardsinhand = game->players[0]->game->hand->nb_cards;
defaultPlayName = card->isLand()?"Play Land":"Cast Card Normally";
Player * player = game->currentlyActing();
if (!player->game->hand->hasCard(card) && !player->game->graveyard->hasCard(card) && !player->game->exile->hasCard(card))
return 0;
@@ -754,6 +756,8 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *
return 0;
alternativeName = "Pay Alternative Cost";
if(card->has(Constants::CANPLAYFROMGRAVEYARD))
alternativeName = "Alternate Cast From Graveyard";
else if(card->has(Constants::CANPLAYFROMEXILE))
@@ -763,6 +767,8 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *
if (card->isLand())
{
alternativeName = "Play Land";
if (game->currentActionPlayer->game->playRestrictions->canPutIntoZone(card, game->currentActionPlayer->game->inPlay) == PlayRestriction::CANT_PLAY)
return 0;
if (card->StackIsEmptyandSorcerySpeed())
+17 -1
View File
@@ -159,6 +159,15 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
tc = tcf.createTargetChooser("creature|mybattlefield", c);
manaCost->addExtraCost(NEW Offering(tc,true));
}
else if(value.substr(0,2) == "e:")
{//Energy Cost
vector<string>valSplit = parseBetween(value,"e:"," ",false);
if (valSplit.size()) {
WParsedInt* energytopay = NEW WParsedInt(valSplit[1], NULL, c);
manaCost->addExtraCost(NEW EnergyCost(energytopay->getValue()));
SAFE_DELETE(energytopay);
}
}
else
//Exile
manaCost->addExtraCost(NEW ExileTargetCost(tc));
@@ -248,12 +257,19 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
break;
}
case 'i' :
if(value == "improvise")
{
if(!tc)
tc = tcf.createTargetChooser("artifact[-tapped]|myBattlefield", c);
manaCost->addExtraCost(NEW Improvise(tc));
}
else
{
SAFE_DELETE(tc);
manaCost->add(0,1);
manaCost->addExtraCost(NEW SnowCost);
break;
}
break;
case 'q':
if(value == "q")
{
+2
View File
@@ -34,8 +34,10 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
skippingTurn = 0;
extraTurn = 0;
drawCounter = 0;
energyCount = 0;
epic = 0;
forcefield = 0;
dealsdamagebycombat = 0;
raidcount = 0;
handmodifier = 0;
snowManaG = 0;
+1
View File
@@ -409,6 +409,7 @@ void Rules::initGame(GameObserver *g, bool currentPlayerSet)
p->poisonCount = initState.playerData[i].player->poisonCount;
p->damageCount = initState.playerData[i].player->damageCount;
p->preventable = initState.playerData[i].player->preventable;
p->energyCount = initState.playerData[i].player->energyCount;
if (initState.playerData[i].player->mAvatarName.size())
{
p->mAvatarName = initState.playerData[i].player->mAvatarName;
+4
View File
@@ -746,6 +746,10 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
{
cd->anyCounter = 1;
}
else if (attribute.find("{notany}") != string::npos)
{
cd->anyCounter = -1;
}
else
{
size_t start = attribute.find("{");
+11
View File
@@ -240,6 +240,11 @@ WEventCombatStepChange::WEventCombatStepChange(CombatStep step) :
WEvent(), step(step)
{
}
WEventplayerEnergized::WEventplayerEnergized(Player * player, int nb_count) :
player(player), nb_count(nb_count)
{
}
;
Targetable * WEventDamage::getTarget(int target)
@@ -408,6 +413,12 @@ Targetable * WEventCardTransforms::getTarget(int target)
return NULL;
}
Targetable * WEventplayerEnergized::getTarget(Player * player)
{
if (player) return player;
return NULL;
}
std::ostream& WEvent::toString(std::ostream& out) const
{
return out << "EVENT";
+40
View File
@@ -263,6 +263,46 @@ JQuadPtr ResourceManagerImpl::RetrieveCard(MTGCard * card, int style, int submod
return JQuadPtr();
}
JQuadPtr ResourceManagerImpl::RetrieveCardToken(MTGCard * card, int style, int submode, int tId)
{
//Cards are never, ever resource managed, so just check cache.
if (!card || options[Options::DISABLECARDS].number) return JQuadPtr();
submode = submode | TEXTURE_SUB_CARD;
//static std::ostringstream filename;
//filename.str("");
string filename;
filename.reserve(4096);
//filename << setlist[card->setId] << "/" << card->getImageName();
filename.append(setlist[card->setId]);
filename.append("/");
int id = -card->getMTGId();
if(tId)
id = -tId;
ostringstream imagename;
imagename << "-" << id << "t.jpg";
filename.append(imagename.str());
//Aliases.
if (style == RETRIEVE_THUMB)
{
submode = submode | TEXTURE_SUB_THUMB;
style = RETRIEVE_NORMAL;
}
JQuadPtr jq = RetrieveQuad(filename, 0, 0, 0, 0, "", style, submode | TEXTURE_SUB_5551, id);
lastError = textureWCache.mError;
if (jq)
{
jq->SetHotSpot(static_cast<float> (jq->mTex->mWidth / 2), static_cast<float> (jq->mTex->mHeight / 2));
return jq;
}
return JQuadPtr();
}
int ResourceManagerImpl::AddQuadToManaged(const WManagedQuad& inQuad)
{
int id = mIDLookupMap.size();