Support for KLD and AER

Kaladesh & Aether Revolt
This commit is contained in:
Anthony Calosa
2017-01-18 22:13:51 +08:00
parent d86b9119a4
commit d03ebdace8
14 changed files with 306 additions and 20 deletions

View File

@@ -560,6 +560,14 @@ private:
{ {
intValue = card->controller()->opponent()->raidcount; intValue = card->controller()->opponent()->raidcount;
} }
else if (s == "pstormcount")
{
intValue = card->controller()->game->stack->seenThisTurn("*", Constants::CAST_ALL);
}
else if (s == "ostormcount")
{
intValue = card->controller()->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL);
}
else if (s == "countallspell") else if (s == "countallspell")
{ {
intValue = card->controller()->game->stack->seenThisTurn("*", Constants::CAST_ALL) + card->controller()->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL); intValue = card->controller()->game->stack->seenThisTurn("*", Constants::CAST_ALL) + card->controller()->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL);
@@ -4514,6 +4522,19 @@ public:
AAAlterPoison * clone() const; AAAlterPoison * clone() const;
~AAAlterPoison(); ~AAAlterPoison();
}; };
//Energy Counter
class AAAlterEnergy: public ActivatedAbilityTP
{
public:
int energy;
AAAlterEnergy(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int energy, ManaCost * _cost = NULL,
int who = TargetChooser::UNSET);
int resolve();
const string getMenuText();
AAAlterEnergy * clone() const;
~AAAlterEnergy();
};
/* Standard Damager, can choose a NEW target each time the price is paid */ /* Standard Damager, can choose a NEW target each time the price is paid */
class TADamager: public TargetAbility class TADamager: public TargetAbility
{ {

View File

@@ -216,6 +216,19 @@ public:
virtual SnowCost * clone() const; virtual SnowCost * clone() const;
}; };
//Energy cost
class EnergyCost : public ExtraCost
{
private:
int enc;
public:
EnergyCost(int enc = 0);
virtual int canPay();
virtual int doPay();
virtual EnergyCost * clone() const;
};
//untap cost //untap cost
class UnTapCost : public ExtraCost class UnTapCost : public ExtraCost
{ {
@@ -295,6 +308,16 @@ public:
virtual int doPay(); virtual int doPay();
virtual Delve * clone() const; virtual Delve * clone() const;
}; };
//improvise
class Improvise : public ExtraCost
{
public:
Improvise(TargetChooser *_tc = NULL);
virtual int canPay();
virtual int isPaymentSet();
virtual int doPay();
virtual Improvise * clone() const;
};
//offering cost //offering cost
class Offering : public ExtraCost class Offering : public ExtraCost
{ {

View File

@@ -262,7 +262,9 @@ class Constants
CONDUITED = 140, CONDUITED = 140,
CANBLOCKTAPPED = 141, CANBLOCKTAPPED = 141,
OPPNOMAXHAND = 142, OPPNOMAXHAND = 142,
NB_BASIC_ABILITIES = 143, CANTCREW = 143,
HIDDENFACE = 144,
NB_BASIC_ABILITIES = 145,
RARITY_S = 'S', //Special Rarity RARITY_S = 'S', //Special Rarity
RARITY_M = 'M', //Mythics RARITY_M = 'M', //Mythics

View File

@@ -42,6 +42,7 @@ public:
int skippingTurn; int skippingTurn;
int extraTurn; int extraTurn;
int drawCounter; int drawCounter;
int energyCount;
int epic; int epic;
int forcefield; int forcefield;
int initLife; int initLife;

View File

@@ -595,6 +595,13 @@ int OrderedAIAction::getEfficiency()
efficiency = 90; efficiency = 90;
} }
} }
else if (dynamic_cast<AAAlterEnergy *>(a))
{
if (playerAbilityTarget && playerAbilityTarget == p)
{
efficiency = 90;
}
}
else if (ATokenCreator * atc = dynamic_cast<ATokenCreator *>(a)) else if (ATokenCreator * atc = dynamic_cast<ATokenCreator *>(a))
{ {
efficiency = 80; efficiency = 80;

View File

@@ -1010,6 +1010,40 @@ AAAlterPoison::~AAAlterPoison()
{ {
} }
//AA Energy Counters
AAAlterEnergy::AAAlterEnergy(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int energy, ManaCost * _cost,
int who) :
ActivatedAbilityTP(observer, _id, _source, _target, _cost, who), energy(energy)
{
}
int AAAlterEnergy::resolve()
{
Damageable * _target = (Damageable *) getTarget();
if (_target)
{
Player * pTarget = (Player*)_target;
if(pTarget)
pTarget->energyCount += energy;
}
return 0;
}
const string AAAlterEnergy::getMenuText()
{
WParsedInt parsedNum(energy);
return _(parsedNum.getStringValue() + " Energy ").c_str();
}
AAAlterEnergy * AAAlterEnergy::clone() const
{
return NEW AAAlterEnergy(*this);
}
AAAlterEnergy::~AAAlterEnergy()
{
}
//Damage Prevent //Damage Prevent
AADamagePrevent::AADamagePrevent(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int preventing, ManaCost * _cost, AADamagePrevent::AADamagePrevent(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int preventing, ManaCost * _cost,
int who) : int who) :
@@ -2011,6 +2045,12 @@ int AAProliferate::resolve()
a->oneShot = true; a->oneShot = true;
pcounters.push_back(a); pcounters.push_back(a);
} }
else if(pTarget && pTarget->energyCount && pTarget == source->controller())
{
MTGAbility * a = NEW AAAlterEnergy(game, game->mLayers->actionLayer()->getMaxId(), source, target, 1, NULL);
a->oneShot = true;
pcounters.push_back(a);
}
else if (cTarget && cTarget->counters) else if (cTarget && cTarget->counters)
{ {
Counters * counters = cTarget->counters; Counters * counters = cTarget->counters;
@@ -7909,17 +7949,9 @@ int AACastCard::resolveSpell()
} }
if (_target) if (_target)
{ {
if (_target->isLand()) if (_target->isLand())
{ putinplay = true;
MTGCardInstance * copy = _target->controller()->game->putInZone(_target, _target->currentZone, source->controller()->game->temp,noEvent);
copy->changeController(source->controller(),true);
Spell * spell = NEW Spell(game, 0,copy,NULL,NULL, 1);
spell->resolve();
delete spell;
}
else
{
Spell * spell = NULL; Spell * spell = NULL;
MTGCardInstance * copy = NULL; MTGCardInstance * copy = NULL;
if ((normal || asNormalMadness)||(!_target->hasType(Subtypes::TYPE_INSTANT) && !_target->hasType(Subtypes::TYPE_SORCERY))) if ((normal || asNormalMadness)||(!_target->hasType(Subtypes::TYPE_INSTANT) && !_target->hasType(Subtypes::TYPE_SORCERY)))
@@ -7943,12 +7975,24 @@ int AACastCard::resolveSpell()
if (game->targetChooser) if (game->targetChooser)
{ {
game->targetChooser->Owner = source->controller(); game->targetChooser->Owner = source->controller();
spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, NULL, 1, 0); if(putinplay)
{
spell = NEW Spell(game, 0,copy,game->targetChooser,NULL, 1);
spell->resolve();
}
else
spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, NULL, 1, 0);
game->targetChooser = NULL; game->targetChooser = NULL;
} }
else else
{ {
spell = game->mLayers->stackLayer()->addSpell(copy, NULL, NULL, 1, 0); if(putinplay)
{
spell = NEW Spell(game, 0,copy,NULL,NULL, 1);
spell->resolve();
}
else
spell = game->mLayers->stackLayer()->addSpell(copy, NULL, NULL, 1, 0);
} }
if (copy->has(Constants::STORM)) if (copy->has(Constants::STORM))
@@ -7980,7 +8024,7 @@ int AACastCard::resolveSpell()
andAbilityClone->addToGame(); andAbilityClone->addToGame();
} }
} }
}
this->forceDestroy = true; this->forceDestroy = true;
processed = true; processed = true;
return 1; return 1;

