diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 15bd61f4e..635d12de9 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -30657,7 +30657,7 @@ toughness=4 [/card] [card] name=Ethereal Haze -auto=preventalldamage to(creature) ueot +auto=preventalldamage from(creature) ueot text=Prevent all damage that would be dealt by creatures this turn. mana={W} type=Instant @@ -69645,6 +69645,66 @@ power=1 toughness=1 [/card] [card] +name=Patron of the Akki +other={kgoblin} name(Goblin Offering) +abilities=offering +auto=@combat(attacking) source(this):all(creature[attacking]) 2/0 ueot +text=Goblin offering (You may cast this card any time you could cast an instant by sacrificing a Goblin and paying the difference in mana costs between this and the sacrificed Goblin. Mana cost includes color.) -- Whenever Patron of the Akki attacks, creatures you control get +2/+0 until end of turn. +mana={4}{R}{R} +type=Legendary Creature +subtype=Spirit +power=5 +toughness=5 +[/card] +[card] +name=Patron of the Kitsune +other={kfox} name(Fox Offering) +abilities=offering +auto=@each blockers:may life:type:creature[attacking]:battlefield controller +text=Fox offering (You may cast this card any time you could cast an instant by sacrificing a Fox and paying the difference in mana costs between this and the sacrificed Fox. Mana cost includes color.) -- Whenever a creature attacks, you may gain 1 life. +mana={4}{W}{W} +type=Legendary Creature +subtype=Spirit +power=5 +toughness=6 +[/card] +[card] +name=Patron of the Moon +other={kmoonfolk} name(Moonfolk Offering) +abilities=flying,offering +auto={1}:name(put 2 lands in play) moveto(mybattlefield) and!(tap)! notatarget(land|myhand) +text=Moonfolk offering (You may cast this card any time you could cast an instant by sacrificing a Moonfolk and paying the difference in mana costs between this and the sacrificed Moonfolk. Mana cost includes color.) -- Flying -- {1}: Put up to two land cards from your hand onto the battlefield tapped. +mana={5}{U}{U} +type=Legendary Creature +subtype=Spirit +power=5 +toughness=4 +[/card] +[card] +name=Patron of the Nezumi +other={krat} name(Rat Offering) +abilities=offering +auto=@movedto(*|opponentgraveyard) from(battlefield):life:-1 opponent +text=Rat offering (You may cast this card any time you could cast an instant by sacrificing a Rat and paying the difference in mana costs between this and the sacrificed Rat. Mana cost includes color.) -- Whenever a permanent is put into an opponent's graveyard, that player loses 1 life. +mana={5}{B}{B} +type=Legendary Creature +subtype=Spirit +power=6 +toughness=6 +[/card] +[card] +name=Patron of the Orochi +other={ksnake} name(Snake Offering) +abilities=offering +auto={T}:name(untap all green creatures and forests) untap all(forest) && untap all(creature[green]) limit:1 +text=Snake offering (You may cast this card any time you could cast an instant by sacrificing a Snake and paying the difference in mana costs between this and the sacrificed Snake. Mana cost includes color.) -- {T}: Untap all Forests and all green creatures. Activate this ability only once each turn. +mana={6}{G}{G} +type=Legendary Creature +subtype=Spirit +power=7 +toughness=7 +[/card] +[card] name=Patron of the Wild facedown={3} autofacedown={2}{G}:morph diff --git a/projects/mtg/bin/Res/sets/primitives/unsupported.txt b/projects/mtg/bin/Res/sets/primitives/unsupported.txt index 345ecc823..f1608d66b 100644 --- a/projects/mtg/bin/Res/sets/primitives/unsupported.txt +++ b/projects/mtg/bin/Res/sets/primitives/unsupported.txt @@ -11637,51 +11637,6 @@ mana={3}{B}{B} type=Sorcery [/card] [card] -name=Patron of the Akki -text=Goblin offering (You may cast this card any time you could cast an instant by sacrificing a Goblin and paying the difference in mana costs between this and the sacrificed Goblin. Mana cost includes color.) -- Whenever Patron of the Akki attacks, creatures you control get +2/+0 until end of turn. -mana={4}{R}{R} -type=Legendary Creature -subtype=Spirit -power=5 -toughness=5 -[/card] -[card] -name=Patron of the Kitsune -text=Fox offering (You may cast this card any time you could cast an instant by sacrificing a Fox and paying the difference in mana costs between this and the sacrificed Fox. Mana cost includes color.) -- Whenever a creature attacks, you may gain 1 life. -mana={4}{W}{W} -type=Legendary Creature -subtype=Spirit -power=5 -toughness=6 -[/card] -[card] -name=Patron of the Moon -text=Moonfolk offering (You may cast this card any time you could cast an instant by sacrificing a Moonfolk and paying the difference in mana costs between this and the sacrificed Moonfolk. Mana cost includes color.) -- Flying -- {1}: Put up to two land cards from your hand onto the battlefield tapped. -mana={5}{U}{U} -type=Legendary Creature -subtype=Spirit -power=5 -toughness=4 -[/card] -[card] -name=Patron of the Nezumi -text=Rat offering (You may cast this card any time you could cast an instant by sacrificing a Rat and paying the difference in mana costs between this and the sacrificed Rat. Mana cost includes color.) -- Whenever a permanent is put into an opponent's graveyard, that player loses 1 life. -mana={5}{B}{B} -type=Legendary Creature -subtype=Spirit -power=6 -toughness=6 -[/card] -[card] -name=Patron of the Orochi -text=Snake offering (You may cast this card any time you could cast an instant by sacrificing a Snake and paying the difference in mana costs between this and the sacrificed Snake. Mana cost includes color.) -- {T}: Untap all Forests and all green creatures. Activate this ability only once each turn. -mana={6}{G}{G} -type=Legendary Creature -subtype=Spirit -power=7 -toughness=7 -[/card] -[card] name=Pay No Heed text=Prevent all damage a source of your choice would deal this turn. mana={W} diff --git a/projects/mtg/bin/Res/test/PT_M15_errata.txt b/projects/mtg/bin/Res/test/PT_M15_errata.txt new file mode 100644 index 000000000..6aa8b7770 --- /dev/null +++ b/projects/mtg/bin/Res/test/PT_M15_errata.txt @@ -0,0 +1,47 @@ +#Testing Turn to Frog to Serra Angel with Crusade in play. +#M15 uses base power template, so setting the power/toughness. +#only affects the base or original power/toughness. +#Turn to Frog makes Serra Angel a 1/1 blue frog... latest pull +#request from GIT fixes the issue of Serra Angel dying +#from crusade because of invalid reduction of P/T :) +# +#First attack is 1/1 blue Serra Angel unaffected by Crusade +#Second attack is 5/5 Serra Angel affected by Crusade :) +[INIT] +FIRSTMAIN +[PLAYER1] +inplay:Serra Angel, Crusade +hand:Turn to Frog +manapool:{1}{U} +[PLAYER2] +[DO] +Turn to Frog +Serra Angel +next +next +Serra Angel +next +eot +eot +#untap +next +#upkeep +next +#draw +next +#main1 +next +#combat begin +next +#attackers +Serra Angel +eot +[ASSERT] +UNTAP +[PLAYER1] +inplay:Serra Angel, Crusade +graveyard:Turn to Frog +manapool:{0} +[PLAYER2] +life:14 +[END] diff --git a/projects/mtg/bin/Res/test/PT_M15_errata2.txt b/projects/mtg/bin/Res/test/PT_M15_errata2.txt new file mode 100644 index 000000000..b71083d80 --- /dev/null +++ b/projects/mtg/bin/Res/test/PT_M15_errata2.txt @@ -0,0 +1,41 @@ +#Testing Turn to Frog to Serra Angel with Glorious Anthem in play. +#First attack is 2/2 blue Serra Angel affected by Glorious Anthem +#Second attack is 5/5 Serra Angel affected by Glorious Anthem :) +[INIT] +FIRSTMAIN +[PLAYER1] +inplay:Serra Angel, Glorious Anthem +hand:Turn to Frog +manapool:{1}{U} +[PLAYER2] +[DO] +Turn to Frog +Serra Angel +next +next +Serra Angel +next +eot +eot +#untap +next +#upkeep +next +#draw +next +#main1 +next +#combat begin +next +#attackers +Serra Angel +eot +[ASSERT] +UNTAP +[PLAYER1] +inplay:Serra Angel, Glorious Anthem +graveyard:Turn to Frog +manapool:{0} +[PLAYER2] +life:13 +[END] diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index 68fc41c15..eede5159b 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -534,6 +534,8 @@ prowess_of_the_fair.txt prowess_of_the_fair2.txt prowess_of_the_fair3.txt PTInstant.txt +PT_M15_errata.txt +PT_M15_errata2.txt pygmy_troll.txt pyknite_i426.txt pyroclasm.txt diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index e8d099441..698eb8a58 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -4307,10 +4307,13 @@ public: string newpower; bool newpowerfound; + int oldpower; + int oldpowerbonus; string newtoughness; bool newtoughnessfound; int oldtoughness; + int oldtoughnessbonus; map > newAbilities; vector newAbilitiesList; bool newAbilityFound; diff --git a/projects/mtg/include/ExtraCost.h b/projects/mtg/include/ExtraCost.h index bf935ec8b..09cf9323a 100644 --- a/projects/mtg/include/ExtraCost.h +++ b/projects/mtg/include/ExtraCost.h @@ -254,6 +254,17 @@ public: virtual Ninja * clone() const; }; +//offering cost +class Offering : public ExtraCost +{ +public: + Offering(TargetChooser *_tc = NULL); + virtual int canPay(); + virtual int isPaymentSet(); + virtual int doPay(); + virtual Offering * clone() const; +}; + class CounterCost : public ExtraCost { public: diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index 82053bcf1..c7132e310 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -72,7 +72,9 @@ public: int regenerateTokens; int isToken; int origpower; + int basepower;//to keep origpower intact int origtoughness; + int basetoughness;//to keep origtoughness intact int isMultiColored; int isLeveler; bool enchanted; diff --git a/projects/mtg/include/MTGDefinitions.h b/projects/mtg/include/MTGDefinitions.h index 79311fc1b..5f4ea6dde 100644 --- a/projects/mtg/include/MTGDefinitions.h +++ b/projects/mtg/include/MTGDefinitions.h @@ -224,7 +224,8 @@ class Constants OPPGRAVEEXILER = 106, LIBRARYDEATH = 107, SHUFFLELIBRARYDEATH = 108, - NB_BASIC_ABILITIES = 109, + OFFERING = 109, + NB_BASIC_ABILITIES = 110, RARITY_S = 'S', //Special Rarity diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index e868654bb..cdff3bc9b 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -4181,21 +4181,24 @@ for (it = types.begin(); it != types.end(); it++) } } if(newpowerfound ) - { + {//setting p/t only overrides base p/t as of M15 changes WParsedInt * val = NEW WParsedInt(newpower,NULL, source); oldpower = _target->power; - _target->power += val->getValue(); - _target->power -= oldpower; - _target->power += reapplyCountersBonus(_target,false,true); + oldpowerbonus = oldpower - _target->basepower; + _target->setPower(oldpowerbonus + val->getValue()); + _target->basepower = val->getValue(); + //?effects that change pt outside this? + //_target->power += reapplyCountersBonus(_target,false,true); delete val; } if(newtoughnessfound ) - { + {//setting p/t only overrides base p/t as of M15 changes WParsedInt * val = NEW WParsedInt(newtoughness,NULL, source); oldtoughness = _target->toughness; - _target->addToToughness(val->getValue()); - _target->addToToughness(-oldtoughness); - _target->addToToughness(reapplyCountersBonus(_target,true,false)); + oldtoughnessbonus = oldtoughness - _target->basetoughness; + _target->setToughness(oldtoughnessbonus + val->getValue()); + _target->basetoughness = val->getValue(); + //_target->addToToughness(reapplyCountersBonus(_target,true,false)); _target->life = _target->toughness; delete val; } @@ -4282,12 +4285,17 @@ int ATransformer::destroy() } if(newpowerfound ) - { - _target->power = oldpower; + {//override since we changed tha base, the bonus must have changed + oldpowerbonus = (_target->power - _target->basepower);//math hurts my head...it's all over the place :P + _target->setPower(_target->origpower + oldpowerbonus); + _target->basepower = _target->origpower;//revert } if(newtoughnessfound ) - { - _target->setToughness(oldtoughness); + {//override since we changed tha base, the bonus must have changed + oldtoughnessbonus = (_target->toughness - _target->basetoughness); + _target->setToughness(_target->origtoughness + oldtoughnessbonus); + _target->basetoughness = _target->origtoughness;//revert + _target->life = _target->toughness;//update } if(newAbilityFound) { diff --git a/projects/mtg/src/ExtraCost.cpp b/projects/mtg/src/ExtraCost.cpp index 3bd2ce7a2..8158f6e62 100644 --- a/projects/mtg/src/ExtraCost.cpp +++ b/projects/mtg/src/ExtraCost.cpp @@ -762,6 +762,65 @@ int Ninja::doPay() } //endbouncetargetcostforninja + +//Sacrifice target as cost for Offering +Offering * Offering::clone() const +{ + Offering * ec = NEW Offering(*this); + if (tc) + ec->tc = tc->clone(); + return ec; +} + +Offering::Offering(TargetChooser *_tc) : +ExtraCost("Select creature to offer", _tc) +{ +} + +int Offering::canPay() +{ + if (target && (!source->controller()->getManaPool()->canAfford(source->getManaCost()->Diff(target->getManaCost())))) + { + tc->removeTarget(target); + target = NULL; + return 0; + } + if (target && (source->controller()->getManaPool()->canAfford(source->getManaCost()->Diff(target->getManaCost())))) + return 1; + return 0; +} + +int Offering::isPaymentSet() +{ + if (target && (!source->controller()->getManaPool()->canAfford(source->getManaCost()->Diff(target->getManaCost())))) + { + tc->removeTarget(target); + target = NULL; + return 0; + } + if (target && (source->controller()->getManaPool()->canAfford(source->getManaCost()->Diff(target->getManaCost())))) + return 1; + return 0; +} + +int Offering::doPay() +{ + if (target) + { + target->controller()->getManaPool()->pay(source->getManaCost()->Diff(target->getManaCost())); + MTGCardInstance * beforeCard = target; + source->storedCard = target->createSnapShot(); + target->controller()->game->putInGraveyard(target); + WEvent * e = NEW WEventCardSacrifice(beforeCard,target); + GameObserver * game = target->owner->getObserver(); + game->receiveEvent(e); + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; +} //------------------------------------------------------------ SacrificeCost * SacrificeCost::clone() const diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index fca67f710..f6b8539c3 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -447,6 +447,12 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe if(cPhase < MTG_PHASE_COMBATBEGIN ||cPhase > MTG_PHASE_COMBATEND ) return 0; } + check = restriction[i].find("during my main phases"); + if(check != string::npos) + { + if( player != observer->currentPlayer && (cPhase != MTG_PHASE_FIRSTMAIN ||cPhase != MTG_PHASE_SECONDMAIN) ) + return 0; + } check = restriction[i].find("during my turn"); if(check != string::npos) { diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index b957afa0c..c2daef4a1 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -36,7 +36,9 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to attacker = 0; lifeOrig = life; origpower = power; + basepower = origpower; origtoughness = toughness; + basetoughness = origtoughness; belongs_to = arg_belongs_to; owner = NULL; if (arg_belongs_to) diff --git a/projects/mtg/src/MTGDefinitions.cpp b/projects/mtg/src/MTGDefinitions.cpp index bf2ca0f09..13d0ec579 100644 --- a/projects/mtg/src/MTGDefinitions.cpp +++ b/projects/mtg/src/MTGDefinitions.cpp @@ -137,7 +137,8 @@ const char* Constants::MTGBasicAbilities[] = { "mygraveexiler", "oppgraveexiler", "librarydeath", - "shufflelibrarydeath" + "shufflelibrarydeath", + "offering" }; map Constants::MTGBasicAbilitiesMap; diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index d3ef99baf..c85bff344 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -317,7 +317,7 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost *) return 1; } } - else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) + else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || (player == card->controller() && !game->isInterrupting && (game->getCurrentGamePhase() == MTG_PHASE_FIRSTMAIN || game->getCurrentGamePhase() == MTG_PHASE_SECONDMAIN)) @@ -651,7 +651,7 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * ) return 1; } - else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) + else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || card->has(Constants::OFFERING) || (player == card->controller() && !game->isInterrupting && (game->getCurrentGamePhase() == MTG_PHASE_FIRSTMAIN || game->getCurrentGamePhase() == MTG_PHASE_SECONDMAIN)) diff --git a/projects/mtg/src/ManaCost.cpp b/projects/mtg/src/ManaCost.cpp index 4c0b0a2e3..31a338161 100644 --- a/projects/mtg/src/ManaCost.cpp +++ b/projects/mtg/src/ManaCost.cpp @@ -193,6 +193,33 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan manaCost->addExtraCost(NEW Ninja(tc)); break; } + case 'k': //kill offering + { + TargetChooserFactory tcf(g); + if (value == "kgoblin") + { + tc = tcf.createTargetChooser("creature[goblin]|myBattlefield", c); + } + else if (value == "kfox") + { + tc = tcf.createTargetChooser("creature[fox]|myBattlefield", c); + } + else if (value == "kmoonfolk") + { + tc = tcf.createTargetChooser("creature[moonfolk]|myBattlefield", c); + } + else if (value == "krat") + { + tc = tcf.createTargetChooser("creature[rat]|myBattlefield", c); + } + else if (value == "ksnake") + { + tc = tcf.createTargetChooser("creature[snake]|myBattlefield", c); + } + //TODO iterate subtypes of creatures + manaCost->addExtraCost(NEW Offering(tc)); + break; + } case 'p' : { SAFE_DELETE(tc);