converted cycling into a cost type to bring it more inline with MTGrules {cycle}, also added the cycled trigger @cycled(tc):

this cost type sends both the event for discard and the event for cycled trigger, it no longer automatically draws a card, that is part of this cost ability instead.
standard cycling is autohand={cycle}:draw:1 controller
its trigger is
auto=@cycled(*|myhand):damage:2 target(creature)
"whenever you cycle a card deal 2 damage to a target creature."
This commit is contained in:
omegablast2002@yahoo.com
2011-11-09 14:27:56 +00:00
parent db6c4795bf
commit d2752a5a22
7 changed files with 113 additions and 72 deletions

View File

@@ -549,16 +549,28 @@ public:
class TrCardDiscarded: public Trigger
{
public:
TrCardDiscarded(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc,bool once = false) :
Trigger(observer, id, source, once, tc)
bool cycledTrigger;
TrCardDiscarded(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc,bool once = false, bool cycledTrigger = false) :
Trigger(observer, id, source, once, tc)
{
}
int triggerOnEventImpl(WEvent * event)
{
WEventCardDiscard * e = dynamic_cast<WEventCardDiscard *> (event);
if (!e) return 0;
if (!tc->canTarget(e->card)) return 0;
MTGCardInstance * targetCard = NULL;
if(cycledTrigger)
{
WEventCardCycle * c = dynamic_cast<WEventCardCycle *> (event);
if (!c) return 0;
targetCard = c->card;
}
else
{
WEventCardDiscard * e = dynamic_cast<WEventCardDiscard *> (event);
if (!e) return 0;
targetCard = e->card;
}
if (!targetCard || !tc->canTarget(targetCard)) return 0;
return 1;
}
@@ -1067,38 +1079,6 @@ public:
};
//Cycling
class ACycle: public ActivatedAbility
{
public:
ACycle(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target) :
ActivatedAbility(observer, _id, card)
{
target = _target;
}
int resolve()
{
WEvent * e = NEW WEventCardDiscard(source);
game->receiveEvent(e);
source->controller()->game->putInGraveyard(source);
source->controller()->game->drawFromLibrary();
return 1;
}
const char * getMenuText()
{
return "Cycling";
}
ACycle * clone() const
{
return NEW ACycle(*this);
}
};
//ninjutsu
class ANinja: public ActivatedAbility

View File

