first part of a series of commits, this one adds "and((" support to the various card removel abilities, tweaks targetedplayer targetchooser, and adds the following number word variables...

counter{}
so you can get a count of a certain counter on a card
the next consist of parts using the same targetchooser method as type:
power:
toughness:
convertedcost:
followed by ---
highest:
lowest:
followed by targetchooser
blah:mybattlefield
so if i want highest converted cost of creatures i control..
convertedcost:highest:creature:mybattlefield

also added an internal ability to reuse and display flying text with a string passed to it.
This commit is contained in:
omegablast2002@yahoo.com
2012-03-13 15:35:43 +00:00
parent 0d5439fb64
commit 0a357e7eb0
8 changed files with 410 additions and 61 deletions

View File

@@ -26,6 +26,17 @@ using std::map;
// //
// Misc classes // Misc classes
// //
class MTGEventText: public MTGAbility
{
public:
int textAlpha;
string text;
void Update(float dt);
void Render();
MTGEventText(GameObserver* observer, int _id,MTGCardInstance * card, string text);
virtual MTGEventText * clone() const;
};
class WParsedInt class WParsedInt
{ {
public: public:
@@ -41,6 +52,8 @@ public:
private: private:
void init(string s, Spell * spell, MTGCardInstance * card) void init(string s, Spell * spell, MTGCardInstance * card)
{ {
if(!s.size())
return;
if(!card) if(!card)
return; return;
MTGCardInstance * target = card->target; MTGCardInstance * target = card->target;
@@ -91,6 +104,10 @@ private:
if(intValue < 0) if(intValue < 0)
intValue = 0; intValue = 0;
} }
else if (s == "castx")
{
intValue = card->castX;
}
else if (s == "gear") else if (s == "gear")
{ {
intValue = target->equipment; intValue = target->equipment;
@@ -135,6 +152,97 @@ private:
} }
SAFE_DELETE(tc); SAFE_DELETE(tc);
} }
else if (s.find("counter{") != string::npos)
{
intValue = 0;
vector<string>counterName = parseBetween(s,"counter{","}");
if(counterName.size())
{
AbilityFactory abf(target->getObserver());
Counter * counter = abf.parseCounter(counterName[1], NULL);
if(counter && target->counters && target->counters->hasCounter(counter->name.c_str(),counter->power,counter->toughness))
{
Counter * targetCounter = target->counters->hasCounter(counter->name.c_str(), counter->power, counter->toughness);
intValue = targetCounter->nb;
}
SAFE_DELETE(counter);
}
}
else if (s.find("convertedcost:") != string::npos || s.find("power:") != string::npos || s.find("toughness:") != string::npos)
{
bool powerCheck = false;
bool toughnessCheck = false;
bool costCheck = false;
intValue = 0;
vector<string>convertedType = parseBetween(s,"convertedcost:",":");
if(convertedType.size())
costCheck = true;
else
{
convertedType = parseBetween(s,"power:",":");
if(convertedType.size())
powerCheck = true;
else
{
convertedType = parseBetween(s,"toughness:",":");
if(convertedType.size())
toughnessCheck = true;
}
}
if(!convertedType.size())
return;
bool high = false;
int highest = 0;
int lowest = 5000;
if(convertedType[1].find("highest") != string::npos)
high = true;
string theType = convertedType[2];
size_t zoned = theType.find(":");
if(zoned == string::npos)
{
theType.append("|mybattlefield");
}
else
{
replace(theType.begin(), theType.end(), ':', '|');
}
TargetChooserFactory tf(card->getObserver());
TargetChooser * tc = tf.createTargetChooser(theType.c_str(),NULL);
int check = 0;
for (int i = 0; i < 2; i++)
{
Player * p = card->getObserver()->players[i];
MTGGameZone * zones[] = { p->game->battlefield, p->game->graveyard, p->game->hand, p->game->library };
for (int k = 0; k < 4; k++)
{
MTGGameZone * zone = zones[k];
if(tc->targetsZone(zone,target))
{
for(unsigned int w = 0;w < zone->cards.size();++w)
{
MTGCardInstance * cCard = zone->cards[w];
if(tc->canTarget(cCard))
{
if(costCheck)
check = cCard->getManaCost()->getConvertedCost();
if(powerCheck)
check = cCard->power;
if(toughnessCheck)
check = cCard->toughness;
check > highest?highest = check:highest = highest;
check <= lowest?lowest = check:lowest = lowest;
}
}
}
}
}
if(lowest == 5000)
lowest = 0;
SAFE_DELETE(tc);
intValue = high?highest:lowest;
}
else if (s == "sunburst") else if (s == "sunburst")
{ {
intValue = 0; intValue = 0;
@@ -147,6 +255,14 @@ private:
{ {
intValue = target->controller()->life; intValue = target->controller()->life;
} }
else if (s == "highestlifetotal")
{
intValue = target->controller()->life <= target->controller()->opponent()->life? target->controller()->opponent()->life:target->controller()->life;
}
else if (s == "lowestlifetotal")
{
intValue = target->controller()->life <= target->controller()->opponent()->life? target->controller()->life:target->controller()->opponent()->life;
}
else if (s == "thatmuch") else if (s == "thatmuch")
{ {
//the value that much is a variable to be used with triggered abilities. //the value that much is a variable to be used with triggered abilities.
@@ -884,7 +1000,7 @@ public:
}; };
//if/ifnot Cond then EFFECT //if/ifnot Cond then EFFECT
class IfThenAbility: public ActivatedAbility class IfThenAbility: public InstantAbility
{ {
public: public:
MTGAbility * delayedAbility; MTGAbility * delayedAbility;
@@ -1067,37 +1183,45 @@ public:
class AABuryCard: public ActivatedAbility class AABuryCard: public ActivatedAbility
{ {
public: public:
MTGAbility * andAbility;
AABuryCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target); AABuryCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target);
int resolve(); int resolve();
const char * getMenuText(); const char * getMenuText();
AABuryCard * clone() const; AABuryCard * clone() const;
~AABuryCard();
}; };
class AADestroyCard: public ActivatedAbility class AADestroyCard: public ActivatedAbility
{ {
public: public:
MTGAbility * andAbility;
AADestroyCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target); AADestroyCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target);
int resolve(); int resolve();
const char * getMenuText(); const char * getMenuText();
AADestroyCard * clone() const; AADestroyCard * clone() const;
~AADestroyCard();
}; };
class AASacrificeCard: public ActivatedAbility class AASacrificeCard: public ActivatedAbility
{ {
public: public:
MTGAbility * andAbility;
AASacrificeCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target); AASacrificeCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target);
int resolve(); int resolve();
const char * getMenuText(); const char * getMenuText();
AASacrificeCard * clone() const; AASacrificeCard * clone() const;
~AASacrificeCard();
}; };
class AADiscardCard: public ActivatedAbility class AADiscardCard: public ActivatedAbility
{ {
public: public:
MTGAbility * andAbility;
AADiscardCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target); AADiscardCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target);
int resolve(); int resolve();
const char * getMenuText(); const char * getMenuText();
AADiscardCard * clone() const; AADiscardCard * clone() const;
~AADiscardCard();
}; };
/* Generic Target Ability */ /* Generic Target Ability */
@@ -1110,8 +1234,9 @@ public:
int counters; int counters;
MTGGameZone * activeZone; MTGGameZone * activeZone;
string newName; string newName;
string tcString;
GenericTargetAbility(GameObserver* observer, string newName, string castRestriction, int _id, MTGCardInstance * _source, TargetChooser * _tc, MTGAbility * a, ManaCost * _cost = NULL, string limit = "",MTGAbility * sideEffects = NULL,string usesBeforeSideEffects = "", int restrictions = 0, MTGGameZone * dest = NULL); GenericTargetAbility(GameObserver* observer, string newName, string castRestriction, int _id, MTGCardInstance * _source, TargetChooser * _tc, MTGAbility * a, ManaCost * _cost = NULL, string limit = "",MTGAbility * sideEffects = NULL,string usesBeforeSideEffects = "", int restrictions = 0, MTGGameZone * dest = NULL,string tcString ="");
const char * getMenuText(); const char * getMenuText();
~GenericTargetAbility(); ~GenericTargetAbility();
GenericTargetAbility * clone() const; GenericTargetAbility * clone() const;
@@ -1775,6 +1900,49 @@ public:
} }
}; };
//this generic ability assumes that what is added will take care of its own removel.
class GenericAbilityMod: public InstantAbility, public NestedAbility
{
public:
GenericAbilityMod(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, MTGAbility * ability) :
InstantAbility(observer, _id, _source,_target), NestedAbility(ability)
{
ability->target = _target;
}
int addToGame()
{
InstantAbility::addToGame();
return 1;
}
int resolve()
{
MTGAbility * toAdd = ability->clone();
toAdd->forceDestroy = -1;
toAdd->target = target;
toAdd->addToGame();
return 1;
}
const char * getMenuText()
{
return ability->getMenuText();
}
GenericAbilityMod * clone() const
{
GenericAbilityMod * a = NEW GenericAbilityMod(*this);
a->ability = ability->clone();
return a;
}
~GenericAbilityMod()
{
SAFE_DELETE(ability);
}
};
//Circle of Protections //Circle of Protections
class ACircleOfProtection: public TargetAbility class ACircleOfProtection: public TargetAbility
{ {
@@ -2987,6 +3155,7 @@ class AADamager: public ActivatedAbilityTP
{ {
public: public:
string d; string d;
bool redirected;
AADamager(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, string d, ManaCost * _cost = NULL, AADamager(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, string d, ManaCost * _cost = NULL,
int who = TargetChooser::UNSET); int who = TargetChooser::UNSET);
@@ -5035,7 +5204,7 @@ public:
target = copy; target = copy;
source->target = copy; source->target = copy;
copy->summoningSickness = 0; copy->summoningSickness = 0;
} }
return 1; return 1;
} }

