Jump to content
New account registrations are disabed. This website is now an archive. Read more here.
  • 0
UnrealJohny

Mode 7 Trouble.

Question

Hey i'm having trouble with mode 7. it gives me an error, and i tried everything to correct but it doesn't work.

 

this is the script i use:

 

#==============================================================================

# Mode 7

# Written by: MGCaladtogel

# Version: unknown

# English version date: 21.5.2007

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=

# - instruction rewritten by Blizzard for easier understanding.

# - slightly optimized by Blizzard

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=

#

# Introduction:

#

# This script can display maps in a type of 3D with depth. It has a low lag

# factor.

#

#

# Instructions:

#

# In the editor in the lower left corner is the map list of the maps you

# are using in your game. You have several options: If you want to make a

# map use Mode 7 you need to ADD one or more of these text commands to the

# map's name. Those commands should not appear in the map's name if using

# a location display script. The options you have are the following:

#

# [M7] : to activate Mode7

# [#XX] : XX is the slant angle (in degree). Default value is 0 (normal maps)

# [Y] : Y-map looping

# [X] : X-map looping. This option needs resources (lower fps).

# [A] : animated autotiles (with 4 patterns). This option increases

# significantly the loading time, so it may crash for large maps

# (SystemStackError)

# [C] : to center the map on the hero (even for small maps)

# [P] : to have a fixed panorama

# [H] : to have a white horizon

# [OV] : Overworld Sprite Resize (a Mewsterus's script feature)

#

# Alternatively you can define prepared settings that will be triggered with

# every map that has that specific text included in its name. See the

# "MODE7_SETTINGS" below to prepare your settings.

#

#

# Control commands:

#

# You can change the settings on the map in-game and use a couple of

# additional commands. If you want to use one of those commands, use a "Call

# Script" event command and type one of the following commands into the text

# input window:

#

# 1. $scene.spriteset.tilemap.mode7_set(ANGLE)

# 2. $scene.spriteset.tilemap.mode7_set_p(ANGLE)

# 3. $scene.spriteset.tilemap.mode7_redraw

# 4. $game_system.map_opacity = VALUE

# 5. $game_system.map_gradual_opacity = VALUE

# 6. $game_system.map_tone = Color.new(RED, GREEN, BLUE)

# 7. $game_system.map_gradual_tone = Tone.new(RED, GREEN, BLUE, GREY)

# 8. $game_system.horizon = VALUE

# 9. $game_system.reset

#

# 1. Redraws the map with a new angle which is specified by ANGLE

# 2. Redraws the map progressively with a new angle which is specified by

# ANGLE

# 3. Redraws the map (can be useful with the following commands)

# 4. Defines the opacity for Mode7 maps (it needs to redraw)

# 5. Defines a gradual opacity for Mode7 maps (it needs to redraw)

# (it bugs with horizontal looping)

# 6. Defines the tone for Mode7 maps (it needs to redraw)

# 7. Defines a gradual tone for Mode7 maps (it needs to redraw)

# 8. Defines the view's distance (default : 960) (it needs to redraw)

# 9. Re-initialize the previous options

#

#

# Additional commands:

#

# 1) If you wish to obtain flat events, add a comment in the event's code

# and type in the word "Flat" without the double quotes).

# 2) You can handle the height of vertical events by adding a comment to the

# event's code with the text "Height X" (without the double quotes).

# Replace X with the height value. Example: If you use Height 1.5, then

# the event will appear floating above its position in a height of 1.5 map

# squares (48 pixels).

#

#==============================================================================

 

# hash for predefined settings

MODE7_SETTINGS = {}

# access for map names

$data_maps = load_data("Data/MapInfos.rxdata")

 

#---------------------#

# START Configuration #

#---------------------#

 

# The map is drawn from all the tiles of the three layers. You can define tiles

# which are not being drawn flat, but vertical which creates the impression

# that the objects would be standing upright.

# To define such tiles, add one or more terrain tags to this array and separate

# them with commas. In your tileset database gives those specific tiles one of

# those terrain tags and the tile will be drawn vertically.

VERTICAL_TILE_TERRAIN_TAGS = [1, 2]

 

# You can create packages of settings which are automatically triggered if a

# map name includes the text corresponding to the setting. Use following

# template to create such settings:

#

# MODE7_SETTINGS['CORRESPONDING_TEXT'] = ['SETTING_1', 'SETTING_2', ...]

#

# CORRESPONDING_TEXT - text in map name

# SETTING - one of the settings from the instructions WITHOUT the

# [ and ] brackets (i.e. instead of [H], use just H)

#

# You can add as many settings as you want. There are two predefined settings

# to make you understand easier how it works.

 

MODE7_SETTINGS['World Map'] = ['#60', 'X', 'Y', 'H', 'P']

MODE7_SETTINGS['Smallslant'] = ['#20', 'A', 'S']

 

#---------------------#

# END Configuration #

#---------------------#

 

#============================================================================

# ■ Game_System

#----------------------------------------------------------------------------

# Add attributes to this class

#============================================================================

 

class Game_System

attr_accessor :mode7 # false : normal map / true : mode 7

attr_accessor :loop_x # true : horizontal-looping map

attr_accessor :loop_y # true : vertical-looping map

attr_accessor :always_scroll # true : to center the camera around the hero

attr_accessor :map_tone # mode7 map's tone (Color)

attr_accessor :map_opacity # mode7 map's opacity (0..255)

attr_accessor :animated # true : animated autotiles for mode7 maps

attr_accessor :white_horizon # true : white line horizon for mode7 maps

attr_accessor :angle # mode7 map's slant angle (in degree)

attr_accessor :horizon # horizon's distance

attr_accessor :fixed_panorama # true : to fix the panorama (no scrolling any more)

attr_accessor :ov # true : Overworld Sprite Resize (smaller hero's sprite)

attr_accessor :ov_zoom # resize's value with ov

attr_accessor :map_gradual_opacity # mode7 map's gradual opacity (0..255)

attr_accessor :map_gradual_tone # mode7 map's gradual tone (Color)

#--------------------------------------------------------------------------

# * Object Initialization

#--------------------------------------------------------------------------

alias initialize_mode7_game_system initialize

def initialize

initialize_mode7_game_system

init_mode7

end

#--------------------------------------------------------------------------

# * Mode 7 Initialization

#--------------------------------------------------------------------------

def init_mode7

self.mode7 = true

self.loop_x = false

self.loop_y = false

self.always_scroll = false

self.animated = false

self.white_horizon = false

self.angle = 0

self.fixed_panorama = false

self.ov = false

self.ov_zoom = 0.6

reset

end

#--------------------------------------------------------------------------

# * Reset the values for opacity, tone and horizon's distance

#--------------------------------------------------------------------------

def reset

self.map_opacity = 255

self.map_tone = Color.new(0,0,0,0)

self.horizon = 960 # default value, equivalent to 30 tiles

self.map_gradual_opacity = 0

self.map_gradual_tone = Tone.new(0,0,0,0)

end

end

 

#============================================================================

# ■ Tilemap_mode7

#----------------------------------------------------------------------------

# This new Tilemap class handles the drawing of a mode7 map

#============================================================================

 

class Tilemap_mode7

attr_accessor :maps_list # contains map's graphics

attr_accessor :map_ground # original map's graphic to handle flat events

attr_accessor :tone_values # tone values for each line (Hash)

attr_accessor :opacity_values # opacity values for each line (Hash)

#--------------------------------------------------------------------------

# * Object Initialization

# viewport : viewport

#--------------------------------------------------------------------------

def initialize(viewport)

@id = $game_map.map_id # map's ID : to load or save the map in Cache

@maps_list = [] # contains map's drawings (Bitmap)

@disp_y = $game_map.display_y # @disp_y : tilemap's display_y

@disp_x = $game_map.display_x # @disp_x : tilemap's display_x

@height = 32 * $game_map.height # @height : map's height (in pixel)

@width = 32 * $game_map.width # @width : map's width (in pixel)

$game_temp.height = @height

# map's drawings are loaded if already in Cache

if RPG::Cache_Carte.in_cache(@id)

@map = RPG::Cache_Carte.load(@id)

@maps_list.push(@map)

@map_ground = RPG::Cache_Carte.load(@id, 4) # to handle flat events

if $game_system.animated

@map_2 = RPG::Cache_Carte.load(@id, 1)

@map_3 = RPG::Cache_Carte.load(@id, 2)

@map_4 = RPG::Cache_Carte.load(@id, 3)

@maps_list.push(@map_2)

@maps_list.push(@map_3)

@maps_list.push(@map_4)

end

else # draw the map and save it in the Cache

draw_map

end

# create vertical elements from tiles

data_V = Data_Vertical_Sprites.new(viewport)

# @sprites_V : list of vertical sprites (Sprite_V)

@sprites_V = data_V.list_sprites_V

