diff --git a/projects/mtg/bin/Res/sets/ICE/_cards.dat b/projects/mtg/bin/Res/sets/ICE/_cards.dat index 95dcfc6d5..7f0d6a230 100644 --- a/projects/mtg/bin/Res/sets/ICE/_cards.dat +++ b/projects/mtg/bin/Res/sets/ICE/_cards.dat @@ -374,7 +374,7 @@ text=Flare deals 1 damage to target creature or player. Draw a card at the begin id=2621 target=creature,player auto=damage:1 -auto=@next upkeep:draw:1 +auto=@next upkeep:draw:1 controller name=Flare rarity=C type=Instant @@ -835,7 +835,7 @@ text=Target player discards a card. Draw a card at the beginning of the next id=2471 target=player auto=discard:1 -auto=@next upkeep:draw:1 +auto=@next upkeep:draw:1 controller name=Mind Ravel rarity=C type=Sorcery @@ -1096,7 +1096,7 @@ text=Target player puts the top card of his or her library into his or her grave id=2529 target=player auto=deplete:1 -auto=@next upkeep:draw:1 +auto=@next upkeep:draw:1 controller name=Ray of Erasure rarity=C type=Instant @@ -1434,8 +1434,8 @@ id=2491 name=Touch of Death target=player auto=damage:1 -auto=@next upkeep:draw:1 -auto=life:1 +auto=@next upkeep:draw:1 controller +auto=life:1 controller rarity=C type=Sorcery mana={2}{B} diff --git a/projects/mtg/bin/Res/sets/MIR/_cards.dat b/projects/mtg/bin/Res/sets/MIR/_cards.dat index 155afdf8c..61c3a1b2e 100644 --- a/projects/mtg/bin/Res/sets/MIR/_cards.dat +++ b/projects/mtg/bin/Res/sets/MIR/_cards.dat @@ -1111,7 +1111,7 @@ text=Flare deals 1 damage to target creature or player. Draw a card at the begi id=3447 name=Flare auto=damage:1 target(creature,player) -auto=@next upkeep:draw:1 +auto=@next upkeep:draw:1 controller type=Instant mana={2}{R} rarity=C diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index 562eea015..58aaf49b8 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -45,6 +45,7 @@ blessed_wine.txt #blinking_spirit.txt bloodfire_colossus.txt bottle_gnomes.txt +bottle_gnomes2.txt boggart_arsonists.txt brass_man.txt castle.txt diff --git a/projects/mtg/bin/Res/test/bottle_gnomes2.txt b/projects/mtg/bin/Res/test/bottle_gnomes2.txt new file mode 100644 index 000000000..0ad4b00bd --- /dev/null +++ b/projects/mtg/bin/Res/test/bottle_gnomes2.txt @@ -0,0 +1,21 @@ +#Bug: Bug: taking control of bottle gnomes, then sacrificing them: opponent gets life +[INIT] +FIRSTMAIN +[PLAYER1] +hand:persuasion +manapool:{3}{U}{U} +[PLAYER2] +inplay:bottle gnomes +[DO] +persuasion +bottle gnomes +bottle gnomes +[ASSERT] +FIRSTMAIN +[PLAYER1] +graveyard:persuasion +manapool:{0} +life:23 +[PLAYER2] +graveyard:bottle gnomes +[END] \ No newline at end of file diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 8fc246127..d3fc40ddd 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -307,18 +307,50 @@ public: }; +class ActivatedAbilityTP:public ActivatedAbility{ +public: + int who; + ActivatedAbilityTP(int id, MTGCardInstance * card, Targetable * _target = NULL, ManaCost * cost=NULL, int doTap = 0, int who = TargetChooser::UNSET):ActivatedAbility(id,card,cost,0,doTap),who(who){ + if (_target) target = _target; + } + + Targetable * getTarget(){ + switch(who){ + case TargetChooser::TARGET_CONTROLLER: + if (target) return ((MTGCardInstance *)target)->controller(); + return NULL; + case TargetChooser::CONTROLLER: + return source->controller(); + case TargetChooser::OPPONENT: + return source->controller()->opponent(); + default: + return target; + } + return NULL; + } +}; + //Drawer, allows to draw a card for a cost: -class AADrawer:public ActivatedAbility{ +class AADrawer:public ActivatedAbilityTP{ public: int nbcards; - AADrawer(int _id, MTGCardInstance * card,ManaCost * _cost, int _nbcards = 1, int _tap = 0):ActivatedAbility(_id, card,_cost,0,_tap),nbcards(_nbcards){ + AADrawer(int _id, MTGCardInstance * card,Targetable * _target,ManaCost * _cost, int _nbcards = 1, int _tap = 0, int who=TargetChooser::UNSET):ActivatedAbilityTP(_id, card,_target,_cost,_tap,who),nbcards(_nbcards){ } int resolve(){ - game->mLayers->stackLayer()->addDraw(source->controller(),nbcards); - game->mLayers->stackLayer()->resolve(); + Targetable * _target = getTarget(); + Player * player; + if (_target){ + if (_target->typeAsTarget() == TARGET_CARD){ + player = ((MTGCardInstance *)_target)->controller(); + }else{ + player = (Player *) _target; + } + game->mLayers->stackLayer()->addDraw(player,nbcards); + game->mLayers->stackLayer()->resolve(); + } return 1; } @@ -335,16 +367,20 @@ class AADrawer:public ActivatedAbility{ }; /*Gives life to target controller*/ -class AALifer:public ActivatedAbility{ +class AALifer:public ActivatedAbilityTP{ public: int life; - AALifer(int _id, MTGCardInstance * card, MTGCardInstance * _target, int life, ManaCost * _cost = NULL, int _tap = 0):ActivatedAbility(_id, card,_cost,0,_tap),life(life){ - target = _target; + AALifer(int _id, MTGCardInstance * card, Targetable * _target, int life, ManaCost * _cost = NULL, int _tap = 0, int who = TargetChooser::UNSET):ActivatedAbilityTP(_id, card,_target,_cost,_tap,who),life(life){ } int resolve(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - _target->controller()->life+=life; + Damageable * _target = (Damageable *) getTarget(); + if (_target){ + if (_target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){ + _target = ((MTGCardInstance *)_target)->controller(); + } + _target->life+=life; + } return 1; } @@ -1615,21 +1651,18 @@ class AForeach:public ListMaintainerAbility{ }; -class AADamager:public ActivatedAbility{ + + +class AADamager:public ActivatedAbilityTP{ public: int damage; - int who; -AADamager(int _id, MTGCardInstance * _source, Damageable * _target, int _damage = 0, ManaCost * _cost=NULL, int who=0):ActivatedAbility(_id,_source,_cost),damage(_damage),who(who){ - if (_target) target = _target; +AADamager(int _id, MTGCardInstance * _source, Targetable * _target, int _damage = 0, ManaCost * _cost=NULL, int doTap = 0, int who = TargetChooser::UNSET):ActivatedAbilityTP(_id,_source,_target,_cost,doTap,who),damage(_damage){ aType = MTGAbility::DAMAGER; } int resolve(){ if(target){ - Damageable * _target = (Damageable *)target; - if (who ==1){ - _target = ((MTGCardInstance *) target)->controller(); - } + Damageable * _target = (Damageable *) getTarget(); game->mLayers->stackLayer()->addDamage(source,_target, damage); game->mLayers->stackLayer()->resolve(); return 1; @@ -3678,19 +3711,25 @@ ALavaborn * clone() const{ //Generic Millstone -class AADepleter:public ActivatedAbility{ +class AADepleter:public ActivatedAbilityTP{ public: int nbcards; - AADepleter(int _id, MTGCardInstance * card, Player * _target, int nbcards = 1, ManaCost * _cost=NULL, int _tap = 0):ActivatedAbility(_id,card, _cost,0,_tap),nbcards(nbcards){ - target = _target; + AADepleter(int _id, MTGCardInstance * card, Targetable * _target, int nbcards = 1, ManaCost * _cost=NULL, int _tap = 0, int who = TargetChooser::UNSET):ActivatedAbilityTP(_id,card, _target,_cost,_tap,who),nbcards(nbcards){ } int resolve(){ - Player * player = (Player *) target; - if (!player) return 0; - MTGLibrary * library = player->game->library; - for (int i = 0; i < nbcards; i++){ - if (library->nb_cards) - player->game->putInZone(library->cards[library->nb_cards-1],library, player->game->graveyard); + Targetable * _target = getTarget(); + Player * player; + if (_target){ + if (_target->typeAsTarget() == TARGET_CARD){ + player = ((MTGCardInstance *)_target)->controller(); + }else{ + player = (Player *) _target; + } + MTGLibrary * library = player->game->library; + for (int i = 0; i < nbcards; i++){ + if (library->nb_cards) + player->game->putInZone(library->cards[library->nb_cards-1],library, player->game->graveyard); + } } return 1; } @@ -3708,18 +3747,24 @@ class AADepleter:public ActivatedAbility{ //Random Discard -class AARandomDiscarder:public ActivatedAbility{ +class AARandomDiscarder:public ActivatedAbilityTP{ public: int nbcards; - AARandomDiscarder(int _id, MTGCardInstance * card, Player * _target, int nbcards = 1, ManaCost * _cost=NULL, int _tap = 0):ActivatedAbility(_id,card, _cost,0,_tap),nbcards(nbcards){ - target = _target; + AARandomDiscarder(int _id, MTGCardInstance * card, Targetable * _target, int nbcards = 1, ManaCost * _cost=NULL, int _tap = 0,int who=TargetChooser::UNSET):ActivatedAbilityTP(_id,card, _target,_cost,_tap,who),nbcards(nbcards){ } int resolve(){ - Player * player = (Player *) target; - if (!player) return 0; - for (int i = 0; i < nbcards; i++){ - player->game->discardRandom(player->game->hand); - } + Targetable * _target = getTarget(); + Player * player; + if (_target){ + if (_target->typeAsTarget() == TARGET_CARD){ + player = ((MTGCardInstance *)_target)->controller(); + }else{ + player = (Player *) _target; + } + for (int i = 0; i < nbcards; i++){ + player->game->discardRandom(player->game->hand); + } + } return 1; } diff --git a/projects/mtg/include/TargetChooser.h b/projects/mtg/include/TargetChooser.h index e2cd76a74..27b76ca3c 100644 --- a/projects/mtg/include/TargetChooser.h +++ b/projects/mtg/include/TargetChooser.h @@ -27,6 +27,14 @@ class TargetChooser: public TargetsList { int forceTargetListReady; public: + enum{ + UNSET = 0, + OPPONENT = -1, + CONTROLLER = 1, + TARGET_CONTROLLER = 2 + }; + + TargetChooser(MTGCardInstance * card = NULL, int _maxtargets = -1); MTGCardInstance * source; diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 13cd3688c..96bd46896 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -377,6 +377,12 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG } } + + int who = TargetChooser::UNSET; + if (s.find(" controller") != string::npos) who=TargetChooser::CONTROLLER; + if (s.find(" opponent") != string::npos) who=TargetChooser::OPPONENT; + if (s.find(" targetcontroller") != string::npos) who=TargetChooser::TARGET_CONTROLLER; + //Damage found = s.find("damage"); if (found != string::npos){ @@ -392,9 +398,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG Damageable * d = NULL; if (spell) d = spell->getNextDamageableTarget(); - int who = 0; - if (s.find("controller") != string::npos) who=1; - MTGAbility * a = NEW AADamager(id,card,d, damage, NULL, who); + MTGAbility * a = NEW AADamager(id,card,d, damage, NULL, 0, who); a->oneShot = 1; return a; } @@ -412,7 +416,9 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG life = atoi(s.substr(start+1).c_str()); } - MTGAbility * a = NEW AALifer(id,card,card,life); + Damageable * d = NULL; + if (spell) d = spell->getNextPlayerTarget(); + MTGAbility * a = NEW AALifer(id,card,d,life,NULL,0,who); a->oneShot = 1; return a; } @@ -429,7 +435,9 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG nbcards = atoi(s.substr(start+1).c_str()); } - MTGAbility * a = NEW AADrawer(id,card,NULL,nbcards); + Targetable * t = NULL; + if (spell) t = spell->getNextPlayerTarget(); + MTGAbility * a = NEW AADrawer(id,card,t,NULL,nbcards,0,who); a->oneShot = 1; return a; } @@ -445,9 +453,10 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG }else{ nbcards = atoi(s.substr(start+1).c_str()); } - Player * player = NULL; - if (spell) player = spell->getNextPlayerTarget(); - MTGAbility * a = NEW AADepleter(id,card,player,nbcards); + + Targetable * t = NULL; + if (spell) t = spell->getNextPlayerTarget(); + MTGAbility * a = NEW AADepleter(id,card,t,nbcards,NULL,0,who); a->oneShot = 1; return a; } @@ -477,10 +486,9 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG nbcards = atoi(s.substr(start+1).c_str()); } - Player * player = NULL; - if (spell) player = spell->getNextPlayerTarget(); - if (!player) player = GameObserver::GetInstance()->currentlyActing(); - MTGAbility * a = NEW AARandomDiscarder (id, card, player,nbcards); + Targetable * t = NULL; + if (spell) t = spell->getNextPlayerTarget(); + MTGAbility * a = NEW AARandomDiscarder (id, card, t,nbcards,NULL,0,who); a->oneShot = 1; return a; } diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 2b377db7f..88ebc9ca4 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -59,6 +59,12 @@ MTGPlayerCards::~MTGPlayerCards(){ void MTGPlayerCards::setOwner(Player * player){ library->setOwner(player); + graveyard->setOwner(player); + hand->setOwner(player); + inPlay->setOwner(player); + removedFromGame->setOwner(player); + stack->setOwner(player); + garbage->setOwner(player); } void MTGPlayerCards::initGame(int shuffle, int draw){ @@ -122,12 +128,13 @@ MTGCardInstance * MTGPlayerCards::putInPlay(MTGCardInstance * card){ MTGCardInstance * MTGPlayerCards::putInGraveyard(MTGCardInstance * card){ MTGCardInstance * copy = NULL; + MTGGraveyard * grave = card->owner->game->graveyard; if (inPlay->hasCard(card)){ - copy = putInZone(card,inPlay, graveyard); + copy = putInZone(card,inPlay, grave); }else if (stack->hasCard(card)){ - copy = putInZone(card,stack, graveyard); + copy = putInZone(card,stack, grave); }else{ - copy = putInZone(card,hand, graveyard); + copy = putInZone(card,hand, grave); } return copy; @@ -223,7 +230,7 @@ MTGCardInstance * MTGGameZone::removeCard(MTGCardInstance * card, int createCopy if (card->isToken){ //TODO better than this ? return card; } - card->lastController = card->controller(); + //card->lastController = card->controller(); if (createCopy) { copy = NEW MTGCardInstance(card->model,card->owner->game); copy->previous = card; @@ -285,6 +292,7 @@ void MTGGameZone::addCard(MTGCardInstance * card){ cards.push_back(card); nb_cards++; cardsMap[card] = 1; + card->lastController = this->owner; }