diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index d5b64db95..38ddcef8a 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -954,7 +954,7 @@ public: MTGGameZone * activeZone; string newName; - GenericActivatedAbility(string newName,int _id, MTGCardInstance * card, MTGAbility * a, ManaCost * _cost, int _tap = 0, string limit = "", + GenericActivatedAbility(string newName,int _id, MTGCardInstance * card, MTGAbility * a, ManaCost * _cost, int _tap = 0, string limit = "",MTGAbility * sideEffects = NULL,string usesBeforeSideEffects = "", int restrictions = 0, MTGGameZone * dest = NULL); int resolve(); const char * getMenuText(); @@ -1083,7 +1083,7 @@ public: string newName; GenericTargetAbility(string newName,int _id, MTGCardInstance * _source, TargetChooser * _tc, MTGAbility * a, ManaCost * _cost = NULL, - int _tap = 0, string limit = "", int restrictions = 0, MTGGameZone * dest = NULL); + int _tap = 0, string limit = "",MTGAbility * sideEffects = NULL,string usesBeforeSideEffects = "", int restrictions = 0, MTGGameZone * dest = NULL); const char * getMenuText(); ~GenericTargetAbility(); GenericTargetAbility * clone() const; @@ -1802,7 +1802,7 @@ public: if(PT.size()) { SAFE_DELETE(wppt); - wppt = NEW WParsedPT(PT,NULL,(MTGCardInstance *) target); + wppt = NEW WParsedPT(PT,NULL,(MTGCardInstance *) source); } MTGCardInstance * _target = (MTGCardInstance *) target; _target->power += wppt->power.getValue(); @@ -1827,7 +1827,16 @@ public: ((MTGCardInstance *) target)->addToToughness(-wppt->toughness.getValue()); return 1; } - + const char * getMenuText() + { + if(PT.size()) + { + SAFE_DELETE(wppt); + wppt = NEW WParsedPT(PT,NULL,(MTGCardInstance *) source); + } + sprintf(menuText, "%i/%i", wppt->power.getValue(), wppt->toughness.getValue()); + return menuText; + } APowerToughnessModifier * clone() const { APowerToughnessModifier * a = NEW APowerToughnessModifier(*this); @@ -1843,132 +1852,6 @@ public: }; -//Alteration of Power and toughness until end of turn (instant) -class AInstantPowerToughnessModifierUntilEOT: public InstantAbility -{ -public: - WParsedPT * wppt; - string s; - AInstantPowerToughnessModifierUntilEOT(int _id, MTGCardInstance * _source, MTGCardInstance * _target, WParsedPT * wppt) : - InstantAbility(_id, _source, _target), wppt(wppt) - { - aType = MTGAbility::STANDARD_PUMP; - } - - int resolve() - { - ((MTGCardInstance *) target)->power += wppt->power.getValue(); - ((MTGCardInstance *) target)->addToToughness(wppt->toughness.getValue()); - if(((MTGCardInstance *) target)->has(Constants::INDESTRUCTIBLE) && wppt->toughness.getValue() < 0 && ((MTGCardInstance *) target)->toughness <= 0) - { - ((MTGCardInstance *) target)->controller()->game->putInGraveyard(((MTGCardInstance *) target)); - } - return 1; - } - - int destroy() - { - ((MTGCardInstance *) target)->power -= wppt->power.getValue(); - ((MTGCardInstance *) target)->addToToughness(-wppt->toughness.getValue()); - return 1; - } - - const char * getMenuText() - { - sprintf(menuText, "%i/%i", wppt->power.getValue(), wppt->toughness.getValue()); - return menuText; - } - - AInstantPowerToughnessModifierUntilEOT * clone() const - { - AInstantPowerToughnessModifierUntilEOT * a = NEW AInstantPowerToughnessModifierUntilEOT(*this); - a->wppt = NEW WParsedPT(*(a->wppt)); - a->isClone = 1; - return a; - } - - ~AInstantPowerToughnessModifierUntilEOT() - { - delete wppt; - } -}; - -//Alteration of Power and Toughness until end of turn (Aura) -class APowerToughnessModifierUntilEndOfTurn: public ActivatedAbility -{ -public: - AInstantPowerToughnessModifierUntilEOT * ability; - int counters; - int maxcounters; - APowerToughnessModifierUntilEndOfTurn(int id, MTGCardInstance * _source, MTGCardInstance * _target, WParsedPT * wppt, - ManaCost * _cost = NULL, int _maxcounters = 0) : - ActivatedAbility(id, _source, _cost, 0, 0), maxcounters(_maxcounters) - { - counters = 0; - target = _target; - ability = NEW AInstantPowerToughnessModifierUntilEOT(id, _source, _target, wppt); - aType = MTGAbility::STANDARD_PUMP; - } - - int isReactingToClick(MTGCardInstance * card, ManaCost * cost = NULL) - { - //The upper level "GenericTargetAbility" takes care of the click so we always return 0 here - return 0; - } - - void Update(float dt) - { - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_AFTER_EOT) - { - counters = 0; - } - ActivatedAbility::Update(dt); - } - - int fireAbility() - { - return resolve(); - } - - const char * getMenuText() - { - return ability->getMenuText(); - } - - /* int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){ - if (!ActivatedAbility::isReactingToClick(card,mana)) return 0; - return (!maxcounters || (counters < maxcounters)); - }*/ - - int resolve() - { - MTGAbility * a = ability->clone(); - a->target = target; - a->addToGame(); - counters++; - return 1; - } - - int addToGame() - { - resolve(); - return ActivatedAbility::addToGame(); - } - - APowerToughnessModifierUntilEndOfTurn * clone() const - { - APowerToughnessModifierUntilEndOfTurn * a = NEW APowerToughnessModifierUntilEndOfTurn(*this); - a->isClone = 1; - return a; - } - - ~APowerToughnessModifierUntilEndOfTurn() - { - if (!isClone) - SAFE_DELETE(ability); - } -}; - class GenericInstantAbility: public InstantAbility, public NestedAbility { public: @@ -3879,6 +3762,22 @@ public: ~ATransformerInstant(); }; +//Adds types/abilities/changes color to a card (generally until end of turn) +class PTInstant: public InstantAbility +{ +public: + APowerToughnessModifier * ability; + WParsedPT * wppt; + string s; + bool nonstatic; + WParsedPT * newWppt; + PTInstant(int id, MTGCardInstance * source, MTGCardInstance * target, WParsedPT * wppt,string s = "",bool nonstatic = false); + int resolve(); + const char * getMenuText(); + PTInstant * clone() const; + ~PTInstant(); +}; + //switch p/t ueot class ASwapPTUEOT: public InstantAbility { @@ -3960,19 +3859,24 @@ public: }; //phase based actions -class APhaseAction: public MTGAbility, public NestedAbility +class APhaseAction: public MTGAbility { public: + string psMenuText; + int abilityId; + string sAbility; int phase; + MTGAbility * ability; bool forcedestroy; bool next; + bool myturn; + bool opponentturn; Player * abilityOwner; - APhaseAction(int _id, MTGCardInstance * card, MTGCardInstance * target, MTGAbility * a, int _tap = 0, int restrictions = 0, int _phase = - Constants::MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true); + APhaseAction(int _id, MTGCardInstance * card, MTGCardInstance * target, string sAbility, int _tap = 0, int restrictions = 0, int _phase = + Constants::MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = true,bool opponentturn = true); void Update(float dt); int resolve(); - int removeAbility(); const char * getMenuText(); APhaseAction * clone() const; ~APhaseAction(); @@ -3982,9 +3886,10 @@ public: class APhaseActionGeneric: public InstantAbility { public: + string sAbility; APhaseAction * ability; - APhaseActionGeneric(int _id, MTGCardInstance * card, MTGCardInstance * target, MTGAbility * a, int _tap = 0, int restrictions = 0, int _phase = - Constants::MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true); + APhaseActionGeneric(int _id, MTGCardInstance * card, MTGCardInstance * target, string sAbility, int _tap = 0, int restrictions = 0, int _phase = + Constants::MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = false,bool opponentturn = false); int resolve(); const char * getMenuText(); APhaseActionGeneric * clone() const; @@ -4831,44 +4736,6 @@ public: } }; -//1284 Dragon Whelp -class ADragonWhelp: public APowerToughnessModifierUntilEndOfTurn -{ -public: - ADragonWhelp(int id, MTGCardInstance * card) : - APowerToughnessModifierUntilEndOfTurn(id, card, card, NEW WParsedPT(1, 0), NEW ManaCost()) - { - cost->add(Constants::MTG_COLOR_RED, 1); - } - - int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL) - { - if (!ActivatedAbility::isReactingToClick(card, mana)) return 0; - return (!maxcounters || (counters < maxcounters)); - } - - void Update(float dt) - { - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_AFTER_EOT && counters > 3) - { - source->controller()->game->putInGraveyard(source); - } - APowerToughnessModifierUntilEndOfTurn::Update(dt); - } - - virtual ostream& toString(ostream& out) const - { - out << "ADragonWhelp ::: ("; - return APowerToughnessModifierUntilEndOfTurn::toString(out) << ")"; - } - ADragonWhelp * clone() const - { - ADragonWhelp * a = NEW ADragonWhelp(*this); - a->isClone = 1; - return a; - } -}; - //1288 EarthBind class AEarthbind: public ABasicAbilityModifier { diff --git a/projects/mtg/include/MTGAbility.h b/projects/mtg/include/MTGAbility.h index eabee6c46..4adfb06d3 100644 --- a/projects/mtg/include/MTGAbility.h +++ b/projects/mtg/include/MTGAbility.h @@ -257,7 +257,11 @@ class ActivatedAbility:public MTGAbility{ int counters; int needsTapping; string limit; - ActivatedAbility(int id, MTGCardInstance * card,ManaCost * _cost = NULL, int _restrictions = NO_RESTRICTION,int tap = 1,string limit = ""); + MTGAbility * sideEffect; + MTGAbility * sa; + string usesBeforeSideEffects; + int uses; + ActivatedAbility(int id, MTGCardInstance * card,ManaCost * _cost = NULL, int _restrictions = NO_RESTRICTION,int tap = 1,string limit = "",MTGAbility * sideEffect = NULL,string usesBeforeSideEffects = ""); virtual ~ActivatedAbility(); virtual void Update(float dt) { diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index e3e4850d9..b409532e5 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -386,25 +386,32 @@ int AIAction::getEfficiency() break; } case MTGAbility::STANDARD_PUMP: - { - MTGCardInstance * _target = (MTGCardInstance *) (a->target); - efficiency = 0; - if (!target && !dynamic_cast (a)) - break; + { + MTGCardInstance * _target = (MTGCardInstance *) (a->target); + efficiency = 0; + if(!target && !dynamic_cast (a) && (((MTGCardInstance *)a->source)->hasSubtype(Subtypes::TYPE_AURA) || ((MTGCardInstance *)a->source)->hasSubtype(Subtypes::TYPE_EQUIPMENT))) + { + if(((MTGCardInstance *)a->source)->target) + _target = ((MTGCardInstance *)a->source)->target; + target = (MTGCardInstance *)a->source; + } + if (!target && !dynamic_cast (a)) + break; if(dynamic_cast (a) && !target) { - target = a->source; + target = a->source; } - + AbilityFactory af; int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY); //i do not set a starting eff. on this ability, this allows Ai to sometimes randomly do it as it normally does. - if (g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS) + int currentPhase = g->getCurrentGamePhase(); + if ((currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS) || (currentPhase == Constants::MTG_PHASE_COMBATATTACKERS)) { - if (suggestion == BAKA_EFFECT_GOOD && target->controller()->isAI()) - { + if (suggestion == BAKA_EFFECT_GOOD && target->controller()->isAI()) + { if ((_target->defenser || _target->blockers.size()) && ((_target->power < _target->getNextOpponent()->toughness - || _target->toughness < _target->getNextOpponent()->power) || (_target->has(Constants::TRAMPLE)))) + || _target->toughness < _target->getNextOpponent()->power) || (_target->has(Constants::TRAMPLE)))) { //this pump is based on a start eff. of 20 multiplied by how good the creature is. efficiency = 20 * _target->DangerRanking(); @@ -413,13 +420,14 @@ int AIAction::getEfficiency() { //this means im heading directly for the player, pump this creature as much as possible. efficiency = 100; + if(_target->power > 50) + efficiency -= _target->power;//we don't need to go overboard. better to not put all your eggs in a single basket. } - } - if (suggestion == BAKA_EFFECT_BAD && !target->controller()->isAI()) - { - efficiency = 100; - } - + } + } + if (suggestion == BAKA_EFFECT_BAD && !target->controller()->isAI()) + { + efficiency = 100; } break; } @@ -736,7 +744,8 @@ int AIPlayer::selectAbility() int chance = 1; if (!forceBestAbilityUse) chance = 1 + WRand() % 100; - if (action.getEfficiency() >= chance) + int actionScore = action.getEfficiency(); + if (actionScore >= chance) { if (!clickstream.size()) { @@ -1464,9 +1473,13 @@ int AIPlayerBaka::computeActions() switch (currentGamePhase) { case Constants::MTG_PHASE_COMBATBLOCKERS: - chooseBlockers(); - break; + { + chooseBlockers(); + selectAbility(); + break; + } default: + selectAbility(); break; } return 1; diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index 07f4d8deb..a8c4021c5 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -186,7 +186,10 @@ ostream& StackAbility::toString(ostream& out) const const string StackAbility::getDisplayName() const { std::ostringstream stream; + if(ability->source) stream << "StackAbility. (Source: " << ability->source->getDisplayName() << ")"; + else + stream << "StackAbility. (Source: " << ability->getMenuText() << ")"; return stream.str(); } diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 338154c6d..e6c5e6b0d 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -5,8 +5,8 @@ //Generic Activated Abilities GenericActivatedAbility::GenericActivatedAbility(string newName,int _id, MTGCardInstance * card, MTGAbility * a, ManaCost * _cost, int _tap, - string limit, int restrictions, MTGGameZone * dest) : - ActivatedAbility(_id, card, _cost, restrictions, _tap,limit), NestedAbility(a), activeZone(dest),newName(newName) + string limit,MTGAbility * sideEffects,string usesBeforeSideEffects, int restrictions, MTGGameZone * dest) : + ActivatedAbility(_id, card, _cost, restrictions, _tap,limit,sideEffects,usesBeforeSideEffects), NestedAbility(a), activeZone(dest),newName(newName) { counters = 0; target = ability->target; @@ -1089,14 +1089,14 @@ int AADynamic::resolve() activateStored(); if(tosrc == false) { - AInstantPowerToughnessModifierUntilEOT * a = NEW AInstantPowerToughnessModifierUntilEOT(this->GetId(), source, (MTGCardInstance*)_target,NEW WParsedPT(sourceamount,0)); + PTInstant * a = NEW PTInstant(this->GetId(), source, (MTGCardInstance*)_target,NEW WParsedPT(sourceamount,0)); GenericInstantAbility * wrapper = NEW GenericInstantAbility(1, source,(MTGCardInstance*)_target, a); wrapper->addToGame(); return 1; } else { - AInstantPowerToughnessModifierUntilEOT * a = NEW AInstantPowerToughnessModifierUntilEOT(this->GetId(), source, OriginalSrc,NEW WParsedPT(sourceamount,0)); + PTInstant * a = NEW PTInstant(this->GetId(), source, OriginalSrc,NEW WParsedPT(sourceamount,0)); GenericInstantAbility * wrapper = NEW GenericInstantAbility(1, source,OriginalSrc, a); wrapper->addToGame(); return 1; @@ -1109,14 +1109,14 @@ int AADynamic::resolve() activateStored(); if(tosrc == false) { - AInstantPowerToughnessModifierUntilEOT * a = NEW AInstantPowerToughnessModifierUntilEOT(this->GetId(), source, (MTGCardInstance*)_target,NEW WParsedPT(0,sourceamount)); + PTInstant * a = NEW PTInstant(this->GetId(), source, (MTGCardInstance*)_target,NEW WParsedPT(0,sourceamount)); GenericInstantAbility * wrapper = NEW GenericInstantAbility(1, source,(MTGCardInstance*)_target, a); wrapper->addToGame(); return 1; } else { - AInstantPowerToughnessModifierUntilEOT * a = NEW AInstantPowerToughnessModifierUntilEOT(this->GetId(), source, OriginalSrc,NEW WParsedPT(0,sourceamount)); + PTInstant * a = NEW PTInstant(this->GetId(), source, OriginalSrc,NEW WParsedPT(0,sourceamount)); GenericInstantAbility * wrapper = NEW GenericInstantAbility(1, source,OriginalSrc, a); wrapper->addToGame(); return 1; @@ -1129,14 +1129,14 @@ int AADynamic::resolve() activateStored(); if(tosrc == false) { - AInstantPowerToughnessModifierUntilEOT * a = NEW AInstantPowerToughnessModifierUntilEOT(this->GetId(), source, (MTGCardInstance*)_target,NEW WParsedPT(sourceamount,sourceamount)); + PTInstant * a = NEW PTInstant(this->GetId(), source, (MTGCardInstance*)_target,NEW WParsedPT(sourceamount,sourceamount)); GenericInstantAbility * wrapper = NEW GenericInstantAbility(1, source,(MTGCardInstance*)_target, a); wrapper->addToGame(); return 1; } else { - AInstantPowerToughnessModifierUntilEOT * a = NEW AInstantPowerToughnessModifierUntilEOT(this->GetId(), source, OriginalSrc,NEW WParsedPT(sourceamount,sourceamount)); + PTInstant * a = NEW PTInstant(this->GetId(), source, OriginalSrc,NEW WParsedPT(sourceamount,sourceamount)); GenericInstantAbility * wrapper = NEW GenericInstantAbility(1, source,OriginalSrc, a); wrapper->addToGame(); return 1; @@ -2001,7 +2001,7 @@ MultiAbility::~MultiAbility() //Generic Target Ability GenericTargetAbility::GenericTargetAbility(string newName,int _id, MTGCardInstance * _source, TargetChooser * _tc, MTGAbility * a, - ManaCost * _cost, int _tap, string limit, int restrictions, MTGGameZone * dest) : + ManaCost * _cost, int _tap, string limit,MTGAbility * sideEffects,string usesBeforeSideEffects, int restrictions, MTGGameZone * dest) : TargetAbility(_id, _source, _tc, _cost, restrictions, _tap), limit(limit), activeZone(dest),newName(newName) { ability = a; @@ -2532,6 +2532,38 @@ ATransformerInstant::~ATransformerInstant() { SAFE_DELETE(ability); } +//P/t ueot +PTInstant::PTInstant(int id, MTGCardInstance * source, MTGCardInstance * target, WParsedPT * wppt,string s,bool nonstatic) : +InstantAbility(id, source, target), wppt(wppt),s(s),nonstatic(nonstatic) +{ + ability = NEW APowerToughnessModifier(id, source, target, wppt,s,nonstatic); + aType = MTGAbility::STANDARD_PUMP; +} + +int PTInstant::resolve() +{ + APowerToughnessModifier * a = ability->clone(); + GenericInstantAbility * wrapper = NEW GenericInstantAbility(1, source, (Damageable *) (this->target), a); + wrapper->addToGame(); + return 1; +} +const char * PTInstant::getMenuText() +{ + return ability->getMenuText(); +} + +PTInstant * PTInstant::clone() const +{ + PTInstant * a = NEW PTInstant(*this); + a->ability = this->ability->clone(); + a->isClone = 1; + return a; +} + +PTInstant::~PTInstant() +{ + SAFE_DELETE(ability); +} // ASwapPTUEOT ASwapPTUEOT::ASwapPTUEOT(int id, MTGCardInstance * source, MTGCardInstance * target) : @@ -2830,33 +2862,58 @@ AUpkeep::~AUpkeep() } //A Phase based Action -APhaseAction::APhaseAction(int _id, MTGCardInstance * card, MTGCardInstance * target, MTGAbility * a, int _tap, int restrictions, int _phase,bool forcedestroy,bool next) : -MTGAbility(_id, card), NestedAbility(a), phase(_phase),forcedestroy(forcedestroy),next(next) +APhaseAction::APhaseAction(int _id, MTGCardInstance * card, MTGCardInstance * target, string sAbility, int _tap, int restrictions, int _phase,bool forcedestroy,bool next,bool myturn,bool opponentturn) : +MTGAbility(_id, card),sAbility(sAbility), phase(_phase),forcedestroy(forcedestroy),next(next),myturn(myturn),opponentturn(opponentturn) { + abilityId = _id; abilityOwner = card->controller(); + psMenuText = ""; + AbilityFactory af; + ability = af.parseMagicLine(sAbility, abilityId, NULL, NULL); + if(ability) + psMenuText = ability->getMenuText(); + else + psMenuText = sAbility.c_str(); + delete (ability); } void APhaseAction::Update(float dt) { if (newPhase != currentPhase) { - if(newPhase == phase && next ) + if((myturn && game->currentPlayer == source->controller())|| + (opponentturn && game->currentPlayer != source->controller())/*||*/ + /*(myturn && opponentturn)*/) { - MTGCardInstance * _target = (MTGCardInstance *) target; - if (_target) + if(newPhase == phase && next ) { - while (_target->next) - _target = _target->next; + MTGCardInstance * _target = (MTGCardInstance *) target; + if (_target) + { + while (_target->next) + _target = _target->next; + } + if(!sAbility.size()) + { + this->forceDestroy = 1; + return; + } + AbilityFactory af; + MTGAbility * ability = af.parseMagicLine(sAbility, abilityId, NULL, _target); + + MTGAbility * a = ability->clone(); + a->target = _target; + a->resolve(); + delete (a); + delete (ability); + if(this->oneShot) + { + this->forceDestroy = 1; + } } - ability->target = _target; - ability->source = _target; - ability->oneShot = 1; - ability->resolve(); - this->forceDestroy = 1; - removeAbility(); + else if(newPhase == phase && next == false) + next = true; } - else if(newPhase == phase && next == false) - next = true; } MTGAbility::Update(dt); } @@ -2868,7 +2925,10 @@ int APhaseAction::resolve() const char * APhaseAction::getMenuText() { - return ability->getMenuText(); + if(psMenuText.size()) + return psMenuText.c_str(); + else + return "Phase Based Action"; } APhaseAction * APhaseAction::clone() const @@ -2879,23 +2939,18 @@ APhaseAction * APhaseAction::clone() const a->isClone = 1; return a; } -int APhaseAction::removeAbility() -{ - if (!isClone) - SAFE_DELETE(ability); - return 1; -} APhaseAction::~APhaseAction() { + } // the main ability -APhaseActionGeneric::APhaseActionGeneric(int _id, MTGCardInstance * card, MTGCardInstance * target, MTGAbility * a, int _tap, int restrictions, int _phase,bool forcedestroy,bool next) : +APhaseActionGeneric::APhaseActionGeneric(int _id, MTGCardInstance * card, MTGCardInstance * target, string sAbility, int _tap, int restrictions, int _phase,bool forcedestroy,bool next,bool myturn,bool opponentturn) : InstantAbility(_id, source, target) { MTGCardInstance * _target = target; - ability = NEW APhaseAction(_id, card,_target, a,_tap, restrictions, _phase,forcedestroy,next); + ability = NEW APhaseAction(_id, card,_target, sAbility,_tap, restrictions, _phase,forcedestroy,next,myturn,opponentturn); } int APhaseActionGeneric::resolve() diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 5a90d3f3c..d19681a71 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -929,7 +929,23 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG if (doTap || cost) { string s1 = sWithoutTc.substr(delimiter + 2); - + //grabbing the sideffect string and amount before parsing abilities. + //side effect ei:dragond whelp. + MTGAbility * sideEffect = NULL; + string usesBeforeSideEffect = ""; + size_t limiteffect_str = s1.find("limit^"); + if (limiteffect_str != string::npos) + { + size_t end = s1.rfind("^"); + string sideEffectStr = s1.substr(limiteffect_str + 6,end - limiteffect_str - 6); + s1.erase(limiteffect_str,end - limiteffect_str); + end = s1.find("^"); + usesBeforeSideEffect = s1.substr(end+1); + s1.erase(end-1); + sideEffect = parseMagicLine(sideEffectStr, id, spell, card, 1); + } + + MTGAbility * a = parseMagicLine(s1, id, spell, card, 1); if (!a) { @@ -955,7 +971,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG { limit = sWithoutTc.substr(limit_str + 6); } - + AEquip *ae = dynamic_cast (a); if (ae) { @@ -969,8 +985,8 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return ae; } if (tc) - return NEW GenericTargetAbility(newName,id, card, tc, a, cost, doTap, limit, restrictions, dest); - return NEW GenericActivatedAbility(newName,id, card, a, cost, doTap, limit, restrictions, dest); + return NEW GenericTargetAbility(newName,id, card, tc, a, cost, doTap, limit,sideEffect,usesBeforeSideEffect, restrictions, dest); + return NEW GenericActivatedAbility(newName,id, card, a, cost, doTap, limit,sideEffect,usesBeforeSideEffect,restrictions, dest); } SAFE_DELETE(cost); } @@ -1136,19 +1152,12 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG next = false; } string sAbility = s.substr(end + 1); - MTGAbility * a = parseMagicLine(sAbility, id, spell, card); - - if (!a) - { - DebugTrace("MTGABILITY: Parsing Error: " << s); - return NULL; - } MTGCardInstance * _target = NULL; if (spell) _target = spell->getNextCardTarget(); if(!_target) _target = target; - return NEW APhaseActionGeneric(id, card,_target, a, doTap, restrictions, phase,sourceinPlay,next); + return NEW APhaseActionGeneric(id, card,_target,sAbility, doTap, restrictions, phase,sourceinPlay,next); } //Multiple abilities for ONE cost @@ -1594,6 +1603,15 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG phase = i; } } + bool opponentturn = true,myturn = true; + if(s1.find("my") != string::npos) + { + opponentturn = false; + } + if(s1.find("opponent") != string::npos) + { + myturn = false; + } if (s1.find("combatends") != string::npos) { phase = Constants::MTG_PHASE_COMBATEND; @@ -1621,19 +1639,12 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG next = false; } string sAbility = s.substr(end + 1); - MTGAbility * a = parseMagicLine(sAbility, id, spell, card); - - if (!a) - { - DebugTrace("MTGABILITY: Parsing Error: " << s); - return NULL; - } MTGCardInstance * _target = NULL; if (spell) _target = spell->getNextCardTarget(); if(!_target) _target = target; - return NEW APhaseActionGeneric(id, card,_target, a, doTap, restrictions, phase,sourceinPlay,next); + return NEW APhaseActionGeneric(id, card,_target, sAbility, doTap, restrictions, phase,sourceinPlay,next,myturn,opponentturn); } //Upkeep Cost @@ -2639,11 +2650,11 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG { if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT) { - return NEW AInstantPowerToughnessModifierUntilEOT(id, card, target, wppt); + return NEW PTInstant(id, card, target, wppt,s,nonstatic); } return NEW APowerToughnessModifier(id, card, target, wppt,s,nonstatic); } - return NEW APowerToughnessModifierUntilEndOfTurn(id, card, target, wppt); + return NEW PTInstant(id, card, target, wppt,s,nonstatic); } else { @@ -2952,11 +2963,11 @@ int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, Targ return BAKA_EFFECT_GOOD; if (dynamic_cast (a)) return BAKA_EFFECT_GOOD; - if (AInstantPowerToughnessModifierUntilEOT * abi = dynamic_cast(a)) + if (PTInstant * abi = dynamic_cast(a)) return (abi->wppt->power.getValue() >= 0 && abi->wppt->toughness.getValue() >= 0) ? BAKA_EFFECT_GOOD : BAKA_EFFECT_BAD; if (APowerToughnessModifier * abi = dynamic_cast(a)) return (abi->wppt->power.getValue() >= 0 && abi->wppt->toughness.getValue() >= 0) ? BAKA_EFFECT_GOOD : BAKA_EFFECT_BAD; - if (APowerToughnessModifierUntilEndOfTurn * abi = dynamic_cast(a)) + if (PTInstant * abi = dynamic_cast(a)) return abilityEfficiency(abi->ability, p, mode, tc); if (dynamic_cast (a)) @@ -3320,11 +3331,6 @@ void AbilityFactory::addAbilities(int _id, Spell * spell) } break; } - case 1284: //Dragon Whelp - { - game->addObserver(NEW ADragonWhelp(_id, card)); - break; - } case 1345: //Farmstead { @@ -3972,12 +3978,13 @@ NestedAbility::NestedAbility(MTGAbility * _ability) // -ActivatedAbility::ActivatedAbility(int id, MTGCardInstance * card, ManaCost * _cost, int restrictions, int tap,string limit) : - MTGAbility(id, card), restrictions(restrictions), needsTapping(tap),limit(limit) +ActivatedAbility::ActivatedAbility(int id, MTGCardInstance * card, ManaCost * _cost, int restrictions, int tap,string limit,MTGAbility * sideEffect,string usesBeforeSideEffects) : + MTGAbility(id, card), restrictions(restrictions), needsTapping(tap),limit(limit),sideEffect(sideEffect),usesBeforeSideEffects(usesBeforeSideEffects) { counters = 0; cost = _cost; abilityCost = 0; + sa = NULL; } int ActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana) @@ -4077,8 +4084,31 @@ int ActivatedAbility::reactToClick(MTGCardInstance * card) } if (needsTapping && source->isInPlay()) source->tap(); - fireAbility(); counters++; + if(sideEffect && usesBeforeSideEffects.size()) + { + WParsedInt * use = NEW WParsedInt(usesBeforeSideEffects.c_str(),NULL,source); + uses = use->getValue(); + delete use; + if(counters == uses) + { + sa = sideEffect->clone(); + sa->target = this->target; + sa->source = this->source; + if(sa->oneShot) + { + sa->fireAbility(); + } + else + { + GenericInstantAbility * wrapper = NEW GenericInstantAbility(1, source, (Damageable *) (this->target), sa); + wrapper->addToGame(); + } + } + + } + + fireAbility(); return 1; } @@ -4107,7 +4137,7 @@ int ActivatedAbility::reactToTargetClick(Targetable * object) AManaProducer * amp = dynamic_cast (this); if(amp) { - needsTapping = amp->tap; + needsTapping = amp->tap; } if (needsTapping && source->isInPlay()) { @@ -4121,9 +4151,54 @@ int ActivatedAbility::reactToTargetClick(Targetable * object) } if (amp) { + counters++; + if(sideEffect && usesBeforeSideEffects.size()) + { + WParsedInt * use = NEW WParsedInt(usesBeforeSideEffects.c_str(),NULL,source); + uses = use->getValue(); + delete use; + if(counters == uses) + { + sa = sideEffect->clone(); + sa->target = this->target; + sa->source = this->source; + if(sa->oneShot) + { + sa->fireAbility(); + } + else + { + GenericInstantAbility * wrapper = NEW GenericInstantAbility(1, source, (Damageable *) (this->target), sa); + wrapper->addToGame(); + } + } + + } this->resolve(); return 1; } + counters++; + if(sideEffect && usesBeforeSideEffects.size()) + { + WParsedInt * use = NEW WParsedInt(usesBeforeSideEffects.c_str(),NULL,source); + uses = use->getValue(); + delete use; + if(counters == uses) + { + sa = sideEffect->clone(); + sa->target = this->target; + sa->source = this->source; + if(sa->oneShot) + { + sa->fireAbility(); + } + else + { + GenericInstantAbility * wrapper = NEW GenericInstantAbility(1, source, (Damageable *) (this->target), sa); + wrapper->addToGame(); + } + } + } fireAbility(); return 1; @@ -4136,6 +4211,8 @@ ActivatedAbility::~ActivatedAbility() // Erwan 2004/04/25 //if (!isClone){ SAFE_DELETE(abilityCost); + SAFE_DELETE(sideEffect); + SAFE_DELETE(sa); //} }