RMRK is retiring.
Server is paid up for the rest of 2026, but the forum may go after that. See here for more information. Please archive or save anything you would like to keep before 2027.
Main Menu
  • Welcome to The RPG Maker Resource Kit.

Help with Zeriab's Caterpillar

Started by booze, December 19, 2010, 01:10:30 PM

0 Members and 1 Guest are viewing this topic.

booze

Hello  ::)
I'm not new to RMXP but only recently started scripting. I can create simple Scenes and Windows almost from scratch and i can edit some scripts (except very complex ones.)

I'm using Zeriab's Caterpillar Script because it allows me to interact with an Event on a map and can be controlled by a switch.

[spoiler="Zeriab's Caterpillar Script"]

#==============================================================================
# ** Zeriab's Caterpillar Script
#------------------------------------------------------------------------------
# Zeriab
# 1.0
# 2008-08-16
#------------------------------------------------------------------------------
# This script creates a caterpillar of the party members by using events.
#------------------------------------------------------------------------------
# Paste this script just above main.
#
# Put \cat_actor[3] in the name of an event and it will be considered the event
# for the actor with id 3. The name could for example be "Cyrus\cat_actor[3]"
#
# The switch number specified with CATERPILLAR_ACTIVE_SWITCH (default is 23) is
# used to determine whether the events should be positioned in the caterpillar
# or not. Then the switch is off they are just like any other event.
#
# The REMOVE_VISIBLE_ACTORS (default is true) is used to determine whether
# actor event not in the party should be erased or not.
# If it is set to an integer rather than true or false the switch with the
# corresponding id is used. For example REMOVE_VISIBLE_ACTORS = 21 will allow
# you to determine whether the events should be erased or not depending whether
# switch 21 is OFF or ON.
#
# The MAX_ACTORS (default is 4) is used to determine how many player moves
# should be remembered. Only change this if you can have a party with more than
# 4 actors.
#==============================================================================
class Game_Caterpillar
  CATERPILLAR_ACTIVE_SWITCH = 23
  REMOVE_VISIBLE_ACTORS = false
  MAX_ACTORS = 2
  ##
  # Initialize the caterpillar
  #
  def initialize
    @actors = []
    @actor_id_to_event = {}
    @move_list = []
  end
  ##
  # Clear the caterpillar data
  #
  def clear
    @actors.clear
    @actor_id_to_event.clear
    @move_list.clear
  end
  ##
  # Add an actor event to the caterpillar
  #
  def add_actor(event, actor_id)
    @actor_id_to_event[actor_id] = event
    event.move_list.clear
    added = false
    for actor in $game_party.actors
      if actor.id == actor_id
        @actors << event
        event.moveto($game_player.x, $game_player.y)
        added = true
      end
    end
    if remove_visible_actors? && !added && $game_switches[CATERPILLAR_ACTIVE_SWITCH]
      event.erase
    end
  end
  ##
  # Check if visible actors should be removed
  #
  def remove_visible_actors?
    if REMOVE_VISIBLE_ACTORS.is_a?(Integer)
      return $game_switches[REMOVE_VISIBLE_ACTORS]
    else
      return REMOVE_VISIBLE_ACTORS
    end
  end
  ##
  # If the game player has been center. I.e. teleported somewhere.
  #
  def center
    # Check if the caterpillar is active
    return unless $game_switches[CATERPILLAR_ACTIVE_SWITCH]
    # Clear the move_llist
    @move_list.clear
    # Refresh the caterpillar
    update
    # Move the actors to the new place
    for event in @actors
      event.moveto($game_player.x, $game_player.y)
      event.move_list.clear
    end
  end
  ##
  # Refresh the caterpillar. (Use sparingly)
  #
  def refresh
    # Check if the caterpillar is active
    return unless $game_switches[CATERPILLAR_ACTIVE_SWITCH]
    # Clear the data
    clear
    # Check each event
    for event in $game_map.events.values
      if event.is_a?(Game_Event)
        event.check_caterpillar
      end
    end
    # Center the events around the player
    center
    # Update the caterpillar
    update
  end
  ##
  # Register a player move
  #
  def register_player_move(move_speed, *args)
    # Check if the caterpillar is active
    return unless $game_switches[CATERPILLAR_ACTIVE_SWITCH]
    # Add the new command
    @move_list.unshift([move_speed, args])
    # Append the new moves to the caterpillar events
    update_actor_movement
    # Check if the last command should be removed
    if @move_list.size > MAX_ACTORS + 1
      # Remove the last move command
      @move_list.pop
    end
  end
  ##
  # Updates the actors movement.
  #
  def update_actor_movement
    for i in 0...@actors.size
      if i + 1 < @move_list.size
        command = @move_list[i + 1]
        actor = @actors[i]
        actor.move_list.unshift(command[1])
        actor.move_speed = command[0]
      end
    end
  end
  ##
  # Update the caterpillar.
  #
  def update
    # Check if the caterpillar is active
    return unless $game_switches[CATERPILLAR_ACTIVE_SWITCH]
    old_actors = @actors
    @actors = []
    # Create a copy of the party actors
    caterpillar = $game_party.actors.dup
    # Remove the first element
    caterpillar.shift
    # Go through each actor that's possible present in the caterpillar
    for actor in caterpillar
      event = @actor_id_to_event[actor.id]
      unless event.nil?
        @actors << event
        event.unerase if remove_visible_actors?
        event.character_name = actor.character_name
      end
    end
    if remove_visible_actors?
      # Go through the old actors to see if any should be erased
      for actor in old_actors
        unless @actors.include?(actor)
          actor.erase
        end
      end
    end
  end
  ##
  # Unerase all erased actor events
  #
  def unerase_all
    for event in @actor_id_to_event.values
      event.unerase
    end
  end
  ##
  # Erase actor events not in the party
  #
  def erase_non_party_events
    for event in @actor_id_to_event.values
      event.erase unless @actors.include?(event)
    end
  end
