Upstream merge with released demo build.
@ -295,6 +295,36 @@
|
||||
"type": "string",
|
||||
"value": "None"
|
||||
},
|
||||
{
|
||||
"name": "Dev Completion Time - Ranger (s)",
|
||||
"type": "float",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "Dev Completion Time - Thief (s)",
|
||||
"type": "float",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "Dev Completion Time - Trapper (s)",
|
||||
"type": "float",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "Dev Completion Time - Warrior (s)",
|
||||
"type": "float",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "Dev Completion Time - Witch (s)",
|
||||
"type": "float",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "Dev Completion Time - Wizard (s)",
|
||||
"type": "float",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "Level Type",
|
||||
"propertyType": "LevelType",
|
||||
@ -618,6 +648,20 @@
|
||||
"tileset"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "#fff7ff5d",
|
||||
"drawFill": true,
|
||||
"id": 40,
|
||||
"members": [
|
||||
],
|
||||
"name": "TrialClock",
|
||||
"type": "class",
|
||||
"useAs": [
|
||||
"property",
|
||||
"object",
|
||||
"project"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "#ffa40aa4",
|
||||
"drawFill": true,
|
||||
|
@ -206,6 +206,10 @@
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
<CustomBuildStep>
|
||||
<Command>
|
||||
</Command>
|
||||
</CustomBuildStep>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Emscripten|Win32'">
|
||||
<Link>
|
||||
@ -519,6 +523,10 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SteamStatsReceivedHandler.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="steam\isteamapps.h" />
|
||||
<ClInclude Include="steam\isteamappticket.h" />
|
||||
<ClInclude Include="steam\isteamclient.h" />
|
||||
@ -816,6 +824,10 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SteamStatsReceivedHandler.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SwordSlash.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
@ -844,6 +856,7 @@
|
||||
<ClCompile Include="Wolf.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\read_debug_log.ps1" />
|
||||
<None Include="ClassDiagram.cd" />
|
||||
<None Include="ClassDiagram2.cd" />
|
||||
<None Include="cpp.hint" />
|
||||
@ -851,6 +864,7 @@
|
||||
<None Include="steam\steam_api.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="assets\config\Achievements.txt" />
|
||||
<Text Include="assets\config\audio\audio.txt" />
|
||||
<Text Include="assets\config\audio\bgm.txt" />
|
||||
<Text Include="assets\config\audio\environmentalaudio.txt" />
|
||||
|
@ -998,6 +998,9 @@
|
||||
<ClCompile Include="SteamKeyboardCallbackHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SteamStatsReceivedHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
@ -1009,6 +1012,7 @@
|
||||
<None Include="steam\steam_api.json">
|
||||
<Filter>Header Files\steam</Filter>
|
||||
</None>
|
||||
<None Include="..\read_debug_log.ps1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="InitialConcept.txt">
|
||||
@ -1159,6 +1163,9 @@
|
||||
<Text Include="assets\config\credits.txt">
|
||||
<Filter>Configurations</Filter>
|
||||
</Text>
|
||||
<Text Include="assets\config\Achievements.txt">
|
||||
<Filter>Configurations</Filter>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="assets\heart.ico">
|
||||
|
@ -80,6 +80,7 @@ All rights reserved.
|
||||
#include "LoadingScreen.h"
|
||||
#include "Tutorial.h"
|
||||
#include "SteamKeyboardCallbackHandler.h"
|
||||
#include "SteamStatsReceivedHandler.h"
|
||||
|
||||
INCLUDE_EMITTER_LIST
|
||||
INCLUDE_ITEM_CATEGORIES
|
||||
@ -232,6 +233,9 @@ AiL::AiL()
|
||||
std::string CREDITS_CONFIG = CONFIG_PATH + "credits_config"_S;
|
||||
utils::datafile::Read(DATA,CREDITS_CONFIG);
|
||||
|
||||
std::string ACHIEVEMENT_CONFIG = CONFIG_PATH + "achievement_config"_S;
|
||||
utils::datafile::Read(DATA,ACHIEVEMENT_CONFIG);
|
||||
|
||||
utils::datafile::DEBUG_ACCESS_OPTIONS="debug_access_options"_I;
|
||||
|
||||
sAppName = "GAME_NAME"_S;
|
||||
@ -334,6 +338,9 @@ bool AiL::OnUserCreate(){
|
||||
if(steamKeyboardCallbackListener==nullptr){
|
||||
steamKeyboardCallbackListener=new SteamKeyboardCallbackHandler();
|
||||
}
|
||||
if(steamStatsReceivedHandlerListener==nullptr){
|
||||
steamStatsReceivedHandlerListener=new SteamStatsReceivedHandler();
|
||||
}
|
||||
#endif
|
||||
|
||||
utils::datafile::INITIAL_SETUP_COMPLETE=true;
|
||||
@ -446,6 +453,7 @@ void AiL::HandleUserInput(float fElapsedTime){
|
||||
if(KEY_MENU.Released()){
|
||||
Menu::OpenMenu(MenuType::PAUSE);
|
||||
}
|
||||
float animationSpd=0.f;
|
||||
if(player->GetVelocity().mag()<"Player.Move Allowed Velocity Lower Limit"_F&&player->CanMove()){
|
||||
auto GetPlayerStaircaseDirection=[&](){
|
||||
for(LayerTag&layer:MAP_DATA[GetCurrentLevel()].LayerData){
|
||||
@ -462,20 +470,26 @@ void AiL::HandleUserInput(float fElapsedTime){
|
||||
std::string staircaseDirection=GetPlayerStaircaseDirection();
|
||||
vf2d newAimingAngle{};
|
||||
if(RightHeld()){
|
||||
player->SetX(player->GetX()+fElapsedTime*"Player.MoveSpd"_F*player->GetMoveSpdMult());
|
||||
player->movementVelocity.x="Player.MoveSpd"_F;
|
||||
float moveAmt="Player.MoveSpd"_F;
|
||||
if(Input::UsingGamepad()&&KEY_SCROLLHORZ_L.Analog()>=0.2f){
|
||||
float controllerAmt=abs(KEY_SCROLLHORZ_L.Analog());
|
||||
if(controllerAmt>=0.6f)controllerAmt=1.f; //Edge zone.
|
||||
if(controllerAmt>animationSpd){
|
||||
animationSpd=controllerAmt;
|
||||
}
|
||||
moveAmt*=controllerAmt;
|
||||
}else animationSpd=1.f;
|
||||
player->SetX(player->GetX()+fElapsedTime*moveAmt*player->GetMoveSpdMult());
|
||||
player->movementVelocity.x=moveAmt*fElapsedTime*player->GetMoveSpdMult();
|
||||
if(staircaseDirection=="RIGHT"){
|
||||
player->SetY(player->GetY()-"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult());
|
||||
player->movementVelocity.y=-"Player.StaircaseClimbSpd"_F;
|
||||
player->movementVelocity.y=-"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult();
|
||||
} else
|
||||
if(staircaseDirection=="LEFT"){
|
||||
player->SetY(player->GetY()+"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult());
|
||||
player->movementVelocity.y="Player.StaircaseClimbSpd"_F;
|
||||
player->movementVelocity.y="Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult();
|
||||
}
|
||||
player->SetFacingDirection(RIGHT);
|
||||
if(player->GetState()==State::NORMAL||player->GetState()==State::PREP_CAST){
|
||||
player->UpdateWalkingAnimation(RIGHT);
|
||||
}
|
||||
|
||||
newAimingAngle+=vf2d{1,0};
|
||||
|
||||
@ -483,21 +497,25 @@ void AiL::HandleUserInput(float fElapsedTime){
|
||||
heldDownMovementKey=true;
|
||||
}
|
||||
if(LeftHeld()){
|
||||
player->SetX(player->GetX()-fElapsedTime*"Player.MoveSpd"_F*player->GetMoveSpdMult());
|
||||
player->movementVelocity.x=-"Player.MoveSpd"_F;
|
||||
float moveAmt="Player.MoveSpd"_F;
|
||||
if(Input::UsingGamepad()&&KEY_SCROLLHORZ_L.Analog()<=-0.2f){
|
||||
float controllerAmt=abs(KEY_SCROLLHORZ_L.Analog());
|
||||
controllerAmt+=0.2f;
|
||||
if(controllerAmt>=0.6f)controllerAmt=1.f; //Edge zone.
|
||||
if(controllerAmt>animationSpd){
|
||||
animationSpd=controllerAmt;
|
||||
}
|
||||
moveAmt*=controllerAmt;
|
||||
}else animationSpd=1.f;
|
||||
player->SetX(player->GetX()-fElapsedTime*moveAmt*player->GetMoveSpdMult());
|
||||
player->movementVelocity.x=-moveAmt*fElapsedTime*player->GetMoveSpdMult();
|
||||
if(staircaseDirection=="RIGHT"){
|
||||
player->SetY(player->GetY()+"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult());
|
||||
player->movementVelocity.y="Player.StaircaseClimbSpd"_F;
|
||||
player->movementVelocity.y="Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult();
|
||||
} else
|
||||
if(staircaseDirection=="LEFT"){
|
||||
player->SetY(player->GetY()-"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult());
|
||||
player->movementVelocity.y=-"Player.StaircaseClimbSpd"_F;
|
||||
}
|
||||
if(setIdleAnimation){
|
||||
player->SetFacingDirection(LEFT);
|
||||
if(player->GetState()==State::NORMAL||player->GetState()==State::PREP_CAST){
|
||||
player->UpdateWalkingAnimation(LEFT);
|
||||
}
|
||||
player->movementVelocity.y=-"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult();
|
||||
}
|
||||
|
||||
newAimingAngle-=vf2d{1,0};
|
||||
@ -506,14 +524,18 @@ void AiL::HandleUserInput(float fElapsedTime){
|
||||
heldDownMovementKey=true;
|
||||
}
|
||||
if(UpHeld()){
|
||||
player->SetY(player->GetY()-fElapsedTime*"Player.MoveSpd"_F*player->GetMoveSpdMult());
|
||||
player->movementVelocity.y=-"Player.MoveSpd"_F*fElapsedTime;
|
||||
if(setIdleAnimation){
|
||||
player->SetFacingDirection(UP);
|
||||
if(player->GetState()==State::NORMAL||player->GetState()==State::PREP_CAST){
|
||||
player->UpdateWalkingAnimation(UP);
|
||||
float moveAmt="Player.MoveSpd"_F;
|
||||
if(Input::UsingGamepad()&&KEY_SCROLLVERT_L.Analog()<=-0.2f){
|
||||
float controllerAmt=abs(KEY_SCROLLVERT_L.Analog());
|
||||
controllerAmt+=0.2f;
|
||||
if(controllerAmt>=0.6f)controllerAmt=1.f; //Edge zone.
|
||||
if(controllerAmt>animationSpd){
|
||||
animationSpd=controllerAmt;
|
||||
}
|
||||
}
|
||||
moveAmt*=controllerAmt;
|
||||
}else animationSpd=1.f;
|
||||
player->SetY(player->GetY()-fElapsedTime*moveAmt*player->GetMoveSpdMult());
|
||||
player->movementVelocity.y=-moveAmt*fElapsedTime*player->GetMoveSpdMult();
|
||||
|
||||
newAimingAngle-=vf2d{0,1};
|
||||
|
||||
@ -521,14 +543,18 @@ void AiL::HandleUserInput(float fElapsedTime){
|
||||
heldDownMovementKey=true;
|
||||
}
|
||||
if(DownHeld()){
|
||||
player->SetY(player->GetY()+fElapsedTime*"Player.MoveSpd"_F*player->GetMoveSpdMult());
|
||||
player->movementVelocity.y="Player.MoveSpd"_F*fElapsedTime;
|
||||
if(setIdleAnimation){
|
||||
player->SetFacingDirection(DOWN);
|
||||
if(player->GetState()==State::NORMAL||player->GetState()==State::PREP_CAST){
|
||||
player->UpdateWalkingAnimation(DOWN);
|
||||
float moveAmt="Player.MoveSpd"_F;
|
||||
if(Input::UsingGamepad()&&KEY_SCROLLVERT_L.Analog()>=0.2f){
|
||||
float controllerAmt=abs(KEY_SCROLLVERT_L.Analog());
|
||||
controllerAmt+=0.2f;
|
||||
if(controllerAmt>=0.6f)controllerAmt=1.f; //Edge zone.
|
||||
if(controllerAmt>animationSpd){
|
||||
animationSpd=controllerAmt;
|
||||
}
|
||||
}
|
||||
moveAmt*=controllerAmt;
|
||||
}else animationSpd=1.f;
|
||||
player->SetY(player->GetY()+fElapsedTime*moveAmt*player->GetMoveSpdMult());
|
||||
player->movementVelocity.y=moveAmt*fElapsedTime*player->GetMoveSpdMult();
|
||||
|
||||
newAimingAngle+=vf2d{0,1};
|
||||
|
||||
@ -539,6 +565,23 @@ void AiL::HandleUserInput(float fElapsedTime){
|
||||
player->aimingAngle=newAimingAngle.norm().polar();
|
||||
}
|
||||
}
|
||||
if(heldDownMovementKey){
|
||||
if(abs(player->movementVelocity.x)>abs(player->movementVelocity.y)){ //Greater Horizontal movement.
|
||||
if(player->movementVelocity.x!=0.f){
|
||||
player->SetFacingDirection(player->movementVelocity.x>0?RIGHT:LEFT);
|
||||
if(player->GetState()==State::NORMAL||player->GetState()==State::PREP_CAST){
|
||||
player->UpdateWalkingAnimation(player->GetFacingDirection(),animationSpd);
|
||||
}
|
||||
}
|
||||
}else{ //Greater Vertical movement.
|
||||
if(player->movementVelocity.y!=0.f){
|
||||
player->SetFacingDirection(player->movementVelocity.y>0?DOWN:UP);
|
||||
if(player->GetState()==State::NORMAL||player->GetState()==State::PREP_CAST){
|
||||
player->UpdateWalkingAnimation(player->GetFacingDirection(),animationSpd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(UpReleased()){
|
||||
player->SetLastReleasedMovementKey(UP);
|
||||
player->movementVelocity.y=0;
|
||||
@ -605,7 +648,7 @@ void AiL::HandleUserInput(float fElapsedTime){
|
||||
}
|
||||
|
||||
if(heldDownMovementKey){
|
||||
player->footstepTimer+=GetElapsedTime();
|
||||
player->footstepTimer+=GetElapsedTime()*animationSpd;
|
||||
if(player->footstepTimer>"Player.Footstep Timer"_F){
|
||||
player->footstepTimer-="Player.Footstep Timer"_F;
|
||||
|
||||
@ -2461,6 +2504,9 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
|
||||
});
|
||||
|
||||
LoadingScreen::AddPhase([&](){
|
||||
STEAMUSERSTATS(
|
||||
SteamUserStats()->StoreStats();
|
||||
)
|
||||
ClearGarbage();
|
||||
return true;
|
||||
});
|
||||
@ -2693,6 +2739,9 @@ bool Steam_Init(){
|
||||
LOG(std::format("STEAM[{}]: {}",severity,std::string(message)));
|
||||
});
|
||||
}
|
||||
STEAMUSERSTATS(
|
||||
SteamUserStats()->RequestCurrentStats();
|
||||
)
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@ -3705,7 +3754,6 @@ void AiL::ResetGame(bool changeToMainMenu){
|
||||
for(int i=0;i<GetLoadoutSize();i++){
|
||||
game->ClearLoadoutItem(i);
|
||||
}
|
||||
Unlock::unlocks.clear();
|
||||
Unlock::Initialize();
|
||||
State_OverworldMap::SetStageMarker("Story I");
|
||||
State_OverworldMap::UpdateCurrentConnectionPoint(*State_OverworldMap::currentConnectionPoint);
|
||||
@ -3885,4 +3933,8 @@ void AiL::ActivateActionSetForAllControllers(InputActionSetHandle_t actionSetHan
|
||||
SteamInput()->ActivateActionSet(Input::steamControllers[i],actionSetHandle);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const float AiL::GetEncounterDuration()const{
|
||||
return encounterDuration;
|
||||
}
|
@ -59,6 +59,7 @@ All rights reserved.
|
||||
|
||||
|
||||
class SteamKeyboardCallbackHandler;
|
||||
class SteamStatsReceivedHandler;
|
||||
|
||||
#define CreateBullet(type) BULLET_LIST.push_back(std::make_unique<type>(type
|
||||
#define EndBullet ));
|
||||
@ -189,6 +190,7 @@ private:
|
||||
#endif
|
||||
Audio audioEngine;
|
||||
SteamKeyboardCallbackHandler*steamKeyboardCallbackListener=nullptr;
|
||||
SteamStatsReceivedHandler*steamStatsReceivedHandlerListener=nullptr;
|
||||
public:
|
||||
AiL();
|
||||
bool OnUserCreate() override;
|
||||
@ -316,6 +318,7 @@ public:
|
||||
rcode LoadResource(Renderable&renderable,std::string_view imgPath,bool filter=false,bool clamp=true);
|
||||
void UpdateMonsters();
|
||||
void ActivateActionSetForAllControllers(InputActionSetHandle_t actionSetHandle);
|
||||
const float GetEncounterDuration()const;
|
||||
|
||||
struct TileGroupData{
|
||||
vi2d tilePos;
|
||||
|
@ -61,25 +61,25 @@ void sig::Animation::InitializeAnimations(){
|
||||
};
|
||||
|
||||
auto SetupClassWalkIdleAnimations=[&](Renderable&sheet,std::string className){
|
||||
Animate2D::FrameSequence pl_walk_s{0.2f};
|
||||
Animate2D::FrameSequence pl_walk_s{"Player.WalkingFrameSpd"_F};
|
||||
pl_walk_s.AddFrame({&sheet,{vi2d{0,0}*24,{24,24}}});
|
||||
pl_walk_s.AddFrame({&sheet,{vi2d{1,0}*24,{24,24}}});
|
||||
pl_walk_s.AddFrame({&sheet,{vi2d{0,0}*24,{24,24}}});
|
||||
pl_walk_s.AddFrame({&sheet,{vi2d{2,0}*24,{24,24}}});
|
||||
ANIMATION_DATA[className+"_WALK_S"]=pl_walk_s;
|
||||
Animate2D::FrameSequence pl_walk_e{0.2f};
|
||||
Animate2D::FrameSequence pl_walk_e{"Player.WalkingFrameSpd"_F};
|
||||
pl_walk_e.AddFrame({&sheet,{vi2d{0,3}*24,{24,24}}});
|
||||
pl_walk_e.AddFrame({&sheet,{vi2d{1,3}*24,{24,24}}});
|
||||
pl_walk_e.AddFrame({&sheet,{vi2d{0,3}*24,{24,24}}});
|
||||
pl_walk_e.AddFrame({&sheet,{vi2d{2,3}*24,{24,24}}});
|
||||
ANIMATION_DATA[className+"_WALK_E"]=pl_walk_e;
|
||||
Animate2D::FrameSequence pl_walk_w{0.2f};
|
||||
Animate2D::FrameSequence pl_walk_w{"Player.WalkingFrameSpd"_F};
|
||||
pl_walk_w.AddFrame({&sheet,{vi2d{0,2}*24,{24,24}}});
|
||||
pl_walk_w.AddFrame({&sheet,{vi2d{1,2}*24,{24,24}}});
|
||||
pl_walk_w.AddFrame({&sheet,{vi2d{0,2}*24,{24,24}}});
|
||||
pl_walk_w.AddFrame({&sheet,{vi2d{2,2}*24,{24,24}}});
|
||||
ANIMATION_DATA[className+"_WALK_W"]=pl_walk_w;
|
||||
Animate2D::FrameSequence pl_walk_n{0.2f};
|
||||
Animate2D::FrameSequence pl_walk_n{"Player.WalkingFrameSpd"_F};
|
||||
pl_walk_n.AddFrame({&sheet,{vi2d{0,1}*24,{24,24}}});
|
||||
pl_walk_n.AddFrame({&sheet,{vi2d{1,1}*24,{24,24}}});
|
||||
pl_walk_n.AddFrame({&sheet,{vi2d{0,1}*24,{24,24}}});
|
||||
|
@ -50,6 +50,9 @@ All rights reserved.
|
||||
#include "SoundEffect.h"
|
||||
#include "ProgressBar.h"
|
||||
#include "MenuItemLabel.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_GFX
|
||||
@ -99,6 +102,17 @@ namespace CharacterMenuWindow{
|
||||
if(!comp.expired()){
|
||||
if(SelectedEquipIsDifferent(comp)){ //If we find that the opposite ring slot is equipped to us, this would be an item swap or the exact same ring, therefore no stat calculations apply.
|
||||
Inventory::EquipItem(comp.lock()->GetItem(),EquipSlot(comp.lock()->I(Attribute::EQUIP_TYPE)));
|
||||
|
||||
#pragma region Fully Decked Out Achievement
|
||||
STEAMUSERSTATS(
|
||||
datafile&unlock=DATA.GetProperty("Achievement.Equip Unlocks.Fully Decked Out");
|
||||
if(Inventory::EquipsFullyMaxedOut(unlock["Weapon Max Level"].GetInt(),unlock["Armor Max Level"].GetInt())){
|
||||
SteamUserStats()->SetAchievement(unlock["API Name"].GetString().c_str());
|
||||
SteamUserStats()->StoreStats();
|
||||
}
|
||||
)
|
||||
#pragma endregion
|
||||
|
||||
if(Menu::IsCurrentlyActive(data.menu.GetType())){
|
||||
SoundEffect::PlaySFX(comp.lock()->GetItem().lock()->UseSound(),SoundEffect::CENTERED);
|
||||
}
|
||||
|
@ -36,12 +36,15 @@ All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#pragma once
|
||||
#include "Ability.h"
|
||||
#include "Animation.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "DEFINES.h"
|
||||
#include "olcUTIL_DataFile.h"
|
||||
|
||||
#undef GetClassInfo
|
||||
|
||||
//Classes have bit-wise operator capabilities.
|
||||
INCLUDE_DATA
|
||||
|
||||
enum Class{
|
||||
ANY=0,
|
||||
WARRIOR=1,
|
||||
@ -49,5 +52,15 @@ enum Class{
|
||||
RANGER=4,
|
||||
TRAPPER=8,
|
||||
WIZARD=16,
|
||||
WITCH=32
|
||||
WITCH=32,
|
||||
};
|
||||
|
||||
namespace classutils{//Classes have bit-wise operator capabilities.
|
||||
static inline Class StringToClass(std::string className){
|
||||
const std::vector<std::string>&classList=DATA["class_list"].GetValues();
|
||||
auto it=std::find(classList.begin(),classList.end(),className);
|
||||
if(it==classList.end())ERR(std::format("WARNING! Class {} does not exist!",className));
|
||||
int element=int(std::distance(classList.begin(),it));
|
||||
return Class(1<<element); //Yes...It's bitwise flags, who in god's name knows why I did this.
|
||||
};
|
||||
};
|
@ -54,15 +54,7 @@ struct ClassInfo{
|
||||
Ability*rightClickAbility;
|
||||
};
|
||||
|
||||
class classutils{
|
||||
public:
|
||||
static inline Class StringToClass(std::string className){
|
||||
const std::vector<std::string>&classList=DATA["class_list"].GetValues();
|
||||
auto it=std::find(classList.begin(),classList.end(),className);
|
||||
if(it==classList.end())ERR(std::format("WARNING! Class {} does not exist!",className));
|
||||
int element=int(std::distance(classList.begin(),it));
|
||||
return Class(1<<element); //Yes...It's bitwise flags, who in god's name knows why I did this.
|
||||
};
|
||||
namespace classutils{
|
||||
static inline ClassInfo GetClassInfo(std::string className){
|
||||
ClassInfo data{
|
||||
DATA.GetProperty(className+".ClassName").GetString(),
|
||||
|
@ -47,6 +47,9 @@ All rights reserved.
|
||||
#include "SoundEffect.h"
|
||||
#include "ClassInfo.h"
|
||||
#include "RowInventoryScrollableWindowComponent.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_DATA
|
||||
@ -840,8 +843,10 @@ void Inventory::EquipItem(const std::weak_ptr<Item>it,EquipSlot slot){
|
||||
if(equippedSlot!=EquipSlot::NONE)UnequipItem(equippedSlot);
|
||||
if(!GetEquip(slot).expired())UnequipItem(slot);
|
||||
Inventory::equipment[slot]=it;
|
||||
|
||||
game->GetPlayer()->RecalculateEquipStats();
|
||||
};
|
||||
|
||||
void Inventory::UnequipItem(EquipSlot slot){
|
||||
Inventory::equipment[slot]=Item::BLANK;
|
||||
game->GetPlayer()->RecalculateEquipStats();
|
||||
@ -923,6 +928,33 @@ void Item::EnhanceItem(uint8_t qty){
|
||||
if(enhancementLevel+1>"Item.Item Max Enhancement Level"_I)ERR("WARNING! Attempted to enhance "<<DisplayName()<<" beyond the cap of "<<"Item.Item Max Enhancement Level"_I);
|
||||
|
||||
enhancementLevel++;
|
||||
|
||||
#pragma region Achievements
|
||||
STEAMUSERSTATS(
|
||||
// Fully Decked Out Achievement
|
||||
datafile&unlock=DATA.GetProperty("Achievement.Equip Unlocks.Fully Decked Out");
|
||||
if(Inventory::EquipsFullyMaxedOut(unlock["Weapon Max Level"].GetInt(),unlock["Armor Max Level"].GetInt())){
|
||||
SteamUserStats()->SetAchievement(unlock["API Name"].GetString().c_str());
|
||||
SteamUserStats()->StoreStats();
|
||||
}
|
||||
// Equipment achievement unlocks
|
||||
for(auto&[key,size]:DATA.GetProperty("Achievement.Equip Unlocks")){
|
||||
datafile&unlock=DATA.GetProperty(std::format("Achievement.Equip Unlocks.{}",key));
|
||||
if(!(unlock.HasProperty("Upgrade Requirement")&&unlock.HasProperty("Equip Slot")))continue; //Ignore any achievements that don't have an upgrade requirement/equipment slot defined.
|
||||
if(EnhancementLevel()>=unlock["Upgrade Requirement"].GetInt()){
|
||||
EquipSlot validSlots=EquipSlot::NONE;
|
||||
for(const std::string&slot:unlock["Equip Slot"].GetValues()){
|
||||
validSlots|=ItemInfo::StringToEquipSlot(slot); //Collect all the bits that this equipment can fall under.
|
||||
}
|
||||
if(GetEquipSlot()&validSlots){
|
||||
//This piece of gear matches one of the provided slots.
|
||||
SteamUserStats()->SetAchievement(unlock["API Name"].GetString().c_str());
|
||||
SteamUserStats()->StoreStats();
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
#pragma endregion
|
||||
|
||||
const CraftingRequirement&consumedResources=GetEnhancementInfo()[EnhancementLevel()].craftingRequirement;
|
||||
|
||||
@ -1284,4 +1316,25 @@ void Item::Lock(){
|
||||
}
|
||||
void Item::Unlock(){
|
||||
locked=false;
|
||||
}
|
||||
|
||||
//Specifically for the "Fully Decked Out" achievement.
|
||||
const bool Inventory::EquipsFullyMaxedOut(int maxWeaponLevel,int maxArmorLevel){
|
||||
for(int i=int(EquipSlot::HELMET);i<=int(EquipSlot::RING2);i<<=1){
|
||||
EquipSlot slot=EquipSlot(i);
|
||||
if(!ISBLANK(Inventory::GetEquip(slot))){
|
||||
std::shared_ptr<Item>equip=Inventory::GetEquip(slot).lock();
|
||||
if(!(equip->IsAccessory()||
|
||||
(equip->IsWeapon()&&equip->EnhancementLevel()>=maxWeaponLevel)||
|
||||
(equip->IsArmor()&&equip->EnhancementLevel()>=maxArmorLevel))
|
||||
){
|
||||
return false;
|
||||
}
|
||||
}else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const EquipSlot ItemInfo::StringToEquipSlot(std::string_view slotName){
|
||||
return nameToEquipSlot[std::string(slotName)];
|
||||
}
|
@ -269,6 +269,7 @@ public:
|
||||
static void AddLoadoutItemUsed(IT item,int slot);
|
||||
static void ResetLoadoutItemsUsed();
|
||||
static void GivePlayerLoadoutItemsUsed();
|
||||
static const bool EquipsFullyMaxedOut(int maxWeaponLevel=10,int maxArmorLevel=10);
|
||||
|
||||
static bool SwapItems(ITCategory itemCategory,uint32_t slot1,uint32_t slot2);
|
||||
//Makes sure this is a valid category. Will error out if it doesn't exist! Use for ERROR HANDLING!
|
||||
@ -338,6 +339,7 @@ public:
|
||||
const std::string&Description()const;
|
||||
const ITCategory Category()const;
|
||||
const::Decal*const Decal()const;
|
||||
static const EquipSlot StringToEquipSlot(std::string_view slotName);
|
||||
/*
|
||||
For the useFunc, return true if the item can be used, false otherwise.
|
||||
*/
|
||||
|
@ -79,8 +79,10 @@ void Menu::InitializeLevelCompleteWindow(){
|
||||
};
|
||||
|
||||
auto nextButtonAction=[](MenuFuncData data){
|
||||
Unlock::UnlockArea(State_OverworldMap::GetCurrentConnectionPoint().map);
|
||||
Merchant::RandomizeTravelingMerchant();
|
||||
if(Component<MenuLabel>(LEVEL_COMPLETE,"Stage Complete Label")->GetLabel()!="Stage Summary"){ //If the label says stage summary, we didn't actually complete the level. Don't unlock anything new for the player.
|
||||
Unlock::UnlockArea(State_OverworldMap::GetCurrentConnectionPoint().map);
|
||||
Merchant::RandomizeTravelingMerchant();
|
||||
}
|
||||
State_LevelComplete::TurnOffXPSound();
|
||||
GameState::ChangeState(States::GAME_HUB,0.25f);
|
||||
return true;
|
||||
|
@ -47,6 +47,10 @@ All rights reserved.
|
||||
#include "MonsterAttribute.h"
|
||||
#include "ItemDrop.h"
|
||||
#include "SoundEffect.h"
|
||||
#include "Unlock.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
|
||||
INCLUDE_ANIMATION_DATA
|
||||
INCLUDE_MONSTER_DATA
|
||||
@ -723,6 +727,27 @@ void Monster::OnDeath(){
|
||||
}
|
||||
}
|
||||
|
||||
Unlock::IncreaseKillCount();
|
||||
|
||||
STEAMUSERSTATS(
|
||||
for(auto&[key,size]:DATA.GetProperty("Achievement.Kill Unlocks")){
|
||||
//Monster-specific achievement unlocks.
|
||||
datafile&unlock=DATA.GetProperty(std::format("Achievement.Kill Unlocks.{}",key));
|
||||
if(unlock.HasProperty("Monster Name")){
|
||||
if(unlock["Monster Name"].GetString()!=GetName())continue;
|
||||
if(unlock.HasProperty("Time Limit")&&isBoss){
|
||||
if(game->GetEncounterDuration()<=unlock["Time Limit"].GetReal()){
|
||||
SteamUserStats()->SetAchievement(unlock["API Name"].GetString().c_str());
|
||||
SteamUserStats()->StoreStats();
|
||||
}
|
||||
}else{
|
||||
SteamUserStats()->SetAchievement(unlock["API Name"].GetString().c_str());
|
||||
SteamUserStats()->StoreStats();
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
if(hasStrategyDeathFunction){
|
||||
GameEvent::AddEvent(std::make_unique<MonsterStrategyGameEvent>(strategyDeathFunc,*this,MONSTER_DATA[name].GetAIStrategy()));
|
||||
}
|
||||
|
@ -57,6 +57,9 @@ All rights reserved.
|
||||
#include "GameSettings.h"
|
||||
#include "Unlock.h"
|
||||
#include "Tutorial.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
|
||||
INCLUDE_MONSTER_DATA
|
||||
INCLUDE_MONSTER_LIST
|
||||
@ -777,9 +780,9 @@ void Player::AddAnimation(std::string state){
|
||||
animation.AddState(state,ANIMATION_DATA.at(state));
|
||||
}
|
||||
|
||||
void Player::UpdateAnimation(std::string animState,int specificClass){
|
||||
void Player::UpdateAnimation(std::string animState,int specificClass, const float frameMult){
|
||||
if(specificClass==ANY||specificClass&GetClass()){
|
||||
animation.ChangeState(internal_animState,animState);
|
||||
animation.ChangeState(internal_animState,animState,frameMult);
|
||||
}
|
||||
}
|
||||
|
||||
@ -868,7 +871,7 @@ void Player::Spin(float duration,float spinSpd){
|
||||
spin_angle=0;
|
||||
}
|
||||
|
||||
void Player::UpdateWalkingAnimation(Key direction){
|
||||
void Player::UpdateWalkingAnimation(Key direction, const float frameMult){
|
||||
std::string anim;
|
||||
switch(direction){
|
||||
case UP:anim=GetWalkNAnimation();break;
|
||||
@ -876,7 +879,7 @@ void Player::UpdateWalkingAnimation(Key direction){
|
||||
case DOWN:anim=GetWalkSAnimation();break;
|
||||
case LEFT:anim=GetWalkWAnimation();break;
|
||||
}
|
||||
UpdateAnimation(anim);
|
||||
UpdateAnimation(anim,0,frameMult);
|
||||
}
|
||||
|
||||
void Player::UpdateIdleAnimation(Key direction){
|
||||
@ -1301,9 +1304,8 @@ void Player::AddXP(const uint32_t xpGain){
|
||||
currentLevelXP+=xpGain;
|
||||
totalXPEarned+=xpGain;
|
||||
if(Level()<LevelCap()){
|
||||
uint32_t nextLevelXP=NextLevelXPRequired();
|
||||
while(currentLevelXP>=nextLevelXP){
|
||||
currentLevelXP-=nextLevelXP;
|
||||
while(currentLevelXP>=NextLevelXPRequired()){
|
||||
currentLevelXP-=NextLevelXPRequired();
|
||||
SetLevel(Level()+1);
|
||||
OnLevelUp();
|
||||
}
|
||||
@ -1324,6 +1326,18 @@ void Player::OnLevelUp(){
|
||||
stats.SetBaseStat("Health",GetBaseStat("Health")+hpGrowthRate);
|
||||
stats.SetBaseStat("Attack",GetBaseStat("Attack")+atkGrowthRate);
|
||||
Heal(GetBaseStat("Health"));
|
||||
|
||||
STEAMUSERSTATS(
|
||||
for(auto&[key,size]:DATA.GetProperty("Achievement.Class Unlocks")){
|
||||
datafile&unlock=DATA.GetProperty(std::format("Achievement.Class Unlocks.{}",key));
|
||||
if(classutils::StringToClass(unlock["Class Requirement"].GetString())==GetClass()&&
|
||||
Level()-1<unlock["Level Requirement"].GetInt()&&
|
||||
Level()==unlock["Level Requirement"].GetInt()){
|
||||
SteamUserStats()->SetAchievement(unlock["API Name"].GetString().c_str());
|
||||
SteamUserStats()->StoreStats();
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
const uint8_t Player::LevelCap()const{
|
||||
return levelCap;
|
||||
@ -1429,17 +1443,18 @@ const vf2d Player::GetAimingLocation(bool useWalkDir,bool invert){
|
||||
vf2d closestPoint={std::numeric_limits<float>::max(),std::numeric_limits<float>::max()};
|
||||
for(Monster&m:MONSTER_LIST){
|
||||
if(m.IsAlive()){
|
||||
float distToMonster=geom2d::line<float>(GetPos(),m.GetPos()).length();
|
||||
geom2d::line<float>aimingLine=geom2d::line<float>(GetPos(),m.GetPos());
|
||||
vf2d aimingPoint=aimingLine.rpoint((invert?-1.f:1.f)*operator""_Pixels("Player.Aiming Cursor Max Distance"_F));
|
||||
float distToMonster=aimingLine.length();
|
||||
float distToClosestPoint=geom2d::line<float>(GetPos(),closestPoint).length();
|
||||
if(distToClosestPoint>distToMonster&&distToMonster<=operator""_Pixels("Player.Auto Aim Detection Distance"_F)){
|
||||
closestPoint=aimingPoint;
|
||||
closestPoint=m.GetPos();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(closestPoint!=vf2d{std::numeric_limits<float>::max(),std::numeric_limits<float>::max()}){
|
||||
return game->GetScreenSize()/2+closestPoint-GetPos();
|
||||
geom2d::line<float>aimingLine=geom2d::line<float>(GetPos(),closestPoint);
|
||||
vf2d aimingPoint=aimingLine.rpoint(invert?(-operator""_Pixels("Player.Aiming Cursor Max Distance"_F)):std::min(aimingLine.length()+24.f,float(operator""_Pixels("Player.Aiming Cursor Max Distance"_F))));
|
||||
return game->GetScreenSize()/2+aimingPoint-GetPos();
|
||||
}else
|
||||
return game->GetScreenSize()/2+vf2d{float(operator""_Pixels("Player.Aiming Cursor Max Distance"_F)),aimingAngle.y}.cart();
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ public:
|
||||
vf2d GetVelocity();
|
||||
bool HasIframes();
|
||||
void Update(float fElapsedTime);
|
||||
void UpdateWalkingAnimation(Key direction);
|
||||
void UpdateWalkingAnimation(Key direction, const float frameMult=1.f);
|
||||
void UpdateIdleAnimation(Key direction);
|
||||
//The range is the search range in tiles.
|
||||
bool CanPathfindTo(vf2d pos,vf2d targetPos,float range=8);
|
||||
@ -176,9 +176,8 @@ public:
|
||||
bool Hurt(int damage,bool onUpperLevel,float z);
|
||||
//Return false if healing was not possible.
|
||||
bool Heal(int damage,bool suppressDamageNumber=false);
|
||||
//specificClass is a bitwise-combination of classes from the Class enum. It makes sure certain animations only play if you are a certain class.
|
||||
//Set force to true to force the animation to restart evne if the animation were already playing.
|
||||
void UpdateAnimation(std::string animState,int specificClass=ANY);
|
||||
//specificClass is a bitwise-combination of classes from the Class enum. It makes sure certain animations only play if you are a certain class.=
|
||||
void UpdateAnimation(std::string animState,int specificClass=ANY,const float frameMult=1.f);
|
||||
Animate2D::Frame GetFrame();
|
||||
Key GetLastReleasedMovementKey();
|
||||
float GetSwordSwingTimer();
|
||||
|
@ -178,7 +178,14 @@ const void SaveFile::SaveGame(){
|
||||
saveSystemFile["Fullscreen"].SetBool(game->IsFullscreen());
|
||||
#pragma endregion
|
||||
|
||||
saveFile["Hash"].SetString("");
|
||||
|
||||
utils::datafile::Write(saveFile,"save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
|
||||
std::string fileHash=util::GetHash("save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
saveFile["Hash"].SetString(fileHash);
|
||||
|
||||
utils::datafile::Write(saveFile,"save_file_path"_S+std::format("save.{:04}",saveFileID)); //Once the hash has been computed and added, save the file a second time.
|
||||
utils::datafile::Write(saveSystemFile,"save_file_path"_S+"system.conf");
|
||||
utils::datafile metadata;
|
||||
if(onlineMode){
|
||||
@ -279,6 +286,24 @@ void SaveFile::LoadFile(){
|
||||
|
||||
if(std::filesystem::exists(loadFilename)){
|
||||
utils::datafile::Read(loadFile,"save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
if(!loadFile.HasProperty("Hash")){
|
||||
LOG(std::format("WARNING! Filehash for file {} does not exist!","save_file_path"_S+std::format("save.{:04}",saveFileID)));
|
||||
return;
|
||||
}
|
||||
if(loadFile.HasProperty("Hash")){
|
||||
std::string expectedFileHash=loadFile["Hash"].GetString();
|
||||
loadFile["Hash"].SetString("");
|
||||
utils::datafile::Write(loadFile,"save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
std::string fileHash=util::GetHash("save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
|
||||
if(expectedFileHash!=fileHash){
|
||||
LOG(std::format("WARNING! Filehash for file {} was not identified as proper! Will not load this file!","save_file_path"_S+std::format("save.{:04}",saveFileID)));
|
||||
return;
|
||||
}
|
||||
|
||||
loadFile["Hash"].SetString(expectedFileHash); //Now write the hash back into the file since we tampered with it.
|
||||
utils::datafile::Write(loadFile,"save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
}
|
||||
game->ResetGame();
|
||||
for(auto&[key,data]:loadFile["Items"].GetOrderedKeys()){
|
||||
std::weak_ptr<Item>newItem=Inventory::AddItem(data["Item Name"].GetString(),data["Amt"].GetInt());
|
||||
|
@ -249,7 +249,7 @@ void Menu::InitializeSettingsWindow(){
|
||||
{game->KEY_CONFIRM,{"Select",[](MenuType type){}}},
|
||||
}
|
||||
,{ //Button Navigation Rules
|
||||
{"BGM Slider",{
|
||||
{"BGM Slider",{
|
||||
.up="Go Back",
|
||||
.down="SFX Slider",}},
|
||||
{"SFX Slider",{
|
||||
@ -260,7 +260,7 @@ void Menu::InitializeSettingsWindow(){
|
||||
.down="Screen Shake Checkbox",
|
||||
.left="Show Max Mana Checkbox",
|
||||
.right="Show Max Mana Checkbox",}},
|
||||
{"Show Max Mana Checkbox",{
|
||||
{"Show Max Mana Checkbox",{
|
||||
.up="SFX Slider",
|
||||
.down="Terrain Collision Boxes Checkbox",
|
||||
.left="Show Max HP Checkbox",
|
||||
|
@ -41,6 +41,7 @@ All rights reserved.
|
||||
#include "GameState.h"
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "Unlock.h"
|
||||
#include "MenuLabel.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
@ -48,7 +49,9 @@ void Menu::InitializeShermanWindow(){
|
||||
Menu*shermanWindow=CreateMenu(SHERMAN,CENTERED,vi2d{144,88});
|
||||
|
||||
shermanWindow->ADD("Leave Button",MenuComponent)(geom2d::rect<float>{{0.f,4.f},{144.f,24.f}},"Leave",[](MenuFuncData data){
|
||||
Unlock::UnlockCurrentMap();
|
||||
if(Component<MenuLabel>(LEVEL_COMPLETE,"Stage Complete Label")->GetLabel()!="Stage Summary"){ //If the label says stage summary, we didn't actually complete the level. Don't unlock anything new for the player.
|
||||
Unlock::UnlockCurrentMap();
|
||||
}
|
||||
GameState::ChangeState(States::OVERWORLD_MAP,0.3f);
|
||||
return true;
|
||||
},vf2d{2.f,2.f},ButtonAttr::FIT_TO_LABEL)END;
|
||||
|
@ -77,6 +77,7 @@ void State_GameHub::OnLevelLoad(){
|
||||
}
|
||||
void State_GameHub::OnUserUpdate(AiL*game){
|
||||
State_GameRun::OnUserUpdate(game);
|
||||
|
||||
game->ClearTimedOutGarbage();
|
||||
}
|
||||
void State_GameHub::Draw(AiL*game){
|
||||
|
@ -42,6 +42,9 @@ All rights reserved.
|
||||
#include "Key.h"
|
||||
#include "ItemDrop.h"
|
||||
#include "util.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
|
54
Adventures in Lestoria/SteamStatsReceivedHandler.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#include "SteamStatsReceivedHandler.h"
|
||||
#include "olcUTIL_DataFile.h"
|
||||
#include "DEFINES.h"
|
||||
#include "Unlock.h"
|
||||
#include "config.h"
|
||||
#include "Error.h"
|
||||
|
||||
INCLUDE_DATA
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
void SteamStatsReceivedHandler::SteamStatsReceived( UserStatsReceived_t* pCallback ){
|
||||
if(pCallback->m_eResult==k_EResultOK){
|
||||
SteamUserStats()->GetStat("Achievement.Kill Unlocks.Total Kill API Name"_S.c_str(),&Unlock::monsterKillCount);
|
||||
LOG(std::format("Retrieved monster kill count: {}",Unlock::monsterKillCount));
|
||||
}
|
||||
}
|
||||
#endif
|
47
Adventures in Lestoria/SteamStatsReceivedHandler.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#pragma once
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#include "steam/steam_api.h"
|
||||
#endif
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
class SteamStatsReceivedHandler{
|
||||
STEAM_CALLBACK(SteamStatsReceivedHandler,SteamStatsReceived,UserStatsReceived_t);
|
||||
};
|
||||
#endif
|
@ -44,6 +44,8 @@ All rights reserved.
|
||||
#include "DEFINES.h"
|
||||
#include "safemap.h"
|
||||
#include "ItemMapData.h"
|
||||
#include "Class.h"
|
||||
|
||||
|
||||
using MapName=std::string;
|
||||
using namespace olc;
|
||||
@ -126,6 +128,7 @@ private:
|
||||
std::vector<NPCData>npcs;
|
||||
std::string mapType="";
|
||||
std::string bgmSongName="";
|
||||
std::unordered_map<Class,float>devCompletionTrialTime;
|
||||
BackdropName backdrop="";
|
||||
std::set<std::string>spawns;
|
||||
std::map<int,SpawnerTag> SpawnerData; //Spawn groups have IDs, mobs associate which spawner they are tied to via this ID.
|
||||
@ -138,6 +141,7 @@ public:
|
||||
const std::vector<ItemMapData>&GetStageLoot()const;
|
||||
const std::vector<LayerTag>&GetLayers()const;
|
||||
const std::vector<EnvironmentalAudio>&GetEnvironmentalAudio()const;
|
||||
const float GetDevCompletionTime(Class cl)const;
|
||||
const MapName&GetMapName()const;
|
||||
const std::string_view GetMapDisplayName()const;
|
||||
std::string FormatLayerData(std::ostream& os, std::vector<LayerTag>tiles);
|
||||
@ -464,6 +468,13 @@ class TMXParser{
|
||||
parsedMapInfo.bgmSongName=newTag.data["value"];
|
||||
}
|
||||
} else
|
||||
if (newTag.tag=="property"&&newTag.data["name"].starts_with("Dev Completion Time")) {
|
||||
if(newTag.data.count("value")){ //None is a default value that we ignore.
|
||||
size_t classStartPos="Dev Completion Time - "s.length();
|
||||
std::string className=newTag.data["name"].substr(classStartPos,newTag.data["name"].find(' ',classStartPos)-classStartPos);
|
||||
parsedMapInfo.devCompletionTrialTime[classutils::StringToClass(className)]=newTag.GetFloat("value");
|
||||
}
|
||||
} else
|
||||
if (newTag.tag=="property"&&newTag.data["name"]=="Backdrop") {
|
||||
if(newTag.data["value"]!="None"){ //None is a default value that we ignore.
|
||||
parsedMapInfo.backdrop=newTag.data["value"];
|
||||
|
@ -1,3 +1,18 @@
|
||||
============================================
|
||||
Time Trial Idea
|
||||
|
||||
Upon completing a stage for the first time, the player is shown the completion time and a record time.
|
||||
On first clears, the player will always obtain a new record. Make it apparent to the player they obtained a new record.
|
||||
|
||||
The overworld map will show a new section that says "Completion Time" for any previous completed stages.
|
||||
Upon the second time entering a stage, the game will spawn a timer that the player can run into to begin a time trial-like mode.
|
||||
During the Time Trial mode the player can defeat monsters to freeze the timer by 1 second per mob killed.
|
||||
|
||||
Upon completion of a stage in time trial mode if the player beat their previous time (which they likely will) the record will update.
|
||||
For each class and stage combination there will be a "dev time"
|
||||
|
||||
Settings menu doesn't scroll back up properly while the scrollbar does?
|
||||
Merchant descriptions have no newlines.
|
||||
|
||||
============================================
|
||||
Consider a "killed by player" / "marked by player" flag for monsters to determine if a player gets credit for a monster kill (for achievements)
|
||||
Make another actions config file for the main build (The app # is different)
|
@ -38,16 +38,33 @@ All rights reserved.
|
||||
#include "Unlock.h"
|
||||
#include "State_OverworldMap.h"
|
||||
#include "config.h"
|
||||
#include "olcUTIL_DataFile.h"
|
||||
#include "DEFINES.h"
|
||||
#include "emscripten_compat.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
|
||||
INCLUDE_DATA
|
||||
|
||||
std::set<std::string>Unlock::unlocks;
|
||||
int Unlock::monsterKillCount=0;
|
||||
|
||||
void Unlock::Initialize(){
|
||||
unlocks.clear();
|
||||
UnlockArea("WORLD_MAP");
|
||||
}
|
||||
|
||||
void Unlock::UnlockArea(std::string mapName){
|
||||
if(mapName=="NPCs.Sherman.Potion Crafting Unlock Condition"_S&& //When we beat the bonus chapter 1 fight, before sherman's potion crafting is unlocked, if the current map we just unlocked for is the bonus boss stage we will notify the Hub connection point and reset it so the player has a notification to go there again.
|
||||
!Unlock::IsUnlocked("NPCs.Sherman.Potion Crafting Unlock Condition"_S))State_OverworldMap::ConnectionPointFromString("HUB").value()->ResetVisitedFlag();
|
||||
STEAMUSERSTATS(
|
||||
datafile&areaUnlocks=DATA.GetProperty("Achievement.Area Unlocks");
|
||||
for(auto&[key,size]:areaUnlocks){
|
||||
datafile&unlock = areaUnlocks[key];
|
||||
if(mapName==unlock["Unlock Name"].GetString())SteamUserStats()->SetAchievement(unlock["API Name"].GetString().c_str());
|
||||
}
|
||||
)
|
||||
unlocks.insert(mapName);
|
||||
}
|
||||
bool Unlock::IsUnlocked(std::string mapName){
|
||||
@ -60,4 +77,21 @@ bool Unlock::IsUnlocked(ConnectionPoint&cp){
|
||||
|
||||
void Unlock::UnlockCurrentMap(){
|
||||
UnlockArea(State_OverworldMap::GetCurrentConnectionPoint().map);
|
||||
}
|
||||
|
||||
void Unlock::IncreaseKillCount(){
|
||||
monsterKillCount++;
|
||||
STEAMUSERSTATS(
|
||||
SteamUserStats()->SetStat("Achievement.Kill Unlocks.Total Kill API Name"_S.c_str(),Unlock::monsterKillCount);
|
||||
datafile&killUnlocks=DATA.GetProperty("Achievement.Kill Unlocks");
|
||||
for(auto&[key,size]:killUnlocks){
|
||||
if(key.starts_with("Kill Monsters")){
|
||||
int killRequirement=killUnlocks[key]["Monster Kill Count"].GetInt();
|
||||
if(monsterKillCount-1<killRequirement&& //These two checks make sure we've just reached the kill requirement, so we can send a more readily live update for the player.
|
||||
monsterKillCount==killRequirement){
|
||||
SteamUserStats()->StoreStats();
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
@ -43,8 +43,10 @@ All rights reserved.
|
||||
class Unlock{
|
||||
friend class AiL;
|
||||
friend class SaveFile;
|
||||
friend class SteamStatsReceivedHandler;
|
||||
static std::set<std::string>unlocks;
|
||||
static void Initialize();
|
||||
static int monsterKillCount;
|
||||
public:
|
||||
//Provide a map's actual name to trigger unlocks for all connected areas. You can get the current map you are on via State_OverworldMap::GetCurrentConnectionPoint().map
|
||||
static void UnlockArea(std::string mapName);
|
||||
@ -52,4 +54,5 @@ public:
|
||||
static void UnlockCurrentMap();
|
||||
static bool IsUnlocked(std::string mapName);
|
||||
static bool IsUnlocked(ConnectionPoint&cp);
|
||||
static void IncreaseKillCount();
|
||||
};
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 8477
|
||||
#define VERSION_BUILD 8598
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
BIN
Adventures in Lestoria/assets/Achievements/BronzeBorder.xcf
Normal file
BIN
Adventures in Lestoria/assets/Achievements/GoldBorder.xcf
Normal file
BIN
Adventures in Lestoria/assets/Achievements/SilverBorder.xcf
Normal file
BIN
Adventures in Lestoria/assets/Achievements/armor_10.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
Adventures in Lestoria/assets/Achievements/armor_10_locked.png
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
Adventures in Lestoria/assets/Achievements/armor_5.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
Adventures in Lestoria/assets/Achievements/armor_5_locked.png
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
Adventures in Lestoria/assets/Achievements/blacksmith_unlock.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
BIN
Adventures in Lestoria/assets/Achievements/camp_unlock.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 104 KiB |
BIN
Adventures in Lestoria/assets/Achievements/chapter1_complete.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 103 KiB |
BIN
Adventures in Lestoria/assets/Achievements/fully_decked_out.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 104 KiB |
BIN
Adventures in Lestoria/assets/Achievements/kill_slime_1.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 155 KiB |
BIN
Adventures in Lestoria/assets/Achievements/kill_slime_2.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 168 KiB |
BIN
Adventures in Lestoria/assets/Achievements/kill_slime_3.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 127 KiB |
BIN
Adventures in Lestoria/assets/Achievements/ranger_level5.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 120 KiB |
BIN
Adventures in Lestoria/assets/Achievements/slime_king.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 92 KiB |
BIN
Adventures in Lestoria/assets/Achievements/slime_king_locked.png
Normal file
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 88 KiB |
BIN
Adventures in Lestoria/assets/Achievements/ursule_unlock.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 101 KiB |
BIN
Adventures in Lestoria/assets/Achievements/warrior_level5.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 117 KiB |
BIN
Adventures in Lestoria/assets/Achievements/weapon_5.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
Adventures in Lestoria/assets/Achievements/weapon_5_locked.png
Normal file
After Width: | Height: | Size: 108 KiB |
BIN
Adventures in Lestoria/assets/Achievements/wizard_level5.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 64 KiB |
@ -1,8 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="205" height="205" tilewidth="24" tileheight="24" infinite="0" backgroundcolor="#475500" nextlayerid="11" nextobjectid="179">
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="205" height="205" tilewidth="24" tileheight="24" infinite="0" backgroundcolor="#475500" nextlayerid="11" nextobjectid="507">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty1_1"/>
|
||||
<property name="Dev Completion Time - Ranger (s)" type="float" value="120"/>
|
||||
<property name="Dev Completion Time - Warrior (s)" type="float" value="120"/>
|
||||
<property name="Dev Completion Time - Wizard (s)" type="float" value="120"/>
|
||||
<property name="Level Type" propertytype="LevelType" value="Dungeon"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="../maps/Tilesheet_No_Shadow24x24.tsx"/>
|
||||
@ -2009,5 +2012,6 @@
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="180" name="Time Trial Clock" type="TrialClock" x="624" y="4224" width="24" height="24"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" class="Map" orientation="orthogonal" renderorder="right-down" width="200" height="122" tilewidth="24" tileheight="24" infinite="0" nextlayerid="9" nextobjectid="82">
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="200" height="122" tilewidth="24" tileheight="24" infinite="0" nextlayerid="9" nextobjectid="83">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty1_1"/>
|
||||
@ -845,5 +845,6 @@
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="82" name="Time Trial Clock" type="TrialClock" x="3648" y="648" width="24" height="24"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="205" height="250" tilewidth="24" tileheight="24" infinite="0" nextlayerid="8" nextobjectid="97">
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="205" height="250" tilewidth="24" tileheight="24" infinite="0" nextlayerid="8" nextobjectid="98">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty1_1"/>
|
||||
@ -1551,6 +1551,7 @@
|
||||
<point/>
|
||||
</object>
|
||||
<object id="95" name="End Zone" type="EndZone" x="1726" y="1681" width="72" height="72"/>
|
||||
<object id="97" name="Time Trial Clock" type="TrialClock" x="1656" y="5448" width="24" height="24"/>
|
||||
</objectgroup>
|
||||
<objectgroup id="7" name="Environmental Sounds">
|
||||
<object id="30" name="Waterfall Sound" type="AudioEnvironmentalSound" x="4313" y="2678">
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" class="Map" orientation="orthogonal" renderorder="right-down" width="250" height="175" tilewidth="24" tileheight="24" infinite="0" nextlayerid="6" nextobjectid="107">
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="250" height="175" tilewidth="24" tileheight="24" infinite="0" nextlayerid="6" nextobjectid="108">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty1_1"/>
|
||||
@ -1154,5 +1154,6 @@
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="107" name="Time Trial Clock" type="TrialClock" x="720" y="3456" width="24" height="24"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" class="Map" orientation="orthogonal" renderorder="right-down" width="229" height="155" tilewidth="24" tileheight="24" infinite="0" nextlayerid="8" nextobjectid="84">
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="229" height="155" tilewidth="24" tileheight="24" infinite="0" nextlayerid="8" nextobjectid="85">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty1_1"/>
|
||||
@ -1118,6 +1118,7 @@
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="84" name="Time Trial Clock" type="TrialClock" x="1824" y="408" width="24" height="24"/>
|
||||
</objectgroup>
|
||||
<objectgroup id="7" name="Environmental Sounds">
|
||||
<object id="24" name="Waterfall Sound" type="AudioEnvironmentalSound" x="3425" y="264">
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" class="Map" orientation="orthogonal" renderorder="right-down" width="250" height="127" tilewidth="24" tileheight="24" infinite="0" nextlayerid="6" nextobjectid="87">
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="250" height="127" tilewidth="24" tileheight="24" infinite="0" nextlayerid="6" nextobjectid="88">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty1_1"/>
|
||||
@ -893,5 +893,6 @@
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="87" name="Time Trial Clock" type="TrialClock" x="360" y="1488" width="24" height="24"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" class="Map" orientation="orthogonal" renderorder="right-down" width="148" height="131" tilewidth="24" tileheight="24" infinite="0" nextlayerid="6" nextobjectid="68">
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="148" height="131" tilewidth="24" tileheight="24" infinite="0" nextlayerid="6" nextobjectid="69">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty1_1"/>
|
||||
@ -796,5 +796,6 @@
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="68" name="Time Trial Clock" type="TrialClock" x="96" y="312" width="24" height="24"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" class="Map" orientation="orthogonal" renderorder="right-down" width="72" height="80" tilewidth="24" tileheight="24" infinite="0" nextlayerid="5" nextobjectid="9">
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="72" height="80" tilewidth="24" tileheight="24" infinite="0" nextlayerid="5" nextobjectid="9">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty_boss"/>
|
||||
|
118
Adventures in Lestoria/assets/config/Achievements.txt
Normal file
@ -0,0 +1,118 @@
|
||||
Achievement
|
||||
{
|
||||
Area Unlocks
|
||||
{
|
||||
# Area Unlocks are automatically checked when a new map unlock is achieved.
|
||||
Camp Unlock
|
||||
{
|
||||
API Name = "CAMP_UNLOCK"
|
||||
Unlock Name = "STORY_1_1"
|
||||
}
|
||||
Blacksmith Unlock
|
||||
{
|
||||
API Name = "BLACKSMITH_UNLOCK"
|
||||
Unlock Name = "STORY_1_2"
|
||||
}
|
||||
Chapter 2 Unlock
|
||||
{
|
||||
API Name = "CHAPTER1_COMPLETE"
|
||||
Unlock Name = "STORY_1_3"
|
||||
}
|
||||
}
|
||||
Kill Unlocks
|
||||
{
|
||||
Total Kill API Name = "MONSTER_KILL_COUNT"
|
||||
|
||||
# Achievements that start with "Kill Monsters" will be checked when a monster is killed.
|
||||
Kill Monsters 1
|
||||
{
|
||||
API Name = "KILL_SLIME_1"
|
||||
Monster Kill Count = 100
|
||||
}
|
||||
Kill Monsters 2
|
||||
{
|
||||
API Name = "KILL_SLIME_2"
|
||||
Monster Kill Count = 250
|
||||
}
|
||||
Kill Monsters 3
|
||||
{
|
||||
API Name = "KILL_SLIME_3"
|
||||
Monster Kill Count = 1000
|
||||
}
|
||||
|
||||
##################################
|
||||
|
||||
# For other Kill Encounter achievements, if they have a Monster Name the game looks for the name when a monster is killed and if it matches, you get awarded that achievement.
|
||||
# If a Time Limit is included, the encounter must be a boss encounter and
|
||||
Slime King
|
||||
{
|
||||
API Name = "SLIME_KING"
|
||||
Monster Name = "Slime King"
|
||||
}
|
||||
Slime King Destroyer
|
||||
{
|
||||
API Name = "SLIME_KING_DESTROYER"
|
||||
Time Limit = 60s
|
||||
Monster Name = "Slime King"
|
||||
}
|
||||
Ursule
|
||||
{
|
||||
API Name = "URSULE"
|
||||
Monster Name = "Ursule, Mother of Bears"
|
||||
}
|
||||
Ursule Destroyer
|
||||
{
|
||||
API Name = "URSULE_DESTROYER"
|
||||
Time Limit = 60s
|
||||
Monster Name = "Ursule, Mother of Bears"
|
||||
}
|
||||
}
|
||||
Class Unlocks
|
||||
{
|
||||
Warrior Lv5
|
||||
{
|
||||
API Name = "WARRIOR_LV5"
|
||||
Class Requirement = Warrior
|
||||
Level Requirement = 5
|
||||
}
|
||||
Ranger Lv5
|
||||
{
|
||||
API Name = "RANGER_LV5"
|
||||
Class Requirement = Ranger
|
||||
Level Requirement = 5
|
||||
}
|
||||
Wizard Lv5
|
||||
{
|
||||
API Name = "WIZARD_LV5"
|
||||
Class Requirement = Wizard
|
||||
Level Requirement = 5
|
||||
}
|
||||
}
|
||||
Equip Unlocks
|
||||
{
|
||||
Weapon Lv5
|
||||
{
|
||||
API Name = "WEAPON_LV5"
|
||||
Equip Slot = Weapon
|
||||
Upgrade Requirement = 5
|
||||
}
|
||||
Armor Lv5
|
||||
{
|
||||
API Name = "ARMOR_LV5"
|
||||
Equip Slot = Helmet,Armor,Gloves,Pants,Shoes
|
||||
Upgrade Requirement = 5
|
||||
}
|
||||
Armor Lv10
|
||||
{
|
||||
API Name = "ARMOR_LV10"
|
||||
Equip Slot = Helmet,Armor,Gloves,Pants,Shoes
|
||||
Upgrade Requirement = 10
|
||||
}
|
||||
Fully Decked Out
|
||||
{
|
||||
API Name = "FULLY_DECKED_OUT"
|
||||
Weapon Max Level = 5
|
||||
Armor Max Level = 10
|
||||
}
|
||||
}
|
||||
}
|
@ -20,6 +20,9 @@ Player
|
||||
# Amount of spd to increase/decrease vertically as you climb staircases
|
||||
StaircaseClimbSpd = 45
|
||||
|
||||
# Walking Default Animation Delay per Frame
|
||||
WalkingFrameSpd = 0.2s
|
||||
|
||||
# How much speed the player loses while no momentum is being added.
|
||||
Friction = 400
|
||||
|
||||
|
@ -28,6 +28,9 @@ player_config = Player.txt
|
||||
# Monster Properties Loading Config
|
||||
monsters_config = Monsters.txt
|
||||
|
||||
# Achievement Config
|
||||
achievement_config = Achievements.txt
|
||||
|
||||
# NPC Loading Config
|
||||
npc_config = NPCs.txt
|
||||
|
||||
|
@ -192,4 +192,9 @@ ItemDatabase
|
||||
ItemCategory = Materials
|
||||
SellValue = 180
|
||||
}
|
||||
Time Medal
|
||||
{
|
||||
Description = A medal provided to top athletes in Lestoria commemorating a huge victory.
|
||||
ItemCategory = Materials
|
||||
}
|
||||
}
|
||||
|
BIN
Adventures in Lestoria/assets/items/Time Medal.png
Normal file
After Width: | Height: | Size: 949 B |
@ -1,18 +1,18 @@
|
||||
"controller_mappings"
|
||||
{
|
||||
"version" "3"
|
||||
"revision" "82"
|
||||
"title" "#Title_Config"
|
||||
"description" "#Description_Config"
|
||||
"revision" "87"
|
||||
"title" "Generic Gamepad"
|
||||
"description" "Default Generic Gamepad controls"
|
||||
"creator" "76561198025675819"
|
||||
"progenitor" ""
|
||||
"url" "usercloud://2895980/generic gamepad_3"
|
||||
"export_type" "personal_cloud"
|
||||
"url" "autosave://C:\\Program Files (x86)\\Steam\\steamapps\\common\\Steam Controller Configs\\65410091\\config\\2895980\\controller_generic.vdf"
|
||||
"export_type" "personal_local"
|
||||
"controller_type" "controller_generic"
|
||||
"controller_caps" "1573375"
|
||||
"major_revision" "0"
|
||||
"minor_revision" "0"
|
||||
"Timestamp" "1711341077"
|
||||
"Timestamp" "1711752971"
|
||||
"actions"
|
||||
{
|
||||
"InGameControls"
|
||||
@ -21,6 +21,11 @@
|
||||
"legacy_set" "0"
|
||||
"StickPadGyro"
|
||||
{
|
||||
"Move"
|
||||
{
|
||||
"title" "#Move"
|
||||
"input_mode" "joystick_move"
|
||||
}
|
||||
"Scroll"
|
||||
{
|
||||
"title" "#Scroll"
|
||||
@ -66,8 +71,8 @@
|
||||
{
|
||||
"english"
|
||||
{
|
||||
"Title_Config" "Generic Gamepad"
|
||||
"Description_Config" "Generic gamepad configuration."
|
||||
"Title_Config" "Adventures in Lestoria Configuration"
|
||||
"Description_Config" "The default control set for Adventures in Lestoria."
|
||||
"Set_Ingame" "Gameplay Controls"
|
||||
"BasicAttack" "Basic Attack"
|
||||
"Defensive" "Use Defensive"
|
||||
@ -84,6 +89,7 @@
|
||||
"Function1" "Menu Function 1"
|
||||
"Function2" "Menu Function 2"
|
||||
"Menu" "Menu/Pause"
|
||||
"Move" "Move"
|
||||
"Up" "Up"
|
||||
"Down" "Down"
|
||||
"Left" "Left"
|
||||
@ -614,6 +620,24 @@
|
||||
}
|
||||
}
|
||||
"group"
|
||||
{
|
||||
"id" "24"
|
||||
"mode" "joystick_move"
|
||||
"name" ""
|
||||
"description" ""
|
||||
"inputs"
|
||||
{
|
||||
}
|
||||
"settings"
|
||||
{
|
||||
"virtual_mode" "1"
|
||||
}
|
||||
"gameactions"
|
||||
{
|
||||
"InGameControls" "Move"
|
||||
}
|
||||
}
|
||||
"group"
|
||||
{
|
||||
"id" "0"
|
||||
"mode" "switches"
|
||||
@ -761,7 +785,8 @@
|
||||
"2" "left_trigger active"
|
||||
"3" "right_trigger active"
|
||||
"15" "joystick inactive"
|
||||
"23" "joystick active"
|
||||
"23" "joystick inactive"
|
||||
"24" "joystick active"
|
||||
"16" "right_joystick inactive"
|
||||
"22" "right_joystick active"
|
||||
"14" "dpad inactive"
|
||||
|
@ -1,18 +1,18 @@
|
||||
"controller_mappings"
|
||||
{
|
||||
"version" "3"
|
||||
"revision" "83"
|
||||
"title" "#Title_Config"
|
||||
"description" "#Description_Config"
|
||||
"revision" "85"
|
||||
"title" "Switch Pro"
|
||||
"description" "Default Switch Pro configuration."
|
||||
"creator" "76561198025675819"
|
||||
"progenitor" ""
|
||||
"url" "usercloud://2895980/switch pro configuration_0"
|
||||
"export_type" "personal_cloud"
|
||||
"url" "autosave://C:\\Program Files (x86)\\Steam\\steamapps\\common\\Steam Controller Configs\\65410091\\config\\2895980\\controller_switch_pro.vdf"
|
||||
"export_type" "personal_local"
|
||||
"controller_type" "controller_switch_pro"
|
||||
"controller_caps" "613772287"
|
||||
"major_revision" "0"
|
||||
"minor_revision" "0"
|
||||
"Timestamp" "1711340749"
|
||||
"Timestamp" "1711752483"
|
||||
"actions"
|
||||
{
|
||||
"InGameControls"
|
||||
@ -21,6 +21,11 @@
|
||||
"legacy_set" "0"
|
||||
"StickPadGyro"
|
||||
{
|
||||
"Move"
|
||||
{
|
||||
"title" "#Move"
|
||||
"input_mode" "joystick_move"
|
||||
}
|
||||
"Scroll"
|
||||
{
|
||||
"title" "#Scroll"
|
||||
@ -66,8 +71,8 @@
|
||||
{
|
||||
"english"
|
||||
{
|
||||
"Title_Config" "Switch Pro"
|
||||
"Description_Config" "Nintendo Switch Pro controller configuration."
|
||||
"Title_Config" "Adventures in Lestoria Configuration"
|
||||
"Description_Config" "The default control set for Adventures in Lestoria."
|
||||
"Set_Ingame" "Gameplay Controls"
|
||||
"BasicAttack" "Basic Attack"
|
||||
"Defensive" "Use Defensive"
|
||||
@ -84,6 +89,7 @@
|
||||
"Function1" "Menu Function 1"
|
||||
"Function2" "Menu Function 2"
|
||||
"Menu" "Menu/Pause"
|
||||
"Move" "Move"
|
||||
"Up" "Up"
|
||||
"Down" "Down"
|
||||
"Left" "Left"
|
||||
@ -614,6 +620,24 @@
|
||||
}
|
||||
}
|
||||
"group"
|
||||
{
|
||||
"id" "25"
|
||||
"mode" "joystick_move"
|
||||
"name" ""
|
||||
"description" ""
|
||||
"inputs"
|
||||
{
|
||||
}
|
||||
"settings"
|
||||
{
|
||||
"virtual_mode" "1"
|
||||
}
|
||||
"gameactions"
|
||||
{
|
||||
"InGameControls" "Move"
|
||||
}
|
||||
}
|
||||
"group"
|
||||
{
|
||||
"id" "0"
|
||||
"mode" "switches"
|
||||
@ -761,7 +785,8 @@
|
||||
"2" "left_trigger active"
|
||||
"3" "right_trigger active"
|
||||
"15" "joystick inactive"
|
||||
"23" "joystick active"
|
||||
"23" "joystick inactive"
|
||||
"25" "joystick active"
|
||||
"16" "right_joystick inactive"
|
||||
"22" "right_joystick active"
|
||||
"14" "dpad inactive"
|
||||
|
@ -1,18 +1,18 @@
|
||||
"controller_mappings"
|
||||
{
|
||||
"version" "3"
|
||||
"revision" "76"
|
||||
"title" "#Title_Config"
|
||||
"description" "#Description_Config"
|
||||
"revision" "78"
|
||||
"title" "Xbox/Playstation"
|
||||
"description" "Default Xbox/Playstation controls"
|
||||
"creator" "76561198025675819"
|
||||
"progenitor" ""
|
||||
"url" "autosave://C:\\Program Files (x86)\\Steam\\steamapps\\common\\Steam Controller Configs\\65410091\\config\\2895980\\controller_xbox360.vdf"
|
||||
"export_type" "personal_cloud"
|
||||
"export_type" "personal_local"
|
||||
"controller_type" "controller_xbox360"
|
||||
"controller_caps" "1590271"
|
||||
"major_revision" "0"
|
||||
"minor_revision" "0"
|
||||
"Timestamp" "1711340807"
|
||||
"Timestamp" "1711752757"
|
||||
"actions"
|
||||
{
|
||||
"InGameControls"
|
||||
@ -21,6 +21,11 @@
|
||||
"legacy_set" "0"
|
||||
"StickPadGyro"
|
||||
{
|
||||
"Move"
|
||||
{
|
||||
"title" "#Move"
|
||||
"input_mode" "joystick_move"
|
||||
}
|
||||
"Scroll"
|
||||
{
|
||||
"title" "#Scroll"
|
||||
@ -66,8 +71,8 @@
|
||||
{
|
||||
"english"
|
||||
{
|
||||
"Title_Config" "Xbox/Playstation"
|
||||
"Description_Config" "Xbox/Playstation controller configuration."
|
||||
"Title_Config" "Adventures in Lestoria Configuration"
|
||||
"Description_Config" "The default control set for Adventures in Lestoria."
|
||||
"Set_Ingame" "Gameplay Controls"
|
||||
"BasicAttack" "Basic Attack"
|
||||
"Defensive" "Use Defensive"
|
||||
@ -84,6 +89,7 @@
|
||||
"Function1" "Menu Function 1"
|
||||
"Function2" "Menu Function 2"
|
||||
"Menu" "Menu/Pause"
|
||||
"Move" "Move"
|
||||
"Up" "Up"
|
||||
"Down" "Down"
|
||||
"Left" "Left"
|
||||
@ -614,6 +620,24 @@
|
||||
}
|
||||
}
|
||||
"group"
|
||||
{
|
||||
"id" "24"
|
||||
"mode" "joystick_move"
|
||||
"name" ""
|
||||
"description" ""
|
||||
"inputs"
|
||||
{
|
||||
}
|
||||
"settings"
|
||||
{
|
||||
"virtual_mode" "1"
|
||||
}
|
||||
"gameactions"
|
||||
{
|
||||
"InGameControls" "Move"
|
||||
}
|
||||
}
|
||||
"group"
|
||||
{
|
||||
"id" "0"
|
||||
"mode" "switches"
|
||||
@ -761,7 +785,8 @@
|
||||
"2" "left_trigger active"
|
||||
"3" "right_trigger active"
|
||||
"15" "joystick inactive"
|
||||
"23" "joystick active"
|
||||
"23" "joystick inactive"
|
||||
"24" "joystick active"
|
||||
"16" "right_joystick inactive"
|
||||
"22" "right_joystick active"
|
||||
"14" "dpad inactive"
|
@ -7,6 +7,11 @@
|
||||
"title" "#Set_Ingame"
|
||||
"StickPadGyro"
|
||||
{
|
||||
"Move"
|
||||
{
|
||||
"title" "#Move"
|
||||
"input_mode" "joystick_move"
|
||||
}
|
||||
"Scroll"
|
||||
{
|
||||
"title" "#Scroll"
|
||||
@ -64,6 +69,7 @@
|
||||
"Function1" "Menu Function 1"
|
||||
"Function2" "Menu Function 2"
|
||||
"Menu" "Menu/Pause"
|
||||
"Move" "Move"
|
||||
"Up" "Up"
|
||||
"Down" "Down"
|
||||
"Left" "Left"
|
||||
@ -79,7 +85,28 @@
|
||||
{
|
||||
"0"
|
||||
{
|
||||
"path" "controller_xbox360.vdf"
|
||||
"path" "controller_xboxone.vdf"
|
||||
}
|
||||
}
|
||||
"controller_xboxone"
|
||||
{
|
||||
"0"
|
||||
{
|
||||
"path" "controller_xboxone.vdf"
|
||||
}
|
||||
}
|
||||
"controller_ps5"
|
||||
{
|
||||
"0"
|
||||
{
|
||||
"path" "controller_xboxone.vdf"
|
||||
}
|
||||
}
|
||||
"controller_ps4"
|
||||
{
|
||||
"0"
|
||||
{
|
||||
"path" "controller_xboxone.vdf"
|
||||
}
|
||||
}
|
||||
"controller_generic"
|
||||
|
@ -15,7 +15,9 @@ inline void SteamAPI_RunCallbacks(){};
|
||||
|
||||
#define STEAMINPUT(statement) if(false){}
|
||||
#define STEAMUTILS(statement) if(false){}
|
||||
#define STEAMUSERSTATS(statement) if(false){}
|
||||
#else
|
||||
#define STEAMINPUT(statement) if(SteamInput()){statement}
|
||||
#define STEAMUTILS(statement) if(SteamUtils()){statement}
|
||||
#define STEAMUSERSTATS(statement) if(SteamUserStats()){statement}
|
||||
#endif
|
||||
|
@ -4690,7 +4690,15 @@ namespace olc
|
||||
{ bHasMouseFocus = state; }
|
||||
|
||||
void PixelGameEngine::olc_UpdateKeyFocus(bool state)
|
||||
{ bHasInputFocus = state; }
|
||||
{
|
||||
if(!state){
|
||||
for (uint32_t i = 0; i < 256; i++)
|
||||
{
|
||||
olc_UpdateKeyState(i,false);
|
||||
}
|
||||
}
|
||||
bHasInputFocus = state;
|
||||
}
|
||||
|
||||
void PixelGameEngine::olc_DropFiles(int32_t x, int32_t y, const std::vector<std::string>& vFiles)
|
||||
{
|
||||
|
@ -104,6 +104,10 @@ namespace olc::utils::Animate2D
|
||||
class FrameSequence
|
||||
{
|
||||
public:
|
||||
Style m_nStyle;
|
||||
std::vector<Frame> m_vFrames;
|
||||
float m_fFrameDuration = 0.1f;
|
||||
float m_fFrameRate = 10.0f;
|
||||
// Constructs a sequence of frames with a duration and a traversal style
|
||||
inline FrameSequence(const float fFrameDuration = 0.1f, const Style nStyle = Style::Repeat)
|
||||
{
|
||||
@ -125,10 +129,6 @@ namespace olc::utils::Animate2D
|
||||
}
|
||||
|
||||
private:
|
||||
Style m_nStyle;
|
||||
std::vector<Frame> m_vFrames;
|
||||
float m_fFrameDuration = 0.1f;
|
||||
float m_fFrameRate = 10.0f;
|
||||
|
||||
inline const size_t ConvertTimeToFrame(const float fTime) const
|
||||
{
|
||||
@ -170,7 +170,13 @@ namespace olc::utils::Animate2D
|
||||
{
|
||||
public:
|
||||
Animation() = default;
|
||||
float mult = 1.f;
|
||||
|
||||
inline bool ChangeState(AnimationState& state, const StatesEnum& sStateName, const float frameMult)
|
||||
{
|
||||
mult=frameMult;
|
||||
return ChangeState(state,sStateName);
|
||||
}
|
||||
// Change an animation state token to a new state
|
||||
inline bool ChangeState(AnimationState& state, const StatesEnum& sStateName) const
|
||||
{
|
||||
@ -188,7 +194,7 @@ namespace olc::utils::Animate2D
|
||||
// Update an animation state token
|
||||
inline void UpdateState(AnimationState& state, const float fElapsedTime) const
|
||||
{
|
||||
state.fTime = std::fmod(state.fTime+fElapsedTime,1000);
|
||||
state.fTime = std::fmod(state.fTime+fElapsedTime*mult,1000);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -269,7 +269,7 @@ namespace olc::utils
|
||||
}
|
||||
nItems--;
|
||||
}
|
||||
|
||||
|
||||
// Property written, move to next line
|
||||
file << "\n";
|
||||
}
|
||||
|
@ -148,6 +148,38 @@ std::u32string util::WrapText(PixelGameEngine*pge,std::u32string str,int width,F
|
||||
return newStr;
|
||||
}
|
||||
|
||||
#pragma region std::string util::GetHash(std::string fileName) //DO NOT MODIFY!
|
||||
std::string util::GetHash(std::string fileName){
|
||||
//WARNING! This function is used to save/load files! This means if we ever modify this function all previous save files
|
||||
//will no longer work! IN OTHER WORDS: DO NOT MODIFY THIS FUNCTION!
|
||||
std::ifstream file(fileName);
|
||||
std::string hash="";
|
||||
uint8_t hashIndex=0;
|
||||
while(file.good()){
|
||||
uint8_t hashChar=0;
|
||||
if(hash.size()==std::numeric_limits<uint8_t>::max()){
|
||||
hashChar=hash[hashIndex];
|
||||
}
|
||||
char newChar=file.get();
|
||||
if(newChar=='\r'||newChar=='\f'||newChar=='\n')continue;
|
||||
hashChar+=newChar*21-7;
|
||||
hashChar^=hashIndex;
|
||||
if(hashIndex>0)hashChar+=hash[hashIndex-1];
|
||||
hashChar%=94;
|
||||
hashChar+=32;
|
||||
if(hashChar=='"'||hashChar==',')hashChar+=60;
|
||||
if(hashChar=='|')hashChar++; //FORBIDDEN CHARACTER IN EMSCRIPTEN BUILD!
|
||||
if(hash.size()<std::numeric_limits<uint8_t>::max()){
|
||||
hash+=hashChar;
|
||||
}else{
|
||||
hash[hashIndex]=hashChar;
|
||||
}
|
||||
hashIndex++;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
long double operator""_Pixels(long double unitDist){
|
||||
return unitDist/100*24.;
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ namespace olc::util{
|
||||
std::string WrapText(PixelGameEngine*pge,std::string str,int width,bool proportional,vd2d scale);
|
||||
std::u32string WrapText(PixelGameEngine*pge,std::u32string str,int width,Font&font,vd2d scale);
|
||||
float angle_difference(float angle_1, float angle_2);
|
||||
std::string GetHash(std::string file);
|
||||
}
|
||||
|
||||
template<class TL, class TR>
|
||||
|
@ -1,6 +1,7 @@
|
||||
rm -R release
|
||||
mkdir release
|
||||
mkdir release/assets
|
||||
mkdir "release/Adventures in Lestoria"
|
||||
cp -R "Adventures in Lestoria/assets/Campaigns" release/assets
|
||||
cp -R "Adventures in Lestoria/assets/config" release/assets
|
||||
cp -R "Adventures in Lestoria/assets/maps" release/assets
|
||||
@ -13,10 +14,10 @@ cp -R "Adventures in Lestoria/assets/npcs" release/assets
|
||||
cp -R "Adventures in Lestoria/assets/sounds" release/assets
|
||||
cp -R "Adventures in Lestoria/assets/themes" release/assets
|
||||
cp -R "Adventures in Lestoria/assets/gamepack.pak" release/assets
|
||||
cp -R "Adventures in Lestoria/assets/*.ttf" release/assets
|
||||
cp -R "Adventures in Lestoria/assets/"*.ttf release/assets
|
||||
cp -R "Adventures in Lestoria/controller_config" release
|
||||
mkdir "release/Adventures in Lestoria"
|
||||
cp "Adventures in Lestoria/Adventures in Lestoria/*.so" "release/Adventures in Lestoria"
|
||||
cp "Adventures in Lestoria/Adventures in Lestoria/"*.so "release/Adventures in Lestoria"
|
||||
cp -R bin release
|
||||
|
||||
rm release/*.pdb
|
||||
|
||||
|
2
read_debug_log.ps1
Normal file
@ -0,0 +1,2 @@
|
||||
clear
|
||||
Get-Content "Adventures in Lestoria/debug.log" -Wait
|