Added Sound effect configuration and implementation.

pull/29/head
sigonasr2 11 months ago
parent 6539bbdb50
commit 0643393b9c
  1. 5
      Adventures in Lestoria/Adventures in Lestoria.vcxproj
  2. 6
      Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
  3. 5
      Adventures in Lestoria/AdventuresInLestoria.cpp
  4. 15
      Adventures in Lestoria/Audio.cpp
  5. 12
      Adventures in Lestoria/Item.cpp
  6. 4
      Adventures in Lestoria/Item.h
  7. 77
      Adventures in Lestoria/SoundEffect.cpp
  8. 55
      Adventures in Lestoria/SoundEffect.h
  9. 2
      Adventures in Lestoria/Version.h
  10. 3
      Adventures in Lestoria/assets/config/audio/bgm.txt
  11. 125
      Adventures in Lestoria/assets/config/audio/events.txt
  12. 6
      Adventures in Lestoria/assets/config/items/ItemDatabase.txt
  13. 1
      Adventures in Lestoria/olcUTIL_DataFile.h

@ -463,6 +463,7 @@
</ClInclude>
<ClInclude Include="ScrollableWindowComponent.h" />
<ClInclude Include="InventoryScrollableWindowComponent.h" />
<ClInclude Include="SoundEffect.h" />
<ClInclude Include="SpawnEncounterLabel.h" />
<ClInclude Include="State.h" />
<ClInclude Include="State_GameRun.h" />
@ -631,6 +632,10 @@
</ClCompile>
<ClCompile Include="ShootAfar.cpp" />
<ClCompile Include="SlimeKing.cpp" />
<ClCompile Include="SoundEffect.cpp">
<SubType>
</SubType>
</ClCompile>
<ClCompile Include="State_GameRun.cpp" />
<ClCompile Include="State_LevelComplete.cpp">
<SubType>

@ -423,6 +423,9 @@
<ClInclude Include="stb_vorbis.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SoundEffect.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Player.cpp">
@ -710,6 +713,9 @@
<ClCompile Include="stb_vorbis.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SoundEffect.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />

