Merge remote-tracking branch 'refs/remotes/WagicProject/master'
This commit is contained in:
@@ -6208,6 +6208,7 @@ class AACascade: public ActivatedAbility
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
string nbcardsStr;
|
string nbcardsStr;
|
||||||
|
MTGCardInstance * castingThis;
|
||||||
vector<MTGCardInstance*>selectedCards;
|
vector<MTGCardInstance*>selectedCards;
|
||||||
vector<MTGCardInstance *>oldOrder;
|
vector<MTGCardInstance *>oldOrder;
|
||||||
vector<MTGCardInstance *>newOrder;
|
vector<MTGCardInstance *>newOrder;
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ class GameObserver{
|
|||||||
int isInPlay(MTGCardInstance * card);
|
int isInPlay(MTGCardInstance * card);
|
||||||
int isInGrave(MTGCardInstance * card);
|
int isInGrave(MTGCardInstance * card);
|
||||||
int isInExile(MTGCardInstance * card);
|
int isInExile(MTGCardInstance * card);
|
||||||
|
int isInHand(MTGCardInstance * card);
|
||||||
virtual void Update(float dt);
|
virtual void Update(float dt);
|
||||||
void Render();
|
void Render();
|
||||||
void ButtonPressed(PlayGuiObject*);
|
void ButtonPressed(PlayGuiObject*);
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ public:
|
|||||||
bool isPhased;
|
bool isPhased;
|
||||||
bool isCascaded;
|
bool isCascaded;
|
||||||
int phasedTurn;
|
int phasedTurn;
|
||||||
|
bool handEffects;
|
||||||
bool graveEffects;
|
bool graveEffects;
|
||||||
bool exileEffects;
|
bool exileEffects;
|
||||||
bool suspended;
|
bool suspended;
|
||||||
|
|||||||
@@ -105,6 +105,10 @@ int OrderedAIAction::getEfficiency()
|
|||||||
target = a->source;
|
target = a->source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AACastCard * CC = dynamic_cast<AACastCard*> (a);
|
||||||
|
if (CC)
|
||||||
|
return 99;
|
||||||
|
|
||||||
switch (a->aType)
|
switch (a->aType)
|
||||||
{
|
{
|
||||||
case MTGAbility::DAMAGER:
|
case MTGAbility::DAMAGER:
|
||||||
|
|||||||
@@ -1143,76 +1143,97 @@ AACascade::AACascade(GameObserver* observer, int _id, MTGCardInstance * _source,
|
|||||||
selectedCards.clear();
|
selectedCards.clear();
|
||||||
oldOrder.clear();
|
oldOrder.clear();
|
||||||
newOrder.clear();
|
newOrder.clear();
|
||||||
|
castingThis = NULL;
|
||||||
}
|
}
|
||||||
int AACascade::resolve()
|
int AACascade::resolve()
|
||||||
|
{
|
||||||
|
Player * player = source->controller();
|
||||||
|
if (!player)
|
||||||
|
return 0;
|
||||||
|
WParsedInt numCards(nbcardsStr, NULL, source);
|
||||||
|
MTGLibrary * library = player->game->library;
|
||||||
|
MTGRemovedFromGame * exile = player->game->exile;
|
||||||
|
MTGCardInstance * viable = NULL;
|
||||||
|
int counter = 0;
|
||||||
|
bool found = false;
|
||||||
|
for (int i = 0; i < numCards.getValue(); i++)
|
||||||
{
|
{
|
||||||
Player * player = source->controller();
|
//*//*//*//
|
||||||
if (player)
|
if (found)
|
||||||
|
continue;
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
if (!library->nb_cards)
|
||||||
|
continue;
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
while (library->nb_cards && !found)
|
||||||
{
|
{
|
||||||
WParsedInt numCards(nbcardsStr, NULL, source);
|
viable = library->cards[library->nb_cards -1];
|
||||||
MTGLibrary * library = player->game->library;
|
if (!found)
|
||||||
MTGRemovedFromGame * exile = player->game->exile;
|
|
||||||
MTGCardInstance * viable = NULL;
|
|
||||||
int counter = 0;
|
|
||||||
for (int i = 0; i < numCards.getValue(); i++)
|
|
||||||
{
|
{
|
||||||
if (library->nb_cards)
|
if (!viable->isLand() && (viable->getManaCost()->getConvertedCost() < source->getManaCost()->getConvertedCost()))
|
||||||
{
|
{
|
||||||
for(int z = library->nb_cards-1; z >= 0; z--)
|
viable = player->game->putInZone(viable, library, exile);
|
||||||
{
|
viable->isCascaded = true;
|
||||||
if(!library->cards[z]->isLand() && (library->cards[z]->getManaCost()->getConvertedCost() < source->getManaCost()->getConvertedCost()))
|
castingThis = viable;
|
||||||
{
|
found = true;
|
||||||
viable = library->cards[z];
|
}
|
||||||
player->game->putInZone(viable, library, exile);
|
else
|
||||||
{
|
{
|
||||||
for(int j=0; j < library->nb_cards; j++)
|
viable = player->game->putInZone(viable, library, exile);
|
||||||
{
|
viable->isCascaded = true;
|
||||||
if(library->cards[j]->isCascaded)
|
counter++;
|
||||||
{
|
|
||||||
library->cards[j]->isCascaded = false;
|
|
||||||
selectedCards.push_back(library->cards[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(selectedCards.size())
|
|
||||||
{
|
|
||||||
std::random_shuffle ( selectedCards.begin(), selectedCards.end() );
|
|
||||||
for(unsigned int i = 0; i < selectedCards.size();++i)
|
|
||||||
{
|
|
||||||
oldOrder = library->cards;
|
|
||||||
newOrder.push_back(selectedCards[i]);
|
|
||||||
for(unsigned int k = 0;k < oldOrder.size();++k)
|
|
||||||
{
|
|
||||||
MTGCardInstance * rearranged = oldOrder[k];
|
|
||||||
if(rearranged != selectedCards[i])
|
|
||||||
newOrder.push_back(rearranged);
|
|
||||||
}
|
|
||||||
library->cards = newOrder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
toCastCard(viable->next);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
library->cards[library->nb_cards - 1]->isCascaded=true;
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
|
//*//*//*//*
|
||||||
}
|
}
|
||||||
|
////////////////////////////////////////////
|
||||||
|
for (int j = 0; j < exile->nb_cards; j++)
|
||||||
|
{
|
||||||
|
if (exile->cards[j]->isCascaded)
|
||||||
|
{
|
||||||
|
MTGCardInstance * CardToPutBack = exile->cards[j];;
|
||||||
|
CardToPutBack->isCascaded = false;
|
||||||
|
selectedCards.push_back(CardToPutBack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//////////////////////////////////////////
|
||||||
|
if (selectedCards.size())
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
MTGCardInstance * toMove = selectedCards.back();
|
||||||
|
if (toMove)
|
||||||
|
{
|
||||||
|
MTGAbility * a = NEW AALibraryBottom(game, game->mLayers->actionLayer()->getMaxId(), source, toMove);
|
||||||
|
a->oneShot = 1;
|
||||||
|
a->resolve();
|
||||||
|
SAFE_DELETE(a);
|
||||||
|
selectedCards.pop_back();
|
||||||
|
}
|
||||||
|
} while (selectedCards.size());
|
||||||
|
|
||||||
|
if (castingThis)
|
||||||
|
{
|
||||||
|
while (castingThis->next)
|
||||||
|
castingThis = castingThis->next;
|
||||||
|
toCastCard(castingThis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//////////////////////////////////////
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void AACascade::toCastCard(MTGCardInstance * thisCard)
|
void AACascade::toCastCard(MTGCardInstance * thisCard)
|
||||||
{
|
{
|
||||||
MTGAbility *ac = NEW AACastCard(game, game->mLayers->actionLayer()->getMaxId(), thisCard, thisCard,false,false,true,"","",false,false);
|
MTGAbility *ac = NEW AACastCard(game, game->mLayers->actionLayer()->getMaxId(), thisCard, thisCard,false,false,true,"","",false,false);
|
||||||
MayAbility *ma1 = NEW MayAbility(game, game->mLayers->actionLayer()->getMaxId(), ac->clone(), thisCard,true);
|
MayAbility *ma1 = NEW MayAbility(game, game->mLayers->actionLayer()->getMaxId(), ac->clone(), thisCard,false);
|
||||||
MTGAbility *ga1 = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), thisCard,NULL,ma1->clone());
|
MTGAbility *ga1 = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), thisCard,NULL,ma1->clone());
|
||||||
SAFE_DELETE(ac);
|
SAFE_DELETE(ac);
|
||||||
SAFE_DELETE(ma1);
|
SAFE_DELETE(ma1);
|
||||||
ga1->resolve();
|
ga1->resolve();
|
||||||
|
SAFE_DELETE(ga1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7291,6 +7312,7 @@ MTGCardInstance * AACastCard::makeCard()
|
|||||||
MTGCardInstance * card = NULL;
|
MTGCardInstance * card = NULL;
|
||||||
MTGCard * cardData = MTGCollection()->getCardByName(cardNamed);
|
MTGCard * cardData = MTGCollection()->getCardByName(cardNamed);
|
||||||
card = NEW MTGCardInstance(cardData, source->controller()->game);
|
card = NEW MTGCardInstance(cardData, source->controller()->game);
|
||||||
|
card->owner = source->controller();
|
||||||
source->controller()->game->temp->addCard(card);
|
source->controller()->game->temp->addCard(card);
|
||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
@@ -7311,6 +7333,7 @@ int AACastCard::resolveSpell()
|
|||||||
MTGCard * cardToCopy = MTGCollection()->getCardById(_target->getId());
|
MTGCard * cardToCopy = MTGCollection()->getCardById(_target->getId());
|
||||||
MTGCardInstance * myDummy = NULL;
|
MTGCardInstance * myDummy = NULL;
|
||||||
myDummy = NEW MTGCardInstance(cardToCopy, source->controller()->game);
|
myDummy = NEW MTGCardInstance(cardToCopy, source->controller()->game);
|
||||||
|
myDummy->setObserver(source->controller()->getObserver());
|
||||||
source->controller()->game->garbage->addCard(myDummy);
|
source->controller()->game->garbage->addCard(myDummy);
|
||||||
_target = myDummy;
|
_target = myDummy;
|
||||||
_target->isToken = 1;
|
_target->isToken = 1;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "Counters.h"
|
#include "Counters.h"
|
||||||
#include "MTGCardInstance.h"
|
#include "MTGCardInstance.h"
|
||||||
|
#include "AllAbilities.h"
|
||||||
|
|
||||||
Counter::Counter(MTGCardInstance * _target, int _power, int _toughness)
|
Counter::Counter(MTGCardInstance * _target, int _power, int _toughness)
|
||||||
{
|
{
|
||||||
@@ -187,10 +188,13 @@ int Counters::removeCounter(const char * _name, int _power, int _toughness)
|
|||||||
if (target->suspended && !target->counters->hasCounter("time",0,0))
|
if (target->suspended && !target->counters->hasCounter("time",0,0))
|
||||||
{
|
{
|
||||||
GameObserver * game = target->getObserver();
|
GameObserver * game = target->getObserver();
|
||||||
MTGCardInstance * copy = target->controller()->game->putInZone(target, target->currentZone, target->controller()->game->stack);
|
MTGAbility *ac = NEW AACastCard(game, game->mLayers->actionLayer()->getMaxId(), target, target, false, false, true, "", "", false, false);
|
||||||
|
MayAbility *ma1 = NEW MayAbility(game, game->mLayers->actionLayer()->getMaxId(), ac->clone(), target, true);
|
||||||
game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, NULL,1, 0);
|
MTGAbility *ga1 = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), target, NULL, ma1->clone());
|
||||||
game->targetChooser = NULL;
|
SAFE_DELETE(ac);
|
||||||
|
SAFE_DELETE(ma1);
|
||||||
|
ga1->resolve();
|
||||||
|
SAFE_DELETE(ga1);
|
||||||
}
|
}
|
||||||
return mCount;
|
return mCount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,6 +249,8 @@ LifeCost::LifeCost(TargetChooser *_tc)
|
|||||||
int LifeCost::canPay()
|
int LifeCost::canPay()
|
||||||
{
|
{
|
||||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
|
if (!_target)
|
||||||
|
return 0;
|
||||||
if (_target->controller()->life <= 0 || _target->controller()->inPlay()->hasAbility(Constants::CANTCHANGELIFE) ||
|
if (_target->controller()->life <= 0 || _target->controller()->inPlay()->hasAbility(Constants::CANTCHANGELIFE) ||
|
||||||
_target->controller()->opponent()->game->battlefield->hasAbility(Constants::CANTPAYLIFE) ||
|
_target->controller()->opponent()->game->battlefield->hasAbility(Constants::CANTPAYLIFE) ||
|
||||||
_target->controller()->game->battlefield->hasAbility(Constants::CANTPAYLIFE))
|
_target->controller()->game->battlefield->hasAbility(Constants::CANTPAYLIFE))
|
||||||
|
|||||||
@@ -1568,7 +1568,17 @@ int GameObserver::isInExile(MTGCardInstance * card)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int GameObserver::isInHand(MTGCardInstance * card)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
MTGGameZone * hand = players[i]->game->hand;
|
||||||
|
if (players[i]->game->isInZone(card, hand))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
void GameObserver::cleanupPhase()
|
void GameObserver::cleanupPhase()
|
||||||
{
|
{
|
||||||
currentPlayer->cleanupPhase();
|
currentPlayer->cleanupPhase();
|
||||||
|
|||||||
@@ -3982,13 +3982,14 @@ int AbilityFactory::getAbilities(vector<MTGAbility *> * v, Spell * spell, MTGCar
|
|||||||
{
|
{
|
||||||
card->graveEffects = false;
|
card->graveEffects = false;
|
||||||
card->exileEffects = false;
|
card->exileEffects = false;
|
||||||
|
card->handEffects = false;
|
||||||
for (int i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
MTGPlayerCards * zones = observer->players[i]->game;
|
MTGPlayerCards * zones = observer->players[i]->game;
|
||||||
if (dest == zones->hand)
|
if (dest == zones->hand)
|
||||||
{
|
{
|
||||||
magicText = card->magicTexts["hand"];
|
magicText = card->magicTexts["hand"];
|
||||||
|
card->handEffects = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (dest == zones->graveyard)
|
if (dest == zones->graveyard)
|
||||||
@@ -4891,6 +4892,8 @@ int MTGAbility::testDestroy()
|
|||||||
return 1;
|
return 1;
|
||||||
if (forceDestroy == -1)
|
if (forceDestroy == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (source->handEffects && game->isInHand(source))
|
||||||
|
return 0;
|
||||||
if(source->graveEffects && game->isInGrave(source))
|
if(source->graveEffects && game->isInGrave(source))
|
||||||
return 0;
|
return 0;
|
||||||
if(source->exileEffects && game->isInExile(source))
|
if(source->exileEffects && game->isInExile(source))
|
||||||
@@ -5934,13 +5937,23 @@ int AManaProducer::isReactingToClick(MTGCardInstance * _card, ManaCost * mana)
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
if (!mana)
|
if (!mana)
|
||||||
mana = game->currentlyActing()->getManaPool();
|
mana = game->currentlyActing()->getManaPool();
|
||||||
if (_card == source && (!tap || !source->isTapped()) && game->currentlyActing()->game->inPlay->hasCard(source)
|
//please do not condense the following, I broke it apart for readability, it was far to difficult to tell what exactly happened before with it all in a single line.
|
||||||
&& (source->hasType(Subtypes::TYPE_LAND) || !tap || !source->hasSummoningSickness()) && !source->isPhased)
|
//and far to prone to bugs.
|
||||||
|
if (_card == source)
|
||||||
{
|
{
|
||||||
ManaCost * cost = getCost();
|
if (!tap || (tap && (!source->isTapped() && !source->hasSummoningSickness())))
|
||||||
if (!cost || (mana->canAfford(cost) && (!cost->extraCosts || cost->extraCosts->canPay())))/*counter cost bypass react to click*/
|
|
||||||
{
|
{
|
||||||
result = 1;
|
if (game->currentlyActing()->game->inPlay->hasCard(source) && (source->hasType(Subtypes::TYPE_LAND) || !tap || !source->hasSummoningSickness()))
|
||||||
|
{
|
||||||
|
if (!source->isPhased)
|
||||||
|
{
|
||||||
|
ManaCost * cost = getCost();
|
||||||
|
if (!cost || (mana->canAfford(cost) && (!cost->extraCosts || cost->extraCosts->canPay())))/*counter cost bypass react to click*/
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -76,10 +76,22 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to
|
|||||||
|
|
||||||
MTGCardInstance * MTGCardInstance::createSnapShot()
|
MTGCardInstance * MTGCardInstance::createSnapShot()
|
||||||
{
|
{
|
||||||
MTGCardInstance * snapShot = NEW MTGCardInstance(*this);
|
//the below section of code was changed without all possible side effects checked
|
||||||
snapShot->previous = NULL;
|
//the reason was becuase while NEW MTGCardInstance(*this); does indeed return an exact copy
|
||||||
snapShot->counters = NEW Counters(snapShot);
|
//the lower layer cardprimitive data is pointed to from the original source.
|
||||||
controller()->game->garbage->addCard(snapShot);
|
//this would cause cards like lotus bloom, which contain a restriction, to already has deleted the restriction
|
||||||
|
//which belonged to the original card before getting to the safe_delete,
|
||||||
|
//it was leaving a dangling pointer which leads to
|
||||||
|
//a total crash on "cleanup()" calls from garbage zone.
|
||||||
|
//snapshots are created for extra cost, they are used for abilities contained after the cost through storecard variable.
|
||||||
|
//TODO:fix this correctly. I want this to use an exact copy of the card in its current state for stored.
|
||||||
|
//making it safe_delete these "copies" leads to the same crash, as they are still pointing to the original data.
|
||||||
|
MTGCardInstance * snapShot = this;
|
||||||
|
//below is how we used to handle this.
|
||||||
|
// MTGCardInstance * snapShot = NEW MTGCardInstance(*this);
|
||||||
|
//snapShot->previous = NULL;
|
||||||
|
// snapShot->counters = NEW Counters(snapShot);
|
||||||
|
//controller()->game->garbage->addCard(snapShot);
|
||||||
return snapShot;
|
return snapShot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -577,7 +577,7 @@ MTGCardInstance * MTGGameZone::removeCard(MTGCardInstance * card, int createCopy
|
|||||||
copy->storedSourceCard = card->storedSourceCard;
|
copy->storedSourceCard = card->storedSourceCard;
|
||||||
copy->lastController = card->controller();
|
copy->lastController = card->controller();
|
||||||
copy->previousController = card->controller();
|
copy->previousController = card->controller();
|
||||||
for (int i = 0; i < ManaCost::MANA_PAID_WITH_OVERLOAD +1; i++)
|
for (int i = 0; i < ManaCost::MANA_PAID_WITH_BESTOW +1; i++)
|
||||||
copy->alternateCostPaid[i] = card->alternateCostPaid[i];
|
copy->alternateCostPaid[i] = card->alternateCostPaid[i];
|
||||||
|
|
||||||
//stupid bug with tokens...
|
//stupid bug with tokens...
|
||||||
|
|||||||
Reference in New Issue
Block a user