From 6728794ce962bfa3cce71a3fc49aa7013bb2e288 Mon Sep 17 00:00:00 2001 From: "wagic.jeck" Date: Thu, 27 Aug 2009 03:17:25 +0000 Subject: [PATCH] Jeck - Quick crashfix when loading without a profiles directory, slight keypad modifications. --- projects/mtg/include/GameOptions.h | 2 +- projects/mtg/include/SimplePad.h | 2 +- projects/mtg/src/ActionStack.cpp | 1886 ++++++++++++++-------------- projects/mtg/src/GameApp.cpp | 1 - projects/mtg/src/GameOptions.cpp | 7 +- projects/mtg/src/OptionItem.cpp | 6 + projects/mtg/src/SimplePad.cpp | 716 +++++------ 7 files changed, 1315 insertions(+), 1305 deletions(-) diff --git a/projects/mtg/include/GameOptions.h b/projects/mtg/include/GameOptions.h index 2745f9cfd..81ebcdeff 100644 --- a/projects/mtg/include/GameOptions.h +++ b/projects/mtg/include/GameOptions.h @@ -101,7 +101,7 @@ public: ~GameSettings(); int save(); - SimplePad * keypadStart(string input, string * _dest = NULL, int _x = SCREEN_WIDTH/2, int _y = SCREEN_HEIGHT/2); + SimplePad * keypadStart(string input, string * _dest = NULL, bool _cancel=true, bool _numpad=false, int _x = SCREEN_WIDTH/2, int _y = SCREEN_HEIGHT/2); string keypadFinish(); void keypadShutdown(); void keypadTitle(string set); diff --git a/projects/mtg/include/SimplePad.h b/projects/mtg/include/SimplePad.h index 331a77805..052f2f18d 100644 --- a/projects/mtg/include/SimplePad.h +++ b/projects/mtg/include/SimplePad.h @@ -40,7 +40,7 @@ public: - SimplePad(bool numbers=false); + SimplePad(); ~SimplePad(); int mX; int mY; diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index bb0cde420..d54fa578e 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -1,948 +1,948 @@ -/* - The Action Stack contains all information for Game Events that can be interrupted (Interruptible) -*/ -#include "../include/config.h" -#include "../include/ActionStack.h" -#include "../include/MTGAbility.h" -#include "../include/GameObserver.h" -#include "../include/Damage.h" -#include "../include/ManaCost.h" -#include "../include/GameOptions.h" -#include "../include/TexturesCache.h" -#include "../include/TargetChooser.h" -#include "../include/CardGui.h" -#include "../include/Translate.h" - -/* - NextGamePhase requested by user -*/ - -int NextGamePhase::resolve(){ - GameObserver::GetInstance()->nextGamePhase(); - return 1; -} - -void NextGamePhase::Render(){ - int nextPhase = (GameObserver::GetInstance()->getCurrentGamePhase() + 1) % Constants::MTG_PHASE_CLEANUP; - JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); - mFont->SetBase(0); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - char buffer[200]; - int playerId = 1; - if (GameObserver::GetInstance()->currentActionPlayer == GameObserver::GetInstance()->players[1]) playerId = 2; - sprintf(buffer, "%s %i : -> %s", _("Player").c_str(), playerId, _(Constants::MTGPhaseNames[nextPhase]).c_str()); - mFont->DrawString(buffer, x + 30 , y, JGETEXT_LEFT); -} - -NextGamePhase::NextGamePhase(int id): Interruptible(id){ - mHeight = 40; - type = ACTION_NEXTGAMEPHASE; -} - -ostream& NextGamePhase::toString(ostream& out) const -{ - out << "NextGamePhase ::: "; - return out; -} - -/* Ability */ -int StackAbility::resolve(){ - return (ability->resolve()); -} -void StackAbility::Render(){ - JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); - mFont->SetBase(0); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - char buffer[200]; - sprintf(buffer, "%s", _(ability->getMenuText()).c_str()); - mFont->DrawString(buffer, x + 30 , y, JGETEXT_LEFT); - JRenderer * renderer = JRenderer::GetInstance(); - JQuad * quad = cache.getThumb(ability->source); - if (quad){ - quad->SetColor(ARGB(255,255,255,255)); - float scale = 30 / quad->mHeight; - renderer->RenderQuad(quad, x , y , 0,scale,scale); - }else{ - mFont->DrawString(_(ability->source->getName()).c_str(),x,y-15); - } - - Targetable * _target = ability->target; +/* + The Action Stack contains all information for Game Events that can be interrupted (Interruptible) +*/ +#include "../include/config.h" +#include "../include/ActionStack.h" +#include "../include/MTGAbility.h" +#include "../include/GameObserver.h" +#include "../include/Damage.h" +#include "../include/ManaCost.h" +#include "../include/GameOptions.h" +#include "../include/TexturesCache.h" +#include "../include/TargetChooser.h" +#include "../include/CardGui.h" +#include "../include/Translate.h" + +/* + NextGamePhase requested by user +*/ + +int NextGamePhase::resolve(){ + GameObserver::GetInstance()->nextGamePhase(); + return 1; +} + +void NextGamePhase::Render(){ + int nextPhase = (GameObserver::GetInstance()->getCurrentGamePhase() + 1) % Constants::MTG_PHASE_CLEANUP; + JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); + mFont->SetBase(0); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + char buffer[200]; + int playerId = 1; + if (GameObserver::GetInstance()->currentActionPlayer == GameObserver::GetInstance()->players[1]) playerId = 2; + sprintf(buffer, "%s %i : -> %s", _("Player").c_str(), playerId, _(Constants::MTGPhaseNames[nextPhase]).c_str()); + mFont->DrawString(buffer, x + 30 , y, JGETEXT_LEFT); +} + +NextGamePhase::NextGamePhase(int id): Interruptible(id){ + mHeight = 40; + type = ACTION_NEXTGAMEPHASE; +} + +ostream& NextGamePhase::toString(ostream& out) const +{ + out << "NextGamePhase ::: "; + return out; +} + +/* Ability */ +int StackAbility::resolve(){ + return (ability->resolve()); +} +void StackAbility::Render(){ + JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); + mFont->SetBase(0); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + char buffer[200]; + sprintf(buffer, "%s", _(ability->getMenuText()).c_str()); + mFont->DrawString(buffer, x + 30 , y, JGETEXT_LEFT); + JRenderer * renderer = JRenderer::GetInstance(); + JQuad * quad = cache.getThumb(ability->source); + if (quad){ + quad->SetColor(ARGB(255,255,255,255)); + float scale = 30 / quad->mHeight; + renderer->RenderQuad(quad, x , y , 0,scale,scale); + }else{ + mFont->DrawString(_(ability->source->getName()).c_str(),x,y-15); + } + + Targetable * _target = ability->target; if (ability->tc){ Targetable * t = ability->tc->getNextTarget(); if(t) _target = t; - } - Damageable * target = NULL; - if (_target!= ability->source && (_target->typeAsTarget() == TARGET_CARD || _target->typeAsTarget() == TARGET_PLAYER)){ - target = (Damageable *) _target; - } - if (target){ - quad = target->getIcon(); - if (quad){ - quad->SetColor(ARGB(255,255,255,255)); - float scale = 30 / quad->mHeight; - renderer->RenderQuad(quad, x + 150 , y , 0,scale,scale); - }else{ - if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE) - mFont->DrawString(_(((MTGCardInstance *)target)->name).c_str(),x+120,y); - } - } -} -StackAbility::StackAbility(int id,MTGAbility * _ability): Interruptible(id),ability(_ability){ - type=ACTION_ABILITY; -} - -ostream& StackAbility::toString(ostream& out) const -{ - out << "StackAbility ::: ability : " << ability; - return out; -} - -/* Spell Cast */ - -Spell::Spell(MTGCardInstance * _source): Interruptible(0){ - source = _source; - mHeight= 40; - type = ACTION_SPELL; - cost = NEW ManaCost(); - tc = NULL; -} - - -Spell::Spell(int id, MTGCardInstance * _source, TargetChooser * tc, ManaCost * _cost): Interruptible(id), tc(tc),cost(_cost){ - source = _source; - mHeight = 40; - type = ACTION_SPELL; -} - - -const string Spell::getDisplayName(){ - return source->getName(); -} - -Spell::~Spell(){ - SAFE_DELETE(cost); - SAFE_DELETE(tc); -} - -int Spell::resolve(){ - GameObserver * game = GameObserver::GetInstance(); - //TODO Remove target if it's not targettable anymore - while (source->next){ - source = source->next; - } + } + Damageable * target = NULL; + if (_target!= ability->source && (_target->typeAsTarget() == TARGET_CARD || _target->typeAsTarget() == TARGET_PLAYER)){ + target = (Damageable *) _target; + } + if (target){ + quad = target->getIcon(); + if (quad){ + quad->SetColor(ARGB(255,255,255,255)); + float scale = 30 / quad->mHeight; + renderer->RenderQuad(quad, x + 150 , y , 0,scale,scale); + }else{ + if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE) + mFont->DrawString(_(((MTGCardInstance *)target)->name).c_str(),x+120,y); + } + } +} +StackAbility::StackAbility(int id,MTGAbility * _ability): Interruptible(id),ability(_ability){ + type=ACTION_ABILITY; +} + +ostream& StackAbility::toString(ostream& out) const +{ + out << "StackAbility ::: ability : " << ability; + return out; +} + +/* Spell Cast */ + +Spell::Spell(MTGCardInstance * _source): Interruptible(0){ + source = _source; + mHeight= 40; + type = ACTION_SPELL; + cost = NEW ManaCost(); + tc = NULL; +} + + +Spell::Spell(int id, MTGCardInstance * _source, TargetChooser * tc, ManaCost * _cost): Interruptible(id), tc(tc),cost(_cost){ + source = _source; + mHeight = 40; + type = ACTION_SPELL; +} + + +const string Spell::getDisplayName(){ + return source->getName(); +} + +Spell::~Spell(){ + SAFE_DELETE(cost); + SAFE_DELETE(tc); +} + +int Spell::resolve(){ + GameObserver * game = GameObserver::GetInstance(); + //TODO Remove target if it's not targettable anymore + while (source->next){ + source = source->next; + } if (!source->hasType("instant") && !source->hasType("sorcery")){ source = source->controller()->game->putInPlay(source); - } - - - //Play SFX - if (options[Options::SFXVOLUME].number > 0){ - JSample * sample = source->getSample(); - if (sample){ - JSoundSystem::GetInstance()->PlaySample(sample); - } - } - - AbilityFactory af; - af.addAbilities(game->mLayers->actionLayer()->getMaxId(), this); - return 1; -} - -MTGCardInstance * Spell::getNextCardTarget(MTGCardInstance * previous){ - if (!tc) return NULL; - return tc->getNextCardTarget(previous); -} - Player * Spell::getNextPlayerTarget(Player * previous){ - if (!tc) return NULL; - return tc->getNextPlayerTarget(previous); -} - Damageable * Spell::getNextDamageableTarget(Damageable * previous){ - if (!tc) return NULL; - return tc->getNextDamageableTarget(previous); -} - Interruptible * Spell::getNextInterruptible(Interruptible * previous, int type){ - if (!tc) return NULL; - return tc->getNextInterruptible(previous,type); -} - Spell * Spell::getNextSpellTarget(Spell * previous){ - if (!tc) return NULL; - return tc->getNextSpellTarget(previous); -} - Damage * Spell::getNextDamageTarget(Damage * previous){ - if (!tc) return NULL; - return tc->getNextDamageTarget(previous); -} - Targetable * Spell::getNextTarget(Targetable * previous, int type ){ - if (!tc) return NULL; - return tc->getNextTarget(previous,type); -} - - int Spell::getNbTargets(){ - if (!tc) return 0; - return tc->cursor; - } - -void Spell::Render(){ - JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); - mFont->SetBase(0); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - mFont->DrawString(_(source->name).c_str(), x + 30 , y, JGETEXT_LEFT); - JRenderer * renderer = JRenderer::GetInstance(); - JQuad * quad = cache.getThumb(source); - if (quad){ - quad->SetColor(ARGB(255,255,255,255)); - float scale = mHeight / quad->mHeight; - renderer->RenderQuad(quad, x+10*scale , y+15*scale , 0,scale,scale); - }else{ - // - } - // WALDORF - added these lines to render a big card as well as the small one - // in the interrupt window. A big card will be rendered no matter whether - // the user has been using big cards or not. However, I do take into which - // kind of big card they like. - // The card will be rendered in the same place as the GuiHand - // card. It doesn't attempt to hide the GUIHand card, it - // just overwrites it. - // I stole the render code from RenderBig() in CardGUI.cpp - - quad = cache.getQuad(source); - if (quad){ - quad->SetColor(ARGB(220,255,255,255)); - float scale = 257.f / quad->mHeight; - renderer->RenderQuad(quad, 10+100*scale , 20+145*scale , 0.0f,scale,scale); - } - else - { - MTGCard * mtgcard = source->model; - // CardGui::alternateRender(mtgcard, NULL, 10 + 90 , 20 + 130, 0.0f,0.9f); - - quad = cache.getThumb(source); - if (quad){ - float scale = 250 / quad->mHeight; - quad->SetColor(ARGB(40,255,255,255)); - renderer->RenderQuad(quad, 20+15*scale, 20+20*scale, 0.0f, scale, scale); - } - } - - // WALDORF - end - - - Damageable * target = getNextDamageableTarget(); - if (target){ - quad = target->getIcon(); - if (quad){ - quad->SetColor(ARGB(255,255,255,255)); - float scale = 30 / quad->mHeight; - renderer->RenderQuad(quad, x + 150 , y , 0,scale,scale); - }else{ - if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE) - mFont->DrawString(_(((MTGCardInstance *)target)->name).c_str(),x+120,y); - } - } -} - -ostream& Spell::toString(ostream& out) const -{ - out << "Spell ::: cost : " << cost; - return out; -} - - -/* Put a card in graveyard */ - -PutInGraveyard::PutInGraveyard(int id, MTGCardInstance * _card):Interruptible(id){ - card = _card; - removeFromGame = 0; - type = ACTION_PUTINGRAVEYARD; -} - -int PutInGraveyard::resolve(){ - GameObserver * g = GameObserver::GetInstance(); - MTGGameZone * zone = card->getCurrentZone(); - if (zone == g->players[0]->game->inPlay || zone == g->players[1]->game->inPlay){ - card->owner->game->putInZone(card,zone,card->owner->game->graveyard); - return 1; - } - return 0; -} - -void PutInGraveyard::Render(){ - JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); - mFont->SetBase(0); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - if (!removeFromGame){ - mFont->DrawString(_("goes to graveyard").c_str(), x + 30 , y, JGETEXT_LEFT); - }else{ - mFont->DrawString(_("is exiled").c_str(), x + 30 , y, JGETEXT_LEFT); - } - JRenderer * renderer = JRenderer::GetInstance(); - JQuad * quad = cache.getThumb(card); - if (quad){ - quad->SetColor(ARGB(255,255,255,255)); - float scale = 30 / quad->mHeight; - renderer->RenderQuad(quad, x , y , 0,scale,scale); - }else{ - mFont->DrawString(_(card->name).c_str(),x,y-15); - } -} - -ostream& PutInGraveyard::toString(ostream& out) const -{ - out << "PutInGraveyard ::: removeFromGame : " << removeFromGame; - return out; -} - -/* Draw a Card */ -DrawAction::DrawAction(int id, Player * _player, int _nbcards):Interruptible(id), nbcards(_nbcards), player(_player){ -} - -int DrawAction::resolve(){ - for (int i = 0 ; i < nbcards ; i++){ - player->game->drawFromLibrary(); - } - return 1; -} - -void DrawAction::Render(){ - JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); - mFont->SetBase(0); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - char buffer[200]; - int playerId = 1; - if (player == GameObserver::GetInstance()->players[1]) playerId = 2; - sprintf(buffer, _("Player %i draws %i card").c_str(), playerId, nbcards); - mFont->DrawString(buffer, x + 20 , y, JGETEXT_LEFT); -} - -ostream& DrawAction::toString(ostream& out) const -{ - out << "DrawAction ::: nbcards : " << nbcards << " ; player : " << player; - return out; -} - -/* The Action Stack itself */ -int ActionStack::addPutInGraveyard(MTGCardInstance * card){ - PutInGraveyard * death = NEW PutInGraveyard(mCount,card); - addAction(death); - return 1; -} - -int ActionStack::addAbility(MTGAbility * ability){ - StackAbility * stackAbility = NEW StackAbility(mCount,ability); - int result = addAction(stackAbility); - if (!game->players[0]->isAI() && - ability->source->controller()==game->players[0] && - 0 == options[Options::INTERRUPTMYABILITIES].number) - interruptDecision[0] = DONT_INTERRUPT; - return result; -} - -int ActionStack::addDraw(Player * player, int nb_cards){ - DrawAction * draw = NEW DrawAction(mCount,player, nb_cards); - addAction(draw); - return 1; -} - -int ActionStack::addDamage(MTGCardInstance * _source, Damageable * _target, int _damage){ - Damage * damage = NEW Damage(mCount, _source, _target, _damage); - addAction(damage); - return 1; -} - -int ActionStack::AddNextGamePhase(){ - if (getNext(NULL,NOT_RESOLVED)) return 0; - NextGamePhase * next = NEW NextGamePhase(mCount); - addAction(next); - int playerId = 0; - if (game->currentActionPlayer == game->players[1]) playerId = 1; - interruptDecision[playerId] = 1; - return 1; -} - -int ActionStack::setIsInterrupting(Player * player){ - if (player == game->players[0]){ - interruptDecision[0] = -1; - }else{ - interruptDecision[1] = -1; - } - game->isInterrupting = player; - askIfWishesToInterrupt = NULL; - return 1; -} - - -int ActionStack::addAction(Interruptible * action){ - for (int i=0; i<2; i++){ - interruptDecision[i] = 0; - } - Add(action); - return 1; -} - -Spell * ActionStack::addSpell(MTGCardInstance * _source, TargetChooser * tc, ManaCost * mana){ -#if defined (WIN32) || defined (LINUX) - char buf[4096], *p = buf; - sprintf(buf, "Add spell\n"); - OutputDebugString(buf); -#endif - Spell * spell = NEW Spell(mCount,_source,tc, mana); - addAction(spell); - if (!game->players[0]->isAI() && - _source->controller()==game->players[0] && - 0 == options[Options::INTERRUPTMYSPELLS].number) - interruptDecision[0] = DONT_INTERRUPT; - return spell; -} - - -Interruptible * ActionStack::getAt(int id){ - if (id < 0) id = mCount + id; - if (id > mCount -1) return NULL; - return (Interruptible *)mObjects[id]; -} - -ActionStack::ActionStack(GameObserver* game) : game(game){ - for (int i=0; i<2; i++) - interruptDecision[i] = 0; - askIfWishesToInterrupt = NULL; - timer = -1; - currentState = -1; - mode = ACTIONSTACK_STANDARD; - checked = 0; - -} - -int ActionStack::has(MTGAbility * ability){ - for (int i = 0; i < mCount ; i++){ - if (((Interruptible *)mObjects[i])->type==ACTION_ABILITY){ - StackAbility * action = ((StackAbility *)mObjects[i]); - if (action->state == NOT_RESOLVED && action->ability == ability) return 1; - } - } - return 0; -} - -int ActionStack::has(Interruptible * action){ - for (int i = 0; i < mCount ; i++){ - if (mObjects[i] == action) return 1; - } - return 0; -} - -int ActionStack::resolve(){ - Interruptible * action = getLatest(NOT_RESOLVED); - - if (!action) - return 0; - - - if (action->resolve()){ - action->state = RESOLVED_OK; - }else{ - action->state = RESOLVED_NOK; - } - if (action->type == ACTION_DAMAGE) ((Damage * )action)->target->afterDamage(); - if (action->type == ACTION_DAMAGES){ - DamageStack * ds = (DamageStack *) action; - for (int i = 0; i < ds->mCount; i++){ - Damage * damage = ((Damage *) ds->mObjects[i]); - damage->state = ds->state; - } - unpackDamageStack(ds); - ds->mCount = 0; - } - - if (!getNext(NULL,NOT_RESOLVED)){ - for (int i = 0; i< 2 ; i++){ - interruptDecision[i] = 0; - } - }else{ - for (int i = 0; i< 2 ; i++){ - if (interruptDecision[i] != 2) interruptDecision[i] = 0; - } - } - - return 1; - -} - -Interruptible * ActionStack::getPrevious(Interruptible * next, int type, int state, int display){ - int n = getPreviousIndex( next, type, state, display); - if (n==-1) return NULL; - return ((Interruptible *) mObjects[n]); -} - -int ActionStack::getPreviousIndex(Interruptible * next, int type, int state, int display){ - int found = 0; - if (!next) found = 1; - for (int i = mCount -1; i >= 0 ; i--){ - Interruptible * current = (Interruptible *)mObjects[i]; - if (found && (type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){ - return i; - } - if (current == next) found = 1; - } - if (!found) return getPreviousIndex(NULL,type, state, display); - return -1; -} - -int ActionStack::count( int type, int state, int display){ - int result = 0; - for (int i = 0; i < mCount ; i++){ - Interruptible * current = (Interruptible *)mObjects[i]; - if((type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){ - result++; - } - } - return result; -} - -Interruptible * ActionStack::getNext(Interruptible * previous, int type, int state, int display){ - int n = getNextIndex( previous, type, state, display); - if (n==-1) return NULL; - return ((Interruptible *) mObjects[n]); -} - -int ActionStack::getNextIndex(Interruptible * previous, int type, int state, int display){ - int found = 0; - if (!previous) found = 1; - for (int i = 0; i < mCount ; i++){ - Interruptible * current = (Interruptible *)mObjects[i]; - if (found && (type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){ - return i; - } - if (current == previous) found = 1; - } - if (!found) return getNextIndex(NULL,type, state, display); - return -1; -} - - -Interruptible * ActionStack::getLatest(int state){ - for (int i = mCount-1; i >=0; i--){ - Interruptible * action = ((Interruptible *)mObjects[i]); - if (action->state == state) return action; - } - return NULL; -} - -void ActionStack::unpackDamageStack(DamageStack * ds){ - for (int j = 0; j < ds->mCount; j++){ - Damage * damage = ((Damage *)ds->mObjects[j]); - Add(damage); - } -} - -void ActionStack::unpackDamageStacks(){ - for (int i = mCount-1; i >=0; i--){ - Interruptible * action = ((Interruptible *)mObjects[i]); - if (action->type == ACTION_DAMAGES){ - DamageStack * ds = (DamageStack *) action; - unpackDamageStack(ds); - } - } -} - -void ActionStack::repackDamageStacks(){ - std::vector::iterator iter = mObjects.begin() ; - - while( iter != mObjects.end() ){ - Interruptible * action = ((Interruptible *) *iter); - int found = 0; - if (action->type == ACTION_DAMAGE){ - Damage * damage = (Damage *) action; - for (int j = 0; j < mCount; j++){ - Interruptible * action2 = ((Interruptible *)mObjects[j]); - if (action2->type == ACTION_DAMAGES){ - DamageStack * ds = (DamageStack *) action2; - for (int k = 0; k< ds->mCount; k++){ - Damage * dsdamage = ((Damage *)ds->mObjects[k]); - if (dsdamage==damage){ - //Remove(damage); - iter = mObjects.erase( iter ) ; - found = 1; - mCount--; - } - } - } - } - } - if (!found) ++iter; - } -} - -void ActionStack::Update(float dt){ - askIfWishesToInterrupt = NULL; - //modal = 0; - GameObserver * game = GameObserver::GetInstance(); - TargetChooser * tc = game->getCurrentTargetChooser(); - int newState = game->getCurrentGamePhase(); - currentState = newState; - if (!tc) checked = 0; - - //Select Stack's display mode - if (mode==ACTIONSTACK_STANDARD && tc && !checked){ - checked = 1; - unpackDamageStacks(); - for (int i = 0; i < mCount ; i++){ - Interruptible * current = (Interruptible *)mObjects[i]; - if (tc->canTarget(current)){ - if (mObjects[mCurr]) mObjects[mCurr]->Leaving(PSP_CTRL_UP); - current->display = 1; - mCurr = i; - mObjects[mCurr]->Entering(); - mode=ACTIONSTACK_TARGET; - modal = 1; - }else{ - current->display = 0; - } - } - if (mode != ACTIONSTACK_TARGET){ - repackDamageStacks(); - } - }else if (mode==ACTIONSTACK_TARGET && !tc){ - mode = ACTIONSTACK_STANDARD; - checked = 0; - repackDamageStacks(); - } - - if (mode == ACTIONSTACK_STANDARD){ - modal = 0; - if (getLatest(NOT_RESOLVED)){ - int currentPlayerId = 0; - int otherPlayerId = 1; - if (game->currentlyActing() != game->players[0]){ - currentPlayerId = 1; - otherPlayerId = 0; - } - if (interruptDecision[currentPlayerId] == 0){ - askIfWishesToInterrupt = game->players[currentPlayerId]; - game->isInterrupting = game->players[currentPlayerId]; - modal = 1; - }else if (interruptDecision[currentPlayerId] == -1){ - game->isInterrupting = game->players[currentPlayerId]; - - }else{ - if (interruptDecision[otherPlayerId] == 0){ - askIfWishesToInterrupt = game->players[otherPlayerId]; - game->isInterrupting = game->players[otherPlayerId]; - modal = 1; - }else if (interruptDecision[otherPlayerId] == -1){ - game->isInterrupting = game->players[otherPlayerId]; - }else{ - resolve(); - } - } - } - }else if (mode == ACTIONSTACK_TARGET){ - GuiLayer::Update(dt); - } - if (askIfWishesToInterrupt){ - // WALDORF - added code to use a game option setting to determine how - // long the Interrupt timer should be. If it is set to zero (0), the - // game will wait for ever for the user to make a selection. - if (options[Options::INTERRUPT_SECONDS].number > 0) - { - if (timer < 0) timer = options[Options::INTERRUPT_SECONDS].number; - timer -= dt; - if (timer < 0) cancelInterruptOffer(); - } - } -} - -void ActionStack::cancelInterruptOffer(int cancelMode){ - if (game->isInterrupting == game->players[0]){ - interruptDecision[0] = cancelMode; - }else{ - interruptDecision[1] = cancelMode; - } - askIfWishesToInterrupt = NULL; - game->isInterrupting = NULL; - timer = -1; -} - -void ActionStack::endOfInterruption(){ - if (game->isInterrupting == game->players[0]){ - interruptDecision[0] = 0; - }else{ - interruptDecision[1] = 0; - } - game->isInterrupting = NULL; -} - - -bool ActionStack::CheckUserInput(u32 key){ - if (mode == ACTIONSTACK_STANDARD){ - if (askIfWishesToInterrupt){ - if (PSP_CTRL_CROSS == key){ - setIsInterrupting(askIfWishesToInterrupt); - return true; - }else if ((PSP_CTRL_CIRCLE == key) || (PSP_CTRL_RTRIGGER == key) ){ - cancelInterruptOffer(); - return true; - }else if ((PSP_CTRL_SQUARE == key)){ - cancelInterruptOffer(2); - return true; - } - return true; - }else if (game->isInterrupting){ - if (PSP_CTRL_CROSS == key){ - endOfInterruption(); - return true; - } - } - }else if (mode == ACTIONSTACK_TARGET){ - if (modal){ - if (PSP_CTRL_UP == key){ - if( mObjects[mCurr]){ - int n = getPreviousIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1); - if (n != -1 && n != mCurr && mObjects[mCurr]->Leaving(PSP_CTRL_UP)){ - mCurr = n; - mObjects[mCurr]->Entering(); -#if defined (WIN32) || defined (LINUX) - char buf[4096]; - sprintf(buf, "Stack UP TO mCurr = %i\n", mCurr); - OutputDebugString(buf); -#endif - } - } - return true; - }else if (PSP_CTRL_DOWN == key){ - if( mObjects[mCurr]){ - int n = getNextIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1); - if (n!= -1 && n != mCurr && mObjects[mCurr]->Leaving(PSP_CTRL_DOWN)){ - mCurr = n; - mObjects[mCurr]->Entering(); -#if defined (WIN32) || defined (LINUX) - char buf[4096]; - sprintf(buf, "Stack DOWN TO mCurr = %i\n", mCurr); - OutputDebugString(buf); -#endif - } - } - return true; - }else if (PSP_CTRL_CIRCLE == key){ -#if defined (WIN32) || defined (LINUX) - char buf[4096]; - sprintf(buf, "Stack CLIKED mCurr = %i\n", mCurr); - OutputDebugString(buf); -#endif - game->stackObjectClicked(((Interruptible *) mObjects[mCurr])); - return true; - } - return true; //Steal the input to other layers if we're visible - } - if (PSP_CTRL_TRIANGLE == key){ - if (modal) modal = 0; else modal = 1; - return true; - } - } - return false; -} - - - - -int ActionStack::CombatDamages(){ - CombatDamages(1); - CombatDamages(0); - return 1; -} - -int ActionStack::CombatDamages(int strike){ - DamageStack * damages = NEW DamageStack(game); - int damageitems = damages->CombatDamages(strike); - if (damageitems) - addAction(damages); - else - SAFE_DELETE(damages); - return damageitems; -} - -//Cleans history of last turn -int ActionStack::garbageCollect(){ -std::vector::iterator iter = mObjects.begin() ; - -while( iter != mObjects.end() ){ - Interruptible * current = ((Interruptible *) *iter); - if (current->state != NOT_RESOLVED){ - iter = mObjects.erase( iter ) ; - mCount--; - SAFE_DELETE(current); - } else - ++iter; -} - return 1; -} - -void ActionStack::Fizzle(Interruptible * action){ - if (!action){ - OutputDebugString("==ERROR==: action is NULL in ActionStack::Fizzle\n"); - return; - } - if (action->type == ACTION_SPELL){ - Spell * spell = (Spell *) action; - spell->source->controller()->game->putInGraveyard(spell->source); - } - action->state = RESOLVED_NOK; -} - -void ActionStack::Render(){ - int x0 = 250; - int y0 = 30; - int width = 200; - int height = 90; - int currenty = y0 + 5 ; - - if (mode == ACTIONSTACK_STANDARD){ - if (!askIfWishesToInterrupt || !askIfWishesToInterrupt->displayStack()) return; - - - for (int i=0;istate==NOT_RESOLVED) height += current->mHeight; - } - - JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); - mFont->SetBase(0); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - mFont->SetColor(ARGB(255,255,255,255)); - JRenderer * renderer = JRenderer::GetInstance(); - - //JQuad * back = GameApp::CommonRes->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 - 5 ,width + 2,height +2 , 10, ARGB(200,0,0,0)); - //renderer->RenderQuad(back,x0,y0,0,xScale, yScale); - renderer->DrawRoundRect(x0 - 5 ,y0 - 5 ,width + 2,height +2 , 10, ARGB(255,255,255,255)); - - - for (int i=0;istate==NOT_RESOLVED){ - current->x = x0 + 5; - if (i != mCount -1){ - current->y = currenty; - currenty += current->mHeight; - }else{ - current->y = currenty + 40 ; - currenty += current->mHeight + 40; - } - current->Render(); - } - } - - char buffer[200]; - // WALDORF - changed "interrupt ?" to "Interrupt?". Don't display count down - // seconds if the user disables auto progressing interrupts by setting the seconds - // value to zero in Options. - if (options[Options::INTERRUPT_SECONDS].number == 0) - sprintf(buffer, _("Interrupt?").c_str()); - else - sprintf(buffer, "%s %i", _("Interrupt?").c_str(),static_cast(timer)); - - //WALDORF - removed all the unnecessary math. just display the prompt at the - // top of the box. - mFont->DrawString(buffer, x0 + 5, y0); - - - if (mCount > 1) sprintf(buffer, _("X Interrupt - 0 No - [] No to All").c_str()); - else sprintf(buffer, _("X Interrupt - 0 No").c_str()); - - // WALDORF - puts the button legend right under the prompt. the stack - // will be displayed below it now. no more need to do wierd currY math. - mFont->DrawString(buffer, x0 + 5, y0 + 14); - }else if (mode == ACTIONSTACK_TARGET && modal){ - for (int i=0;idisplay) height += current->mHeight; - } - - JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); - mFont->SetBase(0); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - - JRenderer * renderer = JRenderer::GetInstance(); - renderer->FillRect(x0 ,y0 , width ,height , ARGB(200,0,0,0)); - renderer->DrawRect(x0 - 1 ,y0 - 1 ,width + 2 ,height +2 , ARGB(255,255,255,255)); - - - for (int i=0;idisplay){ - ((Interruptible *)mObjects[i])->x = x0 + 5; - if (i != mCount -1){ - ((Interruptible *)mObjects[i])->y = currenty; - currenty += ((Interruptible *)mObjects[i])->mHeight; - }else{ - ((Interruptible *)mObjects[i])->y = currenty + 40 ; - currenty += ((Interruptible *)mObjects[i])->mHeight + 40; - } - mObjects[i]->Render(); - } - } - } -} - -#if defined (WIN32) || defined (LINUX) - -void Interruptible::Dump(){ - string stype, sstate, sdisplay = ""; - switch (type){ - case ACTION_SPELL: - stype = "spell"; - break; - case ACTION_DAMAGE: - stype = "damage"; - break; - case ACTION_DAMAGES: - stype = "damages"; - break; - case ACTION_NEXTGAMEPHASE: - stype = "next phase"; - break; - case ACTION_DRAW: - stype = "draw"; - break; - case ACTION_PUTINGRAVEYARD: - stype = "put in graveyard"; - break; - case ACTION_ABILITY: - stype = "ability"; - break; - default: - stype = "unknown"; - break; - } - - switch(state){ - case NOT_RESOLVED: - sstate = "not resolved"; - break; - case RESOLVED_OK: - sstate = "resolved"; - break; - case RESOLVED_NOK: - sstate = "fizzled"; - break; - default: - sstate = "unknown"; - break; - } - - char buf[4096]; - sprintf(buf, " type %s(%i) - state %s(%i) - display %i\n", stype.c_str(), type, sstate.c_str(),state, display); - OutputDebugString(buf); -} - -void ActionStack::Dump(){ - OutputDebugString("=====\nDumping Action Stack=====\n"); - for (int i=0;iDump(); - } -} - - -#endif + } + + + //Play SFX + if (options[Options::SFXVOLUME].number > 0){ + JSample * sample = source->getSample(); + if (sample){ + JSoundSystem::GetInstance()->PlaySample(sample); + } + } + + AbilityFactory af; + af.addAbilities(game->mLayers->actionLayer()->getMaxId(), this); + return 1; +} + +MTGCardInstance * Spell::getNextCardTarget(MTGCardInstance * previous){ + if (!tc) return NULL; + return tc->getNextCardTarget(previous); +} + Player * Spell::getNextPlayerTarget(Player * previous){ + if (!tc) return NULL; + return tc->getNextPlayerTarget(previous); +} + Damageable * Spell::getNextDamageableTarget(Damageable * previous){ + if (!tc) return NULL; + return tc->getNextDamageableTarget(previous); +} + Interruptible * Spell::getNextInterruptible(Interruptible * previous, int type){ + if (!tc) return NULL; + return tc->getNextInterruptible(previous,type); +} + Spell * Spell::getNextSpellTarget(Spell * previous){ + if (!tc) return NULL; + return tc->getNextSpellTarget(previous); +} + Damage * Spell::getNextDamageTarget(Damage * previous){ + if (!tc) return NULL; + return tc->getNextDamageTarget(previous); +} + Targetable * Spell::getNextTarget(Targetable * previous, int type ){ + if (!tc) return NULL; + return tc->getNextTarget(previous,type); +} + + int Spell::getNbTargets(){ + if (!tc) return 0; + return tc->cursor; + } + +void Spell::Render(){ + JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); + mFont->SetBase(0); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + mFont->DrawString(_(source->name).c_str(), x + 30 , y, JGETEXT_LEFT); + JRenderer * renderer = JRenderer::GetInstance(); + JQuad * quad = cache.getThumb(source); + if (quad){ + quad->SetColor(ARGB(255,255,255,255)); + float scale = mHeight / quad->mHeight; + renderer->RenderQuad(quad, x+10*scale , y+15*scale , 0,scale,scale); + }else{ + // + } + // WALDORF - added these lines to render a big card as well as the small one + // in the interrupt window. A big card will be rendered no matter whether + // the user has been using big cards or not. However, I do take into which + // kind of big card they like. + // The card will be rendered in the same place as the GuiHand + // card. It doesn't attempt to hide the GUIHand card, it + // just overwrites it. + // I stole the render code from RenderBig() in CardGUI.cpp + + quad = cache.getQuad(source); + if (quad){ + quad->SetColor(ARGB(220,255,255,255)); + float scale = 257.f / quad->mHeight; + renderer->RenderQuad(quad, 10+100*scale , 20+145*scale , 0.0f,scale,scale); + } + else + { + MTGCard * mtgcard = source->model; + // CardGui::alternateRender(mtgcard, NULL, 10 + 90 , 20 + 130, 0.0f,0.9f); + + quad = cache.getThumb(source); + if (quad){ + float scale = 250 / quad->mHeight; + quad->SetColor(ARGB(40,255,255,255)); + renderer->RenderQuad(quad, 20+15*scale, 20+20*scale, 0.0f, scale, scale); + } + } + + // WALDORF - end + + + Damageable * target = getNextDamageableTarget(); + if (target){ + quad = target->getIcon(); + if (quad){ + quad->SetColor(ARGB(255,255,255,255)); + float scale = 30 / quad->mHeight; + renderer->RenderQuad(quad, x + 150 , y , 0,scale,scale); + }else{ + if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE) + mFont->DrawString(_(((MTGCardInstance *)target)->name).c_str(),x+120,y); + } + } +} + +ostream& Spell::toString(ostream& out) const +{ + out << "Spell ::: cost : " << cost; + return out; +} + + +/* Put a card in graveyard */ + +PutInGraveyard::PutInGraveyard(int id, MTGCardInstance * _card):Interruptible(id){ + card = _card; + removeFromGame = 0; + type = ACTION_PUTINGRAVEYARD; +} + +int PutInGraveyard::resolve(){ + GameObserver * g = GameObserver::GetInstance(); + MTGGameZone * zone = card->getCurrentZone(); + if (zone == g->players[0]->game->inPlay || zone == g->players[1]->game->inPlay){ + card->owner->game->putInZone(card,zone,card->owner->game->graveyard); + return 1; + } + return 0; +} + +void PutInGraveyard::Render(){ + JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); + mFont->SetBase(0); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + if (!removeFromGame){ + mFont->DrawString(_("goes to graveyard").c_str(), x + 30 , y, JGETEXT_LEFT); + }else{ + mFont->DrawString(_("is exiled").c_str(), x + 30 , y, JGETEXT_LEFT); + } + JRenderer * renderer = JRenderer::GetInstance(); + JQuad * quad = cache.getThumb(card); + if (quad){ + quad->SetColor(ARGB(255,255,255,255)); + float scale = 30 / quad->mHeight; + renderer->RenderQuad(quad, x , y , 0,scale,scale); + }else{ + mFont->DrawString(_(card->name).c_str(),x,y-15); + } +} + +ostream& PutInGraveyard::toString(ostream& out) const +{ + out << "PutInGraveyard ::: removeFromGame : " << removeFromGame; + return out; +} + +/* Draw a Card */ +DrawAction::DrawAction(int id, Player * _player, int _nbcards):Interruptible(id), nbcards(_nbcards), player(_player){ +} + +int DrawAction::resolve(){ + for (int i = 0 ; i < nbcards ; i++){ + player->game->drawFromLibrary(); + } + return 1; +} + +void DrawAction::Render(){ + JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); + mFont->SetBase(0); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + char buffer[200]; + int playerId = 1; + if (player == GameObserver::GetInstance()->players[1]) playerId = 2; + sprintf(buffer, _("Player %i draws %i card").c_str(), playerId, nbcards); + mFont->DrawString(buffer, x + 20 , y, JGETEXT_LEFT); +} + +ostream& DrawAction::toString(ostream& out) const +{ + out << "DrawAction ::: nbcards : " << nbcards << " ; player : " << player; + return out; +} + +/* The Action Stack itself */ +int ActionStack::addPutInGraveyard(MTGCardInstance * card){ + PutInGraveyard * death = NEW PutInGraveyard(mCount,card); + addAction(death); + return 1; +} + +int ActionStack::addAbility(MTGAbility * ability){ + StackAbility * stackAbility = NEW StackAbility(mCount,ability); + int result = addAction(stackAbility); + if (!game->players[0]->isAI() && + ability->source->controller()==game->players[0] && + 0 == options[Options::INTERRUPTMYABILITIES].number) + interruptDecision[0] = DONT_INTERRUPT; + return result; +} + +int ActionStack::addDraw(Player * player, int nb_cards){ + DrawAction * draw = NEW DrawAction(mCount,player, nb_cards); + addAction(draw); + return 1; +} + +int ActionStack::addDamage(MTGCardInstance * _source, Damageable * _target, int _damage){ + Damage * damage = NEW Damage(mCount, _source, _target, _damage); + addAction(damage); + return 1; +} + +int ActionStack::AddNextGamePhase(){ + if (getNext(NULL,NOT_RESOLVED)) return 0; + NextGamePhase * next = NEW NextGamePhase(mCount); + addAction(next); + int playerId = 0; + if (game->currentActionPlayer == game->players[1]) playerId = 1; + interruptDecision[playerId] = 1; + return 1; +} + +int ActionStack::setIsInterrupting(Player * player){ + if (player == game->players[0]){ + interruptDecision[0] = -1; + }else{ + interruptDecision[1] = -1; + } + game->isInterrupting = player; + askIfWishesToInterrupt = NULL; + return 1; +} + + +int ActionStack::addAction(Interruptible * action){ + for (int i=0; i<2; i++){ + interruptDecision[i] = 0; + } + Add(action); + return 1; +} + +Spell * ActionStack::addSpell(MTGCardInstance * _source, TargetChooser * tc, ManaCost * mana){ +#if defined (WIN32) || defined (LINUX) + char buf[4096], *p = buf; + sprintf(buf, "Add spell\n"); + OutputDebugString(buf); +#endif + Spell * spell = NEW Spell(mCount,_source,tc, mana); + addAction(spell); + if (!game->players[0]->isAI() && + _source->controller()==game->players[0] && + 0 == options[Options::INTERRUPTMYSPELLS].number) + interruptDecision[0] = DONT_INTERRUPT; + return spell; +} + + +Interruptible * ActionStack::getAt(int id){ + if (id < 0) id = mCount + id; + if (id > mCount -1) return NULL; + return (Interruptible *)mObjects[id]; +} + +ActionStack::ActionStack(GameObserver* game) : game(game){ + for (int i=0; i<2; i++) + interruptDecision[i] = 0; + askIfWishesToInterrupt = NULL; + timer = -1; + currentState = -1; + mode = ACTIONSTACK_STANDARD; + checked = 0; + +} + +int ActionStack::has(MTGAbility * ability){ + for (int i = 0; i < mCount ; i++){ + if (((Interruptible *)mObjects[i])->type==ACTION_ABILITY){ + StackAbility * action = ((StackAbility *)mObjects[i]); + if (action->state == NOT_RESOLVED && action->ability == ability) return 1; + } + } + return 0; +} + +int ActionStack::has(Interruptible * action){ + for (int i = 0; i < mCount ; i++){ + if (mObjects[i] == action) return 1; + } + return 0; +} + +int ActionStack::resolve(){ + Interruptible * action = getLatest(NOT_RESOLVED); + + if (!action) + return 0; + + + if (action->resolve()){ + action->state = RESOLVED_OK; + }else{ + action->state = RESOLVED_NOK; + } + if (action->type == ACTION_DAMAGE) ((Damage * )action)->target->afterDamage(); + if (action->type == ACTION_DAMAGES){ + DamageStack * ds = (DamageStack *) action; + for (int i = 0; i < ds->mCount; i++){ + Damage * damage = ((Damage *) ds->mObjects[i]); + damage->state = ds->state; + } + unpackDamageStack(ds); + ds->mCount = 0; + } + + if (!getNext(NULL,NOT_RESOLVED)){ + for (int i = 0; i< 2 ; i++){ + interruptDecision[i] = 0; + } + }else{ + for (int i = 0; i< 2 ; i++){ + if (interruptDecision[i] != 2) interruptDecision[i] = 0; + } + } + + return 1; + +} + +Interruptible * ActionStack::getPrevious(Interruptible * next, int type, int state, int display){ + int n = getPreviousIndex( next, type, state, display); + if (n==-1) return NULL; + return ((Interruptible *) mObjects[n]); +} + +int ActionStack::getPreviousIndex(Interruptible * next, int type, int state, int display){ + int found = 0; + if (!next) found = 1; + for (int i = mCount -1; i >= 0 ; i--){ + Interruptible * current = (Interruptible *)mObjects[i]; + if (found && (type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){ + return i; + } + if (current == next) found = 1; + } + if (!found) return getPreviousIndex(NULL,type, state, display); + return -1; +} + +int ActionStack::count( int type, int state, int display){ + int result = 0; + for (int i = 0; i < mCount ; i++){ + Interruptible * current = (Interruptible *)mObjects[i]; + if((type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){ + result++; + } + } + return result; +} + +Interruptible * ActionStack::getNext(Interruptible * previous, int type, int state, int display){ + int n = getNextIndex( previous, type, state, display); + if (n==-1) return NULL; + return ((Interruptible *) mObjects[n]); +} + +int ActionStack::getNextIndex(Interruptible * previous, int type, int state, int display){ + int found = 0; + if (!previous) found = 1; + for (int i = 0; i < mCount ; i++){ + Interruptible * current = (Interruptible *)mObjects[i]; + if (found && (type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){ + return i; + } + if (current == previous) found = 1; + } + if (!found) return getNextIndex(NULL,type, state, display); + return -1; +} + + +Interruptible * ActionStack::getLatest(int state){ + for (int i = mCount-1; i >=0; i--){ + Interruptible * action = ((Interruptible *)mObjects[i]); + if (action->state == state) return action; + } + return NULL; +} + +void ActionStack::unpackDamageStack(DamageStack * ds){ + for (int j = 0; j < ds->mCount; j++){ + Damage * damage = ((Damage *)ds->mObjects[j]); + Add(damage); + } +} + +void ActionStack::unpackDamageStacks(){ + for (int i = mCount-1; i >=0; i--){ + Interruptible * action = ((Interruptible *)mObjects[i]); + if (action->type == ACTION_DAMAGES){ + DamageStack * ds = (DamageStack *) action; + unpackDamageStack(ds); + } + } +} + +void ActionStack::repackDamageStacks(){ + std::vector::iterator iter = mObjects.begin() ; + + while( iter != mObjects.end() ){ + Interruptible * action = ((Interruptible *) *iter); + int found = 0; + if (action->type == ACTION_DAMAGE){ + Damage * damage = (Damage *) action; + for (int j = 0; j < mCount; j++){ + Interruptible * action2 = ((Interruptible *)mObjects[j]); + if (action2->type == ACTION_DAMAGES){ + DamageStack * ds = (DamageStack *) action2; + for (int k = 0; k< ds->mCount; k++){ + Damage * dsdamage = ((Damage *)ds->mObjects[k]); + if (dsdamage==damage){ + //Remove(damage); + iter = mObjects.erase( iter ) ; + found = 1; + mCount--; + } + } + } + } + } + if (!found) ++iter; + } +} + +void ActionStack::Update(float dt){ + askIfWishesToInterrupt = NULL; + //modal = 0; + GameObserver * game = GameObserver::GetInstance(); + TargetChooser * tc = game->getCurrentTargetChooser(); + int newState = game->getCurrentGamePhase(); + currentState = newState; + if (!tc) checked = 0; + + //Select Stack's display mode + if (mode==ACTIONSTACK_STANDARD && tc && !checked){ + checked = 1; + unpackDamageStacks(); + for (int i = 0; i < mCount ; i++){ + Interruptible * current = (Interruptible *)mObjects[i]; + if (tc->canTarget(current)){ + if (mObjects[mCurr]) mObjects[mCurr]->Leaving(PSP_CTRL_UP); + current->display = 1; + mCurr = i; + mObjects[mCurr]->Entering(); + mode=ACTIONSTACK_TARGET; + modal = 1; + }else{ + current->display = 0; + } + } + if (mode != ACTIONSTACK_TARGET){ + repackDamageStacks(); + } + }else if (mode==ACTIONSTACK_TARGET && !tc){ + mode = ACTIONSTACK_STANDARD; + checked = 0; + repackDamageStacks(); + } + + if (mode == ACTIONSTACK_STANDARD){ + modal = 0; + if (getLatest(NOT_RESOLVED)){ + int currentPlayerId = 0; + int otherPlayerId = 1; + if (game->currentlyActing() != game->players[0]){ + currentPlayerId = 1; + otherPlayerId = 0; + } + if (interruptDecision[currentPlayerId] == 0){ + askIfWishesToInterrupt = game->players[currentPlayerId]; + game->isInterrupting = game->players[currentPlayerId]; + modal = 1; + }else if (interruptDecision[currentPlayerId] == -1){ + game->isInterrupting = game->players[currentPlayerId]; + + }else{ + if (interruptDecision[otherPlayerId] == 0){ + askIfWishesToInterrupt = game->players[otherPlayerId]; + game->isInterrupting = game->players[otherPlayerId]; + modal = 1; + }else if (interruptDecision[otherPlayerId] == -1){ + game->isInterrupting = game->players[otherPlayerId]; + }else{ + resolve(); + } + } + } + }else if (mode == ACTIONSTACK_TARGET){ + GuiLayer::Update(dt); + } + if (askIfWishesToInterrupt){ + // WALDORF - added code to use a game option setting to determine how + // long the Interrupt timer should be. If it is set to zero (0), the + // game will wait for ever for the user to make a selection. + if (options[Options::INTERRUPT_SECONDS].number > 0) + { + if (timer < 0) timer = options[Options::INTERRUPT_SECONDS].number; + timer -= dt; + if (timer < 0) cancelInterruptOffer(); + } + } +} + +void ActionStack::cancelInterruptOffer(int cancelMode){ + if (game->isInterrupting == game->players[0]){ + interruptDecision[0] = cancelMode; + }else{ + interruptDecision[1] = cancelMode; + } + askIfWishesToInterrupt = NULL; + game->isInterrupting = NULL; + timer = -1; +} + +void ActionStack::endOfInterruption(){ + if (game->isInterrupting == game->players[0]){ + interruptDecision[0] = 0; + }else{ + interruptDecision[1] = 0; + } + game->isInterrupting = NULL; +} + + +bool ActionStack::CheckUserInput(u32 key){ + if (mode == ACTIONSTACK_STANDARD){ + if (askIfWishesToInterrupt){ + if (PSP_CTRL_CROSS == key){ + setIsInterrupting(askIfWishesToInterrupt); + return true; + }else if ((PSP_CTRL_CIRCLE == key) || (PSP_CTRL_RTRIGGER == key) ){ + cancelInterruptOffer(); + return true; + }else if ((PSP_CTRL_SQUARE == key)){ + cancelInterruptOffer(2); + return true; + } + return true; + }else if (game->isInterrupting){ + if (PSP_CTRL_CROSS == key){ + endOfInterruption(); + return true; + } + } + }else if (mode == ACTIONSTACK_TARGET){ + if (modal){ + if (PSP_CTRL_UP == key){ + if( mObjects[mCurr]){ + int n = getPreviousIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1); + if (n != -1 && n != mCurr && mObjects[mCurr]->Leaving(PSP_CTRL_UP)){ + mCurr = n; + mObjects[mCurr]->Entering(); +#if defined (WIN32) || defined (LINUX) + char buf[4096]; + sprintf(buf, "Stack UP TO mCurr = %i\n", mCurr); + OutputDebugString(buf); +#endif + } + } + return true; + }else if (PSP_CTRL_DOWN == key){ + if( mObjects[mCurr]){ + int n = getNextIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1); + if (n!= -1 && n != mCurr && mObjects[mCurr]->Leaving(PSP_CTRL_DOWN)){ + mCurr = n; + mObjects[mCurr]->Entering(); +#if defined (WIN32) || defined (LINUX) + char buf[4096]; + sprintf(buf, "Stack DOWN TO mCurr = %i\n", mCurr); + OutputDebugString(buf); +#endif + } + } + return true; + }else if (PSP_CTRL_CIRCLE == key){ +#if defined (WIN32) || defined (LINUX) + char buf[4096]; + sprintf(buf, "Stack CLIKED mCurr = %i\n", mCurr); + OutputDebugString(buf); +#endif + game->stackObjectClicked(((Interruptible *) mObjects[mCurr])); + return true; + } + return true; //Steal the input to other layers if we're visible + } + if (PSP_CTRL_TRIANGLE == key){ + if (modal) modal = 0; else modal = 1; + return true; + } + } + return false; +} + + + + +int ActionStack::CombatDamages(){ + CombatDamages(1); + CombatDamages(0); + return 1; +} + +int ActionStack::CombatDamages(int strike){ + DamageStack * damages = NEW DamageStack(game); + int damageitems = damages->CombatDamages(strike); + if (damageitems) + addAction(damages); + else + SAFE_DELETE(damages); + return damageitems; +} + +//Cleans history of last turn +int ActionStack::garbageCollect(){ +std::vector::iterator iter = mObjects.begin() ; + +while( iter != mObjects.end() ){ + Interruptible * current = ((Interruptible *) *iter); + if (current->state != NOT_RESOLVED){ + iter = mObjects.erase( iter ) ; + mCount--; + SAFE_DELETE(current); + } else + ++iter; +} + return 1; +} + +void ActionStack::Fizzle(Interruptible * action){ + if (!action){ + OutputDebugString("==ERROR==: action is NULL in ActionStack::Fizzle\n"); + return; + } + if (action->type == ACTION_SPELL){ + Spell * spell = (Spell *) action; + spell->source->controller()->game->putInGraveyard(spell->source); + } + action->state = RESOLVED_NOK; +} + +void ActionStack::Render(){ + int x0 = 250; + int y0 = 30; + int width = 200; + int height = 90; + int currenty = y0 + 5 ; + + if (mode == ACTIONSTACK_STANDARD){ + if (!askIfWishesToInterrupt || !askIfWishesToInterrupt->displayStack()) return; + + + for (int i=0;istate==NOT_RESOLVED) height += current->mHeight; + } + + JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); + mFont->SetBase(0); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + mFont->SetColor(ARGB(255,255,255,255)); + JRenderer * renderer = JRenderer::GetInstance(); + + //JQuad * back = GameApp::CommonRes->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 - 5 ,width + 2,height +2 , 10, ARGB(200,0,0,0)); + //renderer->RenderQuad(back,x0,y0,0,xScale, yScale); + renderer->DrawRoundRect(x0 - 5 ,y0 - 5 ,width + 2,height +2 , 10, ARGB(255,255,255,255)); + + + for (int i=0;istate==NOT_RESOLVED){ + current->x = x0 + 5; + if (i != mCount -1){ + current->y = currenty; + currenty += current->mHeight; + }else{ + current->y = currenty + 40 ; + currenty += current->mHeight + 40; + } + current->Render(); + } + } + + char buffer[200]; + // WALDORF - changed "interrupt ?" to "Interrupt?". Don't display count down + // seconds if the user disables auto progressing interrupts by setting the seconds + // value to zero in Options. + if (options[Options::INTERRUPT_SECONDS].number == 0) + sprintf(buffer, _("Interrupt?").c_str()); + else + sprintf(buffer, "%s %i", _("Interrupt?").c_str(),static_cast(timer)); + + //WALDORF - removed all the unnecessary math. just display the prompt at the + // top of the box. + mFont->DrawString(buffer, x0 + 5, y0); + + + if (mCount > 1) sprintf(buffer, _("X Interrupt - 0 No - [] No to All").c_str()); + else sprintf(buffer, _("X Interrupt - 0 No").c_str()); + + // WALDORF - puts the button legend right under the prompt. the stack + // will be displayed below it now. no more need to do wierd currY math. + mFont->DrawString(buffer, x0 + 5, y0 + 14); + }else if (mode == ACTIONSTACK_TARGET && modal){ + for (int i=0;idisplay) height += current->mHeight; + } + + JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); + mFont->SetBase(0); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + + JRenderer * renderer = JRenderer::GetInstance(); + renderer->FillRect(x0 ,y0 , width ,height , ARGB(200,0,0,0)); + renderer->DrawRect(x0 - 1 ,y0 - 1 ,width + 2 ,height +2 , ARGB(255,255,255,255)); + + + for (int i=0;idisplay){ + ((Interruptible *)mObjects[i])->x = x0 + 5; + if (i != mCount -1){ + ((Interruptible *)mObjects[i])->y = currenty; + currenty += ((Interruptible *)mObjects[i])->mHeight; + }else{ + ((Interruptible *)mObjects[i])->y = currenty + 40 ; + currenty += ((Interruptible *)mObjects[i])->mHeight + 40; + } + mObjects[i]->Render(); + } + } + } +} + +#if defined (WIN32) || defined (LINUX) + +void Interruptible::Dump(){ + string stype, sstate, sdisplay = ""; + switch (type){ + case ACTION_SPELL: + stype = "spell"; + break; + case ACTION_DAMAGE: + stype = "damage"; + break; + case ACTION_DAMAGES: + stype = "damages"; + break; + case ACTION_NEXTGAMEPHASE: + stype = "next phase"; + break; + case ACTION_DRAW: + stype = "draw"; + break; + case ACTION_PUTINGRAVEYARD: + stype = "put in graveyard"; + break; + case ACTION_ABILITY: + stype = "ability"; + break; + default: + stype = "unknown"; + break; + } + + switch(state){ + case NOT_RESOLVED: + sstate = "not resolved"; + break; + case RESOLVED_OK: + sstate = "resolved"; + break; + case RESOLVED_NOK: + sstate = "fizzled"; + break; + default: + sstate = "unknown"; + break; + } + + char buf[4096]; + sprintf(buf, " type %s(%i) - state %s(%i) - display %i\n", stype.c_str(), type, sstate.c_str(),state, display); + OutputDebugString(buf); +} + +void ActionStack::Dump(){ + OutputDebugString("=====\nDumping Action Stack=====\n"); + for (int i=0;iDump(); + } +} + + +#endif diff --git a/projects/mtg/src/GameApp.cpp b/projects/mtg/src/GameApp.cpp index 551421960..a66c78a6e 100644 --- a/projects/mtg/src/GameApp.cpp +++ b/projects/mtg/src/GameApp.cpp @@ -95,7 +95,6 @@ void GameApp::Create() manaIcons[Constants::MTG_COLOR_GREEN] = GameApp::CommonRes->GetQuad("c_green"); for (int i = sizeof(manaIcons)/sizeof(manaIcons[0]) - 1; i >= 0; --i) manaIcons[i]->SetHotSpot(16,16); - CommonRes->CreateTexture("sets/back.jpg"); CommonRes->CreateQuad("back", "sets/back.jpg", 0, 0, 200, 285); CommonRes->GetQuad("back")->SetHotSpot(100, 145); diff --git a/projects/mtg/src/GameOptions.cpp b/projects/mtg/src/GameOptions.cpp index d35d89910..8c08b5c30 100644 --- a/projects/mtg/src/GameOptions.cpp +++ b/projects/mtg/src/GameOptions.cpp @@ -282,6 +282,7 @@ string GameSettings::themeGraphic(string filename) { char buf[4096]; string theme = (*this)[Options::ACTIVE_THEME].str; + if(theme == "" || theme == "default"){ sprintf(buf,"graphics/%s",filename.c_str()); return buf; @@ -304,6 +305,8 @@ void GameSettings::checkProfile(){ if(profileOptions != NULL) SAFE_DELETE(profileOptions); + //Force our directories to exist. + MAKEDIR(RESPATH"/profiles"); string temp = profileFile("","",false,false); MAKEDIR(temp.c_str()); temp+="/stats"; @@ -394,9 +397,11 @@ void GameSettings::keypadTitle(string set){ if(keypad != NULL) keypad->title = set; } -SimplePad * GameSettings::keypadStart(string input, string * _dest,int _x,int _y){ +SimplePad * GameSettings::keypadStart(string input, string * _dest,bool _cancel, bool _numpad, int _x,int _y ){ if(keypad == NULL) keypad = new SimplePad(); + keypad->bShowCancel = _cancel; + keypad->bShowNumpad = _numpad; keypad->mX = _x; keypad->mY = _y; keypad->Start(input,_dest); diff --git a/projects/mtg/src/OptionItem.cpp b/projects/mtg/src/OptionItem.cpp index cb4134392..4b9f00a39 100644 --- a/projects/mtg/src/OptionItem.cpp +++ b/projects/mtg/src/OptionItem.cpp @@ -331,6 +331,9 @@ void OptionDirectory::Reload(){ char buf[4096]; mDip = opendir(root.c_str()); + if(!mDip) + return; + while ((mDit = readdir(mDip))){ if(mDit->d_name[0] != '.'){ sprintf(buf,"%s/%s",root.c_str(),mDit->d_name); @@ -356,6 +359,9 @@ OptionDirectory::OptionDirectory(string _root, string _id, string _displayValue) root = _root; mDip = opendir(root.c_str()); + if(!mDip) + return; + while ((mDit = readdir(mDip))){ if(mDit->d_name[0] != '.'){ sprintf(buf,"%s/%s",root.c_str(),mDit->d_name); diff --git a/projects/mtg/src/SimplePad.cpp b/projects/mtg/src/SimplePad.cpp index 81880ecb4..591ef4a7a 100644 --- a/projects/mtg/src/SimplePad.cpp +++ b/projects/mtg/src/SimplePad.cpp @@ -1,349 +1,349 @@ -#include "../include/config.h" -#include "../include/SimplePad.h" -#include "JTypes.h" -#include "../include/GameApp.h" -#include "../include/Translate.h" - - -#define ALPHA_COLUMNS 8 -#define ALPHA_ROWS 8 - -#define KPD_UP 0 -#define KPD_DOWN 1 -#define KPD_LEFT 2 -#define KPD_RIGHT 3 - -SimpleKey::SimpleKey( string _ds, int _id){ - displayValue = _ds; id = _id; - for(int x=0;x<4;x++) - adjacency[4] = KPD_NOWHERE; -} - -void SimplePad::linkKeys(int from, int to, int dir){ - - if(keys[from] && keys[to]){ - keys[from]->adjacency[dir] = to; - switch(dir){ - case KPD_UP: - case KPD_LEFT: - dir++; - break; - default: - dir--; - } - keys[to]->adjacency[dir] = from; - } -} - -SimplePad::SimplePad(bool numbers){ - nbitems = 0; - bActive = false; - selected = 0; - priorKey = 0; - cursor = 0; - bShowCancel = false; - bShowNumpad = false; - bCapslock = true; - char buf[2]; - buf[1] = '\0'; - SimpleKey * k; - - for(int x=0;x KPD_A) - k->adjacency[KPD_LEFT] = idx-1; - if(idx < KPD_Z) - k->adjacency[KPD_RIGHT] = idx+1; - if(idx > ALPHA_COLUMNS) - k->adjacency[KPD_UP] = idx-1-ALPHA_COLUMNS; - else - k->adjacency[KPD_UP] = KPD_INPUT; - if(idx < 25-ALPHA_COLUMNS) - k->adjacency[KPD_DOWN] = idx+1+ALPHA_COLUMNS; +#include "../include/config.h" +#include "../include/SimplePad.h" +#include "JTypes.h" +#include "../include/GameApp.h" +#include "../include/Translate.h" + + +#define ALPHA_COLUMNS 8 +#define ALPHA_ROWS 8 + +#define KPD_UP 0 +#define KPD_DOWN 1 +#define KPD_LEFT 2 +#define KPD_RIGHT 3 + +SimpleKey::SimpleKey( string _ds, int _id){ + displayValue = _ds; id = _id; + for(int x=0;x<4;x++) + adjacency[4] = KPD_NOWHERE; +} + +void SimplePad::linkKeys(int from, int to, int dir){ + + if(keys[from] && keys[to]){ + keys[from]->adjacency[dir] = to; + switch(dir){ + case KPD_UP: + case KPD_LEFT: + dir++; + break; + default: + dir--; } - - Add("Spacebar",KPD_SPACE); - - for(int x=25-ALPHA_COLUMNS;x<26;x++) - keys[x]->adjacency[KPD_DOWN] = KPD_SPACE; - - k=Add("Confirm",KPD_OK); - keys[KPD_Z]->adjacency[KPD_RIGHT] = KPD_OK; - k->adjacency[KPD_UP] = KPD_CAPS; - k->adjacency[KPD_LEFT] = KPD_Z; - k->adjacency[KPD_DOWN] = KPD_CANCEL; - - k=Add("Cancel",KPD_CANCEL); - k->adjacency[KPD_UP] = KPD_OK; - k->adjacency[KPD_LEFT] = KPD_SPACE; - - k=Add("Del",KPD_DEL); - keys[KPD_I]->adjacency[KPD_RIGHT] = KPD_DEL; - k->adjacency[KPD_UP] = KPD_9; - k->adjacency[KPD_DOWN] = KPD_CAPS; - k->adjacency[KPD_LEFT] = KPD_I; - - k=Add("Caps",KPD_CAPS); - keys[KPD_R]->adjacency[KPD_RIGHT] = KPD_CAPS; - keys[KPD_R]->adjacency[KPD_DOWN] = KPD_Z; - k->adjacency[KPD_UP] = KPD_DEL; - k->adjacency[KPD_DOWN] = KPD_OK; - k->adjacency[KPD_LEFT] = KPD_R; - - - for(int x=0;x<10;x++){ - buf[0] = '0'+x; - Add(buf,KPD_0+x); - if(x < 8) - linkKeys(KPD_0+x,KPD_A+x,KPD_DOWN); - if(x > 0) - linkKeys(KPD_0+x,KPD_0+x-1,KPD_LEFT); - } - - keys[KPD_8]->adjacency[KPD_DOWN] = KPD_DEL; - keys[KPD_9]->adjacency[KPD_DOWN] = KPD_DEL; - - keys[KPD_0]->adjacency[KPD_LEFT] = KPD_NOWHERE; - keys[KPD_A]->adjacency[KPD_LEFT] = KPD_NOWHERE; - keys[KPD_J]->adjacency[KPD_LEFT] = KPD_NOWHERE; - keys[KPD_S]->adjacency[KPD_LEFT] = KPD_NOWHERE; - -} - -SimplePad::~SimplePad() -{ - for(int x=0;x= KPD_MAX) - return NULL; - - keys[nbitems++] = NEW SimpleKey(display,id); - return keys[nbitems-1]; -} -void SimplePad::pressKey(unsigned char key){ - string input = ""; - int tCursor = cursor; - - if(isalpha(key)) { - if(bCapslock) - input += toupper(key); - else - input += key; - - if(cursor < 0 || cursor > buffer.size()) - tCursor = buffer.size(); - else - cursor++; - buffer.insert(tCursor,input); - } - else if(key == KPD_CAPS) - bCapslock = !bCapslock; - else if(key == KPD_DEL) { - if(cursor < 0 || cursor > buffer.size()) - cursor = buffer.size(); - if(cursor == buffer.size()) - buffer = buffer.substr(0,cursor-1); - else if(cursor > 0) - buffer = buffer.substr(0,cursor) + buffer.substr(cursor+1); - else - return; - - cursor--; - } - else if(key == KPD_OK) - Finish(); - else if(key == KPD_CANCEL) { - bCanceled = true; - Finish(); - } - -} -void SimplePad::MoveSelection(unsigned char moveto) -{ - if(!bShowNumpad && moveto >= KPD_0 && moveto <= KPD_9 ) - moveto = KPD_INPUT; - else if(!bShowCancel && moveto == KPD_CANCEL ) - moveto = KPD_SPACE; - - if(selected < KPD_MAX && selected >= 0) - priorKey = selected; - - if(moveto < KPD_MAX && moveto >= 0) { - selected = moveto; - } - else if(moveto == KPD_INPUT) - selected = KPD_INPUT; -} - + keys[to]->adjacency[dir] = from; + } +} + +SimplePad::SimplePad(){ + nbitems = 0; + bActive = false; + selected = 0; + priorKey = 0; + cursor = 0; + bShowCancel = false; + bShowNumpad = false; + bCapslock = true; + char buf[2]; + buf[1] = '\0'; + SimpleKey * k; + + for(int x=0;x KPD_A) + k->adjacency[KPD_LEFT] = idx-1; + if(idx < KPD_Z) + k->adjacency[KPD_RIGHT] = idx+1; + if(idx > ALPHA_COLUMNS) + k->adjacency[KPD_UP] = idx-1-ALPHA_COLUMNS; + else + k->adjacency[KPD_UP] = KPD_INPUT; + if(idx < 25-ALPHA_COLUMNS) + k->adjacency[KPD_DOWN] = idx+1+ALPHA_COLUMNS; + } + + Add("Spacebar",KPD_SPACE); + + for(int x=25-ALPHA_COLUMNS;x<26;x++) + keys[x]->adjacency[KPD_DOWN] = KPD_SPACE; + + k=Add("Confirm",KPD_OK); + keys[KPD_Z]->adjacency[KPD_RIGHT] = KPD_OK; + k->adjacency[KPD_UP] = KPD_CAPS; + k->adjacency[KPD_LEFT] = KPD_Z; + k->adjacency[KPD_DOWN] = KPD_CANCEL; + + k=Add("Cancel",KPD_CANCEL); + k->adjacency[KPD_UP] = KPD_OK; + k->adjacency[KPD_LEFT] = KPD_SPACE; + + k=Add("Del",KPD_DEL); + keys[KPD_I]->adjacency[KPD_RIGHT] = KPD_DEL; + k->adjacency[KPD_UP] = KPD_9; + k->adjacency[KPD_DOWN] = KPD_CAPS; + k->adjacency[KPD_LEFT] = KPD_I; + + k=Add("Caps",KPD_CAPS); + keys[KPD_R]->adjacency[KPD_RIGHT] = KPD_CAPS; + keys[KPD_R]->adjacency[KPD_DOWN] = KPD_Z; + k->adjacency[KPD_UP] = KPD_DEL; + k->adjacency[KPD_DOWN] = KPD_OK; + k->adjacency[KPD_LEFT] = KPD_R; + + + for(int x=0;x<10;x++){ + buf[0] = '0'+x; + Add(buf,KPD_0+x); + if(x < 8) + linkKeys(KPD_0+x,KPD_A+x,KPD_DOWN); + if(x > 0) + linkKeys(KPD_0+x,KPD_0+x-1,KPD_LEFT); + } + + keys[KPD_8]->adjacency[KPD_DOWN] = KPD_DEL; + keys[KPD_9]->adjacency[KPD_DOWN] = KPD_DEL; + + keys[KPD_0]->adjacency[KPD_LEFT] = KPD_NOWHERE; + keys[KPD_A]->adjacency[KPD_LEFT] = KPD_NOWHERE; + keys[KPD_J]->adjacency[KPD_LEFT] = KPD_NOWHERE; + keys[KPD_S]->adjacency[KPD_LEFT] = KPD_NOWHERE; + +} + +SimplePad::~SimplePad() +{ + for(int x=0;x= KPD_MAX) + return NULL; + + keys[nbitems++] = NEW SimpleKey(display,id); + return keys[nbitems-1]; +} +void SimplePad::pressKey(unsigned char key){ + string input = ""; + int tCursor = cursor; + + if(isalpha(key)) { + if(bCapslock) + input += toupper(key); + else + input += key; + + if(cursor < 0 || cursor > buffer.size()) + tCursor = buffer.size(); + else + cursor++; + buffer.insert(tCursor,input); + } + else if(key == KPD_CAPS) + bCapslock = !bCapslock; + else if(key == KPD_DEL) { + if(cursor < 0 || cursor > buffer.size()) + cursor = buffer.size(); + if(cursor == buffer.size()) + buffer = buffer.substr(0,cursor-1); + else if(cursor > 0) + buffer = buffer.substr(0,cursor) + buffer.substr(cursor+1); + else + return; + + cursor--; + } + else if(key == KPD_OK) + Finish(); + else if(key == KPD_CANCEL) { + bCanceled = true; + Finish(); + } + +} +void SimplePad::MoveSelection(unsigned char moveto) +{ + if(!bShowNumpad && moveto >= KPD_0 && moveto <= KPD_9 ) + moveto = KPD_INPUT; + else if(!bShowCancel && moveto == KPD_CANCEL ) + moveto = KPD_SPACE; + + if(selected < KPD_MAX && selected >= 0) + priorKey = selected; + + if(moveto < KPD_MAX && moveto >= 0) { + selected = moveto; + } + else if(moveto == KPD_INPUT) + selected = KPD_INPUT; +} + void SimplePad::Update(float dt){ JGE * mEngine = JGE::GetInstance(); - - //We can always confirm! - if(mEngine->GetButtonClick(PSP_CTRL_START)) - { - if(selected != KPD_OK) - selected = KPD_OK; - else - Finish(); - return; - } - - if(selected == KPD_SPACE){ - if(bShowCancel && mEngine->GetButtonClick(PSP_CTRL_RIGHT)) - selected = KPD_CANCEL; - else if (mEngine->GetButtonClick(PSP_CTRL_LEFT)||mEngine->GetButtonClick(PSP_CTRL_RIGHT) - ||mEngine->GetButtonClick(PSP_CTRL_UP)||mEngine->GetButtonClick(PSP_CTRL_DOWN)) - selected = priorKey; - } //Moving in/from the text field. - else if(selected == KPD_INPUT){ - if (mEngine->GetButtonClick(PSP_CTRL_DOWN) ) - selected = priorKey; - if (mEngine->GetButtonClick(PSP_CTRL_LEFT) && cursor > -1){ - if(cursor > buffer.size()) - cursor = buffer.size() - 1; - else - cursor--; - } - else if (mEngine->GetButtonClick(PSP_CTRL_RIGHT)) - if(cursor < buffer.size()) - cursor++; - else - cursor = buffer.size() + 1; - } - else if(selected >= 0 && keys[selected]){ - if (mEngine->GetButtonClick(PSP_CTRL_LEFT)) - MoveSelection(keys[selected]->adjacency[KPD_LEFT]); - else if (mEngine->GetButtonClick(PSP_CTRL_RIGHT)) - MoveSelection(keys[selected]->adjacency[KPD_RIGHT]); - if (mEngine->GetButtonClick(PSP_CTRL_DOWN)) - MoveSelection(keys[selected]->adjacency[KPD_DOWN]); - else if (mEngine->GetButtonClick(PSP_CTRL_UP)) - MoveSelection(keys[selected]->adjacency[KPD_UP]); - } - - - //These bits require a valid key... - if(selected >= 0 && selected < nbitems && keys[selected]){ - if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)) - pressKey(keys[selected]->id); - } - if (mEngine->GetButtonClick(PSP_CTRL_CROSS) && buffer.size() > 0) - buffer = buffer.substr(0,buffer.size() - 1); - if (mEngine->GetButtonClick(PSP_CTRL_LTRIGGER)){ - if(buffer.size() != 0 && cursor != 0) - if(cursor < 0 || cursor >= buffer.size()) - cursor = buffer.size() - 1; - else - cursor--; - } - else if (mEngine->GetButtonClick(PSP_CTRL_RTRIGGER)){ - if(cursor > -1 && cursor < buffer.size()) - cursor++; - else{ - buffer += ' '; - cursor = buffer.size(); - } - } - - mX = 50; - mY = 50; - -} + + //We can always confirm! + if(mEngine->GetButtonClick(PSP_CTRL_START)) + { + if(selected != KPD_OK) + selected = KPD_OK; + else + Finish(); + return; + } + + if(selected == KPD_SPACE){ + if(bShowCancel && mEngine->GetButtonClick(PSP_CTRL_RIGHT)) + selected = KPD_CANCEL; + else if (mEngine->GetButtonClick(PSP_CTRL_LEFT)||mEngine->GetButtonClick(PSP_CTRL_RIGHT) + ||mEngine->GetButtonClick(PSP_CTRL_UP)||mEngine->GetButtonClick(PSP_CTRL_DOWN)) + selected = priorKey; + } //Moving in/from the text field. + else if(selected == KPD_INPUT){ + if (mEngine->GetButtonClick(PSP_CTRL_DOWN) ) + selected = priorKey; + if (mEngine->GetButtonClick(PSP_CTRL_LEFT) && cursor > -1){ + if(cursor > buffer.size()) + cursor = buffer.size() - 1; + else + cursor--; + } + else if (mEngine->GetButtonClick(PSP_CTRL_RIGHT)) + if(cursor < buffer.size()) + cursor++; + else + cursor = buffer.size() + 1; + } + else if(selected >= 0 && keys[selected]){ + if (mEngine->GetButtonClick(PSP_CTRL_LEFT)) + MoveSelection(keys[selected]->adjacency[KPD_LEFT]); + else if (mEngine->GetButtonClick(PSP_CTRL_RIGHT)) + MoveSelection(keys[selected]->adjacency[KPD_RIGHT]); + if (mEngine->GetButtonClick(PSP_CTRL_DOWN)) + MoveSelection(keys[selected]->adjacency[KPD_DOWN]); + else if (mEngine->GetButtonClick(PSP_CTRL_UP)) + MoveSelection(keys[selected]->adjacency[KPD_UP]); + } + + + //These bits require a valid key... + if(selected >= 0 && selected < nbitems && keys[selected]){ + if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)) + pressKey(keys[selected]->id); + } + if (mEngine->GetButtonClick(PSP_CTRL_CROSS) && buffer.size() > 0) + buffer = buffer.substr(0,buffer.size() - 1); + if (mEngine->GetButtonClick(PSP_CTRL_LTRIGGER)){ + if(buffer.size() != 0 && cursor != 0) + if(cursor < 0 || cursor >= buffer.size()) + cursor = buffer.size() - 1; + else + cursor--; + } + else if (mEngine->GetButtonClick(PSP_CTRL_RTRIGGER)){ + if(cursor > -1 && cursor < buffer.size()) + cursor++; + else{ + buffer += ' '; + cursor = buffer.size(); + } + } + + mX = 50; + mY = 50; + +} void SimplePad::Start(string value, string * _dest) { bActive = true; bCanceled=false; buffer = value; original = buffer; - dest = _dest; + dest = _dest; cursor = buffer.size(); } -string SimplePad::Finish() { - bActive = false; - if(bCanceled){ - dest = NULL; - return original; - } - if(dest != NULL){ - dest->clear(); dest->insert(0,buffer); - dest = NULL; - } - return buffer; -} - -void SimplePad::Render(){ - //This could use some cleaning up to make margins more explicit - JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); - +string SimplePad::Finish() { + bActive = false; + if(bCanceled){ + dest = NULL; + return original; + } + if(dest != NULL){ + dest->clear(); dest->insert(0,buffer); + dest = NULL; + } + return buffer; +} + +void SimplePad::Render(){ + //This could use some cleaning up to make margins more explicit + JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); + int offX = 0, offY = 0; int kH = mFont->GetHeight(); int hSpacing = mFont->GetStringWidth("W"); int vSpacing = 0; int kW = hSpacing; - JRenderer * renderer = JRenderer::GetInstance(); - - - if(title != "") - vSpacing = kH+8; - else - vSpacing = 0; - - offY = vSpacing; - if(bShowNumpad) - offY += kH+14; - //Draw Keypad Background. - renderer->FillRoundRect(mX-kW,mY-kH,(kW+12)*11,(kH+14)*5+offY,2,options[Metrics::POPUP_MENU_FC].asColor(ARGB(180,0,0,0))); - offY = vSpacing; - //Draw text entry bubble - renderer->FillRoundRect(mX-kW/2,mY+offY,(kW+12)*9+kW/2,kH,2,options[Metrics::KEYPAD_FCH].asColor(ARGB(255,255,255,255))); - - //Draw text-entry title, if we've got one. - if(title != ""){ - mFont->DrawString(title.c_str(),mX,mY); - mY+=kH+12; - } - - //Draw cursor. - int cPos = cursor; - if(cPos > -1 && cPos < buffer.size()) - { - kW = mFont->GetStringWidth(buffer.substr(cPos,1).c_str()); - renderer->FillRoundRect(mX+mFont->GetStringWidth(buffer.substr(0,cPos).c_str()),mY+kH-4, - kW,4,2,options[Metrics::KEY_FCH].asColor(ARGB(150,150,150,0))); - } - else - { - cPos = buffer.size(); - renderer->FillRoundRect(mX+mFont->GetStringWidth(buffer.substr(0,cPos).c_str()),mY+kH-4, - kW,4,2,options[Metrics::KEY_FCH].asColor(ARGB(150,150,150,0))); - } - - mFont->SetColor(options[Metrics::KEYPAD_TC].asColor(ARGB(255,0,0,0))); - mFont->DrawString(buffer.c_str(),mX,mY); - offY += kH + 12; - - int rowLen[4]; - if(!bShowNumpad) - vSpacing -= kH + 12; - - for(int x=0;x= KPD_0 && x <= KPD_9 && !bShowNumpad)) - continue; + JRenderer * renderer = JRenderer::GetInstance(); + + + if(title != "") + vSpacing = kH+8; + else + vSpacing = 0; + + offY = vSpacing; + if(bShowNumpad) + offY += kH+14; + //Draw Keypad Background. + renderer->FillRoundRect(mX-kW,mY-kH,(kW+12)*11,(kH+14)*5+offY,2,options[Metrics::POPUP_MENU_FC].asColor(ARGB(180,0,0,0))); + offY = vSpacing; + //Draw text entry bubble + renderer->FillRoundRect(mX-kW/2,mY+offY,(kW+12)*9+kW/2,kH,2,options[Metrics::KEYPAD_FCH].asColor(ARGB(255,255,255,255))); + + //Draw text-entry title, if we've got one. + if(title != ""){ + mFont->DrawString(title.c_str(),mX,mY); + mY+=kH+12; + } + + //Draw cursor. + int cPos = cursor; + if(cPos > -1 && cPos < buffer.size()) + { + kW = mFont->GetStringWidth(buffer.substr(cPos,1).c_str()); + renderer->FillRoundRect(mX+mFont->GetStringWidth(buffer.substr(0,cPos).c_str()),mY+kH-4, + kW,4,2,options[Metrics::KEY_FCH].asColor(ARGB(150,150,150,0))); + } + else + { + cPos = buffer.size(); + renderer->FillRoundRect(mX+mFont->GetStringWidth(buffer.substr(0,cPos).c_str()),mY+kH-4, + kW,4,2,options[Metrics::KEY_FCH].asColor(ARGB(150,150,150,0))); + } + + mFont->SetColor(options[Metrics::KEYPAD_TC].asColor(ARGB(255,0,0,0))); + mFont->DrawString(buffer.c_str(),mX,mY); + offY += kH + 12; + + int rowLen[4]; + if(!bShowNumpad) + vSpacing -= kH + 12; + + for(int x=0;x= KPD_0 && x <= KPD_9 && !bShowNumpad)) + continue; switch(x){ case KPD_0: @@ -392,35 +392,35 @@ void SimplePad::Render(){ break; } - kW = mFont->GetStringWidth(keys[x]->displayValue.c_str()); - //Render a key. - if(x != selected){ + kW = mFont->GetStringWidth(keys[x]->displayValue.c_str()); + //Render a key. + if(x != selected){ renderer->FillRoundRect(mX+offX-4,mY+offY-4,kW+8,kH+4,2,options[Metrics::POPUP_MENU_FC].asColor(ARGB(180,50,50,50))); - mFont->SetColor(options[Metrics::POPUP_MENU_TCH].asColor(ARGB(255,255,255,0))); - } - else{ + mFont->SetColor(options[Metrics::POPUP_MENU_TCH].asColor(ARGB(255,255,255,0))); + } + else{ renderer->FillRoundRect(mX+offX-4,mY+offY-4,kW+8,kH+4,2,options[Metrics::POPUP_MENU_FC].asColor(ARGB(255,100,100,100))); - mFont->SetColor(options[Metrics::POPUP_MENU_TC].asColor(ARGB(255,255,255,255))); - } - - char vkey[2]; - vkey[1] = '\0'; - vkey[0] = keys[x]->id; - - - if(isalpha(vkey[0])) { - if(bCapslock) vkey[0] = toupper(vkey[0]); - mFont->DrawString(vkey,mX+offX,mY+offY); - } - else - mFont->DrawString(keys[x]->displayValue.c_str(),mX+offX,mY+offY); - offX += kW + 14; - } -} - -int SimplePad::cursorPos(){ - if(cursor < 0 || cursor > buffer.size()) - return buffer.size(); - - return cursor; + mFont->SetColor(options[Metrics::POPUP_MENU_TC].asColor(ARGB(255,255,255,255))); + } + + char vkey[2]; + vkey[1] = '\0'; + vkey[0] = keys[x]->id; + + + if(isalpha(vkey[0])) { + if(bCapslock) vkey[0] = toupper(vkey[0]); + mFont->DrawString(vkey,mX+offX,mY+offY); + } + else + mFont->DrawString(keys[x]->displayValue.c_str(),mX+offX,mY+offY); + offX += kW + 14; + } +} + +int SimplePad::cursorPos(){ + if(cursor < 0 || cursor > buffer.size()) + return buffer.size(); + + return cursor; } \ No newline at end of file