- Parser: Added possibility to add multiple abilities for one cost, using keyword && (see Ardakar wastes in 10E). Currently only works with mana and damage
- Added a dozen new cards
- Improved testing suite : new keyword "choice" to select an item in the abilities popup menu
This commit is contained in:
wagic.the.homebrew
2009-01-18 06:42:59 +00:00
parent e978a7d168
commit 9e314720e9
15 changed files with 723 additions and 546 deletions
+110
View File
@@ -101,6 +101,17 @@ subtype=Angel
toughness=3 toughness=3
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {W} or {U} to your mana pool. Adarkar Wastes deals 1 damage to you.
auto={T}:Add {1}
auto={T}:Add {W} && Damage 1 controller
auto={T}:Add {B} && Damage 1 controller
id=129458
name=Adarkar Wastes
rarity=R
color=Land
type=Land
[/card]
[card]
text=Flying (This creature can't be blocked except by creatures with flying or reach.) Other black creatures get +1/+1. Nonblack creatures get -1/-1. text=Flying (This creature can't be blocked except by creatures with flying or reach.) Other black creatures get +1/+1. Nonblack creatures get -1/-1.
abilities=Legendary, flying abilities=Legendary, flying
auto=lord(creature[black]) 1/1 auto=lord(creature[black]) 1/1
@@ -127,6 +138,17 @@ type=Sorcery
mana={2}{B} mana={2}{B}
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {R} or {W} to your mana pool. Battlefield Forge deals 1 damage to you.
id=129479
auto={T}:Add {1}
auto={T}:Add {R} && Damage 1 controller
auto={T}:Add {W} && Damage 1 controller
name=Battlefield Forge
rarity=R
color=Land
type=Land
[/card]
[card]
text=Flash (You may play this spell any time you could play an instant.) First strike (This creature deals combat damage before creatures without first strike.) text=Flash (You may play this spell any time you could play an instant.) First strike (This creature deals combat damage before creatures without first strike.)
abilities=flash,first strike abilities=flash,first strike
id=136279 id=136279
@@ -189,6 +211,28 @@ type=Instant
mana={U}{U} mana={U}{U}
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {G} or {W} to your mana pool. Brushland deals 1 damage to you.
auto={T}:Add {1}
auto={T}:Add {G} && Damage 1 controller
auto={T}:Add {W} && Damage 1 controller
id=129496
name=Brushland
rarity=R
color=Land
type=Land
[/card]
[card]
text={T}: Add {1} to your mana pool. {T}: Add {W} or {B} to your mana pool. Caves of Koilos deals 1 damage to you.
auto={T}:Add {1}
auto={T}:Add {W} && Damage 1 controller
auto={T}:Add {B} && Damage 1 controller
id=129497
name=Caves of Koilos
rarity=R
color=Land
type=Land
[/card]
[card]
text=Counter target spell. text=Counter target spell.
alias=1196 alias=1196
id=129882 id=129882
@@ -809,6 +853,17 @@ subtype=Human Barbarian
toughness=1 toughness=1
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {R} or {G} to your mana pool. Karplusan Forest deals 1 damage to you.
auto={T}:Add {1}
auto={T}:Add {R} && Damage 1 controller
auto={T}:Add {G} && Damage 1 controller
id=129614
name=Karplusan Forest
rarity=R
color=Land
type=Land
[/card]
[card]
text=When Kavu Climber comes into play, draw a card. text=When Kavu Climber comes into play, draw a card.
id=129511 id=129511
name=Kavu Climber name=Kavu Climber
@@ -859,6 +914,17 @@ subtype=Elf Druid
toughness=1 toughness=1
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {B} or {G} to your mana pool. Llanowar Wastes deals 1 damage to you.
id=129627
auto={T}:Add {1}
auto={T}:Add {B} && Damage 1 controller
auto={T}:Add {G} && Damage 1 controller
name=Llanowar Wastes
rarity=R
color=Land
type=Land
[/card]
[card]
text={B}: Looming Shade gets +1/+1 until end of turn. text={B}: Looming Shade gets +1/+1 until end of turn.
auto={B}:1/1 auto={B}:1/1
id=129628 id=129628
@@ -1547,6 +1613,17 @@ subtype=Dragon
toughness=5 toughness=5
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {U} or {R} to your mana pool. Shivan Reef deals 1 damage to you.
id=129731
auto={T}:Add {1}
auto={T}:Add {U} && Damage 1 controller
auto={T}:Add {R} && Damage 1 controller
name=Shivan Reef
rarity=R
color=Land
type=Land
[/card]
[card]
text=Shock deals 2 damage to target creature or player. text=Shock deals 2 damage to target creature or player.
target=creature,player target=creature,player
auto=Damage:2 auto=Damage:2
@@ -1712,6 +1789,17 @@ subtype=Human Rebel
toughness=2 toughness=2
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {B} or {R} to your mana pool. Sulfurous Springs deals 1 damage to you.
id=129751
auto={T}:Add {1}
auto={T}:Add {B} && Damage 1 controller
auto={T}:Add {R} && Damage 1 controller
name=Sulfurous Springs
rarity=R
color=Land
type=Land
[/card]
[card]
text=Flying (This creature can't be blocked except by creatures with flying or reach.) text=Flying (This creature can't be blocked except by creatures with flying or reach.)
abilities=flying abilities=flying
id=129753 id=129753
@@ -1845,6 +1933,17 @@ subtype=Wolf
toughness=1 toughness=1
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {U} or {B} to your mana pool. Underground River deals 1 damage to you.
id=129778
auto={T}:Add {1}
auto={T}:Add {U} && Damage 1 controller
auto={T}:Add {B} && Damage 1 controller
name=Underground River
rarity=R
color=Land
type=Land
[/card]
[card]
text=Enchant creature (Target a creature as you play this. This card comes into play attached to that creature.) Enchanted creature gets +2/+1. text=Enchant creature (Target a creature as you play this. This card comes into play attached to that creature.) Enchanted creature gets +2/+1.
target=creature target=creature
auto=:2/1 auto=:2/1
@@ -1984,6 +2083,17 @@ type=Sorcery
mana={2}{W}{W} mana={2}{W}{W}
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {G} or {U} to your mana pool. Yavimaya Coast deals 1 damage to you.
id=129810
auto={T}:Add {1}
auto={T}:Add {G} && Damage 1 controller
auto={T}:Add {U} && Damage 1 controller
name=Yavimaya Coast
rarity=R
color=Land
type=Land
[/card]
[card]
text=First strike (This creature deals combat damage before creatures without first strike.) text=First strike (This creature deals combat damage before creatures without first strike.)
abilities=first strike abilities=first strike
id=129790 id=129790
+1 -80
View File
@@ -20,14 +20,6 @@ subtype=Human Wizard
toughness=2 toughness=2
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {W} or {U} to your mana pool. Adarkar Wastes deals 1 damage to you.
id=129458
name=Adarkar Wastes
rarity=R
color=Land
type=Land
[/card]
[card]
text=Look at target player's hand and choose two cards from it. Put them on top of that player's library in any order. text=Look at target player's hand and choose two cards from it. Put them on top of that player's library in any order.
id=135228 id=135228
name=Agonizing Memories name=Agonizing Memories
@@ -178,14 +170,6 @@ type=Instant
mana={W} mana={W}
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {R} or {W} to your mana pool. Battlefield Forge deals 1 damage to you.
id=129479
name=Battlefield Forge
rarity=R
color=Land
type=Land
[/card]
[card]
text=Beacon of Destruction deals 5 damage to target creature or player. Shuffle Beacon of Destruction into its owner's library. text=Beacon of Destruction deals 5 damage to target creature or player. Shuffle Beacon of Destruction into its owner's library.
id=135262 id=135262
name=Beacon of Destruction name=Beacon of Destruction
@@ -271,22 +255,6 @@ subtype=Gnome
toughness=3 toughness=3
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {G} or {W} to your mana pool. Brushland deals 1 damage to you.
id=129496
name=Brushland
rarity=R
color=Land
type=Land
[/card]
[card]
text={T}: Add {1} to your mana pool. {T}: Add {W} or {B} to your mana pool. Caves of Koilos deals 1 damage to you.
id=129497
name=Caves of Koilos
rarity=R
color=Land
type=Land
[/card]
[card]
text=Whenever Cephalid Constable deals combat damage to a player, return up to that many target permanents that player controls to their owners' hands. text=Whenever Cephalid Constable deals combat damage to a player, return up to that many target permanents that player controls to their owners' hands.
id=135261 id=135261
name=Cephalid Constable name=Cephalid Constable
@@ -945,14 +913,6 @@ subtype=Juggernaut
toughness=3 toughness=3
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {R} or {G} to your mana pool. Karplusan Forest deals 1 damage to you.
id=129614
name=Karplusan Forest
rarity=R
color=Land
type=Land
[/card]
[card]
text=Karplusan Strider can't be the target of blue or black spells. text=Karplusan Strider can't be the target of blue or black spells.
id=129911 id=129911
name=Karplusan Strider name=Karplusan Strider
@@ -1041,14 +1001,6 @@ subtype=Elf
toughness=3 toughness=3
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {B} or {G} to your mana pool. Llanowar Wastes deals 1 damage to you.
id=129627
name=Llanowar Wastes
rarity=R
color=Land
type=Land
[/card]
[card]
text=Equipped creature gets +3/+0 and has lifelink and trample. (When it deals damage, you gain that much life. If it would deal enough combat damage to its blockers to destroy them, you may have it deal the rest of its damage to defending player.) Equip {3} ({3}: Attach to target creature you control. Equip only as a sorcery.) text=Equipped creature gets +3/+0 and has lifelink and trample. (When it deals damage, you gain that much life. If it would deal enough combat damage to its blockers to destroy them, you may have it deal the rest of its damage to defending player.) Equip {3} ({3}: Attach to target creature you control. Equip only as a sorcery.)
id=129630 id=129630
name=Loxodon Warhammer name=Loxodon Warhammer
@@ -1645,14 +1597,6 @@ mana={U}
subtype=Aura subtype=Aura
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {U} or {R} to your mana pool. Shivan Reef deals 1 damage to you.
id=129731
name=Shivan Reef
rarity=R
color=Land
type=Land
[/card]
[card]
text=Change the target of target spell with a single target. text=Change the target of target spell with a single target.
id=130362 id=130362
name=Shunt name=Shunt
@@ -1870,14 +1814,7 @@ color=Red
type=Instant type=Instant
mana={3}{R} mana={3}{R}
[/card] [/card]
[card]
text={T}: Add {1} to your mana pool. {T}: Add {B} or {R} to your mana pool. Sulfurous Springs deals 1 damage to you.
id=129751
name=Sulfurous Springs
rarity=R
color=Land
type=Land
[/card]
[card] [card]
text=At the beginning of each player's upkeep, that player returns a creature he or she controls to its owner's hand. text=At the beginning of each player's upkeep, that player returns a creature he or she controls to its owner's hand.
id=129509 id=129509
@@ -2077,14 +2014,6 @@ mana={2}{R}{R}
subtype=Aura subtype=Aura
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {U} or {B} to your mana pool. Underground River deals 1 damage to you.
id=129778
name=Underground River
rarity=R
color=Land
type=Land
[/card]
[card]
text=Whenever an opponent draws a card, Underworld Dreams deals 1 damage to him or her. text=Whenever an opponent draws a card, Underworld Dreams deals 1 damage to him or her.
id=129779 id=129779
name=Underworld Dreams name=Underworld Dreams
@@ -2212,14 +2141,6 @@ type=Artifact
mana={2} mana={2}
[/card] [/card]
[card] [card]
text={T}: Add {1} to your mana pool. {T}: Add {G} or {U} to your mana pool. Yavimaya Coast deals 1 damage to you.
id=129810
name=Yavimaya Coast
rarity=R
color=Land
type=Land
[/card]
[card]
text=Yavimaya Enchantress gets +1/+1 for each enchantment in play. text=Yavimaya Enchantress gets +1/+1 for each enchantment in play.
id=130515 id=130515
name=Yavimaya Enchantress name=Yavimaya Enchantress
+64
View File
@@ -12,6 +12,32 @@ subtype=Imp
toughness=1 toughness=1
[/card] [/card]
[card] [card]
text=Red creatures you control have first strike.
auto=lord(creature[red]|myinplay) first strike includeself
id=142062
name=Bloodmark Mentor
rarity=U
type=Creature
mana={1}{R}
power=1
subtype=Goblin Warrior
toughness=1
[/card]
[card]
text=Trample Other red creatures you control get +1/+1. Other green creatures you control get +1/+1.
abilities=trample
auto=lord(creature[red]|myinplay) 1/1
auto=lord(creature[green]|myinplay) 1/1
id=147428
name=Boartusk Liege
rarity=R
type=Creature
mana={1}{RG}{RG}{RG}
power=3
subtype=Goblin Knight
toughness=4
[/card]
[card]
text=Haste Wither (This deals damage to creatures in the form of -1/-1 counters.) text=Haste Wither (This deals damage to creatures in the form of -1/-1 counters.)
abilities=haste,wither abilities=haste,wither
id=153970 id=153970
@@ -37,6 +63,30 @@ subtype=Elemental Skeleton
toughness=1 toughness=1
[/card] [/card]
[card] [card]
text=Black creatures you control have wither. (They deal damage to creatures in the form of -1/-1 counters.)
auto=lord(creature[black]|myinplay) wither includeself
id=142034
name=Corrosive Mentor
rarity=U
type=Creature
mana={2}{B}
power=1
subtype=Elemental Rogue
toughness=3
[/card]
[card]
text=Blue creatures you control are unblockable.
auto=lord(creature[blue]|myinplay) unblockable includeself
id=141981
name=Deepchannel Mentor
rarity=U
type=Creature
mana={5}{U}
power=2
subtype=Merfolk Rogue
toughness=2
[/card]
[card]
text={T}: Add {1} to your mana pool. {RG}, {T}: Add {R}{R}, {R}{G}, or {G}{G} to your mana pool. text={T}: Add {1} to your mana pool. {RG}, {T}: Add {R}{R}, {R}{G}, or {G}{G} to your mana pool.
auto={T}:Add{1} auto={T}:Add{1}
auto={RG}{T}:Add{R}{R} auto={RG}{T}:Add{R}{R}
@@ -106,6 +156,20 @@ subtype=Treefolk Shaman
toughness=6 toughness=6
[/card] [/card]
[card] [card]
text=Flying Other blue creatures you control get +1/+1. Other black creatures you control get +1/+1.
abilities=flying
auto=lord(creature[blue]|myinplay) 1/1
auto=lord(creature[black]|myinplay) 1/1
id=146743
name=Glen Elendra Liege
rarity=R
type=Creature
mana={1}{UB}{UB}{UB}
power=2
subtype=Faerie Knight
toughness=3
[/card]
[card]
text=Persist (When this creature is put into a graveyard from play, if it had no -1/-1 counters on it, return it to play under its owner's control with a -1/-1 counter on it.) text=Persist (When this creature is put into a graveyard from play, if it had no -1/-1 counters on it, return it to play under its owner's control with a -1/-1 counter on it.)
abilities=persist abilities=persist
id=141935 id=141935
-55
View File
@@ -165,17 +165,6 @@ mana={2}
subtype=Equipment subtype=Equipment
[/card] [/card]
[card] [card]
text=Red creatures you control have first strike.
id=142062
name=Bloodmark Mentor
rarity=U
type=Creature
mana={1}{R}
power=1
subtype=Goblin Warrior
toughness=1
[/card]
[card]
text=Enchant creature Enchanted creature attacks each turn if able. text=Enchant creature Enchanted creature attacks each turn if able.
id=159395 id=159395
name=Bloodshed Fever name=Bloodshed Fever
@@ -193,17 +182,6 @@ type=Enchantment
mana={2}{B} mana={2}{B}
[/card] [/card]
[card] [card]
text=Trample Other red creatures you control get +1/+1. Other green creatures you control get +1/+1.
id=147428
name=Boartusk Liege
rarity=R
type=Creature
mana={1}{RG}{RG}{RG}
power=3
subtype=Goblin Knight
toughness=4
[/card]
[card]
text=Plainswalk {2}{R}, Sacrifice Boggart Arsonists: Destroy target Scarecrow or Plains. text=Plainswalk {2}{R}, Sacrifice Boggart Arsonists: Destroy target Scarecrow or Plains.
id=158684 id=158684
name=Boggart Arsonists name=Boggart Arsonists
@@ -299,17 +277,6 @@ type=Instant
mana={2}{U} mana={2}{U}
[/card] [/card]
[card] [card]
text=Black creatures you control have wither. (They deal damage to creatures in the form of -1/-1 counters.)
id=142034
name=Corrosive Mentor
rarity=U
type=Creature
mana={2}{B}
power=1
subtype=Elemental Rogue
toughness=3
[/card]
[card]
text=Corrupt deals damage equal to the number of Swamps you control to target creature or player. You gain life equal to the damage dealt this way. text=Corrupt deals damage equal to the number of Swamps you control to target creature or player. You gain life equal to the damage dealt this way.
id=146013 id=146013
name=Corrupt name=Corrupt
@@ -406,17 +373,6 @@ type=Sorcery
mana={X}{GW} mana={X}{GW}
[/card] [/card]
[card] [card]
text=Blue creatures you control are unblockable.
id=141981
name=Deepchannel Mentor
rarity=U
type=Creature
mana={5}{U}
power=2
subtype=Merfolk Rogue
toughness=2
[/card]
[card]
text=Deep-Slumber Titan comes into play tapped. Deep-Slumber Titan doesn't untap during your untap step. Whenever Deep-Slumber Titan is dealt damage, untap it. text=Deep-Slumber Titan comes into play tapped. Deep-Slumber Titan doesn't untap during your untap step. Whenever Deep-Slumber Titan is dealt damage, untap it.
id=159396 id=159396
name=Deep-Slumber Titan name=Deep-Slumber Titan
@@ -755,17 +711,6 @@ type=Sorcery
mana={1}{G} mana={1}{G}
[/card] [/card]
[card] [card]
text=Flying Other blue creatures you control get +1/+1. Other black creatures you control get +1/+1.
id=146743
name=Glen Elendra Liege
rarity=R
type=Creature
mana={1}{UB}{UB}{UB}
power=2
subtype=Faerie Knight
toughness=3
[/card]
[card]
text=Destroy target creature. If that creature was green or white, its controller discards a card. text=Destroy target creature. If that creature was green or white, its controller discards a card.
id=158757 id=158757
name=Gloomlance name=Gloomlance
+1
View File
@@ -15,6 +15,7 @@ afflict.txt
anarchy.txt anarchy.txt
animate_dead.txt animate_dead.txt
animate_dead2.txt animate_dead2.txt
ardakar_wastes.txt
ascendant_evincar.txt ascendant_evincar.txt
ascendant_evincar2.txt ascendant_evincar2.txt
brass_man.txt brass_man.txt
@@ -0,0 +1,18 @@
#Testing Ardakar Wastes with multi
[INIT]
FIRSTMAIN
[PLAYER1]
inplay:129458
[PLAYER2]
[DO]
129458
choice 1
129458
[ASSERT]
FIRSTMAIN
[PLAYER1]
inplay:129458
manapool:{W}
life:19
[PLAYER2]
[END]
+1
View File
@@ -30,6 +30,7 @@ class ActionLayer: public GuiLayer, public JGuiListener{
int reactToClick(MTGCardInstance * card); int reactToClick(MTGCardInstance * card);
void setMenuObject(Targetable * object); void setMenuObject(Targetable * object);
void ButtonPressed(int controllerid, int controlid); void ButtonPressed(int controllerid, int controlid);
void doReactTo(int menuIndex);
TargetChooser * getCurrentTargetChooser(); TargetChooser * getCurrentTargetChooser();
}; };
+53 -2
View File
@@ -23,6 +23,51 @@ using std::map;
*/ */
//MultiAbility : triggers several actions for a cost
class MultiAbility:public ActivatedAbility{
public:
vector<MTGAbility *> abilities;
vector<TriggeredEvent *> events;
MultiAbility(int _id, MTGCardInstance * card,ManaCost * _cost, int _tap):ActivatedAbility(_id, card,_cost,0,_tap){
}
int Add(TriggeredEvent * event){
events.push_back(event);
return 1;
}
int Add(MTGAbility * ability){
abilities.push_back(ability);
return 1;
}
int resolve(){
vector<int>::size_type sz = abilities.size();
for (unsigned int i = 0; i < sz; i++){
abilities[i]->resolve();
}
sz = events.size();
for (unsigned int i = 0; i < sz; i++){
events[i]->resolve();
}
return 1;
}
~MultiAbility(){
vector<int>::size_type sz = abilities.size();
for (unsigned int i = 0; i < sz; i++){
delete abilities[i];
}
sz = events.size();
for (unsigned int i = 0; i < sz; i++){
delete events[i];
}
}
};
//Drawer, allows to draw a card for a cost: //Drawer, allows to draw a card for a cost:
class ADrawer:public ActivatedAbility{ class ADrawer:public ActivatedAbility{
@@ -627,7 +672,7 @@ class AManaProducer: public MTGAbility{
if (animation < 0){ if (animation < 0){
animation = 0; animation = 0;
currentlyTapping--; currentlyTapping--;
controller->getManaPool()->add(output); resolve();
if (mParticleSys) mParticleSys->Stop(); if (mParticleSys) mParticleSys->Stop();
} }
} }
@@ -653,6 +698,12 @@ class AManaProducer: public MTGAbility{
return result; return result;
} }
int resolve(){
controller = source->controller();
controller->getManaPool()->add(output);
return 1;
}
int reactToClick(MTGCardInstance * _card){ int reactToClick(MTGCardInstance * _card){
if (!isReactingToClick( _card)) return 0; if (!isReactingToClick( _card)) return 0;
source->tapped = 1; source->tapped = 1;
@@ -664,7 +715,7 @@ class AManaProducer: public MTGAbility{
x0 = cardg->x + 15; x0 = cardg->x + 15;
y0 = cardg->y + 20; y0 = cardg->y + 20;
} }
controller = source->controller();
if (GameOptions::GetInstance()->values[OPTIONS_SFXVOLUME] > 0 && currentlyTapping < 3){ if (GameOptions::GetInstance()->values[OPTIONS_SFXVOLUME] > 0 && currentlyTapping < 3){
JSample * sample = SampleCache::GetInstance()->getSample("sound/sfx/mana.wav"); JSample * sample = SampleCache::GetInstance()->getSample("sound/sfx/mana.wav");
+12
View File
@@ -147,6 +147,8 @@ class TriggerNextPhase:public TriggerAtPhase{
class TriggeredEvent:public MTGAbilityBasicFeatures{ class TriggeredEvent:public MTGAbilityBasicFeatures{
public: public:
TriggeredEvent();
TriggeredEvent(MTGCardInstance * source, Damageable * target = NULL);
virtual int resolve()=0; virtual int resolve()=0;
}; };
@@ -163,6 +165,15 @@ class BuryEvent: public TriggeredEvent{
int resolve(); int resolve();
}; };
class DamageEvent:public TriggeredEvent{
public:
int damage;
DamageEvent(MTGCardInstance * _source, Damageable * _target, int _damage);
int resolve();
};
class DestroyCondition:public MTGAbilityBasicFeatures{ class DestroyCondition:public MTGAbilityBasicFeatures{
public: public:
virtual int testDestroy(); virtual int testDestroy();
@@ -189,6 +200,7 @@ class AbilityFactory{
int putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone, Player * p); int putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone, Player * p);
int parsePowerToughness(string s, int *power, int *toughness); int parsePowerToughness(string s, int *power, int *toughness);
Trigger * parseTrigger(string magicText); Trigger * parseTrigger(string magicText);
Damageable * parseCollateralTarget(MTGCardInstance * card, string s);
public: public:
int magicText(int id, Spell * spell, MTGCardInstance * card = NULL); int magicText(int id, Spell * spell, MTGCardInstance * card = NULL);
void addAbilities(int _id, Spell * spell); void addAbilities(int _id, Spell * spell);
+2
View File
@@ -3,6 +3,8 @@
#if defined (WIN32) || defined (LINUX) #if defined (WIN32) || defined (LINUX)
#define TESTSUITE 1 #define TESTSUITE 1
#else
#define OutputDebugString(val) {}
#endif #endif
#if defined (_DEBUG) && defined (WIN32) #if defined (_DEBUG) && defined (WIN32)
+13 -1
View File
@@ -176,10 +176,22 @@ void ActionLayer::setMenuObject(Targetable * object){
modal = 1; modal = 1;
} }
void ActionLayer::doReactTo(int menuIndex){
if (menuObject){
int controlid = abilitiesMenu->mObjects[menuIndex]->GetId();
char buf[4096];
sprintf(buf, "doReact To %i\n",controlid);
OutputDebugString(buf);
ActionElement * currentAction = (ActionElement *)mObjects[controlid];
currentAction->reactToTargetClick(menuObject);
menuObject = 0;
}
}
void ActionLayer::ButtonPressed(int controllerid, int controlid){ void ActionLayer::ButtonPressed(int controllerid, int controlid){
if (controlid == -1){ if (controlid == -1){
}else{ }else{
ActionElement * currentAction = (ActionElement *)mObjects[controlid]; ActionElement * currentAction = (ActionElement *)mObjects[controlid];
currentAction->reactToTargetClick(menuObject); currentAction->reactToTargetClick(menuObject);
+2 -2
View File
@@ -321,9 +321,9 @@ void GameObserver::cardClick (MTGCardInstance * card, Targetable * object){
} }
}else if (reaction){ }else if (reaction){
if (reaction == 1){ if (reaction == 1){
mLayers->actionLayer()->reactToClick(card); mLayers->actionLayer()->reactToClick(card);
}else{ }else{
mLayers->actionLayer()->setMenuObject(object); mLayers->actionLayer()->setMenuObject(object);
} }
}else if (card->isTapped() && card->controller() == currentPlayer){ }else if (card->isTapped() && card->controller() == currentPlayer){
// int a = ConstraintResolver::untap(this, card); // int a = ConstraintResolver::untap(this, card);
+440 -405
View File
@@ -9,8 +9,6 @@
#include "../include/MTGDeck.h" #include "../include/MTGDeck.h"
int AbilityFactory::countCards(TargetChooser * tc, Player * player, int option){ int AbilityFactory::countCards(TargetChooser * tc, Player * player, int option){
int result = 0; int result = 0;
GameObserver * game = GameObserver::GetInstance(); GameObserver * game = GameObserver::GetInstance();
@@ -60,6 +58,11 @@ int AbilityFactory::putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone
return 1; return 1;
} }
Damageable * AbilityFactory::parseCollateralTarget(MTGCardInstance * card, string s){
size_t found = s.find("controller");
if (found != string::npos) return card->controller();
return NULL;
}
int AbilityFactory::parsePowerToughness(string s, int *power, int *toughness){ int AbilityFactory::parsePowerToughness(string s, int *power, int *toughness){
size_t found = s.find("/"); size_t found = s.find("/");
@@ -118,7 +121,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
//An awful way to get access to the aliasedcard //An awful way to get access to the aliasedcard
magicText = GameObserver::GetInstance()->players[0]->game->collection->getCardById(card->alias)->magicText; magicText = GameObserver::GetInstance()->players[0]->game->collection->getCardById(card->alias)->magicText;
} }
string s; string line;
int size = magicText.size(); int size = magicText.size();
if (size == 0) return 0; if (size == 0) return 0;
unsigned int found; unsigned int found;
@@ -128,442 +131,465 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
while (magicText.size()){ while (magicText.size()){
found = magicText.find("\n"); found = magicText.find("\n");
if (found != string::npos){ if (found != string::npos){
s = magicText.substr(0,found); line = magicText.substr(0,found);
magicText = magicText.substr(found+1); magicText = magicText.substr(found+1);
}else{ }else{
s = magicText; line = magicText;
magicText = ""; magicText = "";
} }
#if defined (WIN32) || defined (LINUX) #if defined (WIN32) || defined (LINUX)
char buf[4096]; char buf[4096];
sprintf(buf, "AUTO ACTION: %s\n", s.c_str()); sprintf(buf, "AUTO ACTION: %s\n", line.c_str());
OutputDebugString(buf); OutputDebugString(buf);
#endif #endif
TargetChooser * tc = NULL;
MultiAbility * multi = NULL;
int delimiter = line.find("}:");
ManaCost * cost = NULL;
if (delimiter!= string::npos){
cost = ManaCost::parseManaCost(line.substr(0,delimiter+1));
}
OutputDebugString("Pqrsing cost\n");
if (cost && !cost->getConvertedCost()){
OutputDebugString("Cost is null\n");
SAFE_DELETE(cost);
}
int doTap = 0; int doTap = 0;
TargetChooser * lordTargets = NULL;
int lordIncludeSelf = 0;
Trigger * trigger = parseTrigger(s);
//Dirty way to remove the trigger text (could get in the way)
if (trigger){
found = s.find(":");
s = s.substr(found+1);
}
//Tap in the cost ? //Tap in the cost ?
if (s.find("{t}") != string::npos) doTap = 1; if (line.find("{t}") != string::npos) doTap = 1;
//Target Abilities while (line.size()){
found = s.find("target("); string s;
if (found != string::npos){ found = line.find("&&");
int end = s.find(")");
string starget = s.substr(found + 7,end - found - 7);
TargetChooserFactory tcf;
tc = tcf.createTargetChooser(starget, card);
}
//Lord
found = s.find("lord(");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
unsigned int end = s.find(")", found+5);
if (end != string::npos){
string lordType = s.substr(found+5,end-found-5).c_str();
TargetChooserFactory tcf;
lordTargets = tcf.createTargetChooser(lordType, card);
}
if (s.find("includeself") != string::npos) lordIncludeSelf = 1;
}
//foreach. Very basic, needs to be improved !
found = s.find("foreach(name:");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
unsigned int end = s.find(")", found+13);
if (end != string::npos){
string type = s.substr(found+13,end-found-13).c_str();
game->addObserver(NEW APlagueRats(id,card,type.c_str()));
result++;
continue;
}
}
//Untapper (Ley Druid...)
found = s.find("untap");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
ManaCost * cost = ManaCost::parseManaCost(s);
if (tc){
game->addObserver(NEW AUntaper(id, card, cost, tc));
}else{
target->tapped = 0;
}
result++;
continue;
}
//Regeneration
found = s.find("}:regenerate");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
ManaCost * cost = ManaCost::parseManaCost(s);
if (lordTargets){
game->addObserver(NEW ALord(id,card,lordTargets,lordIncludeSelf,0,0,-1,cost));
}else{
if (tc){
//TODO
}else{
game->addObserver(NEW AStandardRegenerate(id, card, target, cost));
//TODO death ward !
}
}
result++;
continue;
}
//Token creator. Name, type, p/t, abilities
found = s.find("token(");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
int end = s.find(",", found);
string sname = s.substr(found + 6,end - found - 6);
int previous = end+1;
end = s.find(",",previous);
string stypes = s.substr(previous,end - previous);
previous = end+1;
end = s.find(",",previous);
string spt = s.substr(previous,end - previous);
int power, toughness;
parsePowerToughness(spt,&power, &toughness);
string sabilities = s.substr(end+1);
ManaCost * cost = ManaCost::parseManaCost(s);
int multiplier = 1;
found = s.find("*");
if (found != string::npos)multiplier = atoi(s.substr(found+1).c_str());
if(cost->getConvertedCost() || doTap){
game->addObserver(NEW ATokenCreator(id,card,cost,sname,stypes,power,toughness,sabilities,doTap));
}else{
delete cost;
cost = NULL;
ATokenCreator * tok = NEW ATokenCreator(id,card,cost,sname,stypes,power,toughness,sabilities,doTap);
for (int i=0; i < multiplier; i++){
tok->resolve();
}
delete tok;
}
result++;
continue;
}
//MoveTo Move a card from a zone to another
found = s.find("moveto(");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_BAD; //TODO : depends on where from, where to...
int end = s.find(")");
string szone = s.substr(found + 7,end - found - 7);
if (tc){
ManaCost * cost = ManaCost::parseManaCost(s);
if (cost->getConvertedCost() == 0){
delete cost;
cost = NULL;
}
game->addObserver(NEW AZoneMover(id,card,tc,szone,cost));
}else{
MTGGameZone * fromZone = target->getCurrentZone();
MTGGameZone * destZone = MTGGameZone::stringToZone(szone, target);
target->controller()->game->putInZone(target,fromZone,destZone);
}
result++;
continue;
}
//Bury
found = s.find("bury");
if (found != string::npos){
if (trigger){
if (dryMode) return BAKA_EFFECT_BAD;
BuryEvent * action = NEW BuryEvent();
game->addObserver(NEW GenericTriggeredAbility(id, card,trigger,action));
}else{
found = s.find("all(");
if (found != string::npos){
int end = s.find(")");
string starget = s.substr(found + 4,end - found - 4);
TargetChooserFactory tcf;
TargetChooser * targetAll = tcf.createTargetChooser(starget, card);
if (dryMode){
int myNbCards = countCards(targetAll,card->controller());
int opponentNbCards = countCards(targetAll, card->controller()->opponent());
int myCardsPower = countCards(targetAll,card->controller(),COUNT_POWER);
int opponentCardsPower = countCards(targetAll, card->controller()->opponent(),COUNT_POWER);
delete targetAll;
if (myNbCards < opponentNbCards || myCardsPower < opponentCardsPower) return BAKA_EFFECT_GOOD;
return BAKA_EFFECT_BAD;
}else{
this->destroyAllInPlay(targetAll,1);
delete targetAll;
}
}else{
if (dryMode) return BAKA_EFFECT_BAD;
if (tc){
game->addObserver(NEW ABurier(id, card,tc));
}else{
target->controller()->game->putInGraveyard(target);
}
}
}
result++;
continue;
}
//Destroy
found = s.find("destroy");
if (found != string::npos){
found = s.find("all(");
if (found != string::npos){ if (found != string::npos){
int end = s.find(")"); s = line.substr(0,found);
string starget = s.substr(found + 4,end - found - 4); line = line.substr(found+2);
TargetChooserFactory tcf; if (!multi){
TargetChooser * targetAll = tcf.createTargetChooser(starget, card); OutputDebugString("Multi initializing\n");
if (dryMode){ multi = NEW MultiAbility(id, card, cost,doTap);
int myNbCards = countCards(targetAll,card->controller()); game->addObserver(multi);
int opponentNbCards = countCards(targetAll, card->controller()->opponent()); OutputDebugString("Multi initialized\n");
int myCardsPower = countCards(targetAll,card->controller(),COUNT_POWER); }
int opponentCardsPower = countCards(targetAll, card->controller()->opponent(),COUNT_POWER);
delete targetAll;
if (myNbCards < opponentNbCards || myCardsPower < opponentCardsPower) return BAKA_EFFECT_GOOD;
return BAKA_EFFECT_BAD;
}else{
this->destroyAllInPlay(targetAll);
delete targetAll;
}
}else{ }else{
if (dryMode) return BAKA_EFFECT_BAD; s = line;
if (tc){ line = "";
game->addObserver(NEW ADestroyer(id, card,tc));
}else{
game->mLayers->stackLayer()->addPutInGraveyard(target);
}
} }
result++;
continue;
}
//Damage TargetChooser * tc = NULL;
found = s.find("damage");
if (found != string::npos){
unsigned int start = s.find(":",found);
if (start == string::npos) start = s.find(" ",found);
unsigned int end = s.find(" ",start);
int damage;
ManaCost * cost = ManaCost::parseManaCost(s);
if (end != string::npos){
damage = atoi(s.substr(start+1,end-start-1).c_str());
}else{
damage = atoi(s.substr(start+1).c_str());
}
if (dryMode) return BAKA_EFFECT_BAD;
if (tc){
game->addObserver(NEW ADamager(id, card, cost, damage, tc,doTap));
}else{
delete cost;
game->mLayers->stackLayer()->addDamage(card,spell->getNextDamageableTarget(), damage);
}
result++;
continue;
}
//gain/lose life TargetChooser * lordTargets = NULL;
found = s.find("life"); int lordIncludeSelf = 0;
if (found != string::npos){
unsigned int start = s.find(":",found);
unsigned int end = s.find(" ",start);
int life;
ManaCost * cost = ManaCost::parseManaCost(s);
if (end != string::npos){
life = atoi(s.substr(start+1,end-start-1).c_str());
}else{
life = atoi(s.substr(start+1).c_str());
}
if (dryMode) return BAKA_EFFECT_GOOD;
if (tc){
//TODO ?
}else{
if (cost->getConvertedCost() == 0 && !doTap){
delete cost;
card->controller()->life+=life;
}else{
//TODO;
}
}
result++;
continue;
}
//Draw Trigger * trigger = parseTrigger(s);
found = s.find("draw:"); //Dirty way to remove the trigger text (could get in the way)
if (found != string::npos){
unsigned int start = s.find(":",found);
unsigned int end = s.find(" ",start);
int nbcards;
ManaCost * cost = ManaCost::parseManaCost(s);
if (end != string::npos){
nbcards = atoi(s.substr(start+1,end-start-1).c_str());
}else{
nbcards = atoi(s.substr(start+1).c_str());
}
if (dryMode) return BAKA_EFFECT_GOOD;
if (trigger){ if (trigger){
DrawEvent * action = NEW DrawEvent(card->controller(),nbcards); found = s.find(":");
game->addObserver(NEW GenericTriggeredAbility(id, card,trigger,action)); s = s.substr(found+1);
}else{
if (tc){
//TODO ?
}else{
if (cost->getConvertedCost() == 0){
delete cost;
game->mLayers->stackLayer()->addDraw(card->controller(),nbcards);
}else{
game->addObserver(NEW ADrawer(id,card,cost,nbcards,doTap));
}
}
} }
result++;
continue;
}
//Change Power/Toughness
int power, toughness;
if ( parsePowerToughness(s,&power, &toughness)){
if (dryMode){
if (power >=0 && toughness >= 0 ) return BAKA_EFFECT_GOOD;
return BAKA_EFFECT_BAD;
}
int limit = 0;
unsigned int limit_str = s.find("limit:");
if (limit_str != string::npos){
limit = atoi(s.substr(limit_str+6).c_str());
}
ManaCost * cost = ManaCost::parseManaCost(s);
if (lordTargets){ //Target Abilities
game->addObserver(NEW ALord(id,card,lordTargets,lordIncludeSelf,power,toughness)); found = s.find("target(");
}else{ if (found != string::npos){
if(tc){ int end = s.find(")");
game->addObserver(NEW ATargetterPowerToughnessModifierUntilEOT(id, card,power,toughness, cost, tc)); string starget = s.substr(found + 7,end - found - 7);
}else{ TargetChooserFactory tcf;
if (cost->getConvertedCost() == 0){ tc = tcf.createTargetChooser(starget, card);
delete cost;
if(card->hasType("enchantment")){ }
game->addObserver(NEW APowerToughnessModifier(id, card, target,power,toughness));
}else{ //Lord
game->addObserver(NEW AInstantPowerToughnessModifierUntilEOT(id, card, target,power,toughness)); found = s.find("lord(");
} if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
unsigned int end = s.find(")", found+5);
if (end != string::npos){
string lordType = s.substr(found+5,end-found-5).c_str();
TargetChooserFactory tcf;
lordTargets = tcf.createTargetChooser(lordType, card);
}
if (s.find("includeself") != string::npos) lordIncludeSelf = 1;
}
//foreach. Very basic, needs to be improved !
found = s.find("foreach(name:");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
unsigned int end = s.find(")", found+13);
if (end != string::npos){
string type = s.substr(found+13,end-found-13).c_str();
game->addObserver(NEW APlagueRats(id,card,type.c_str()));
result++;
continue;
}
}
//Untapper (Ley Druid...)
found = s.find("untap");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
if (tc){
game->addObserver(NEW AUntaper(id, card, cost, tc));
}else{
target->tapped = 0;
}
result++;
continue;
}
//Regeneration
found = s.find("}:regenerate");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
if (lordTargets){
game->addObserver(NEW ALord(id,card,lordTargets,lordIncludeSelf,0,0,-1,cost));
}else{
if (tc){
//TODO
}else{ }else{
game->addObserver(NEW APowerToughnessModifierUntilEndOfTurn(id, card, target,power,toughness, cost, limit)); game->addObserver(NEW AStandardRegenerate(id, card, target, cost));
//TODO death ward !
} }
} }
} result++;
result++; continue;
continue;
}
//Mana Producer
found = s.find("add");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
ManaCost * cost = ManaCost::parseManaCost(s.substr(0,found));
ManaCost * output = ManaCost::parseManaCost(s.substr(found));
if (cost->getConvertedCost()){
game->addObserver(NEW AManaProducer(id, target, output, cost));
}else{
delete cost;
if (doTap){
game->addObserver(NEW AManaProducer(id, target, output));
}else{
card->controller()->getManaPool()->add(output);
delete output;
}
}
result++;
continue;
}
//Gain/loose Ability
for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){
found = s.find(Constants::MTGBasicAbilities[j]);
if (found!= string::npos){
int modifier = 1;
if (found > 0 && s[found-1] == '-') modifier = 0;
if (dryMode){
if (j == Constants::DEFENDER){
if (modifier == 1) return BAKA_EFFECT_BAD;
return BAKA_EFFECT_GOOD;
}else{
if (modifier == 1) return BAKA_EFFECT_GOOD;
return BAKA_EFFECT_BAD;
}
}
ManaCost * cost = ManaCost::parseManaCost(s);
if (lordTargets){
game->addObserver(NEW ALord(id,card,lordTargets,lordIncludeSelf,0,0,j));
}else{
if (tc){
game->addObserver(NEW ABasicAbilityModifierUntilEOT(id, card, j, cost,tc, modifier));
}else{
if (cost->getConvertedCost() == 0){
delete cost;
if(card->hasType("enchantment")){
game->addObserver(NEW ABasicAbilityModifier(id, card,target, j,modifier));
}else{
game->addObserver(NEW AInstantBasicAbilityModifierUntilEOT(id, card,target, j,modifier));
}
}else{
game->addObserver(NEW ABasicAbilityAuraModifierUntilEOT(id, card,target, cost,j,modifier));
}
}
}
result++;
continue;
} }
//Tapper (icy manipulator) //Token creator. Name, type, p/t, abilities
found = s.find("tap"); found = s.find("token(");
if (found != string::npos){ if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD; if (dryMode) return BAKA_EFFECT_GOOD;
ManaCost * cost = ManaCost::parseManaCost(s); int end = s.find(",", found);
if (tc){ string sname = s.substr(found + 6,end - found - 6);
game->addObserver(NEW ATapper(id, card, cost, tc)); int previous = end+1;
}else{ end = s.find(",",previous);
target->tapped = 1; string stypes = s.substr(previous,end - previous);
previous = end+1;
end = s.find(",",previous);
string spt = s.substr(previous,end - previous);
int power, toughness;
parsePowerToughness(spt,&power, &toughness);
string sabilities = s.substr(end+1);
int multiplier = 1;
found = s.find("*");
if (found != string::npos)multiplier = atoi(s.substr(found+1).c_str());
if(cost || doTap){
game->addObserver(NEW ATokenCreator(id,card,cost,sname,stypes,power,toughness,sabilities,doTap));
}else{
ATokenCreator * tok = NEW ATokenCreator(id,card,cost,sname,stypes,power,toughness,sabilities,doTap);
for (int i=0; i < multiplier; i++){
tok->resolve();
}
delete tok;
}
result++;
continue;
} }
result++; //MoveTo Move a card from a zone to another
continue; found = s.find("moveto(");
} if (found != string::npos){
if (dryMode) return BAKA_EFFECT_BAD; //TODO : depends on where from, where to...
int end = s.find(")");
string szone = s.substr(found + 7,end - found - 7);
if (tc){
if (cost){
game->addObserver(NEW AZoneMover(id,card,tc,szone,cost));
}
}else{
MTGGameZone * fromZone = target->getCurrentZone();
MTGGameZone * destZone = MTGGameZone::stringToZone(szone, target);
target->controller()->game->putInZone(target,fromZone,destZone);
}
result++;
continue;
}
//Bury
found = s.find("bury");
if (found != string::npos){
if (trigger){
if (dryMode) return BAKA_EFFECT_BAD;
BuryEvent * action = NEW BuryEvent();
game->addObserver(NEW GenericTriggeredAbility(id, card,trigger,action));
}else{
found = s.find("all(");
if (found != string::npos){
int end = s.find(")");
string starget = s.substr(found + 4,end - found - 4);
TargetChooserFactory tcf;
TargetChooser * targetAll = tcf.createTargetChooser(starget, card);
if (dryMode){
int myNbCards = countCards(targetAll,card->controller());
int opponentNbCards = countCards(targetAll, card->controller()->opponent());
int myCardsPower = countCards(targetAll,card->controller(),COUNT_POWER);
int opponentCardsPower = countCards(targetAll, card->controller()->opponent(),COUNT_POWER);
delete targetAll;
if (myNbCards < opponentNbCards || myCardsPower < opponentCardsPower) return BAKA_EFFECT_GOOD;
return BAKA_EFFECT_BAD;
}else{
this->destroyAllInPlay(targetAll,1);
delete targetAll;
}
}else{
if (dryMode) return BAKA_EFFECT_BAD;
if (tc){
game->addObserver(NEW ABurier(id, card,tc));
}else{
target->controller()->game->putInGraveyard(target);
}
}
}
result++;
continue;
}
//Destroy
found = s.find("destroy");
if (found != string::npos){
found = s.find("all(");
if (found != string::npos){
int end = s.find(")");
string starget = s.substr(found + 4,end - found - 4);
TargetChooserFactory tcf;
TargetChooser * targetAll = tcf.createTargetChooser(starget, card);
if (dryMode){
int myNbCards = countCards(targetAll,card->controller());
int opponentNbCards = countCards(targetAll, card->controller()->opponent());
int myCardsPower = countCards(targetAll,card->controller(),COUNT_POWER);
int opponentCardsPower = countCards(targetAll, card->controller()->opponent(),COUNT_POWER);
delete targetAll;
if (myNbCards < opponentNbCards || myCardsPower < opponentCardsPower) return BAKA_EFFECT_GOOD;
return BAKA_EFFECT_BAD;
}else{
this->destroyAllInPlay(targetAll);
delete targetAll;
}
}else{
if (dryMode) return BAKA_EFFECT_BAD;
if (tc){
game->addObserver(NEW ADestroyer(id, card,tc));
}else{
game->mLayers->stackLayer()->addPutInGraveyard(target);
}
}
result++;
continue;
}
//Damage
found = s.find("damage");
if (found != string::npos){
unsigned int start = s.find(":",found);
if (start == string::npos) start = s.find(" ",found);
unsigned int end = s.find(" ",start);
int damage;
if (end != string::npos){
damage = atoi(s.substr(start+1,end-start-1).c_str());
}else{
damage = atoi(s.substr(start+1).c_str());
}
if (dryMode) return BAKA_EFFECT_BAD;
if (tc){
MTGAbility * a = NEW ADamager(id, card, cost, damage, tc,doTap);
if (multi){
multi->Add(a);
}else{
game->addObserver(a);
}
}else{
if (multi){
Damageable * target = parseCollateralTarget(card, s);
if (!target) target = spell->getNextDamageableTarget();
if (!target)OutputDebugString("NO TARGET FOR DAMAGE\n");
multi->Add(NEW DamageEvent(card,target,damage));
}else{
game->mLayers->stackLayer()->addDamage(card,spell->getNextDamageableTarget(), damage);
}
}
result++;
continue;
}
//gain/lose life
found = s.find("life");
if (found != string::npos){
unsigned int start = s.find(":",found);
unsigned int end = s.find(" ",start);
int life;
if (end != string::npos){
life = atoi(s.substr(start+1,end-start-1).c_str());
}else{
life = atoi(s.substr(start+1).c_str());
}
if (dryMode) return BAKA_EFFECT_GOOD;
if (tc){
//TODO ?
}else{
if (!cost && !doTap){
card->controller()->life+=life;
}else{
//TODO;
}
}
result++;
continue;
}
//Draw
found = s.find("draw:");
if (found != string::npos){
unsigned int start = s.find(":",found);
unsigned int end = s.find(" ",start);
int nbcards;
if (end != string::npos){
nbcards = atoi(s.substr(start+1,end-start-1).c_str());
}else{
nbcards = atoi(s.substr(start+1).c_str());
}
if (dryMode) return BAKA_EFFECT_GOOD;
if (trigger){
DrawEvent * action = NEW DrawEvent(card->controller(),nbcards);
game->addObserver(NEW GenericTriggeredAbility(id, card,trigger,action));
}else{
if (tc){
//TODO ?
}else{
if (!cost){
game->mLayers->stackLayer()->addDraw(card->controller(),nbcards);
}else{
game->addObserver(NEW ADrawer(id,card,cost,nbcards,doTap));
}
}
}
result++;
continue;
}
//Change Power/Toughness
int power, toughness;
if ( parsePowerToughness(s,&power, &toughness)){
if (dryMode){
if (power >=0 && toughness >= 0 ) return BAKA_EFFECT_GOOD;
return BAKA_EFFECT_BAD;
}
int limit = 0;
unsigned int limit_str = s.find("limit:");
if (limit_str != string::npos){
limit = atoi(s.substr(limit_str+6).c_str());
}
if (lordTargets){
game->addObserver(NEW ALord(id,card,lordTargets,lordIncludeSelf,power,toughness));
}else{
if(tc){
game->addObserver(NEW ATargetterPowerToughnessModifierUntilEOT(id, card,power,toughness, cost, tc));
}else{
if (!cost){
if(card->hasType("enchantment")){
game->addObserver(NEW APowerToughnessModifier(id, card, target,power,toughness));
}else{
game->addObserver(NEW AInstantPowerToughnessModifierUntilEOT(id, card, target,power,toughness));
}
}else{
game->addObserver(NEW APowerToughnessModifierUntilEndOfTurn(id, card, target,power,toughness, cost, limit));
}
}
}
result++;
continue;
}
//Mana Producer
found = s.find("add");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
ManaCost * input = ManaCost::parseManaCost(s.substr(0,found));
ManaCost * output = ManaCost::parseManaCost(s.substr(found));
if (input->getConvertedCost() || doTap){
SAFE_DELETE(cost); //erk
if (!input->getConvertedCost()){
SAFE_DELETE(input);
}
MTGAbility * a = NEW AManaProducer(id, target, output, input);
if (multi){
multi->Add(a);
}else{
game->addObserver(a);
}
}else{
OutputDebugString ("uh oh\n");
card->controller()->getManaPool()->add(output);
delete output;
}
result++;
continue;
}
//Gain/loose Ability
for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){
found = s.find(Constants::MTGBasicAbilities[j]);
if (found!= string::npos){
int modifier = 1;
if (found > 0 && s[found-1] == '-') modifier = 0;
if (dryMode){
if (j == Constants::DEFENDER){
if (modifier == 1) return BAKA_EFFECT_BAD;
return BAKA_EFFECT_GOOD;
}else{
if (modifier == 1) return BAKA_EFFECT_GOOD;
return BAKA_EFFECT_BAD;
}
}
if (lordTargets){
game->addObserver(NEW ALord(id,card,lordTargets,lordIncludeSelf,0,0,j));
}else{
if (tc){
game->addObserver(NEW ABasicAbilityModifierUntilEOT(id, card, j, cost,tc, modifier));
}else{
if (!cost){
if(card->hasType("enchantment")){
game->addObserver(NEW ABasicAbilityModifier(id, card,target, j,modifier));
}else{
game->addObserver(NEW AInstantBasicAbilityModifierUntilEOT(id, card,target, j,modifier));
}
}else{
game->addObserver(NEW ABasicAbilityAuraModifierUntilEOT(id, card,target, cost,j,modifier));
}
}
}
result++;
continue;
}
}
//Tapper (icy manipulator)
found = s.find("tap");
if (found != string::npos){
if (dryMode) return BAKA_EFFECT_GOOD;
if (tc){
game->addObserver(NEW ATapper(id, card, cost, tc));
}else{
target->tapped = 1;
}
result++;
continue;
}
#if defined (WIN32) || defined (LINUX)
char buf[4096];
sprintf(buf, "AUTO ACTION PARSED: %s\n", line.c_str());
OutputDebugString(buf);
#endif
} }
} }
return result; return result;
} }
void AbilityFactory::addAbilities(int _id, Spell * spell){ void AbilityFactory::addAbilities(int _id, Spell * spell){
@@ -1853,8 +1879,17 @@ int TriggerNextPhase::testDestroy(){
return 0; return 0;
} }
TriggeredEvent::TriggeredEvent():MTGAbilityBasicFeatures(){}
TriggeredEvent::TriggeredEvent(MTGCardInstance * _source, Damageable * _target):MTGAbilityBasicFeatures(_source, _target){}
DamageEvent::DamageEvent(MTGCardInstance * _source, Damageable * _target, int _damage):TriggeredEvent(_source,_target),damage(_damage){
}
int DamageEvent::resolve(){
game->mLayers->stackLayer()->addDamage(source,target, damage);
return damage;
}
DrawEvent::DrawEvent(Player * _player, int _nbcards):TriggeredEvent(),player(_player),nbcards(_nbcards){ DrawEvent::DrawEvent(Player * _player, int _nbcards):TriggeredEvent(),player(_player),nbcards(_nbcards){
} }
+1
View File
@@ -206,6 +206,7 @@ Player * MTGCardInstance::controller(){
if (game->players[i]->game->inPlay->hasCard(this)) return game->players[i]; if (game->players[i]->game->inPlay->hasCard(this)) return game->players[i];
if (game->players[i]->game->stack->hasCard(this)) return game->players[i]; if (game->players[i]->game->stack->hasCard(this)) return game->players[i];
if (game->players[i]->game->graveyard->hasCard(this)) return game->players[i]; if (game->players[i]->game->graveyard->hasCard(this)) return game->players[i];
if (game->players[i]->game->hand->hasCard(this)) return game->players[i];
} }
return NULL; return NULL;
} }
+5 -1
View File
@@ -83,6 +83,10 @@ int TestSuiteAI::Act(float dt){
if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this){ if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this){
g->mLayers->stackLayer()->cancelInterruptOffer(); g->mLayers->stackLayer()->cancelInterruptOffer();
} }
}else if(action.find("choice ")!=string::npos){
OutputDebugString("choice !!!\n");
int choice = atoi(action.substr(action.find("choice ") + 7).c_str());
g->mLayers->actionLayer()->doReactTo(choice);
}else{ }else{
int mtgid = atoi(action.c_str()); int mtgid = atoi(action.c_str());
if (mtgid){ if (mtgid){
@@ -92,7 +96,7 @@ int TestSuiteAI::Act(float dt){
}else{ }else{
MTGCardInstance * card = suite->getCardByMTGId(mtgid); MTGCardInstance * card = suite->getCardByMTGId(mtgid);
if (card) { if (card) {
g->cardClick(card); g->cardClick(card,card);
} }
} }
}else{ }else{