# @sprites_V_animated : list of animated vertical sprites (Sprite_V)

@sprites_V_animated = data_V.list_sprites_V_animated

@angle = $game_system.angle # map's slant angle (in degree)

@distance_h = 480 # distance between the map's center and the vanishing point

@pivot = 256 # screenline's number of the slant's pivot

@index_animated = 0 # 0..3 : index of animated tiles pattern

@viewport = viewport

@tone_values = {} # list of the tone values for each line

@opacity_values = {} # list of the opacity values for each line

init_sprites(@angle) # initialize screenlines sprites

end

#--------------------------------------------------------------------------

# * Dispose

#--------------------------------------------------------------------------

def dispose

# dispose of @sprites (scanlines), @sprites_V (vertical_sprites), and

# @sprites_loop_x (additional scanlines for horizontal looping)

(@sprites + @sprites_V + @sprites_loop_x).each {|sprite| sprite.dispose}

[@sprites, @sprites_V, @sprites_loop_x, @sprites_V_animated,

@maps_list].each {|obj| obj.clear}

$game_system.angle = @angle

end

#--------------------------------------------------------------------------

# * Increase slant's angle

#--------------------------------------------------------------------------

def increase_angle

return if @angle == 88

@angle += 2

@angle = 88 if @angle > 88

@sprites.clear

@sprites_loop_x.clear

init_sprites(@angle) # reinitialize screenlines sprites

end

#--------------------------------------------------------------------------

# * Decrease slant's angle

#--------------------------------------------------------------------------

def decrease_angle

return if @angle == 0

@angle -= 2

@angle = 0 if @angle < 0

@sprites.clear

@sprites_loop_x.clear

init_sprites(@angle) # reinitialize screenlines sprites

end

#--------------------------------------------------------------------------

# * Slide from the current angle into the target value

# value : target angle's value (in degree)

#--------------------------------------------------------------------------

def mode7_set_p(value)

while value > @angle

increase_angle

update

Graphics.update

end

while value < @angle

decrease_angle

update

Graphics.update

end

end

#--------------------------------------------------------------------------

# * Redraw the map instantaneously with the new slant angle's value

# value : target angle's value (in degree)

#--------------------------------------------------------------------------

def mode7_set(value)

if value < 0

@angle = 0

elsif value > 89

@angle = 89

else

@angle = value

end

@sprites.clear

@sprites_loop_x.clear

init_sprites(@angle) # reinitialize screenlines sprites

update

Graphics.update

end

#--------------------------------------------------------------------------

# * Reinitialize screenlines sprites

#--------------------------------------------------------------------------

def mode7_redraw

@sprites.clear

@sprites_loop_x.clear

init_sprites(@angle) # reinitialize scanlines

update

Graphics.update

end

#--------------------------------------------------------------------------

# * Create sprites equivalent to scanlines

# value : target angle's value (in degree)

#--------------------------------------------------------------------------

def init_sprites(angle)

@horizon = $game_system.horizon

angle_rad = (Math::PI * angle) / 180 # angle in radian

@sprites = [] # list of the scanlines sprites (Sprite)

@sprites_loop_x = [] # list of the additionnal sprites (for X-looping)

cos_angle = Math.cos(angle_rad)

sin_angle = Math.sin(angle_rad)

# save values in $game_temp

$game_temp.distance_h = @distance_h

$game_temp.pivot = @pivot

$game_temp.cos_angle = cos_angle

$game_temp.sin_angle = sin_angle

# h0, z0 : intermediate values

h0 = (- @distance_h * @pivot * cos_angle).to_f /

(@distance_h + @pivot * sin_angle) + @pivot

z0 = @distance_h.to_f / (@distance_h + @pivot * sin_angle)

$game_temp.slope_value = (1.0 - z0) / (@pivot - h0)

$game_temp.corrective_value = 1.0 - @pivot * $game_temp.slope_value

last_line = - @pivot - @horizon # last_line : the highest line that is drawn

height_limit = (@distance_h * last_line * cos_angle).to_f /

(@distance_h - last_line * sin_angle) + @pivot # the line corresponding to

# the last_line in the warped reference = horizon's line

$game_temp.height_limit = height_limit

# constant to handle gradual opacity

k2lim = ((@distance_h * last_line).to_f /

(@distance_h * cos_angle + last_line * sin_angle)).to_i

# one sprite is created for each screenline

(0..479).each {|j|

next if j < height_limit # if the line is further than the horizon's line,

# no sprite is created

i = j - @pivot # y-reference is the pivot's line

sprite = Sprite.new(@viewport)

sprite.x = 320 # x-reference is the vertical line in the middle of the screen

sprite.y = j

sprite.z = - 99999 # map must not mask vertical elements

sprite.y_origin_bitmap = (@distance_h * i).to_f /

(@distance_h * cos_angle + i * sin_angle) + @pivot

sprite.y_origin_bitmap_i = (sprite.y_origin_bitmap + 0.5).to_i

sprite.y_origin_bitmap_i %= @height if $game_system.loop_y

sprite.zoom_x = $game_temp.slope_value * j + $game_temp.corrective_value

sprite.length = 2 + (640.to_f / sprite.zoom_x).to_i

sprite.x_origin_bitmap_i = ((642 - sprite.length) / 2)

sprite.x_origin_bitmap_i %= @width if $game_system.loop_x

sprite.x_origin_bitmap = (sprite.x_origin_bitmap_i).to_f

sprite.ox = sprite.length / 2

sprite.bitmap = @map

# horizontal translation to center around the hero

if @disp_x != 0

sprite.x_origin_bitmap += @disp_x / 4

sprite.x_origin_bitmap_i = (sprite.x_origin_bitmap).to_i

sprite.x_origin_bitmap_i %= @width if $game_system.loop_x

end

# vertical translation to center around the hero

if @disp_y != 0

sprite.y_origin_bitmap += @disp_y / 4

sprite.y_origin_bitmap_i = (sprite.y_origin_bitmap + 0.5).to_i

sprite.y_origin_bitmap_i %= @height if $game_system.loop_y

end

# handle opacity and tone

k2 = ((@distance_h * i).to_f /

(@distance_h * cos_angle + i * sin_angle)).to_i

k2 = 0 if k2 > 0

k_red = (- k2.to_f/k2lim * $game_system.map_gradual_tone.red).to_i

k_green = (- k2.to_f/k2lim * $game_system.map_gradual_tone.green).to_i

k_blue = (- k2.to_f/k2lim * $game_system.map_gradual_tone.blue).to_i

k_gray = (- k2.to_f/k2lim * $game_system.map_gradual_tone.gray).to_i

k2 = (- k2.to_f/k2lim * $game_system.map_gradual_opacity).to_i

sprite.tone = Tone.new(k_red, k_green, k_blue, k_gray)

sprite.opacity = 255 - k2

sprite.opacity *= ($game_system.map_opacity).to_f / 255

sprite.color = $game_system.map_tone

# white horizon's line

k = 500 / (j - height_limit)

if $game_system.white_horizon

tone_red = sprite.tone.red + k

tone_green = sprite.tone.green + k

tone_blue = sprite.tone.blue + k

tone_gray = sprite.tone.gray + k

sprite.tone = Tone.new(tone_red, tone_green, tone_blue, tone_gray)

end

@tone_values[j] = sprite.tone

@opacity_values[j] = sprite.opacity

# set sprite's graphics

sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,

sprite.length, 1)

@sprites.push(sprite)

if $game_system.loop_x && j < @pivot

# additional sprite to handle horizontal looping

sprite2 = Sprite.new(@viewport)

sprite2.x = 320

sprite2.y = j

sprite2.z = - 99999

sprite2.y_origin_bitmap = sprite.y_origin_bitmap

sprite2.y_origin_bitmap_i = sprite.y_origin_bitmap_i

sprite2.zoom_x = sprite.zoom_x

sprite2.length = sprite.length

sprite2.x_origin_bitmap_i = sprite.x_origin_bitmap_i - @width

sprite2.x_origin_bitmap = sprite.x_origin_bitmap_i - @width

sprite2.ox = sprite.ox

sprite2.bitmap = @map

sprite2.opacity = sprite.opacity

sprite2.color = sprite.color

sprite2.tone = sprite.tone

sprite2.src_rect.set(sprite2.x_origin_bitmap_i, sprite2.y_origin_bitmap_i,

sprite2.length, 1)

@sprites_loop_x.push(sprite2)

end}

end

#--------------------------------------------------------------------------

# * Update the screenlines sprites and the vertical sprites

# compare tilemap's display with map's display

#--------------------------------------------------------------------------

def update

# update screenlines sprites

if @disp_y < $game_map.display_y

difference = $game_map.display_y - @disp_y

@disp_y += difference

