[RESOLVED][RMXP] Scrollable/Wrappable maps + Blizz-ABS

Started by Agckuu Coceg, May 01, 2012, 10:06:26 am

Previous topic - Next topic

Agckuu Coceg

May 01, 2012, 10:06:26 am Last Edit: May 07, 2012, 12:07:36 am by Agckuu Coceg
While being on a small part-time work related to RMXP as a game designer, I encountered with a small problem, which is slightly slowed down the development process. I'm used Blizz-ABS as a combat system, but for the original concept it's need to use a script associated with a maps wrap - the use of "map-linker" scripts like Continuous Maps aren't suitable.

Spoiler: ShowHide

#--------------------------------------------------------------------------
#  Game_Temp (edit)
#      Script to check for "_wrap" in the map name.
#--------------------------------------------------------------------------
class Game_Temp

  attr_reader    :map_infos
  attr_reader    :outside_array

  alias wrap_original_game_temp_initialize initialize

  def initialize
    wrap_original_game_temp_initialize
    @map_infos = load_data("Data/MapInfos.rxdata")
    @outside_array=Array.new
    for key in @map_infos.keys
      @outside_array[key]=@map_infos[key].name.include?("_wrap")
    end
    for key in @map_infos.keys
      @map_infos[key] = @map_infos[key].name
      @map_infos[key].delete!("_wrap")
    end
  end

end

#--------------------------------------------------------------------------
#  Game_Map
#--------------------------------------------------------------------------
class Game_Map

  attr_accessor :wrap

  alias wrap_original_game_map_scroll_left scroll_left
  alias wrap_original_game_map_scroll_right scroll_right
  alias wrap_original_game_map_scroll_up scroll_up
  alias wrap_original_game_map_scroll_down scroll_down

# Left
  def scroll_left(distance)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_game_map_scroll_left(distance)
    else
      @display_x = [@display_x - distance].max
    end
  end

# Right
  def scroll_right(distance)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_game_map_scroll_right(distance)
    else
      @display_x = [@display_x + distance].min
    end
  end

# Top
  def scroll_up(distance)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_game_map_scroll_up(distance)
    else
      @display_y = [@display_y - distance].max
    end
  end

# Bottom
  def scroll_down(distance)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_game_map_scroll_down(distance)
    else
      @display_y = [@display_y + distance].min
   end
  end

end

#--------------------------------------------------------------------------
# Game_Player
#--------------------------------------------------------------------------
class Game_Player

  alias wrap_original_game_player_center center

  def center(x, y)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_game_player_center(x, y)
    else
      max_x = ($game_map.width + 20) * 128
      max_y = ($game_map.height + 15) * 128
      $game_map.display_x = [-20 * 128, [x * 128 - CENTER_X, max_x].min].max
      $game_map.display_y = [-15 * 128, [y * 128 - CENTER_Y, max_y].min].max
    end
  end

end

#--------------------------------------------------------------------------
# Check_Coordinates
#--------------------------------------------------------------------------
class Check_Coordinates

#------------------------------------------------------------------------
# Handles left edge
#------------------------------------------------------------------------
  def refresh_left
    unless $game_temp.outside_array[$game_map.map_id]
    else
      if $game_player.real_x == 0
        if Input.press?(Input::LEFT)
          def $game_player.passable?(x, y, d)
            return true
          end
          @left_trigger = true
        end
      end
    end
  end
 
#------------------------------------------------------------------------
# Handles right edge
#------------------------------------------------------------------------
  def refresh_right
    unless $game_temp.outside_array[$game_map.map_id]
    else
      @map_width_max = ($game_map.width - 1) * 128
      if $game_player.real_x == @map_width_max
        if Input.press?(Input::RIGHT)
          def $game_player.passable?(x, y, d)
            return true
          end
          @right_trigger = true
        end
      end
    end
  end

#------------------------------------------------------------------------
# Handles top edge
#------------------------------------------------------------------------
  def refresh_top
    unless $game_temp.outside_array[$game_map.map_id]
    else
      if $game_player.real_y == 0
        if Input.press?(Input::UP)
          def $game_player.passable?(x, y, d)
            return true
          end
          @top_trigger = true
        end
      end
    end
  end

#------------------------------------------------------------------------
# Handles bottom edge
#------------------------------------------------------------------------
  def refresh_bottom
    unless $game_temp.outside_array[$game_map.map_id]
    else
      @map_height_max = ($game_map.height - 1) * 128
      if $game_player.real_y == @map_height_max
        if Input.press?(Input::DOWN)
          def $game_player.passable?(x, y, d)
            return true
          end
          @bottom_trigger = true
        end
      end
    end
  end