View File

@@ -533,6 +533,7 @@ void CardGui::AlternateRender(MTGCard * card, const Pos& pos)
// Draw the "unknown" card model // Draw the "unknown" card model
JRenderer * renderer = JRenderer::GetInstance(); JRenderer * renderer = JRenderer::GetInstance();
JQuadPtr q; JQuadPtr q;
MTGCardInstance * thiscard = dynamic_cast<MTGCardInstance*> (card);
float x = pos.actX; float x = pos.actX;
@@ -553,6 +554,14 @@ void CardGui::AlternateRender(MTGCard * card, const Pos& pos)
items.clear(); items.clear();
if (q.get() && q->mTex) if (q.get() && q->mTex)
{ {
//test
//draw black border ingame only
if(thiscard && thiscard->getObserver())
{
renderer->FillRoundRect((pos.actX - (pos.actZ * 84.f))-11.5f,(pos.actY - (pos.actZ * 119.7f))-14.f,pos.actZ * 168.f + 6.5f,pos.actZ * 239.4f + 12.f,8.f,ARGB(255,5,5,5));
renderer->DrawRoundRect((pos.actX - (pos.actZ * 84.f))-11.5f,(pos.actY - (pos.actZ * 119.7f))-14.f,pos.actZ * 168.f + 6.5f,pos.actZ * 239.4f + 12.f,8.f,ARGB(50,240,240,240));
}
q->SetHotSpot(static_cast<float> (q->mTex->mWidth / 2), static_cast<float> (q->mTex->mHeight / 2)); q->SetHotSpot(static_cast<float> (q->mTex->mWidth / 2), static_cast<float> (q->mTex->mHeight / 2));
float scale = pos.actZ * 250 / q->mHeight; float scale = pos.actZ * 250 / q->mHeight;

View File

@@ -232,6 +232,37 @@ int SnowCost::doPay()
return 0; return 0;
} }
//Energy Cost
EnergyCost * EnergyCost::clone() const
{
EnergyCost * ec = NEW EnergyCost(*this);
return ec;
}
EnergyCost::EnergyCost(int enc) :
ExtraCost("Energy Cost"),enc(enc)
{
}
int EnergyCost::canPay()
{
if(source->controller()->energyCount >= enc)
{
return 1;
}
return 0;
}
int EnergyCost::doPay()
{
if(source->controller()->energyCount)
{
source->controller()->energyCount -= enc;
return 1;
}
return 0;
}
//life cost //life cost
LifeCost * LifeCost::clone() const LifeCost * LifeCost::clone() const
{ {
@@ -1118,6 +1149,74 @@ int Delve::doPay()
return 0; return 0;
} }
//IMPROVISE
Improvise * Improvise::clone() const
{
Improvise * ec = NEW Improvise(*this);
if (tc)
ec->tc = tc->clone();
return ec;
}
Improvise::Improvise(TargetChooser *_tc) :
ExtraCost("Select Artifacts To Tap", _tc)
{
}
int Improvise::canPay()
{
return isPaymentSet();
}
int Improvise::isPaymentSet()
{
ManaCost * toReduce = NEW ManaCost(source->getManaCost());
tc->maxtargets = source->getManaCost()->getCost(Constants::MTG_COLOR_ARTIFACT);
if (tc->getNbTargets())
{
toReduce->remove(Constants::MTG_COLOR_ARTIFACT, tc->getNbTargets());
}
if (target && (!source->controller()->getManaPool()->canAfford(toReduce)))
{
target = NULL;
SAFE_DELETE(toReduce);
return 0;
}
if (target && (source->controller()->getManaPool()->canAfford(toReduce)))
{
/*if (target->getObserver()->guiOpenDisplay)
target->getObserver()->ButtonPressed(target->getObserver()->guiOpenDisplay);*/
SAFE_DELETE(toReduce);
return 1;
}
SAFE_DELETE(toReduce);
return 0;
}
int Improvise::doPay()
{
if (target && tc->getNbTargets())
{
ManaCost * toReduce = NEW ManaCost(source->getManaCost());
toReduce->remove(Constants::MTG_COLOR_ARTIFACT, tc->getNbTargets());
target->controller()->getManaPool()->pay(toReduce);
SAFE_DELETE(toReduce);
vector<Targetable*>targetlist = tc->getTargetsFrom();
for (vector<Targetable*>::iterator it = targetlist.begin(); it != targetlist.end(); it++)
{
MTGCardInstance * targetCard = dynamic_cast<MTGCardInstance*>(*it);
source->storedCard = targetCard->createSnapShot();
targetCard->tap();
}
if (tc)
tc->initTargets();
return 1;
}
return 0;
}
/////////////// ///////////////
//Sacrifice target as cost for Offering //Sacrifice target as cost for Offering
Offering * Offering::clone() const Offering * Offering::clone() const

