Add RepeatingSoundEffect class to allow easy creation and handling of looping sound effects ingame. Add rock breaking, rock toss cast, pillar rise, dig sound effects. Fix typo on Hawk Feather item description key name. Placeholder item icons added. Add sound effects to Stone Elemental's attacks. Release Build 9656.
@ -2290,6 +2290,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
|
||||
ItemDrop::drops.clear();
|
||||
GameEvent::events.clear();
|
||||
Audio::SetBGMPitch(1.f);
|
||||
RepeatingSoundEffect::StopAllSounds();
|
||||
#ifdef __EMSCRIPTEN__
|
||||
Audio::muted=true;
|
||||
Audio::UpdateBGMVolume();
|
||||
|
@ -80,4 +80,10 @@ public:
|
||||
}
|
||||
return std::get<std::vector<std::any>>(attributes[a]);
|
||||
};
|
||||
inline size_t&GetSizeT(Attribute a){
|
||||
if(attributes.count(a)==0){
|
||||
attributes[a]=size_t(0);
|
||||
}
|
||||
return std::get<size_t>(attributes[a]);
|
||||
};
|
||||
};
|
@ -72,7 +72,7 @@ using MonsterSpawnerID=int;
|
||||
|
||||
#define ACCESS_PLAYER Player*p=game->GetPlayer();
|
||||
|
||||
#define VARIANTS float,int,std::string,bool,vf2d,std::vector<std::any>
|
||||
#define VARIANTS float,int,std::string,bool,vf2d,std::vector<std::any>,size_t
|
||||
#undef INFINITE
|
||||
#define INFINITE 999999
|
||||
|
||||
|
@ -40,6 +40,7 @@ All rights reserved.
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "FallingDebris.h"
|
||||
#include "util.h"
|
||||
#include "SoundEffect.h"
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_MONSTER_LIST
|
||||
@ -82,6 +83,8 @@ void LargeStone::Update(float fElapsedTime){
|
||||
#pragma endregion
|
||||
|
||||
fadeOutTime=0.5f;
|
||||
|
||||
SoundEffect::PlaySFX("Large Rock Break",pos);
|
||||
}else
|
||||
if(z>0.f&&fadeOutTime>=0.f){
|
||||
pos=startingPos.lerp(landingPos,(GetTimeAlive()-initialMoveWaitTime)/stoneThrowTime);
|
||||
|
@ -823,6 +823,11 @@ std::map<ItemInfo*,uint16_t>Monster::SpawnDrops(){
|
||||
void Monster::OnDeath(){
|
||||
animation.ChangeState(internal_animState,GetDeathAnimationName());
|
||||
|
||||
if(GetSizeT(Attribute::LOOPING_SOUND_ID)!=std::numeric_limits<size_t>::max()){//Just make sure on death any looping sound effect has been discarded proper.
|
||||
SoundEffect::StopLoopingSFX(GetSizeT(Attribute::LOOPING_SOUND_ID));
|
||||
GetSizeT(Attribute::LOOPING_SOUND_ID)=std::numeric_limits<size_t>::max();
|
||||
}
|
||||
|
||||
if(HasMountedMonster()){
|
||||
for(DeathSpawnInfo&deathInfo:deathData){
|
||||
deathInfo.Spawn(GetPos(),OnUpperLevel());
|
||||
|
@ -39,6 +39,7 @@ All rights reserved.
|
||||
#include <string>
|
||||
#define F(attr) GetFloat(attr)
|
||||
#define I(attr) GetInt(attr)
|
||||
#define SIZET(attr) GetSizeT(attr)
|
||||
#define S(attr) GetString(attr)
|
||||
#define B(attr) GetBool(attr)
|
||||
#define V(attr) GetVf2d(attr)
|
||||
@ -121,4 +122,6 @@ enum class Attribute{
|
||||
WIND_STRENGTH,
|
||||
WIND_PHASE_TIMER,
|
||||
MARKED_DEAD,
|
||||
LOOPING_SOUND_ID,
|
||||
PLAYED_FLAG,
|
||||
};
|
@ -48,6 +48,15 @@ INCLUDE_game
|
||||
|
||||
std::multimap<EventName,SoundEffect>SoundEffect::SOUND_EFFECTS;
|
||||
const vf2d SoundEffect::CENTERED={-8419.f,-3289.f};
|
||||
std::unordered_set<size_t>RepeatingSoundEffect::playingSoundEffects;
|
||||
|
||||
void RepeatingSoundEffect::StopAllSounds(){
|
||||
for(auto&id:playingSoundEffects){
|
||||
Audio::Engine().Stop(id);
|
||||
Audio::Engine().UnloadSound(id);
|
||||
}
|
||||
playingSoundEffects.clear();
|
||||
}
|
||||
|
||||
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){
|
||||
@ -79,18 +88,7 @@ void SoundEffect::Initialize(){
|
||||
|
||||
void SoundEffect::PlaySFX(const std::string_view eventName,const vf2d&pos){
|
||||
if(eventName.length()==0)return;
|
||||
auto itr=SOUND_EFFECTS.equal_range(std::string(eventName));
|
||||
size_t soundCount=std::distance(itr.first,itr.second);
|
||||
if(soundCount==0)ERR("WARNING! Sound Effect "<<std::quoted(eventName)<<" does not have any sound effects loaded/doesn't exist!")
|
||||
size_t soundEffectChoice=util::random()%soundCount;
|
||||
|
||||
int counter=0;
|
||||
auto it=itr.first;
|
||||
while(counter!=soundEffectChoice){
|
||||
++counter;
|
||||
++it;
|
||||
}
|
||||
const SoundEffect&sfx=(*it).second;
|
||||
const SoundEffect&sfx=GetRandomSFXFromFile(eventName);
|
||||
|
||||
if(GameState::STATE==GameState::states[States::MAIN_MENU]&&sfx.combatSound)return; //Do not play combat sounds on the main menu.
|
||||
|
||||
@ -112,4 +110,35 @@ void SoundEffect::PlaySFX(const std::string_view eventName,const vf2d&pos){
|
||||
Audio::Engine().Play(operator""_SFX(sfx.filename.c_str(),sfx.filename.length()),vol,pan,pitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t SoundEffect::PlayLoopingSFX(const std::string_view eventName,const vf2d&pos){
|
||||
const SoundEffect&sfx=GetRandomSFXFromFile(eventName);
|
||||
const size_t id=Audio::Engine().LoadSound(operator""_SFX(sfx.filename.c_str(),sfx.filename.length()));
|
||||
RepeatingSoundEffect::playingSoundEffects.insert(id);
|
||||
Audio::Engine().Play(id,true);
|
||||
return id;
|
||||
}
|
||||
|
||||
void SoundEffect::StopLoopingSFX(const int id){
|
||||
if(!RepeatingSoundEffect::playingSoundEffects.count(id))return; //Prevent crashes from stopping a sound more than once. Called by accident probably.
|
||||
Audio::Engine().Stop(id);
|
||||
Audio::Engine().UnloadSound(id);
|
||||
RepeatingSoundEffect::playingSoundEffects.erase(id);
|
||||
}
|
||||
|
||||
SoundEffect&SoundEffect::GetRandomSFXFromFile(const std::string_view eventName){
|
||||
auto itr=SOUND_EFFECTS.equal_range(std::string(eventName));
|
||||
size_t soundCount=std::distance(itr.first,itr.second);
|
||||
if(soundCount==0)ERR("WARNING! Sound Effect "<<std::quoted(eventName)<<" does not have any sound effects loaded/doesn't exist!")
|
||||
size_t soundEffectChoice=util::random()%soundCount;
|
||||
|
||||
int counter=0;
|
||||
auto it=itr.first;
|
||||
while(counter!=soundEffectChoice){
|
||||
++counter;
|
||||
++it;
|
||||
}
|
||||
|
||||
return (*it).second;
|
||||
}
|
@ -38,18 +38,30 @@ All rights reserved.
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include "Error.h"
|
||||
|
||||
using EventName=std::string;
|
||||
|
||||
class RepeatingSoundEffect{
|
||||
friend class AiL;
|
||||
friend class SoundEffect;
|
||||
private:
|
||||
static void StopAllSounds();
|
||||
static std::unordered_set<size_t>playingSoundEffects;
|
||||
};
|
||||
|
||||
class SoundEffect{
|
||||
public:
|
||||
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);
|
||||
//Sets up a sound to be looped continuously.
|
||||
static size_t PlayLoopingSFX(const std::string_view eventName,const vf2d&pos);
|
||||
static void StopLoopingSFX(const int id);
|
||||
static void Initialize();
|
||||
static const vf2d CENTERED;
|
||||
private:
|
||||
static SoundEffect&GetRandomSFXFromFile(const std::string_view eventName);
|
||||
static std::multimap<EventName,SoundEffect>SOUND_EFFECTS;
|
||||
std::string filename;
|
||||
float vol;
|
||||
|
@ -42,6 +42,7 @@ All rights reserved.
|
||||
#include "DEFINES.h"
|
||||
#include "util.h"
|
||||
#include "BulletTypes.h"
|
||||
#include "SoundEffect.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
@ -67,6 +68,7 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str
|
||||
m.F(A::RECOVERY_TIME)-=fElapsedTime;
|
||||
if(m.F(A::RECOVERY_TIME)<=0.f){
|
||||
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
|
||||
m.SIZET(A::LOOPING_SOUND_ID)=SoundEffect::PlayLoopingSFX("Rock Toss Cast",m.GetPos());
|
||||
m.PerformAnimation("CAST",m.GetFacingDirectionToTarget(m.V(A::LOCKON_POS)));
|
||||
game->AddEffect(std::make_unique<SpellCircle>(m.V(A::LOCKON_POS),ConfigFloat("Beginning Phase.Pillar Cast Time"),"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Beginning Phase.Pillar Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Beginning Phase.Pillar Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Beginning Phase.Pillar Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Beginning Phase.Pillar Spell Insignia Rotation Spd"))),true);
|
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Beginning Phase.Pillar Cast Time");
|
||||
@ -76,6 +78,8 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str
|
||||
case SPAWN_PILLAR_CAST:{
|
||||
m.F(A::CASTING_TIMER)-=fElapsedTime;
|
||||
if(m.F(A::CASTING_TIMER)<=0.f){
|
||||
SoundEffect::StopLoopingSFX(m.SIZET(A::LOOPING_SOUND_ID));
|
||||
SoundEffect::PlaySFX("Pillar Rise",m.V(A::LOCKON_POS));
|
||||
m.I(A::PATTERN_REPEAT_COUNT)--;
|
||||
game->SpawnMonster(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Golem Pillar"),m.OnUpperLevel());
|
||||
game->Hurt(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult(),MONSTER_DATA.at("Stone Golem Pillar").GetAttack(),m.OnUpperLevel(),0.f,HurtType::PLAYER);
|
||||
@ -107,6 +111,8 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str
|
||||
//Physics!! Kinematic equation from https://openstax.org/books/physics/pages/3-2-representing-acceleration-with-equations-and-graphs a=(2d)/(t^2)
|
||||
const float acc{(2*-ConfigFloat("Standard Attack.Stone Throw Height Offset"))/std::pow(stoneTossTime,2.f)};
|
||||
|
||||
m.SIZET(A::LOOPING_SOUND_ID)=SoundEffect::PlayLoopingSFX("Rock Toss Cast",m.GetPos());
|
||||
|
||||
CreateBullet(LargeStone)(m.GetPos()+vf2d{0,ConfigFloat("Standard Attack.Stone Throw Height Offset")/2.f},ConfigFloat("Standard Attack.Stone Throw Time"),m.V(A::LOCKON_POS),m.F(A::CASTING_TIMER),ConfigPixels("Standard Attack.Stone Radius"),ConfigFloat("Standard Attack.Stone Throw Height Offset"),acc,ConfigInt("Standard Attack.Stone Damage"),ConfigFloat("Standard Attack.Stone Throw Knockback Factor"),m.OnUpperLevel(),false,INFINITY,false,WHITE,vf2d{1,1}*m.GetSizeMult(),util::random(2*PI))EndBullet;
|
||||
}
|
||||
}
|
||||
@ -114,6 +120,7 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str
|
||||
case STONE_THROW_CAST:{
|
||||
m.F(A::CASTING_TIMER)-=fElapsedTime;
|
||||
if(m.F(A::CASTING_TIMER)<=0.f){
|
||||
SoundEffect::StopLoopingSFX(m.SIZET(A::LOOPING_SOUND_ID));
|
||||
m.PerformAnimation("TOSS ROCK");
|
||||
m.F(A::RECOVERY_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration();
|
||||
m.phase=STONE_THROW_FINISH_ANIMATION;
|
||||
|
@ -41,6 +41,7 @@ All rights reserved.
|
||||
#include "MonsterStrategyHelpers.h"
|
||||
#include "BulletTypes.h"
|
||||
#include "util.h"
|
||||
#include "SoundEffect.h"
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_BULLET_LIST
|
||||
@ -93,6 +94,7 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string
|
||||
switch(randomAttackChoice){
|
||||
case 0:{
|
||||
m.PerformAnimation("STONE PILLAR CAST");
|
||||
m.SIZET(A::LOOPING_SOUND_ID)=SoundEffect::PlayLoopingSFX("Rock Toss Cast",m.GetPos());
|
||||
m.phase=STONE_PILLAR_CAST;
|
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Stone Pillar Cast Time");
|
||||
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
|
||||
@ -100,7 +102,9 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string
|
||||
}break;
|
||||
case 1:{
|
||||
m.PerformAnimation("ROCK TOSS CAST");
|
||||
m.SIZET(A::LOOPING_SOUND_ID)=SoundEffect::PlayLoopingSFX("Rock Toss Cast",m.GetPos());
|
||||
m.phase=SHOOT_STONE_CAST;
|
||||
m.B(A::PLAYED_FLAG)=false;
|
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Rock Toss Track Time")+ConfigFloat("Rock Toss Wait Time");
|
||||
CreateBullet(LevitatingRock)(m,game->GetPlayer()->GetPos(),1.f,0.f,ConfigPixels("Rock Toss Max Spawn Distance"),ConfigFloat("Rock Toss Track Time"),ConfigFloat("Rock Toss Wait Time"),ConfigFloat("Rock Toss Bullet Speed"),ConfigFloat("Rock Radius"),std::max(1,ConfigInt("Rock Toss Damage")/5),m.OnUpperLevel(),false,WHITE,vf2d{1,1})EndBullet;
|
||||
const int masterRockInd=BULLET_LIST.size()-1;
|
||||
@ -115,6 +119,7 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string
|
||||
}
|
||||
}break;
|
||||
case 2:{
|
||||
SoundEffect::PlaySFX("Dig",m.GetPos());
|
||||
m.PerformAnimation("BURROW UNDERGROUND");
|
||||
m.phase=DIVE_UNDERGROUND_DIG;
|
||||
m.F(A::CASTING_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration();
|
||||
@ -125,6 +130,8 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string
|
||||
case STONE_PILLAR_CAST:{
|
||||
m.F(A::CASTING_TIMER)-=fElapsedTime;
|
||||
if(m.F(A::CASTING_TIMER)<=0.f){
|
||||
SoundEffect::StopLoopingSFX(m.SIZET(A::LOOPING_SOUND_ID));
|
||||
SoundEffect::PlaySFX("Pillar Rise",m.V(A::LOCKON_POS));
|
||||
game->SpawnMonster(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar"),m.OnUpperLevel());
|
||||
ReturnToWaitingPhase();
|
||||
game->Hurt(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Pillar").GetSizeMult(),m.GetAttack(),m.OnUpperLevel(),0.f,HurtType::PLAYER);
|
||||
@ -141,10 +148,16 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string
|
||||
case SHOOT_STONE_CAST:{
|
||||
m.F(A::CASTING_TIMER)-=fElapsedTime;
|
||||
if(m.F(A::CASTING_TIMER)>=ConfigFloat("Rock Toss Wait Time")-ConfigFloat("Rock Toss Track Time")){
|
||||
SoundEffect::StopLoopingSFX(m.SIZET(A::LOOPING_SOUND_ID));
|
||||
m.PerformAnimation("STONE PILLAR CAST");
|
||||
m.UpdateFacingDirection(game->GetPlayer()->GetPos());
|
||||
}
|
||||
if(m.F(A::CASTING_TIMER)>=ConfigFloat("Rock Toss Track Time")&&!m.B(A::PLAYED_FLAG)){
|
||||
SoundEffect::PlaySFX("Rock Break",m.GetPos());
|
||||
m.B(A::PLAYED_FLAG)=true;
|
||||
}
|
||||
if(m.F(A::CASTING_TIMER)<=0.f){
|
||||
SoundEffect::StopLoopingSFX(m.SIZET(A::LOOPING_SOUND_ID));
|
||||
ReturnToWaitingPhase();
|
||||
}
|
||||
}break;
|
||||
@ -180,6 +193,7 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string
|
||||
|
||||
if(m.F(A::CASTING_TIMER)<=0.f){
|
||||
m.B(A::IGNORE_DEFAULT_ANIMATIONS)=false;
|
||||
SoundEffect::PlaySFX("Rise",m.GetPos());
|
||||
m.PerformAnimation("RISE FROM UNDERGROUND");
|
||||
m.phase=DIVE_UNDERGROUND_SURFACE;
|
||||
m.targetAcquireTimer=0;
|
||||
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 3
|
||||
#define VERSION_BUILD 9648
|
||||
#define VERSION_BUILD 9656
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -49,6 +49,12 @@ Events
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = craft_equip.ogg, 70%
|
||||
}
|
||||
Dig
|
||||
{
|
||||
CombatSound = True
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = dig.ogg, 100%
|
||||
}
|
||||
Equip Armor
|
||||
{
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
@ -115,6 +121,12 @@ Events
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = item_collect.ogg, 40%
|
||||
}
|
||||
Large Rock Break
|
||||
{
|
||||
CombatSound = True
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = rockbreak.ogg, 90%, 40%, 50%
|
||||
}
|
||||
Level Up
|
||||
{
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
@ -138,6 +150,12 @@ Events
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = monster_hurt.ogg, 40%
|
||||
}
|
||||
Pillar Rise
|
||||
{
|
||||
CombatSound = True
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = pillar_rise.ogg, 90%
|
||||
}
|
||||
Player Hit
|
||||
{
|
||||
CombatSound = True
|
||||
@ -176,6 +194,24 @@ Events
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = ranger_charged_shot.ogg, 70%
|
||||
}
|
||||
Rise
|
||||
{
|
||||
CombatSound = True
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = rise.ogg, 100%
|
||||
}
|
||||
Rock Break
|
||||
{
|
||||
CombatSound = True
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = rockbreak.ogg, 90%
|
||||
}
|
||||
Rock Toss Cast
|
||||
{
|
||||
CombatSound = True
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = rocktosscast.ogg, 100%
|
||||
}
|
||||
Slime Dead
|
||||
{
|
||||
CombatSound = True
|
||||
|
@ -228,7 +228,7 @@ ItemDatabase
|
||||
}
|
||||
Hawk Feather
|
||||
{
|
||||
Desciption = A Feather of a Hawk. Sadly no longer in perfect condition.
|
||||
Description = A Feather of a Hawk. Sadly no longer in perfect condition.
|
||||
ItemCategory = Materials
|
||||
SellValue = 7
|
||||
}
|
||||
|
BIN
Adventures in Lestoria/assets/items/Bird's Treasure.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
Adventures in Lestoria/assets/items/Blackpowder.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
Adventures in Lestoria/assets/items/Boar Meat.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
Adventures in Lestoria/assets/items/Broken Bow.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
Adventures in Lestoria/assets/items/Broken Dagger.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
Adventures in Lestoria/assets/items/Hawk Feather.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
Adventures in Lestoria/assets/items/Stone Heart.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
Adventures in Lestoria/assets/items/Stone Ring.png
Normal file
After Width: | Height: | Size: 621 B |