diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 94cc59ae6..8cb2fdacc 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -1868,7 +1868,52 @@ public: } }; +//cant be the blocker of targetchooser +//Can't be blocked by... +class ACantBeBlockerOf: public MTGAbility +{ +public: + TargetChooser * fromTc; + bool thisCard; + ACantBeBlockerOf(GameObserver* observer, int id, MTGCardInstance * _source, MTGCardInstance * _target, TargetChooser *fromTc,bool aThis) : + MTGAbility(observer, id, _source, _target), fromTc(fromTc),thisCard(aThis) + { + } + + int addToGame() + { + MTGCardInstance * _target = (MTGCardInstance *) target; + if(!thisCard) + _target->addCantBeBlockerOf(fromTc); + else + _target->addCantBeBlockerOfCard((MTGCardInstance*)source); + return MTGAbility::addToGame(); + } + + int destroy() + { + if(!thisCard) + ((MTGCardInstance *) target)->removeCantBeBlockerOf(fromTc); + else + ((MTGCardInstance *) target)->removeCantBeBlockerOfCard((MTGCardInstance*)source); + return 1; + } + + ACantBeBlockerOf * clone() const + { + ACantBeBlockerOf * a = NEW ACantBeBlockerOf(*this); + if(fromTc) + a->fromTc = fromTc->clone(); + return a; + } + + ~ACantBeBlockerOf() + { + SAFE_DELETE(fromTc); + } + +}; //Alteration of Power and Toughness (enchantments) class APowerToughnessModifier: public MTGAbility { @@ -2415,7 +2460,10 @@ public: int canBeInList(MTGCardInstance * card) { if(card->isPhased || source->isPhased) + { + removed(card); return 0; + } if ((includeSelf || card != source) && tc->canTarget(card)) return 1; return 0; @@ -3975,6 +4023,7 @@ MTGCardInstance * manaReducer; int type; AAlterCost(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, int amount, int type); int addToGame(); + int destroy(); int testDestroy(); void refreshCost(MTGCardInstance * card = NULL); void increaseTheCost(MTGCardInstance * card = NULL); @@ -5413,7 +5462,7 @@ public: } }; -//Bushido ability +//Bushido ability todo:add bushido count. class ABushidoAbility: public MTGAbility { public: diff --git a/projects/mtg/include/GameObserver.h b/projects/mtg/include/GameObserver.h index 41314108d..4447aacc2 100644 --- a/projects/mtg/include/GameObserver.h +++ b/projects/mtg/include/GameObserver.h @@ -119,6 +119,7 @@ class GameObserver{ Player * currentlyActing(); GameObserver(WResourceManager* output = 0, JGE* input = 0); virtual ~GameObserver(); + int waitingGameStateCheck; void gameStateBasedEffects(); void enchantmentStatus(); void Affinity(); diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index dbf139514..0b2d7fdf5 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -193,9 +193,17 @@ public: int CantBeTargetby(MTGCardInstance * card); vectorcantBeBlockedBys; + vectorcantBeBlockerOfs; + vectorcantBeBlockerOfCards; int addCantBeBlockedBy(TargetChooser * tc); int removeCantBeBlockedBy(TargetChooser *tc, int erase = 0); int cantBeBlockedBy(MTGCardInstance * card); + int addCantBeBlockerOf(TargetChooser * tc); + int removeCantBeBlockerOf(TargetChooser *tc, int erase = 0); + int cantBeBlockerOf(MTGCardInstance * card); + int addCantBeBlockerOfCard(MTGCardInstance * card); + int removeCantBeBlockerOfCard(MTGCardInstance * card, int erase = 0); + int cantBeBlockerOfCard(MTGCardInstance * card); void copy(MTGCardInstance * card); diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 0c346bdae..375e28585 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -3566,6 +3566,26 @@ int AAlterCost::addToGame() return MTGAbility::addToGame(); } +int AAlterCost::destroy() +{ + MTGCardInstance * _target = (MTGCardInstance *)target; + if(!this->manaReducer->isInPlay(game)) + { + if (amount > 0) + { + _target->getIncreasedManaCost()->remove(type,amount); + refreshCost(_target);//special case for 0 cost. + } + else + { + _target->getReducedManaCost()->remove(type,abs(amount)); + refreshCost(_target);//special case for 0 cost. + } + return MTGAbility::testDestroy(); + } + return 0; +} + int AAlterCost::testDestroy() { MTGCardInstance * _target = (MTGCardInstance *)target; diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index 1a7d9b000..e718eafab 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -103,6 +103,7 @@ GameObserver::GameObserver(WResourceManager *output, JGE* input) mLayers = NULL; mTrash = new Trash(); mDeckManager = new DeckManager(); + waitingGameStateCheck = 0; } GamePhase GameObserver::getCurrentGamePhase() @@ -581,7 +582,13 @@ void GameObserver::gameStateBasedEffects() { if(getCurrentTargetChooser() && int(getCurrentTargetChooser()->getNbTargets()) == getCurrentTargetChooser()->maxtargets) getCurrentTargetChooser()->done = true; - if (mLayers->stackLayer()->count(0, NOT_RESOLVED) <= 50) + waitingGameStateCheck++; + if(waitingGameStateCheck > 50) + { + waitingGameStateCheck++; + waitingGameStateCheck--; + } + if(waitingGameStateCheck > 50) { //if there are more than 50 unresolved actions on the stack, lets allow a gameStates update //to make sure we are not caught up in a loop, example :Exquisite Blood + Sanguine Bond @@ -592,6 +599,7 @@ void GameObserver::gameStateBasedEffects() if (getCurrentTargetChooser() || mLayers->actionLayer()->isWaitingForAnswer()) return; } + waitingGameStateCheck = 0; //////////////////////// //---apply damage-----// //after combat effects// diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index f1d0416eb..1d928c349 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -2760,7 +2760,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return NULL; //TODO } - //Can't be blocked by... + //Can't be blocked by...need cantdefendagainst( vector splitCantBlock = parseBetween(s, "cantbeblockedby(", ")"); if (splitCantBlock.size()) { @@ -2779,7 +2779,29 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG } return NULL; //TODO } + + //cant be the blocker of targetchooser. + vector splitCantBeBlock = parseBetween(s, "cantbeblockeof(", ")"); + if (splitCantBeBlock.size()) + { + TargetChooserFactory tcf(observer); + TargetChooser * fromTc = NULL; + if (splitCantBeBlock[1].find("this") == string::npos) + { + fromTc = tcf.createTargetChooser(splitCantBeBlock[1], card); + } + if (!activated) + { + if(fromTc) + return NEW ACantBeBlockerOf(observer, id, card, target, fromTc, false);//of a targetchooser + else + return NEW ACantBeBlockerOf(observer, id, card, target, fromTc, true);//blocker of the card source. + } + return NULL; + } + + //affinity based on targetchooser vector splitNewAffinity = parseBetween(s, "affinity(", ")"); if (splitNewAffinity.size()) @@ -4835,8 +4857,8 @@ void ListMaintainerAbility::updateTargets() for (int i = 0; i < 2; i++) { Player * p = game->players[i]; - MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library }; - for (int k = 0; k < 4; k++) + MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack }; + for (int k = 0; k < 5; k++) { MTGGameZone * zone = zones[k]; if (canTarget(zone)) @@ -4907,8 +4929,8 @@ void ListMaintainerAbility::checkTargets() for (int i = 0; i < 2; i++) { Player * p = game->players[i]; - MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library }; - for (int k = 0; k < 4; k++) + MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack }; + for (int k = 0; k < 5; k++) { MTGGameZone * zone = zones[k]; if (canTarget(zone)) diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index a50a1dab8..75ee1b4dc 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -301,7 +301,7 @@ int MTGCardInstance::isInPlay(GameObserver* game) for (int i = 0; i < 2; i++) { MTGGameZone * zone = game->players[i]->game->inPlay; - if (zone->hasCard(this)) + if (zone->hasCard(this) && !isPhased) return 1; } return 0; @@ -609,6 +609,10 @@ int MTGCardInstance::canBlock(MTGCardInstance * opponent) return 0; if (opponent->cantBeBlockedBy(this)) return 0; + if (this->cantBeBlockerOf(opponent)) + return 0; + if (this->cantBeBlockerOfCard(opponent)) + return 0; if (opponent->basicAbilities[(int)Constants::UNBLOCKABLE]) return 0; if (opponent->basicAbilities[(int)Constants::ONEBLOCKER] && opponent->blocked) @@ -1044,7 +1048,69 @@ int MTGCardInstance::cantBeBlockedBy(MTGCardInstance * card) } return 0; } +//cant be the block of +int MTGCardInstance::addCantBeBlockerOf(TargetChooser * tc) +{ + cantBeBlockerOfs.push_back(tc); + return cantBeBlockerOfs.size(); +} +int MTGCardInstance::removeCantBeBlockerOf(TargetChooser * tc, int erase) +{ + for (size_t i = 0; i < cantBeBlockerOfs.size(); i++) + { + if (cantBeBlockerOfs[i] == tc) + { + if (erase) + delete (cantBeBlockerOfs[i]); + cantBeBlockerOfs.erase(cantBeBlockerOfs.begin() + i); + return 1; + } + } + return 0; +} + +int MTGCardInstance::cantBeBlockerOf(MTGCardInstance * card) +{ + for (size_t i = 0; i < cantBeBlockerOfs.size(); i++) + { + if (cantBeBlockerOfs[i]->canTarget(card)) + return 1; + } + return 0; +} + +//cant be the block of +int MTGCardInstance::addCantBeBlockerOfCard(MTGCardInstance * card) +{ + cantBeBlockerOfCards.push_back(card); + return cantBeBlockerOfCards.size(); +} + +int MTGCardInstance::removeCantBeBlockerOfCard(MTGCardInstance * card, int erase) +{ + for (size_t i = 0; i < cantBeBlockerOfCards.size(); i++) + { + if (cantBeBlockerOfCards[i] == card) + { + if (erase) + delete (cantBeBlockerOfCards[i]); + cantBeBlockerOfCards.erase(cantBeBlockerOfCards.begin() + i); + return 1; + } + } + return 0; +} + +int MTGCardInstance::cantBeBlockerOfCard(MTGCardInstance * card) +{ + for (size_t i = 0; i < cantBeBlockerOfCards.size(); i++) + { + if (cantBeBlockerOfCards[i] == card) + return 1; + } + return 0; +} /* Choose a sound sample to associate to that card */ const string& MTGCardInstance::getSample() {