diff --git a/projects/mtg/include/ActionLayer.h b/projects/mtg/include/ActionLayer.h index 8c066c3df..c47d9e5e2 100644 --- a/projects/mtg/include/ActionLayer.h +++ b/projects/mtg/include/ActionLayer.h @@ -44,7 +44,7 @@ public: int reactToTargetClick(ActionElement * ability, Targetable * card); int stillInUse(MTGCardInstance * card); void setMenuObject(Targetable * object, bool must = false); - void setCustomMenuObject(Targetable * object, bool must = false,vectorabilities = vector()); + void setCustomMenuObject(Targetable * object, bool must = false,vectorabilities = vector(),string customName = ""); void ButtonPressed(int controllerid, int controlid); void ButtonPressedOnMultipleChoice(int choice = -1); void doReactTo(int menuIndex); diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 3569a32fb..963c26ee9 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -1105,7 +1105,8 @@ public: MTGAbility * mClone; vectorabilities; Player * who; - MenuAbility(GameObserver* observer, int _id, Targetable * target, MTGCardInstance * _source, bool must = false, vectorabilities = vector(),Player * who = NULL); + string newNameString; + MenuAbility(GameObserver* observer, int _id, Targetable * target, MTGCardInstance * _source, bool must = false, vectorabilities = vector(),Player * who = NULL,string _newName = ""); void Update(float dt); int resolve(); const char * getMenuText(); @@ -1393,9 +1394,9 @@ class AADrawer: public ActivatedAbilityTP public: string nbcardsStr; - + bool noReplace; AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost,string nbcardsStr, int who = - TargetChooser::UNSET); + TargetChooser::UNSET,bool noReplace = false); int resolve(); const char * getMenuText(); AADrawer * clone() const; @@ -2622,7 +2623,14 @@ public: int resolve(); PairCard * clone() const; }; - +//pick a card to dredge +class dredgeCard: public InstantAbility +{ +public: + dredgeCard(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL); + int resolve(); + dredgeCard * clone() const; +}; /* create a parent child association between cards */ class AAConnect: public InstantAbility { @@ -4300,6 +4308,18 @@ public: }; +class ADrawReplacer: public MTGAbility +{ +public: + REDrawReplacement * re; + MTGAbility * replacer; + bool OtherPlayer; + ADrawReplacer(GameObserver* observer, int id, MTGCardInstance * source, MTGAbility * _replace = NULL,bool otherPlayer = false); + int addToGame(); + int destroy(); + ADrawReplacer * clone() const; + ~ADrawReplacer(); +}; /* Specific Classes */ diff --git a/projects/mtg/include/CardPrimitive.h b/projects/mtg/include/CardPrimitive.h index c64a48217..6bad49cee 100644 --- a/projects/mtg/include/CardPrimitive.h +++ b/projects/mtg/include/CardPrimitive.h @@ -66,6 +66,7 @@ public: int power; int toughness; int suspendedTime; + int dredgeAmount; vectortypes; CardPrimitive(); @@ -110,7 +111,7 @@ public: bool isCreature(); bool isLand(); bool isSpell(); - + int dredge(); void setPower(int _power); int getPower(); void setToughness(int _toughness); diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index 433dafa6b..dbf139514 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -99,6 +99,7 @@ public: int fresh; int MaxLevelUp; int kicked; + int dredge; bool isDualWielding; bool stillNeeded; Player * lastController; diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index f0daba0b9..d32d15037 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -272,6 +272,24 @@ public: virtual ostream& toString(ostream& out) const; virtual MTGSoulbondRule * clone() const; }; +/*dredge*/ +class MTGDredgeRule: public PermanentAbility, public ReplacementEffect +{ +public: + vectorsoulbonders; + TargetChooser * tcb; + MTGAbility * dredgeAbility; + MTGAbility * targetAbility; + MTGAbility * targetAbilityAdder; + MTGAbility * targetAbility1; + MTGAbility * mod; + MTGAbility * activateDredge; + vectorpairing; + MTGDredgeRule(GameObserver* observer, int _id); + WEvent * replace(WEvent *e); + virtual ostream& toString(ostream& out) const; + virtual MTGDredgeRule * clone() const; +}; /* Persist Rule */ class MTGPersistRule: public PermanentAbility { diff --git a/projects/mtg/include/ReplacementEffects.h b/projects/mtg/include/ReplacementEffects.h index 7a26caf9e..182bef26c 100644 --- a/projects/mtg/include/ReplacementEffects.h +++ b/projects/mtg/include/ReplacementEffects.h @@ -49,12 +49,22 @@ public: WEvent * replace(WEvent *e); ~RECountersPrevention(); }; - -class ReplacementEffects +class REDrawReplacement: public ReplacementEffect { protected: - list modifiers; + MTGAbility * source; + public: + Player * DrawerOfCard; + MTGAbility * replacementAbility; + REDrawReplacement(MTGAbility * _source, Player * Drawer = NULL, MTGAbility * replaceWith = NULL); + WEvent * replace(WEvent *e); + ~REDrawReplacement(); +}; +class ReplacementEffects +{ +public: + list modifiers; ReplacementEffects(); WEvent * replace(WEvent *e); int add(ReplacementEffect * re); diff --git a/projects/mtg/include/TargetChooser.h b/projects/mtg/include/TargetChooser.h index 5323ddaf4..184eea35f 100644 --- a/projects/mtg/include/TargetChooser.h +++ b/projects/mtg/include/TargetChooser.h @@ -298,6 +298,25 @@ public: virtual bool equals(TargetChooser * tc); }; +class dredgeChooser: public TypeTargetChooser +{ +public: + bool withoutProtections; + dredgeChooser(GameObserver *observer, int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false, bool targetMin = false) : + TypeTargetChooser(observer, "*|mygraveyard",_zones, _nbzones, card, _maxtargets, other, targetMin) + { + } + ; + dredgeChooser(GameObserver *observer, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false,bool targetMin = false) : + TypeTargetChooser(observer, "*|mygraveyard", card, _maxtargets, other,targetMin) + { + } + ; + virtual bool canTarget(Targetable * target, bool withoutProtections = false); + virtual dredgeChooser * clone() const; + virtual bool equals(TargetChooser * tc); +}; + class myCursesChooser: public TypeTargetChooser { public: diff --git a/projects/mtg/include/WEvent.h b/projects/mtg/include/WEvent.h index 6a680cd41..99695069f 100644 --- a/projects/mtg/include/WEvent.h +++ b/projects/mtg/include/WEvent.h @@ -12,6 +12,8 @@ class Targetable; class ManaPool; class AACounter; class Counters; +class MTGAbility; +class DrawAction; class WEvent { public: @@ -221,7 +223,13 @@ struct WEventcardDraw : public WEvent { int nb_cards; virtual Targetable * getTarget(Player * player); }; - +//event for a card draw ability resolving +struct WEventDraw : public WEvent { + WEventDraw(Player * player,int nb_cards,MTGAbility * drawer); + Player * player; + int nb_cards; + MTGAbility * drawAbility; +}; //Event when a blocker is reordered //exchangeWith: exchange card's position with exchangeWith's position //attacker:both card and exchangeWith *should* be in attacker's "blockers" list. diff --git a/projects/mtg/src/AIPlayerBaka.cpp b/projects/mtg/src/AIPlayerBaka.cpp index 6e1a7315e..1d3d69332 100644 --- a/projects/mtg/src/AIPlayerBaka.cpp +++ b/projects/mtg/src/AIPlayerBaka.cpp @@ -602,7 +602,7 @@ int OrderedAIAction::getEfficiency() if (!efficiency && may) { AIPlayer * chk = (AIPlayer*)p; - if(may->ability->getActionTc() && chk->chooseTarget(may->ability->getActionTc(),NULL,NULL,true)) + if(may->ability && may->ability->getActionTc() && chk->chooseTarget(may->ability->getActionTc(),NULL,NULL,true)) efficiency = 50 + (owner->getRandomGenerator()->random() % 50); } if (p->game->hand->nb_cards == 0) diff --git a/projects/mtg/src/ActionLayer.cpp b/projects/mtg/src/ActionLayer.cpp index 64e218cf1..3efc2106a 100644 --- a/projects/mtg/src/ActionLayer.cpp +++ b/projects/mtg/src/ActionLayer.cpp @@ -415,7 +415,7 @@ void ActionLayer::setMenuObject(Targetable * object, bool must) modal = 1; } -void ActionLayer::setCustomMenuObject(Targetable * object, bool must,vectorabilities) +void ActionLayer::setCustomMenuObject(Targetable * object, bool must,vectorabilities,string customName) { if (!object) { @@ -424,7 +424,7 @@ void ActionLayer::setCustomMenuObject(Targetable * object, bool must,vectorgetInput(), 10, this, Fonts::MAIN_FONT, 100, 100, object->getDisplayName().c_str()); + abilitiesMenu = NEW SimpleMenu(observer->getInput(), 10, this, Fonts::MAIN_FONT, 100, 100, customName.size()?customName.c_str():object->getDisplayName().c_str()); currentActionCard = NULL; abilitiesMenu->isMultipleChoice = false; if(abilities.size()) diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index 0be3b2105..73b504bd4 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -467,7 +467,7 @@ int DrawAction::resolve() { for (int i = 0; i < nbcards; i++) { - player->game->drawFromLibrary(); + player->game->drawFromLibrary(); } return 1; } diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 8c0563b3c..92a66351e 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -581,7 +581,7 @@ ACounterShroud::~ACounterShroud() SAFE_DELETE(counter); } -//shield a card from a certain type of counter. +//track counters placed on a card ACounterTracker::ACounterTracker(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, string scounter) : MTGAbility(observer, id, source, target),scounter(scounter) { @@ -1112,6 +1112,47 @@ AASetCoin::~AASetCoin() { } + +//replace drawing a card with activation of an ability +ADrawReplacer::ADrawReplacer(GameObserver* observer, int id, MTGCardInstance * source, MTGAbility * replace, bool otherPlayer) : +MTGAbility(observer, id, source),re(NULL),replacer(replace),OtherPlayer(otherPlayer) +{ +} + +int ADrawReplacer::addToGame() +{ + SAFE_DELETE(re); + if(OtherPlayer) + re = NEW REDrawReplacement(this,source->controller()->opponent(),replacer); + else + re = NEW REDrawReplacement(this,source->controller(),replacer); + if (re) + { + game->replacementEffects->add(re); + return MTGAbility::addToGame(); + } + return 0; +} + +int ADrawReplacer::destroy() +{ + game->replacementEffects->remove(re); + SAFE_DELETE(re); + return 1; +} + +ADrawReplacer * ADrawReplacer::clone() const +{ + ADrawReplacer * a = NEW ADrawReplacer(*this); + a->re = NULL; + return a; +} + +ADrawReplacer::~ADrawReplacer() +{ + SAFE_DELETE(re); + SAFE_DELETE(replacer); +} //Reset Damage on creatures AAResetDamage::AAResetDamage(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target, ManaCost * cost): ActivatedAbility(observer, id, source, cost, 0) @@ -1394,8 +1435,8 @@ AADiscardCard::~AADiscardCard() SAFE_DELETE(andAbility); } AADrawer::AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost, string nbcardsStr, - int who) : - ActivatedAbilityTP(observer, _id, card, _target, _cost, who), nbcardsStr(nbcardsStr) + int who, bool noreplace) : + ActivatedAbilityTP(observer, _id, card, _target, _cost, who), nbcardsStr(nbcardsStr),noReplace(noreplace) { aType = MTGAbility::STANDARD_DRAW; } @@ -1403,17 +1444,24 @@ AADrawer::AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targ int AADrawer::resolve() { Player * player = getPlayerFromTarget(getTarget()); - + if (player) { WParsedInt numCards(nbcardsStr, NULL, source); - game->mLayers->stackLayer()->addDraw(player, numCards.getValue()); - game->mLayers->stackLayer()->resolve(); - for(int i = numCards.getValue(); i > 0;i--) + WEvent * e = NEW WEventDraw(player, numCards.getValue(),this); + if(!noReplace) + e = game->replacementEffects->replace(e); + if(e) { + game->mLayers->stackLayer()->addDraw(player, numCards.getValue()); + game->mLayers->stackLayer()->resolve(); + for(int i = numCards.getValue(); i > 0;i--) + { WEvent * e = NEW WEventcardDraw(player, 1); game->receiveEvent(e); + } } + SAFE_DELETE(e); } return 1; } @@ -3116,8 +3164,8 @@ MayAbility::~MayAbility() //Menu building ability Abilities //this will eventaully handle choosen discards/sacrifices. -MenuAbility::MenuAbility(GameObserver* observer, int _id, Targetable * mtarget, MTGCardInstance * _source, bool must,vectorabilities,Player * who) : -MayAbility(observer, _id,NULL,_source,must), must(must),abilities(abilities),who(who) +MenuAbility::MenuAbility(GameObserver* observer, int _id, Targetable * mtarget, MTGCardInstance * _source, bool must,vectorabilities,Player * who, string newName) : +MayAbility(observer, _id,NULL,_source,must), must(must),abilities(abilities),who(who),newNameString(newName) { triggered = 0; mClone = NULL; @@ -3129,7 +3177,7 @@ void MenuAbility::Update(float dt) { MTGAbility::Update(dt); ActionLayer * object = game->mLayers->actionLayer(); - if (!triggered && !object->menuObject) + if (!triggered && !object->menuObject && !object->getCurrentTargetChooser()) { triggered = 1; @@ -3146,7 +3194,7 @@ void MenuAbility::Update(float dt) } if(triggered) { - game->mLayers->actionLayer()->setCustomMenuObject(source, must,abilities); + game->mLayers->actionLayer()->setCustomMenuObject(source, must,abilities,newNameString.size()?newNameString.c_str():""); previousInterrupter = game->isInterrupting; game->mLayers->stackLayer()->setIsInterrupting(source->controller(), false); } @@ -3239,10 +3287,13 @@ MenuAbility::~MenuAbility() { for(int i = 0;i < int(abilities.size());i++) { - AASetColorChosen * chooseA = dynamic_cast(abilities[i]); - if(chooseA && chooseA->abilityAltered) - SAFE_DELETE(chooseA->abilityAltered); - SAFE_DELETE(abilities[i]); + if(abilities[i]) + { + AASetColorChosen * chooseA = dynamic_cast(abilities[i]); + if(chooseA && chooseA->abilityAltered) + SAFE_DELETE(chooseA->abilityAltered); + SAFE_DELETE(abilities[i]); + } } } else @@ -4897,7 +4948,35 @@ PairCard * PairCard::clone() const { return NEW PairCard(*this); } +//target is dredged +dredgeCard::dredgeCard(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost) : +InstantAbility(observer, id, card, target) +{ + target = _target; + oneShot = true; + forceDestroy = 1; +} +int dredgeCard::resolve() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if(_target) + { + for(int j = 0; j < _target->data->dredge();j++) + { + _target->controller()->game->putInZone( + _target->controller()->game->library->cards[_target->controller()->game->library->nb_cards - 1], + _target->controller()->game->library, _target->controller()->game->graveyard); + } + _target->controller()->game->putInZone(_target,_target->currentZone,_target->controller()->game->hand); + } + return 1; +} + +dredgeCard * dredgeCard::clone() const +{ + return NEW dredgeCard(*this); +} // target becomes a parent of card(source) AAConnect::AAConnect(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost) : diff --git a/projects/mtg/src/CardPrimitive.cpp b/projects/mtg/src/CardPrimitive.cpp index acbf59fab..bce13789f 100644 --- a/projects/mtg/src/CardPrimitive.cpp +++ b/projects/mtg/src/CardPrimitive.cpp @@ -58,6 +58,7 @@ CardPrimitive::CardPrimitive(CardPrimitive * source) toughness = source->toughness; restrictions = source->restrictions ? source->restrictions->clone() : NULL; suspendedTime = source->suspendedTime; + dredgeAmount = source->dredgeAmount; magicText = source->magicText; for (map::const_iterator it = source->magicTexts.begin(); it != source->magicTexts.end(); ++it) @@ -82,6 +83,7 @@ int CardPrimitive::init() spellTargetType = ""; alias = 0; restrictions = NULL; + dredgeAmount = 0; return 1; } @@ -100,6 +102,11 @@ bool CardPrimitive::isSpell() return (!isCreature() && !isLand()); } +int CardPrimitive::dredge() +{ + return dredgeAmount; +} + void CardPrimitive::setRestrictions(string _restriction) { if (!restrictions) diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index d42612f46..8cf728b13 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -961,13 +961,20 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG observer->addObserver(NEW MTGBlockRule(observer, -1)); return NULL; } - //this rule handles blocking ability during blocker phase + //this rule handles cards that have soulbond found = s.find("soulbondrule"); if(found != string::npos) { observer->addObserver(NEW MTGSoulbondRule(observer, -1)); return NULL; } + //this rule handles cards that have dredge + found = s.find("dredgerule"); + if(found != string::npos) + { + observer->replacementEffects->add(NEW MTGDredgeRule(observer, -1)); + return NULL; + } //this rule handles combat related triggers. note, combat related triggered abilities will not work without it. found = s.find("combattriggerrule"); if(found != string::npos) @@ -1700,6 +1707,30 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return NULL; } + //opponent replace draw with + found = s.find("opponentreplacedraw "); + if (found != string::npos) + { + string s1 = s.substr(found + 19); + MTGAbility * a = NULL; + a = parseMagicLine(s1, id, spell, card, false, activated); + if(a) + return NEW ADrawReplacer(observer,id, card,a,true); + return NULL; + } + + //replace draw with + found = s.find("replacedraw "); + if (found != string::npos) + { + string s1 = s.substr(found + 11); + MTGAbility * a = NULL; + a = parseMagicLine(s1, id, spell, card, false, activated); + if(a) + return NEW ADrawReplacer(observer,id, card,a); + return NULL; + } + if (!activated && tc) { MTGAbility * a = parseMagicLine(sWithoutTc, id, spell, card); @@ -1870,9 +1901,19 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG { if (storedAbilityString.size()) { + vector splitName = parseBetween(storedAbilityString, "name(", ")"); + if (splitName.size()) + { + newName = splitName[1]; + storedAbilityString = splitName[0]; + storedAbilityString.append(splitName[2]); + //we erase the name section from the string to avoid + //accidently building an mtg ability with the text meant for menuText. + } ATargetedAbilityCreator * abl = NEW ATargetedAbilityCreator(observer, id, card,target, NULL,newName, storedAbilityString, who); abl->oneShot = 1; storedString.clear(); + storedAbilityString.clear(); return abl; } } @@ -2228,7 +2269,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG if (splitDraw.size()) { Targetable * t = spell ? spell->getNextTarget() : NULL; - MTGAbility * a = NEW AADrawer(observer, id, card, t, NULL,splitDraw[1], who); + MTGAbility * a = NEW AADrawer(observer, id, card, t, NULL,splitDraw[1], who,s.find("noreplace") != string::npos); a->oneShot = 1; return a; } diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 7e5c23ebc..1e559236d 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -163,6 +163,7 @@ void MTGCardInstance::initMTGCI() mPropertiesChangedSinceLastUpdate = false; stillNeeded = true; kicked = 0; + dredge = 0; chooseacolor = -1; chooseasubtype = ""; coinSide = -1; diff --git a/projects/mtg/src/MTGDeck.cpp b/projects/mtg/src/MTGDeck.cpp index 992d99dc8..e81ff4223 100644 --- a/projects/mtg/src/MTGDeck.cpp +++ b/projects/mtg/src/MTGDeck.cpp @@ -119,7 +119,17 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi } } break; + case 'd'://dredge + if (!primitive) primitive = NEW CardPrimitive(); + { + string value = val; + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + vector values = parseBetween(value,"dredge(",")"); + if(values.size()) + primitive->dredgeAmount = atoi(values[1].c_str()); + break; + } case 'f': //flashback//morph { if (!primitive) primitive = NEW CardPrimitive(); diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 7b63e10a2..9d4a75d6f 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -2098,7 +2098,107 @@ MTGSoulbondRule * MTGSoulbondRule::clone() const { return NEW MTGSoulbondRule(*this); } +/*dredge*/ +MTGDredgeRule::MTGDredgeRule(GameObserver* observer, int _id) : +PermanentAbility(observer, _id) +{ + tcb = NULL; + dredgeAbility = NULL; + targetAbility = NULL; + mod = NULL; +} +; +WEvent * MTGDredgeRule::replace(WEvent * event) +{ + WEventDraw * e = dynamic_cast (event); + if (e) + { + MTGCardInstance * card = NULL; + if(e->player->game->library->nb_cards) + card = e->player->game->library->cards[e->player->game->library->nb_cards-1]; + if(!card) + return event; + TargetChooserFactory tf(e->player->getObserver()); + tcb = tf.createTargetChooser("dredgeable",card); + tcb->targetter = NULL; + if(!tcb->validTargetsExist()) + { + SAFE_DELETE(tcb); + return event; + } + SAFE_DELETE(tcb); + for (int i = 0; i < 2; i++) + { + Player * p = game->players[i]; + if (e->player == p) + { + for(int draw = 0;draw < e->nb_cards;draw++) + { + tcb = tf.createTargetChooser("dredgeable",card); + tcb->targetter = NULL; + + vectorselection; + //look for other draw replacement effects + list::iterator it; + for (it = game->replacementEffects->modifiers.begin(); it != game->replacementEffects->modifiers.end(); it++) + { + ReplacementEffect *re = *it; + if(REDrawReplacement * DR = dynamic_cast(*it)) + { + MTGAbility * otherA = NULL; + if(DR->DrawerOfCard == p) + if(DR->replacementAbility->oneShot) + selection.push_back(DR->replacementAbility->clone()); + else + { + otherA = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(),DR->replacementAbility->source,NULL,DR->replacementAbility->clone()); + selection.push_back(otherA); + } + } + } + + //there is a memleak here that i have no idea what causes it. + dredgeAbility = NEW dredgeCard(game, game->mLayers->actionLayer()->getMaxId(), card,NULL); + dredgeAbility->oneShot = true; + targetAbility = NEW GenericTargetAbility(game, "Dredge A Card","",game->mLayers->actionLayer()->getMaxId(), card,tcb->clone(),dredgeAbility->clone()); + targetAbility->oneShot = true; + SAFE_DELETE(dredgeAbility); + + targetAbilityAdder = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), card,NULL,targetAbility->clone()); + targetAbilityAdder->oneShot = true; + SAFE_DELETE(targetAbility); + MTGAbility * setDredge = targetAbilityAdder->clone(); + SAFE_DELETE(targetAbilityAdder); + setDredge->oneShot = true; + + selection.push_back(setDredge); + targetAbility1 = NEW AADrawer(game, this->GetId(), card,card,NULL, "1",TargetChooser::CONTROLLER,true); + selection.push_back(targetAbility1); + MTGAbility * menuChoice = NEW MenuAbility(game, this->GetId(), card, card,true,selection,card->controller(),"Dredge or Draw"); + + menuChoice->addToGame(); + SAFE_DELETE(tcb); + } + + SAFE_DELETE(event); + return event; + } + } + } + return event; +} + +ostream& MTGDredgeRule::toString(ostream& out) const +{ + out << "MTGDredgeRule ::: ("; + return MTGAbility::toString(out) << ")"; +} + +MTGDredgeRule * MTGDredgeRule::clone() const +{ + return NEW MTGDredgeRule(*this); +} /* Persist */ MTGPersistRule::MTGPersistRule(GameObserver* observer, int _id) : PermanentAbility(observer, _id) diff --git a/projects/mtg/src/ReplacementEffects.cpp b/projects/mtg/src/ReplacementEffects.cpp index 0a762e87a..ad9179df1 100644 --- a/projects/mtg/src/ReplacementEffects.cpp +++ b/projects/mtg/src/ReplacementEffects.cpp @@ -77,6 +77,81 @@ RECountersPrevention::~RECountersPrevention() { SAFE_DELETE(TargetingCards); } +////--draw replacement--------------------- +REDrawReplacement::REDrawReplacement(MTGAbility * source, Player * Drawer, MTGAbility * replaceWith) : + source(source), DrawerOfCard(Drawer),replacementAbility(replaceWith) +{ +} + +WEvent * REDrawReplacement::replace(WEvent *event) +{ + if (!event) return event; + WEventDraw * e = dynamic_cast (event); + if (!e) return event; + if (DrawerOfCard != e->player) return event; + if(!replacementAbility) return event; + //check for dredge + TargetChooserFactory tf(e->player->getObserver()); + TargetChooser * tcb = NULL; + tcb = tf.createTargetChooser("dredgeable",source->source); + tcb->targetter = NULL; + if(tcb->validTargetsExist()) + { + if(e->player == DrawerOfCard && e->player == source->source->controller()) + { + SAFE_DELETE(tcb); + return event; + } + } + SAFE_DELETE(tcb); + + vectorselection; + //look for other draw replacement effects + list::iterator it; + GameObserver * game = source->source->getObserver(); + if(replacementAbility->source->controller() == DrawerOfCard) + for (it = game->replacementEffects->modifiers.begin(); it != game->replacementEffects->modifiers.end(); it++) + { + ReplacementEffect *re = *it; + if(REDrawReplacement * DR = dynamic_cast(*it)) + { + MTGAbility * otherA = NULL; + if(DR->DrawerOfCard == e->player) + if(DR->replacementAbility->oneShot) + selection.push_back(DR->replacementAbility->clone()); + else + { + otherA = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), source->source,NULL,DR->replacementAbility->clone()); + selection.push_back(otherA); + } + } + } + + + for(int j = 0; j < e->nb_cards; j++) + { + if(e->player != DrawerOfCard || selection.size() < 2) + { + MTGAbility * toResolve = replacementAbility->clone(); + if(replacementAbility->oneShot) + toResolve->resolve(); + else + toResolve->addToGame(); + } + else + { + MTGAbility * menuChoice = NEW MenuAbility(game, 1, source->source, source->source,true,selection,NULL,"Choose Draw Replacement"); + menuChoice->addToGame(); + } + } + + delete event; + event = NULL; + return event; +} +REDrawReplacement::~REDrawReplacement() +{ +} ////////////////////////////////////////////// ReplacementEffects::ReplacementEffects() { diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 536402a32..6bb489efc 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -32,6 +32,14 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta return NEW pairableChooser(observer, card, maxtargets); } + found = s.find("dredgeable"); + if (found != string::npos) + { + int maxtargets = 1; + zones[nbzones++] = MTGGameZone::MY_GRAVEYARD; + return NEW dredgeChooser(observer,zones,nbzones, card, maxtargets); + } + found = s.find("mytgt"); if (found == 0) { @@ -1601,6 +1609,35 @@ bool pairableChooser::equals(TargetChooser * tc) return TypeTargetChooser::equals(tc); } +//*Dredge targetchooser*// +bool dredgeChooser::canTarget(Targetable * target,bool withoutProtections) +{ + if (MTGCardInstance * card = dynamic_cast(target)) + { + if((card->data->dredgeAmount < 1) || (card->data->dredgeAmount > card->controller()->game->library->nb_cards)) + return false; + if(card->currentZone == card->controller()->game->graveyard) + return true; + } + return false; +} + +dredgeChooser* dredgeChooser::clone() const +{ + dredgeChooser * a = NEW dredgeChooser(*this); + return a; +} + +bool dredgeChooser::equals(TargetChooser * tc) +{ + + dredgeChooser * dtc = dynamic_cast (tc); + if (!dtc) + return false; + + return TypeTargetChooser::equals(tc); +} +//----------- //----------- /*Proliferate Target */ bool ProliferateChooser::canTarget(Targetable * target,bool withoutProtections) diff --git a/projects/mtg/src/WEvent.cpp b/projects/mtg/src/WEvent.cpp index 33ea9943e..b125dc1ee 100644 --- a/projects/mtg/src/WEvent.cpp +++ b/projects/mtg/src/WEvent.cpp @@ -91,6 +91,11 @@ WEventCardBlocked::WEventCardBlocked(MTGCardInstance * card,MTGCardInstance * op WEventcardDraw::WEventcardDraw(Player * player, int nb_cards) : player(player), nb_cards(nb_cards) { +} + + WEventDraw::WEventDraw(Player * player, int nb_cards,MTGAbility * cardDraw) ://happens at the call for drawfromlibrary +player(player), nb_cards(nb_cards),drawAbility(cardDraw) +{ } WEventCardSacrifice::WEventCardSacrifice(MTGCardInstance * card, MTGCardInstance * after) :