查看: 1214|回复: 0

[已经过期] 腳本衝突,求救

[复制链接]
梦石
0
星屑
2116
在线时间
950 小时
注册时间
2015-7-16
回帖
692

开拓者

发表于 2016-3-17 15:31:27 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
未命名.png

theo 的反lag 搭配 mode 7 會出錯
開飛船時

反lag[pre lang="ruby"]#===============================================================================
# TheoAllen - Insane Anti Lag
# Version : 1.1
# Language : English
#-------------------------------------------------------------------------------
# With help from following people :
# - Tsukihime
# - KilloZapit
# - Galv
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Contact :
#-------------------------------------------------------------------------------
# *> http://www.rpgmakerid.com
# *> http://www.rpgmakervxace.net
# *> http://www.theolized.com
#===============================================================================
($imported ||= {})[:Theo_AntiLag] = true
#===============================================================================
# Change Logs:
# ------------------------------------------------------------------------------
# 2015.02.20 - Added page check enhancer to work with parallel process
# 2015.01.25 - Compatibility with Shaz's Mouse Script. def events_xy now should
#              always return array,
#            - Avoid error 'undefined method delete_sprite for nilClass'
# 2015.01.01 - Avoid unexpected error 'undefined method spriteset for scene'
# 2014.12.05 - Finished
#===============================================================================
=begin

  ------------------------------------------
  *) Introduction :
  ------------------------------------------
  As most of you already know, lag is common problem in RPG Maker games. You may
  started to think it was because you have many events on map. And so, to avoid
  lag, you split your map into part and limiting the event as well.

  It's not entirely wrong because when you have a lot of events, program need
  to checks all events. However, it wasn't done efficienly. This script
  increase the efficiency on how default script works and prevent unecessary
  update when it's not needed to gain speed.
   
  However, I can not guarantee that it will have high compatibility since I
  overwrite most of stuff. I will likely to make compatibility with my own
  scripts. But I'm not sure about someone's script.
  
  ------------------------------------------
  *) How to use :
  ------------------------------------------
  Put this script below material but above main. And it's recommended to put
  this above most of custom script.
  
  Set the type of optimization that you like in config
  You may disable some kind of optimization if you have compatibility issues
  
  ------------------------------------------
  *) Terms of use :
  ------------------------------------------
  Credit me, TheoAllen. You are free to edit this script by your own. As long
  as you don't claim it's yours. For commercial purpose, don't forget to give me
  a free copy of the game.
  
  Additional people to put in credit credit list are listed in header above.
  You should give them a free copy of your game as well if it's commercial ;)
  
=end
#==============================================================================
# Configurations :
#==============================================================================
module Theo
  module AntiLag
   
  #=============================================================================
  # *) Normal optimization
  #-----------------------------------------------------------------------------
  # This kind of optimization is for normal usage. These optimization may works
  # only if the total events on map is around 200 - 300.
  #=============================================================================
  
  #-----------------------------------------------------------------------------
    Optimize_XY     = true
  #-----------------------------------------------------------------------------
  # By default, event position checking is to check ALL the events on the map.
  # If you want to check an event is in x,y position, it ask EVERY event if
  # their position is match. By using this optimization, all events registered
  # to the map table so that the engine won't check all events on map. Instead,
  # it checks if there's event on a certain table.
  #
  # This kind of optimization is recommended to set it to true. However, it may
  # not compatible with any pixel movement since they using box collider instead
  # of using grid.
  #-----------------------------------------------------------------------------
  
  #-----------------------------------------------------------------------------
    Optimize_Event  = true
  #-----------------------------------------------------------------------------
  # By default, if the engine want to check if there's event starting, they
  # checked ALL the events on map. They did it in every frame. If you have 200
  # events in map, they checked 60 x 200 events per second.
  #
  # By using this optimization, if event is triggered, it will be registered
  # into a record. And then engine checked if there is event on the record
  #-----------------------------------------------------------------------------
  
  #-----------------------------------------------------------------------------
    Optimize_Sprite = true
  #-----------------------------------------------------------------------------
  # By default, the engine still update every sprites which located off screen.
  # This might waste the time since updating it is not necessary sometimes. By
  # using this optimization, it ignores character sprite that already off screen
  #-----------------------------------------------------------------------------
   
  #=============================================================================
  # *) Insane optimization
  #-----------------------------------------------------------------------------
  # This kind of optimization is to overcome the problem of using event beyond
  # 230 on the map which normal optimization is failed to do. This optimization
  # uses insane algorithm like table search and dispose any unecessary sprite on
  # the fly.
  #=============================================================================
   
  #-----------------------------------------------------------------------------
    Table_Limit_Search = 230
  #-----------------------------------------------------------------------------
  # Table search is a custom algorithm to grab events based on the map table.
  # Instead of iterating all events and checked them if they're on the screen,
  # it checked the visible map table instead. So, event that located far away
  # from the player won't be updated. But any parallel process or autorun events
  # or move route for an event will still updated.
  #
  # Table limit search means that if the total of events on map is above the
  # limit, this script will switch event update algorithm to table search. So
  # you will not worrying about having 999 or even 10.000 events on map.
  #
  # Table search required Optimize_XY to set to true.
  #
  # If you don't want to use table search algorithm, just put the parameter
  # to nil.
  #-----------------------------------------------------------------------------
  
  #-----------------------------------------------------------------------------
    Table_Range_Search = 2
  #-----------------------------------------------------------------------------
  # This determine how far table search will perform check. Putting 3 means that
  # it will update the event that located 3 tiles away from the screen.
  #
  # Keep in mind that the longer range search will affect the performance as
  # well. It's recommended to put it between 2 - 4
  #-----------------------------------------------------------------------------
  
  #-----------------------------------------------------------------------------
    Dispose_Sprite  = true
  #-----------------------------------------------------------------------------
  # Sometimes, limiting the events which is being updated is not enough. Sprite
  # objects is still being performace killer. Disposing sprite which is already
  # off screen will greatly affect the performance. This kind of optimization
  # is enabled only if the table search is used.
  #
  # Disposing sprite on the fly might be problematic sometimes. When something
  # wrong happened, you can disable dispose sprite be setting this to false.
  #-----------------------------------------------------------------------------
  
  #-----------------------------------------------------------------------------
    PageCheck_Enchancer = true
  #-----------------------------------------------------------------------------
  # When a lot of events put together in one map, and each has 20 pages, and
  # you have parallel process to change the variable or switches, you will see
  # noticable lag.
  #
  # This kind of enhancer only refresh the visible events on the screen or when
  # the event is on the visible range. So that it prevents to refresh all events
  # This concept is a fool proof to the player since they will never know what
  # is in their visible range
  #
  # However, this may ruin some system since this concept is still experimental.
  #-----------------------------------------------------------------------------
  
  end
end

#===============================================================================
# *) Final note :
#-------------------------------------------------------------------------------
# After all, these are just my attempt to speed up the game. Performance are
# still under influence by many factors. These include but may not limited to
#
# - Your CPU speed
# - Your laptop / PC temperature
# - How much power do you give for your CPU
# - Multi tasking
# - Someone's script
#
# I once used RM in old computer. When I switched to more advanced laptop, I
# saw that 60 FPS is really smooth.
#
# If your CPU seems overheat, turn off your laptop / PC for a while for cooling.
# My laptop was once overheat due to broken fan. When I played my own game I
# got 10 FPS. I made my own antilag and no one of them worked until I realized
# my laptop was overheat.
#
# Power saver mode in laptop may affect performance. Try to go high performance
# instead and let see if the lag gone. Once my friend played my game using power
# saver mode, and he got 15 FPS.
#
# If you have many programs running at same time, it may cause a little lag in
# RPG Maker games. Something like the screen won't be updated for a while.
#
# Some scripts can affect performance if it's not done right. This antilag
# script is tested using default script without additional scripts which
# directly affect something on map.
#
#-------------------------------------------------------------------------------
# *) Below this line is sacred place to visit. Unless you have enough skill,
# do not try to enter or any risk is yours.
#===============================================================================

#===============================================================================
# ** MapTable
#-------------------------------------------------------------------------------
#  This class used to register the event into 2D table to increase performance
#===============================================================================

class MapTable
  #-----------------------------------------------------------------------------
  # * Initialize
  #-----------------------------------------------------------------------------
  def initialize
    @table = []
    ($game_map.width + 1).times do |x|
      @table[x] = []
      ($game_map.height + 1).times do |y|
        @table[x][y] = []
      end
    end
  end
  #-----------------------------------------------------------------------------
  # * Set value
  #-----------------------------------------------------------------------------
  def set(x,y,val)
    @table[x][y] << val
  end
  #-----------------------------------------------------------------------------
  # * Get array
  #-----------------------------------------------------------------------------
  def get(x,y)
    @table[x][y]
  end
  
end

#===============================================================================
# ** Array
#===============================================================================

class Array
  
  # Just a fool proof
  def values
    return self
  end
  
end

#===============================================================================
# ** Game_Map
#===============================================================================

class Game_Map
  #-----------------------------------------------------------------------------
  # * Public attributes
  #-----------------------------------------------------------------------------
  attr_accessor :event_redirect     # Redirect events
  attr_reader :forced_update_events # To keep force move route updated
  attr_reader :keep_update_events   # To keep parallel process updated
  attr_reader :cached_events        # To store event that need to be updated
  attr_reader :starting_events      # To store activated event
  attr_reader :table                # 2D Map table
  #-----------------------------------------------------------------------------
  # * Constant
  #-----------------------------------------------------------------------------
  EVENT_LIMIT = Theo::AntiLag::Table_Limit_Search
  RANGE = Theo::AntiLag::Table_Range_Search
  #-----------------------------------------------------------------------------
  # * Alias method : Setup Events
  #-----------------------------------------------------------------------------
  alias theo_antilag_setup_events setup_events
  def setup_events
    @table = MapTable.new
    @forced_update_events = []
    @keep_update_events = []
    @starting_events = []
    @refreshed_events = []
    theo_antilag_setup_events
    select_on_screen_events
  end
  #-----------------------------------------------------------------------------
  # * Overwrite method : Events
  #-----------------------------------------------------------------------------
  def events
    @event_redirect ? @cached_events : @events
  end
#///////////////////////////////////////////////////////////////////////////////
  if Theo::AntiLag::Optimize_XY
