From f87c703866d784cda44d0b5883f831a730460caf Mon Sep 17 00:00:00 2001 From: "wagic.the.homebrew" Date: Mon, 16 Feb 2009 13:46:14 +0000 Subject: [PATCH] Erwan - Added WEvent class, allows to send events to abilities - Cards that change zones now becomes new objects (as specified in the Comprehensive rules). This should allow to fix lots of stupid bugs in the near future, but probably brings loads of new issues :( --- projects/mtg/Makefile | 2 +- projects/mtg/include/ActionElement.h | 3 + projects/mtg/include/ActionLayer.h | 5 +- projects/mtg/include/AllAbilities.h | 67 +++++++++++---------- projects/mtg/include/Counters.h | 1 + projects/mtg/include/MTGAbility.h | 6 +- projects/mtg/include/MTGCardInstance.h | 4 ++ projects/mtg/include/MTGGameZones.h | 9 +-- projects/mtg/include/MTGGuiPlay.h | 1 + projects/mtg/include/MTGRules.h | 83 ++++++++++++++++++++------ projects/mtg/include/WEvent.h | 24 ++++++++ projects/mtg/src/ActionLayer.cpp | 18 ++++++ projects/mtg/src/ActionStack.cpp | 5 +- projects/mtg/src/Counters.cpp | 10 ++++ projects/mtg/src/MTGAbility.cpp | 16 +++-- projects/mtg/src/MTGCardInstance.cpp | 32 +++++++--- projects/mtg/src/MTGGameZones.cpp | 58 +++++++++++------- projects/mtg/src/MTGGuiPlay.cpp | 34 +++++++---- projects/mtg/src/MTGRules.cpp | 13 ++-- projects/mtg/src/TestSuiteAI.cpp | 7 +-- projects/mtg/src/WEvent.cpp | 13 ++++ projects/mtg/template.vcproj | 8 +++ 22 files changed, 307 insertions(+), 112 deletions(-) create mode 100644 projects/mtg/include/WEvent.h create mode 100644 projects/mtg/src/WEvent.cpp diff --git a/projects/mtg/Makefile b/projects/mtg/Makefile index 2aaf10bf6..5f60bff1c 100644 --- a/projects/mtg/Makefile +++ b/projects/mtg/Makefile @@ -1,4 +1,4 @@ -OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIPlayer.o objs/AIStats.o objs/Blocker.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/ConstraintResolver.o objs/Counters.o objs/Damage.o objs/DamagerDamaged.o objs/DamageResolverLayer.o objs/DeckDataWrapper.o objs/DeckStats.o objs/DuelLayers.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GuiCardsController.o objs/GuiLayers.o objs/Logger.o objs/ManaCost.o objs/ManaCostHybrid.o objs/MenuItem.o objs/MTGAbility.o objs/MTGCardInstance.o objs/MTGCard.o objs/MTGDeck.o objs/MTGDefinitions.o objs/MTGGamePhase.o objs/MTGGameZones.o objs/MTGGuiHand.o objs/MTGGuiPlay.o objs/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/PriceList.o objs/ShopItem.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TexturesCache.o objs/Token.o objs/utils.o +OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIPlayer.o objs/AIStats.o objs/Blocker.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/ConstraintResolver.o objs/Counters.o objs/Damage.o objs/DamagerDamaged.o objs/DamageResolverLayer.o objs/DeckDataWrapper.o objs/DeckStats.o objs/DuelLayers.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GuiCardsController.o objs/GuiLayers.o objs/Logger.o objs/ManaCost.o objs/ManaCostHybrid.o objs/MenuItem.o objs/MTGAbility.o objs/MTGCardInstance.o objs/MTGCard.o objs/MTGDeck.o objs/MTGDefinitions.o objs/MTGGamePhase.o objs/MTGGameZones.o objs/MTGGuiHand.o objs/MTGGuiPlay.o objs/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/PriceList.o objs/ShopItem.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TexturesCache.o objs/Token.o objs/utils.o objs/WEvent.o DEPS = $(patsubst objs/%.o, deps/%.d, $(OBJS)) RESULT = $(shell psp-config --psp-prefix 2> Makefile.cache) diff --git a/projects/mtg/include/ActionElement.h b/projects/mtg/include/ActionElement.h index 8241a2491..cc458eac9 100644 --- a/projects/mtg/include/ActionElement.h +++ b/projects/mtg/include/ActionElement.h @@ -16,6 +16,7 @@ class MTGCardInstance; class Targetable; class TargetChooser; +class WEvent; class ActionElement: public JGuiObject{ protected: @@ -39,6 +40,8 @@ class ActionElement: public JGuiObject{ virtual int isReactingToTargetClick(Targetable * card); virtual int reactToTargetClick(Targetable * card); virtual int isReactingToClick(MTGCardInstance * card){return 0;}; + virtual int stillInUse(MTGCardInstance * card){return 0;}; + virtual int receiveEvent(WEvent * event){return 0;}; virtual int reactToClick(MTGCardInstance * card){return 0;}; virtual const char * getMenuText(){return "Ability";}; }; diff --git a/projects/mtg/include/ActionLayer.h b/projects/mtg/include/ActionLayer.h index 70fd097fe..869897adc 100644 --- a/projects/mtg/include/ActionLayer.h +++ b/projects/mtg/include/ActionLayer.h @@ -13,6 +13,7 @@ class GuiLayer; class Targetable; +class WEvent; class ActionLayer: public GuiLayer, public JGuiListener{ public: @@ -22,12 +23,14 @@ class ActionLayer: public GuiLayer, public JGuiListener{ virtual void Update(float dt); int unstopableRenderInProgress(); bool CheckUserInput(u32 key); - ActionLayer(int id, GameObserver* _game):GuiLayer(id, _game){ menuObject = NULL; abilitiesMenu = NULL;}; + ActionLayer(int id, GameObserver* _game):GuiLayer(id, _game){ menuObject = NULL; abilitiesMenu = NULL;}; int isWaitingForAnswer(); int isReactingToTargetClick(Targetable * card); + int receiveEvent(WEvent * event); int reactToTargetClick(Targetable * card); int isReactingToClick(MTGCardInstance * card); int reactToClick(MTGCardInstance * card); + int stillInUse(MTGCardInstance * card); void setMenuObject(Targetable * object); void ButtonPressed(int controllerid, int controlid); void doReactTo(int menuIndex); diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 54bd296fc..991e5b553 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -10,6 +10,7 @@ #include "CardGui.h" #include "GameOptions.h" #include "Token.h" +#include "WEvent.h" #include #include @@ -169,10 +170,11 @@ public: } for ( it=abilities.begin() ; it != abilities.end(); it++ ){ myToken->basicAbilities[*it] = 1; - } + } + source->controller()->game->stack->addCard(myToken); Spell * spell = NEW Spell(myToken); - source->controller()->game->stack->addCard(myToken); + spell->resolve(); delete spell; return 1; @@ -201,8 +203,9 @@ public: //inplay is a special zone ! for (int i=0; i < 2; i++){ if (destZone == game->players[i]->game->inPlay){ - Spell * spell = NEW Spell(_target); - game->players[i]->game->putInZone(_target, fromZone, game->players[i]->game->stack); + MTGCardInstance * copy = game->players[i]->game->putInZone(_target, fromZone, game->players[i]->game->stack); + Spell * spell = NEW Spell(copy); + spell->resolve(); delete spell; return 1; @@ -1201,9 +1204,9 @@ class AAladdinsLamp: public TargetAbility{ int fireAbility(){ source->tapped = 1; MTGLibrary * library = game->currentlyActing()->game->library; - library->removeCard(tc->getNextCardTarget()); + MTGCardInstance * card = library->removeCard(tc->getNextCardTarget()); library->shuffleTopToBottom(nbcards - 1 ); - library->addCard(tc->getNextCardTarget()); + library->addCard(card); init = 0; return 1; } @@ -1442,41 +1445,39 @@ class AConservator: public MTGAbility{ //Creature bond -class ACreatureBond:public TriggeredAbility{ +class ACreatureBond:public MTGAbility{ public: - int mTriggered; int resolved; - ACreatureBond(int _id, MTGCardInstance * _source, MTGCardInstance * _target):TriggeredAbility(_id,_source,_target){ - mTriggered = 0; + ACreatureBond(int _id, MTGCardInstance * _source, MTGCardInstance * _target):MTGAbility(_id,_source,_target){ resolved = 0; } - int trigger(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - for (int i = 0; i < 2; i++){ - if (!mTriggered && game->players[i]->game->graveyard->hasCard(_target)){ - mTriggered = 1; - return 1; + int receiveEvent(WEvent * event){ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (event->type == WEvent::CHANGE_ZONE){ + WEventZoneChange * e = (WEventZoneChange *) event; + MTGCardInstance * card = e->card->previous; + if (card == _target){ + for (int i = 0; i < 2 ; i++){ + Player * p = game->players[i]; + if (e->to == p->game->graveyard){ + game->mLayers->stackLayer()->addDamage(source,_target->controller(),_target->toughness); + return 1; + } + } } - } + } return 0; - } + } - int resolve(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - game->mLayers->stackLayer()->addDamage(source,_target->controller(),_target->toughness); - resolved = 1; - return 1; - } - - int testDestroy(){ + /* int testDestroy(){ MTGCardInstance * _target = (MTGCardInstance *)target; if(_target->controller()->game->graveyard->hasCard(_target) && !resolved){ return 0; }else{ return TriggeredAbility::testDestroy(); } - } + }*/ }; //1105: Dingus Egg @@ -1733,10 +1734,12 @@ class AAnimateDead:public MTGAbility{ card->life = card->toughness; //Put the card in play again, with all its abilities ! //AbilityFactory af; - Spell * spell = NEW Spell(card); + MTGCardInstance * copy = source->controller()->game->putInZone(card, _target->controller()->game->graveyard, source->controller()->game->stack); + Spell * spell = NEW Spell(copy); //af.addAbilities(game->mLayers->actionLayer()->getMaxId(), spell); - source->controller()->game->putInZone(card, _target->controller()->game->graveyard, source->controller()->game->stack); + spell->resolve(); + target = spell->source; delete spell; } @@ -1893,14 +1896,14 @@ class AKudzu: public TargetAbility{ void Update(float dt){ MTGCardInstance * _target = (MTGCardInstance *)target; - if (!_target->tapped){ + if (_target && !_target->tapped){ previouslyTapped = 0; }else if (!previouslyTapped){ #if defined (WIN32) || defined (LINUX) OutputDebugString("Kudzu Strikes !\n"); #endif MTGCardInstance * _target = (MTGCardInstance *)target; - _target->controller()->game->putInGraveyard(_target); + target = _target->controller()->game->putInGraveyard(_target); reactToClick(source); // ???? } TargetAbility::Update(dt); @@ -1922,7 +1925,7 @@ class AKudzu: public TargetAbility{ target = tc->getNextCardTarget(); source->target = (MTGCardInstance *) target; previouslyTapped = 0; - if (source->target->tapped) previouslyTapped = 1; + if (source->target && source->target->tapped) previouslyTapped = 1; return 1; } diff --git a/projects/mtg/include/Counters.h b/projects/mtg/include/Counters.h index f9191638d..7ad40b0fa 100644 --- a/projects/mtg/include/Counters.h +++ b/projects/mtg/include/Counters.h @@ -37,6 +37,7 @@ class Counters{ Counter * hasCounter(const char * _name,int _power = 0, int _toughness = 0); Counter * hasCounter(int _power, int _toughness); Counter * getNext(Counter * previous = NULL); + int init(); }; diff --git a/projects/mtg/include/MTGAbility.h b/projects/mtg/include/MTGAbility.h index aa7f675d1..ed6e87d6b 100644 --- a/projects/mtg/include/MTGAbility.h +++ b/projects/mtg/include/MTGAbility.h @@ -13,6 +13,7 @@ class ManaCost; class MTGGameZone; class Player; class AManaProducer; +class WEvent; #include "ActionElement.h" #include @@ -33,9 +34,10 @@ using std::map; class MTGAbility: public ActionElement{ protected: char menuText[25]; - Damageable * target; + GameObserver * game; public: + Damageable * target; MTGCardInstance * source; MTGAbility(int id, MTGCardInstance * card); MTGAbility(int id, MTGCardInstance * _source, Damageable * _target); @@ -44,8 +46,10 @@ class MTGAbility: public ActionElement{ virtual void Render(){}; virtual int isReactingToClick(MTGCardInstance * card){return 0;}; virtual int reactToClick(MTGCardInstance * card){return 0;}; + virtual int receiveEvent(WEvent * event){return 0;}; virtual void Update(float dt){}; virtual int fireAbility(); + virtual int stillInUse(MTGCardInstance * card){if (card==source) return 1; return 0;}; virtual int resolve(){return 0;}; diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index a671f89b9..cc6782503 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -38,8 +38,12 @@ class MTGCardInstance: public MTGCard, public Damageable, public Targetable { void initMTGCI(); public: bool isToken; + int stillInUse(); + Player * lastController; MTGGameZone * getCurrentZone(); MTGGameZone * previousZone; + MTGCardInstance * previous; + MTGCardInstance * next; int doDamageTest; int summoningSickness; // The recommended method to test for summoning Sickness ! diff --git a/projects/mtg/include/MTGGameZones.h b/projects/mtg/include/MTGGameZones.h index 68ddb8973..26a44ecf4 100644 --- a/projects/mtg/include/MTGGameZones.h +++ b/projects/mtg/include/MTGGameZones.h @@ -15,8 +15,9 @@ class Player; class MTGGameZone { protected: - Player * owner; + public: + Player * owner; //Both cards and cardsMap contain the cards of a zone. The long term objective is to get rid of the array MTGCardInstance * cards[MTG_MAX_PLAYER_CARDS]; map cardsMap; @@ -93,9 +94,9 @@ class MTGPlayerCards { void discardRandom(MTGGameZone * from); void drawFromLibrary(); void showHand(); - void putInGraveyard(MTGCardInstance * card); - void putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGameZone * to); - void putInPlay(MTGCardInstance * card); + MTGCardInstance * putInGraveyard(MTGCardInstance * card); + MTGCardInstance * putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGameZone * to); + MTGCardInstance * putInPlay(MTGCardInstance * card); int isInPlay(MTGCardInstance * card); }; diff --git a/projects/mtg/include/MTGGuiPlay.h b/projects/mtg/include/MTGGuiPlay.h index 69b0e04f5..259f17a7c 100644 --- a/projects/mtg/include/MTGGuiPlay.h +++ b/projects/mtg/include/MTGGuiPlay.h @@ -49,6 +49,7 @@ class MTGGuiPlay: public PlayGuiObjectController { void Update(float dt); bool CheckUserInput(u32 key); virtual void Render(); + void forceUpdateCards(); void updateCards(); }; diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index 99971281f..7b0f862b7 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -6,7 +6,7 @@ #include "../include/MTGAbility.h" #include "../include/Counters.h" - +#include "../include/WEvent.h" class MTGPutInPlayRule:public MTGAbility{ public: @@ -39,6 +39,49 @@ class MTGBlockRule:public MTGAbility{ /* Persist Rule */ +class MTGPersistRule:public MTGAbility{ + public: + MTGPersistRule(int _id):MTGAbility(_id,NULL){}; + + int receiveEvent(WEvent * event){ +OutputDebugString("Receive1\n"); + if (event->type == WEvent::CHANGE_ZONE){ +OutputDebugString("Receive2\n"); + WEventZoneChange * e = (WEventZoneChange *) event; + MTGCardInstance * card = e->card->previous; + if (card && card->basicAbilities[Constants::PERSIST] && !card->counters->hasCounter(-1,-1)){ +OutputDebugString("Receive3\n"); + int ok = 0; + for (int i = 0; i < 2 ; i++){ + Player * p = game->players[i]; + if (e->from == p->game->inPlay) ok = 1; + } + if (!ok) return 0; +OutputDebugString("Receive4\n"); + for (int i = 0; i < 2 ; i++){ + Player * p = game->players[i]; + if (e->to == p->game->graveyard){ +OutputDebugString("Receive5\n"); + //p->game->putInZone(card, p->game->graveyard, card->owner->game->hand); + MTGCardInstance * copy = p->game->putInZone(e->card, p->game->graveyard, e->card->owner->game->stack); + Spell * spell = NEW Spell(copy); + spell->resolve(); + spell->source->counters->addCounter(-1,-1); + game->mLayers->playLayer()->forceUpdateCards(); + delete spell; + return 1; + } + } + } + } + return 0; + } + + int testDestroy(){return 0;} + +}; + +/* class MTGPersistRule:public ListMaintainerAbility{ public: MTGPersistRule(int _id):ListMaintainerAbility(_id){}; @@ -50,23 +93,29 @@ class MTGPersistRule:public ListMaintainerAbility{ MTGCardInstance * card = ((*it).first); Player * p = card->controller(); if (p->game->graveyard->hasCard(card)){ -#if defined (WIN32) || defined (LINUX) - OutputDebugString("persist passed test 1 !\n"); -#endif - p->game->putInZone(card, p->game->graveyard, p->game->hand); - Spell * spell = NEW Spell(card); - p->game->putInZone(card, p->game->hand, p->game->stack); - spell->resolve(); - delete spell; -#if defined (WIN32) || defined (LINUX) - OutputDebugString("persist passed test 2 !\n"); -#endif - card->counters->addCounter(-1,-1); -#if defined (WIN32) || defined (LINUX) - OutputDebugString("persist passed test 3 !\n"); -#endif + p->game->putInZone(card, p->game->graveyard, p->game->hand); + Spell * spell = NEW Spell(card); + p->game->putInZone(card, p->game->hand, p->game->stack); + spell->resolve(); + delete spell; + card->counters->addCounter(-1,-1); } } + + // Dirtiest Code Ever, we remove the counters here + + for (int i = 0; i < 2; i++){ + Player * p = game->players[i]; + MTGGameZone * zones[] = {p->game->graveyard, p->game->hand, p->game->library, p->game->removedFromGame}; + for (int j = 0; j < 5; j++){ + MTGGameZone * zone = zones[j]; + for (int k=0; k < zone->nb_cards; k++){ + zone->cards[k]->counters->init(); + } + } + } + + ListMaintainerAbility::Update(dt); } @@ -87,7 +136,7 @@ class MTGPersistRule:public ListMaintainerAbility{ int testDestroy(){return 0;} }; - +*/ /* * Rule 420.5e (Legend Rule) diff --git a/projects/mtg/include/WEvent.h b/projects/mtg/include/WEvent.h new file mode 100644 index 000000000..96ac4a9a9 --- /dev/null +++ b/projects/mtg/include/WEvent.h @@ -0,0 +1,24 @@ +#ifndef _WEVENT_H_ +#define _WEVENT_H_ + +class MTGCardInstance; +class MTGGameZone; + +class WEvent{ +public: + enum{ + CHANGE_ZONE = 1, + }; + int type; + WEvent(int _type); +}; + +class WEventZoneChange: public WEvent{ +public: + MTGCardInstance * card; + MTGGameZone * from; + MTGGameZone * to; + WEventZoneChange(MTGCardInstance * _card, MTGGameZone * _from, MTGGameZone *_to); +}; + +#endif \ No newline at end of file diff --git a/projects/mtg/src/ActionLayer.cpp b/projects/mtg/src/ActionLayer.cpp index 6e283ff04..b17294d2f 100644 --- a/projects/mtg/src/ActionLayer.cpp +++ b/projects/mtg/src/ActionLayer.cpp @@ -2,6 +2,7 @@ #include "../include/ActionLayer.h" #include "../include/GameObserver.h" #include "../include/Targetable.h" +#include "../include/WEvent.h" int ActionLayer::unstopableRenderInProgress(){ @@ -93,6 +94,23 @@ int ActionLayer::isWaitingForAnswer(){ return 0; } +int ActionLayer::stillInUse(MTGCardInstance * card){ + for (int i=0;istillInUse(card)) return 1; + } + return 0; +} + +int ActionLayer::receiveEvent(WEvent * event){ + int result = 0; + for (int i=0;ireceiveEvent(event); + } + return result; +} + int ActionLayer::isReactingToTargetClick(Targetable * card){ int result = 0; diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index 5ccedfbe9..2b22c5a37 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -86,7 +86,10 @@ Spell::~Spell(){ int Spell::resolve(){ GameObserver * game = GameObserver::GetInstance(); //TODO Remove target if it's not targettable anymore - source->controller()->game->putInPlay(source); + while (source->next){ + source = source->next; + } + source = source->controller()->game->putInPlay(source); //Play SFX if (GameOptions::GetInstance()->values[OPTIONS_SFXVOLUME].getIntValue() > 0){ diff --git a/projects/mtg/src/Counters.cpp b/projects/mtg/src/Counters.cpp index e54bb64a1..9355a74ab 100644 --- a/projects/mtg/src/Counters.cpp +++ b/projects/mtg/src/Counters.cpp @@ -81,6 +81,16 @@ int Counters::addCounter(int _power, int _toughness){ return addCounter("",_power, _toughness); } +int Counters::init(){ + for (int i = mCount-1; i >= 0; i--){ + while (counters[i]->nb >= 1) { + counters[i]->removed(); + counters[i]->nb--; + } + } + return 1; +} + int Counters::removeCounter(const char * _name,int _power, int _toughness){ for (int i = 0; i < mCount; i++){ if (counters[i]->sameAs(_name, _power,_toughness)){ diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index db7c64949..3109aab66 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -51,8 +51,8 @@ int AbilityFactory::destroyAllInPlay(TargetChooser * tc, int bury){ int AbilityFactory::putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone, Player * p){ - Spell * spell = NEW Spell(card); - p->game->putInZone(card, zone, p->game->stack); + MTGCardInstance * copy = p->game->putInZone(card, zone, p->game->stack); + Spell * spell = NEW Spell(copy); spell->resolve(); delete spell; return 1; @@ -595,6 +595,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ void AbilityFactory::addAbilities(int _id, Spell * spell){ MTGCardInstance * card = spell->source; + if (spell->cursor==1) card->target = spell->getNextCardTarget(); _id = magicText(_id, spell); int putSourceInGraveyard = 0; //For spells that are not already InstantAbilities; @@ -942,7 +943,9 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){ } case 1143: //Animate Dead { - game->addObserver(NEW AAnimateDead(_id, card, card->target)); + AAnimateDead * a = NEW AAnimateDead(_id, card, card->target); + game->addObserver(a); + card->target = ((MTGCardInstance * )a->target); break; } case 1148 : //Cursed lands @@ -1379,8 +1382,9 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){ case 1367: //Swords to Plowshares { - card->target->controller()->life+= card->target->power; - card->target->controller()->game->inPlay->removeCard(card->target); + Player * p = card->target->controller(); + p->life+= card->target->power; + p->game->putInZone(card->target,p->game->inPlay,card->owner->game->removedFromGame); break; } case 1182: //Terror @@ -1597,7 +1601,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){ } if (putSourceInGraveyard == 1){ MTGPlayerCards * zones = card->controller()->game; - zones->putInGraveyard(card); + card = zones->putInGraveyard(card); } } diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 8c74a3771..7cbd736d4 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -22,6 +22,8 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * _belongs_to): attacker = 0; lifeOrig = life; belongs_to=_belongs_to; + owner = _belongs_to->library->owner; + lastController = owner; initAttackersDefensers(); life=toughness; LOG("==Creating MTGCardInstance Successful=="); @@ -32,6 +34,7 @@ MTGCardInstance::~MTGCardInstance(){ LOG("==Deleting MTGCardInstance=="); SAFE_DELETE(blockers); SAFE_DELETE(counters); + SAFE_DELETE(previous); LOG("==Deleting MTGCardInstance Succesfull=="); } void MTGCardInstance::initMTGCI(){ @@ -53,6 +56,9 @@ void MTGCardInstance::initMTGCI(){ changedZoneRecently = 0; counters = NEW Counters(this); previousZone = NULL; + previous = NULL; + next = NULL; + lastController = NULL; } @@ -164,9 +170,19 @@ int MTGCardInstance::cleanup(){ life=toughness; GameObserver * game = GameObserver::GetInstance(); if (!game || game->currentPlayer == controller()) summoningSickness = 0; + if (previous && !previous->stillInUse()){ + SAFE_DELETE(previous); + } return 1; } +int MTGCardInstance::stillInUse(){ +GameObserver * game = GameObserver::GetInstance(); +if (game->mLayers->actionLayer()->stillInUse(this)) return 1; +if (!previous) return 0; +return previous->stillInUse(); +} + /* Summoning Sickness * 212.3f A creaturefs activated ability with the tap symbol or the untap symbol in its activation cost * canft be played unless the creature has been under its controllerfs control since the start of his or @@ -184,9 +200,9 @@ int MTGCardInstance::hasSummoningSickness(){ int MTGCardInstance::changeController(Player * newController){ Player * originalOwner = controller(); if (originalOwner == newController) return 0; - originalOwner->game->inPlay->removeCard(this); - newController->game->inPlay->addCard(this); - summoningSickness = 1; + MTGCardInstance * copy = originalOwner->game->inPlay->removeCard(this); + newController->game->inPlay->addCard(copy); + //summoningSickness = 1; return 1; } @@ -204,12 +220,12 @@ Player * MTGCardInstance::controller(){ GameObserver * game = GameObserver::GetInstance(); if (!game) return NULL; for (int i = 0; i < 2; 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->graveyard->hasCard(this)) return game->players[i]; - if (game->players[i]->game->hand->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->graveyard->hasCard(this)) return game->players[i]; + if (game->players[i]->game->hand->hasCard(this)) return game->players[i]; } - return NULL; + return lastController; } int MTGCardInstance::canAttack(){ diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index d5d11a7bc..ada2029a2 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -2,6 +2,7 @@ #include "../include/MTGGameZones.h" #include "../include/Player.h" #include "../include/GameOptions.h" +#include "../include/WEvent.h" #if defined (WIN32) || defined (LINUX) #include @@ -69,28 +70,32 @@ void MTGPlayerCards::showHand(){ } -void MTGPlayerCards::putInPlay(MTGCardInstance * card){ - hand->removeCard(card); - stack->removeCard(card); //Which one is it ??? +MTGCardInstance * MTGPlayerCards::putInPlay(MTGCardInstance * card){ + MTGCardInstance * copy = hand->removeCard(card); + if(!copy) copy = stack->removeCard(card); //Which one is it ??? - inPlay->addCard(card); - card->summoningSickness = 1; - card->changedZoneRecently = 1.f; + inPlay->addCard(copy); + copy->summoningSickness = 1; + copy->changedZoneRecently = 1.f; + return copy; } -void MTGPlayerCards::putInGraveyard(MTGCardInstance * card){ +MTGCardInstance * MTGPlayerCards::putInGraveyard(MTGCardInstance * card){ + MTGCardInstance * copy = NULL; if (inPlay->hasCard(card)){ - putInZone(card,inPlay, graveyard); + copy = putInZone(card,inPlay, graveyard); }else if (stack->hasCard(card)){ - putInZone(card,stack, graveyard); + copy = putInZone(card,stack, graveyard); }else{ - putInZone(card,hand, graveyard); + copy = putInZone(card,hand, graveyard); } + return copy; } -void MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGameZone * to){ - if (from->removeCard(card)){ +MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGameZone * to){ + MTGCardInstance * copy = NULL; + if (copy = from->removeCard(card)){ if (GameOptions::GetInstance()->values[OPTIONS_SFXVOLUME].getIntValue() > 0){ if (to == graveyard){ @@ -106,14 +111,17 @@ void MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGa if (to != g->players[0]->game->inPlay && to != g->players[1]->game->inPlay){ //Token leaves play: we destroy it //TODO DELETE Object - return; + return NULL; } } - to->addCard(card); - card->changedZoneRecently = 1.f; - - card->reset(); + to->addCard(copy); + copy->changedZoneRecently = 1.f; + GameObserver *g = GameObserver::GetInstance(); + WEvent * e = NEW WEventZoneChange(copy, from, to); + g->mLayers->actionLayer()->receiveEvent(e); + delete e; + return copy; } } @@ -147,6 +155,9 @@ MTGGameZone::~MTGGameZone(){ } void MTGGameZone::setOwner(Player * player){ + char buf[4096]; + sprintf(buf, "Setting Owner : %p\n", player); +OutputDebugString(buf); for (int i=0; iowner = player; } @@ -160,8 +171,15 @@ MTGCardInstance * MTGGameZone::removeCard(MTGCardInstance * card){ if (cards[i] == card){ cards[i] = cards[nb_cards -1]; nb_cards--; - card->previousZone = this; - return card; + if (card->isToken){ //TODO better than this ? + return card; + } + card->lastController = card->controller(); + MTGCardInstance * copy = NEW MTGCardInstance(card->model,card->owner->game); + copy->previous = card; + card->next = copy; + copy->previousZone = this; + return copy; } } return NULL; @@ -206,7 +224,7 @@ void MTGGameZone::shuffle(){ int r = i + (rand() % (nb_cards-i)); // Random remaining position. MTGCardInstance * temp = cards[i]; cards[i] = cards[r]; cards[r] = temp; } - srand(time(0)); // initialize seed "randomly" TODO :improve + //srand(time(0)); // initialize seed "randomly" TODO :improve } diff --git a/projects/mtg/src/MTGGuiPlay.cpp b/projects/mtg/src/MTGGuiPlay.cpp index 052e31753..9e5247b96 100644 --- a/projects/mtg/src/MTGGuiPlay.cpp +++ b/projects/mtg/src/MTGGuiPlay.cpp @@ -156,26 +156,20 @@ void MTGGuiPlay::setTargettingCardPosition(CardGui * cardg, int player, int play return; } -void MTGGuiPlay::updateCards(){ +void MTGGuiPlay::forceUpdateCards(){ GameObserver * game = GameObserver::GetInstance(); Player * player = game->players[0]; int player0Mode =(game->currentPlayer == player); int nb_cards = player->game->inPlay->nb_cards; - MTGCardInstance * attackers[MAX_ATTACKERS]; - for (int i = 0; i players[1]; - int opponent_cards = opponent ->game->inPlay->nb_cards; - if (mCount - offset != (nb_cards+opponent_cards) || game->currentPlayer != currentPlayer ){ //if the number of cards has changed, then an update occured (is this test engouh ?) resetObjects(); AddPlayersGuiInfo(); offset = mCount; bool hasFocus = player0Mode; + offset = 6; + + Player * opponent = game->players[1]; + int opponent_cards = opponent ->game->inPlay->nb_cards; for (int i = 0;icurrentPlayer; +} + +void MTGGuiPlay::updateCards(){ + GameObserver * game = GameObserver::GetInstance(); + Player * player = game->players[0]; + int player0Mode =(game->currentPlayer == player); + int nb_cards = player->game->inPlay->nb_cards; + MTGCardInstance * attackers[MAX_ATTACKERS]; + for (int i = 0; i players[1]; + int opponent_cards = opponent ->game->inPlay->nb_cards; + if (mCount - offset != (nb_cards+opponent_cards) || game->currentPlayer != currentPlayer ){ //if the number of cards has changed, then an update occured (is this test engouh ?) + forceUpdateCards(); } diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index f8a7c2553..6d9ad26b6 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -51,21 +51,22 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){ card->getManaCost()->doPayExtra(); ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); delete previousManaPool; - if (card->hasType("land")){ - Spell * spell = NEW Spell(card); - player->game->putInZone(card, player->game->hand, player->game->stack); + if (card->hasType("land")){ + MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); + Spell * spell = NEW Spell(copy); spell->resolve(); delete spellCost; delete spell; player->canPutLandsIntoPlay--; }else{ + MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); if (game->targetChooser){ - game->mLayers->stackLayer()->addSpell(card,game->targetChooser->targets,game->targetChooser->cursor, spellCost); + game->mLayers->stackLayer()->addSpell(copy,game->targetChooser->targets,game->targetChooser->cursor, spellCost); SAFE_DELETE(game->targetChooser); }else{ - game->mLayers->stackLayer()->addSpell(card,NULL,0, spellCost); + game->mLayers->stackLayer()->addSpell(copy,NULL,0, spellCost); } - player->game->putInZone(card, player->game->hand, player->game->stack); + } return 1; diff --git a/projects/mtg/src/TestSuiteAI.cpp b/projects/mtg/src/TestSuiteAI.cpp index b08273ac2..92ca3f18f 100644 --- a/projects/mtg/src/TestSuiteAI.cpp +++ b/projects/mtg/src/TestSuiteAI.cpp @@ -235,11 +235,10 @@ void TestSuite::initGame(){ OutputDebugString(buf); if (card && zone != p->game->library){ if (zone == p->game->inPlay){ - p->game->putInZone(card, p->game->library, p->game->hand); - Spell * spell = NEW Spell(card); - p->game->putInZone(card, p->game->hand, p->game->stack); + MTGCardInstance * copy = p->game->putInZone(card, p->game->library, p->game->stack); + Spell * spell = NEW Spell(copy); spell->resolve(); - if (!summoningSickness) card->summoningSickness = 0; + if (!summoningSickness) p->game->inPlay->cards[k]->summoningSickness = 0; delete spell; }else{ if (!p->game->library->hasCard(card)){ diff --git a/projects/mtg/src/WEvent.cpp b/projects/mtg/src/WEvent.cpp new file mode 100644 index 000000000..e5fe72616 --- /dev/null +++ b/projects/mtg/src/WEvent.cpp @@ -0,0 +1,13 @@ +#include "../include/WEvent.h" +#include "../include/MTGCardInstance.h" +#include "../include/MTGGameZones.h" + +WEvent::WEvent(int _type){ + type=_type; +} + +WEventZoneChange::WEventZoneChange(MTGCardInstance * _card, MTGGameZone * _from, MTGGameZone *_to):WEvent(CHANGE_ZONE){ + card = _card; + from = _from; + to = _to; +} \ No newline at end of file diff --git a/projects/mtg/template.vcproj b/projects/mtg/template.vcproj index 3ab367c0d..b6942707e 100644 --- a/projects/mtg/template.vcproj +++ b/projects/mtg/template.vcproj @@ -488,6 +488,10 @@ RelativePath=".\src\utils.cpp" > + + + +