massive update, additions and changelog in first comment.
This commit is contained in:
@@ -172,6 +172,7 @@ class ActionStack :public GuiLayer{
|
|||||||
int addAction(Interruptible * interruptible);
|
int addAction(Interruptible * interruptible);
|
||||||
Spell * addSpell(MTGCardInstance* card, TargetChooser * tc, ManaCost * mana, int payResult, int storm);
|
Spell * addSpell(MTGCardInstance* card, TargetChooser * tc, ManaCost * mana, int payResult, int storm);
|
||||||
int AddNextGamePhase();
|
int AddNextGamePhase();
|
||||||
|
int AddNextCombatStep();
|
||||||
int addPutInGraveyard(MTGCardInstance * card);
|
int addPutInGraveyard(MTGCardInstance * card);
|
||||||
int addDraw(Player * player, int nbcards = 1);
|
int addDraw(Player * player, int nbcards = 1);
|
||||||
int addDamage(MTGCardInstance * _source, Damageable * target, int _damage);
|
int addDamage(MTGCardInstance * _source, Damageable * target, int _damage);
|
||||||
|
|||||||
@@ -60,6 +60,11 @@ public:
|
|||||||
intValue = target->equipment;
|
intValue = target->equipment;
|
||||||
}else if (s == "manacost"){
|
}else if (s == "manacost"){
|
||||||
intValue = target->getManaCost()->getConvertedCost();
|
intValue = target->getManaCost()->getConvertedCost();
|
||||||
|
}else if (s == "sunburst"){
|
||||||
|
intValue = 0;
|
||||||
|
if(card && card->previous && card->previous->previous){
|
||||||
|
intValue = card->previous->previous->sunburst;
|
||||||
|
}
|
||||||
}else if (s == "lifetotal"){
|
}else if (s == "lifetotal"){
|
||||||
intValue = target->controller()->life;
|
intValue = target->controller()->life;
|
||||||
}else if (s == "odcount"){
|
}else if (s == "odcount"){
|
||||||
@@ -188,11 +193,240 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TrCardTappedformana:public TriggeredAbility{
|
||||||
|
public:
|
||||||
|
TargetChooser * tc;
|
||||||
|
bool tap;
|
||||||
|
TrCardTappedformana(int id, MTGCardInstance * source, TargetChooser * tc, bool tap = true):TriggeredAbility(id,source), tc(tc),tap(tap){}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
return 0; //This is a trigger, this function should not be called
|
||||||
|
}
|
||||||
|
|
||||||
|
int triggerOnEvent(WEvent * event){
|
||||||
|
WEventCardTappedForMana * e = dynamic_cast<WEventCardTappedForMana *>(event);
|
||||||
|
if (!e) return 0;
|
||||||
|
if (e->before == e->after) return 0;
|
||||||
|
if (e->after != tap) return 0;
|
||||||
|
if (!tc->canTarget(e->card)) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TrCardTappedformana(){
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrCardTappedformana * clone() const{
|
||||||
|
TrCardTappedformana * a = NEW TrCardTappedformana(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TrCardAttackedNotBlocked:public TriggeredAbility{
|
||||||
|
public:
|
||||||
|
TargetChooser * tc;
|
||||||
|
TrCardAttackedNotBlocked(int id, MTGCardInstance * source, TargetChooser * tc):TriggeredAbility(id,source), tc(tc){}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
return 0; //This is a trigger, this function should not be called
|
||||||
|
}
|
||||||
|
|
||||||
|
int triggerOnEvent(WEvent * event){
|
||||||
|
WEventCardAttackedNotBlocked * e = dynamic_cast<WEventCardAttackedNotBlocked *>(event);
|
||||||
|
if (!e) return 0;
|
||||||
|
if(e->card->didattacked < 1) return 0;
|
||||||
|
if(e->card->blocked) return 0;
|
||||||
|
if (!tc->canTarget(e->card)) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TrCardAttackedNotBlocked(){
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrCardAttackedNotBlocked * clone() const{
|
||||||
|
TrCardAttackedNotBlocked * a = NEW TrCardAttackedNotBlocked(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TrCardAttackedBlocked:public TriggeredAbility{
|
||||||
|
public:
|
||||||
|
TargetChooser * tc;
|
||||||
|
TargetChooser * fromTc;
|
||||||
|
TrCardAttackedBlocked(int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL ):TriggeredAbility(id,source), tc(tc), fromTc(fromTc){}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
return 0; //This is a trigger, this function should not be called
|
||||||
|
}
|
||||||
|
|
||||||
|
int triggerOnEvent(WEvent * event){
|
||||||
|
WEventCardAttackedBlocked * e = dynamic_cast<WEventCardAttackedBlocked *>(event);
|
||||||
|
if (!e) return 0;
|
||||||
|
if(e->card->didattacked < 1) return 0;
|
||||||
|
if(!e->card->blocked) return 0;
|
||||||
|
if (fromTc && !fromTc->canTarget(e->card->getNextOpponent())) return 0;
|
||||||
|
if (!tc->canTarget(e->card)) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TrCardAttackedBlocked(){
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
SAFE_DELETE(fromTc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrCardAttackedBlocked * clone() const{
|
||||||
|
TrCardAttackedBlocked * a = NEW TrCardAttackedBlocked(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TrCardAttacked:public TriggeredAbility{
|
||||||
|
public:
|
||||||
|
TargetChooser * tc;
|
||||||
|
TrCardAttacked(int id, MTGCardInstance * source, TargetChooser * tc):TriggeredAbility(id,source), tc(tc){}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
return 0; //This is a trigger, this function should not be called
|
||||||
|
}
|
||||||
|
|
||||||
|
int triggerOnEvent(WEvent * event){
|
||||||
|
WEventCardAttacked * e = dynamic_cast<WEventCardAttacked *>(event);
|
||||||
|
if (!e) return 0;
|
||||||
|
if(e->card->didattacked < 1) return 0;
|
||||||
|
if (!tc->canTarget(e->card)) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TrCardAttacked(){
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrCardAttacked * clone() const{
|
||||||
|
TrCardAttacked * a = NEW TrCardAttacked(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TrCardBlocked:public TriggeredAbility{
|
||||||
|
public:
|
||||||
|
TargetChooser * tc;
|
||||||
|
TargetChooser * fromTc;
|
||||||
|
TrCardBlocked(int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL):TriggeredAbility(id,source), tc(tc), fromTc(fromTc){}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
return 0; //This is a trigger, this function should not be called
|
||||||
|
}
|
||||||
|
|
||||||
|
int triggerOnEvent(WEvent * event){
|
||||||
|
WEventCardBlocked * e = dynamic_cast<WEventCardBlocked *>(event);
|
||||||
|
if (!e) return 0;
|
||||||
|
//if(e->card->didblocked < 1) return 0;
|
||||||
|
if (fromTc && !fromTc->canTarget(e->card->getNextOpponent())) return 0;
|
||||||
|
if (!tc->canTarget(e->card)) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TrCardBlocked(){
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
SAFE_DELETE(fromTc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrCardBlocked * clone() const{
|
||||||
|
TrCardBlocked * a = NEW TrCardBlocked(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TrcardDrawn:public TriggeredAbility{
|
||||||
|
public:
|
||||||
|
TargetChooser * tc;
|
||||||
|
TrcardDrawn(int id, MTGCardInstance * source, TargetChooser * tc):TriggeredAbility(id,source), tc(tc){}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
return 0; //This is a trigger, this function should not be called
|
||||||
|
}
|
||||||
|
|
||||||
|
int triggerOnEvent(WEvent * event){
|
||||||
|
WEventcardDraw * e = dynamic_cast<WEventcardDraw *>(event);
|
||||||
|
if (!e) return 0;
|
||||||
|
if (!tc->canTarget(e->player))return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TrcardDrawn(){
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrcardDrawn * clone() const{
|
||||||
|
TrcardDrawn * a = NEW TrcardDrawn(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TrCardSacrificed:public TriggeredAbility{
|
||||||
|
public:
|
||||||
|
TargetChooser * tc;
|
||||||
|
TrCardSacrificed(int id, MTGCardInstance * source, TargetChooser * tc):TriggeredAbility(id,source), tc(tc){}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
return 0; //This is a trigger, this function should not be called
|
||||||
|
}
|
||||||
|
|
||||||
|
int triggerOnEvent(WEvent * event){
|
||||||
|
WEventCardSacrifice * e = dynamic_cast<WEventCardSacrifice *>(event);
|
||||||
|
if (!e) return 0;
|
||||||
|
if (!tc->canTarget(e->card)) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TrCardSacrificed(){
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrCardSacrificed * clone() const{
|
||||||
|
TrCardSacrificed * a = NEW TrCardSacrificed(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TrCardDiscarded:public TriggeredAbility{
|
||||||
|
public:
|
||||||
|
TargetChooser * tc;
|
||||||
|
TrCardDiscarded(int id, MTGCardInstance * source, TargetChooser * tc):TriggeredAbility(id,source), tc(tc){}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
return 0; //This is a trigger, this function should not be called
|
||||||
|
}
|
||||||
|
int triggerOnEvent(WEvent * event){
|
||||||
|
WEventCardDiscard * e = dynamic_cast<WEventCardDiscard *>(event);
|
||||||
|
if (!e) return 0;
|
||||||
|
if (!tc->canTarget(e->card)) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
~TrCardDiscarded(){
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
}
|
||||||
|
TrCardDiscarded * clone() const{
|
||||||
|
TrCardDiscarded * a = NEW TrCardDiscarded(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class TrDamaged:public TriggeredAbility{
|
class TrDamaged:public TriggeredAbility{
|
||||||
public:
|
public:
|
||||||
TargetChooser * tc;
|
TargetChooser * tc;
|
||||||
TargetChooser * fromTc;
|
TargetChooser * fromTc;
|
||||||
TrDamaged (int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL):TriggeredAbility(id,source), tc(tc), fromTc(fromTc){}
|
int type;//this allows damagenoncombat and combatdamage to share this trigger
|
||||||
|
TrDamaged (int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL,int type = 0):TriggeredAbility(id,source), tc(tc), fromTc(fromTc), type(type){}
|
||||||
|
|
||||||
int resolve(){
|
int resolve(){
|
||||||
return 0; //This is a trigger, this function should not be called
|
return 0; //This is a trigger, this function should not be called
|
||||||
@@ -203,6 +437,8 @@ public:
|
|||||||
if (!e) return 0;
|
if (!e) return 0;
|
||||||
if(!tc->canTarget(e->damage->target)) return 0;
|
if(!tc->canTarget(e->damage->target)) return 0;
|
||||||
if (fromTc && !fromTc->canTarget(e->damage->source)) return 0;
|
if (fromTc && !fromTc->canTarget(e->damage->source)) return 0;
|
||||||
|
if (type == 1 && e->damage->typeOfDamage != DAMAGE_COMBAT ) return 0;
|
||||||
|
if (type == 2 && e->damage->typeOfDamage == DAMAGE_COMBAT ) return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,6 +732,102 @@ class AACopier:public ActivatedAbility{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//cloning...this makes a token thats a copy of the target.
|
||||||
|
class AACloner:public ActivatedAbility{
|
||||||
|
public:
|
||||||
|
int who;
|
||||||
|
string with;
|
||||||
|
list<int>awith;
|
||||||
|
list<int>colors;
|
||||||
|
AACloner(int _id, MTGCardInstance * _source, MTGCardInstance * _target = NULL, ManaCost * _cost=NULL, int who = 0,string with =""):ActivatedAbility(_id,_source,_cost,0,0), who(who){
|
||||||
|
target = _target;
|
||||||
|
source = _source;
|
||||||
|
|
||||||
|
for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){
|
||||||
|
size_t found = with.find(Constants::MTGBasicAbilities[j]);
|
||||||
|
if (found != string::npos){
|
||||||
|
awith.push_back(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int j = 0; j < Constants::MTG_NB_COLORS; j++){
|
||||||
|
size_t found = with.find(Constants::MTGColorStrings[j]);
|
||||||
|
if (found != string::npos){
|
||||||
|
colors.push_back(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
|
if(_target && !_target->isToken){
|
||||||
|
MTGCardInstance * myClone;
|
||||||
|
MTGCard * clone = GameApp::collection->getCardById(_target->getId());
|
||||||
|
myClone = NULL;
|
||||||
|
if(who != 1) myClone = NEW MTGCardInstance(clone,source->controller()->game);
|
||||||
|
if(who == 1) myClone = NEW MTGCardInstance(clone,source->controller()->opponent()->game);
|
||||||
|
if(who != 1) source->controller()->game->temp->addCard(myClone);
|
||||||
|
else source->controller()->opponent()->game->temp->addCard(myClone);
|
||||||
|
Spell * spell = NEW Spell(myClone);
|
||||||
|
spell->resolve();
|
||||||
|
spell->source->isToken = 1;
|
||||||
|
spell->source->fresh = 1;
|
||||||
|
list<int>::iterator it;
|
||||||
|
for ( it=awith.begin() ; it != awith.end(); it++ ){
|
||||||
|
spell->source->basicAbilities[*it] = 1;
|
||||||
|
}
|
||||||
|
for ( it=colors.begin() ; it != colors.end(); it++ ){
|
||||||
|
spell->source->setColor(*it);
|
||||||
|
}
|
||||||
|
delete spell;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(_target && _target->isToken){
|
||||||
|
MTGCardInstance * myClone;
|
||||||
|
MTGCardInstance * clone = _target;
|
||||||
|
myClone = NULL;
|
||||||
|
if(who != 1) myClone = NEW MTGCardInstance(clone,source->controller()->game);
|
||||||
|
if(who == 1) myClone = NEW MTGCardInstance(clone,source->controller()->opponent()->game);
|
||||||
|
if(who != 1) source->controller()->game->temp->addCard(myClone);
|
||||||
|
else source->controller()->opponent()->game->temp->addCard(myClone);
|
||||||
|
Spell * spell = NEW Spell(myClone);
|
||||||
|
spell->resolve();
|
||||||
|
spell->source->isToken = 1;
|
||||||
|
spell->source->fresh = 1;
|
||||||
|
list<int>::iterator it;
|
||||||
|
for ( it=awith.begin() ; it != awith.end(); it++ ){
|
||||||
|
spell->source->basicAbilities[*it] = 1;
|
||||||
|
}
|
||||||
|
for ( it=colors.begin() ; it != colors.end(); it++ ){
|
||||||
|
spell->source->setColor(*it);
|
||||||
|
}
|
||||||
|
delete spell;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * getMenuText(){
|
||||||
|
if(who == 1) return "Clone For Opponent";
|
||||||
|
return "Clone";
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ostream& toString(ostream& out) const
|
||||||
|
{
|
||||||
|
out << "AACloner ::: with : ?" // << abilities
|
||||||
|
<< " (";
|
||||||
|
return ActivatedAbility::toString(out) << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AACloner * clone() const{
|
||||||
|
AACloner * a = NEW AACloner(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
~AACloner(){}
|
||||||
|
};
|
||||||
|
|
||||||
class AAMover:public ActivatedAbility{
|
class AAMover:public ActivatedAbility{
|
||||||
public:
|
public:
|
||||||
string destination;
|
string destination;
|
||||||
@@ -652,6 +984,9 @@ class ACycle:public ActivatedAbility{
|
|||||||
}
|
}
|
||||||
|
|
||||||
int resolve(){
|
int resolve(){
|
||||||
|
WEvent * e = NEW WEventCardDiscard(source);
|
||||||
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
|
game->receiveEvent(e);
|
||||||
source->controller()->game->putInGraveyard(source);
|
source->controller()->game->putInGraveyard(source);
|
||||||
source->controller()->game->drawFromLibrary();
|
source->controller()->game->drawFromLibrary();
|
||||||
return 1;
|
return 1;
|
||||||
@@ -670,6 +1005,37 @@ class ACycle:public ActivatedAbility{
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//ninjutsu
|
||||||
|
|
||||||
|
class ANinja:public ActivatedAbility{
|
||||||
|
public:
|
||||||
|
ANinja(int _id, MTGCardInstance * card,Targetable * _target):ActivatedAbility(_id, card){
|
||||||
|
target = _target;
|
||||||
|
}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
MTGCardInstance * copy = source->controller()->game->putInZone(source, source->controller()->game->hand, source->controller()->game->temp);
|
||||||
|
Spell * spell = NEW Spell(copy);
|
||||||
|
spell->resolve();
|
||||||
|
MTGCardInstance * newcard = spell->source;
|
||||||
|
newcard->summoningSickness = 0;
|
||||||
|
newcard->tap();
|
||||||
|
newcard->setAttacker(1);
|
||||||
|
delete spell;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * getMenuText(){
|
||||||
|
return "Ninjutsu";
|
||||||
|
}
|
||||||
|
|
||||||
|
ANinja * clone() const{
|
||||||
|
ANinja * a = NEW ANinja(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//Drawer, allows to draw a card for a cost:
|
//Drawer, allows to draw a card for a cost:
|
||||||
|
|
||||||
@@ -845,16 +1211,18 @@ public:
|
|||||||
int tokenId;
|
int tokenId;
|
||||||
string name;
|
string name;
|
||||||
WParsedInt * multiplier;
|
WParsedInt * multiplier;
|
||||||
ATokenCreator(int _id,MTGCardInstance * _source,ManaCost * _cost, int tokenId, int _doTap, WParsedInt * multiplier = NULL):ActivatedAbility(_id,_source,_cost,0,_doTap), tokenId(tokenId), multiplier(multiplier){
|
int who;
|
||||||
|
ATokenCreator(int _id,MTGCardInstance * _source,ManaCost * _cost, int tokenId, int _doTap, WParsedInt * multiplier = NULL,int who = 0):ActivatedAbility(_id,_source,_cost,0,_doTap), tokenId(tokenId), multiplier(multiplier), who(who){
|
||||||
if(!multiplier) this->multiplier = NEW WParsedInt(1);
|
if(!multiplier) this->multiplier = NEW WParsedInt(1);
|
||||||
MTGCard * card = GameApp::collection->getCardById(tokenId);
|
MTGCard * card = GameApp::collection->getCardById(tokenId);
|
||||||
if (card) name = card->data->getName();
|
if (card) name = card->data->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
ATokenCreator(int _id,MTGCardInstance * _source,ManaCost * _cost, string sname, string stypes,int _power,int _toughness, string sabilities, int _doTap, WParsedInt * multiplier = NULL):ActivatedAbility(_id,_source,_cost,0,_doTap), multiplier(multiplier){
|
ATokenCreator(int _id,MTGCardInstance * _source,ManaCost * _cost, string sname, string stypes,int _power,int _toughness, string sabilities, int _doTap, WParsedInt * multiplier = NULL,int who = 0):ActivatedAbility(_id,_source,_cost,0,_doTap), multiplier(multiplier),who(who){
|
||||||
power = _power;
|
power = _power;
|
||||||
toughness = _toughness;
|
toughness = _toughness;
|
||||||
name = sname;
|
name = sname;
|
||||||
|
who = who;
|
||||||
tokenId = 0;
|
tokenId = 0;
|
||||||
if(!multiplier) this->multiplier = NEW WParsedInt(1);
|
if(!multiplier) this->multiplier = NEW WParsedInt(1);
|
||||||
//TODO this is a copy/past of other code that's all around the place, everything should be in a dedicated parser class;
|
//TODO this is a copy/past of other code that's all around the place, everything should be in a dedicated parser class;
|
||||||
@@ -907,11 +1275,22 @@ public:
|
|||||||
myToken->basicAbilities[*it] = 1;
|
myToken->basicAbilities[*it] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(who == 0 || who != 1){
|
||||||
source->controller()->game->temp->addCard(myToken);
|
source->controller()->game->temp->addCard(myToken);
|
||||||
Spell * spell = NEW Spell(myToken);
|
Spell * spell = NEW Spell(myToken);
|
||||||
spell->resolve();
|
spell->resolve();
|
||||||
spell->source->isToken = 1;
|
spell->source->isToken = 1;
|
||||||
|
spell->source->fresh = 1;
|
||||||
delete spell;
|
delete spell;
|
||||||
|
}else if (who == 1){
|
||||||
|
source->controller()->opponent()->game->temp->addCard(myToken);
|
||||||
|
Spell * spell = NEW Spell(myToken);
|
||||||
|
spell->resolve();
|
||||||
|
spell->source->owner = spell->source->controller();
|
||||||
|
spell->source->isToken = 1;
|
||||||
|
spell->source->fresh = 1;
|
||||||
|
delete spell;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -929,6 +1308,7 @@ public:
|
|||||||
<< " ; power : " << power
|
<< " ; power : " << power
|
||||||
<< " ; toughness : " << toughness
|
<< " ; toughness : " << toughness
|
||||||
<< " ; name : " << name
|
<< " ; name : " << name
|
||||||
|
<< " ; who : " << who
|
||||||
<< " (";
|
<< " (";
|
||||||
return ActivatedAbility::toString(out) << ")";
|
return ActivatedAbility::toString(out) << ")";
|
||||||
}
|
}
|
||||||
@@ -1007,7 +1387,47 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AASacDis:public ActivatedAbility{
|
||||||
|
public:
|
||||||
|
int sacrifice;
|
||||||
|
AASacDis(int _id, MTGCardInstance * _source, MTGCardInstance * _target, int _sacrifice = 0, ManaCost * _cost=NULL):ActivatedAbility(_id,_source,_cost),sacrifice(_sacrifice){
|
||||||
|
if (_target) target = _target;
|
||||||
|
}
|
||||||
|
int resolve(){
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
|
|
||||||
|
if(_target){
|
||||||
|
Player * p = _target->controller();
|
||||||
|
Player * owner = _target->owner;
|
||||||
|
if (sacrifice)
|
||||||
|
{
|
||||||
|
WEvent * e = NEW WEventCardSacrifice(_target);
|
||||||
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
|
game->receiveEvent(e);
|
||||||
|
p->game->putInGraveyard(_target);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WEvent * e = NEW WEventCardDiscard(_target);
|
||||||
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
|
game->receiveEvent(e);
|
||||||
|
p->game->putInGraveyard(_target);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const char * getMenuText(){
|
||||||
|
if(sacrifice) return "Sacrifice";
|
||||||
|
else return "Discard";
|
||||||
|
}
|
||||||
|
AASacDis * clone() const{
|
||||||
|
AASacDis * a = NEW AASacDis(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*Changes one of the basic abilities of target
|
/*Changes one of the basic abilities of target
|
||||||
source : spell
|
source : spell
|
||||||
@@ -2075,6 +2495,8 @@ public:
|
|||||||
a = NULL;
|
a = NULL;
|
||||||
SAFE_DELETE(tc);
|
SAFE_DELETE(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int removeFromGame(){
|
int removeFromGame(){
|
||||||
return removeAbilityFromGame();
|
return removeAbilityFromGame();
|
||||||
}
|
}
|
||||||
@@ -2278,6 +2700,7 @@ AADamager(int _id, MTGCardInstance * _source, Targetable * _target, WParsedInt *
|
|||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//prevent next damage
|
//prevent next damage
|
||||||
class AADamagePrevent:public ActivatedAbilityTP{
|
class AADamagePrevent:public ActivatedAbilityTP{
|
||||||
public:
|
public:
|
||||||
@@ -2435,6 +2858,56 @@ class AAFrozen:public ActivatedAbility{
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* switch power and toughness of target */
|
||||||
|
class ATwist:public InstantAbility{
|
||||||
|
public:
|
||||||
|
int oldpower;
|
||||||
|
int oldtoughness;
|
||||||
|
ATwist(int _id, MTGCardInstance * _source, MTGCardInstance * _target): InstantAbility(_id, _source, _target){
|
||||||
|
target = _target;
|
||||||
|
}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
|
if (_target){
|
||||||
|
while (_target->next) _target=_target->next; //This is for cards such as rampant growth
|
||||||
|
oldpower = _target->power;
|
||||||
|
oldtoughness = _target->toughness;
|
||||||
|
|
||||||
|
_target->addToToughness(oldpower);
|
||||||
|
_target->addToToughness(-oldtoughness);
|
||||||
|
_target->power = oldtoughness;
|
||||||
|
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int destroy(){
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
|
if (_target){
|
||||||
|
while (_target->next) _target=_target->next; //This is for cards such as rampant growth
|
||||||
|
oldpower = _target->power;
|
||||||
|
oldtoughness = _target->toughness;
|
||||||
|
|
||||||
|
_target->addToToughness(oldpower);
|
||||||
|
_target->addToToughness(-oldtoughness);
|
||||||
|
_target->power = oldtoughness;
|
||||||
|
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * getMenuText(){
|
||||||
|
return "Switch";
|
||||||
|
}
|
||||||
|
ATwist * clone() const{
|
||||||
|
ATwist * a = NEW ATwist(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Add life of gives damage if a given zone has more or less than [condition] cards at the beginning of [phase]
|
// Add life of gives damage if a given zone has more or less than [condition] cards at the beginning of [phase]
|
||||||
//Ex : the rack, ivory tower...
|
//Ex : the rack, ivory tower...
|
||||||
class ALifeZoneLink:public MTGAbility{
|
class ALifeZoneLink:public MTGAbility{
|
||||||
@@ -2844,6 +3317,26 @@ public:
|
|||||||
return a;}
|
return a;}
|
||||||
~ATransformerFOREVER(){delete ability;
|
~ATransformerFOREVER(){delete ability;
|
||||||
}};
|
}};
|
||||||
|
//switch p/t ueot
|
||||||
|
class ATwistUEOT: public InstantAbility{
|
||||||
|
public:
|
||||||
|
ATwist * ability;
|
||||||
|
ATwistUEOT(int id, MTGCardInstance * source, MTGCardInstance * target):InstantAbility(id,source,target){
|
||||||
|
ability = NEW ATwist(id,source,target);}
|
||||||
|
int resolve(){
|
||||||
|
ATwist * a = ability->clone();
|
||||||
|
GenericInstantAbility * wrapper = NEW GenericInstantAbility(1,source,(Damageable *)(this->target),a);
|
||||||
|
wrapper->addToGame();
|
||||||
|
return 1;}
|
||||||
|
ATwistUEOT * clone() const{
|
||||||
|
ATwistUEOT * a = NEW ATwistUEOT(*this);
|
||||||
|
a->ability = this->ability->clone();
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;}
|
||||||
|
~ATwistUEOT(){
|
||||||
|
delete ability;
|
||||||
|
}};
|
||||||
|
|
||||||
//becomes ability
|
//becomes ability
|
||||||
//Adds types/abilities/P/T to a card (aura)
|
//Adds types/abilities/P/T to a card (aura)
|
||||||
class ABecomes:public MTGAbility{
|
class ABecomes:public MTGAbility{
|
||||||
@@ -2971,8 +3464,9 @@ class APreventAllCombatDamage:public MTGAbility{
|
|||||||
public:
|
public:
|
||||||
string to, from;
|
string to, from;
|
||||||
REDamagePrevention * re;
|
REDamagePrevention * re;
|
||||||
|
int type;
|
||||||
|
|
||||||
APreventAllCombatDamage(int id,MTGCardInstance * source,string to,string from):MTGAbility(id,source),to(to),from(from){
|
APreventAllCombatDamage(int id,MTGCardInstance * source,string to,string from,int type = 0):MTGAbility(id,source),to(to),from(from),type(type){
|
||||||
re = NULL;
|
re = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2986,7 +3480,17 @@ class APreventAllCombatDamage:public MTGAbility{
|
|||||||
if (toTc) toTc->targetter = NULL;
|
if (toTc) toTc->targetter = NULL;
|
||||||
TargetChooser *fromTc = tcf.createTargetChooser(from,source,this);
|
TargetChooser *fromTc = tcf.createTargetChooser(from,source,this);
|
||||||
if (fromTc) fromTc->targetter = NULL;
|
if (fromTc) fromTc->targetter = NULL;
|
||||||
|
if(type != 1 && type != 2){//not adding this creates a memory leak.
|
||||||
re = NEW REDamagePrevention (this, fromTc, toTc, -1, false, DAMAGE_COMBAT);
|
re = NEW REDamagePrevention (this, fromTc, toTc, -1, false, DAMAGE_COMBAT);
|
||||||
|
}
|
||||||
|
if(type == 1){
|
||||||
|
re = NULL;
|
||||||
|
re = NEW REDamagePrevention (this, fromTc, toTc, -1, false, DAMAGE_ALL_TYPES);
|
||||||
|
}
|
||||||
|
if(type == 2){
|
||||||
|
re = NULL;
|
||||||
|
re = NEW REDamagePrevention (this, fromTc, toTc, -1, false, DAMAGE_OTHER);
|
||||||
|
}
|
||||||
game->replacementEffects->add(re);
|
game->replacementEffects->add(re);
|
||||||
return MTGAbility::addToGame();
|
return MTGAbility::addToGame();
|
||||||
}
|
}
|
||||||
@@ -3010,11 +3514,11 @@ class APreventAllCombatDamageUEOT: public InstantAbility{
|
|||||||
public:
|
public:
|
||||||
APreventAllCombatDamage * ability;
|
APreventAllCombatDamage * ability;
|
||||||
vector<APreventAllCombatDamage *> clones;
|
vector<APreventAllCombatDamage *> clones;
|
||||||
APreventAllCombatDamageUEOT(int id,MTGCardInstance * source,string to, string from):InstantAbility(id,source){
|
int type;
|
||||||
ability = NEW APreventAllCombatDamage(id,source,to, from);
|
APreventAllCombatDamageUEOT(int id,MTGCardInstance * source,string to, string from,int type = 0):InstantAbility(id,source){
|
||||||
|
ability = NEW APreventAllCombatDamage(id,source,to, from,type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int resolve(){
|
int resolve(){
|
||||||
APreventAllCombatDamage * a = ability->clone();
|
APreventAllCombatDamage * a = ability->clone();
|
||||||
GenericInstantAbility * wrapper = NEW GenericInstantAbility(1,source,(Damageable *)(this->target),a);
|
GenericInstantAbility * wrapper = NEW GenericInstantAbility(1,source,(Damageable *)(this->target),a);
|
||||||
@@ -3022,8 +3526,6 @@ public:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int destroy(){
|
int destroy(){
|
||||||
for (size_t i = 0; i < clones.size(); ++i){
|
for (size_t i = 0; i < clones.size(); ++i){
|
||||||
clones[i]->forceDestroy = 0;
|
clones[i]->forceDestroy = 0;
|
||||||
@@ -3036,7 +3538,6 @@ public:
|
|||||||
return ability->getMenuText();
|
return ability->getMenuText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
APreventAllCombatDamageUEOT * clone() const{
|
APreventAllCombatDamageUEOT * clone() const{
|
||||||
APreventAllCombatDamageUEOT * a = NEW APreventAllCombatDamageUEOT(*this);
|
APreventAllCombatDamageUEOT * a = NEW APreventAllCombatDamageUEOT(*this);
|
||||||
a->ability = this->ability->clone();
|
a->ability = this->ability->clone();
|
||||||
@@ -3672,7 +4173,7 @@ class AHypnoticSpecter:public MTGAbility{
|
|||||||
if (e->damage->source != source) return 0;
|
if (e->damage->source != source) return 0;
|
||||||
Player * p = dynamic_cast<Player *>(e->damage->target);
|
Player * p = dynamic_cast<Player *>(e->damage->target);
|
||||||
if (!p) return 0;
|
if (!p) return 0;
|
||||||
p->game->discardRandom(p->game->hand);
|
p->game->discardRandom(p->game->hand,source);
|
||||||
return 1; //is this meant to return 0 or 1?
|
return 1; //is this meant to return 0 or 1?
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4456,7 +4957,7 @@ class AARandomDiscarder:public ActivatedAbilityTP{
|
|||||||
player = (Player *) _target;
|
player = (Player *) _target;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < nbcards; i++){
|
for (int i = 0; i < nbcards; i++){
|
||||||
player->game->discardRandom(player->game->hand);
|
player->game->discardRandom(player->game->hand,source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -4562,6 +5063,98 @@ class ARampageAbility:public MTGAbility{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//flanking ability
|
||||||
|
class AFlankerAbility:public MTGAbility{
|
||||||
|
public:
|
||||||
|
MTGCardInstance * opponents[20];
|
||||||
|
int nbOpponents;
|
||||||
|
AFlankerAbility(int _id, MTGCardInstance * _source):MTGAbility(_id, _source){
|
||||||
|
nbOpponents = 0;
|
||||||
|
}
|
||||||
|
int receiveEvent(WEvent * event) {
|
||||||
|
if (dynamic_cast<WEventBlockersChosen*>(event)) {
|
||||||
|
nbOpponents = 0;
|
||||||
|
MTGCardInstance * opponent = source->getNextOpponent();
|
||||||
|
while (opponent && !opponent->has(Constants::FLANKING) && game->currentlyActing() == source->controller()->opponent()){
|
||||||
|
opponents[nbOpponents] = opponent;
|
||||||
|
nbOpponents ++;
|
||||||
|
opponent = source->getNextOpponent(opponent);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < nbOpponents ; i++){
|
||||||
|
opponents[i]->power -= 1;
|
||||||
|
opponents[i]->addToToughness(-1);
|
||||||
|
opponents[i]->flanked += 1;
|
||||||
|
if(opponents[i]->life == 0){opponents[i]->setPower(0);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ostream& toString(ostream& out) const
|
||||||
|
{
|
||||||
|
out << "AFlankerAbility ::: opponents : " << opponents
|
||||||
|
<< " ; nbOpponents : " << nbOpponents
|
||||||
|
<< " (";
|
||||||
|
return MTGAbility::toString(out) << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
AFlankerAbility * clone() const{
|
||||||
|
AFlankerAbility * a = NEW AFlankerAbility(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//Bushido ability
|
||||||
|
class ABushidoAbility:public MTGAbility{
|
||||||
|
public:
|
||||||
|
MTGCardInstance * opponents[20];
|
||||||
|
int nbOpponents;
|
||||||
|
int PowerModifier;
|
||||||
|
int ToughnessModifier;
|
||||||
|
|
||||||
|
ABushidoAbility(int _id, MTGCardInstance * _source,int _PowerModifier, int _ToughnessModifier):MTGAbility(_id, _source){
|
||||||
|
PowerModifier = _PowerModifier;
|
||||||
|
ToughnessModifier = _ToughnessModifier;
|
||||||
|
nbOpponents = 0;
|
||||||
|
}
|
||||||
|
int receiveEvent(WEvent * event) {
|
||||||
|
if (dynamic_cast<WEventBlockersChosen*>(event)) {
|
||||||
|
MTGCardInstance * opponent = source->getNextOpponent();
|
||||||
|
if (!opponent) return 0;
|
||||||
|
source->power += PowerModifier;
|
||||||
|
source->addToToughness(ToughnessModifier);
|
||||||
|
while (opponent){
|
||||||
|
opponents[nbOpponents] = opponent;
|
||||||
|
nbOpponents ++;
|
||||||
|
opponent = source->getNextOpponent(opponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (WEventPhaseChange* pe = dynamic_cast<WEventPhaseChange*>(event)) {
|
||||||
|
if (Constants::MTG_PHASE_AFTER_EOT == pe->to->id && nbOpponents)
|
||||||
|
{
|
||||||
|
source->power -= PowerModifier;
|
||||||
|
source->addToToughness(-ToughnessModifier);
|
||||||
|
nbOpponents = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ostream& toString(ostream& out) const
|
||||||
|
{
|
||||||
|
out << "ABushidoAbility ::: opponents : " << opponents
|
||||||
|
<< " ; nbOpponents : " << nbOpponents
|
||||||
|
<< " (";
|
||||||
|
return MTGAbility::toString(out) << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
ABushidoAbility * clone() const{
|
||||||
|
ABushidoAbility * a = NEW ABushidoAbility(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
//Instant Steal control of a target
|
//Instant Steal control of a target
|
||||||
class AInstantControlSteal: public InstantAbility{
|
class AInstantControlSteal: public InstantAbility{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class CardDescriptor: public MTGCardInstance{
|
|||||||
int init();
|
int init();
|
||||||
CardDescriptor();
|
CardDescriptor();
|
||||||
void unsecureSetTapped(int i);
|
void unsecureSetTapped(int i);
|
||||||
|
void unsecuresetfresh(int k);
|
||||||
void setNegativeSubtype( string value);
|
void setNegativeSubtype( string value);
|
||||||
int counterPower;
|
int counterPower;
|
||||||
int counterToughness;
|
int counterToughness;
|
||||||
|
|||||||
@@ -70,6 +70,14 @@ public:
|
|||||||
virtual DiscardRandomCost * clone() const;
|
virtual DiscardRandomCost * clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//a choosen discard
|
||||||
|
class DiscardCost: public ExtraCost{
|
||||||
|
public:
|
||||||
|
DiscardCost(TargetChooser *_tc = NULL);
|
||||||
|
virtual int doPay();
|
||||||
|
virtual DiscardCost * clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
//tolibrary cost
|
//tolibrary cost
|
||||||
class ToLibraryCost: public ExtraCost{
|
class ToLibraryCost: public ExtraCost{
|
||||||
public:
|
public:
|
||||||
@@ -118,6 +126,15 @@ public:
|
|||||||
virtual BounceTargetCost * clone() const;
|
virtual BounceTargetCost * clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//bounce cost
|
||||||
|
class Ninja: public ExtraCost{
|
||||||
|
public:
|
||||||
|
Ninja(TargetChooser *_tc = NULL);
|
||||||
|
virtual int isPaymentSet();
|
||||||
|
virtual int doPay();
|
||||||
|
virtual Ninja * clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
class CounterCost: public ExtraCost{
|
class CounterCost: public ExtraCost{
|
||||||
public:
|
public:
|
||||||
Counter * counter;
|
Counter * counter;
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ class MTGAbility: public ActionElement{
|
|||||||
BUYBACK_COST = 9,
|
BUYBACK_COST = 9,
|
||||||
FLASHBACK_COST = 10,
|
FLASHBACK_COST = 10,
|
||||||
RETRACE_COST = 11,
|
RETRACE_COST = 11,
|
||||||
|
MTG_COMBATTRIGGERS_RULE = 13,
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,11 +49,17 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable {
|
|||||||
int flashedback;
|
int flashedback;
|
||||||
int paymenttype;
|
int paymenttype;
|
||||||
int frozen;
|
int frozen;
|
||||||
|
int sunburst;
|
||||||
int equipment;
|
int equipment;
|
||||||
int reduxamount;
|
int reduxamount;
|
||||||
|
int flanked;
|
||||||
int regenerateTokens;
|
int regenerateTokens;
|
||||||
int isToken;
|
int isToken;
|
||||||
int stillInUse();
|
int stillInUse();
|
||||||
|
int didattacked;
|
||||||
|
int didblocked;
|
||||||
|
int notblocked;
|
||||||
|
int fresh;
|
||||||
Player * lastController;
|
Player * lastController;
|
||||||
MTGGameZone * getCurrentZone();
|
MTGGameZone * getCurrentZone();
|
||||||
MTGGameZone * previousZone;
|
MTGGameZone * previousZone;
|
||||||
@@ -138,6 +144,11 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable {
|
|||||||
void tap();
|
void tap();
|
||||||
void attemptUntap();
|
void attemptUntap();
|
||||||
|
|
||||||
|
void eventattacked();
|
||||||
|
void eventattackednotblocked();
|
||||||
|
void eventattackedblocked();
|
||||||
|
void eventblocked();
|
||||||
|
|
||||||
int isInPlay();
|
int isInPlay();
|
||||||
JSample * getSample();
|
JSample * getSample();
|
||||||
|
|
||||||
|
|||||||
@@ -136,8 +136,11 @@ class Constants
|
|||||||
LEYLINE = 78,
|
LEYLINE = 78,
|
||||||
PLAYERSHROUD = 79,
|
PLAYERSHROUD = 79,
|
||||||
CONTROLLERSHROUD = 80,
|
CONTROLLERSHROUD = 80,
|
||||||
|
SUNBURST = 81,
|
||||||
|
FLANKING = 82,
|
||||||
|
EXILEBURY = 83,
|
||||||
|
|
||||||
NB_BASIC_ABILITIES = 81,
|
NB_BASIC_ABILITIES = 84,
|
||||||
|
|
||||||
|
|
||||||
RARITY_S = 'S', //Special Rarity
|
RARITY_S = 'S', //Special Rarity
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ class MTGPlayerCards {
|
|||||||
~MTGPlayerCards();
|
~MTGPlayerCards();
|
||||||
void initGame(int shuffle = 1, int draw = 1);
|
void initGame(int shuffle = 1, int draw = 1);
|
||||||
void setOwner(Player * player);
|
void setOwner(Player * player);
|
||||||
void discardRandom(MTGGameZone * from);
|
void discardRandom(MTGGameZone * from,MTGCardInstance * source);
|
||||||
void drawFromLibrary();
|
void drawFromLibrary();
|
||||||
void showHand();
|
void showHand();
|
||||||
void resetLibrary();
|
void resetLibrary();
|
||||||
|
|||||||
@@ -86,6 +86,17 @@ class MTGAttackRule:public MTGAbility, public Limitor{
|
|||||||
virtual MTGAttackRule * clone() const;
|
virtual MTGAttackRule * clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* handles combat trigger send recieve events*/
|
||||||
|
class MTGCombatTriggersRule:public MTGAbility{
|
||||||
|
public:
|
||||||
|
MTGCombatTriggersRule(int _id);
|
||||||
|
int receiveEvent(WEvent * event);
|
||||||
|
virtual ostream& toString(ostream& out) const;
|
||||||
|
int testDestroy();
|
||||||
|
virtual MTGCombatTriggersRule * clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
class MTGBlockRule:public MTGAbility{
|
class MTGBlockRule:public MTGAbility{
|
||||||
public:
|
public:
|
||||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
|
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ using namespace std;
|
|||||||
|
|
||||||
class Player;
|
class Player;
|
||||||
|
|
||||||
typedef enum { BLOCKERS, ORDER, FIRST_STRIKE, END_FIRST_STRIKE, DAMAGE, END_DAMAGE } CombatStep;
|
typedef enum { BLOCKERS, TRIGGERS, ORDER, FIRST_STRIKE, END_FIRST_STRIKE, DAMAGE, END_DAMAGE } CombatStep;
|
||||||
class Phase{
|
class Phase{
|
||||||
public:
|
public:
|
||||||
int id;
|
int id;
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ class TargetChooser: public TargetsList {
|
|||||||
UNSET = 0,
|
UNSET = 0,
|
||||||
OPPONENT = -1,
|
OPPONENT = -1,
|
||||||
CONTROLLER = 1,
|
CONTROLLER = 1,
|
||||||
TARGET_CONTROLLER = 2
|
TARGET_CONTROLLER = 2,
|
||||||
|
OWNER = 3
|
||||||
};
|
};
|
||||||
bool other;
|
bool other;
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,21 @@ class ThisEquip:public ThisDescriptor{
|
|||||||
ThisEquip(int equipment);
|
ThisEquip(int equipment);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ThisAttacked:public ThisDescriptor{
|
||||||
|
public:
|
||||||
|
virtual int match(MTGCardInstance * card);
|
||||||
|
|
||||||
|
ThisAttacked(int attack);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ThisNotBlocked:public ThisDescriptor{
|
||||||
|
public:
|
||||||
|
virtual int match(MTGCardInstance * card);
|
||||||
|
|
||||||
|
ThisNotBlocked(int unblocked);
|
||||||
|
};
|
||||||
|
|
||||||
class ThisPower:public ThisDescriptor{
|
class ThisPower:public ThisDescriptor{
|
||||||
public:
|
public:
|
||||||
virtual int match(MTGCardInstance * card);
|
virtual int match(MTGCardInstance * card);
|
||||||
|
|||||||
@@ -85,6 +85,14 @@ struct WEventCardTap : public WEventCardUpdate {
|
|||||||
virtual Targetable * getTarget(int target);
|
virtual Targetable * getTarget(int target);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WEventCardTappedForMana : public WEventCardUpdate {
|
||||||
|
bool before;
|
||||||
|
bool after;
|
||||||
|
WEventCardTappedForMana(MTGCardInstance * card, bool before, bool after);
|
||||||
|
virtual Targetable * getTarget(int target);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//Event when a card's "attacker" status changes
|
//Event when a card's "attacker" status changes
|
||||||
//before:Player/Planeswalker that card was attacking previously
|
//before:Player/Planeswalker that card was attacking previously
|
||||||
//after: Player/Planeswalker that card is attacking now
|
//after: Player/Planeswalker that card is attacking now
|
||||||
@@ -94,6 +102,42 @@ struct WEventCreatureAttacker : public WEventCardUpdate {
|
|||||||
WEventCreatureAttacker(MTGCardInstance * card, Targetable * from, Targetable * to);
|
WEventCreatureAttacker(MTGCardInstance * card, Targetable * from, Targetable * to);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//event when card attacks.
|
||||||
|
struct WEventCardAttacked : public WEventCardUpdate {
|
||||||
|
WEventCardAttacked(MTGCardInstance * card);
|
||||||
|
virtual Targetable * getTarget(int target);
|
||||||
|
};
|
||||||
|
|
||||||
|
//event when card attacks but is not blocked.
|
||||||
|
struct WEventCardAttackedNotBlocked : public WEventCardUpdate {
|
||||||
|
WEventCardAttackedNotBlocked(MTGCardInstance * card);
|
||||||
|
virtual Targetable * getTarget(int target);
|
||||||
|
};
|
||||||
|
|
||||||
|
//event when card attacks but is blocked.
|
||||||
|
struct WEventCardAttackedBlocked : public WEventCardUpdate {
|
||||||
|
WEventCardAttackedBlocked(MTGCardInstance * card);
|
||||||
|
virtual Targetable * getTarget(int target);
|
||||||
|
};
|
||||||
|
|
||||||
|
//event when card blocked.
|
||||||
|
struct WEventCardBlocked : public WEventCardUpdate {
|
||||||
|
WEventCardBlocked(MTGCardInstance * card);
|
||||||
|
virtual Targetable * getTarget(int target);
|
||||||
|
};
|
||||||
|
|
||||||
|
//event when card is sacrificed.
|
||||||
|
struct WEventCardSacrifice : public WEventCardUpdate {
|
||||||
|
WEventCardSacrifice(MTGCardInstance * card);
|
||||||
|
virtual Targetable * getTarget(int target);
|
||||||
|
};
|
||||||
|
|
||||||
|
//event when card is discarded.
|
||||||
|
struct WEventCardDiscard : public WEventCardUpdate {
|
||||||
|
WEventCardDiscard(MTGCardInstance * card);
|
||||||
|
virtual Targetable * getTarget(int target);
|
||||||
|
};
|
||||||
|
|
||||||
//Event when a card's "defenser" status changes
|
//Event when a card's "defenser" status changes
|
||||||
//before : attacker that card was blocking previously
|
//before : attacker that card was blocking previously
|
||||||
//after: attacker that card is blocking now
|
//after: attacker that card is blocking now
|
||||||
@@ -108,6 +152,13 @@ struct WEventCreatureBlocker : public WEventCardUpdate {
|
|||||||
struct WEventBlockersChosen : public WEvent {
|
struct WEventBlockersChosen : public WEvent {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WEventcardDraw : public WEvent {
|
||||||
|
WEventcardDraw(Player * player,int nb_cards);
|
||||||
|
Player * player;
|
||||||
|
int nb_cards;
|
||||||
|
virtual Targetable * getTarget(Player * player);
|
||||||
|
};
|
||||||
|
|
||||||
//Event when a blocker is reordered
|
//Event when a blocker is reordered
|
||||||
//exchangeWith: exchange card's position with exchangeWith's position
|
//exchangeWith: exchange card's position with exchangeWith's position
|
||||||
//attacker:both card and exchangeWith *should* be in attacker's "blockers" list.
|
//attacker:both card and exchangeWith *should* be in attacker's "blockers" list.
|
||||||
|
|||||||
@@ -102,7 +102,6 @@ void ActionLayer::Update(float dt){
|
|||||||
cancelCurrentAction();
|
cancelCurrentAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionLayer::Render (){
|
void ActionLayer::Render (){
|
||||||
@@ -120,7 +119,7 @@ void ActionLayer::Render (){
|
|||||||
|
|
||||||
|
|
||||||
void ActionLayer::setCurrentWaitingAction(ActionElement * ae){
|
void ActionLayer::setCurrentWaitingAction(ActionElement * ae){
|
||||||
assert(!ae || !currentWaitingAction);
|
assert(!ae || !currentWaitingAction);//this assert causes crashes when may abilities overlap each other on ai. this conidiation is preexsiting.
|
||||||
currentWaitingAction = ae;
|
currentWaitingAction = ae;
|
||||||
if (!ae) cantCancel = 0;
|
if (!ae) cantCancel = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,7 +215,6 @@ bool Spell::RetraceWasPaid(){
|
|||||||
const string Spell::getDisplayName() const {
|
const string Spell::getDisplayName() const {
|
||||||
return source->getName();
|
return source->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
Spell::~Spell(){
|
Spell::~Spell(){
|
||||||
SAFE_DELETE(cost);
|
SAFE_DELETE(cost);
|
||||||
SAFE_DELETE(tc);
|
SAFE_DELETE(tc);
|
||||||
@@ -391,6 +390,9 @@ int ActionStack::addAbility(MTGAbility * ability){
|
|||||||
int ActionStack::addDraw(Player * player, int nb_cards){
|
int ActionStack::addDraw(Player * player, int nb_cards){
|
||||||
DrawAction * draw = NEW DrawAction(mCount,player, nb_cards);
|
DrawAction * draw = NEW DrawAction(mCount,player, nb_cards);
|
||||||
addAction(draw);
|
addAction(draw);
|
||||||
|
GameObserver *g = GameObserver::GetInstance();
|
||||||
|
WEvent * e = NEW WEventcardDraw(player,nb_cards);
|
||||||
|
g->receiveEvent(e);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,11 +407,19 @@ int ActionStack::AddNextGamePhase(){
|
|||||||
NextGamePhase * next = NEW NextGamePhase(mCount);
|
NextGamePhase * next = NEW NextGamePhase(mCount);
|
||||||
addAction(next);
|
addAction(next);
|
||||||
int playerId = 0;
|
int playerId = 0;
|
||||||
if (game->currentActionPlayer == game->players[1]) playerId = 1;
|
game->currentActionPlayer = game->GetInstance()->currentActionPlayer;
|
||||||
|
if (game->currentActionPlayer == game->players[1]){ playerId = 1;}
|
||||||
interruptDecision[playerId] = 1;
|
interruptDecision[playerId] = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ActionStack::AddNextCombatStep(){
|
||||||
|
if (getNext(NULL,NOT_RESOLVED)) return 0;
|
||||||
|
NextGamePhase * next = NEW NextGamePhase(mCount);
|
||||||
|
addAction(next);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int ActionStack::setIsInterrupting(Player * player){
|
int ActionStack::setIsInterrupting(Player * player){
|
||||||
if (player == game->players[0]){
|
if (player == game->players[0]){
|
||||||
interruptDecision[0] = -1;
|
interruptDecision[0] = -1;
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ void CardDescriptor::unsecureSetTapped(int i){
|
|||||||
tapped = i;
|
tapped = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CardDescriptor::unsecuresetfresh(int k){
|
||||||
|
fresh = k;
|
||||||
|
}
|
||||||
|
|
||||||
void CardDescriptor::setNegativeSubtype( string value){
|
void CardDescriptor::setNegativeSubtype( string value){
|
||||||
int id = Subtypes::subtypesList->find(value);
|
int id = Subtypes::subtypesList->find(value);
|
||||||
addType(-id);
|
addType(-id);
|
||||||
@@ -150,15 +154,17 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((tapped == -1 && card->isTapped()) || (tapped == 1 && !card->isTapped())){
|
if ((tapped == -1 && card->isTapped()) || (tapped == 1 && !card->isTapped())){
|
||||||
match = NULL;
|
match = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((fresh == -1 && card->fresh) || (fresh == 1 && !card->fresh)){
|
||||||
|
match = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if ((isToken== -1 && card->isToken) || (isToken == 1 && !card->isToken)){
|
if ((isToken== -1 && card->isToken) || (isToken == 1 && !card->isToken)){
|
||||||
match = NULL;
|
match = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attacker == 1){
|
if (attacker == 1){
|
||||||
if (defenser == &AnyCard){
|
if (defenser == &AnyCard){
|
||||||
if (!card->attacker && !card->defenser) match = NULL;
|
if (!card->attacker && !card->defenser) match = NULL;
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ void CardGui::Render()
|
|||||||
else if (card->hasSubtype("island"))
|
else if (card->hasSubtype("island"))
|
||||||
icon = resources.GetQuad("c_blue");
|
icon = resources.GetQuad("c_blue");
|
||||||
|
|
||||||
|
|
||||||
if (icon){
|
if (icon){
|
||||||
icon->SetColor(ARGB(static_cast<unsigned char>(actA),255,255,255));
|
icon->SetColor(ARGB(static_cast<unsigned char>(actA),255,255,255));
|
||||||
renderer->RenderQuad(icon, actX, actY, 0);
|
renderer->RenderQuad(icon, actX, actY, 0);
|
||||||
@@ -588,7 +589,7 @@ void CardGui::RenderBig(MTGCard* card, const Pos& pos){
|
|||||||
if (quad->mHeight < quad->mWidth) {
|
if (quad->mHeight < quad->mWidth) {
|
||||||
return tinyCropRender(card, pos, quad);
|
return tinyCropRender(card, pos, quad);
|
||||||
}
|
}
|
||||||
quad->SetColor(ARGB((int)pos.actA,255,255,255));
|
quad->SetColor(ARGB(255,255,255,255));
|
||||||
float scale = pos.actZ * 257.f / quad->mHeight;
|
float scale = pos.actZ * 257.f / quad->mHeight;
|
||||||
renderer->RenderQuad(quad, x, pos.actY, pos.actT, scale, scale);
|
renderer->RenderQuad(quad, x, pos.actY, pos.actT, scale, scale);
|
||||||
return;
|
return;
|
||||||
@@ -599,7 +600,7 @@ void CardGui::RenderBig(MTGCard* card, const Pos& pos){
|
|||||||
if ((q = resources.RetrieveCard(card,CACHE_THUMB)))
|
if ((q = resources.RetrieveCard(card,CACHE_THUMB)))
|
||||||
{
|
{
|
||||||
float scale = pos.actZ * 250 / q->mHeight;
|
float scale = pos.actZ * 250 / q->mHeight;
|
||||||
q->SetColor(ARGB((int)pos.actA,255,255,255));
|
q->SetColor(ARGB(255,255,255,255));
|
||||||
renderer->RenderQuad(q, x, pos.actY, pos.actT, scale, scale);
|
renderer->RenderQuad(q, x, pos.actY, pos.actT, scale, scale);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ int Damage::resolve(){
|
|||||||
state = RESOLVED_OK;
|
state = RESOLVED_OK;
|
||||||
GameObserver * g = GameObserver::GetInstance();
|
GameObserver * g = GameObserver::GetInstance();
|
||||||
WEvent * e = NEW WEventDamage(this);
|
WEvent * e = NEW WEventDamage(this);
|
||||||
|
|
||||||
//Replacement Effects
|
//Replacement Effects
|
||||||
e = g->replacementEffects->replace(e);
|
e = g->replacementEffects->replace(e);
|
||||||
if (!e) return 0;
|
if (!e) return 0;
|
||||||
@@ -114,7 +113,6 @@ int Damage::resolve(){
|
|||||||
// Poison on player
|
// Poison on player
|
||||||
Player * _target = (Player *)target;
|
Player * _target = (Player *)target;
|
||||||
_target->poisonCount += damage;//this will be changed to poison counters.
|
_target->poisonCount += damage;//this will be changed to poison counters.
|
||||||
|
|
||||||
} else if (target->type_as_damageable == DAMAGEABLE_PLAYER &&
|
} else if (target->type_as_damageable == DAMAGEABLE_PLAYER &&
|
||||||
( source->has(Constants::POISONTOXIC) || source->has(Constants::POISONTWOTOXIC) || source->has(Constants::POISONTHREETOXIC) )) {
|
( source->has(Constants::POISONTOXIC) || source->has(Constants::POISONTWOTOXIC) || source->has(Constants::POISONTHREETOXIC) )) {
|
||||||
//Damage + 1, 2, or 3 poison counters on player
|
//Damage + 1, 2, or 3 poison counters on player
|
||||||
@@ -189,10 +187,9 @@ int DamageStack::resolve(){
|
|||||||
Damage * damage = (Damage*)mObjects[i];
|
Damage * damage = (Damage*)mObjects[i];
|
||||||
if (damage->state == NOT_RESOLVED) damage->resolve();
|
if (damage->state == NOT_RESOLVED) damage->resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObserver::GetInstance()->receiveEvent(NEW WEventDamageStackResolved());
|
GameObserver::GetInstance()->receiveEvent(NEW WEventDamageStackResolved());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DamageStack::receiveEvent(WEvent * e) {
|
int DamageStack::receiveEvent(WEvent * e) {
|
||||||
WEventDamageStackResolved *event = dynamic_cast<WEventDamageStackResolved*>(e);
|
WEventDamageStackResolved *event = dynamic_cast<WEventDamageStackResolved*>(e);
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ void DamagerDamaged::Render(CombatStep mode)
|
|||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case BLOCKERS :
|
case BLOCKERS :
|
||||||
|
case TRIGGERS :
|
||||||
case ORDER :
|
case ORDER :
|
||||||
mFont->SetColor(ARGB(92,255,255,255));
|
mFont->SetColor(ARGB(92,255,255,255));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ void DuelLayers::init(){
|
|||||||
action->Add(NEW MTGRetraceRule(-1));
|
action->Add(NEW MTGRetraceRule(-1));
|
||||||
action->Add(NEW MTGAttackRule(-1));
|
action->Add(NEW MTGAttackRule(-1));
|
||||||
action->Add(NEW MTGBlockRule(-1));
|
action->Add(NEW MTGBlockRule(-1));
|
||||||
|
action->Add(NEW MTGCombatTriggersRule(-1));
|
||||||
action->Add(NEW MTGLegendRule(-1));
|
action->Add(NEW MTGLegendRule(-1));
|
||||||
action->Add(NEW MTGTokensCleanup(-1)); // needs to be before persist
|
action->Add(NEW MTGTokensCleanup(-1)); // needs to be before persist
|
||||||
action->Add(NEW MTGPersistRule(-1));
|
action->Add(NEW MTGPersistRule(-1));
|
||||||
|
|||||||
@@ -23,8 +23,7 @@ int ExtraCost::setSource(MTGCardInstance * _source){
|
|||||||
if (tc)
|
if (tc)
|
||||||
{
|
{
|
||||||
tc->source = _source;
|
tc->source = _source;
|
||||||
// Cryptic comment from cloned/refactored code:
|
// "extra cost is not targetting, protections do not apply" this is not cryptic at all :) make an ability you will understand it then. this keeps the target chooser from being unable to select a creature with shroud/protections.
|
||||||
// "Tapping targets is not targetting, protections do not apply"
|
|
||||||
tc->targetter = NULL;
|
tc->targetter = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -93,19 +92,46 @@ int DiscardRandomCost::canPay(){
|
|||||||
MTGGameZone * z = target->controller()->game->hand;
|
MTGGameZone * z = target->controller()->game->hand;
|
||||||
int nbcards = z->nb_cards;
|
int nbcards = z->nb_cards;
|
||||||
if(nbcards < 1) return 0;
|
if(nbcards < 1) return 0;
|
||||||
|
if(nbcards == 1 && z->hasCard(source)) return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DiscardRandomCost::doPay(){
|
int DiscardRandomCost::doPay(){
|
||||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
if(target){
|
if(target){
|
||||||
_target->controller()->game->discardRandom(_target->controller()->game->hand);
|
_target->controller()->game->discardRandom(_target->controller()->game->hand,source);
|
||||||
target = NULL;
|
target = NULL;
|
||||||
if (tc) tc->initTargets();
|
if (tc) tc->initTargets();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
//a choosen discard
|
||||||
|
|
||||||
|
DiscardCost * DiscardCost::clone() const{
|
||||||
|
DiscardCost * ec = NEW DiscardCost(*this);
|
||||||
|
if (tc) ec->tc = tc->clone();
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscardCost::DiscardCost(TargetChooser *_tc)
|
||||||
|
: ExtraCost("Choose card to Discard", _tc){
|
||||||
|
}
|
||||||
|
|
||||||
|
int DiscardCost::doPay(){
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
|
if(target){
|
||||||
|
WEvent * e = NEW WEventCardDiscard(target);
|
||||||
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
|
game->receiveEvent(e);
|
||||||
|
_target->controller()->game->putInGraveyard(_target);
|
||||||
|
target = NULL;
|
||||||
|
if (tc) tc->initTargets();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//to library cost
|
||||||
|
|
||||||
ToLibraryCost * ToLibraryCost::clone() const{
|
ToLibraryCost * ToLibraryCost::clone() const{
|
||||||
ToLibraryCost * ec = NEW ToLibraryCost(*this);
|
ToLibraryCost * ec = NEW ToLibraryCost(*this);
|
||||||
@@ -242,6 +268,39 @@ int BounceTargetCost::doPay(){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Bounce as cost for ninja
|
||||||
|
Ninja * Ninja::clone() const{
|
||||||
|
Ninja * ec = NEW Ninja(*this);
|
||||||
|
if (tc) ec->tc = tc->clone();
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ninja::Ninja(TargetChooser *_tc)
|
||||||
|
: ExtraCost("Select unblocked attacker", _tc){
|
||||||
|
}
|
||||||
|
|
||||||
|
int Ninja::isPaymentSet(){
|
||||||
|
GameObserver * g = GameObserver::GetInstance();
|
||||||
|
int currentPhase = g->getCurrentGamePhase();
|
||||||
|
if (target && ((target->isAttacker() && target->blocked == true) || target->isAttacker() < 1 || currentPhase != Constants::MTG_PHASE_COMBATBLOCKERS)){ tc->removeTarget(target);target = NULL; return 0;}
|
||||||
|
if(target) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Ninja::doPay(){
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
|
if(target){
|
||||||
|
target->controller()->game->putInHand(target);
|
||||||
|
target = NULL;
|
||||||
|
if (tc) tc->initTargets();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//endbouncetargetcostforninja
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
SacrificeCost * SacrificeCost::clone() const{
|
SacrificeCost * SacrificeCost::clone() const{
|
||||||
SacrificeCost * ec = NEW SacrificeCost(*this);
|
SacrificeCost * ec = NEW SacrificeCost(*this);
|
||||||
if (tc) ec->tc = tc->clone();
|
if (tc) ec->tc = tc->clone();
|
||||||
@@ -254,6 +313,9 @@ SacrificeCost::SacrificeCost(TargetChooser *_tc)
|
|||||||
|
|
||||||
int SacrificeCost::doPay(){
|
int SacrificeCost::doPay(){
|
||||||
if(target){
|
if(target){
|
||||||
|
WEvent * e = NEW WEventCardSacrifice(target);
|
||||||
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
|
game->receiveEvent(e);
|
||||||
target->controller()->game->putInGraveyard(target);
|
target->controller()->game->putInGraveyard(target);
|
||||||
target = NULL;
|
target = NULL;
|
||||||
if (tc) tc->initTargets();
|
if (tc) tc->initTargets();
|
||||||
|
|||||||
@@ -74,8 +74,9 @@ void GameObserver::nextGamePhase(){
|
|||||||
if (FIRST_STRIKE == combatStep || END_FIRST_STRIKE == combatStep || DAMAGE == combatStep) {
|
if (FIRST_STRIKE == combatStep || END_FIRST_STRIKE == combatStep || DAMAGE == combatStep) {
|
||||||
nextCombatStep(); return;
|
nextCombatStep(); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS)
|
if (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS)
|
||||||
if (BLOCKERS == combatStep) { nextCombatStep(); return; }
|
if (BLOCKERS == combatStep || TRIGGERS == combatStep) { nextCombatStep(); return; }
|
||||||
|
|
||||||
phaseRing->forward();
|
phaseRing->forward();
|
||||||
|
|
||||||
@@ -151,8 +152,12 @@ void GameObserver::nextCombatStep()
|
|||||||
{
|
{
|
||||||
switch (combatStep)
|
switch (combatStep)
|
||||||
{
|
{
|
||||||
case BLOCKERS : receiveEvent(NEW WEventBlockersChosen());
|
case BLOCKERS :
|
||||||
receiveEvent(NEW WEventCombatStepChange(combatStep = ORDER)); return;
|
receiveEvent(NEW WEventBlockersChosen());
|
||||||
|
receiveEvent(NEW WEventCombatStepChange(combatStep = TRIGGERS));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case TRIGGERS : receiveEvent(NEW WEventCombatStepChange(combatStep = ORDER)); return;
|
||||||
case ORDER : receiveEvent(NEW WEventCombatStepChange(combatStep = FIRST_STRIKE)); return;
|
case ORDER : receiveEvent(NEW WEventCombatStepChange(combatStep = FIRST_STRIKE)); return;
|
||||||
case FIRST_STRIKE : receiveEvent(NEW WEventCombatStepChange(combatStep = END_FIRST_STRIKE)); return;
|
case FIRST_STRIKE : receiveEvent(NEW WEventCombatStepChange(combatStep = END_FIRST_STRIKE)); return;
|
||||||
case END_FIRST_STRIKE : receiveEvent(NEW WEventCombatStepChange(combatStep = DAMAGE)); return;
|
case END_FIRST_STRIKE : receiveEvent(NEW WEventCombatStepChange(combatStep = DAMAGE)); return;
|
||||||
@@ -164,17 +169,27 @@ void GameObserver::nextCombatStep()
|
|||||||
void GameObserver::userRequestNextGamePhase(){
|
void GameObserver::userRequestNextGamePhase(){
|
||||||
if (mLayers->stackLayer()->getNext(NULL,0,NOT_RESOLVED)) return;
|
if (mLayers->stackLayer()->getNext(NULL,0,NOT_RESOLVED)) return;
|
||||||
if (getCurrentTargetChooser()) return;
|
if (getCurrentTargetChooser()) return;
|
||||||
|
|
||||||
|
bool executeNextPhaseImmediately = true;
|
||||||
|
|
||||||
Phase * cPhaseOld = phaseRing->getCurrentPhase();
|
Phase * cPhaseOld = phaseRing->getCurrentPhase();
|
||||||
|
|
||||||
|
|
||||||
if ((cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER) ||
|
if ((cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER) ||
|
||||||
|
(cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == TRIGGERS)||
|
||||||
cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE ||
|
cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE ||
|
||||||
opponent()->isAI() ||
|
opponent()->isAI() ||
|
||||||
options[Options::optionInterrupt(currentGamePhase)].number)
|
options[Options::optionInterrupt(currentGamePhase)].number)
|
||||||
mLayers->stackLayer()->AddNextGamePhase();
|
{
|
||||||
else
|
executeNextPhaseImmediately = false;
|
||||||
nextGamePhase();
|
}
|
||||||
|
|
||||||
|
if (executeNextPhaseImmediately)
|
||||||
|
{
|
||||||
|
nextGamePhase();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mLayers->stackLayer()->AddNextGamePhase();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int GameObserver::forceShuffleLibraries(){
|
int GameObserver::forceShuffleLibraries(){
|
||||||
@@ -280,15 +295,26 @@ void GameObserver::Update(float dt){
|
|||||||
Player * player = currentPlayer;
|
Player * player = currentPlayer;
|
||||||
if (Constants::MTG_PHASE_COMBATBLOCKERS == currentGamePhase && BLOCKERS == combatStep)
|
if (Constants::MTG_PHASE_COMBATBLOCKERS == currentGamePhase && BLOCKERS == combatStep)
|
||||||
player = player->opponent();
|
player = player->opponent();
|
||||||
|
|
||||||
currentActionPlayer = player;
|
currentActionPlayer = player;
|
||||||
if (isInterrupting) player = isInterrupting;
|
if (isInterrupting) player = isInterrupting;
|
||||||
mLayers->Update(dt,player);
|
mLayers->Update(dt,player);
|
||||||
|
|
||||||
while (mLayers->actionLayer()->stuffHappened){
|
while (mLayers->actionLayer()->stuffHappened){
|
||||||
mLayers->actionLayer()->Update(0);
|
mLayers->actionLayer()->Update(0);
|
||||||
}
|
}
|
||||||
stateEffects();
|
stateEffects();
|
||||||
oldGamePhase = currentGamePhase;
|
oldGamePhase = currentGamePhase;
|
||||||
|
|
||||||
|
|
||||||
|
if (combatStep == TRIGGERS)
|
||||||
|
{
|
||||||
|
if (!mLayers->stackLayer()->getNext(NULL,0,NOT_RESOLVED))
|
||||||
|
{
|
||||||
|
mLayers->stackLayer()->AddNextCombatStep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Auto skip Phases
|
//Auto skip Phases
|
||||||
int skipLevel = (player->playMode == Player::MODE_TEST_SUITE) ? Constants::ASKIP_NONE :
|
int skipLevel = (player->playMode == Player::MODE_TEST_SUITE) ? Constants::ASKIP_NONE :
|
||||||
options[Options::ASPHASES].number;
|
options[Options::ASPHASES].number;
|
||||||
|
|||||||
@@ -133,7 +133,10 @@ bool GuiCombat::clickOK(){
|
|||||||
cursor_pos = NONE;
|
cursor_pos = NONE;
|
||||||
switch (step)
|
switch (step)
|
||||||
{
|
{
|
||||||
case BLOCKERS : assert(false); return false; // that should not happen
|
case BLOCKERS :
|
||||||
|
case TRIGGERS :
|
||||||
|
assert(false); return false; // that should not happen
|
||||||
|
|
||||||
case ORDER : go->nextGamePhase(); return true;
|
case ORDER : go->nextGamePhase(); return true;
|
||||||
case FIRST_STRIKE : return false;
|
case FIRST_STRIKE : return false;
|
||||||
case DAMAGE : validateDamage(); return true;
|
case DAMAGE : validateDamage(); return true;
|
||||||
@@ -443,6 +446,11 @@ int GuiCombat::receiveEventMinus(WEvent* e)
|
|||||||
{
|
{
|
||||||
case BLOCKERS:
|
case BLOCKERS:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TRIGGERS:
|
||||||
|
step = TRIGGERS;
|
||||||
|
return 1;
|
||||||
|
|
||||||
case ORDER:
|
case ORDER:
|
||||||
{
|
{
|
||||||
if (ORDER == step) return 0; // Why do I take this twice ? >.>
|
if (ORDER == step) return 0; // Why do I take this twice ? >.>
|
||||||
|
|||||||
+321
-12
@@ -153,7 +153,133 @@ TriggeredAbility * AbilityFactory::parseTrigger(string magicText, int id, Spell
|
|||||||
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
tc->targetter = NULL;
|
tc->targetter = NULL;
|
||||||
|
|
||||||
return NEW TrCardTapped(id,card,tc);
|
return NEW TrCardTapped(id,card,tc,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Card unTapped
|
||||||
|
found = s.find("untapping(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")");
|
||||||
|
string starget = s.substr(found+10,end - found - 10);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
|
tc->targetter = NULL;
|
||||||
|
|
||||||
|
return NEW TrCardTapped(id,card,tc,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Card Tapped for mana
|
||||||
|
found = s.find("tappedformana(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")");
|
||||||
|
string starget = s.substr(found+14,end - found - 14);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
|
tc->targetter = NULL;
|
||||||
|
|
||||||
|
return NEW TrCardTappedformana(id,card,tc,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Card is attacking
|
||||||
|
found = s.find("attacking(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")");
|
||||||
|
string starget = s.substr(found+10,end - found - 10);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
|
tc->targetter = NULL;
|
||||||
|
|
||||||
|
return NEW TrCardAttacked(id,card,tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Card card attacked and is not blocked
|
||||||
|
found = s.find("notblocked(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")");
|
||||||
|
string starget = s.substr(found+11,end - found - 11);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
|
tc->targetter = NULL;
|
||||||
|
|
||||||
|
return NEW TrCardAttackedNotBlocked(id,card,tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Card card attacked and is blocked
|
||||||
|
found = s.find("blocked(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")");
|
||||||
|
string starget = s.substr(found+8,end - found - 8);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
|
tc->targetter = NULL;
|
||||||
|
found = s.find("from(");
|
||||||
|
|
||||||
|
TargetChooser *fromTc = NULL;
|
||||||
|
if (found != string::npos){
|
||||||
|
end = s.find (")", found);
|
||||||
|
starget = s.substr(found+5,end - found - 5);
|
||||||
|
fromTc = tcf.createTargetChooser(starget,card);
|
||||||
|
fromTc->targetter = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NEW TrCardAttackedBlocked(id,card,tc,fromTc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Card card is a blocker
|
||||||
|
found = s.find("blocking(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")");
|
||||||
|
string starget = s.substr(found+9,end - found - 9);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
|
tc->targetter = NULL;
|
||||||
|
found = s.find("from(");
|
||||||
|
|
||||||
|
TargetChooser *fromTc = NULL;
|
||||||
|
if (found != string::npos){
|
||||||
|
end = s.find (")", found);
|
||||||
|
starget = s.substr(found+5,end - found - 5);
|
||||||
|
fromTc = tcf.createTargetChooser(starget,card);
|
||||||
|
fromTc->targetter = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NEW TrCardBlocked(id,card,tc,fromTc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Card card is drawn
|
||||||
|
found = s.find("drawn(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")");
|
||||||
|
string starget = s.substr(found+6,end - found - 6);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
|
tc->targetter = NULL;
|
||||||
|
|
||||||
|
return NEW TrcardDrawn(id,card,tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Card is sacrificed
|
||||||
|
found = s.find("sacrificed(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")");
|
||||||
|
string starget = s.substr(found+11,end - found - 11);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
|
tc->targetter = NULL;
|
||||||
|
|
||||||
|
return NEW TrCardSacrificed(id,card,tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Card is sacrificed
|
||||||
|
found = s.find("discarded(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")");
|
||||||
|
string starget = s.substr(found+10,end - found - 10);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
|
tc->targetter = NULL;
|
||||||
|
|
||||||
|
return NEW TrCardDiscarded(id,card,tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Card Damaging
|
//Card Damaging
|
||||||
@@ -173,7 +299,47 @@ TriggeredAbility * AbilityFactory::parseTrigger(string magicText, int id, Spell
|
|||||||
fromTc = tcf.createTargetChooser(starget,card);
|
fromTc = tcf.createTargetChooser(starget,card);
|
||||||
fromTc->targetter = NULL;
|
fromTc->targetter = NULL;
|
||||||
}
|
}
|
||||||
return NEW TrDamaged(id,card,tc,fromTc);
|
return NEW TrDamaged(id,card,tc,fromTc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Card Damaging combat
|
||||||
|
found = s.find("combatdamage(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")");
|
||||||
|
string starget = s.substr(found+13,end - found - 13);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
|
tc->targetter = NULL;
|
||||||
|
found = s.find("from(");
|
||||||
|
|
||||||
|
TargetChooser *fromTc = NULL;
|
||||||
|
if (found != string::npos){
|
||||||
|
end = s.find (")", found);
|
||||||
|
starget = s.substr(found+5,end - found - 5);
|
||||||
|
fromTc = tcf.createTargetChooser(starget,card);
|
||||||
|
fromTc->targetter = NULL;
|
||||||
|
}
|
||||||
|
return NEW TrDamaged(id,card,tc,fromTc, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Card Damaging non combat
|
||||||
|
found = s.find("damagenoncombat(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")");
|
||||||
|
string starget = s.substr(found+16,end - found - 16);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser *tc = tcf.createTargetChooser(starget,card);
|
||||||
|
tc->targetter = NULL;
|
||||||
|
found = s.find("from(");
|
||||||
|
|
||||||
|
TargetChooser *fromTc = NULL;
|
||||||
|
if (found != string::npos){
|
||||||
|
end = s.find (")", found);
|
||||||
|
starget = s.substr(found+5,end - found - 5);
|
||||||
|
fromTc = tcf.createTargetChooser(starget,card);
|
||||||
|
fromTc->targetter = NULL;
|
||||||
|
}
|
||||||
|
return NEW TrDamaged(id,card,tc,fromTc, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int who = 0;
|
int who = 0;
|
||||||
@@ -320,8 +486,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
limit = atoi(sWithoutTc.substr(limit_str+6).c_str());
|
limit = atoi(sWithoutTc.substr(limit_str+6).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AEquip *ae = dynamic_cast<AEquip*>(a);
|
AEquip *ae = dynamic_cast<AEquip*>(a);
|
||||||
if (ae){
|
if (ae){
|
||||||
ae->cost = cost;
|
ae->cost = cost;
|
||||||
@@ -339,7 +503,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
SAFE_DELETE(cost);
|
SAFE_DELETE(cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//kicker cost
|
//kicker cost
|
||||||
found = s.find("kicker ");
|
found = s.find("kicker ");
|
||||||
if (found == 0){
|
if (found == 0){
|
||||||
@@ -492,7 +655,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
case 1: result = NEW AThisForEach(id, card, _target, td, a); break;
|
case 1: result = NEW AThisForEach(id, card, _target, td, a); break;
|
||||||
default: result = NULL;
|
default: result = NULL;
|
||||||
}
|
}
|
||||||
if (result) result->oneShot = oneShot;
|
if (result){ result->oneShot = oneShot;}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -633,6 +796,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ninjutsu
|
||||||
|
found = s.find("ninjutsu");
|
||||||
|
if (found != string::npos){
|
||||||
|
MTGAbility * a = NEW ANinja(id,card,target);
|
||||||
|
a->oneShot = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
//Fizzle (counterspell...)
|
//Fizzle (counterspell...)
|
||||||
found = s.find("fizzle");
|
found = s.find("fizzle");
|
||||||
if (found != string::npos){
|
if (found != string::npos){
|
||||||
@@ -660,10 +831,17 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
if (star != string::npos) multiplier = NEW WParsedInt(s.substr(star+1),spell,card);
|
if (star != string::npos) multiplier = NEW WParsedInt(s.substr(star+1),spell,card);
|
||||||
size_t end = s.find(")", found);
|
size_t end = s.find(")", found);
|
||||||
int tokenId = atoi(s.substr(found + 6,end - found - 6).c_str());
|
int tokenId = atoi(s.substr(found + 6,end - found - 6).c_str());
|
||||||
|
int who;
|
||||||
|
size_t opponent = s.find("opponent");
|
||||||
|
if (opponent != string::npos){
|
||||||
|
who = 1;
|
||||||
|
}else{
|
||||||
|
who = 0;
|
||||||
|
}
|
||||||
if (tokenId){
|
if (tokenId){
|
||||||
MTGCard * safetycard = GameApp::collection->getCardById(tokenId);
|
MTGCard * safetycard = GameApp::collection->getCardById(tokenId);
|
||||||
if (safetycard){//contenue
|
if (safetycard){//contenue
|
||||||
ATokenCreator * tok = NEW ATokenCreator(id,card,NULL,tokenId,0, multiplier);
|
ATokenCreator * tok = NEW ATokenCreator(id,card,NULL,tokenId,0, multiplier,who);
|
||||||
tok->oneShot = 1;
|
tok->oneShot = 1;
|
||||||
return tok;
|
return tok;
|
||||||
}else{
|
}else{
|
||||||
@@ -687,8 +865,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
if(!spt.find("XX/XX") || !spt.find("xx/xx")){value = spell->computeXX(card);}
|
if(!spt.find("XX/XX") || !spt.find("xx/xx")){value = spell->computeXX(card);}
|
||||||
parsePowerToughness(spt,&power, &toughness);
|
parsePowerToughness(spt,&power, &toughness);
|
||||||
string sabilities = s.substr(end+1);
|
string sabilities = s.substr(end+1);
|
||||||
|
if(s.find("opponent")){
|
||||||
ATokenCreator * tok = NEW ATokenCreator(id,card,NULL,sname,stypes,power + value,toughness + value,sabilities,0, multiplier);
|
if (opponent != string::npos){
|
||||||
|
who = 1;
|
||||||
|
}else{
|
||||||
|
who = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ATokenCreator * tok = NEW ATokenCreator(id,card,NULL,sname,stypes,power + value,toughness + value,sabilities,0, multiplier,who);
|
||||||
tok->oneShot = 1;
|
tok->oneShot = 1;
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
@@ -743,6 +927,25 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//clone
|
||||||
|
found = s.find("clone");
|
||||||
|
if (found != string::npos){
|
||||||
|
int who;
|
||||||
|
who = 0;
|
||||||
|
found = s.find("opponent");
|
||||||
|
if (found != string::npos){
|
||||||
|
who = 1;
|
||||||
|
}
|
||||||
|
string with;
|
||||||
|
found = s.find("with(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")", found);
|
||||||
|
with = s.substr(found+5,end - found - 5);
|
||||||
|
}
|
||||||
|
MTGAbility * a = NEW AACloner(id,card,target,0,who,with);
|
||||||
|
a->oneShot = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
//Bury, destroy
|
//Bury, destroy
|
||||||
string destroys[] = {"bury","destroy"};
|
string destroys[] = {"bury","destroy"};
|
||||||
@@ -757,11 +960,26 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//sacrifices and discards
|
||||||
|
string sacdis[] = {"sacrifice","reject"};
|
||||||
|
int sacdisTypes[]= {1, 0};
|
||||||
|
for (int i = 0; i < 2; ++i){
|
||||||
|
found = s.find(sacdis[i]);
|
||||||
|
if (found != string::npos){
|
||||||
|
int sacrifice = sacdisTypes[i];
|
||||||
|
MTGAbility * a = NEW AASacDis(id,card,target,sacrifice);
|
||||||
|
a->oneShot = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int who = TargetChooser::UNSET;
|
int who = TargetChooser::UNSET;
|
||||||
if (s.find(" controller") != string::npos) who=TargetChooser::CONTROLLER;
|
if (s.find(" controller") != string::npos) who=TargetChooser::CONTROLLER;
|
||||||
if (s.find(" opponent") != string::npos) who=TargetChooser::OPPONENT;
|
if (s.find(" opponent") != string::npos) who=TargetChooser::OPPONENT;
|
||||||
if (s.find(" targetcontroller") != string::npos) who=TargetChooser::TARGET_CONTROLLER;
|
if (s.find(" targetcontroller") != string::npos) who=TargetChooser::TARGET_CONTROLLER;
|
||||||
|
if (s.find(" owner") != string::npos) who=TargetChooser::OWNER;
|
||||||
|
|
||||||
found = s.find("ueot");
|
found = s.find("ueot");
|
||||||
if (found!= string::npos) forceUEOT = 1;
|
if (found!= string::npos) forceUEOT = 1;
|
||||||
@@ -798,6 +1016,53 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
}
|
}
|
||||||
return ab;
|
return ab;
|
||||||
}
|
}
|
||||||
|
//PreventCombat Damage
|
||||||
|
found = s.find("preventalldamage");
|
||||||
|
if (found != string::npos){
|
||||||
|
string to = "";
|
||||||
|
string from = "";
|
||||||
|
found = s.find("to(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")", found);
|
||||||
|
to = s.substr(found+3,end - found - 3);
|
||||||
|
}
|
||||||
|
found = s.find("from(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")", found);
|
||||||
|
from = s.substr(found+5,end - found - 5);
|
||||||
|
}
|
||||||
|
MTGAbility * ab;
|
||||||
|
if (forceUEOT){
|
||||||
|
ab = NEW APreventAllCombatDamageUEOT(id,card,to,from,1);
|
||||||
|
}else{
|
||||||
|
ab = NEW APreventAllCombatDamage(id,card,to,from,1);
|
||||||
|
}
|
||||||
|
return ab;
|
||||||
|
}
|
||||||
|
|
||||||
|
//PreventCombat Damage
|
||||||
|
found = s.find("preventallnoncombat");
|
||||||
|
if (found != string::npos){
|
||||||
|
string to = "";
|
||||||
|
string from = "";
|
||||||
|
found = s.find("to(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")", found);
|
||||||
|
to = s.substr(found+3,end - found - 3);
|
||||||
|
}
|
||||||
|
found = s.find("from(");
|
||||||
|
if (found != string::npos){
|
||||||
|
size_t end = s.find (")", found);
|
||||||
|
from = s.substr(found+5,end - found - 5);
|
||||||
|
}
|
||||||
|
MTGAbility * ab;
|
||||||
|
if (forceUEOT){
|
||||||
|
ab = NEW APreventAllCombatDamageUEOT(id,card,to,from,2);
|
||||||
|
}else{
|
||||||
|
ab = NEW APreventAllCombatDamage(id,card,to,from,2);
|
||||||
|
}
|
||||||
|
return ab;
|
||||||
|
}
|
||||||
|
|
||||||
//PreventCombat Damage
|
//PreventCombat Damage
|
||||||
found = s.find("fog");
|
found = s.find("fog");
|
||||||
@@ -838,6 +1103,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
a->oneShot = 1;
|
a->oneShot = 1;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
//remove poison
|
//remove poison
|
||||||
found = s.find("removepoison:");
|
found = s.find("removepoison:");
|
||||||
if (found != string::npos){
|
if (found != string::npos){
|
||||||
@@ -1051,7 +1317,25 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
// the following is NOT dead code. this is for stacking flanking. except auras do not yet support
|
||||||
|
//giving creatures activated/MTGAbility keywords. soon as i add this support this will be uncommented for stacking flanking.
|
||||||
|
// //flanking
|
||||||
|
// found = s.find("flanking");
|
||||||
|
// if (found != string::npos){
|
||||||
|
// return NEW AFlankerAbility(id,card);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//bushido
|
||||||
|
found = s.find("bushido(");
|
||||||
|
if (found != string::npos){
|
||||||
|
int end = s.find(")", found);
|
||||||
|
string spt = s.substr(8,end - 1);
|
||||||
|
int power, toughness;
|
||||||
|
if (parsePowerToughness(spt,&power, &toughness)){
|
||||||
|
return NEW ABushidoAbility(id,card,power,toughness);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//counter
|
//counter
|
||||||
found = s.find("counter(");
|
found = s.find("counter(");
|
||||||
@@ -1289,6 +1573,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//switch targest power with toughness
|
||||||
|
found = s.find("twist");
|
||||||
|
if (found != string::npos){
|
||||||
|
MTGAbility * a = NEW ATwistUEOT(id,card,target);
|
||||||
|
a->oneShot = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
//Untapper (Ley Druid...)
|
//Untapper (Ley Druid...)
|
||||||
found = s.find("untap");
|
found = s.find("untap");
|
||||||
if (found != string::npos){
|
if (found != string::npos){
|
||||||
@@ -1331,6 +1623,9 @@ int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, Targ
|
|||||||
if (AAsLongAs * abi = dynamic_cast<AAsLongAs *>(a)) return abilityEfficiency(abi->ability,p, mode,tc);
|
if (AAsLongAs * abi = dynamic_cast<AAsLongAs *>(a)) return abilityEfficiency(abi->ability,p, mode,tc);
|
||||||
if (AForeach * abi = dynamic_cast<AForeach *>(a)) return abilityEfficiency(abi->ability,p, mode,tc);
|
if (AForeach * abi = dynamic_cast<AForeach *>(a)) return abilityEfficiency(abi->ability,p, mode,tc);
|
||||||
if (dynamic_cast<AAFizzler *>(a)) return BAKA_EFFECT_BAD;
|
if (dynamic_cast<AAFizzler *>(a)) return BAKA_EFFECT_BAD;
|
||||||
|
if (dynamic_cast<AADamagePrevent *>(a)) return BAKA_EFFECT_GOOD;
|
||||||
|
if (dynamic_cast<AACloner *>(a)) return BAKA_EFFECT_GOOD;
|
||||||
|
if (dynamic_cast<ATwistUEOT *>(a)) return BAKA_EFFECT_BAD;
|
||||||
if (dynamic_cast<AAUntapper *>(a)) return BAKA_EFFECT_GOOD;
|
if (dynamic_cast<AAUntapper *>(a)) return BAKA_EFFECT_GOOD;
|
||||||
if (dynamic_cast<AATapper *>(a)) return BAKA_EFFECT_BAD;
|
if (dynamic_cast<AATapper *>(a)) return BAKA_EFFECT_BAD;
|
||||||
if (AACounter * ac = dynamic_cast<AACounter *>(a)) {
|
if (AACounter * ac = dynamic_cast<AACounter *>(a)) {
|
||||||
@@ -1805,7 +2100,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
|
|||||||
{
|
{
|
||||||
int xCost = computeX(spell,card);
|
int xCost = computeX(spell,card);
|
||||||
for (int i = 0; i < xCost; i++){
|
for (int i = 0; i < xCost; i++){
|
||||||
game->opponent()->game->discardRandom(game->opponent()->game->hand);
|
game->opponent()->game->discardRandom(game->opponent()->game->hand,card);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2076,6 +2371,10 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
|
|||||||
game->addObserver(NEW AExalted(_id, card));
|
game->addObserver(NEW AExalted(_id, card));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (card->basicAbilities[Constants::FLANKING]){
|
||||||
|
game->addObserver(NEW AFlankerAbility(_id, card));
|
||||||
|
}
|
||||||
|
|
||||||
// Tested works the first r10 did not function because of the mistake in the array of the definition
|
// Tested works the first r10 did not function because of the mistake in the array of the definition
|
||||||
if (card->basicAbilities[Constants::FORESTHOME]){
|
if (card->basicAbilities[Constants::FORESTHOME]){
|
||||||
game->addObserver(NEW AStrongLandLinkCreature(_id, card, "forest"));
|
game->addObserver(NEW AStrongLandLinkCreature(_id, card, "forest"));
|
||||||
@@ -2715,7 +3014,10 @@ AManaProducer::AManaProducer(int id, MTGCardInstance * card, Targetable * t, Man
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
if (!mana) mana = game->currentlyActing()->getManaPool();
|
if (!mana) mana = game->currentlyActing()->getManaPool();
|
||||||
if (_card == source && (!tap || !source->isTapped()) && game->currentlyActing()->game->inPlay->hasCard(source) && (source->hasType(Subtypes::TYPE_LAND) || !tap || !source->hasSummoningSickness()) ){
|
if (_card == source && (!tap || !source->isTapped()) && game->currentlyActing()->game->inPlay->hasCard(source) && (source->hasType(Subtypes::TYPE_LAND) || !tap || !source->hasSummoningSickness()) ){
|
||||||
if (!cost || mana->canAfford(cost)) result = 1;
|
if (!cost || mana->canAfford(cost))
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -2746,7 +3048,12 @@ AManaProducer::AManaProducer(int id, MTGCardInstance * card, Targetable * t, Man
|
|||||||
GameObserver::GetInstance()->currentlyActing()->getManaPool()->pay(cost);
|
GameObserver::GetInstance()->currentlyActing()->getManaPool()->pay(cost);
|
||||||
cost->doPayExtra();
|
cost->doPayExtra();
|
||||||
}
|
}
|
||||||
if (tap) source->tap();
|
if (tap){
|
||||||
|
GameObserver *g = GameObserver::GetInstance();
|
||||||
|
WEvent * e = NEW WEventCardTappedForMana(source, 0, 1);
|
||||||
|
g->receiveEvent(e);
|
||||||
|
source->tap();
|
||||||
|
}
|
||||||
|
|
||||||
if (options[Options::SFXVOLUME].number > 0){
|
if (options[Options::SFXVOLUME].number > 0){
|
||||||
JSample * sample = resources.RetrieveSample("mana.wav");
|
JSample * sample = resources.RetrieveSample("mana.wav");
|
||||||
@@ -2833,6 +3140,8 @@ AManaProducer::AManaProducer(int id, MTGCardInstance * card, Targetable * t, Man
|
|||||||
return source->controller();
|
return source->controller();
|
||||||
case TargetChooser::OPPONENT:
|
case TargetChooser::OPPONENT:
|
||||||
return source->controller()->opponent();
|
return source->controller()->opponent();
|
||||||
|
case TargetChooser::OWNER:
|
||||||
|
return source->owner;
|
||||||
default:
|
default:
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to
|
|||||||
banding = NULL;
|
banding = NULL;
|
||||||
life = toughness;
|
life = toughness;
|
||||||
preventable = 0;
|
preventable = 0;
|
||||||
|
flanked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTGCardInstance::copy(MTGCardInstance * card){
|
void MTGCardInstance::copy(MTGCardInstance * card){
|
||||||
@@ -99,6 +100,11 @@ void MTGCardInstance::initMTGCI(){
|
|||||||
tapped = 0;
|
tapped = 0;
|
||||||
untapping = 0;
|
untapping = 0;
|
||||||
frozen = 0;
|
frozen = 0;
|
||||||
|
fresh = 0;
|
||||||
|
didattacked = 0;
|
||||||
|
didblocked = 0;
|
||||||
|
notblocked = 0;
|
||||||
|
sunburst = NULL;
|
||||||
equipment = NULL;
|
equipment = NULL;
|
||||||
boughtback = 0;
|
boughtback = 0;
|
||||||
flashedback = 0;
|
flashedback = 0;
|
||||||
@@ -106,6 +112,7 @@ void MTGCardInstance::initMTGCI(){
|
|||||||
reduxamount = 0;
|
reduxamount = 0;
|
||||||
summoningSickness = 1;
|
summoningSickness = 1;
|
||||||
preventable = 0;
|
preventable = 0;
|
||||||
|
flanked = 0;
|
||||||
target = NULL;
|
target = NULL;
|
||||||
type_as_damageable = DAMAGEABLE_MTGCARDINSTANCE;
|
type_as_damageable = DAMAGEABLE_MTGCARDINSTANCE;
|
||||||
banding = NULL;
|
banding = NULL;
|
||||||
@@ -184,6 +191,10 @@ int MTGCardInstance::afterDamage(){
|
|||||||
|
|
||||||
int MTGCardInstance::bury(){
|
int MTGCardInstance::bury(){
|
||||||
Player * p = controller();
|
Player * p = controller();
|
||||||
|
if (basicAbilities[Constants::EXILEBURY]){
|
||||||
|
p->game->putInZone(this,p->game->inPlay,owner->game->exile);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if (!basicAbilities[Constants::INDESTRUCTIBLE]){
|
if (!basicAbilities[Constants::INDESTRUCTIBLE]){
|
||||||
p->game->putInZone(this,p->game->inPlay,owner->game->graveyard);
|
p->game->putInZone(this,p->game->inPlay,owner->game->graveyard);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -203,6 +214,40 @@ int MTGCardInstance::has(int basicAbility){
|
|||||||
return basicAbilities[basicAbility];
|
return basicAbilities[basicAbility];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//sets card as attacked and sends events
|
||||||
|
void MTGCardInstance::eventattacked(){
|
||||||
|
didattacked = 1;
|
||||||
|
WEvent * e = NEW WEventCardAttacked(this);
|
||||||
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
|
game->receiveEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//sets card as attacked and sends events
|
||||||
|
void MTGCardInstance::eventattackednotblocked(){
|
||||||
|
didattacked = 1;
|
||||||
|
WEvent * e = NEW WEventCardAttackedNotBlocked(this);
|
||||||
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
|
game->receiveEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//sets card as attacked and sends events
|
||||||
|
void MTGCardInstance::eventattackedblocked(){
|
||||||
|
didattacked = 1;
|
||||||
|
WEvent * e = NEW WEventCardAttackedBlocked(this);
|
||||||
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
|
game->receiveEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//sets card as blocking and sends events
|
||||||
|
void MTGCardInstance::eventblocked(){
|
||||||
|
didblocked = 1;
|
||||||
|
WEvent * e = NEW WEventCardBlocked(this);
|
||||||
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
|
game->receiveEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//Taps the card
|
//Taps the card
|
||||||
void MTGCardInstance::tap(){
|
void MTGCardInstance::tap(){
|
||||||
if (tapped) return;
|
if (tapped) return;
|
||||||
@@ -265,6 +310,8 @@ int MTGCardInstance::initAttackersDefensers(){
|
|||||||
banding = NULL;
|
banding = NULL;
|
||||||
blockers.clear();
|
blockers.clear();
|
||||||
blocked = false;
|
blocked = false;
|
||||||
|
didattacked = 0;
|
||||||
|
didblocked = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +320,10 @@ int MTGCardInstance::cleanup(){
|
|||||||
initAttackersDefensers();
|
initAttackersDefensers();
|
||||||
life=toughness;
|
life=toughness;
|
||||||
GameObserver * game = GameObserver::GetInstance();
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
if (!game || game->currentPlayer == controller()) summoningSickness = 0;
|
if (!game || game->currentPlayer == controller())
|
||||||
|
{
|
||||||
|
summoningSickness = 0;
|
||||||
|
}
|
||||||
if (previous && !previous->stillInUse()){
|
if (previous && !previous->stillInUse()){
|
||||||
SAFE_DELETE(previous);
|
SAFE_DELETE(previous);
|
||||||
}
|
}
|
||||||
@@ -471,7 +521,9 @@ int MTGCardInstance::getDefenserRank(MTGCardInstance * blocker){
|
|||||||
|
|
||||||
int MTGCardInstance::removeBlocker(MTGCardInstance * blocker){
|
int MTGCardInstance::removeBlocker(MTGCardInstance * blocker){
|
||||||
blockers.remove(blocker);
|
blockers.remove(blocker);
|
||||||
if (!blockers.size()) blocked = false;
|
if (!blockers.size()){
|
||||||
|
blocked = false;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,13 +589,18 @@ int MTGCardInstance::toggleDefenser(MTGCardInstance * opponent){
|
|||||||
if (canBlock()){
|
if (canBlock()){
|
||||||
if (canBlock(opponent)){
|
if (canBlock(opponent)){
|
||||||
setDefenser(opponent);
|
setDefenser(opponent);
|
||||||
|
didblocked = 1;
|
||||||
|
if(opponent && opponent->controller()->isAI()){
|
||||||
|
opponent->view->actZ += .8;
|
||||||
|
opponent->view->actT -= .2;
|
||||||
|
}
|
||||||
|
if(!opponent) didblocked = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int MTGCardInstance::addProtection(TargetChooser * tc){
|
int MTGCardInstance::addProtection(TargetChooser * tc){
|
||||||
tc->targetter = NULL;
|
tc->targetter = NULL;
|
||||||
protections.push_back(tc);
|
protections.push_back(tc);
|
||||||
|
|||||||
@@ -96,6 +96,11 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi
|
|||||||
colors.push_back(j);
|
colors.push_back(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(colors.size())
|
||||||
|
{
|
||||||
|
primitive->setColor(0,1);
|
||||||
|
primitive->removeColor(0);
|
||||||
|
}
|
||||||
list<int>::iterator it;
|
list<int>::iterator it;
|
||||||
for ( it=colors.begin() ; it != colors.end(); it++ ){
|
for ( it=colors.begin() ; it != colors.end(); it++ ){
|
||||||
primitive->setColor(*it);
|
primitive->setColor(*it);
|
||||||
|
|||||||
@@ -89,6 +89,9 @@ const char* Constants::MTGBasicAbilities[] = {
|
|||||||
"leyline",
|
"leyline",
|
||||||
"playershroud",
|
"playershroud",
|
||||||
"controllershroud",
|
"controllershroud",
|
||||||
|
"sunburst",
|
||||||
|
"flanking",
|
||||||
|
"exiledeath",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -249,10 +249,13 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
|
|||||||
return card; //Error
|
return card; //Error
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTGPlayerCards::discardRandom(MTGGameZone * from){
|
void MTGPlayerCards::discardRandom(MTGGameZone * from,MTGCardInstance * source){
|
||||||
if (!from->nb_cards)
|
if (!from->nb_cards)
|
||||||
return;
|
return;
|
||||||
int r = WRand() % (from->nb_cards);
|
int r = WRand() % (from->nb_cards);
|
||||||
|
WEvent * e = NEW WEventCardDiscard(from->cards[r]);
|
||||||
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
|
game->receiveEvent(e);
|
||||||
putInZone(from->cards[r],from, graveyard);
|
putInZone(from->cards[r],from, graveyard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,23 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
|||||||
|
|
||||||
//cost of card.
|
//cost of card.
|
||||||
if (playerMana->canAfford(cost)){
|
if (playerMana->canAfford(cost)){
|
||||||
|
//-------
|
||||||
|
if(card->has(Constants::SUNBURST)){
|
||||||
|
for(int i = 1; i != 6;i++)
|
||||||
|
{
|
||||||
|
if(player->getManaPool()->hasColor(i)){
|
||||||
|
if(card->getManaCost()->hasColor(i) > 0){//do nothing if the card already has this color.
|
||||||
|
}else{
|
||||||
|
if(card->sunburst < card->getManaCost()->getConvertedCost()){
|
||||||
|
card->getManaCost()->add(i,1);
|
||||||
|
card->getManaCost()->remove(0,1);
|
||||||
|
card->sunburst += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//-------
|
||||||
|
}
|
||||||
|
}
|
||||||
return 1;//play if you can afford too.
|
return 1;//play if you can afford too.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -736,6 +753,83 @@ MTGAttackRule * MTGAttackRule::clone() const{
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//this rules handles returning cards to combat triggers for activations.
|
||||||
|
MTGCombatTriggersRule::MTGCombatTriggersRule(int _id):MTGAbility(_id,NULL){
|
||||||
|
aType=MTGAbility::MTG_COMBATTRIGGERS_RULE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MTGCombatTriggersRule::receiveEvent(WEvent *e){
|
||||||
|
if (WEventPhaseChange* event = dynamic_cast<WEventPhaseChange*>(e)) {
|
||||||
|
if (Constants::MTG_PHASE_COMBATATTACKERS == event->from->id) {
|
||||||
|
Player * p = game->currentPlayer;
|
||||||
|
MTGGameZone * z = p->game->inPlay;
|
||||||
|
for (int i= 0; i < z->nb_cards; i++){
|
||||||
|
MTGCardInstance * card = z->cards[i];
|
||||||
|
if (card && card->isAttacker()){
|
||||||
|
card->eventattacked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Constants::MTG_PHASE_COMBATEND == event->from->id) {
|
||||||
|
Player * p = game->currentPlayer->opponent();
|
||||||
|
MTGGameZone * z = p->game->inPlay;
|
||||||
|
for (int i= 0; i < z->nb_cards; i++){
|
||||||
|
MTGCardInstance * card = z->cards[i];
|
||||||
|
if (card){
|
||||||
|
card->didattacked = 0;
|
||||||
|
card->didblocked = 0;
|
||||||
|
card->notblocked = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------
|
||||||
|
}
|
||||||
|
if (WEventBlockersChosen * event = dynamic_cast<WEventBlockersChosen*>(e))
|
||||||
|
{
|
||||||
|
Player * p = game->currentPlayer;
|
||||||
|
MTGGameZone * z = p->game->inPlay;
|
||||||
|
for (int i= 0; i < z->nb_cards; i++){
|
||||||
|
MTGCardInstance * card = z->cards[i];
|
||||||
|
if (card && card->isAttacker() && !card->blocked)
|
||||||
|
{
|
||||||
|
card->eventattackednotblocked();
|
||||||
|
card->notblocked += 1;
|
||||||
|
}
|
||||||
|
if (card && card->isAttacker() && card->blocked)
|
||||||
|
{
|
||||||
|
card->eventattackedblocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MTGGameZone* opponentZone = game->currentPlayer->opponent()->game->inPlay;
|
||||||
|
for (int i = 0; i < opponentZone->nb_cards; i++)
|
||||||
|
{
|
||||||
|
MTGCardInstance* card = opponentZone->cards[i];
|
||||||
|
if (card && card->didblocked > 0){
|
||||||
|
card->eventblocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//trigger rules are never distroyed
|
||||||
|
int MTGCombatTriggersRule::testDestroy(){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream& MTGCombatTriggersRule::toString(ostream& out) const
|
||||||
|
{
|
||||||
|
out << "MTGCombatTriggersRule ::: (";
|
||||||
|
return MTGAbility::toString(out) << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
MTGCombatTriggersRule * MTGCombatTriggersRule::clone() const{
|
||||||
|
MTGCombatTriggersRule * a = NEW MTGCombatTriggersRule(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
///------------
|
||||||
|
|
||||||
OtherAbilitiesEventReceiver::OtherAbilitiesEventReceiver(int _id):MTGAbility(_id,NULL){
|
OtherAbilitiesEventReceiver::OtherAbilitiesEventReceiver(int _id):MTGAbility(_id,NULL){
|
||||||
}
|
}
|
||||||
@@ -773,7 +867,7 @@ MTGBlockRule::MTGBlockRule(int _id):MTGAbility(_id,NULL){
|
|||||||
|
|
||||||
int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){
|
int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){
|
||||||
if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting && card->controller() == game->currentlyActing()){
|
if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting && card->controller() == game->currentlyActing()){
|
||||||
if (card->canBlock()) return 1;
|
if (card->canBlock())return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1085,6 +1179,12 @@ int MTGCantCasterstart::receiveEvent(WEvent * event){
|
|||||||
WEventZoneChange * e = (WEventZoneChange *) event;
|
WEventZoneChange * e = (WEventZoneChange *) event;
|
||||||
MTGCardInstance * card = e->card->previous;
|
MTGCardInstance * card = e->card->previous;
|
||||||
if(card){
|
if(card){
|
||||||
|
if(e->from == e->card->controller()->game->battlefield && e->to == e->card->controller()->game->graveyard){
|
||||||
|
e->card->fresh = 1;
|
||||||
|
}
|
||||||
|
if(e->to == e->card->controller()->game->battlefield){
|
||||||
|
e->card->fresh = 1;
|
||||||
|
}
|
||||||
if (card->basicAbilities[Constants::BOTHCANTCAST] || card->basicAbilities[Constants::BOTHNOCREATURE] || card->basicAbilities[Constants::CANTCAST] || card->basicAbilities[Constants::CANTCASTCREATURE] || card->basicAbilities[Constants::CANTCASTTWO] || card->basicAbilities[Constants::ONLYONEBOTH] || card->basicAbilities[Constants::NOMAXHAND] ){
|
if (card->basicAbilities[Constants::BOTHCANTCAST] || card->basicAbilities[Constants::BOTHNOCREATURE] || card->basicAbilities[Constants::CANTCAST] || card->basicAbilities[Constants::CANTCASTCREATURE] || card->basicAbilities[Constants::CANTCASTTWO] || card->basicAbilities[Constants::ONLYONEBOTH] || card->basicAbilities[Constants::NOMAXHAND] ){
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
for (int i = 0; i < 2 ; i++){
|
for (int i = 0; i < 2 ; i++){
|
||||||
@@ -1240,8 +1340,30 @@ int MTGSneakAttackRule::receiveEvent(WEvent *e){
|
|||||||
MTGGameZone * z = p->game->inPlay;
|
MTGGameZone * z = p->game->inPlay;
|
||||||
for (int i= 0; i < z->nb_cards; i++){
|
for (int i= 0; i < z->nb_cards; i++){
|
||||||
MTGCardInstance * card = z->cards[i];
|
MTGCardInstance * card = z->cards[i];
|
||||||
if (card->has(Constants::TREASON)) {p->game->putInGraveyard(card);i--;}
|
while(card->flanked){//undoes the flanking on a card
|
||||||
|
card->power += 1;
|
||||||
|
card->addToToughness(1);
|
||||||
|
card->flanked -= 1;
|
||||||
|
}
|
||||||
|
if (card->has(Constants::TREASON))
|
||||||
|
{
|
||||||
|
WEvent * e = NEW WEventCardSacrifice(card);
|
||||||
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
|
game->receiveEvent(e);
|
||||||
|
p->game->putInGraveyard(card);i--;
|
||||||
|
}
|
||||||
if (card->has(Constants::UNEARTH)) {p->game->putInExile(card);i--;}
|
if (card->has(Constants::UNEARTH)) {p->game->putInExile(card);i--;}
|
||||||
|
if (card->fresh) card->fresh = 0;
|
||||||
|
if (card->has(Constants::ONLYONEBOTH))
|
||||||
|
{
|
||||||
|
card->controller()->castcount = 0;
|
||||||
|
card->controller()->opponent()->castcount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MTGGameZone * f = p->game->graveyard;
|
||||||
|
for (int k= 0; k < f->nb_cards; k++){
|
||||||
|
MTGCardInstance * card = f->cards[k];
|
||||||
|
card->fresh = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,10 +97,19 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'd': //DiscardRandom cost
|
case 'd': //DiscardRandom cost
|
||||||
|
if (value == "d"){
|
||||||
manaCost->addExtraCost(NEW DiscardRandomCost(tc));
|
manaCost->addExtraCost(NEW DiscardRandomCost(tc));
|
||||||
|
}else{
|
||||||
|
manaCost->addExtraCost(NEW DiscardCost(tc));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'm': //Mill yourself as a cost
|
case 'm': //Mill yourself as a cost
|
||||||
manaCost->addExtraCost(NEW MillCost(tc));
|
manaCost->addExtraCost(NEW MillCost(tc));
|
||||||
|
break;
|
||||||
|
case 'n': //return unblocked attacker cost
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
tc = tcf.createTargetChooser("creature|myBattlefield", c);
|
||||||
|
manaCost->addExtraCost(NEW Ninja(tc));
|
||||||
break;
|
break;
|
||||||
case 'c': //Counters
|
case 'c': //Counters
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,20 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
|||||||
return NEW CardTargetChooser(target,card);
|
return NEW CardTargetChooser(target,card);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
found = s.find("opponent");
|
||||||
|
if (found == 0){
|
||||||
|
int maxtargets = 1;
|
||||||
|
Player * opponent = card->controller()->opponent();
|
||||||
|
return NEW PlayerTargetChooser(card,maxtargets,opponent);
|
||||||
|
};
|
||||||
|
|
||||||
|
found = s.find("controller");
|
||||||
|
if (found == 0){
|
||||||
|
int maxtargets = 1;
|
||||||
|
Player * controller = card->controller();
|
||||||
|
return NEW PlayerTargetChooser(card,maxtargets,controller);
|
||||||
|
};
|
||||||
|
|
||||||
found = s.find("other ");
|
found = s.find("other ");
|
||||||
if (found == 0){
|
if (found == 0){
|
||||||
other = true;
|
other = true;
|
||||||
@@ -191,15 +205,17 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
|||||||
}else{
|
}else{
|
||||||
cd->attacker = 1;
|
cd->attacker = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//Blocker
|
//Blocker
|
||||||
}else if (attribute.find("blocking") != string::npos){
|
else if (attribute.find("blocking") != string::npos){
|
||||||
if (minus){
|
if (minus){
|
||||||
cd->defenser = & MTGCardInstance::NoCard;
|
cd->defenser = & MTGCardInstance::NoCard;
|
||||||
}else{
|
}else{
|
||||||
cd->defenser = & MTGCardInstance::AnyCard;
|
cd->defenser = & MTGCardInstance::AnyCard;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//Tapped, untapped
|
//Tapped, untapped
|
||||||
}else if (attribute.find("tapped") != string::npos){
|
else if (attribute.find("tapped") != string::npos){
|
||||||
if (minus){
|
if (minus){
|
||||||
cd->unsecureSetTapped(-1);
|
cd->unsecureSetTapped(-1);
|
||||||
}else{
|
}else{
|
||||||
@@ -212,6 +228,13 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
|||||||
}else{
|
}else{
|
||||||
cd->isToken = 1;
|
cd->isToken = 1;
|
||||||
}
|
}
|
||||||
|
//put in its zone this turn
|
||||||
|
}else if (attribute.find("fresh") != string::npos){
|
||||||
|
if (minus){
|
||||||
|
cd->unsecuresetfresh(-1);
|
||||||
|
}else{
|
||||||
|
cd->unsecuresetfresh(1);
|
||||||
|
}
|
||||||
//Power restrictions
|
//Power restrictions
|
||||||
}else if (attribute.find("power") != string::npos){
|
}else if (attribute.find("power") != string::npos){
|
||||||
cd->setPower(comparisonCriterion);
|
cd->setPower(comparisonCriterion);
|
||||||
@@ -520,7 +543,6 @@ bool TypeTargetChooser::canTarget(Targetable * target){
|
|||||||
MTGCardInstance * card = (MTGCardInstance *) target;
|
MTGCardInstance * card = (MTGCardInstance *) target;
|
||||||
for (int i= 0; i < nbtypes; i++){
|
for (int i= 0; i < nbtypes; i++){
|
||||||
if (card->hasSubtype(types[i])) return true;
|
if (card->hasSubtype(types[i])) return true;
|
||||||
if (card->has(Constants::CHANGELING)) return true;
|
|
||||||
if (Subtypes::subtypesList->find(card->getLCName()) == types[i]) return true;
|
if (Subtypes::subtypesList->find(card->getLCName()) == types[i]) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -137,6 +137,28 @@ ThisDescriptor * ThisDescriptorFactory::createThisDescriptor(string s){
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//whenever this creature attacks do effect
|
||||||
|
found = s.find("attacking");
|
||||||
|
if (found != string::npos) {
|
||||||
|
ThisAttacked * td = NEW ThisAttacked(criterion);
|
||||||
|
if (td) {
|
||||||
|
td->comparisonMode = mode;
|
||||||
|
return td;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//whenever this creature attacks do effect
|
||||||
|
found = s.find("notblocked");
|
||||||
|
if (found != string::npos) {
|
||||||
|
ThisNotBlocked * td = NEW ThisNotBlocked(criterion);
|
||||||
|
if (td) {
|
||||||
|
td->comparisonMode = mode;
|
||||||
|
return td;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//controller life
|
//controller life
|
||||||
found = s.find("opponentlife");
|
found = s.find("opponentlife");
|
||||||
if (found != string::npos) {
|
if (found != string::npos) {
|
||||||
@@ -262,6 +284,25 @@ int ThisEquip::match(MTGCardInstance * card){
|
|||||||
return matchValue(card->equipment);
|
return matchValue(card->equipment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ThisAttacked::ThisAttacked(int attack){
|
||||||
|
|
||||||
|
comparisonCriterion = attack;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ThisAttacked::match(MTGCardInstance * card){
|
||||||
|
|
||||||
|
return matchValue(card->didattacked);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThisNotBlocked::ThisNotBlocked(int unblocked){
|
||||||
|
|
||||||
|
comparisonCriterion = unblocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ThisNotBlocked::match(MTGCardInstance * card){
|
||||||
|
|
||||||
|
return matchValue(card->notblocked);
|
||||||
|
}
|
||||||
|
|
||||||
ThisToughness::ThisToughness(int toughness){
|
ThisToughness::ThisToughness(int toughness){
|
||||||
comparisonCriterion = toughness;
|
comparisonCriterion = toughness;
|
||||||
|
|||||||
@@ -18,6 +18,22 @@ WEventPhaseChange::WEventPhaseChange(Phase * from, Phase * to) : WEvent(CHANGE_P
|
|||||||
|
|
||||||
WEventCardTap::WEventCardTap(MTGCardInstance * card, bool before, bool after) : WEventCardUpdate(card), before(before), after(after){}
|
WEventCardTap::WEventCardTap(MTGCardInstance * card, bool before, bool after) : WEventCardUpdate(card), before(before), after(after){}
|
||||||
|
|
||||||
|
WEventCardTappedForMana::WEventCardTappedForMana(MTGCardInstance * card, bool before, bool after) : WEventCardUpdate(card), before(before), after(after){}
|
||||||
|
|
||||||
|
WEventCardAttacked::WEventCardAttacked(MTGCardInstance * card) : WEventCardUpdate(card){}
|
||||||
|
|
||||||
|
WEventCardAttackedNotBlocked::WEventCardAttackedNotBlocked(MTGCardInstance * card) : WEventCardUpdate(card){}
|
||||||
|
|
||||||
|
WEventCardAttackedBlocked::WEventCardAttackedBlocked(MTGCardInstance * card) : WEventCardUpdate(card){}
|
||||||
|
|
||||||
|
WEventCardBlocked::WEventCardBlocked(MTGCardInstance * card) : WEventCardUpdate(card){}
|
||||||
|
|
||||||
|
WEventcardDraw::WEventcardDraw(Player * player,int nb_cards) : player(player), nb_cards(nb_cards){}
|
||||||
|
|
||||||
|
WEventCardSacrifice::WEventCardSacrifice(MTGCardInstance * card) : WEventCardUpdate(card){}
|
||||||
|
|
||||||
|
WEventCardDiscard::WEventCardDiscard(MTGCardInstance * card) : WEventCardUpdate(card){}
|
||||||
|
|
||||||
WEventCardChangeType::WEventCardChangeType(MTGCardInstance * card, int type, bool before, bool after) : WEventCardUpdate(card), type(type), before(before), after(after){}
|
WEventCardChangeType::WEventCardChangeType(MTGCardInstance * card, int type, bool before, bool after) : WEventCardUpdate(card), type(type), before(before), after(after){}
|
||||||
|
|
||||||
WEventCreatureAttacker::WEventCreatureAttacker(MTGCardInstance * card, Targetable * before, Targetable * after) : WEventCardUpdate(card), before(before), after(after){}
|
WEventCreatureAttacker::WEventCreatureAttacker(MTGCardInstance * card, Targetable * before, Targetable * after) : WEventCardUpdate(card), before(before), after(after){}
|
||||||
@@ -51,11 +67,61 @@ Targetable * WEventZoneChange::getTarget(int target) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Targetable * WEventCardAttacked::getTarget(int target) {
|
||||||
|
if (target) return card;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Targetable * WEventCardSacrifice::getTarget(int target) {
|
||||||
|
if (target) return card;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Targetable * WEventCardDiscard::getTarget(int target) {
|
||||||
|
if (target) return card;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Targetable * WEventCardAttackedNotBlocked::getTarget(int target) {
|
||||||
|
if (target) return card;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Targetable * WEventCardAttackedBlocked::getTarget(int target) {
|
||||||
|
switch (target) {
|
||||||
|
case TARGET_TO :
|
||||||
|
return card;
|
||||||
|
case TARGET_FROM :
|
||||||
|
return card->getNextOpponent();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Targetable * WEventCardBlocked::getTarget(int target) {
|
||||||
|
switch (target) {
|
||||||
|
case TARGET_TO :
|
||||||
|
return card;
|
||||||
|
case TARGET_FROM :
|
||||||
|
return card->getNextOpponent();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Targetable * WEventCardTap::getTarget(int target){
|
Targetable * WEventCardTap::getTarget(int target){
|
||||||
if (target) return card;
|
if (target) return card;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Targetable * WEventCardTappedForMana::getTarget(int target){
|
||||||
|
if (target) return card;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Targetable * WEventcardDraw::getTarget(Player * player){
|
||||||
|
if (player) return player;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& WEvent::toString(std::ostream& out) const
|
std::ostream& WEvent::toString(std::ostream& out) const
|
||||||
{
|
{
|
||||||
return out << "EVENT";
|
return out << "EVENT";
|
||||||
|
|||||||
Reference in New Issue
Block a user