Added/fixed primitives, fixed crash with Taj-Nar Swordsmith, Fixed monarch switch after player takes combat damage, fixed allsubtypes in transforms keyword, fixed controllerdamager and opponentdamager keywords and all primitives using them, fixed Emerge alternative cost restriction, fixed Kinship condition on same creature subtype, added alterexperience keyword and fixed all primitives that use experience counters, fixed all primitives using ability counters from Ikoria, fixed mypoolsave keyword in order to don't finish effect at the end of turn, fixed all primitives using mypoolsave (e.g. Omnath, Locus of Mana), fixed Gravepurge and Daretti, Scrap Savant, in order to allow the player to discard zero cards while using their effects.
This commit is contained in:
@@ -1376,6 +1376,8 @@ int AAAlterEnergy::resolve()
|
||||
if(pTarget)
|
||||
{
|
||||
pTarget->energyCount += energy;
|
||||
if(pTarget->energyCount < 0)
|
||||
pTarget->energyCount = 0;
|
||||
if(energy > 0)
|
||||
{
|
||||
WEvent * e = NEW WEventplayerEnergized(pTarget, energy);
|
||||
@@ -1401,6 +1403,49 @@ AAAlterEnergy::~AAAlterEnergy()
|
||||
{
|
||||
}
|
||||
|
||||
//AA Experience Counters
|
||||
AAAlterExperience::AAAlterExperience(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int experience, ManaCost * _cost,
|
||||
int who) :
|
||||
ActivatedAbilityTP(observer, _id, _source, _target, _cost, who), experience(experience)
|
||||
{
|
||||
}
|
||||
|
||||
int AAAlterExperience::resolve()
|
||||
{
|
||||
Damageable * _target = (Damageable *) getTarget();
|
||||
if (_target)
|
||||
{
|
||||
Player * pTarget = (Player*)_target;
|
||||
if(pTarget)
|
||||
{
|
||||
pTarget->experienceCount += experience;
|
||||
if(pTarget->experienceCount < 0)
|
||||
pTarget->experienceCount = 0;
|
||||
if(experience > 0)
|
||||
{
|
||||
WEvent * e = NEW WEventplayerExperienced(pTarget, experience);
|
||||
game->receiveEvent(e);
|
||||
}//todo loses experience event
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const string AAAlterExperience::getMenuText()
|
||||
{
|
||||
WParsedInt parsedNum(experience);
|
||||
return _(parsedNum.getStringValue() + " Experience ").c_str();
|
||||
}
|
||||
|
||||
AAAlterExperience * AAAlterExperience::clone() const
|
||||
{
|
||||
return NEW AAAlterExperience(*this);
|
||||
}
|
||||
|
||||
AAAlterExperience::~AAAlterExperience()
|
||||
{
|
||||
}
|
||||
|
||||
//Damage Prevent
|
||||
AADamagePrevent::AADamagePrevent(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int preventing, ManaCost * _cost,
|
||||
int who) :
|
||||
@@ -2615,6 +2660,12 @@ int AARemoveSingleCounter::resolve()
|
||||
a->oneShot = true;
|
||||
pcounters.push_back(a);
|
||||
}
|
||||
else if(pTarget && pTarget->experienceCount)
|
||||
{
|
||||
MTGAbility * a = NEW AAAlterExperience(game, game->mLayers->actionLayer()->getMaxId(), source, target, -nb, NULL);
|
||||
a->oneShot = true;
|
||||
pcounters.push_back(a);
|
||||
}
|
||||
else if (cTarget && cTarget->counters)
|
||||
{
|
||||
Counters * counters = cTarget->counters;
|
||||
@@ -2688,6 +2739,16 @@ int AADuplicateCounters::resolve()
|
||||
a->oneShot = true;
|
||||
pcounters.push_back(a);
|
||||
}
|
||||
else if(pTarget && pTarget->experienceCount)
|
||||
{
|
||||
MTGAbility * a = NULL;
|
||||
if(single)
|
||||
a = NEW AAAlterExperience(game, game->mLayers->actionLayer()->getMaxId(), source, target, 1, NULL);
|
||||
else
|
||||
a = NEW AAAlterExperience(game, game->mLayers->actionLayer()->getMaxId(), source, target, pTarget->experienceCount, NULL);
|
||||
a->oneShot = true;
|
||||
pcounters.push_back(a);
|
||||
}
|
||||
else if (cTarget && cTarget->counters)
|
||||
{
|
||||
Counters * counters = cTarget->counters;
|
||||
@@ -2768,6 +2829,12 @@ int AAProliferate::resolve()
|
||||
a->oneShot = true;
|
||||
pcounters.push_back(a);
|
||||
}
|
||||
else if(pTarget && pTarget->experienceCount && pTarget == source->controller())
|
||||
{
|
||||
MTGAbility * a = NEW AAAlterExperience(game, game->mLayers->actionLayer()->getMaxId(), source, target, 1, NULL);
|
||||
a->oneShot = true;
|
||||
pcounters.push_back(a);
|
||||
}
|
||||
else if (cTarget && cTarget->counters)
|
||||
{
|
||||
Counters * counters = cTarget->counters;
|
||||
@@ -3517,23 +3584,37 @@ GenericPaidAbility::~GenericPaidAbility()
|
||||
SAFE_DELETE(baseAbility);
|
||||
}
|
||||
|
||||
//saves a listed mana type until end of turn.
|
||||
AManaPoolSaver::AManaPoolSaver(GameObserver* observer, int id, MTGCardInstance * source,string color, bool otherPlayer) :
|
||||
MTGAbility(observer, id, source),Color(color),OtherPlayer(otherPlayer)
|
||||
//saves a listed mana type.
|
||||
AManaPoolSaver::AManaPoolSaver(GameObserver* observer, int id, MTGCardInstance * source,string color, bool otherPlayer, bool removePool) :
|
||||
MTGAbility(observer, id, source),Color(color),OtherPlayer(otherPlayer),RemovePool(removePool)
|
||||
{
|
||||
}
|
||||
|
||||
int AManaPoolSaver::addToGame()
|
||||
{
|
||||
int colorInt = Constants::GetColorStringIndex(Color.c_str());
|
||||
source->controller()->poolDoesntEmpty->add(colorInt,1);
|
||||
if(OtherPlayer){
|
||||
if(RemovePool)
|
||||
source->controller()->opponent()->poolDoesntEmpty->remove(colorInt,1);
|
||||
else
|
||||
source->controller()->opponent()->poolDoesntEmpty->add(colorInt,1);
|
||||
}
|
||||
else {
|
||||
if(RemovePool)
|
||||
source->controller()->poolDoesntEmpty->remove(colorInt,1);
|
||||
else
|
||||
source->controller()->poolDoesntEmpty->add(colorInt,1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AManaPoolSaver::destroy()
|
||||
{
|
||||
int colorInt = Constants::GetColorStringIndex(Color.c_str());
|
||||
source->controller()->poolDoesntEmpty->remove(colorInt,1);
|
||||
if(OtherPlayer)
|
||||
source->controller()->opponent()->poolDoesntEmpty->remove(colorInt,1);
|
||||
else
|
||||
source->controller()->poolDoesntEmpty->remove(colorInt,1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -6099,6 +6180,22 @@ int AARemoveMana::resolve()
|
||||
return 1;
|
||||
}
|
||||
manaPool->Empty();
|
||||
}
|
||||
else if(game->getCurrentGamePhase() == MTG_PHASE_ENDOFTURN && !forceclean)
|
||||
{
|
||||
if(player->poolDoesntEmpty->getConvertedCost())
|
||||
{
|
||||
ManaCost * toSave = NEW ManaCost();
|
||||
for(int k = Constants::MTG_COLOR_ARTIFACT; k < Constants::NB_Colors;k++)
|
||||
{
|
||||
if(player->poolDoesntEmpty->getCost(k))
|
||||
toSave->add(k,manaPool->getCost(k));
|
||||
}
|
||||
player->getManaPool()->pay(manaPool->Diff(toSave));
|
||||
delete(toSave);
|
||||
return 1;
|
||||
}
|
||||
manaPool->Empty();
|
||||
}
|
||||
else
|
||||
manaPool->Empty();
|
||||
@@ -7144,14 +7241,9 @@ ATransformer::ATransformer(GameObserver* observer, int id, MTGCardInstance * sou
|
||||
|
||||
if (stypes.find("allsubtypes") != string::npos || stypes.find("removecreaturesubtypes") != string::npos)
|
||||
{
|
||||
const vector<string> values = MTGAllCards::getValuesById();
|
||||
for (size_t i = 0; i <values.size(); ++i)
|
||||
{
|
||||
if (!MTGAllCards::isSubtypeOfType(i,Subtypes::TYPE_CREATURE))
|
||||
continue;
|
||||
|
||||
types.push_back(i);
|
||||
}
|
||||
const vector<string> values = MTGAllCards::getCreatureValuesById();
|
||||
for (size_t i = 0; i < values.size(); ++i)
|
||||
types.push_back(MTGAllCards::findType(values.at(i)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -411,9 +411,9 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card)
|
||||
match = NULL;
|
||||
}
|
||||
|
||||
if(CDopponentDamaged == -1 || CDopponentDamaged == 1)
|
||||
if(CDopponentDamaged == -1 || CDopponentDamaged == 1 || CDcontrollerDamaged == -1 || CDcontrollerDamaged == 1)
|
||||
{
|
||||
Player * p = card->controller()->opponent();//controller()->opponent();
|
||||
Player * p = card->controller();
|
||||
if ((CDopponentDamaged == -1 && card->damageToOpponent && card->controller() == p)
|
||||
|| (CDopponentDamaged == 1 && !card->damageToOpponent && card->controller() == p)
|
||||
|| (CDopponentDamaged == -1 && card->damageToController && card->controller() == p->opponent())
|
||||
|
||||
@@ -33,6 +33,7 @@ void GuiAvatar::Render()
|
||||
int life = player->life;
|
||||
int poisonCount = player->poisonCount;
|
||||
int energyCount = player->energyCount;
|
||||
int experienceCount = player->experienceCount;
|
||||
WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
|
||||
mFont->SetScale(DEFAULT_MAIN_FONT_SCALE);
|
||||
TargetChooser * tc = NULL;
|
||||
@@ -166,6 +167,23 @@ void GuiAvatar::Render()
|
||||
break;
|
||||
}
|
||||
}
|
||||
//experience
|
||||
char experience[15];
|
||||
if (experienceCount > 0)
|
||||
{
|
||||
sprintf(experience, "%i", experienceCount);
|
||||
switch (corner)
|
||||
{
|
||||
case TOP_LEFT:
|
||||
mFont->SetColor(ARGB((int)actA / 1, 255, 0, 255));
|
||||
mFont->DrawString(experience, actX + 2, actY + 24);
|
||||
break;
|
||||
case BOTTOM_RIGHT:
|
||||
mFont->SetColor(ARGB((int)actA / 1 ,255, 0, 255));
|
||||
mFont->DrawString(experience, actX - 10, actY - 27, JGETEXT_RIGHT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
PlayGuiObject::Render();
|
||||
}
|
||||
|
||||
|
||||
@@ -1192,7 +1192,6 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell
|
||||
attackingTrigger,attackedAloneTrigger,notBlockedTrigger,attackBlockedTrigger,blockingTrigger);
|
||||
}
|
||||
|
||||
|
||||
//energized player - controller of card
|
||||
if (TargetChooser * tc = parseSimpleTC(s, "energizedof", card))
|
||||
return NEW TrplayerEnergized(observer, id, card, tc,once,true,false);
|
||||
@@ -1201,6 +1200,14 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell
|
||||
if (TargetChooser * tc = parseSimpleTC(s, "energizedfoeof", card))
|
||||
return NEW TrplayerEnergized(observer, id, card, tc,once,false,true);
|
||||
|
||||
//experienced player - controller of card
|
||||
if (TargetChooser * tc = parseSimpleTC(s, "experiencedof", card))
|
||||
return NEW TrplayerExperienced(observer, id, card, tc,once,true,false);
|
||||
|
||||
//experienced player - opponent of card controller
|
||||
if (TargetChooser * tc = parseSimpleTC(s, "experiencedfoeof", card))
|
||||
return NEW TrplayerExperienced(observer, id, card, tc,once,false,true);
|
||||
|
||||
//becomes monarch - controller of card
|
||||
if (TargetChooser * tc = parseSimpleTC(s, "becomesmonarchof", card))
|
||||
return NEW TrplayerMonarch(observer, id, card, tc,once,true,false);
|
||||
@@ -2619,14 +2626,15 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
return NEW APaired(observer,id, card,card->myPair,a);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//mana of the listed type doesnt get emptied from the pools.
|
||||
vector<string>colorType = parseBetween(s,"poolsave(",")",false);
|
||||
if (colorType.size())
|
||||
{
|
||||
return NEW AManaPoolSaver(observer,id, card,colorType[1],s.find("opponentpool")!=string::npos);
|
||||
return NEW AManaPoolSaver(observer, id, card, colorType[1], s.find("opponentpool")!=string::npos, s.find("terminate") != string::npos);// Added a way to terminate effect when source card leave battlefield.
|
||||
}
|
||||
|
||||
//opponent replace draw with
|
||||
//opponent replace draw with
|
||||
found = s.find("opponentreplacedraw ");
|
||||
if (found != string::npos)
|
||||
{
|
||||
@@ -3690,6 +3698,17 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
return a;
|
||||
}
|
||||
|
||||
//alter experience
|
||||
vector<string> splitExperience = parseBetween(s, "alterexperience:", " ", false);
|
||||
if (splitExperience.size())
|
||||
{
|
||||
int exp = atoi(splitExperience[1].c_str());
|
||||
Targetable * t = spell ? spell->getNextTarget() : NULL;
|
||||
MTGAbility * a = NEW AAAlterExperience(observer, id, card, t, exp, NULL, who);
|
||||
a->oneShot = 1;
|
||||
return a;
|
||||
}
|
||||
|
||||
//alter dungeon completed
|
||||
vector<string> splitDungeonCompleted = parseBetween(s, "completedungeon:", " ", false);
|
||||
if (splitDungeonCompleted.size())
|
||||
|
||||
@@ -35,6 +35,7 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
|
||||
extraTurn = 0;
|
||||
drawCounter = 0;
|
||||
energyCount = 0;
|
||||
experienceCount = 0;
|
||||
yidaroCount = 0;
|
||||
dungeonCompleted = 0;
|
||||
numOfCommandCast = 0;
|
||||
|
||||
@@ -602,6 +602,7 @@ void Rules::initGame(GameObserver *g, bool currentPlayerSet)
|
||||
p->damageCount = initState.playerData[i].player->damageCount;
|
||||
p->preventable = initState.playerData[i].player->preventable;
|
||||
p->energyCount = initState.playerData[i].player->energyCount;
|
||||
p->experienceCount = initState.playerData[i].player->experienceCount;
|
||||
p->yidaroCount = initState.playerData[i].player->yidaroCount;
|
||||
p->dungeonCompleted = initState.playerData[i].player->dungeonCompleted;
|
||||
p->numOfCommandCast = initState.playerData[i].player->numOfCommandCast;
|
||||
|
||||
@@ -287,6 +287,11 @@ WEventplayerEnergized::WEventplayerEnergized(Player * player, int nb_count) :
|
||||
{
|
||||
}
|
||||
|
||||
WEventplayerExperienced::WEventplayerExperienced(Player * player, int nb_count) :
|
||||
player(player), nb_count(nb_count)
|
||||
{
|
||||
}
|
||||
|
||||
WEventplayerMonarch::WEventplayerMonarch(Player * player) :
|
||||
player(player)
|
||||
{
|
||||
@@ -605,6 +610,12 @@ Targetable * WEventplayerEnergized::getTarget(Player * player)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Targetable * WEventplayerExperienced::getTarget(Player * player)
|
||||
{
|
||||
if (player) return player;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Targetable * WEventplayerMonarch::getTarget(Player * player)
|
||||
{
|
||||
if (player) return player;
|
||||
|
||||
@@ -1289,6 +1289,10 @@ void WParsedInt::extendedParse(string s, Spell * spell, MTGCardInstance * card)
|
||||
{
|
||||
intValue = (card->controller()->isAI())?0:1;
|
||||
}
|
||||
else if (s == "pexperience" || s == "oexperience")
|
||||
{
|
||||
intValue = (s == "pexperience")?card->controller()->experienceCount:card->controller()->opponent()->experienceCount;
|
||||
}
|
||||
else if(!intValue)//found nothing, try parsing a atoi
|
||||
{
|
||||
intValue = atoi(s.c_str());
|
||||
|
||||
Reference in New Issue
Block a user