im forced to do this commit in whole instead of parts as originally planned, and before my beta test period of the changes is complete BECAUSE there are people doing "clean up" and the MASSIVE amount of conflicts i have to resolve from it is WAY too much for me to take on after nearly 200 hours of coding this patch. i cant seem to get enough respect to have people hold off on "clean up" so this brings me to being forced to do a full commit before playtest period is done, so they can go ahead with there *super important* clean up.
ok i WAS going to write a full change log with code exsamples ect, but since im rushed you will get the short version of this log.
first bug fixes, and there were many,
indestructible creature bug fixed
halimar execavator *embearessing youtube video" bug is fixed
token text now displays source name and tokens abilities
fixed a card view null pointer in an iterator when code used combinations of foreach and aslongas with CD.
epic struggle bug fixed, aslongas was only parsing one space to the right of the operator.
extra cost containing targetting fixed, cards can now have multiple extra cost in all mana...this includes giving a card 2 targeted sacrifices as its main cost.
angelic chorus bug fixed, the card will be soft coded now.
and many other minor bugs fixed, hard to remember all which were fixed.
now, new abilities = words
"legendarylandwalk",
"desertlandwalk",
"snowforestlandwalk",
"snowplainslandwalk",
"snowmountainlandwalk",
"snowislandlandwalk",
"snowswamplandwalk",
"snowlandwalk",
"nonbasiclandwalk",
"strong",//cant be blocked by creature with less power
"weak",//cant block creatures with more power
"phasing",
all true landwalks will now be supported.
new cost types:
morph which is coded as follows
[card]
name=Bloodstoke Howler
facedown={3}
autofacedown={6}{R}:morph
autofaceup=3/0 all(beast|mybattlefield))
text=Morph {6}{R} (You may cast this face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.) -- When Bloodstoke Howler is turned
face up, Beast creatures you control get +3/+0 until end of turn.
mana={5}{R}
type=Creature
subtype=Beast
power=3
toughness=4
[/card]
you will notice new auto lines autofaceup and autofacedown
these are abilities the cards will have when theyre in that state.
the cost is coded as
facedown={cost}
when a card is faced up it gains auto= lines also.
tho is played normally it will NOT gain autofaceup=lines
card restrictions:
cards can now have restrictions placed on them the restrictions are.
all previous restrictions usable in activated abilities
with the follow additions
control two or more vampires
control less creatures
control snow land
casted a spell
one of a kind
fourth turn
before battle damage
after battle
during battle
[card]
name=Blood Frenzy
target=creature[attacking;blocking]
restriction=before battle damage
auto=4/0
auto=treason
text=Cast Blood Frenzy only before the combat damage step. -- Target attacking or blocking creature gets +4/+0 until end of turn. Destroy that creature
at the beginning of the next end step.
mana={1}{R}
type=Instant
[/card]
other cost now can have specail restrictions also:
otherrestriction=mytypemin:1 type(swamp),opponenttypemin:1 opponenttype(plains)
these are minimums required inplay of a type
it can be just you, or you and opponent or just opponent
you can also use the words "more" and "less" and * to compare the 2 players fields.
[card]
name=Cho-Arrim Legate
abilities=protection from black
other={0}
otherrestriction=mytypemin:1 type(swamp) , opponenttypemin:1 opponenttype(plains)
text=Protection from black -- If an opponent controls a Swamp and you control a Plains, you may cast Cho-Arrim Legate without paying its mana cost.
mana={2}{W}
type=Creature
subtype=Human Soldier
power=1
toughness=2
[/card]
activated ability gained a new restriction "opponentturnonly"
variables will now be recalculated during the resolve of the major abilities to produce the most current number.
{x}:draw:x <----
new number variables words:
using draw as an exsample
draw:auras <--auras on a creature
draw:type:ally <---counts the allys in your field. self explanitory
draw:thatmuch <--mostly a triggered effects number.
when you take damage draw that much
draw:lifelost
draw:oplifelost
these return the value of the life lost that turn.
new TRIGGER restricitions
sourcenottap
sourceTap
foelostthree<--card cycle uses opponent lost life
foelosttwo<--same as above
once<--this trigger will only ever trigger one time and never again.
new card discriptor words
[multicolor]
[leveler]
[enchanted]
[blackandgreen]
[blackandwhite]
[redandblue]
[blueandgreen]
[redandwhite]
CD will now recalculate the number again on resolve
meaning {x}:target(CreatureTargetChooser[manacost <=x]) will work, with an added bonus {x}:target(CreatureTargetChooser[manacost <=any word variable])
new this(:
this(tapped)<--for strange case cards.
this(untapped)
this(auras)
new MTGAbility keywords
(blink)
(blink)forsrc <--stay blinked while source inplay
hand(blink <---adding hand to the front makes it target hand.
livingweapon
this is an extension of token, simple attach the words "livingweapon" to the front of token( and it will autoamtically token that and attach the card to it.
token( gained:
"targetcontroller" targetting.
"battleready" if put in the tokens abilities it will be a attacker and tapped as it is entering play.
phaseout <--self explanitory
spiritlink <--stacking lifelink style effect that benifits the OWNER of the card.
combatspiritlink same as above.
stacking flanking, requires 2 abilities unfortunately
[card]
name=Agility
target=creature
auto=teach(creature) flanker
auto=teach(creature) flanking
text=Enchant creature -- Enchanted creature gets +1/+1 and has flanking. (Whenever a creature without flanking blocks this creature, the blocking
creature gets -1/-1 until end of turn.)
mana={1}{R}
type=Enchantment
subtype=Aura
[/card]
removeallcounters(number/number,name)
removes all counters of the type from a card, can all be
"all"
vampire hexmage effect.
added new tools for transforms
,setpower=number
,settoughness=number
removetypes
morph
autofacedown={0}:morph
eradicate <---same as the card name.
cumulativeupcost[ <--self explanitory
upcostmulti[ <--an upcost that will resolve with a && ability
phaseaction[ phase name ] ability
an ability that will trigger on the stated phase name.
also support for phaseactionmulti[
new triggers added:
@vampired( <--sengir vampire effect
@targeted(
@lifeloss(
@lifed(
add a special ability builder called dynamicability
it acts alot like a choose your own adventure book
dynamicability<! variable 1, variable 2, variable 3,variable 4!> optional ability targetting the original target.
variable list 1:
this is the primary amount source
source
mytgt
myself
myfoe
variable list 2:
this is the variable we're after, or the amount
power
toughness
manacost
colors
age
charge
oneonecounters
thatmuch
variable list 3:
this is the main effect
strike
draw
lifeloss
lifegain
pumppow
pumptough
pumpboth
deplete
countersoneone
variable list 4:
how it will do this effect to.
itself
eachother
targetcontroller
targetopponent
tosrc
srccontroller
srcopponent
the best way to explain its usage is to look at cards coded with this ability. or experiment with combinations.
new gameoption
First turn player:player, opponent, random
who takes the first turn
added poisoned status, tho not complete since MBS hasnt spoiled enough cards to see where this variable will be used.
taught ai how to counter spell
improved ai, it will now cast instants during interupts and during your turn.
previously ai treated instant cards the same as it treated sorceries, which was not fair to the ai.
im sure there is some messed items, but the rev directly before this one had formatting in the code that created hundreds of conflicts with this one, so i had to dig this info out of red and green sections.
cards and test are coming soon, i ask PLEASE do not alter these new additions until the test are commited.
im commiting without the test because instead of allowing me to proceed with my beta test period, there are some that wish to rush me into a commit. if you do not like this commit revert it, i absolutely on no grounds give permission to recommit afterwards. and i will not recommit if a revert is called.
This commit is contained in:
+177
-105
@@ -150,7 +150,7 @@ ManaCost * AIPlayer::getPotentialMana(MTGCardInstance * target)
|
||||
MTGCardInstance * card = amp->source;
|
||||
if (card == target)
|
||||
used[card] = true; //http://code.google.com/p/wagic/issues/detail?id=76
|
||||
if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost() == 1)
|
||||
if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost() >= 1)
|
||||
{
|
||||
result->add(amp->output);
|
||||
used[card] = true;
|
||||
@@ -771,7 +771,7 @@ int AIPlayer::effectBadOrGood(MTGCardInstance * card, int mode, TargetChooser *
|
||||
return BAKA_EFFECT_DONTKNOW;
|
||||
}
|
||||
|
||||
int AIPlayer::chooseTarget(TargetChooser * _tc, Player * forceTarget)
|
||||
int AIPlayer::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCardInstance * Choosencard)
|
||||
{
|
||||
vector<Targetable *> potentialTargets;
|
||||
TargetChooser * tc = _tc;
|
||||
@@ -780,11 +780,13 @@ int AIPlayer::chooseTarget(TargetChooser * _tc, Player * forceTarget)
|
||||
int checkOnly = 0;
|
||||
if (tc)
|
||||
{
|
||||
if(!Choosencard)
|
||||
checkOnly = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tc = gameObs->getCurrentTargetChooser();
|
||||
tc = gameObs->getCurrentTargetChooser();
|
||||
|
||||
}
|
||||
if (!tc)
|
||||
return 0;
|
||||
@@ -845,6 +847,35 @@ int AIPlayer::chooseTarget(TargetChooser * _tc, Player * forceTarget)
|
||||
}
|
||||
}
|
||||
}
|
||||
//targetting the stack
|
||||
zone = playerZones->stack;
|
||||
for (int k = 0; k < zone->nb_cards; k++)
|
||||
{
|
||||
MTGCardInstance* card = zone->cards[k];
|
||||
if (!tc->alreadyHasTarget(card) && tc->canTarget(card) && nbtargets < 50)
|
||||
{
|
||||
if (checkOnly)
|
||||
return 1;
|
||||
int multiplier = 1;
|
||||
if (getStats() && getStats()->isInTop(card, 10))
|
||||
{
|
||||
multiplier++;
|
||||
if (getStats()->isInTop(card, 5))
|
||||
{
|
||||
multiplier++;
|
||||
if (getStats()->isInTop(card, 3))
|
||||
{
|
||||
multiplier++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int l = 0; l < multiplier; l++)
|
||||
{
|
||||
potentialTargets.push_back(card);
|
||||
nbtargets++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nbtargets)
|
||||
{
|
||||
@@ -853,26 +884,28 @@ int AIPlayer::chooseTarget(TargetChooser * _tc, Player * forceTarget)
|
||||
switch (type)
|
||||
{
|
||||
case TARGET_CARD:
|
||||
{
|
||||
MTGCardInstance * card = ((MTGCardInstance *) potentialTargets[i]);
|
||||
clickstream.push(NEW AIAction(card));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
{
|
||||
MTGCardInstance * card = ((MTGCardInstance *) potentialTargets[i]);
|
||||
clickstream.push(NEW AIAction(card));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
case TARGET_PLAYER:
|
||||
{
|
||||
Player * player = ((Player *) potentialTargets[i]);
|
||||
clickstream.push(NEW AIAction(player));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
{
|
||||
Player * player = ((Player *) potentialTargets[i]);
|
||||
clickstream.push(NEW AIAction(player));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Couldn't find any valid target,
|
||||
//usually that's because we played a card that has bad side effects (ex: when X comes into play, return target land you own to your hand)
|
||||
//so we try again to choose a target in the other player's field...
|
||||
if (checkOnly)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int cancel = gameObs->cancelCurrentAction();
|
||||
if (!cancel && !forceTarget)
|
||||
return chooseTarget(_tc, target->opponent());
|
||||
@@ -1180,6 +1213,7 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
||||
if (tc)
|
||||
{
|
||||
int hasTarget = (chooseTarget(tc));
|
||||
if(tc)
|
||||
delete tc;
|
||||
if (!hasTarget)
|
||||
continue;
|
||||
@@ -1241,7 +1275,6 @@ void AIPlayerBaka::initTimer()
|
||||
{
|
||||
timer = 0.1f;
|
||||
}
|
||||
|
||||
int AIPlayerBaka::computeActions()
|
||||
{
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
@@ -1256,121 +1289,160 @@ int AIPlayerBaka::computeActions()
|
||||
if (chooseTarget())
|
||||
return 1;
|
||||
int currentGamePhase = g->getCurrentGamePhase();
|
||||
if (g->isInterrupting == this)
|
||||
{ // interrupting
|
||||
selectAbility();
|
||||
return 1;
|
||||
static bool findingCard = false;
|
||||
//this guard is put in place to prevent Ai from
|
||||
//ever running computeActions() function WHILE its already doing so.
|
||||
// Break if this happens in debug mode. If this happens, it's actually a bug
|
||||
assert(!findingCard);
|
||||
if (findingCard)
|
||||
{//is already looking kick me out of this function!
|
||||
return 0;
|
||||
}
|
||||
if (p != this && (Player*)g->isInterrupting == this && g->mLayers->stackLayer()->count(0, NOT_RESOLVED) == 1)
|
||||
{
|
||||
findingCard = true;
|
||||
CardDescriptor cd;
|
||||
ManaCost * currentMana = getPotentialMana();
|
||||
bool potential = false;
|
||||
if (currentMana->getConvertedCost())
|
||||
{
|
||||
//if theres mana i can use there then potential is true.
|
||||
potential = true;
|
||||
}
|
||||
//look for an instant of ability to interupt with
|
||||
if((castrestrictedspell == false && nospellinstant == false)&&
|
||||
(onlyonecast == false || castcount < 2) && (onlyoneinstant == false || castcount < 2))
|
||||
{
|
||||
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "instant");
|
||||
}
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
selectAbility();
|
||||
}
|
||||
}
|
||||
if (currentMana != NULL)
|
||||
delete (currentMana);
|
||||
if (nextCardToPlay)
|
||||
{
|
||||
if (potential)
|
||||
{
|
||||
tapLandsForMana(nextCardToPlay->getManaCost());
|
||||
}
|
||||
AIAction * a = NEW AIAction(nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
findingCard = false;
|
||||
nextCardToPlay = NULL;
|
||||
return 1;
|
||||
}
|
||||
nextCardToPlay = NULL;
|
||||
findingCard = false;
|
||||
return 0;
|
||||
}
|
||||
else if (p == this && g->mLayers->stackLayer()->count(0, NOT_RESOLVED) == 0)
|
||||
else if(p == this && g->mLayers->stackLayer()->count(0, NOT_RESOLVED) == 0)
|
||||
{ //standard actions
|
||||
CardDescriptor cd;
|
||||
|
||||
switch (currentGamePhase)
|
||||
{
|
||||
case Constants::MTG_PHASE_FIRSTMAIN:
|
||||
case Constants::MTG_PHASE_SECONDMAIN:
|
||||
{
|
||||
|
||||
bool potential = false;
|
||||
ManaCost * currentMana = getPotentialMana();
|
||||
if (currentMana->getConvertedCost())
|
||||
{
|
||||
//if theres mana i can use there then potential is true.
|
||||
potential = true;
|
||||
}
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "land");
|
||||
selectAbility();
|
||||
//look for the most expensive creature we can afford
|
||||
if (castrestrictedspell == false && nospellinstant == false)
|
||||
{
|
||||
if (onlyonecast == false || castcount < 2)
|
||||
ManaCost * currentMana = getPotentialMana();
|
||||
bool potential = false;
|
||||
if (currentMana->getConvertedCost())
|
||||
{
|
||||
if (onlyoneinstant == false || castcount < 2)
|
||||
//if theres mana i can use there then potential is true.
|
||||
potential = true;
|
||||
}
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "land");
|
||||
selectAbility();
|
||||
//look for the most expensive creature we can afford
|
||||
if((castrestrictedspell == false && nospellinstant == false)&&
|
||||
(onlyonecast == false || castcount < 2)&&(onlyoneinstant == false || castcount < 2))
|
||||
{
|
||||
if (castrestrictedcreature == false && nocreatureinstant == false)
|
||||
{
|
||||
if (castrestrictedcreature == false && nocreatureinstant == false)
|
||||
{
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "creature");
|
||||
}
|
||||
}
|
||||
//Let's Try an enchantment maybe ?
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "enchantment");
|
||||
}
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "artifact");
|
||||
}
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "sorcery");
|
||||
}
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "instant");
|
||||
}
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
selectAbility();
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "creature");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (currentMana != NULL)
|
||||
delete (currentMana);
|
||||
if (nextCardToPlay)
|
||||
{
|
||||
if (potential)
|
||||
{
|
||||
/////////////////////////
|
||||
//had to force this on Ai other wise it would pay nothing but 1 color for a sunburst card.
|
||||
//this does not teach it to use manaproducer more effectively, it simply allow it to use the manaproducers it does understand better on sunburst by force.
|
||||
if (nextCardToPlay->has(Constants::SUNBURST))
|
||||
//Let's Try an enchantment maybe ?
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
ManaCost * SunCheck = manaPool;
|
||||
SunCheck = getPotentialMana();
|
||||
for (int i = Constants::MTG_NB_COLORS - 1; i > 0; i--)
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "enchantment");
|
||||
}
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "artifact");
|
||||
}
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "sorcery");
|
||||
}
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
nextCardToPlay = FindCardToPlay(currentMana, "instant");
|
||||
}
|
||||
if (!nextCardToPlay)
|
||||
{
|
||||
selectAbility();
|
||||
}
|
||||
}
|
||||
if (currentMana != NULL)
|
||||
delete (currentMana);
|
||||
if (nextCardToPlay)
|
||||
{
|
||||
if (potential)
|
||||
{
|
||||
/////////////////////////
|
||||
//had to force this on Ai other wise it would pay nothing but 1 color for a sunburst card.
|
||||
//this does not teach it to use manaproducer more effectively, it simply allow it to use the manaproducers it does understand better on sunburst by force.
|
||||
if (nextCardToPlay->has(Constants::SUNBURST))
|
||||
{
|
||||
//sunburst for Ai
|
||||
if (SunCheck->hasColor(i))
|
||||
ManaCost * SunCheck = manaPool;
|
||||
SunCheck = getPotentialMana();
|
||||
for (int i = Constants::MTG_NB_COLORS - 1; i > 0; i--)
|
||||
{
|
||||
if (nextCardToPlay->getManaCost()->hasColor(i) > 0)
|
||||
{//do nothing if the card already has this color.
|
||||
}
|
||||
else
|
||||
//sunburst for Ai
|
||||
if (SunCheck->hasColor(i))
|
||||
{
|
||||
if (nextCardToPlay->sunburst < nextCardToPlay->getManaCost()->getConvertedCost())
|
||||
if (nextCardToPlay->getManaCost()->hasColor(i) > 0)
|
||||
{//do nothing if the card already has this color.
|
||||
}
|
||||
else
|
||||
{
|
||||
nextCardToPlay->getManaCost()->add(i, 1);
|
||||
nextCardToPlay->getManaCost()->remove(0, 1);
|
||||
nextCardToPlay->sunburst += 1;
|
||||
if (nextCardToPlay->sunburst < nextCardToPlay->getManaCost()->getConvertedCost())
|
||||
{
|
||||
nextCardToPlay->getManaCost()->add(i, 1);
|
||||
nextCardToPlay->getManaCost()->remove(0, 1);
|
||||
nextCardToPlay->sunburst += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete (SunCheck);
|
||||
}
|
||||
delete (SunCheck);
|
||||
/////////////////////////
|
||||
tapLandsForMana(nextCardToPlay->getManaCost());
|
||||
}
|
||||
/////////////////////////
|
||||
tapLandsForMana(nextCardToPlay->getManaCost());
|
||||
AIAction * a = NEW AIAction(nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
return 1;
|
||||
}
|
||||
AIAction * a = NEW AIAction(nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
selectAbility();
|
||||
}
|
||||
if (p->getManaPool()->getConvertedCost() > 0 && Checked == false)//not the best thing ever, but allows the Ai a chance to double check if its mana pool has something before moving on, atleast one time.
|
||||
{
|
||||
Checked = true;
|
||||
computeActions();
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectAbility();
|
||||
}
|
||||
if (p->getManaPool()->getConvertedCost() > 0 && Checked == false)//not the best thing ever, but allows the Ai a chance to double check if its mana pool has something before moving on, atleast one time.
|
||||
{
|
||||
Checked = true;
|
||||
computeActions();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Constants::MTG_PHASE_COMBATATTACKERS:
|
||||
chooseAttackers();
|
||||
break;
|
||||
|
||||
@@ -214,7 +214,8 @@ Interruptible(id), tc(tc), cost(_cost), payResult(payResult)
|
||||
int Spell::computeX(MTGCardInstance * card)
|
||||
{
|
||||
ManaCost * c = cost->Diff(card->getManaCost());
|
||||
int x = c->getCost(Constants::MTG_NB_COLORS);
|
||||
int x = 0;
|
||||
x = c->getCost(Constants::MTG_NB_COLORS);
|
||||
delete c;
|
||||
return x;
|
||||
}
|
||||
@@ -222,7 +223,8 @@ int Spell::computeX(MTGCardInstance * card)
|
||||
int Spell::computeXX(MTGCardInstance * card)
|
||||
{
|
||||
ManaCost * c = cost->Diff(card->getManaCost());
|
||||
int xx = c->getCost(Constants::MTG_NB_COLORS) / 2;
|
||||
int xx = 0;
|
||||
xx = c->getCost(Constants::MTG_NB_COLORS) / 2;
|
||||
delete c;
|
||||
return xx;
|
||||
}
|
||||
@@ -451,7 +453,39 @@ ostream& DrawAction::toString(ostream& out) const
|
||||
out << "DrawAction ::: nbcards : " << nbcards << " ; player : " << player;
|
||||
return out;
|
||||
}
|
||||
//////
|
||||
LifeAction::LifeAction(int id, Damageable * _target, int amount) :
|
||||
Interruptible(id), amount(amount),target(_target)
|
||||
{
|
||||
}
|
||||
|
||||
int LifeAction::resolve()
|
||||
{
|
||||
target->life += amount;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LifeAction::Render()
|
||||
{
|
||||
WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
|
||||
mFont->SetBase(0);
|
||||
mFont->SetScale(DEFAULT_MAIN_FONT_SCALE);
|
||||
char buffer[200];
|
||||
if(amount >= 0)
|
||||
sprintf(buffer, _("Player gains %i life").c_str(), amount);
|
||||
else if(amount >= 0)
|
||||
sprintf(buffer, _("Player loses %i life").c_str(), amount);
|
||||
else
|
||||
sprintf(buffer, _("Nothing happened").c_str(), amount);
|
||||
mFont->DrawString(buffer, x + 20, y, JGETEXT_LEFT);
|
||||
}
|
||||
|
||||
ostream& LifeAction::toString(ostream& out) const
|
||||
{
|
||||
out << "LifeAction ::: amount : " << amount << " ; target : " << target;
|
||||
return out;
|
||||
}
|
||||
/* The Action Stack itself */
|
||||
int ActionStack::addPutInGraveyard(MTGCardInstance * card)
|
||||
{
|
||||
PutInGraveyard * death = NEW PutInGraveyard(mCount, card);
|
||||
@@ -482,10 +516,20 @@ int ActionStack::addDraw(Player * player, int nb_cards)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ActionStack::addLife(Damageable * _target, int amount)
|
||||
{
|
||||
LifeAction * life = NEW LifeAction(mCount, _target, amount);
|
||||
addAction(life);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ActionStack::addDamage(MTGCardInstance * _source, Damageable * _target, int _damage)
|
||||
{
|
||||
Damage * damage = NEW Damage(_source, _target, _damage);
|
||||
addAction(damage);
|
||||
_source->thatmuch = _damage;
|
||||
_target->thatmuch = _damage;
|
||||
_target->lifeLostThisTurn += _damage;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+1278
-112
File diff suppressed because it is too large
Load Diff
@@ -42,6 +42,32 @@ void CardDescriptor::unsecuresetfresh(int k)
|
||||
fresh = k;
|
||||
}
|
||||
|
||||
void CardDescriptor::setisMultiColored(int w)
|
||||
{
|
||||
isMultiColored = w;
|
||||
}
|
||||
|
||||
void CardDescriptor::setisBlackAndWhite(int w)
|
||||
{
|
||||
isBlackAndWhite = w;
|
||||
}
|
||||
void CardDescriptor::setisRedAndBlue(int w)
|
||||
{
|
||||
isRedAndBlue = w;
|
||||
}
|
||||
void CardDescriptor::setisBlackAndGreen(int w)
|
||||
{
|
||||
isBlackAndGreen = w;
|
||||
}
|
||||
void CardDescriptor::setisBlueAndGreen(int w)
|
||||
{
|
||||
isBlueAndGreen = w;
|
||||
}
|
||||
void CardDescriptor::setisRedAndWhite(int w)
|
||||
{
|
||||
isRedAndWhite = w;
|
||||
}
|
||||
|
||||
void CardDescriptor::setNegativeSubtype(string value)
|
||||
{
|
||||
int id = Subtypes::subtypesList->find(value);
|
||||
@@ -203,10 +229,42 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card)
|
||||
match = NULL;
|
||||
}
|
||||
|
||||
if ((isToken == -1 && card->isToken) || (isToken == 1 && !card->isToken))
|
||||
if ((isMultiColored == -1 && card->isMultiColored) || (isMultiColored == 1 && !card->isMultiColored))
|
||||
{
|
||||
match = NULL;
|
||||
}
|
||||
if ((isBlackAndWhite == -1 && card->isBlackAndWhite) || (isBlackAndWhite == 1 && !card->isBlackAndWhite))
|
||||
{
|
||||
match = NULL;
|
||||
}
|
||||
if ((isRedAndBlue == -1 && card->isRedAndBlue) || (isRedAndBlue == 1 && !card->isRedAndBlue))
|
||||
{
|
||||
match = NULL;
|
||||
}
|
||||
if ((isBlackAndGreen == -1 && card->isBlackAndGreen) || (isBlackAndGreen == 1 && !card->isBlackAndGreen))
|
||||
{
|
||||
match = NULL;
|
||||
}
|
||||
if ((isBlueAndGreen == -1 && card->isBlueAndGreen) || (isBlueAndGreen == 1 && !card->isBlueAndGreen))
|
||||
{
|
||||
match = NULL;
|
||||
}
|
||||
if ((isRedAndWhite == -1 && card->isRedAndWhite) || (isRedAndWhite == 1 && !card->isRedAndWhite))
|
||||
{
|
||||
match = NULL;
|
||||
}
|
||||
if ((isLeveler == -1 && card->isLeveler) || (isLeveler == 1 && !card->isLeveler))
|
||||
{
|
||||
match = NULL;
|
||||
}
|
||||
if ((CDenchanted == -1 && card->enchanted) || (CDenchanted == 1 && !card->enchanted))
|
||||
{
|
||||
match = NULL;
|
||||
}
|
||||
if ((isToken == -1 && card->isToken) || (isToken == 1 && !card->isToken))
|
||||
{
|
||||
match = NULL;
|
||||
}
|
||||
if (attacker == 1)
|
||||
{
|
||||
if (defenser == &AnyCard)
|
||||
|
||||
@@ -141,6 +141,7 @@ void CardGui::Render()
|
||||
|
||||
bool alternate = true;
|
||||
JQuad * quad = WResourceManager::Instance()->RetrieveCard(card, CACHE_THUMB);
|
||||
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
//On pcs we render the big image if the thumbnail is not available
|
||||
if (!quad) quad = WResourceManager::Instance()->RetrieveCard(card);
|
||||
@@ -160,7 +161,13 @@ void CardGui::Render()
|
||||
shadow->SetColor(ARGB(static_cast<unsigned char>(actA)/2,255,255,255));
|
||||
renderer->RenderQuad(shadow, actX + (actZ - 1) * 15, actY + (actZ - 1) * 15, actT, 28 * actZ / 16, 40 * actZ / 16);
|
||||
}
|
||||
|
||||
JQuad* extracostshadow = NULL;
|
||||
if(card->isExtraCostTarget == true)
|
||||
{
|
||||
extracostshadow = WResourceManager::Instance()->GetQuad("extracostshadow");
|
||||
extracostshadow->SetColor(ARGB(static_cast<unsigned char>(actA)/2,100,0,0));
|
||||
renderer->RenderQuad(extracostshadow, actX + (actZ - 1) * 15, actY + (actZ - 1) * 15, actT, 28 * actZ / 16, 40 * actZ / 16);
|
||||
}
|
||||
if (quad)
|
||||
{
|
||||
quad->SetColor(ARGB(static_cast<unsigned char>(actA),255,255,255));
|
||||
@@ -185,7 +192,7 @@ void CardGui::Render()
|
||||
icon = WResourceManager::Instance()->GetQuad("c_red");
|
||||
else if (card->hasSubtype("island"))
|
||||
icon = WResourceManager::Instance()->GetQuad("c_blue");
|
||||
|
||||
|
||||
if (icon)
|
||||
{
|
||||
icon->SetColor(ARGB(static_cast<unsigned char>(actA),255,255,255));
|
||||
@@ -194,6 +201,14 @@ void CardGui::Render()
|
||||
}
|
||||
|
||||
}
|
||||
JQuad * mor = NULL;
|
||||
if(card->isMorphed && !alternate)
|
||||
{
|
||||
mor = WResourceManager::Instance()->GetQuad("morph");
|
||||
mor->SetColor(ARGB(255,255,255,255));
|
||||
renderer->RenderQuad(mor, actX, actY, actT,scale, scale);
|
||||
}
|
||||
|
||||
//draws the numbers power/toughness
|
||||
if (card->isCreature())
|
||||
{
|
||||
@@ -236,7 +251,6 @@ void CardGui::Render()
|
||||
shadow->SetColor(ARGB(200,255,255,255));
|
||||
renderer->RenderQuad(shadow, actX, actY, actT, (28 * actZ + 1) / 16, 40 * actZ / 16);
|
||||
}
|
||||
|
||||
PlayGuiObject::Render();
|
||||
}
|
||||
|
||||
@@ -552,6 +566,7 @@ void CardGui::TinyCropRender(MTGCard * card, const Pos& pos, JQuad * quad)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (q && q->mTex)
|
||||
{
|
||||
q->SetHotSpot(static_cast<float> (q->mTex->mWidth / 2), static_cast<float> (q->mTex->mHeight / 2));
|
||||
|
||||
@@ -29,6 +29,8 @@ CardPrimitive::CardPrimitive(CardPrimitive * source)
|
||||
|
||||
power = source->power;
|
||||
toughness = source->toughness;
|
||||
restriction = source->restriction;
|
||||
otherrestriction = source->otherrestriction;
|
||||
|
||||
magicText = source->magicText;
|
||||
for (map<string, string>::const_iterator it = source->magicTexts.begin(); it != source->magicTexts.end(); ++it)
|
||||
@@ -50,6 +52,7 @@ int CardPrimitive::init()
|
||||
magicTexts.clear();
|
||||
spellTargetType = "";
|
||||
alias = 0;
|
||||
bool hasRestriction = false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -83,6 +86,24 @@ bool CardPrimitive::isSpell()
|
||||
return (!isCreature() && !isLand());
|
||||
}
|
||||
|
||||
void CardPrimitive::setRestrictions(int _restriction)
|
||||
{
|
||||
restriction = _restriction;
|
||||
}
|
||||
int CardPrimitive::getRestrictions()
|
||||
{
|
||||
return restriction;
|
||||
}
|
||||
|
||||
void CardPrimitive::setOtherRestrictions(string _restriction)
|
||||
{
|
||||
otherrestriction = _restriction;
|
||||
}
|
||||
void CardPrimitive::getOtherRestrictions()
|
||||
{
|
||||
otherrestriction;
|
||||
}
|
||||
|
||||
void CardPrimitive::setColor(string _color, int removeAllOthers)
|
||||
{
|
||||
if (_color.compare("blue") == 0)
|
||||
|
||||
@@ -94,7 +94,9 @@ int Damage::resolve()
|
||||
}
|
||||
if ((_target)->has(Constants::ABSORB))
|
||||
{
|
||||
damage -= 1;
|
||||
damage -= (_target)->basicAbilities[Constants::ABSORB];
|
||||
if(damage < 0)
|
||||
damage = 0;
|
||||
}
|
||||
if ((_target)->has(Constants::WILTING))
|
||||
{
|
||||
@@ -132,6 +134,8 @@ int Damage::resolve()
|
||||
{
|
||||
_target->counters->addCounter(-1, -1);
|
||||
}
|
||||
if(_target->toughness <= 0 && _target->has(Constants::INDESTRUCTIBLE))
|
||||
_target->controller()->game->putInGraveyard(_target);
|
||||
|
||||
}
|
||||
else if (target->type_as_damageable == DAMAGEABLE_PLAYER && source->has(Constants::INFECT))
|
||||
|
||||
@@ -39,7 +39,7 @@ void DuelLayers::init()
|
||||
action->Add(NEW MTGLifelinkRule(-1));
|
||||
action->Add(NEW MTGDeathtouchRule(-1));
|
||||
action->Add(NEW OtherAbilitiesEventReceiver(-1));
|
||||
|
||||
action->Add(NEW MTGMorphCostRule(-1));
|
||||
//Other display elements
|
||||
action->Add(NEW HUDDisplay(-1));
|
||||
|
||||
|
||||
@@ -79,7 +79,13 @@ int LifeCost::doPay()
|
||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||
if (target)
|
||||
{
|
||||
_target->controller()->thatmuch = 1;
|
||||
WEvent * lifed = NULL;
|
||||
lifed = NEW WEventLife(_target->controller(),-1,1);
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
game->receiveEvent(lifed);
|
||||
_target->controller()->life -= 1;
|
||||
_target->controller()->lifeLostThisTurn += 1;
|
||||
target = NULL;
|
||||
if (tc)
|
||||
tc->initTargets();
|
||||
@@ -263,6 +269,20 @@ TapTargetCost::TapTargetCost(TargetChooser *_tc) :
|
||||
{
|
||||
}
|
||||
|
||||
int TapTargetCost::isPaymentSet()
|
||||
{
|
||||
if (target && target->isTapped())
|
||||
{
|
||||
tc->removeTarget(target);
|
||||
target->isExtraCostTarget = false;
|
||||
target = NULL;
|
||||
return 0;
|
||||
}
|
||||
if (target)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TapTargetCost::doPay()
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||
@@ -563,8 +583,19 @@ int ExtraCosts::tryToSetPayment(MTGCardInstance * card)
|
||||
{
|
||||
for (size_t i = 0; i < costs.size(); i++)
|
||||
{
|
||||
if (int result = costs[i]->setPayment(card))
|
||||
return result;
|
||||
if(!costs[i]->isPaymentSet())
|
||||
{
|
||||
for(size_t k = 0; k < costs.size(); k++)
|
||||
{
|
||||
if(card == costs[k]->target)
|
||||
return 0;
|
||||
}
|
||||
if (int result = costs[i]->setPayment(card))
|
||||
{
|
||||
card->isExtraCostTarget = true;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -584,7 +615,10 @@ int ExtraCosts::canPay()
|
||||
for (size_t i = 0; i < costs.size(); i++)
|
||||
{
|
||||
if (!costs[i]->canPay())
|
||||
{
|
||||
costs[i]->target->isExtraCostTarget = false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -594,6 +628,8 @@ int ExtraCosts::doPay()
|
||||
int result = 0;
|
||||
for (size_t i = 0; i < costs.size(); i++)
|
||||
{
|
||||
if(costs[i]->target)
|
||||
costs[i]->target->isExtraCostTarget = false;
|
||||
result += costs[i]->doPay();
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -191,6 +191,8 @@ void GameApp::Create()
|
||||
WResourceManager::Instance()->RetrieveTexture("BattleIcon.png", RETRIEVE_MANAGE);
|
||||
WResourceManager::Instance()->RetrieveTexture("DefenderIcon.png", RETRIEVE_MANAGE);
|
||||
WResourceManager::Instance()->RetrieveTexture("shadow.png", RETRIEVE_MANAGE);
|
||||
WResourceManager::Instance()->RetrieveTexture("extracostshadow.png", RETRIEVE_MANAGE);
|
||||
WResourceManager::Instance()->RetrieveTexture("morph.jpg", RETRIEVE_MANAGE);
|
||||
|
||||
jq = WResourceManager::Instance()->RetrieveQuad("BattleIcon.png", 0, 0, 25, 25, "BattleIcon", RETRIEVE_MANAGE);
|
||||
if (jq)
|
||||
@@ -201,6 +203,12 @@ void GameApp::Create()
|
||||
jq = WResourceManager::Instance()->RetrieveQuad("shadow.png", 0, 0, 16, 16, "shadow", RETRIEVE_MANAGE);
|
||||
if (jq)
|
||||
jq->SetHotSpot(8, 8);
|
||||
jq = WResourceManager::Instance()->RetrieveQuad("extracostshadow.png", 0, 0, 16, 16, "extracostshadow", RETRIEVE_MANAGE);
|
||||
if (jq)
|
||||
jq->SetHotSpot(8, 8);
|
||||
jq = WResourceManager::Instance()->RetrieveQuad("morph.jpg", 0, 0, MTG_MINIIMAGE_WIDTH, MTG_MINIIMAGE_HEIGHT, "morph", RETRIEVE_MANAGE);
|
||||
if (jq)
|
||||
jq->SetHotSpot(static_cast<float> (jq->mTex->mWidth / 2), static_cast<float> (jq->mTex->mHeight / 2));
|
||||
jq = WResourceManager::Instance()->RetrieveQuad("phasebar.png", 0, 0, 0, 0, "phasebar", RETRIEVE_MANAGE);
|
||||
|
||||
LOG("Init Collection");
|
||||
|
||||
@@ -118,6 +118,7 @@ void GameObserver::nextGamePhase()
|
||||
currentPlayer->onlyoneinstant = false;
|
||||
currentPlayer->damageCount = 0;
|
||||
currentPlayer->preventable = 0;
|
||||
currentPlayer->isPoisoned = false;
|
||||
mLayers->actionLayer()->cleanGarbage(); //clean abilities history for this turn;
|
||||
mLayers->stackLayer()->garbageCollect(); //clean stack history for this turn;
|
||||
mLayers->actionLayer()->Update(0);
|
||||
@@ -140,6 +141,8 @@ void GameObserver::nextGamePhase()
|
||||
while (currentPlayer->game->hand->nb_cards > 7 && currentPlayer->nomaxhandsize == false)
|
||||
currentPlayer->game->putInGraveyard(currentPlayer->game->hand->cards[0]);
|
||||
mLayers->actionLayer()->Update(0);
|
||||
currentPlayer->lifeLostThisTurn = 0;
|
||||
currentPlayer->opponent()->lifeLostThisTurn = 0;
|
||||
return nextGamePhase();
|
||||
}
|
||||
|
||||
@@ -382,6 +385,14 @@ void GameObserver::gameStateBasedEffects()
|
||||
{
|
||||
players[i]->canPutLandsIntoPlay = true;
|
||||
}
|
||||
if(players[i]->poisonCount > 0)
|
||||
{
|
||||
players[i]->isPoisoned = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
players[i]->isPoisoned = false;
|
||||
}
|
||||
}
|
||||
if (mLayers->stackLayer()->count(0, NOT_RESOLVED) != 0)
|
||||
return;
|
||||
@@ -401,12 +412,77 @@ void GameObserver::gameStateBasedEffects()
|
||||
{
|
||||
MTGCardInstance * card = zone->cards[j];
|
||||
card->afterDamage();
|
||||
|
||||
//Remove auras that don't have a valid target anymore
|
||||
///////////////////////////////////////////////////////
|
||||
//Remove auras that don't have a valid target anymore//
|
||||
///////////////////////////////////////////////////////
|
||||
if (card->target && !isInPlay(card->target) && !card->hasType("equipment"))
|
||||
{
|
||||
players[i]->game->putInGraveyard(card);
|
||||
}
|
||||
card->enchanted = false;
|
||||
if (card->target && isInPlay(card->target) && !card->hasType("equipment") && card->hasSubtype("aura"))
|
||||
{
|
||||
card->target->enchanted = true;
|
||||
}
|
||||
///////////////////////////
|
||||
//reset extracost shadows//
|
||||
///////////////////////////
|
||||
card->isExtraCostTarget = false;
|
||||
if(mExtraPayment != NULL)
|
||||
{
|
||||
for(unsigned int ec = 0;ec < mExtraPayment->costs.size();ec++)
|
||||
{
|
||||
if( mExtraPayment->costs[ec]->target)
|
||||
mExtraPayment->costs[ec]->target->isExtraCostTarget = true;
|
||||
}
|
||||
}
|
||||
//////////////////////
|
||||
//reset morph hiding//
|
||||
//////////////////////
|
||||
if((card->previous && card->previous->morphed && !card->turningOver) || (card->morphed && !card->turningOver))
|
||||
{
|
||||
card->morphed = true;
|
||||
card->isMorphed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
card->isMorphed = false;
|
||||
card->morphed = false;
|
||||
}
|
||||
//////////////////////////
|
||||
//handles phasing events//
|
||||
//////////////////////////
|
||||
if((card->has(Constants::PHASING)&& currentGamePhase == Constants::MTG_PHASE_UNTAP && currentPlayer == card->controller() && card->phasedTurn != turn && !card->isPhased) || (card->isTempPhased && !card->isPhased))
|
||||
{
|
||||
card->isPhased = true;
|
||||
card->phasedTurn = turn;
|
||||
if(card->view)
|
||||
card->view->alpha = 50;
|
||||
card->initAttackersDefensers();
|
||||
}
|
||||
else if((card->has(Constants::PHASING) || card->isTempPhased)&& currentGamePhase == Constants::MTG_PHASE_UNTAP && currentPlayer == card->controller() && card->phasedTurn != turn)
|
||||
{
|
||||
card->isPhased = false;
|
||||
card->phasedTurn = turn;
|
||||
if(card->view)
|
||||
card->view->alpha = 255;
|
||||
card->isTempPhased = false;
|
||||
}
|
||||
if (card->target && isInPlay(card->target) && (card->hasSubtype("equipment") || card->hasSubtype("aura")))
|
||||
{
|
||||
card->isPhased = card->target->isPhased;
|
||||
card->phasedTurn = card->target->phasedTurn;
|
||||
if(card->view && card->target->view)
|
||||
card->view->alpha = card->target->view->alpha;
|
||||
}
|
||||
//////////////////////////
|
||||
//forceDestroy over ride//
|
||||
//////////////////////////
|
||||
if(card->isInPlay())
|
||||
{
|
||||
card->graveEffects = false;
|
||||
card->exileEffects = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//-------------------------------------
|
||||
@@ -524,22 +600,22 @@ void GameObserver::gameStateBasedEffects()
|
||||
}
|
||||
//------------------------------------
|
||||
if (players[0]->bothrestrictedcreature)
|
||||
players[1]->castrestrictedcreature = true;
|
||||
players[1]->castrestrictedcreature = true;
|
||||
//------------------------------------
|
||||
if (players[0]->bothrestrictedspell)
|
||||
players[1]->castrestrictedspell = true;
|
||||
players[1]->castrestrictedspell = true;
|
||||
//------------------------------------
|
||||
if (players[0]->onlyoneboth)
|
||||
players[1]->onlyoneboth = true;
|
||||
players[1]->onlyoneboth = true;
|
||||
//------------------------------------
|
||||
if (players[1]->bothrestrictedcreature)
|
||||
players[0]->castrestrictedcreature = true;
|
||||
players[0]->castrestrictedcreature = true;
|
||||
//------------------------------------
|
||||
if (players[1]->bothrestrictedspell)
|
||||
players[0]->castrestrictedspell = true;
|
||||
players[0]->castrestrictedspell = true;
|
||||
//------------------------------------
|
||||
if (players[1]->onlyoneboth)
|
||||
players[0]->onlyoneboth = true;
|
||||
players[0]->onlyoneboth = true;
|
||||
//------------------------------------
|
||||
/////////////////////////////////////////////////
|
||||
//handle end of turn effects while we're at it.//
|
||||
@@ -552,7 +628,10 @@ void GameObserver::gameStateBasedEffects()
|
||||
|
||||
if(!c)break;
|
||||
while (c->flanked)
|
||||
{//undoes the flanking on a card
|
||||
{
|
||||
/////////////////////////////////
|
||||
//undoes the flanking on a card//
|
||||
/////////////////////////////////
|
||||
c->power += 1;
|
||||
c->addToToughness(1);
|
||||
c->flanked -= 1;
|
||||
@@ -582,14 +661,13 @@ void GameObserver::gameStateBasedEffects()
|
||||
p->game->putInExile(c);
|
||||
|
||||
}
|
||||
if(nbcards > z->nb_cards)
|
||||
{
|
||||
t = 0;
|
||||
nbcards = z->nb_cards;
|
||||
}
|
||||
if(nbcards > z->nb_cards)
|
||||
{
|
||||
t = 0;
|
||||
nbcards = z->nb_cards;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MTGGameZone * f = p->game->graveyard;
|
||||
for (int k = 0; k < f->nb_cards; k++)
|
||||
{
|
||||
@@ -601,11 +679,55 @@ void GameObserver::gameStateBasedEffects()
|
||||
{
|
||||
p->nomaxhandsize = false;
|
||||
if (!p->bothrestrictedcreature && !p->opponent()->bothrestrictedcreature)
|
||||
p->castrestrictedcreature = false;
|
||||
p->castrestrictedcreature = false;
|
||||
if (!p->bothrestrictedspell && !p->opponent()->bothrestrictedspell)
|
||||
p->castrestrictedspell = false;
|
||||
p->castrestrictedspell = false;
|
||||
p->onlyonecast = false;
|
||||
}
|
||||
//////////////////////////
|
||||
// Check auras on a card//
|
||||
//////////////////////////
|
||||
enchantmentStatus();
|
||||
/////////////////////////////////////
|
||||
// Check colored statuses on cards //
|
||||
/////////////////////////////////////
|
||||
for(int w = 0;w < z->nb_cards;w++)
|
||||
{
|
||||
int colored = 0;
|
||||
for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; ++i)
|
||||
{
|
||||
if (z->cards[w]->hasColor(i))
|
||||
++colored;
|
||||
}
|
||||
if(colored > 1)
|
||||
{
|
||||
z->cards[w]->isMultiColored = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
z->cards[w]->isMultiColored = 0;
|
||||
}
|
||||
if(z->cards[w]->hasColor(Constants::MTG_COLOR_WHITE) && z->cards[w]->hasColor(Constants::MTG_COLOR_BLACK))
|
||||
z->cards[w]->isBlackAndWhite = 1;
|
||||
else
|
||||
z->cards[w]->isBlackAndWhite = 0;
|
||||
if(z->cards[w]->hasColor(Constants::MTG_COLOR_RED) && z->cards[w]->hasColor(Constants::MTG_COLOR_BLUE))
|
||||
z->cards[w]->isRedAndBlue = 1;
|
||||
else
|
||||
z->cards[w]->isRedAndBlue = 0;
|
||||
if(z->cards[w]->hasColor(Constants::MTG_COLOR_GREEN) && z->cards[w]->hasColor(Constants::MTG_COLOR_BLACK))
|
||||
z->cards[w]->isBlackAndGreen = 1;
|
||||
else
|
||||
z->cards[w]->isBlackAndGreen = 0;
|
||||
if(z->cards[w]->hasColor(Constants::MTG_COLOR_BLUE) && z->cards[w]->hasColor(Constants::MTG_COLOR_GREEN))
|
||||
z->cards[w]->isBlueAndGreen = 1;
|
||||
else
|
||||
z->cards[w]->isBlueAndGreen = 0;
|
||||
if(z->cards[w]->hasColor(Constants::MTG_COLOR_RED) && z->cards[w]->hasColor(Constants::MTG_COLOR_WHITE))
|
||||
z->cards[w]->isRedAndWhite = 1;
|
||||
else
|
||||
z->cards[w]->isRedAndWhite = 0;
|
||||
}
|
||||
}
|
||||
///////////////////////////////////
|
||||
//phase based state effects------//
|
||||
@@ -613,33 +735,58 @@ void GameObserver::gameStateBasedEffects()
|
||||
if (combatStep == TRIGGERS)
|
||||
{
|
||||
if (!mLayers->stackLayer()->getNext(NULL, 0, NOT_RESOLVED) && !targetChooser
|
||||
&& !mLayers->actionLayer()->isWaitingForAnswer())
|
||||
mLayers->stackLayer()->AddNextCombatStep();
|
||||
&& !mLayers->actionLayer()->isWaitingForAnswer())
|
||||
mLayers->stackLayer()->AddNextCombatStep();
|
||||
}
|
||||
|
||||
//Auto skip Phases
|
||||
GameObserver * game = game->GetInstance();
|
||||
int skipLevel = (game->currentPlayer->playMode == Player::MODE_TEST_SUITE) ? Constants::ASKIP_NONE
|
||||
: options[Options::ASPHASES].number;
|
||||
: options[Options::ASPHASES].number;
|
||||
int nrCreatures = currentPlayer->game->inPlay->countByType("Creature");
|
||||
|
||||
if (skipLevel == Constants::ASKIP_SAFE || skipLevel == Constants::ASKIP_FULL)
|
||||
{
|
||||
if ((opponent()->isAI() && !(isInterrupting)) && ((currentGamePhase == Constants::MTG_PHASE_UNTAP)
|
||||
|| (currentGamePhase == Constants::MTG_PHASE_DRAW) || (currentGamePhase == Constants::MTG_PHASE_COMBATBEGIN)
|
||||
|| ((currentGamePhase == Constants::MTG_PHASE_COMBATATTACKERS) && (nrCreatures == 0))
|
||||
|| currentGamePhase == Constants::MTG_PHASE_COMBATEND || currentGamePhase == Constants::MTG_PHASE_ENDOFTURN
|
||||
|| ((currentGamePhase == Constants::MTG_PHASE_CLEANUP) && (currentPlayer->game->hand->nb_cards < 8))))
|
||||
userRequestNextGamePhase();
|
||||
|| (currentGamePhase == Constants::MTG_PHASE_DRAW) || (currentGamePhase == Constants::MTG_PHASE_COMBATBEGIN)
|
||||
|| ((currentGamePhase == Constants::MTG_PHASE_COMBATATTACKERS) && (nrCreatures == 0))
|
||||
|| currentGamePhase == Constants::MTG_PHASE_COMBATEND || currentGamePhase == Constants::MTG_PHASE_ENDOFTURN
|
||||
|| ((currentGamePhase == Constants::MTG_PHASE_CLEANUP) && (currentPlayer->game->hand->nb_cards < 8))))
|
||||
userRequestNextGamePhase();
|
||||
}
|
||||
if (skipLevel == Constants::ASKIP_FULL)
|
||||
{
|
||||
if ((opponent()->isAI() && !(isInterrupting)) && (currentGamePhase == Constants::MTG_PHASE_UPKEEP
|
||||
|| currentGamePhase == Constants::MTG_PHASE_COMBATDAMAGE))
|
||||
userRequestNextGamePhase();
|
||||
|| currentGamePhase == Constants::MTG_PHASE_COMBATDAMAGE))
|
||||
userRequestNextGamePhase();
|
||||
}
|
||||
}
|
||||
|
||||
void GameObserver::enchantmentStatus()
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
MTGGameZone * zone = players[i]->game->inPlay;
|
||||
for (int k = zone->nb_cards - 1; k >= 0; k--)
|
||||
{
|
||||
MTGCardInstance * card = zone->cards[k];
|
||||
if (card && !card->hasType("equipment") && !card->hasSubtype("aura"))
|
||||
{
|
||||
card->enchanted = false;
|
||||
card->auras = 0;
|
||||
}
|
||||
}
|
||||
for (int j = zone->nb_cards - 1; j >= 0; j--)
|
||||
{
|
||||
MTGCardInstance * card = zone->cards[j];
|
||||
if (card->target && isInPlay(card->target) && !card->hasType("equipment") && card->hasSubtype("aura"))
|
||||
{
|
||||
card->target->enchanted = true;
|
||||
card->target->auras += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void GameObserver::Render()
|
||||
{
|
||||
mLayers->Render();
|
||||
@@ -883,7 +1030,28 @@ int GameObserver::isInPlay(MTGCardInstance * card)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int GameObserver::isInGrave(MTGCardInstance * card)
|
||||
{
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
MTGGameZone * graveyard = players[i]->game->graveyard;
|
||||
if (players[i]->game->isInZone(card,graveyard))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int GameObserver::isInExile(MTGCardInstance * card)
|
||||
{
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
MTGGameZone * exile = players[i]->game->exile;
|
||||
if (players[i]->game->isInZone(card,exile))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void GameObserver::draw()
|
||||
{
|
||||
currentPlayer->game->drawFromLibrary();
|
||||
|
||||
@@ -28,6 +28,7 @@ const string Options::optionNames[] = {
|
||||
"disable_cards",
|
||||
"maxGrade",
|
||||
"ASPhases",
|
||||
"FirstPlayer",
|
||||
"economic_difficulty",
|
||||
"transitions",
|
||||
"bgStyle",
|
||||
@@ -441,6 +442,11 @@ GameOption * GameOptions::get(int optionID)
|
||||
goEnum->def = OptionASkipPhase::getInstance();
|
||||
go = goEnum;
|
||||
break;
|
||||
case Options::FIRSTPLAYER:
|
||||
goEnum = NEW GameOptionEnum();
|
||||
goEnum->def = OptionWhosFirst::getInstance();
|
||||
go = goEnum;
|
||||
break;
|
||||
case Options::KEY_BINDINGS:
|
||||
go = NEW GameOptionKeyBindings();
|
||||
break;
|
||||
@@ -870,6 +876,16 @@ OptionASkipPhase::OptionASkipPhase()
|
||||
mDef.values.push_back(EnumDefinition::assoc(Constants::ASKIP_FULL, "Full"));
|
||||
}
|
||||
;
|
||||
|
||||
OptionWhosFirst OptionWhosFirst::mDef;
|
||||
OptionWhosFirst::OptionWhosFirst()
|
||||
{
|
||||
mDef.values.push_back(EnumDefinition::assoc(Constants::WHO_P, "Player"));
|
||||
mDef.values.push_back(EnumDefinition::assoc(Constants::WHO_O, "Opponent"));
|
||||
mDef.values.push_back(EnumDefinition::assoc(Constants::WHO_R, "Random"));
|
||||
}
|
||||
;
|
||||
|
||||
OptionClosedHand OptionClosedHand::mDef;
|
||||
OptionClosedHand::OptionClosedHand()
|
||||
{
|
||||
|
||||
@@ -103,6 +103,10 @@ void GameStateOptions::Start()
|
||||
optionsList->Add(oASPhases);
|
||||
optionsTabs->Add(optionsList);
|
||||
|
||||
WDecoEnum * oFirstPlayer = NEW WDecoEnum(NEW OptionInteger(Options::FIRSTPLAYER, "First Turn Player", Constants::WHO_R, 1,
|
||||
Constants::WHO_P, "", Constants::WHO_P));
|
||||
optionsList->Add(oFirstPlayer);
|
||||
|
||||
optionsList = NEW WGuiKeyBinder("Key Bindings", this);
|
||||
optionsTabs->Add(optionsList);
|
||||
|
||||
|
||||
@@ -44,8 +44,11 @@ GuiHand::GuiHand(MTGHand* hand) :
|
||||
|
||||
GuiHand::~GuiHand()
|
||||
{
|
||||
for (vector<CardView*>::iterator it = cards.begin(); it != cards.end(); ++it)
|
||||
delete (*it);
|
||||
if(cards.size())
|
||||
{
|
||||
for (vector<CardView*>::iterator it = cards.begin(); it != cards.end(); ++it)
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
|
||||
void GuiHand::Update(float dt)
|
||||
|
||||
+920
-61
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,8 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to
|
||||
model = card;
|
||||
attacker = 0;
|
||||
lifeOrig = life;
|
||||
origpower = power;
|
||||
origtoughness = toughness;
|
||||
belongs_to = arg_belongs_to;
|
||||
owner = NULL;
|
||||
if (arg_belongs_to)
|
||||
@@ -69,7 +71,6 @@ void MTGCardInstance::copy(MTGCardInstance * card)
|
||||
toughness = data->toughness;
|
||||
life = toughness;
|
||||
lifeOrig = life;
|
||||
|
||||
magicText = data->magicText;
|
||||
spellTargetType = data->spellTargetType;
|
||||
alias = data->alias;
|
||||
@@ -109,6 +110,7 @@ void MTGCardInstance::initMTGCI()
|
||||
{
|
||||
sample = "";
|
||||
model = NULL;
|
||||
imprint = NULL;
|
||||
isToken = false;
|
||||
lifeOrig = 0;
|
||||
doDamageTest = 1;
|
||||
@@ -117,11 +119,29 @@ void MTGCardInstance::initMTGCI()
|
||||
untapping = 0;
|
||||
frozen = 0;
|
||||
fresh = 0;
|
||||
isMultiColored = 0;
|
||||
isBlackAndWhite = 0;
|
||||
isRedAndBlue = 0;
|
||||
isBlackAndGreen = 0;
|
||||
isBlueAndGreen = 0;
|
||||
isRedAndWhite = 0;
|
||||
isLeveler = 0;
|
||||
enchanted = false;
|
||||
CDenchanted = NULL;
|
||||
blinked = false;
|
||||
isExtraCostTarget = false;
|
||||
morphed = false;
|
||||
turningOver = false;
|
||||
isMorphed = false;
|
||||
isPhased = false;
|
||||
isTempPhased = false;
|
||||
phasedTurn = -1;
|
||||
didattacked = 0;
|
||||
didblocked = 0;
|
||||
notblocked = 0;
|
||||
sunburst = NULL;
|
||||
equipment = NULL;
|
||||
equipment = 0;
|
||||
auras = 0;
|
||||
|
||||
for (int i = 0; i < ManaCost::MANA_PAID_WITH_RETRACE +1; i++)
|
||||
alternateCostPaid[i] = 0;
|
||||
@@ -161,13 +181,39 @@ void MTGCardInstance::initMTGCI()
|
||||
s == "Dismiss" || s == "Equipment" || s == "Everglades" || s == "Grasslands" || s == "Lair" ||
|
||||
s == "Level" || s == "Levelup" || s == "Mine" || s == "Oasis" || s == "World" || s == "Aura"
|
||||
)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
addType(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int colored = 0;
|
||||
|
||||
for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; ++i)
|
||||
{
|
||||
if (this->hasColor(i))
|
||||
++colored;
|
||||
}
|
||||
if(colored > 1)
|
||||
{
|
||||
isMultiColored = 1;
|
||||
}
|
||||
|
||||
if(this->hasColor(Constants::MTG_COLOR_WHITE) && this->hasColor(Constants::MTG_COLOR_BLACK))
|
||||
isBlackAndWhite = 1;
|
||||
if(this->hasColor(Constants::MTG_COLOR_RED) && this->hasColor(Constants::MTG_COLOR_BLUE))
|
||||
isRedAndBlue = 1;
|
||||
if(this->hasColor(Constants::MTG_COLOR_GREEN) && this->hasColor(Constants::MTG_COLOR_BLACK))
|
||||
isBlackAndGreen = 1;
|
||||
if(this->hasColor(Constants::MTG_COLOR_BLUE) && this->hasColor(Constants::MTG_COLOR_GREEN))
|
||||
isBlueAndGreen = 1;
|
||||
if(this->hasColor(Constants::MTG_COLOR_RED) && this->hasColor(Constants::MTG_COLOR_WHITE))
|
||||
isRedAndWhite = 1;
|
||||
if(previous && previous->morphed == true && !turningOver)
|
||||
{
|
||||
morphed = true;
|
||||
isMorphed = true;
|
||||
}
|
||||
}
|
||||
|
||||
const string MTGCardInstance::getDisplayName() const
|
||||
@@ -529,6 +575,10 @@ int MTGCardInstance::canBlock(MTGCardInstance * opponent)
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::ONEBLOCKER] && opponent->blocked)
|
||||
return 0;
|
||||
if(opponent->basicAbilities[Constants::STRONG] && power < opponent->power)
|
||||
return 0;
|
||||
if(has(basicAbilities[Constants::WEAK]) && power < opponent->power)
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::FEAR] && !(hasType(Subtypes::TYPE_ARTIFACT) || hasColor(Constants::MTG_COLOR_BLACK)))
|
||||
return 0;
|
||||
|
||||
@@ -572,6 +622,24 @@ int MTGCardInstance::canBlock(MTGCardInstance * opponent)
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::PLAINSWALK] && controller()->game->inPlay->hasType("plains"))
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::LEGENDARYWALK] && controller()->game->inPlay->hasPrimaryType("legendary","land"))
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::DESERTWALK] && controller()->game->inPlay->hasSpecificType("land","desert"))
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::SNOWSWAMPWALK] && controller()->game->inPlay->hasSpecificType("snow","swamp"))
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::SNOWFORESTWALK] && controller()->game->inPlay->hasSpecificType("snow","forest"))
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::SNOWISLANDWALK] && controller()->game->inPlay->hasSpecificType("snow","island"))
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::SNOWMOUNTAINWALK] && controller()->game->inPlay->hasSpecificType("snow","mountain"))
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::SNOWPLAINSWALK] && controller()->game->inPlay->hasSpecificType("snow","plains"))
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::SNOWWALK] && controller()->game->inPlay->hasPrimaryType("snow","land"))
|
||||
return 0;
|
||||
if (opponent->basicAbilities[Constants::NONBASICWALK] && controller()->game->inPlay->hasTypeButNotType("land","basic"))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,12 +138,21 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi
|
||||
|
||||
case 'o': //othercost
|
||||
if (!primitive) primitive = NEW CardPrimitive();
|
||||
if(key[5] == 'r')//otherrestrictions
|
||||
{
|
||||
string value = val;
|
||||
primitive->setOtherRestrictions(value);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ManaCost * cost = primitive->getManaCost())
|
||||
{
|
||||
string value = val;
|
||||
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
||||
cost->alternative = ManaCost::parseManaCost(value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b': //buyback
|
||||
@@ -155,16 +164,26 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi
|
||||
cost->BuyBack = ManaCost::parseManaCost(value);
|
||||
}
|
||||
break;
|
||||
case 'f': //flashback
|
||||
if (!primitive) primitive = NEW CardPrimitive();
|
||||
if (ManaCost * cost = primitive->getManaCost())
|
||||
case 'f': //flashback//morph
|
||||
{
|
||||
string value = val;
|
||||
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
||||
cost->FlashBack = ManaCost::parseManaCost(value);
|
||||
if (!primitive) primitive = NEW CardPrimitive();
|
||||
if(ManaCost * cost = primitive->getManaCost())
|
||||
{
|
||||
if( s.find("facedown") != string::npos)//morph
|
||||
{
|
||||
string value = val;
|
||||
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
||||
cost->morph = ManaCost::parseManaCost(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
string value = val;
|
||||
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
||||
cost->FlashBack = ManaCost::parseManaCost(value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i': //id
|
||||
if (!card) card = NEW MTGCard();
|
||||
card->setMTGId(atoi(val));
|
||||
@@ -200,7 +219,61 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi
|
||||
break;
|
||||
|
||||
case 'r': //retrace/rarity
|
||||
if ('e' == key[1])
|
||||
if('s' == key[2])//restrictions
|
||||
{
|
||||
if (!primitive) primitive = NEW CardPrimitive();
|
||||
string value = val;
|
||||
primitive->setRestrictions(CardPrimitive::NO_RESTRICTION);
|
||||
primitive->hasRestriction = false;
|
||||
if (value.find("control two or more vampires") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::VAMPIRES);
|
||||
if (value.find("control less creatures") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::LESS_CREATURES);
|
||||
if (value.find("control snow land") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::SNOW_LAND_INPLAY);
|
||||
if (value.find("casted a spell") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::CASTED_A_SPELL);
|
||||
if (value.find("one of a kind") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::ONE_OF_AKIND);
|
||||
if (value.find("fourth turn") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::FOURTHTURN);
|
||||
if (value.find("before battle damage") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::BEFORECOMBATDAMAGE);
|
||||
if (value.find("after battle") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::AFTERCOMBAT);
|
||||
if (value.find("during battle") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::DURINGCOMBAT);
|
||||
if (value.find("myturnonly") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::PLAYER_TURN_ONLY);
|
||||
if (value.find("opponentturnonly") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::OPPONENT_TURN_ONLY);
|
||||
if (value.find("assorcery") != string::npos)
|
||||
primitive->setRestrictions(CardPrimitive::AS_SORCERY);
|
||||
string types[] = { "my", "opponent", "" };
|
||||
int starts[] = { CardPrimitive::MY_BEFORE_BEGIN, CardPrimitive::OPPONENT_BEFORE_BEGIN, CardPrimitive::BEFORE_BEGIN };
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
size_t found = value.find(types[j]);
|
||||
if (found != string::npos)
|
||||
{
|
||||
for (int i = 0; i < Constants::NB_MTG_PHASES; i++)
|
||||
{
|
||||
string toFind = types[j];
|
||||
toFind.append(Constants::MTGPhaseCodeNames[i]).append("only");
|
||||
found = value.find(toFind);
|
||||
if (found != string::npos)
|
||||
{
|
||||
if(primitive->hasRestriction == false)
|
||||
{
|
||||
primitive->setRestrictions(starts[j] + i);
|
||||
primitive->hasRestriction = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ('e' == key[1])
|
||||
{ //retrace
|
||||
if (!primitive) primitive = NEW CardPrimitive();
|
||||
if (ManaCost * cost = primitive->getManaCost())
|
||||
|
||||
@@ -24,6 +24,7 @@ const string Constants::kBuyBackKeyword = "buyback";
|
||||
const string Constants::kFlashBackKeyword = "flashback";
|
||||
const string Constants::kRetraceKeyword = "retrace";
|
||||
const string Constants::kKickerKeyword = "kicker";
|
||||
const string Constants::kMorphKeyword = "facedown";
|
||||
|
||||
const char* Constants::MTGBasicAbilities[] = {
|
||||
"trample",
|
||||
@@ -110,6 +111,18 @@ const char* Constants::MTGBasicAbilities[] = {
|
||||
"sunburst",
|
||||
"flanking",
|
||||
"exiledeath",
|
||||
"legendarylandwalk",
|
||||
"desertlandwalk",
|
||||
"snowforestlandwalk",
|
||||
"snowplainslandwalk",
|
||||
"snowmountainlandwalk",
|
||||
"snowislandlandwalk",
|
||||
"snowswamplandwalk",
|
||||
"snowlandwalk",
|
||||
"nonbasiclandwalk",
|
||||
"strong",//cant be blocked by creature with less power
|
||||
"weak",//cant block creatures with more power
|
||||
"phasing",
|
||||
};
|
||||
|
||||
map<string,int> Constants::MTGBasicAbilitiesMap;
|
||||
|
||||
@@ -275,6 +275,10 @@ MTGCardInstance * MTGPlayerCards::putInExile(MTGCardInstance * card)
|
||||
{
|
||||
copy = putInZone(card, stack, exile);
|
||||
}
|
||||
else if (hand->hasCard(card))
|
||||
{
|
||||
copy = putInZone(card, hand, exile);
|
||||
}
|
||||
else if (graveyard->hasCard(card))
|
||||
{
|
||||
copy = putInZone(card, graveyard, exile);
|
||||
@@ -325,6 +329,10 @@ MTGCardInstance * MTGPlayerCards::putInHand(MTGCardInstance * card)
|
||||
{
|
||||
copy = putInZone(card, graveyard, hand);
|
||||
}
|
||||
else if (exile->hasCard(card))
|
||||
{
|
||||
copy = putInZone(card, exile, hand);
|
||||
}
|
||||
else
|
||||
{
|
||||
copy = putInZone(card, hand, hand);
|
||||
@@ -332,6 +340,33 @@ MTGCardInstance * MTGPlayerCards::putInHand(MTGCardInstance * card)
|
||||
return copy;
|
||||
}
|
||||
|
||||
MTGCardInstance * MTGPlayerCards::putInBattlefield(MTGCardInstance * card)
|
||||
{
|
||||
MTGCardInstance * copy = NULL;
|
||||
MTGInPlay * InPlay = card->owner->game->battlefield;
|
||||
if (inPlay->hasCard(card))
|
||||
{
|
||||
copy = putInZone(card, inPlay, InPlay);
|
||||
}
|
||||
else if (stack->hasCard(card))
|
||||
{
|
||||
copy = putInZone(card, stack, InPlay);
|
||||
}
|
||||
else if (graveyard->hasCard(card))
|
||||
{
|
||||
copy = putInZone(card, graveyard, InPlay);
|
||||
}
|
||||
else if (exile->hasCard(card))
|
||||
{
|
||||
copy = putInZone(card, exile, InPlay);
|
||||
}
|
||||
else
|
||||
{
|
||||
copy = putInZone(card, InPlay, InPlay);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGameZone * to)
|
||||
{
|
||||
MTGCardInstance * copy = NULL;
|
||||
@@ -420,7 +455,14 @@ int MTGPlayerCards::isInPlay(MTGCardInstance * card)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGPlayerCards::isInZone(MTGCardInstance * card,MTGGameZone * zone)
|
||||
{
|
||||
if (zone->hasCard(card))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//--------------------------------------
|
||||
// Zones specific code
|
||||
//--------------------------------------
|
||||
@@ -537,6 +579,54 @@ int MTGGameZone::hasType(const char * value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGGameZone::hasPrimaryType(const char * value,const char * secondvalue)
|
||||
{
|
||||
for (int i = 0; i < (nb_cards); i++)
|
||||
{
|
||||
if (cards[i]->hasType(value) && cards[i]->hasType(secondvalue))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGGameZone::hasSpecificType(const char * value,const char * secondvalue)
|
||||
{
|
||||
for (int i = 0; i < (nb_cards); i++)
|
||||
{
|
||||
if (cards[i]->hasType(value) && cards[i]->hasSubtype(secondvalue))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGGameZone::hasTypeButNotType(const char * value,const char * secondvalue)
|
||||
{
|
||||
for (int i = 0; i < (nb_cards); i++)
|
||||
{
|
||||
if (cards[i]->hasType(value) && cards[i]->hasSubtype(value) && !cards[i]->hasType(secondvalue) && !cards[i]->hasSubtype(secondvalue))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGGameZone::hasName(string value)
|
||||
{
|
||||
for (int i = 0; i < (nb_cards); i++)
|
||||
{
|
||||
if (cards[i]->name == value)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGGameZone::hasColor(int value)
|
||||
{
|
||||
for (int i = 0; i < (nb_cards); i++)
|
||||
|
||||
@@ -35,6 +35,8 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if(!allowedToCast(card,player))
|
||||
return 0;
|
||||
if (card->hasType("land"))
|
||||
{
|
||||
if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay
|
||||
@@ -44,7 +46,7 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if ((card->hasType("instant")) || card->has(Constants::FLASH)
|
||||
else if ((card->hasType("instant")) || card->basicAbilities[Constants::FLASH]
|
||||
|| (player == currentPlayer && !game->isInterrupting
|
||||
&& (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
|
||||
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
|
||||
@@ -250,6 +252,11 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *
|
||||
if (!alternateManaCost)
|
||||
return 0;
|
||||
|
||||
if(!allowedToCast(card,player))
|
||||
return 0;
|
||||
if(!allowedToAltCast(card,player))
|
||||
return 0;
|
||||
|
||||
if (card->hasType("land"))
|
||||
{
|
||||
if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay
|
||||
@@ -356,7 +363,7 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter
|
||||
|
||||
if (card->hasType("land"))
|
||||
{
|
||||
MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp);
|
||||
MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->temp);
|
||||
spell = NEW Spell(copy);
|
||||
copy->alternateCostPaid[alternateCostType] = 1;
|
||||
spell->resolve();
|
||||
@@ -368,7 +375,7 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter
|
||||
else
|
||||
{
|
||||
ManaCost *spellCost = previousManaPool->Diff(player->getManaPool());
|
||||
MTGCardInstance * copy = player->game->putInZone(card, originatingZone, player->game->stack);
|
||||
MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->stack);
|
||||
copy->alternateCostPaid[alternateCostType] = 1;
|
||||
spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, spellCost, payResult, 0);
|
||||
game->targetChooser = NULL;
|
||||
@@ -431,6 +438,8 @@ MTGAlternativeCostRule(_id)
|
||||
int MTGBuyBackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
||||
{
|
||||
Player * player = game->currentlyActing();
|
||||
if(!allowedToCast(card,player))
|
||||
return 0;
|
||||
if (!player->game->hand->hasCard(card))
|
||||
return 0;
|
||||
return MTGAlternativeCostRule::isReactingToClick( card, mana, card->getManaCost()->BuyBack );
|
||||
@@ -584,13 +593,179 @@ MTGRetraceRule * MTGRetraceRule::clone() const
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
//-----------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
MTGMorphCostRule::MTGMorphCostRule(int _id) :
|
||||
MTGAbility(_id, NULL)
|
||||
{
|
||||
aType = MTGAbility::MORPH_COST;
|
||||
}
|
||||
int MTGMorphCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
||||
{
|
||||
int cardsinhand = game->players[0]->game->hand->nb_cards;
|
||||
Player * player = game->currentlyActing();
|
||||
Player * currentPlayer = game->currentPlayer;
|
||||
if (!player->game->hand->hasCard(card))
|
||||
return 0;
|
||||
if (!card->getManaCost()->morph)
|
||||
return 0;
|
||||
if(!allowedToCast(card,player))
|
||||
return 0;
|
||||
if(!allowedToAltCast(card,player))
|
||||
return 0;
|
||||
//note lands can morph too, this is different from other cost types.
|
||||
if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer
|
||||
&& !game->isInterrupting
|
||||
&& (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
|
||||
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
|
||||
)
|
||||
{
|
||||
ManaCost * playerMana = player->getManaPool();
|
||||
ManaCost * cost = card->getManaCost();
|
||||
ManaCost * morph = card->getManaCost()->morph;
|
||||
#ifdef WIN32
|
||||
cost->Dump();
|
||||
#endif
|
||||
if (player->castrestrictedspell == true && !card->hasType("land"))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (player->onlyonecast == true && player->castcount >= 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (player->nospellinstant == true)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (player->onlyoneinstant == true)
|
||||
{
|
||||
if (player->castcount >= 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (player->nocreatureinstant == true && card->hasType("creature"))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (player->castrestrictedcreature == true && card->hasType("creature"))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
//cost of card.
|
||||
if (morph && playerMana->canAfford(morph))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;//dont play if you cant afford it.
|
||||
}
|
||||
|
||||
int MTGMorphCostRule::reactToClick(MTGCardInstance * card)
|
||||
{
|
||||
//morphs reactToClick is extremely different then the other cost.
|
||||
if (!isReactingToClick(card))
|
||||
return 0;
|
||||
Player * player = game->currentlyActing();
|
||||
ManaCost * cost = card->getManaCost();
|
||||
ManaCost * morph = card->getManaCost()->morph;
|
||||
ManaCost * playerMana = player->getManaPool();
|
||||
//this handles extra cost payments at the moment a card is played.
|
||||
if (playerMana->canAfford(morph))
|
||||
{
|
||||
if (cost->morph->isExtraPaymentSet())
|
||||
{
|
||||
card->paymenttype = MTGAbility::MORPH_COST;
|
||||
if (!game->targetListIsSet(card))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cost->morph->setExtraCostsAction(this, card);
|
||||
game->mExtraPayment = cost->morph->extraCosts;
|
||||
card->paymenttype = MTGAbility::MORPH_COST;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
ManaCost * previousManaPool = NEW ManaCost(player->getManaPool());
|
||||
int payResult = player->getManaPool()->pay(card->getManaCost()->morph);
|
||||
card->getManaCost()->morph->doPayExtra();
|
||||
payResult = ManaCost::MANA_PAID_WITH_MORPH;
|
||||
//if morph has a extra payment thats set, this code pays it.the if statement is 100% needed as it would cause a crash on cards that dont have the morph cost.
|
||||
if (morph)
|
||||
{
|
||||
card->getManaCost()->morph->doPayExtra();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
ManaCost * spellCost = previousManaPool->Diff(player->getManaPool());
|
||||
delete previousManaPool;
|
||||
card->morphed = true;
|
||||
card->isMorphed = true;
|
||||
MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->stack);
|
||||
Spell * spell = NULL;
|
||||
spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 0);
|
||||
spell->source->morphed = true;
|
||||
spell->source->isMorphed = true;
|
||||
spell->source->name = "";
|
||||
spell->source->power = 2;
|
||||
spell->source->toughness = 2;
|
||||
copy->morphed = true;
|
||||
copy->isMorphed = true;
|
||||
copy->power = 2;
|
||||
copy->toughness = 2;
|
||||
player->castedspellsthisturn += 1;
|
||||
player->opponent()->castedspellsthisturn += 1;
|
||||
if (player->onlyonecast == true || player->onlyoneinstant == true)
|
||||
{
|
||||
player->castcount += 1;
|
||||
|
||||
}
|
||||
if (!card->has(Constants::STORM))
|
||||
{
|
||||
copy->X = spell->computeX(copy);
|
||||
copy->XX = spell->computeXX(copy);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//The morph rule is never destroyed
|
||||
int MTGMorphCostRule::testDestroy()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ostream& MTGMorphCostRule::toString(ostream& out) const
|
||||
{
|
||||
out << "MTGMorphCostRule ::: (";
|
||||
return MTGAbility::toString(out) << ")";
|
||||
}
|
||||
|
||||
MTGMorphCostRule * MTGMorphCostRule::clone() const
|
||||
{
|
||||
MTGMorphCostRule * a = NEW MTGMorphCostRule(*this);
|
||||
a->isClone = 1;
|
||||
return a;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
bool MTGAttackRule::select(Target* t)
|
||||
{
|
||||
if (CardView* c = dynamic_cast<CardView*>(t))
|
||||
{
|
||||
MTGCardInstance * card = c->getCard();
|
||||
if (card->canAttack())
|
||||
if (card->canAttack() && !card->isPhased)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -610,6 +785,8 @@ int MTGAttackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
||||
{
|
||||
if (currentPhase == Constants::MTG_PHASE_COMBATATTACKERS && card->controller() == game->currentPlayer)
|
||||
{
|
||||
if(card->isPhased)
|
||||
return 0;
|
||||
if (card->isAttacker())
|
||||
return 1;
|
||||
if (card->canAttack())
|
||||
@@ -845,7 +1022,7 @@ int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
|
||||
&& card->controller() == game->currentlyActing()
|
||||
)
|
||||
{
|
||||
if (card->canBlock())
|
||||
if (card->canBlock() && !card->isPhased)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -1620,6 +1797,8 @@ ListMaintainerAbility(_id)
|
||||
|
||||
int MTGLegendRule::canBeInList(MTGCardInstance * card)
|
||||
{
|
||||
if(card->isPhased)
|
||||
return 0;
|
||||
if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->isInPlay(card))
|
||||
{
|
||||
return 1;
|
||||
@@ -1684,6 +1863,11 @@ int MTGLifelinkRule::receiveEvent(WEvent * event)
|
||||
MTGCardInstance * card = d->source;
|
||||
if (d->damage > 0 && card && card->basicAbilities[Constants::LIFELINK])
|
||||
{
|
||||
card->controller()->thatmuch = d->damage;
|
||||
WEvent * lifed = NULL;
|
||||
lifed = NEW WEventLife(card->controller(),d->damage);
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
game->receiveEvent(lifed);
|
||||
card->controller()->life += d->damage;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -251,13 +251,13 @@ ManaCost::~ManaCost()
|
||||
{
|
||||
SAFE_DELETE(hybrids[i]);
|
||||
}
|
||||
|
||||
SAFE_DELETE(extraCosts);
|
||||
SAFE_DELETE(kicker);
|
||||
SAFE_DELETE(alternative);
|
||||
SAFE_DELETE(BuyBack);
|
||||
SAFE_DELETE(FlashBack);
|
||||
SAFE_DELETE(Retrace);
|
||||
SAFE_DELETE(morph);
|
||||
}
|
||||
|
||||
void ManaCost::x()
|
||||
@@ -285,6 +285,7 @@ void ManaCost::init()
|
||||
BuyBack = NULL;
|
||||
FlashBack = NULL;
|
||||
Retrace = NULL;
|
||||
morph = NULL;
|
||||
}
|
||||
|
||||
void ManaCost::copy(ManaCost * _manaCost)
|
||||
@@ -341,6 +342,12 @@ void ManaCost::copy(ManaCost * _manaCost)
|
||||
Retrace = NEW ManaCost();
|
||||
Retrace->copy(_manaCost->Retrace);
|
||||
}
|
||||
SAFE_DELETE(morph);
|
||||
if (_manaCost->morph)
|
||||
{
|
||||
morph = NEW ManaCost();
|
||||
morph->copy(_manaCost->morph);
|
||||
}
|
||||
}
|
||||
|
||||
int ManaCost::getCost(int color)
|
||||
|
||||
@@ -166,7 +166,7 @@ void RulesState::parsePlayerState(int playerId, string s)
|
||||
void Rules::addExtraRules()
|
||||
{
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
|
||||
|
||||
int id = g->mLayers->actionLayer()->getMaxId();
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
@@ -378,6 +378,16 @@ void Rules::initGame()
|
||||
DebugTrace("RULES Init Game\n");
|
||||
|
||||
//Set the current player/phase
|
||||
if (g->currentPlayer->playMode
|
||||
!= Player::MODE_TEST_SUITE && /*g->mRules->gamemode != GAME_TYPE_MOMIR && g->mRules->gamemode
|
||||
!= GAME_TYPE_RANDOM1 && g->mRules->gamemode != GAME_TYPE_RANDOM2 &&*/ g->mRules->gamemode
|
||||
!= GAME_TYPE_STORY)
|
||||
{
|
||||
if(OptionWhosFirst::WHO_R == options[Options::FIRSTPLAYER].number)
|
||||
initState.player = WRand() % 2;
|
||||
if(OptionWhosFirst::WHO_O == options[Options::FIRSTPLAYER].number)
|
||||
initState.player = 1;
|
||||
}
|
||||
g->currentPlayer = g->players[initState.player];
|
||||
g->currentActionPlayer = g->currentPlayer;
|
||||
g->currentPlayerId = initState.player;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Subtypes.h"
|
||||
#include "Counters.h"
|
||||
#include "WEvent.h"
|
||||
#include "AllAbilities.h"
|
||||
|
||||
TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInstance * card, MTGAbility * ability)
|
||||
{
|
||||
@@ -153,8 +154,23 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
||||
TargetChooser * tc = NULL;
|
||||
int maxtargets = 1;
|
||||
CardDescriptor * cd = NULL;
|
||||
//max targets allowed
|
||||
size_t limit = s1.find('<');
|
||||
if (limit != string::npos)
|
||||
{
|
||||
size_t end = s1.find(">", limit);
|
||||
string howmany;
|
||||
if (end != string::npos)
|
||||
{
|
||||
howmany = s1.substr(limit + 1, end - limit - 1);
|
||||
WParsedInt * howmuch = NEW WParsedInt(howmany, NULL, card);
|
||||
maxtargets = howmuch->getValue();
|
||||
delete howmuch;
|
||||
s1 = s1.substr(end + 1);
|
||||
}
|
||||
}
|
||||
|
||||
while (s1.size())
|
||||
while (s1.size())
|
||||
{
|
||||
found = s1.find(",");
|
||||
string typeName;
|
||||
@@ -206,8 +222,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
||||
size_t operatorPosition = attribute.find("=", 1);
|
||||
if (operatorPosition != string::npos)
|
||||
{
|
||||
comparisonCriterion = atoi(
|
||||
attribute.substr(operatorPosition + 1, attribute.size() - operatorPosition - 1).c_str());
|
||||
string numberCD = attribute.substr(operatorPosition + 1, attribute.size() - operatorPosition - 1);
|
||||
WParsedInt * val = NEW WParsedInt(numberCD,NULL, card);
|
||||
comparisonCriterion = val->getValue();
|
||||
/*atoi(attribute.substr(operatorPosition + 1, attribute.size() - operatorPosition - 1).c_str());*/
|
||||
delete val;
|
||||
switch (attribute[operatorPosition - 1])
|
||||
{
|
||||
case '<':
|
||||
@@ -305,10 +324,112 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
||||
{
|
||||
cd->unsecuresetfresh(1);
|
||||
}
|
||||
//Power restrictions
|
||||
}
|
||||
//creature is a level up creature
|
||||
else if (attribute.find("leveler") != string::npos)
|
||||
{
|
||||
if (minus)
|
||||
{
|
||||
cd->isLeveler = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
cd->isLeveler = 1;
|
||||
}
|
||||
}
|
||||
//creature is a level up creature
|
||||
else if (attribute.find("enchanted") != string::npos)
|
||||
{
|
||||
if (minus)
|
||||
{
|
||||
cd->CDenchanted = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
cd->CDenchanted = 1;
|
||||
}
|
||||
}
|
||||
else if (attribute.find("multicolor") != string::npos)
|
||||
{
|
||||
//card is multicolored?
|
||||
if (minus)
|
||||
{
|
||||
cd->setisMultiColored(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cd->setisMultiColored(1);
|
||||
}
|
||||
|
||||
}
|
||||
else if (attribute.find("blackandgreen") != string::npos)
|
||||
{
|
||||
//card is both colors?
|
||||
if (minus)
|
||||
{
|
||||
cd->setisBlackAndGreen(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cd->setisBlackAndGreen(1);
|
||||
}
|
||||
|
||||
}
|
||||
else if (attribute.find("blackandwhite") != string::npos)
|
||||
{
|
||||
//card is both colors?
|
||||
if (minus)
|
||||
{
|
||||
cd->setisBlackAndWhite(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cd->setisBlackAndWhite(1);
|
||||
}
|
||||
|
||||
}
|
||||
else if (attribute.find("redandblue") != string::npos)
|
||||
{
|
||||
//card is both colors?
|
||||
if (minus)
|
||||
{
|
||||
cd->setisRedAndBlue(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cd->setisRedAndBlue(1);
|
||||
}
|
||||
|
||||
}
|
||||
else if (attribute.find("blueandgreen") != string::npos)
|
||||
{
|
||||
//card is both colors?
|
||||
if (minus)
|
||||
{
|
||||
cd->setisBlueAndGreen(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cd->setisBlueAndGreen(1);
|
||||
}
|
||||
|
||||
}
|
||||
else if (attribute.find("redandwhite") != string::npos)
|
||||
{
|
||||
//card is both colors?
|
||||
if (minus)
|
||||
{
|
||||
cd->setisRedAndWhite(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cd->setisRedAndWhite(1);
|
||||
}
|
||||
|
||||
}
|
||||
else if (attribute.find("power") != string::npos)
|
||||
{
|
||||
//Power restrictions
|
||||
cd->setPower(comparisonCriterion);
|
||||
cd->powerComparisonMode = comparisonMode;
|
||||
//Toughness restrictions
|
||||
@@ -462,6 +583,8 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
||||
|
||||
TargetChooser * TargetChooserFactory::createTargetChooser(MTGCardInstance * card)
|
||||
{
|
||||
if(!card)
|
||||
return NULL;
|
||||
int id = card->getId();
|
||||
string s = card->spellTargetType;
|
||||
if (card->alias)
|
||||
@@ -540,6 +663,11 @@ bool TargetChooser::canTarget(Targetable * target)
|
||||
tempcard = tempcard->previous;
|
||||
}
|
||||
}
|
||||
if(source && ((source->hasSubtype("aura") || source->hasSubtype("equipment")) && source->target && source->target == card && source->target->isPhased && targetter->target == card))
|
||||
return true;
|
||||
//this is kinda cheating but by defualt we let auras and equipments always contenue to target a phased creature.
|
||||
else if(card->isPhased)
|
||||
return false;
|
||||
if (source && targetter && card->isInPlay())
|
||||
{
|
||||
if (card->has(Constants::SHROUD)) return false;
|
||||
@@ -574,7 +702,7 @@ int TargetChooser::ForceTargetListReady()
|
||||
|
||||
int TargetChooser::targetsReadyCheck()
|
||||
{
|
||||
if (cursor == 0)
|
||||
if (cursor <= 0)
|
||||
{
|
||||
return TARGET_NOK;
|
||||
}
|
||||
@@ -605,8 +733,8 @@ bool TargetChooser::validTargetsExist()
|
||||
{
|
||||
Player *p = GameObserver::GetInstance()->players[i];
|
||||
if (canTarget(p)) return true;
|
||||
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library };
|
||||
for (int k = 0; k < 4; k++)
|
||||
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile };
|
||||
for (int k = 0; k < 5; k++)
|
||||
{
|
||||
MTGGameZone * z = zones[k];
|
||||
if (targetsZone(z))
|
||||
@@ -764,7 +892,8 @@ bool DescriptorTargetChooser::canTarget(Targetable * target)
|
||||
if (target->typeAsTarget() == TARGET_CARD)
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||
if (cd->match(_target)) return true;
|
||||
if (cd->match(_target))
|
||||
return true;
|
||||
}
|
||||
else if (target->typeAsTarget() == TARGET_STACKACTION)
|
||||
{
|
||||
|
||||
@@ -135,13 +135,44 @@ int TestSuiteAI::Act(float dt)
|
||||
playMode = MODE_AI;
|
||||
return 1;
|
||||
}
|
||||
else if (action.compare("next") == 0)
|
||||
else if (action.compare("next") == 0 || action.find("goto") != string::npos)
|
||||
{
|
||||
GuiCombat * gc = g->mLayers->combatLayer();
|
||||
if (ORDER == g->combatStep || DAMAGE == g->combatStep)
|
||||
gc->clickOK();
|
||||
if(action.find("goto ")!= string::npos)
|
||||
{
|
||||
size_t found = action.find("goto ");
|
||||
string phase = action.substr(found + 5);
|
||||
int phaseToGo = 0;
|
||||
for (int i = 0; i < Constants::NB_MTG_PHASES; i++)
|
||||
{
|
||||
if (phase.find(Constants::MTGPhaseCodeNames[i]) != string::npos)
|
||||
{
|
||||
phaseToGo = i;
|
||||
}
|
||||
}
|
||||
if(g->currentGamePhase != phaseToGo)
|
||||
suite->currentAction--;
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
GuiCombat * gc = g->mLayers->combatLayer();
|
||||
if (ORDER == g->combatStep || DAMAGE == g->combatStep)
|
||||
{
|
||||
gc->clickOK();
|
||||
}
|
||||
else
|
||||
{
|
||||
g->userRequestNextGamePhase();
|
||||
}
|
||||
}
|
||||
else
|
||||
g->userRequestNextGamePhase();
|
||||
{
|
||||
GuiCombat * gc = g->mLayers->combatLayer();
|
||||
if (ORDER == g->combatStep || DAMAGE == g->combatStep)
|
||||
gc->clickOK();
|
||||
else
|
||||
g->userRequestNextGamePhase();
|
||||
}
|
||||
}
|
||||
else if (action.compare("yes") == 0)
|
||||
g->mLayers->stackLayer()->setIsInterrupting(this);
|
||||
|
||||
@@ -144,7 +144,7 @@ ThisDescriptor * ThisDescriptorFactory::createThisDescriptor(string s)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//equips
|
||||
//equips and auras
|
||||
found = s.find("gear");//still same meaning, better wording to word conflict with MTGAbility equip.
|
||||
if (found != string::npos)
|
||||
{
|
||||
@@ -156,7 +156,52 @@ ThisDescriptor * ThisDescriptorFactory::createThisDescriptor(string s)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
found = s.find("auras");
|
||||
if (found != string::npos)
|
||||
{
|
||||
ThisAuras * td = NEW ThisAuras(criterion);
|
||||
if (td)
|
||||
{
|
||||
td->comparisonMode = mode;
|
||||
return td;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
// opponent damage count
|
||||
found = s.find("opponentdamagecount");
|
||||
if (found != string::npos)
|
||||
{
|
||||
ThisOpponentDamageAmount * td = NEW ThisOpponentDamageAmount(criterion);
|
||||
if (td)
|
||||
{
|
||||
td->comparisonMode = mode;
|
||||
return td;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
//untapped status
|
||||
found = s.find("untapped");
|
||||
if (found != string::npos)
|
||||
{
|
||||
ThisUntapped * td = NEW ThisUntapped(criterion);
|
||||
if (td)
|
||||
{
|
||||
td->comparisonMode = mode;
|
||||
return td;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
found = s.find("tapped");
|
||||
if (found != string::npos)
|
||||
{
|
||||
ThisTapped * td = NEW ThisTapped(criterion);
|
||||
if (td)
|
||||
{
|
||||
td->comparisonMode = mode;
|
||||
return td;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
//whenever this creature attacks do effect
|
||||
found = s.find("attacking");
|
||||
if (found != string::npos)
|
||||
@@ -338,6 +383,42 @@ int ThisEquip::match(MTGCardInstance * card)
|
||||
return matchValue(card->equipment);
|
||||
}
|
||||
|
||||
ThisAuras::ThisAuras(int auras)
|
||||
{
|
||||
comparisonCriterion = auras;
|
||||
}
|
||||
int ThisAuras::match(MTGCardInstance * card)
|
||||
{
|
||||
return matchValue(card->auras);
|
||||
}
|
||||
|
||||
ThisOpponentDamageAmount::ThisOpponentDamageAmount(int damagecount)
|
||||
{
|
||||
comparisonCriterion = damagecount;
|
||||
}
|
||||
int ThisOpponentDamageAmount::match(MTGCardInstance * card)
|
||||
{
|
||||
return matchValue(card->controller()->opponent()->damageCount);
|
||||
}
|
||||
|
||||
ThisUntapped::ThisUntapped(int untapped)
|
||||
{
|
||||
comparisonCriterion = untapped;
|
||||
}
|
||||
int ThisUntapped::match(MTGCardInstance * card)
|
||||
{
|
||||
return matchValue(!card->isTapped());
|
||||
}
|
||||
|
||||
ThisTapped::ThisTapped(int tapped)
|
||||
{
|
||||
comparisonCriterion = tapped;
|
||||
}
|
||||
int ThisTapped::match(MTGCardInstance * card)
|
||||
{
|
||||
return matchValue(card->isTapped());
|
||||
}
|
||||
|
||||
ThisAttacked::ThisAttacked(int attack)
|
||||
{
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ Token::Token(string _name, MTGCardInstance * source, int _power, int _toughness)
|
||||
toughness = _toughness;
|
||||
life = toughness;
|
||||
lifeOrig = life;
|
||||
origpower = _power;
|
||||
origtoughness = _toughness;
|
||||
rarity = Constants::RARITY_T;
|
||||
name = _name;
|
||||
if (name.size() && name[0] >= 97 && name[0] <= 122) name[0] -= 32; //Poor man's camelcase. We assume strings we get are either Camelcased or lowercase
|
||||
|
||||
@@ -103,7 +103,11 @@ bool WCachedTexture::isLocked()
|
||||
|
||||
for (vector<WTrackedQuad*>::iterator it = trackedQuads.begin(); it != trackedQuads.end(); it++)
|
||||
{
|
||||
if ((*it)->isLocked()) return true;
|
||||
if ((*it) && (*it)->isLocked()) return true;
|
||||
//null case
|
||||
//tokens that were using workarounds such as mixes of aslongas with CD checks
|
||||
//and thisforeach would call to cache the tokens image, but since the effect never resolved it was NULL
|
||||
//when it came time to check if it was locked, it would trigger a break point here.
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -21,6 +21,11 @@ WEventDamage::WEventDamage(Damage *damage) :
|
||||
{
|
||||
}
|
||||
|
||||
WEventLife::WEventLife(Player * player,int amount,int Ltype) :
|
||||
WEvent(), player(player),amount(amount), Ltype(Ltype)
|
||||
{
|
||||
}
|
||||
|
||||
WEventDamageStackResolved::WEventDamageStackResolved() :
|
||||
WEvent()
|
||||
{
|
||||
@@ -87,6 +92,16 @@ WEventCardDiscard::WEventCardDiscard(MTGCardInstance * card) :
|
||||
{
|
||||
}
|
||||
|
||||
WEventVampire::WEventVampire(MTGCardInstance * card,MTGCardInstance * source,MTGCardInstance * victem) :
|
||||
WEventCardUpdate(card),source(source),victem(victem)
|
||||
{
|
||||
}
|
||||
|
||||
WEventTarget::WEventTarget(MTGCardInstance * card,MTGCardInstance * source) :
|
||||
WEventCardUpdate(card),card(card),source(source)
|
||||
{
|
||||
}
|
||||
|
||||
WEventCardChangeType::WEventCardChangeType(MTGCardInstance * card, int type, bool before, bool after) :
|
||||
WEventCardUpdate(card), type(type), before(before), after(after)
|
||||
{
|
||||
@@ -144,6 +159,42 @@ int WEventDamage::getValue()
|
||||
return damage->damage;
|
||||
}
|
||||
|
||||
Targetable * WEventLife::getTarget(int target)
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case TARGET_TO:
|
||||
return player;
|
||||
case TARGET_FROM:
|
||||
return player;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Targetable * WEventVampire::getTarget(int target)
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case TARGET_TO:
|
||||
return victem->next;
|
||||
case TARGET_FROM:
|
||||
return source;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Targetable * WEventTarget::getTarget(int target)
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case TARGET_TO:
|
||||
return card;
|
||||
case TARGET_FROM:
|
||||
return source;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Targetable * WEventZoneChange::getTarget(int target)
|
||||
{
|
||||
if (target) return card;
|
||||
|
||||
Reference in New Issue
Block a user