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
|
class TrCardDiscarded: public Trigger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TrCardDiscarded(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc,bool once = false) :
|
bool cycledTrigger;
|
||||||
Trigger(observer, id, source, once, tc)
|
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)
|
int triggerOnEventImpl(WEvent * event)
|
||||||
{
|
{
|
||||||
WEventCardDiscard * e = dynamic_cast<WEventCardDiscard *> (event);
|
MTGCardInstance * targetCard = NULL;
|
||||||
if (!e) return 0;
|
if(cycledTrigger)
|
||||||
if (!tc->canTarget(e->card)) return 0;
|
{
|
||||||
|
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;
|
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
|
//ninjutsu
|
||||||
|
|
||||||
class ANinja: public ActivatedAbility
|
class ANinja: public ActivatedAbility
|
||||||
|
|||||||
@@ -106,6 +106,15 @@ public:
|
|||||||
virtual DiscardCost * clone() const;
|
virtual DiscardCost * clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//cycle
|
||||||
|
class CycleCost : public ExtraCost
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CycleCost(TargetChooser *_tc = NULL);
|
||||||
|
virtual int doPay();
|
||||||
|
virtual CycleCost * clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
//tolibrary cost
|
//tolibrary cost
|
||||||
class ToLibraryCost : public ExtraCost
|
class ToLibraryCost : public ExtraCost
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -183,6 +183,12 @@ struct WEventCardDiscard : public WEventCardUpdate {
|
|||||||
virtual Targetable * getTarget(int target);
|
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
|
//Event when a card's "defenser" status changes
|
||||||
//before : attacker that card was blocking previously
|
//before : attacker that card was blocking previously
|
||||||
//after: attacker that card is blocking now
|
//after: attacker that card is blocking now
|
||||||
|
|||||||
@@ -225,8 +225,40 @@ int DiscardCost::doPay()
|
|||||||
}
|
}
|
||||||
return 0;
|
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 * ToLibraryCost::clone() const
|
||||||
{
|
{
|
||||||
ToLibraryCost * ec = NEW ToLibraryCost(*this);
|
ToLibraryCost * ec = NEW ToLibraryCost(*this);
|
||||||
|
|||||||
@@ -598,6 +598,10 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string magicText, int
|
|||||||
if (TargetChooser * tc = parseSimpleTC(s, "discarded", card))
|
if (TargetChooser * tc = parseSimpleTC(s, "discarded", card))
|
||||||
return NEW TrCardDiscarded(observer, id, card, tc,once);
|
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
|
//Card Damaging non combat
|
||||||
if (TargetChooser * tc = parseSimpleTC(s, "noncombatdamaged", card))
|
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);
|
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
|
//ninjutsu
|
||||||
found = s.find("ninjutsu");
|
found = s.find("ninjutsu");
|
||||||
|
|||||||
@@ -163,34 +163,41 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
|
|||||||
manaCost->addExtraCost(NEW UnTapCost);
|
manaCost->addExtraCost(NEW UnTapCost);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'c': //Counters
|
case 'c': //Counters or cycle
|
||||||
{
|
|
||||||
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);
|
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
|
default: //uncolored cost and hybrid costs
|
||||||
{
|
{
|
||||||
int intvalue = atoi(value.c_str());
|
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) :
|
WEventVampire::WEventVampire(MTGCardInstance * card,MTGCardInstance * source,MTGCardInstance * victem) :
|
||||||
WEventCardUpdate(card),source(source),victem(victem)
|
WEventCardUpdate(card),source(source),victem(victem)
|
||||||
{
|
{
|
||||||
@@ -232,6 +237,12 @@ Targetable * WEventCardDiscard::getTarget(int target)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Targetable * WEventCardCycle::getTarget(int target)
|
||||||
|
{
|
||||||
|
if (target) return card;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Targetable * WEventCardAttackedNotBlocked::getTarget(int target)
|
Targetable * WEventCardAttackedNotBlocked::getTarget(int target)
|
||||||
{
|
{
|
||||||
if (target) return card;
|
if (target) return card;
|
||||||
|
|||||||
Reference in New Issue
Block a user