06-09-2025, 09:16 PM
(This post was last modified: 11 hours ago by DerVVulfman.)
Animated Message Profiles VX
Version: 1.1
Version: 1.1
Introduction
This is an add-on for the default message systems, or for those custom message systems that are compliant. It permits the game developer to present an image behind the default message window, and even allow for the image to display cel animation properties.
Essentially, one can present characters that appear to be talking.
Script
Instructions/Configuration
Code:
#==============================================================================
# ** Animated Message Profiles VX
#------------------------------------------------------------------------------
# by DerVVulfman
# Version 1.1
# 06-14-2025 (MM/DD/YYYY)
# RGSS2 / RPGMaker VX
#==============================================================================
#
# > INSTRUCTION / CONFIGURATION PAGE <
#
#==============================================================================
#
# INTRODUCTION:
# =============
#
# This is an add-on for the default message systems, or for those custom mes-
# sage systems that are compliant. It permits the game developer to present
# an image behind the default message window, and even allow for the image to
# display cel animation properties.
#
# Essentially, one can present characters that appear to be talking.
#
#
#------------------------------------------------------------------------------
#
# INSTALLATION:
# =============
#
# At bare minimum, place both the Instruction / Configuration and the Engine
# scripts below Scene_Debug and above Main.
#
# The configuration page defines the actual profiles that are displayed, the
# location where they are shown, and if they are indeed animated.
#
#
#------------------------------------------------------------------------------
#
# CONFIGURATION SETTINGS:
# =======================
#
# The configuration section has two areas to adjust, the first is the setting
# that determines if the profile shows when the message 'begins' to show or
# waits until the message display is complete, and the second is the list of
# profiles themselves. These profiles are the images or renders of the char-
# acters that appear beind the message window, whether animated or not.
#
# Profiles are defined within a hash array. Each of these profiles are iden-
# tified by a key, a string value that can be easily referenced. And each of
# these profiles points to an array indicating where the profiles are placed,
# the speed in which the profiles circulate between animated frames, and the
# list of one (or more) profile animation frames.
#
# Syntax: DATA[key] = [ xpos, ypos, speed, repeat img, img, img... img ]
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# * key: A string (in quotes) that separates it from other profiles.
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# * xpos: X-Position or Coordinates where the sprite(s) will draw.
# * ypos: Y-Position or Coordinates where the sprite(s) will draw.
# * speed: (in frames per second) The number of frames between each image.
# * repeat: (a true/false value) Indicating if multiple images repeat
# * img: An image file (or set of file) in the Graphics\Pictures folder.
#
# You can show one single image behind the message box with the following
# example:
# DATA["LunarSmile"] = [50,120,4,true'actor1']
# -- or --
# DATA["LunarSmile"] = [50,120,4,true'actor1']
#
# Or, you can render a profile that draws three images in the pictures folder
# in rapid succession like so:
#
# DATA["ZeldaIsLaughing"] = [50,120,4, true 'actor1','actor1a','actor1b']
# -- if the animation continues until closed --
# DATA["ZeldaIsLaughing"] = [50,120,4, false 'actor1','actor1a','actor1b']
# -- if the animation ends after all three images have been shown --
#
#
#------------------------------------------------------------------------------
#
# MESSAGE WINDOW COMMANDS:
# ========================
#
# DISPLAYING THE PROFILE:
#
# You may display a profile by using the Message Code: \AB[key].
#
# While the key must have quotes when defined in the module, the message
# code's key value does not use quotes.
#
# EX: \ab[ZeldaIsLaughing]That is so funny!!!
#
# The above example would display an animated profile with the defined
# profile name of 'ZeldaIsLaughing' with text following immediately.
#
# Alternately, you may use a script call prior to the display of the
# message with the 'set_profile' command like so:
# @>Script: set_profile("ZeldaIsLaughing")
# @>Text: That is so funny!!!!"
#
# - - - - -
#
# HOLDING A PROFILE PRESENT
#
# Normally, the image vanishes when you close a window. However, there may be
# instances where a character is delivering multiple message windows of text
# and you want the image to remain for the very next message.
#
# For this, you need to apply the 'hold_profile' script call on the message
# the contains the current profile. This is to prevent it from erasing the
# profile before the message ends. This may appear like so:
#
# @>Script: set_profile("ZeldaIsLaughing")
# @>Script: hold_profile
# @>Text: That is so funny!!!!"
# @>Text: I am just laughing uncontrollably!!!!"
#
# This example would use the same profile image for both messages. However,
# the below exaple would have its third message window without the profile.
#
# @>Script: set_profile("ZeldaIsLaughing")
# @>Script: hold_profile
# @>Text: That is so funny!!!!"
# @>Text: I am just laughing uncontrollably!!!!"
# @>Text: Okay, I'm done now."
#
# To continue with the image remaining in place, you must use the hold_profile
# command before each message that you want to PREVENT the profile's erasure.
#
# - - - - -
#
# SWAPPING A PROFILE PRESENT
#
# For use in tandem with the above 'hold_profile' call, this is a special
# command that lets you switch from one profile set to another without the
# profile sprite erasing. Unlike the hold_profile call, the 'swap_profile'
# is run right before the new message is shown, and used in tandem with the
# application of a new profile like so:
#
# @>Script: set_profile("ZeldaIsLaughing")
# @>Script: hold_profile
# @>Text: That is so funny!!!!"
# @>Script: swap_profile
# @>Text: \AB[ZeldaCry]Waaahhh!"
#
# This would provide a more seamless change in character behavior between
# messages without the character needing to vanish and be redrawn.
#
#
#------------------------------------------------------------------------------
#
# PAPERDOLL/BITMAP COMPATABILITY:
# ===============================
#
# paper doll (noun)
# 1. A paper or cardboard representation of a person usually in two dimen-
# sions for children to play with.
# 2. Figures cut out of paper or thin card, with separate clothes, also made
# of paper, that are usually held onto the dolls by paper folding tabs.
#
# Sometimes called a Visual Equipment script, a paperdoll system is one that
# can change a character's appearance based on the gear attached.
#
# While Animated Message Profiles does not have a built-in paperdoll system,
# it contains an area where changes to a profile's appearance may be made. It
# is within the Window_Message class, and is a specifically defined method to
# grant a would-be scripter access to the bitmaps to adjust.
#
# In short, I made a method a scripter can mess with. ^_^
#
# Line # 331: update_profile_reader
#
#
#------------------------------------------------------------------------------
#
# NOTES ON THE EXAMPLE CONFIG:
# ============================
#
# The two profiles are using images found in the 'Graphics\Profiles' folder.
# And in that folder, there are only two files, "Ikuno1.png" & "Ikuno2.png".
#
# You use multiple image files to creat an animation, and at least one file
# to create a portrait if static and not animated.
#
# The first profile is that of "Ikuno". The profile will appear at coordi-
# nates 80,140 which would line up nice with the default message window if
# it is at the bottom of the screen. The speed is set to 4, which means the
# individual cels change after 4 frames (in framerate). It is set to false,
# this indicates it will only cycle through all the animation cels once. And
# it only has two images: "Ikuno1.png" and "Ikuno2.png". This means that it
# only plays the two images in sequence once... and stops.
#
# The second profile is that of "Ikuno2". The profile will appear at coordi-
# nates 80,140 the same as the first. The speed is set to 0, however, this
# is an illegal value as the animation speed rate cannot go below '1'. The
# repeat value is set to 'true' so it will play every animation frame in its
# set over and over aggain. And it lists "Ikuno1", "Ikuno2" and "Ikuno1".
#
# The third profile is that of "Ikuno3". And this one is merely a static,
# one frame/image profile. Ergo, it will not appear animated.
#
# - - - - -
#
# Example I used with the three profile settings:
#
#
# @>Script: hold_profile
# @>Text: \AB[Ikuno]What? Yeah, my mouth isn't moving.
# @>Script: swap_profile
# @>Text: \AB[Ikuno2]Yap Yap Yap!
# @>Text: Peekaboo... you don't see me
# @>Script: set_profile("Ikuno3")
# @>Text: Now you do.
#
#
#------------------------------------------------------------------------------
#
# VERSION HISTORY:
# ================
# YYYY MM DD
# 2025-06-09 - Original release
# 2025-06-14 - Fix: Disposed portrait sprite issue and increased z-depth
#
#
#------------------------------------------------------------------------------
#
# COMPATABILITY:
# ==============
#
# Designed for message systems compliant with RPGMaker VX's default system.
# All default scripts aliased.
#
#
#==============================================================================
#
# TERMS AND CONDITIONS:
# =====================
#
# Free to use, even in commercial projects. However, I will need some form
# of due credit.
#
#
#==============================================================================
module Profiles
# --------------------------------------------------------------------------
DATA = {} # Do Not Touch
# --------------------------------------------------------------------------
# Do profiles show when beginning to render?
# ==========================================
SHOW_ON_OPENING = false
# PROFILE LIST
#
# Profile w Key X Y Spd Repeat Animation frames...
# =============== ==== ==== ==== ====== =============================
DATA["Ikuno"] = [ 80, 140, 4, false, 'Ikuno1', 'Ikuno2' ]
DATA["Ikuno2"] = [ 80, 140, 0, true, 'Ikuno1', 'Ikuno2', 'Ikuno1' ]
DATA["Ikuno3"] = [ 80, 140, 0, false, 'Ikuno2' ]
end
Main Code
Code:
#==============================================================================
# ** Animated Message Profiles VX
#------------------------------------------------------------------------------
# by DerVVulfman
# Version 1.1
# 06-14-2025 (MM/DD/YYYY)
# RGSS2 / RPGMaker VX
#==============================================================================
#
# > MAIN SYSTEM PAGE <
#
#==============================================================================
#==============================================================================
# ** Cache
#------------------------------------------------------------------------------
# This module loads each of graphics, creates a Bitmap object, and retains it.
# To speed up load times and conserve memory, this module holds the created
# Bitmap object in the internal hash, allowing the program to return
# preexisting objects when the same bitmap is requested again.
#==============================================================================
module Cache
#------------------------------------------------------------------------
# * Profile image
# filename : filename of the cached bitmap
#------------------------------------------------------------------------
def self.profiles(filename)
#
begin
self.load_bitmap("Graphics/Profiles/", filename)
rescue
self.load_bitmap("Graphics/Profiles/", "")
end
#
end
end
#==============================================================================
# ** Game_System
#------------------------------------------------------------------------------
# This class handles system-related data. Also manages vehicles and BGM, etc.
# The instance of this class is referenced by $game_system.
#==============================================================================
class Game_System
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :profile_name # Name of profile image data
attr_accessor :profile_hold # Profile do not erase flag
attr_accessor :profile_swap
#--------------------------------------------------------------------------
# * Alias Listings
#--------------------------------------------------------------------------
alias msg_profiles_game_system_initialize initialize
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
#
msg_profiles_game_system_initialize
@profile_name = nil
@profile_hold = false
@profile_swap = false
#
end
end
#==============================================================================
# ** Game_Interpreter
#------------------------------------------------------------------------------
# An interpreter for executing event commands. This class is used within the
# Game_Map, Game_Troop, and Game_Event classes.
#==============================================================================
class Game_Interpreter
#--------------------------------------------------------------------------
# * Set Message Profile outside of Show Text box
# key : key as defined in the Profiles Module
#--------------------------------------------------------------------------
def set_profile(key=nil)
#
if key.nil? # If no valid key supplied
$game_system.profile_name = nil # ..set erased profile name
return # ..and exit method.
end
unless Profiles::DATA.has_key?(key) # If no valid profile given
$game_system.profile_name = nil # ..set erased profile name
return # ..and exit method.
end
$game_system.profile_name = key # Set the profile name
#
end
#--------------------------------------------------------------------------
# * Set image hold/freeze to use in next message
#--------------------------------------------------------------------------
def hold_profile
#
$game_system.profile_hold = true # Set the profile hold flag
#
end
#--------------------------------------------------------------------------
# * Set sprite frozent to allow profile image and animation swapping
#--------------------------------------------------------------------------
def swap_profile
#
$game_system.profile_swap = true # Set the profile swap flag
#
end
end
#==============================================================================
# ** Window_Message
#------------------------------------------------------------------------------
# This message window is used to display text.
#==============================================================================
class Window_Message < Window_Selectable
#--------------------------------------------------------------------------
# * Alias Listings
#--------------------------------------------------------------------------
alias msg_profiles_windows_initialize initialize
alias msg_profiles_windows_dispose dispose
alias msg_profiles_windows_update update
alias msg_profiles_windows_csc convert_special_characters
alias msg_profiles_windows_terminate_message terminate_message
#--------------------------------------------------------------------------
# * Original methods Aliased
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
#
msg_profiles_windows_initialize # Run the original method
initialize_message_profile # Create profile data
#
end
#--------------------------------------------------------------------------
# * Dispose
#--------------------------------------------------------------------------
def dispose
#
@profile.dispose # Dispose of profile sprite
msg_profiles_windows_dispose # Run the original method
#
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
#
deny_flag = @closing # Set deny flag on closing
unless Profiles::SHOW_ON_OPENING # If opening is denied
deny_flag = true if @opening # ...set flag if also opening
end
unless deny_flag # Unless denied from showing
update_message_profile # Perform update if showing
end
msg_profiles_windows_update # Run the original method
#
end
#--------------------------------------------------------------------------
# * Convert Special Characters
#--------------------------------------------------------------------------
def convert_special_characters
#
convert_special_characters_profile # Perform profile refresh
msg_profiles_windows_csc # Run the original method
#
end
#--------------------------------------------------------------------------
# * Terminate Message
#--------------------------------------------------------------------------
def terminate_message
#
msg_profiles_windows_terminate_message # Run the original method
terminate_message_profile # Terminate profile data
#
end
#--------------------------------------------------------------------------
# * New Content
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
# * Object Initialization : Creation of clear profile data variables
#--------------------------------------------------------------------------
def initialize_message_profile
#
@profile = Sprite.new # Create the profile sprite
@profile.z = self.z - 5 # Set it behind the message
@msgprofile = [] # Create empty filename array
@msgwait_count = 0 # Reset the wait count
@profilerepeat = true # Reset repeat function
#
end
#--------------------------------------------------------------------------
# * Frame Update: Profile display and animation
#--------------------------------------------------------------------------
def update_message_profile
#
unless $game_system.profile_swap # Unless swapping profiles
return if @profilerepeat == false # Exit method on no repeat
end
#
if @msgwait_count > 0 # If a wait count exists
@msgwait_count -= 1 # ..reduce the wait count
return # ..and exit the method
end
#
update_profile_generator # Run the profile generator
#
return if @bitmap.nil? # Exit if not valid bitmap
return if @profile.bitmap.nil? # Exit if no profile bitmap
return if @pattern.nil? # Exit if no defined pattern
return if @sprite_numbers.nil? # Exit if no sprite number set
return if @msgprofile.nil? # Exit if no configed profile
#
@pattern = (@pattern + 1) % @sprite_numbers # Set animation pattern
if @pattern == (@sprite_numbers-1) # If at end of loop
@profilerepeat = @msg_repeat # .. determine if repeating
end
#
sx = @pattern * @cw # Define which image to use
src_rect = Rect.new(sx, 0, @cw, @ch) # Acquire the sprite image
@profile.bitmap.clear # Clear the sprite bitmap
@profile.bitmap.blt(0, 0, @bitmap, src_rect) # Apply the new bitmap
@msgwait_count = @msg_count # Reset the wait count
@profile.visible = true # Show the provile sprite
#
end
#--------------------------------------------------------------------------
# * Update: Generate the Profile Animation Strip
#--------------------------------------------------------------------------
def update_profile_generator
#
return if $game_system.profile_name.nil? # Exit if no profile name
return if $game_system.profile_name == "" # Exit if profile name empty
name = $game_system.profile_name # Get the profile name
#
return unless update_profile_empty? # Exit if exist or is to swap
return if Profiles::DATA.nil? # Exit if no configured data
return unless Profiles::DATA.has_key?(name) # Exit if no profile configed
#
if $game_system.profile_swap == true # If profiles are swapped
@profilerepeat = true # Ensure repeat at restart
end
#
unless $game_system.profile_swap == true # If profiles are not swapped
@profile = Sprite.new # ..make a new profile sprite
end
#
@msgprofile = Profiles::DATA[name] # Acquire configured profile
@profile.z = self.z - 5 # Set profile behind message
@profile.x = @msgprofile[0] # Set x-coordinate of profile
@profile.y = @msgprofile[1] # Set y-coordinate of profile
@msg_count = @msgprofile[2] # Set Message wait count
@msg_repeat = @msgprofile[3] # Set Message repeat flag
files = @msgprofile[4] # Set first file in list
@msg_count = 1 if @msg_count < 1 # Set wait count minimum
@pattern = 0 # Reset profile pattern
#
@sprite_numbers = @msgprofile.size-4 # Get size of configed profile
bitmap = Cache.profiles(files) # Set first bitmap
@cw = bitmap.width # Get profile strip width
@ch = bitmap.height # Get character height
width = @cw * @sprite_numbers # Get single-image width
@bitmap = Bitmap.new(width, @ch) # Create simgle-image bitmap
#
for i in 0...@sprite_numbers # Cycle through sprites
src = update_profile_reader(@msgprofile,i) # Acquire individual sprite
src_rect = Rect.new(0, 0, @cw, @ch) # Acquire sprite rectangle
@bitmap.blt(@cw*i, 0, src, src_rect) # Blit sprite
end
#
@profile.bitmap = Bitmap.new(@cw, @ch) # Create clean profile bitmap
@profile.visible = true # Make visible
$game_system.profile_swap = false # And clear swap flag
#
end
#--------------------------------------------------------------------------
# * Update: Testing if there is no image, or if image is to be replaced.
#--------------------------------------------------------------------------
def update_profile_empty?
#
if $game_system.profile_swap == true # If swapping profiles set
return true # ..Exit method true
end
if @profile.bitmap.nil? # If there is no bitmap
return true # ..Exit method true
end
return false # Exit method false
#
end
#--------------------------------------------------------------------------
# * Update: Acquire each Profile from the Animation Strip
# name : used to identify the profile for possible editing
# index : index within the animation strip
#--------------------------------------------------------------------------
def update_profile_reader(name, index)
#
# Acquire the cached bitmap
src_bitmap = Cache.profiles(@msgprofile[index+4])
# Possible edits to the bitmap may go here... before the returned bitmap
return src_bitmap
#
end
#--------------------------------------------------------------------------
# * Convert Special Characters : Setting profile data name and message
#--------------------------------------------------------------------------
def convert_special_characters_profile
#
@text.gsub!(/\\[Aa][Bb]\[(.*?)\]/) do # Substitute the \ab code
$game_system.profile_name = $1 # ..and set the profile name
""
end
#
end
#--------------------------------------------------------------------------
# * Terminate Message : Resetting of profile
#--------------------------------------------------------------------------
def terminate_message_profile
#
terminate_message_profile_erase # Clear profile image
$game_system.profile_hold = false # Clear profile hold flag
#
end
#--------------------------------------------------------------------------
# * Terminate Message : Erasing of profile image and data
#--------------------------------------------------------------------------
def terminate_message_profile_erase
#
return if $game_system.profile_hold # Clear profile hold
return if @profile.nil? # Exit if no profile sprite
return if @profile.disposed? # Exit if no profile sprite
@profile.visible = false # Make profile sprite hidden
unless @profile.bitmap.nil? # Only if there is a bitmap
@profile.bitmap.dispose # ..dispose of the bitmap
end
@profile.bitmap = nil # Nil out the profile bitmap
@msgprofile = [] # Clear the filename array
$game_system.profile_name = nil # Erase the profile name
@profilerepeat = true
#
end
end
Instructions
Within the main header page / configuration page
Compatibility
Designed to work with the default message system, but should be compliant with most that are structurally similar.
Terms and Conditions
Free to use, even in commercial projects. However, I will need some form of due credit.
Up is down, left is right and sideways is straight ahead. - Cord "Circle of Iron", 1978 (written by Bruce Lee and James Coburn... really...)
Above are clickable links