(@sprites + @sprites_loop_x).each {|sprite|

sprite.y_origin_bitmap += difference.to_f / 4

sprite.y_origin_bitmap_i = (sprite.y_origin_bitmap+0.5).to_i

sprite.y_origin_bitmap_i %= @height if $game_system.loop_y

sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,

sprite.length, 1)}

end

if @disp_y > $game_map.display_y

difference = @disp_y - $game_map.display_y

@disp_y -= difference

(@sprites + @sprites_loop_x).each {|sprite|

sprite.y_origin_bitmap -= difference.to_f / 4

sprite.y_origin_bitmap_i = (sprite.y_origin_bitmap+0.5).to_i

sprite.y_origin_bitmap_i %= @height if $game_system.loop_y

sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,

sprite.length, 1)}

end

if @disp_x < $game_map.display_x

difference = $game_map.display_x - @disp_x

@disp_x += difference

@sprites.each {|sprite|

sprite.x_origin_bitmap += difference.to_f / 4

sprite.x_origin_bitmap_i = (sprite.x_origin_bitmap).to_i

sprite.x_origin_bitmap_i %= @width if $game_system.loop_x

sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,

sprite.length, 1)}

@sprites_loop_x.each {|sprite|

sprite.x_origin_bitmap += difference.to_f / 4

sprite.x_origin_bitmap_i = (sprite.x_origin_bitmap).to_i

sprite.x_origin_bitmap_i %= @width

sprite.x_origin_bitmap_i -= @width

sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,

sprite.length, 1)}

end

if @disp_x > $game_map.display_x

difference = @disp_x - $game_map.display_x

@disp_x -= difference

@sprites.each {|sprite|

sprite.x_origin_bitmap -= difference.to_f / 4

sprite.x_origin_bitmap_i = (sprite.x_origin_bitmap).to_i

sprite.x_origin_bitmap_i %= @width if $game_system.loop_x

sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,

sprite.length, 1)}

@sprites_loop_x.each {|sprite|

sprite.x_origin_bitmap -= difference.to_f / 4

sprite.x_origin_bitmap_i = (sprite.x_origin_bitmap).to_i

sprite.x_origin_bitmap_i %= @width

sprite.x_origin_bitmap_i -= @width

sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,

sprite.length, 1)}

end

# update vertical sprites

@sprites_V.each {|sprite| sprite.update}

end

#--------------------------------------------------------------------------

# * Update animation for animated tiles

#--------------------------------------------------------------------------

def update_animated

@index_animated += 1

@index_animated %= 4

map = @maps_list[@index_animated]

# update screenlines sprites

(@sprites + @sprites_loop_x).each {|sprite|

sprite.bitmap = map

sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,

sprite.length, 1)}

# update vertical sprites

@sprites_V_animated.each {|sprite| sprite.update_animated(@index_animated)}

end

#--------------------------------------------------------------------------

# * Create bitmaps representing the map

#--------------------------------------------------------------------------

def draw_map

data = $game_map.data

# Table where animated tiles are flagged

data_animated = Table.new($game_map.width, $game_map.height)

# bigger maps to handle horizontal looping

offset = ($game_system.loop_x ? 640 : 0)

@map = Bitmap.new(@width + offset, @height)

@maps_list.push(@map)

rect = Rect.new(0, 0, 32, 32)

# create autotiles graphics

RPG::Cache.clear

@autotiles = []

(0..6).each {|i|

autotile_name = $game_map.autotile_names

fichier = RPG::Cache.autotile(autotile_name)

(0..3).each {|l|

data_autotile = Data_Autotiles.new(fichier,l)

data_autotile.number = 4*i + l

RPG::Cache.save_autotile(data_autotile, data_autotile.number)

@autotiles.push(data_autotile)}}

# scan map's data to draw it

(0...$game_map.height).each {|i| (0...$game_map.width).each {|j|

data_animated[j, i] = 0

# tile's ID for the first layer

value1 = data[j, i, 0].to_i

# prevent from drawing a vertical tile

value1 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value1]) ?

0 : value1)

# value1 != 0

if value1 != 0

# tile's ID for the second layer

value2 = data[j, i, 1].to_i

# prevent from drawing a vertical tile

value2 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value2]) ?

0 : value2)

# tile's ID for the third layer

value3 = data[j, i, 2].to_i

# prevent from drawing a vertical tile

value3 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value3]) ?

0 : value3)

# value1 != 0, value2 = 0

if value2 == 0

# value1 != 0, value2 = 0, value3 = 0

if value3 == 0

# value1 associated with a normal autotile

if value1 > 383

bitmap = RPG::Cache.tile($game_map.tileset_name, value1, 0)

@map.blt(32*j, 32*i, bitmap, rect)

if $game_system.loop_x && j.between?(0, 19)

@map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)

end

# value1 associated with an autotile

else

num = 4*((value1 / 48) - 1)

bitmap = RPG::Cache.autotile_base(num, value1)

if @autotiles[num].animated

data_animated[j, i] = 1

end

@map.blt(32*j, 32*i, bitmap, rect)

if $game_system.loop_x && j.between?(0, 19)

@map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)

end

end

# value1 != 0, value2 = 0, value3 != 0

else

bitmap = RPG::Cache_Tile.load(value1, value3)

# value1 associated with an autotile

if value1 < 384

num = 4*((value1 / 48) - 1)

data_animated[j, i] = 1 if @autotiles[num].animated

end

# value3 associated with an autotile

if value3 < 384

num = 4*((value3 / 48) - 1)

data_animated[j, i] = 1 if @autotiles[num].animated

end

@map.blt(32*j, 32*i, bitmap, rect)

if $game_system.loop_x && j.between?(0, 19)

@map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)

end

end

# value1 != 0, value2 != 0, value3 = 0

elsif value3 == 0

bitmap = RPG::Cache_Tile.load(value1, value2)

# value1 associated with an autotile

if value1 < 384

num = 4*((value1 / 48) - 1)

data_animated[j, i] = 1 if @autotiles[num].animated

end

# value2 associated with an autotile

if value2 < 384

num = 4*((value2 / 48) - 1)

data_animated[j, i] = 1 if @autotiles[num].animated

end

@map.blt(32*j, 32*i, bitmap, rect)

if $game_system.loop_x && j.between?(0, 19)

@map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)

end

# value1 != 0, value2 != 0, value3 != 0

else

bitmap = RPG::Cache_Tile.load2(value1, value2, value3)

# value1 associated with an autotile

if value1 < 384

num = 4*((value1 / 48) - 1)

data_animated[j, i] = 1 if @autotiles[num].animated

end

# value2 associated with an autotile

if value2 < 384

num = 4*((value2 / 48) - 1)

data_animated[j, i] = 1 if @autotiles[num].animated

end

# value3 associated with an autotile

if value3 < 384

num = 4*((value3 / 48) - 1)

data_animated[j, i] = 1 if @autotiles[num].animated

end

@map.blt(32*j, 32*i, bitmap, rect)

if $game_system.loop_x && j.between?(0, 19)

@map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)

end

end

# value1 = 0

else

value2 = data[j, i, 1].to_i

value2 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value2]) ?

0 : value2)

value3 = data[j, i, 2].to_i

value3 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value3]) ?

0 : value3)

# value1 = 0, value2 = 0

if value2 == 0

# value1 = 0, value2 = 0, value3 != 0

if value3 != 0

# value3 associated with a normal tile

if value3 > 383

bitmap = RPG::Cache.tile($game_map.tileset_name, value3, 0)

@map.blt(32*j, 32*i, bitmap, rect)

if $game_system.loop_x && j.between?(0, 19)

@map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)

end

# value3 associated with an autotile

else

num = 4*((value3 / 48) - 1)

bitmap = RPG::Cache.autotile_base(num, value3)

if @autotiles[num].animated

data_animated[j, i] = 1

end

@map.blt(32*j, 32*i, bitmap, rect)

if $game_system.loop_x && j.between?(0, 19)

@map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)

end

end

end

# value1 = 0, value2 != 0, value3 = 0

elsif value3 == 0

# value2 associated with a normal tile

if value2 > 383

bitmap = RPG::Cache.tile($game_map.tileset_name, value2, 0)

@map.blt(32*j, 32*i, bitmap, rect)

if $game_system.loop_x && j.between?(0, 19)

@map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)

end

# value2 associated with an autotile

else

num = 4*((value2 / 48) - 1)

bitmap = RPG::Cache.autotile_base(num, value2)

if @autotiles[num].animated

data_animated[j, i] = 1

end

@map.blt(32*j, 32*i, bitmap, rect)

if $game_system.loop_x && j.between?(0, 19)

@map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)

end

end

# value1 = 0, value2 != 0, value3 != 0

else

bitmap = RPG::Cache_Tile.load(value2, value3)

# value2 associated with an autotile

if value2 < 384

num = 4*((value2 / 48) - 1)

data_animated[j, i] = 1 if @autotiles[num].animated

end

# value3 associated with an autotile

if value3 < 384

