This system is designed with the purpose of protecting your game's music and audio files, giving them a minor encryption using the same data structure as RPGMaker XP's innate system, storing them within the game's Data folder, and allowing them to be compressed/encrypted within the .rgsaad file.
Features
Gives a level of protection towards your audio files
Places them within your Data Folder and permits rxdata compression
Drawbacks
Audio files take slightly longer to load based on filesize
Minor increase in cached file size by approximately 1.18 percent
Audio saved in the Data folder cannot be played in the Editor, game only*
During playback, original file is temporarily 'restored' in the root folder... but PROTECTED from copying anyway.
* Caching audio files makes valid .rxdata copies within your Data folder, and does not erase the originals. Original audio files within the Audio folder may still be played.
Script
Kached Audio
Code:
#==============================================================================
# ** Kichi's Kached Audio
#------------------------------------------------------------------------------
# version 1.2
# by DerVVulfman
# 08-21-2023 (MM-DD-YYYY)
# RGSS / RPGMaker XP
#==============================================================================
#
# INTRODUCTION:
#
# This system is designed with the purpose of protecting your game's music and
# audio files, giving them a minor encryption using the same data structure as
# RPGMaker XP's innate system, storing them within the game's Data folder, and
# allowing them to be compressed/encrypted within the .rgsaad file.
#
# It is nearly plug and play, with only a couple minor issues that are noted.
#
# Positives:
# * Gives a level of protection towards your audio files
# * Places them within your Data Folder and permits rxdata compression
#
# Negatives:
# * Audio files take slightly longer to load based on filesize
# * Minor increase in cached file size by approximately 1.18 percent
# * Audio saved in the Data folder cannot be played in the Editor, game only
#
#
#------------------------------------------------------------------------------
#
# INSTALLATION:
#
# Place this script below Scene_Debug and above Main. Use the described script
# calls to cache, monitor and/or un-cache your files.
#
#
#------------------------------------------------------------------------------
#
# FILES CREATED:
#
# This system will create a series of subfolders within your project's Data
# folder, these subfolders being BGM, BGS, ME and SE. It is within these that
# your stored 'cached' audio files will be recorded in .rxdata format.
#
# As all audio files kept here will have the same extension, the system will
# also create the 'AudioCache.rxdata' file, this too within the Data folder.
#
# The AudioCache file keeps track of all cached audio files, and their file
# extensions. This is vital for both playback of all cached audio files, as
# well as un-cached file restoration if the original audio files from within
# the project's Audio folder had been accidentally erased.
#
# All of the cached audio files will begin with '~$' to denote and identify
# them as temporary 'owner locked' files. Initially for Microsoft Word, this
# prefix will identify these filenames for temporary usage. This was found to
# be necessary with users who have their PCs connected to cloud services.
#
#
#------------------------------------------------------------------------------
#
# USAGE:
#
# When first run, this system generates a new file which it saves within your
# Data folder. This file is the 'AudioCache.rxdata' data file, and its pur-
# pose is to help track your cached audio files, and stores the file exten-
# sions of your audio for proper playback. It must not be deleted, otherwise
# the system will not function.
#
# The default methods of play_bgm, play_bgs, play_me and play_se have been
# altered to allow the playback of audio from within the Data folder. At the
# same time, a method within the sprite class that generate battle animation
# sound effects have too been altered. These alterations allow the system
# determine if the audio files have been cached, or are still within the
# default audio folder. This is quite handy as you will not be caching any
# audio from the RTP itself, only that from your own game project.
#
# There isn't a built-in function that will automatically cache all of your
# audio files. If you do not have access to a custom editor which may cache
# or un-cache an audio file, I will describe the actual script calls which
# will need to use this system. Even if you have an editor, please read it.
#
# If you are actively done with your project and are about to compress your
# game into the .rgsaad format, you will need to toggle the RGSAAD variable
# in the below 'AudioCache' module. The script itself does not know if the
# project is or isn't compressed, and needs this switch activated if true.
#
#
#------------------------------------------------------------------------------
#
# CLOUD SERVICES:
#
# The .rxdata audio files are stored with the '~$' prefix, identifying these
# files as temporary and to be ignored by cloud services. This was necessary
# for the system to work as it temporarily extracts the audio files for play-
# back. However, this means that a variety of cloud storage services will not
# copy and save your .rxdata encrypted audio files. In this instance, you'll
# need to manually upload them into your cloud.
#
#
#------------------------------------------------------------------------------
#
# SCRIPT CALLS:
#
# * Is it cached?
# -------------
# Syntax: result = $game_system.is_cached?(file, path)
# Params: file - the filename of the audio file (no extension included)
# path - the folder path ( "BGM\", "BGS\", "ME\" or "SE\ ")
#
# Function: This script call will let you know if the defined audio file
# has been cached and can be found within the Data folder under
# its specifically defined path.
#
#
# * * * * *
#
#
# * Cache the audio file
# --------------------
# Syntax: $game_system.cache_audio(file, path)
# Params: file - the filename of the audio file (no extension included)
# path - the folder path ( "BGM\", "BGS\", "ME\" or "SE\ ")
#
# Function: This script call is used to convert its innate format into an
# rxdata format which can be cached. It stores the resulting
# file within the Data folder and its defined path, and records
# the file and its original extension in the AudioCache file.
# Once this is performed, checking the audio file with the
# is_cached? script call (above) will return a 'true' result.
#
# This does not delete the original file from the Audio folder.
#
#
# * * * * *
#
#
# * Read/Restore from a Cache
# -------------------------
# Syntax: $game_system.audio_cache(file, path)
# Params: file - the filename of the audio file (no extension included)
# path - the folder path ( "BGM\", "BGS\", "ME\" or "SE\ ")
# dest - (optional) a folder in which to save the audio copy
#
# Function: This script call reads the cached audio file from the proper
# Data folder, and converts it into its original music format
# so it may be properly played within the system. It is assumed
# that the restored file is to be deleted after playback, and
# this call does not delete the file from the data folder.
#
# This brings out a copy of the audio file from the Data folder
# and saves it to the described destination folder, or it will
# be saved in the project's root folder if none specified.
#
#
# * * * * *
#
#
# * Remove from the Cache
# ---------------------
# Syntax: $game_system.remove_cache(file, path)
# Params: file - the filename of the audio file (no extension included)
# path - the folder path ( "BGM\", "BGS\", "ME\" or "SE\ ")
#
# Function: This script call is intended to restore the cached audio file
# back to the specified Audio folder, and eliminate it from the
# specified Data folder. Along with that, it will also remove
# the file from the AudioCache list. Doing so will generate a
# 'false' return when the 'is_cached?' script call is used.
#
# If an audio folder (BGM, ME, etc) is empty, the folder will
# be erased. A nice little bit of cleanup duty, eh?
#
# Removing a cached file will overwrite any audio file within
# the project's actual Audio folder it it exists.
#
# When this command is used to restore the last cached audio
# file, the AudioCache.rxdata file will have been emptied. When
# that happens, the AudioCache.rxdata file will also be erased.
# You will need to restart or use the Kichi Editor to recreate
# the AudioCache file for the file extention tracking service.
#
#
#------------------------------------------------------------------------------
#
# KNOWN CONFLICTS:
#
# This script will obviously conflict with any other script that will modify
# the bgm_play, bgs_play, me_play and/or se_play methods within Game System,
# and will conflict with any script that alters the animation_process_timing
# method within the RPG::Sprite class that handles battle system effects.
#
#
#------------------------------------------------------------------------------
#
# COMPATIBILITY:
#
# Fairly compatible for RPGMaker XP systems other than the conflicts just
# described above.
#
#
#------------------------------------------------------------------------------
#
# CREDITS AND THANKS:
#
# Thanks goes to Carlos_Davilla. Were not for his assistance, I would not
# have been aware of issues pertaining cloud storage systems, nor the use of
# established temporary file naming conventions to fix the issues.
#
#
#==============================================================================
#
# TERMS AND CONDITIONS:
#
# Free to use, even in commercial projects. Just note that I need some form
# of due credit, not just myself but Carlos_Davilla who assisted.
#
#
#==============================================================================
module AudioCache
RGSAAD = true # Switch to identify that that the project is encrypted
end
#==============================================================================
# ** RPG::Sprite
#------------------------------------------------------------------------------
# This is a class within the RPGXP module itself that loads each of RPGXP's
# graphic formats, creates a Bitmap object, and retains it.
#==============================================================================
class RPG::Sprite < ::Sprite
#--------------------------------------------------------------------------
# * Process Timing for animation flash and effects
# timing : timing
# hit : flag determining battle action effectiveness
#--------------------------------------------------------------------------
def animation_process_timing(timing, hit)
if (timing.condition == 0) or
(timing.condition == 1 and hit == true) or
(timing.condition == 2 and hit == false)
if timing.se.name != ""
se = timing.se
# If we have a cached file, use cached system
if $game_system.is_cached?("~$" + se.name,"SE/")
name = "~$" + se.name
$game_system.audio_cache(name,"SE/")
# Playback audio (not tied now to the Audio/SE folder)
Audio.se_play(name, se.volume, se.pitch)
# Acquire cached extension
ext = $game_system.get_cache_ext(name, "SE/")
# Delete temp file generated by audio_cache
File.delete(name + ext)
# Otherwise, default playback system
else
Audio.se_play("Audio/SE/" + se.name, se.volume, se.pitch)
end
end
case timing.flash_scope
when 1
self.flash(timing.flash_color, timing.flash_duration * 2)
when 2
if self.viewport != nil
self.viewport.flash(timing.flash_color, timing.flash_duration * 2)
end
when 3
self.flash(nil, timing.flash_duration * 2)
end
end
end
end
#==============================================================================
# ** Game_System
#------------------------------------------------------------------------------
# This class handles data surrounding the system. Background music, etc.
# is managed here as well. Refer to "$game_system" for the instance of
# this class.
#==============================================================================
class Game_System
#--------------------------------------------------------------------------
# * Alias Listings
#--------------------------------------------------------------------------
alias dvv_game_system_cache_audio_initialize initialize
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
# Perform the original call
dvv_game_system_cache_audio_initialize
# Set up the audio cache data file
initialize_audio_cache
end
#--------------------------------------------------------------------------
# * Play Background Sound
# bgs : background sound to be played
#--------------------------------------------------------------------------
def bgm_play(bgm)
@playing_bgm = bgm
if bgm != nil and bgm.name != ""
# If we have a cached file, use cached system
if is_cached?("~$" + bgm.name,"BGM/")
name = "~$" + bgm.name
audio_cache(name,"BGM/")
# Playback audio (not tied now to the Audio/BGM folder)
Audio.bgm_play(name, bgm.volume, bgm.pitch)
# Acquire cached extension
ext = get_cache_ext(name, "BGM/")
# Delete temp file generated by audio_cache
File.delete(name + ext)
# Otherwise, default playback system
else
Audio.bgm_play("Audio/BGM/" + bgm.name, bgm.volume, bgm.pitch)
end
else
Audio.bgm_stop
end
Graphics.frame_reset
end
#--------------------------------------------------------------------------
# * Play Background Sound
# bgs : background sound to be played
#--------------------------------------------------------------------------
def bgs_play(bgs)
@playing_bgs = bgs
if bgs != nil and bgs.name != ""
# If we have a cached file, use cached system
if is_cached?("~$" + bgs.name,"BGS/")
name = "~$" + bgs.name
audio_cache(name,"BGS/")
# Playback audio (not tied now to the Audio/BGS folder)
Audio.bgs_play(name, bgs.volume, bgs.pitch)
# Acquire cached extension
ext = get_cache_ext(name, "BGS/")
# Delete temp file generated by audio_cache
File.delete(name + ext)
# Otherwise, default playback system
else
Audio.bgs_play("Audio/BGS/" + bgs.name, bgs.volume, bgs.pitch)
end
else
Audio.bgs_stop
end
Graphics.frame_reset
end
#--------------------------------------------------------------------------
# * Play Music Effect
# me : music effect to be played
#--------------------------------------------------------------------------
def me_play(me)
if me != nil and me.name != ""
# If we have a cached file, use cached system
if is_cached?("~$" + me.name,"ME/")
name = "~$" + me.name
audio_cache(name,"ME/")
# Playback audio (not tied now to the Audio/ME folder)
Audio.me_play(name, me.volume, me.pitch)
# Acquire cached extension
ext = get_cache_ext(name, "ME/")
# Delete temp file generated by audio_cache
File.delete(name + ext)
# Otherwise, default playback system
else
Audio.me_play("Audio/ME/" + me.name, me.volume, me.pitch)
end
else
Audio.me_stop
end
Graphics.frame_reset
end
#--------------------------------------------------------------------------
# * Play Sound Effect
# se : sound effect to be played
#--------------------------------------------------------------------------
def se_play(se)
if se != nil and se.name != ""
# If we have a cached file, use cached system
if is_cached?("~$" + se.name,"SE/")
name = "~$" + se.name
audio_cache(name,"SE/")
# Playback audio (not tied now to the Audio/SE folder)
Audio.se_play(name, se.volume, se.pitch)
# Acquire cached extension
ext = get_cache_ext(name, "SE/")
# Delete temp file generated by audio_cache
File.delete(name + ext)
# Otherwise, default playback system
else
Audio.se_play("Audio/SE/" + se.name, se.volume, se.pitch)
end
end
end
#--------------------------------------------------------------------------
# * Cache Audio List Initialization
#--------------------------------------------------------------------------
def initialize_audio_cache
# Establish Paths
cache_path = "Data/AudioCache.rxdata"
# Generate / load cached audio data
@cache_audiolist = {}
# If a cached/encrypted game
if AudioCache::RGSAAD
# We load current data and exit, no saving done
@cache_audiolist = load_data(cache_path)
return
end
# Either load current or save new data file
if File.exists?(cache_path)
@cache_audiolist = load_data(cache_path)
else
save_data(@cache_audiolist, cache_path)
end
end
#--------------------------------------------------------------------------
# * Get audio list
#--------------------------------------------------------------------------
def cache_audiolist
@cache_audiolist
end
#--------------------------------------------------------------------------
# * Is file cached?
# file : audio file being tested
# path : the initial folder in the Data folder for testing
#--------------------------------------------------------------------------
def is_cached?(file, path)
# Establish Paths
data_path = "Data/" + path
# Determine true if it exists within the cached audio list
key = data_path + file
return true if @cache_audiolist.has_key?(key)
return false
end
#--------------------------------------------------------------------------
# * Cache Audio
# file : audio file to be cached
# path : the initial folder from the Audio folder, now the Data folder
#--------------------------------------------------------------------------
def cache_audio(file, path)
# Establish Paths
cache_path = "Data/AudioCache.rxdata"
audio_path = "Audio/" + path
data_path = "Data/" + path
# Create specified data folder unless it exists
Dir.mkdir(data_path) unless File.exists?(data_path)
# Acquire file extension
ext = get_file_ext(audio_path + file)
# Load File from specified audio folder
afile = File.open(audio_path + file + ext, "rb")
audio_data = afile.readlines
afile.close
#
file = "~$" + file
# Save File in specified data folder
save_data(audio_data, data_path + file + ".rxdata")
# Record audio extension in cached audio list
key = data_path + file
unless @cache_audiolist.has_key?(key)
@cache_audiolist[key] = ext
end
# Save cached audio data
save_data(@cache_audiolist, cache_path)
end
#--------------------------------------------------------------------------
# * Get Audio from Cache
# file : audio file that is cached
# path : the folder within the Data folder, mirroring the Audio folder
# dest : custom audio path in which to redirect
#--------------------------------------------------------------------------
def audio_cache(file, path, dest="")
# Establish Paths
data_path = "Data/" + path
# Acquire extension from cached audio list
ext = get_cache_ext(file, path)
# Load File from specified data folder
audio_data = load_data(data_path + file + ".rxdata")
# Perform file manipulation if possible
begin
# Save File into folder for playback
afile = File.open(dest+file + ext, "wb")
afile.print audio_data
afile.close
rescue
# Cannot open as yet
end
end
#--------------------------------------------------------------------------
# * Remove from Cache
# file : audio file that is returned to the Audio folder (if needed)
# path : the folder within the Data folder, mirroring the Audio folder
#--------------------------------------------------------------------------
def remove_cache(file, path)
# Establish Paths and renamed rxdata file
cache_path = "Data/AudioCache.rxdata"
audio_path = "Audio/" + path
data_path = "Data/" + path
rx_file = "~$" + file
# Acquire extension from cached audio list
ext = get_cache_ext(rx_file, path)
# Load rx audio file from the specified data folder
audio_data = load_data(data_path + rx_file + ".rxdata")
# Create the return pathway for the audio file (trims last character)
return_path = audio_path[ 0, (audio_path.length)-1 ]
# Create the audio folder and subfolders if necessary
Dir.mkdir("Audio") unless File.exists?("Audio")
Dir.mkdir(return_path) unless File.exists?(return_path)
# Perform file manipulation if possible
begin
# Save File into folder for playback
afile = File.open(audio_path + file + ext, "wb")
afile.print audio_data
afile.close
rescue
# Restoration/copying permission must be denied
p "File could not be restored within the " + return_path + " folder."
return
end
# Delete the rxdata file from specified data folder
File.delete(data_path + rx_file + ".rxdata")
# Acquire the key and erase from the cached audio list
key = data_path + rx_file
@cache_audiolist.delete(key) if @cache_audiolist.has_key?(key)
# Remove empty cached audio folders
remove_cache_pathway
# Eliminate AudioCache file and exit if empty
num_keys = @cache_audiolist.keys.size
return File.delete(cache_path) if num_keys == 0
# Save the updated cached audio list
save_data(@cache_audiolist, cache_path)
end
#--------------------------------------------------------------------------
# * Remove empty cached audio folders
#--------------------------------------------------------------------------
def remove_cache_pathway
begin
Dir.rmdir("Data/BGM")
rescue
end
begin
Dir.rmdir("Data/BGS")
rescue
end
begin
Dir.rmdir("Data/ME")
rescue
end
begin
Dir.rmdir("Data/SE")
rescue
end
end
#--------------------------------------------------------------------------
# * Get the extension of an Audio folder file
# filename : filename
#--------------------------------------------------------------------------
def get_file_ext(filename)
if FileTest.exist?(filename + ".wav")
return ".wav"
elsif FileTest.exist?(filename + ".mp3")
return ".mp3"
elsif FileTest.exist?(filename + ".ogg")
return ".ogg"
elsif FileTest.exist?(filename + ".mid")
return ".mid"
elsif FileTest.exist?(filename + ".wma")
return ".wma"
end
end
#--------------------------------------------------------------------------
# * Get the extension of an Data folder cached file
# file : audio file that is in the Data Folder
# path : the folder within the Data folder to test
#--------------------------------------------------------------------------
def get_cache_ext(file, path)
data_path = "Data/" + path
key = data_path + file
ext = @cache_audiolist[key]
return ext
end
end
Instructions
Pretty much plug-and-play in its functions, but it does require you to use script calls to actively 'cache' audio which self-stores within the Data folder. And when you are done, use the "RGSAAD" value to let the script know it is ready for an encrypted/compressed game.
Detailed instructions are inside the script itself.
But if you need an editor for the system, a simple and easy-to-use one is available below:
Kached Audio Editor
Code:
#==============================================================================
# ** Kichi's Kached Audio Editor
# An editor for 'Kichi's Kached Audio' by DerVVulfman
#------------------------------------------------------------------------------
# version 1.1
# by DerVVulfman
# 08-21-2023 (MM-DD-YYYY)
# RGSS / RPGMaker XP
# Requires: Kichi's Kached Audio to function
#
#==============================================================================
#
# INTRODUCTION:
#
# This is a very simple editor utilizing the arrow keys to select your chosen
# audio file which cna be cached or uncached by hitting the Enter/Select key.
# When a file is cached, it is turned into an .rxdata file and sent into the
# appropriate subfolder within your game's data folder. And when an audio
# file has been un-cached, it is removed from the data folder. All changes to
# the files are updated within the 'Cache Audio' system's 'AudioCache' data
# file. And no files are ever deleted from the project's root audio folder.
# However, un-caching a file will restore it to its spefified Audio folder,
# and may overwrite an existing audio file of the same name.
#
#------------------------------------------------------------------------------
#
# INSTALLATION:
#
# Place this script either above or below 'Cached Audio' to function. To acti-
# vate, toggle the KACHED_AUDIO_EDITOR value to true. A false setting disables
# this script.
#
# The BUFFER_SIZE value is to ensure that projects with large quantities of
# does not bog down the file loading system which could result in 'script is
# hanging' errors to occur.
#
#
#==============================================================================
# Just set this to 'true' and it's turned on, or to 'false' to disable it.
# The rest of the instructions are in the menu.
#
KACHED_AUDIO_EDITOR = false
# This sets how many songs/files are read before a necessary Graphics frame
# update. This to prevent 'script hanging' issues. Larger values slows
# down the system, but with better running security on editor load.
#
BUFFER_SIZE = 100
#==============================================================================
# *** The actual editor, once made fully active
#==============================================================================
if KACHED_AUDIO_EDITOR == true
#============================================================================
# ** Game_AudioCacheEditor
#----------------------------------------------------------------------------
# It is the MP3 player.
#============================================================================
class Game_AudioCacheEditor
#------------------------------------------------------------------------
# * Object Initialization
#------------------------------------------------------------------------
def initialize
# Initialization of data
@page = 1 # Setting page to BGMs at start
@list_bgm = [] # List of BGM audio
@list_bgs = [] # List of BGS audio
@list_me = [] # List of ME audio
@list_se = [] # List of SE audio
# Generate Data Lists for each audio type
@list_bgm = list_process("BGM/")
@list_bgs = list_process("BGS/")
@list_me = list_process("ME/")
@list_se = list_process("SE/")
# Create array for List Window
@list_window = []
# Generate List Windows
@list_window[1] = Window_ACList.new(@list_bgm)
@list_window[2] = Window_ACList.new(@list_bgs)
@list_window[3] = Window_ACList.new(@list_me)
@list_window[4] = Window_ACList.new(@list_se)
# Define windows active/inactive
for i in 2..4
@list_window[i].visible = false
@list_window[i].active = false
end
@list_window[1].visible = true
@list_window[1].active = true
## Compilation of data window
@data_window = Window_ACData.new
@help_window = Window_ACHelp.new
end
#------------------------------------------------------------------------
# * Process List
#------------------------------------------------------------------------
def list_process(type)
# Initialize values based on folder type
audio_sort = "Audio/" + type + "*" # Used to acquire folder filenames
audio_pattern = /Audio\/#{type}(.*?)/ # Formerly /Audio\/BGM\/(.*?)/
data_type = "Data/" + type # To acquire Data subfolder
d_size = data_type.size # To slice point in name
# Create arrays for data acquisition
inituncached = []
initcached = []
temp = []
result = []
# Reset the buffer
buffer = 0
# Generate uncached data list
for name in Dir[audio_sort]
# Handle buffer
buffer += 1
if buffer > BUFFER_SIZE
buffer = 0
Graphics.update
end
# Acquire name from Directory
tempname = name.sub(audio_pattern) { $1 }
next unless init_extensions?(tempname)
inituncached.push(tempname)
end
# Generate cached data
for key in $game_system.cache_audiolist
# Handle buffer
buffer += 1
if buffer > BUFFER_SIZE
buffer = 0
Graphics.update
end
tempname = key[0]
next unless tempname[0,d_size] == data_type
tempname = key[0]
tempname = tempname[d_size,(tempname.size)-d_size]
tempname = tempname + key[1]
audio_filename = tempname.delete "~$"
initcached.push(audio_filename)
end
# Eliminate cached files from uncached list
for name in inituncached
temp.push(name) unless initcached.include?(name)
end
# Push names as arrays with binary tags (0 = uncached, 1 = cached)
for name in initcached
result.push( [name,1] )
end
for name in temp
result.push( [name,0] )
end
# Sort list and return
result.sort!
return result
end
#------------------------------------------------------------------------
# * Test for file extension
#------------------------------------------------------------------------
def init_extensions?(name)
effective = false
effective = true if name[(name.size)-4,4] == ".mid"
effective = true if name[(name.size)-4,4] == ".mp3"
effective = true if name[(name.size)-4,4] == ".ogg"
effective = true if name[(name.size)-4,4] == ".wav"
effective = true if name[(name.size)-4,4] == ".wma"
return effective
end
#------------------------------------------------------------------------
# * Frame Update
#------------------------------------------------------------------------
def update
@oldpage = @page if @oldpage.nil?
# Update windows
@list_window[@page].update
# If in active list
update_list if @list_window[@page].active
# Acquire list index
@idx = @list_window[@page].index
# Update Data window when scrolling
if @name != @list_window[@page].item(@idx)[0]
@name = @list_window[@page].item(@idx)[0]
@state = @list_window[@page].item(@idx)[1]
@data_window.refresh(@page, @name, @state)
end
end
#------------------------------------------------------------------------
# * Frame Update : when list window is active
#------------------------------------------------------------------------
def update_list
# Handle page change
update_list_paging
return if update_list_decision?
end
#------------------------------------------------------------------------
# * Frame Update : when list window is active - changing pages
#------------------------------------------------------------------------
def update_list_paging
if Input.repeat?(Input::LEFT)
@page -= 1
@page = 4 if @page == 0
end
if Input.repeat?(Input::RIGHT)
@page += 1
@page = 1 if @page == 5
end
if @oldpage != @page
@list_window[@oldpage].visible = false
@list_window[@oldpage].active = false
@list_window[@page].visible = true
@list_window[@page].active = true
@oldpage = @page
@data_window.refresh(@page, @name, @state)
end
end
#------------------------------------------------------------------------
# * Frame Update : when list window is active - hitting Enter/Select
#------------------------------------------------------------------------
def update_list_decision?
# Exit unless hitting Enter/Select
return false unless Input.trigger?(Input::C)
# Play Decision SE
$game_system.se_play($data_system.decision_se)
# Choose Path for Cache System
case @page
when 1 ; path = "BGM/"
when 2 ; path = "BGS/"
when 3 ; path = "ME/"
when 4 ; path = "SE/"
end
# If State is already cached
if @state == 1
# Get filename without extension, uncache, and change state
file = @name[0,(@name.size)-4]
$game_system.remove_cache(file, path)
@state = 0
# Otherwise, state is not cached
else
# Get filename without extension, cache, and change state
file = @name[0,(@name.size)-4]
$game_system.cache_audio(file, path)
@state = 1
end
# Change State in the current list and update data window
@list_window[@page].item(@idx)[1] = @state
@data_window.refresh(@page, @name, @state)
return true
end
end
#============================================================================
# ** Window_ACList
#----------------------------------------------------------------------------
# It is the window which lists all of the audio files within your project's
# Audio folder or Data cached folder.
#============================================================================
class Window_ACList < Window_Selectable
#------------------------------------------------------------------------
# * Object Initialization
#------------------------------------------------------------------------
def initialize(list)
super(64, 64, 256, 352)
@list = list
@item_max = @list.size
@index = 0
temp_size = @list.size
temp_size = 1 if temp_size == 0
self.contents = Bitmap.new(width - 32, temp_size * 32)
self.opacity = 192
for i in 0...@list.size
text = @list[i]
text = "" if text.nil?
self.contents.draw_text(0, i * 32, 256, 32, @list[i][0])
end
end
#------------------------------------------------------------------------
# * Get Item
#------------------------------------------------------------------------
def item(index)
value = @list[index]
value = ["",0] if value.nil?
return value
end
end
#============================================================================
# ** Window_ACData
#----------------------------------------------------------------------------
# It is the window which depicts the cached state of a highlighted audio
# file, and the folder in which it belongs
#============================================================================
class Window_ACData < Window_Selectable
#------------------------------------------------------------------------
# * Object Initialization
#------------------------------------------------------------------------
def initialize
super(320, 64, 256, 128)
self.contents = Bitmap.new(width - 32, height - 32)
self.opacity = 192
end
#------------------------------------------------------------------------
# * Refresh
#------------------------------------------------------------------------
def refresh(page, audio, state)
if audio == ""
audio = "> No file present <"
state = 2
else
audio = audio[0,(audio.size)-4]
end
# Initialization of contents
self.contents.fill_rect(0, 0, 224, 168, Color.new(0, 0, 0, 0))
# Drawing of Page
self.contents.font.color = Color.new(255, 255, 255)
self.contents.font.color = Color.new(192, 192, 192) if state == 2
case page
when 1; self.contents.draw_text(0, 0, 224, 24, "[BGM]")
when 2; self.contents.draw_text(0, 0, 224, 24, "[BGS]")
when 3; self.contents.draw_text(0, 0, 224, 24, "[ME]")
when 4; self.contents.draw_text(0, 0, 224, 24, "[SE]")
end
# Drawing of audio name
self.contents.font.color = Color.new(192, 255, 255)
self.contents.font.color = Color.new(192, 192, 192) if state == 2
self.contents.draw_text(0, 32, 224, 24, audio)
# Exit if no valid filename
return if state == 2
# Drawing of audio cached state
if state == 0
self.contents.font.color = Color.new(255, 255, 255)
self.contents.draw_text(0, 64, 224, 24, "Uncached")
else
self.contents.font.color = Color.new(255, 255, 64)
self.contents.draw_text(0, 64, 224, 24, "Cached")
end
end
end
#============================================================================
# ** Window_ACHelp
#----------------------------------------------------------------------------
# It is the window which depicts basic instructions for the editor.
#============================================================================
class Window_ACHelp < Window_Base
#------------------------------------------------------------------------
# * Object Initialization
#------------------------------------------------------------------------
def initialize
super(320, 192, 256, 224)
self.contents = Bitmap.new(width - 32, height - 32)
self.opacity = 192
refresh
end
#------------------------------------------------------------------------
# * Refresh
#------------------------------------------------------------------------
def refresh
self.contents.font.size = 20
self.contents.font.bold = true
self.contents.font.color = Color.new(255, 255, 255)
self.contents.draw_text(0, 0, 224, 24, "The [Up] & [Down] arrows")
self.contents.draw_text(0, 22, 224, 24, "highlights the audio file.")
self.contents.font.color = Color.new(224, 224, 224)
self.contents.draw_text(0, 55, 224, 24, "The [Left] & [Right] arrows")
self.contents.draw_text(0, 77, 224, 24, "changes what type of audio")
self.contents.draw_text(0, 99, 224, 24, "you are viewing.")
self.contents.font.color = Color.new(192,192,192)
self.contents.draw_text(0, 132, 224, 24, "Pressing [Enter] will change")
self.contents.draw_text(0, 154, 224, 24, "the cached state of the file.")
end
end
#============================================================================
# ** Scene_Title
#----------------------------------------------------------------------------
# This class performs title screen processing.
#============================================================================
class Scene_Title
#-------------------------------------------------------------------------
# * Main Processing
#------------------------------------------------------------------------
def main
# Bring up required game system data
$data_system = load_data("Data/System.rxdata")
$game_system = Game_System.new
# Drawing up title graphics
@sprite = Sprite.new
@sprite.bitmap = RPG::Cache.title($data_system.title_name)
@gac = Game_AudioCacheEditor.new
# Execute transition
Graphics.transition
# Main loop
loop do
# Update game screen
Graphics.update
# Update input information
Input.update
# Frame update
update
# Abort loop if screen is changed
break if $scene != self
end
end
#------------------------------------------------------------------------
# * Frame Update
#------------------------------------------------------------------------
def update
@gac.update
end
end
This script will obviously conflict with any other script that will modify the bgm_play, bgs_play, me_play and/or se_play methods within Game System, and will conflict with any script that alters the animation_process_timing method within the RPG::Sprite class that handles battle system effects.
Other than that, it is compatible for RPGMaker XP systems.
Terms of Use
Free to use, even in commercial projects. Just note that I need some form of due credit, not just myself but Carlos_Davilla who assisted.
The Windows OS is a fun little system. It can prevent a user from copying or deleting a file whilst the file is in use. So I added some lines to prevent the possibility of one's game crashing.
Meanwhile, I now have a fun and adorable little logo thanks to a good friend.
A new version exists and a problem averted thanks to Carlos_Davilla. It was not realized until recently that some cloud services would have issues with the temporarily extracted audio files that Kichi would use. Such issues would result in CTD (or Crash to Desktop) errors. Said extracted music will now be automatically renamed to the same standard as other temporary files, such as those from Microsoft Word, and thus be ignored by cloud storage systems.
Oh, as a bonus... I just added two demos to the page. I always had the main script and the editor script in the main page, but the two demos are ... fun.
Both demos are of the same setup... single map, single fight with two ghosts... everything looking generic.. But the audio is completely different.
The first demo is open in that you can open the project and edit it. However, you will find that there is no Audio folder in the demo, despite that all the audio within the demo is custom. If you look within the Data folder, you will see BGM, BGS, ME and SE subfolders. And within these are rxdata files that are the music files converted and able to be cached.
The second demo cannot be opened as it is already converted and compressed. The contents are within the .rgsaad file, data and all. There is no outside Audio folder that needs to be shipped or packed away because all of the audio is packed within the .rgsaad file, and only extracts a copy of the necessary audio when needed.