end

class Game_Player < Game_Character
  unless self.method_defined?('zeriab_caterpillar_game_player_center')
    alias_method(:zeriab_caterpillar_game_player_center, :center)
  end
  ##
  # When the player is centered (i.e. teleported somewhere)
  #
  def center(*args)
    zeriab_caterpillar_game_player_center(*args)
    $game_system.caterpillar.center
  end
 
  ##
  # Generate registration of player moves to the caterpillar code
  #
  MOVE_METHODS = ['move_down', 'move_left', 'move_right', 'move_up',
                  'move_lower_left', 'move_lower_right', 'move_upper_left',
                  'move_upper_right', 'jump']
 
  # Go through each method
  for method in MOVE_METHODS
    # Create the script for the specific method
    PROG = <<_END_
  def #{method}(*args)
    x,y = self.x, self.y
    super(*args)
    unless self.x == x && self.y == y
      $game_system.caterpillar.register_player_move(@move_speed, '#{method}', args, [self.x, self.y])
    end
  end
_END_
    # Run the script
    eval(PROG)
  end
end

class Module
  # Prevent adding the method again should it already be present.
  unless self.method_defined?('attr_sec_accessor')
    def attr_sec_accessor(sym, default = 0)
      attr_writer sym
      attr_sec_reader sym, default
    end
   
    def attr_sec_reader(sym, default = 0)
      sym = sym.id2name
      string = "def #{sym};" +
               "  @#{sym} = #{default}  if @#{sym}.nil?;" +
               "  @#{sym};" +
               "end;"
      module_eval(string)
    end
  end
end

class Game_System
  attr_sec_accessor :caterpillar, 'Game_Caterpillar.new'
end