num = 4*((value3 / 48) - 1)

data_animated[j, i] = 1 if @autotiles[num].animated

end

@map.blt(32*j, 32*i, bitmap, rect)

if $game_system.loop_x && j.between?(0, 19)

@map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)

end

end

end}}

# save the map's drawing in the Cache

RPG::Cache_Carte.save(@id, @map)

@map_ground = @map.clone

# save a copy of the map to handle flat events

RPG::Cache_Carte.save(@id, @map_ground, 4)

return if !$game_system.animated

# create 3 other maps in case of animated tiles

@map_2 = @map.clone

@map_3 = @map.clone

@map_4 = @map.clone

@maps_list.push(@map_2)

@maps_list.push(@map_3)

@maps_list.push(@map_4)

(0...$game_map.height).each {|i| (0...$game_map.width).each {|j|

next if data_animated[j, i].to_i == 0

# modify the tile if it is flagged as animated

value1 = data[j, i, 0].to_i

value2 = data[j, i, 1].to_i

value3 = data[j, i, 2].to_i

# prevent from drawing a vertical tile

value1 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value3]) ?

0 : value3)

value2 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value3]) ?

0 : value3)

value3 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value3]) ?

0 : value3)

if value1 != 0

if value2 == 0

if value3 == 0

num = 4*((value1 / 48) - 1)

bitmap_2 = RPG::Cache.autotile_base(num+1, value1)

bitmap_3 = RPG::Cache.autotile_base(num+2, value1)

bitmap_4 = RPG::Cache.autotile_base(num+3, value1)

@map_2.blt(32*j, 32*i, bitmap_2, rect)

@map_3.blt(32*j, 32*i, bitmap_3, rect)

@map_4.blt(32*j, 32*i, bitmap_4, rect)

if $game_system.loop_x && j.between?(0, 19)

@map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)

@map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)

@map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)

end

else

bitmap_2 = RPG::Cache_Tile.load(value1, value3, 1)

bitmap_3 = RPG::Cache_Tile.load(value1, value3, 2)

bitmap_4 = RPG::Cache_Tile.load(value1, value3, 3)

@map_2.blt(32*j, 32*i, bitmap_2, rect)

@map_3.blt(32*j, 32*i, bitmap_3, rect)

@map_4.blt(32*j, 32*i, bitmap_4, rect)

if $game_system.loop_x && j.between?(0, 19)

@map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)

@map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)

@map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)

end

end

elsif value3 == 0

bitmap_2 = RPG::Cache_Tile.load(value1, value2, 1)

bitmap_3 = RPG::Cache_Tile.load(value1, value2, 2)

bitmap_4 = RPG::Cache_Tile.load(value1, value2, 3)

@map_2.blt(32*j, 32*i, bitmap_2, rect)

@map_3.blt(32*j, 32*i, bitmap_3, rect)

@map_4.blt(32*j, 32*i, bitmap_4, rect)

if $game_system.loop_x && j.between?(0, 19)

@map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)

@map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)

@map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)

end

else

bitmap_2 = RPG::Cache_Tile.load2(value1, value2, value3, 1)

bitmap_3 = RPG::Cache_Tile.load2(value1, value2, value3, 2)

bitmap_4 = RPG::Cache_Tile.load2(value1, value2, value3, 3)

@map_2.blt(32*j, 32*i, bitmap_2, rect)

@map_3.blt(32*j, 32*i, bitmap_3, rect)

@map_4.blt(32*j, 32*i, bitmap_4, rect)

if $game_system.loop_x && j.between?(0, 19)

@map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)

@map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)

@map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)

end

end

elsif value2 != 0

if value3 == 0

num = 4*((value2 / 48) - 1)

bitmap_2 = RPG::Cache.autotile_base(num+1, value2)

bitmap_3 = RPG::Cache.autotile_base(num+2, value2)

bitmap_4 = RPG::Cache.autotile_base(num+3, value2)

@map_2.blt(32*j, 32*i, bitmap_2, rect)

@map_3.blt(32*j, 32*i, bitmap_3, rect)

@map_4.blt(32*j, 32*i, bitmap_4, rect)

if $game_system.loop_x && j.between?(0, 19)

@map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)

@map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)

@map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)

end

else

bitmap_2 = RPG::Cache_Tile.load(value2, value3, 1)

bitmap_3 = RPG::Cache_Tile.load(value2, value3, 2)

bitmap_4 = RPG::Cache_Tile.load(value2, value3, 3)

@map_2.blt(32*j, 32*i, bitmap_2, rect)

@map_3.blt(32*j, 32*i, bitmap_3, rect)

@map_4.blt(32*j, 32*i, bitmap_4, rect)

if $game_system.loop_x && j.between?(0, 19)

@map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)

@map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)

@map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)

end

end

elsif value3 != 0

num = 4*((value3 / 48) - 1)

bitmap_2 = RPG::Cache.autotile_base(num+1, value3)

bitmap_3 = RPG::Cache.autotile_base(num+2, value3)

bitmap_4 = RPG::Cache.autotile_base(num+3, value3)

@map_2.blt(32*j, 32*i, bitmap_2, rect)

@map_3.blt(32*j, 32*i, bitmap_3, rect)

@map_4.blt(32*j, 32*i, bitmap_4, rect)

if $game_system.loop_x && j.between?(0, 19)

@map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)

@map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)

@map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)

end

end}}

# save the three additional maps in the Cache

RPG::Cache_Carte.save(@id, @map_2, 1)

RPG::Cache_Carte.save(@id, @map_3, 2)

RPG::Cache_Carte.save(@id, @map_4, 3)

end

end

 

#============================================================================

# ■ Game_Map

#----------------------------------------------------------------------------

# Methods modifications to handle map looping

#============================================================================

 

class Game_Map

#--------------------------------------------------------------------------

# * Scroll Down

# distance : scroll distance

#--------------------------------------------------------------------------

alias scroll_down_mode7_game_map scroll_down

def scroll_down(distance)

if !$game_system.mode7

scroll_down_mode7_game_map(distance)

return

end

@display_y = @display_y + distance

unless $game_system.loop_y || $game_system.always_scroll

height = (self.height - 15) * 128

@display_y = height if @display_y > height

end

end

#--------------------------------------------------------------------------

# * Scroll Left

# distance : scroll distance

#--------------------------------------------------------------------------

alias scroll_left_mode7_game_map scroll_left

def scroll_left(distance)

if !$game_system.mode7

scroll_left_mode7_game_map(distance)

return

end

@display_x = @display_x - distance

unless $game_system.loop_x || $game_system.always_scroll

@display_x = 0 if @display_x < 0

end

end

#--------------------------------------------------------------------------

# * Scroll Right

# distance : scroll distance

#--------------------------------------------------------------------------

alias scroll_right_mode7_game_map scroll_right

def scroll_right(distance)

if !$game_system.mode7

scroll_right_mode7_game_map(distance)

return

end

@display_x = @display_x + distance

unless $game_system.loop_x || $game_system.always_scroll

width = (self.width - 20) * 128

@display_x = width if @display_x > width

end

end

#--------------------------------------------------------------------------

# * Scroll Up

# distance : scroll distance

#--------------------------------------------------------------------------

alias scroll_up_mode7_game_map scroll_up

def scroll_up(distance)

if !$game_system.mode7

scroll_up_mode7_game_map(distance)

return

end

@display_y = @display_y - distance

unless $game_system.loop_y || $game_system.always_scroll

@display_y = 0 if @display_y < 0

end

end

#--------------------------------------------------------------------------

# * Determine Valid Coordinates

# x : x-coordinate

# y : y-coordinate

# Allow the hero to go out of the map when map looping

#--------------------------------------------------------------------------

alias valid_mode7_game_map? valid?

def valid?(x, y)

return (valid_mode7_game_map?(x, y)) if !$game_system.mode7

if $game_system.loop_x

return ($game_system.loop_y || y >= 0 && y < height)

elsif $game_system.loop_y

return (x >= 0 && x < width)

end

return (x >= 0 && x < width && y >= 0 && y < height)

end

#--------------------------------------------------------------------------

# * Determine if Passable

# x : x-coordinate

# y : y-coordinate

# d : direction (0,2,4,6,8,10)

# * 0,10 = determine if all directions are impassable

# self_event : Self (If event is determined passable)

#--------------------------------------------------------------------------

alias passable_mode7_game_map? passable?

def passable?(x, y, d, self_event = nil)

if !$game_system.mode7

passable_mode7_game_map?(x, y, d, self_event)

return(passable_mode7_game_map?(x, y, d, self_event))

end

return false unless valid?(x, y)

bit = (1 << (d / 2 - 1)) & 0x0f

events.each_value {|event|

if event.tile_id >= 0 && event != self_event &&

event.x == x && event.y == y && !event.through

if @passages[event.tile_id] & bit != 0

return false

elsif @passages[event.tile_id] & 0x0f == 0x0f

return false

elsif @priorities[event.tile_id] == 0

return true

end

end}

