Version 1.5
Information
This script keeps a collection of photos for your party. These photos hold both images, and information
about any Events that were caught in the photo.
You can use tags to set whether an Event's details are recorded or not, and also set Event-specific functions to run AFTER a photo is saved.
Images
Instructions
Place the Photo script in the Materials section, above Main.
Place the ZLib script above that.
Make sure you have a folder in your game's 'Graphics' folder called 'Photos'.
The comments at the start of the script will tell you how to use the system.
Notes
This is the final version of the script, and includes windows for saving and choosing a photo, and finally a Scene too.
Credits
The ZLib script was not written by me, and I don't know the author, sorry.
Scripts
ZLib Script
CODE
#=============================================================================
# ** ZLIB
#=============================================================================
module Zlib
class Png_File < GzipWriter
def make_png(bitmap, mode = 0)
@bitmap, @mode = bitmap, mode
self.write(make_header)
self.write(make_ihdr)
self.write(make_idat)
self.write(make_iend)
end
def make_header
return [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a].pack('C*')
end
def make_ihdr
ih_size = [13].pack('N')
ih_sign = 'IHDR'
ih_width = [@bitmap.width].pack('N')
ih_height = [@bitmap.height].pack('N')
ih_bit_depth = [8].pack('C')
ih_color_type = [6].pack('C')
ih_compression_method = [0].pack('C')
ih_filter_method = [0].pack('C')
ih_interlace_method = [0].pack('C')
string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
ih_compression_method + ih_filter_method + ih_interlace_method
ih_crc = [Zlib.crc32(string)].pack('N')
return ih_size + string + ih_crc
end
def make_idat
header = "\x49\x44\x41\x54"
data = @mode == 0 ? make_bitmap_data0 : make_bitmap_data1
data = Zlib::Deflate.deflate(data, 8)
crc = [Zlib.crc32(header + data)].pack('N')
size = [data.length].pack('N')
return size + header + data + crc
end
def make_bitmap_data0
gz = Zlib::GzipWriter.open('png2.tmp')
t_Fx = 0
w = @bitmap.width
h = @bitmap.height
data = []
for y in 0...h
data.push(0)
for x in 0...w
t_Fx += 1
if t_Fx % 10000 == 0
Graphics.update
end
if t_Fx % 100000 == 0
s = data.pack('C*')
gz.write(s)
data.clear
end
color = @bitmap.get_pixel(x, y)
red = color.red
green = color.green
blue = color.blue
alpha = color.alpha
data.push(red)
data.push(green)
data.push(blue)
data.push(alpha)
end
end
s = data.pack('C*')
gz.write(s)
gz.close
data.clear
gz = Zlib::GzipReader.open('png2.tmp')
data = gz.read
gz.close
File.delete('png2.tmp')
return data
end
def make_bitmap_data1
w = @bitmap.width
h = @bitmap.height
data = []
for y in 0...h
data.push(0)
for x in 0...w
color = @bitmap.get_pixel(x, y)
red = color.red
green = color.green
blue = color.blue
alpha = color.alpha
data.push(red)
data.push(green)
data.push(blue)
data.push(alpha)
end
end
return data.pack('C*')
end
def make_iend
ie_size = [0].pack('N')
ie_sign = 'IEND'
ie_crc = [Zlib.crc32(ie_sign)].pack('N')
return ie_size + ie_sign + ie_crc
end
end
end
#=============================================================================
# ** Bitmap
#=============================================================================
class Bitmap
def make_png(name = 'like', path = '', mode = 0)
Zlib::Png_File.open('png.tmp') { |gz| gz.make_png(self, mode) }
Zlib::GzipReader.open('png.tmp') { |gz| $read = gz.read }
f = File.open(path + name + '.png', 'wb')
f.write($read)
f.close
File.delete('png.tmp')
end
end
# ** ZLIB
#=============================================================================
module Zlib
class Png_File < GzipWriter
def make_png(bitmap, mode = 0)
@bitmap, @mode = bitmap, mode
self.write(make_header)
self.write(make_ihdr)
self.write(make_idat)
self.write(make_iend)
end
def make_header
return [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a].pack('C*')
end
def make_ihdr
ih_size = [13].pack('N')
ih_sign = 'IHDR'
ih_width = [@bitmap.width].pack('N')
ih_height = [@bitmap.height].pack('N')
ih_bit_depth = [8].pack('C')
ih_color_type = [6].pack('C')
ih_compression_method = [0].pack('C')
ih_filter_method = [0].pack('C')
ih_interlace_method = [0].pack('C')
string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
ih_compression_method + ih_filter_method + ih_interlace_method
ih_crc = [Zlib.crc32(string)].pack('N')
return ih_size + string + ih_crc
end
def make_idat
header = "\x49\x44\x41\x54"
data = @mode == 0 ? make_bitmap_data0 : make_bitmap_data1
data = Zlib::Deflate.deflate(data, 8)
crc = [Zlib.crc32(header + data)].pack('N')
size = [data.length].pack('N')
return size + header + data + crc
end
def make_bitmap_data0
gz = Zlib::GzipWriter.open('png2.tmp')
t_Fx = 0
w = @bitmap.width
h = @bitmap.height
data = []
for y in 0...h
data.push(0)
for x in 0...w
t_Fx += 1
if t_Fx % 10000 == 0
Graphics.update
end
if t_Fx % 100000 == 0
s = data.pack('C*')
gz.write(s)
data.clear
end
color = @bitmap.get_pixel(x, y)
red = color.red
green = color.green
blue = color.blue
alpha = color.alpha
data.push(red)
data.push(green)
data.push(blue)
data.push(alpha)
end
end
s = data.pack('C*')
gz.write(s)
gz.close
data.clear
gz = Zlib::GzipReader.open('png2.tmp')
data = gz.read
gz.close
File.delete('png2.tmp')
return data
end
def make_bitmap_data1
w = @bitmap.width
h = @bitmap.height
data = []
for y in 0...h
data.push(0)
for x in 0...w
color = @bitmap.get_pixel(x, y)
red = color.red
green = color.green
blue = color.blue
alpha = color.alpha
data.push(red)
data.push(green)
data.push(blue)
data.push(alpha)
end
end
return data.pack('C*')
end
def make_iend
ie_size = [0].pack('N')
ie_sign = 'IEND'
ie_crc = [Zlib.crc32(ie_sign)].pack('N')
return ie_size + ie_sign + ie_crc
end
end
end
#=============================================================================
# ** Bitmap
#=============================================================================
class Bitmap
def make_png(name = 'like', path = '', mode = 0)
Zlib::Png_File.open('png.tmp') { |gz| gz.make_png(self, mode) }
Zlib::GzipReader.open('png.tmp') { |gz| $read = gz.read }
f = File.open(path + name + '.png', 'wb')
f.write($read)
f.close
File.delete('png.tmp')
end
end
Photo System
CODE
=begin
##############################
## Basic Photo System V 1.5 ##
##############################
Author : Sel Feena
Date : 06.07.11
Dependencies
------------
You need to have the ZLib module for this to work; put the script above this
one. Thanks to Kread-EX from RRR forums for showing it to me.
You also need to make a folder called 'Photos' in the game's Graphics folder.
Overview
--------
A simple system that lets your party keep a collection of
screenshots, which are stored along with descriptive data.
The data stored is:
* The snapshot itself (obviously), which is a Bitmap object.
* The ID of the map the photo was taken on.
* The name of the map the photo was taken on.
* The player's XY coords and what direction they were facing.
* The top left XY coords of the photo.
* Information about any events that are captured in the photo:
-The event's ID
-The event's name
-The event's XY coords
-The values for the event's Self-Switches
Conditional Event Recording
---------------------------
If you don't want an event's info to be stored in a photo
(i.e. if the event's something like a Player Transfer) then
put '[NP]' at the start or end of the event's name. For example:
'Warp to town [NP]'
'[NP] Puzzle switch 1'
If you want to use switches to determine if an event's info is stored, then
put '[x]' at the start or end of an event's name, where x is the switch
number. For example:
'Clue [21]' # Event info only stored if switch 21 is ON.
'[1][74] Phantom' # Event info only stored if switches 1 and 74 are ON.
Event Specific Processing
-------------------------
You can set individual script calls for an event, after the photo
image is saved.
BEAR IN MIND: The function will only be called if the event is
going to be stored in a photo. Some example event names:
'Alexander' # Event-specific processing ALWAYS performed.
'[NP] Switch' # Event-specific processing NEVER performed.
'Clue [21]' # Event-specific processing performed if switch 21 is ON.
'[1][9] Sue' # Event-specific processing performed if switches 1 and 9 are ON.
In the event's Page, insert a single-line comment anywhere that reads:
'[POSTPHOTO]'
IMMEDIATELY AFTER that comment, insert the function you wish to call
as another single-line comment. This function MUST:
* Be inside class Game_Interpreter (just add it at the bottom).
* Take a Game_Event object as THE LAST PARAMETER. This represents the
event itself.
When you're done, insert a single-line comment anywhere that reads:
'[/POSTPHOTO]'
Example:
GOAL - Create a function that will cause an event to turn invisible.
STEP 1 - Place the function inside class Game_Interpreter:
def set_transparency(val, event)
event.transparent = val
end
STEP 2 - Set up the tags inside an event's Page, by entering 2 single-line
comments like so:
-> Comment: [POSTPHOTO]
-> Comment: set_transparency false
-> Comment: [/POSTPHOTO]
There's no need to mention the event parameter in the function calls; the
photo system does that for you.
The photo system refreshes itself for you as well, so don't worry about
doing that either.
Forcing the Photo Image
-----------------------
You can force the image that a photo captures by using the tag [FORCEPHOTO]
This works by specifying the an area that the player must be in, and the
image to be shown (which must be in the Pictures folder, and 544 * 416)
Example:
-> Comment: [FORCEPHOTO]
-> Comment: 8, 8, 1, 1, [2], "sexypixie", false
-> Comment: 8, 10, 1, 1, [8], "sexypixie", false
-> Comment: 7, 9, 1, 1, [6], "sexypixie", false
-> Comment: 9, 9, 1, 1, [4], "sexypixie", false
-> Comment: [/FORCEPHOTO]
The parameters, in order, are:
1) The top-left corner of the rectangle (X).
2) The top-left corner of the rectangle (Y).
3) The width of the rectangle.
4) The height of the rectangle.
5) An array of the directions that the player can be facing.
6) The image within the Pictures folder to use.
7) Whether the numbers given for 1 and 2 are added to the event's x and y
to get their position or not. Use true for moving events.
If the photo is forced to an image by an event, then bear in mind that:
1) The only event whose details will be recorded are that event.
2) Only that event will be checked for a [POSTPHOTO] event.
###################
## Possible Bugs ##
###################
It doesn't seem possible in the editor, but using maps in your game that are
smaller than 17 X 13 in size could mess things up.
########################
## How To Use Windows ##
########################
Photos Scene
------------
There is a Scene_Photos class that displays all the photos in the party's
collection, and various info about them (you can set this in the module
below).
I recommend using a custom main menu manager to add this scene to your menu.
Leongon's Main Menu Manager is very easy to use. :3
Select a Photo
--------------
To let the player select a photo from their collection, use the script:
$game_variables[ x ] = sfp_choose_photo( s, z )
Where s is the string displayed for the 'confirm' option.
Where z sets whether the player can cancel (true / false).
Example:
$game_variables[10] = choose_photo("Select", true)
After this script call, $game_variables[10] may contain:
* The index of the selected photo (0 and above)
* The code SFPhotoModule::CANCEL_SELECTION (-1)
* The code SFPhotoModule::EMPTY_COLLECTION (-2)
You can set what is displayed by the selection window by setting values
in SFPhotoModule below.
Take a Photo
------------
To let the player take a photo, use the script:
sfp_save_photo
The player can then choose to save the photo, or cancel.
#################################
## How To Use Script Functions ##
#################################
Create Photo
------------
To create a photo, use the following script call:
myPhoto = SelFeenaPhoto.new
Add Photo to Collection
-----------------------
To add the photo to your collection, you'd then type:
$game_party.addPhoto(myPhoto)
The new photo will be added to your party's collection. HOWEVER, if your
collection is full then the photo in slot 0 will be erased to make room.
Set the maximum number of photos allowed in the module below.
Get Photo from Collection
-------------------------
To get a photo, call:
myPhoto = $game_party.getPhoto( x )
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Remove Photo from Collection
----------------------------
To destroy a photo, call:
$game_party.delPhoto( x )
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Get Number of Photos in Collection
----------------------------------
Use this script:
collection_size = $game_party.getPhotoCount
Make good use of this function call to avoid out-of-bounds errors!
Determine if Photo was Created Through [FORCEPHOTO] tag
-------------------------------------------------------
forced_image = $game_party.getPhoto( x ).isForcedImage
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Get Photo Image
---------------
myPhoto = $game_party.getPhoto( x )
picture = myPhoto.getImage
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
This function returns a Bitmap object.
Get Location of Photo
---------------------
myPhoto = $game_party.getPhoto( x )
location_id = myPhoto.getLocationID
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Variable 'location_id' will then have the Map ID of where the photo was taken.
myPhoto = $game_party.getPhoto( x )
location_name = myPhoto.getLocationName
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Variable 'location_name' will then have the name of the map
where the photo was taken.
Get Player's Position when Taking Photo
---------------------------------------
myPhoto = $game_party.getPhoto( x )
player_loc_data = myPhoto.getPlayerPosition
player_x = player_loc_data[0]
player_y = player_loc_data[1]
player_dir = player_loc_data[2]
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
This function returns an array of three integers:
- The player's X position.
- The player's Y position.
- The direction the player was facing:
- 2 -> Down
- 4 -> Left
- 6 -> Right
- 8 -> Up
Get Photo's Position
--------------------
myPhoto = $game_party.getPhoto( x )
photo_loc_data = myPhoto.getPhotoPosition
photo_x = photo_loc_data[0]
photo_y = photo_loc_data[1]
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
This function returns an array of two integers:
- The photo's top-left X position.
- The photo's top-left Y position.
Get Number of Events in Photo
-----------------------------
myPhoto = $game_party.getPhoto( x )
events_in_photo = myPhoto.getEventCount
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Is a Certain Event in Photo?
---------------------------
myPhoto = $game_party.getPhoto( x )
has_event = myPhoto.hasEventWithID( i )
Where x is the index of the photo in the collection, and i is the ID
number you're looking for.
Returns true or false.
How Many Events With Name "???" Are There?
-----------------------------------------
myPhoto = $game_party.getPhoto( x )
ev_count = myPhoto.countEventsWithName( z )
Where x is the index of the photo in the collection, and z is the name
you're looking for.
Get Info About Event With ID
----------------------------
myEventInfo = $game_party.getPhoto( x ).getEventWithID( z )
Where x is the index of the photo in the collection, and z is the event ID
you're looking for.
This function returns a SelFeenaPhotoEvent object.
WARNING! If photo x doesn't have an event with ID z, then you will get nil
Get Info About Events With Name
-------------------------------
myEventInfoArray = $game_party.getPhoto( x ).getEventsWithName( z )
Where x is the index of the photo in the collection, and z is the name
you're looking for.
This function returns an array of SelFeenaPhotoEvent objects.
Get All Event Data From Photo
-----------------------------
myEventInfoArray = $game_party.getPhoto( x ).getEvents
Where x is the index of the photo in the collection.
This function returns an array of SelFeenaPhotoEvent objects.
Handling Event Data From a Photo
--------------------------------
You can use the following functions on a SelFeenaPhotoEvent object:
* getID : Returns the ID number of this event.
* getName : Returns the event name, MINUS any tags.
* getPosition : Returns an array in the format [event.x, event.y]
* getSwitch( x ) : Returns the recorded status of self-switch x, where:
0 returns self_switch A
1 returns self_switch B
2 returns self_switch C
3 returns self_switch D
* getSwitches : Returns self-switch data in the format [A, B, C, D]
=end
#==============================================================================
# ** SFPhotoModule
#------------------------------------------------------------------------------
# Settings for the system and error/GUI codes stored here.
#==============================================================================
module SFPhotoModule
# ***********************
# *** COLLECTION SIZE ***
# ***********************
# Set this value to how many photos your party can have. Needs to
# be set to 1 or higher.
MAX_PHOTOS = 8
# ***********************
# *** DATABASE OUTPUT ***
# ***********************
# Set this to the game variable you want to store the photo count.
# If this value is -1 then no game variable is set.
PHOTO_COUNT_VAR = -1
# Set this to the game switch you want to say if there is at least
# one photo in the collection.
# If this value is -1 then no game switch is set.
HAS_PHOTO_SWITCH = -1
# ***********************
# *** WINDOW SETTINGS ***
# ***********************
# Image to display on top of a new photo when saving. Maybe something
# saying 'NEW!' or what have you.
# Must be in the Pictures folder.
NEW_PICTURE = ""
# Position of this image in the New Photo window, in format [ X, Y ]
NEW_POS = [0, 0]
# Name of the image to display if the party's photo collection is empty.
# This image must be in the Pictures folder, and should be 544 * 416
EMPTY_PICTURE = ""
# Message to display at the bottom of the Photos Scene when the photo
# collection is empty.
EMPTY_MSG = ""
# The type of info you want to display about a photo that is a snapshot
# of the screen (i.e. not a forced image). The format is:
# 1) Start string
# 2) Photo function to call. Must return a string.
# 3) End string.
SNAP_INFO = [
#String, Photo function, String
["Photo taken at ", "getLocationName", ""]
]
# The type of info you want to display about a photo that is a forced image.
# The format is:
# 1) Start string
# 2) Photo function to call
# 3) End string.
FORCED_INFO = [
#String, Photo function, String
["Photo taken at ", "getLocationName", ""],
["Photo of ", "getEvents[0].getName", ""]
]
# ********************
# *** SYSTEM STUFF ***
# ********************
# DON'T change the values here!
EMPTY_COLLECTION = -2
CANCEL_SELECTION = -1
end
###############################
###############################
## ##
## DON'T GO PAST HERE! ##
## ##
###############################
###############################
#==============================================================================
# ** Game_Map
#------------------------------------------------------------------------------
# Update Game_Map to allow access to map name.
#==============================================================================
class Game_Map
attr_reader :name
alias mapname_setup setup
def setup(map_id)
mapname_setup(map_id)
data = load_data("Data/MapInfos.rvdata")
@name = data[map_id].name
end
end
#==============================================================================
# ** Game_Event
#------------------------------------------------------------------------------
# Update Game_Event to allow access to name and test it against tags.
#==============================================================================
class Game_Event < Game_Character
attr_accessor :event
# Return the full name of the Event.
def getName
return @event.name
end
# Removes any occurence of photo tags from name and returns it.
def getNameWithoutTags
trimmed_name = @event.name
trimmed_name = trimmed_name.gsub(/\s*\[[0-9]*\]\s*/){""}
trimmed_name = trimmed_name.gsub(/\s*\[NP\]\s*/){""}
return trimmed_name
end
# Do the tags in this Event's name allow it to be stored in a photo?
def allowPhoto
# [NP] tag means NEVER record event's info...
if(@event.name.scan(/\[NP\]/).size > 0)
return false
end
# Go through switch tags and check if the switches referenced are ON.
result = true
switch_arr = []
@event.name.scan(/\[[0-9]*\]/){|s| switch_arr.push(s[1, s.length - 2].to_i)}
for switch_id in switch_arr
if($game_switches[switch_id] == false)
result = false
end
end
return result
end
end
#==============================================================================
# ** Game_Party
#------------------------------------------------------------------------------
# Update Game_Party to include access to photo data.
#==============================================================================
class Game_Party < Game_Unit
alias selfeenaphoto_init initialize
def initialize
@photos = []
if(SFPhotoModule::PHOTO_COUNT_VAR >= 0)
$game_variables[SFPhotoModule::PHOTO_COUNT_VAR] = 0
end
if(SFPhotoModule::HAS_PHOTO_SWITCH >= 0)
$game_switches[SFPhotoModule::HAS_PHOTO_SWITCH] = false
end
selfeenaphoto_init
end
# Number of photos currently in collection.
def getPhotoCount
return @photos.length
end
# Is the photo collection full?
def photoAlbumFull
return (@photos.length == SFPhotoModule::MAX_PHOTOS)
end
# Return photo at index i
# Use getPhotoCount to avoid out-of-bounds errors!
def getPhoto(i)
return @photos[i]
end
# Destroy photo at index i
# Use getPhotoCount to avoid out-of-bounds errors!
def delPhoto(i)
@photos.delete_at(i)
if(SFPhotoModule::PHOTO_COUNT_VAR >= 0)
$game_variables[SFPhotoModule::PHOTO_COUNT_VAR] = @photos.length
end
if(SFPhotoModule::HAS_PHOTO_SWITCH >= 0)
$game_switches[SFPhotoModule::HAS_PHOTO_SWITCH] = (@photos.length > 0)
end
end
# Add a new photo to the collection. If the collection is full,
# the photo at index 0 is destroyed to make room.
def addPhoto(p)
if(@photos.length == SFPhotoModule::MAX_PHOTOS)
@photos.delete_at(0)
end
@photos.push(p)
if(SFPhotoModule::PHOTO_COUNT_VAR >= 0)
$game_variables[SFPhotoModule::PHOTO_COUNT_VAR] = @photos.length
end
if(SFPhotoModule::HAS_PHOTO_SWITCH >= 0)
$game_switches[SFPhotoModule::HAS_PHOTO_SWITCH] = (@photos.length > 0)
end
end
end
#==============================================================================
# ** SelFeenaPhoto
#------------------------------------------------------------------------------
# Class encapsulating photo data.
#==============================================================================
class SelFeenaPhoto
def initialize
# Variables used to check for forced photo image...
@forcedeventid = 0
@forcedpicture = ""
# Save Map ID and name...
@map_id = $game_map.map_id
@map_name = $game_map.name
# Save player position and direction...
@player_x = $game_player.x
@player_y = $game_player.y
@player_dir = $game_player.direction
# Save xy position of photo (top-left corner) as map coordinates
@photo_pos_x = $game_map.display_x / 256
@photo_pos_y = $game_map.display_y / 256
# What events have we captured in the photo?
arr = []
for x in @photo_pos_x..(@photo_pos_x + 16)
if(x >= $game_map.width) # Horizontal loop fix
x -= $game_map.width
end
for y in @photo_pos_y..(@photo_pos_y + 12)
if(y >= $game_map.height) # Vertical loop fix
y -= $game_map.height
end
arr = arr + $game_map.events_xy(x, y)
end
end
# Whittle down events to those that are valid...
ev_arr = []
for e in arr
if(e.allowPhoto == true)
ev_arr.push(e)
end
end
# Check for image forcing.
processEvents("[FORCEPHOTO]", "self.forceImage ", "[/FORCEPHOTO]", ev_arr)
# Store event data. If a forced image has been triggered,
# only store information about that event.
@event_data = []
for i in ev_arr
if (@forcedeventid == 0) or (@forcedeventid == i.id)
# Event ID...
ev_id = i.id
# Event name...
ev_name = i.getNameWithoutTags
# Event position...
ev_pos = [i.x, i.y]
# Event self-switch info...
i_swa = $game_self_switches[[$game_map.map_id, i.id, "A"]]
i_swb = $game_self_switches[[$game_map.map_id, i.id, "B"]]
i_swc = $game_self_switches[[$game_map.map_id, i.id, "C"]]
i_swd = $game_self_switches[[$game_map.map_id, i.id, "D"]]
ev_switches = [i_swa, i_swb, i_swc, i_swd]
new_ev = SelFeenaPhotoEvent.new(ev_id, ev_name, ev_pos, ev_switches)
@event_data.push(new_ev)
end
end
# Store image. Either a screenshot or the forced image.
if(@forcedeventid == 0)
@image_data = Graphics.snap_to_bitmap
else
@image_data = Cache.picture(@forcedpicture).clone
end
# Postprocessing. Process either ALL events or just the event
# that has forced the photo image.
if(@forcedeventid == 0)
processEvents("[POSTPHOTO]", "$game_map.interpreter.",
"[/POSTPHOTO]", ev_arr)
else
fev = $game_map.events[@forcedeventid]
processEvent(fev, "[POSTPHOTO]", "$game_map.interpreter.", "[/POSTPHOTO]")
end
end
# Remove Bitmap. Go on, shoo! :3
def dispose
@image_data.dispose
end
# Is this photo a forced image ([FORCEPHOTO] tag)?
def isForcedImage
return (@forcedeventid != 0)
end
# Loop through Events and perform processing if tag is present in Page.
# When done, update to reflect changes.
def processEvents(tag, eval_str, endtag, ev_a)
for ev in ev_a
processEvent(ev, tag, eval_str, endtag)
end
$game_map.refresh
end
# Perform processing for a specific Event based on the tag given.
def processEvent(my_event, my_tag, my_str, my_endtag)
for i in 0...my_event.list.size
if (my_event.list[i].code == 108)
if (my_event.list[i].parameters == [my_tag])
linecount = i + 1
command = my_event.list[linecount].parameters
until (command == [my_endtag])
eval(my_str + command[0] + ", my_event")
linecount += 1
command = my_event.list[linecount].parameters
end
return
end
end
end
end
# Determine if image should be a specified bitmap.
def forceImage(x, y, width, height, dir_arr, pic_name, centred, ev)
# Is the rectangle's position based on the event's?
if(centred == true)
x = ev.x + x
y = ev.y + y
end
# Go through rectangle, with corrections for looping maps.
for ix in x..(x + width - 1)
if(ix >= $game_map.width) and ($game_map.loop_horizontal?)
ix -= $game_map.width
end
for iy in y..(y + height - 1)
if(iy >= $game_map.height) and ($game_map.loop_vertical?)
iy -= $game_map.height
end
# We have a match inside our rectangle. Now, what about direction?
if(@player_x == ix) and (@player_y == iy)
if(dir_arr.include?(@player_dir))
@forcedeventid = ev.id
@forcedpicture = pic_name
end
return
end
end
end
end
# Return image bitmap.
def getImage
return @image_data
end
# Set image bitmap.
def setImage(pic)
@image_data = pic
end
# Destroy image bitmap.
def delImage
@image_data.dispose
@image_data = nil
end
# Return ID of map where photo was taken.
def getLocationID
return @map_id
end
# Return name of map where photo was taken.
def getLocationName
return @map_name
end
# Return player position when photo was taken.
# Format = [ Map X position, Map Y position, Direction player was facing ]
def getPlayerPosition
return [@player_x, @player_y, @player_dir]
end
# Return position of photo's top-left corner on map.
# Format = [ Photo X position, Photo Y position ]
def getPhotoPosition
return [@photo_pos_x, @photo_pos_y]
end
# Number of SelFeenaPhotoEvents caught on camera.
def getEventCount
return @event_data.length
end
# Does photo have info about a SelFeenaPhotoEvent with a specific ID?
def hasEventWithID(target_id)
result = false
for i in @event_data
if i.getID == target_id
result = true
end
end
return result
end
# How many SelFeenaPhotoEvents with a specific name are in the photo?
def countEventsWithName(target_name)
result = 0
for i in @event_data
if i.getName == target_name
result += 1
end
end
return result
end
# Return an array of SelFeenaPhotoEvents with a specific name. May be empty.
def getEventsWithName(target_name)
result = []
for i in @event_data
if i.getName == target_name
result.push(i)
end
end
return result
end
# Return SelFeenaPhotoEvent with a specific ID.
# If there is no SelFeenaPhotoEvent with that ID, returns nil.
def getEventWithID(target_id)
result = nil
for i in @event_data
if i.getID == target_id
result = i
end
end
return result
end
# Return all SelFeenaPhotoEvents in photo as an array.
def getEvents
return @event_data
end
end
#==============================================================================
# ** SelFeenaPhotoEvent
#------------------------------------------------------------------------------
# Class encapsulating info about an event captured in a photo.
#==============================================================================
class SelFeenaPhotoEvent
def initialize(e_id, e_name, e_pos, e_switches)
@id = e_id
@name = e_name
@position = e_pos
@switches = e_switches
end
# Event ID.
def getID
return @id
end
# Event name.
def getName
return @name
end
# Return MAP position of Event.
# Format = [ Event X position, Event Y position ]
def getPosition
return @position
end
# Return Self-Switch information recorded for Event:
# 0 : Self-Switch A
# 1 : Self-Switch B
# 2 : Self-Switch C
# 3 : Self-Switch D
def getSwitch(s)
return @switches[s]
end
# Return recorded Self-Switch information for Event.
# Format = [ A, B, C, D ]
def getSwitches
return @switches
end
end
#==============================================================================
# ** Window_PhotoSelect
#------------------------------------------------------------------------------
# This window displays photos from the party's collection.
#==============================================================================
class Window_PhotoSelect < Window_Base
def initialize(x, y, w, h, sa = true)
super(x, y, w, h)
@showarrows = sa
# If the party's collection is empty, then set index to error code.
if($game_party.getPhotoCount == 0)
@index = SFPhotoModule::EMPTY_COLLECTION
else
@index = 0
end
refresh
end
# Return index of the currently displayed photo.
def getIndex
return @index
end
# Select the previous photo in collection (wraps around).
def prevPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
oldindex = @index
@index -= 1
# Wraparound.
if (@index < 0)
@index = $game_party.getPhotoCount - 1
end
# Sound if new photo selected.
if(@index != oldindex)
Sound.play_cursor
end
end
end
# Select the next photo in collection (wraps around).
def nextPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
oldindex = @index
@index += 1
# Wraparound.
if (@index == $game_party.getPhotoCount)
@index = 0
end
# Sound if new photo selected.
if(@index != oldindex)
Sound.play_cursor
end
end
end
# Display a photo from party's collection.
def refresh
self.contents.clear
# Check if we're dealing with an empty collection.
if(@index == SFPhotoModule::EMPTY_COLLECTION)
# Display empty collection image.
if(SFPhotoModule::EMPTY_PICTURE.length > 0)
scaled_rect = Rect.new(0, 0, width - 32, height - 32)
pic_rect = Rect.new(0, 0, 544, 416)
pic = Cache.picture(SFPhotoModule::EMPTY_PICTURE)
self.contents.stretch_blt(scaled_rect, pic, pic_rect)
end
else
# Display scaled photo image.
scaled_rect = Rect.new(0, 0, width - 32, height - 32)
pic_rect = Rect.new(0, 0, 544, 416)
photo = $game_party.getPhoto(@index)
self.contents.stretch_blt(scaled_rect, photo.getImage, pic_rect)
# Display arrows if collection larger than 1
if($game_party.getPhotoCount > 1) and (@showarrows == true)
l_rect = Rect.new(80, 25, 8, 14)
r_rect = Rect.new(104, 25, 8, 14)
self.contents.blt(0, (height / 2) - 23, windowskin, l_rect)
self.contents.blt(width - 40, (height / 2) - 23, windowskin, r_rect)
end
end
end
end
#==============================================================================
# ** Window_PhotoPreview
#------------------------------------------------------------------------------
# This window displays a photo passed to it on instantiation.
#==============================================================================
class Window_PhotoPreview < Window_Base
def initialize(x, y, w, h, p, newp)
@preview = p
@newphoto = newp
super(x, y, w, h)
refresh
end
# Display the photo.
def refresh
self.contents.clear
# Display scaled photo image.
scaled_rect = Rect.new(0, 0, width - 32, height - 32)
pic_rect = Rect.new(0, 0, 544, 416)
self.contents.stretch_blt(scaled_rect, @preview.getImage, pic_rect)
# Display 'new image' tag.
if(SFPhotoModule::NEW_PICTURE.length > 0) and (newp == true)
pic_x = SFPhotoModule::NEW_POS[0]
pic_y = SFPhotoModule::NEW_POS[1]
pic = Cache.picture(SFPhotoModule::NEW_PICTURE)
pic_rect = Rect.new(0, 0, pic.width, pic.height)
self.contents.blt(pic_x, pic_y, pic, pic_rect)
end
end
end
#==============================================================================
# ** Window_PhotoStrip
#------------------------------------------------------------------------------
# This displays a list of all photos in a strip.
#==============================================================================
class Window_PhotoStrip < Window_Base
def initialize
super(0, 0, 104, 344)
# If the party's collection is empty, then set index to error code.
if($game_party.getPhotoCount == 0)
@index = SFPhotoModule::EMPTY_COLLECTION
else
@index = 0
end
@startindex = 0
refresh
end
# Update cursor position.
def prevPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
# Update cursor.
@index -= 1
flip = false
if(@index < 0)
@index = $game_party.getPhotoCount - 1
flip = true
end
# Update strip display.
if(flip == true)
if($game_party.getPhotoCount - 5 < 0)
@startindex = 0
else
@startindex = $game_party.getPhotoCount - 5
end
else
if(@index < @startindex)
@startindex -= 1
end
end
refresh
end
end
# Update cursor position.
def nextPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
# Update cursor.
@index += 1
flip = false
if(@index == $game_party.getPhotoCount)
@index = 0
flip = true
end
# Update strip display.
if(flip == true)
@startindex = 0
else
if(@index > @startindex + 4)
@startindex += 1
end
end
refresh
end
end
# Calculate how far to draw from current @startindex value.
def getDrawLimit
if(@startindex + 4 <= $game_party.getPhotoCount - 1)
return @startindex + 4
else
return $game_party.getPhotoCount - 1
end
end
# Display photo strip.
def refresh
self.contents.clear
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
# Draw cursor.
cursor_rect = Rect.new(0, 10 + (@index - @startindex) * 60, 72, 52)
self.contents.font.color = normal_color
self.contents.fill_rect(cursor_rect, self.contents.font.color)
# Draw strip.
for i in @startindex..getDrawLimit
pic = $game_party.getPhoto(i).getImage
scaled_rect = Rect.new(2, 10 + (i - @startindex) * 60, 68, 52)
pic_rect = Rect.new(0, 0, 544, 416)
self.contents.stretch_blt(scaled_rect, pic, pic_rect)
end
# Draw up / down arrows if necessary.
if($game_party.getPhotoCount > 5)
u_rect = Rect.new(89, 17, 14, 8)
d_rect = Rect.new(89, 40, 14, 8)
self.contents.blt((width / 2) - 23, 0, windowskin, u_rect)
self.contents.blt((width / 2) - 23, height - 40, windowskin, d_rect)
end
end
end
end
#==============================================================================
# ** Window_PhotoText
#------------------------------------------------------------------------------
# This window displays info about a photo.
#==============================================================================
class Window_PhotoText < Window_Base
def initialize
super(0, 344, 544, 72)
@info = 0
# If the party's collection is empty, then set index to error code.
if($game_party.getPhotoCount == 0)
@index = SFPhotoModule::EMPTY_COLLECTION
else
@index = 0
end
refresh
end
# Set the window to display info about the previous photo.
def prevPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
oldindex = @index
@index -= 1
# Wraparound.
if (@index < 0)
@index = $game_party.getPhotoCount - 1
end
# Reset info index if new photo selected.
if(@index != oldindex)
@info = 0
end
refresh
end
end
# Set the window to display info about the previous photo.
def nextPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
oldindex = @index
@index += 1
# Wraparound.
if (@index == $game_party.getPhotoCount)
@index = 0
end
# Reset info index if new photo selected.
if(@index != oldindex)
@info = 0
end
refresh
end
end
# Get limit of info index for the current photo
def getInfoSize
if(@index != SFPhotoModule::EMPTY_COLLECTION)
if($game_party.getPhoto(@index).isForcedImage)
return SFPhotoModule::FORCED_INFO.length
else
return SFPhotoModule::SNAP_INFO.length
end
else
return 0
end
end
# Display previous piece of info about the photo
def prevInfo
# Only if there is info to display.
if(getInfoSize != 0)
oldinfo = @info
@info -= 1
# Wraparound.
if (@info < 0)
@info = getInfoSize - 1
end
# Play sound if new info selected.
if(@info != oldinfo)
Sound.play_cursor
end
refresh
end
end
# Display next piece of info about the photo
def nextInfo
# Only if there is info to display.
if(getInfoSize != 0)
oldinfo = @info
@info += 1
# Wraparound.
if (@info == getInfoSize)
@info = 0
end
# Play sound if new info selected.
if(@info != oldinfo)
Sound.play_cursor
end
refresh
end
end
def refresh
self.contents.clear
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
# Only if there is info to display.
if(getInfoSize != 0)
info_arr = []
if($game_party.getPhoto(@index).isForcedImage)
info_arr = SFPhotoModule::FORCED_INFO[@info]
else
info_arr = SFPhotoModule::SNAP_INFO[@info]
end
info_str = info_arr[0]
info_str = info_str + eval("$game_party.getPhoto(@index)." + info_arr[1])
info_str = info_str + info_arr[2]
self.contents.font.color = normal_color
self.contents.draw_text(16, 8, width, WLH, info_str, 0)
# Display arrows if info array larger than 1.
if(getInfoSize > 1)
l_rect = Rect.new(80, 25, 8, 14)
r_rect = Rect.new(104, 25, 8, 14)
self.contents.blt(0, (height / 2) - 23, windowskin, l_rect)
self.contents.blt(width - 40, (height / 2) - 23, windowskin, r_rect)
end
end
else
self.contents.font.color = normal_color
self.contents.draw_text(16, 8, width, WLH, SFPhotoModule::EMPTY_MSG, 0)
end
end
end
#==============================================================================
# ** Scene_Photos
#------------------------------------------------------------------------------
# Display photographs taken by the player.
#==============================================================================
class Scene_Photos < Scene_Base
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
end
#--------------------------------------------------------------------------
# * Start processing
#--------------------------------------------------------------------------
def start
super
create_menu_background
@photo_window = Window_PhotoSelect.new(104, 0, 440, 344, false)
@photo_strip = Window_PhotoStrip.new
@text_window = Window_PhotoText.new
end
#--------------------------------------------------------------------------
# * Termination Processing
#--------------------------------------------------------------------------
def terminate
super
dispose_menu_background
@photo_window.dispose
@photo_strip.dispose
@text_window.dispose
end
#--------------------------------------------------------------------------
# * Return to Original Screen
#--------------------------------------------------------------------------
def return_scene
$scene = Scene_Menu.new
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
update_menu_background
@photo_window.update
@text_window.update
if Input.trigger?(Input::UP)
@photo_window.prevPhoto
@photo_window.refresh
@photo_strip.prevPhoto
@text_window.prevPhoto
end
if Input.trigger?(Input::DOWN)
@photo_window.nextPhoto
@photo_window.refresh
@photo_strip.nextPhoto
@text_window.nextPhoto
end
if Input.trigger?(Input::LEFT)
@text_window.prevInfo
end
if Input.trigger?(Input::RIGHT)
@text_window.nextInfo
end
if Input.trigger?(Input::B)
Sound.play_cancel
return_scene
end
super
end
end
#==============================================================================
# ** Game_Interpreter
#------------------------------------------------------------------------------
# Add functions for photographs.
#==============================================================================
class Game_Interpreter
# Select a photo from the party's collection. Returns the index.
# Selecting from empty collection returns SFPhotoModule::EMPTY_COLLECTION
# Cancelling will return SFPhotoModule::CANCEL_SELECTION
def sfp_choose_photo(choice_str, allowcancel)
# Create photo display and selection window...
photo_window = Window_PhotoSelect.new(120, 44, 304, 240)
choice_arr = []
choice_arr.push(choice_str)
if(allowcancel == true)
choice_arr.push("Cancel")
end
confirm_window = Window_Command.new(photo_window.width, choice_arr)
confirm_window.x = photo_window.x
confirm_window.y = photo_window.y + photo_window.height
# Process input...
while true
Graphics.update
Input.update
confirm_window.update
photo_window.update
if Input.trigger?(Input::LEFT)
photo_window.prevPhoto
photo_window.refresh
end
if Input.trigger?(Input::RIGHT)
photo_window.nextPhoto
photo_window.refresh
end
break if Input.trigger?(Input::C)
end
Input.update
# Clean up...
picchoice = photo_window.getIndex
choice = confirm_window.index
photo_window.dispose
confirm_window.dispose
# Return selection or cancel code...
if(choice == 0)
Sound.play_decision
return picchoice
else
Sound.play_cancel
return SFPhotoModule::CANCEL_SELECTION
end
end
# 1) Take a photo.
# 2) Show the photo, with options to save or cancel.
# 3) Save photo, or discard.
def sfp_save_photo
# Create photo...
newphoto = SelFeenaPhoto.new
# Create and position windows...
photo_window = Window_PhotoPreview.new(120, 44, 304, 240, newphoto, true)
confirm_window = Window_Command.new(photo_window.width, ["Save", "Cancel"])
confirm_window.x = photo_window.x
confirm_window.y = photo_window.y + photo_window.height
# Processing...
while true
Graphics.update
Input.update
photo_window.update
confirm_window.update
break if Input.trigger?(Input::C)
end
Input.update
# Clean up...
choice = confirm_window.index
photo_window.dispose
confirm_window.dispose
# Save photo, or dispose of it...
if(choice == 0)
Sound.play_decision
# Overwrite photo or just add to collection?
if($game_party.photoAlbumFull == true)
overwrite_index = sfp_choose_photo("Overwrite", true)
# Photo selected, or cancel?
if(overwrite_index >= 0)
$game_party.delPhoto(overwrite_index)
$game_party.addPhoto(newphoto)
else
newphoto.dispose
end
else
$game_party.addPhoto(newphoto)
end
else
Sound.play_cancel
newphoto.dispose
end
end
end
#==============================================================================
# ** Scene_File
#------------------------------------------------------------------------------
# It's necessary to overwrite these two functions as VX doesn't like
# writing Bitmap objects to file. Somewhat annoying, but whatever.
#
# Instead the photo images are saved as png files, and loaded up when
# the player loads a game. Example file format, in case you wanted to know...
#
# S0P7.png <= Photo number 7, Save slot 0.
#
# This means a bit of a pause when saving/loading, but not much.
#==============================================================================
class Scene_File < Scene_Base
#--------------------------------------------------------------------------
# * Write Save Data
# file : write file object (opened)
#--------------------------------------------------------------------------
alias selfeenaphoto_save write_save_data
alias selfeenaphoto_read read_save_data
def write_save_data(file)
# Save photos to file, and temporarily destroy Bitmaps.
i = 0
tempphoto_arr = []
while (i < $game_party.getPhotoCount)
pic = $game_party.getPhoto(i).getImage.clone
tempphoto_arr.push(pic)
pic.make_png("S" + @index.to_s + "P" + i.to_s, "Graphics/Photos/")
$game_party.getPhoto(i).delImage
i += 1
end
# Normal save stuff.
selfeenaphoto_save(file)
# Put image data back in photos.
i = 0
for p in tempphoto_arr
$game_party.getPhoto(i).setImage(p)
i += 1
end
end
#--------------------------------------------------------------------------
# * Read Save Data
# file : file object for reading (opened)
#--------------------------------------------------------------------------
def read_save_data(file)
# Normal load stuff.
selfeenaphoto_read(file)
# Load images from files into photos.
i = 0
while(i < $game_party.getPhotoCount)
pic = Bitmap.new("Graphics/Photos/S" + @index.to_s + "P" + i.to_s)
$game_party.getPhoto(i).setImage(pic)
i += 1
end
end
end
##############################
## Basic Photo System V 1.5 ##
##############################
Author : Sel Feena
Date : 06.07.11
Dependencies
------------
You need to have the ZLib module for this to work; put the script above this
one. Thanks to Kread-EX from RRR forums for showing it to me.
You also need to make a folder called 'Photos' in the game's Graphics folder.
Overview
--------
A simple system that lets your party keep a collection of
screenshots, which are stored along with descriptive data.
The data stored is:
* The snapshot itself (obviously), which is a Bitmap object.
* The ID of the map the photo was taken on.
* The name of the map the photo was taken on.
* The player's XY coords and what direction they were facing.
* The top left XY coords of the photo.
* Information about any events that are captured in the photo:
-The event's ID
-The event's name
-The event's XY coords
-The values for the event's Self-Switches
Conditional Event Recording
---------------------------
If you don't want an event's info to be stored in a photo
(i.e. if the event's something like a Player Transfer) then
put '[NP]' at the start or end of the event's name. For example:
'Warp to town [NP]'
'[NP] Puzzle switch 1'
If you want to use switches to determine if an event's info is stored, then
put '[x]' at the start or end of an event's name, where x is the switch
number. For example:
'Clue [21]' # Event info only stored if switch 21 is ON.
'[1][74] Phantom' # Event info only stored if switches 1 and 74 are ON.
Event Specific Processing
-------------------------
You can set individual script calls for an event, after the photo
image is saved.
BEAR IN MIND: The function will only be called if the event is
going to be stored in a photo. Some example event names:
'Alexander' # Event-specific processing ALWAYS performed.
'[NP] Switch' # Event-specific processing NEVER performed.
'Clue [21]' # Event-specific processing performed if switch 21 is ON.
'[1][9] Sue' # Event-specific processing performed if switches 1 and 9 are ON.
In the event's Page, insert a single-line comment anywhere that reads:
'[POSTPHOTO]'
IMMEDIATELY AFTER that comment, insert the function you wish to call
as another single-line comment. This function MUST:
* Be inside class Game_Interpreter (just add it at the bottom).
* Take a Game_Event object as THE LAST PARAMETER. This represents the
event itself.
When you're done, insert a single-line comment anywhere that reads:
'[/POSTPHOTO]'
Example:
GOAL - Create a function that will cause an event to turn invisible.
STEP 1 - Place the function inside class Game_Interpreter:
def set_transparency(val, event)
event.transparent = val
end
STEP 2 - Set up the tags inside an event's Page, by entering 2 single-line
comments like so:
-> Comment: [POSTPHOTO]
-> Comment: set_transparency false
-> Comment: [/POSTPHOTO]
There's no need to mention the event parameter in the function calls; the
photo system does that for you.
The photo system refreshes itself for you as well, so don't worry about
doing that either.
Forcing the Photo Image
-----------------------
You can force the image that a photo captures by using the tag [FORCEPHOTO]
This works by specifying the an area that the player must be in, and the
image to be shown (which must be in the Pictures folder, and 544 * 416)
Example:
-> Comment: [FORCEPHOTO]
-> Comment: 8, 8, 1, 1, [2], "sexypixie", false
-> Comment: 8, 10, 1, 1, [8], "sexypixie", false
-> Comment: 7, 9, 1, 1, [6], "sexypixie", false
-> Comment: 9, 9, 1, 1, [4], "sexypixie", false
-> Comment: [/FORCEPHOTO]
The parameters, in order, are:
1) The top-left corner of the rectangle (X).
2) The top-left corner of the rectangle (Y).
3) The width of the rectangle.
4) The height of the rectangle.
5) An array of the directions that the player can be facing.
6) The image within the Pictures folder to use.
7) Whether the numbers given for 1 and 2 are added to the event's x and y
to get their position or not. Use true for moving events.
If the photo is forced to an image by an event, then bear in mind that:
1) The only event whose details will be recorded are that event.
2) Only that event will be checked for a [POSTPHOTO] event.
###################
## Possible Bugs ##
###################
It doesn't seem possible in the editor, but using maps in your game that are
smaller than 17 X 13 in size could mess things up.
########################
## How To Use Windows ##
########################
Photos Scene
------------
There is a Scene_Photos class that displays all the photos in the party's
collection, and various info about them (you can set this in the module
below).
I recommend using a custom main menu manager to add this scene to your menu.
Leongon's Main Menu Manager is very easy to use. :3
Select a Photo
--------------
To let the player select a photo from their collection, use the script:
$game_variables[ x ] = sfp_choose_photo( s, z )
Where s is the string displayed for the 'confirm' option.
Where z sets whether the player can cancel (true / false).
Example:
$game_variables[10] = choose_photo("Select", true)
After this script call, $game_variables[10] may contain:
* The index of the selected photo (0 and above)
* The code SFPhotoModule::CANCEL_SELECTION (-1)
* The code SFPhotoModule::EMPTY_COLLECTION (-2)
You can set what is displayed by the selection window by setting values
in SFPhotoModule below.
Take a Photo
------------
To let the player take a photo, use the script:
sfp_save_photo
The player can then choose to save the photo, or cancel.
#################################
## How To Use Script Functions ##
#################################
Create Photo
------------
To create a photo, use the following script call:
myPhoto = SelFeenaPhoto.new
Add Photo to Collection
-----------------------
To add the photo to your collection, you'd then type:
$game_party.addPhoto(myPhoto)
The new photo will be added to your party's collection. HOWEVER, if your
collection is full then the photo in slot 0 will be erased to make room.
Set the maximum number of photos allowed in the module below.
Get Photo from Collection
-------------------------
To get a photo, call:
myPhoto = $game_party.getPhoto( x )
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Remove Photo from Collection
----------------------------
To destroy a photo, call:
$game_party.delPhoto( x )
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Get Number of Photos in Collection
----------------------------------
Use this script:
collection_size = $game_party.getPhotoCount
Make good use of this function call to avoid out-of-bounds errors!
Determine if Photo was Created Through [FORCEPHOTO] tag
-------------------------------------------------------
forced_image = $game_party.getPhoto( x ).isForcedImage
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Get Photo Image
---------------
myPhoto = $game_party.getPhoto( x )
picture = myPhoto.getImage
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
This function returns a Bitmap object.
Get Location of Photo
---------------------
myPhoto = $game_party.getPhoto( x )
location_id = myPhoto.getLocationID
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Variable 'location_id' will then have the Map ID of where the photo was taken.
myPhoto = $game_party.getPhoto( x )
location_name = myPhoto.getLocationName
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Variable 'location_name' will then have the name of the map
where the photo was taken.
Get Player's Position when Taking Photo
---------------------------------------
myPhoto = $game_party.getPhoto( x )
player_loc_data = myPhoto.getPlayerPosition
player_x = player_loc_data[0]
player_y = player_loc_data[1]
player_dir = player_loc_data[2]
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
This function returns an array of three integers:
- The player's X position.
- The player's Y position.
- The direction the player was facing:
- 2 -> Down
- 4 -> Left
- 6 -> Right
- 8 -> Up
Get Photo's Position
--------------------
myPhoto = $game_party.getPhoto( x )
photo_loc_data = myPhoto.getPhotoPosition
photo_x = photo_loc_data[0]
photo_y = photo_loc_data[1]
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
This function returns an array of two integers:
- The photo's top-left X position.
- The photo's top-left Y position.
Get Number of Events in Photo
-----------------------------
myPhoto = $game_party.getPhoto( x )
events_in_photo = myPhoto.getEventCount
Where x is the index of the photo in the collection. Just like
arrays, this starts from 0
Is a Certain Event in Photo?
---------------------------
myPhoto = $game_party.getPhoto( x )
has_event = myPhoto.hasEventWithID( i )
Where x is the index of the photo in the collection, and i is the ID
number you're looking for.
Returns true or false.
How Many Events With Name "???" Are There?
-----------------------------------------
myPhoto = $game_party.getPhoto( x )
ev_count = myPhoto.countEventsWithName( z )
Where x is the index of the photo in the collection, and z is the name
you're looking for.
Get Info About Event With ID
----------------------------
myEventInfo = $game_party.getPhoto( x ).getEventWithID( z )
Where x is the index of the photo in the collection, and z is the event ID
you're looking for.
This function returns a SelFeenaPhotoEvent object.
WARNING! If photo x doesn't have an event with ID z, then you will get nil
Get Info About Events With Name
-------------------------------
myEventInfoArray = $game_party.getPhoto( x ).getEventsWithName( z )
Where x is the index of the photo in the collection, and z is the name
you're looking for.
This function returns an array of SelFeenaPhotoEvent objects.
Get All Event Data From Photo
-----------------------------
myEventInfoArray = $game_party.getPhoto( x ).getEvents
Where x is the index of the photo in the collection.
This function returns an array of SelFeenaPhotoEvent objects.
Handling Event Data From a Photo
--------------------------------
You can use the following functions on a SelFeenaPhotoEvent object:
* getID : Returns the ID number of this event.
* getName : Returns the event name, MINUS any tags.
* getPosition : Returns an array in the format [event.x, event.y]
* getSwitch( x ) : Returns the recorded status of self-switch x, where:
0 returns self_switch A
1 returns self_switch B
2 returns self_switch C
3 returns self_switch D
* getSwitches : Returns self-switch data in the format [A, B, C, D]
=end
#==============================================================================
# ** SFPhotoModule
#------------------------------------------------------------------------------
# Settings for the system and error/GUI codes stored here.
#==============================================================================
module SFPhotoModule
# ***********************
# *** COLLECTION SIZE ***
# ***********************
# Set this value to how many photos your party can have. Needs to
# be set to 1 or higher.
MAX_PHOTOS = 8
# ***********************
# *** DATABASE OUTPUT ***
# ***********************
# Set this to the game variable you want to store the photo count.
# If this value is -1 then no game variable is set.
PHOTO_COUNT_VAR = -1
# Set this to the game switch you want to say if there is at least
# one photo in the collection.
# If this value is -1 then no game switch is set.
HAS_PHOTO_SWITCH = -1
# ***********************
# *** WINDOW SETTINGS ***
# ***********************
# Image to display on top of a new photo when saving. Maybe something
# saying 'NEW!' or what have you.
# Must be in the Pictures folder.
NEW_PICTURE = ""
# Position of this image in the New Photo window, in format [ X, Y ]
NEW_POS = [0, 0]
# Name of the image to display if the party's photo collection is empty.
# This image must be in the Pictures folder, and should be 544 * 416
EMPTY_PICTURE = ""
# Message to display at the bottom of the Photos Scene when the photo
# collection is empty.
EMPTY_MSG = ""
# The type of info you want to display about a photo that is a snapshot
# of the screen (i.e. not a forced image). The format is:
# 1) Start string
# 2) Photo function to call. Must return a string.
# 3) End string.
SNAP_INFO = [
#String, Photo function, String
["Photo taken at ", "getLocationName", ""]
]
# The type of info you want to display about a photo that is a forced image.
# The format is:
# 1) Start string
# 2) Photo function to call
# 3) End string.
FORCED_INFO = [
#String, Photo function, String
["Photo taken at ", "getLocationName", ""],
["Photo of ", "getEvents[0].getName", ""]
]
# ********************
# *** SYSTEM STUFF ***
# ********************
# DON'T change the values here!
EMPTY_COLLECTION = -2
CANCEL_SELECTION = -1
end
###############################
###############################
## ##
## DON'T GO PAST HERE! ##
## ##
###############################
###############################
#==============================================================================
# ** Game_Map
#------------------------------------------------------------------------------
# Update Game_Map to allow access to map name.
#==============================================================================
class Game_Map
attr_reader :name
alias mapname_setup setup
def setup(map_id)
mapname_setup(map_id)
data = load_data("Data/MapInfos.rvdata")
@name = data[map_id].name
end
end
#==============================================================================
# ** Game_Event
#------------------------------------------------------------------------------
# Update Game_Event to allow access to name and test it against tags.
#==============================================================================
class Game_Event < Game_Character
attr_accessor :event
# Return the full name of the Event.
def getName
return @event.name
end
# Removes any occurence of photo tags from name and returns it.
def getNameWithoutTags
trimmed_name = @event.name
trimmed_name = trimmed_name.gsub(/\s*\[[0-9]*\]\s*/){""}
trimmed_name = trimmed_name.gsub(/\s*\[NP\]\s*/){""}
return trimmed_name
end
# Do the tags in this Event's name allow it to be stored in a photo?
def allowPhoto
# [NP] tag means NEVER record event's info...
if(@event.name.scan(/\[NP\]/).size > 0)
return false
end
# Go through switch tags and check if the switches referenced are ON.
result = true
switch_arr = []
@event.name.scan(/\[[0-9]*\]/){|s| switch_arr.push(s[1, s.length - 2].to_i)}
for switch_id in switch_arr
if($game_switches[switch_id] == false)
result = false
end
end
return result
end
end
#==============================================================================
# ** Game_Party
#------------------------------------------------------------------------------
# Update Game_Party to include access to photo data.
#==============================================================================
class Game_Party < Game_Unit
alias selfeenaphoto_init initialize
def initialize
@photos = []
if(SFPhotoModule::PHOTO_COUNT_VAR >= 0)
$game_variables[SFPhotoModule::PHOTO_COUNT_VAR] = 0
end
if(SFPhotoModule::HAS_PHOTO_SWITCH >= 0)
$game_switches[SFPhotoModule::HAS_PHOTO_SWITCH] = false
end
selfeenaphoto_init
end
# Number of photos currently in collection.
def getPhotoCount
return @photos.length
end
# Is the photo collection full?
def photoAlbumFull
return (@photos.length == SFPhotoModule::MAX_PHOTOS)
end
# Return photo at index i
# Use getPhotoCount to avoid out-of-bounds errors!
def getPhoto(i)
return @photos[i]
end
# Destroy photo at index i
# Use getPhotoCount to avoid out-of-bounds errors!
def delPhoto(i)
@photos.delete_at(i)
if(SFPhotoModule::PHOTO_COUNT_VAR >= 0)
$game_variables[SFPhotoModule::PHOTO_COUNT_VAR] = @photos.length
end
if(SFPhotoModule::HAS_PHOTO_SWITCH >= 0)
$game_switches[SFPhotoModule::HAS_PHOTO_SWITCH] = (@photos.length > 0)
end
end
# Add a new photo to the collection. If the collection is full,
# the photo at index 0 is destroyed to make room.
def addPhoto(p)
if(@photos.length == SFPhotoModule::MAX_PHOTOS)
@photos.delete_at(0)
end
@photos.push(p)
if(SFPhotoModule::PHOTO_COUNT_VAR >= 0)
$game_variables[SFPhotoModule::PHOTO_COUNT_VAR] = @photos.length
end
if(SFPhotoModule::HAS_PHOTO_SWITCH >= 0)
$game_switches[SFPhotoModule::HAS_PHOTO_SWITCH] = (@photos.length > 0)
end
end
end
#==============================================================================
# ** SelFeenaPhoto
#------------------------------------------------------------------------------
# Class encapsulating photo data.
#==============================================================================
class SelFeenaPhoto
def initialize
# Variables used to check for forced photo image...
@forcedeventid = 0
@forcedpicture = ""
# Save Map ID and name...
@map_id = $game_map.map_id
@map_name = $game_map.name
# Save player position and direction...
@player_x = $game_player.x
@player_y = $game_player.y
@player_dir = $game_player.direction
# Save xy position of photo (top-left corner) as map coordinates
@photo_pos_x = $game_map.display_x / 256
@photo_pos_y = $game_map.display_y / 256
# What events have we captured in the photo?
arr = []
for x in @photo_pos_x..(@photo_pos_x + 16)
if(x >= $game_map.width) # Horizontal loop fix
x -= $game_map.width
end
for y in @photo_pos_y..(@photo_pos_y + 12)
if(y >= $game_map.height) # Vertical loop fix
y -= $game_map.height
end
arr = arr + $game_map.events_xy(x, y)
end
end
# Whittle down events to those that are valid...
ev_arr = []
for e in arr
if(e.allowPhoto == true)
ev_arr.push(e)
end
end
# Check for image forcing.
processEvents("[FORCEPHOTO]", "self.forceImage ", "[/FORCEPHOTO]", ev_arr)
# Store event data. If a forced image has been triggered,
# only store information about that event.
@event_data = []
for i in ev_arr
if (@forcedeventid == 0) or (@forcedeventid == i.id)
# Event ID...
ev_id = i.id
# Event name...
ev_name = i.getNameWithoutTags
# Event position...
ev_pos = [i.x, i.y]
# Event self-switch info...
i_swa = $game_self_switches[[$game_map.map_id, i.id, "A"]]
i_swb = $game_self_switches[[$game_map.map_id, i.id, "B"]]
i_swc = $game_self_switches[[$game_map.map_id, i.id, "C"]]
i_swd = $game_self_switches[[$game_map.map_id, i.id, "D"]]
ev_switches = [i_swa, i_swb, i_swc, i_swd]
new_ev = SelFeenaPhotoEvent.new(ev_id, ev_name, ev_pos, ev_switches)
@event_data.push(new_ev)
end
end
# Store image. Either a screenshot or the forced image.
if(@forcedeventid == 0)
@image_data = Graphics.snap_to_bitmap
else
@image_data = Cache.picture(@forcedpicture).clone
end
# Postprocessing. Process either ALL events or just the event
# that has forced the photo image.
if(@forcedeventid == 0)
processEvents("[POSTPHOTO]", "$game_map.interpreter.",
"[/POSTPHOTO]", ev_arr)
else
fev = $game_map.events[@forcedeventid]
processEvent(fev, "[POSTPHOTO]", "$game_map.interpreter.", "[/POSTPHOTO]")
end
end
# Remove Bitmap. Go on, shoo! :3
def dispose
@image_data.dispose
end
# Is this photo a forced image ([FORCEPHOTO] tag)?
def isForcedImage
return (@forcedeventid != 0)
end
# Loop through Events and perform processing if tag is present in Page.
# When done, update to reflect changes.
def processEvents(tag, eval_str, endtag, ev_a)
for ev in ev_a
processEvent(ev, tag, eval_str, endtag)
end
$game_map.refresh
end
# Perform processing for a specific Event based on the tag given.
def processEvent(my_event, my_tag, my_str, my_endtag)
for i in 0...my_event.list.size
if (my_event.list[i].code == 108)
if (my_event.list[i].parameters == [my_tag])
linecount = i + 1
command = my_event.list[linecount].parameters
until (command == [my_endtag])
eval(my_str + command[0] + ", my_event")
linecount += 1
command = my_event.list[linecount].parameters
end
return
end
end
end
end
# Determine if image should be a specified bitmap.
def forceImage(x, y, width, height, dir_arr, pic_name, centred, ev)
# Is the rectangle's position based on the event's?
if(centred == true)
x = ev.x + x
y = ev.y + y
end
# Go through rectangle, with corrections for looping maps.
for ix in x..(x + width - 1)
if(ix >= $game_map.width) and ($game_map.loop_horizontal?)
ix -= $game_map.width
end
for iy in y..(y + height - 1)
if(iy >= $game_map.height) and ($game_map.loop_vertical?)
iy -= $game_map.height
end
# We have a match inside our rectangle. Now, what about direction?
if(@player_x == ix) and (@player_y == iy)
if(dir_arr.include?(@player_dir))
@forcedeventid = ev.id
@forcedpicture = pic_name
end
return
end
end
end
end
# Return image bitmap.
def getImage
return @image_data
end
# Set image bitmap.
def setImage(pic)
@image_data = pic
end
# Destroy image bitmap.
def delImage
@image_data.dispose
@image_data = nil
end
# Return ID of map where photo was taken.
def getLocationID
return @map_id
end
# Return name of map where photo was taken.
def getLocationName
return @map_name
end
# Return player position when photo was taken.
# Format = [ Map X position, Map Y position, Direction player was facing ]
def getPlayerPosition
return [@player_x, @player_y, @player_dir]
end
# Return position of photo's top-left corner on map.
# Format = [ Photo X position, Photo Y position ]
def getPhotoPosition
return [@photo_pos_x, @photo_pos_y]
end
# Number of SelFeenaPhotoEvents caught on camera.
def getEventCount
return @event_data.length
end
# Does photo have info about a SelFeenaPhotoEvent with a specific ID?
def hasEventWithID(target_id)
result = false
for i in @event_data
if i.getID == target_id
result = true
end
end
return result
end
# How many SelFeenaPhotoEvents with a specific name are in the photo?
def countEventsWithName(target_name)
result = 0
for i in @event_data
if i.getName == target_name
result += 1
end
end
return result
end
# Return an array of SelFeenaPhotoEvents with a specific name. May be empty.
def getEventsWithName(target_name)
result = []
for i in @event_data
if i.getName == target_name
result.push(i)
end
end
return result
end
# Return SelFeenaPhotoEvent with a specific ID.
# If there is no SelFeenaPhotoEvent with that ID, returns nil.
def getEventWithID(target_id)
result = nil
for i in @event_data
if i.getID == target_id
result = i
end
end
return result
end
# Return all SelFeenaPhotoEvents in photo as an array.
def getEvents
return @event_data
end
end
#==============================================================================
# ** SelFeenaPhotoEvent
#------------------------------------------------------------------------------
# Class encapsulating info about an event captured in a photo.
#==============================================================================
class SelFeenaPhotoEvent
def initialize(e_id, e_name, e_pos, e_switches)
@id = e_id
@name = e_name
@position = e_pos
@switches = e_switches
end
# Event ID.
def getID
return @id
end
# Event name.
def getName
return @name
end
# Return MAP position of Event.
# Format = [ Event X position, Event Y position ]
def getPosition
return @position
end
# Return Self-Switch information recorded for Event:
# 0 : Self-Switch A
# 1 : Self-Switch B
# 2 : Self-Switch C
# 3 : Self-Switch D
def getSwitch(s)
return @switches[s]
end
# Return recorded Self-Switch information for Event.
# Format = [ A, B, C, D ]
def getSwitches
return @switches
end
end
#==============================================================================
# ** Window_PhotoSelect
#------------------------------------------------------------------------------
# This window displays photos from the party's collection.
#==============================================================================
class Window_PhotoSelect < Window_Base
def initialize(x, y, w, h, sa = true)
super(x, y, w, h)
@showarrows = sa
# If the party's collection is empty, then set index to error code.
if($game_party.getPhotoCount == 0)
@index = SFPhotoModule::EMPTY_COLLECTION
else
@index = 0
end
refresh
end
# Return index of the currently displayed photo.
def getIndex
return @index
end
# Select the previous photo in collection (wraps around).
def prevPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
oldindex = @index
@index -= 1
# Wraparound.
if (@index < 0)
@index = $game_party.getPhotoCount - 1
end
# Sound if new photo selected.
if(@index != oldindex)
Sound.play_cursor
end
end
end
# Select the next photo in collection (wraps around).
def nextPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
oldindex = @index
@index += 1
# Wraparound.
if (@index == $game_party.getPhotoCount)
@index = 0
end
# Sound if new photo selected.
if(@index != oldindex)
Sound.play_cursor
end
end
end
# Display a photo from party's collection.
def refresh
self.contents.clear
# Check if we're dealing with an empty collection.
if(@index == SFPhotoModule::EMPTY_COLLECTION)
# Display empty collection image.
if(SFPhotoModule::EMPTY_PICTURE.length > 0)
scaled_rect = Rect.new(0, 0, width - 32, height - 32)
pic_rect = Rect.new(0, 0, 544, 416)
pic = Cache.picture(SFPhotoModule::EMPTY_PICTURE)
self.contents.stretch_blt(scaled_rect, pic, pic_rect)
end
else
# Display scaled photo image.
scaled_rect = Rect.new(0, 0, width - 32, height - 32)
pic_rect = Rect.new(0, 0, 544, 416)
photo = $game_party.getPhoto(@index)
self.contents.stretch_blt(scaled_rect, photo.getImage, pic_rect)
# Display arrows if collection larger than 1
if($game_party.getPhotoCount > 1) and (@showarrows == true)
l_rect = Rect.new(80, 25, 8, 14)
r_rect = Rect.new(104, 25, 8, 14)
self.contents.blt(0, (height / 2) - 23, windowskin, l_rect)
self.contents.blt(width - 40, (height / 2) - 23, windowskin, r_rect)
end
end
end
end
#==============================================================================
# ** Window_PhotoPreview
#------------------------------------------------------------------------------
# This window displays a photo passed to it on instantiation.
#==============================================================================
class Window_PhotoPreview < Window_Base
def initialize(x, y, w, h, p, newp)
@preview = p
@newphoto = newp
super(x, y, w, h)
refresh
end
# Display the photo.
def refresh
self.contents.clear
# Display scaled photo image.
scaled_rect = Rect.new(0, 0, width - 32, height - 32)
pic_rect = Rect.new(0, 0, 544, 416)
self.contents.stretch_blt(scaled_rect, @preview.getImage, pic_rect)
# Display 'new image' tag.
if(SFPhotoModule::NEW_PICTURE.length > 0) and (newp == true)
pic_x = SFPhotoModule::NEW_POS[0]
pic_y = SFPhotoModule::NEW_POS[1]
pic = Cache.picture(SFPhotoModule::NEW_PICTURE)
pic_rect = Rect.new(0, 0, pic.width, pic.height)
self.contents.blt(pic_x, pic_y, pic, pic_rect)
end
end
end
#==============================================================================
# ** Window_PhotoStrip
#------------------------------------------------------------------------------
# This displays a list of all photos in a strip.
#==============================================================================
class Window_PhotoStrip < Window_Base
def initialize
super(0, 0, 104, 344)
# If the party's collection is empty, then set index to error code.
if($game_party.getPhotoCount == 0)
@index = SFPhotoModule::EMPTY_COLLECTION
else
@index = 0
end
@startindex = 0
refresh
end
# Update cursor position.
def prevPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
# Update cursor.
@index -= 1
flip = false
if(@index < 0)
@index = $game_party.getPhotoCount - 1
flip = true
end
# Update strip display.
if(flip == true)
if($game_party.getPhotoCount - 5 < 0)
@startindex = 0
else
@startindex = $game_party.getPhotoCount - 5
end
else
if(@index < @startindex)
@startindex -= 1
end
end
refresh
end
end
# Update cursor position.
def nextPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
# Update cursor.
@index += 1
flip = false
if(@index == $game_party.getPhotoCount)
@index = 0
flip = true
end
# Update strip display.
if(flip == true)
@startindex = 0
else
if(@index > @startindex + 4)
@startindex += 1
end
end
refresh
end
end
# Calculate how far to draw from current @startindex value.
def getDrawLimit
if(@startindex + 4 <= $game_party.getPhotoCount - 1)
return @startindex + 4
else
return $game_party.getPhotoCount - 1
end
end
# Display photo strip.
def refresh
self.contents.clear
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
# Draw cursor.
cursor_rect = Rect.new(0, 10 + (@index - @startindex) * 60, 72, 52)
self.contents.font.color = normal_color
self.contents.fill_rect(cursor_rect, self.contents.font.color)
# Draw strip.
for i in @startindex..getDrawLimit
pic = $game_party.getPhoto(i).getImage
scaled_rect = Rect.new(2, 10 + (i - @startindex) * 60, 68, 52)
pic_rect = Rect.new(0, 0, 544, 416)
self.contents.stretch_blt(scaled_rect, pic, pic_rect)
end
# Draw up / down arrows if necessary.
if($game_party.getPhotoCount > 5)
u_rect = Rect.new(89, 17, 14, 8)
d_rect = Rect.new(89, 40, 14, 8)
self.contents.blt((width / 2) - 23, 0, windowskin, u_rect)
self.contents.blt((width / 2) - 23, height - 40, windowskin, d_rect)
end
end
end
end
#==============================================================================
# ** Window_PhotoText
#------------------------------------------------------------------------------
# This window displays info about a photo.
#==============================================================================
class Window_PhotoText < Window_Base
def initialize
super(0, 344, 544, 72)
@info = 0
# If the party's collection is empty, then set index to error code.
if($game_party.getPhotoCount == 0)
@index = SFPhotoModule::EMPTY_COLLECTION
else
@index = 0
end
refresh
end
# Set the window to display info about the previous photo.
def prevPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
oldindex = @index
@index -= 1
# Wraparound.
if (@index < 0)
@index = $game_party.getPhotoCount - 1
end
# Reset info index if new photo selected.
if(@index != oldindex)
@info = 0
end
refresh
end
end
# Set the window to display info about the previous photo.
def nextPhoto
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
oldindex = @index
@index += 1
# Wraparound.
if (@index == $game_party.getPhotoCount)
@index = 0
end
# Reset info index if new photo selected.
if(@index != oldindex)
@info = 0
end
refresh
end
end
# Get limit of info index for the current photo
def getInfoSize
if(@index != SFPhotoModule::EMPTY_COLLECTION)
if($game_party.getPhoto(@index).isForcedImage)
return SFPhotoModule::FORCED_INFO.length
else
return SFPhotoModule::SNAP_INFO.length
end
else
return 0
end
end
# Display previous piece of info about the photo
def prevInfo
# Only if there is info to display.
if(getInfoSize != 0)
oldinfo = @info
@info -= 1
# Wraparound.
if (@info < 0)
@info = getInfoSize - 1
end
# Play sound if new info selected.
if(@info != oldinfo)
Sound.play_cursor
end
refresh
end
end
# Display next piece of info about the photo
def nextInfo
# Only if there is info to display.
if(getInfoSize != 0)
oldinfo = @info
@info += 1
# Wraparound.
if (@info == getInfoSize)
@info = 0
end
# Play sound if new info selected.
if(@info != oldinfo)
Sound.play_cursor
end
refresh
end
end
def refresh
self.contents.clear
# Only if there are photos in collection.
if(@index != SFPhotoModule::EMPTY_COLLECTION)
# Only if there is info to display.
if(getInfoSize != 0)
info_arr = []
if($game_party.getPhoto(@index).isForcedImage)
info_arr = SFPhotoModule::FORCED_INFO[@info]
else
info_arr = SFPhotoModule::SNAP_INFO[@info]
end
info_str = info_arr[0]
info_str = info_str + eval("$game_party.getPhoto(@index)." + info_arr[1])
info_str = info_str + info_arr[2]
self.contents.font.color = normal_color
self.contents.draw_text(16, 8, width, WLH, info_str, 0)
# Display arrows if info array larger than 1.
if(getInfoSize > 1)
l_rect = Rect.new(80, 25, 8, 14)
r_rect = Rect.new(104, 25, 8, 14)
self.contents.blt(0, (height / 2) - 23, windowskin, l_rect)
self.contents.blt(width - 40, (height / 2) - 23, windowskin, r_rect)
end
end
else
self.contents.font.color = normal_color
self.contents.draw_text(16, 8, width, WLH, SFPhotoModule::EMPTY_MSG, 0)
end
end
end
#==============================================================================
# ** Scene_Photos
#------------------------------------------------------------------------------
# Display photographs taken by the player.
#==============================================================================
class Scene_Photos < Scene_Base
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
end
#--------------------------------------------------------------------------
# * Start processing
#--------------------------------------------------------------------------
def start
super
create_menu_background
@photo_window = Window_PhotoSelect.new(104, 0, 440, 344, false)
@photo_strip = Window_PhotoStrip.new
@text_window = Window_PhotoText.new
end
#--------------------------------------------------------------------------
# * Termination Processing
#--------------------------------------------------------------------------
def terminate
super
dispose_menu_background
@photo_window.dispose
@photo_strip.dispose
@text_window.dispose
end
#--------------------------------------------------------------------------
# * Return to Original Screen
#--------------------------------------------------------------------------
def return_scene
$scene = Scene_Menu.new
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
update_menu_background
@photo_window.update
@text_window.update
if Input.trigger?(Input::UP)
@photo_window.prevPhoto
@photo_window.refresh
@photo_strip.prevPhoto
@text_window.prevPhoto
end
if Input.trigger?(Input::DOWN)
@photo_window.nextPhoto
@photo_window.refresh
@photo_strip.nextPhoto
@text_window.nextPhoto
end
if Input.trigger?(Input::LEFT)
@text_window.prevInfo
end
if Input.trigger?(Input::RIGHT)
@text_window.nextInfo
end
if Input.trigger?(Input::B)
Sound.play_cancel
return_scene
end
super
end
end
#==============================================================================
# ** Game_Interpreter
#------------------------------------------------------------------------------
# Add functions for photographs.
#==============================================================================
class Game_Interpreter
# Select a photo from the party's collection. Returns the index.
# Selecting from empty collection returns SFPhotoModule::EMPTY_COLLECTION
# Cancelling will return SFPhotoModule::CANCEL_SELECTION
def sfp_choose_photo(choice_str, allowcancel)
# Create photo display and selection window...
photo_window = Window_PhotoSelect.new(120, 44, 304, 240)
choice_arr = []
choice_arr.push(choice_str)
if(allowcancel == true)
choice_arr.push("Cancel")
end
confirm_window = Window_Command.new(photo_window.width, choice_arr)
confirm_window.x = photo_window.x
confirm_window.y = photo_window.y + photo_window.height
# Process input...
while true
Graphics.update
Input.update
confirm_window.update
photo_window.update
if Input.trigger?(Input::LEFT)
photo_window.prevPhoto
photo_window.refresh
end
if Input.trigger?(Input::RIGHT)
photo_window.nextPhoto
photo_window.refresh
end
break if Input.trigger?(Input::C)
end
Input.update
# Clean up...
picchoice = photo_window.getIndex
choice = confirm_window.index
photo_window.dispose
confirm_window.dispose
# Return selection or cancel code...
if(choice == 0)
Sound.play_decision
return picchoice
else
Sound.play_cancel
return SFPhotoModule::CANCEL_SELECTION
end
end
# 1) Take a photo.
# 2) Show the photo, with options to save or cancel.
# 3) Save photo, or discard.
def sfp_save_photo
# Create photo...
newphoto = SelFeenaPhoto.new
# Create and position windows...
photo_window = Window_PhotoPreview.new(120, 44, 304, 240, newphoto, true)
confirm_window = Window_Command.new(photo_window.width, ["Save", "Cancel"])
confirm_window.x = photo_window.x
confirm_window.y = photo_window.y + photo_window.height
# Processing...
while true
Graphics.update
Input.update
photo_window.update
confirm_window.update
break if Input.trigger?(Input::C)
end
Input.update
# Clean up...
choice = confirm_window.index
photo_window.dispose
confirm_window.dispose
# Save photo, or dispose of it...
if(choice == 0)
Sound.play_decision
# Overwrite photo or just add to collection?
if($game_party.photoAlbumFull == true)
overwrite_index = sfp_choose_photo("Overwrite", true)
# Photo selected, or cancel?
if(overwrite_index >= 0)
$game_party.delPhoto(overwrite_index)
$game_party.addPhoto(newphoto)
else
newphoto.dispose
end
else
$game_party.addPhoto(newphoto)
end
else
Sound.play_cancel
newphoto.dispose
end
end
end
#==============================================================================
# ** Scene_File
#------------------------------------------------------------------------------
# It's necessary to overwrite these two functions as VX doesn't like
# writing Bitmap objects to file. Somewhat annoying, but whatever.
#
# Instead the photo images are saved as png files, and loaded up when
# the player loads a game. Example file format, in case you wanted to know...
#
# S0P7.png <= Photo number 7, Save slot 0.
#
# This means a bit of a pause when saving/loading, but not much.
#==============================================================================
class Scene_File < Scene_Base
#--------------------------------------------------------------------------
# * Write Save Data
# file : write file object (opened)
#--------------------------------------------------------------------------
alias selfeenaphoto_save write_save_data
alias selfeenaphoto_read read_save_data
def write_save_data(file)
# Save photos to file, and temporarily destroy Bitmaps.
i = 0
tempphoto_arr = []
while (i < $game_party.getPhotoCount)
pic = $game_party.getPhoto(i).getImage.clone
tempphoto_arr.push(pic)
pic.make_png("S" + @index.to_s + "P" + i.to_s, "Graphics/Photos/")
$game_party.getPhoto(i).delImage
i += 1
end
# Normal save stuff.
selfeenaphoto_save(file)
# Put image data back in photos.
i = 0
for p in tempphoto_arr
$game_party.getPhoto(i).setImage(p)
i += 1
end
end
#--------------------------------------------------------------------------
# * Read Save Data
# file : file object for reading (opened)
#--------------------------------------------------------------------------
def read_save_data(file)
# Normal load stuff.
selfeenaphoto_read(file)
# Load images from files into photos.
i = 0
while(i < $game_party.getPhotoCount)
pic = Bitmap.new("Graphics/Photos/S" + @index.to_s + "P" + i.to_s)
$game_party.getPhoto(i).setImage(pic)
i += 1
end
end
end