@@ -106,6 +106,15 @@ public:
virtual DiscardCost * clone() const;
};
//cycle
class CycleCost : public ExtraCost
{
public:
CycleCost(TargetChooser *_tc = NULL);
virtual int doPay();
virtual CycleCost * clone() const;
};
//tolibrary cost
class ToLibraryCost : public ExtraCost
{

View File

@@ -183,6 +183,12 @@ struct WEventCardDiscard : public WEventCardUpdate {
virtual Targetable * getTarget(int target);
};
//event when card is cycled.
struct WEventCardCycle : public WEventCardUpdate {
WEventCardCycle(MTGCardInstance * card);
virtual Targetable * getTarget(int target);
};
//Event when a card's "defenser" status changes
//before : attacker that card was blocking previously
//after: attacker that card is blocking now

View File

@@ -225,8 +225,40 @@ int DiscardCost::doPay()
}
return 0;
}
//to library cost
//cycling
CycleCost * CycleCost::clone() const
{
CycleCost * ec = NEW CycleCost(*this);
if (tc)
ec->tc = tc->clone();
return ec;
}
CycleCost::CycleCost(TargetChooser *_tc) :
ExtraCost("Cycle", _tc)
{
}
int CycleCost::doPay()
{
MTGCardInstance * _source = (MTGCardInstance *) source;
if (_source)
{
WEvent * e = NEW WEventCardDiscard(target);//cycling sends 2 events one for the discard and one for the specific cycle trigger
GameObserver * game = _source->owner->getObserver();
game->receiveEvent(e);
WEvent * e2 = NEW WEventCardCycle(_source);
game->receiveEvent(e2);
_source->controller()->game->putInGraveyard(_source);
if (tc)
tc->initTargets();
return 1;
}
return 0;
}
//to library cost
ToLibraryCost * ToLibraryCost::clone() const
{
ToLibraryCost * ec = NEW ToLibraryCost(*this);

View File

@@ -598,6 +598,10 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string magicText, int
if (TargetChooser * tc = parseSimpleTC(s, "discarded", card))
return NEW TrCardDiscarded(observer, id, card, tc,once);
//Card is cycled
if (TargetChooser * tc = parseSimpleTC(s, "cycled", card))
return NEW TrCardDiscarded(observer, id, card, tc,once,true);
//Card Damaging non combat
if (TargetChooser * tc = parseSimpleTC(s, "noncombatdamaged", card))
{
@@ -1510,14 +1514,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
{
return AbilityFactory::parseUpkeepAbility(s,card,spell,restrictions,id);
}
//Cycling
found = s.find("cycling");
if (found != string::npos)
{
MTGAbility * a = NEW ACycle(observer, id, card, target);
a->oneShot = 1;
return a;
}
//ninjutsu
found = s.find("ninjutsu");

View File

@@ -163,34 +163,41 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
manaCost->addExtraCost(NEW UnTapCost);
break;
}
case 'c': //Counters
{
size_t counter_start = value.find("(");
size_t counter_end = value.find(")", counter_start);
AbilityFactory abf(g);
string counterString = value.substr(counter_start + 1, counter_end - counter_start - 1);
Counter * counter = abf.parseCounter(counterString, c);
size_t separator = value.find(",", counter_start);
size_t separator2 = string::npos;
if (separator != string::npos)
case 'c': //Counters or cycle
{
separator2 = value.find(",", counter_end + 1);
if(value == "cycle")
{
manaCost->addExtraCost(NEW CycleCost(tc));
}
else
{
size_t counter_start = value.find("(");
size_t counter_end = value.find(")", counter_start);
AbilityFactory abf(g);
string counterString = value.substr(counter_start + 1, counter_end - counter_start - 1);
Counter * counter = abf.parseCounter(counterString, c);
size_t separator = value.find(",", counter_start);
size_t separator2 = string::npos;
if (separator != string::npos)
{
separator2 = value.find(",", counter_end + 1);
}
SAFE_DELETE(tc);
size_t target_start = string::npos;
if (separator2 != string::npos)
{
target_start = value.find(",", counter_end + 1);
}
size_t target_end = value.length();
if (target_start != string::npos && target_end != string::npos)
{
string target = value.substr(target_start + 1, target_end - 1 - target_start);
tc = tcf.createTargetChooser(target, c);
}
manaCost->addExtraCost(NEW CounterCost(counter, tc));
}
break;
}
SAFE_DELETE(tc);
size_t target_start = string::npos;
if (separator2 != string::npos)
{
target_start = value.find(",", counter_end + 1);
}
size_t target_end = value.length();
if (target_start != string::npos && target_end != string::npos)
{
string target = value.substr(target_start + 1, target_end - 1 - target_start);
tc = tcf.createTargetChooser(target, c);
}
manaCost->addExtraCost(NEW CounterCost(counter, tc));
break;
}
default: //uncolored cost and hybrid costs
{
int intvalue = atoi(value.c_str());

View File

@@ -97,6 +97,11 @@ WEventCardDiscard::WEventCardDiscard(MTGCardInstance * card) :
{
}
WEventCardCycle::WEventCardCycle(MTGCardInstance * card) :
WEventCardUpdate(card)
{
}
WEventVampire::WEventVampire(MTGCardInstance * card,MTGCardInstance * source,MTGCardInstance * victem) :
WEventCardUpdate(card),source(source),victem(victem)
{
@@ -232,6 +237,12 @@ Targetable * WEventCardDiscard::getTarget(int target)
return NULL;
}
Targetable * WEventCardCycle::getTarget(int target)
{
if (target) return card;
return NULL;
}
Targetable * WEventCardAttackedNotBlocked::getTarget(int target)
{
if (target) return card;