[2, 1, 0].each {|i|

tile_id = data[x % width, y % height, i] # handle map looping

if tile_id == nil

return false

elsif @passages[tile_id] & bit != 0

return false

elsif @passages[tile_id] & 0x0f == 0x0f

return false

elsif @priorities[tile_id] == 0

return true

end}

return true

end

end

 

#============================================================================

# ■ Game_Character

#----------------------------------------------------------------------------

# "update" method modifications to handle map looping

#============================================================================

 

class Game_Character

attr_accessor :x

attr_accessor :y

attr_accessor :real_x

attr_accessor :real_y

attr_reader :flat

attr_reader :height

#--------------------------------------------------------------------------

# * Object Initialization

#--------------------------------------------------------------------------

alias initialize_mode7_game_character initialize

def initialize

initialize_mode7_game_character

init_mode7

end

#--------------------------------------------------------------------------

# * Mode7 Initialization

#--------------------------------------------------------------------------

def init_mode7

@flat = false

@height = 0.0

end

#--------------------------------------------------------------------------

# * Update

#--------------------------------------------------------------------------

alias update_mode7_game_character update

def update

if !$game_system.mode7

update_mode7_game_character

return

end

# if x-coordinate is out of the map

if !(x.between?(0, $game_map.width - 1))

difference = 128 * x - real_x

if self.is_a?(Game_Player)

# increase or decrease map's number

self.map_number_x += difference / (difference.abs)

end

# x-coordinate is equal to its equivalent in the map

self.x %= $game_map.width

self.real_x = 128 * x - difference

end

# if y-coordinate is out of the map

if !(y.between?(0, $game_map.height - 1))

difference = 128 * y - real_y

if self.is_a?(Game_Player)

# increase or decrease map's number

self.map_number_y += difference / (difference.abs)

end

# y-coordinate is equal to its equivalent in the map

self.y %= $game_map.height

self.real_y = 128 * y - difference

end

update_mode7_game_character

end

end

 

#==============================================================================

# ■ Game_Event

#----------------------------------------------------------------------------

# Add methods to handle flat events and altitude for vertical event

#============================================================================

 

class Game_Event < Game_Character

#--------------------------------------------------------------------------

# * scan the event's commands list

# page : the scanned page (RPG::Event::Page)

#--------------------------------------------------------------------------

def check_commands(page)

@height = 0.0

command_list = page.list

(0..command_list.length - 2).each {|k|

command = command_list[k]

if (command.parameters[0].to_s).include?('Height')

@height = (command.parameters[0][7,command.parameters[0].length-1]).to_f

end

@flat = (command.parameters[0].to_s).include?('Flat')}

end

#--------------------------------------------------------------------------

# * scan the event's commands list of the current page when refreshed

#--------------------------------------------------------------------------

alias refresh_mode7_game_character refresh

def refresh

refresh_mode7_game_character

check_commands(@page) if @page != nil

end

end

 

#============================================================================

# ■ Game_Player

#----------------------------------------------------------------------------

# Add attributes to have a well-working panorama's scrolling

#============================================================================

 

class Game_Player < Game_Character

attr_accessor :map_number_x # map's number with X-looping

attr_accessor :map_number_y # map's number with Y-looping

#--------------------------------------------------------------------------

# * Object Initialization

#--------------------------------------------------------------------------

alias initialize_mode7_game_player initialize

def initialize

initialize_mode7_game_player

init_mode7

end

#--------------------------------------------------------------------------

# * Mode 7 Initialization

#--------------------------------------------------------------------------

def init_mode7

self.map_number_x = 0

self.map_number_y = 0

super

end

#--------------------------------------------------------------------------

# * Handle the option : center around the hero

#--------------------------------------------------------------------------

alias center_mode7_game_player center

def center(x, y)

if !$game_system.mode7 || !$game_system.always_scroll

center_mode7_game_player(x, y)

return

end

$game_map.display_x = x * 128 - CENTER_X

$game_map.display_y = y * 128 - CENTER_Y

end

end

 

#============================================================================

# ■ Sprite

#----------------------------------------------------------------------------

# Add attributes to work efficiently with scanlines sprites

#============================================================================

 

class Sprite

attr_accessor :y_origin_bitmap # bitmap's y-coordinate for the "src_rect.set"

#method (float)

attr_accessor :x_origin_bitmap # bitmap's x-coordinate for the "src_rect.set"

#method (float)

attr_accessor :y_origin_bitmap_i # bitmap's y-coordinate for the

#"src_rect.set" method (integer)

attr_accessor :x_origin_bitmap_i # bitmap's x-coordinate for the

#"src_rect.set" method (integer)

attr_accessor :length # sprite's width

end

 

#============================================================================

# ■ Sprite_Character

#----------------------------------------------------------------------------

# Calculate x-coordinate and y-coordinate for a mode7 map

#============================================================================

 

class Sprite_Character < RPG::Sprite

attr_reader :flat_indicator # true if the event is flat-drawn

#--------------------------------------------------------------------------

# * Object Initialization

#--------------------------------------------------------------------------

alias initialize_mode7_sprite_character initialize

def initialize(viewport, character = nil)

@flat_indicator = false

initialize_mode7_sprite_character(viewport, character)

end

#--------------------------------------------------------------------------

# * Update

#--------------------------------------------------------------------------

alias update_mode7_sprite_character update

def update

if !$game_system.mode7

update_mode7_sprite_character

return

end

if @flat_indicator

if (!@character.flat || @character.moving? ||

@tile_id != @character.tile_id ||

@character_name != @character.character_name ||

@character_hue != @character.character_hue)

@flat_indicator = @character.flat

# redraw the original ground

maps_list = $scene.spriteset.tilemap.maps_list

map_ground = $scene.spriteset.tilemap.map_ground

rect = Rect.new(@flat_x_map, @flat_y_map, @flat_width, @flat_height)

maps_list.each {|map|

map.blt(@flat_x_map, @flat_y_map, map_ground, rect)

if $game_system.loop_x && @flat_x_map.between?(0, 19 * 32)

map.blt(@flat_x_map + 32 * $game_map.width, @flat_y_map, map_ground,

rect)

end}

else

return

end

end

super

if @tile_id != @character.tile_id ||

@character_name != @character.character_name ||

@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

# pivot correction (intersection between the map and this sprite)

self.oy -= 4

end

end