#///////////////////////////////////////////////////////////////////////////////
  #-----------------------------------------------------------------------------
  # * Overwrite method : Event XY
  #-----------------------------------------------------------------------------
  def events_xy(x, y)
    @table.get(x,y) || []
  end
  #-----------------------------------------------------------------------------
  # * Overwrite method : Event XY nt
  #-----------------------------------------------------------------------------
  def events_xy_nt(x, y)
    @table.get(x,y).select do |event|
      event.pos_nt?(x, y)
    end
  end
#///////////////////////////////////////////////////////////////////////////////
  end
#///////////////////////////////////////////////////////////////////////////////
  if Theo::AntiLag::Optimize_Event
#///////////////////////////////////////////////////////////////////////////////
  #-----------------------------------------------------------------------------
  # * Overwrite method : Setup starting event
  #-----------------------------------------------------------------------------
  def setup_starting_map_event
    event = @starting_events[0]
    event.clear_starting_flag if event
    @interpreter.setup(event.list, event.id) if event
    event
  end
  #-----------------------------------------------------------------------------
  # * Overwrite method : Any event starting?
  #-----------------------------------------------------------------------------
  def any_event_starting?
    !@starting_events.empty?
  end
#///////////////////////////////////////////////////////////////////////////////
  end
#///////////////////////////////////////////////////////////////////////////////
  #-----------------------------------------------------------------------------
  # * Overwrite method : Refresh
  #-----------------------------------------------------------------------------
  def refresh
    return table_refresh if table_update? && Theo::AntiLag::PageCheck_Enchancer
    @events.each_value {|event| next if event.never_refresh; event.refresh }
    @common_events.each {|event| event.refresh }
    refresh_tile_events
    @need_refresh = false
  end
  #-----------------------------------------------------------------------------
  # * New method : Refresh event by table search
  #-----------------------------------------------------------------------------
  def table_refresh
    @refreshed_events = []
    @tile_events = []
    @common_events.each {|event| event.refresh }
    @need_refresh = false
  end
  #-----------------------------------------------------------------------------
  # * Overwrite method : Update events
  #-----------------------------------------------------------------------------
  def update_events
    last_events = (@cached_events.dup rescue @events.values)
    select_on_screen_events
    events = @cached_events | @keep_update_events | @forced_update_events
    if Theo::AntiLag::Dispose_Sprite
      offscreen_events = last_events - events
      offscreen_events.each {|event| event.delete_sprite}
    end
    events.each {|event| event.update}
    @common_events.each {|event| event.update}
  end
  #-----------------------------------------------------------------------------
  # * New method : Select on screen events
  #-----------------------------------------------------------------------------
  def select_on_screen_events
    unless table_update?
      @cached_events = @events.values
      return
    end
    #---------------------------------------------------------------------------
    # * Table search algorithm
    #---------------------------------------------------------------------------
    new_dpx = display_x.to_i
    new_dpy = display_y.to_i
    dpx = loop_horizontal? ? new_dpx - RANGE : [new_dpx - RANGE, 0].max
    dpy = loop_vertical? ? new_dpy - RANGE : [new_dpy - RANGE, 0].max
    sw = (Graphics.width >> 5) + RANGE * 2
    sh = (Graphics.height >> 5) + RANGE * 2
    @cached_events = []
    sw.times do |x|
      sh.times do |y|
        xpos = loop_horizontal? ? (x + dpx) % width : x + dpx
        ypos = loop_vertical? ? (y + dpy) % height : y + dpy
        next if xpos >= width || ypos >= height
        ary = @table.get(xpos, ypos)
        ary.each do |ev|
          unless @refreshed_events.include?(ev.id)
            ev.refresh
            @tile_events << ev if ev.tile?
            @refreshed_events << ev.id
          end
        end if Theo::AntiLag::PageCheck_Enchancer
        @cached_events += ary
      end
    end
    @cached_events.uniq!
  end
  #-----------------------------------------------------------------------------
  # * Check if table search need to be performed or not
  #-----------------------------------------------------------------------------
  def table_update?
    EVENT_LIMIT && @events.size > EVENT_LIMIT && Theo::AntiLag::Optimize_XY
  end
  
end

#===============================================================================
# ** Game_Temp
#===============================================================================

class Game_Temp
  attr_reader :event_sprites
  #-----------------------------------------------------------------------------
  # * Alias method : Initialize
  #-----------------------------------------------------------------------------
  alias theo_antilag_init initialize
  def initialize
    theo_antilag_init
    @event_sprites = {}
  end
  
end

#===============================================================================
# ** Game_CharacterBase
#===============================================================================

class Game_CharacterBase
  #-----------------------------------------------------------------------------
  # * Empty method : Sprite
  #-----------------------------------------------------------------------------
  def sprite
    return nil
  end
  #-----------------------------------------------------------------------------
  # * Empty method : Sprite =
  #-----------------------------------------------------------------------------
  def sprite=(spr)
  end
  
end

#===============================================================================
# ** Game_Event
#===============================================================================

class Game_Event
  #-----------------------------------------------------------------------------
  # * Never refesh flag
  #-----------------------------------------------------------------------------
  attr_reader :never_refresh
  #-----------------------------------------------------------------------------
  # * Alias method : Initialize
  #-----------------------------------------------------------------------------
  alias theo_antilag_init initialize
  def initialize(map_id, event)
    theo_antilag_init(map_id, event)
    $game_map.table.set(x,y,self)
    @last_x = @x
    @last_y = @y
  end
  #-----------------------------------------------------------------------------
  # * Alias method : Update
  #-----------------------------------------------------------------------------
  alias theo_antilag_update update
  def update
    if (sprite && sprite.disposed?) || sprite.nil?
      spriteset = SceneManager.scene.spriteset
      return unless spriteset
      spriteset.add_sprite(self)
    end
    theo_antilag_update
    if Theo::AntiLag::Optimize_XY && (@last_x != @x || @last_y != @y)
      $game_map.table.get(@last_x, @last_y).delete(self)
      $game_map.table.set(@x,@y,self)
      @last_x = @x
      @last_y = @y
    end
  end
  #-----------------------------------------------------------------------------
  # * Alias method : Start
  #-----------------------------------------------------------------------------
  alias theo_antilag_start start
  def start
    theo_antilag_start
    return unless Theo::AntiLag::Optimize_Event
    $game_map.starting_events << self if @starting
  end
  #-----------------------------------------------------------------------------
  # * Alias method : Clear starting flag
  #-----------------------------------------------------------------------------
  alias theo_antilag_clear_start clear_starting_flag
  def clear_starting_flag
    theo_antilag_clear_start
    return unless Theo::AntiLag::Optimize_Event
    $game_map.starting_events.delete(self)
  end
  #-----------------------------------------------------------------------------
  # * Alias method : Setup page setting
  #-----------------------------------------------------------------------------
  alias theo_antilag_setup_page_settings setup_page_settings
  def setup_page_settings
    theo_antilag_setup_page_settings
    if @event.pages.size == 1 && no_condition?(@event.pages[0].condition)
      @never_refresh = true
    end
    if @trigger == 3 || @interpreter
      $game_map.keep_update_events << self
      $game_map.keep_update_events.uniq!
    else
      $game_map.keep_update_events.delete(self)
    end
  end
  #-----------------------------------------------------------------------------
  # * Check if the events has no page condition
  #-----------------------------------------------------------------------------
  def no_condition?(page)
    !page.switch1_valid && !page.switch2_valid && !page.variable_valid &&
      !page.self_switch_valid && !page.item_valid && !page.actor_valid
  end
  #-----------------------------------------------------------------------------
  # * Delete sprite
  #-----------------------------------------------------------------------------
  def delete_sprite
    sprset = SceneManager.scene.spriteset
    return unless sprset
    SceneManager.scene.spriteset.delete_sprite(sprite)
  end
  #-----------------------------------------------------------------------------
  # * Overwrite method : Force move route
  #-----------------------------------------------------------------------------
  def force_move_route(move_route)
    super
    $game_map.forced_update_events << self
    $game_map.forced_update_events.uniq!
  end
  #-----------------------------------------------------------------------------
  # * Overwrite method : Restore move route
  #-----------------------------------------------------------------------------
  def restore_move_route
    super
    $game_map.forced_update_events.delete(self)
  end
  #-----------------------------------------------------------------------------
  # * Overwrite method : Sprite
  #-----------------------------------------------------------------------------
  def sprite
    $game_temp.event_sprites[@id]
  end
  #-----------------------------------------------------------------------------
  # * Overwrite method : Sprite =
  #-----------------------------------------------------------------------------
  def sprite=(spr)
    $game_temp.event_sprites[@id] = spr
  end
  
end

#===============================================================================
# ** Sprite Character
#===============================================================================

class Sprite_Character
  #-----------------------------------------------------------------------------
  # * Alias method : Initialize
  #-----------------------------------------------------------------------------
  alias theo_antilag_init initialize
  def initialize(viewport, character = nil)
    character.sprite = self if character
    theo_antilag_init(viewport, character)
  end
  #-----------------------------------------------------------------------------
  # * Alias method : Update
  #-----------------------------------------------------------------------------
  alias theo_antilag_update update
  def update
    @sx = @character.screen_x
    @sy = @character.screen_y
    if Theo::AntiLag::Optimize_Sprite && !need_update?
      self.visible = false
      return
    end  
    theo_antilag_update
  end
  #-----------------------------------------------------------------------------
  # * New method : Determine if on screen
  #-----------------------------------------------------------------------------
  def need_update?
    return true if graphic_changed?
    return true if @character.animation_id > 0
    return true if @balloon_sprite
    return true if @character.balloon_id != 0
    w = Graphics.width
    h = Graphics.height
    cw = @cw || 32
    ch = @ch || 32
    @sx.between?(-cw,w+cw) && @sy.between?(0,h+ch)
  end
  #-----------------------------------------------------------------------------
  # * Overwrite update position.
  # To limit screen_x and screen_y to be called many times
  #-----------------------------------------------------------------------------
  def update_position
    move_animation(@sx - x, @sy - y)
    self.x = @sx
    self.y = @sy
    self.z = @character.screen_z
  end
  #-----------------------------------------------------------------------------
  # * Overwrite animation origin
  # Since X and Y axis of sprite is not updated when off screen
  #-----------------------------------------------------------------------------
  def set_animation_origin
    if @animation.position == 3
      if viewport == nil
        @ani_ox = Graphics.width / 2
        @ani_oy = Graphics.height / 2
      else
        @ani_ox = viewport.rect.width / 2
        @ani_oy = viewport.rect.height / 2
      end
    else
      @ani_ox = @sx - ox + width / 2
      @ani_oy = @sy - oy + height / 2
      if @animation.position == 0
        @ani_oy -= height / 2
      elsif @animation.position == 2
        @ani_oy += height / 2
      end
    end
  end
  
