From 47c9ad1b659154bb92f14c90e3b625ae240e122f Mon Sep 17 00:00:00 2001 From: "wagic.the.homebrew@gmail.com" Date: Sun, 8 Aug 2010 14:04:37 +0000 Subject: [PATCH] Erwan - new features by Zethfox: -- "oneshot" optional parameters for lords (helps fixing issues with bouncelands) -- Life as a cost (avoids using a dirty trick of paying life as an effect) -- set life total abilitiy (lifeset -- new auto lines: autostack, autoexile The test suite passes with these changes, also no test using these abilities has been added yet --- projects/mtg/include/AllAbilities.h | 43 ++++++++++++++++++++- projects/mtg/include/ExtraCost.h | 14 +++++++ projects/mtg/src/ExtraCost.cpp | 58 +++++++++++++++++++++++++++++ projects/mtg/src/MTGAbility.cpp | 44 ++++++++++++++++++++++ projects/mtg/src/ManaCost.cpp | 17 +++++++++ 5 files changed, 174 insertions(+), 2 deletions(-) diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 054e99400..81f12858c 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -51,6 +51,10 @@ public: intValue = computeX(spell,card); }else if (s == "manacost"){ intValue = target->getManaCost()->getConvertedCost(); + }else if (s == "lifetotal"){ + intValue = target->controller()->life; + }else if (s == "opponentlifetotal"){ + intValue = target->controller()->opponent()->life; }else if (s == "p"){ intValue = target->power; }else if (s == "t"){ @@ -699,7 +703,7 @@ class AALifer:public ActivatedAbilityTP{ if (_target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){ _target = ((MTGCardInstance *)_target)->controller(); } - _target->life+=life->getValue(); + _target->life +=life->getValue(); } return 1; } @@ -1166,7 +1170,6 @@ public: }; - /*Gives life each time a spell matching CardDescriptor's criteria are match . Optionnal manacost*/ class ASpellCastLife:public MTGAbility{ public: @@ -2087,7 +2090,43 @@ class AThisForEach:public MTGAbility, public NestedAbility{ return a; } }; +//lifeset +class AALifeSet:public ActivatedAbilityTP{ +public: + WParsedInt * life; +AALifeSet(int _id, MTGCardInstance * _source, Targetable * _target, WParsedInt * life, ManaCost * _cost=NULL, int doTap = 0, int who = TargetChooser::UNSET):ActivatedAbilityTP(_id,_source,_target,_cost,doTap,who),life(life){ + } + int resolve(){ + Damageable * _target = (Damageable *) getTarget(); + if(_target){ + if (_target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){ + _target = ((MTGCardInstance *)_target)->controller(); + } + _target->life =life->getValue(); + } + return 0; + } + + const char * getMenuText(){ + return "Set Life"; + } + + AALifeSet * clone() const{ + AALifeSet * a = NEW AALifeSet(*this); + a->life = NEW WParsedInt(*(a->life)); + a->isClone = 1; + return a; + } + + ~AALifeSet(){ + SAFE_DELETE(life); + } + + +}; + +//lifesetend class AADamager:public ActivatedAbilityTP{ public: WParsedInt * damage; diff --git a/projects/mtg/include/ExtraCost.h b/projects/mtg/include/ExtraCost.h index 3193109c7..496e53e85 100644 --- a/projects/mtg/include/ExtraCost.h +++ b/projects/mtg/include/ExtraCost.h @@ -55,6 +55,20 @@ public: virtual SacrificeCost * clone() const; }; +//life cost +class LifeCost: public ExtraCost{ +public: + MTGCardInstance * target; + LifeCost(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 LifeCost * clone() const; +}; + //tap other cost class TapTargetCost: public ExtraCost{ public: diff --git a/projects/mtg/src/ExtraCost.cpp b/projects/mtg/src/ExtraCost.cpp index de563a11c..db195e4ec 100644 --- a/projects/mtg/src/ExtraCost.cpp +++ b/projects/mtg/src/ExtraCost.cpp @@ -20,6 +20,64 @@ int ExtraCost::setSource(MTGCardInstance * _source){ if (tc){ tc->source = _source; tc->targetter = _source;} return 1; } +//life cost +LifeCost * LifeCost::clone() const{ + LifeCost * ec = NEW LifeCost(*this); + if (tc) ec->tc = tc->clone(); + return ec; +} +LifeCost::LifeCost(TargetChooser *_tc):ExtraCost(_tc){ + if (tc) tc->targetter = NULL; + target = NULL; +} + +int LifeCost::setSource(MTGCardInstance * card){ + ExtraCost::setSource(card); + if (tc) tc->targetter = NULL; + if (!tc) target = card; + return 1; +} +int LifeCost::setPayment(MTGCardInstance * card){ + if (tc) { + int result = tc->addTarget(card); + if (result) { + target = card; + return result; + } + } + return 0; +} +int LifeCost::isPaymentSet(){ + if (target) return 1; + return 0; +} + +int LifeCost::canPay(){ + return 1; +} +int LifeCost::doPay(){ + MTGCardInstance * _target = (MTGCardInstance *) target; + if(target){ + _target->controller()->life -= 1; + target = NULL; + if (tc) tc->initTargets(); + return 1; + } + return 0; +} + + +void LifeCost::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", _("Life").c_str()); + mFont->DrawString(buffer, 20 ,20, JGETEXT_LEFT); +} +//endlifecost + //Tap target cost TapTargetCost * TapTargetCost::clone() const{ TapTargetCost * ec = NEW TapTargetCost(*this); diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 986baf7e6..e5f1bf79a 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -354,6 +354,17 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG else a1 = NEW GenericActivatedAbility(id, card, a1,NULL); return NEW MayAbility(id,a1,card); } + //When...comes into play, choose one... + found = s.find("choice "); + if (found == 0){ + string s1 = sWithoutTc.substr(found+4); + MTGAbility * a1 = parseMagicLine(s1,id,spell, card); + if (!a1) return NULL; + + if (tc) a1 = NEW GenericTargetAbility(id, card, tc, a1); + else a1 = NEW GenericActivatedAbility(id, card, a1,NULL); + return NEW MayAbility(id,a1,card,true); + } //Multiple abilities for ONE cost @@ -498,10 +509,16 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG int mini = 0; int maxi = 0; + found = s.find(" >"); if (found !=string::npos) mini = atoi(s.substr(found+2,1).c_str()); + found = s.find(" <"); if (found !=string::npos) maxi = atoi(s.substr(found+2,1).c_str()); + + found = s.find(" oneshot"); + if (found !=string::npos) oneShot = 1; + switch(i){ case 0: result = NEW ALord(id, card, lordTargets, lordIncludeSelf, a); break; case 1: result = NEW AForeach(id, card, _target,lordTargets, lordIncludeSelf, a,mini,maxi); break; @@ -742,6 +759,25 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return a; } +//set life total + found = s.find("lifeset"); + if (found != string::npos){ + size_t start = s.find(":",found); + if (start == string::npos) start = s.find(" ",found); + size_t end = s.find(" ",start); + string d; + if (end != string::npos){ + d = s.substr(start+1,end-start-1); + }else{ + d = s.substr(start+1); + } + WParsedInt * life = NEW WParsedInt(d,spell,card); + Damageable * t = NULL; + if (spell) t = spell->getNextDamageableTarget(); + MTGAbility * a = NEW AALifeSet(id,card,t, life, NULL, 0, who); + a->oneShot = 1; + return a; + } //gain/lose life found = s.find("life:"); @@ -1110,6 +1146,14 @@ int AbilityFactory::getAbilities(vector * v, Spell * spell, MTGCar if (dest == zones->graveyard){ magicText = card->magicTexts["graveyard"]; break; + } + if (dest == zones->stack){ + magicText = card->magicTexts["stack"]; + break; + } + if (dest == zones->exile){ + magicText = card->magicTexts["exile"]; + break; } //Other zones needed ? return 0; diff --git a/projects/mtg/src/ManaCost.cpp b/projects/mtg/src/ManaCost.cpp index 09a110dd8..7a01c869f 100644 --- a/projects/mtg/src/ManaCost.cpp +++ b/projects/mtg/src/ManaCost.cpp @@ -79,6 +79,23 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan } manaCost->addExtraCost(NEW TapTargetCost(tc)); //tapcost + + + //life cost + }else if (value[0] == 'l'){ + //tap + OutputDebugString("Life\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 LifeCost(tc)); + //end life cost + }else if (value[0] == 'c'){ //Counters OutputDebugString("Counter\n");