Add in intro level scenes and identify combat-related sounds so they do not play on the main menu. Release Build 7587.

pull/35/head
sigonasr2 9 months ago
parent 141e1622d6
commit 99049d6fa0
  1. 39
      Adventures in Lestoria/Adventures in Lestoria.tiled-project
  2. 18
      Adventures in Lestoria/AdventuresInLestoria.cpp
  3. 1
      Adventures in Lestoria/AdventuresInLestoria.h
  4. 9
      Adventures in Lestoria/Player.cpp
  5. 3
      Adventures in Lestoria/Player.h
  6. 16
      Adventures in Lestoria/SoundEffect.cpp
  7. 3
      Adventures in Lestoria/SoundEffect.h
  8. 8
      Adventures in Lestoria/State_GameRun.cpp
  9. 15
      Adventures in Lestoria/State_MainMenu.cpp
  10. 12
      Adventures in Lestoria/TMXParser.h
  11. 2
      Adventures in Lestoria/TODO.txt
  12. 2
      Adventures in Lestoria/Version.h
  13. 1628
      Adventures in Lestoria/assets/Campaigns/Intro_Map.tmx
  14. 2
      Adventures in Lestoria/assets/Campaigns/World_Map.tmx
  15. 27
      Adventures in Lestoria/assets/config/audio/events.txt
  16. 2
      Adventures in Lestoria/assets/config/configuration.txt
  17. 5
      Adventures in Lestoria/assets/config/levels.txt
  18. BIN
      x64/Release/Adventures in Lestoria.exe