self.visible = (!@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

if @character.flat # event must be flat drawn

return if $scene.spriteset == nil

if @tile_id == 0

@flat_x_map = @character.real_x / 4 - (@cw - 32) / 2

@flat_y_map = @character.real_y / 4 - @ch + 32

@flat_x0 = sx

@flat_y0 = sy

@flat_width = @cw

@flat_height = @ch

else

@flat_x_map = @character.real_x / 4

@flat_y_map = @character.real_y / 4

@flat_x0 = 0

@flat_y0 = 0

@flat_width = 32

@flat_height = 32

end

# modify the maps graphics

maps_list = $scene.spriteset.tilemap.maps_list

rect = Rect.new(@flat_x0, @flat_y0, @flat_width, @flat_height)

maps_list.each {|map|

map.blt(@flat_x_map, @flat_y_map, bitmap, rect, @character.opacity)

if $game_system.loop_x && @flat_x_map.between?(0, 19 * 32)

map.blt(@flat_x_map + 32 * $game_map.width, @flat_y_map, bitmap, rect,

@character.opacity)

end}

@flat_indicator = true

self.opacity = 0

return

end

x_intermediate = @character.screen_x

y_intermediate = @character.screen_y

y_intermediate -= $game_temp.pivot + 4 if $game_system.mode7

# if vertical looping

if $game_system.loop_y

h = 32 * $game_map.height

y_intermediate = (y_intermediate + h / 2) % h - h / 2

end

# coordinates in a mode7 map

self.y = (($game_temp.distance_h * y_intermediate *

$game_temp.cos_angle).to_f / ($game_temp.distance_h - y_intermediate *

$game_temp.sin_angle) + $game_temp.pivot)

self.zoom_x = $game_temp.slope_value * y + $game_temp.corrective_value

self.zoom_y = zoom_x

self.x = 320 + zoom_x * (x_intermediate - 320)

# if horizontal looping

if $game_system.loop_x

offset = ($game_map.width >= 24 ? 64 * zoom_x : 0)

l = 32 * $game_map.width * zoom_x

self.x = (x + offset) % l - offset

end

# Overworld Sprite Resize

if @character.is_a?(Game_Player) && $game_system.ov

self.zoom_x *= $game_system.ov_zoom

self.zoom_y *= $game_system.ov_zoom

end

self.z = @character.screen_z(@ch)

# hide the sprite if it is beyond the horizon's line

self.opacity = (y < $game_temp.height_limit ? 0 : @character.opacity)

self.y -= 32 * @character.height * zoom_y # height correction

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_V (Vertical Sprites)

#----------------------------------------------------------------------------

# Sprites corresponding to the vertical elements formed by tiles

#============================================================================

 

class Sprite_V < Sprite

attr_accessor :x_map # sprite's x_coordinates (in squares) (Float)

attr_accessor :y_map # sprite's y_coordinates (in squares) (Float)

attr_accessor :square_y # sprite's y_coordinates (in squares) (Integer)

attr_accessor :priority # sprite's priority

attr_accessor :animated # True if animated

attr_accessor :list_bitmap # list of sprite's bitmaps (Bitmap)

#--------------------------------------------------------------------------

# * Update

#--------------------------------------------------------------------------

def update

square_y_corrected = square_y

y_intermediate = 32 * y_map - $game_temp.pivot - $game_map.display_y / 4

y_intermediate_reference = y_intermediate

# if vertical looping

if $game_system.loop_y

y_intermediate = (y_intermediate + $game_temp.height / 2) %

$game_temp.height - $game_temp.height / 2

if y_intermediate_reference < y_intermediate

square_y_corrected = square_y + $game_map.height

elsif y_intermediate_reference > y_intermediate

square_y_corrected = square_y - $game_map.height

end

end

self.y = ($game_temp.distance_h * y_intermediate *

$game_temp.cos_angle).to_f / ($game_temp.distance_h - y_intermediate *

$game_temp.sin_angle) + $game_temp.pivot

if y < $game_temp.height_limit

# hide the sprite if it is beyond the horizon's line

self.opacity = 0

return

end

self.opacity = 255

if $scene.spriteset != nil

opacity_values = $scene.spriteset.tilemap.opacity_values

tone_values = $scene.spriteset.tilemap.tone_values

if opacity_values.has_key?(y)

self.opacity = opacity_values[y]

self.tone = tone_values[y]

end

end

self.zoom_x = $game_temp.slope_value * y + $game_temp.corrective_value

self.zoom_y = zoom_x

x_intermediate = 32 * x_map - $game_map.display_x / 4

self.x = 320 + (zoom_x * (x_intermediate - 320))

# if horizontal looping

if $game_system.loop_x

offset = ($game_map.width >= 24 ? 64 * zoom_x : 0)

l = 32 * $game_map.width * self.zoom_x

self.x = (self.x + offset) % l - offset

end

self.z = (128 * square_y_corrected - $game_map.display_y + 3) / 4 +

32 + 32 * priority

end

#--------------------------------------------------------------------------

# * Update bitmap for animation

# index : 0..3 : animation's index

#--------------------------------------------------------------------------

def update_animated(index)

self.bitmap = @list_bitmap[index]

end

end

 

#============================================================================

# ■ Spriteset_Map

#----------------------------------------------------------------------------

# Modifications to call a mode7 map

#============================================================================

 

class Spriteset_Map

attr_accessor :tilemap # just to be able to access the tilemap

#--------------------------------------------------------------------------

# * Defines map's options from its name

# Refer to Game_System class

#--------------------------------------------------------------------------

def init_options

map_data = $data_maps[$game_map.map_id]

MODE7_SETTINGS.each_key {|keyword|

if map_data.name2.include?(keyword)

command_list = MODE7_SETTINGS[keyword]

$game_system.mode7 = true

$game_system.loop_x = command_list.include?("X")

$game_system.loop_y = command_list.include?("Y")

$game_system.always_scroll = command_list.include?("C")

$game_system.animated = command_list.include?("A")

$game_system.white_horizon = command_list.include?("H")

$game_system.fixed_panorama = command_list.include?("P")

$game_system.ov = command_list.include?("OV")

command_list.each {|command|

if command.include?("#")

$game_system.angle = (command.slice(1, 2)).to_i

if $game_system.angle < 0

$game_system.angle = 0

elsif $game_system.angle > 89

$game_system.angle = 89

end

break

end}

return

end}

$game_system.mode7 = map_data.name2.include?("[M7]")

$game_system.loop_x = map_data.name2.include?("[X]")

$game_system.loop_y = map_data.name2.include?("[Y]")

$game_system.always_scroll = map_data.name2.include?("[C]")

$game_system.animated = map_data.name2.include?("[A]")

$game_system.white_horizon = map_data.name2.include?("[H]")

$game_system.fixed_panorama = map_data.name2.include?("[P]")

$game_system.ov = map_data.name2.include?("[OV]")

if $game_system.mode7

map_data.name2 =~ /\[#[ ]*([00-99]+)\]/i

$game_system.angle = $1.to_i

if $game_system.angle < 0

$game_system.angle = 0

elsif $game_system.angle > 89

$game_system.angle = 89

end

end

end

#--------------------------------------------------------------------------

# * Initialize Object

# Rewritten to call a map with mode7

#--------------------------------------------------------------------------

alias initialize_mode7_spriteset_map initialize

def initialize

if !$game_system.mode7

initialize_mode7_spriteset_map

return

end

init_options

@viewport1 = Viewport.new(0, 0, 640, 480)

@viewport2 = Viewport.new(0, 0, 640, 480)

@viewport3 = Viewport.new(0, 0, 640, 480)

@viewport2.z = 200

@viewport3.z = 5000

# mode7 map

@tilemap = Tilemap_mode7.new(@viewport1)

@panorama = Plane.new(@viewport1)

# sprites drawn at the horizon's level have a negative z, and with a z value

# of -100000 the panorama is still below

@panorama.z = ($game_system.mode7 ? -100000 : -1000)

@fog = Plane.new(@viewport1)

@fog.z = 3000

@character_sprites = []

$game_map.events.keys.sort.each {|i|

sprite = Sprite_Character.new(@viewport1, $game_map.events)

@character_sprites.push(sprite)}

@character_sprites.push(Sprite_Character.new(@viewport1, $game_player))

@weather = RPG::Weather.new(@viewport1)

@picture_sprites = []

(1..50).each {|i|

@picture_sprites.push(Sprite_Picture.new(@viewport2,

$game_screen.pictures))}

@timer_sprite = Sprite_Timer.new

update

end

#--------------------------------------------------------------------------

# * Dispose

#--------------------------------------------------------------------------

alias dispose_mode7_spriteset_map dispose

def dispose

if !$game_system.mode7

dispose_mode7_spriteset_map

return

end

@tilemap.dispose

@panorama.dispose

@fog.dispose

@character_sprites.each {|sprite| sprite.dispose}

@weather.dispose

@picture_sprites.each {|sprite| sprite.dispose}

@timer_sprite.dispose

@viewport1.dispose

@viewport2.dispose

@viewport3.dispose

end

#--------------------------------------------------------------------------

# * Update

#--------------------------------------------------------------------------

alias update_mode7_spriteset_map update

def update

if !$game_system.mode7

update_mode7_spriteset_map

return

end

if @panorama_name != $game_map.panorama_name ||

@panorama_hue != $game_map.panorama_hue

@panorama_name = $game_map.panorama_name

@panorama_hue = $game_map.panorama_hue

if @panorama.bitmap != nil

@panorama.bitmap.dispose

@panorama.bitmap = nil

end

if @panorama_name != ""

@panorama.bitmap = RPG::Cache.panorama(@panorama_name, @panorama_hue)

end

Graphics.frame_reset

end

if @fog_name != $game_map.fog_name || @fog_hue != $game_map.fog_hue

@fog_name = $game_map.fog_name

@fog_hue = $game_map.fog_hue

if @fog.bitmap != nil

@fog.bitmap.dispose

@fog.bitmap = nil

end

@fog.bitmap = RPG::Cache.fog(@fog_name, @fog_hue) if @fog_name != ''

Graphics.frame_reset

end

# update animated tiles each 20 frames

if Graphics.frame_count % 20 == 0 && $game_system.animated

@tilemap.update_animated

end

@tilemap.update

# if the panorama is fixed

if $game_system.fixed_panorama

@panorama.ox = 0

@panorama.oy = 0

# if it is a mode7 map

else

# to have a fluent panorama scrolling

@panorama.ox = (128 * $game_map.width * $game_player.map_number_x +

$game_player.real_x) / 8

@panorama.oy = - (128 * $game_map.height * $game_player.map_number_y +

$game_player.real_y) / 32

end

@fog.zoom_x = $game_map.fog_zoom / 100.0

@fog.zoom_y = $game_map.fog_zoom / 100.0

@fog.opacity = $game_map.fog_opacity

@fog.blend_type = $game_map.fog_blend_type

@fog.ox = $game_map.display_x / 4 + $game_map.fog_ox

@fog.oy = $game_map.display_y / 4 + $game_map.fog_oy

@fog.tone = $game_map.fog_tone

@character_sprites.each {|sprite| sprite.update}

@weather.type = $game_screen.weather_type

@weather.max = $game_screen.weather_max

@weather.ox = $game_map.display_x / 4

@weather.oy = $game_map.display_y / 4

@weather.update

@picture_sprites.each {|sprite| sprite.update}

@timer_sprite.update

@viewport1.tone = $game_screen.tone

@viewport1.ox = $game_screen.shake

@viewport3.color = $game_screen.flash_color

@viewport1.update

@viewport3.update

end

end

 

#============================================================================

# ■ Scene_Map

#============================================================================

class Scene_Map

attr_accessor :spriteset # just need to access the spriteset

end

 

#============================================================================

# ■ Data_Autotiles

#----------------------------------------------------------------------------

# Creates the set of tiles from an autotile's file

#============================================================================

 

class Data_Autotiles < Bitmap

# data list to form tiles from an atotiles file

Data_creation = [[27,28,33,34],[5,28,33,34],[27,6,33,34],[5,6,33,34],

[27,28,33,12],[5,28,33,12],[27,6,33,12],[5,6,33,12],[27,28,11,34],

[5,28,11,34],[27,6,11,34],[5,6,11,34],[27,28,11,12],[5,28,11,12],

[27,6,11,12],[5,6,11,12],[25,26,31,32],[25,6,31,32],[25,26,31,12],

[25,6,31,12],[15,16,21,22],[15,16,21,12],[15,16,11,22],[15,16,11,12],

[29,30,35,36],[29,30,11,36],[5,30,35,36],[5,30,11,36],[39,40,45,46],

[5,40,45,46],[39,6,45,46],[5,6,45,46],[25,30,31,36],[15,16,45,46],

[13,14,19,20],[13,14,19,12],[17,18,23,24],[17,18,11,24],[41,42,47,48],

[5,42,47,48],[37,38,43,44],[37,6,43,44],[13,18,19,24],[13,14,43,44],

[37,42,43,48],[17,18,47,48],[13,18,43,48],[13,18,43,48]]

attr_accessor :number # autotile's number to identify it

attr_accessor :animated # TRUE if the autotile is animated

#--------------------------------------------------------------------------

# * Initialize Object

# file : autotiles file's bitmap (Bitmap)

# l : 0..3 : pattern's number for animated autotiles

#--------------------------------------------------------------------------

def initialize(file, l)

super(8*32, 6*32)

create(file, l)

end

#--------------------------------------------------------------------------

# * Create the tiles set

# file : autotiles file's bitmap (Bitmap)

# l : 0..3 : pattern's number for animated autotiles

#--------------------------------------------------------------------------

def create(file, l)

l = (file.width > 96 ? l : 0)

self.animated = (file.width > 96)

(0..5).each {|i| (0..7).each {|j| Data_creation[8 * i + j].each {|number|

number -= 1

m = 16 * (number % 6)

n = 16 * (number / 6)

blt(32 * j + m % 32, 32 * i + n % 32, file,

Rect.new(m + 96 * l, n, 16, 16))}}}

end

end

 

#============================================================================

# ■ Data_Vertical_Sprites

#----------------------------------------------------------------------------

# Create a list of vertical sprites for the three layers of a map

# "V" for "Vertical" in the script

# "num" for "number"

#============================================================================

 

class Data_Vertical_Sprites

attr_accessor :list_sprites_V # list of vertical sprites

attr_accessor :list_sprites_V_animated # list of animated vertical sprites

#--------------------------------------------------------------------------

# * A little method to compare terrain_tags

# value : tile's ID

# num : reference terrain_tag's value

#--------------------------------------------------------------------------

def suitable?(value, num)

return ($game_map.terrain_tags[value] == num)

end

#--------------------------------------------------------------------------

# * This algorithm scans each layer and create a sprites formed by tiles

# in contact

# viewport : Viewport

#--------------------------------------------------------------------------

def initialize(viewport)

@viewport = viewport

# lists initialization

self.list_sprites_V = []

self.list_sprites_V_animated = []

# @num_tiles : list of tiles coordinates that form a vertical sprite

@num_tiles = []

# create copy of map's data

@dataV = ($game_map.data).clone

# scan each layer, row and column

(0..2).each {|h| (0..$game_map.height).each {|i| (0..$game_map.width).each {|j|

value = @dataV[j, i, h].to_i

# if tile's terrain tag is declared to give vertical sprites

if VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value])

@reference_terrain_tag = $game_map.terrain_tags[value]

@num_tiles.push([j, i])

# the following algorithm is so complex that I really don't know how

# it works exactly

list_end = 0

length = 0

while j + length + 1 < $game_map.width &&

suitable?(@dataV[j +length+ 1, i, h].to_i, @reference_terrain_tag)

@num_tiles.push([j + length+ 1,i])

length += 1

end

list_start = j

list_end = length + j

indicator = true

row = 0

j2 = j

while indicator

row += 1

break if (i + row) == $game_map.height

list_start2 = j2

length2 = 0

indicator = false

if length >= 2

((j2 + 1)..(j2 + length -1)).each {|k|

if suitable?(@dataV[k, i + row, h].to_i,

@reference_terrain_tag)

if !indicator

list_start2 = k

else

length2 = k - list_start2

end

indicator = true

@num_tiles.push([k, i + row])

elsif !indicator

length2 -= 1

end}

end

if suitable?(@dataV[j2 + length, i + row, h].to_i,

@reference_terrain_tag)

length2 = j2 + length - list_start2

indicator = true

@num_tiles.push([j2 + length, i + row])

length3 = 1

while j2 + length + length3 < $game_map.width &&

suitable?(@dataV[j2 + length + length3, i + row, h].to_i,

@reference_terrain_tag)

@num_tiles.push([j2 + length + length3, i + row])

length3 += 1

length2 += 1

if j2 + length + length3 > list_end

list_end = j2 + length + length3

end

end

end

if suitable?(@dataV[j2, i + row, h].to_i, @reference_terrain_tag)

list_start3 = list_start2 - j2

length2 = length2 + list_start3

list_start2 = j2

indicator = true

@num_tiles.push([j2, i + row])

length3 = 1

while j2 - length3 >= 0 &&

suitable?(@dataV[j2 - length3, i + row, h].to_i,

@reference_terrain_tag)

@num_tiles.push([j2 - length3, i + row])

length3 += 1

length2 += 1

list_start2 -= 1

list_start = list_start2 if list_start2 < list_start

end

end

length = length2

j2 = list_start2

end

row -= 1

# create a bitmap and a sprite from the tiles listed in @num_tiles

create_bitmap(i, list_start, row, list_end - list_start, h)

# clear the used tiles

clear_data(h)

# reinitialize the list of tiles

@num_tiles = []

end}}}

