=begin
==============================================================================
External Achievements v1.01 by AdiktuzMiko
maintained and commisioned by: boldpaste2
--- Date Created: 10/17/2014
--- Last Date Updated: 10/17/2014
--- Level: Easy
--- Do not use this script if you did not obtain it from the official forum.
Each game needs to have their own unique code so they don't overwrite other
projects achievement data or prevent other projects from running.
==============================================================================
Overview
==============================================================================
This script adds the ability to place achievements into games and stores the
data outside of saves so in the event if the save or game is deleted, the
achievement data will be stored.
Changelog ---------
7/3/2015 - Rewrote Configuration description and preconfigured settings.
==============================================================================
Features
==============================================================================
--- Creates a new option in the option menu to view achievement data
--- Allows banners to display when an achievement is earned
--- Stores achievements externally so other api's may access the achievement data
--- Customizable achievement window
--- Luna Engine Friendly
==============================================================================
Set-Up
==============================================================================
Just put this script into a blank slot above main but below materials
(see compatibility section) and modify the settings below
By default a command is added to the main menu using the symbol :achievements
using the handler method command_achievements To call it from somewhere else
SceneManager.call(Scene_Achievements) <--- Script call that opens the
achievements window
To unlock a new achievement: ADIK::ACHIEVEMENTS.add_achievement(id) <--- Script
call to show that an achievement has been earned where id => index of the
achievement that you want to unlock
==============================================================================
Compatibility
==============================================================================
This script aliases Scene_Title's start method, Might alias DataManager's
save_without_rescue and load_game, Scene_Menu's add_main_commands and
create_command_window, Scene_Base's terminate
==============================================================================
Terms of Use
==============================================================================
This script is free to use in both non-commercial and commercial games so long
as the following terms are met.-You may not post this script elsewhere or pass
it on to anybody. If you have received this script from a source outside of
the main post, do not use it! Each release is specifically configured per game!
Using identical configs will cause other peoples achievements from running or
prevents them from running all together. If you would like to receive a copy,
please send a PM to
http://forums.rpgmakerweb.com/index.php?/user/23718-boldpaste2/
-you may not use this script if obtained from an external source.
-You CAN modify the script so long as you do not redistribute the modifications.
-Give credit to AdiktuzMiko for the creation of the script.
==============================================================================
=end
module ADIK
module ACHIEVEMENTS
#==============================================================================
#Banner Configuration
#==============================================================================
#Background image for the achievement window. The image should be a .png stored in Graphics\System
ACHIEVEMENT_BACKGROUND = ""
#Position of the banner. You know, the title thing in the achievement window.
ACHIEVEMENT_BANNER_X = 0
ACHIEVEMENT_BANNER_Y = 0
ACHIEVEMENT_BANNER_WIDTH = Graphics.width
#A padding option to allow you to budge your achievement list down or up (just in case)
ACHIEVEMENT_BANNER_HEIGHT = 64
#If you want to give the banner a window skin, leave it as "" to not use a window skin.
#You can also change the font, font color, size, and actual title.
ACHIEVEMENT_BANNER_WINDOWSKIN = ""
ACHIEVEMENT_BANNER_FONT_NAME = Font.default_name
ACHIEVEMENT_BANNER_FONT_COLOR = Color.new(255,0,255)
ACHIEVEMENT_BANNER_FONT_SIZE = 32
ACHIEVEMENT_BANNER_TEXT = "ACHIEVEMENTS"
#Fill color for Achievement Banner
ACHIEVEMENT_BANNER_FILL_COLOR = Color.new(100,100,100,255)
#Width and height of fill for Achievement Banner
ACHIEVEMENT_BANNER_FILL_WIDTH = Graphics.width
ACHIEVEMENT_BANNER_FILL_HEIGHT = ACHIEVEMENT_BANNER_HEIGHT
#==============================================================================
#Achievement Window Configuration
#==============================================================================
#Size of the achievement menu itself. This is practaclly done for you.
ACHIEVEMENT_WINDOW_X = 0
ACHIEVEMENT_WINDOW_Y = ACHIEVEMENT_BANNER_HEIGHT + 12
ACHIEVEMENT_WINDOW_WIDTH = Graphics.width
ACHIEVEMENT_WINDOW_HEIGHT = Graphics.height - ACHIEVEMENT_WINDOW_Y
#Configuration of achievement grid. You made need math on your side for this.
#example, if using 4 columns with no spacing, and using a screen size of 640
#your achievement icons must not be bigger then 160 width.
ACHIEVEMENT_COLUMNS = 4
ACHIEVEMENT_ROWS_VISIBLE = 5
ACHIEVEMENT_SPACING_X = 4
ACHIEVEMENT_SPACING_Y = 4
#Width and height for each achievement
ACHIEVEMENT_WIDTH = (ACHIEVEMENT_WINDOW_WIDTH / 4) - ACHIEVEMENT_SPACING_X
ACHIEVEMENT_HEIGHT = (ACHIEVEMENT_WINDOW_HEIGHT / 5) - 4*ACHIEVEMENT_SPACING_Y
#==============================================================================
#Achievement Notification Configuration
#==============================================================================
#The position on the screen where the icon "pops up" when the script call is activated.
NEW_ACHIEVEMENT_X = 200
NEW_ACHIEVEMENT_Y = 380
#Width of the pop-up (generally width of image)
NEW_ACHIEVEMENT_WIDTH = 128
NEW_ACHIEVEMENT_HEIGHT = Graphics.height - NEW_ACHIEVEMENT_Y
#How fast the pop-up fades in and out and how long it stays on screen.
NEW_ACHIEVEMENT_FADE_IN = 60
NEW_ACHIEVEMENT_FADE_OUT = 60
NEW_ACHIEVEMENT_WAIT = 60
#When changing scenes, does the pop-up go away if the above settings have not been completed.
NEW_ACHIEVEMENT_PERSIST = true
#==============================================================================
#Achievement Configuration
#------------------------------------------------------------------------------
#The heart of the script. this is where you store your achievements for your project.
#The images used are stored in Graphics\Pictures as .png files.
## Format is: LIST[index] = image_file_name
# Where index is achievement ID
## Example LIST[1] = "Achievment_1"
#==============================================================================
LIST = [] #Do not delete this.
LIST[1] = "Achievment_1"
LIST[2] = "Achievment_2"
#Use a different image when the achievement has not been earned?
#WARNING! if false, it will greyscale the image which causes a huge performance drop
DIF_IMAGE = true
#List of disabled icon images if DIF-IMAGE is TRUE
LIST_DIS = []
LIST_DIS[1] = "Achievment_1D"
LIST_DIS[2] = "Achievment_2D"
#Add a command to open achievements scene from the main menu
ADD_TO_MAIN_MENU = true
COMMAND_NAME = "Achievements"
#==============================================================================
#DATA
#------------------------------------------------------------------------------
###~ Here is a list of parameters you can set the DATA_PATH into
##~ AppData = Contains the full path to the Application Data directory of the logged-in user
#~ LOCALAPPDATA = This variable is the temporary files of Applications.
#~ CURRENT = Folder where the game is run from
##~ !!!The following might require your game to run in admin mode!!!
##~ ProgramFiles = This variable points to Program Files directory
#~ CommonProgramFiles = This variable points to Common Files directory
#==============================================================================
#Autosave the achievements file when a new achievement
#is achieved
AUTOSAVE = true
# Primary folder where the achievements rgss file will be placed
# based on the default paths in your computer
# set to nil if you don't want to use this
DATA_PATH = 'AppData'
#Enter each subfolder paths after the primary folder here
#The script automatically creates the folder path specified
#FOLDER = [FOLDER1,FOLDER2,and so on]
FOLDER = ["MyRMGames","GAME NAME"]
#Filename for the achievements file
#USE A NAME NOBODY WILL COME UP WITH!
NAME = "Defualt.rgss3"
# Primary folder where the achievements text file will be placed
# based on the default paths in your computer
# set to nil if you don't want to use this
TEXT_PATH = 'AppData'
#Enter each sub folder paths after the primary folder here
#The script automatically creates the folder path specified
#FOLDER = [FOLDER1,FOLDER2,and so on]
TEXT_FOLDER = ["MyRMGames","GAME NAME"]
#Filename for the achievements text file
#USE A NAME NOBODY WILL COME UP WITH!
TEXT_NAME = "Defualt.ini"
#==================================================================
#DO NOT EDIT BEYOND THIS POINT
#==================================================================
#==================================================================
#I SAID DO NOT EDIT BEYOND THIS POINT
#==================================================================
def self.check_achievements
@path = ""
if not DATA_PATH == 'CURRENT'
@path = ENV[DATA_PATH] + "\\"
end
FOLDER.each do |path|
@path += path + "\\"
Dir.mkdir(@path) if !FileTest.exist?(@path)
end
@path += NAME
@text_path = ""
if not TEXT_PATH == 'CURRENT'
@text_path = ENV[TEXT_PATH] + "\\"
end
TEXT_FOLDER.each do |path|
@text_path += path + "\\"
Dir.mkdir(@text_path) if !FileTest.exist?(@text_path)
end
@text_path += TEXT_NAME
begin load_achievements rescue
$achievements = []
save_achievements
end
end
def self.has_achievement(id)
return $achievements.include?(id)
end
def self.save_achievements
File.open(@path, "wb") do |file|
Marshal.dump($achievements, file)
end
File.open(@text_path,"w+") do |file|
ADIK::ACHIEVEMENTS::LIST.each_index do |index|
if has_achievement(index)
file.write("Achievement"+index.to_s+"=1"+"\n")
else
file.write("Achievement"+index.to_s+"=0"+"\n")
end
end
end
end
def self.load_achievements
File.open(@path, "rb") do |file|
$achievements = Marshal.load(file)
end
File.open(@text_path,"w+") do |file|
ADIK::ACHIEVEMENTS::LIST.each_index do |index|
if has_achievement(index)
file.write("Achievement"+index.to_s+"=1"+"\n")
else
file.write("Achievement"+index.to_s+"=0"+"\n")
end
end
end
end
check_achievements
def self.add_achievement(id)
return if $achievements.include?(id)
$achievements.push(id)
SceneManager.scene.show_new_achievement(id)
save_achievements if AUTOSAVE
end
end
end
class Window_Achievements < Window_Base
def initialize(x, y, width, height)
super
self.windowskin = Cache.system("")
@row = 1
@row_max = 1 + ((ADIK::ACHIEVEMENTS::LIST.size)/ADIK::ACHIEVEMENTS::ACHIEVEMENT_COLUMNS).truncate
create_achievements
end
def add_row(value)
@row = [@row+value,@row_max].min
refresh_achivements
end
def red_row(value)
@row = [@row-value,1].max
refresh_achivements
end
def create_achievements
@gallery = []
refresh_achivements
end
def refresh_achivements
@gallery.each do |spr|
spr.dispose unless spr.nil?
end
@gallery = []
columns = ADIK::ACHIEVEMENTS::ACHIEVEMENT_COLUMNS
column = 1
row = 1
dx = ADIK::ACHIEVEMENTS::ACHIEVEMENT_SPACING_X
dy = ADIK::ACHIEVEMENTS::ACHIEVEMENT_SPACING_Y
w = ADIK::ACHIEVEMENTS::ACHIEVEMENT_WIDTH
h = ADIK::ACHIEVEMENTS::ACHIEVEMENT_HEIGHT
min = (@row-1)*columns + 1
max = (@row+ADIK::ACHIEVEMENTS::ACHIEVEMENT_ROWS_VISIBLE-1)*columns
(min..max).each do |index|
return if ADIK::ACHIEVEMENTS::LIST[index].nil?
@gallery[index] = Sprite.new
@gallery[index].bitmap = Bitmap.new(ADIK::ACHIEVEMENTS::ACHIEVEMENT_WINDOW_WIDTH,ADIK::ACHIEVEMENTS::ACHIEVEMENT_WINDOW_HEIGHT)
rect = Rect.new(x+(dx+w)*(column-1),y+(dy+h)*(row-1),w,h)
if ADIK::ACHIEVEMENTS::DIF_IMAGE
if ADIK::ACHIEVEMENTS.has_achievement(index)
bit = Cache.picture(ADIK::ACHIEVEMENTS::LIST[index])
else
bit = Cache.picture(ADIK::ACHIEVEMENTS::LIST_DIS[index])
end
@gallery[index].bitmap.stretch_blt(rect,bit,Rect.new(0,0,bit.width,bit.height))
else
bit = Cache.picture(ADIK::ACHIEVEMENTS::LIST[index])
@gallery[index].bitmap.stretch_blt(rect,bit,Rect.new(0,0,bit.width,bit.height))
@gallery[index].tone.set(0,0,0,255) unless ADIK::ACHIEVEMENTS.has_achievement(index)
end
column += 1
if column > 4
column = 1
row += 1
return if row > ADIK::ACHIEVEMENTS::ACHIEVEMENT_ROWS_VISIBLE
end
end
end
def dispose
@gallery.each do |spr|
spr.dispose unless spr.nil?
end
super
end
end
class Window_AchievementBanner < Window_Base
def initialize(x, y, width, height)
super
self.windowskin = Cache.system(ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_WINDOWSKIN)
contents.font.name = ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_FONT_NAME
contents.font.color = ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_FONT_COLOR
contents.font.size = ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_FONT_SIZE
contents.draw_text(0,0,width,height/2,ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_TEXT,1)
end
end
class Scene_Achievements < Scene_Base
def start
super
create_background
create_banner_window
create_achievement_window
end
def update
super
if Input.trigger?(:B)
SceneManager.return
elsif Input.trigger?(:DOWN)
@achievement_window.add_row(1)
elsif Input.trigger?(:UP)
@achievement_window.red_row(1)
end
end
def create_background
@background = Sprite.new
@background.bitmap = Bitmap.new(Graphics.width,Graphics.height)
x = ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_X
y = ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_Y
w = ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_WIDTH
h = ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_HEIGHT
bit = Cache.system(ADIK::ACHIEVEMENTS::ACHIEVEMENT_BACKGROUND)
@background.bitmap.blt(0,0,bit,Rect.new(0,0,bit.width,bit.height))
color = ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_FILL_COLOR
@background.bitmap.fill_rect(x,y,w,h,color)
end
def create_achievement_window
@achievement_window = Window_Achievements.new(ADIK::ACHIEVEMENTS::ACHIEVEMENT_WINDOW_X,ADIK::ACHIEVEMENTS::ACHIEVEMENT_WINDOW_Y,ADIK::ACHIEVEMENTS::ACHIEVEMENT_WINDOW_WIDTH,ADIK::ACHIEVEMENTS::ACHIEVEMENT_WINDOW_HEIGHT)
end
def create_banner_window
@banner_window = Window_AchievementBanner.new(ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_X,ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_Y,ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_WIDTH,ADIK::ACHIEVEMENTS::ACHIEVEMENT_BANNER_HEIGHT)
end
def terminate
@achievement_window.dispose
@background.dispose
@banner_window.dispose
super
end
end
#For the new achievement pop-up
#If persist is true
if ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_PERSIST
class Scene_Base
@@new_achievement = nil
alias update_achievements update
def update
update_achievements
return if @@new_achievement.nil?
@@new_achievement.z = 99999
if @@na_fadein_time > 0
@@na_fadein_time -= 1
@@new_achievement.opacity += @@ops_in
elsif @@na_wait_time > 0
@@na_wait_time -= 1
elsif @@na_fadeout_time > 0
@@na_fadeout_time -= 1
@@new_achievement.opacity -= @@ops_out
else
@@new_achievement.dispose
@@new_achievement = nil
end
end
def show_new_achievement(id)
@@new_achievement = Sprite.new
@@new_achievement.z = 99999
@@new_achievement.bitmap = Bitmap.new(Graphics.width,Graphics.height)
@@na_fadein_time = ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_FADE_IN
@@na_fadeout_time = ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_FADE_OUT
@@na_wait_time = ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_WAIT
@@ops_in = 255/(@@na_fadein_time)
@@ops_out = 255/(@@na_fadeout_time)
bit = Cache.picture(ADIK::ACHIEVEMENTS::LIST[id])
rect = Rect.new(ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_X,ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_Y,ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_WIDTH,ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_HEIGHT)
@@new_achievement.opacity = 0
@@new_achievement.bitmap.stretch_blt(rect,bit,Rect.new(0,0,bit.width,bit.height))
end
end
else
#If don't persist
class Scene_Base
@new_achievement = nil
alias update_achievements update
def update
update_achievements
return if @new_achievement.nil?
@new_achievement.z = 99999
if @na_fadein_time > 0
@na_fadein_time -= 1
@new_achievement.opacity += @ops_in
elsif @na_wait_time > 0
@na_wait_time -= 1
elsif @na_fadeout_time > 0
@na_fadeout_time -= 1
@new_achievement.opacity -= @ops_out
else
@new_achievement.dispose
@new_achievement = nil
end
end
def show_new_achievement(id)
@new_achievement = Sprite.new
@new_achievement.z = 99999
@new_achievement.bitmap = Bitmap.new(Graphics.width,Graphics.height)
@na_fadein_time = ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_FADE_IN
@na_fadeout_time = ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_FADE_OUT
@na_wait_time = ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_WAIT
@ops_in = 255/(@na_fadein_time)
@ops_out = 255/(@na_fadeout_time)
bit = Cache.picture(ADIK::ACHIEVEMENTS::LIST[id])
rect = Rect.new(ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_X,ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_Y,ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_WIDTH,ADIK::ACHIEVEMENTS::NEW_ACHIEVEMENT_HEIGHT)
@new_achievement.opacity = 0
@new_achievement.bitmap.stretch_blt(rect,bit,Rect.new(0,0,bit.width,bit.height))
end
alias terminate_achievements terminate
def terminate
@new_achievement.dispose unless @new_achievement.nil?
@new_achievement = nil
terminate_achievements
end
end
end
#Saves/Loads achievements upon saving and loading
#Only if autosave is false, since there's no point in doing this
#if it's on autosave
if not ADIK::ACHIEVEMENTS::AUTOSAVE
module DataManager
class <<self;
alias load_game_achievements load_game;
end
def self.load_game(index)
load_game_achievements(index)
ADIK::ACHIEVEMENTS.load_achievements
end
class <<self;
alias save_game_without_rescue_achievements save_game_without_rescue;
end
def self.save_game_without_rescue(index) save_game_without_rescue_achievements(index)
ADIK::ACHIEVEMENTS.save_achievements
return true
end
end
end
#So that the menu is only edited if ADD_TO_MAIN_MENU is true
if ADIK::ACHIEVEMENTS::ADD_TO_MAIN_MENU
class Window_MenuCommand
alias add_main_commands_add_achievement add_main_commands
def add_main_commands
add_main_commands_add_achievement
add_command(ADIK::ACHIEVEMENTS::COMMAND_NAME, :achievements, true)
end
end
class Scene_Menu
alias create_command_window_achievements create_command_window
def create_command_window
create_command_window_achievements
@command_window.set_handler(:achievements, method(:command_achievements))
end
def command_achievements
SceneManager.call(Scene_Achievements)
end
end
end