Fixed Etchings of the Chosen (issue #1051 by @ranger7271), added primitives with choose card name, added two keywords "chooseaname" and "chooseanameopp" to choose a card name ("chosenname" and "lastchoosenname") between your cards or opponent cards, added a keyword "[attached]" to target equipment attached to a permanent.

This commit is contained in:
Vittorio Alfieri
2021-01-26 20:47:33 +01:00
parent c60f8787d1
commit dd844fc25e
15 changed files with 288 additions and 86 deletions
+98 -8
View File
@@ -2739,14 +2739,15 @@ AAProliferate::~AAProliferate()
{
}
//
//choosing a type or color
GenericChooseTypeColor::GenericChooseTypeColor(GameObserver* observer, int id, MTGCardInstance * source, Targetable *,string _toAdd,bool chooseColor,bool nonwall, ManaCost * cost) :
ActivatedAbility(observer, id, source, cost, 0), baseAbility(_toAdd),chooseColor(chooseColor),ANonWall(nonwall)
//choosing a type or color or name
GenericChooseTypeColorName::GenericChooseTypeColorName(GameObserver* observer, int id, MTGCardInstance * source, Targetable *, string _toAdd, bool chooseColor, bool chooseName, bool chooseOppName, bool nonwall, bool nonbasicland, bool nonland, ManaCost * cost) :
ActivatedAbility(observer, id, source, cost, 0), baseAbility(_toAdd),chooseColor(chooseColor),chooseName(chooseName),chooseOppName(chooseOppName),ANonWall(nonwall),ANonBasicLand(nonbasicland),ANonLand(nonland)
{
this->GetId();
setColor = NULL;
setName = NULL;
}
int GenericChooseTypeColor::resolve()
int GenericChooseTypeColorName::resolve()
{
if (!target)
return 0;
@@ -2762,6 +2763,33 @@ int GenericChooseTypeColor::resolve()
SAFE_DELETE(setColor);
}
}
else if(chooseName || chooseOppName)
{
vector<string> names;
Player* p = (chooseName)?source->controller():source->controller()->opponent();
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile, p->game->commandzone, p->game->sideboard, p->game->reveal };
for (int k = 0; k < 9; k++){
MTGGameZone * zone = zones[k];
for (int j = zone->nb_cards - 1; j >= 0; --j){
if ((!ANonBasicLand || (!zone->cards[j]->hasType(Subtypes::TYPE_BASIC) && !zone->cards[j]->hasType(Subtypes::TYPE_LAND))) && (!ANonLand || !zone->cards[j]->hasType(Subtypes::TYPE_LAND))){
bool added = false;
for (int i = names.size() - 1; i >= 0; --i)
if(names[i] == zone->cards[j]->name)
added = true;
if(!added)
names.push_back(zone->cards[j]->name);
}
}
}
for (size_t i = 0; i < names.size(); ++i){
string menu = names[i];
setName = NEW AASetNameChosen(game, game->mLayers->actionLayer()->getMaxId(), source, (MTGCardInstance*)target, names[i], menu, baseAbility);
MTGAbility * set = setName->clone();
set->oneShot = true;
selection.push_back(set);
SAFE_DELETE(setName);
}
}
else
{
vector<string> values = MTGAllCards::getCreatureValuesById();
@@ -2789,21 +2817,23 @@ int GenericChooseTypeColor::resolve()
}
const string GenericChooseTypeColor::getMenuText()
const string GenericChooseTypeColorName::getMenuText()
{
if(chooseColor)
return "Choose a color";
if(chooseName || chooseOppName)
return "Choose a name";
else
return "Choose a type";
}
GenericChooseTypeColor * GenericChooseTypeColor::clone() const
GenericChooseTypeColorName * GenericChooseTypeColorName::clone() const
{
GenericChooseTypeColor * a = NEW GenericChooseTypeColor(*this);
GenericChooseTypeColorName * a = NEW GenericChooseTypeColorName(*this);
return a;
}
GenericChooseTypeColor::~GenericChooseTypeColor()
GenericChooseTypeColorName::~GenericChooseTypeColorName()
{
}
@@ -2922,6 +2952,64 @@ AASetTypeChosen::~AASetTypeChosen()
{
}
//set name choosen
AASetNameChosen::AASetNameChosen(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target,string _name ,string _menu,string toAlter):
InstantAbility(observer, id, source),name(_name), abilityToAlter(toAlter), menutext(_menu)
{
this->target = _target;
abilityAltered = NULL;
}
int AASetNameChosen::resolve()
{
MTGCardInstance * _target = (MTGCardInstance *)target;
string nameChoosen = menutext;
_target->chooseaname = nameChoosen;
_target->controller()->lastChosenName = nameChoosen;
if(abilityToAlter.size())
{
AbilityFactory af(game);
abilityAltered = af.parseMagicLine(abilityToAlter, 0, NULL, _target);
if(abilityAltered->oneShot)
{
abilityAltered->resolve();
SAFE_DELETE(abilityAltered);
}
else
{
abilityAltered->target = _target;
MayAbility * dontAdd = dynamic_cast<MayAbility*>(abilityAltered);
if (!dontAdd)
{
_target->cardsAbilities.push_back(abilityAltered);
for(unsigned int j = 0;j < _target->cardsAbilities.size();++j)
{
if(_target->cardsAbilities[j] == this)
_target->cardsAbilities.erase(_target->cardsAbilities.begin() + j);
}
}
abilityAltered->addToGame();
}
_target->skipDamageTestOnce = true;//some cards rely on this ability updating before damage test are run. otherwise they die before toughnes bonus applies.
}
return 1;
}
const string AASetNameChosen::getMenuText()
{
return menutext.c_str();
}
AASetNameChosen * AASetNameChosen::clone() const
{
return NEW AASetNameChosen(*this);
}
AASetNameChosen::~AASetNameChosen()
{
}
//
//choosing flip coin
GenericFlipACoin::GenericFlipACoin(GameObserver* observer, int id, MTGCardInstance * source, Targetable *,string _toAdd, ManaCost * cost) :
@@ -4261,6 +4349,8 @@ int AAFlip::resolve()
{
if(flipStats == "myorigname" && _target->nameOrig != "")
flipStats = _target->nameOrig; // Added to undo the copy effect at end of turn for a generic card (es. Shapeshifter transformations).
else if(flipStats == "chosenname" && _target->chooseaname != "")
flipStats = _target->chooseaname; // Added to allow the transformation of a card in a choosen name.
MTGCard * fcard = MTGCollection()->getCardByName(flipStats);
if(!fcard) return 0;
MTGCardInstance * myFlip = NEW MTGCardInstance(fcard, _target->controller()->game);
+7 -1
View File
@@ -31,6 +31,7 @@ CardDescriptor::CardDescriptor()
CDcontrollerDamaged = 0;
CDdamager = 0;
CDgeared = 0;
CDattached = 0;
CDblocked = 0;
CDcanProduceC = 0;
CDcanProduceG = 0;
@@ -293,7 +294,12 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card)
{
match = NULL;
}
if ((CDattached == -1 && card->parentCards.size() > 0) || (CDattached == 1 && card->parentCards.size() < 1))
{
match = NULL;
}
if (CDblocked == -1)
{
if(!card->isAttacker())
+21
View File
@@ -512,6 +512,16 @@ void CardGui::Render()
mFont->DrawString(buffer, actX - 10 * actZ, actY - (25.3f * actZ));
mFont->SetScale(1);
}
if(card->chooseaname.size() && !alternate && game)
{
mFont->SetScale(DEFAULT_MAIN_FONT_SCALE);
char buffer[200];
sprintf(buffer, "%s", card->chooseaname.c_str());
mFont->SetColor(ARGB(static_cast<unsigned char>(actA),255,215,0));//Gold indicator
mFont->SetScale(0.8f);
mFont->DrawString(buffer, actX - 10 * actZ, actY - (25.3f * actZ));
mFont->SetScale(1);
}
if(!alternate && buff != "" && game)
{
mFont->SetScale(DEFAULT_MAIN_FONT_SCALE);
@@ -1568,6 +1578,17 @@ bool CardGui::FilterCard(MTGCard * _card,string filter)
cd.CDgeared = 1;
}
}
else if (attribute.find("attached") != string::npos)
{
if (minus)
{
cd.CDattached = -1;
}
else
{
cd.CDattached = 1;
}
}
//creature is a level up creature
else if (attribute.find("leveler") != string::npos)
{
+1 -1
View File
@@ -278,7 +278,7 @@ int Damage::resolve()
}
}
if (target->type_as_damageable == Damageable::DAMAGEABLE_MTGCARDINSTANCE && ((MTGCardInstance*)target)->hasType(Subtypes::TYPE_PLANESWALKER)){ // Fix life calculation for planeswalker damage.
if (target->type_as_damageable == Damageable::DAMAGEABLE_MTGCARDINSTANCE && ((MTGCardInstance*)target)->hasType(Subtypes::TYPE_PLANESWALKER)){ // Fix life calculation for planeswalker damage.
if (((MTGCardInstance*)target)->counters){
Counters * counters = ((MTGCardInstance*)target)->counters;
for(size_t i = 0; i < counters->counters.size(); ++i){
+17 -5
View File
@@ -1778,7 +1778,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
}
if (StartsWith(s, "chooseacolor ") || StartsWith(s, "chooseatype "))
if (StartsWith(s, "chooseacolor ") || StartsWith(s, "chooseatype ") || StartsWith(s, "chooseaname"))
{
MTGAbility * choose = parseChooseActionAbility(s,card,spell,target,0,id);
choose = NEW GenericActivatedAbility(observer, "","",id, card,choose,NULL);
@@ -4807,7 +4807,7 @@ MTGAbility * AbilityFactory::parseChooseActionAbility(string s,MTGCardInstance *
if (splitChooseAColor2.size())
{
string a1 = splitChooseAColor2[1];
MTGAbility * a = NEW GenericChooseTypeColor(observer, id, card, target,a1,true);
MTGAbility * a = NEW GenericChooseTypeColorName(observer, id, card, target,a1,true);
a->oneShot = 1;
a->canBeInterrupted = false;
return a;
@@ -4817,7 +4817,7 @@ MTGAbility * AbilityFactory::parseChooseActionAbility(string s,MTGCardInstance *
if (splitChooseAType2.size())
{
string a1 = splitChooseAType2[1];
MTGAbility * a = NEW GenericChooseTypeColor(observer, id, card, target,a1,false,s.find("nonwall")!=string::npos);
MTGAbility * a = NEW GenericChooseTypeColorName(observer, id, card, target,a1,false,false,false,s.find("nonwall")!=string::npos);
a->oneShot = 1;
a->canBeInterrupted = false;
return a;
@@ -4827,7 +4827,7 @@ MTGAbility * AbilityFactory::parseChooseActionAbility(string s,MTGCardInstance *
if (splitChooseAColor.size())
{
string a1 = splitChooseAColor[1];
MTGAbility * a = NEW GenericChooseTypeColor(observer, id, card, target,a1,true);
MTGAbility * a = NEW GenericChooseTypeColorName(observer, id, card, target,a1,true);
a->oneShot = 1;
a->canBeInterrupted = false;
return a;
@@ -4837,7 +4837,19 @@ MTGAbility * AbilityFactory::parseChooseActionAbility(string s,MTGCardInstance *
if (splitChooseAType.size())
{
string a1 = splitChooseAType[1];
MTGAbility * a = NEW GenericChooseTypeColor(observer, id, card, target,a1,false,s.find("nonwall")!=string::npos);
MTGAbility * a = NEW GenericChooseTypeColorName(observer, id, card, target,a1,false,false,false,s.find("nonwall")!=string::npos);
a->oneShot = 1;
a->canBeInterrupted = false;
return a;
}
//choose a name
vector<string> splitChooseAName = parseBetween(s, "chooseaname ", " chooseend");
vector<string> splitChooseAOppName = parseBetween(s, "chooseanameopp ", " chooseend");
if (splitChooseAName.size() || splitChooseAOppName.size())
{
bool oppName = (splitChooseAOppName.size() > 0);
string a1 = oppName?splitChooseAOppName[1]:splitChooseAName[1];
MTGAbility * a = NEW GenericChooseTypeColorName(observer, id, card, target,a1,false,!oppName,oppName,false,s.find("nonbasicland")!=string::npos,s.find("nonland")!=string::npos);
a->oneShot = 1;
a->canBeInterrupted = false;
return a;
+1
View File
@@ -261,6 +261,7 @@ void MTGCardInstance::initMTGCI()
zpos = 0;
chooseacolor = -1;
chooseasubtype = "";
chooseaname = "";
coinSide = -1;
lastFlipResult = -1;
dieSide = 0;
+1
View File
@@ -51,6 +51,7 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
snowManaU = 0;
snowManaW = 0;
snowManaC = 0;
lastChosenName = "";
prowledTypes.clear();
doesntEmpty = NEW ManaCost();
poolDoesntEmpty = NEW ManaCost();
+1
View File
@@ -607,6 +607,7 @@ void Rules::initGame(GameObserver *g, bool currentPlayerSet)
p->monarch = initState.playerData[i].player->monarch;
p->surveilOffset = initState.playerData[i].player->surveilOffset;
p->devotionOffset = initState.playerData[i].player->devotionOffset;
p->lastChosenName = initState.playerData[i].player->lastChosenName;
if (initState.playerData[i].player->mAvatarName.size())
{
p->mAvatarName = initState.playerData[i].player->mAvatarName;
+31
View File
@@ -607,6 +607,17 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
cd->CDgeared = 1;
}
}
else if (attribute.find("attached") != string::npos)
{
if (minus)
{
cd->CDattached = -1;
}
else
{
cd->CDattached = 1;
}
}
//creature is a level up creature
else if (attribute.find("leveler") != string::npos)
{
@@ -953,6 +964,26 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
}
}
if (attribute.find("chosenname") != string::npos && card->chooseaname != "")
{
attributefound = 1;
cd->compareName = card->chooseaname;
if (minus)
cd->nameComparisonMode = COMPARISON_UNEQUAL;
else
cd->nameComparisonMode = COMPARISON_EQUAL;
}
if (attribute.find("lastnamechosen") != string::npos && card->controller()->lastChosenName != "")
{
attributefound = 1;
cd->compareName = card->controller()->lastChosenName;
if (minus)
cd->nameComparisonMode = COMPARISON_UNEQUAL;
else
cd->nameComparisonMode = COMPARISON_EQUAL;
}
if (attribute.find("evictname") != string::npos && card->imprintedCards.size())
{
attributefound = 1;