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;
}
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")
{
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();
};
//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 */
class TADamager: public TargetAbility
{

View File

@@ -216,6 +216,19 @@ public:
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
class UnTapCost : public ExtraCost
{
@@ -295,6 +308,16 @@ public:
virtual int doPay();
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
class Offering : public ExtraCost
{

View File

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

View File

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

View File

@@ -595,6 +595,13 @@ int OrderedAIAction::getEfficiency()
efficiency = 90;
}
}
else if (dynamic_cast<AAAlterEnergy *>(a))
{
if (playerAbilityTarget && playerAbilityTarget == p)
{
efficiency = 90;
}
}
else if (ATokenCreator * atc = dynamic_cast<ATokenCreator *>(a))
{
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
AADamagePrevent::AADamagePrevent(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int preventing, ManaCost * _cost,
int who) :
@@ -2011,6 +2045,12 @@ int AAProliferate::resolve()
a->oneShot = true;
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)
{
Counters * counters = cTarget->counters;
@@ -7909,17 +7949,9 @@ int AACastCard::resolveSpell()
}
if (_target)
{
if (_target->isLand())
{
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
{
putinplay = true;
Spell * spell = NULL;
MTGCardInstance * copy = NULL;
if ((normal || asNormalMadness)||(!_target->hasType(Subtypes::TYPE_INSTANT) && !_target->hasType(Subtypes::TYPE_SORCERY)))
@@ -7943,12 +7975,24 @@ int AACastCard::resolveSpell()
if (game->targetChooser)
{
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;
}
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))
@@ -7980,7 +8024,7 @@ int AACastCard::resolveSpell()
andAbilityClone->addToGame();
}
}
}
this->forceDestroy = true;
processed = true;
return 1;

View File

@@ -533,6 +533,7 @@ void CardGui::AlternateRender(MTGCard * card, const Pos& pos)
// Draw the "unknown" card model
JRenderer * renderer = JRenderer::GetInstance();
JQuadPtr q;
MTGCardInstance * thiscard = dynamic_cast<MTGCardInstance*> (card);
float x = pos.actX;
@@ -553,6 +554,14 @@ void CardGui::AlternateRender(MTGCard * card, const Pos& pos)
items.clear();
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));
float scale = pos.actZ * 250 / q->mHeight;

View File

@@ -232,6 +232,37 @@ int SnowCost::doPay()
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
LifeCost * LifeCost::clone() const
{
@@ -1118,6 +1149,74 @@ int Delve::doPay()
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
Offering * Offering::clone() const

View File

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

View File

@@ -329,6 +329,37 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
if(!count)
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");
if(check != string::npos)
{
@@ -2949,6 +2980,17 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
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
vector<string> splitPrevent = parseBetween(s, "prevent:", " ", false);
if (splitPrevent.size())

View File

@@ -173,7 +173,9 @@ const char* Constants::MTGBasicAbilities[] = {
"asflash",
"conduited",
"canblocktapped",
"oppnomaxhand"
"oppnomaxhand",
"cantcrew",
"hiddenface"//test for facedown
};
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);
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
//Exile
manaCost->addExtraCost(NEW ExileTargetCost(tc));
@@ -248,12 +257,19 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
break;
}
case 'i' :
if(value == "improvise")
{
if(!tc)
tc = tcf.createTargetChooser("artifact[-tapped]|myBattlefield", c);
manaCost->addExtraCost(NEW Improvise(tc));
}
else
{
SAFE_DELETE(tc);
manaCost->add(0,1);
manaCost->addExtraCost(NEW SnowCost);
break;
}
break;
case 'q':
if(value == "q")
{

View File

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

View File

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