diff --git a/projects/mtg/include/ActionStack.h b/projects/mtg/include/ActionStack.h index 7da2e3ebb..15688cfa5 100644 --- a/projects/mtg/include/ActionStack.h +++ b/projects/mtg/include/ActionStack.h @@ -2,150 +2,150 @@ * Wagic, The Homebrew ?! is licensed under the BSD license * See LICENSE in the Folder's root * http://wololo.net/wagic/ -*/ - -#ifndef _SPELLSTACK_H_ -#define _SPELLSTACK_H_ - -#define MAX_SPELL_TARGETS 10 - - -#define ACTION_SPELL 10 -#define ACTION_DAMAGE 11 -#define ACTION_DAMAGES 12 -#define ACTION_NEXTGAMEPHASE 13 -#define ACTION_DRAW 14 -#define ACTION_PUTINGRAVEYARD 15 -#define ACTION_ABILITY 16 - -#define NOT_RESOLVED -2 -#define RESOLVED_OK 1 -#define RESOLVED_NOK -1 - -#include "../include/PlayGuiObject.h" -#include "GuiLayers.h" -#include "../include/TargetsList.h" -#include "../include/Targetable.h" - -class GuiLayer; -class PlayGuiObject; -class MTGCardInstance; -class GameObserver; -class Player; -class Damageable; -class MTGAbility; -class Targetable; -class DamageStack; -class ManaCost; - - -#define ACTIONSTACK_STANDARD 0 -#define ACTIONSTACK_TARGET 1 - -class Interruptible: public PlayGuiObject, public Targetable{ -public: - int state, display; - MTGCardInstance * source; - virtual void Entering(){mHasFocus = true;}; - virtual bool Leaving(u32 key){mHasFocus = false;return true;}; - virtual bool ButtonPressed(){return true;}; - virtual int resolve(){return 0;}; - virtual void Render(){}; - int typeAsTarget(){return TARGET_STACKACTION;}; - Interruptible(int id,bool hasFocus = false):PlayGuiObject(id,40,x,y,hasFocus){state=NOT_RESOLVED;display=0;source=NULL;}; -}; - -class NextGamePhase: public Interruptible { -public: - int resolve(); - void Render(); - NextGamePhase(int id); -}; - -class Spell: public Interruptible, public TargetsList { -protected: - -public: - ManaCost * cost; - Spell(MTGCardInstance* _source); - Spell(int id, MTGCardInstance* _source, Targetable * _targets[], int _nbtargets, ManaCost * _cost); - ~Spell(); - int resolve(); - void Render(); -}; - -class StackAbility: public Interruptible { -public: - MTGAbility * ability; - int resolve(); - void Render(); - StackAbility(int id, MTGAbility * _ability); -}; - -class PutInGraveyard: public Interruptible { -public: - MTGCardInstance * card; - int removeFromGame; - int resolve(); - void Render(); - PutInGraveyard(int id, MTGCardInstance * _card); -}; - - -class DrawAction: public Interruptible { -public: - int nbcards; - Player * player; - int resolve(); - void Render(); - DrawAction(int id, Player * _player, int _nbcards); -}; - -class ActionStack :public GuiLayer{ -protected: - int interruptDecision[2]; - int timer; - int currentState; - int mode; - int checked; - - - void unpackDamageStacks(); - void unpackDamageStack(DamageStack * ds); - void repackDamageStacks(); -public: - int setIsInterrupting(Player * player); - int count( int type = 0 , int state = 0 , int display = -1); - Interruptible * getPrevious(Interruptible * next, int type = 0, int state = 0 , int display = -1); - int getPreviousIndex(Interruptible * next, int type = 0, int state = 0 , int display = -1); - Interruptible * getNext(Interruptible * previous, int type = 0, int state = 0 , int display = -1); - int getNextIndex(Interruptible * previous, int type = 0, int state = 0 , int display = -1); - void Fizzle(Interruptible * action); - Interruptible * _(int id); - void cancelInterruptOffer(int cancelMode = 1); - void endOfInterruption(); - Interruptible * getLatest(int state); - Player * askIfWishesToInterrupt; - int garbageCollect(); - int addAction(Interruptible * interruptible); - int addSpell(MTGCardInstance* card, Targetable * targets[], int nbtargets, ManaCost * mana); - int AddNextGamePhase(); - int addPutInGraveyard(MTGCardInstance * card); - int addDraw(Player * player, int nbcards = 1); - int addDamage(MTGCardInstance * _source, Damageable * target, int _damage); - int addAbility(MTGAbility * ability); - void Update(float dt); - void CheckUserInput(float dt); - virtual void Render(); - ActionStack(int id, GameObserver* _game); - int resolve(); - int CombatDamages(); - int CombatDamages(int firststrike); - int has(Interruptible * action); -}; - - - - - -#endif +*/ + +#ifndef _SPELLSTACK_H_ +#define _SPELLSTACK_H_ + +#define MAX_SPELL_TARGETS 10 + + +#define ACTION_SPELL 10 +#define ACTION_DAMAGE 11 +#define ACTION_DAMAGES 12 +#define ACTION_NEXTGAMEPHASE 13 +#define ACTION_DRAW 14 +#define ACTION_PUTINGRAVEYARD 15 +#define ACTION_ABILITY 16 + +#define NOT_RESOLVED -2 +#define RESOLVED_OK 1 +#define RESOLVED_NOK -1 + +#include "../include/PlayGuiObject.h" +#include "GuiLayers.h" +#include "../include/TargetsList.h" +#include "../include/Targetable.h" + +class GuiLayer; +class PlayGuiObject; +class MTGCardInstance; +class GameObserver; +class Player; +class Damageable; +class MTGAbility; +class Targetable; +class DamageStack; +class ManaCost; + + +#define ACTIONSTACK_STANDARD 0 +#define ACTIONSTACK_TARGET 1 + +class Interruptible: public PlayGuiObject, public Targetable{ +public: + int state, display; + MTGCardInstance * source; + virtual void Entering(){mHasFocus = true;}; + virtual bool Leaving(u32 key){mHasFocus = false;return true;}; + virtual bool ButtonPressed(){return true;}; + virtual int resolve(){return 0;}; + virtual void Render(){}; + int typeAsTarget(){return TARGET_STACKACTION;}; + Interruptible(int id,bool hasFocus = false):PlayGuiObject(id,40,x,y,hasFocus){state=NOT_RESOLVED;display=0;source=NULL;}; +}; + +class NextGamePhase: public Interruptible { +public: + int resolve(); + void Render(); + NextGamePhase(int id); +}; + +class Spell: public Interruptible, public TargetsList { +protected: + +public: + ManaCost * cost; + Spell(MTGCardInstance* _source); + Spell(int id, MTGCardInstance* _source, Targetable * _targets[], int _nbtargets, ManaCost * _cost); + ~Spell(); + int resolve(); + void Render(); +}; + +class StackAbility: public Interruptible { +public: + MTGAbility * ability; + int resolve(); + void Render(); + StackAbility(int id, MTGAbility * _ability); +}; + +class PutInGraveyard: public Interruptible { +public: + MTGCardInstance * card; + int removeFromGame; + int resolve(); + void Render(); + PutInGraveyard(int id, MTGCardInstance * _card); +}; + + +class DrawAction: public Interruptible { +public: + int nbcards; + Player * player; + int resolve(); + void Render(); + DrawAction(int id, Player * _player, int _nbcards); +}; + +class ActionStack :public GuiLayer{ +protected: + int interruptDecision[2]; + int timer; + int currentState; + int mode; + int checked; + + + void unpackDamageStacks(); + void unpackDamageStack(DamageStack * ds); + void repackDamageStacks(); +public: + int setIsInterrupting(Player * player); + int count( int type = 0 , int state = 0 , int display = -1); + Interruptible * getPrevious(Interruptible * next, int type = 0, int state = 0 , int display = -1); + int getPreviousIndex(Interruptible * next, int type = 0, int state = 0 , int display = -1); + Interruptible * getNext(Interruptible * previous, int type = 0, int state = 0 , int display = -1); + int getNextIndex(Interruptible * previous, int type = 0, int state = 0 , int display = -1); + void Fizzle(Interruptible * action); + Interruptible * _(int id); + void cancelInterruptOffer(int cancelMode = 1); + void endOfInterruption(); + Interruptible * getLatest(int state); + Player * askIfWishesToInterrupt; + int garbageCollect(); + int addAction(Interruptible * interruptible); + int addSpell(MTGCardInstance* card, Targetable * targets[], int nbtargets, ManaCost * mana); + int AddNextGamePhase(); + int addPutInGraveyard(MTGCardInstance * card); + int addDraw(Player * player, int nbcards = 1); + int addDamage(MTGCardInstance * _source, Damageable * target, int _damage); + int addAbility(MTGAbility * ability); + void Update(float dt); + void CheckUserInput(float dt); + virtual void Render(); + ActionStack(int id, GameObserver* _game); + int resolve(); + int CombatDamages(); + int CombatDamages(int firststrike); + int has(Interruptible * action); +}; + + + + + +#endif diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index d5a49bea0..8d724414c 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -2715,7 +2715,6 @@ public: }; // GiveLifeForTappedType - class AGiveLifeForTappedType:public MTGAbility{ public: char type[20]; @@ -2746,6 +2745,67 @@ public: } }; +// People of the Woods +class APeopleOfTheWoods:public ListMaintainerAbility{ +public: + APeopleOfTheWoods(int _id, MTGCardInstance * _source):ListMaintainerAbility(_id, _source){ + } + + int canBeInList(MTGCardInstance * card){ + if (source->controller()->game->inPlay->hasCard(card) && card->hasType("forest") ) return 1; + return 0; + } + + int added(MTGCardInstance * card){ + source->addToToughness(1); + return 1; + } + + int removed(MTGCardInstance * card){ + source->addToToughness(-1); + return 1; + } + +}; + +//Abomination Kill blocking creature if white or green +class AAbomination :public MTGAbility{ +public: + MTGCardInstance * opponents[20]; + int nbOpponents; + AAbomination (int _id, MTGCardInstance * _source):MTGAbility(_id, _source){ + nbOpponents = 0; + } + + void Update(float dt){ + if (newPhase != currentPhase){ + if( newPhase == MTG_PHASE_COMBATDAMAGE){ + nbOpponents = 0; + MTGCardInstance * opponent = source->getNextOpponent(); + while (opponent && opponent->hasColor(MTG_COLOR_GREEN) || opponent->hasColor(MTG_COLOR_WHITE)){ + opponents[nbOpponents] = opponent; + nbOpponents ++; + opponent = source->getNextOpponent(opponent); + } + }else if (newPhase == MTG_PHASE_COMBATEND){ + for (int i = 0; i < nbOpponents ; i++){ + game->mLayers->stackLayer()->addPutInGraveyard(opponents[i]); + } + } + } + } + + int testDestroy(){ + if(!game->isInPlay(source) && currentPhase != MTG_PHASE_UNTAP){ + return 0; + }else{ + return MTGAbility::testDestroy(); + } + } +}; + + + //Minion of Leshrac class AMinionofLeshrac: public TargetAbility{ public: @@ -2808,5 +2868,114 @@ public: }; +//CreaturePowerToughnessModifierForAllTypeControlled +class ACreaturePowerToughnessModifierForAllTypeControlled:public ListMaintainerAbility{ +public: + char type[20]; + ACreaturePowerToughnessModifierForAllTypeControlled(int _id, MTGCardInstance * _source, const char * _type):ListMaintainerAbility(_id, _source){ + } + int canBeInList(MTGCardInstance * card){ + if (source->controller()->game->inPlay->hasCard(card) && card->hasType(type) ) return 1; + return 0; + } + + int added(MTGCardInstance * card){ + source->power += 1; + source->addToToughness(1); + return 1; + } + + int removed(MTGCardInstance * card){ + source->power -= 1; + source->addToToughness(-1); + return 1; + } + +}; + +//GenericKirdApe +class AGenericKirdApe:public MTGAbility{ +public: + int init; + char type [20]; + int power; + int toughness; + AGenericKirdApe(int _id, MTGCardInstance * _source, const char * _type, int _power, int _toughness):MTGAbility(_id, _source){ + init = 0; + } + + void Update(float dt){ + if (source->controller()->game->inPlay->hasType(type)){ + if(!init){ + init = 1; + source->power+=power; + source->addToToughness(toughness); + } + }else{ + if (init){ + init = 0; + source->power-=power; + source->addToToughness(-toughness); + } + } + } +}; + + +//Rampage ability Tentative 2 +class ARampageAbility:public MTGAbility{ +public: + int nbOpponents; + int PowerModifier; + int ToughnessModifier; + int modifier; + ARampageAbility(int _id, MTGCardInstance * _source,int _PowerModifier, int _ToughnessModifier):MTGAbility(_id, _source){ + modifier=0; + } + void Update(float dt){ + if (source->isAttacker()){ + MTGInPlay * inPlay = game->opponent()->game->inPlay; + for (int i = 0; i < inPlay->nb_cards; i ++){ + MTGCardInstance * current = inPlay->cards[i]; + if (current->isDefenser()){ + modifier++; + } + } + source->power+= (PowerModifier * modifier); + source->addToToughness(ToughnessModifier * modifier); + } + } +}; + + +//Rampage ability Tentative 1 - Did not work as expected +class A1RampageAbility:public MTGAbility{ +public: + MTGCardInstance * opponents[20]; + int nbOpponents; + int PowerModifier; + int ToughnessModifier; + A1RampageAbility(int _id, MTGCardInstance * _source,int _PowerModifier, int _ToughnessModifier):MTGAbility(_id, _source){ + nbOpponents = 0; + } + + void Update(float dt){ + if (source->isAttacker()){ + if (newPhase != currentPhase){ + if( newPhase == MTG_PHASE_COMBATDAMAGE){ + nbOpponents = 0; + MTGCardInstance * opponent = source->getNextOpponent(); + while (opponent){ + opponents[nbOpponents] = opponent; + nbOpponents ++; + source->power+= PowerModifier; + source->addToToughness(ToughnessModifier); + opponent = source->getNextOpponent(opponent); + } + } + } + } + } +}; #endif diff --git a/projects/mtg/include/MTGDefinitions.h b/projects/mtg/include/MTGDefinitions.h index 977635e0f..551b26e41 100644 --- a/projects/mtg/include/MTGDefinitions.h +++ b/projects/mtg/include/MTGDefinitions.h @@ -93,8 +93,10 @@ static int _b[7] = {20, 0, 140,15, 50,255,128}; #define MOUNTAINHOME 33 #define SWAMPHOME 34 #define PLAINSHOME 35 +#define FLANKING 36 +#define RAMPAGE1 37 -#define NB_BASIC_ABILITIES 36 +#define NB_BASIC_ABILITIES 38 static const char * MTGBasicAbilities[] = { "trample", @@ -132,7 +134,9 @@ static const char * MTGBasicAbilities[] = { "islandhome", "moutainhome", "swamphome", -"plainshome" +"plainshome", +"flanking", +"rampage", }; diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index a039789c2..5c72ab516 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -154,6 +154,17 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ result++; continue; } + //Tentative Destroyall not working char is not compatible with string variable + //found = s.find("destroyall("); + //if (found != string::npos){ + // if (dryMode) return BAKA_EFFECT_GOOD; + // unsigned int end = s.find(")", found+11); + // if (end != string::npos){ + // string type = s.substr(found+11,end-found-11).c_str(); + // destroyAllFromTypeInPlay(type.c_str(), card); + // result++; + // continue; + //} //Regeneration found = s.find("}:regenerate"); @@ -200,6 +211,10 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ continue; } + //Summon + + //Reveal Take Target and put in in hand (should be also able to target hand since some card needs you to reveal a card in your hand + //Damage found = s.find("damage"); if (found != string::npos){ @@ -959,8 +974,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){ { MTGPlayerCards * zones = card->target->controller()->game; zones->putInZone(card->target,zones->inPlay,zones->hand); - break; - + break; } case 1235: //Aspect of Wolf { @@ -1256,6 +1270,77 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){ break; } + +// Addons ALA + + case 175114: // Master of Etherium + { + game->addObserver(NEW ACreaturePowerToughnessModifierForAllTypeControlled(_id,card,"artifact")); + break; + } + + case 174989: // Wild Nacatl + { + game->addObserver(NEW AGenericKirdApe(_id,card,"plains",1,1)); + game->addObserver(NEW AGenericKirdApe(_id,card,"moutain",1,1)); + break; + } + +//Addons The Dark + + case 1797: //Inferno does 6 damage to all players and all creatures. + { + for (int i = 0; i < 2 ; i++){ + game->mLayers->stackLayer()->addDamage(card, game->players[i], 6); + for (int j = 0; j < game->players[i]->game->inPlay->nb_cards; j++){ + MTGCardInstance * current = game->players[i]->game->inPlay->cards[j]; + if (current->isACreature()){ + game->mLayers->stackLayer()->addDamage(card, current, 6); + } + } + } + break; + } + + case 1773 : //People of the Woods + { + game->addObserver(NEW APeopleOfTheWoods(_id, card)); + break; + } + + case 1818: //Tivadar's Crusade + { + destroyAllFromTypeInPlay("goblin", card); + break; + } + +//Addons Legends + case 1470: //Acid Rain + { + destroyAllFromTypeInPlay("forest", card); + break; + } + case 1427: //Abomination + { + game->addObserver(NEW AAbomination(_id,card)); + break; + } + case 1533: //Livingplane + { + game->addObserver(NEW AConvertLandToCreatures(id, card, "land")); + break; + } + case 1607: //Divine Offering + { + card->target->controller()->game->putInGraveyard(card->target); + game->currentlyActing()->life+= card->target->getManaCost()->getConvertedCost(); + break; + } + case 1625: //Lifeblood + { + game->addObserver(NEW AGiveLifeForTappedType (_id, card, "island")); + break; + } //Addons ICE-AGE Cards case 2631: //Jokulhaups { @@ -1385,6 +1470,12 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){ if (card->basicAbilities[PLAINSHOME]){ game->addObserver(NEW AStrongLandLinkCreature(_id, card,"plains")); } + // New Abilities Flanking and Rampage + + if (card->basicAbilities [RAMPAGE1]){ + game->addObserver (NEW ARampageAbility(_id, card, 1, 1)); + } + //Instants are put in the graveyard automatically if that's not already done if (!putSourceInGraveyard){ if (card->hasType("instant") || card->hasType("sorcery")){ diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 1b713fa2c..1a2b66cb7 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -233,23 +233,22 @@ int MTGCardInstance::setToughness(int value){ int MTGCardInstance::canBlock(){ if (!tapped && isACreature())return 1; - if (!basicAbilities[SHADOW]&& isACreature()) return 1; // Try to add shadow return 0; } - int MTGCardInstance::canBlock(MTGCardInstance * opponent){ if (!canBlock()) return 0; if (!opponent) return 1; if (!opponent->isAttacker()) return 0; - // Comprehensive rule 502.7f : If a creature with protection attacks, it can't be blocked by creatures that have the stated quality. if (opponent->protectedAgainst(this)) return 0; - if (opponent->basicAbilities[UNBLOCKABLE]) return 0; if (opponent->basicAbilities[FEAR] && !(hasColor(MTG_COLOR_ARTIFACT) || hasColor(MTG_COLOR_BLACK))) return 0; if (opponent->basicAbilities[FLYING] && !( basicAbilities[FLYING] || basicAbilities[REACH])) return 0; + // If opponent has shadow and a creature does not have either shadow or reachshadow it cannot be blocked if (opponent->basicAbilities[SHADOW] && !( basicAbilities[SHADOW] || basicAbilities[REACHSHADOW])) return 0; + // If opponent does not have shadow and a creature has shadow it cannot be blocked + if (!opponent->basicAbilities[SHADOW] && basicAbilities[SHADOW]) return 0; if (opponent->basicAbilities[SWAMPWALK] && controller()->game->inPlay->hasType("swamp")) return 0; if (opponent->basicAbilities[FORESTWALK] && controller()->game->inPlay->hasType("forest")) return 0; if (opponent->basicAbilities[ISLANDWALK] && controller()->game->inPlay->hasType("island")) return 0; @@ -258,7 +257,6 @@ int MTGCardInstance::canBlock(MTGCardInstance * opponent){ return 1; } - MTGCardInstance * MTGCardInstance::getNextPartner(){ MTGInPlay * inplay = controller()->game->inPlay; MTGCardInstance * bandingPartner = inplay->getNextAttacker(banding);