Merge branch 'master' into iOS-Build

This commit is contained in:
xawotihs
2015-09-13 18:42:31 +02:00
25 changed files with 2390 additions and 201 deletions
+40 -14
View File
@@ -1328,6 +1328,31 @@ AAFakeAbility * AAFakeAbility::clone() const
return NEW AAFakeAbility(*this);
}
//EPIC
AAEPIC::AAEPIC(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target, string _named,ManaCost * cost):
ActivatedAbility(observer, id, source, cost, 0),named(_named)
{
this->target = _target;
}
int AAEPIC::resolve()
{
MTGCardInstance * _target = (MTGCardInstance *)target;
_target->controller()->epic = 1;
return 1;
}
const string AAEPIC::getMenuText()
{
if(named.size())
return named.c_str();
return "EPIC";
}
AAEPIC * AAEPIC::clone() const
{
return NEW AAEPIC(*this);
}
// Fizzler
AAFizzler::AAFizzler(GameObserver* observer, int _id, MTGCardInstance * card, Spell * _target, ManaCost * _cost) :
ActivatedAbility(observer, _id, card, _cost, 0)
@@ -4156,22 +4181,19 @@ for (it = types.begin(); it != types.end(); it++)
}
}
if(newpowerfound )
{
{//setting p/t only overrides base p/t as of M15 changes
WParsedInt * val = NEW WParsedInt(newpower,NULL, source);
oldpower = _target->power;
_target->power += val->getValue();
_target->power -= oldpower;
_target->power += reapplyCountersBonus(_target,false,true);
_target->basepower = val->getValue();
_target->isSettingBase = true;
_target->applyPTL();
delete val;
}
if(newtoughnessfound )
{
{//setting p/t only overrides base p/t as of M15 changes
WParsedInt * val = NEW WParsedInt(newtoughness,NULL, source);
oldtoughness = _target->toughness;
_target->addToToughness(val->getValue());
_target->addToToughness(-oldtoughness);
_target->addToToughness(reapplyCountersBonus(_target,true,false));
_target->life = _target->toughness;
_target->basetoughness = val->getValue();
_target->isSettingBase = true;
_target->applyPTL();
delete val;
}
@@ -4257,12 +4279,16 @@ int ATransformer::destroy()
}
if(newpowerfound )
{
_target->power = oldpower;
{//override since we changed tha base, the bonus must have changed
_target->isSettingBase = false;
_target->basepower = _target->origpower;
_target->applyPTL();
}
if(newtoughnessfound )
{
_target->setToughness(oldtoughness);
_target->isSettingBase = false;
_target->basetoughness = _target->origtoughness;
_target->applyPTL();
}
if(newAbilityFound)
{
+19 -9
View File
@@ -56,8 +56,9 @@ int Counter::added()
{
if (power != 0 || toughness != 0)
{
target->power += power;
target->addToToughness(toughness);
target->pbonus += power;
target->tbonus += toughness;
target->applyPTL();
}
return 1;
}
@@ -66,8 +67,9 @@ int Counter::removed()
{
if (power != 0 || toughness != 0)
{
target->power -= power;
target->addToToughness(-toughness);
target->pbonus -= power;
target->tbonus -= toughness;
target->applyPTL();
}
return 1;
}
@@ -85,7 +87,7 @@ Counters::~Counters()
}
}
int Counters::addCounter(const char * _name, int _power, int _toughness)
int Counters::addCounter(const char * _name, int _power, int _toughness, bool _noevent)
{
/*420.5n If a permanent has both a +1/+1 counter and a -1/-1 counter on it, N +1/+1 and N -1/-1 counters are removed from it, where N is the smaller of the number of +1/+1 and -1/-1 counters on it.*/
GameObserver *g = target->getObserver();
@@ -109,9 +111,12 @@ int Counters::addCounter(const char * _name, int _power, int _toughness)
Counter * counter = NEW Counter(target, _name, _power, _toughness);
counters.push_back(counter);
counter->added();
WEvent * w = NEW WEventCounters(this,_name,_power,_toughness,true,false);
dynamic_cast<WEventCounters*>(w)->targetCard = this->target;
g->receiveEvent(w);
if (!_noevent)
{
WEvent * w = NEW WEventCounters(this,_name,_power,_toughness,true,false);
dynamic_cast<WEventCounters*>(w)->targetCard = this->target;
g->receiveEvent(w);
}
mCount++;
this->target->doDamageTest = 1;
this->target->afterDamage();
@@ -122,7 +127,12 @@ int Counters::addCounter(const char * _name, int _power, int _toughness)
int Counters::addCounter(int _power, int _toughness)
{
return addCounter("", _power, _toughness);
return addCounter("", _power, _toughness, false);
}
int Counters::addCounter(int _power, int _toughness, bool _noevent)
{
return addCounter("", _power, _toughness, _noevent);
}
int Counters::init()
+67 -3
View File
@@ -540,7 +540,12 @@ ExtraCost("UnTap")
int UnTapCost::isPaymentSet()
{
if (source && !source->isTapped())
/*602.5a A creature's activated ability with the tap symbol ({T}) or the untap symbol ({Q})
* in its activation cost can't be activated unless the creature has been under its
* controller's control since the start of his or her most recent turn.
* Ignore this rule for creatures with haste (see rule 702.10). As of 6/1/2014 Comprehensive Rules
*/
if (source && (!source->isTapped() || source->hasSummoningSickness()))
{
return 0;
}
@@ -757,6 +762,65 @@ int Ninja::doPay()
}
//endbouncetargetcostforninja
//Sacrifice target as cost for Offering
Offering * Offering::clone() const
{
Offering * ec = NEW Offering(*this);
if (tc)
ec->tc = tc->clone();
return ec;
}
Offering::Offering(TargetChooser *_tc) :
ExtraCost("Select creature to offer", _tc)
{
}
int Offering::canPay()
{
if (target && (!source->controller()->getManaPool()->canAfford(source->getManaCost()->Diff(target->getManaCost()))))
{
tc->removeTarget(target);
target = NULL;
return 0;
}
if (target && (source->controller()->getManaPool()->canAfford(source->getManaCost()->Diff(target->getManaCost()))))
return 1;
return 0;
}
int Offering::isPaymentSet()
{
if (target && (!source->controller()->getManaPool()->canAfford(source->getManaCost()->Diff(target->getManaCost()))))
{
tc->removeTarget(target);
target = NULL;
return 0;
}
if (target && (source->controller()->getManaPool()->canAfford(source->getManaCost()->Diff(target->getManaCost()))))
return 1;
return 0;
}
int Offering::doPay()
{
if (target)
{
target->controller()->getManaPool()->pay(source->getManaCost()->Diff(target->getManaCost()));
MTGCardInstance * beforeCard = target;
source->storedCard = target->createSnapShot();
target->controller()->game->putInGraveyard(target);
WEvent * e = NEW WEventCardSacrifice(beforeCard,target);
GameObserver * game = target->owner->getObserver();
game->receiveEvent(e);
target = NULL;
if (tc)
tc->initTargets();
return 1;
}
return 0;
}
//------------------------------------------------------------
SacrificeCost * SacrificeCost::clone() const
@@ -885,8 +949,8 @@ int CounterCost::doPay()
if (counter->nb >= 0)
{ //Add counters as a cost
for (int i = 0; i < counter->nb; i++)
{
target->counters->addCounter(counter->name.c_str(), counter->power, counter->toughness);
{//send no event because its a cost not an effect... for doubling season
target->counters->addCounter(counter->name.c_str(), counter->power, counter->toughness, true);
}
if (tc)
tc->initTargets();
+28 -6
View File
@@ -447,6 +447,12 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
if(cPhase < MTG_PHASE_COMBATBEGIN ||cPhase > MTG_PHASE_COMBATEND )
return 0;
}
check = restriction[i].find("during my main phases");
if(check != string::npos)
{
if( player != observer->currentPlayer && (cPhase != MTG_PHASE_FIRSTMAIN ||cPhase != MTG_PHASE_SECONDMAIN) )
return 0;
}
check = restriction[i].find("during my turn");
if(check != string::npos)
{
@@ -2408,7 +2414,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a;
}
//Reset damages on cards
//Do nothing
found = s.find("donothing");
if (found != string::npos)
{
@@ -2418,6 +2424,16 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a;
}
//Epic
found = s.find("epic");
if (found != string::npos)
{
MTGAbility * a = NEW AAEPIC(observer, id, card, target,newName);
a->oneShot = 1;
return a;
}
//Damage
vector<string> splitDamage = parseBetween(s, "damage:", " ", false);
if (splitDamage.size())
@@ -3581,9 +3597,9 @@ int AbilityFactory::getAbilities(vector<MTGAbility *> * v, Spell * spell, MTGCar
if(card->previous && card->previous->morphed && !card->turningOver)
{
magicText = card->magicTexts["facedown"];
card->power = 2;
card->basepower = 2;
card->life = 2;
card->toughness = 2;
card->basetoughness = 2;
card->setColor(0,1);
card->name = "Morph";
card->types.clear();
@@ -3591,12 +3607,17 @@ int AbilityFactory::getAbilities(vector<MTGAbility *> * v, Spell * spell, MTGCar
card->setType(cre.c_str());
card->basicAbilities.reset();
card->getManaCost()->resetCosts();
card->isSettingBase = true;
card->applyPTL();
}
else if(card && !card->morphed && card->turningOver)
{
card->power += card->origpower-2;
card->life += card->origtoughness-2;
card->toughness += card->origtoughness-2;
card->isSettingBase = false;
card->power = card->origpower;
card->basepower = card->origpower;
card->life = card->origtoughness;
card->toughness = card->origtoughness;
card->basetoughness = card->origtoughness;
card->setColor(0,1);
card->name = card->model->data->name;
card->types = card->model->data->types;
@@ -3610,6 +3631,7 @@ int AbilityFactory::getAbilities(vector<MTGAbility *> * v, Spell * spell, MTGCar
string faceupC= card->magicTexts["faceup"];
magicText.append("\n");
magicText.append(faceupC);
card->applyPTL();
}
else if(card && card->hasType(Subtypes::TYPE_EQUIPMENT) && card->target)
+34
View File
@@ -36,7 +36,11 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to
attacker = 0;
lifeOrig = life;
origpower = power;
basepower = origpower;
pbonus = 0;
origtoughness = toughness;
basetoughness = origtoughness;
tbonus = 0;
belongs_to = arg_belongs_to;
owner = NULL;
if (arg_belongs_to)
@@ -49,6 +53,8 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to
thatmuch = 0;
flanked = 0;
castMethod = Constants::NOT_CAST;
isSettingBase = false;
isPTswitch = false;
}
MTGCardInstance * MTGCardInstance::createSnapShot()
@@ -60,6 +66,34 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to
return snapShot;
}
void MTGCardInstance::applyPTL()
{
//7a ??how to add cda(Characteristic Defining Ability)??
power = origpower;
toughness = origtoughness;
//7b
if (isSettingBase)
{
power = basepower;
toughness = basetoughness;
}
//7c - 7d shared?
power += pbonus;
toughness += tbonus;
life = toughness;
//7e switch is last
if (isPTswitch)
{
oldP = power;
oldT = toughness;
this->addToToughness(oldP);
this->addToToughness(-oldT);
this->power = oldT;
}
/* end */
doDamageTest = 1;
}
void MTGCardInstance::copy(MTGCardInstance * card)
{
MTGCard * source = card->model;
+6 -1
View File
@@ -133,7 +133,12 @@ const char* Constants::MTGBasicAbilities[] = {
"lure",
"nolegend",
"canplayfromgraveyard",
"tokenizer"//parallel lives
"tokenizer",//parallel lives,
"mygraveexiler",
"oppgraveexiler",
"librarydeath",
"shufflelibrarydeath",
"offering"
};
map<string,int> Constants::MTGBasicAbilitiesMap;
+30
View File
@@ -321,6 +321,33 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
return card; //Error check
int doCopy = 1;
bool shufflelibrary = card->basicAbilities[(int)Constants::SHUFFLELIBRARYDEATH];
bool ripToken = false;
if (g->players[0]->game->battlefield->hasName("Rest in Peace")||g->players[1]->game->battlefield->hasName("Rest in Peace"))
ripToken = true;
//Darksteel Colossus, Legacy Weapon ... top priority since we replace destination directly automatically...
for(int i = 0; i < 2; ++i)
{
if ((to == g->players[i]->game->graveyard) && (
card->basicAbilities[(int)Constants::LIBRARYDEATH]||
card->basicAbilities[(int)Constants::SHUFFLELIBRARYDEATH]))
{
to = g->players[i]->game->library;
}
}
//Leyline of the Void, Yawgmoth's Agenda... effect...
for(int i = 0; i < 2; ++i)
{
if ((to == g->players[i]->game->graveyard) && (
g->players[i]->game->battlefield->hasAbility(Constants::MYGRAVEEXILER) ||
g->players[i]->opponent()->game->battlefield->hasAbility(Constants::OPPGRAVEEXILER)))
{
if ((card->isToken && ripToken))
to = g->players[i]->game->exile;
if (!card->isToken)
to = g->players[i]->game->exile;
}
}
//When a card is moved from inPlay to inPlay (controller change, for example), it is still the same object
if ((to == g->players[0]->game->inPlay || to == g->players[1]->game->inPlay) && (from == g->players[0]->game->inPlay || from
== g->players[1]->game->inPlay))
@@ -384,6 +411,9 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
}
if(!asCopy)
{
if(shufflelibrary)
copy->owner->game->library->shuffle();
WEvent * e = NEW WEventZoneChange(copy, from, to);
g->receiveEvent(e);
}
+15 -9
View File
@@ -317,14 +317,16 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
return 1;
}
}
else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH)
|| (player == currentPlayer && !game->isInterrupting
else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH)
|| (player == card->controller() && !game->isInterrupting
&& (game->getCurrentGamePhase() == MTG_PHASE_FIRSTMAIN
|| game->getCurrentGamePhase() == MTG_PHASE_SECONDMAIN))
)
{
if(card->controller()->epic)
return 0;
if (game->currentActionPlayer->game->playRestrictions->canPutIntoZone(card, game->currentActionPlayer->game->stack) == PlayRestriction::CANT_PLAY)
if (card->controller()->game->playRestrictions->canPutIntoZone(card, game->currentActionPlayer->game->stack) == PlayRestriction::CANT_PLAY)
return 0;
ManaCost * playerMana = player->getManaPool();
ManaCost * cost = card->getManaCost();
@@ -649,13 +651,15 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *
)
return 1;
}
else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH)
|| (player == currentPlayer && !game->isInterrupting
else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || card->has(Constants::OFFERING)
|| (player == card->controller() && !game->isInterrupting
&& (game->getCurrentGamePhase() == MTG_PHASE_FIRSTMAIN
|| game->getCurrentGamePhase() == MTG_PHASE_SECONDMAIN))
)
{
if (game->currentActionPlayer->game->playRestrictions->canPutIntoZone(card, game->currentActionPlayer->game->stack) == PlayRestriction::CANT_PLAY)
if(card->controller()->epic)
return 0;
if (card->controller()->game->playRestrictions->canPutIntoZone(card, card->controller()->game->stack) == PlayRestriction::CANT_PLAY)
return 0;
ManaCost * playerMana = player->getManaPool();
@@ -1028,21 +1032,23 @@ int MTGMorphCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
{
Player * player = game->currentlyActing();
Player * currentPlayer = game->currentPlayer;
//Player * currentPlayer = game->currentPlayer;
if (!player->game->hand->hasCard(card))
return 0;
if (!card->getManaCost()->getMorph())
return 0;
if(!allowedToAltCast(card,player))
return 0;
if(card->controller()->epic)//zoetic cavern... morph is casted for a cost...
return 0;
//note lands can morph too, this is different from other cost types.
if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || (player == currentPlayer
if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || (player == card->controller()
&& !game->isInterrupting
&& (game->getCurrentGamePhase() == MTG_PHASE_FIRSTMAIN
|| game->getCurrentGamePhase() == MTG_PHASE_SECONDMAIN))
)
{
if (game->currentActionPlayer->game->playRestrictions->canPutIntoZone(card, game->currentActionPlayer->game->stack) == PlayRestriction::CANT_PLAY)
if (card->controller()->game->playRestrictions->canPutIntoZone(card, card->controller()->game->stack) == PlayRestriction::CANT_PLAY)
return 0;
ManaCost * playerMana = player->getManaPool();
ManaCost * morph = card->getManaCost()->getMorph();
+27
View File
@@ -193,6 +193,33 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
manaCost->addExtraCost(NEW Ninja(tc));
break;
}
case 'k': //kill offering
{
TargetChooserFactory tcf(g);
if (value == "kgoblin")
{
tc = tcf.createTargetChooser("creature[goblin]|myBattlefield", c);
}
else if (value == "kfox")
{
tc = tcf.createTargetChooser("creature[fox]|myBattlefield", c);
}
else if (value == "kmoonfolk")
{
tc = tcf.createTargetChooser("creature[moonfolk]|myBattlefield", c);
}
else if (value == "krat")
{
tc = tcf.createTargetChooser("creature[rat]|myBattlefield", c);
}
else if (value == "ksnake")
{
tc = tcf.createTargetChooser("creature[snake]|myBattlefield", c);
}
//TODO iterate subtypes of creatures
manaCost->addExtraCost(NEW Offering(tc));
break;
}
case 'p' :
{
SAFE_DELETE(tc);
+1
View File
@@ -33,6 +33,7 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
skippingTurn = 0;
extraTurn = 0;
drawCounter = 0;
epic = 0;
prowledTypes.clear();
doesntEmpty = NEW ManaCost();
poolDoesntEmpty = NEW ManaCost();
+7 -1
View File
@@ -1078,7 +1078,13 @@ bool TypeTargetChooser::canTarget(Targetable * target,bool withoutProtections)
{
if (card->hasSubtype(types[i])) return true;
if (card->data->basicAbilities[(int)Constants::CHANGELING]) return true;//changelings can be targeted as any subtype.
if (card->data->basicAbilities[(int)Constants::CHANGELING])
{
if (!MTGAllCards::isSubtypeOfType(i,Subtypes::TYPE_CREATURE))
return false;
return true;
}
if(card->getLCName().size())
{
if (MTGAllCards::findType(card->getLCName()) == types[i])