diff --git a/projects/mtg/bin/Res/sets/LRW/_cards.dat b/projects/mtg/bin/Res/sets/LRW/_cards.dat index f5678e45c..4e95d657a 100644 --- a/projects/mtg/bin/Res/sets/LRW/_cards.dat +++ b/projects/mtg/bin/Res/sets/LRW/_cards.dat @@ -635,7 +635,7 @@ toughness=2 [/card] [card] text=Sacrifice Moonglove Extract: Moonglove Extract deals 2 damage to target creature or player. -auot={S}:damage:2 target(creature,player) +auto={S}:damage:2 target(creature,player) id=139506 name=Moonglove Extract rarity=C diff --git a/projects/mtg/bin/Res/sets/M10/_cards.dat b/projects/mtg/bin/Res/sets/M10/_cards.dat index 4776beadb..667e6bc64 100644 --- a/projects/mtg/bin/Res/sets/M10/_cards.dat +++ b/projects/mtg/bin/Res/sets/M10/_cards.dat @@ -690,7 +690,7 @@ subtype=Spider power=2 toughness=4 text=Reach (This creature can block creatures with flying.) -abilites=reach +abilities=reach rarity=C [/card] [card] diff --git a/projects/mtg/bin/Res/sets/TMP/_cards.dat b/projects/mtg/bin/Res/sets/TMP/_cards.dat index 945996ecd..4dbd98739 100644 --- a/projects/mtg/bin/Res/sets/TMP/_cards.dat +++ b/projects/mtg/bin/Res/sets/TMP/_cards.dat @@ -303,7 +303,6 @@ id=4693 target=*|stack auto=fizzle name=Counterspell -Color=Blue rarity=C mana={U}{U} type=Instant diff --git a/projects/mtg/bin/Res/sets/USG/_cards.dat b/projects/mtg/bin/Res/sets/USG/_cards.dat index 25cd9f136..024989a26 100644 --- a/projects/mtg/bin/Res/sets/USG/_cards.dat +++ b/projects/mtg/bin/Res/sets/USG/_cards.dat @@ -827,7 +827,6 @@ text=At end of turn, if no creatures are on the battlefield, sacrifice Pestilenc alias=1172 id=5619 name=Pestilence -colour=Black rarity=C mana={2}{B}{B} type=Enchantment diff --git a/projects/mtg/bin/Res/sets/ZEN/_cards.dat b/projects/mtg/bin/Res/sets/ZEN/_cards.dat index a31a644e5..1a0057119 100644 --- a/projects/mtg/bin/Res/sets/ZEN/_cards.dat +++ b/projects/mtg/bin/Res/sets/ZEN/_cards.dat @@ -173,7 +173,7 @@ mana={B} type=Instant [/card] [card] -text=Flying Landfall — Whenever a land enters the battlefield under your control, you may put a 1/1 white Bird creature token with flying into the battlefield. +text=Flying Landfall EWhenever a land enters the battlefield under your control, you may put a 1/1 white Bird creature token with flying into the battlefield. id=190399 name=Emeria Angel rarity=R @@ -1304,6 +1304,18 @@ auto={T}{S}:moveTo(myBattlefield) target(swamp,forest|mylibrary) && life:-1 cont type=Land [/card] [card] +text=Kicker {G} (You may pay an additional {G} as you cast this spell.) Target creature can't be the target of spells or abilities your opponents control this turn. If Vines of Vastwood was kicked, that creature gets +4/+4 until end of turn. +id=177571 +target=creature +name=Vines of Vastwood +mana={G} +kicker={G} +auto=opponentshroud +auto=kicker 4/4 +type=Instant +rarity=C +[/card] +[card] text=Flying Welkin Tern can block only creatures with flying. id=191353 name=Welkin Tern diff --git a/projects/mtg/bin/Res/sets/ZEN/todo.dat b/projects/mtg/bin/Res/sets/ZEN/todo.dat index cdfe17185..6e0a9052a 100644 --- a/projects/mtg/bin/Res/sets/ZEN/todo.dat +++ b/projects/mtg/bin/Res/sets/ZEN/todo.dat @@ -1187,14 +1187,6 @@ text=Deathtouch (Creatures dealt damage by this creature are destroyed. You can rarity=U [/card] [card] -id=177571 -name=Vines of Vastwood -mana={G} -type=Instant -text=Kicker {G} (You may pay an additional {G} as you cast this spell.) Target creature can't be the target of spells or abilities your opponents control this turn. If Vines of Vastwood was kicked, that creature gets +4/+4 until end of turn. -rarity=C -[/card] -[card] id=178135 name=Adventuring Gear mana={1} diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index dfb5aba44..0902b7092 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -9,6 +9,8 @@ generic/first_strike3.txt generic/hybrid_mana.txt generic/hybrid_mana_2.txt generic/hybrid_mana_3.txt +generic/kicker.txt +generic/kicker2.txt generic/legendary.txt generic/lifelink.txt generic/m10_blockers.txt diff --git a/projects/mtg/bin/Res/test/generic/kicker.txt b/projects/mtg/bin/Res/test/generic/kicker.txt new file mode 100644 index 000000000..4d2911b14 --- /dev/null +++ b/projects/mtg/bin/Res/test/generic/kicker.txt @@ -0,0 +1,23 @@ +#Test Kicker (cost not paid, grizzly bears shouldn't get 4/4) +# Vines of Vastwood on grizzly bears +# text=Kicker {G} (You may pay an additional {G} as you cast this spell.) Target creature can't be the target of spells or abilities your opponents control this turn. If Vines of Vastwood was kicked, that creature gets +4/+4 until end of turn. +[INIT] +FIRSTMAIN +[PLAYER1] +inplay:grizzly bears,mountain +hand:Vines of Vastwood,shock +manapool:{G} +[PLAYER2] +[DO] +Vines of Vastwood +grizzly bears +mountain +shock +grizzly bears +[ASSERT] +FIRSTMAIN +[PLAYER1] +graveyard:shock,grizzly bears,Vines of Vastwood +inplay:mountain +[PLAYER2] +[END] \ No newline at end of file diff --git a/projects/mtg/bin/Res/test/generic/kicker2.txt b/projects/mtg/bin/Res/test/generic/kicker2.txt new file mode 100644 index 000000000..b1cda16f4 --- /dev/null +++ b/projects/mtg/bin/Res/test/generic/kicker2.txt @@ -0,0 +1,23 @@ +#Test Kicker (cost paid, grizzly bears should get 4/4) +# Vines of Vastwood on grizzly bears +# text=Kicker {G} (You may pay an additional {G} as you cast this spell.) Target creature can't be the target of spells or abilities your opponents control this turn. If Vines of Vastwood was kicked, that creature gets +4/+4 until end of turn. +[INIT] +FIRSTMAIN +[PLAYER1] +inplay:grizzly bears,mountain +hand:Vines of Vastwood,shock +manapool:{G}{G} +[PLAYER2] +[DO] +Vines of Vastwood +grizzly bears +mountain +shock +grizzly bears +[ASSERT] +FIRSTMAIN +[PLAYER1] +graveyard:shock,Vines of Vastwood +inplay:grizzly bears,mountain +[PLAYER2] +[END] \ No newline at end of file diff --git a/projects/mtg/bin/daily_build/template.exe b/projects/mtg/bin/daily_build/template.exe index 60ee0acde..728036681 100644 Binary files a/projects/mtg/bin/daily_build/template.exe and b/projects/mtg/bin/daily_build/template.exe differ diff --git a/projects/mtg/include/ActionStack.h b/projects/mtg/include/ActionStack.h index 52067c181..4b9d3a366 100644 --- a/projects/mtg/include/ActionStack.h +++ b/projects/mtg/include/ActionStack.h @@ -79,11 +79,13 @@ class Spell: public Interruptible { MTGGameZone * from; TargetChooser * tc; ManaCost * cost; + int payResult; Spell(MTGCardInstance* _source); - Spell(int id, MTGCardInstance* _source, TargetChooser *_tc, ManaCost * _cost); + Spell(int id, MTGCardInstance* _source, TargetChooser *_tc, ManaCost * _cost, int payResult); ~Spell(); int resolve(); void Render(); + bool kickerWasPaid(); const string getDisplayName() const; virtual ostream& toString(ostream& out) const; MTGCardInstance * getNextCardTarget(MTGCardInstance * previous = 0); @@ -158,7 +160,7 @@ class ActionStack :public GuiLayer{ Player * askIfWishesToInterrupt; int garbageCollect(); int addAction(Interruptible * interruptible); - Spell * addSpell(MTGCardInstance* card, TargetChooser * tc, ManaCost * mana); + Spell * addSpell(MTGCardInstance* card, TargetChooser * tc, ManaCost * mana, int payResult); int AddNextGamePhase(); int addPutInGraveyard(MTGCardInstance * card); int addDraw(Player * player, int nbcards = 1); diff --git a/projects/mtg/include/ManaCost.h b/projects/mtg/include/ManaCost.h index 5d334f7f8..5ce447dce 100644 --- a/projects/mtg/include/ManaCost.h +++ b/projects/mtg/include/ManaCost.h @@ -20,7 +20,12 @@ class ManaCost{ int extraCostsIsCopy; public: + enum{ + MANA_PAID = 1, + MANA_PAID_WITH_KICKER = 2 + }; ExtraCosts * extraCosts; + ManaCost * kicker; 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 4b0c424f9..b2ba297d2 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -114,13 +114,16 @@ Spell::Spell(MTGCardInstance * _source): Interruptible(0){ } -Spell::Spell(int id, MTGCardInstance * _source, TargetChooser * tc, ManaCost * _cost): Interruptible(id), tc(tc),cost(_cost){ +Spell::Spell(int id, MTGCardInstance * _source, TargetChooser * tc, ManaCost * _cost, int payResult): Interruptible(id), tc(tc),cost(_cost), payResult(payResult){ source = _source; mHeight = 40; type = ACTION_SPELL; from = _source->getCurrentZone(); } +bool Spell::kickerWasPaid(){ + return (payResult == ManaCost::MANA_PAID_WITH_KICKER); +} const string Spell::getDisplayName() const { return source->getName(); @@ -389,13 +392,13 @@ int ActionStack::addAction(Interruptible * action){ return 1; } -Spell * ActionStack::addSpell(MTGCardInstance * _source, TargetChooser * tc, ManaCost * mana){ +Spell * ActionStack::addSpell(MTGCardInstance * _source, TargetChooser * tc, ManaCost * mana, int payResult){ #if defined (WIN32) || defined (LINUX) char buf[4096], *p = buf; sprintf(buf, "ACTIONSTACK Add spell\n"); OutputDebugString(buf); #endif - Spell * spell = NEW Spell(mCount,_source,tc, mana); + Spell * spell = NEW Spell(mCount,_source,tc, mana,payResult); addAction(spell); if (!game->players[0]->isAI() && _source->controller()==game->players[0] && diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 186ab71fd..fd8d02799 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -229,7 +229,15 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG SAFE_DELETE(cost); } - + //kicker cost + found = s.find("kicker "); + if (found == 0){ + if (spell->kickerWasPaid()){ + 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){ @@ -286,10 +294,10 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG } if (end != string::npos){ int lordIncludeSelf = 1; - size_t other = s.find("other", end); + size_t other = s1.find("other"); if ( other != string::npos){ lordIncludeSelf = 0; - s.replace(other, 5,""); + s1.replace(other, 5,""); } string lordTargetsString = s.substr(found+header,end-found-header); TargetChooserFactory tcf; @@ -596,7 +604,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG //Gain/loose Ability for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){ found = s.find(Constants::MTGBasicAbilities[j]); - if (found!= string::npos){ + if (found == 0 || found == 1){ int modifier = 1; if (found > 0 && s[found-1] == '-') modifier = 0; if (!activated){ diff --git a/projects/mtg/src/MTGDeck.cpp b/projects/mtg/src/MTGDeck.cpp index d18c21ef8..ba31cf831 100644 --- a/projects/mtg/src/MTGDeck.cpp +++ b/projects/mtg/src/MTGDeck.cpp @@ -141,7 +141,14 @@ int MTGAllCards::processConfLine(string s, MTGCard *card){ } }else if(key.compare("toughness")==0){ card->setToughness(atoi(value.c_str())); + }else if(key.compare("kicker")==0){ + std::transform( value.begin(), value.end(), value.begin(),::tolower ); + if (ManaCost * cost = card->getManaCost()){ + cost->kicker = ManaCost::parseManaCost(value); + } }else{ + string error = "MTGDECK Parsing Error:" + s + "\n"; + OutputDebugString(error.c_str()); } diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 0d51f328a..7c6d3adaf 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -49,7 +49,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){ return 0; } ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); - player->getManaPool()->pay(card->getManaCost()); + int payResult = player->getManaPool()->pay(card->getManaCost()); card->getManaCost()->doPayExtra(); ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); delete previousManaPool; @@ -64,10 +64,10 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){ Spell * spell = NULL; MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); if (game->targetChooser){ - spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost); + spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult); game->targetChooser = NULL; }else{ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost); + spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult); } } return 1; diff --git a/projects/mtg/src/ManaCost.cpp b/projects/mtg/src/ManaCost.cpp index c197efceb..3358cf10f 100644 --- a/projects/mtg/src/ManaCost.cpp +++ b/projects/mtg/src/ManaCost.cpp @@ -128,6 +128,8 @@ ManaCost::~ManaCost(){ if (!extraCostsIsCopy) { SAFE_DELETE(extraCosts); } + + SAFE_DELETE(kicker); } void ManaCost::x(){ @@ -142,6 +144,7 @@ void ManaCost::init(){ nbhybrids = 0; extraCosts = NULL; extraCostsIsCopy = 0; + kicker = NULL; } @@ -149,6 +152,9 @@ void ManaCost::copy(ManaCost * _manaCost){ for (unsigned int i = 0; i <= Constants::MTG_NB_COLORS; i++){ cost[i] = _manaCost->getCost(i); } + for (unsigned int i = 0; i < nbhybrids ; i++){ + SAFE_DELETE(hybrids[i]); + } for (unsigned int i = 0; i < _manaCost->nbhybrids; i++){ hybrids[i] = NEW ManaCostHybrid((*_manaCost->hybrids[i])); } @@ -160,6 +166,12 @@ void ManaCost::copy(ManaCost * _manaCost){ extraCosts = _manaCost->extraCosts; extraCostsIsCopy = 1; } + + SAFE_DELETE(kicker); + if (_manaCost->kicker){ + kicker = NEW ManaCost(); + kicker->copy(_manaCost->kicker); + } } int ManaCost::getCost(int color){ @@ -267,12 +279,24 @@ int ManaCost::setExtraCostsAction(MTGAbility * action, MTGCardInstance * card){ } int ManaCost::pay(ManaCost * _cost){ - ManaCost * diff = Diff(_cost); + int result = MANA_PAID; + ManaCost * toPay = NEW ManaCost(); + toPay->copy(_cost); + if (toPay->kicker){ + toPay->add(toPay->kicker); + if (!canAfford(toPay)){ + toPay->copy(_cost); + }else{ + result = MANA_PAID_WITH_KICKER; + } + } + ManaCost * diff = Diff(toPay); for (int i=0; i < Constants::MTG_NB_COLORS; i++){ cost[i] = diff->getCost(i); } delete diff; - return 1; + delete toPay; + return result; //TODO return 0 if can't afford the cost! }