Animations with Eval
Authors: Wecoc
Version: 1.2
Type: Animation Add-on
Key Term: Misc Add-on
IntroductionBy default on animations you can assign a sound, screen flash, target flash or delete the target in a specific frame.
This script allows to add eval, ie "Call Script" in the animations.
With this you will be able to do things not possible until now.
I also added some shortcuts to make the eval a bit more easy, they are inside the module Skill_Shortcuts and you can create more there.
So basically you can add inside an animation whatever a Script Call supports. On Features I will list only the default 'shortcut' functions made on the script.
Features
- SE play (with no limits on volume and frequence)
- Screen flash, Target flash and Target erase (now you can use variables for parameters)
- Screen Shake
- Screen Tone (with memorize / restore functions)
- Sprite x / y displacement
DemoAnimations with Eval 1.2 (http://share.cherrytree.at/showfile-16370/animations_with_eval_12.zip)
Script#------------------------------------------------------------------------------
# Game_Animation with Eval Support
# Version: 1.2
# Author: Wecoc
#------------------------------------------------------------------------------
# o DESCRIPTION
#
# By default on animations you can assign a sound, screen flash, target flash
# or delete the target in a specific frame.
#
# This script allows to add eval, ie "Call Script" in the animations.
# With this you will be able to do things not possible until now.
# I also added some shortcuts to make the eval a bit more easy, they are
# inside the module Skill_Shortcuts and you can create more there.
#
# With this new version of the script, all the changes you do will be saved.
# So you can assign all the evals in the first map and they will be kept fixed.
#
#------------------------------------------------------------------------------
# o COMPATIBILITY
#
# CAUTION - If you use other scripts there may be two types of incompatibilities
#
# 1) Aliased methods
#
# - RPG::Sprite :update_animation (alias), :update_loop_animation (alias)
# - Scene_Title :command_new_game (alias), :battle_test (alias)
# - Scene_Save :write_save_data (alias)
# - Scene_Load :read_save_data (alias)
# - Sprite_Character :update (alias)
# - Sprite_Battler :update (alias)
#
# 2) $data_animations
#
# Although $data_animations still works it will do without the evals.
# To call an animation with its included evals you have to use
# $game_animations in all the not default scripts.
#
#------------------------------------------------------------------------------
# o INSTRUCTIONS
#
# How to set a new eval:
# $game_animations[id].add_effect(frame, 'text', condition)
# text - Code to eval
# condition - 0 - Always, 1 - Hit, 2 - Miss ; optional, 0 by default
#
# / Example: $game_animations[1].add_effect(5, '$game_switches[1] = true', 1)
#
# How to clear all the added evals of an animation
# $game_animations[id].clear_effects
#------------------------------------------------------------------------------
# o SHORTCUTS
#
# Shortcuts are defined inside Skill_Shortcuts and you can add all you want.
# This is what will be used within the above described as 'text' but actually
# you can use them in any eval.
#==============================================================================
#==============================================================================
# Skill_Shortcuts
#==============================================================================
module Skill_Shortcuts
# SE play
def se_play(name, volume, pitch)
Audio.se_play("Audio/SE/" + name, volume, pitch)
end
# Screen Flash
def flash_screen(color, time)
self.viewport.flash(color, time)
end
# (Use flash method for target flash)
# Erase Target
def hide(time)
self.flash(nil, time)
end
# Shake Screen (I don't like how it looks in battle)
def shake(power, speed, duration)
$game_screen.start_shake(power, speed, duration)
end
# Memorize the current screen tone
def get_tone
@screen_tone = $game_screen.tone.clone
end
# Change the screen tone
def set_tone(tone, time)
$game_screen.start_tone_change(tone, time)
end
# Restore the memorized screen tone
def restore_tone(time)
@screen_tone ||= Tone.new(0, 0, 0, 0)
$game_screen.start_tone_change(@screen_tone, time)
end
# Change the screen tone (it depends on the actual tone)
def change_tone(tone, time)
@screen_tone ||= Tone.new(0, 0, 0, 0)
new_tone = @screen_tone.clone
new_tone.red += tone.red
new_tone.green += tone.green
new_tone.blue += tone.blue
new_tone.gray += tone.gray
$game_screen.start_tone_change(new_tone, time)
end
# Change the x of the sprite
def change_ani_x(new_x, duration=0)
return @ani_x = new_x if duration == 0
@ani_x_new = new_x
@ani_x_duration = duration
end
# Change the y of the sprite
def change_ani_y(new_y, duration=0)
return @ani_y = new_y if duration == 0
@ani_y_new = new_y
@ani_y_duration = duration
end
end
#==============================================================================
# RPG::Animation & RPG::Sprite Edits
#==============================================================================
class RPG::Animation::Frame
define_method(:text_array) { @text_array ||= []}
end
class RPG::Sprite < ::Sprite
alias update_animation_eval_hit update_animation unless $@
alias update_loop_animation_eval_hit update_loop_animation unless $@
def update_animation(*args)
if @_animation_duration > 0
frame_index = @_animation.frame_max - @_animation_duration
text_array = @_animation.frames[frame_index].text_array
for text_pair in text_array
text = text_pair[0]
cond = text_pair[1]
hit = @_animation_hit
if (cond == 0) or (cond == 1 and hit) or (cond == 2 and !hit)
result = eval(text)
end
end
end
update_animation_eval_hit(*args)
end
def update_loop_animation(*args)
frame_index = @_loop_animation_index
text_array = @_animation.frames[frame_index].text_array
for text_pair in text_array
text = text_pair[0]
cond = text_pair[1]
hit = @_animation_hit
if (cond == 0) or (cond == 1 and hit) or (cond == 2 and !hit)
class_eval(text)
end
end
update_loop_animation_eval_hit(*args)
end
end
#==============================================================================
# Game_Animation & Game_Animations ($game_animations)
#==============================================================================
class Game_Animation
attr_reader :animation_id
attr_reader :name
attr_reader :animation_name
attr_reader :animation_hue
attr_reader :position
attr_reader :frame_max
attr_reader :timings
attr_reader :frames
def initialize(animation_id)
setup(animation_id)
end
def setup(animation_id)
@animation_id = animation_id
animation = $data_animations[animation_id]
@name = animation.name
@animation_name = animation.animation_name
@animation_hue = animation.animation_hue
@position = animation.position
@frame_max = animation.frame_max
@timings = animation.timings
@frames = animation.frames
end
def id
@animation_id
end
def add_effect(frame, text, condition=0)
return false if frame > @frame_max
@frames[frame].text_array.push([text, condition])
@frames[frame].text_array.uniq!
return true
end
def clear_effects(frame=nil)
frames = frame.nil? ? @frames[0...@frame_max] : [@frames[frame]]
frames.each {|f| f.text_array.clear}
return true
end
end
class Game_Animations
def [](animation_id)
return nil if animation_id > 999 or $data_animations[animation_id] == nil
(@data||=[])[animation_id] ||= Game_Animation.new(animation_id)
end
end
#==============================================================================
# $game_animations load/save
#==============================================================================
class Scene_Title
alias animation_fix_new_game command_new_game unless $@
alias animation_fix_battle battle_test unless $@
def command_new_game
$game_animations = Game_Animations.new
animation_fix_new_game
end
def battle_test
$game_animations = Game_Animations.new
animation_fix_battle
end
end
class Scene_Save < Scene_File
alias animation_fix_write write_save_data unless $@
def write_save_data(file)
$game_system.game_animations = $game_animations
animation_fix_write(file)
end
end
class Scene_Load < Scene_File
alias animation_fix_read read_save_data unless $@
def read_save_data(file)
animation_fix_read(file)
$game_animations = $game_system.game_animations || Game_Animations.new
end
end
class Game_System
attr_accessor :game_animations
end
#==============================================================================
# Sprite_Character & Sprite_Battler Edits
#==============================================================================
class Sprite_Character < RPG::Sprite
include Skill_Shortcuts
attr_accessor :ani_x
attr_accessor :ani_y
alias animation_fix_upd update unless $@
def update(*args)
pre_update_animation_effect
animation_fix_upd(*args)
update_animation_position_effect
end
def pre_update_animation_effect
if @character && @character.animation_id != 0
animation = $game_animations[@character.animation_id]
animation(animation, true)
@character.animation_id = 0
end
end
def update_animation_position_effect
return if @character.nil?
if (@ani_x_duration ||= 0) >= 1
d = @ani_x_duration
@ani_x = ((@ani_x || 0) * (d - 1) + (@ani_x_new ||= 0)) / d
@ani_x_duration -= 1
end
if (@ani_y_duration ||= 0) >= 1
d = @ani_y_duration
@ani_y = ((@ani_y || 0) * (d - 1) + (@ani_y_new ||= 0)) / d
@ani_y_duration -= 1
end
self.x = @character.screen_x + (@ani_x ||= 0)
self.y = @character.screen_y + (@ani_y ||= 0)
end
end
class Sprite_Battler < RPG::Sprite
include Skill_Shortcuts
attr_accessor :ani_x
attr_accessor :ani_y
alias animation_fix_upd update unless $@
def update(*args)
pre_update_animation_effect
animation_fix_upd(*args)
update_animation_position_effect
end
def pre_update_animation_effect
if @battler.nil?
@battler_name = nil
else
if @battler.damage.nil? and
@battler.state_animation_id != @state_animation_id
@state_animation_id = @battler.state_animation_id
animation = $game_animations[@state_animation_id]
loop_animation(animation)
end
if @battler_visible && @battler.animation_id != 0
animation = $game_animations[@battler.animation_id]
animation(animation, @battler.animation_hit)
@battler.animation_id = 0
end
end
end
def update_animation_position_effect
return if @battler.nil?
if (@ani_x_duration ||= 0) >= 1
d = @ani_x_duration
@ani_x = ((@ani_x || 0) * (d - 1) + (@ani_x_new ||= 0)) / d
@ani_x_duration -= 1
end
if (@ani_y_duration ||= 0) >= 1
d = @ani_y_duration
@ani_y = ((@ani_y || 0) * (d - 1) + (@ani_y_new ||= 0)) / d
@ani_y_duration -= 1
end
self.x = @battler.screen_x + (@ani_x ||= 0)
self.y = @battler.screen_y + (@ani_y ||= 0)
end
end
InstructionsThey are all in the code.
CompatibilityThis part is explained in the code. It has some possible incompatibilities.
Author's NotesDo you need help to add a new shortcut? Contact me and I will try to help.
Thank you for fixing the alias! I usually have problems to alias :update methods because they contain a huge loop do, but it was not the case so I have no excuse xD
I edited my post with your script, it has less incompatibilities and less code lines.
The demo was also updated.
I love eval implementations, hehehe.
Heyo, i decided to check this out and in Demo after interracting with the armored guy 2 times quickly (second animation was initiated before the first one ended playing) the screen got darker for good. Talking to him again few times can give us the constant pitch black screen. Is this supposed to be like that? :)
Ok it's because when you talk with him he sets the current screen tone (dark because the animation) as the last target tone, so calculates the tones wrong... It's a bug on the demo, but it will not cause problems on default battle animations nor default events with a wait counter after the animation. If I could, I would fix that definitely but I don't know how it's supposed to be corrected.
Thank you for your reply.