View File

@@ -31,6 +31,7 @@ void GuiAvatar::Render()
JRenderer * r = JRenderer::GetInstance(); JRenderer * r = JRenderer::GetInstance();
int life = player->life; int life = player->life;
int poisonCount = player->poisonCount; int poisonCount = player->poisonCount;
int energyCount = player->energyCount;
WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE);
//Avatar //Avatar
@@ -108,10 +109,10 @@ void GuiAvatar::Render()
{ {
case TOP_LEFT: case TOP_LEFT:
mFont->SetColor(ARGB((int)actA / 4, 0, 0, 0)); mFont->SetColor(ARGB((int)actA / 4, 0, 0, 0));
mFont->DrawString(buffer, actX + 2, actY + 2); mFont->DrawString(buffer, actX + 2, actY - 2);
mFont->SetScale(1.3f); mFont->SetScale(1.3f);
mFont->SetColor(ARGB((int)actA, lx, ly, lz)); mFont->SetColor(ARGB((int)actA, lx, ly, lz));
mFont->DrawString(buffer, actX + 1, actY + 1); mFont->DrawString(buffer, actX + 1, actY - 1);
mFont->SetScale(1); mFont->SetScale(1);
break; break;
case BOTTOM_RIGHT: case BOTTOM_RIGHT:
@@ -122,8 +123,8 @@ void GuiAvatar::Render()
break; break;
} }
//poison //poison
char poison[5]; char poison[10];
if (poisonCount > 0) if (poisonCount >= 0)
{ {
sprintf(poison, "%i", poisonCount); sprintf(poison, "%i", poisonCount);
switch (corner) switch (corner)
@@ -138,6 +139,23 @@ void GuiAvatar::Render()
break; break;
} }
} }
//energy
char energy[15];
if (energyCount >= 0)
{
sprintf(energy, "%i", energyCount);
switch (corner)
{
case TOP_LEFT:
mFont->SetColor(ARGB((int)actA / 1, 255, 255, 0));
mFont->DrawString(energy, actX + 2, actY + 17);
break;
case BOTTOM_RIGHT:
mFont->SetColor(ARGB((int)actA / 1 ,255, 255, 0));
mFont->DrawString(energy, actX, actY - 27, JGETEXT_RIGHT);
break;
}
}
PlayGuiObject::Render(); PlayGuiObject::Render();
} }