end

#--------------------------------------------------------------------------

# * Clear the used data to prevent from reusing them

# layer : current scanned layer

#--------------------------------------------------------------------------

def clear_data(layer)

@num_tiles.each {|num| @dataV[num[0], num[1], layer] = 0}

end

#--------------------------------------------------------------------------

# * Create a Bitmap from the listed tiles in @num_tiles and its associated

# sprite (Sprite_V)

# row : start row's value

# column : start column's value

# height : sprite's height (in tiles)

# width : sprite's width (in tiles)

# layer : current scanned layer

#--------------------------------------------------------------------------

def create_bitmap(row, column, height, width, layer)

bmp = Bitmap.new(32*(1+width), 32*(1+height))

rect = Rect.new(0, 0, 32, 32)

@num_tiles.sort! {|a, b| -(a[1] - b[1])}

sprite = Sprite_V.new(@viewport)

# initialize sprite's attributes

sprite.animated = false

sprite.list_bitmap = []

# draw the bitmap

@num_tiles.each {|tile_coordinates|

value = @dataV[tile_coordinates[0], tile_coordinates[1], layer].to_i

# if tile is a normal tile

if value > 383

bitmap = RPG::Cache.tile($game_map.tileset_name, value, 0)

else # tile is an autotile

file = (value / 48) - 1

num_file = 4 * file

if !sprite.animated

autotile_name = $game_map.autotile_names[file]

fichier = RPG::Cache.autotile(autotile_name)

sprite.animated = (fichier.width > 96 ? true : false)

end

bitmap = RPG::Cache.autotile_base(num_file, value)

end

bmp.blt(32 * (tile_coordinates[0] - column),

32 * (tile_coordinates[1] - row), bitmap, rect)}

sprite.list_bitmap.push(bmp)

# create 3 additionnal bitmaps for animated sprites

if sprite.animated

(1..3).each {|j|

bmp = Bitmap.new(32 * (1 + width), 32 * (1 + height))

@num_tiles.each {|tile_coordinates|

value = @dataV[tile_coordinates[0], tile_coordinates[1], layer].to_i

if value > 383

bitmap = RPG::Cache.tile($game_map.tileset_name, value, 0)

else

num_file = 4 * ((value / 48) - 1)

bitmap = RPG::Cache.autotile_base(num_file + j, value)

end

bmp.blt(32 * (tile_coordinates[0] - column),

32 * (tile_coordinates[1] - row), bitmap, rect)}

sprite.list_bitmap.push(bmp)}

