Added / fixed primitives from ONE set, fixed Treasure name in all sets and primitives, updated missing cards by sets list, improved token creator ability by trying to retrieve the token id from the same set of source card (e.g. Urza's Saga), improved toxic ability adding a new target chooser "hastoxic" and adding a new keyword "toxicity" to retrieve the toxic amount of card.

This commit is contained in:
Vittorio Alfieri
2023-06-18 23:23:51 +02:00
parent 2ca092090d
commit 3b05932a8b
24 changed files with 487 additions and 295 deletions

View File

@@ -9,6 +9,15 @@ power=4
toughness=7
[/card]
[card]
name=Melira, the Living Cure
text=If you would get one or more poison counters, instead you get one poison counter and you can't get additional poison counters this turn. -- Exile Melira, the Living Cure: Choose another target creature or artifact. When it's put into a graveyard this turn, return that card to the battlefield under its owner's control.
mana={G}{W}
type=Legendary Creature
subtype=Human Scout
power=3
toughness=3
[/card]
[card]
name=Mirran Safehouse
text=As long as Mirran Safehouse is on the battlefield, it has all activated abilities of all land cards in all graveyards.
mana={3}
@@ -60,6 +69,15 @@ mana={3}
type=Artifact
[/card]
[card]
name=Melira, the Living Cure
text=If you would get one or more poison counters, instead you get one poison counter and you can't get additional poison counters this turn. -- Exile Melira, the Living Cure: Choose another target creature or artifact. When it's put into a graveyard this turn, return that card to the battlefield under its owner's control.
mana={G}{W}
type=Legendary Creature
subtype=Human Scout
power=3
toughness=3
[/card]
[card]
name=Drivnod, Carnage Dominus
text=If a creature dying causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. -- {B/P}{B/P}, Exile three creature cards from your graveyard: Put an indestructible counter on Drivnod, Carnage Dominus. ({B/P} can be paid with either {B} or 2 life.)
mana={3}{B}{B}

View File

@@ -16,12 +16,12 @@ id=-484906
rarity=T
[/card]
[card]
primitive=Treasure Sur
primitive=Treasure
id=-484904
rarity=T
[/card]
[card]
primitive=Treasure Shi
primitive=Treasure
id=-484902
rarity=T
[/card]

View File

@@ -81,7 +81,7 @@ id=-503834
rarity=T
[/card]
[card]
primitive=Treasure For
primitive=Treasure
id=-503827
rarity=T
[/card]
@@ -146,7 +146,7 @@ id=-503758
rarity=T
[/card]
[card]
primitive=Treasure Mag
primitive=Treasure
id=-503754
rarity=T
[/card]

View File

@@ -56,7 +56,7 @@ id=-485471
rarity=T
[/card]
[card]
primitive=Treasure Gad
primitive=Treasure
id=-485469
rarity=T
[/card]

View File

@@ -51,7 +51,7 @@ id=-53939511
rarity=T
[/card]
[card]
primitive=Treasure Sur
primitive=Treasure
id=-540753
rarity=T
[/card]

View File

@@ -31,7 +31,7 @@ id=-546993
rarity=T
[/card]
[card]
primitive=Treasure Sur
primitive=Treasure
id=-546992
rarity=T
[/card]

View File

@@ -133,8 +133,8 @@
# Explore, not implemented
#AUTO_DEFINE _EXPLORE_ reveal:1 optionone if type(land|reveal)~lessthan~1 then transforms((,newability[counter(1/1)])) optiononeend optiontwo if type(land|reveal)~morethan~0 then name(move to Hand) target(<1>*|reveal) moveto(myHand) else transforms((,newability[Choice name(back to library) target(<1>*|reveal) moveto(mylibrary)],newability[Choice name(put into Graveyard) target(<1>*|reveal) moveto(myGraveyard)])) optiontwoend revealend limit:1
# Treasure token, Set XLN
#AUTO_DEFINE _TREASURE_ token(Treasure Sur)
# Treasure token
#AUTO_DEFINE _TREASURE_ token(Treasure)
# Cast a historic spell
#AUTO_DEFINE _CASTHISTORIC_ @movedTo(*[artifact;legendary;saga]|mystack):

File diff suppressed because it is too large Load Diff

View File

@@ -3525,7 +3525,7 @@ name=Vraska, Betrayal's Sting
auto=if paid(alternative) then counter(0/0,4,loyalty)
auto=ifnot paid(alternative) then counter(0/0,6,loyalty)
auto={C(0/0,0,Loyalty)}:name(0: Draw card and lose life) draw:1 controller && life:-1 controller && _PROLIFERATE_
auto={C(0/0,-2,Loyalty)}:name(-2: Creature becomes treasure) target(creature|battlefield) flip(Treasure Sur)
auto={C(0/0,-2,Loyalty)}:name(-2: Creature becomes treasure) target(creature|battlefield) flip(Treasure)
auto={C(0/0,-9,Loyalty)}:name(-9: You get poison counter) alterpoison:9minusmypoisoncountminusend controller
auto={C(0/0,-9,Loyalty)}:name(-9: Opponent gets poison counter) alterpoison:9minusopponentpoisoncountminusend opponent
text=Compleated ({B/P} can be paid with {B} or 2 life. If life was paid, this planeswalker enters with two fewer loyalty counters.) -- [0]: You draw a card and you lose 1 life. Proliferate. -- [-2]: Target creature becomes a Treasure artifact with "{T}, Sacrifice this artifact: Add one mana of any color" and loses all other card types and abilities. -- [-9]: If target player has fewer than nine poison counters, they get a number of poison counters equal to the difference.

View File

@@ -2,7 +2,7 @@ grade=unsupported
#The cards in this file are not implemented/incomplete yet.
#Updated Card lists not in primitives (Borderline, Crappy, Unsupported and Missing Cards)
#Please keep these card alphabetized, and try to have the "name=" line at the top of each card
#I sorted this programatically - Vitty85 13-06-2023
#I sorted this programatically - Vitty85 18-06-2023
[card]
name="Ach! Hans, Run!"
text=At the beginning of your upkeep, you may say "Ach Hans, run It's the . . ." and name a creature card. If you do, search your library for the named card, put it into play, then shuffle your library. That creature has haste. Remove it from the game at end of turn.
@@ -6403,6 +6403,15 @@ mana={4}{R}
type=Instant
[/card]
[card]
name=Melira, the Living Cure
text=If you would get one or more poison counters, instead you get one poison counter and you can't get additional poison counters this turn. -- Exile Melira, the Living Cure: Choose another target creature or artifact. When it's put into a graveyard this turn, return that card to the battlefield under its owner's control.
mana={G}{W}
type=Legendary Creature
subtype=Human Scout
power=3
toughness=3
[/card]
[card]
name=Memory Crystal
text=Buyback costs cost {2} less.
mana={3}

View File

@@ -1747,7 +1747,7 @@ class ANewAffinity: public MTGAbility
public:
string tcString;
string manaString;
ANewAffinity(GameObserver* observer, int _id, MTGCardInstance * _source,string Tc = "", string mana ="");
ANewAffinity(GameObserver* observer, int _id, MTGCardInstance * _source, string Tc = "", string mana ="");
void Update(float dt);
int testDestroy();
ANewAffinity * clone() const;
@@ -3646,9 +3646,11 @@ public:
ActivatedAbility(observer, _id, _source, _cost, 0), _cardName(cardName), starfound(starfound), multiplier(multiplier), who(who), aLivingWeapon(aLivingWeapon)
{
if (!multiplier) this->multiplier = NEW WParsedInt(1);
MTGCard * card = MTGCollection()->getCardByName(_cardName);
tokenId = card->getId();
if (card) name = card->data->getName();
MTGCard * card = MTGCollection()->getCardByName(_cardName, _source->setId); // Try to retrieve token id from the same set of source card (e.g. Urza's Saga).
if (card) {
tokenId = card->getId();
name = card->data->getName();
}
battleReady = false;
andAbility = NULL;
cID = "";
@@ -3742,7 +3744,6 @@ public:
}
for (int i = 0; i < Tokenizer(); ++i)
{
//MTGCardInstance * myToken;
if (tokenId)
{
MTGCard * card = MTGCollection()->getCardById(tokenId);

View File

@@ -52,18 +52,20 @@ class CardDescriptor: public MTGCardInstance
int hasFlashbackCost;
int hasBackSide;
int modified;
int toxicity;
int hasPartner;
int hasXCost;
int anyCounter;
int init();
CardDescriptor();
void unsecureSetKicked(int i);
void unsecureSetHasKickerCost(int i);
void unsecureSetHasConvokeCost(int i);
void unsecureSetHasFlashbackCost(int i);
void unsecureSetHasBackSide(int i);
void unsecureSetModified(int i);
void unsecureSetHasPartner(int i);
void unsecureSetKicked(int k);
void unsecureSetHasKickerCost(int k);
void unsecureSetHasConvokeCost(int k);
void unsecureSetHasFlashbackCost(int k);
void unsecureSetHasBackSide(int k);
void unsecureSetModified(int k);
void unsecureSetHasToxic(int k);
void unsecureSetHasPartner(int k);
void unsecureSetTapped(int i);
void unsecuresetfresh(int k);
void unsecuresetrecent(int j);

View File

@@ -210,6 +210,7 @@ public:
int stepPower(CombatStep step);
int afterDamage();
int has(int ability);
int getToxicity();
int cleanup();
MTGCard * model;

View File

@@ -129,7 +129,7 @@ public:
void prefetchCardNameCache();
#endif
MTGCard * getCardByName(string name);
MTGCard * getCardByName(string name, int forcedSetId = -1);
void loadFolder(const string& folder, const string& filename="" );
int load(const string& config_file);

View File

@@ -225,7 +225,7 @@ class Constants
NOMANA = 97,
ONLYMANA = 98,
POISONDAMAGER = 99,
soulbond = 100,
SOULBOND = 100,
LURE = 101,
NOLEGEND = 102,
CANPLAYFROMGRAVEYARD = 103,
@@ -355,7 +355,14 @@ class Constants
AFFINITYATTACKINGCREATURES = 227,
AFFINITYGRAVEINSTSORC = 228,
CANLOYALTYTWICE = 229,
NB_BASIC_ABILITIES = 230,
POISONFOURTOXIC = 230,
POISONFIVETOXIC = 231,
POISONSIXTOXIC = 232,
POISONSEVENTOXIC = 233,
POISONEIGHTTOXIC = 234,
POISONNINETOXIC = 235,
POISONTENTOXIC = 236,
NB_BASIC_ABILITIES = 237,
RARITY_S = 'S', //Special Rarity
RARITY_M = 'M', //Mythics

View File

@@ -32,8 +32,9 @@ CardDescriptor::CardDescriptor()
hasBackSide = 0;
hasPartner = 0;
modified = 0;
toxicity = 0;
hasXCost = 0;
compareName ="";
compareName = "";
nameComparisonMode = COMPARISON_NONE;
colorComparisonMode = COMPARISON_NONE;
CDopponentDamaged = 0;
@@ -95,6 +96,11 @@ void CardDescriptor::unsecureSetModified(int k)
modified = k;
}
void CardDescriptor::unsecureSetHasToxic(int k)
{
toxicity = k;
}
void CardDescriptor::unsecureSetHasPartner(int k)
{
hasPartner = k;
@@ -367,6 +373,11 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card)
match = NULL;
}
if ((toxicity == -1 && card->getToxicity() > 0) || (toxicity == 1 && card->getToxicity() == 0))
{
match = NULL;
}
if ((hasPartner == -1 && card->partner != "") || (hasPartner == 1 && card->partner == ""))
{
match = NULL;

View File

@@ -1568,6 +1568,18 @@ bool CardGui::FilterCard(MTGCard * _card,string filter)
cd.unsecureSetModified(1);
}
}
//Has toxic
else if (attribute.find("hastoxic") != string::npos)
{
if (minus)
{
cd.unsecureSetHasToxic(-1);
}
else
{
cd.unsecureSetHasToxic(1);
}
}
//Has partner
else if (attribute.find("haspartner") != string::npos)
{

View File

@@ -7,6 +7,7 @@
#include "Translate.h"
#include "WResourceManager.h"
#include "GameObserver.h"
#include "WParsedInt.h"
Damage::Damage(GameObserver* observer, MTGCardInstance * source, Damageable * target)
: Interruptible(observer)
@@ -213,10 +214,9 @@ int Damage::resolve()
}
}
}
else if (target->type_as_damageable == Damageable::DAMAGEABLE_PLAYER && (source->has(Constants::POISONTOXIC) ||
source->has(Constants::POISONTWOTOXIC) || source->has(Constants::POISONTHREETOXIC)))
else if ((target->type_as_damageable == Damageable::DAMAGEABLE_PLAYER) && (source->getToxicity() > 0))
{
//Damage + 1, 2, or 3 poison counters on player
//Damage + poison counters on player
Player * _target = (Player *) target;
if(!_target->inPlay()->hasAbility(Constants::CANTCHANGELIFE))
a = target->dealDamage(damage);
@@ -234,20 +234,7 @@ int Damage::resolve()
}
if(!_target->inPlay()->hasAbility(Constants::POISONSHROUD))
{
int poison = 0;
if (source->has(Constants::POISONTOXIC))
{
poison = 1;
}
else if (source->has(Constants::POISONTWOTOXIC))
{
poison = 2;
}
else
{
poison = 3;
}
_target->poisonCount += poison;
_target->poisonCount += source->getToxicity();
WEvent * e = NEW WEventplayerPoisoned(_target, damage); // Added an event when player receives any poison counter.
_target->getObserver()->receiveEvent(e);
}

