added a "while " tag for aslongas effects which are not supposed to be treated as oneshot abilities. adding it as a tag allows for maximum flexibility in the code.

while i was at it reworked the aslongas class completely, i promised myself if another bug popped up with aslongas i would rewrite it. 20 hours later, we have an aslongas which does not care about when cards come or go.
aslongas should never have used the added/removed to determine the validity of its effect. i allow update to sort it out now in the update function of aslongas...also added a new function to it called sorterfunction tho it looks as it could be reduced in code i would appreciate that it remains as it is, simply because of the nightmare i went through fixing the previous 7 bugs or more reported for aslongas. the logic was far to jumbled up. this i hope is atleast cleaner and easier to understand for the future devs that might work on it.

note: all test passed, all manual testing also passed.

new while tag is used as follows.

[card]
name=Emperor Crocodile
auto=aslongas(other creature|myBattlefield) all(this) sacrifice while <1
text=When you control no other creatures, sacrifice Emperor Crocodile.
mana={3}{G}
type=Creature
subtype=Crocodile
power=5
toughness=5
[/card]

this will denote that the ability is NOT a oneshot ability and should remain effective for the entire time the card is in the field.
Issue: 613
This commit is contained in:
omegablast2002@yahoo.com
2011-03-27 14:37:12 +00:00
parent 45566ad5bd
commit 7d98628355
2 changed files with 92 additions and 54 deletions

View File

@@ -2347,9 +2347,10 @@ public:
MTGAbility * a;
int includeSelf;
int mini, maxi;
bool miniFound, maxiFound;
AAsLongAs(int _id, MTGCardInstance * _source, Damageable * _target, TargetChooser * _tc, int _includeSelf,
MTGAbility * ability, int mini = 0, int maxi = 0) :
ListMaintainerAbility(_id, _source, _target), NestedAbility(ability), mini(mini), maxi(maxi)
MTGAbility * ability, int mini = 0, int maxi = 0,bool miniFound = false,bool maxiFound = false) :
ListMaintainerAbility(_id, _source, _target), NestedAbility(ability), mini(mini), maxi(maxi),miniFound(miniFound),maxiFound(maxiFound)
{
tc = _tc;
includeSelf = _includeSelf;
@@ -2359,34 +2360,70 @@ public:
a = NULL;
}
int canBeInList(MTGCardInstance * card)
{
if(card->isPhased || source->isPhased)
return 0;
int size = 0;
size = (int) cards.size();
if (includeSelf && maxi && card == source && size > maxi)
{
removed(card);
}
if ((includeSelf || card != source) && tc->canTarget(card))
return 1;
return 0;
}
int resolve()
void Update(float dt)
{
ListMaintainerAbility::Update(dt);
if(!ability->oneShot)
SorterFunction();
}
int SorterFunction()
{
//TODO check if ability is oneShot ?
updateTargets();
int size = (int) cards.size();
if (maxi && size < maxi && (!mini || size > mini)) addAbilityToGame(); //special case for 0
if (ability->oneShot) a = NULL; //allows to call the effect several times
int size = 0;
size = (int) cards.size();
/////////////////DO NOT REFACTOR THIS SECTION/////////////////////////////////////////
//these were seperated becuase previous methods were far too confusing to understand//
//////////////////////////////////////////////////////////////////////////////////////
if (miniFound)
{
if (size > mini)
{
addAbilityToGame();
}
else
{
removeAbilityFromGame();
}
}
if (maxiFound)
{
if (size < maxi)
{
addAbilityToGame();
}
else
{
removeAbilityFromGame();
}
}
/////////////////////////////////////////////////////////////////////////
cards.clear();
players.clear();
return 1;
}
int canBeInList(MTGCardInstance * card)
{
if(card->isPhased || source->isPhased)
return 0;
if ((includeSelf || card != source) && tc->canTarget(card))
return 1;
return 0;
}
//////////resolve is used when the aslongas is nested, or used on instants and sorceries/////////
int resolve()
{
SorterFunction();
if (ability->oneShot)
{
a = NULL; //allows to call the effect several times
}
return 1;
}
int addAbilityToGame()
{
if (a) return 0;
@@ -2410,52 +2447,36 @@ public:
a = NULL;
return 1;
}
int _added(Damageable * d)
{
int size = (int) cards.size();
if (maxi && size >= maxi) return removeAbilityFromGame();
if (maxi) return 0;
if (size <= mini) return 0;
return addAbilityToGame();
}
/////////////////section required/////////////////////
int added(MTGCardInstance * card)
{
return _added(card);
return 1;
}
int added(Player * p)
{
return _added(p);
return 1;
}
int removed(MTGCardInstance * card)
{
size_t size = cards.size();
if (maxi && (int) size < maxi) return addAbilityToGame();
if (mini && (int) size > mini) return 0;
if (mini && (int) size <= mini) return removeAbilityFromGame();
if (!mini && !maxi && size != 0) return 0;
return removeAbilityFromGame();
return 1;
}
///////////////////////////////////////////////////////
~AAsLongAs()
{
if (!isClone)
SAFE_DELETE(ability);
SAFE_DELETE(ability);
}
const char * getMenuText()
{
if(ability)
{
return ability->getMenuText();
}
else
{
return "Ability";
}
if(ability)
{
return ability->getMenuText();
}
else
{
return "Ability";
}
}
AAsLongAs * clone() const

View File

@@ -1291,6 +1291,9 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
oneShot = 1;
if (a->oneShot)
oneShot = 1;
found = s.find("while ");
if (found != string::npos)
oneShot = 0;
Damageable * _target = NULL;
if (spell)
_target = spell->getNextDamageableTarget();
@@ -1299,14 +1302,22 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
int mini = 0;
int maxi = 0;
bool miniFound = false;
bool maxiFound = false;
found = s.find(" >");
if (found != string::npos)
{
mini = atoi(s.substr(found + 2, 3).c_str());
miniFound = true;
}
found = s.find(" <");
if (found != string::npos)
{
maxi = atoi(s.substr(found + 2, 3).c_str());
maxiFound = true;
}
switch (i)
{
@@ -1317,7 +1328,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
result = NEW AForeach(id, card, _target, lordTargets, lordIncludeSelf, a, mini, maxi);
break;
case 2:
result = NEW AAsLongAs(id, card, _target, lordTargets, lordIncludeSelf, a, mini, maxi);
{
if (!miniFound && !maxiFound)//for code without an operator treat as a mini.
{
miniFound = true;
}
result = NEW AAsLongAs(id, card, _target, lordTargets, lordIncludeSelf, a, mini, maxi,miniFound,maxiFound);
}
break;
case 3:
result = NEW ATeach(id, card, lordTargets, lordIncludeSelf, a);