View File

@@ -54,6 +54,7 @@ public:
MTGGameZone * currentZone; MTGGameZone * currentZone;
Pos* view; Pos* view;
int X; int X;
int castX;
int alternateCostPaid[ManaCost::MANA_PAID_WITH_RETRACE + 1]; int alternateCostPaid[ManaCost::MANA_PAID_WITH_RETRACE + 1];
int paymenttype; int paymenttype;
int castMethod; /* Tells if the card reached its current zone by being cast or not (brought into the zone by an effect). non 0 == cast, 0 == not cast */ int castMethod; /* Tells if the card reached its current zone by being cast or not (brought into the zone by an effect). non 0 == cast, 0 == not cast */
@@ -118,6 +119,7 @@ public:
Counters * counters; Counters * counters;
const string getDisplayName() const; const string getDisplayName() const;
MTGCardInstance * target; MTGCardInstance * target;
Player * playerTarget;
vector<Targetable *> backupTargets; vector<Targetable *> backupTargets;

View File

@@ -32,6 +32,14 @@ public:
Spell * getNextSpellTarget(Spell * previous = 0); Spell * getNextSpellTarget(Spell * previous = 0);
Damage * getNextDamageTarget(Damage * previous = 0); Damage * getNextDamageTarget(Damage * previous = 0);
Targetable * getNextTarget(Targetable * previous = 0); Targetable * getNextTarget(Targetable * previous = 0);
vector<Targetable*> getTargetsFrom()
{
return targets;
}
void setTargetsTo(vector<Targetable*>targetTo)
{
targets = targetTo;
}
void initTargets() void initTargets()
{ {
targets.clear(); targets.clear();

View File

@@ -38,10 +38,10 @@ int ActionLayer::removeFromGame(ActionElement * e)
AbilityFactory af(observer); AbilityFactory af(observer);
MTGAbility * a = dynamic_cast<MTGAbility*>(e); MTGAbility * a = dynamic_cast<MTGAbility*>(e);
if (a != NULL) if (a != NULL)
{ {
AManaProducer * manaObject = dynamic_cast<AManaProducer*>(af.getCoreAbility(a)); MTGAbility * toCheck = af.getCoreAbility(a);
AManaProducer * manaObject = dynamic_cast<AManaProducer*>(toCheck);
if(manaObject) if(manaObject)
{ {
for (size_t i = 0; i < manaObjects.size(); i++) for (size_t i = 0; i < manaObjects.size(); i++)
@@ -53,7 +53,6 @@ int ActionLayer::removeFromGame(ActionElement * e)
} }
mObjects.erase(mObjects.begin() + i); mObjects.erase(mObjects.begin() + i);
return 1; return 1;
} }
bool ActionLayer::moveToGarbage(ActionElement * e) bool ActionLayer::moveToGarbage(ActionElement * e)
@@ -71,7 +70,7 @@ void ActionLayer::cleanGarbage()
{ {
for (size_t i = 0; i < garbage.size(); ++i) for (size_t i = 0; i < garbage.size(); ++i)
{ {
delete (garbage[i]); SAFE_DELETE(garbage[i]);
} }
garbage.clear(); garbage.clear();
} }

View File

@@ -3,6 +3,45 @@
#include "Translate.h" #include "Translate.h"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
//display a text animation, this is not a real ability.
MTGEventText::MTGEventText(GameObserver* observer, int _id, MTGCardInstance * card, string textToShow) :
MTGAbility(observer, _id,card)
{
textAlpha = 255;
text = textToShow;
}
void MTGEventText::Update(float dt)
{
if (textAlpha)
{
textAlpha -= static_cast<int> (200 * dt);
if (textAlpha < 0)
{
textAlpha = 0;
this->forceDestroy = 1;
}
}
MTGAbility::Update(dt);
}
void MTGEventText::Render()
{
if (!textAlpha)
return;
WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::OPTION_FONT);
mFont->SetScale(2 - (float) textAlpha / 130);
mFont->SetColor(ARGB(255,255,255,255));
mFont->DrawString(text.c_str(), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, JGETEXT_CENTER);
}
MTGEventText * MTGEventText::clone() const
{
return NEW MTGEventText(*this);
}
////////////////////////
//Activated Abilities //Activated Abilities
//Generic Activated Abilities //Generic Activated Abilities
@@ -17,9 +56,9 @@ GenericActivatedAbility::GenericActivatedAbility(GameObserver* observer, string
int GenericActivatedAbility::resolve() int GenericActivatedAbility::resolve()
{ {
//Note: I've seen a similar block in some other MTGAbility, can this be refactored . //Note: I've seen a similar block in some other MTGAbility, can this be refactored .
source->X = 0;
if (abilityCost) if (abilityCost)
{ {
source->X = 0;
ManaCost * diff = abilityCost->Diff(getCost()); ManaCost * diff = abilityCost->Diff(getCost());
source->X = diff->hasX(); source->X = diff->hasX();
SAFE_DELETE(diff); SAFE_DELETE(diff);
@@ -704,6 +743,7 @@ AABuryCard::AABuryCard(GameObserver* observer, int _id, MTGCardInstance * _sourc
ActivatedAbility(observer, _id, _source) ActivatedAbility(observer, _id, _source)
{ {
target = _target; target = _target;
andAbility = NULL;
} }
int AABuryCard::resolve() int AABuryCard::resolve()
@@ -711,7 +751,24 @@ int AABuryCard::resolve()
MTGCardInstance * _target = (MTGCardInstance *) target; MTGCardInstance * _target = (MTGCardInstance *) target;
if (_target) if (_target)
{ {
return _target->bury(); _target->bury();
while(_target->next)
_target = _target->next;
if(andAbility)
{
MTGAbility * andAbilityClone = andAbility->clone();
andAbilityClone->target = _target;
if(andAbility->oneShot)
{
andAbilityClone->resolve();
SAFE_DELETE(andAbilityClone);
}
else
{
andAbilityClone->addToGame();
}
}
return 1;
} }
return 0; return 0;
} }
@@ -723,7 +780,15 @@ const char * AABuryCard::getMenuText()
AABuryCard * AABuryCard::clone() const AABuryCard * AABuryCard::clone() const
{ {
return NEW AABuryCard(*this); AABuryCard * a = NEW AABuryCard(*this);
if(andAbility)
a->andAbility = andAbility->clone();
return a;
}
AABuryCard::~AABuryCard()
{
SAFE_DELETE(andAbility);
} }
// Destroy // Destroy
@@ -732,6 +797,7 @@ AADestroyCard::AADestroyCard(GameObserver* observer, int _id, MTGCardInstance *
ActivatedAbility(observer, _id, _source) ActivatedAbility(observer, _id, _source)
{ {
target = _target; target = _target;
andAbility = NULL;
} }
int AADestroyCard::resolve() int AADestroyCard::resolve()
@@ -739,7 +805,24 @@ int AADestroyCard::resolve()
MTGCardInstance * _target = (MTGCardInstance *) target; MTGCardInstance * _target = (MTGCardInstance *) target;
if (_target) if (_target)
{ {
return _target->destroy(); _target->destroy();
while(_target->next)
_target = _target->next;
if(andAbility)
{
MTGAbility * andAbilityClone = andAbility->clone();
andAbilityClone->target = _target;
if(andAbility->oneShot)
{
andAbilityClone->resolve();
SAFE_DELETE(andAbilityClone);
}
else
{
andAbilityClone->addToGame();
}
}
return 1;
} }
return 0; return 0;
} }
@@ -751,14 +834,22 @@ const char * AADestroyCard::getMenuText()
AADestroyCard * AADestroyCard::clone() const AADestroyCard * AADestroyCard::clone() const
{ {
return NEW AADestroyCard(*this); AADestroyCard * a = NEW AADestroyCard(*this);
} if(andAbility)
a->andAbility = andAbility->clone();
return a;
}
AADestroyCard::~AADestroyCard()
{
SAFE_DELETE(andAbility);
}
// Sacrifice // Sacrifice
AASacrificeCard::AASacrificeCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) : AASacrificeCard::AASacrificeCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) :
ActivatedAbility(observer, _id, _source) ActivatedAbility(observer, _id, _source)
{ {
target = _target; target = _target;
andAbility = NULL;
} }
int AASacrificeCard::resolve() int AASacrificeCard::resolve()
@@ -770,6 +861,22 @@ int AASacrificeCard::resolve()
WEvent * e = NEW WEventCardSacrifice(_target); WEvent * e = NEW WEventCardSacrifice(_target);
game->receiveEvent(e); game->receiveEvent(e);
p->game->putInGraveyard(_target); p->game->putInGraveyard(_target);
while(_target->next)
_target = _target->next;
if(andAbility)
{
MTGAbility * andAbilityClone = andAbility->clone();
andAbilityClone->target = _target;
if(andAbility->oneShot)
{
andAbilityClone->resolve();
SAFE_DELETE(andAbilityClone);
}
else
{
andAbilityClone->addToGame();
}
}
return 1; return 1;
} }
return 0; return 0;
@@ -782,15 +889,22 @@ const char * AASacrificeCard::getMenuText()
AASacrificeCard * AASacrificeCard::clone() const AASacrificeCard * AASacrificeCard::clone() const
{ {
return NEW AASacrificeCard(*this); AASacrificeCard * a = NEW AASacrificeCard(*this);
if(andAbility)
a->andAbility = andAbility->clone();
return a;
}
AASacrificeCard::~AASacrificeCard()
{
SAFE_DELETE(andAbility);
} }
// Discard // Discard
AADiscardCard::AADiscardCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) : AADiscardCard::AADiscardCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) :
ActivatedAbility(observer, _id, _source) ActivatedAbility(observer, _id, _source)
{ {
target = _target; target = _target;
andAbility = NULL;
} }
int AADiscardCard::resolve() int AADiscardCard::resolve()
@@ -802,6 +916,22 @@ int AADiscardCard::resolve()
WEvent * e = NEW WEventCardDiscard(_target); WEvent * e = NEW WEventCardDiscard(_target);
game->receiveEvent(e); game->receiveEvent(e);
p->game->putInGraveyard(_target); p->game->putInGraveyard(_target);
while(_target->next)
_target = _target->next;
if(andAbility)
{
MTGAbility * andAbilityClone = andAbility->clone();
andAbilityClone->target = _target;
if(andAbility->oneShot)
{
andAbilityClone->resolve();
SAFE_DELETE(andAbilityClone);
}
else
{
andAbilityClone->addToGame();
}
}
return 1; return 1;
} }
return 0; return 0;
@@ -814,9 +944,15 @@ const char * AADiscardCard::getMenuText()
AADiscardCard * AADiscardCard::clone() const AADiscardCard * AADiscardCard::clone() const
{ {
return NEW AADiscardCard(*this); AADiscardCard * a = NEW AADiscardCard(*this);
if(andAbility)
a->andAbility = andAbility->clone();
return a;
}
AADiscardCard::~AADiscardCard()
{
SAFE_DELETE(andAbility);
} }
AADrawer::AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost, string nbcardsStr, AADrawer::AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost, string nbcardsStr,
int who) : int who) :
ActivatedAbilityTP(observer, _id, card, _target, _cost, who), nbcardsStr(nbcardsStr) ActivatedAbilityTP(observer, _id, card, _target, _cost, who), nbcardsStr(nbcardsStr)
@@ -995,7 +1131,11 @@ int AAMorph::resolve()
else else
{ {
a->addToGame(); a->addToGame();
_target->cardsAbilities.push_back(a); MayAbility * dontAdd = dynamic_cast<MayAbility*>(a);
if(!dontAdd)
{
_target->cardsAbilities.push_back(a);
}
} }
} }
} }
@@ -1087,7 +1227,11 @@ int AAFlip::resolve()
else else
{ {
a->addToGame(); a->addToGame();
_target->cardsAbilities.push_back(a); MayAbility * dontAdd = dynamic_cast<MayAbility*>(a);
if(!dontAdd)
{
_target->cardsAbilities.push_back(a);
}
} }
} }
} }
@@ -1724,6 +1868,8 @@ int AACloner::resolve()
spell->resolve(); spell->resolve();
spell->source->isToken = 1; spell->source->isToken = 1;
spell->source->fresh = 1; spell->source->fresh = 1;
spell->source->model = spell->source;
spell->source->model->data = spell->source;
if(_target->isToken) if(_target->isToken)
{ {
spell->source->power = _target->origpower; spell->source->power = _target->origpower;
@@ -1930,6 +2076,8 @@ int AAMover::resolve()
} }
} }
p->game->putInZone(_target, fromZone, destZone); p->game->putInZone(_target, fromZone, destZone);
while(_target->next)
_target = _target->next;
if(andAbility) if(andAbility)
{ {
MTGAbility * andAbilityClone = andAbility->clone(); MTGAbility * andAbilityClone = andAbility->clone();
@@ -2401,7 +2549,7 @@ ANewAffinity * ANewAffinity::clone() const
//IfThenEffect //IfThenEffect
IfThenAbility::IfThenAbility(GameObserver* observer, int _id, MTGAbility * delayedAbility, MTGCardInstance * _source, Targetable * _target, int type,string Cond) : IfThenAbility::IfThenAbility(GameObserver* observer, int _id, MTGAbility * delayedAbility, MTGCardInstance * _source, Targetable * _target, int type,string Cond) :
ActivatedAbility(observer, _id, _source),delayedAbility(delayedAbility), type(type),Cond(Cond) InstantAbility(observer, _id, _source),delayedAbility(delayedAbility), type(type),Cond(Cond)
{ {
target = _target; target = _target;
} }
@@ -2508,9 +2656,9 @@ int MayAbility::testDestroy()
if (game->mLayers->actionLayer()->getIndexOf(mClone) != -1) if (game->mLayers->actionLayer()->getIndexOf(mClone) != -1)
return 0; return 0;
if(game->currentPlayer == source->controller() && game->isInterrupting == source->controller() && dynamic_cast<AManaProducer*>(AbilityFactory::getCoreAbility(ability))) if(game->currentPlayer == source->controller() && game->isInterrupting == source->controller() && dynamic_cast<AManaProducer*>(AbilityFactory::getCoreAbility(ability)))
//if its my turn, and im interrupting myself(why?) then set interrupting to previous interrupter if the ability was a manaability //if its my turn, and im interrupting myself(why?) then set interrupting to previous interrupter if the ability was a manaability
//special case since they don't use the stack. //special case since they don't use the stack.
game->mLayers->stackLayer()->setIsInterrupting(previousInterrupter, false); game->mLayers->stackLayer()->setIsInterrupting(previousInterrupter, false);
return 1; return 1;
} }
@@ -2611,6 +2759,7 @@ int MenuAbility::testDestroy()
return 0; return 0;
if (game->mLayers->actionLayer()->getIndexOf(mClone) != -1) if (game->mLayers->actionLayer()->getIndexOf(mClone) != -1)
return 0; return 0;
return 1; return 1;
} }
@@ -2629,14 +2778,17 @@ int MenuAbility::reactToChoiceClick(Targetable * object,int choice,int control)
if(choice == i) if(choice == i)
mClone = abilities[choice]->clone(); mClone = abilities[choice]->clone();
else else
abilities[i]->clone();//all get cloned for clean up purposes. SAFE_DELETE(abilities[i]);
//else
// abilities[i]->clone();//all get cloned for clean up purposes. EDIT:removed, cause memleaks.
} }
if(!mClone) if(!mClone)
return 0; return 0;
mClone->target = abilities[choice]->target; mClone->target = abilities[choice]->target;
mClone->oneShot = true; mClone->oneShot = true;
mClone->forceDestroy = 1; mClone->forceDestroy = 1;
mClone->resolve(); mClone->canBeInterrupted = false;
mClone->resolve();
SAFE_DELETE(mClone); SAFE_DELETE(mClone);
if (source->controller() == game->isInterrupting) if (source->controller() == game->isInterrupting)
game->mLayers->stackLayer()->cancelInterruptOffer(ActionStack::DONT_INTERRUPT, false); game->mLayers->stackLayer()->cancelInterruptOffer(ActionStack::DONT_INTERRUPT, false);
@@ -2765,11 +2917,10 @@ MultiAbility::~MultiAbility()
abilities.clear(); abilities.clear();
} }
//Generic Target Ability //Generic Target Ability
GenericTargetAbility::GenericTargetAbility(GameObserver* observer, string newName, string castRestriction, int _id, MTGCardInstance * _source, TargetChooser * _tc, MTGAbility * a, GenericTargetAbility::GenericTargetAbility(GameObserver* observer, string newName, string castRestriction, int _id, MTGCardInstance * _source, TargetChooser * _tc, MTGAbility * a,
ManaCost * _cost, string limit,MTGAbility * sideEffects,string usesBeforeSideEffects, int restrictions, MTGGameZone * dest) : ManaCost * _cost, string limit,MTGAbility * sideEffects,string usesBeforeSideEffects, int restrictions, MTGGameZone * dest,string _tcString) :
TargetAbility(observer, _id, _source, _tc, _cost, restrictions, castRestriction), limit(limit), activeZone(dest),newName(newName) TargetAbility(observer, _id, _source, _tc, _cost, restrictions, castRestriction), limit(limit), activeZone(dest),newName(newName),tcString(_tcString)
{ {
ability = a; ability = a;
MTGAbility * core = AbilityFactory::getCoreAbility(a); MTGAbility * core = AbilityFactory::getCoreAbility(a);
@@ -2789,7 +2940,6 @@ const char * GenericTargetAbility::getMenuText()
MTGAbility * core = AbilityFactory::getCoreAbility(ability); MTGAbility * core = AbilityFactory::getCoreAbility(ability);
if (AAMover * move = dynamic_cast<AAMover *>(core)) if (AAMover * move = dynamic_cast<AAMover *>(core))
return (move->getMenuText(tc)); return (move->getMenuText(tc));
return ability->getMenuText(); return ability->getMenuText();
} }
@@ -2811,6 +2961,15 @@ int GenericTargetAbility::isReactingToClick(MTGCardInstance * card, ManaCost * m
} }
if (limitPerTurn && counters >= limitPerTurn) if (limitPerTurn && counters >= limitPerTurn)
return 0; return 0;
if(tcString.size() && !tc->targetListSet())
{
TargetChooser * current = this->getActionTc();
TargetChooserFactory tcf(game);
TargetChooser *refreshed = tcf.createTargetChooser(tcString, source, this);
refreshed->setTargetsTo(current->getTargetsFrom());
this->setActionTC(refreshed);
SAFE_DELETE(current);
}
return TargetAbility::isReactingToClick(card, mana); return TargetAbility::isReactingToClick(card, mana);
} }
@@ -2977,15 +3136,15 @@ ATransformer::ATransformer(GameObserver* observer, int id, MTGCardInstance * sou
removeTypes = (stypes.find("removetypes") != string::npos); removeTypes = (stypes.find("removetypes") != string::npos);
if (stypes.find("allsubtypes") != string::npos || stypes.find("removecreaturesubtypes") != string::npos) if (stypes.find("allsubtypes") != string::npos || stypes.find("removecreaturesubtypes") != string::npos)
{ {
const vector<string> values = MTGAllCards::getValuesById(); const vector<string> values = MTGAllCards::getValuesById();
for (size_t i = 0; i <values.size(); ++i) for (size_t i = 0; i <values.size(); ++i)
{ {
if (!MTGAllCards::isSubtypeOfType(i,Subtypes::TYPE_CREATURE)) if (!MTGAllCards::isSubtypeOfType(i,Subtypes::TYPE_CREATURE))
continue; continue;
types.push_back(i); types.push_back(i);
} }
} }
else else
{ {
@@ -3051,25 +3210,26 @@ int ATransformer::addToGame()
} }
else else
{ {
for (it = types.begin(); it != types.end(); it++) for (it = types.begin(); it != types.end(); it++)
{ {
if(removeCreatureSubtypes)
{ if(removeCreatureSubtypes)
_target->removeType(*it); {
} _target->removeType(*it);
else if(_target->hasSubtype(*it)) }
{ else if(_target->hasSubtype(*it))
//we generally don't want to give a creature type creature again {
//all it does is create a sloppy mess of the subtype line on alternative quads //we generally don't want to give a creature type creature again
//also creates instances where a card gained a type from an ability like this one //all it does is create a sloppy mess of the subtype line on alternative quads
//then loses the type through another ability, when this effect is destroyed the creature regains //also creates instances where a card gained a type from an ability like this one
//the type, which is wrong. //then loses the type through another ability, when this effect is destroyed the creature regains
dontremove.push_back(*it); //the type, which is wrong.
} dontremove.push_back(*it);
else }
{ else
_target->addType(*it); {
} _target->addType(*it);
}
} }
} }
for (it = colors.begin(); it != colors.end(); it++) for (it = colors.begin(); it != colors.end(); it++)
@@ -3226,6 +3386,7 @@ int ATransformer::destroy()
if(newAbilities[_target].at(i)) if(newAbilities[_target].at(i))
{ {
newAbilities[_target].at(i)->forceDestroy = 1; newAbilities[_target].at(i)->forceDestroy = 1;
newAbilities[_target].at(i)->removeFromGame();
} }
} }
if (newAbilities.find(_target) != newAbilities.end()) if (newAbilities.find(_target) != newAbilities.end())
@@ -3233,11 +3394,12 @@ int ATransformer::destroy()
newAbilities.erase(_target); newAbilities.erase(_target);
} }
} }
if (remove) if (remove || removeCreatureSubtypes)
{ {
for (it = oldtypes.begin(); it != oldtypes.end(); it++) for (it = oldtypes.begin(); it != oldtypes.end(); it++)
{ {
_target->addType(*it); if(!_target->hasSubtype(*it))
_target->addType(*it);
} }
} }
//in the case that we removed or added types to a card, so that it retains its original name when the effect is removed. //in the case that we removed or added types to a card, so that it retains its original name when the effect is removed.
@@ -3294,6 +3456,7 @@ ATransformerInstant::~ATransformerInstant()
{ {
SAFE_DELETE(ability); SAFE_DELETE(ability);
} }
//P/t ueot //P/t ueot
PTInstant::PTInstant(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, WParsedPT * wppt,string s,bool nonstatic) : PTInstant::PTInstant(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, WParsedPT * wppt,string s,bool nonstatic) :
InstantAbility(observer, id, source, target), wppt(wppt),s(s),nonstatic(nonstatic) InstantAbility(observer, id, source, target), wppt(wppt),s(s),nonstatic(nonstatic)
@@ -3325,7 +3488,6 @@ PTInstant::~PTInstant()
{ {
SAFE_DELETE(ability); SAFE_DELETE(ability);
} }
// ASwapPTUEOT // ASwapPTUEOT
ASwapPTUEOT::ASwapPTUEOT(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target) : ASwapPTUEOT::ASwapPTUEOT(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target) :
InstantAbility(observer, id, source, target) InstantAbility(observer, id, source, target)
@@ -3682,7 +3844,12 @@ AUpkeep::AUpkeep(GameObserver* observer, int _id, MTGCardInstance * card, MTGAbi
{ {
paidThisTurn = 0; paidThisTurn = 0;
aType = MTGAbility::UPCOST; aType = MTGAbility::UPCOST;
backupMana = NEW ManaCost(this->getCost()); if(Cumulative)
{
backupMana = NEW ManaCost();
backupMana->copy(this->getCost());
backupMana->addExtraCosts(this->getCost()->extraCosts);
}
} }
int AUpkeep::receiveEvent(WEvent * event) int AUpkeep::receiveEvent(WEvent * event)
@@ -3705,7 +3872,7 @@ void AUpkeep::Update(float dt)
// once: 0 means always go off, 1 means go off only once, 2 means go off only once and already has. // once: 0 means always go off, 1 means go off only once, 2 means go off only once and already has.
if (newPhase != currentPhase && source->controller() == game->currentPlayer && once < 2) if (newPhase != currentPhase && source->controller() == game->currentPlayer && once < 2)
{ {
if (newPhase == MTG_PHASE_UNTAP) if (newPhase == MTG_PHASE_BEFORE_BEGIN)
{ {
paidThisTurn = 0; paidThisTurn = 0;
} }
@@ -3770,8 +3937,11 @@ AUpkeep * AUpkeep::clone() const
AUpkeep::~AUpkeep() AUpkeep::~AUpkeep()
{ {
if(Cumulative)
{
SAFE_DELETE(backupMana);
}
SAFE_DELETE(ability); SAFE_DELETE(ability);
SAFE_DELETE(backupMana);
} }
//A Phase based Action //A Phase based Action

View File

@@ -37,6 +37,8 @@ CardPrimitive::CardPrimitive()
CardPrimitive::CardPrimitive(CardPrimitive * source) CardPrimitive::CardPrimitive(CardPrimitive * source)
{ {
if(!source)
return;
basicAbilities = source->basicAbilities; basicAbilities = source->basicAbilities;
for (size_t i = 0; i < source->types.size(); ++i) for (size_t i = 0; i < source->types.size(); ++i)
@@ -215,6 +217,7 @@ void CardPrimitive::setSubtype(const string& value)
break; break;
} }
} }
int id = MTGAllCards::add(value, parentType); int id = MTGAllCards::add(value, parentType);
addType(id); addType(id);
} }

View File

@@ -162,6 +162,7 @@ void MTGCardInstance::initMTGCI()
thatmuch = 0; thatmuch = 0;
flanked = 0; flanked = 0;
target = NULL; target = NULL;
playerTarget = NULL;
type_as_damageable = DAMAGEABLE_MTGCARDINSTANCE; type_as_damageable = DAMAGEABLE_MTGCARDINSTANCE;
banding = NULL; banding = NULL;
owner = NULL; owner = NULL;

View File

@@ -29,14 +29,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
found = s.find("targetedplayer"); found = s.find("targetedplayer");
if (found == 0) if (found == 0)
{ {
if(card && card->backupTargets.size()) Player * pTarget = card->playerTarget;
{
Player * pTarget = dynamic_cast<Player*>(card->backupTargets[0]);
if (ability) if (ability)
pTarget = dynamic_cast<Player*>(ability->target); pTarget = dynamic_cast<Player*>(ability->target);
if(pTarget) if(pTarget)
return NEW PlayerTargetChooser(observer, card, 1, pTarget); return NEW PlayerTargetChooser(observer, card, 1, pTarget);
}
}; };
found = s.find("opponent"); found = s.find("opponent");