class Game_Event < Game_Character
  ##
  # Attributes
  #
  attr_sec_accessor :move_list, '[]'
  attr_accessor     :move_speed
  attr_writer       :character_name
  ##
  # Aliases
  #
  unless self.method_defined?('zeriab_caterpillar_game_event_passable?')
    alias zeriab_caterpillar_game_event_initialize :initialize
    alias zeriab_caterpillar_game_event_passable?  :passable?
    if Module.constants.include?('SDK')
      alias zeriab_caterpillar_game_event_update_movement  :update_movement
    else
      alias zeriab_caterpillar_game_event_update  :update
    end
  end
  ##
  # Object Initialization
  #
  def initialize(map_id, event, *args)
    # Default update
    zeriab_caterpillar_game_event_initialize(map_id, event, *args)
    # Check if the caterpillar is active
    return unless $game_switches[Game_Caterpillar::CATERPILLAR_ACTIVE_SWITCH]
    # Check for caterpillar actor denomination
    check_caterpillar
  end
  ##
  # Check for caterpillar actor denomination
  #
  def check_caterpillar
    # Check for caterpillar actor denomination (Last is used if more present)
    @event.name.gsub(/\\cat_actor\[([0-9]+)\]/i) {@caterpillar_actor = $1 }
    # Check if an valid denomination is found.
    if @caterpillar_actor.is_a?(String)
      @caterpillar_actor = @caterpillar_actor.to_i
      if $data_actors[@caterpillar_actor].nil?
        @caterpillar_actor = nil
      else
        $game_system.caterpillar.add_actor(self, @caterpillar_actor)
      end
    end
  end
  ##
  # Check passability
  #
  def passable?(*args)
    if @caterpillar_actor.nil? || move_list.empty? ||
       !$game_switches[Game_Caterpillar::CATERPILLAR_ACTIVE_SWITCH]
      return zeriab_caterpillar_game_event_passable?(*args)
    else
      return true
    end
  end
  ##
  # SDK and Non-SDK stuff
  #
  if Module.constants.include?('SDK')
    ##
    # Update Movement
    #
    def update_movement
      if @caterpillar_actor.nil? || move_list.empty? ||
         !$game_switches[Game_Caterpillar::CATERPILLAR_ACTIVE_SWITCH]
        return zeriab_caterpillar_game_event_update_movement
      end
      # Interrupt if not stopping
      if jumping? or moving?
        return
      end
      # Retrive the command
      command = move_list[0]
      # Call the command
      method(command[0]).call(*command[1])
      # Make sure the x and y are right in the end
      @x, @y = *command[2]
      # Remove the command
      move_list.pop
    end
  else # Non-SDK version
    ##
    # Update Movement
    #
    def update
      # Interrupt if not stopping
      no_move = jumping? or moving?
      # Update
      zeriab_caterpillar_game_event_update
      # Check if it should return
      if $game_switches[Game_Caterpillar::CATERPILLAR_ACTIVE_SWITCH] &&
         @caterpillar_actor != nil && !move_list.empty? && !no_move
        # Retrive the command
        command = move_list[0]
        # Call the command
        method(command[0]).call(*command[1])
        # Make sure the x and y are right in the end
        @x, @y = *command[2]
        # Remove the command
        move_list.pop
      end
    end
  end
  ##
  # Bring back an erased event
  #
  def unerase
    @erased = false
    refresh
  end
end

class Game_Map
  ##
  # Aliases
  #
  unless self.method_defined?('zeriab_caterpillar_game_map_setup')
    alias zeriab_caterpillar_game_map_setup :setup
  end
  ##
  # Transfer Player
  #
  def setup(*args)
    $game_system.caterpillar.clear
    zeriab_caterpillar_game_map_setup(*args)
  end
end

class Game_Switches
  ##
  # Aliases
  #
  unless self.method_defined?('zeriab_caterpillar_game_switches_setter')
    alias zeriab_caterpillar_game_switches_setter :[]=
  end
  ##
  # Setter
  #
  def []=(switch_id, value, *args)
    zeriab_caterpillar_game_switches_setter(switch_id, value, *args)
    if switch_id == Game_Caterpillar::CATERPILLAR_ACTIVE_SWITCH
      $game_system.caterpillar.refresh
    elsif switch_id == Game_Caterpillar::REMOVE_VISIBLE_ACTORS
      if value
        $game_system.caterpillar.erase_non_party_events
      else
        $game_system.caterpillar.unerase_all
      end
    end
  end