View File

@@ -329,6 +329,37 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
if(!count) if(!count)
return 0; return 0;
} }
check = restriction[i].find("revolt");
if(check != string::npos)
{
int count = 0;
for(unsigned int k = 0; k < player->game->hand->cardsSeenThisTurn.size(); k++)
{
MTGCardInstance * tCard = player->game->hand->cardsSeenThisTurn[k];
if(tCard && tCard->previousZone == card->controller()->game->battlefield)
count++;
}
for(unsigned int k = 0; k < player->game->exile->cardsSeenThisTurn.size(); k++)
{
MTGCardInstance * tCard = player->game->exile->cardsSeenThisTurn[k];
if(tCard && tCard->previousZone == card->controller()->game->battlefield)
count++;
}
for(unsigned int k = 0; k < player->game->library->cardsSeenThisTurn.size(); k++)
{
MTGCardInstance * tCard = player->game->library->cardsSeenThisTurn[k];
if(tCard && tCard->previousZone == card->controller()->game->battlefield)
count++;
}
for(unsigned int k = 0; k < player->game->graveyard->cardsSeenThisTurn.size(); k++)
{
MTGCardInstance * tCard = player->game->graveyard->cardsSeenThisTurn[k];
if(tCard && tCard->previousZone == card->controller()->game->battlefield)
count++;
}
if(!count)
return 0;
}
check = restriction[i].find("morbid"); check = restriction[i].find("morbid");
if(check != string::npos) if(check != string::npos)
{ {
@@ -2949,6 +2980,17 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a; return a;
} }
//alter energy
vector<string> splitEnergy = parseBetween(s, "alterenergy:", " ", false);
if (splitEnergy.size())
{
int energy = atoi(splitEnergy[1].c_str());
Targetable * t = spell ? spell->getNextTarget() : NULL;
MTGAbility * a = NEW AAAlterEnergy(observer, id, card, t, energy, NULL, who);
a->oneShot = 1;
return a;
}
//prevent next damage //prevent next damage
vector<string> splitPrevent = parseBetween(s, "prevent:", " ", false); vector<string> splitPrevent = parseBetween(s, "prevent:", " ", false);
if (splitPrevent.size()) if (splitPrevent.size())