end

#===============================================================================
# ** Spriteset_Map
#===============================================================================

class Spriteset_Map
  #-----------------------------------------------------------------------------
  # * Alias method : create character
  #-----------------------------------------------------------------------------
  alias theo_antilag_create_characters create_characters
  def create_characters
    $game_map.event_redirect = Theo::AntiLag::Dispose_Sprite
    theo_antilag_create_characters
    $game_map.event_redirect = false
  end
  #-----------------------------------------------------------------------------
  # * New method : delete sprite
  #-----------------------------------------------------------------------------
  def delete_sprite(spr)
    return unless spr
    return if spr.disposed?
    @character_sprites.delete(spr)
    spr.dispose
  end
  #-----------------------------------------------------------------------------
  # * New method : add sprite
  #-----------------------------------------------------------------------------
  def add_sprite(char)
    spr = Sprite_Character.new(@viewport1, char)
    @character_sprites.push(spr)
  end
  
end

#===============================================================================
# ** Scene_Base
#===============================================================================

class Scene_Base
  attr_reader :spriteset
end[/pre]




mod7

[pre lang="ruby"]#====================================================================
# Mode 7 Ace
# v.1.9
# Auteur : MGC
#
# Il s'agit d'un script de mode 7 basique pour RMVX Ace.
#
# - Permet une inclinaison de la carte de 0° à 89°
# - Toute la carte est inclinée, sans relief. Seuls les évènements
#   paraissent dressés verticalement.
# - L'effet de colorisation à l'horizon est personnalisable.
# - Les tiles animés sont supportés, ainsi que le bouclage de la carte.
# - possibilité de zoomer (de 1:8 à 8:1) quand le mode 7 est activé.
#
# IMPORTANT : SI VOUS RENCONTREZ DU LAG, VEUILLEZ VOUS ASSURER D'AVOIR
# DECOCHER "REDUCE SCREEN FLICKERING" (F1).
#
# Nécessite :
# - le fichier MGC_Mode7_Ace_1_9.dll à la racine du projet
# - les 3 fichiers graphiques suivants, déposés dans Pictures/ :
#         - autotiles_data.png
#         - autotiles_data_small.png
#         - autotiles_data_xsmall.png
#
# Configuration :
# - MODE7_MAPS_ID : Contient la liste des id des cartes pour lesquelles
#         le mode 7 est appliqué dès l'entrée sur ces cartes
# - MODE7_DEFAULT_ZOOM : valeur de zoom par défaut qui s'applique dès le
#         passage en mode 7. Compris entre 0.125 et 8.0.
# - MODE7_DEFAULT_ANGLE : valeur d'angle d'inclinaison par défaut qui
#         s'applique dès le passage en mode 7. Compris entre 0 et 89.
# - MODE7_VIEW_LIMIT : nombre de tiles supplémentaires à afficher (en plus
#         des 13 pour la vue normale de la carte en 544 * 416) avant l'horizon.
# - MODE7_FADING_DISTANCE : nombre de tiles avant l'horizon subissant un
#         dégradé de ton et/ou d'opacité.
# - MODE7_FADING_TONE : composantes de couleur R, G, B vers lesquelles tend
#         le dégradé de ton à l'horizon. Chaque composantes peut varier
#         entre -255 et 255.
# - MODE7_FADING_OPACITY : opacité vers laquelle tend le dégradé d'opacité ton
#         à l'horizon. Compris entre 255 (pas de dégradé d'opacité) et 0.
# - MODE7_SCAN_STEP : méthode de rafraîchissement de l'écran :
#         - 1 : l'écran est entièrement redessiné en 1 frame. Déconseillé
#               car extrêmement gourmand en ressources.
#         - 2 : l'écran est redessiné en 2 frames (une ligne de l'écran sur
#               deux est dessinée pour chaque frame).
#         - 3 : l'écran est redessiné en 3 frames (une ligne de l'écran sur
#               trois est dessinée pour chaque frame). Conseillé s'il y a
#               trop de lag.
# - MODE7_TERRAIN_TAGS : liste de valeurs de terrain tags pour lesquelles les
#         tiles doivent être dessinés verticalement en mode 7. Si le paramètre
#         MODE7_VERTICAL_TILES_TYPE n'a pas sa valeur égale à 0, utiliser
#         plusieurs valeurs permet de séparer des regroupements de tiles
#         contigus.
# - MODE7_VERTICAL_TILES_TYPE :
#         - 0 : aucun regroupement des tiles verticaux même si des tiles voisins
#               ont le même terrain tag. Pour un tile avec un terrain tag
#               configuré pour être dessiné verticalement, un sprite de
#               dimensions 32*32 est créé. A priori aucun intérêt sans la
#               rotation, car aura le même effet que la valeur 2 mais avec
#               plus de sprites à l'écran, donc plus de ralentissements.
#         - 1 : regroupement des tiles verticaux contigus sur la même colonne
#               ayant le même terrain tag. Un sprite est créé par regroupement,
#               le tile le plus bas du regroupement servant de base au sprite.
#               A priori aucun intérêt sans la rotation, car aura le même effet
#               que la valeur 3 mais avec plus de sprites à afficher.
#         - 2 : regroupement des tiles verticaux contigus sur la même ligne
#               ayant le même terrain tag. Un sprite est créé par regroupement,
#               l'origine horizontale étant fixée au milieu du regroupement.
#         - 3 : regroupement des tiles verticaux contigus ayant le même
#               terrain tag, quelle que soit la ligne ou la colonne. Un sprite
#               est créé par regroupement, le tile le plus bas du regroupement
#               servant de base au sprite et l'origine horizontale étant fixée
#               au milieu du regroupement. Valeur par défaut.
# - MODE7_ALWAYS_DRAW_TILES_ON_MAP :
#         - 0 : les tiles verticaux ne sont pas dessinés couchés sur la carte.
#               Valeur par défaut.
#         - 1 : les tiles verticaux sont également dessinés couchés sur la carte.
# - MODE7_PARALLAXED_MAPS_ID : Contient la liste des id des cartes en mode 7
#         pour lesquelles le panorama est utilisé en tant que couche inférieure.
#         Vous pouvez utiliser un second panorama pour le fond, il faut ajouter
#         dans les notes de la carte le texte suivant : [m7a_pano:nom_du_fichier]
#
# Utilisation :
# Commandes utilisables comme commandes d'évènement avec Script... :
# - MGC.start_mode7 : lance le mode 7 pour la carte
# - MGC.to_mode7_angle(nouvel angle, durée de transition)
# - MGC.to_mode7_zoom(nouvelle valeur de zoom, durée de transition)
# - MGC.end_mode7 : quitte le mode 7
# - MGC.set_mode7_scan(nouvelle valeur) : modifie le paramètre MODE7_SCAN_STEP
#
# Vous pouvez ajouter des commandes dans le nom des cartes pour forcer le
# paramétrage du mode 7 de la carte. Les paramètres dans le nom de la
# carte sont prioritaires par rapport à ceux dans la partie CONFIGURATION
# - [M7] : active le mode 7 pour la carte
# - [Ax], où x est un entier entre 0 et 89 : angle de la carte
# - [Zx], où x est un décimal entre 0.125 et 8.0 : zoom de la carte
# - [FDx], où x est un entier positif : nombre de tiles avant l'horizon
#         subissant un dégradé de ton et/ou d'opacité
# - [FTx,y,z], où x, y et z sont des entiers entre -255 et 255 :
#         composantes de couleur R, G, B vers lesquelles tend le dégradé
#         de ton à l'horizon
# - [FOx], où x est un entier entre 0 et 255 : opacité vers laquelle
#         tend le dégradé d'opacité ton à l'horizon
# - [P] : le panorama est utilisé en tant que couche inférieure de la carte
# Exemple :
# My Worldmap [M7][A55][Z0.5][FD20][FT128,64,-32][FO128]
#====================================================================
module MGC
  #--------------------------------------------------------------------------
  # * CONFIGURATION
  #--------------------------------------------------------------------------
  MODE7_MAPS_ID = []
  MODE7_DEFAULT_ZOOM = 1.0
  MODE7_DEFAULT_ANGLE = 0
  MODE7_VIEW_LIMIT = 26
  MODE7_FADING_DISTANCE = 13
  MODE7_FADING_TONE = Tone.new(64, 64, 128)
  MODE7_FADING_OPACITY = 0
  MODE7_SCAN_STEP = 2
  MODE7_TERRAIN_TAGS = [1, 2] # [1.7]
  MODE7_VERTICAL_TILES_TYPE = 3 # [1.7]
  MODE7_ALWAYS_DRAW_TILES_ON_MAP = 0 # [1.7]
  MODE7_PARALLAXED_MAPS_ID = [] # [1.9]
  #--------------------------------------------------------------------------
  # * Initialisation
  #--------------------------------------------------------------------------
  @mode7_zoom = 1.0
  @mode7_active = false
  #--------------------------------------------------------------------------
  # * Lancement du mode 7
  #--------------------------------------------------------------------------
  def self.start_mode7
    @end_mode7 = false
    @spriteset.start_mode7
  end
  #--------------------------------------------------------------------------
  # * Fin du mode 7
  #--------------------------------------------------------------------------
  def self.end_mode7
    @end_mode7 = true
    self.to_mode7_zoom(1.0, 1)
  end
  #--------------------------------------------------------------------------
  # * Setter pour l'attribut spriteset
  #--------------------------------------------------------------------------
  def self.spriteset=(spriteset)
    @spriteset = spriteset
  end
  #--------------------------------------------------------------------------
  # * Initialisation des données du mode 7
  #--------------------------------------------------------------------------
  def self.initialize_mode7(reset = false) # [1.9]
    if reset
      self.mode7_angle = $game_map.get_default_mode7_angle
      @mode7_zoom = $game_map.get_default_mode7_zoom
    else
      self.mode7_angle = $game_system.mode7_angle ? $game_system.mode7_angle :
      $game_map.get_default_mode7_angle
      @mode7_zoom = $game_system.mode7_zoom ? $game_system.mode7_zoom :
      $game_map.get_default_mode7_zoom
    end
    @mode7_angle_duration = 0
    @mode7_zoom_incr = Math.log(@mode7_zoom) / Math.log(2)
    @mode7_zoom_duration = 0
    pivot = (Graphics.height >> 1) + 12
    @mode7_data = [pivot, pivot.to_f / Graphics.height, 1.0, 1.0, 0,
    Graphics.height, 0, 0, 0, 0]
  end
  #--------------------------------------------------------------------------
  # * Change Map
  #--------------------------------------------------------------------------
  def self.start_change_map
    self.mode7_angle = $game_map.get_default_mode7_angle
    @mode7_angle_duration = 0
    @mode7_zoom = $game_map.get_default_mode7_zoom
    @mode7_zoom_incr = Math.log(@mode7_zoom) / Math.log(2)
    @mode7_zoom_duration = 0
    @change_map = true
  end
  #--------------------------------------------------------------------------
  # * Is Changing Map ?
  #--------------------------------------------------------------------------
  def self.is_changing_map?
    return @change_map
  end
  #--------------------------------------------------------------------------
  # * End Change Map
  #--------------------------------------------------------------------------
  def self.end_change_map
    @change_map = false
  end
  #--------------------------------------------------------------------------
  # * Getter pour l'attribut mode7_data
  #--------------------------------------------------------------------------
  def self.mode7_data
    return @mode7_data
  end
  #--------------------------------------------------------------------------
  # * Getter pour l'attribut mode7_zoom
  #--------------------------------------------------------------------------
  def self.mode7_zoom
    return @mode7_zoom
  end
  #--------------------------------------------------------------------------
  # * Getter pour l'attribut mode7_angle
  #--------------------------------------------------------------------------
  def self.mode7_angle
    return @mode7_angle
  end
  #--------------------------------------------------------------------------
  # * Getter pour l'attribut mode7_active
  #--------------------------------------------------------------------------
  def self.mode7_active
    return @mode7_active
  end
  #--------------------------------------------------------------------------
  # * Setter pour l'attribut mode7_active
  #--------------------------------------------------------------------------
  def self.mode7_active=(flag)
    $game_system.mode7_active = flag
    @mode7_active = flag
  end
  #--------------------------------------------------------------------------
  # * Setter pour l'attribut mode7_zoom
  #--------------------------------------------------------------------------
  def self.mode7_zoom=(zoom_value)
    unless mode7_zoom == zoom_value
      if zoom_value < 0.125 || zoom_value > 8.0 then return end
      @mode7_zoom = zoom_value
      $game_system.mode7_zoom = @mode7_zoom
      $game_player.center($game_player.x, $game_player.y)
    end
  end
  #--------------------------------------------------------------------------
  # * Incrémentation de la valeur du zoom du mode 7
  #--------------------------------------------------------------------------
  def self.incr_mode7_zoom(val = 0.02)
    @mode7_zoom_incr += val
    new_zoom = 2 ** @mode7_zoom_incr
    self.mode7_zoom = new_zoom
  end
  #--------------------------------------------------------------------------
  # * Pour aller progressivement vers une nouvelle valeur de zoom du mode 7
  #--------------------------------------------------------------------------
  def self.to_mode7_zoom(new_zoom, duration)
    unless mode7_zoom == new_zoom
      if new_zoom < 0.125 || new_zoom > 8.0 then return end
      @mode7_zoom_duration = duration
      target_zoom_incr = Math.log(new_zoom) / Math.log(2)
      @mode7_zoom_step = (target_zoom_incr - @mode7_zoom_incr) / duration
      @target_mode7_zoom = new_zoom
    end
  end
  #--------------------------------------------------------------------------
  # * Setter pour l'attribut mode7_angle
  #--------------------------------------------------------------------------
  def self.mode7_angle=(new_angle)
    unless new_angle == @mode7_angle
      @mode7_angle = [[new_angle, 0].max, 89].min
      @mode7_angle_real = @mode7_angle
      $game_system.mode7_angle = @mode7_angle
    end
  end
  #--------------------------------------------------------------------------
  # * Autre setter pour l'attribut mode7_angle, ne réinitialisant pas @mode7_angle_real
  #--------------------------------------------------------------------------
  def self.set_mode7_angle(new_angle)
    unless new_angle == @mode7_angle
      @mode7_angle = [[new_angle, 0].max, 89].min
      $game_system.mode7_angle = @mode7_angle
    end
  end
  #--------------------------------------------------------------------------
  # * Incrémentation de la valeur de l'angle du mode 7
  #--------------------------------------------------------------------------
  def self.incr_mode7_angle
    @mode7_angle_real += @mode7_angle_step
    self.set_mode7_angle(@mode7_angle_real.to_i)
  end
  #--------------------------------------------------------------------------
  # * Pour aller progressivement vers une nouvelle valeur de l'angle du mode 7
  #--------------------------------------------------------------------------
  def self.to_mode7_angle(new_angle, duration)
    unless @mode7_angle == new_angle
      new_angle = [[new_angle, 0].max, 89].min
      @mode7_angle_duration = duration
      @mode7_angle_step = (new_angle - @mode7_angle).to_f / duration
      @target_mode7_angle = new_angle
    end
  end
  #--------------------------------------------------------------------------
  # * Mise à jour du mode 7
  #--------------------------------------------------------------------------
  def self.update_mode7
    if @mode7_active
      if @mode7_zoom_duration > 0
        @mode7_zoom_duration -= 1
        if @mode7_zoom_duration == 0
          self.mode7_zoom = @target_mode7_zoom
        else
          self.incr_mode7_zoom(@mode7_zoom_step)
        end
      elsif @mode7_angle_duration > 0
        @mode7_angle_duration -= 1
        if @mode7_angle_duration == 0
          self.mode7_angle = @target_mode7_angle
        else
          self.incr_mode7_angle
        end
      elsif @end_mode7
        @spriteset.end_mode7
        @end_mode7 = false
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Vérifie si un effet est en cours
  #--------------------------------------------------------------------------
  def self.effect?
    return @mode7_active && (@mode7_zoom_duration > 0 ||
    @mode7_angle_duration > 0 || @end_mode7)
  end
  #--------------------------------------------------------------------------
  # * Modifie la valeur de la méthode de rafraîchissement de l'écran
  #--------------------------------------------------------------------------
  def self.set_mode7_scan(new_value)
    new_value = [[new_value, 1].max, 3].min
    unless MODE7_SCAN_STEP == new_value
      self.const_set(:MODE7_SCAN_STEP, new_value)
    end
  end
  #==============================================================================
  # ** MGC::Mode7_Map
  #==============================================================================
  class Mode7_Map
    #--------------------------------------------------------------------------
    # * Attributs
    #--------------------------------------------------------------------------
    attr_reader :viewport, :visible, :ox, :oy, :opacity, :blend_type, :color,
    :tone, :wave_amp, :wave_length, :wave_speed, :wave_phase, :zoom, :map_data,
    :flags
    attr_accessor :bitmaps, :flash_data
    attr_reader :alpha, :parameters
    attr_reader :param_tiles # [1.7]
    attr_reader :map_id # [1.9]
    #--------------------------------------------------------------------------
    # * Constantes
    #--------------------------------------------------------------------------
    RENDER = Win32API.new("MGC_Mode7_Ace_Rot_1_9", "renderMode7", "l", "l")
    #--------------------------------------------------------------------------
    # * Initialisation
    #--------------------------------------------------------------------------
    def initialize(viewport)
      @viewport = viewport
      self.bitmaps = [0, 0, 0, 0, 0, 0, 0, 0, 0]
      @map_data = 0
      @flags = 0
      self.flash_data = nil
      @cx = Graphics.width >> 1
      @cy = Graphics.height >> 1
      @sprite_render = Sprite.new(viewport)
      @render = Bitmap.new(Graphics.width, Graphics.height)
      @sprite_render.bitmap = @render
      @sprite_render.x = 0
      @sprite_render.y = 0
      @sprite_render.z = 0
      @zoom = 1.0
      @view_limit = MODE7_VIEW_LIMIT << 5
      m7_data = Table.new(6, Graphics.height) # [1.7]
      @parameters = [@render, 0, map_data, bitmaps,
      Cache.picture('autotiles_data'), Cache.picture('autotiles_data_small'),
      Cache.picture('autotiles_data_xsmall'), 0, 0, 0, 0, 0, 0, 0, 4096,
      100, $game_map.loop_horizontal?, $game_map.loop_vertical?, MODE7_SCAN_STEP,
      0, m7_data, 2048, 0, MGC.mode7_data[5], MGC.mode7_data[0], 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0]
      @parameters << $game_map.tileset.flags # 36 [1.7]
      @parameters << MGC::MODE7_ALWAYS_DRAW_TILES_ON_MAP # 37 [1.7]
      @parameters << MGC::MODE7_TERRAIN_TAGS # 38 [1.7]
      @parameters << 0 # 39 [1.9]
      refresh_fading
      MGC.mode7_data[9] = m7_data
      self.alpha = 0
      self.visible = true
      self.zoom = 1.0
      self.ox = 0
      self.oy = 0
      self.opacity = 255
      self.blend_type = 0
      self.color = Color.new
      self.tone = Tone.new
      self.wave_amp = 0
      self.wave_length = 180
      self.wave_speed = 360
      self.wave_phase = 0.0
      @initialization = true
      @param_tiles = [Bitmap.new(32, 32), bitmaps,
      Cache.picture('autotiles_data'),
      Cache.picture('autotiles_data_small'),
      Cache.picture('autotiles_data_xsmall'), 0, [0, 0, 0]] # [1.7]
      @map_id = $game_map.map_id # [1.9]
    end
    #--------------------------------------------------------------------------
    # * Refresh Fading
    #--------------------------------------------------------------------------
    def refresh_fading
      fading_dist = $game_map.get_default_fading_distance << 5
      fading_begin = Graphics.height + @view_limit - fading_dist
      @parameters[30] = fading_begin
      @parameters[31] = fading_dist
      @parameters[32] = $game_map.get_default_fading_tone.red.to_i
      @parameters[33] = $game_map.get_default_fading_tone.green.to_i
      @parameters[34] = $game_map.get_default_fading_tone.blue.to_i
      @parameters[35] = $game_map.get_default_fading_opacity
    end
    #--------------------------------------------------------------------------
    # * Refresh all the parameters dependent on the angle of slant
    #--------------------------------------------------------------------------
    def refresh_alpha
      # angle of slant
      alpha_rad = (Math::PI * alpha) / 180
      cos_alpha_real = Math.cos(alpha_rad)
      sin_alpha_real = Math.sin(alpha_rad)
      cos_alpha = (2048 * cos_alpha_real).to_i
      sin_alpha = (2048 * sin_alpha_real).to_i
      distance_h = MGC.mode7_data[5]
      pivot = MGC.mode7_data[0]
      # h0,  z0 : intermediate values used to calculate the slope
      h0 = (-distance_h * pivot * cos_alpha) / ((distance_h << 11) +
      pivot * sin_alpha) + pivot
      z0 = (distance_h << 11).to_f / ((distance_h << 11) + pivot * sin_alpha)
      # slope
      slope_value = (1.0 - z0) / (pivot - h0)
      slope_value_map = (131072 * slope_value).to_i
      corrective_value = 1.0 - pivot * slope_value
      corrective_value_map = (131072 * corrective_value).to_i
      last_line = ((-pivot - @view_limit) * zoom).to_i
      height_limit = (distance_h * last_line * cos_alpha) /
      ((distance_h << 11) - last_line * sin_alpha) + pivot
      height_limit = [height_limit.to_i, 0].max
      parameters[21] = cos_alpha
      parameters[22] = sin_alpha
      parameters[25] = slope_value_map
      parameters[26] = corrective_value_map
      parameters[27] = height_limit
      parameters[29] = MODE7_SCAN_STEP
      @need_refresh = true
      MGC.mode7_data[3] = cos_alpha_real
      MGC.mode7_data[4] = sin_alpha_real
      MGC.mode7_data[6] = slope_value
      MGC.mode7_data[7] = corrective_value
      MGC.mode7_data[8] = height_limit     
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut map_data
    #--------------------------------------------------------------------------
    def map_data=(new_map_data)
      @map_data = new_map_data
      parameters[2] = @map_data
    end
    #--------------------------------------------------------------------------
    # * Charge le panorama en mode 7 [1.9]
    #--------------------------------------------------------------------------
    def parallax=(new_parallax)
      if new_parallax
        parameters[39] = new_parallax
      else
        parameters[39] = 0
      end
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut flags
    #--------------------------------------------------------------------------
    def flags=(new_flags)
      @flags = new_flags
      parameters[7] = @flags
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut zoom
    #--------------------------------------------------------------------------
    def zoom=(new_zoom)
      unless zoom == new_zoom
        @zoom = new_zoom
        parameters[14] = (4096.0 / new_zoom).to_i
        MGC.mode7_data[2] = new_zoom
        vox = @ox
        @ox = nil
        self.ox = vox
        voy = @oy
        @oy = nil
        self.oy = voy
        @need_refresh = true
        parameters[29] = MODE7_SCAN_STEP
        @need_refresh = true
        last_line = ((-parameters[24] - @view_limit) * zoom).to_i
        height_limit = (parameters[23] * last_line * parameters[21]) /
        ((parameters[23] << 11) - last_line * parameters[22]) + parameters[24]
        parameters[27] = [height_limit.to_i, 0].max
        MGC.mode7_data[8] = parameters[27]
      end
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut alpha
    #--------------------------------------------------------------------------
    def alpha=(new_alpha)
      unless new_alpha == alpha
        @alpha = new_alpha
        refresh_alpha
      end
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut shadow_opacity
    #--------------------------------------------------------------------------
    def shadow_opacity=(value)
      @parameters[15] = [[value, 0].max, 255].min
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut visible
    #--------------------------------------------------------------------------
    def visible=(flag)
      @visible = flag
      @sprite_render.visible = flag
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut ox
    #--------------------------------------------------------------------------
    def ox=(new_ox)
      new_ox = new_ox.to_i
      unless new_ox == @ox
        @ox = new_ox
        @need_refresh = true
        parameters[8] = @ox
        parameters[29] = MODE7_SCAN_STEP
      end
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut oy
    #--------------------------------------------------------------------------
    def oy=(new_oy)
      new_oy = new_oy.to_i
      unless new_oy == @oy
        @oy = new_oy
        @need_refresh = true
        parameters[9] = @oy
        parameters[29] = MODE7_SCAN_STEP
      end
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut opacity
    #--------------------------------------------------------------------------
    def opacity=(new_opacity)
      @opacity = new_opacity
      @sprite_render.opacity = new_opacity
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut blend_type
    #--------------------------------------------------------------------------
    def blend_type=(new_blend_type)
      @blend_type = new_blend_type
      @sprite_render.blend_type = new_blend_type
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut color
    #--------------------------------------------------------------------------
    def color=(new_color)
      @color = new_color
      @sprite_render.color = new_color
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut tone
    #--------------------------------------------------------------------------
    def tone=(new_tone)
      @tone = new_tone
      @sprite_render.tone = new_tone
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut wave_amp
    #--------------------------------------------------------------------------
    def wave_amp=(new_wave_amp)
      @wave_amp = new_wave_amp
      @sprite_render.wave_amp = new_wave_amp
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut wave_length
    #--------------------------------------------------------------------------
    def wave_length=(new_wave_length)
      @wave_length = new_wave_length
      @sprite_render.wave_length = new_wave_length
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut wave_speed
    #--------------------------------------------------------------------------
    def wave_speed=(new_wave_speed)
      @wave_speed = new_wave_speed
      @sprite_render.wave_speed = new_wave_speed
    end
    #--------------------------------------------------------------------------
    # * Setter pour l'attribut wave_phase
    #--------------------------------------------------------------------------
    def wave_phase=(new_wave_phase)
      @wave_phase = new_wave_phase
      @sprite_render.wave_phase = new_wave_phase
    end
    #--------------------------------------------------------------------------
    # * Libération de l'instance
    #--------------------------------------------------------------------------
    def dispose
      @render.dispose
      @sprite_render.dispose
      clear_vertical_tiles # [1.7]
      @param_tiles[0].dispose
    end
    #--------------------------------------------------------------------------
    # * Suppression des tiles verticaux [1.7]
    #--------------------------------------------------------------------------
    def clear_vertical_tiles
      if @vertical_tiles
        @vertical_tiles.each {|sprite| sprite.dispose}
        @vertical_tiles.clear
      end
    end
    #--------------------------------------------------------------------------
    # * Retourne true si l'instance a été libérée
    #--------------------------------------------------------------------------
    def disposed?
      return @render.disposed?
    end
    #--------------------------------------------------------------------------
    # * Mise à jour, appelée normalement à chaque frame
    #--------------------------------------------------------------------------
    def update
      if @visible
        if MGC.is_changing_map?
          refresh_fading
          MGC.end_change_map
        end
        if parameters[18] != MODE7_SCAN_STEP
          parameters[18] = MODE7_SCAN_STEP
          parameters[19] = 0
          parameters[29] = 0
          @need_refresh = true
        end
        self.alpha = MGC.mode7_angle
        self.zoom = MGC.mode7_zoom
        if Graphics.frame_count & 31 == 0
          parameters[10] += 1
          parameters[10] %= 3
          parameters[29] = MODE7_SCAN_STEP
          unless @need_refresh
            @need_refresh_anim = true
          end
        end
        if parameters[29] > 0 && !@need_refresh && !@need_refresh_anim
          @need_refresh = true
        end
        begin
          if @need_refresh
            parameters[19] += 1
            if parameters[19] == parameters[18]
              parameters[19] = 0
            end
            parameters[11] = 0
            RENDER.call(parameters.__id__)
            parameters[29] -= 1
            if parameters[29] == 0
              @need_refresh = false
            end
          elsif @need_refresh_anim
            parameters[19] += 1
            if parameters[19] == parameters[18]
              parameters[19] = 0
            end
            parameters[11] = 1
            RENDER.call(parameters.__id__)
            parameters[29] -= 1
            if parameters[29] == 0
              @need_refresh_anim = false
            end
          end
          if @initialization && parameters[29] == 0
            @initialization = false
          end
        end while @initialization
        @sprite_render.update
        @vertical_tiles.each {|sprite| sprite.update} # [1.7]
      end
    end
    #--------------------------------------------------------------------------
    # * Flash des couches de la tilemap
    #--------------------------------------------------------------------------
    def flash(color, duration)
      @sprite_render.flash(color, duration)
    end
    #--------------------------------------------------------------------------
    # * Create vertical tiles [1.7]
    #--------------------------------------------------------------------------
    def create_vertical_tiles
      unless @vertical_tiles
        @vertical_tiles = []
      end
      clear_vertical_tiles
      @vt_checked_tiles = Table.new($game_map.width, $game_map.height,
      MGC::MODE7_TERRAIN_TAGS.size)
      (0...$game_map.height).each {|iy|
        (0...$game_map.width).each {|ix|
          (0...3).each {|il|
            terrain_tag = $game_map.terrain_tag_for_layer(ix, iy, il)
            if terrain_tag > 0 && MGC::MODE7_TERRAIN_TAGS.include?(terrain_tag)
              tag_index = MGC::MODE7_TERRAIN_TAGS.index(terrain_tag)
              unless @vt_checked_tiles[ix, iy, tag_index] == 1
                @vt_found_tiles = []
                @vt_x_min = ix
                @vt_x_max = ix
                @vt_y_min = iy
                @vt_y_max = iy
                find_linked_tiles(ix, iy, terrain_tag, tag_index)
                v_tile = MGC::Vertical_Tile.new(self, @viewport)
                v_tile.x = 1 + @vt_x_max + @vt_x_min << 5 >> 1
                v_tile.y = 1 + @vt_y_max << 5
                v_tile.refresh_tile_data(@vt_found_tiles,
                @vt_x_min, @vt_x_max, @vt_y_min, @vt_y_max)
                @vertical_tiles << v_tile
                break
              end
            end
          }
        }
      }
      @vt_checked_tiles = nil
    end
    #--------------------------------------------------------------------------
    # * Find linked tiles [1.7]
    # param x : Integer
    # param y : Integer
    # param terrain_tag : Integer
    # param tag_index : Integer
    #--------------------------------------------------------------------------
    def find_linked_tiles(x, y, terrain_tag, tag_index)
      unless @vt_checked_tiles[x, y, tag_index] == 1
        @vt_checked_tiles[x, y, tag_index] = 1
        found = false
        (0...3).each {|il|
          if $game_map.terrain_tag_for_layer(x, y, il) == terrain_tag
            unless found
              found_tile = [x, y, [false, false, false]]
              @vt_found_tiles << found_tile
              found = true
            end
            found_tile[2][il] = true
          end
        }
        if found
          if x > @vt_x_max
            @vt_x_max = x
          end
          if x < @vt_x_min
            @vt_x_min = x
          end
          if y > @vt_y_max
            @vt_y_max = y
          end
          if y < @vt_y_min
            @vt_y_min = y
          end
          if MGC::MODE7_VERTICAL_TILES_TYPE & 1 == 1
            if y < $game_map.height - 1
              find_linked_tiles(x, y + 1, terrain_tag, tag_index)
            end
          end
          if MGC::MODE7_VERTICAL_TILES_TYPE & 2 == 2
            if x < $game_map.width - 1
              find_linked_tiles(x + 1, y, terrain_tag, tag_index)
            end
          end
          if MGC::MODE7_VERTICAL_TILES_TYPE == 3
            if x > 0
              find_linked_tiles(x - 1, y, terrain_tag, tag_index)
            end
            if y > 0
              find_linked_tiles(x, y - 1, terrain_tag, tag_index)
            end
          end
        end
      end
    end
  end