View File

@@ -583,6 +583,33 @@ int MTGCardInstance::has(int basicAbility)
return basicAbilities[basicAbility];
}
//Return the toxicity of card
int MTGCardInstance::getToxicity()
{
int toxicity = 0;
if(has(Constants::POISONTOXIC))
toxicity = 1;
else if(has(Constants::POISONTWOTOXIC))
toxicity = 2;
else if(has(Constants::POISONTHREETOXIC))
toxicity = 3;
else if(has(Constants::POISONFOURTOXIC))
toxicity = 4;
else if(has(Constants::POISONFIVETOXIC))
toxicity = 5;
else if(has(Constants::POISONSIXTOXIC))
toxicity = 6;
else if(has(Constants::POISONSEVENTOXIC))
toxicity = 7;
else if(has(Constants::POISONEIGHTTOXIC))
toxicity = 8;
else if(has(Constants::POISONNINETOXIC))
toxicity = 9;
else if(has(Constants::POISONTENTOXIC))
toxicity = 10;
return toxicity;
}
ManaCost* MTGCardInstance::getReducedManaCost()
{
return &reducedCost;

View File

@@ -822,7 +822,7 @@ void MTGAllCards::prefetchCardNameCache()
}
#endif
MTGCard * MTGAllCards::getCardByName(string nameDescriptor)
MTGCard * MTGAllCards::getCardByName(string nameDescriptor, int forcedSetId)
{
boost::mutex::scoped_lock lock(instance->mMutex);
if (!nameDescriptor.size()) return NULL;
@@ -832,7 +832,7 @@ MTGCard * MTGAllCards::getCardByName(string nameDescriptor)
map<string, MTGCard * >::iterator cached = mtgCardByNameCache.find(nameDescriptor);
if (cached!= mtgCardByNameCache.end())
if ((forcedSetId < 0) && (cached!= mtgCardByNameCache.end()))
{
return cached->second;
}
@@ -845,6 +845,21 @@ MTGCard * MTGAllCards::getCardByName(string nameDescriptor)
return result;
}
map<int, MTGCard *>::iterator it;
if(forcedSetId != -1){
for (it = collection.begin(); it != collection.end(); it++)
{
MTGCard * c = it->second;
if (forcedSetId != c->setId) continue;
string cardName = c->data->name;
std::transform(cardName.begin(), cardName.end(), cardName.begin(), ::tolower);
if (cardName.compare(nameDescriptor) == 0) {
mtgCardByNameCache[nameDescriptor] = c;
return c;
}
}
}
int setId = -1;
size_t found = nameDescriptor.find(" (");
string name = nameDescriptor;
@@ -859,9 +874,8 @@ MTGCard * MTGAllCards::getCardByName(string nameDescriptor)
//Reconstruct a clean string "name (set)" for cache consistency
nameDescriptor = name + " (" + setName + ")";
}
map<int, MTGCard *>::iterator it;
for (it = collection.begin(); it != collection.end(); it++)
{
MTGCard * c = it->second;
@@ -872,8 +886,8 @@ MTGCard * MTGAllCards::getCardByName(string nameDescriptor)
mtgCardByNameCache[nameDescriptor] = c;
return c;
}
}
mtgCardByNameCache[nameDescriptor] = NULL;
return NULL;
}

