=begin ============================================================================== ** Actor Creation System Author: Hime Date: Apr 25, 2013 ------------------------------------------------------------------------------ ** Change log Apr 25, 2013 -updated to custom database's new API Dec 14, 2012 -refreshed the player character after updating character sprite -add_bonus_stats method added to Scene_ActorCreate -fixed bug where wrong face/char is shown when scene begins Nov 28 -fixed issue where actor fields are empty or null -removed name processing. Use normal name processing command for that May 26 -fixed issue where actor didn't have a face, or the sheet containing the face was not loaded May 25 -fixed equip stats bug -fixed bonus stats bug -added option to add specific actor to party by preparing the scene May 22 -Added field locking -Can update existing actor information -Serves as stat distribution feature May 21, 2012 -Initial release ------------------------------------------------------------------------------ Create new actors during the game! Access the scene using the script call SceneManager.call(Scene_ActorCreate) If you want to modify an existing actor, you must prepare the scene with an extra call SceneManager.scene.prepare(actor_id, class_fixed?, face_fixed?, char_fixed?) The actor ID must be one of the actors that are currently in the game. The rest of the arguments are for locking fields from editing If you want to add bonus stats when the scene has been accessed, you can use SceneManager.scene.add_bonus_stats(n) For some integer n. You can lock or unlock classes with the following script calls $game_system.lock_class(n) $game_system.unlock_class(n) Where n is the class ID. You can choose your actor face and character sprite, as well as class ID. You can distribute bonus stats as well. Once you have completed your selection, press OK and you will be asked to choose a name for your new actor. After you've chosen a name the actor will be added to your party ready to explore. At the top of the script there is some configuration. In particular, if you want to add more faces and character sprites, you just have to add the filenames to the lists. Note that I'm assuming you're using Ace's 4x2 sprite sheets. ============================================================================== =end $imported = {} if $imported.nil? $imported["Tsuki_ActorCreation"] = true #============================================================================== # ** Configuration. #============================================================================== module Tsuki module Actor_Creation # show the change command in party menu Show_Change_Command = false # Keep exp when changing classes? Keep_Exp = true # Enter the filenames of all of the faces you would like to choose # Note that they must be the Ace standard 8 face sheets Faces = ["Actor1","Actor2","Actor3","Actor4","Actor5"] # Filenames of all character sprites you would like to choose # Note that they must be the Ace standard 8 character sheets Chars = ["Actor1","Actor2","Actor3","Actor4","Actor5"] # max character name length Max_Chars = 6 # How much of that stat is given per stat point allocated # mhp, mmp, atk, def, mat, mdf, agi, luk Param_Rate = [10, 5, 1, 1, 1, 1, 1, 1] # Minimum that you can have of a particular stat Min_Params = [1, 0, 0, 0, 0, 0, 0, 0] end end module RPG class Actor < BaseItem attr_accessor :bonus_params attr_accessor :bonus_stats alias :tsuki_actor_create_initialize_rpg_actor :initialize def initialize tsuki_actor_create_initialize_rpg_actor load_notetags_actor_creation end def load_notetags_actor_creation @bonus_params = [0] * 8 @bonus_stats = 0 end end end module DataManager class << self alias actor_creation_load_database load_database alias actor_creation_init init end def self.init actor_creation_init load_notetags_actor_creation end def self.load_database actor_creation_load_database if $BTEST load_notetags_actor_creation end end def self.load_notetags_actor_creation groups = [$data_actors] for group in groups for obj in group next if obj.nil? obj.load_notetags_actor_creation end end end end class Game_System attr_reader :locked_classes alias th_actor_create_initialize initialize def initialize th_actor_create_initialize @locked_classes = [] end def lock_class(class_id) @locked_classes << class_id end def unlock_class(class_id) @locked_classes.delete(class_id) end end class Game_Actor attr_accessor :bonus_params attr_accessor :bonus_stats alias th_actor_create_setup_actor setup def setup(actor_id) th_actor_create_setup_actor(actor_id) @bonus_params = actor.bonus_params.clone @bonus_stats = actor.bonus_stats end alias :th_actor_create_clear_param_plus :clear_param_plus def clear_param_plus @bonus_params = [0] * 8 th_actor_create_clear_param_plus end alias :th_actor_create_param_plus :param_plus def param_plus(param_id) @bonus_params[param_id] + th_actor_create_param_plus(param_id) end def add_bonus_stats(amount) @bonus_stats = [0, @bonus_stats + amount].max end end class Game_Actors def size @data.size end def add_actor(actor) @data << actor end end class Game_Party < Game_Unit def has_actor?(actor_id) @actors.include?(actor_id) end end class Window_MenuCommand < Window_Command include Tsuki::Actor_Creation #-------------------------------------------------------------------------- # * Add arena command to List #-------------------------------------------------------------------------- alias :th_actor_create_commands :add_main_commands def add_main_commands th_actor_create_commands add_command("Change", :change )if Show_Change_Command end end class Scene_Menu < Scene_MenuBase include Tsuki::Actor_Creation #-------------------------------------------------------------------------- # * Add arena handler #-------------------------------------------------------------------------- alias :th_actor_create_command_window :create_command_window def create_command_window th_actor_create_command_window @command_window.set_handler(:change, method(:command_personal)) if Show_Change_Command end alias :th_actor_create_personal_ok :on_personal_ok def on_personal_ok th_actor_create_personal_ok case @command_window.current_symbol when :change command_change end end def command_change SceneManager.call(Scene_ActorCreate) actor_id = $game_party.members[@status_window.index].id SceneManager.scene.prepare(actor_id, false) end end #============================================================================== # ** Actor creation scene #============================================================================== class Scene_ActorCreate < Scene_Base include Tsuki::Actor_Creation def start super create_all_windows @face_fix = false @char_fix = false @class_fix = false @face_window.activate end def prepare(actor_id, class_fix=true, face_fix=true, char_fix=true) @actor = $game_actors[actor_id] if actor_id && actor_id > 0 @face_fix = face_fix @char_fix = char_fix @class_fix = class_fix end def create_all_windows create_background_window create_face_status_window create_char_status_window create_face_window create_character_window create_class_window create_stats_window create_confirm_window end def create_confirm_window wx = Graphics.width / 2 wy = Graphics.height / 2 @confirm_window = Window_Confirm.new(wx, wy) @confirm_window.set_handler(:ok, method(:on_confirm_ok)) @confirm_window.set_handler(:cancel, method(:on_confirm_cancel)) end def create_background_window @status_window = Window_ActorCreateStatus.new end def create_face_status_window @face_status_window = Window_ActorCreateFaceStatus.new(20, 20) end def create_char_status_window wx = @face_status_window.x + @face_status_window.width - 10 wy = @face_status_window.y @char_status_window = Window_ActorCreateCharStatus.new(wx, wy) end def create_face_window wx = 180 @face_window = Window_ActorCreateFace.new(wx, 20) @face_window.set_handler(:ok, method(:on_confirm)) @face_window.set_handler(:cancel, method(:return_scene)) @face_window.set_handler(:DOWN, method(:on_face_next)) @face_window.status_window = @face_status_window @face_window.actor = @actor @face_window.fixed = @face_fix end def create_character_window wx = @face_window.x wy = @face_window.y + @face_window.height - 20 @char_window = Window_ActorCreateChar.new(wx, wy) @char_window.set_handler(:ok, method(:on_confirm)) @char_window.set_handler(:cancel, method(:return_scene)) @char_window.set_handler(:UP, method(:on_char_prev)) @char_window.set_handler(:DOWN, method(:on_char_next)) @char_window.status_window = @char_status_window @char_window.actor = @actor @char_window.fixed = @char_fix end def create_class_window wx = @face_window.x wy = @char_window.y + @char_window.height - 20 @class_window = Window_ActorCreateClass.new(wx, wy) @class_window.set_handler(:ok, method(:on_confirm)) @class_window.set_handler(:cancel, method(:return_scene)) @class_window.set_handler(:UP, method(:on_class_prev)) @class_window.set_handler(:DOWN, method(:on_class_next)) @class_window.actor = @actor @class_window.fixed = @class_fix end def create_stats_window wx = 0 wy = @class_window.y + @class_window.height width = 300 height = Graphics.height - wy @stats_window = Window_ActorCreateStats.new(wx, wy, width, height) @stats_window.set_handler(:UP, method(:on_stats_prev)) @stats_window.set_handler(:ok, method(:on_confirm)) @stats_window.set_handler(:cancel, method(:return_scene)) @stats_window.actor = @actor @class_window.stats_window = @stats_window end def on_face_next @face_window.deactivate @char_window.activate end def on_char_prev @char_window.deactivate @face_window.activate end def on_char_next @char_window.deactivate @class_window.activate end def on_class_prev @class_window.deactivate @char_window.activate end def on_class_next @stats_window.activate @class_window.deactivate end def on_stats_prev @stats_window.deactivate @class_window.activate end def on_confirm @face_window.deactivate @char_window.deactivate @class_window.deactivate @stats_window.deactivate @confirm_window.activate.show end def on_confirm_ok if @actor if $game_party.has_actor?(@actor.id) update_actor(@actor.id) return_scene else update_actor(@actor.id) # update the actor and add to party $game_party.add_actor(@actor.id) return_scene #~ SceneManager.call(Scene_Name) #~ SceneManager.scene.prepare(@actor.id, Max_Chars) end else actor_id = create_actor return_scene end $game_player.refresh end def on_confirm_cancel @confirm_window.deactivate.hide @face_window.activate end def create_actor actor_id = $data_actors.size actor = make_new_actor(actor_id) update_data(actor) add_actor(actor_id) return actor_id end def update_actor(actor_id) game_actor = $game_actors[actor_id] game_actor.change_class(@class_window.index + 1, Keep_Exp) char_name = @char_status_window.character_name char_index = @char_status_window.character_index face_name = @face_status_window.face_name face_index = @face_status_window.face_index game_actor.set_graphic(char_name, char_index, face_name, face_index) game_actor.bonus_params = @stats_window.bonus_params game_actor.bonus_stats = @stats_window.bonus end def make_new_actor(actor_id) actor = RPG::Actor.new actor.id = actor_id actor.class_id = @class_window.index + 1 actor.character_name = @char_status_window.character_name actor.character_index = @char_status_window.character_index actor.face_name = @face_status_window.face_name actor.face_index = @face_status_window.face_index actor.bonus_params = @stats_window.bonus_params actor.bonus_stats = @stats_window.bonus setup_extra(actor) return actor end def setup_extra(actor) # need extensions? end def update_data(actor) CustomData.add_actor(actor) end def add_actor(actor_id) game_actor = Game_Actor.new(actor_id) $game_actors.add_actor(game_actor) $game_party.add_actor(actor_id) end def add_bonus_stats(amount) @actor.add_bonus_stats(amount) if @actor end end #============================================================================== # ** Actor Creation windows #============================================================================== class Window_ActorHorzCommand < Window_HorzCommand include Tsuki::Actor_Creation attr_accessor :fixed def initialize(x, y) super self.index = 0 self.back_opacity = 0 self.opacity = 0 @last_index = 0 @actor = nil @fixed = false end def actor=(actor) return if @actor == actor @actor = actor refresh end def cursor_right(wrap = false) if !@fixed && (index < item_max - 1 || (wrap && horizontal?)) select((index + 1) % item_max) end end def cursor_left(wrap = false) if !@fixed && (index > 0 || (wrap && horizontal?)) select((index - 1 + item_max) % item_max) end end def top_col=(col) col = 0 if col < 0 self.ox = col * (item_width + spacing) end def unselect @last_index = self.index end def select_last select(@last_index) end def cursor_down(wrap = false) call_handler(:DOWN) Sound.play_cursor Input.update end def cursor_up(wrap = false) call_handler(:UP) Sound.play_cursor Input.update end def col_max 1 end def deactivate unselect super end def activate select_last super end end class Window_ActorCreateFace < Window_ActorHorzCommand def make_command_list n = 1 Faces.each do |filename| 8.times do |i| name = "Face %d" %n add_command(name, name.to_sym) n += 1 end end end def update super @status_window.face = index end def status_window=(window) @status_window = window end def refresh super return unless @actor @sheet = Faces.index(@actor.face_name) @last_index = @sheet ? @sheet * 8 + @actor.face_index : 0 select(@last_index) end end class Window_ActorCreateClass < Window_ActorHorzCommand def initialize(x, y) super deactivate end def make_command_list $data_classes.each do |cls| next if cls.nil? || $game_system.locked_classes.include?(cls.id) add_command(cls.name, cls.name.to_sym) end end def update super refresh_stats if @stats_window end def refresh super return unless @actor @last_index = @actor.class_id - 1 select(@last_index) end def refresh_stats @stats_window.class = index + 1 end def stats_window=(window) return unless window @stats_window = window refresh end end class Window_ActorCreateChar < Window_ActorHorzCommand def initialize(x, y) super deactivate end def make_command_list n = 1 Chars.each do |filename| 8.times do |i| name = "Character %d" %n add_command(name, name.to_sym) n += 1 end end end def update super @status_window.char = index end def status_window=(window) @status_window = window end def refresh super return unless @actor return 0 if @actor.character_name.nil? || @actor.character_name.empty? @sheet = Chars.index(@actor.character_name) @last_index = @sheet * 8 + @actor.character_index select(@last_index) end end class Window_ActorCreateStats < Window_Selectable include Tsuki::Actor_Creation attr_reader :bonus_params attr_reader :bonus def initialize(x, y, width, height) super deactivate self.back_opacity = 0 self.opacity = 0 @bonus = 0 @actor = nil @curr_class = $data_classes[1] @param_rate = Param_Rate.clone @param_min = Min_Params.clone @params = [0]*8 @bonus_params = [0]*8 refresh_params refresh end def make_item_list @data = $data_system.terms.params end def item_max @data ? @data.size : 1 end def draw_bonus draw_text(0, 200, 100, line_height, "Bonus", 1) draw_text(100, 200, 100, line_height, @bonus, 1) end def draw_item(index) item = @data[index] if item rect = item_rect(index) rect.width -= 4 change_color(normal_color) draw_text(rect.x, rect.y, 100, line_height, item, 1) draw_text(rect.x + 100, rect.y, 100, line_height, @params[index], 1) draw_bonus_param(@bonus_params[index], rect.x+140, rect.y) end end def draw_bonus_param(param, x, y) if param >= 0 change_color(text_color(16)) draw_text(x, y, 100, line_height, "+ %d" %param, 2) else change_color(text_color(9)) draw_text(x, y, 100, line_height, "- %d" %param.abs, 2) end end def refresh make_item_list create_contents draw_bonus draw_all_items end def refresh_actor 8.times do |i| @params[i] = @actor.param(i) - @actor.bonus_params[i] end @bonus_params = @actor.bonus_params @bonus = @actor.bonus_stats end def refresh_class level = @actor ? @actor.level : 1 8.times do |i| @params[i] = @curr_class.params[i, level] end end def refresh_params refresh_actor if @actor refresh_class if @curr_class end def cursor_right(wrap = false) if @bonus > 0 @bonus_params[index] += @param_rate[index] @bonus -= 1 Sound.play_ok else Sound.play_buzzer end refresh end def cursor_left(wrap = false) if @bonus_params[index] > @param_min[index] @bonus_params[index] -= @param_rate[index] @bonus += 1 Sound.play_ok else Sound.play_buzzer end refresh end def cursor_up(wrap = false) if index == 0 call_handler(:UP) Input.update else super end end def activate select(0) super end def deactivate unselect super end def actor=(actor) return if @actor == actor @actor = actor refresh_actor refresh end def class=(new_class) return if @curr_class.id == new_class @curr_class = $data_classes[new_class] refresh_class refresh end end class Window_ActorCreateStatus < Window_Base def initialize super(0, 0, Graphics.width, Graphics.height) end end class Window_ActorCreateFaceStatus < Window_Base include Tsuki::Actor_Creation attr_reader :face_name attr_reader :face_index def initialize(x, y) super(x, y, window_width, window_height) @f_index = -1 @face_name = "" @face_index = -1 self.opacity = 0 refresh end def window_width 120 end def window_height 120 end def face=(index) return if @f_index == index @f_index = index refresh end def redraw_face if @f_index >= 0 @face_name = Faces[@f_index / 8] @face_index = @f_index % 8 draw_face(@face_name, @face_index, 0, 0) end end def refresh contents.clear redraw_face end end class Window_ActorCreateCharStatus < Window_Base include Tsuki::Actor_Creation attr_reader :character_name attr_reader :character_index def initialize(x, y) super(x, y, window_width, window_height) @c_index = -1 self.opacity = 0 @character_name = "" @character_index = -1 refresh end def window_width 56 end def window_height 56 end def char=(index) return if @c_index == index @c_index = index refresh end def redraw_char if @c_index >= 0 @character_name = Chars[@c_index / 8] @character_index = @c_index % 8 draw_character(@character_name, @character_index, 16, 32) end end def refresh contents.clear redraw_char end end class Window_Confirm < Window_Command attr_accessor :mode def initialize(x, y) super self.openness = 0 @mode = nil end #-------------------------------------------------------------------------- # * Get Window Width #-------------------------------------------------------------------------- def window_width return 160 end #-------------------------------------------------------------------------- # * Get Window Height #-------------------------------------------------------------------------- def window_height fitting_height(visible_line_number) end def make_command_list add_command("Yes", :ok, true) add_command("No", :cancel, true) end def show self.openness = 255 end def hide self.openness = 0 end end