#------------------------------------------------------------------------
# Left teleport
#------------------------------------------------------------------------
  def left_trigger
    if @left_trigger == true
      if $game_player.real_x == -128
        $game_player.moveto(($game_map.width - 1), $game_player.y)
        def $game_player.passable?(x, y, d)
          new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
          new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
          unless $game_map.valid?(new_x, new_y)
            return false
          end
          if $DEBUG and Input.press?(Input::CTRL)
            return true
          end
          super
        end
        @left_trigger = false
      end
    end
  end

#------------------------------------------------------------------------
# Right teleport
#------------------------------------------------------------------------
  def right_trigger
    if @right_trigger == true
      if $game_player.real_x == ($game_map.width * 128)
        $game_player.moveto(0, $game_player.y)
        def $game_player.passable?(x, y, d)
          new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
          new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
          unless $game_map.valid?(new_x, new_y)
            return false
          end
          if $DEBUG and Input.press?(Input::CTRL)
            return true
          end
          super
        end
        @right_trigger = false
      end
    end
  end

#------------------------------------------------------------------------
# Top teleport
#------------------------------------------------------------------------
  def top_trigger
    if @top_trigger == true
      if $game_player.real_y == -128
        $game_player.moveto($game_player.x, ($game_map.height - 1))
        def $game_player.passable?(x, y, d)
          new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
          new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
          unless $game_map.valid?(new_x, new_y)
            return false
          end
          if $DEBUG and Input.press?(Input::CTRL)
            return true
          end
          super
        end
        @top_trigger = false
      end
    end
  end

#------------------------------------------------------------------------
# Bottom teleport
#------------------------------------------------------------------------
  def bottom_trigger
    if @bottom_trigger == true
      if $game_player.real_y == ($game_map.height * 128)
        $game_player.moveto($game_player.x, 0)
        def $game_player.passable?(x, y, d)
          new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
          new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
          unless $game_map.valid?(new_x, new_y)
            return false
          end
          if $DEBUG and Input.press?(Input::CTRL)
            return true
          end
          super
        end
        @bottom_trigger = false
      end
    end
  end

end

#--------------------------------------------------------------------------
# Sprite_Duplicate
#--------------------------------------------------------------------------
class Sprite_Duplicate < RPG::Sprite

  attr_accessor :character # @character is the original event
 
  def initialize(viewport, character = nil, x = 0, y = 0)
    @x = x
    @y = y
    super(viewport)
    @character = character
    @z=@character.screen_z
    update
  end

  def update
    super
    if @tile_id != @character.tile_id or
      @character_name != @character.character_name or
      @character_hue != @character.character_hue
        @tile_id = @character.tile_id
        @character_name = @character.character_name
        @character_hue = @character.character_hue
        if @tile_id >= 384
          self.bitmap = RPG::Cache.tile($game_map.tileset_name, @tile_id, @character.character_hue)
          self.src_rect.set(0, 0, 32, 32)
          self.ox = 16
          self.oy = 32
        else
          self.bitmap = RPG::Cache.character(@character.character_name, @character.character_hue)
          @cw = bitmap.width / 4
          @ch = bitmap.height / 4
          self.ox = @cw / 2
          self.oy = @ch
        end
    end
    self.visible = (not @character.transparent)
    if @tile_id == 0
      sx = @character.pattern * @cw
      sy = (@character.direction - 2) / 2 * @ch
      self.src_rect.set(sx, sy, @cw, @ch)
    end
    # The coordinates of the duplicate event sprite. They are relative to the original event,
    # so the duplicates will move and act as the original does; except the z coordinate,
    # as when the original sprite would be of range, the duplicate would not appear.
    self.x = @character.screen_x + @x
    self.y = @character.screen_y + @y
    self.z = @z
    self.opacity = @character.opacity
    self.blend_type = @character.blend_type
    self.bush_depth = @character.bush_depth
    if @character.animation_id != 0
      animation = $data_animations[@character.animation_id]
      animation(animation, true)
      @character.animation_id = 0
    end
  end

end

#--------------------------------------------------------------------------
# Sprite_Character
#--------------------------------------------------------------------------
class Sprite_Character < RPG::Sprite

  alias wrap_original_sprite_character_initialize initialize
  alias wrap_original_sprite_character_update update

  def initialize(viewport, character = nil)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_sprite_character_initialize(viewport, character)
    else
      @character = character
      super(viewport)
      if $game_map.wrap == nil
        $game_map.wrap = []
      end
      # 8 duplicates are created, stored in the $game_map.wrap array
      if character.is_a?(Game_Event)
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, (-$game_map.width * 32), 0))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, 0, (-$game_map.height * 32)))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, ($game_map.width * 32), 0))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, 0, ($game_map.height * 32)))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, (-$game_map.width * 32), (-$game_map.height * 32)))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, ($game_map.width * 32), ($game_map.height * 32)))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, (-$game_map.width * 32), ($game_map.height * 32)))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, ($game_map.width * 32), (-$game_map.height * 32)))
      end
      wrap_original_sprite_character_initialize(viewport, @character)
    end
  end

