diff --git a/JGE/JGE.vcproj b/JGE/JGE.vcproj index 0560af45f..9b4298b2a 100644 --- a/JGE/JGE.vcproj +++ b/JGE/JGE.vcproj @@ -542,6 +542,10 @@ /> + + @@ -757,6 +761,10 @@ RelativePath="include\JLBFont.h" > + + diff --git a/JGE/Makefile b/JGE/Makefile index 50268a9e6..16c604f48 100644 --- a/JGE/Makefile +++ b/JGE/Makefile @@ -5,6 +5,7 @@ endif GENERIC_OBJS = src/JApp.o src/JGBKFont.o \ src/JGE.o src/JGui.o src/JLBFont.o \ + src/JLogger.o \ src/JGameObject.o src/JSpline.o src/JAnimator.o \ src/JResourceManager.o src/JFileSystem.o \ src/JNetwork.o \ diff --git a/JGE/include/JGE.h b/JGE/include/JGE.h index 0ceb8ca30..8422f0570 100644 --- a/JGE/include/JGE.h +++ b/JGE/include/JGE.h @@ -23,7 +23,6 @@ #define DEBUG_PRINT -//#define _MP3_ENABLED_ #if defined(WIN32) #include @@ -62,9 +61,6 @@ bool JGEToggleFullscreen(); #endif -//#include "JGEInit.h" - -//#include "JTypes.h" #include "Vector2D.h" diff --git a/JGE/include/JMP3.h b/JGE/include/JMP3.h index 46a9d5554..0f498da7c 100644 --- a/JGE/include/JMP3.h +++ b/JGE/include/JMP3.h @@ -33,6 +33,7 @@ protected: int m_lastDecoded; int m_playTime; int GetID3TagSize(char *fname); + static bool init_done; public: int m_paused; int m_channel; diff --git a/JGE/src/JMP3.cpp b/JGE/src/JMP3.cpp index 9ca425c4f..36d027b85 100644 --- a/JGE/src/JMP3.cpp +++ b/JGE/src/JMP3.cpp @@ -8,14 +8,17 @@ #include "../include/JAudio.h" #include "../include/JFileSystem.h" #include "../include/JMP3.h" - +#include "../include/JLogger.h" JMP3* JMP3::mInstance = NULL; +bool JMP3::init_done = false; void JMP3::init() { - loadModules(); + if (!init_done) { + init_done = loadModules(); + } } JMP3::JMP3() : @@ -27,6 +30,7 @@ JMP3::~JMP3() { } bool JMP3::loadModules() { + JLOG("loading Audio modules"); int loadAvCodec = sceUtilityLoadModule(PSP_MODULE_AV_AVCODEC); if (loadAvCodec < 0) { return false; @@ -36,11 +40,16 @@ bool JMP3::loadModules() { if (loadMp3 < 0) { return false; } - + JLOG("Audio modules loaded"); return true; } bool JMP3::fillBuffers() { + JLOG("Start JMP3::fillBuffers"); + if (!init_done) { + JLOG("JMP3::fillBuffers called but init_done is false!"); + return false; + } SceUChar8* dest; SceInt32 length; SceInt32 pos; @@ -72,6 +81,7 @@ bool JMP3::fillBuffers() { if (ret < 0) return false; + JLOG("End JMP3::fillBuffers"); return true; } int JMP3::GetID3TagSize(char *fname) @@ -105,6 +115,11 @@ int JMP3::GetID3TagSize(char *fname) } bool JMP3::load(const std::string& filename, int inBufferSize, int outBufferSize) { +JLOG("Start JMP3::load"); + if (!init_done) { + JLOG("JMP3::load called but init_done is false!"); + return false; + } m_inBufferSize = inBufferSize; //m_inBuffer = new char[m_inBufferSize]; //if (!m_inBuffer) @@ -166,10 +181,16 @@ bool JMP3::load(const std::string& filename, int inBufferSize, int outBufferSize m_numChannels = sceMp3GetMp3ChannelNum(m_mp3Handle); m_samplingRate = sceMp3GetSamplingRate(m_mp3Handle); +JLOG("End JMP3::load"); return true; } bool JMP3::unload() { +JLOG("Start JMP3::unload"); + if (!init_done) { + JLOG("JMP3::unload called but init_done is false!"); + return false; + } if (m_channel >= 0) sceAudioSRCChRelease(); @@ -182,11 +203,14 @@ bool JMP3::unload() { //delete[] m_inBuffer; //delete[] m_outBuffer; - +JLOG("End JMP3::unload"); return true; } bool JMP3::update() { + if (!init_done) { + return false; + } int retry = 8;//FIXME:magic number JMP3_update_start: @@ -238,7 +262,6 @@ bool JMP3::update() { } } - return true; } @@ -251,8 +274,14 @@ bool JMP3::pause() { } bool JMP3::setLoop(bool loop) { +JLOG("Start JMP3::setLoop"); + if (!init_done) { + JLOG("JMP3::setLoop called but init_done is false!"); + return false; + } sceMp3SetLoopNum(m_mp3Handle, (loop == true) ? -1 : 0); return (m_loop = loop); +JLOG("End JMP3::setLoop"); } int JMP3::setVolume(int volume) { diff --git a/JGE/src/main.cpp b/JGE/src/main.cpp index 995c9c369..7048d666a 100644 --- a/JGE/src/main.cpp +++ b/JGE/src/main.cpp @@ -20,6 +20,7 @@ #include "../../JGE/include/JApp.h" #include "../../JGE/include/JGameLauncher.h" #include "../../JGE/include/JRenderer.h" +#include "../../JGE/include/JLogger.h" #ifndef JGEApp_Title @@ -360,8 +361,10 @@ void Run() // The main loop int main() { + JLOG("SetupCallbacks()"); SetupCallbacks(); #ifdef DEVHOOK + JLOG("initExceptionHandler()"); initExceptionHandler(); #endif g_engine = NULL; @@ -372,12 +375,16 @@ int main() if ((flags&JINIT_FLAG_ENABLE3D) != 0) JRenderer::Set3DFlag(true); + JLOG("sceRtcGetTickResolution()"); gTickFrequency = sceRtcGetTickResolution(); + JLOG("JGE::GetInstance()"); g_engine = JGE::GetInstance(); + JLOG("Create Game"); game = launcher->GetGameApp(); game->Create(); + JLOG("Run Game"); g_engine->SetApp(game); g_engine->Run(); diff --git a/projects/mtg/Makefile b/projects/mtg/Makefile index 358a895a4..5eccf487e 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/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardPrimitive.o objs/CardSelector.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DeckDataWrapper.o objs/DeckMetaData.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/GameStateAwards.o objs/GameStateDeckViewer.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GameStateTransitions.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/MTGPack.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/Rules.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/SimplePad.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/ThisDescriptor.o objs/Token.o objs/Translate.o objs/TranslateKeys.o objs/Trash.o objs/utils.o objs/WEvent.o objs/WResourceManager.o objs/WCachedResource.o objs/WDataSrc.o objs/WGui.o objs/WFilter.o objs/Tasks.o +OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIMomirPlayer.o objs/AIPlayer.o objs/AIStats.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardPrimitive.o objs/CardSelector.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DeckDataWrapper.o objs/DeckMetaData.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/GameStateAwards.o objs/GameStateDeckViewer.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GameStateStory.o objs/GameStateTransitions.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/MTGPack.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/Rules.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/SimplePad.o objs/StoryFlow.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/ThisDescriptor.o objs/Token.o objs/Translate.o objs/TranslateKeys.o objs/Trash.o objs/utils.o objs/WEvent.o objs/WResourceManager.o objs/WCachedResource.o objs/WDataSrc.o objs/WGui.o objs/WFilter.o objs/Tasks.o DEPS = $(patsubst objs/%.o, deps/%.d, $(OBJS)) RESULT = $(shell psp-config --psp-prefix 2> Makefile.cache) diff --git a/projects/mtg/bin/Res/campaigns/01.Where it all begins/_gfx/shopkeeper.jpg b/projects/mtg/bin/Res/campaigns/01.Where it all begins/_gfx/shopkeeper.jpg new file mode 100644 index 000000000..e168d391f Binary files /dev/null and b/projects/mtg/bin/Res/campaigns/01.Where it all begins/_gfx/shopkeeper.jpg differ diff --git a/projects/mtg/bin/Res/campaigns/01.Where it all begins/attack/rules.txt b/projects/mtg/bin/Res/campaigns/01.Where it all begins/attack/rules.txt new file mode 100644 index 000000000..93ad047dc --- /dev/null +++ b/projects/mtg/bin/Res/campaigns/01.Where it all begins/attack/rules.txt @@ -0,0 +1,7 @@ +[INIT] +mode=mtg +[PLAYER1] +inplay:white knight +auto=@tapped(creature):wingame controller +auto=lord(*) haste +auto=@next secondmain:wingame opponent \ No newline at end of file diff --git a/projects/mtg/bin/Res/campaigns/01.Where it all begins/cast_spell_1/rules.txt b/projects/mtg/bin/Res/campaigns/01.Where it all begins/cast_spell_1/rules.txt new file mode 100644 index 000000000..cf7a74407 --- /dev/null +++ b/projects/mtg/bin/Res/campaigns/01.Where it all begins/cast_spell_1/rules.txt @@ -0,0 +1,7 @@ +[INIT] +mode=mtg +[PLAYER1] +inplay:plains,plains +hand:white knight +auto=@movedTo(creature|myinplay):wingame controller +auto=@next combatbegins:wingame opponent \ No newline at end of file diff --git a/projects/mtg/bin/Res/campaigns/01.Where it all begins/cast_spell_2/rules.txt b/projects/mtg/bin/Res/campaigns/01.Where it all begins/cast_spell_2/rules.txt new file mode 100644 index 000000000..3274bb960 --- /dev/null +++ b/projects/mtg/bin/Res/campaigns/01.Where it all begins/cast_spell_2/rules.txt @@ -0,0 +1,7 @@ +[INIT] +mode=mtg +[PLAYER1] +inplay:plains,forest,mountain,island,swamp +hand:grizzly bears +auto=@movedTo(creature|myinplay):wingame controller +auto=@next combatbegins:wingame opponent \ No newline at end of file diff --git a/projects/mtg/bin/Res/campaigns/01.Where it all begins/story.xml b/projects/mtg/bin/Res/campaigns/01.Where it all begins/story.xml new file mode 100644 index 000000000..1273fd98c --- /dev/null +++ b/projects/mtg/bin/Res/campaigns/01.Where it all begins/story.xml @@ -0,0 +1,149 @@ + + + +dialog +WELCOME YOUNG ADVENTURER... +_gfx/shopkeeper.jpg +So you want to become a sorcerer? +You've come to the right place. I'm myself just +a humble retailer, but I've met a lot of adventurers like you +in my life, enough to understand the basics of their craft... + +Interested? + + + +dialog +TAPPING LANDS FOR MANA +In your quests you will have to fight against other wizards. +You will only have your brain and your spells to help you. +The basic Energy to cast your spells in Wagic is called mana. +The most frequent sources of Mana are called "Lands". +For a land to produce mana, +you just have to click on it with the action button (CIRCLE by default) +Go ahead and tap some mana! + + + +duel +tap_mana_ok +tap_mana_try_again + + + +dialog +HMMM... +It seems you didn't get that right +Simply navigate (with the D-Pad) to the land that appears on your screen, +then click on the action button (CIRCLE by default) +Let's try again! + + + +dialog +WELL DONE...NOW LET'S CAST A SPELL +That was too easy for you! +Now let's see if you can cast a spell... +Spells have a cost represented by mana symbols on the top right corner +of the card. For example, 2 white mana icons on the top right of the card +means that you have to produce 2 white manas (by activating 2 plains) +in order to put it into play. +Try to produce 2 white mana and put a white knight in play + + + +duel +cast_spell_1_ok +cast_spell_1_try_again + + + +dialog +HMMM... +It seems you didn't get that right +Simply navigate (with the D-Pad) to the lands that appear on your screen, +then click on the action button (CIRCLE by default) on each of them to produce 2 white mana. +Once this is done, navigate to the White Knight in your hand and click (CIRCLE by default) on it. +Depending on your configuration, you might need to display your hand (RTRIGGER by default) +Let's try again! + + + +dialog +PERFECT...BUT THERE'S MORE TO IT +You did great, young adventurer! +But you will see that some spells have slighlty different costs. +Sometimes the cost contains a number with no mana color. It means you can +pay with mana of whatever color you want. +for example a card which cost has a number "1" and a green icon +needs you to pay 1 green mana + a mana of any color if you want to play it. +Try to put a grizzly bear card in play. + + + +duel +cast_spell_2_ok +cast_spell_2_try_again + + + +dialog +HMMM... +It seems you didn't get that right +Simply navigate (with the D-Pad) to the lands that appear on your screen, +then click on the action button (CIRCLE by default) on some of them to produce some mana. +Remember, you need 1 green mana and one other mana of any color. +Once this is done, navigate to the Grizzly Bears in your hand and click (CIRCLE by default) on it. +Let's try again! + + + +dialog +GREAT. NOW LET'S TALK ABOUT PHASES +Once you put them into play, you will want your creatures to attack your opponent. +After all, they are here to help you defeat other sorcerers! +Your creatures can't attack anytime they want, however, +they must wait for the combat phase of your turn. +Your turn is divided into several phases. You can go through the phases by +clicking on LTRIGGER by default. The name of the current phase is displayed on the +top right corner of the screen. + +Go to the "Attackers" phase, then click on your White Knight to attack. + + + +duel +attack_ok +attack_try_again + + + +dialog +HMMM... +It seems you didn't get that right +Go to the "Attackers" phase by clicking on LTRIGGER several times, +then click on your White Knight (with CIRCLE by default) to attack your opponent. +Let's try again! + + + +dialog +GOOD! +Let me tell you a bit more about phases. +Your turn is divided into several phases. The actions you can perform +Depend on the phase you're in. For now, let's say that you can: +- Play creatures during the "main phase 1" and the "main phase 2" phases of your turn. +- Attack with your creatures during the "Attackers" phase of your turn. +- Block your opponent's attacking creatures during the "blockers" phase of his turn. +There are lots of other phases but we'll discuss them later + +Continue + + + +End +CONGRATULATIONS! +This is the end of this tutorial, +now time for you to fight some real ennemies! +Click on the action button to go back to the main menu + diff --git a/projects/mtg/bin/Res/campaigns/01.Where it all begins/tap_mana/rules.txt b/projects/mtg/bin/Res/campaigns/01.Where it all begins/tap_mana/rules.txt new file mode 100644 index 000000000..95dc6ce73 --- /dev/null +++ b/projects/mtg/bin/Res/campaigns/01.Where it all begins/tap_mana/rules.txt @@ -0,0 +1,6 @@ +[INIT] +mode=mtg +[PLAYER1] +inplay:forest +auto=@tapped(land|myinplay):wingame controller +auto=@next combatbegins:wingame opponent \ No newline at end of file diff --git a/projects/mtg/bin/Res/campaigns/tutorial/duel1/deck.txt b/projects/mtg/bin/Res/campaigns/tutorial/duel1/deck.txt deleted file mode 100644 index 077fd776a..000000000 --- a/projects/mtg/bin/Res/campaigns/tutorial/duel1/deck.txt +++ /dev/null @@ -1,21 +0,0 @@ -#NAME:Magnivore -#DESC:Do not underestimate -#DESC:this... thing... because -#DESC:it happens to be blind. -#DESC:For if you do, it will -#DESC:be your last mistake! -Hymn to Tourach (FEM) * 4 # -Magnivore (ODY) * 4 # -Stone Rain (CHK) * 4 # -Mountain (RAV) * 4 # -Swamp (RAV) * 4 # -Swamp (TSP) * 4 # -Mountain (TSP) * 4 # -Damnation (PLC) * 4 # -Demolish (10E) * 4 # -Mountain (LRW) * 4 # -Swamp (LRW) * 4 # -Blightning (ALA) * 4 # -Megrim (M10) * 4 # -Sign in Blood (M10) * 4 # -Pyroclasm (M10) * 4 # diff --git a/projects/mtg/bin/Res/campaigns/tutorial/duel1/rules.txt b/projects/mtg/bin/Res/campaigns/tutorial/duel1/rules.txt deleted file mode 100644 index 118fdad76..000000000 --- a/projects/mtg/bin/Res/campaigns/tutorial/duel1/rules.txt +++ /dev/null @@ -1,9 +0,0 @@ -[INIT] -mode=mtg -[PLAYERS] -life:4 -auto=shuffle -auto=draw:7 -auto=@each my draw:draw:1 -[PLAYER2] -library:forest,forest,forest,mountain,mountain,plains,raging goblin,goblin king \ No newline at end of file diff --git a/projects/mtg/bin/Res/campaigns/tutorial/story.xml b/projects/mtg/bin/Res/campaigns/tutorial/story.xml deleted file mode 100644 index 8cdef9738..000000000 --- a/projects/mtg/bin/Res/campaigns/tutorial/story.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - -dialog -This is a test Story, what do you want to do? -Go left -Go right - - - -dialog -You found the Grail -click to continue - - - -dialog -You found the Arch of Noah -click to continue - - - -duel -End -1 - - - -End -The End - \ No newline at end of file diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 5e00d1895..1742e14f1 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -400,7 +400,9 @@ class GenericActivatedAbility:public ActivatedAbility, public NestedAbility{ int resolve(){ counters++; - source->X = abilityCost->Diff(cost)->hasX(); + ManaCost * diff = abilityCost->Diff(cost); + source->X = diff->hasX(); + SAFE_DELETE(diff); SAFE_DELETE(abilityCost); ability->target = target; //may have been updated... if (ability) return ability->resolve(); @@ -630,6 +632,35 @@ class AALifer:public ActivatedAbilityTP{ }; +/*Player Wins Game*/ +class AAWinGame:public ActivatedAbilityTP{ + public: + AAWinGame(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost = NULL, int _tap = 0, int who = TargetChooser::UNSET):ActivatedAbilityTP(_id, card,_target,_cost,_tap,who){ + } + + int resolve(){ + Damageable * _target = (Damageable *) getTarget(); + if (_target){ + if (_target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){ + _target = ((MTGCardInstance *)_target)->controller(); + } + game->gameOver = ((Player *)_target)->opponent(); + } + return 1; + } + + const char * getMenuText(){ + return "Win Game"; + } + + AAWinGame * clone() const{ + AAWinGame * a = NEW AAWinGame(*this); + a->isClone = 1; + return a; + } + +}; + class ATokenCreator:public ActivatedAbility{ @@ -1968,10 +1999,10 @@ class AThisForEach:public MTGAbility, public NestedAbility{ int matches; matches = td->match(source); if (matches > 0) { - if (abilities.size() > matches){ + if ((int)(abilities.size()) > matches){ removeAbilityFromGame(); } - for (int i = 0; i < matches - abilities.size(); i++) { + for (int i = 0; i < matches - (int)(abilities.size()); i++) { addAbilityToGame(); } } @@ -2988,53 +3019,6 @@ class ALivingArtifact:public MTGAbility{ } }; -//Lord of the Pit -class ALordOfThePit: public TargetAbility{ - public: - int paidThisTurn; - ALordOfThePit(int _id, MTGCardInstance * source):TargetAbility(_id, source, NEW CreatureTargetChooser(),0,1,0){ - paidThisTurn = 1; - } - - void Update(float dt){ - if (newPhase != currentPhase && source->controller() == game->currentPlayer){ - if (newPhase == Constants::MTG_PHASE_UNTAP){ - paidThisTurn = 0; - }else if( newPhase == Constants::MTG_PHASE_UPKEEP + 1 && !paidThisTurn){ - game->mLayers->stackLayer()->addDamage(source,source->controller(), 7); - } - } - TargetAbility::Update(dt); - } - - int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){ - if (currentPhase != Constants::MTG_PHASE_UPKEEP || paidThisTurn) return 0; - return TargetAbility::isReactingToClick(card,mana); - } - - int resolve(){ - MTGCardInstance * card = tc->getNextCardTarget(); - if (card && card != source && card->controller() == source->controller()){ - card->controller()->game->putInGraveyard(card); - paidThisTurn = 1; - return 1; - } - return 0; - } - - virtual ostream& toString(ostream& out) const - { - out << "ALordOfThePit ::: paidThisTurn : " << paidThisTurn - << " ("; - return TargetAbility::toString(out) << ")"; - } - ALordOfThePit * clone() const{ - ALordOfThePit * a = NEW ALordOfThePit(*this); - a->isClone = 1; - return a; - } -}; - //1143 Animate Dead class AAnimateDead:public MTGAbility{ public: @@ -3577,48 +3561,6 @@ class AFireball:public InstantAbility{ } }; -//1245 ForceOfNature -class AForceOfNature:public ActivatedAbility{ - public: - int dealDamageThisTurn; - AForceOfNature(int _id, MTGCardInstance * card):ActivatedAbility(_id,card, NEW ManaCost(),1,0){ - dealDamageThisTurn = 0; - cost->add(Constants::MTG_COLOR_GREEN,4); - } - - void Update(float dt){ - if (newPhase !=currentPhase){ - if (newPhase == Constants::MTG_PHASE_UNTAP){ - dealDamageThisTurn = 1; - }else if (newPhase == Constants::MTG_PHASE_DRAW && dealDamageThisTurn && game->currentPlayer==source->controller() ){ - game->mLayers->stackLayer()->addDamage(source,source->controller(),8); - } - } - ActivatedAbility::Update(dt); - } - - int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){ - return (dealDamageThisTurn && currentPhase == Constants::MTG_PHASE_UPKEEP && ActivatedAbility::isReactingToClick(card,mana)); - } - - int resolve(){ - dealDamageThisTurn = 0; - return 1; - } - - virtual ostream& toString(ostream& out) const - { - out << "AForceOfNature ::: dealDamageThisTurn : " << dealDamageThisTurn - << " ("; - return ActivatedAbility::toString(out) << ")"; - } - AForceOfNature * clone() const{ - AForceOfNature * a = NEW AForceOfNature(*this); - a->isClone = 1; - return a; - } -}; - //1351 Island Sanctuary class AIslandSanctuary:public MTGAbility{ diff --git a/projects/mtg/include/GameApp.h b/projects/mtg/include/GameApp.h index 745d5333d..727cfa52b 100644 --- a/projects/mtg/include/GameApp.h +++ b/projects/mtg/include/GameApp.h @@ -35,12 +35,14 @@ #define PLAYER_TYPE_HUMAN 1 #define PLAYER_TYPE_TESTSUITE 2 - -#define GAME_TYPE_CLASSIC 0 -#define GAME_TYPE_MOMIR 1 -#define GAME_TYPE_RANDOM1 2 -#define GAME_TYPE_RANDOM2 3 -#define GAME_TYPE_STORY 4 +enum +{ + GAME_TYPE_CLASSIC, + GAME_TYPE_MOMIR, + GAME_TYPE_RANDOM1, + GAME_TYPE_RANDOM2, + GAME_TYPE_STORY +}; class MTGAllCards; class TransitionBase; diff --git a/projects/mtg/include/Logger.h b/projects/mtg/include/Logger.h index dc316fd66..ccbd4e992 100644 --- a/projects/mtg/include/Logger.h +++ b/projects/mtg/include/Logger.h @@ -1,6 +1,9 @@ #ifndef _LOGGER_H #define _LOGGER_H_ +//TODO Remove this and use the jge logging facility (same system) +//#define DOLOG + #ifdef DOLOG #define LOG(x) Logger::Log(x); #else diff --git a/projects/mtg/include/StoryFlow.h b/projects/mtg/include/StoryFlow.h index 87dc34731..e9046d45c 100644 --- a/projects/mtg/include/StoryFlow.h +++ b/projects/mtg/include/StoryFlow.h @@ -10,12 +10,39 @@ using namespace std; class GameObserver; #define CAMPAIGNS_FOLDER "Res/campaigns/" + +class StoryGraphicalElement:public JGuiObject { +public: + float mX; + float mY; + StoryGraphicalElement(float x, float y); +}; + +class StoryText:public StoryGraphicalElement { +public : + string text; + int align; +StoryText(string text, float mX, float mY, string align = "center"); + void Render(); + void Update(float dt); + virtual ostream& toString(ostream& out) const; +}; +class StoryImage:public StoryGraphicalElement { +public : + string img; +StoryImage(string img, float mX, float mY); + void Render(); + void Update(float dt); + virtual ostream& toString(ostream& out) const; +}; + class StoryChoice:public JGuiObject { public: string pageId; string text; - int mX; - int mY; + float mX; + float mY; + bool mHasFocus; float mScale; float mTargetScale; @@ -42,10 +69,12 @@ public: class StoryDialog:public StoryPage, public JGuiListener,public JGuiController { private: - string text; + vectorgraphics; + string safeAttribute(TiXmlElement* element, string attribute); public: StoryDialog(TiXmlElement* el,StoryFlow * mParent); + ~StoryDialog(); void Update(float dt); void Render(); void ButtonPressed(int,int); diff --git a/projects/mtg/include/ThisDescriptor.h b/projects/mtg/include/ThisDescriptor.h index 357b127d4..61aa013cb 100644 --- a/projects/mtg/include/ThisDescriptor.h +++ b/projects/mtg/include/ThisDescriptor.h @@ -16,6 +16,7 @@ class ThisDescriptor{ int comparisonCriterion; virtual int match(MTGCardInstance * card) = 0; int matchValue(int value); + virtual ~ThisDescriptor(); }; class ThisDescriptorFactory{ diff --git a/projects/mtg/src/GameApp.cpp b/projects/mtg/src/GameApp.cpp index 556746ea5..514651f83 100644 --- a/projects/mtg/src/GameApp.cpp +++ b/projects/mtg/src/GameApp.cpp @@ -17,8 +17,7 @@ #include "../include/GameStateOptions.h" #include "../include/GameStateShop.h" #include "../include/GameStateAwards.h" -//Story mode not yet ready -//#include "../include/GameStateStory.h" +#include "../include/GameStateStory.h" #include "../include/DeckStats.h" #include "../include/DeckMetaData.h" #include "../include/Translate.h" @@ -89,8 +88,10 @@ void GameApp::Create() options.theGame = this; //Ensure that options are partially loaded before loading files. + LOG("options.reloadProfile()"); options.reloadProfile(); + LOG("Checking for music files"); //Test for Music files presence string filepath = RESPATH; filepath = filepath + "/" + resources.musicFile("Track0.mp3"); @@ -108,7 +109,10 @@ void GameApp::Create() else HasMusic = 0; + LOG("Loading Textures"); + LOG("--Loading menuicons.png"); resources.RetrieveTexture("menuicons.png",RETRIEVE_MANAGE); + //Creating thes quad in this specific order allows us to have them in the correct order to call them by integer id manaIcons[Constants::MTG_COLOR_GREEN] = resources.RetrieveQuad("menuicons.png", 2 + 0*36, 38, 32, 32, "c_green",RETRIEVE_MANAGE); manaIcons[Constants::MTG_COLOR_BLUE] = resources.RetrieveQuad("menuicons.png", 2 + 1*36, 38, 32, 32, "c_blue",RETRIEVE_MANAGE); @@ -121,6 +125,7 @@ void GameApp::Create() for (int i = sizeof(manaIcons)/sizeof(manaIcons[0]) - 1; i >= 0; --i) manaIcons[i]->SetHotSpot(16,16); + LOG("--Loading Other Textures"); resources.RetrieveTexture("back.jpg",RETRIEVE_MANAGE); JQuad * jq = resources.RetrieveQuad("back.jpg", 0, 0, 0, 0, "back",RETRIEVE_MANAGE); if (jq) jq->SetHotSpot(jq->mWidth/2, jq->mHeight/2); @@ -158,9 +163,11 @@ void GameApp::Create() jq = resources.RetrieveQuad("shadow.png", 0, 0, 16, 16,"shadow",RETRIEVE_MANAGE); jq->SetHotSpot(8, 8); jq = resources.RetrieveQuad("phasebar.png",0,0,0,0,"phasebar",RETRIEVE_MANAGE); - + + LOG("Init Collection"); collection = NEW MTGAllCards(); + LOG("Loading Particles"); Particles[0] = NEW hgeParticleSystem("graphics/particle1.psi", resources.GetQuad("particles")); Particles[1] = NEW hgeParticleSystem("graphics/particle2.psi", resources.GetQuad("particles")); Particles[2] = NEW hgeParticleSystem("graphics/particle3.psi", resources.GetQuad("particles")); @@ -168,6 +175,7 @@ void GameApp::Create() Particles[4] = NEW hgeParticleSystem("graphics/particle5.psi", resources.GetQuad("particles")); Particles[5] = NEW hgeParticleSystem("graphics/particle7.psi", resources.GetQuad("particles")); + LOG("Creating Game States"); mGameStates[GAME_STATE_DECK_VIEWER] = NEW GameStateDeckViewer(this); mGameStates[GAME_STATE_DECK_VIEWER]->Create(); @@ -186,10 +194,8 @@ void GameApp::Create() mGameStates[GAME_STATE_AWARDS] = NEW GameStateAwards(this); mGameStates[GAME_STATE_AWARDS]->Create(); - //Story mode not yet ready - //mGameStates[GAME_STATE_STORY] = NEW GameStateStory(this); - //mGameStates[GAME_STATE_STORY]->Create(); - + mGameStates[GAME_STATE_STORY] = NEW GameStateStory(this); + mGameStates[GAME_STATE_STORY]->Create(); mGameStates[GAME_STATE_TRANSITION] = NULL; @@ -206,6 +212,7 @@ void GameApp::Create() sprintf(buf, "size of CardPrimitive : %llu\n" , (long long unsigned int)sizeof(CardPrimitive)); OutputDebugString(buf); + LOG("Game Creation Done."); } diff --git a/projects/mtg/src/GameStateMenu.cpp b/projects/mtg/src/GameStateMenu.cpp index 127a0402f..5f96c2ea2 100644 --- a/projects/mtg/src/GameStateMenu.cpp +++ b/projects/mtg/src/GameStateMenu.cpp @@ -130,6 +130,7 @@ void GameStateMenu::Destroy() } void GameStateMenu::Start(){ + LOG("GameStateMenu::Start"); JRenderer::GetInstance()->EnableVSync(true); subMenuController = NULL; SAFE_DELETE(mGuiController); @@ -293,6 +294,7 @@ void GameStateMenu::setLang(int id){ } void GameStateMenu::loadLangMenu(){ + LOG("GameStateMenu::loadLangMenu"); subMenuController = NEW SimpleMenu(103, this, Constants::MENU_FONT, 150,60); if (!subMenuController) return; resetDirectory(); @@ -320,9 +322,11 @@ void GameStateMenu::loadLangMenu(){ } } resetDirectory(); + LOG("GameStateMenu::loadLangMenu - Done"); } void GameStateMenu::listPrimitives(){ + LOG("GameStateMenu::listPrimitives"); resetDirectory(); if (!mDip){ mDip = opendir("Res/sets/primitives/"); @@ -338,6 +342,7 @@ void GameStateMenu::listPrimitives(){ } resetDirectory(); primitivesLoadCounter = 0; + LOG("GameStateMenu::listPrimitives - Done"); } void GameStateMenu::ensureMGuiController(){ @@ -446,8 +451,7 @@ void GameStateMenu::Update(float dt) currentState = MENU_STATE_MAJOR_SUBMENU; subMenuController = NEW SimpleMenu(102, this, Constants::MENU_FONT, 150,60); if (subMenuController){ - //Story mode not yet ready - //subMenuController->Add(SUBMENUITEM_STORY,"Story"); + subMenuController->Add(SUBMENUITEM_STORY,"Story"); subMenuController->Add(SUBMENUITEM_CLASSIC,"Classic"); if (options[Options::MOMIR_MODE_UNLOCKED].number) subMenuController->Add(SUBMENUITEM_MOMIR, "Momir Basic"); @@ -458,8 +462,8 @@ void GameStateMenu::Update(float dt) subMenuController->Add(SUBMENUITEM_CANCEL, "Cancel"); } }else{ - if (mParent->gameType == GAME_TYPE_STORY) - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_STORY); + if (mParent->gameType == GAME_TYPE_STORY ) + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_STORY); else mParent->DoTransition(TRANSITION_FADE,GAME_STATE_DUEL); currentState = MENU_STATE_MAJOR_MAINMENU; diff --git a/projects/mtg/src/GameStateStory.cpp b/projects/mtg/src/GameStateStory.cpp index c167d9ad9..18c9a6b47 100644 --- a/projects/mtg/src/GameStateStory.cpp +++ b/projects/mtg/src/GameStateStory.cpp @@ -71,12 +71,14 @@ void GameStateStory::Update(float dt) { //return; } if (flow){ - flow->Update(dt); if (flow->currentPageId == "End") { if (mEngine->GetButtonClick(JGE_BTN_OK) || mEngine->GetButtonClick(JGE_BTN_SEC)){ mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); } } + else { + flow->Update(dt); + } } } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 951b095bd..fe1536e49 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -57,6 +57,7 @@ Counter * AbilityFactory::parseCounter(string s, MTGCardInstance * target, Spell wpi = NEW WParsedInt(atoi(nbstr.c_str())); } nb = wpi->getValue(); + delete(wpi); end = separator; } @@ -560,6 +561,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG OutputDebugString("MTGABILITY: Parsing Error:"); OutputDebugString(s.c_str()); OutputDebugString("\n"); + delete(cost); return NULL; } @@ -757,6 +759,16 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return a; } + // Win the game + found = s.find("wingame"); + if (found != string::npos){ + Damageable * d = NULL; + if (spell) d = spell->getNextDamageableTarget(); + MTGAbility * a = NEW AAWinGame(id,card,d,NULL,0,who); + a->oneShot = 1; + return a; + } + //Draw found = s.find("draw:"); if (found != string::npos){ @@ -849,6 +861,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG Counter * counter = parseCounter(counterString,target,spell); if (counter){ MTGAbility * a = NEW AACounter(id,card,target,counter->name.c_str(),counter->power,counter->toughness,counter->nb); + delete(counter); a->oneShot = 1; return a; } @@ -1297,11 +1310,6 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){ game->addObserver(NEW AFireball(_id, card,spell, x)); break; } - case 1245: //Force of Nature - { - game->addObserver(NEW AForceOfNature(_id,card)); - break; - } case 1112: //Howling Mine { game->addObserver(NEW AHowlingMine(_id, card)); @@ -1457,11 +1465,6 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){ game->addObserver(NEW ALivingArtifact( _id, card, card->target)); break; } - case 1166: //Lord Of The Pit - { - game->addObserver(NEW ALordOfThePit( _id, card)); - break; - } case 1209: //Mana Short { Player * player = spell->getNextPlayerTarget(); @@ -1906,6 +1909,7 @@ int ActivatedAbility::reactToClick(MTGCardInstance * card){ ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); game->currentlyActing()->getManaPool()->pay(cost); cost->doPayExtra(); + SAFE_DELETE(abilityCost); abilityCost = previousManaPool->Diff(player->getManaPool()); delete previousManaPool; } @@ -1928,6 +1932,7 @@ int ActivatedAbility::reactToTargetClick(Targetable * object){ ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); game->currentlyActing()->getManaPool()->pay(cost); cost->doPayExtra(); + SAFE_DELETE(abilityCost); abilityCost = previousManaPool->Diff(player->getManaPool()); delete previousManaPool; } @@ -1938,9 +1943,12 @@ int ActivatedAbility::reactToTargetClick(Targetable * object){ } ActivatedAbility::~ActivatedAbility(){ - if (!isClone){ + //Ok, this will probably lead to crashes, maybe with lord abilities involving "X" costs. + // If that's the case, we need to improve the clone() method of GenericActivatedAbility and GenericTargetAbility, I think + // Erwan 2004/04/25 + //if (!isClone){ SAFE_DELETE(abilityCost); - } + //} } ostream& ActivatedAbility::toString(ostream& out) const @@ -2011,7 +2019,9 @@ void TargetAbility::Render(){ int TargetAbility::resolve(){ Targetable * t = tc->getNextTarget(); if (t && ability){ - source->X = abilityCost->Diff(cost)->hasX(); + ManaCost * diff = abilityCost->Diff(cost); + source->X = diff->hasX(); + delete (diff); ability->target = t; if (ability->oneShot) return ability->resolve(); MTGAbility * a = ability->clone(); diff --git a/projects/mtg/src/ManaCost.cpp b/projects/mtg/src/ManaCost.cpp index a12cff174..aed55fc73 100644 --- a/projects/mtg/src/ManaCost.cpp +++ b/projects/mtg/src/ManaCost.cpp @@ -70,9 +70,9 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan OutputDebugString("Counter\n"); size_t counter_start = value.find("("); size_t counter_end = value.find(")", counter_start); - AbilityFactory * abf = NEW AbilityFactory(); + AbilityFactory abf; string counterString = value.substr(counter_start+1,counter_end-counter_start-1); - Counter * counter = abf->parseCounter(counterString,c); + Counter * counter = abf.parseCounter(counterString,c); size_t separator = value.find(",",counter_start); size_t separator2 = string::npos; if (separator != string::npos) { diff --git a/projects/mtg/src/StoryFlow.cpp b/projects/mtg/src/StoryFlow.cpp index f5c72a6b7..1ae06466f 100644 --- a/projects/mtg/src/StoryFlow.cpp +++ b/projects/mtg/src/StoryFlow.cpp @@ -8,9 +8,64 @@ #include #include + +StoryGraphicalElement::StoryGraphicalElement(float x, float y): JGuiObject(0), mX(x),mY(y) { +} + +StoryText::StoryText(string text, float _mX, float _mY, string _align):StoryGraphicalElement(_mX,_mY), text(text) { + align = JGETEXT_LEFT; + if (_align.compare("center") == 0) { + align = JGETEXT_CENTER; + }else if (_align.compare("right") == 0) { + align = JGETEXT_RIGHT; + } + if (align == JGETEXT_CENTER && mX == 0){ + mX = SCREEN_WIDTH/2; + } +} +void StoryText::Render() { + JLBFont * mFont = resources.GetJLBFont(Constants::MAIN_FONT); + mFont->SetColor(ARGB(200,255,255,255)); + mFont->SetScale(1.0); + mFont->DrawString(text.c_str(), mX, mY, align); +} + void StoryText::Update(float dt){ + //Nothing for now + } + + ostream& StoryText::toString(ostream& out) const +{ + return out << "StoryText ::: text : " << text; +} + + StoryImage::StoryImage(string img, float mX, float mY):StoryGraphicalElement(mX,mY), img(img) { + +} +void StoryImage::Render() { + JQuad * quad = resources.RetrieveQuad(img); + if (quad) { + float x = mX; + if (mX == -1) { + x = SCREEN_WIDTH/2; + quad->SetHotSpot(quad->mWidth/2, 0); + } + JRenderer::GetInstance()->RenderQuad(quad,x, mY); + } +} + void StoryImage::Update(float dt){ + //Nothing for now + } + + ostream& StoryImage::toString(ostream& out) const +{ + return out << "StoryImage ::: img : " << img; +} + StoryPage::StoryPage(StoryFlow * mParent):mParent(mParent){ } + + StoryFlow::StoryFlow(string folder): folder(folder){ string path = "campaigns/"; path.append(folder).append("/story.xml"); @@ -155,15 +210,43 @@ void StoryDuel::Render(){ game->Render(); } +string StoryDialog::safeAttribute(TiXmlElement* element, string attribute) { + string s; + if (element->Attribute(attribute.c_str())){ + s = element->Attribute(attribute.c_str()); + } + return s; +} -StoryDialog::StoryDialog(TiXmlElement* root, StoryFlow * mParent):JGuiListener(), JGuiController(1,NULL), StoryPage(mParent) { + +StoryDialog::StoryDialog(TiXmlElement* root, StoryFlow * mParent):StoryPage(mParent), JGuiListener(), JGuiController(1,NULL) { for (TiXmlNode* node = root->FirstChild(); node; node = node->NextSibling()) { TiXmlElement* element = node->ToElement(); if (element) { if (strcmp(element->Value(), "text")==0) { - const char* textC = element->GetText(); - text = textC; + string sX = safeAttribute(element, "x"); + float x = atof(sX.c_str()); + string sY = safeAttribute(element,"y"); + float y = atof(sY.c_str()); + string align = safeAttribute(element,"align"); + const char* textC = element->GetText(); + string text = textC; + graphics.push_back(NEW StoryText(text,x,y,align)); + } + else if (strcmp(element->Value(), "img")==0) { + string sX = safeAttribute(element,"x"); + float x = atof(sX.c_str()); + //special case to force center + if (sX.compare("") == 0 ){ + x = -1; + } + string sY = safeAttribute(element,"y"); + float y = atof(sY.c_str()); + const char* imgC = element->GetText(); + string img = imgC; + img = string("campaigns/").append(mParent->folder).append("/").append(img); + graphics.push_back(NEW StoryImage(img,x,y)); } else if (strcmp(element->Value(), "answer")==0){ string id = element->Attribute("goto"); @@ -183,14 +266,16 @@ StoryDialog::StoryDialog(TiXmlElement* root, StoryFlow * mParent):JGuiListener() void StoryDialog::Update(float dt){ JGuiController::Update(dt); + for (size_t i = 0; i < graphics.size(); ++i){ + graphics[i]->Update(dt); + } } void StoryDialog::Render() { - JLBFont * mFont = resources.GetJLBFont(Constants::MAIN_FONT); - mFont->SetColor(ARGB(255,255,255,255)); - mFont->SetScale(1.0); - mFont->DrawString(text.c_str(), 0, 0); + for (size_t i = 0; i < graphics.size(); ++i){ + graphics[i]->Render(); + } JGuiController::Render(); } @@ -198,6 +283,12 @@ void StoryDialog::ButtonPressed(int controllerid,int controlid) { mParent->gotoPage(((StoryChoice *)mObjects[controlid])->pageId); } +StoryDialog::~StoryDialog(){ + for (size_t i = 0; i < graphics.size(); ++i){ + delete(graphics[i]); + } +} + StoryPage * StoryFlow::loadPage(TiXmlElement* element){ TiXmlNode* typeNode = element->FirstChild("type"); if (!typeNode) return NULL; diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 83f8969f8..105ff1cd8 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -215,13 +215,14 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta size_t start = attribute.find("{"); size_t end = attribute.find("}"); string counterString = attribute.substr(start+1,end-start-1); - AbilityFactory * abf = NEW AbilityFactory(); - Counter * counter = abf->parseCounter(counterString,card); + AbilityFactory abf; + Counter * counter = abf.parseCounter(counterString,card); if (counter) { cd->counterName = counter->name; cd->counterNB = counter->nb; cd->counterPower = counter->power; cd->counterToughness = counter->toughness; + delete(counter); } if (minus) { cd->counterComparisonMode = COMPARISON_LESS; diff --git a/projects/mtg/src/ThisDescriptor.cpp b/projects/mtg/src/ThisDescriptor.cpp index 44b43bb2f..2a4ca5eae 100644 --- a/projects/mtg/src/ThisDescriptor.cpp +++ b/projects/mtg/src/ThisDescriptor.cpp @@ -5,6 +5,10 @@ #include "../include/CardDescriptor.h" +ThisDescriptor::~ThisDescriptor(){ + //nothing to do for now +} + //Returns the amount by which a value passes the comparison. int ThisDescriptor::matchValue(int value){ switch (comparisonMode){ @@ -98,8 +102,8 @@ ThisDescriptor * ThisDescriptorFactory::createThisDescriptor(string s){ size_t start = s.find("{"); size_t end = s.find("}"); string counterString = s.substr(start+1,end-start-1); - AbilityFactory * abf = NEW AbilityFactory(); - Counter * counter = abf->parseCounter(counterString,NULL); + AbilityFactory abf; + Counter * counter = abf.parseCounter(counterString,NULL); if (counter) { if (criterionFound) counter->nb = criterion; ThisCounter * td = NEW ThisCounter(counter); diff --git a/projects/mtg/src/WResourceManager.cpp b/projects/mtg/src/WResourceManager.cpp index f5943ef18..9d6ca120e 100644 --- a/projects/mtg/src/WResourceManager.cpp +++ b/projects/mtg/src/WResourceManager.cpp @@ -534,6 +534,11 @@ string WResourceManager::graphicsFile(const string filename){ if(fileOK(buf,true)) return buf; + //Failure. Check raw faile. + sprintf(buf,"%s",filename.c_str()); + if(fileOK(buf,true)) + return buf; + //Complete abject failure. Probably a crash... return graphdir; }