Erwan - fizzle spells that have invalid targets
This commit is contained in:
@@ -83,6 +83,7 @@ elvish_piper.txt
|
|||||||
elvish_promenade.txt
|
elvish_promenade.txt
|
||||||
fastbond.txt
|
fastbond.txt
|
||||||
fault_line.txt
|
fault_line.txt
|
||||||
|
fists_of_ironwood.txt
|
||||||
flare.txt
|
flare.txt
|
||||||
fledgling_imp.txt
|
fledgling_imp.txt
|
||||||
fledgling_imp2.txt
|
fledgling_imp2.txt
|
||||||
|
|||||||
26
projects/mtg/bin/Res/test/fists_of_ironwood.txt
Normal file
26
projects/mtg/bin/Res/test/fists_of_ironwood.txt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#Bug: fists of ironwood and swords to plowshares
|
||||||
|
[INIT]
|
||||||
|
FIRSTMAIN
|
||||||
|
[PLAYER1]
|
||||||
|
hand:fists of ironwood
|
||||||
|
inplay:grizzly bears
|
||||||
|
manapool:{1}{G}
|
||||||
|
[PLAYER2]
|
||||||
|
hand:swords to plowshares
|
||||||
|
manapool:{W}
|
||||||
|
[DO]
|
||||||
|
fists of ironwood
|
||||||
|
grizzly bears
|
||||||
|
no
|
||||||
|
yes
|
||||||
|
swords to plowshares
|
||||||
|
grizzly bears
|
||||||
|
endinterrupt
|
||||||
|
[ASSERT]
|
||||||
|
FIRSTMAIN
|
||||||
|
[PLAYER1]
|
||||||
|
graveyard:fists of ironwood
|
||||||
|
life:22
|
||||||
|
[PLAYER2]
|
||||||
|
graveyard:swords to plowshares
|
||||||
|
[END]
|
||||||
@@ -37,6 +37,7 @@ class MTGAbility;
|
|||||||
class Targetable;
|
class Targetable;
|
||||||
class DamageStack;
|
class DamageStack;
|
||||||
class ManaCost;
|
class ManaCost;
|
||||||
|
class TargetChooser;
|
||||||
|
|
||||||
|
|
||||||
#define ACTIONSTACK_STANDARD 0
|
#define ACTIONSTACK_STANDARD 0
|
||||||
@@ -67,18 +68,27 @@ class NextGamePhase: public Interruptible {
|
|||||||
NextGamePhase(int id);
|
NextGamePhase(int id);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Spell: public Interruptible, public TargetsList {
|
class Spell: public Interruptible {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
TargetChooser * tc;
|
||||||
ManaCost * cost;
|
ManaCost * cost;
|
||||||
Spell(MTGCardInstance* _source);
|
Spell(MTGCardInstance* _source);
|
||||||
Spell(int id, MTGCardInstance* _source, Targetable * _targets[], int _nbtargets, ManaCost * _cost);
|
Spell(int id, MTGCardInstance* _source, TargetChooser *_tc, ManaCost * _cost);
|
||||||
~Spell();
|
~Spell();
|
||||||
int resolve();
|
int resolve();
|
||||||
void Render();
|
void Render();
|
||||||
const char *getDisplayName();
|
const char *getDisplayName();
|
||||||
virtual ostream& toString(ostream& out) const;
|
virtual ostream& toString(ostream& out) const;
|
||||||
|
MTGCardInstance * getNextCardTarget(MTGCardInstance * previous = 0);
|
||||||
|
Player * getNextPlayerTarget(Player * previous = 0);
|
||||||
|
Damageable * getNextDamageableTarget(Damageable * previous = 0);
|
||||||
|
Interruptible * getNextInterruptible(Interruptible * previous, int type);
|
||||||
|
Spell * getNextSpellTarget(Spell * previous = 0);
|
||||||
|
Damage * getNextDamageTarget(Damage * previous = 0);
|
||||||
|
Targetable * getNextTarget(Targetable * previous = 0, int type = -1);
|
||||||
|
int getNbTargets();
|
||||||
};
|
};
|
||||||
|
|
||||||
class StackAbility: public Interruptible {
|
class StackAbility: public Interruptible {
|
||||||
@@ -146,7 +156,7 @@ class ActionStack :public GuiLayer{
|
|||||||
Player * askIfWishesToInterrupt;
|
Player * askIfWishesToInterrupt;
|
||||||
int garbageCollect();
|
int garbageCollect();
|
||||||
int addAction(Interruptible * interruptible);
|
int addAction(Interruptible * interruptible);
|
||||||
Spell * addSpell(MTGCardInstance* card, Targetable * targets[], int nbtargets, ManaCost * mana);
|
Spell * addSpell(MTGCardInstance* card, TargetChooser * tc, ManaCost * mana);
|
||||||
int AddNextGamePhase();
|
int AddNextGamePhase();
|
||||||
int addPutInGraveyard(MTGCardInstance * card);
|
int addPutInGraveyard(MTGCardInstance * card);
|
||||||
int addDraw(Player * player, int nbcards = 1);
|
int addDraw(Player * player, int nbcards = 1);
|
||||||
|
|||||||
@@ -3369,7 +3369,7 @@ class AEarthbind:public ABasicAbilityModifier{
|
|||||||
class AFireball:public InstantAbility{
|
class AFireball:public InstantAbility{
|
||||||
public:
|
public:
|
||||||
AFireball(int _id, MTGCardInstance * card, Spell * spell, int x):InstantAbility(_id, card){
|
AFireball(int _id, MTGCardInstance * card, Spell * spell, int x):InstantAbility(_id, card){
|
||||||
int nbtargets = spell->cursor;
|
int nbtargets = spell->getNbTargets();
|
||||||
int totaldamage = x+1-nbtargets;
|
int totaldamage = x+1-nbtargets;
|
||||||
int individualdamage = 0;
|
int individualdamage = 0;
|
||||||
if (nbtargets) individualdamage = totaldamage / nbtargets;
|
if (nbtargets) individualdamage = totaldamage / nbtargets;
|
||||||
|
|||||||
@@ -79,9 +79,6 @@ class GameObserver{
|
|||||||
void draw();
|
void draw();
|
||||||
int isInPlay(MTGCardInstance * card);
|
int isInPlay(MTGCardInstance * card);
|
||||||
int isACreature(MTGCardInstance * card);
|
int isACreature(MTGCardInstance * card);
|
||||||
int tryToTapOrUntap(MTGCardInstance * card);
|
|
||||||
|
|
||||||
int checkManaCost(MTGCardInstance * card);
|
|
||||||
|
|
||||||
void Update(float dt);
|
void Update(float dt);
|
||||||
void Render();
|
void Render();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "../include/Damage.h"
|
#include "../include/Damage.h"
|
||||||
#include "../include/ManaCost.h"
|
#include "../include/ManaCost.h"
|
||||||
#include "../include/GameOptions.h"
|
#include "../include/GameOptions.h"
|
||||||
|
#include "../include/TargetChooser.h"
|
||||||
// WALDORF - added to support drawing big cards during interrupts
|
// WALDORF - added to support drawing big cards during interrupts
|
||||||
#include "../include/CardGui.h"
|
#include "../include/CardGui.h"
|
||||||
#include "../include/Translate.h"
|
#include "../include/Translate.h"
|
||||||
@@ -98,15 +99,16 @@ ostream& StackAbility::toString(ostream& out) const
|
|||||||
|
|
||||||
/* Spell Cast */
|
/* Spell Cast */
|
||||||
|
|
||||||
Spell::Spell(MTGCardInstance * _source): Interruptible(0), TargetsList(){
|
Spell::Spell(MTGCardInstance * _source): Interruptible(0){
|
||||||
source = _source;
|
source = _source;
|
||||||
mHeight= 40;
|
mHeight= 40;
|
||||||
type = ACTION_SPELL;
|
type = ACTION_SPELL;
|
||||||
cost = NEW ManaCost();
|
cost = NEW ManaCost();
|
||||||
|
tc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Spell::Spell(int id, MTGCardInstance * _source, Targetable * _targets[], int nb_targets, ManaCost * _cost): Interruptible(id), TargetsList(_targets, nb_targets),cost(_cost){
|
Spell::Spell(int id, MTGCardInstance * _source, TargetChooser * tc, ManaCost * _cost): Interruptible(id), tc(tc),cost(_cost){
|
||||||
source = _source;
|
source = _source;
|
||||||
mHeight = 40;
|
mHeight = 40;
|
||||||
type = ACTION_SPELL;
|
type = ACTION_SPELL;
|
||||||
@@ -119,6 +121,7 @@ const char * Spell::getDisplayName(){
|
|||||||
|
|
||||||
Spell::~Spell(){
|
Spell::~Spell(){
|
||||||
SAFE_DELETE(cost);
|
SAFE_DELETE(cost);
|
||||||
|
SAFE_DELETE(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Spell::resolve(){
|
int Spell::resolve(){
|
||||||
@@ -145,6 +148,40 @@ int Spell::resolve(){
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MTGCardInstance * Spell::getNextCardTarget(MTGCardInstance * previous){
|
||||||
|
if (!tc) return NULL;
|
||||||
|
return tc->getNextCardTarget(previous);
|
||||||
|
}
|
||||||
|
Player * Spell::getNextPlayerTarget(Player * previous){
|
||||||
|
if (!tc) return NULL;
|
||||||
|
return tc->getNextPlayerTarget(previous);
|
||||||
|
}
|
||||||
|
Damageable * Spell::getNextDamageableTarget(Damageable * previous){
|
||||||
|
if (!tc) return NULL;
|
||||||
|
return tc->getNextDamageableTarget(previous);
|
||||||
|
}
|
||||||
|
Interruptible * Spell::getNextInterruptible(Interruptible * previous, int type){
|
||||||
|
if (!tc) return NULL;
|
||||||
|
return tc->getNextInterruptible(previous,type);
|
||||||
|
}
|
||||||
|
Spell * Spell::getNextSpellTarget(Spell * previous){
|
||||||
|
if (!tc) return NULL;
|
||||||
|
return tc->getNextSpellTarget(previous);
|
||||||
|
}
|
||||||
|
Damage * Spell::getNextDamageTarget(Damage * previous){
|
||||||
|
if (!tc) return NULL;
|
||||||
|
return tc->getNextDamageTarget(previous);
|
||||||
|
}
|
||||||
|
Targetable * Spell::getNextTarget(Targetable * previous, int type ){
|
||||||
|
if (!tc) return NULL;
|
||||||
|
return tc->getNextTarget(previous,type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Spell::getNbTargets(){
|
||||||
|
if (!tc) return 0;
|
||||||
|
return tc->cursor;
|
||||||
|
}
|
||||||
|
|
||||||
void Spell::Render(){
|
void Spell::Render(){
|
||||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT);
|
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT);
|
||||||
mFont->SetBase(0);
|
mFont->SetBase(0);
|
||||||
@@ -343,13 +380,13 @@ int ActionStack::addAction(Interruptible * action){
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spell * ActionStack::addSpell(MTGCardInstance * _source, Targetable * _targets[], int _nbtargets, ManaCost * mana){
|
Spell * ActionStack::addSpell(MTGCardInstance * _source, TargetChooser * tc, ManaCost * mana){
|
||||||
#if defined (WIN32) || defined (LINUX)
|
#if defined (WIN32) || defined (LINUX)
|
||||||
char buf[4096], *p = buf;
|
char buf[4096], *p = buf;
|
||||||
sprintf(buf, "Add spell\n");
|
sprintf(buf, "Add spell\n");
|
||||||
OutputDebugString(buf);
|
OutputDebugString(buf);
|
||||||
#endif
|
#endif
|
||||||
Spell * spell = NEW Spell(mCount,_source,_targets,_nbtargets, mana);
|
Spell * spell = NEW Spell(mCount,_source,tc, mana);
|
||||||
addAction(spell);
|
addAction(spell);
|
||||||
if (!game->players[0]->isAI() &&
|
if (!game->players[0]->isAI() &&
|
||||||
_source->controller()==game->players[0] &&
|
_source->controller()==game->players[0] &&
|
||||||
|
|||||||
@@ -478,29 +478,6 @@ Player * GameObserver::currentlyActing(){
|
|||||||
return currentActionPlayer;
|
return currentActionPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GameObserver::tryToTapOrUntap(MTGCardInstance * card){
|
|
||||||
|
|
||||||
int reaction = mLayers->actionLayer()->isReactingToClick(card);
|
|
||||||
if (reaction){
|
|
||||||
if (reaction == 1){
|
|
||||||
mLayers->actionLayer()->reactToClick(card);
|
|
||||||
}else{
|
|
||||||
//TODO, what happens when several abilities react to the click ?
|
|
||||||
}
|
|
||||||
return reaction;
|
|
||||||
}else{
|
|
||||||
if (card->isTapped() && card->controller() == currentPlayer){
|
|
||||||
int a = ConstraintResolver::untap(this, card);
|
|
||||||
return a;
|
|
||||||
}else{
|
|
||||||
//TODO Check Spells
|
|
||||||
//card->tap();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO CORRECT THIS MESS
|
//TODO CORRECT THIS MESS
|
||||||
int GameObserver::targetListIsSet(MTGCardInstance * card){
|
int GameObserver::targetListIsSet(MTGCardInstance * card){
|
||||||
if (targetChooser == NULL){
|
if (targetChooser == NULL){
|
||||||
@@ -514,12 +491,3 @@ int GameObserver::targetListIsSet(MTGCardInstance * card){
|
|||||||
return (targetChooser->targetListSet());
|
return (targetChooser->targetListSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int GameObserver::checkManaCost(MTGCardInstance * card){
|
|
||||||
ManaCost * playerMana = currentlyActing()->getManaPool();
|
|
||||||
ManaCost * cost = card->getManaCost();
|
|
||||||
if (playerMana->canAfford(cost)){
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -838,7 +838,14 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
|
|||||||
MTGCardInstance * card = spell->source;
|
MTGCardInstance * card = spell->source;
|
||||||
|
|
||||||
|
|
||||||
if (spell->cursor==1) card->target = spell->getNextCardTarget();
|
if (spell->getNbTargets()==1){
|
||||||
|
card->target = spell->getNextCardTarget();
|
||||||
|
if (card->target && !spell->tc->canTarget(card->target)){
|
||||||
|
MTGPlayerCards * zones = card->controller()->game;
|
||||||
|
zones->putInGraveyard(card);
|
||||||
|
return; //fizzle
|
||||||
|
}
|
||||||
|
}
|
||||||
_id = magicText(_id, spell);
|
_id = magicText(_id, spell);
|
||||||
|
|
||||||
GameObserver * game = GameObserver::GetInstance();
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
@@ -1242,7 +1249,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
|
|||||||
}
|
}
|
||||||
case 1192: //BrainGeyser
|
case 1192: //BrainGeyser
|
||||||
{
|
{
|
||||||
Player * player = ((Player * )spell->targets[0]);
|
Player * player = spell->getNextPlayerTarget();
|
||||||
int x = spell->cost->getConvertedCost() - 2;
|
int x = spell->cost->getConvertedCost() - 2;
|
||||||
for (int i = 0; i < x ; i++){
|
for (int i = 0; i < x ; i++){
|
||||||
player->game->drawFromLibrary();
|
player->game->drawFromLibrary();
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){
|
|||||||
}else{
|
}else{
|
||||||
Spell * spell = NULL;
|
Spell * spell = NULL;
|
||||||
if (game->targetChooser){
|
if (game->targetChooser){
|
||||||
spell = game->mLayers->stackLayer()->addSpell(card,game->targetChooser->targets,game->targetChooser->cursor, spellCost);
|
spell = game->mLayers->stackLayer()->addSpell(card,game->targetChooser, spellCost);
|
||||||
SAFE_DELETE(game->targetChooser);
|
game->targetChooser = NULL;
|
||||||
}else{
|
}else{
|
||||||
spell = game->mLayers->stackLayer()->addSpell(card,NULL,0, spellCost);
|
spell = game->mLayers->stackLayer()->addSpell(card,NULL, spellCost);
|
||||||
}
|
}
|
||||||
MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack);
|
MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack);
|
||||||
spell->source = copy;
|
spell->source = copy;
|
||||||
|
|||||||
Reference in New Issue
Block a user