Added tutorial tooltips. Release Build 7758.
This commit is contained in:
parent
65587bed88
commit
2bd3e370e5
@ -512,6 +512,7 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Tutorial.h" />
|
||||
<ClInclude Include="VisualNovel.h" />
|
||||
<ClInclude Include="Test.h" />
|
||||
<ClInclude Include="Theme.h" />
|
||||
@ -753,6 +754,7 @@
|
||||
<ClCompile Include="TitleScreen.cpp" />
|
||||
<ClCompile Include="Trapper.cpp" />
|
||||
<ClCompile Include="Turret.cpp" />
|
||||
<ClCompile Include="Tutorial.cpp" />
|
||||
<ClCompile Include="Unlock.cpp" />
|
||||
<ClCompile Include="Ursule.cpp" />
|
||||
<ClCompile Include="UserIDMenu.cpp">
|
||||
|
@ -471,6 +471,9 @@
|
||||
<ClInclude Include="State_Death.h">
|
||||
<Filter>Header Files\State</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Tutorial.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Player.cpp">
|
||||
@ -830,6 +833,9 @@
|
||||
<ClCompile Include="DeathMenu.cpp">
|
||||
<Filter>Source Files\Interface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Tutorial.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
|
@ -291,6 +291,8 @@ bool AiL::OnUserCreate(){
|
||||
|
||||
TitleScreen::Initialize();
|
||||
|
||||
Tutorial::Initialize();
|
||||
|
||||
Stats::InitializeDamageReductionTable();
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
@ -1752,7 +1754,7 @@ void AiL::RenderCooldowns(){
|
||||
if(loadoutSlot!=-1){
|
||||
drawOffset.y+=2.f;
|
||||
}
|
||||
a.input->DrawInput(game,pos+vf2d{14,0.f}+drawOffset,"",255,controlType,{0.75f,0.75f});
|
||||
a.input->DrawPrimaryInput(game,pos+vf2d{14,0.f}+drawOffset,"",255,controlType,{0.75f,0.75f});
|
||||
|
||||
if(a.cooldown>0.1){
|
||||
vf2d iconScale={1,1};
|
||||
@ -1885,6 +1887,9 @@ void AiL::InitializeLevel(std::string mapFile,MapName map){
|
||||
int pctChance=100;
|
||||
if(data.GetValueCount()>3)pctChance=data.GetInt(3U);
|
||||
MAP_DATA[map].stageLoot.push_back(ItemMapData(data.GetString(0U),data.GetInt(1U),data.GetInt(2U),pctChance));
|
||||
}else
|
||||
if(key.starts_with("Skip Loadout Selection")){
|
||||
MAP_DATA[map].skipLoadoutScreen=DATA["Levels"][map]["Skip Loadout Selection"].GetBool();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3265,6 +3270,7 @@ void AiL::SetLoadoutItem(int slot,std::string itemName){
|
||||
bool AiL::UseLoadoutItem(int slot){
|
||||
if(slot<0||slot>GetLoadoutSize()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(GetLoadoutSize()-1)+").");
|
||||
if(GetLoadoutItem(slot).lock()->Amt()>0){
|
||||
Tutorial::GetTask(TutorialTaskName::USE_RECOVERY_ITEMS).I(A::ITEM_USE_COUNT)++;
|
||||
Inventory::UseItem(GetLoadoutItem(slot).lock()->ActualName());
|
||||
Inventory::AddLoadoutItemUsed(GetLoadoutItem(slot).lock()->ActualName(),slot);
|
||||
GetLoadoutItem(slot).lock()->amt--;
|
||||
@ -3450,6 +3456,7 @@ void AiL::ResetGame(){
|
||||
State_OverworldMap::ResetConnectionPoints();
|
||||
SetChapter(1);
|
||||
SaveFile::SetSaveFileName("");
|
||||
Tutorial::Initialize();
|
||||
}
|
||||
|
||||
void AiL::OnRequestCompleted(const std::string_view receivedData)const{
|
||||
|
@ -73,6 +73,6 @@ protected:
|
||||
InputType controlType=KEY;
|
||||
if(Input::UsingGamepad())controlType=CONTROLLER;
|
||||
|
||||
ability->input->DrawInput(&window,textPos+vf2d{boxWidth/2,7},"",255,controlType,{0.5f,0.5f});
|
||||
ability->input->DrawPrimaryInput(&window,textPos+vf2d{boxWidth/2,7},"",255,controlType,{0.5f,0.5f});
|
||||
}
|
||||
};
|
@ -57,6 +57,6 @@ public:
|
||||
protected:
|
||||
inline void DrawDecal(ViewPort&window,bool focused)override{
|
||||
MenuComponent::DrawDecal(window,focused);
|
||||
input.DrawInput(game,Menu::menus[parentMenu]->pos+vf2d{rect.middle().x,rect.bottom().end.y+1},""sv,255,type);
|
||||
input.DrawPrimaryInput(game,Menu::menus[parentMenu]->pos+vf2d{rect.middle().x,rect.bottom().end.y+1},""sv,255,type);
|
||||
}
|
||||
};
|
@ -52,7 +52,7 @@ void Menu::InitializeItemLoadoutWindow(){
|
||||
|
||||
itemLoadoutWindow->ADD("Loadout Label",MenuLabel)(geom2d::rect<float>{{0,24},{itemLoadoutWindowWidth,24}},"Setup Item Loadout",2,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END;
|
||||
|
||||
itemLoadoutWindow->ADD("Loadout Map Name Label",MenuLabel)(geom2d::rect<float>{{0,48},{itemLoadoutWindowWidth,24}},std::format("About to Enter: {}",State_OverworldMap::GetCurrentConnectionPoint().name),1,ComponentAttr::SHADOW)END;
|
||||
itemLoadoutWindow->ADD("Loadout Map Name Label",MenuLabel)(geom2d::rect<float>{{0,48},{itemLoadoutWindowWidth,24}},std::format("About to Enter: #FFFF00{}",""),1,ComponentAttr::SHADOW)END;
|
||||
itemLoadoutWindow->ADD("Loadout Description Label",MenuLabel)(geom2d::rect<float>{{0,58},{itemLoadoutWindowWidth,24}},"Bring up to 3 items with you.",1,ComponentAttr::SHADOW)END;
|
||||
|
||||
float buttonBorderPadding=64;
|
||||
@ -98,7 +98,10 @@ void Menu::InitializeItemLoadoutWindow(){
|
||||
itemLoadoutWindow->ADD("Item Description",MenuLabel)(geom2d::rect<float>{{0,158},{itemLoadoutWindowWidth,24}},"",1,ComponentAttr::SHADOW)END;
|
||||
|
||||
|
||||
itemLoadoutWindow->ADD("Start Level Button",MenuComponent)(geom2d::rect<float>{{itemLoadoutWindowWidth/2+32,202},{64,16}},"Start",[](MenuFuncData data){State_OverworldMap::StartLevel();return true;})END;
|
||||
itemLoadoutWindow->ADD("Start Level Button",MenuComponent)(geom2d::rect<float>{{itemLoadoutWindowWidth/2+32,202},{64,16}},"Start",[](MenuFuncData data){
|
||||
State_OverworldMap::StartLevel();
|
||||
return true;
|
||||
})END;
|
||||
itemLoadoutWindow->ADD("Back Button",MenuComponent)(geom2d::rect<float>{{itemLoadoutWindowWidth/2-96,202},{64,16}},"Back",[](MenuFuncData data){Menu::CloseMenu();return true;})END;
|
||||
|
||||
itemLoadoutWindow->SetupKeyboardNavigation(
|
||||
|
@ -199,6 +199,11 @@ void InputGroup::AddKeybind(Input bind){
|
||||
keyOrder.push_back(bind);
|
||||
}
|
||||
|
||||
void InputGroup::ClearAllKeybinds(){
|
||||
keys.clear();
|
||||
keyOrder.clear();
|
||||
}
|
||||
|
||||
void InputGroup::RemoveKeybind(Input bind){
|
||||
size_t erased=keys.erase(bind);
|
||||
erased+=std::erase(keyOrder,bind);
|
||||
@ -303,6 +308,102 @@ std::string InputGroup::GetDisplayName(){
|
||||
}
|
||||
|
||||
void InputGroup::DrawInput(const std::variant<AiL*const,TileTransformedView*const,ViewPort*const>renderer,const vf2d pos,const std::string_view displayText,const uint8_t alpha,InputType type,vf2d textScale)const{
|
||||
std::vector<Input>displayKeys;
|
||||
switch(type){
|
||||
case CONTROLLER:std::copy_if(keys.begin(),keys.end(),std::back_inserter(displayKeys),[](const Input&input){return input.GetType()==CONTROLLER;});break;
|
||||
case MOUSE:std::copy_if(keys.begin(),keys.end(),std::back_inserter(displayKeys),[](const Input&input){return input.GetType()==KEY||input.GetType()==MOUSE;});break;
|
||||
default:std::copy_if(keys.begin(),keys.end(),std::back_inserter(displayKeys),[](const Input&input){return input.GetType()==KEY||input.GetType()==MOUSE;});break;
|
||||
}
|
||||
|
||||
vf2d buttonImgSize{};
|
||||
std::vector<std::variant<Decal*,std::string>>buttonImgs;
|
||||
|
||||
for(const Input&input:displayKeys){
|
||||
if(input.HasExtendedIcons()){
|
||||
buttonImgSize.x+=input.GetIcon(GameSettings::GetIconType()).Sprite()->width*textScale.x+"Interface.InputHelperSpacing"_F;
|
||||
buttonImgSize.y=std::max(buttonImgSize.y,float(input.GetIcon(GameSettings::GetIconType()).Sprite()->height));
|
||||
buttonImgs.push_back(input.GetIcon(GameSettings::GetIconType()).Decal());
|
||||
}else
|
||||
if(input.HasIcon()){
|
||||
buttonImgSize.x+=input.GetIcon().Sprite()->width*textScale.x+"Interface.InputHelperSpacing"_F;
|
||||
buttonImgSize.y=std::max(buttonImgSize.y,float(input.GetIcon().Sprite()->height));
|
||||
buttonImgs.push_back(input.GetIcon().Decal());
|
||||
}else{
|
||||
buttonImgSize.x+=game->GetTextSizeProp(input.GetDisplayName()).x*textScale.x+"Interface.InputHelperSpacing"_F;
|
||||
buttonImgSize.y=std::max(buttonImgSize.y,float(game->GetTextSizeProp(input.GetDisplayName()).y)+"Interface.InputHelperSpacing"_F);
|
||||
buttonImgs.push_back(input.GetDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
vf2d descriptionTextSize=game->GetTextSizeProp(displayText);
|
||||
vf2d offset=-((buttonImgSize+descriptionTextSize)/2.f);
|
||||
for(auto&button:buttonImgs){
|
||||
if(std::holds_alternative<Decal*>(button)){
|
||||
Decal*img=std::get<Decal*>(button);
|
||||
|
||||
#pragma region Render Macro
|
||||
#define Render(rendererType) \
|
||||
std::get<rendererType*const>(renderer)->DrawDecal(pos+offset-vf2d{0.f,2.f},img,textScale,{255,255,255,alpha});
|
||||
#pragma endregion
|
||||
if(std::holds_alternative<AiL*const>(renderer)){
|
||||
Render(AiL);
|
||||
}else
|
||||
if(std::holds_alternative<TileTransformedView*const>(renderer)){
|
||||
Render(TileTransformedView);
|
||||
}else
|
||||
if(std::holds_alternative<ViewPort*const>(renderer)){
|
||||
Render(ViewPort);
|
||||
}else ERR("Could not find proper renderer for rendering Inputs!");
|
||||
offset.x+=img->sprite->width*textScale.x+"Interface.InputHelperSpacing"_I;
|
||||
}else
|
||||
if(std::holds_alternative<std::string>(button)){
|
||||
std::string label=std::get<std::string>(button);
|
||||
vf2d textSize=game->GetTextSizeProp(label)*textScale;
|
||||
Pixel buttonBackCol="Interface.InputButtonBackCol"_Pixel;
|
||||
Pixel buttonTextCol="Interface.InputButtonTextCol"_Pixel;
|
||||
buttonBackCol.a=alpha;
|
||||
buttonTextCol.a=alpha;
|
||||
|
||||
#pragma region Render Macro
|
||||
#define Render(rendererType) \
|
||||
std::get<rendererType*const>(renderer)->FillRectDecal(pos+offset+vf2d{-2.f,0.f},vf2d{textSize.x+4,textSize.y},buttonBackCol); \
|
||||
std::get<rendererType*const>(renderer)->FillRectDecal(pos+offset+vf2d{-1.f,-1.f},vf2d{textSize.x+2,textSize.y},buttonBackCol); \
|
||||
std::get<rendererType*const>(renderer)->FillRectDecal(pos+offset+vf2d{-1.f,0.f},vf2d{textSize.x+2,textSize.y+1.f},buttonBackCol); \
|
||||
std::get<rendererType*const>(renderer)->DrawStringPropDecal(pos+offset+vf2d{0.f,0.f},label,buttonTextCol,textScale);
|
||||
#pragma endregion
|
||||
|
||||
if(std::holds_alternative<AiL*const>(renderer)){
|
||||
Render(AiL);
|
||||
}else
|
||||
if(std::holds_alternative<TileTransformedView*const>(renderer)){
|
||||
Render(TileTransformedView);
|
||||
}else
|
||||
if(std::holds_alternative<ViewPort*const>(renderer)){
|
||||
Render(ViewPort);
|
||||
}else ERR("Could not find proper renderer for rendering Inputs!");
|
||||
offset.x+=textSize.x+"Interface.InputHelperSpacing"_I;
|
||||
}else [[unlikely]]ERR("WARNING! Hit a state where no data is inside of the button! THIS SHOULD NOT BE HAPPENING!");
|
||||
}
|
||||
|
||||
#pragma region Render Display Text
|
||||
#pragma region Render Macro
|
||||
#define Render(rendererType) \
|
||||
std::get<rendererType*const>(renderer)->DrawShadowStringPropDecal(pos+offset,displayText,{255,255,255,alpha},{0,0,0,alpha},textScale);
|
||||
#pragma endregion
|
||||
|
||||
if(std::holds_alternative<AiL*const>(renderer)){
|
||||
Render(AiL);
|
||||
}else
|
||||
if(std::holds_alternative<TileTransformedView*const>(renderer)){
|
||||
Render(TileTransformedView);
|
||||
}else
|
||||
if(std::holds_alternative<ViewPort*const>(renderer)){
|
||||
Render(ViewPort);
|
||||
}else ERR("Could not find proper renderer for rendering Inputs!");
|
||||
#pragma endregion
|
||||
}
|
||||
|
||||
void InputGroup::DrawPrimaryInput(const std::variant<AiL*const,TileTransformedView*const,ViewPort*const>renderer,const vf2d pos,const std::string_view displayText,const uint8_t alpha,InputType type,vf2d textScale)const{
|
||||
std::optional<Input>primaryKey;
|
||||
switch(type){
|
||||
case CONTROLLER:primaryKey=GetPrimaryKey(CONTROLLER);break;
|
||||
@ -419,12 +520,12 @@ void InputGroup::DrawInput(const std::variant<AiL*const,TileTransformedView*cons
|
||||
#pragma endregion
|
||||
}
|
||||
|
||||
void InputGroup::DrawInput(const std::variant<AiL*const,TileTransformedView*const,ViewPort*const>renderer,const vf2d pos,const std::string_view displayText,const uint8_t alpha)const{
|
||||
void InputGroup::DrawPrimaryInput(const std::variant<AiL*const,TileTransformedView*const,ViewPort*const>renderer,const vf2d pos,const std::string_view displayText,const uint8_t alpha)const{
|
||||
InputType primaryType;
|
||||
if(Input::UsingGamepad())primaryType=CONTROLLER;
|
||||
else if(Menu::UsingMouseNavigation())primaryType=MOUSE;
|
||||
else primaryType=KEY;
|
||||
DrawInput(renderer,pos,displayText,alpha,primaryType);
|
||||
DrawPrimaryInput(renderer,pos,displayText,alpha,primaryType);
|
||||
}
|
||||
|
||||
const bool Input::HasIcon()const{
|
||||
|
@ -118,9 +118,11 @@ public:
|
||||
const bool Released();
|
||||
const float Analog()const;
|
||||
const float AnalogDAS(const float threshold=0.2f);
|
||||
void ClearAllKeybinds();
|
||||
std::string GetDisplayName();
|
||||
//Draws an input display with accompanying text centered at given position.
|
||||
void DrawInput(const std::variant<AiL*const,TileTransformedView*const,ViewPort*const>renderer,const vf2d pos,const std::string_view displayText,const uint8_t alpha)const;
|
||||
void DrawPrimaryInput(const std::variant<AiL*const,TileTransformedView*const,ViewPort*const>renderer,const vf2d pos,const std::string_view displayText,const uint8_t alpha)const;
|
||||
void DrawPrimaryInput(const std::variant<AiL*const,TileTransformedView*const,ViewPort*const>renderer,const vf2d pos,const std::string_view displayText,const uint8_t alpha,const InputType type,vf2d textScale={1.f,1.f})const;
|
||||
void DrawInput(const std::variant<AiL*const,TileTransformedView*const,ViewPort*const>renderer,const vf2d pos,const std::string_view displayText,const uint8_t alpha,const InputType type,vf2d textScale={1.f,1.f})const;
|
||||
const std::optional<Input>GetPrimaryKey(InputType type)const;
|
||||
};
|
||||
|
@ -100,4 +100,8 @@ enum class Attribute{
|
||||
ITEM_SLOT,
|
||||
MERCHANT_ITEM_SLOT,
|
||||
RUMBLE_TIMER, //NOTE: This timer automatically counts down inside of Menu.cpp!! Stops controller rumble when the timer ends.
|
||||
ATTACK_COUNT,
|
||||
ABILITY_COUNT,
|
||||
DEFENSIVE_COUNT,
|
||||
ITEM_USE_COUNT,
|
||||
};
|
@ -44,6 +44,7 @@ All rights reserved.
|
||||
#include "Unlock.h"
|
||||
#include "RowInventoryScrollableWindowComponent.h"
|
||||
#include "InventoryCreator.h"
|
||||
#include "Tutorial.h"
|
||||
|
||||
using A=Attribute;
|
||||
|
||||
@ -57,7 +58,7 @@ void Monster::STRATEGY::NPC(Monster&m,float fElapsedTime,std::string strategy){
|
||||
vf2d nameTextSize=game->GetTextSizeProp(m.GetName());
|
||||
uint8_t alpha=uint8_t(util::lerp(0.f,255.f,m.F(A::TARGET_TIMER)/ConfigFloat("Interaction Display Ease in Timer")));
|
||||
game->view.DrawShadowStringPropDecal(m.GetPos()-vf2d{0,12}-nameTextSize/2.f,m.GetName(),{255,255,0},{0,0,0});
|
||||
game->KEY_CONFIRM.DrawInput(&game->view,m.GetPos()+vf2d{ConfigFloatArr("Interaction Display Offset",0),ConfigFloatArr("Interaction Display Offset",1)},"Interact",alpha);
|
||||
game->KEY_CONFIRM.DrawPrimaryInput(&game->view,m.GetPos()+vf2d{ConfigFloatArr("Interaction Display Offset",0),ConfigFloatArr("Interaction Display Offset",1)},"Interact",alpha);
|
||||
});
|
||||
}
|
||||
m.phase=1;
|
||||
@ -67,6 +68,7 @@ void Monster::STRATEGY::NPC(Monster&m,float fElapsedTime,std::string strategy){
|
||||
m.F(A::TARGET_TIMER)=std::min(m.F(A::TARGET_TIMER)+fElapsedTime,ConfigFloat("Interaction Display Ease in Timer"));
|
||||
if(game->KEY_CONFIRM.Released()&&Menu::stack.size()==0){
|
||||
if(m.npcData.function=="Blacksmith"){
|
||||
Tutorial::CompleteTask(TutorialTaskName::BLACKSMITH);
|
||||
Menu::OpenMenu(MenuType::BLACKSMITH);
|
||||
//First reset all items displayed in the blacksmith's shop (showing only our equipment.)
|
||||
Inventory::UpdateBlacksmithInventoryLists();
|
||||
|
@ -38,11 +38,13 @@ All rights reserved.
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "DEFINES.h"
|
||||
#include "Menu.h"
|
||||
#include "EncountersSpawnListScrollableWindowComponent.h"
|
||||
#include "EncountersSpawnListScrollableWindowComponent.h"a
|
||||
#include "MenuLabel.h"
|
||||
#include "MenuComponent.h"
|
||||
#include "State_OverworldMap.h"
|
||||
#include "Map.h"
|
||||
#include "Unlock.h"
|
||||
#include "Tutorial.h"
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_MONSTER_DATA
|
||||
@ -61,8 +63,20 @@ void Menu::InitializeOverworldMapLevelWindow(){
|
||||
levelSelectWindow->ADD("Spawns List",EncountersSpawnListScrollableWindowComponent)(geom2d::rect<float>{{1,64},{windowSize.x-2,84}},ComponentAttr::BACKGROUND)END;
|
||||
|
||||
levelSelectWindow->ADD("Enter Button",MenuComponent)(geom2d::rect<float>{{0,166},{windowSize.x-1,16}},"Enter",[](MenuFuncData data){
|
||||
Component<MenuLabel>(ITEM_LOADOUT,"Loadout Map Name Label")->SetLabel(std::format("About to Enter: {}",State_OverworldMap::GetCurrentConnectionPoint().name));
|
||||
Menu::OpenMenu(ITEM_LOADOUT);
|
||||
if(State_OverworldMap::GetCurrentConnectionPoint().map=="HUB"&&Unlock::IsUnlocked("CAMPAIGN_1_3")&&!Tutorial::TaskIsComplete(TutorialTaskName::BLACKSMITH)){
|
||||
Tutorial::SetNextTask(TutorialTaskName::BLACKSMITH);
|
||||
}
|
||||
|
||||
if(game->MAP_DATA[State_OverworldMap::GetCurrentConnectionPoint().map].skipLoadoutScreen||
|
||||
State_OverworldMap::GetCurrentConnectionPoint().type.starts_with("STORY")){
|
||||
State_OverworldMap::StartLevel();
|
||||
}else{
|
||||
if(!Tutorial::TaskIsComplete(TutorialTaskName::SET_LOADOUT_ITEM)){
|
||||
Tutorial::SetNextTask(TutorialTaskName::SET_LOADOUT_ITEM);
|
||||
}
|
||||
Component<MenuLabel>(ITEM_LOADOUT,"Loadout Map Name Label")->SetLabel(std::format("About to Enter: #FFFF00{}",State_OverworldMap::GetCurrentConnectionPoint().name));
|
||||
Menu::OpenMenu(ITEM_LOADOUT);
|
||||
}
|
||||
return true;
|
||||
})END;
|
||||
|
||||
|
@ -56,6 +56,7 @@ All rights reserved.
|
||||
#include "MenuLabel.h"
|
||||
#include "GameSettings.h"
|
||||
#include "Unlock.h"
|
||||
#include "Tutorial.h"
|
||||
|
||||
INCLUDE_MONSTER_DATA
|
||||
INCLUDE_MONSTER_LIST
|
||||
@ -496,6 +497,7 @@ void Player::Update(float fElapsedTime){
|
||||
if(Menu::stack.empty()){
|
||||
|
||||
if(CanAct()&&attack_cooldown_timer==0&&AiL::KEY_ATTACK.Held()){
|
||||
Tutorial::GetTask(TutorialTaskName::USE_ATTACK).I(A::ATTACK_COUNT)++;
|
||||
AutoAttack();
|
||||
}
|
||||
|
||||
@ -506,6 +508,11 @@ void Player::Update(float fElapsedTime){
|
||||
if(CanAct(ability)){
|
||||
if(ability.cooldown==0&&GetMana()>=ability.manaCost){
|
||||
if(key.Held()||key.Released()&&&ability==castPrepAbility&&GetState()==State::PREP_CAST){
|
||||
if(&ability==&rightClickAbility){
|
||||
Tutorial::GetTask(TutorialTaskName::USE_DEFENSIVE).I(A::DEFENSIVE_COUNT)++;
|
||||
}else{
|
||||
Tutorial::GetTask(TutorialTaskName::USE_ABILITIES).I(A::ABILITY_COUNT)++;
|
||||
}
|
||||
if(AllowedToCast(ability)&&ability.action(this,{})){
|
||||
bool allowed=ability.actionPerformedDuringCast;
|
||||
ability.cooldown=ability.GetCooldownTime();
|
||||
@ -733,6 +740,11 @@ bool Player::Hurt(int damage,bool onUpperLevel,float z){
|
||||
DAMAGENUMBER_LIST.push_back(damageNumberPtr);
|
||||
}
|
||||
lastHitTimer=0.05f;
|
||||
|
||||
if(game->GetPlayer()->GetHealth()<game->GetPlayer()->GetMaxHealth()*0.5f&&!Tutorial::TaskIsComplete(TutorialTaskName::USE_RECOVERY_ITEMS)){
|
||||
Tutorial::SetNextTask(TutorialTaskName::USE_RECOVERY_ITEMS);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -783,6 +795,17 @@ void Player::Moved(){
|
||||
}
|
||||
for(MonsterSpawner&spawner:SPAWNER_LIST){
|
||||
if(!spawner.SpawnTriggered()&&spawner.DoesUpperLevelSpawning()==OnUpperLevel()&&geom2d::contains(geom2d::rect<float>{spawner.GetPos(),spawner.GetRange()},pos)){
|
||||
if(GameState::STATE==GameState::states[States::GAME_RUN]){
|
||||
if(!Tutorial::TaskIsComplete(TutorialTaskName::USE_ATTACK)){
|
||||
Tutorial::SetNextTask(TutorialTaskName::USE_ATTACK);
|
||||
}else
|
||||
if(!Tutorial::TaskIsComplete(TutorialTaskName::USE_ABILITIES)){
|
||||
Tutorial::SetNextTask(TutorialTaskName::USE_ABILITIES);
|
||||
}else
|
||||
if(game->GetPlayer()->GetHealth()<game->GetPlayer()->GetMaxHealth()*0.8f&&!Tutorial::TaskIsComplete(TutorialTaskName::USE_DEFENSIVE)){
|
||||
Tutorial::SetNextTask(TutorialTaskName::USE_DEFENSIVE);
|
||||
}
|
||||
}
|
||||
spawner.SetTriggered(true);
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ All rights reserved.
|
||||
#include "Checkbox.h"
|
||||
#include "InputDisplayComponent.h"
|
||||
#include "GameSettings.h"
|
||||
#include "Tutorial.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
@ -119,6 +120,11 @@ const void SaveFile::SaveGame(){
|
||||
saveFile["Unlocks"][unlockName].SetString("False",1U);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto&[taskName,task]:Tutorial::taskList){
|
||||
saveFile["Tutorial"][std::to_string(int(taskName))].SetBool(Tutorial::TaskIsComplete(taskName));
|
||||
}
|
||||
|
||||
saveFile["Overworld Map Location"].SetString(State_OverworldMap::GetCurrentConnectionPoint().name);
|
||||
saveFile["Chapter"].SetInt(game->GetCurrentChapter());
|
||||
saveFile["Save Name"].SetString(std::string(GetSaveFileName()));
|
||||
@ -334,6 +340,14 @@ void SaveFile::LoadFile(){
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
if(loadFile.HasProperty("Tutorial")){
|
||||
for(auto&[key,size]:loadFile["Tutorial"].GetKeys()){
|
||||
if(loadFile["Tutorial"][key].GetBool()){
|
||||
Tutorial::CompleteTask(TutorialTaskName(stoi(key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GameState::ChangeState(States::OVERWORLD_MAP,0.5f);
|
||||
}else{
|
||||
std::cout<<std::format("WARNING! File {} does not exist for loading!","save_file_path"_S+std::format("save.{:04}",saveFileID))<<std::endl;
|
||||
|
@ -61,7 +61,7 @@ void State_GameHub::OnStateChange(GameState*prevState){
|
||||
game->LoadLevel("HUB");
|
||||
}
|
||||
void State_GameHub::OnLevelLoad(){
|
||||
game->UpdateDiscordStatus("Hub Area",game->GetPlayer()->GetClassName());
|
||||
game->UpdateDiscordStatus("Camp",game->GetPlayer()->GetClassName());
|
||||
}
|
||||
void State_GameHub::OnUserUpdate(AiL*game){
|
||||
State_GameRun::OnUserUpdate(game);
|
||||
|
@ -45,6 +45,7 @@ All rights reserved.
|
||||
#include "GameEvent.h"
|
||||
#include "MenuComponent.h"
|
||||
#include "Unlock.h"
|
||||
#include "Tutorial.h"
|
||||
|
||||
INCLUDE_MONSTER_LIST
|
||||
INCLUDE_game
|
||||
@ -79,6 +80,9 @@ void State_GameRun::OnLevelLoad(){
|
||||
Component<MenuComponent>(MenuType::PAUSE,"Return to Camp Button")->SetGrayedOut(
|
||||
!Unlock::IsUnlocked("HUB")||game->GetCurrentMapName()=="HUB"
|
||||
);
|
||||
if(!Tutorial::TaskIsComplete(TutorialTaskName::MOVE_AROUND)){
|
||||
Tutorial::SetNextTask(TutorialTaskName::MOVE_AROUND);
|
||||
}
|
||||
}
|
||||
void State_GameRun::OnUserUpdate(AiL*game){
|
||||
game->bossDisplayTimer=std::max(0.f,game->bossDisplayTimer-game->GetElapsedTime());
|
||||
|
@ -252,11 +252,6 @@ void State_OverworldMap::UpdateCurrentConnectionPoint(const ConnectionPoint&conn
|
||||
}else{
|
||||
Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Enter Button")->Disable();
|
||||
}
|
||||
if(currentConnectionPoint->levelDataExists&&!(currentConnectionPoint->type=="STORY"||currentConnectionPoint->type=="SHOP")){
|
||||
Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Change Loadout Button")->Enable();
|
||||
}else{
|
||||
Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Change Loadout Button")->Disable();
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<ConnectionPoint*>State_OverworldMap::ConnectionPointFromString(std::string_view mapName){
|
||||
|
@ -132,6 +132,7 @@ private:
|
||||
std::map<std::string,std::vector<::ZoneData>> ZoneData;
|
||||
const std::map<std::string,std::vector<::ZoneData>>&GetZones()const;
|
||||
public:
|
||||
bool skipLoadoutScreen=false;
|
||||
const MapTag&GetMapData()const;
|
||||
const std::string_view GetMapType()const;
|
||||
const std::vector<ItemMapData>&GetStageLoot()const;
|
||||
|
@ -10,6 +10,6 @@ March 30th -> Public Demo Release
|
||||
|
||||
- Credits/Licensing
|
||||
|
||||
- Basic tutorial on the first stage, Only allow the player to select "Change Loadout", explain how to setup items, can only start once a loadout item is set.
|
||||
|
||||
- show inputs that can be used by the player to navigate, ability usage, and defensive. When player takes enough damage show how to use recovery items.
|
||||
- Check Story 2 Bugs
|
||||
- Check online username boxes (does not show the *?)\
|
||||
- Show Game Saved
|
@ -38,20 +38,47 @@ All rights reserved.
|
||||
#include "Error.h"
|
||||
#include "Tutorial.h"
|
||||
|
||||
TutorialTaskName Tutorial::currentTaskState=TutorialTaskName::CHANGE_LOADOUT;
|
||||
TutorialTaskName Tutorial::currentTaskState=TutorialTaskName::SET_LOADOUT_ITEM;
|
||||
std::map<TutorialTaskName,std::unique_ptr<TutorialTask>>Tutorial::taskList;
|
||||
|
||||
void Tutorial::Initialize(){
|
||||
using enum TutorialTaskName;
|
||||
#define CREATETASK(enum,class) taskList.insert(enum,std::make_unique<class>());
|
||||
CREATETASK(SET_LOADOUT_ITEM,SetLoadoutItemTask);
|
||||
CREATETASK(MOVE_AROUND,MoveAroundTask);
|
||||
#define CREATETASK(enum,class) taskList[enum]=std::move(std::make_unique<class>());
|
||||
CREATETASK(TutorialTaskName::SET_LOADOUT_ITEM,SetLoadoutItemTask);
|
||||
CREATETASK(TutorialTaskName::MOVE_AROUND,MoveAroundTask);
|
||||
CREATETASK(TutorialTaskName::USE_ATTACK,UseAttackTask);
|
||||
CREATETASK(TutorialTaskName::USE_ABILITIES,UseAbilitiesTask);
|
||||
CREATETASK(TutorialTaskName::USE_DEFENSIVE,UseDefensiveTask);
|
||||
CREATETASK(TutorialTaskName::USE_RECOVERY_ITEMS,UseRecoveryItemsTask);
|
||||
CREATETASK(TutorialTaskName::BLACKSMITH,BlacksmithTask);
|
||||
currentTaskState=TutorialTaskName::SET_LOADOUT_ITEM;
|
||||
ResetTasks();
|
||||
}
|
||||
|
||||
void Tutorial::SetNextTask(TutorialTaskName task){
|
||||
currentTaskState=task;
|
||||
if(taskList.count(currentTaskState)){
|
||||
taskList[currentTaskState]->OnActivate();
|
||||
}
|
||||
}
|
||||
|
||||
void Tutorial::CompleteTask(TutorialTaskName task){
|
||||
if(taskList.count(task)){
|
||||
taskList[task]->completed=true;
|
||||
Tutorial::SetNextTask(TutorialTaskName::NONE);
|
||||
taskList[task]->OnComplete();
|
||||
}
|
||||
}
|
||||
|
||||
TutorialTask&Tutorial::GetTask(TutorialTaskName task){
|
||||
return *taskList.at(task);
|
||||
}
|
||||
|
||||
TutorialTask::TutorialTask(){
|
||||
_Initialize();
|
||||
}
|
||||
|
||||
void TutorialTask::Draw()const{}
|
||||
|
||||
void TutorialTask::_Initialize(){
|
||||
completed=false;
|
||||
systemInitializeCalled=true;
|
||||
@ -69,25 +96,33 @@ const bool TutorialTask::IsComplete()const{
|
||||
|
||||
void TutorialTask::Update(){}
|
||||
|
||||
void TutorialTask::OnActivate(){}
|
||||
|
||||
void Tutorial::ResetTasks(){
|
||||
for(TutorialTask&tt:taskList){
|
||||
tt._Initialize();
|
||||
for(auto&[task,tt]:taskList){
|
||||
tt->_Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void Tutorial::Update(){
|
||||
for(TutorialTask&tt:taskList){
|
||||
if(!tt.completed){
|
||||
tt.Update();
|
||||
if(tt.CompleteCondition()){
|
||||
tt.completed=true;
|
||||
tt.OnComplete();
|
||||
if(taskList.count(currentTaskState)){
|
||||
TutorialTask*currentTask=taskList[currentTaskState].get();
|
||||
if(!currentTask->completed){
|
||||
currentTask->Update();
|
||||
if(currentTask->CompleteCondition()){
|
||||
currentTask->completed=true;
|
||||
Tutorial::SetNextTask(TutorialTaskName::NONE);
|
||||
currentTask->OnComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tutorial::Draw()const{}
|
||||
void Tutorial::Draw(){
|
||||
if(taskList.count(currentTaskState)){
|
||||
taskList[currentTaskState]->Draw();
|
||||
}
|
||||
}
|
||||
|
||||
const bool Tutorial::TaskIsComplete(TutorialTaskName task){
|
||||
return taskList.at(task)->IsComplete();
|
||||
|
@ -36,28 +36,41 @@ All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "MenuComponent.h"
|
||||
#include "LoadingScreen.h"
|
||||
#include "Key.h"
|
||||
|
||||
using A=Attribute;
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
#undef BLACKSMITH
|
||||
|
||||
enum class TutorialTaskName{
|
||||
SET_LOADOUT_ITEM,
|
||||
MOVE_AROUND,
|
||||
USE_ATTACK,
|
||||
USE_ABILITIES,
|
||||
USE_DEFENSIVE,
|
||||
USE_RECOVERY_ITEMS,
|
||||
BLACKSMITH,
|
||||
NONE,
|
||||
};
|
||||
|
||||
class TutorialTask{
|
||||
class TutorialTask:public IAttributable{
|
||||
friend class Tutorial;
|
||||
protected:
|
||||
bool completed=false;
|
||||
bool systemInitializeCalled=false;
|
||||
TutorialTask();
|
||||
private:
|
||||
public:
|
||||
TutorialTask();
|
||||
protected:
|
||||
bool completed=false;
|
||||
bool systemInitializeCalled=false;
|
||||
virtual void Initialize();
|
||||
private:
|
||||
void _Initialize();
|
||||
//Actions that occur when this task is reset/locked. DO NOT CALL DIRECTLY, USE _Initialize()!
|
||||
virtual void Initialize();
|
||||
virtual void Update();
|
||||
virtual void OnActivate();
|
||||
virtual void Draw()const;
|
||||
//Returns true when the task has detected it is completed.
|
||||
virtual bool CompleteCondition()=0;
|
||||
@ -67,19 +80,25 @@ class TutorialTask{
|
||||
};
|
||||
|
||||
class Tutorial{
|
||||
friend class SaveFile;
|
||||
public:
|
||||
static void Initialize();
|
||||
static void ResetTasks();
|
||||
static void Update();
|
||||
static void Draw();
|
||||
static const bool TaskIsComplete(TutorialTaskName task);
|
||||
static void SetNextTask(TutorialTaskName task);
|
||||
static TutorialTask&GetTask(TutorialTaskName task);
|
||||
static void CompleteTask(TutorialTaskName task);
|
||||
private:
|
||||
static TutorialTaskName currentTaskState;
|
||||
static std::unordered_map<TutorialTaskName,std::unique_ptr<TutorialTask>>taskList;
|
||||
static std::map<TutorialTaskName,std::unique_ptr<TutorialTask>>taskList;
|
||||
};
|
||||
|
||||
class SetLoadoutItemTask:protected TutorialTask{
|
||||
class SetLoadoutItemTask:public TutorialTask{
|
||||
public:
|
||||
inline SetLoadoutItemTask():TutorialTask(){};
|
||||
private:
|
||||
virtual inline void Initialize()override final{
|
||||
Component<MenuComponent>(ITEM_LOADOUT,"Start Level Button")->SetGrayedOut(true);
|
||||
}
|
||||
@ -96,11 +115,23 @@ class SetLoadoutItemTask:protected TutorialTask{
|
||||
}
|
||||
};
|
||||
|
||||
class MoveAroundTask:protected TutorialTask{
|
||||
vf2d initialPlayerPos=vf2d{};
|
||||
class MoveAroundTask:public TutorialTask{
|
||||
public:
|
||||
inline MoveAroundTask():TutorialTask(){};
|
||||
private:
|
||||
InputGroup moveGroup;
|
||||
vf2d initialPlayerPos=vf2d{};
|
||||
virtual inline void Initialize()override final{
|
||||
initialPlayerPos=vf2d{};
|
||||
moveGroup.ClearAllKeybinds();
|
||||
moveGroup.AddKeybind(game->KEY_LEFT.GetPrimaryKey(InputType::CONTROLLER).value());
|
||||
moveGroup.AddKeybind(game->KEY_DOWN.GetPrimaryKey(InputType::CONTROLLER).value());
|
||||
moveGroup.AddKeybind(game->KEY_UP.GetPrimaryKey(InputType::CONTROLLER).value());
|
||||
moveGroup.AddKeybind(game->KEY_RIGHT.GetPrimaryKey(InputType::CONTROLLER).value());
|
||||
moveGroup.AddKeybind(game->KEY_LEFT.GetPrimaryKey(InputType::KEY).value());
|
||||
moveGroup.AddKeybind(game->KEY_DOWN.GetPrimaryKey(InputType::KEY).value());
|
||||
moveGroup.AddKeybind(game->KEY_UP.GetPrimaryKey(InputType::KEY).value());
|
||||
moveGroup.AddKeybind(game->KEY_RIGHT.GetPrimaryKey(InputType::KEY).value());
|
||||
}
|
||||
virtual inline void Update()override final{
|
||||
if(!LoadingScreen::loading&&initialPlayerPos==vf2d{}){
|
||||
@ -108,9 +139,148 @@ class MoveAroundTask:protected TutorialTask{
|
||||
}
|
||||
}
|
||||
virtual inline bool CompleteCondition()override final{
|
||||
return initialPlayerPos!={}&&geom2d::line<float>(initialPlayerPos,game->GetPlayer()).length()>60;
|
||||
return initialPlayerPos!=vf2d{}&&geom2d::line<float>(initialPlayerPos,game->GetPlayer()->GetPos()).length()>60;
|
||||
}
|
||||
virtual inline void OnComplete()override final{
|
||||
initialPlayerPos={};
|
||||
initialPlayerPos=vf2d{};
|
||||
}
|
||||
virtual inline void Draw()const override final{
|
||||
if(Input::UsingGamepad()){
|
||||
moveGroup.DrawInput(game,{game->ScreenWidth()/2.f,48.f},"Move",180,InputType::CONTROLLER);
|
||||
}else{
|
||||
moveGroup.DrawInput(game,{game->ScreenWidth()/2.f,48.f},"Move",180,InputType::KEY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#define ADDKEYBIND(group,key,type) \
|
||||
group.AddKeybind(key.GetPrimaryKey(InputType::type).value());\
|
||||
if(type==InputType::KEY&&key.GetPrimaryKey(InputType::MOUSE).has_value()){ \
|
||||
group.AddKeybind(key.GetPrimaryKey(InputType::MOUSE).value()); \
|
||||
}
|
||||
|
||||
class UseAttackTask:public TutorialTask{
|
||||
public:
|
||||
inline UseAttackTask():TutorialTask(){};
|
||||
private:
|
||||
InputGroup attackGroup;
|
||||
virtual inline void OnActivate()override final{
|
||||
attackGroup.ClearAllKeybinds();
|
||||
ADDKEYBIND(attackGroup,game->KEY_ATTACK,CONTROLLER);
|
||||
ADDKEYBIND(attackGroup,game->KEY_ATTACK,KEY);
|
||||
}
|
||||
virtual inline bool CompleteCondition()override final{
|
||||
return I(A::ATTACK_COUNT)>=10;
|
||||
}
|
||||
virtual inline void OnComplete()override final{}
|
||||
virtual inline void Draw()const override final{
|
||||
if(Input::UsingGamepad()){
|
||||
attackGroup.DrawInput(game,{game->ScreenWidth()/2.f,48.f},"Attack",180,InputType::CONTROLLER);
|
||||
}else{
|
||||
attackGroup.DrawInput(game,{game->ScreenWidth()/2.f,48.f},"Attack",180,InputType::KEY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class UseAbilitiesTask:public TutorialTask{
|
||||
public:
|
||||
inline UseAbilitiesTask():TutorialTask(){};
|
||||
private:
|
||||
InputGroup abilityGroup;
|
||||
virtual inline void OnActivate()override final{
|
||||
abilityGroup.ClearAllKeybinds();
|
||||
ADDKEYBIND(abilityGroup,game->GetPlayer()->KEY_ABILITY1,CONTROLLER);
|
||||
ADDKEYBIND(abilityGroup,game->GetPlayer()->KEY_ABILITY1,KEY);
|
||||
ADDKEYBIND(abilityGroup,game->GetPlayer()->KEY_ABILITY2,CONTROLLER);
|
||||
ADDKEYBIND(abilityGroup,game->GetPlayer()->KEY_ABILITY2,KEY);
|
||||
ADDKEYBIND(abilityGroup,game->GetPlayer()->KEY_ABILITY3,CONTROLLER);
|
||||
ADDKEYBIND(abilityGroup,game->GetPlayer()->KEY_ABILITY3,KEY);
|
||||
}
|
||||
virtual inline bool CompleteCondition()override final{
|
||||
return I(A::ABILITY_COUNT)>=5;
|
||||
}
|
||||
virtual inline void OnComplete()override final{}
|
||||
virtual inline void Draw()const override final{
|
||||
if(Input::UsingGamepad()){
|
||||
abilityGroup.DrawInput(game,{game->ScreenWidth()/2.f,48.f},"Use Abilities",180,InputType::CONTROLLER);
|
||||
}else{
|
||||
abilityGroup.DrawInput(game,{game->ScreenWidth()/2.f,48.f},"Use Abilities",180,InputType::KEY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class UseDefensiveTask:public TutorialTask{
|
||||
public:
|
||||
inline UseDefensiveTask():TutorialTask(){};
|
||||
private:
|
||||
InputGroup defensiveGroup;
|
||||
virtual inline void OnActivate()override final{
|
||||
defensiveGroup.ClearAllKeybinds();
|
||||
ADDKEYBIND(defensiveGroup,game->GetPlayer()->KEY_DEFENSIVE,CONTROLLER);
|
||||
ADDKEYBIND(defensiveGroup,game->GetPlayer()->KEY_DEFENSIVE,KEY);
|
||||
}
|
||||
virtual inline bool CompleteCondition()override final{
|
||||
return I(A::DEFENSIVE_COUNT)>=2;
|
||||
}
|
||||
virtual inline void OnComplete()override final{}
|
||||
virtual inline void Draw()const override final{
|
||||
if(Input::UsingGamepad()){
|
||||
defensiveGroup.DrawInput(game,{game->ScreenWidth()/2.f,48.f},"Defensive Ability",180,InputType::CONTROLLER);
|
||||
}else{
|
||||
defensiveGroup.DrawInput(game,{game->ScreenWidth()/2.f,48.f},"Defensive Ability",180,InputType::KEY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class UseRecoveryItemsTask:public TutorialTask{
|
||||
public:
|
||||
inline UseRecoveryItemsTask():TutorialTask(){};
|
||||
private:
|
||||
InputGroup itemsGroup;
|
||||
virtual inline void OnActivate()override final{
|
||||
itemsGroup.ClearAllKeybinds();
|
||||
if(!ISBLANK(game->GetLoadoutItem(0))){
|
||||
ADDKEYBIND(itemsGroup,game->GetPlayer()->KEY_ITEM1,CONTROLLER);
|
||||
ADDKEYBIND(itemsGroup,game->GetPlayer()->KEY_ITEM1,KEY);
|
||||
}
|
||||
if(!ISBLANK(game->GetLoadoutItem(1))){
|
||||
ADDKEYBIND(itemsGroup,game->GetPlayer()->KEY_ITEM2,CONTROLLER);
|
||||
ADDKEYBIND(itemsGroup,game->GetPlayer()->KEY_ITEM2,KEY);
|
||||
}
|
||||
if(!ISBLANK(game->GetLoadoutItem(2))){
|
||||
ADDKEYBIND(itemsGroup,game->GetPlayer()->KEY_ITEM3,CONTROLLER);
|
||||
ADDKEYBIND(itemsGroup,game->GetPlayer()->KEY_ITEM3,KEY);
|
||||
}
|
||||
}
|
||||
virtual inline bool CompleteCondition()override final{
|
||||
return I(A::ITEM_USE_COUNT)>=1;
|
||||
}
|
||||
virtual inline void OnComplete()override final{}
|
||||
virtual inline void Draw()const override final{
|
||||
if(Input::UsingGamepad()){
|
||||
itemsGroup.DrawInput(game,{game->ScreenWidth()/2.f,48.f},"Use Consumables",180,InputType::CONTROLLER);
|
||||
}else{
|
||||
itemsGroup.DrawInput(game,{game->ScreenWidth()/2.f,48.f},"Use Consumables",180,InputType::KEY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class BlacksmithTask:public TutorialTask{
|
||||
public:
|
||||
inline BlacksmithTask():TutorialTask(){};
|
||||
private:
|
||||
virtual inline void OnActivate()override final{
|
||||
Component<MenuComponent>(SHERMAN,"Leave Button")->SetGrayedOut(true);
|
||||
}
|
||||
virtual inline bool CompleteCondition()override final{
|
||||
return I(A::ITEM_USE_COUNT)>=1;
|
||||
}
|
||||
virtual inline void OnComplete()override final{
|
||||
Component<MenuComponent>(SHERMAN,"Leave Button")->SetGrayedOut(false);
|
||||
}
|
||||
virtual inline void Draw()const override final{
|
||||
std::string helpText="Visit #00FFD0\"Greg\" the Blacksmith#FFFFFF to browse craftable gear.";
|
||||
float textWidth=game->GetTextSizeProp(helpText).x;
|
||||
game->DrawShadowStringPropDecal({game->ScreenWidth()/2.f-textWidth/2.f,48.f},helpText);
|
||||
}
|
||||
};
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 7706
|
||||
#define VERSION_BUILD 7758
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -601,7 +601,7 @@
|
||||
<property name="Unlock Condition" propertytype="Level" value="CAMPAIGN_1_2"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="8" name="Hub Area" type="StagePlate" x="416" y="416" width="20" height="24">
|
||||
<object id="8" name="Camp" type="StagePlate" x="416" y="416" width="20" height="24">
|
||||
<properties>
|
||||
<property name="Map" propertytype="Level" value="HUB"/>
|
||||
<property name="Type" propertytype="StageType" value="HUB"/>
|
||||
|
@ -2,6 +2,10 @@ map_path = assets/Campaigns/
|
||||
|
||||
Levels
|
||||
{
|
||||
# Optionally specify
|
||||
# Skip Loadout Selection = True
|
||||
# To Skip the loadout selection screen for a given location.
|
||||
|
||||
INTRO_MAP
|
||||
{
|
||||
Map File = Intro_Map.tmx
|
||||
@ -105,6 +109,8 @@ Levels
|
||||
}
|
||||
HUB
|
||||
{
|
||||
Skip Loadout Selection = True
|
||||
|
||||
Map File = Hub_v2.tmx
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user