end

#==============================================================================
# ** Game_System
#==============================================================================
class Game_System
  #--------------------------------------------------------------------------
  # * Attributs
  #--------------------------------------------------------------------------
  attr_accessor :mode7_zoom, :mode7_angle, :mode7_active
end

#==============================================================================
# ** Game_Map
#==============================================================================
class Game_Map
  attr_accessor :start_mode7, :end_mode7
  #--------------------------------------------------------------------------
  # * Aliased methods
  #--------------------------------------------------------------------------
  unless @already_aliased_mgc_m7a
    alias setup_mgc_m7a setup
    alias set_display_pos_mgc_m7a set_display_pos
    alias scroll_down_mgc_m7a scroll_down
    alias scroll_left_mgc_m7a scroll_left
    alias scroll_right_mgc_m7a scroll_right
    alias scroll_up_mgc_m7a scroll_up
    @already_aliased_mgc_m7a = true
  end
  #--------------------------------------------------------------------------
  # * Setup
  #--------------------------------------------------------------------------
  def setup(map_id)
    setup_mgc_m7a(map_id)
    @map = load_data(sprintf("Data/Map%03d.rvdata2", map_id)) # [1.9]
    if is_mode7?
      if MGC.mode7_active
        MGC.start_change_map
      end
      self.start_mode7 = true
    else
      self.end_mode7 = true
    end
  end
  #--------------------------------------------------------------------------
  # * Check if the map is configured for mode 7
  #--------------------------------------------------------------------------
  def is_mode7?
    return MGC::MODE7_MAPS_ID.include?(@map_id) ||
    $data_mapinfos[@map_id].full_name[/\[M7\]/]
  end
  #--------------------------------------------------------------------------
  # * Get default mode7 angle
  #--------------------------------------------------------------------------
  def get_default_mode7_angle
    if $data_mapinfos[@map_id].full_name[/\[A(\d+)\]/]
      return [[$1.to_i, 0].max, 89].min
    else
      return MGC::MODE7_DEFAULT_ANGLE
    end
  end
  #--------------------------------------------------------------------------
  # * Get default mode7 zoom
  #--------------------------------------------------------------------------
  def get_default_mode7_zoom
    if $data_mapinfos[@map_id].full_name[/\[Z(\d+(?:\.\d+)*)\]/]
      return [[$1.to_f, 0.125].max, 8.0].min
    else
      return MGC::MODE7_DEFAULT_ZOOM
    end
  end
  #--------------------------------------------------------------------------
  # * Get default fading distance
  #--------------------------------------------------------------------------
  def get_default_fading_distance
    if $data_mapinfos[@map_id].full_name[/\[FD(\d{1,3})\]/]
      return [$1.to_i, 0].max
    else
      return MGC::MODE7_FADING_DISTANCE
    end
  end
  #--------------------------------------------------------------------------
  # * Get default fading opacity
  #--------------------------------------------------------------------------
  def get_default_fading_opacity
    if $data_mapinfos[@map_id].full_name[/\[FO(\d{1,3})\]/]
      return [[$1.to_i, 0].max, 255].min
    else
      return MGC::MODE7_FADING_OPACITY
    end
  end
  #--------------------------------------------------------------------------
  # * Get default fading tone
  #--------------------------------------------------------------------------
  def get_default_fading_tone
    if $data_mapinfos[@map_id].full_name[/\[FT(\-?\d{1,3}),(\-?\d{1,3}),(\-?\d{1,3})\]/]
      red = [[$1.to_i, -255].max, 255].min
      green = [[$2.to_i, -255].max, 255].min
      blue = [[$3.to_i, -255].max, 255].min
      return Tone.new(red, green, blue)
    else
      return MGC::MODE7_FADING_TONE
    end
  end
  #--------------------------------------------------------------------------
  # * Check if the map is parallaxed [1.9]
  #--------------------------------------------------------------------------
  def is_parallaxed?
    return MGC::MODE7_PARALLAXED_MAPS_ID.include?(@map_id) ||
    $data_mapinfos[@map_id].full_name[/\[P\]/]
  end
  #--------------------------------------------------------------------------
  # * Check if the parallaxed map has a panorama in mode 7 [1.9]
  #--------------------------------------------------------------------------
  def has_additionnal_panorama?
    return @map.note[/\[m7a_pano:\w+\]/]
  end
  #--------------------------------------------------------------------------
  # * Return the panorama in mode 7 if the map is parallaxed [1.9]
  #--------------------------------------------------------------------------
  def set_additional_panorama
    if @map.note[/\[m7a_pano:(\w+)\]/]
      @parallax_name = $1
    end
  end
  #--------------------------------------------------------------------------
  # * Set Display Position
  #--------------------------------------------------------------------------
  def set_display_pos(x, y)
    if MGC.mode7_active
      if loop_horizontal?
        @display_x = (x + width) % width
      else
        if MGC.mode7_zoom < 1.0 && width * MGC.mode7_zoom < screen_tile_x
          @display_x = (width - screen_tile_x) / 2
        else
          x_min = screen_tile_x * (1.0 / MGC.mode7_zoom - 1.0) / 2
          x_max = width + screen_tile_x * ((1.0 - 1.0 / MGC.mode7_zoom) / 2 - 1)
          x = [x_min, [x, x_max].min].max
          @display_x = x
        end
      end
      if loop_vertical?
        @display_y = (y + height) % height
      else
        if MGC.mode7_zoom < 1.0 && height * MGC.mode7_zoom < screen_tile_y
          @display_y = (height - screen_tile_y) * MGC.mode7_data[1]
        else
          y_min = screen_tile_y * (1.0 / MGC.mode7_zoom - 1.0) * MGC.mode7_data[1]
          y_max = height + screen_tile_y *
          ((1.0 - 1.0 / MGC.mode7_zoom) * (1 - MGC.mode7_data[1]) - 1)
          y = [y_min, [y, y_max].min].max
          @display_y = y
        end
      end
      @parallax_x = x
      @parallax_y = y
    else
      set_display_pos_mgc_m7a(x, y)
    end
  end
  #--------------------------------------------------------------------------
  # * Scroll Down
  #--------------------------------------------------------------------------
  def scroll_down(distance)
    if MGC.mode7_active
      if loop_vertical?
        @display_y += distance
        @display_y %= @map.height
        @parallax_y += distance if @parallax_loop_y
      else
        last_y = @display_y
        if MGC.mode7_zoom < 1.0 && height * MGC.mode7_zoom < screen_tile_y
          @display_y = (height - screen_tile_y) * MGC.mode7_data[1]
        else
          max = height + screen_tile_y *
          ((1.0 - 1.0 / MGC.mode7_zoom) * (1 - MGC.mode7_data[1]) - 1)
          @display_y = [@display_y + distance, max].min
        end
        @parallax_y += @display_y - last_y
      end
    else
      scroll_down_mgc_m7a(distance)
    end
  end
  #--------------------------------------------------------------------------
  # * Scroll Left
  #--------------------------------------------------------------------------
  def scroll_left(distance)
    if MGC.mode7_active
      if loop_horizontal?
        @display_x += @map.width - distance
        @display_x %= @map.width
        @parallax_x -= distance if @parallax_loop_x
      else
        last_x = @display_x
        if MGC.mode7_zoom < 1.0 && width * MGC.mode7_zoom < screen_tile_x
          @display_x = (width - screen_tile_x) / 2
        else
          min = screen_tile_x * (1.0 / MGC.mode7_zoom - 1.0) / 2
          @display_x = [@display_x - distance, min].max
        end
        @parallax_x += @display_x - last_x
      end
    else
      scroll_left_mgc_m7a(distance)
    end
  end
  #--------------------------------------------------------------------------
  # * Scroll Right
  #--------------------------------------------------------------------------
  def scroll_right(distance)
    if MGC.mode7_active
      if loop_horizontal?
        @display_x += distance
        @display_x %= @map.width
        @parallax_x += distance if @parallax_loop_x
      else
        last_x = @display_x
        if MGC.mode7_zoom < 1.0 && width * MGC.mode7_zoom < screen_tile_x
          @display_x = (width - screen_tile_x) / 2
        else
          max = width + screen_tile_x * ((1.0 - 1.0 / MGC.mode7_zoom) / 2 - 1)
          @display_x = [@display_x + distance, max].min
        end
        @parallax_x += @display_x - last_x
      end
    else
      scroll_right_mgc_m7a(distance)
    end
  end
  #--------------------------------------------------------------------------
  # * Scroll Up
  #--------------------------------------------------------------------------
  def scroll_up(distance)
    if MGC.mode7_active
      if loop_vertical?
        @display_y += @map.height - distance
        @display_y %= @map.height
        @parallax_y -= distance if @parallax_loop_y
      else
        last_y = @display_y
        if MGC.mode7_zoom < 1.0 && height * MGC.mode7_zoom < screen_tile_y
          @display_y = (height - screen_tile_y) * MGC.mode7_data[1]
        else
          min = screen_tile_y * (1.0 / MGC.mode7_zoom - 1.0) * MGC.mode7_data[1]
          @display_y = [@display_y - distance, min].max
        end
        @parallax_y += @display_y - last_y
      end
    else
      scroll_up_mgc_m7a(distance)
    end
  end
  #--------------------------------------------------------------------------
  # * Get Terrain Tag for a layer [1.7]
  #--------------------------------------------------------------------------
  def terrain_tag_for_layer(x, y, layer)
    return 0 unless valid?(x, y)
    return tileset.flags[tile_id(x, y, layer)] >> 12
  end