end

class Interpreter
  ##
  # Aliases
  #
  unless self.method_defined?('zeriab_caterpillar_interpreter_command_129')
    alias zeriab_caterpillar_interpreter_command_129 :command_129
    alias zeriab_caterpillar_interpreter_command_322 :command_322
  end
  ##
  # Change Party Member
  #
  def command_129
    result = zeriab_caterpillar_interpreter_command_129
    $game_system.caterpillar.refresh
    return result
  end
  ##
  # Change Actor Graphic
  #
  def command_322
    result = zeriab_caterpillar_interpreter_command_322
    $game_system.caterpillar.update
    return result
  end
end

[/spoiler]

I've already created a scene for when you press the X button (A key on keyboard) and it is perfectly functional:

[spoiler="My Scene_Come"]

#==============================================================================
# **Scene_Come
#------------------------------------------------------------------------------
#  This scene will handle catterpillar "COME" comand input
#==============================================================================

class Scene_Come
 
  def initialize(menu_index = 0)
   @menu_index = menu_index #Store the cursor position
  end 
 
  def main
   
    @background = Spriteset_Map.new #draw background
   
    @upper_window = Window_Comehelp.new
    @upper_window.update(" ")
   
    s1 = "Come over here"
    s2 = "Stay there"

    @come_window = Window_Command.new(320, [s1, s2])
    @come_window.x=160
    @come_window.y=64
    @come_window.back_opacity = 160
    @come_window.index = @menu_index
   
   
   
    # keep updating:
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      if $scene != self
        break
      end # if cond
    end # loop
   
    # execute when exiting the scene
    Graphics.freeze
    @background.dispose
    @upper_window.dispose
    @come_window.dispose
  end
 
  # update method:
 
  def update
   
    @come_window.update
   
    @upper_window.update("Choose an action:")
   
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      $scene = Scene_Map.new
    end
   
    if Input.trigger?(Input::X)
      $game_system.se_play($data_system.cancel_se)
      $scene = Scene_Map.new
    end
   
    if Input.trigger?(Input::C) # if enter is pressed
      case @come_window.index #the index for window is the position of the cursor
        when 0 #starts at 0 because it's an array
          $scene = Scene_Map.new
          $game_switches[23] = true
         
        when 1
          $scene = Scene_Map.new
          $game_switches[23] = false

      end
       
      end
    end
   
 
end #of the scene

   
   
#===================================================
#   Window_Diaryhelp (Upper Window)
#===================================================
class Window_Comehelp < Window_Base 
   
  def initialize
    super(160, 0, 320, 64)
    self.contents = Bitmap.new(width-32, height-32)
    self.contents.font.name = "Arial" 
    self.contents.font.size = 20
  end

  def update(help_text) #Receive argument, show relevant help text in window
    self.contents.clear #Clear the content before displaying new data !
    self.contents.draw_text(0, 0, 180, 32, help_text) #show the content of "help_text" variable
  end

end

#===================================================
#    Window_Diaryhelp ends
#===================================================

def disable_item(index)
@disabled[index] = true
end

[/spoiler]

What I got here basically is disabling the caterpillar depending on the selected command.

What I need is that when I select 'Come over here', the event following me(the other party member, which will be only one) takes the exactsame steps I took and not walk a straight line or be teleported to my location. For example, when I first select 'Stay there' the event stops following me, and even if i walk in circles around trees in the map and end up on the other side, if I select 'Come over here' I want him to follow the exact same footsteps, including walking in circles.

I wonder if someone'll help me!  :o

Thanks in advance!  ;D
Don't click here