diff --git a/projects/mtg/include/ActionStack.h b/projects/mtg/include/ActionStack.h index bfc3714aa..80b1ebdb6 100644 --- a/projects/mtg/include/ActionStack.h +++ b/projects/mtg/include/ActionStack.h @@ -92,6 +92,7 @@ class Spell: public Interruptible { bool AlternativeWasPaid(); bool BuyBackWasPaid(); bool FlashBackWasPaid(); + bool RetraceWasPaid(); const string getDisplayName() const; virtual ostream& toString(ostream& out) const; MTGCardInstance * getNextCardTarget(MTGCardInstance * previous = 0); diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 6606757ad..857c90d92 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -2409,7 +2409,6 @@ class AAFrozen:public ActivatedAbility{ return a; } }; - // 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... class ALifeZoneLink:public MTGAbility{ @@ -2636,11 +2635,25 @@ public: MTGCardInstance * _target = (MTGCardInstance *)target; amount; type; - _target->getManaCost()->add(type,amount); + if(amount < 0){ + //amount = amount * -1; + amount = abs(amount); + if(_target->getManaCost()->hasColor(type)){ + if(_target->getManaCost()->getConvertedCost() >= 1){ + _target->getManaCost()->remove(type,amount); + if(_target->getManaCost()->alternative > 0){ + _target->getManaCost()->alternative->remove(type,amount);} + if(_target->getManaCost()->BuyBack > 0){ + _target->getManaCost()->BuyBack->remove(type,amount);} + } + } + }else{ + _target->getManaCost()->add(type,amount); if(_target->getManaCost()->alternative > 0){ _target->getManaCost()->alternative->add(type,amount);} if(_target->getManaCost()->BuyBack > 0){ _target->getManaCost()->BuyBack->add(type,amount);} + } return MTGAbility::addToGame(); } AManaRedux * clone() const{ diff --git a/projects/mtg/include/ExtraCost.h b/projects/mtg/include/ExtraCost.h index 9a27ffb35..17c8f621f 100644 --- a/projects/mtg/include/ExtraCost.h +++ b/projects/mtg/include/ExtraCost.h @@ -81,6 +81,45 @@ public: virtual int setSource(MTGCardInstance * _source); virtual DiscardRandomCost * clone() const; }; +//tolibrary cost +class ToLibraryCost: public ExtraCost{ +public: + MTGCardInstance * target; + ToLibraryCost(TargetChooser *_tc = NULL); + virtual int setPayment(MTGCardInstance * card); + virtual int isPaymentSet(); + virtual int canPay(); + virtual int doPay(); + virtual void Render(); + virtual int setSource(MTGCardInstance * _source); + virtual ToLibraryCost * clone() const; +}; +//Millyourself cost +class MillCost: public ExtraCost{ +public: + MTGCardInstance * target; + MillCost(TargetChooser *_tc = NULL); + virtual int setPayment(MTGCardInstance * card); + virtual int isPaymentSet(); + virtual int canPay(); + virtual int doPay(); + virtual void Render(); + virtual int setSource(MTGCardInstance * _source); + virtual MillCost * clone() const; +}; +//Mill to exile yourself cost +class MillExileCost: public ExtraCost{ +public: + MTGCardInstance * target; + MillExileCost(TargetChooser *_tc = NULL); + virtual int setPayment(MTGCardInstance * card); + virtual int isPaymentSet(); + virtual int canPay(); + virtual int doPay(); + virtual void Render(); + virtual int setSource(MTGCardInstance * _source); + virtual MillExileCost * clone() const; +}; //tap other cost class TapTargetCost: public ExtraCost{ public: diff --git a/projects/mtg/include/MTGAbility.h b/projects/mtg/include/MTGAbility.h index a96cabfa0..48c060d0a 100644 --- a/projects/mtg/include/MTGAbility.h +++ b/projects/mtg/include/MTGAbility.h @@ -52,6 +52,7 @@ class MTGAbility: public ActionElement{ ManaCost * alternative; ManaCost * BuyBack; ManaCost * FlashBack; + ManaCost * Retrace; Targetable * target; int aType; @@ -87,6 +88,7 @@ class MTGAbility: public ActionElement{ ALTERNATIVE_COST = 8, BUYBACK_COST = 9, FLASHBACK_COST = 10, + RETRACE_COST = 11, }; }; diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index f6ca2877a..d833aa2f8 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -49,6 +49,7 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable { int flashedback; int paymenttype; int frozen; + int reduxamount; int regenerateTokens; int isToken; int stillInUse(); diff --git a/projects/mtg/include/MTGGameZones.h b/projects/mtg/include/MTGGameZones.h index 20992094d..a38df039f 100644 --- a/projects/mtg/include/MTGGameZones.h +++ b/projects/mtg/include/MTGGameZones.h @@ -161,6 +161,7 @@ class MTGPlayerCards { void initDeck(MTGDeck * deck); MTGCardInstance * putInGraveyard(MTGCardInstance * card); MTGCardInstance * putInExile(MTGCardInstance * card); + MTGCardInstance * putInLibrary(MTGCardInstance * card); MTGCardInstance * putInHand(MTGCardInstance * card); MTGCardInstance * putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGameZone * to); int isInPlay(MTGCardInstance * card); diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index 61e09ba4c..879e1a906 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -61,6 +61,17 @@ class MTGFlashBackRule:public MTGAbility{ virtual MTGFlashBackRule * clone() const; }; +class MTGRetraceRule:public MTGAbility{ + public: + int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); + int reactToClick(MTGCardInstance * card); + int testDestroy(); + virtual ostream& toString(ostream& out) const; + MTGRetraceRule(int _id); + const char * getMenuText(){return "Retrace";} + virtual MTGRetraceRule * clone() const; +}; + class MTGAttackRule:public MTGAbility, public Limitor{ public: virtual bool select(Target*); diff --git a/projects/mtg/include/ManaCost.h b/projects/mtg/include/ManaCost.h index f17eff491..bd6728429 100644 --- a/projects/mtg/include/ManaCost.h +++ b/projects/mtg/include/ManaCost.h @@ -25,7 +25,8 @@ class ManaCost{ MANA_PAID_WITH_KICKER = 2, MANA_PAID_WITH_ALTERNATIVE = 3, MANA_PAID_WITH_BUYBACK = 4, - MANA_PAID_WITH_FLASHBACK = 5 + MANA_PAID_WITH_FLASHBACK = 5, + MANA_PAID_WITH_RETRACE = 6 }; ExtraCosts * extraCosts; @@ -33,6 +34,7 @@ class ManaCost{ ManaCost * alternative; ManaCost * BuyBack; ManaCost * FlashBack; + ManaCost * Retrace; static ManaCost * parseManaCost(string value, ManaCost * _manacost = NULL, MTGCardInstance * c = NULL); virtual void init(); void x(); diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index 27d361b94..e9dc4e15d 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -185,6 +185,10 @@ bool Spell::FlashBackWasPaid(){ return (payResult == ManaCost::MANA_PAID_WITH_FLASHBACK); } +bool Spell::RetraceWasPaid(){ + return (payResult == ManaCost::MANA_PAID_WITH_RETRACE); +} + const string Spell::getDisplayName() const { return source->getName(); } @@ -410,6 +414,7 @@ Spell * ActionStack::addSpell(MTGCardInstance * _source, TargetChooser * tc, Man OutputDebugString(buf); #endif if(storm > 0){ mana = NULL;} + if(mana < 0) {mana = 0;} Spell * spell = NEW Spell(mCount,_source,tc, mana,payResult); addAction(spell); if (!game->players[0]->isAI() && diff --git a/projects/mtg/src/DuelLayers.cpp b/projects/mtg/src/DuelLayers.cpp index c6e294ce9..8071ae39e 100644 --- a/projects/mtg/src/DuelLayers.cpp +++ b/projects/mtg/src/DuelLayers.cpp @@ -24,6 +24,7 @@ void DuelLayers::init(){ action->Add(NEW MTGAlternativeCostRule(-1)); action->Add(NEW MTGBuyBackRule(-1)); action->Add(NEW MTGFlashBackRule(-1)); + action->Add(NEW MTGRetraceRule(-1)); action->Add(NEW MTGAttackRule(-1)); action->Add(NEW MTGBlockRule(-1)); action->Add(NEW MTGLegendRule(-1)); diff --git a/projects/mtg/src/ExtraCost.cpp b/projects/mtg/src/ExtraCost.cpp index 032214373..6e43c6a43 100644 --- a/projects/mtg/src/ExtraCost.cpp +++ b/projects/mtg/src/ExtraCost.cpp @@ -138,6 +138,200 @@ void DiscardRandomCost::Render(){ mFont->DrawString(buffer, 20 ,20, JGETEXT_LEFT); } //discardrandomcost + +//put a card ontop of your library cost + +//ToLibrarycost +ToLibraryCost * ToLibraryCost::clone() const{ + ToLibraryCost * ec = NEW ToLibraryCost(*this); + if (tc) ec->tc = tc->clone(); + return ec; +} + +ToLibraryCost::ToLibraryCost(TargetChooser *_tc):ExtraCost(_tc){ + if (tc) tc->targetter = NULL; //tapping targets is not targetting, protections do not apply + target = NULL; +} + +int ToLibraryCost::setSource(MTGCardInstance * card){ + ExtraCost::setSource(card); + if (tc) tc->targetter = NULL; //Tapping targets is not targetting, protections do not apply + if (!tc) target = card; + return 1; +} + +int ToLibraryCost::setPayment(MTGCardInstance * card){ + if (tc) { + int result = tc->addTarget(card); + if (result) { + target = card; + return result; + } + } + return 0; +} + +int ToLibraryCost::isPaymentSet(){ + if (target) return 1; + return 0; +} + +int ToLibraryCost::canPay(){ + //tap target does not have any additional restrictions. + return 1; +} + +int ToLibraryCost::doPay(){ + MTGCardInstance * _target = (MTGCardInstance *) target; + if(target){ + _target->controller()->game->putInLibrary(target); + target = NULL; + if (tc) tc->initTargets(); + return 1; + } + return 0; +} +void ToLibraryCost::Render(){ + //TODO : real stuff + WFont * mFont = resources.GetWFont(Constants::MAIN_FONT); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + mFont->SetColor(ARGB(255,255,255,255)); + char buffer[200]; + sprintf(buffer, "%s", _("Put a card on top of Library").c_str()); + mFont->DrawString(buffer, 20 ,20, JGETEXT_LEFT); +} +//ToLibrarycost + +//put a card from top of library into graveyard + +//Mill yourself as a cost +MillCost * MillCost::clone() const{ + MillCost * ec = NEW MillCost(*this); + if (tc) ec->tc = tc->clone(); + return ec; +} + +MillCost::MillCost(TargetChooser *_tc):ExtraCost(_tc){ + if (tc) tc->targetter = NULL; //tapping targets is not targetting, protections do not apply + target = NULL; +} + +int MillCost::setSource(MTGCardInstance * card){ + ExtraCost::setSource(card); + if (tc) tc->targetter = NULL; //Tapping targets is not targetting, protections do not apply + if (!tc) target = card; + return 1; +} + +int MillCost::setPayment(MTGCardInstance * card){ + if (tc) { + int result = tc->addTarget(card); + if (result) { + target = card; + return result; + } + } + return 0; +} + +int MillCost::isPaymentSet(){ + if (target) return 1; + return 0; +} + +int MillCost::canPay(){ + MTGGameZone * z = target->controller()->game->library; + int nbcards = z->nb_cards; + if(nbcards < 1) return 0; + return 1; +} + +int MillCost::doPay(){ + MTGCardInstance * _target = (MTGCardInstance *) target; + if(target){ + _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 = NULL; + if (tc) tc->initTargets(); + return 1; + } + return 0; +} +void MillCost::Render(){ + //TODO : real stuff + WFont * mFont = resources.GetWFont(Constants::MAIN_FONT); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + mFont->SetColor(ARGB(255,255,255,255)); + char buffer[200]; + sprintf(buffer, "%s", _("Deplete").c_str()); + mFont->DrawString(buffer, 20 ,20, JGETEXT_LEFT); +} +//millyourselfcost + +//put a card from top of library into exile + +//Mill ot exile yourself as a cost +MillExileCost * MillExileCost::clone() const{ + MillExileCost * ec = NEW MillExileCost(*this); + if (tc) ec->tc = tc->clone(); + return ec; +} + +MillExileCost::MillExileCost(TargetChooser *_tc):ExtraCost(_tc){ + if (tc) tc->targetter = NULL; //tapping targets is not targetting, protections do not apply + target = NULL; +} + +int MillExileCost::setSource(MTGCardInstance * card){ + ExtraCost::setSource(card); + if (tc) tc->targetter = NULL; //Tapping targets is not targetting, protections do not apply + if (!tc) target = card; + return 1; +} + +int MillExileCost::setPayment(MTGCardInstance * card){ + if (tc) { + int result = tc->addTarget(card); + if (result) { + target = card; + return result; + } + } + return 0; +} + +int MillExileCost::isPaymentSet(){ + if (target) return 1; + return 0; +} + +int MillExileCost::canPay(){ + MTGGameZone * z = target->controller()->game->library; + int nbcards = z->nb_cards; + if(nbcards < 1) return 0; + return 1; +} + +int MillExileCost::doPay(){ + MTGCardInstance * _target = (MTGCardInstance *) target; + if(target){ + _target->controller()->game->putInZone(_target->controller()->game->library->cards[_target->controller()->game->library->nb_cards-1],_target->controller()->game->library, _target->controller()->game->exile); + target = NULL; + if (tc) tc->initTargets(); + return 1; + } + return 0; +} +void MillExileCost::Render(){ + //TODO : real stuff + WFont * mFont = resources.GetWFont(Constants::MAIN_FONT); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + mFont->SetColor(ARGB(255,255,255,255)); + char buffer[200]; + sprintf(buffer, "%s", _("Deplete To Exile").c_str()); + mFont->DrawString(buffer, 20 ,20, JGETEXT_LEFT); +} +//milltoExileyourselfcost + //Tap target cost TapTargetCost * TapTargetCost::clone() const{ TapTargetCost * ec = NEW TapTargetCost(*this); diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index 973047c55..702372c4b 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -98,6 +98,7 @@ void GameObserver::nextGamePhase(){ cleanupPhase(); currentPlayer->canPutLandsIntoPlay = 1; currentPlayer->castedspellsthisturn = 0; + currentPlayer->opponent()->castedspellsthisturn = 0; currentPlayer->castcount = 0; currentPlayer->nocreatureinstant = 0; currentPlayer->nospellinstant = 0; @@ -523,6 +524,17 @@ void GameObserver::cardClick (MTGCardInstance * card, Targetable * object){ return; } + reaction = mLayers->actionLayer()->isReactingToClick(card); + if (reaction == -1) mLayers->actionLayer()->reactToClick(card); + } + //===================== + else if (card && card->paymenttype == 4){//this is retrace + if (targetChooser) { + MTGAbility * a = mLayers->actionLayer()->getAbility(MTGAbility::RETRACE_COST); + a->reactToClick(card); + return; + } + reaction = mLayers->actionLayer()->isReactingToClick(card); if (reaction == -1) mLayers->actionLayer()->reactToClick(card); } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index b11268167..e5375c158 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -364,7 +364,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return NULL; } - //buyback cost + //flashback cost found = s.find("flashback "); if (found == 0){ if (spell && spell->FlashBackWasPaid()){ @@ -374,6 +374,15 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return NULL; } + //retrace cost + found = s.find("retrace "); + if (found == 0){ + if (spell && spell->RetraceWasPaid()){ + string s1 = s.substr(found+7); + return parseMagicLine(s1,id,spell, card); + } + return NULL; + } //When...comes into play, you may... found = s.find("may "); if (found == 0){ diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index dca9066fc..74ef65333 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -102,6 +102,7 @@ void MTGCardInstance::initMTGCI(){ boughtback = 0; flashedback = 0; paymenttype = 0; + reduxamount = 0; summoningSickness = 1; preventable = 0; target = NULL; diff --git a/projects/mtg/src/MTGDeck.cpp b/projects/mtg/src/MTGDeck.cpp index 33678dcff..ef872a6b8 100644 --- a/projects/mtg/src/MTGDeck.cpp +++ b/projects/mtg/src/MTGDeck.cpp @@ -168,9 +168,19 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi } break; - case 'r': //rarity - if (!card) card = NEW MTGCard(); + case 'r': //retrace/rarity + if ('e' == key[1]) { //retrace + if (!primitive) primitive = NEW CardPrimitive(); + if (ManaCost * cost = primitive->getManaCost()) + { + string value = val; + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + cost->Retrace = ManaCost::parseManaCost(value); + } + } else {//rarity + if(!card) card = NEW MTGCard(); card->setRarity(val[0]); + } break; case 's': //subtype diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 0cfd0b4fc..aa62a6391 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -142,14 +142,28 @@ MTGCardInstance * MTGPlayerCards::putInExile(MTGCardInstance * card){ copy = putInZone(card,inPlay, exile); }else if (stack->hasCard(card)){ copy = putInZone(card,stack, exile); - } - if(graveyard->hasCard(card)){ + }else if(graveyard->hasCard(card)){ copy = putInZone(card,graveyard, exile); }else{ copy = putInZone(card,hand, exile); } return copy; } +MTGCardInstance * MTGPlayerCards::putInLibrary(MTGCardInstance * card){ + MTGCardInstance * copy = NULL; + MTGLibrary * library = card->owner->game->library; + MTGHand * hand = card->owner->game->hand; + if (inPlay->hasCard(card)){ + copy = putInZone(card,inPlay, library); + }else if (stack->hasCard(card)){ + copy = putInZone(card,stack, library); + }else if(graveyard->hasCard(card)){ + copy = putInZone(card,graveyard, library); + }else{ + copy = putInZone(card,hand, library); + } + return copy; +} MTGCardInstance * MTGPlayerCards::putInHand(MTGCardInstance * card){ MTGCardInstance * copy = NULL; @@ -158,8 +172,7 @@ MTGCardInstance * MTGPlayerCards::putInHand(MTGCardInstance * card){ copy = putInZone(card,inPlay, hand); }else if (stack->hasCard(card)){ copy = putInZone(card,stack, hand); - } - if(graveyard->hasCard(card)){ + }else if(graveyard->hasCard(card)){ copy = putInZone(card,graveyard, hand); }else{ copy = putInZone(card,hand, hand); diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 8611de990..4a9343ac4 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -73,7 +73,6 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){ ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); int payResult = player->getManaPool()->pay(card->getManaCost()); card->getManaCost()->doPayExtra(); - ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); delete previousManaPool; @@ -91,10 +90,12 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){ spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult,0); game->targetChooser = NULL; player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} }else{ spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,0); player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} } @@ -222,10 +223,12 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card){ spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult,0); game->targetChooser = NULL; player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} }else{ spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,0); player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1; } } @@ -353,10 +356,12 @@ int MTGBuyBackRule::reactToClick(MTGCardInstance * card){ spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult,0); game->targetChooser = NULL; player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} }else{ spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,0); player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1; } @@ -481,10 +486,12 @@ int MTGFlashBackRule::reactToClick(MTGCardInstance * card){ spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult,0); game->targetChooser = NULL; player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} }else{ spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,0); player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1; } @@ -527,7 +534,132 @@ ostream& MTGFlashBackRule::toString(ostream& out) const //------------------------------------------------------------------------- //------------------------------------------------------------------------- + //retrace +MTGRetraceRule::MTGRetraceRule(int _id):MTGAbility(_id, NULL){ + aType=MTGAbility::RETRACE_COST; +} +int MTGRetraceRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){ +int cardsingraveyard = game->players[0]->game->graveyard->nb_cards; + Player * player = game->currentlyActing(); + Player * currentPlayer = game->currentPlayer; + if (!player->game->graveyard->hasCard(card)) return 0; + if (!card->getManaCost()->Retrace) return 0; + if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))){ + ManaCost * playerMana = player->getManaPool(); + ManaCost * cost = card->getManaCost(); + ManaCost * Retrace = card->getManaCost()->Retrace; +#ifdef WIN32 + cost->Dump(); +#endif + if(player->castrestrictedspell > 0 && !card->hasType("land")){ return 0;} + if(player->onlyonecast > 0 && player->castcount >= 1){return 0;} + if(player->nospellinstant > 0){return 0;} + if(player->onlyoneinstant > 0){ if(player->castcount >= 1){return 0;}} + if(player->nocreatureinstant > 0 && card->hasType("creature")){return 0;} + if(player->castrestrictedcreature > 0 && card->hasType("creature")){return 0;} + //cost of card. + if(Retrace && playerMana->canAfford(Retrace)){ + return 1; + } + } + return 0;//dont play if you cant afford it. +} +int MTGRetraceRule::reactToClick(MTGCardInstance * card){ + if (!isReactingToClick(card)) return 0; + Player * player = game->currentlyActing(); + ManaCost * cost = card->getManaCost(); + ManaCost * Retrace = card->getManaCost()->Retrace; + ManaCost * playerMana = player->getManaPool(); +//this handles extra cost payments at the moment a card is played. + if(playerMana->canAfford(Retrace)){ + if (cost->Retrace->isExtraPaymentSet()){ + card->paymenttype = 4; + if (!game->targetListIsSet(card)){ + return 0; + } + }else{ + cost->Retrace->setExtraCostsAction(this, card); + game->waitForExtraPayment = cost->Retrace->extraCosts; + card->paymenttype = 4; + return 0; + } + } +//------------------------------------------------------------------------ + ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); + int payResult = player->getManaPool()->pay(card->getManaCost()->Retrace); + card->getManaCost()->doPayExtra(); + payResult = ManaCost::MANA_PAID_WITH_RETRACE; +//if Retrace has a extra payment thats set, this code pays it.the if statement is 100% needed as it would cause a crash on cards that dont have the Retrace cost. + if(Retrace){ + card->getManaCost()->Retrace->doPayExtra(); + } +//--------------------------------------------------------------------------- + ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); + delete previousManaPool; + if (card->hasType("land")){ + MTGCardInstance * copy = player->game->putInZone(card, player->game->graveyard, player->game->temp); + Spell * spell = NEW Spell(copy); + spell->resolve(); + delete spellCost; + delete spell; + player->canPutLandsIntoPlay--; + payResult = ManaCost::MANA_PAID_WITH_RETRACE; + spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); + }else{ + Spell * spell = NULL; + MTGCardInstance * copy = player->game->putInZone(card, player->game->graveyard, player->game->stack); + if (game->targetChooser){ + spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult,0); + game->targetChooser = NULL; + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} + }else{ + spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,0); + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1; + + } + } + if(card->has(Constants::STORM)){ + int storm = player->castedspellsthisturn; + ManaCost * spellCost = player->getManaPool(); + for(int i = storm; i > 1; i--){ + spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); + } + }//end of storm + if(!card->has(Constants::STORM)){ + copy->X = spell->computeX(copy); + copy->XX = spell->computeXX(copy); + } + } + + return 1; +} + +//The Put into play rule is never destroyed +int MTGRetraceRule::testDestroy(){ + return 0; +} + +ostream& MTGRetraceRule::toString(ostream& out) const +{ + out << "MTGRetraceRule ::: ("; + return MTGAbility::toString(out) << ")"; +} + MTGRetraceRule * MTGRetraceRule::clone() const{ + MTGRetraceRule * a = NEW MTGRetraceRule(*this); + a->isClone = 1; + return a; + } + + + //------------------------------------------------------------------------- + //------------------------------------------------------------------------- + //------------------------------------------------------------------------- + //----------------------------- bool MTGAttackRule::select(Target* t) { if (CardView* c = dynamic_cast(t)) { @@ -1334,9 +1466,12 @@ HUDDisplay::~HUDDisplay(){ int nbcards = z->nb_cards; for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; + int check = e->card->getManaCost()->getConvertedCost(); if (c->hasSubtype("artifact")){ + if( check > 0){ e->card->getManaCost()->remove(0,1);//one less colorless to cast } + } }//--end of redux bracket } } @@ -1503,7 +1638,9 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYARTIFACTS)){ + if(c->getManaCost()->getConvertedCost() > 0){ c->getManaCost()->remove(0,1);//one less colorless to cast + }else{c->reduxamount += 1;} } }//--end of redux bracket } @@ -1518,7 +1655,10 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYARTIFACTS)){ + if(c->reduxamount > 0){ + c->reduxamount -= 1;}else{ c->getManaCost()->add(0,1); + } } } //-- @@ -1545,7 +1685,9 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYSWAMP)){ + if(c->getManaCost()->getConvertedCost() > 0){ c->getManaCost()->remove(0,1);//one less colorless to cast + }else{c->reduxamount += 1;} } }//--end of redux bracket } @@ -1560,7 +1702,10 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYSWAMP)){ + if(c->reduxamount > 0){ c->reduxamount -+ 1;} + else{ c->getManaCost()->add(0,1); + } } } //-- @@ -1586,7 +1731,9 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYMOUNTAIN)){ + if(c->getManaCost()->getConvertedCost() > 0){ c->getManaCost()->remove(0,1);//one less colorless to cast + }else{c->reduxamount += 1;} } }//--end of redux bracket } @@ -1601,7 +1748,10 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYMOUNTAIN)){ + if(c->reduxamount > 0){c->reduxamount -= 1;} + else{ c->getManaCost()->add(0,1); + } } } //-- @@ -1627,7 +1777,9 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYPLAINS)){ + if(c->getManaCost()->getConvertedCost() > 0){ c->getManaCost()->remove(0,1);//one less colorless to cast + }else{c->reduxamount += 1;} } }//--end of redux bracket } @@ -1642,7 +1794,10 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYPLAINS)){ + if(c->reduxamount > 0){c->reduxamount -= 1;} + else{ c->getManaCost()->add(0,1); + } } } //-- @@ -1669,7 +1824,9 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYISLAND)){ + if(c->getManaCost()->getConvertedCost() > 0){ c->getManaCost()->remove(0,1);//one less colorless to cast + }else{c->reduxamount += 1;} } }//--end of redux bracket } @@ -1684,7 +1841,10 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYISLAND)){ + if(c->reduxamount > 0){c->reduxamount -= 1;} + else{ c->getManaCost()->add(0,1); + } } } //-- @@ -1711,7 +1871,9 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYFOREST)){ + if(c->getManaCost()->getConvertedCost() > 0){ c->getManaCost()->remove(0,1);//one less colorless to cast + }else{c->reduxamount += 1;} } }//--end of redux bracket } @@ -1726,7 +1888,10 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYFOREST)){ + if(c->reduxamount > 0){c->reduxamount -= 1;} + else{ c->getManaCost()->add(0,1); + } } } //-- @@ -1753,7 +1918,9 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYGREENCREATURES)){ + if(c->getManaCost()->getConvertedCost() > 0){ c->getManaCost()->remove(1,1);//one less colorless to cast + }else{c->reduxamount += 1;} } }//--end of redux bracket } @@ -1768,7 +1935,10 @@ HUDDisplay::~HUDDisplay(){ for (int j = 0; j < nbcards; ++j){ MTGCardInstance * c = z->cards[j]; if (c->has(Constants::AFFINITYGREENCREATURES)){ - c->getManaCost()->add(1,1); + if(c->reduxamount > 0){c->reduxamount -= 1;} + else{ + c->getManaCost()->add(1,1); + } } } //-- diff --git a/projects/mtg/src/ManaCost.cpp b/projects/mtg/src/ManaCost.cpp index 793e5b40c..f87e71fed 100644 --- a/projects/mtg/src/ManaCost.cpp +++ b/projects/mtg/src/ManaCost.cpp @@ -92,10 +92,9 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan tc = tcf.createTargetChooser(target,c); } manaCost->addExtraCost(NEW ExileTargetCost(tc)); -//--------------------------------- +/*--------------------------------- */ //bounce cost }else if (value[0] == 'h'){ - //tap OutputDebugString("Bounce\n"); TargetChooserFactory tcf; TargetChooser * tc = NULL; @@ -111,6 +110,7 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan //life cost }else if (value[0] == 'l'){ //tap + OutputDebugString("Life\n"); TargetChooserFactory tcf; TargetChooser * tc = NULL; @@ -122,6 +122,7 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan } manaCost->addExtraCost(NEW LifeCost(tc)); //end life cost + //----------------------------------- //DiscardRandom cost }else if (value[0] == 'd'){ //tap @@ -135,7 +136,46 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan tc = tcf.createTargetChooser(target,c); } manaCost->addExtraCost(NEW DiscardRandomCost(tc)); - //DiscardRandom cost +//------------------------------------- + + //hand to library cost + }else if (value[0] == 'q'){ + OutputDebugString("ToLibrary\n"); + TargetChooserFactory tcf; + TargetChooser * tc = NULL; + size_t target_start = value.find("("); + size_t target_end = value.find(")"); + if (target_start!=string::npos && target_end!=string::npos){ + string target = value.substr(target_start+1, target_end-1 - target_start); + tc = tcf.createTargetChooser(target,c); + } + manaCost->addExtraCost(NEW ToLibraryCost(tc)); + + //Millyourself as a cost + }else if (value[0] == 'm'){ + OutputDebugString("Mill\n"); + TargetChooserFactory tcf; + TargetChooser * tc = NULL; + size_t target_start = value.find("("); + size_t target_end = value.find(")"); + if (target_start!=string::npos && target_end!=string::npos){ + string target = value.substr(target_start+1, target_end-1 - target_start); + tc = tcf.createTargetChooser(target,c); + } + manaCost->addExtraCost(NEW MillCost(tc)); + + //Mill to exile yourself as a cost + }else if (value[0] == 'z'){ + OutputDebugString("MillExile\n"); + TargetChooserFactory tcf; + TargetChooser * tc = NULL; + size_t target_start = value.find("("); + size_t target_end = value.find(")"); + if (target_start!=string::npos && target_end!=string::npos){ + string target = value.substr(target_start+1, target_end-1 - target_start); + tc = tcf.createTargetChooser(target,c); + } + manaCost->addExtraCost(NEW MillExileCost(tc)); }else if (value[0] == 'c'){ //Counters @@ -233,6 +273,8 @@ ManaCost::~ManaCost(){ SAFE_DELETE(BuyBack); SAFE_DELETE(FlashBack); + + SAFE_DELETE(Retrace); } void ManaCost::x(){ @@ -255,6 +297,7 @@ void ManaCost::init(){ alternative = NULL; BuyBack = NULL; FlashBack = NULL; + Retrace = NULL; } @@ -296,6 +339,11 @@ void ManaCost::copy(ManaCost * _manaCost){ FlashBack = NEW ManaCost(); FlashBack->copy(_manaCost->FlashBack); } + SAFE_DELETE(Retrace); + if (_manaCost->Retrace){ + Retrace = NEW ManaCost(); + Retrace->copy(_manaCost->Retrace); + } } int ManaCost::getCost(int color){ @@ -334,10 +382,12 @@ int ManaCost::getConvertedCost(){ int ManaCost::remove(int color, int value){ cost[color] -= value; + if(cost[color] < 0){cost[color] = 0;} return 1; } int ManaCost::add(int color, int value){ + if(value < 0) value = 0; cost[color] += value; return 1; } @@ -592,6 +642,7 @@ int ManaPool::pay (ManaCost * _cost){ for (int j = 0; j receiveEvent(e); + } } return result;