View File

@@ -173,7 +173,9 @@ const char* Constants::MTGBasicAbilities[] = {
"asflash", "asflash",
"conduited", "conduited",
"canblocktapped", "canblocktapped",
"oppnomaxhand" "oppnomaxhand",
"cantcrew",
"hiddenface"//test for facedown
}; };
map<string,int> Constants::MTGBasicAbilitiesMap; map<string,int> Constants::MTGBasicAbilitiesMap;

View File

@@ -159,6 +159,15 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
tc = tcf.createTargetChooser("creature|mybattlefield", c); tc = tcf.createTargetChooser("creature|mybattlefield", c);
manaCost->addExtraCost(NEW Offering(tc,true)); manaCost->addExtraCost(NEW Offering(tc,true));
} }
else if(value.substr(0,2) == "e:")
{//Energy Cost
vector<string>valSplit = parseBetween(value,"e:"," ",false);
if (valSplit.size()) {
WParsedInt* energytopay = NEW WParsedInt(valSplit[1], NULL, c);
manaCost->addExtraCost(NEW EnergyCost(energytopay->getValue()));
SAFE_DELETE(energytopay);
}
}
else else
//Exile //Exile
manaCost->addExtraCost(NEW ExileTargetCost(tc)); manaCost->addExtraCost(NEW ExileTargetCost(tc));
@@ -248,12 +257,19 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
break; break;
} }
case 'i' : case 'i' :
if(value == "improvise")
{
if(!tc)
tc = tcf.createTargetChooser("artifact[-tapped]|myBattlefield", c);
manaCost->addExtraCost(NEW Improvise(tc));
}
else
{ {
SAFE_DELETE(tc); SAFE_DELETE(tc);
manaCost->add(0,1); manaCost->add(0,1);
manaCost->addExtraCost(NEW SnowCost); manaCost->addExtraCost(NEW SnowCost);
break;
} }
break;
case 'q': case 'q':
if(value == "q") if(value == "q")
{ {

View File

@@ -34,6 +34,7 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
skippingTurn = 0; skippingTurn = 0;
extraTurn = 0; extraTurn = 0;
drawCounter = 0; drawCounter = 0;
energyCount = 0;
epic = 0; epic = 0;
forcefield = 0; forcefield = 0;
raidcount = 0; raidcount = 0;

View File

@@ -409,6 +409,7 @@ void Rules::initGame(GameObserver *g, bool currentPlayerSet)
p->poisonCount = initState.playerData[i].player->poisonCount; p->poisonCount = initState.playerData[i].player->poisonCount;
p->damageCount = initState.playerData[i].player->damageCount; p->damageCount = initState.playerData[i].player->damageCount;
p->preventable = initState.playerData[i].player->preventable; p->preventable = initState.playerData[i].player->preventable;
p->energyCount = initState.playerData[i].player->energyCount;
if (initState.playerData[i].player->mAvatarName.size()) if (initState.playerData[i].player->mAvatarName.size())
{ {
p->mAvatarName = initState.playerData[i].player->mAvatarName; p->mAvatarName = initState.playerData[i].player->mAvatarName;