From 6dab048a9e25bc04f8b9e4f7e13d09950d549529 Mon Sep 17 00:00:00 2001 From: "jean.chalard" Date: Mon, 31 Aug 2009 02:00:33 +0000 Subject: [PATCH] J : * Interface for damage assignment. --- projects/mtg/Makefile | 2 +- projects/mtg/bin/Res/test/order_blockers.txt | 12 +- projects/mtg/include/Damage.h | 4 +- projects/mtg/include/DamagerDamaged.h | 32 +- projects/mtg/include/GuiCombat.h | 23 +- projects/mtg/include/MTGCardInstance.h | 1 + projects/mtg/include/PhaseRing.h | 1 + projects/mtg/include/Pos.h | 1 + projects/mtg/include/WEvent.h | 10 +- projects/mtg/src/AIPlayer.cpp | 2 - projects/mtg/src/ActionStack.cpp | 2 +- projects/mtg/src/Damage.cpp | 12 +- projects/mtg/src/DamageResolverLayer.cpp | 17 +- projects/mtg/src/DamagerDamaged.cpp | 122 ++++--- projects/mtg/src/GameObserver.cpp | 4 +- projects/mtg/src/GuiCombat.cpp | 325 +++++++++++++------ projects/mtg/src/MTGCardInstance.cpp | 12 + projects/mtg/src/Pos.cpp | 4 + projects/mtg/src/WEvent.cpp | 4 +- 19 files changed, 377 insertions(+), 213 deletions(-) diff --git a/projects/mtg/Makefile b/projects/mtg/Makefile index bb89da929..f4bf76f29 100644 --- a/projects/mtg/Makefile +++ b/projects/mtg/Makefile @@ -1,4 +1,4 @@ -OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIMomirPlayer.o objs/AIPlayer.o objs/AIStats.o objs/Blocker.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardSelector.o objs/ConstraintResolver.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DamageResolverLayer.o objs/DeckDataWrapper.o objs/DeckStats.o objs/DuelLayers.o objs/Effects.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameState.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GuiAvatars.o objs/GuiBackground.o objs/GuiCardsController.o objs/GuiCombat.o objs/GuiFrame.o objs/GuiHand.o objs/GuiLayers.o objs/GuiMana.o objs/GuiPhaseBar.o objs/GuiPlay.o objs/GuiStatic.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/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/Pos.o objs/PriceList.o objs/ReplacementEffects.o objs/ShopItem.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/TexturesCache.o objs/SimplePad.o objs/Token.o objs/Translate.o objs/utils.o objs/WEvent.o objs/WResourceManager.o +OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIMomirPlayer.o objs/AIPlayer.o objs/AIStats.o objs/Blocker.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardSelector.o objs/ConstraintResolver.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DeckDataWrapper.o objs/DeckStats.o objs/DuelLayers.o objs/Effects.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameState.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GuiAvatars.o objs/GuiBackground.o objs/GuiCardsController.o objs/GuiCombat.o objs/GuiFrame.o objs/GuiHand.o objs/GuiLayers.o objs/GuiMana.o objs/GuiPhaseBar.o objs/GuiPlay.o objs/GuiStatic.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/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/Pos.o objs/PriceList.o objs/ReplacementEffects.o objs/ShopItem.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/TexturesCache.o objs/SimplePad.o objs/Token.o objs/Translate.o objs/utils.o objs/WEvent.o objs/WResourceManager.o DEPS = $(patsubst objs/%.o, deps/%.d, $(OBJS)) RESULT = $(shell psp-config --psp-prefix 2> Makefile.cache) diff --git a/projects/mtg/bin/Res/test/order_blockers.txt b/projects/mtg/bin/Res/test/order_blockers.txt index 989d998c3..c67438648 100644 --- a/projects/mtg/bin/Res/test/order_blockers.txt +++ b/projects/mtg/bin/Res/test/order_blockers.txt @@ -2,22 +2,18 @@ [INIT] COMBATATTACKERS [PLAYER1] -inplay:Elite Vanguard,Rhox Pikemaster,Bog wraith +inplay:Rootbreaker Wurm,Benthic Behemoth,Bog wraith [PLAYER2] -inplay:air elemental,grizzly bears,spark elemental,drudge skeletons,vampire bats,tundra wolves,spined wurm,paladin en-vec +inplay:air elemental,grizzly bears,spark elemental,drudge skeletons,vampire bats,spined wurm [DO] -Elite Vanguard -Rhox Pikemaster +Rootbreaker Wurm +Benthic Behemoth Bog wraith next -paladin en-vec -paladin en-vec spined wurm spined wurm vampire bats vampire bats -tundra wolves -tundra wolves air elemental air elemental grizzly bears diff --git a/projects/mtg/include/Damage.h b/projects/mtg/include/Damage.h index daa929c34..3b3cd69eb 100644 --- a/projects/mtg/include/Damage.h +++ b/projects/mtg/include/Damage.h @@ -33,8 +33,8 @@ class Damage: public Interruptible { Damageable * target; int damage; void Render(); - Damage(int id, MTGCardInstance* source, Damageable * target); - Damage(int id, MTGCardInstance* source, Damageable * target, int damage); + Damage(MTGCardInstance* source, Damageable * target); + Damage(MTGCardInstance* source, Damageable * target, int damage); int resolve(); virtual ostream& toString(ostream& out) const; }; diff --git a/projects/mtg/include/DamagerDamaged.h b/projects/mtg/include/DamagerDamaged.h index 4f6443aff..97fcdebc0 100644 --- a/projects/mtg/include/DamagerDamaged.h +++ b/projects/mtg/include/DamagerDamaged.h @@ -1,27 +1,35 @@ #ifndef _DAMAGERDAMAGED_H_ #define _DAMAGERDAMAGED_H_ -#include "../include/MTGCardInstance.h" +#include "MTGCardInstance.h" +#include "CardGui.h" class Player; -struct DamagerDamaged { - MTGCardInstance* card; +struct DamagerDamaged : TransientCardView { + bool show; Player * damageSelecter; - int mCount; - Damage * damages[10]; + vector damages; int damageToDeal; - int dealOneDamage(DamagerDamaged * target); - int addDamage(int damage, DamagerDamaged * source); - int removeDamagesTo(DamagerDamaged * target); - int removeDamagesFrom(DamagerDamaged * source); + void addDamage(int damage, DamagerDamaged* source); + int removeDamagesTo(DamagerDamaged* target); + int removeDamagesFrom(DamagerDamaged* source); + void clearDamage(); int sumDamages(); - int hasLethalDamage(); - DamagerDamaged(MTGCardInstance* card, Player * _damageSelecter, bool _hasFocus); + bool hasLethalDamage(); + DamagerDamaged(MTGCardInstance* card, float x, float y, bool show, Player* damageSelecter); + DamagerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player* damageSelecter); + ~DamagerDamaged(); - void Render(Player * currentPlayer); + void Render(CombatStep mode); }; +typedef DamagerDamaged DefenserDamaged; +struct AttackerDamaged : DamagerDamaged { + vector blockers; + AttackerDamaged(MTGCardInstance* card, float x, float y, bool show, Player* damageSelecter); + AttackerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player* damageSelecter); +}; #endif diff --git a/projects/mtg/include/GuiCombat.h b/projects/mtg/include/GuiCombat.h index f5a5a9d13..768d7ddd7 100644 --- a/projects/mtg/include/GuiCombat.h +++ b/projects/mtg/include/GuiCombat.h @@ -5,22 +5,24 @@ #include "WEvent.h" #include "CardGui.h" #include "MTGCardInstance.h" +#include "DamagerDamaged.h" class GuiCombat : public GuiLayer { protected: GameObserver* go; - TransientCardView* active, *activeAtk; - JQuad* ok_quad; + DamagerDamaged* active; + AttackerDamaged* activeAtk; + static JQuad* ok_quad; Pos ok; - vector attackers; - TransientCardView* current; + vector attackers; + DamagerDamaged* current; enum { BLK, ATK, OK, NONE } cursor_pos; - - vector atkViews; - vector blkViews; - - void generateBlkViews(MTGCardInstance* card); + CombatStep step; + void addOne(DefenserDamaged* blocker, CombatStep); + void removeOne(DefenserDamaged* blocker, CombatStep); + void reaffectDamage(AttackerDamaged* attacker, CombatStep); + void remaskBlkViews(AttackerDamaged* before, AttackerDamaged* after); public: GuiCombat(GameObserver* go); @@ -30,7 +32,8 @@ class GuiCombat : public GuiLayer virtual bool CheckUserInput(u32 key); virtual int receiveEventPlus(WEvent* e); virtual int receiveEventMinus(WEvent* e); + + typedef vector::iterator inner_iterator; }; - #endif // _GUICOMBAT_H_ diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index 3f93d0e17..3fdad75e0 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -82,6 +82,7 @@ class MTGCardInstance: public MTGCard, public Damageable { MTGCardInstance * getNextOpponent(MTGCardInstance * previous=NULL); MTGCardInstance * getNextDefenser(MTGCardInstance * previous=NULL); int nbOpponents(); + int stepPower(CombatStep step); int afterDamage(); diff --git a/projects/mtg/include/PhaseRing.h b/projects/mtg/include/PhaseRing.h index 7a111d0c3..6936e7f2e 100644 --- a/projects/mtg/include/PhaseRing.h +++ b/projects/mtg/include/PhaseRing.h @@ -10,6 +10,7 @@ using std::list; class Player; +typedef enum { ORDER, FIRST_STRIKE, DAMAGE } CombatStep; class Phase{ public: int id; diff --git a/projects/mtg/include/Pos.h b/projects/mtg/include/Pos.h index 25111ee5f..0a2935cf9 100644 --- a/projects/mtg/include/Pos.h +++ b/projects/mtg/include/Pos.h @@ -8,6 +8,7 @@ struct Pos { float x, y, zoom, t, alpha; Pos(float, float, float, float, float); virtual void Update(float dt); + void UpdateNow(); virtual void Render(); void Render(JQuad*); }; diff --git a/projects/mtg/include/WEvent.h b/projects/mtg/include/WEvent.h index 62331f466..e2412e6fd 100644 --- a/projects/mtg/include/WEvent.h +++ b/projects/mtg/include/WEvent.h @@ -1,6 +1,8 @@ #ifndef _WEVENT_H_ #define _WEVENT_H_ +#include "PhaseRing.h" + class MTGCardInstance; class MTGGameZone; class Damage; @@ -82,10 +84,14 @@ struct WEventCreatureBlockerRank : public WEventCardUpdate { WEventCreatureBlockerRank(MTGCardInstance * card,MTGCardInstance * exchangeWith, MTGCardInstance * attacker); }; -//Event when blockers are assigned and need to be reordered -struct WEventBlockersAssigned : public WEvent { +//Event when a combat phase step ends +struct WEventCombatStepChange : public WEvent +{ + CombatStep step; + WEventCombatStepChange(CombatStep); }; + //Event when a mana is engaged //color : color struct WEventEngageMana : public WEvent { diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index f1dc60e63..ed44e3403 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -1,8 +1,6 @@ #include "../include/config.h" #include "../include/AIPlayer.h" #include "../include/CardDescriptor.h" -#include "../include/DamageResolverLayer.h" -#include "../include/DamagerDamaged.h" #include "../include/AIStats.h" #include "../include/AllAbilities.h" #include "../include/ExtraCost.h" diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index 06978640a..9a317bb83 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -345,7 +345,7 @@ int ActionStack::addDraw(Player * player, int nb_cards){ } int ActionStack::addDamage(MTGCardInstance * _source, Damageable * _target, int _damage){ - Damage * damage = NEW Damage(mCount, _source, _target, _damage); + Damage * damage = NEW Damage(_source, _target, _damage); addAction(damage); return 1; } diff --git a/projects/mtg/src/Damage.cpp b/projects/mtg/src/Damage.cpp index d5348a739..f043ccbc8 100644 --- a/projects/mtg/src/Damage.cpp +++ b/projects/mtg/src/Damage.cpp @@ -6,11 +6,11 @@ #include "../include/Translate.h" #include "../include/TexturesCache.h" -Damage::Damage(int id, MTGCardInstance * source, Damageable * target) { +Damage::Damage(MTGCardInstance * source, Damageable * target) { init(source, target, source->getPower()); } -Damage::Damage(int id, MTGCardInstance * source, Damageable * target, int damage) { +Damage::Damage(MTGCardInstance * source, Damageable * target, int damage) { init(source, target, damage); } @@ -114,21 +114,21 @@ int DamageStack::CombatDamages(int strike){ int nbdefensers = defensers->nbDefensers(attacker); if ((!strike && !attacker->has(Constants::FIRSTSTRIKE)) || (strike && attacker->has(Constants::FIRSTSTRIKE)) || attacker->has(Constants::DOUBLESTRIKE)){ if (nbdefensers == 0){ - Damage * damage = NEW Damage (mCount, attacker, game->opponent()); + Damage * damage = NEW Damage(attacker, game->opponent()); Add(damage); }else if (nbdefensers == 1){ - Damage * damage = NEW Damage (mCount, attacker, defensers->getNextDefenser(NULL, attacker)); + Damage * damage = NEW Damage(attacker, defensers->getNextDefenser(NULL, attacker)); Add(damage); }else{ //TODO Fetch list of defensers and allow user to choose targets - Damage * damage = NEW Damage (mCount, attacker, defensers->getNextDefenser(NULL, attacker)); + Damage * damage = NEW Damage(attacker, defensers->getNextDefenser(NULL, attacker)); Add(damage); } } MTGCardInstance * defenser = defensers->getNextDefenser(NULL, attacker); while (defenser != NULL){ if ((!strike && !defenser->has(Constants::FIRSTSTRIKE)) || (strike && defenser->has(Constants::FIRSTSTRIKE)) || defenser->has(Constants::DOUBLESTRIKE)){ - Damage * damage = NEW Damage (mCount,defenser, attacker); + Damage * damage = NEW Damage(defenser, attacker); Add(damage); } defenser = defensers->getNextDefenser(defenser, attacker); diff --git a/projects/mtg/src/DamageResolverLayer.cpp b/projects/mtg/src/DamageResolverLayer.cpp index c8400d6c3..610bbccd1 100644 --- a/projects/mtg/src/DamageResolverLayer.cpp +++ b/projects/mtg/src/DamageResolverLayer.cpp @@ -106,11 +106,12 @@ DamagerDamaged * DamageResolverLayer::addIfNotExists(MTGCardInstance * card, Pla DamagerDamaged * item = (DamagerDamaged *)mObjects[i]; if (item->card == card) return item; } - // CardGui * cardg = game->mLayers->playLayer()->getByCard(card); - DamagerDamaged * item = NEW DamagerDamaged(card, selecter, mCount == 0); - // Add(NEW TransientCardView(card->gui)); - mCurr = 0; - return item; + // CardGui * cardg = game->mLayers->playLayer()->getByCard(card); + // DamagerDamaged * item = NEW DamagerDamaged(card, selecter, mCount == 0); + // Add(NEW TransientCardView(card->gui)); + // mCurr = 0; + // return item; + return NULL; } void DamageResolverLayer::updateAllCoordinates(){ @@ -303,6 +304,7 @@ int DamageResolverLayer::trampleDamage(){ int DamageResolverLayer::resolveDamages(){ trampleDamage(); + /* for (int i = 0; i < mCount ; i++){ DamagerDamaged * current = (DamagerDamaged *) mObjects[i]; for (int j =0; j < current->mCount ; j++){ @@ -310,6 +312,7 @@ int DamageResolverLayer::resolveDamages(){ damageStack->Add(damage); } } + */ game->mLayers->stackLayer()->addAction(damageStack); game->mLayers->stackLayer()->resolve(); //Wagic 2010 remainingDamageSteps--; @@ -525,10 +528,10 @@ void DamageResolverLayer::Render(){ mFont->DrawString(_("Current Damager:").c_str(), 10, 5); } for (int i = 0; i < mCount; i++){ - ((DamagerDamaged *)mObjects[i])->Render(currentChoosingPlayer); + ((DamagerDamaged *)mObjects[i])->Render(); } if (mObjects[mCurr]){ - ((DamagerDamaged *)mObjects[mCurr])->Render(currentChoosingPlayer); + ((DamagerDamaged *)mObjects[mCurr])->Render(); } diff --git a/projects/mtg/src/DamagerDamaged.cpp b/projects/mtg/src/DamagerDamaged.cpp index 300e5b7e4..2aa5e3a6b 100644 --- a/projects/mtg/src/DamagerDamaged.cpp +++ b/projects/mtg/src/DamagerDamaged.cpp @@ -5,88 +5,74 @@ Temporary objects that store the damages dealt to/from creatures during the combat phase */ +DamagerDamaged::DamagerDamaged(MTGCardInstance* card, float x, float y, bool show, Player * damageSelecter) : TransientCardView(card, x, y), show(show), damageSelecter(damageSelecter) {} +DamagerDamaged::DamagerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player * damageSelecter) : TransientCardView(card, ref), show(show), damageSelecter(damageSelecter) {} -DamagerDamaged::DamagerDamaged(MTGCardInstance* card, Player * _damageSelecter, bool _hasFocus) : card(card){ - mCount = 0; - damageSelecter = _damageSelecter; - damageToDeal = card->power; -} - -DamagerDamaged::~DamagerDamaged(){ - for (int i = 0; i < mCount; i++){ - SAFE_DELETE(damages[i]); - - } -} +DamagerDamaged::~DamagerDamaged(){} int DamagerDamaged::sumDamages(){ int total = 0; - for (int i = 0; i < mCount; i++){ - total += damages[i]->damage; - } + for (vector::iterator i = damages.begin(); i != damages.end(); ++i) + total += i->damage; return total; } -int DamagerDamaged::hasLethalDamage(){ - if (sumDamages() >= card->life) return 1; +bool DamagerDamaged::hasLethalDamage(){ + return (sumDamages() >= card->life); +} + +void DamagerDamaged::addDamage(int damage, DamagerDamaged* source){ + for (vector::iterator i = damages.begin(); i != damages.end(); ++i) + if (i->source == source->card){ + i->damage += damage; + if (0 >= i->damage) damages.erase(i); + return; + } + if (0 < damage) damages.push_back(Damage(source->card, this->card,damage)); + return; +} + + +int DamagerDamaged::removeDamagesFrom(DamagerDamaged* source){ + for (vector::iterator i = damages.begin(); i != damages.end(); ++i) + if (i->source == source->card){ + int damage = i->damage; + damages.erase(i); + return damage; + } return 0; } -int DamagerDamaged::dealOneDamage(DamagerDamaged * target){ - if (!damageToDeal) return 0; - damageToDeal--; -#if defined (WIN32) || defined (LINUX) - char buf[4096]; - sprintf(buf, "==========\n%s can still deal %i damages\n=============\n", card->getName().c_str(), damageToDeal); - OutputDebugString(buf); -#endif - return target->addDamage(1, this); +void DamagerDamaged::clearDamage() +{ + damages.clear(); } -int DamagerDamaged::addDamage(int damage, DamagerDamaged * source){ - for (int i = 0; i < mCount; i++){ - if (damages[i]->source == source->card){ - damages[i]->damage+= damage; - return damage; - } - } - damages[mCount] = NEW Damage(mCount, source->card, this->card,damage); - mCount++; - return damage; -} - -int DamagerDamaged::removeDamagesTo(DamagerDamaged * target){ - damageToDeal+= target->removeDamagesFrom(this); - return 1; -} - -int DamagerDamaged::removeDamagesFrom(DamagerDamaged * source){ - for (int i = 0; i < mCount; i++){ - if (damages[i]->source == source->card){ - int damage = damages[i]->damage; - SAFE_DELETE(damages[i]); - damages[i] = damages[mCount-1]; - mCount--; - return damage; - } - } - return 0; -} - -void DamagerDamaged::Render(Player * currentPlayer){ +void DamagerDamaged::Render(CombatStep mode) +{ + TransientCardView::Render(); JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); mFont->SetBase(0); - // CardGui::Render(); - - /* - char buf[4096]; - if (currentPlayer != damageSelecter){ - if (hasLethalDamage()){ - mFont->DrawString("X",x,y); + + switch (mode) + { + case ORDER : + mFont->SetColor(ARGB(92,255,255,255)); + break; + case FIRST_STRIKE : + case DAMAGE : + mFont->SetColor(ARGB(255, 255, 64, 0)); + break; } - mFont->SetColor(ARGB(255,255,0,0)); + + char buf[6]; + // if (currentPlayer != damageSelecter){ + /* if (hasLethalDamage()){ + mFont->DrawString("X",x,y); + }*/ sprintf(buf, "%i", sumDamages()); - mFont->DrawString(buf,x+5, y+5); + mFont->DrawString(buf, actX - 14 * actZ + 5, actY - 14 * actZ); + /* }else{ mFont->SetColor(ARGB(255,0,0,255)); sprintf(buf, "%i", damageToDeal); @@ -95,3 +81,7 @@ void DamagerDamaged::Render(Player * currentPlayer){ mFont->SetColor(ARGB(255,255,255,255)); */ } + + +AttackerDamaged::AttackerDamaged(MTGCardInstance* card, float x, float y, bool show, Player * damageSelecter) : DamagerDamaged(card, x, y, show, damageSelecter) {} +AttackerDamaged::AttackerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player * damageSelecter) : DamagerDamaged(card, ref, show, damageSelecter) {} diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index 4e56436ac..69db5c027 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -88,7 +88,7 @@ void GameObserver::nextGamePhase(){ Phase * cPhaseOld = phaseRing->getCurrentPhase(); if (!blockersSorted && cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS){ blockersAssigned = 1; - receiveEvent(NEW WEventBlockersAssigned()); + receiveEvent(NEW WEventCombatStepChange(ORDER)); /* if (!mLayers->combatLayer()->autoOrderBlockers()){ OutputDebugString("Player has To choose ordering!"); @@ -156,7 +156,7 @@ void GameObserver::userRequestNextGamePhase(){ Phase * cPhaseOld = phaseRing->getCurrentPhase(); if (!blockersSorted && cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS){ blockersAssigned = 1; - receiveEvent(NEW WEventBlockersAssigned()); + receiveEvent(NEW WEventCombatStepChange(ORDER)); /* if (!mLayers->combatLayer()->autoOrderBlockers()){ OutputDebugString("Player has To choose ordering!"); diff --git a/projects/mtg/src/GuiCombat.cpp b/projects/mtg/src/GuiCombat.cpp index ea03510e2..ef0313a77 100644 --- a/projects/mtg/src/GuiCombat.cpp +++ b/projects/mtg/src/GuiCombat.cpp @@ -4,83 +4,137 @@ #include "Closest.cpp" static const float MARGIN = 70; +static const float TOP_LINE = 80; +struct Left : public Exp { static inline bool test(DamagerDamaged* ref, DamagerDamaged* test) + { return ref->y == test->y && ref->x > test->x && test->show; } }; +struct Right : public Exp { static inline bool test(DamagerDamaged* ref, DamagerDamaged* test) + { return ref->y == test->y && ref->x < test->x && test->show; } }; -struct Left : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) - { return ref->y == test->y && ref->x > test->x; } }; -struct Right : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) - { return ref->y == test->y && ref->x < test->x; } }; +JQuad* GuiCombat::ok_quad = NULL; - -GuiCombat::GuiCombat(GameObserver* go) : GuiLayer(), go(go), active(false), ok(SCREEN_WIDTH - MARGIN, 210, 1, 0, 255), cursor_pos(NONE) +GuiCombat::GuiCombat(GameObserver* go) : GuiLayer(), go(go), active(false), activeAtk(NULL), ok(SCREEN_WIDTH - MARGIN, 210, 1, 0, 255), cursor_pos(NONE), step(DAMAGE) { - if (!GameApp::CommonRes->GetTexture("Ok.png")) + if (NULL == ok_quad) { - GameApp::CommonRes->CreateTexture("Ok.png"); - GameApp::CommonRes->CreateQuad("OK", "Ok.png", 0, 0, 56, 45); + if (!GameApp::CommonRes->GetTexture("Ok.png")) + { + GameApp::CommonRes->CreateTexture("Ok.png"); + GameApp::CommonRes->CreateQuad("OK", "Ok.png", 0, 0, 56, 45); + } + ok_quad = GameApp::CommonRes->GetQuad("OK"); + ok_quad->SetHotSpot(28, 22); } - ok_quad = GameApp::CommonRes->GetQuad("OK"); - if(ok_quad) - ok_quad->SetHotSpot(28, 22); } GuiCombat::~GuiCombat() { } +template +static inline void repos(typename vector::iterator begin, typename vector::iterator end, signed size = -1) +{ + for (typename vector::iterator it = begin; it != end; ++it) + if ((*it)->show) ++size; + float space = (SCREEN_WIDTH - 2*MARGIN) / size; + float pos = MARGIN; + for (typename vector::iterator it = begin; it != end; ++it) + if ((*it)->show) + { + (*it)->x = pos; + pos += space; + } +} + void GuiCombat::Update(float dt) { - if (NONE != cursor_pos) + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + (*it)->Update(dt); + if (activeAtk) + for (vector::iterator q = activeAtk->blockers.begin(); q != activeAtk->blockers.end(); ++q) + (*q)->Update(dt); + ok.Update(dt); +} + +void GuiCombat::remaskBlkViews(AttackerDamaged* before, AttackerDamaged* after) +{ + if (after) { - for (vector::iterator it = atkViews.begin(); it != atkViews.end(); ++it) - (*it)->Update(dt); - for (vector::iterator it = blkViews.begin(); it != blkViews.end(); ++it) - (*it)->Update(dt); - ok.Update(dt); + for (vector::iterator q = after->blockers.begin(); q != after->blockers.end(); ++q) + { + (*q)->actX = MARGIN; (*q)->y = TOP_LINE; + (*q)->zoom = 2.2; (*q)->t = 0; + } + repos(after->blockers.begin(), after->blockers.end()); } } -void GuiCombat::generateBlkViews(MTGCardInstance* card) +void GuiCombat::reaffectDamage(AttackerDamaged* attacker, CombatStep step) { - for (vector::iterator it = blkViews.begin(); it != blkViews.end(); ++it) - SAFE_DELETE(*it); - blkViews.clear(); - if (card && card->blockers.size() > 0) + attacker->clearDamage(); + unsigned damage = attacker->card->stepPower(step); + for (vector::iterator it = attacker->blockers.begin(); it != attacker->blockers.end(); ++it) { - float space = (SCREEN_WIDTH - 2*MARGIN) / card->blockers.size(); - float pos = MARGIN; - for (list::iterator it = card->blockers.begin(); it != card->blockers.end(); ++it) - { - TransientCardView* t = NEW TransientCardView(*it, 20, 60); - blkViews.push_back(t); - t->x = pos; t->y = 60; - t->zoom = 2.2; t->t = 0; - pos += space; - } + (*it)->clearDamage(); + unsigned actual_damage = MIN(damage, (unsigned)MAX((*it)->card->toughness, 0)); + (*it)->addDamage(actual_damage, attacker); + attacker->addDamage((*it)->card->stepPower(step), *it); + damage -= actual_damage; } } +void GuiCombat::addOne(DefenserDamaged* blocker, CombatStep step) +{ + blocker->addDamage(1, activeAtk); + signed damage = activeAtk->card->stepPower(step); + for (vector::iterator it = activeAtk->blockers.begin(); it != activeAtk->blockers.end(); ++it) + { + damage -= (*it)->sumDamages(); + if (0 > damage) { (*it)->addDamage(-1, activeAtk); break; } + } +} +void GuiCombat::removeOne(DefenserDamaged* blocker, CombatStep step) +{ + blocker->addDamage(-1, activeAtk); + for (vector::iterator it = activeAtk->blockers.begin(); it != activeAtk->blockers.end(); ++it) + if (!(*it)->hasLethalDamage()) { (*it)->addDamage(1, activeAtk); break; } +} + bool GuiCombat::CheckUserInput(u32 key) { if (NONE == cursor_pos) return false; - TransientCardView* oldActive = active; + DamagerDamaged* oldActive = active; switch (key) { case PSP_CTRL_CIRCLE: if (BLK == cursor_pos) - activeAtk->card->raiseBlockerRankOrder(active->card); - else if (OK == cursor_pos) { cursor_pos = NONE; go->userRequestNextGamePhase(); }; - break; - case PSP_CTRL_UP: - if (ATK == cursor_pos) + if (ORDER == step) { activeAtk->card->raiseBlockerRankOrder(active->card); } + else + { + signed damage = activeAtk->card->stepPower(step); + for (vector::iterator it = activeAtk->blockers.begin(); *it != active; ++it) + damage -= (*it)->sumDamages(); + signed now = active->sumDamages(); + damage -= now; + if (damage > 0) addOne(active, step); + else + for (now -= active->card->toughness; now >= 0; --now) removeOne(active, step); + } + else if (ATK == cursor_pos) { - activeAtk = active; - active = blkViews.front(); + active = activeAtk->blockers.front(); active->zoom = 2.7; cursor_pos = BLK; } - return true; - case PSP_CTRL_DOWN: + else if (OK == cursor_pos) + switch (step) + { + case ORDER : go->receiveEvent(NEW WEventCombatStepChange(FIRST_STRIKE)); break; + case FIRST_STRIKE : go->receiveEvent(NEW WEventCombatStepChange(DAMAGE)); break; + case DAMAGE : cursor_pos = NONE; go->userRequestNextGamePhase(); break; + } + break; + case PSP_CTRL_TRIANGLE: if (BLK == cursor_pos) { oldActive->zoom = 2.2; @@ -92,9 +146,13 @@ bool GuiCombat::CheckUserInput(u32 key) switch (cursor_pos) { case NONE : break; - case OK : active = atkViews.back(); cursor_pos = ATK; break; - case ATK : active = closest(atkViews, NULL, active); break; - case BLK : active = closest(blkViews, NULL, active); break; + case OK : + for (vector::reverse_iterator it = attackers.rbegin(); it != attackers.rend(); ++it) if ((*it)->show) { active = *it; break; } + activeAtk = static_cast(active); + cursor_pos = ATK; + break; + case ATK : active = closest(attackers, NULL, static_cast(active)); activeAtk = static_cast(active); break; + case BLK : active = closest(activeAtk->blockers, NULL, static_cast(active)); break; } break; case PSP_CTRL_RIGHT: @@ -102,22 +160,31 @@ bool GuiCombat::CheckUserInput(u32 key) { case NONE : case OK : break; - case BLK : active = closest(blkViews, NULL, active); break; - case ATK : active = closest(atkViews, NULL, active); - if (active == oldActive) { active = NULL; cursor_pos = OK; } + case BLK : active = closest(activeAtk->blockers, NULL, static_cast(active)); break; + case ATK : active = closest(attackers, NULL, static_cast(active)); + if (active == oldActive) { active = activeAtk = NULL; cursor_pos = OK; } + else activeAtk = static_cast(active); break; } break; + case PSP_CTRL_DOWN: + if (ORDER == step || BLK != cursor_pos || active->sumDamages() <= 0) break; + removeOne(active, step); + break; + case PSP_CTRL_UP: + if (ORDER == step || BLK != cursor_pos) break; + addOne(active, step); + break; case PSP_CTRL_SQUARE: case PSP_CTRL_RTRIGGER: - active = NULL; cursor_pos = OK; + active = activeAtk = NULL; cursor_pos = OK; break; } if (oldActive != active) { - if (oldActive) oldActive->zoom = 2.2; + if (oldActive && oldActive != activeAtk) oldActive->zoom = 2.2; if (active) active->zoom = 2.7; - if (ATK == cursor_pos) generateBlkViews(active->card); + if (ATK == cursor_pos) remaskBlkViews(dynamic_cast(oldActive), static_cast(active)); } if (OK == cursor_pos) ok.zoom = 1.5; else ok.zoom = 1.0; return true; @@ -129,15 +196,19 @@ void GuiCombat::Render() JRenderer* renderer = JRenderer::GetInstance(); renderer->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(200,0,0,0)); - for (vector::iterator it = atkViews.begin(); it != atkViews.end(); ++it) - (*it)->Render(); - for (vector::iterator it = blkViews.begin(); it != blkViews.end(); ++it) - (*it)->Render(); - - if(ok_quad) - ok.Render(ok_quad); - + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->show) (*it)->Render(step); + if (activeAtk) + for (vector::iterator q = activeAtk->blockers.begin(); q != activeAtk->blockers.end(); ++q) + (*q)->Render(step); + if (ok_quad) ok.Render(ok_quad); renderer->DrawLine(0, SCREEN_HEIGHT / 2 + 10, SCREEN_WIDTH, SCREEN_HEIGHT / 2 + 10, ARGB(255, 255, 64, 0)); + if (FIRST_STRIKE == step) + { + JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); + mFont->SetColor(ARGB(255, 64, 255, 64)); + mFont->DrawString("First strike damage", 370, 2); + } } int GuiCombat::receiveEventPlus(WEvent* e) @@ -146,65 +217,133 @@ int GuiCombat::receiveEventPlus(WEvent* e) { if (NULL == event->after) return 0; cout << "Attacker : " << event->card->name << " " << event->before << " -> " << event->after << endl; - attackers.push_back(event->card); + AttackerDamaged* t = NEW AttackerDamaged(event->card, *(event->card->view), true, NULL); + attackers.push_back(t); return 1; } else if (WEventCreatureBlocker* event = dynamic_cast(e)) { cout << "Blocker : " << event->card->name << " " << event->before << " -> " << event->after << endl; - if (NULL == event->after) return 0; - return 1; + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->card == event->after) + { + DefenserDamaged* t = NEW DefenserDamaged(event->card, *(event->card->view), true, NULL); + t->y = t->actY = TOP_LINE; t->actT = t->t = 0; t->actZ = t->zoom = 2.2; + (*it)->blockers.push_back(t); + return 1; + } + return 0; } else if (WEventCreatureBlockerRank* event = dynamic_cast(e)) { cout << "Order : " << event->card->name << " -> " << event->exchangeWith->name << endl; - vector::iterator it1, it2; - for (it1 = blkViews.begin(); it1 != blkViews.end(); ++it1) if ((*it1)->card == event->card) break; if (blkViews.end() == it1) return 1; - for (it2 = blkViews.begin(); it2 != blkViews.end(); ++it2) if ((*it2)->card == event->exchangeWith) break; if (blkViews.end() == it2) return 1; - float x = (*it1)->x; - (*it1)->x = (*it2)->x; - (*it2)->x = x; + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->card == event->attacker) + { + vector::iterator it1, it2; + for (it1 = (*it)->blockers.begin(); it1 != (*it)->blockers.end(); ++it1) if ((*it1)->card == event->card) break; + if ((*it)->blockers.end() == it1) return 1; + for (it2 = (*it)->blockers.begin(); it2 != (*it)->blockers.end(); ++it2) if ((*it2)->card == event->exchangeWith) break; + if ((*it)->blockers.end() == it2) return 1; + float x = (*it1)->x; + (*it1)->x = (*it2)->x; + (*it2)->x = x; + std::iter_swap(it1, it2); + reaffectDamage(*it, DAMAGE); + } return 1; } return 0; } int GuiCombat::receiveEventMinus(WEvent* e) { - // (WEventZoneChange* event = dynamic_cast(e) if (WEventCreatureAttacker* event = dynamic_cast(e)) { if (NULL == event->before) return 0; - for (vector::iterator it = attackers.begin(); it != attackers.end(); ++it) - if (*it == event->card) + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->card == event->card) { attackers.erase(it); return 1; } return 1; } - else if (WEventBlockersAssigned* event = dynamic_cast(e)) + else if (WEventCreatureBlocker* event = dynamic_cast(e)) { - if (active) return 0; // Why do I take this event twice >.> - if (go->currentPlayer->isAI()) return 0; - unsigned size = 0; - for (vector::iterator it = attackers.begin(); it != attackers.end(); ++it) - if (1 < (*it)->blockers.size()) ++size; - if (0 == size) return 1; - float space = (SCREEN_WIDTH - 2*MARGIN) / size; - float pos = MARGIN; - for (vector::iterator it = attackers.begin(); it != attackers.end(); ++it) - if (1 < (*it)->blockers.size()) - { - TransientCardView* t = NEW TransientCardView(*it, *(*it)->view); - atkViews.push_back(t); - t->x = pos; t->y = 210; - t->zoom = 2.2; t->t = 0; - pos += space; - } - active = *atkViews.begin(); - active->zoom = 2.7; - generateBlkViews(active->card); + cout << "Blocker : " << event->card->name << " " << event->before << " -> " << event->after << endl; + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->card == event->before) + for (vector::iterator q = (*it)->blockers.begin(); q != (*it)->blockers.end(); ++q) + if ((*q)->card == event->card) + { + DefenserDamaged* d = *q; + (*it)->blockers.erase(q); + SAFE_DELETE(d); + return 1; + } + return 0; + } + else if (WEventCombatStepChange* event = dynamic_cast(e)) + switch (event->step) + { + case ORDER: + { + if (ORDER == step) return 0; // Why do I take this twice ? >.> + if (go->currentPlayer->isAI()) { go->receiveEvent(NEW WEventCombatStepChange(FIRST_STRIKE)); return 1; } + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + { + (*it)->show = (1 < (*it)->blockers.size()); + reaffectDamage(*it, DAMAGE); + } + active = NULL; + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->show) + { + (*it)->y = 210; + (*it)->zoom = 2.2; (*it)->t = 0; + if (!active) active = *it; + } + repos(attackers.begin(), attackers.end(), 0); + if (active) + { + active->zoom = 2.7; // We know there is at least one, so this cannot be NULL + activeAtk = static_cast(active); + remaskBlkViews(NULL, static_cast(active)); + cursor_pos = ATK; + step = ORDER; + } + else + go->receiveEvent(NEW WEventCombatStepChange(FIRST_STRIKE)); + return 1; + } + case FIRST_STRIKE: + for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker) + if ((*attacker)->card->has(Constants::FIRSTSTRIKE) || (*attacker)->card->has(Constants::DOUBLESTRIKE)) goto DAMAGE; + go->receiveEvent(NEW WEventCombatStepChange(DAMAGE)); + return 1; + case DAMAGE: DAMAGE: + if (go->currentPlayer->isAI()) { go->userRequestNextGamePhase(); return 1; } + step = event->step; cursor_pos = ATK; + for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker) + reaffectDamage(*attacker, step); + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + (*it)->show = ((*it)->card->has(Constants::DOUBLESTRIKE) || ((*it)->card->has(Constants::FIRSTSTRIKE) ^ (DAMAGE == step))) && (1 < (*it)->blockers.size()); + repos(attackers.begin(), attackers.end(), 0); + active = NULL; + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) if ((*it)->show) { active = *it; break; } + if (active) + { + active->zoom = 2.7; + activeAtk = static_cast(active); + remaskBlkViews(NULL, static_cast(active)); + } + else + { + if (FIRST_STRIKE == step) go->receiveEvent(NEW WEventCombatStepChange(DAMAGE)); + else go->userRequestNextGamePhase(); + } + return 1; } return 0; } diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 9cd44e0b0..efb7ce31e 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -630,3 +630,15 @@ JSample * MTGCardInstance::getSample(){ return NULL; } + +int MTGCardInstance::stepPower(CombatStep step) +{ + switch (step) + { + case FIRST_STRIKE : + if (has(Constants::FIRSTSTRIKE) || has(Constants::DOUBLESTRIKE)) return MAX(0, power); else return 0; + case DAMAGE : + if (has(Constants::FIRSTSTRIKE)) return 0; else return MAX(0, power); + default : return 0; + } +} diff --git a/projects/mtg/src/Pos.cpp b/projects/mtg/src/Pos.cpp index c8f2fd75f..45bc4c4ea 100644 --- a/projects/mtg/src/Pos.cpp +++ b/projects/mtg/src/Pos.cpp @@ -11,6 +11,10 @@ void Pos::Update(float dt) actA += 10 * dt * (alpha - actA); } +void Pos::UpdateNow() +{ + actX = x; actY = y; actT = t; actZ = zoom; actA = alpha; +} void Pos::Render(){} void Pos::Render(JQuad* quad) { diff --git a/projects/mtg/src/WEvent.cpp b/projects/mtg/src/WEvent.cpp index 9b3853fae..9b8d5daf1 100644 --- a/projects/mtg/src/WEvent.cpp +++ b/projects/mtg/src/WEvent.cpp @@ -24,4 +24,6 @@ WEventCreatureBlockerRank::WEventCreatureBlockerRank(MTGCardInstance * card, MTG WEventEngageMana::WEventEngageMana(int color, MTGCardInstance* card, ManaPool * destination) : WEvent(), color(color), card(card), destination(destination) {} WEventConsumeMana::WEventConsumeMana(int color, ManaPool * source) : WEvent(), color(color),source(source) {} -WEventEmptyManaPool::WEventEmptyManaPool(ManaPool * source):WEvent(),source(source){} +WEventEmptyManaPool::WEventEmptyManaPool(ManaPool * source) : WEvent(), source(source){} + +WEventCombatStepChange::WEventCombatStepChange(CombatStep step) : WEvent(), step(step) {};