@ -69,6 +69,7 @@ All rights reserved.
#include "Merchant.h"
#include "SaveFile.h"
#include "TitleScreen.h"
#include "SoundEffect.h"
#ifndef __EMSCRIPTEN__
#include "discord.h"
#endif
@ -237,6 +238,7 @@ bool AiL::OnUserCreate(){
Audio::Initialize();
EnvironmentalAudio::Initialize();
SoundEffect::Initialize();
LoadLevel(LEVEL_NAMES["starting_map"_S]);
ChangePlayerClass(WARRIOR);
@ -2467,6 +2469,9 @@ bool AiL::UseLoadoutItem(int slot){
if(GetLoadoutItem(slot).lock()->Amt()>0){
Inventory::UseItem(GetLoadoutItem(slot).lock()->ActualName());
GetLoadoutItem(slot).lock()->amt--;
if(GetLoadoutItem(slot).lock()->UseSound().length()>0){
SoundEffect::PlaySFX(GetLoadoutItem(slot).lock()->UseSound());
}
return true;
}
return false;

@ -48,7 +48,9 @@ void Audio::Initialize(){
Engine().SetBackgroundPlay(true);
Self().events.insert("Default Volume");
for(auto&[key,data]:DATA["Events"]){
Self().events.insert(key);
if(key!="SFX"){ //HACK ALERT! We are specifically excluding the SFX key because it's used to specify the sound effects in-game.
Self().events.insert(key);
}
}
for(auto&[songFileName,size]:DATA["BGM"]){
auto&data=DATA["BGM"][songFileName];
@ -67,14 +69,7 @@ void Audio::Initialize(){
channelCounter++;
}
if(!data.HasProperty("Default Volume"))ERR(std::format("WARNING! Track {} does not have a Default Volume parameter!",bgm.GetName()));
if(data["Default Volume"].GetValueCount()!=bgm.GetChannelCount())ERR(std::format("WARNING! Default Volume parameters do not match channel count. {} != {}",data["Default Volume"].GetValueCount(),bgm.GetChannelCount()));
VolumeList volumes;
for(int i=0;i<data["Default Volume"].GetValueCount();i++){
volumes.push_back(data["Default Volume"].GetInt(i)/100.f);
}
bgm.AddEventVolumes("Default Volume",volumes);
if(!data["Events"].HasProperty("Default Volume"))ERR(std::format("WARNING! Track {} does not have a Default Volume parameter!",bgm.GetName()));
if(data.HasProperty("Fade Time")){
bgm.SetFadeTime(data["Fade Time"].GetReal());
@ -84,7 +79,7 @@ void Audio::Initialize(){
if(data.HasProperty("Events")){
for(auto&[eventName,size]:DATA["Events"]){
for(auto&eventName:Self().events){
auto&eventData=data["Events"][eventName];
if(eventData.GetValueCount()!=bgm.GetChannelCount())ERR(std::format("WARNING! {} parameters do not match channel count. {} != {}",eventName,eventData.GetValueCount(),bgm.GetChannelCount()));
VolumeList volumes;

@ -110,6 +110,7 @@ void ItemInfo::InitializeItems(){
Stats minStats;
Stats maxStats;
bool useDuringCast=false;
EventName useSound;
for(auto&[itemKey,itemValue]:data[key].GetKeys()){
std::string keyName=itemKey;
if(keyName=="Description"){
@ -145,6 +146,9 @@ void ItemInfo::InitializeItems(){
}else
if(keyName=="SellValue"){
sellValue=data[key][keyName].GetInt();
}else
if(keyName=="UseSound"){
useSound=data[key][keyName].GetString();
}else{ //THis is a custom override modifier for a script. NO-OP
}
}
@ -230,6 +234,7 @@ void ItemInfo::InitializeItems(){
it.buyValue=buyValue;
it.sellValue=sellValue;
it.useDuringCast=useDuringCast;
it.useSound=useSound;
if(slot.size()>0){
for(std::string&s:slot){
if(!nameToEquipSlot.count(s))ERR("WARNING! Tried to add item "<<it.name<<" to slot "<<s<<" which doesn't exist!");
@ -1097,4 +1102,11 @@ Stats ItemInfo::RandomizeStats(){
const bool Item::HasRandomizedStats()const{
return randomizedStats.size()>0;
}
const EventName&ItemInfo::UseSound()const{
return useSound;
}
const EventName&Item::UseSound()const{
return it->UseSound();
}

@ -54,6 +54,7 @@ class ItemProps;
using IT=std::string;
using ITCategory=std::string;
using EventName=std::string;
using ItemScript=std::function<bool(AiL*,ItemProps)>;
@ -180,6 +181,7 @@ public:
//Use for places where the item name is actually displayed. Provides modified text that shows additional information like enhancement levels.
const std::string DisplayName()const;
const std::string Description(CompactText compact=COMPACT)const;
const EventName&UseSound()const;
const ITCategory Category()const;
const EquipSlot GetEquipSlot()const;
const::Decal*const Decal()const;
@ -286,6 +288,7 @@ class ItemInfo{
EquipSlot slot;
EnhancementInfo enhancement;
::Decal*img;
EventName useSound="";
std::string set="";
//Returns true if the item can be used, false otherwise
std::string useFunc="";
@ -313,6 +316,7 @@ public:
/*
For the useFunc, return true if the item can be used, false otherwise.
*/
const EventName&UseSound()const;
const ItemScript&OnUseAction()const;
const Stats GetStats(int enhancementLevel)const;
const float CastTime()const;

@ -0,0 +1,77 @@
#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 © 2023 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#include "olcUTIL_DataFile.h"
#include "SoundEffect.h"
#include "Audio.h"
#include "util.h"
#include "DEFINES.h"
INCLUDE_DATA
std::multimap<EventName,SoundEffect>SoundEffect::SOUND_EFFECTS;
SoundEffect::SoundEffect(const std::string_view filename,const float&vol)
:filename(filename),vol(vol){
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;
while(DATA["Events"]["SFX"][key].HasProperty(std::format("File[{}]",counter))){
utils::datafile&data=DATA["Events"]["SFX"][key][std::format("File[{}]",counter)];
SOUND_EFFECTS.insert({key,SoundEffect{data.GetString(0),data.GetInt(1)/100.f}});
counter++;
}
}
}
void SoundEffect::PlaySFX(const std::string_view eventName){
auto itr=SOUND_EFFECTS.equal_range(std::string(eventName));
size_t soundCount=std::distance(itr.first,itr.second);
size_t soundEffectChoice=util::random()%soundCount;
int counter=0;
auto it=itr.first;
while(counter!=soundEffectChoice){
++counter;
++it;
}
const SoundEffect&sfx=(*it).second;
Audio::Engine().Play(operator""_SFX(sfx.filename.c_str(),sfx.filename.length()),sfx.vol);
}

@ -0,0 +1,55 @@
#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 © 2023 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#pragma once
#include <string>
#include <map>
#include "Error.h"
using EventName=std::string;
class SoundEffect{
public:
SoundEffect(const std::string_view filename,const float&vol);
static void PlaySFX(const std::string_view eventName);
static void Initialize();
private:
static std::multimap<EventName,SoundEffect>SOUND_EFFECTS;
std::string filename;
float vol;
};

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 1
#define VERSION_BUILD 5466
#define VERSION_BUILD 5476
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -18,13 +18,12 @@ BGM
channel[8]=foresty1_1_strings.ogg
channel[9]=foresty1_1_xtra perc.ogg
Default Volume = 70%,70%,70%,70%,70%,70%,70%,70%,70%,70%
# Transition time between one phase to the next.
Fade Time = 2.0
Events
{
Default Volume = 70%,70%,70%,70%,70%,70%,70%,70%,70%,70%
LowHealth = 100%,100%,100%,20%,20%,20%,100%,100%,20%,100%
InCombat = 100%,100%,100%,100%,100%,100%,100%,100%,100%,100%
Underwater = 10%,10%,10%,60%,80%,80%,10%,10%,70%,10%

@ -8,158 +8,195 @@ Events
{
Consume Potion
{
File[0] = consume_potion.ogg
# Specify file names, followed by volume %
File[0] = consume_potion.ogg, 70%
}
Consume Item
{
File[0] = consume_item.ogg
# Specify file names, followed by volume %
File[0] = consume_item.ogg, 60%
}
Equip Armor
{
File[0] = equip.ogg
File[1] = equip2.ogg
# Specify file names, followed by volume %
File[0] = equip.ogg, 100%
File[1] = equip2.ogg, 100%
}
Equip Accessory
{
File[0] = equip_ring.ogg
# Specify file names, followed by volume %
File[0] = equip_ring.ogg, 100%
}
Footstep
{
File[0] = footsteps.ogg
# Specify file names, followed by volume %
File[0] = footsteps.ogg, 100%
}
Footstep - Wet
{
File[0] = footsteps_wet.ogg
# Specify file names, followed by volume %
File[0] = footsteps_wet.ogg, 100%
}
Buy Item
{
File[0] = item_buy.ogg
# Specify file names, followed by volume %
File[0] = item_buy.ogg, 100%
}
Sell Item
{
File[0] = item_sell.ogg
# Specify file names, followed by volume %
File[0] = item_sell.ogg, 100%
}
Craft Item
{
File[0] = item_craft.ogg
# Specify file names, followed by volume %
File[0] = item_craft.ogg, 100%
}
Enhance Item
{
File[0] = item_enhance.ogg
# Specify file names, followed by volume %
File[0] = item_enhance.ogg, 100%
}
Monster Hurt
{
File[0] = monster_hurt.ogg
# Specify file names, followed by volume %
File[0] = monster_hurt.ogg, 100%
}
Ranger Auto Attack
{
File[0] = ranger_auto1.ogg
File[1] = ranger_auto2.ogg
# Specify file names, followed by volume %
File[0] = ranger_auto1.ogg, 100%
File[1] = ranger_auto2.ogg, 100%
}
Ranger Backstep
{
File[0] = ranger_backstep.ogg
# Specify file names, followed by volume %
File[0] = ranger_backstep.ogg, 100%
}
Ranger Multishot
{
File[0] = ranger_multishot.ogg
# Specify file names, followed by volume %
File[0] = ranger_multishot.ogg, 100%
}
Ranger Rapid Fire
{
File[0] = ranger_rapid_fire.ogg
# Specify file names, followed by volume %
File[0] = ranger_rapid_fire.ogg, 100%
}
Ranger Charged Shot
{
File[0] = ranger_charged_shot.ogg
# Specify file names, followed by volume %
File[0] = ranger_charged_shot.ogg, 100%
}
Ranger Multishot
{
File[0] = ranger_multishot.ogg
# Specify file names, followed by volume %
File[0] = ranger_multishot.ogg, 100%
}
Slime Dead
{
File[0] = slime_dead.ogg
# Specify file names, followed by volume %
File[0] = slime_dead.ogg, 100%
}
Monster Dead
{
File[0] = slime_dead2.ogg
# Specify file names, followed by volume %
File[0] = slime_dead2.ogg, 100%
}
Slime King Land
{
File[0] = slime_king_landing.ogg
# Specify file names, followed by volume %
File[0] = slime_king_landing.ogg, 100%
}
Slime King Shoot
{
File[0] = slime_king_shoot.ogg
# Specify file names, followed by volume %
File[0] = slime_king_shoot.ogg, 100%
}
Slime Shoot
{
File[0] = slime_shoot.ogg
File[1] = slime_shoot2.ogg
# Specify file names, followed by volume %
File[0] = slime_shoot.ogg, 100%
File[1] = slime_shoot2.ogg, 100%
}
Slime Walk
{
File[0] = slime_walk.ogg
File[1] = slime_walk2.ogg
File[2] = slime_walk3.ogg
# Specify file names, followed by volume %
File[0] = slime_walk.ogg, 100%
File[1] = slime_walk2.ogg, 100%
File[2] = slime_walk3.ogg, 100%
}
Spell Cast
{
File[0] = spell_cast.ogg
# Specify file names, followed by volume %
File[0] = spell_cast.ogg, 100%
}
Warrior Auto Attack
{
File[0] = warrior_auto1.ogg
# Specify file names, followed by volume %
File[0] = warrior_auto1.ogg, 100%
}
Warrior Battlecry
{
File[0] = warrior_battlecry.ogg
# Specify file names, followed by volume %
File[0] = warrior_battlecry.ogg, 100%
}
Warrior Block Hit
{
File[0] = warrior_blockhit1.ogg
File[1] = warrior_blockhit2.ogg
# Specify file names, followed by volume %
File[0] = warrior_blockhit1.ogg, 100%
File[1] = warrior_blockhit2.ogg, 100%
}
Warrior Ground Slam
{
File[0] = warrior_groundslam.ogg
# Specify file names, followed by volume %
File[0] = warrior_groundslam.ogg, 100%
}
Warrior Sonic Slash
{
File[0] = warrior_sonicslash.ogg
# Specify file names, followed by volume %
File[0] = warrior_sonicslash.ogg, 100%
}
Wizard Auto Attack
{
File[0] = wizard_auto1.ogg
File[1] = wizard_auto2.ogg
# Specify file names, followed by volume %
File[0] = wizard_auto1.ogg, 100%
File[1] = wizard_auto2.ogg, 100%
}
Wizard Fire Bolt
{
File[0] = wizard_firebolt.ogg
# Specify file names, followed by volume %
File[0] = wizard_firebolt.ogg, 100%
}
Wizard Fire Bolt Hit
{
File[0] = wizard_firebolt_hit.ogg
# Specify file names, followed by volume %
File[0] = wizard_firebolt_hit.ogg, 100%
}
Wizard Lightning Bolt
{
File[0] = wizard_lightningbolt.ogg
# Specify file names, followed by volume %
File[0] = wizard_lightningbolt.ogg, 100%
}
Wizard Lightning Bolt Hit
{
File[0] = wizard_firebolt_hit.ogg
# Specify file names, followed by volume %
File[0] = wizard_firebolt_hit.ogg, 100%
}
Wizard Meteor
{
File[0] = wizard_meteor.ogg
# Specify file names, followed by volume %
File[0] = wizard_meteor.ogg, 100%
}
Wizard Meteor Flames
{
File[0] = wizard_meteor_lingering.ogg
# Specify file names, followed by volume %
File[0] = wizard_meteor_lingering.ogg, 100%
}
Wizard Teleport
{
File[0] = wizard_teleport.ogg
# Specify file names, followed by volume %
File[0] = wizard_teleport.ogg, 100%
}
}
}

@ -10,6 +10,7 @@ ItemDatabase
Cooldown Time = 5.0
Cast Time = 0.0
SellValue = 8
UseSound = Consume Item
}
Minor Health Potion
{
@ -21,6 +22,7 @@ ItemDatabase
Cast Time = 0.0
SellValue = 16
BuyValue = 23
UseSound = Consume Potion
Crafting
{
# When this crafting recipe is available.
@ -42,6 +44,7 @@ ItemDatabase
Cast Time = 0.0
SellValue = 21
BuyValue = 30
UseSound = Consume Potion
Crafting
{
# When this crafting recipe is available.
@ -62,6 +65,7 @@ ItemDatabase
Cooldown Time = 5.0
Cast Time = 0.0
SellValue = 15
UseSound = Consume Potion
Crafting
{
# When this crafting recipe is available.
@ -83,6 +87,7 @@ ItemDatabase
Cooldown Time = 5.0
Cast Time = 0.0
SellValue = 30
UseSound = Consume Potion
Crafting
{
# When this crafting recipe is available.
@ -104,6 +109,7 @@ ItemDatabase
ItemCategory = Consumables
SellValue = 7
BuyValue = 10
UseSound = Consume Item
}
Green Slime Remains
{

@ -63,6 +63,7 @@ David Barr, aka javidx9, <EFBFBD>OneLoneCoder 2019, 2020, 2021, 2022
#include <sstream>
#include <numeric>
#include "Error.h"
#include "olcPixelGameEngine.h"
using namespace std::literals;

Loading…
Cancel
Save