end

#==============================================================================
# ** Game_CharacterBase
#==============================================================================
class Game_CharacterBase
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :sprite
end

#==============================================================================
# ** Serialisation
#==============================================================================
[:Sprite, :Viewport, :Bitmap, :Font].each {|classname|
  eval(
  "class #{classname}
    def marshal_dump
      return []
    end
    def marshal_load(array)
    end
  end")
}

#==============================================================================
# ** Sprite
#==============================================================================
class Sprite
  #--------------------------------------------------------------------------
  # * Aliased methods
  #--------------------------------------------------------------------------
  unless @already_aliased_mgc_m7a
    alias initialize_mgc_m7a initialize
    alias zoom_x_mgc_m7a= zoom_x=
    alias zoom_y_mgc_m7a= zoom_y=
    alias zoom_x_mgc_m7a zoom_x
    alias zoom_y_mgc_m7a zoom_y
    @already_aliased_mgc_m7a = true
  end
  #--------------------------------------------------------------------------
  # * Initialisation
  #--------------------------------------------------------------------------
  def initialize(*args)
    initialize_mgc_m7a(*args)
    @phase_mode7 = false
    self.zoom_x = 1.0
    self.zoom_y = 1.0
  end
  #--------------------------------------------------------------------------
  # * Setter pour l'attribut zoom_x
  #--------------------------------------------------------------------------
  def zoom_x=(new_zoom_x)
    unless @phase_mode7
      @base_zoom_x = new_zoom_x
    end
    self.zoom_x_mgc_m7a = new_zoom_x
  end
  #--------------------------------------------------------------------------
  # * Setter pour l'attribut zoom_y
  #--------------------------------------------------------------------------
  def zoom_y=(new_zoom_y)
    unless @phase_mode7
      @base_zoom_y = new_zoom_y
    end
    self.zoom_y_mgc_m7a = new_zoom_y
  end
  #--------------------------------------------------------------------------
  # * Getter pour l'attribut zoom_x
  #--------------------------------------------------------------------------
  def zoom_x
    return @base_zoom_x
  end
  #--------------------------------------------------------------------------
  # * Getter pour l'attribut zoom_y
  #--------------------------------------------------------------------------
  def zoom_y
    return @base_zoom_y
  end
  #--------------------------------------------------------------------------
  # * Valeur réelle du zoom_x en prenant en compte le zoom de la carte
  #--------------------------------------------------------------------------
  def zoom_x_real
    return zoom_x_mgc_m7a
  end
  #--------------------------------------------------------------------------
  # * Valeur réelle du zoom_y en prenant en compte le zoom de la carte
  #--------------------------------------------------------------------------
  def zoom_y_real
    return zoom_y_mgc_m7a
  end
end

#==============================================================================
# ** Sprite_Base
#==============================================================================
class Sprite_Base
  #--------------------------------------------------------------------------
  # * Aliased methods
  #--------------------------------------------------------------------------
  unless @already_aliased_mgc_m7a
    alias animation_set_sprites_mgc_m7a_aprite_base animation_set_sprites
    @already_aliased_mgc_m7a = true
  end
  #--------------------------------------------------------------------------
  # * Set Animation Sprite
  #     frame : Frame data (RPG::Animation::Frame)
  #--------------------------------------------------------------------------
  def animation_set_sprites(frame)
    if MGC.mode7_active
      cell_data = frame.cell_data
      @ani_sprites.each_with_index do |sprite, i|
        next unless sprite
        pattern = cell_data[i, 0]
        if !pattern || pattern < 0
          sprite.visible = false
          next
        end
        sprite.bitmap = pattern < 100 ? @ani_bitmap1 : @ani_bitmap2
        sprite.visible = true
        sprite.src_rect.set(pattern % 5 * 192,
          pattern % 100 / 5 * 192, 192, 192)
        if @ani_mirror
          sprite.x = @ani_ox - cell_data[i, 1] * zoom_y_real
          sprite.y = @ani_oy + cell_data[i, 2] * zoom_y_real
          sprite.angle = (360 - cell_data[i, 4])
          sprite.mirror = (cell_data[i, 5] == 0)
        else
          sprite.x = @ani_ox + cell_data[i, 1] * zoom_y_real
          sprite.y = @ani_oy + cell_data[i, 2] * zoom_y_real
          sprite.angle = cell_data[i, 4]
          sprite.mirror = (cell_data[i, 5] == 1)
        end
        sprite.z = self.z + 300 + i
        sprite.ox = 96
        sprite.oy = 96
        sprite.zoom_x = cell_data[i, 3] * zoom_y_real / 100.0
        sprite.zoom_y = cell_data[i, 3] * zoom_y_real / 100.0
        sprite.opacity = cell_data[i, 6] * self.opacity / 255.0
        sprite.blend_type = cell_data[i, 7]
      end
    else
      animation_set_sprites_mgc_m7a_aprite_base(frame)
    end
  end
end

#==============================================================================
# ** Sprite_Character
#==============================================================================
class Sprite_Character < Sprite_Base
  #--------------------------------------------------------------------------
  # * Aliased methods
  #--------------------------------------------------------------------------
  unless @already_aliased_mgc_m7a
    alias initialize_mgc_m7a_aprite_character initialize
    alias update_position_mgc_m7a_aprite_character update_position
    alias update_other_mgc_m7a_aprite_character update_other
    alias update_balloon_mgc_m7a_aprite_character update_balloon
    @already_aliased_mgc_m7a = true
  end
  #--------------------------------------------------------------------------
  # * Object Initialization
  #     character : Game_Character
  #--------------------------------------------------------------------------
  def initialize(viewport, character = nil)
    initialize_mgc_m7a_aprite_character(viewport, character)
    character.sprite = self
  end
  #--------------------------------------------------------------------------
  # * Update Position
  #--------------------------------------------------------------------------
  def update_position
    if MGC.mode7_active
      old_x = x
      old_y = y
      update_mode7
      @in_mode_7 = true # [1.5]
      move_animation(x - old_x, y - old_y)
    else
      if @in_mode_7 # [1.5]
        self.zoom_x = zoom_x
        self.zoom_y = zoom_y
        @in_mode_7 = false
      end
      update_position_mgc_m7a_aprite_character
    end
  end
  #--------------------------------------------------------------------------
  # * Update Other
  #--------------------------------------------------------------------------
  def update_other
    update_other_mgc_m7a_aprite_character
    if MGC.mode7_active && visible
      if !@force_mode7_invisible &&
        y >= MGC.mode7_data[8] &&
        (y - height * zoom_y_real) < Graphics.height
      then
        self.visible = true
        if y < Graphics.height
          dat = MGC.mode7_data[9]
          self.opacity += dat[5, y]
          self.tone.set(dat[2, y], dat[3, y], dat[4, y])
        end
      else
        self.visible = false
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Update Position In Mode7
  #--------------------------------------------------------------------------
  def update_mode7
    if @character.tile_id == 0 && character.character_name == "" # [1.8]
      @force_mode7_invisible = true
      return
    end
    y_screen = character.screen_y +
    (character.is_a?(Game_Vehicle) ? character.altitude : 0)
    y_init = MGC.mode7_data[2] * (y_screen - MGC.mode7_data[0])
    if y_init < - (MGC::MODE7_VIEW_LIMIT << 5) - MGC.mode7_data[0] ||
      y_init > Graphics.height
    then
      @force_mode7_invisible = true
      return
    else
      @force_mode7_invisible = false
    end
    x_init = MGC.mode7_data[2] * (character.screen_x - (Graphics.width >> 1))
    self.y = (MGC.mode7_data[0] + (MGC.mode7_data[5] * y_init *
    MGC.mode7_data[3]) / (MGC.mode7_data[5] - y_init * MGC.mode7_data[4])).to_i
    zx = MGC.mode7_data[6] * y + MGC.mode7_data[7]
    self.x = ((Graphics.width >> 1) + zx * x_init).to_i
    @phase_mode7 = true
    self.zoom_x = MGC.mode7_data[2] * zx
    self.zoom_y = zoom_x_real
    @phase_mode7 = false
    self.z = @character.screen_z + (y << 8) # [1.7]
    if character.is_a?(Game_Vehicle)
      self.y -= character.altitude * zoom_y_real
    end
  end
  #--------------------------------------------------------------------------
  # * Update Balloon Icon
  #--------------------------------------------------------------------------
  def update_balloon
    update_balloon_mgc_m7a_aprite_character
    if MGC.mode7_active && @balloon_duration > 0
      @balloon_sprite.y = y - height * zoom_y_real
      @balloon_sprite.zoom_x = zoom_x_real
      @balloon_sprite.zoom_y = zoom_y_real
    end
  end
end

#==============================================================================
# ** Spriteset_Map
#==============================================================================
class Spriteset_Map
  #--------------------------------------------------------------------------
  # * Aliased methods
  #--------------------------------------------------------------------------
  unless @already_aliased_mgc_m7a
    alias initialize_mgc_m7a initialize
    alias create_tilemap_mgc_m7a create_tilemap
    alias update_mgc_m7a update
    alias update_shadow_mgc_m7a update_shadow
    alias update_parallax_mgc_m7a update_parallax
    @already_aliased_mgc_m7a = true
  end
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    MGC.spriteset = self
    initialize_mgc_m7a
  end
  #--------------------------------------------------------------------------
  # * Lance le mode 7
  #--------------------------------------------------------------------------
  def start_mode7
    unless @tilemap_mode7 && @tilemap_mode7.map_id == $game_map.map_id # [1.9]
      if @tilemap_mode7
        @tilemap_mode7.dispose unless @tilemap_mode7.disposed?
        MGC.initialize_mode7(true)
      else
        MGC.initialize_mode7
        @tilemap_classic = @tilemap
      end
      @tilemap_mode7 = MGC::Mode7_Map.new(@viewport1)
      @tilemap_mode7.map_data = $game_map.data
      if $game_map.is_parallaxed? && $game_map.parallax_name &&
        $game_map.parallax_name != '' # [1.9]
      then
        @tilemap_mode7.parallax = Cache.parallax($game_map.parallax_name)
        $game_map.set_additional_panorama
      end
      @tilemap = @tilemap_mode7
      load_tileset
    end
    @tilemap_mode7.create_vertical_tiles # [1.7]
    @tilemap_mode7.visible = true
    @tilemap_classic.visible = false
    @tilemap = @tilemap_mode7
    MGC.mode7_active = true
  end
  #--------------------------------------------------------------------------
  # * Met fin au mode 7
  #--------------------------------------------------------------------------
  def end_mode7
    if @tilemap_mode7
      @tilemap_mode7.visible = false
      @tilemap_classic.visible = true
      @tilemap = @tilemap_classic
      @tilemap_mode7.clear_vertical_tiles # [1.7]
      @parallax.visible = true # [1.9]
    end
    MGC.mode7_active = false
  end
  #--------------------------------------------------------------------------
  # * Create Tilemap
  #--------------------------------------------------------------------------
  def create_tilemap
    create_tilemap_mgc_m7a
    unless $game_system.mode7_active
      MGC.mode7_active = false
    end
    if $game_map.is_mode7? || $game_system.mode7_active
      start_mode7
    end
  end
  #--------------------------------------------------------------------------
  # * Update
  #--------------------------------------------------------------------------
  def update
    MGC.update_mode7
    if $game_map.start_mode7
      start_mode7
      $game_map.start_mode7 = false
    elsif $game_map.end_mode7
      end_mode7
      $game_map.end_mode7 = false
    end
    update_mgc_m7a
  end
  #--------------------------------------------------------------------------
  # * Update Parallax [1.9]
  #--------------------------------------------------------------------------
  def update_parallax
    update_parallax_mgc_m7a
    if MGC.mode7_active && $game_map.is_parallaxed?
      if $game_map.has_additionnal_panorama?
        $game_map.set_additional_panorama
      else
        @parallax.visible = false
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Update Airship Shadow Sprite
  #--------------------------------------------------------------------------
  def update_shadow
    if MGC.mode7_active
      airship_sprite = $game_map.airship.sprite
      @shadow_sprite.x = airship_sprite.x
      @shadow_sprite.y = airship_sprite.y + $game_map.airship.altitude *
      airship_sprite.zoom_y_real
      @shadow_sprite.opacity = $game_map.airship.altitude * 8 *
      airship_sprite.opacity
      @shadow_sprite.zoom_x = airship_sprite.zoom_x_real
      @shadow_sprite.zoom_y = airship_sprite.zoom_y_real
      @shadow_sprite.update
    else
      update_shadow_mgc_m7a
    end
  end
end

#==============================================================================
# ** Scene_Map
#==============================================================================
class Scene_Map < Scene_Base
  #--------------------------------------------------------------------------
  # * Aliased methods
  #--------------------------------------------------------------------------
  unless @already_aliased_mgc_m7a
    alias update_call_menu_mgc_m7a update_call_menu
    @already_aliased_mgc_m7a = true
  end
  #--------------------------------------------------------------------------
  # * Determine if Menu is Called due to Cancel Button
  #--------------------------------------------------------------------------
  def update_call_menu
    unless MGC.effect?
      update_call_menu_mgc_m7a
    end
  end
end

#============================================================================
# ** RPG::MapInfo
#============================================================================
class RPG::MapInfo
  # defines the map name as the name without anything within brackets,
  # including brackets
  def name
    return @name.gsub(/\[.*\]/) {''}
  end
  #--------------------------------------------------------------------------
  # the original name with the codes
  def full_name
    return @name
  end
end

module MGC
  #--------------------------------------------------------------------------
  # * Constantes [1.7]
  #--------------------------------------------------------------------------
  RENDER_TILE = Win32API.new("MGC_Mode7_Ace_1_9", "renderTile", "l", "l")
  #==============================================================================
  # ** MGC::Vertical_Tile [1.7]
  #==============================================================================
  class Vertical_Tile
    #--------------------------------------------------------------------------
    # * Attributs
    #--------------------------------------------------------------------------
    attr_accessor :x, :y, :screen_x, :screen_y, :zoom
    attr_accessor :tile_width, :tile_height, :width, :height
    #--------------------------------------------------------------------------
    # * Initialisation
    # param parent : MGC::Mode7_Map
    # param viewport : Viewport
    #--------------------------------------------------------------------------
    def initialize(parent, viewport)
      @parent = parent
      @viewport = viewport
      @visible = false
      @sprite = nil
    end
    #--------------------------------------------------------------------------
    # * Refresh tile data
    # param tiles : Array<Array[Integer, Integer, Array[3]<Boolean>]>
    # param x_min : Integer
    # param x_max : Integer
    # param y_min : Integer
    # param y_max : Integer
    #--------------------------------------------------------------------------
    def refresh_tile_data(tiles, x_min, x_max, y_min, y_max)
      self.tile_width = 1 + x_max - x_min
      self.width = tile_width << 5
      self.tile_height = 1 + y_max - y_min
      self.height = tile_height << 5
      @tiles_data = Array.new(tile_width * tile_height)
      tiles.each {|tile|
        x_tile = tile[0] - x_min
        y_tile = tile[1] - y_min
        @tiles_data[x_tile + y_tile * tile_width] = tile
      }
    end
    #--------------------------------------------------------------------------
    # * Dispose
    #--------------------------------------------------------------------------
    def dispose
      if @sprite
        @sprite.bitmap.dispose
        @sprite.dispose
        @sprite = nil
      end
    end
    #--------------------------------------------------------------------------
    # * Update
    #--------------------------------------------------------------------------
    def update
      update_mode7
      update_visibility
    end
    #--------------------------------------------------------------------------
    # * Update Position In Mode7
    #--------------------------------------------------------------------------
    def update_mode7
      x_scr = 32 * $game_map.adjust_x(x.to_f / 32)
      y_scr = 32 * $game_map.adjust_y(y.to_f / 32)
      y_init = MGC.mode7_data[2] * (y_scr - MGC.mode7_data[0])
      if y_init < - (MGC::MODE7_VIEW_LIMIT << 5) - MGC.mode7_data[0] ||
        y_init > Graphics.height
      then
        @force_invisible = true
        return
      else
        @force_invisible = false
      end
      x_init = MGC.mode7_data[2] * (x_scr - (Graphics.width >> 1))
      self.screen_y = (MGC.mode7_data[0] + (MGC.mode7_data[5] * y_init *
      MGC.mode7_data[3]) / (MGC.mode7_data[5] - y_init * MGC.mode7_data[4])).to_i
      zx = MGC.mode7_data[6] * screen_y + MGC.mode7_data[7]
      self.screen_x = ((Graphics.width >> 1) + zx * x_init).to_i
      self.zoom = MGC.mode7_data[2] * zx
    end
    #--------------------------------------------------------------------------
    # * Update Visibility
    #--------------------------------------------------------------------------
    def update_visibility
      if @visible
        if !@force_invisible &&
          screen_y >= MGC.mode7_data[8] &&
          (screen_y - height * zoom) < Graphics.height &&
          (screen_x + width * zoom / 2)  >= 0 &&
          (screen_x - width * zoom / 2) < Graphics.width
        then
          if screen_y < Graphics.height
            dat = MGC.mode7_data[9]
            @sprite.opacity = 255 + dat[5, screen_y]
            @sprite.tone.set(dat[2, screen_y], dat[3, screen_y], dat[4, screen_y])
          end
          @sprite.x = screen_x
          @sprite.y = screen_y
          @sprite.z = screen_y << 8
          @sprite.zoom_x = zoom
          @sprite.zoom_y = zoom
        else
          @visible = false
          @sprite.bitmap.dispose
          @sprite.dispose
          @sprite = nil
        end
      else
        if !@force_invisible &&
          screen_y >= MGC.mode7_data[8] &&
          (screen_y - height * zoom) < Graphics.height &&
          (screen_x + width * zoom / 2)  >= 0 &&
          (screen_x - width * zoom / 2) < Graphics.width
        then
          @visible = true
          @sprite = Sprite.new(@viewport)
          @sprite.ox = tile_width * 32 / 2
          @sprite.oy = tile_height * 32
          @sprite.x = screen_x
          @sprite.y = screen_y
          @sprite.z = screen_y << 8
          @sprite.zoom_x = zoom
          @sprite.zoom_y = zoom
          @sprite.bitmap = Bitmap.new(32 * tile_width, 32 * tile_height)
          (0...tile_height).each {|iy|
            (0...tile_width).each {|ix|
              tile_data = @tiles_data[ix + iy * tile_width]
              if tile_data
                (0...3).each {|il|
                  if tile_data[2][il]
                    @parent.param_tiles[6][il] =
                    $game_map.tile_id(tile_data[0], tile_data[1], il)
                  else
                    @parent.param_tiles[6][il] = 0
                  end
                }
                @parent.param_tiles[0].clear
                MGC::RENDER_TILE.call(@parent.param_tiles.__id__)
                @sprite.bitmap.blt(ix << 5, iy << 5, @parent.param_tiles[0],
                @parent.param_tiles[0].rect)
              end
            }
          }
          if screen_y < Graphics.height
            dat = MGC.mode7_data[9]
            @sprite.opacity = 255 + dat[5, screen_y]
            @sprite.tone.set(dat[2, screen_y], dat[3, screen_y], dat[4, screen_y])
          end
        end
      end
    end
  end
end[/pre]  
[神性领域扩张:扩张神性领域]
说了等于没说.
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部