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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user