View File

@@ -80,9 +80,9 @@ const char* Constants::MTGBasicAbilities[] = {
"cantregen",
"oneblocker",
"infect",
"poisontoxic",
"poisontwotoxic",
"poisonthreetoxic",
"poisontoxic", // Card has toxic 1
"poisontwotoxic", // Card has toxic 2
"poisonthreetoxic", // Card has toxic 3
"phantom",//prevents damage and remove 1 +1/+1 counter
"wilting",//source takes damage in the form of -1/-1 counters.
"vigor",//instead of taking damage the source gains +1/+1 counters
@@ -260,7 +260,14 @@ const char* Constants::MTGBasicAbilities[] = {
"affinitygravecreatures", //Cost 1 less for each creature in your graveyard.
"affinityattackingcreatures", //Cost 1 less for each attacking creature in your battlefield.
"affinitygraveinstsorc", //Cost 1 less for each instant or sorcery in your graveyard.
"canloyaltytwice" //Planeswalker can activate its loyalty abilities twice in a turn (e.g. "Urza, Planeswalker").
"canloyaltytwice", //Planeswalker can activate its loyalty abilities twice in a turn (e.g. "Urza, Planeswalker").
"poisonfourtoxic", // Card has toxic 4
"poisonfivetoxic", // Card has toxic 5
"poisonsixtoxic", // Card has toxic 6
"poisonseventoxic", // Card has toxic 7
"poisoneighttoxic", // Card has toxic 8
"poisonninetoxic", // Card has toxic 9
"poisontentoxic" // Card has toxic 10
};
map<string,int> Constants::MTGBasicAbilitiesMap;

View File

@@ -3063,7 +3063,7 @@ int MTGSoulbondRule::receiveEvent(WEvent * event)
MTGCardInstance * card = e->card;
if (!card || !card->isCreature()) return 0;
int ok = 0;
if(card->has(Constants::soulbond) || soulbonders.size())
if(card->has(Constants::SOULBOND) || soulbonders.size())
{
for (int i = 0; i < 2; i++)
{
@@ -3071,7 +3071,7 @@ int MTGSoulbondRule::receiveEvent(WEvent * event)
if (e->to == p->game->inPlay)
{
ok = 1;
if(card->basicAbilities[(int)Constants::soulbond])
if(card->basicAbilities[(int)Constants::SOULBOND])
soulbonders.push_back(e->card);
}
}

View File

@@ -663,6 +663,18 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
cd->unsecureSetModified(1);
}
}
//Has toxic
else if (attribute.find("hastoxic") != string::npos)
{
if (minus)
{
cd->unsecureSetHasToxic(-1);
}
else
{
cd->unsecureSetHasToxic(1);
}
}
//Has partner
else if (attribute.find("haspartner") != string::npos)
{
@@ -2237,7 +2249,7 @@ bool pairableChooser::canTarget(Targetable * target,bool)
return false;
if(card->controller() != source->controller())
return false;
if(!card->has(Constants::soulbond) && !source->has(Constants::soulbond))
if(!card->has(Constants::SOULBOND) && !source->has(Constants::SOULBOND))
return false;
return true;
}

View File

@@ -1619,6 +1619,29 @@ void WParsedInt::extendedParse(string s, Spell * spell, MTGCardInstance * card)
intValue = card->getManaCost()->getManaUsedToCast()->getConvertedCost();
}
}
else if(s.find("toxicity") != string::npos){ //Return the toxicity of card.
intValue = card->getToxicity();
}
else if (s.find("ninelands") != string::npos) //Count the number of lands with different names among the Basic, Sphere, and Locus lands you control.
{
intValue = 0;
vector<string> list;
for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j)
{
if (card->controller()->game->inPlay->cards[j]->isLand() &&
(card->controller()->game->inPlay->cards[j]->hasType("basic") || card->controller()->game->inPlay->cards[j]->hasType("sphere") || card->controller()->game->inPlay->cards[j]->hasType("locus"))){
bool name_found = false;
for(unsigned int i = 0; i < list.size() && !name_found; i++){
if(list[i] == card->controller()->game->inPlay->cards[j]->name)
name_found = true;
}
if(!name_found){
list.push_back(card->controller()->game->inPlay->cards[j]->name);
intValue += 1;
}
}
}
}
else if(!intValue)//found nothing, try parsing a atoi
{
intValue = atoi(s.c_str());