@ -7,6 +7,8 @@
"folders": [
"."
],
"properties": [
],
"propertyTypes": [
{
"color": "#ff3af8eb",
@ -170,6 +172,26 @@
"layer"
]
},
{
"color": "#ff4f4f51",
"drawFill": true,
"id": 37,
"members": [
{
"name": "Scroll Direction",
"propertyType": "ScrollDirection",
"type": "string",
"value": "NORTH"
}
],
"name": "Focus Area",
"type": "class",
"useAs": [
"property",
"object",
"project"
]
},
{
"color": "#ffd9d929",
"drawFill": true,
@ -420,6 +442,23 @@
"tile"
]
},
{
"id": 38,
"name": "ScrollDirection",
"storageType": "string",
"type": "enum",
"values": [
"NORTH",
"NORTHEAST",
"EAST",
"SOUTHEAST",
"SOUTH",
"SOUTHWEST",
"WEST",
"NORTHWEST"
],
"valuesAsFlags": false
},
{
"color": "#ffe67300",
"drawFill": true,

@ -279,7 +279,6 @@ bool AiL::OnUserCreate(){
Inventory::AddItem("Minor Health Potion"s,3);
Inventory::AddItem("Bandages"s,10);
LoadLevel("starting_map"_S,NO_MUSIC_CHANGE);
ChangePlayerClass(WARRIOR);
GameState::Initialize();
@ -899,6 +898,7 @@ void AiL::RenderWorld(float fElapsedTime){
PopulateRenderLists();
auto RenderPlayer=[&](vf2d pos,vf2d scale){
if(player->IsInvisible())return;
vf2d playerScale=vf2d(player->GetSizeMult(),player->GetSizeMult());
int count=0;
for(vf2d&pos:player->ghostPositions){
@ -1154,7 +1154,9 @@ void AiL::RenderWorld(float fElapsedTime){
if(view.IsRectVisible(group.GetRange().pos,group.GetRange().size)){
if(geom2d::overlaps(group.GetFadeRange(),player->pos)){
group.playerBehind=true;
if(GameState::STATE!=GameState::states[States::MAIN_MENU]){ //Don't fade out tile groups while we are on the main menu.
group.fadeFactor=std::min(group.fadeFactor+fElapsedTime,TileGroup::FADE_TIME);
}
} else {
group.playerBehind=false;
group.fadeFactor=std::max(group.fadeFactor-fElapsedTime,0.f);
@ -1320,7 +1322,9 @@ void AiL::RenderWorld(float fElapsedTime){
if(view.IsRectVisible(group.GetRange().pos,group.GetRange().size)){
if(geom2d::overlaps(group.GetFadeRange(),player->pos)){
group.playerBehind=true;
if(GameState::STATE!=GameState::states[States::MAIN_MENU]){ //Don't fade out tile groups while we are on the main menu.
group.fadeFactor=std::min(group.fadeFactor+fElapsedTime,TileGroup::FADE_TIME);
}
} else {
group.playerBehind=false;
group.fadeFactor=std::max(group.fadeFactor-fElapsedTime,0.f);
@ -1871,6 +1875,8 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
GetPlayer()->SetState(State::NORMAL);
GetPlayer()->GetCastInfo()={};
GetPlayer()->ResetAccumulatedXP();
GetPlayer()->SetIframes(0.f);
GetPlayer()->SetInvisible(false);
ZONE_LIST=game->MAP_DATA[game->GetCurrentLevel()].ZoneData;
return true;
@ -3425,3 +3431,13 @@ rcode AiL::LoadResource(Renderable&renderable,std::string_view imgPath,bool filt
}
return returnCode;
}
void AiL::UpdateMonsters(){
for(Monster&m:MONSTER_LIST){
m.Update(game->GetElapsedTime());
}
for(Monster&m:game->monstersToBeSpawned){
MONSTER_LIST.push_back(m);
}
game->monstersToBeSpawned.clear();
}

@ -296,6 +296,7 @@ public:
void ResumeGame();
const bool GameInitialized()const;
rcode LoadResource(Renderable&renderable,std::string_view imgPath,bool filter=false,bool clamp=true);
void UpdateMonsters();
struct TileGroupData{
vi2d tilePos;

@ -1350,3 +1350,12 @@ void Player::UpdateHealthAndMana(){
mana=std::min(mana,GetMaxMana());
}
}
void Player::SetInvisible(const bool invisibleState){
invisibility=invisibleState;
}
const bool Player::IsInvisible()const{
return invisibility;
}

@ -245,6 +245,8 @@ public:
void SetXP(const uint32_t xp);
void SetTotalXPEarned(const uint32_t totalXP);
void SetLevel(uint8_t newLevel);
void SetInvisible(const bool invisibleState);
const bool IsInvisible()const;
private:
int hp="Warrior.BaseHealth"_I;
int mana="Player.BaseMana"_I;
@ -293,6 +295,7 @@ private:
uint32_t money="Player.Starting Money"_I;
EntityStats stats;
ItemAttribute&Get(std::string_view attr);
bool invisibility=false;
//Returns true if the move was valid and successful.
//If playerInvoked is true, this means the player was the one that instantiated this input, and it's not an extra movement done via collision.
//Set playerInvoked to false when you don't want a movement loop due to collisions.

@ -49,23 +49,31 @@ INCLUDE_game
std::multimap<EventName,SoundEffect>SoundEffect::SOUND_EFFECTS;
const vf2d SoundEffect::CENTERED={-8419.f,-3289.f};
SoundEffect::SoundEffect(const std::string_view filename,const float&vol,const float&minPitch,const float&maxPitch)
:filename(filename),vol(vol),minPitch(minPitch),maxPitch(maxPitch){
SoundEffect::SoundEffect(const std::string_view filename,const float&vol,const float&minPitch,const float&maxPitch,const bool combatSound)
:filename(filename),vol(vol),minPitch(minPitch),maxPitch(maxPitch),combatSound(combatSound){
if(vol<0.f||vol>1.f)ERR(std::format("WARNING! Volume must be between 0.0f ~ 1.0f! Provided value {}",vol));
}
void SoundEffect::Initialize(){
for(auto&[key,size]:DATA["Events"]["SFX"]){
int counter=0;
bool combatSound=false;
if(DATA["Events"]["SFX"][key].HasProperty("CombatSound")){
combatSound=DATA["Events"]["SFX"][key]["CombatSound"].GetBool();
}
while(DATA["Events"]["SFX"][key].HasProperty(std::format("File[{}]",counter))){
utils::datafile&data=DATA["Events"]["SFX"][key][std::format("File[{}]",counter)];
float minPitch=0.9f;
float maxPitch=1.1f;
if(data.GetValueCount()>=3){minPitch=data.GetInt(2)/100.f;}
if(data.GetValueCount()>=4){maxPitch=data.GetInt(3)/100.f;}
SOUND_EFFECTS.insert({key,SoundEffect{data.GetString(0),data.GetInt(1)/100.f,minPitch,maxPitch}});
SOUND_EFFECTS.insert({key,SoundEffect{data.GetString(0),data.GetInt(1)/100.f,minPitch,maxPitch,combatSound}});
counter++;
}
auto itr=SOUND_EFFECTS.equal_range(key);
for(auto it=itr.first;it!=itr.second;++it){
it->second.combatSound=combatSound;
}
}
}
@ -84,6 +92,8 @@ void SoundEffect::PlaySFX(const std::string_view eventName,const vf2d&pos){
}
const SoundEffect&sfx=(*it).second;
if(GameState::STATE==GameState::states[States::MAIN_MENU])return; //Do not play combat sounds on the main menu.
float pitchDiff=sfx.maxPitch-sfx.minPitch;
float pitch=util::random(pitchDiff)+sfx.minPitch;

@ -45,7 +45,7 @@ using EventName=std::string;
class SoundEffect{
public:
SoundEffect(const std::string_view filename,const float&vol,const float&minPitch=0.9f,const float&maxPitch=1.1f);
SoundEffect(const std::string_view filename,const float&vol,const float&minPitch=0.9f,const float&maxPitch=1.1f,const bool combatSound=false);
static void PlaySFX(const std::string_view eventName,const vf2d&pos);
static void Initialize();
static const vf2d CENTERED;
@ -53,6 +53,7 @@ private:
static std::multimap<EventName,SoundEffect>SOUND_EFFECTS;
std::string filename;
float vol;
bool combatSound=false;
float minPitch=0.9f;
float maxPitch=1.1f;
};

@ -85,13 +85,7 @@ void State_GameRun::OnUserUpdate(AiL*game){
game->UpdateEffects(game->GetElapsedTime());
GameEvent::UpdateEvents();
game->GetPlayer()->Update(game->GetElapsedTime());
for(Monster&m:MONSTER_LIST){
m.Update(game->GetElapsedTime());
}
for(Monster&m:game->monstersToBeSpawned){
MONSTER_LIST.push_back(m);
}
game->monstersToBeSpawned.clear();
game->UpdateMonsters();
ItemDrop::UpdateDrops(game->GetElapsedTime());
game->UpdateBullets(game->GetElapsedTime());

@ -40,6 +40,7 @@ All rights reserved.
#include "Menu.h"
#include "TitleScreen.h"
#include "Key.h"
#include "ItemDrop.h"
INCLUDE_game
@ -47,13 +48,25 @@ void State_MainMenu::OnStateChange(GameState*prevState){
Audio::PlayBGM("title_screen");
TitleScreen::Reset();
game->UpdateDiscordStatus("Main Menu","");
game->LoadLevel("starting_map"_S,AiL::NO_MUSIC_CHANGE);
};
void State_MainMenu::OnLevelLoad(){}
void State_MainMenu::OnLevelLoad(){
game->GetPlayer()->SetIframes(999999.f);
game->GetPlayer()->SetInvisible(true);
}
void State_MainMenu::OnUserUpdate(AiL*game){
TitleScreen::Update();
if(AiL::KEY_CONFIRM.Released()){
TitleScreen::Skip();
}
game->UpdateEffects(game->GetElapsedTime());
GameEvent::UpdateEvents();
game->UpdateMonsters();
ItemDrop::UpdateDrops(game->GetElapsedTime());
game->UpdateBullets(game->GetElapsedTime());
game->UpdateCamera(game->GetElapsedTime());
};
void State_MainMenu::Draw(AiL*game){
TitleScreen::Draw();

@ -478,7 +478,11 @@ class TMXParser{
}
} else
if (newTag.tag=="object"&&newTag.data["type"]=="PlayerSpawnLocation") {
parsedMapInfo.MapData.playerSpawnLocation={newTag.GetInteger("x")-newTag.GetInteger("width")/2,newTag.GetInteger("y")-newTag.GetInteger("height")/2};
float width=1.f;
float height=1.f;
if(newTag.data.count("width")>0)width=newTag.GetFloat("width");
if(newTag.data.count("height")>0)height=newTag.GetFloat("height");
parsedMapInfo.MapData.playerSpawnLocation={int(newTag.GetFloat("x")-width/2),int(newTag.GetFloat("y")-height/2)};
} else
if (newTag.tag=="object"&&newTag.data["type"]=="NPC") {
if(inNPCTag)parsedMapInfo.npcs.push_back(NPCData{npcTag});
@ -517,7 +521,11 @@ class TMXParser{
//This is an object with a type that doesn't fit into other categories, we can add it to ZoneData.
if(parsedMapInfo.ZoneData.find(newTag.data["type"])!=parsedMapInfo.ZoneData.end()){
std::vector<ZoneData>&zones=parsedMapInfo.ZoneData.at(newTag.data["type"]);
zones.emplace_back(geom2d::rect<int>{{newTag.GetInteger("x"),newTag.GetInteger("y")},{newTag.GetInteger("width"),newTag.GetInteger("height")}});
float width=1.f;
float height=1.f;
if(newTag.data.count("width")>0)width=newTag.GetFloat("width");
if(newTag.data.count("height")>0)height=newTag.GetFloat("height");
zones.emplace_back(geom2d::rect<int>{{newTag.GetInteger("x"),newTag.GetInteger("y")},{int(width),int(height)}});
prevZoneData=&zones.back();
} else {
if(newTag.data["width"].length()>0&&newTag.data["height"].length()>0){ //This ensures the zone is valid to begin with.

@ -23,8 +23,6 @@ Add Bonus XP when completing a stage
- Credits/Licensing
- Implement some obtained commercial art.
- 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.

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0
#define VERSION_MINOR 3
#define VERSION_PATCH 0
#define VERSION_BUILD 7577
#define VERSION_BUILD 7587
#define stringify(a) stringify_(a)
#define stringify_(a) #a

File diff suppressed because it is too large Load Diff

@ -571,7 +571,7 @@
<property name="Connection 4 - West" type="object" value="7"/>
<property name="Map" propertytype="Level" value="CAMPAIGN_1_2"/>
<property name="Type" propertytype="StageType" value="DUNGEON"/>
<property name="Unlock Condition" propertytype="Level" value="CAMPAIGN_1_1"/>
<property name="Unlock Condition" propertytype="Level" value="STORY_1_1"/>
</properties>
</object>
<object id="5" name="Story I" type="StagePlate" x="344" y="476" width="20" height="24">

@ -9,6 +9,7 @@ Events
{
Bear Slam Attack
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = bear_slam.ogg, 70%
}
@ -112,70 +113,83 @@ Events
}
Monster Hurt
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = monster_hurt.ogg, 40%
}
Player Hit
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = player_hit1.ogg, 40%
File[1] = player_hit2.ogg, 100%
}
Ranger Auto Attack
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = ranger_auto1.ogg, 50%
File[1] = ranger_auto2.ogg, 50%
}
Ranger Retreat
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = ranger_backstep.ogg, 90%
}
Ranger Multishot
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = ranger_multishot.ogg, 100%
}
Ranger Rapid Fire
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = ranger_rapid_fire.ogg, 100%
}
Ranger Charged Shot
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = ranger_charged_shot.ogg, 70%
}
Slime Dead
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = slime_dead.ogg, 60%
File[1] = slime_dead2.ogg, 60%
}
Monster Dead
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = slime_dead2.ogg, 60%
}
Slime King Land
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = slime_king_landing.ogg, 100%
}
Slime King Shoot
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = slime_king_shoot.ogg, 60%
}
Slime Shoot
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = slime_shoot.ogg, 100%
File[1] = slime_shoot2.ogg, 80%
}
Slime Walk
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = slime_walk.ogg, 10%
File[1] = slime_walk2.ogg, 10%
@ -203,37 +217,44 @@ Events
}
Ursule Dead
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = ursule_dead.ogg, 100%
}
Ursule Phase Transition
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = ursule_phase_transition.ogg, 100%
}
Warrior Auto Attack
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = warrior_auto1.ogg, 60%
}
Warrior Battlecry
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = warrior_battlecry.ogg, 100%
}
Warrior Block Hit
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = warrior_blockhit1.ogg, 100%
File[1] = warrior_blockhit2.ogg, 100%
}
Warrior Ground Slam
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = warrior_groundslam.ogg, 100%
}
Warrior Sonic Slash
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = warrior_sonicslash.ogg, 70%
}
@ -255,31 +276,37 @@ Events
}
Wizard Fire Bolt Hit
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = wizard_firebolt_hit.ogg, 100%
}
Wizard Lightning Bolt Shoot
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = wizard_lightningbolt.ogg, 60%
}
Wizard Lightning Bolt Hit
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = wizard_firebolt_hit.ogg, 100%
}
Wizard Meteor
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = wizard_meteor.ogg, 100%
}
Wizard Meteor Flames
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = wizard_meteor_lingering.ogg, 100%
}
Wizard Teleport
{
CombatSound = True
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = wizard_teleport.ogg, 100%
}

@ -20,7 +20,7 @@ save_server = https://projectdivar.com:4505/AiL
map_config = levels.txt
# Starting map when loading the game.
starting_map = WORLD_MAP
starting_map = INTRO_MAP
# Player Properties Loading Config
player_config = Player.txt

@ -2,6 +2,11 @@ map_path = assets/Campaigns/
Levels
{
INTRO_MAP
{
Map File = Intro_Map.tmx
}
WORLD_MAP
{
Map File = World_Map.tmx

Loading…
Cancel
Save