#------------------------------------------------------------------------
# Updates each sprite in the $game_map.wrap array
#------------------------------------------------------------------------
  def update
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_sprite_character_update
    else
      wrap_original_sprite_character_update
      if $game_map.wrap != [] and character.is_a?(Game_Player)
        for duplicate in $game_map.wrap
          if duplicate != nil
            duplicate.update
          end
        end
      end
    end
  end

end

#--------------------------------------------------------------------------
# Spriteset_Map
#--------------------------------------------------------------------------

class Spriteset_Map

  alias wrap_original_spriteset_map_initialize initialize

  def initialize
    $game_map.wrap=nil
    wrap_original_spriteset_map_initialize
  end
 
end

#--------------------------------------------------------------------------
# Scene_Save edit
# Prevent save errors
#--------------------------------------------------------------------------
class Scene_Save < Scene_File

  alias wrap_original_scene_save_write_save_data write_save_data

  def write_save_data(file)
    $game_map.wrap = nil
    wrap_original_scene_save_write_save_data(file)
  end
 
end

#--------------------------------------------------------------------------
# Scene Map
#--------------------------------------------------------------------------
class Scene_Map

  $coordinate_check = Check_Coordinates.new
 
  alias wrap_original_scene_map_update update
 
  def update
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_scene_map_update
    else
      $coordinate_check.refresh_left
      $coordinate_check.refresh_right
      $coordinate_check.refresh_top
      $coordinate_check.refresh_bottom
      $coordinate_check.left_trigger
      $coordinate_check.right_trigger
      $coordinate_check.top_trigger
      $coordinate_check.bottom_trigger
      wrap_original_scene_map_update
    end
  end
end



However, its compatibility with BABS isn't too good, but other similar scripts for RMXP with the needed effect simply isn't find.

Description of problems:

1) The scrolling of wrapped map isn't going on the standard way - when player approaches to the end of the map, camera centered on the player and showing a necessary part of the map in the window, but after the transfer to the other end of map camera sharply fast scrolls to the standard RMXP mode at this positions.
2) Sprite_Character class isn't good on compatibility - displaying of enemy sprites on the visible screen-part of the wrapped map doesn't happen - they appear only after the transfer to the other end of the map.

Other problems associated with the scripting part wasn't detected. That script is located above the BABS.
I'm not retarded, but I'm busy. Sorry for patience.


Agckuu Coceg



Guys, I'm absolutely contraindicated to be lazy and I'm still have time.
I'm not retarded, but I'm busy. Sorry for patience.


LiTTleDRAgo

1. place below blizz abs

module BlizzABS
  class Controller
    alias drg131_center center unless method_defined?(:drg131_center)
    def center(x, y, flag = false)
      unless $game_temp.outside_array[$game_map.map_id]
        drg131_center(x, y, flag)
      else
        pix = flag ? $BlizzABS.pixel : 1
        max_x = ($game_map.width + 20) * 128
        max_y = ($game_map.height + 15) * 128
        $game_map.display_x = [-20 * 128, [(x * 128 / pix) - CX, max_x].min].max
        $game_map.display_y = [-15 * 128, [(y * 128 / pix) - CY, max_y].min].max
      end
    end
  end
end


2. place below your script but above blizz abs

class Sprite_Character < RPG::Sprite
  alias drg131_init initialize unless method_defined?(:drg131_init)
  def initialize(v, c = nil)
    if $game_temp.outside_array[$game_map.map_id]
      super(v)
      $game_map.wrap = [] if $game_map.wrap.nil?
      wh = [$game_map.width * 32, $game_map.height * 32]
      if character.is_a?(Map_Battler)
        $game_map.wrap.push(Sprite_Duplicate.new(v, c, (-wh[0]), 0))
        $game_map.wrap.push(Sprite_Duplicate.new(v, c, 0, (-wh[1])))
        $game_map.wrap.push(Sprite_Duplicate.new(v, c, (wh[0]), 0))
        $game_map.wrap.push(Sprite_Duplicate.new(v, c, 0, (wh[1])))
        $game_map.wrap.push(Sprite_Duplicate.new(v, c, (-wh[0]), (-wh[1])))
        $game_map.wrap.push(Sprite_Duplicate.new(v, c, (wh[0]), (wh[1])))
        $game_map.wrap.push(Sprite_Duplicate.new(v, c, (-wh[0]), (wh[1])))
        $game_map.wrap.push(Sprite_Duplicate.new(v, c, (wh[0]), (-wh[1])))
      end
    end
    drg131_init(v, c)
  end
end

Agckuu Coceg

May 07, 2012, 12:07:10 am #3 Last Edit: May 07, 2012, 12:08:15 am by Agckuu Coceg
Mission completed. GT, LiTTleDRAgo.
I'm not retarded, but I'm busy. Sorry for patience.