From ab33d296823917727b1b7e0a27d849ee2987e624 Mon Sep 17 00:00:00 2001 From: "wagic.the.homebrew" Date: Sat, 7 May 2011 11:58:37 +0000 Subject: [PATCH] - Fixed a bug where the AI would block its own attacking creatures (I reintroduced that bug recently when I removed a safeguard Zethfox had added a while ago) - Added a way to specify "no interrupt" in modrules.xml (I need to write a doc about this file) for a given game. This does not mean the stack does not show up (the stack is interesting to see what the opponent does), but that it only offers to continue. --- projects/mtg/include/ModRules.h | 24 ++++++++++++ projects/mtg/src/AIPlayer.cpp | 9 ++++- projects/mtg/src/ActionStack.cpp | 65 ++++++++++++++++++-------------- projects/mtg/src/ModRules.cpp | 37 +++++++++++++----- 4 files changed, 95 insertions(+), 40 deletions(-) diff --git a/projects/mtg/include/ModRules.h b/projects/mtg/include/ModRules.h index b543dc314..80be6bb44 100644 --- a/projects/mtg/include/ModRules.h +++ b/projects/mtg/include/ModRules.h @@ -1,3 +1,16 @@ +/* + * Wagic, The Homebrew ?! is licensed under the BSD license + * See LICENSE in the Folder's root + * http://wololo.net/wagic/ + */ + +/* +ModRules class describes global game rules used for a given Wagic Mod. +These rules describe some high level Game rules, +some graphical effects, what parts of the game are made accessible to the player, etc... +They are accessed through the global variable gModRules, and loaded from rules/modrules.xml +*/ + #ifndef _MODRULES_H_ #define _MODRULES_H_ @@ -70,6 +83,16 @@ public: ~ModRulesMenu(); }; +class ModRulesGame +{ +public: + bool mCanInterrupt; +public: + bool canInterrupt() {return mCanInterrupt;}; + ModRulesGame(); + void parse(TiXmlElement* element); +}; + class ModRulesGeneral { protected: @@ -98,6 +121,7 @@ public: ModRulesGeneral general; ModRulesCards cards; ModRulesMenu menu; + ModRulesGame game; bool load(string filename); static int getValueAsInt(TiXmlElement* element, string childName); diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index e0d41af7a..4b677d320 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -882,8 +882,7 @@ int AIPlayer::interruptIfICan() if (!clickstream.empty()) g->mLayers->stackLayer()->cancelInterruptOffer(); else - g->mLayers->stackLayer()->setIsInterrupting(this); - return 1; + return g->mLayers->stackLayer()->setIsInterrupting(this); } return 0; } @@ -1131,8 +1130,14 @@ int AIPlayer::canFirstStrikeKill(MTGCardInstance * card, MTGCardInstance *ennemy int AIPlayer::chooseBlockers() { GameObserver * g = GameObserver::GetInstance(); + + //Should not block during my own turn... + if (g->currentPlayer == this) + return 0; + //Should not run this if I'm not the player with priority if (g->currentActionPlayer != this) return 0; + //I am interrupting, why would I be choosing blockers now? if(g->isInterrupting == this) return 0; //ai should not be allowed to run this if it is not legally allowed to do so diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index 07942810a..1589b58c1 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -14,6 +14,7 @@ The Action Stack contains all information for Game Events that can be interrupte #include "TargetChooser.h" #include "Translate.h" #include "WResourceManager.h" +#include "ModRules.h" #include @@ -573,10 +574,17 @@ int ActionStack::AddNextCombatStep() int ActionStack::setIsInterrupting(Player * player) { + askIfWishesToInterrupt = NULL; + + if (!gModRules.game.canInterrupt()) + { + cancelInterruptOffer(); + return 0; + } + int playerId = (player == game->players[1]) ? 1 : 0; interruptDecision[playerId] = -1; game->isInterrupting = player; - askIfWishesToInterrupt = NULL; return 1; } @@ -634,12 +642,6 @@ ActionStack::ActionStack(GameObserver* game) pspIcons[i] = WResourceManager::Instance()->RetrieveQuad("iconspsp.png", (float) i * 32, 0, 32, 32, stream.str(), RETRIEVE_MANAGE); pspIcons[i]->SetHotSpot(16, 16); } - - // fix for translation. - kInterruptMessageString = _(kInterruptMessageString); - kInterruptString = _(kInterruptString); - kNoString = _(kNoString); - kNoToAllString = _(kNoToAllString); } int ActionStack::has(MTGAbility * ability) @@ -961,7 +963,7 @@ bool ActionStack::CheckUserInput(JButton key) { if (askIfWishesToInterrupt) { - if (JGE_BTN_SEC == key) + if (JGE_BTN_SEC == key && gModRules.game.canInterrupt()) { setIsInterrupting(askIfWishesToInterrupt); return true; @@ -1100,12 +1102,8 @@ void ActionStack::Render() mFont->SetColor(ARGB(255,255,255,255)); JRenderer * renderer = JRenderer::GetInstance(); - //JQuad * back = WResourceManager::Instance()->GetQuad("interrupt"); - //float xScale = width / back->mWidth; - //float yScale = height / back->mHeight; renderer->FillRoundRect(x0 + 16, y0 + 16, width + 2, height + 2, 10, ARGB(128,0,0,0)); renderer->FillRoundRect(x0 - 5, y0, width + 2, height + 2, 10, ARGB(200,0,0,0)); - //renderer->RenderQuad(back,x0,y0,0,xScale, yScale); renderer->DrawRoundRect(x0 - 5, y0, width + 2, height + 2, 10, ARGB(255,255,255,255)); std::ostringstream stream; @@ -1116,31 +1114,40 @@ void ActionStack::Render() // Mootpoint 01/12/2011: draw the interrupt text first, at the top. Offset the rest of the // unresolved stack effects down so that they don't collide with the interrupt text. if (options[Options::INTERRUPT_SECONDS].number == 0) - stream << kInterruptMessageString; + stream << _(kInterruptMessageString); else - stream << kInterruptMessageString << " " << static_cast(timer); + stream << _(kInterruptMessageString) << " " << static_cast(timer); mFont->DrawString(stream.str(), x0 + 5, currenty); static const float kIconVerticalOffset = 24; - if (mCount > 1) + static const float kIconHorizontalOffset = 9; + static const float kBeforeIconSpace = 10; + + //Render "interrupt?" text + possible actions { - renderer->RenderQuad(pspIcons[7].get(), x0 + 10, kIconVerticalOffset, 0, kGamepadIconSize, kGamepadIconSize); - mFont->DrawString(kInterruptString, x0 + 19, kIconVerticalOffset - 6); + float currentx = x0 + 10; + + if (gModRules.game.canInterrupt()) + { + renderer->RenderQuad(pspIcons[7].get(), currentx, kIconVerticalOffset, 0, kGamepadIconSize, kGamepadIconSize); + currentx+= kIconHorizontalOffset; + mFont->DrawString(_(kInterruptString), currentx, kIconVerticalOffset - 6); + currentx+= mFont->GetStringWidth(_(kInterruptString).c_str()) + kBeforeIconSpace; + } - renderer->RenderQuad(pspIcons[4].get(), x0 + 97, kIconVerticalOffset, 0, kGamepadIconSize, kGamepadIconSize); - mFont->DrawString(kNoString, x0 + 106, kIconVerticalOffset - 6); + renderer->RenderQuad(pspIcons[4].get(), currentx, kIconVerticalOffset, 0, kGamepadIconSize, kGamepadIconSize); + currentx+= kIconHorizontalOffset; + mFont->DrawString(_(kNoString), currentx, kIconVerticalOffset - 6); + currentx+= mFont->GetStringWidth(_(kNoString).c_str()) + kBeforeIconSpace; - renderer->RenderQuad(pspIcons[6].get(), x0 + 145, kIconVerticalOffset, 0, kGamepadIconSize, kGamepadIconSize); - mFont->DrawString(kNoToAllString, x0 + 154, kIconVerticalOffset - 6); - } - else - { - renderer->RenderQuad(pspIcons[7].get(), x0 + 40, kIconVerticalOffset, 0, kGamepadIconSize, kGamepadIconSize); - mFont->DrawString(kInterruptString, x0 + 49, kIconVerticalOffset - 6); - - renderer->RenderQuad(pspIcons[4].get(), x0 + 140, kIconVerticalOffset - 6, 0, kGamepadIconSize, kGamepadIconSize); - mFont->DrawString(kNoString, x0 + 146, kIconVerticalOffset - 6); + if (mCount > 1) + { + renderer->RenderQuad(pspIcons[6].get(), currentx, kIconVerticalOffset, 0, kGamepadIconSize, kGamepadIconSize); + currentx+= kIconHorizontalOffset; + mFont->DrawString(_(kNoToAllString), currentx, kIconVerticalOffset - 6); + currentx+= mFont->GetStringWidth(_(kNoToAllString).c_str()) + kBeforeIconSpace; + } } currenty += kIconVerticalOffset + kSpacer; diff --git a/projects/mtg/src/ModRules.cpp b/projects/mtg/src/ModRules.cpp index acf57f1cf..9309cd744 100644 --- a/projects/mtg/src/ModRules.cpp +++ b/projects/mtg/src/ModRules.cpp @@ -46,6 +46,10 @@ bool ModRules::load(string filename) { cards.parse(element); } + else if (strcmp(element->Value(), "game") == 0) + { + game.parse(element); + } } } return true; @@ -174,21 +178,27 @@ ModRulesMenu::~ModRulesMenu() other.clear(); } +//inGame rules +ModRulesGame::ModRulesGame() +{ + mCanInterrupt = true; +} + +void ModRulesGame::parse(TiXmlElement* element) +{ + int value = ModRules::getValueAsInt(element, "canInterrupt"); + if (value != -1) + mCanInterrupt = value; +} + + +//General Rules ModRulesGeneral::ModRulesGeneral() { mHasDeckEditor = true; mHasShop = true; } -int ModRules::getValueAsInt(TiXmlElement* element, string childName){ - TiXmlNode* node = element->FirstChild(childName.c_str()); - if (node) { - const char* value = node->ToElement()->GetText(); - return atoi(value); - } - return -1; -} - void ModRulesGeneral::parse(TiXmlElement* element) { int value = ModRules::getValueAsInt(element, "hasDeckEditor"); @@ -201,6 +211,15 @@ void ModRulesGeneral::parse(TiXmlElement* element) } +int ModRules::getValueAsInt(TiXmlElement* element, string childName){ + TiXmlNode* node = element->FirstChild(childName.c_str()); + if (node) { + const char* value = node->ToElement()->GetText(); + return atoi(value); + } + return -1; +} + ModRulesCards::ModRulesCards() { activateEffect = NEW SimpleCardEffectRotate(M_PI/2); //Default activation effect