diff --git a/Crawler/Crawler.cpp b/Crawler/Crawler.cpp index 5826c03f..0e13eea2 100644 --- a/Crawler/Crawler.cpp +++ b/Crawler/Crawler.cpp @@ -59,6 +59,7 @@ SUCH DAMAGE. #include "Test.h" #include "ItemDrop.h" #include "VisualNovel.h" +#include "util.h" INCLUDE_EMITTER_LIST @@ -79,6 +80,7 @@ InputGroup Crawler::KEY_RIGHT; InputGroup Crawler::KEY_UP; InputGroup Crawler::KEY_DOWN; InputGroup Crawler::KEY_ATTACK; +InputGroup Crawler::KEY_CONFIRM; float Crawler::SIZE_CHANGE_SPEED=1; @@ -132,6 +134,9 @@ Crawler::Crawler() bool Crawler::OnUserCreate(){ InitializeDefaultKeybinds(); + + VisualNovel::Initialize(); + InitializeLevels(); player=std::make_unique(); @@ -185,8 +190,6 @@ bool Crawler::OnUserCreate(){ Unlock::Initialize(); ItemDrop::Initialize(); - VisualNovel::Initialize(); - ValidateGameStatus(); //Checks to make sure everything has been initialized properly. return true; @@ -195,10 +198,13 @@ bool Crawler::OnUserCreate(){ bool Crawler::OnUserUpdate(float fElapsedTime){ fElapsedTime=std::clamp(fElapsedTime,0.f,1/30.f); //HACK fix. We can't have a negative time. Although using a more precise system clock should make this never occur. Also make sure if the game is too slow we advance by only 1/30th of a second. levelTime+=fElapsedTime; - GameState::STATE->OnUserUpdate(this); + if(!GamePaused()){ + GameState::STATE->OnUserUpdate(this); + } RenderWorld(GetElapsedTime()); GameState::STATE->Draw(this); RenderMenu(); + RenderFadeout(); RenderVersionInfo(); return true; } @@ -1390,6 +1396,10 @@ void Crawler::InitializeLevel(std::string mapFile,MapName map){ } for(ConnectionPoint&cp:State_OverworldMap::connections){ + if(VisualNovel::storyLevelData.count(cp.map)){ //Visual novel story data for story levels. + cp.levelDataExists=true; + break; + } if(LEVEL_NAMES.count(cp.map)&&&MapHelper::MapFromString(cp.map)==&MAP_DATA[map]){ MAP_DATA[map].name=cp.name; for(int spawn:MAP_DATA[map].spawns){ @@ -1914,6 +1924,8 @@ void Crawler::InitializeDefaultKeybinds(){ KEY_UP.AddKeybind({KEY,W}); KEY_DOWN.AddKeybind({KEY,DOWN}); KEY_DOWN.AddKeybind({KEY,S}); + KEY_CONFIRM.AddKeybind({MOUSE,Mouse::LEFT}); + KEY_CONFIRM.AddKeybind({KEY,ENTER}); } void Crawler::SetBossNameDisplay(std::string name,float time){ @@ -1977,7 +1989,7 @@ void Crawler::ReduceBossEncounterMobCount(){ } void Crawler::RenderMenu(){ - if(Menu::stack.size()>0){ + if(!GamePaused()&&Menu::stack.size()>0){ Menu::stack.back()->Update(this); } if(Menu::stack.size()>0){ @@ -2029,7 +2041,7 @@ void Crawler::InitializeGraphics(){ std::sort(mappedKeys.begin(),mappedKeys.end(),[](std::pair&key1,std::pair&key2){return key1.secondloadout.size()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(loadout.size()-1)+")."); - loadout[slot].amt=0; loadout[slot].it=nullptr; +} + +void Crawler::RenderFadeout(){ + uint8_t alpha=0; + if(fadeOutDuration>0){ + fadeOutDuration=std::max(0.f,fadeOutDuration-GetElapsedTime()); + if(fadeOutDuration==0){ + GameState::_ChangeState(transitionState); + } + alpha=uint8_t(util::lerp(0,255,1-(fadeOutDuration/fadeOutTotalTime))); + }else + if(fadeInDuration>0){ + fadeInDuration=std::max(0.f,fadeInDuration-GetElapsedTime()); + alpha=uint8_t(util::lerp(255,0,1-(fadeInDuration/fadeOutTotalTime))); + } + FillRectDecal({0,0},GetScreenSize(),{0,0,0,alpha}); +} + +bool Crawler::GamePaused(){ + return fadeOutDuration>0; } \ No newline at end of file diff --git a/Crawler/Crawler.h b/Crawler/Crawler.h index 92cd107e..fcebf500 100644 --- a/Crawler/Crawler.h +++ b/Crawler/Crawler.h @@ -45,14 +45,17 @@ SUCH DAMAGE. #include "TMXParser.h" #include "olcUTIL_DataFile.h" #include "Key.h" +#include "GameState.h" class Crawler : public olc::PixelGameEngine { + friend class GameState; friend class State_GameRun; friend class sig::Animation; std::unique_ptrplayer; public: Pathfinding pathfinder; + static InputGroup KEY_CONFIRM; static InputGroup KEY_ATTACK; static InputGroup KEY_LEFT; static InputGroup KEY_RIGHT; @@ -96,6 +99,10 @@ private: int totalBossEncounterMobs=0; int chapter=1; //We start at chapter 1. std::arrayloadout; + float fadeOutDuration=0; + float fadeOutTotalTime=0; + float fadeInDuration=0; + States::State transitionState=States::State::GAME_RUN; std::vectormonstersToBeSpawned; @@ -182,6 +189,8 @@ public: bool UseLoadoutItem(int slot); //Blanks out this loadout item. void ClearLoadoutItem(int slot); + void RenderFadeout(); + bool GamePaused(); struct TileGroupData{ vi2d tilePos; diff --git a/Crawler/Crawler.vcxproj b/Crawler/Crawler.vcxproj index 7be5a93e..128c07bc 100644 --- a/Crawler/Crawler.vcxproj +++ b/Crawler/Crawler.vcxproj @@ -429,7 +429,6 @@ - diff --git a/Crawler/Crawler.vcxproj.filters b/Crawler/Crawler.vcxproj.filters index c5ff7c70..9a43f092 100644 --- a/Crawler/Crawler.vcxproj.filters +++ b/Crawler/Crawler.vcxproj.filters @@ -533,9 +533,6 @@ Documentation\Story - - Configurations\Story - diff --git a/Crawler/GameState.cpp b/Crawler/GameState.cpp index d3439c54..7de93705 100644 --- a/Crawler/GameState.cpp +++ b/Crawler/GameState.cpp @@ -53,14 +53,23 @@ void GameState::Initialize(){ GameState::ChangeState(States::OVERWORLD_MAP); } -void GameState::ChangeState(States::State newState){ - GameState*prevState=STATE; - if(!states.count(newState)){ - ERR("WARNING! State not defined for state "<camera.SetTarget(game->GetPlayer()->GetPos()); - STATE->OnStateChange(prevState); +void GameState::_ChangeState(States::State newState){ + GameState*prevState=STATE; + if(!states.count(newState)){ + ERR("WARNING! State not defined for state "<camera.SetTarget(game->GetPlayer()->GetPos()); + STATE->OnStateChange(prevState); +} + +void GameState::ChangeState(States::State newState,float fadeOutDuration){ + if(fadeOutDuration>0){ + game->fadeOutDuration=game->fadeOutTotalTime=game->fadeInDuration=fadeOutDuration; + game->transitionState=newState; + }else{ + _ChangeState(newState); + } +} GameState::~GameState(){} \ No newline at end of file diff --git a/Crawler/GameState.h b/Crawler/GameState.h index 2edf1f33..93e93436 100644 --- a/Crawler/GameState.h +++ b/Crawler/GameState.h @@ -1,3 +1,4 @@ +#pragma region License /* License (OLC-3) ~~~~~~~~~~~~~~~ @@ -29,6 +30,7 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#pragma endregion #pragma once #include #include @@ -47,6 +49,9 @@ namespace States{ }; class GameState{ + friend class Crawler; +private: + static void _ChangeState(States::State newState); public: inline static GameState*STATE=nullptr; inline static std::mapstates; @@ -55,5 +60,5 @@ public: virtual void OnStateChange(GameState*prevState)=0; virtual void OnUserUpdate(Crawler*game)=0; virtual void Draw(Crawler*game)=0; - static void ChangeState(States::State newState); + static void ChangeState(States::State newState,float fadeOutDuration=0); }; \ No newline at end of file diff --git a/Crawler/LevelCompleteWindow.cpp b/Crawler/LevelCompleteWindow.cpp index 269fca60..f3dd38f8 100644 --- a/Crawler/LevelCompleteWindow.cpp +++ b/Crawler/LevelCompleteWindow.cpp @@ -37,6 +37,8 @@ SUCH DAMAGE. #include "MenuComponent.h" #include "InventoryScrollableWindowComponent.h" #include "PopupMenuLabel.h" +#include "Unlock.h" +#include "State_OverworldMap.h" INCLUDE_game @@ -64,10 +66,16 @@ void Menu::InitializeLevelCompleteWindow(){ levelCompleteWindow->AddComponent("Stage Loot Outline",stageLootOutline); levelCompleteWindow->AddComponent("Stage Loot Label",stageLootLabel); levelCompleteWindow->AddComponent("Stage Loot Window",stageLootWindow); + + auto nextButtonAction=[](MenuFuncData data){ + Unlock::UnlockArea(State_OverworldMap::GetCurrentConnectionPoint().map); + GameState::ChangeState(States::OVERWORLD_MAP,0.5f); + return true; + }; MenuComponent*detailsOutline=NEW MenuComponent(LEVEL_COMPLETE,{{windowSize.size.x-72.f,32},{71,72}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE); MenuLabel*detailsExpGain=NEW MenuLabel(LEVEL_COMPLETE,{{windowSize.size.x-72.f,104},{71,36}},"+ Exp",1,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND); - MenuComponent*nextButton=NEW MenuComponent(LEVEL_COMPLETE,{{windowSize.size.x-72.f,144},{71,32}},"Next",DO_NOTHING); + MenuComponent*nextButton=NEW MenuComponent(LEVEL_COMPLETE,{{windowSize.size.x-72.f,144},{71,32}},"Next",nextButtonAction); levelCompleteWindow->AddComponent("Level Details Outline",detailsOutline); levelCompleteWindow->AddComponent("Level EXP Gain Outline",detailsExpGain); diff --git a/Crawler/Menu.cpp b/Crawler/Menu.cpp index 1f8893d2..f11fd90c 100644 --- a/Crawler/Menu.cpp +++ b/Crawler/Menu.cpp @@ -63,6 +63,7 @@ MenuType Menu::lastMenuTypeCreated; std::string Menu::lastRegisteredComponent; bool Menu::cover; +INCLUDE_game INCLUDE_GFX extern vi2d WINDOW_SIZE; @@ -301,9 +302,9 @@ void Menu::Update(Crawler*game){ void Menu::Draw(Crawler*game){ if(GetCurrentTheme().IsScaled()){ - DrawScaledWindowBackground(game,pos); + DrawScaledWindowBackground(game,pos,size,GetRenderColor()); }else{ - DrawTiledWindowBackground(game,pos); + DrawTiledWindowBackground(game,pos,size,GetRenderColor()); } game->SetDrawTarget(r.Sprite()); @@ -340,9 +341,9 @@ void Menu::Draw(Crawler*game){ } if(GetCurrentTheme().IsScaled()){ - DrawScaledWindowBorder(game,pos); + DrawScaledWindowBorder(game,pos,size,GetRenderColor()); }else{ - DrawTiledWindowBorder(game,pos); + DrawTiledWindowBorder(game,pos,size,GetRenderColor()); } if(draggingComponent!=nullptr){ @@ -535,69 +536,69 @@ void Menu::KeyboardButtonNavigation(Crawler*game,vf2d menuPos){ } } -void Menu::DrawScaledWindowBorder(Crawler*game,vf2d menuPos){ +void Menu::DrawScaledWindowBorder(Crawler*game,vf2d menuPos,vf2d size,Pixel renderColor){ vf2d patchSize={"Interface.9PatchSize"_f[0],"Interface.9PatchSize"_f[1]}; //Upper-Left - game->DrawPartialDecal(menuPos-patchSize,patchSize,GetPatchPart(0,0).Decal(),{patchSize.x*0,patchSize.y*0},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos-patchSize,patchSize,GetPatchPart(0,0).Decal(),{patchSize.x*0,patchSize.y*0},patchSize,renderColor); //Upper-Right - game->DrawPartialDecal(menuPos+vf2d{size.x,-patchSize.y},patchSize,GetPatchPart(2,0).Decal(),{patchSize.x*2,patchSize.y*0},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{size.x,-patchSize.y},patchSize,GetPatchPart(2,0).Decal(),{patchSize.x*2,patchSize.y*0},patchSize,renderColor); //Bottom-Left - game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,size.y},patchSize,GetPatchPart(0,2).Decal(),{patchSize.x*0,patchSize.y*2},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,size.y},patchSize,GetPatchPart(0,2).Decal(),{patchSize.x*0,patchSize.y*2},patchSize,renderColor); //Bottom-Right - game->DrawPartialDecal(menuPos+vf2d{size.x,size.y},patchSize,GetPatchPart(2,2).Decal(),{patchSize.x*2,patchSize.y*2},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{size.x,size.y},patchSize,GetPatchPart(2,2).Decal(),{patchSize.x*2,patchSize.y*2},patchSize,renderColor); //Top - game->DrawPartialDecal(menuPos+vf2d{0,-patchSize.y},vf2d{size.x,patchSize.y},GetPatchPart(1,0).Decal(),{patchSize.x*1,patchSize.y*0},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{0,-patchSize.y},vf2d{size.x,patchSize.y},GetPatchPart(1,0).Decal(),{patchSize.x*1,patchSize.y*0},patchSize,renderColor); //Left - game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,0},vf2d{patchSize.x,size.y},GetPatchPart(0,1).Decal(),{patchSize.x*0,patchSize.y*1},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,0},vf2d{patchSize.x,size.y},GetPatchPart(0,1).Decal(),{patchSize.x*0,patchSize.y*1},patchSize,renderColor); //Right - game->DrawPartialDecal(menuPos+vf2d{size.x,0},vf2d{patchSize.x,size.y},GetPatchPart(2,1).Decal(),{patchSize.x*2,patchSize.y*1},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{size.x,0},vf2d{patchSize.x,size.y},GetPatchPart(2,1).Decal(),{patchSize.x*2,patchSize.y*1},patchSize,renderColor); //Bottom - game->DrawPartialDecal(menuPos+vf2d{0,size.y},vf2d{size.x,patchSize.y},GetPatchPart(1,2).Decal(),{patchSize.x*1,patchSize.y*2},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{0,size.y},vf2d{size.x,patchSize.y},GetPatchPart(1,2).Decal(),{patchSize.x*1,patchSize.y*2},patchSize,renderColor); } -void Menu::DrawTiledWindowBorder(Crawler*game,vf2d menuPos){ +void Menu::DrawTiledWindowBorder(Crawler*game,vf2d menuPos,vf2d size,Pixel renderColor){ vf2d patchSize={"Interface.9PatchSize"_f[0],"Interface.9PatchSize"_f[1]}; //Upper-Left - game->DrawPartialDecal(menuPos-patchSize,patchSize,GetPatchPart(0,0).Decal(),{0,0},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos-patchSize,patchSize,GetPatchPart(0,0).Decal(),{0,0},patchSize,renderColor); //Upper-Right - game->DrawPartialDecal(menuPos+vf2d{size.x,-patchSize.y},patchSize,GetPatchPart(2,0).Decal(),{0,0},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{size.x,-patchSize.y},patchSize,GetPatchPart(2,0).Decal(),{0,0},patchSize,renderColor); //Bottom-Left - game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,size.y},patchSize,GetPatchPart(0,2).Decal(),{0,0},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,size.y},patchSize,GetPatchPart(0,2).Decal(),{0,0},patchSize,renderColor); //Bottom-Right - game->DrawPartialDecal(menuPos+vf2d{size.x,size.y},patchSize,GetPatchPart(2,2).Decal(),{0,0},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{size.x,size.y},patchSize,GetPatchPart(2,2).Decal(),{0,0},patchSize,renderColor); //Top - game->DrawPartialDecal(menuPos+vf2d{0,-patchSize.y},vf2d{size.x,patchSize.y},GetPatchPart(1,0).Decal(),{0,0},vf2d{size.x,patchSize.y},GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{0,-patchSize.y},vf2d{size.x,patchSize.y},GetPatchPart(1,0).Decal(),{0,0},vf2d{size.x,patchSize.y},renderColor); //Left - game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,0},vf2d{patchSize.x,size.y},GetPatchPart(0,1).Decal(),{0,0},vf2d{patchSize.x,size.y},GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,0},vf2d{patchSize.x,size.y},GetPatchPart(0,1).Decal(),{0,0},vf2d{patchSize.x,size.y},renderColor); //Right - game->DrawPartialDecal(menuPos+vf2d{size.x,0},vf2d{patchSize.x,size.y},GetPatchPart(2,1).Decal(),{0,0},vf2d{patchSize.x,size.y},GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{size.x,0},vf2d{patchSize.x,size.y},GetPatchPart(2,1).Decal(),{0,0},vf2d{patchSize.x,size.y},renderColor); //Bottom - game->DrawPartialDecal(menuPos+vf2d{0,size.y},vf2d{size.x,patchSize.y},GetPatchPart(1,2).Decal(),{0,0},vf2d{size.x,patchSize.y},GetRenderColor()); + game->DrawPartialDecal(menuPos+vf2d{0,size.y},vf2d{size.x,patchSize.y},GetPatchPart(1,2).Decal(),{0,0},vf2d{size.x,patchSize.y},renderColor); } -void Menu::DrawScaledWindowBackground(Crawler*game,vf2d menuPos){ +void Menu::DrawScaledWindowBackground(Crawler*game,vf2d menuPos,vf2d size,Pixel renderColor){ vf2d patchSize={"Interface.9PatchSize"_f[0],"Interface.9PatchSize"_f[1]}; //Center if(GetCurrentTheme().HasBackground()){ Decal*back=GetCurrentTheme().GetBackground(); - game->DrawPartialDecal(menuPos,size,back,{0,0},back->sprite->Size(),GetRenderColor()); + game->DrawPartialDecal(menuPos,size,back,{0,0},back->sprite->Size(),renderColor); }else{ - game->DrawPartialDecal(menuPos,size,GetPatchPart(1,1).Decal(),{patchSize.x*1,patchSize.y*1},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos,size,GetPatchPart(1,1).Decal(),{patchSize.x*1,patchSize.y*1},patchSize,renderColor); } } -void Menu::DrawTiledWindowBackground(Crawler*game,vf2d menuPos){ +void Menu::DrawTiledWindowBackground(Crawler*game,vf2d menuPos,vf2d size,Pixel renderColor){ vf2d patchSize={"Interface.9PatchSize"_f[0],"Interface.9PatchSize"_f[1]}; //Center if(GetCurrentTheme().HasBackground()){ Decal*back=GetCurrentTheme().GetBackground(); - game->DrawPartialDecal(menuPos,size,back,{0,0},size,GetRenderColor()); + game->DrawPartialDecal(menuPos,size,back,{0,0},size,renderColor); }else{ - game->DrawPartialDecal(menuPos,size,GetPatchPart(1,1).Decal(),{0,0},patchSize,GetRenderColor()); + game->DrawPartialDecal(menuPos,size,GetPatchPart(1,1).Decal(),{0,0},patchSize,renderColor); } } @@ -701,4 +702,14 @@ void Menu::CleanupAllMenus(){ Menu::menus.clear(); } -void Menu::Cleanup(){} \ No newline at end of file +void Menu::Cleanup(){} + +void Menu::DrawThemedWindow(vf2d menuPos,vf2d size,Pixel renderColor){ + if(GetCurrentTheme().IsScaled()){ + DrawScaledWindowBackground(game,menuPos,size,renderColor); + DrawScaledWindowBorder(game,menuPos,size,renderColor); + }else{ + DrawTiledWindowBackground(game,menuPos,size,renderColor); + DrawTiledWindowBorder(game,menuPos,size,renderColor); + } +} \ No newline at end of file diff --git a/Crawler/Menu.h b/Crawler/Menu.h index b706fdf0..d3a20e00 100644 --- a/Crawler/Menu.h +++ b/Crawler/Menu.h @@ -105,6 +105,8 @@ public: //Returns the last menu type created and last registered component, in case a component is detected as memory leaking, provides this information to each component for safety. static std::pairGetMemoryLeakReportInfo(); virtual void Cleanup(); + + static void DrawThemedWindow(vf2d menuPos,vf2d size,Pixel renderColor=WHITE); private: Menu(vf2d pos,vf2d size); static MenuType lastMenuTypeCreated; @@ -128,10 +130,10 @@ private: static Renderable&GetPatchPart(int x,int y); void KeyboardButtonNavigation(Crawler*game,vf2d menuPos); - void DrawScaledWindowBackground(Crawler*game,vf2d menuPos); - void DrawTiledWindowBackground(Crawler*game,vf2d menuPos); - void DrawScaledWindowBorder(Crawler*game,vf2d menuPos); - void DrawTiledWindowBorder(Crawler*game,vf2d menuPos); + static void DrawScaledWindowBackground(Crawler*game,vf2d menuPos,vf2d size,Pixel renderColor); + static void DrawTiledWindowBackground(Crawler*game,vf2d menuPos,vf2d size,Pixel renderColor); + static void DrawScaledWindowBorder(Crawler*game,vf2d menuPos,vf2d size,Pixel renderColor); + static void DrawTiledWindowBorder(Crawler*game,vf2d menuPos,vf2d size,Pixel renderColor); //This triggers if we use a keyboard/controller input to try and select some off-screen menu item. We should ideally follow the menu cursor. bool HandleOutsideDisabledButtonSelection(MenuComponent*disabledButton); diff --git a/Crawler/OverworldMapLevelWindow.cpp b/Crawler/OverworldMapLevelWindow.cpp index 167ee86b..dbecab44 100644 --- a/Crawler/OverworldMapLevelWindow.cpp +++ b/Crawler/OverworldMapLevelWindow.cpp @@ -50,15 +50,6 @@ void Menu::InitializeOverworldMapLevelWindow(){ Menu*levelSelectWindow=CreateMenu(OVERWORLD_LEVEL_SELECT,{game->GetScreenSize().x-game->GetScreenSize().x/3.f,24},windowSize); State_OverworldMap*overworldMap=(State_OverworldMap*)GameState::states[States::OVERWORLD_MAP]; //HACK ALERT!! We're going to make an assumption that we are in the overworld map state. - - //Map&loadedMap=MapHelper::MapFromString(overworldMap->GetCurrentConnectionPoint().map); - //std::set&spawns=loadedMap.spawns; - /*int yOffset=40; - for(int key:spawns){ - MenuLabel*testLabel=new MenuLabel(OVERWORLD_LEVEL_SELECT,{{0,float(yOffset)},{windowSize.x,24}},MONSTER_DATA[key].GetDisplayName()); - yOffset+=28; - levelSelectWindow->AddComponent(MONSTER_DATA[key].GetDisplayName()+" Display Label",testLabel); - }*/ MenuLabel*chapterLabel=NEW MenuLabel(OVERWORLD_LEVEL_SELECT,{{0,4},{windowSize.x,16}},"Chapter",1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN); MenuLabel*stageLabel=NEW MenuLabel(OVERWORLD_LEVEL_SELECT,{{0,24},{windowSize.x,16}},"Stage",1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN); diff --git a/Crawler/State_OverworldMap.cpp b/Crawler/State_OverworldMap.cpp index af9ff61e..6f626e49 100644 --- a/Crawler/State_OverworldMap.cpp +++ b/Crawler/State_OverworldMap.cpp @@ -41,6 +41,7 @@ SUCH DAMAGE. #include "drawutil.h" #include "MenuLabel.h" #include "EncountersSpawnListScrollableWindowComponent.h" +#include "VisualNovel.h" INCLUDE_MONSTER_LIST INCLUDE_game @@ -51,6 +52,7 @@ State_OverworldMap::State_OverworldMap(){ SetStageMarker("Stage I-I"); //Eventually we will load the game from a file and this will not be necessary. We just set it to this for now. } void State_OverworldMap::OnStateChange(GameState*prevState){ + game->LoadLevel(WORLD_MAP); if(Menu::IsMenuOpen()){ Menu::CloseAllMenus(); } @@ -84,7 +86,7 @@ void State_OverworldMap::OnUserUpdate(Crawler*game){ for(int neighborInd:currentConnectionPoint->neighbors){ if(neighborInd==-1)continue; ConnectionPoint&neighbor=ConnectionPointFromIndex(neighborInd); - if(Unlock::IsUnlocked(neighbor.name)&&&cp==&neighbor){ + if(Unlock::IsUnlocked(neighbor.unlockCondition)&&&cp==&neighbor){ currentConnectionPoint=&neighbor; playerTargetPos=currentConnectionPoint->rect.pos+currentConnectionPoint->rect.size/2+vf2d{0,16}; float angleTo=util::angleTo(game->GetPlayer()->GetPos(),playerTargetPos); @@ -141,6 +143,10 @@ ConnectionPoint&State_OverworldMap::GetCurrentConnectionPoint(){ } void State_OverworldMap::StartLevel(){ - game->LoadLevel(LEVEL_NAMES.at(State_OverworldMap::GetCurrentConnectionPoint().map)); - GameState::ChangeState(States::GAME_RUN); + if(State_OverworldMap::GetCurrentConnectionPoint().map.starts_with("STORY")){ + VisualNovel::LoadVisualNovel(State_OverworldMap::GetCurrentConnectionPoint().map); + }else{ + game->LoadLevel(LEVEL_NAMES.at(State_OverworldMap::GetCurrentConnectionPoint().map)); + GameState::ChangeState(States::GAME_RUN); + } } \ No newline at end of file diff --git a/Crawler/State_Story.cpp b/Crawler/State_Story.cpp index 203059c1..37f4cc6f 100644 --- a/Crawler/State_Story.cpp +++ b/Crawler/State_Story.cpp @@ -33,11 +33,14 @@ SUCH DAMAGE. #pragma endregion #include "State_Story.h" #include "VisualNovel.h" +#include "Menu.h" -void State_Story::OnStateChange(GameState*prevState){}; +void State_Story::OnStateChange(GameState*prevState){ + Menu::CloseAllMenus(); +}; void State_Story::OnUserUpdate(Crawler*game){ - VisualNovel::Update(); + VisualNovel::novel.Update(); }; void State_Story::Draw(Crawler*game){ - VisualNovel::Draw(); + VisualNovel::novel.Draw(); }; \ No newline at end of file diff --git a/Crawler/Unlock.cpp b/Crawler/Unlock.cpp index 3ec63ec8..320f1c28 100644 --- a/Crawler/Unlock.cpp +++ b/Crawler/Unlock.cpp @@ -32,20 +32,26 @@ SUCH DAMAGE. */ #pragma endregion #include "Unlock.h" +#include "State_OverworldMap.h" std::setUnlock::unlocks; void Unlock::Initialize(){ UnlockArea("WORLD_MAP"); + UnlockArea("CAMPAIGN_1_1"); } -void Unlock::UnlockArea(std::string unlock){ - unlocks.insert(unlock); +void Unlock::UnlockArea(std::string mapName){ + unlocks.insert(mapName); } -bool Unlock::IsUnlocked(std::string unlock){ - return unlocks.count(unlock); +bool Unlock::IsUnlocked(std::string mapName){ + return unlocks.count(mapName); } bool Unlock::IsUnlocked(ConnectionPoint&cp){ return unlocks.count(cp.unlockCondition); +} + +void Unlock::UnlockCurrentMap(){ + UnlockArea(State_OverworldMap::GetCurrentConnectionPoint().map); } \ No newline at end of file diff --git a/Crawler/Unlock.h b/Crawler/Unlock.h index 5b3593db..8cf7e83e 100644 --- a/Crawler/Unlock.h +++ b/Crawler/Unlock.h @@ -41,7 +41,10 @@ class Unlock{ static std::setunlocks; static void Initialize(); public: - static void UnlockArea(std::string unlock); - static bool IsUnlocked(std::string unlock); + //Provide a map's actual name to trigger unlocks for all connected areas. You can get the current map you are on via State_OverworlMap::GetCurrentConnectionPoint().map + static void UnlockArea(std::string mapName); + //Uses the current map as the unlock criteria. + static void UnlockCurrentMap(); + static bool IsUnlocked(std::string mapName); static bool IsUnlocked(ConnectionPoint&cp); }; \ No newline at end of file diff --git a/Crawler/Version.h b/Crawler/Version.h index 5f114956..a89c6e83 100644 --- a/Crawler/Version.h +++ b/Crawler/Version.h @@ -35,7 +35,7 @@ SUCH DAMAGE. #define VERSION_MAJOR 0 #define VERSION_MINOR 2 #define VERSION_PATCH 1 -#define VERSION_BUILD 3172 +#define VERSION_BUILD 3212 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Crawler/VisualNovel.cpp b/Crawler/VisualNovel.cpp index 432dd05a..a2e246c4 100644 --- a/Crawler/VisualNovel.cpp +++ b/Crawler/VisualNovel.cpp @@ -35,9 +35,16 @@ SUCH DAMAGE. #include "GameState.h" #include "Crawler.h" #include +#include "DEFINES.h" +#include "Unlock.h" +#include "Menu.h" + +INCLUDE_game +INCLUDE_GFX VisualNovel VisualNovel::novel; safemap>>VisualNovel::storyLevelData; +std::setVisualNovel::graphicsToLoad; void VisualNovel::Initialize(){ for(int chapter=1;chapter<=6;chapter++){ @@ -80,6 +87,17 @@ void VisualNovel::Initialize(){ case '{':{ //Start of a command. auto&data=storyLevelData.at(currentStory); + auto AddImagesForLoading=[](std::vector&arguments){ + for(std::string&arg:arguments){ + if(arg=="story_player_name"_S){ + graphicsToLoad.insert("character_image_location"_S+"Player_F.png"); + graphicsToLoad.insert("character_image_location"_S+"Player_M.png"); + }else{ + graphicsToLoad.insert("character_image_location"_S+arg+".png"); + } + } + }; + size_t spacePos=line.find(' '); std::vectorarguments; @@ -97,12 +115,15 @@ void VisualNovel::Initialize(){ }else if(line.find("{BACKGROUND")!=std::string::npos){//Background command if(arguments.size()!=1)ERR("Arguments size is "<(arguments[0])); }else if(line.find("{LEFT")!=std::string::npos){//Left command + AddImagesForLoading(arguments); data.push_back(std::make_unique(arguments)); }else if(line.find("{RIGHT")!=std::string::npos){//Right command + AddImagesForLoading(arguments); data.push_back(std::make_unique(arguments)); }else if(line.find("{PAUSE")!=std::string::npos){//Pause command @@ -141,13 +162,51 @@ void VisualNovel::Initialize(){ }; void VisualNovel::LoadVisualNovel(std::string storyLevelName){ novel.storyLevel=storyLevelName; - GameState::ChangeState(States::STORY); + novel.activeText=""; + novel.leftCharacters.clear(); + novel.rightCharacters.clear(); + novel.backgroundFilename=""; + novel.commands.clear(); + for(std::unique_ptr&command:storyLevelData.at(storyLevelName)){ + novel.commands.push_back(command.get()); + } + GameState::ChangeState(States::STORY,0.5f); + novel.ExecuteNextCommand(); + novel.prevTheme=Menu::GetCurrentTheme().GetThemeName(); + Menu::themeSelection="Purple"; } void VisualNovel::Update(){ - + if(game->KEY_CONFIRM.Pressed()){ + novel.ExecuteNextCommand(); + } + locationDisplayTime=std::max(0.f,locationDisplayTime-game->GetElapsedTime()); +} +void VisualNovel::ExecuteNextCommand(){ + if(commandIndexExecute(novel); + }else{ + Unlock::UnlockCurrentMap(); + Menu::themeSelection=novel.prevTheme; + GameState::ChangeState(States::OVERWORLD_MAP,0.5f); + } } void VisualNovel::Draw(){ - + if(backgroundFilename!=""){ + game->DrawDecal({0,0},GFX["backgrounds/"+backgroundFilename].Decal()); + }else{ + game->FillRectDecal({0,0},game->GetScreenSize()); + } + if(locationDisplayTime>0){ + vi2d textSize=game->GetTextSizeProp(locationDisplayText)*2; + game->FillRectDecal(game->GetScreenSize()/2-textSize/2-vi2d{4,4},textSize+vi2d{8,8},BLACK); + game->DrawRectDecal(game->GetScreenSize()/2-textSize/2-vi2d{4,4},textSize+vi2d{8,8},WHITE); + game->DrawShadowStringPropDecal(game->GetScreenSize()/2-textSize/2,locationDisplayText,WHITE,VERY_DARK_BLUE,{2.f,2.f}); + } + if(activeText.length()>0){ + Menu::DrawThemedWindow({24.f,game->GetScreenSize().y-60.f},{48.f,-12.f}); + Menu::DrawThemedWindow({24.f,game->GetScreenSize().y-48.f},{game->GetScreenSize().x-48.f,20.f}); + } } VisualNovel::VisualNovel(){} @@ -155,60 +214,49 @@ VisualNovel::VisualNovel(){} Command::Command(){} void LocationCommand::Execute(VisualNovel&vn){ - + vn.locationDisplayTime=5.f; + vn.locationDisplayText=location; + vn.ExecuteNextCommand(); } LocationCommand::LocationCommand(std::string location) -:location(location){ - -} +:location(location){} void BackgroundCommand::Execute(VisualNovel&vn){ - + vn.backgroundFilename=backgroundFilename; + vn.ExecuteNextCommand(); } BackgroundCommand::BackgroundCommand(std::string backgroundFilename) -:backgroundFilename(backgroundFilename){ - -} +:backgroundFilename(backgroundFilename){} void LeftCommand::Execute(VisualNovel&vn){ - + vn.leftCharacters=characters; + vn.ExecuteNextCommand(); } LeftCommand::LeftCommand(std::vectorcharacters) -:characters(characters){ - -} +:characters(characters){} void RightCommand::Execute(VisualNovel&vn){ - + vn.rightCharacters=characters; + vn.ExecuteNextCommand(); } RightCommand::RightCommand(std::vectorcharacters) -:characters(characters){ - -} +:characters(characters){} void SpeakerCommand::Execute(VisualNovel&vn){ - + vn.speakerDisplayName=displayedName; + vn.actualSpeakerName=actualSpeakerName; + vn.ExecuteNextCommand(); } SpeakerCommand::SpeakerCommand(std::string speaker) -:displayedName(speaker),actualSpeakerName(speaker){ - -} +:displayedName(speaker),actualSpeakerName(speaker){} SpeakerCommand::SpeakerCommand(std::string displayedName,std::string speaker) -:displayedName(displayedName),actualSpeakerName(speaker){ - -} +:displayedName(displayedName),actualSpeakerName(speaker){} void DialogCommand::Execute(VisualNovel&vn){ - + vn.activeText=dialog; } DialogCommand::DialogCommand(std::string dialog) -:dialog(dialog){ - -} +:dialog(dialog){} -void PauseCommand::Execute(VisualNovel&vn){ - -} -PauseCommand::PauseCommand(){ - -} \ No newline at end of file +void PauseCommand::Execute(VisualNovel&vn){} +PauseCommand::PauseCommand(){} \ No newline at end of file diff --git a/Crawler/VisualNovel.h b/Crawler/VisualNovel.h index e1a27458..866b98d6 100644 --- a/Crawler/VisualNovel.h +++ b/Crawler/VisualNovel.h @@ -35,10 +35,12 @@ SUCH DAMAGE. #include #include #include "safemap.h" +#include class VisualNovel; class Command{ + friend class VisualNovel; virtual void Execute(VisualNovel&vn)=0; protected: Command(); @@ -95,14 +97,30 @@ public: }; class VisualNovel{ + friend class State_Story; + friend class Crawler; + friend class Command; + friend class LocationCommand; + friend class BackgroundCommand; + friend class LeftCommand; + friend class RightCommand; + friend class SpeakerCommand; + friend class DialogCommand; + friend class PauseCommand; std::string storyLevel; + std::string speakerDisplayName=""; + std::string actualSpeakerName=""; std::string activeText; std::vectorleftCharacters; std::vectorrightCharacters; std::string backgroundFilename; std::vectorcommands; int commandIndex=0; + std::string locationDisplayText=""; + float locationDisplayTime=0; + std::string prevTheme=""; + static std::setgraphicsToLoad; static safemap>>storyLevelData; static VisualNovel novel; @@ -112,6 +130,7 @@ public: VisualNovel(VisualNovel&&)=delete; static void Initialize(); static void LoadVisualNovel(std::string storyLevelName); - static void Update(); - static void Draw(); + void ExecuteNextCommand(); + void Update(); + void Draw(); }; \ No newline at end of file diff --git a/Crawler/assets/characters/red_stone.png b/Crawler/assets/characters/Red Stone.png similarity index 100% rename from Crawler/assets/characters/red_stone.png rename to Crawler/assets/characters/Red Stone.png diff --git a/Crawler/assets/config/configuration.txt b/Crawler/assets/config/configuration.txt index 996f1ad2..b44e42f1 100644 --- a/Crawler/assets/config/configuration.txt +++ b/Crawler/assets/config/configuration.txt @@ -51,6 +51,15 @@ item_img_directory = items/ # Path to story files story_directory = config/story/ +# Path to character images +character_image_location = characters/ + +# Path to story backgrounds +story_background_image_location = backgrounds/ + +# The name substituted for the player in dialogs +story_player_name = You + # Whether or not to show individual data accesses from config data structure. debug_access_options = 0 diff --git a/Crawler/assets/config/gfx/themes.txt b/Crawler/assets/config/gfx/themes.txt index 9770235c..26598738 100644 --- a/Crawler/assets/config/gfx/themes.txt +++ b/Crawler/assets/config/gfx/themes.txt @@ -30,7 +30,7 @@ Themes BlueDefault { - Name = 9patch + filename = 9patch ButtonColor = 0,0,64,255 HighlightColor = 0,200,200,255 @@ -43,7 +43,7 @@ Themes } Purple { - Name = 9patch_2 + filename = 9patch_2 ButtonColor = 40,16,71,255 HighlightColor = 192,128,238,255 @@ -56,7 +56,7 @@ Themes } NicoPink { - Name = 9patch_3 + filename = 9patch_3 ButtonColor = 208,73,182,255 HighlightColor = 255,239,232,255 @@ -69,7 +69,7 @@ Themes } NicoPinkTiled { - Name = 9patch_4 + filename = 9patch_4 ButtonColor = 208,73,182,255 HighlightColor = 255,239,232,255 diff --git a/Crawler/assets/config/story/characters.txt b/Crawler/assets/config/story/characters.txt deleted file mode 100644 index d0556c77..00000000 --- a/Crawler/assets/config/story/characters.txt +++ /dev/null @@ -1,10 +0,0 @@ -character_image_location = assets/characters - -Characters -{ - Player_F = player_f.png - Player_M = player_m.png - Sherman = sherman.png - Greg = greg.png - Red Stone = red_stone.png -} \ No newline at end of file