end

value = @dataV[@num_tiles[0][0], @num_tiles[0][1], layer].to_i

# set sprite's priority

sprite.priority = $game_map.priorities[value]

# set sprite's coordinates (in squares (32 * 32 pixels))

sprite.x_map = (column.to_f) + bmp.width / 64

sprite.x_map += 0.5 if width % 2 == 0

sprite.y_map = (row + height).to_f + 0.5

sprite.square_y = sprite.y_map.to_i # Integer

# set the y_pivot (intersection between the map and the sprite)

sprite.oy = bmp.height - 16

sprite.ox = bmp.width / 2

sprite.bitmap = sprite.list_bitmap[0]

self.list_sprites_V.push(sprite)

self.list_sprites_V_animated.push(sprite) if sprite.animated

end

end

 

#============================================================================

# ■ RPG::Cache_Tile

#----------------------------------------------------------------------------

# The tiles resulting in a superimposing of several tiles are kept in memory

# for a faster call

# valueX : tile's ID

#============================================================================

 

module RPG::Cache_Tile

@cache = {}

#--------------------------------------------------------------------------

# * Superimposing of two tiles, offset = pattern's number for animated

# autotiles

#--------------------------------------------------------------------------

def self.load(value1, value2, offset=0)

if !@cache.include?([value1, value2, offset])

bitmap = Bitmap.new(32, 32)

rect = Rect.new(0, 0, 32, 32)

if value1 > 383 # normal tile

bitmap.blt(0, 0, RPG::Cache.tile($game_map.tileset_name, value1, 0),

rect)

else # autotile

num = 4*((value1 / 48) - 1) + offset

bitmap.blt(0, 0, RPG::Cache.autotile_base(num, value1), rect)

end

if value2 > 383 # normal tile

bitmap.blt(0, 0, RPG::Cache.tile($game_map.tileset_name, value2, 0),

rect)

else # autotile

num = 4*((value2 / 48) - 1) + offset

bitmap.blt(0, 0, RPG::Cache.autotile_base(num, value2), rect)

end

###@cache[[value1, value2, offset]] = bitmap

return bitmap

end

@cache[[value1, value2, offset]]

end

#--------------------------------------------------------------------------

# * Superimposing of three tiles

#--------------------------------------------------------------------------

def self.load2(value1, value2, value3, offset = 0)

if !@cache.include?([value1, value2, value3, offset])

bitmap = Bitmap.new(32, 32)

rect = Rect.new(0, 0, 32, 32)

if value1 > 383 # normal tile

bitmap.blt(0, 0, RPG::Cache.tile($game_map.tileset_name, value1, 0),

rect)

else # autotile

num = 4*((value1 / 48) - 1) + offset

bitmap.blt(0, 0, RPG::Cache.autotile_base(num, value1), rect)

end

if value2 > 383 # normal tile

bitmap.blt(0, 0, RPG::Cache.tile($game_map.tileset_name, value2, 0),

rect)

else # autotile

num = 4*((value2 / 48) - 1) + offset

bitmap.blt(0, 0, RPG::Cache.autotile_base(num, value2), rect)

end

if value3 > 383 # normal tile

bitmap.blt(0, 0, RPG::Cache.tile($game_map.tileset_name, value3, 0),

rect)

else # autotile

num = 4*((value3 / 48) - 1) + offset

bitmap.blt(0, 0, RPG::Cache.autotile_base(num, value3), rect)

end

###@cache[[value1, value2, value3, offset]] = bitmap

return bitmap

end

@cache[[value1, value2, value3, offset]]

end

#--------------------------------------------------------------------------

# * Clear the Cache

#--------------------------------------------------------------------------

def self.clear

@cache = {}

GC.start

end

end

 

#============================================================================

# ■ RPG::Cache_Carte

#----------------------------------------------------------------------------

# Maps drawn with mode7 are kept in memory to have a faster call the next

# times they need to be drawn

#============================================================================

 

module RPG::Cache_Carte

@cache = {}

#--------------------------------------------------------------------------

# * Check if the map is in the Cache

# map_id : map's ID

#--------------------------------------------------------------------------

def self.in_cache(map_id)

return @cache.include?(map_id)

end

#--------------------------------------------------------------------------

# * Return the map's drawing (Bitmap)

# map_id : map's ID

# num : pattern's number for animated autotiles

#--------------------------------------------------------------------------

def self.load(map_id, num = 0)

return @cache[map_id][num]

end

#--------------------------------------------------------------------------

# * Save the map's drawing in the Cache

# map_id : map's ID

# bitmap : map's drawing (Bitmap)

# num : pattern's number for animated autotiles

#--------------------------------------------------------------------------

def self.save(map_id, bitmap, num = 0)

@cache[map_id] = [] if !self.in_cache(map_id)

@cache[map_id][num] = bitmap

end

#--------------------------------------------------------------------------

# * Clear the Cache

#--------------------------------------------------------------------------

def self.clear

@cache = {}

GC.start

end

end

 

#============================================================================

# ■ RPG::Cache

#----------------------------------------------------------------------------

# The tiles from autotiles files are kept in memory for a faster call

#============================================================================

 

module RPG::Cache

#--------------------------------------------------------------------------

# * Check if the map is in the Cache

# num : autotiles file's ID

# value : tile's ID

#--------------------------------------------------------------------------

def self.autotile_base(num, value)

key = [num, value]

if !@cache.include?(key) || @cache[key].disposed?

@cache[key] = Bitmap.new(32, 32)

num_tile = value % 48

sx = 32 * (num_tile % 8)

sy = 32 * (num_tile / 8)

rect = Rect.new(sx, sy, 32, 32)

@cache[key].blt(0, 0, self.load_autotile(num), rect)

end

@cache[key]

end

#--------------------------------------------------------------------------

# * Save the tile's drawing in the Cache

# bitmap : tile's drawing (Bitmap)

# key : tile's ID

#--------------------------------------------------------------------------

def self.save_autotile(bitmap, key)

@cache[key] = bitmap

end

#--------------------------------------------------------------------------

# * Return the tile's drawing (Bitmap)

# key : tile's ID

#--------------------------------------------------------------------------

def self.load_autotile(key)

@cache[key]

end

end

 

#============================================================================

# ■ RPG::MapInfo

#============================================================================

 

class RPG::MapInfo

# defines the map's name as the name without anything within brackets,

# including brackets

def name

return @name.gsub(/\[.*\]/) {""}

end

#--------------------------------------------------------------------------

# the original name with the codes

def name2

return @name

end

end

 

#============================================================================

# ■ Game_Temp

#----------------------------------------------------------------------------

# Add attributes to this class / Avoid using too many global variables

#============================================================================

 

class Game_Temp

attr_accessor :pivot # screenline's number of the slant's pivot

attr_accessor :cos_angle # cosinus of the slant's angle

attr_accessor :sin_angle # sinus of the slant's angle

attr_accessor :height_limit # horizon's line

attr_accessor :distance_h # distance between the map's center and the vanishing point

attr_accessor :slope_value # intermediate value

attr_accessor :corrective_value # intermediate value

attr_accessor :height # map's height (in pixel)

#--------------------------------------------------------------------------

# * Object Initialization

#--------------------------------------------------------------------------

alias initialize_mode7_game_temp initialize

def initialize

initialize_mode7_game_temp

self.pivot = 0

self.cos_angle = 0.0

self.sin_angle = 0.0

self.height_limit = 0

self.distance_h = 0

self.slope_value = 0.0

self.corrective_value = 0.0

self.height = 0

end

end

 

***************************************************************************

 

and this is the error:

 

Script 'spriteset_map' line 123: NoMethodError occured.

undefined method`ox=' for#<Tilemap_mode7:0x305bc30

 

thnx in advance.

Edited by UnrealJohny

Share this post


Link to post
Share on other sites

1 answer to this question

Recommended Posts

  • 0

Your problem is you didn't read the setup instructions. I put this script into a brand new project, hit play and was able to recreate the error instantly. I read the first paragraph of the setup and it said I needed to add an extension to any map names in the project. I picked a random extension from the list (I used [M7] to activate the mode) and the error went away. Always make sure to read everything in the setup multiple times, and toggle/leave the same EVERY option in a script before wondering why it won't work. More often than not it's simply a user error. Just a hint too, any time you see 'undefined method' it means the script is missing something it thinks it should have, so it's likely you forgot it during setup. I hope this clears things up, feel free to ask any follow up questions etc.

 

-Cheers, and happy making!

 

EDIT* In the future try and put scripts into spoiler tags it keeps threads easier to read.

 
[spoiler] Script text would go here. [/spoiler]
 

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...