[Script] [ACE] [VXA] Topic hỏi-đáp về script VXA

Focker_cFocker_c Posts: 1,577Registered
Engine này hiện nay đang là sự lựa chọn số 1 tại forum và nhu cầu script của mọi người mình thấy cũng ko hề ít ỏi.
Nhằm nâng cao mức độ script của mọi người, mình lập ra topic này để mọi người tiện hỏi và đáp về script.
Những người khác cũng có thể đọc qua để thêm hiểu biết hoặc ko còn bỡ ngỡ khi gặp câu hỏi tương tự.

:D

Nào ! Ask !




Mở màn luôn cái :

[php]if true # << Make true to use this script, false to disable.
#===============================================================================
#
# ☆ $D13x - Key Menu
# -- Author : Dekita
# -- Version : 1.2
# -- Level : Easy / Normal
# -- Requires : $D13x Core v 1.4+
# -- Engine : RPG Maker VX Ace.
#
#===============================================================================
# ☆ Import
#
$D13x={}if$D13x==nil
$D13x[:Key_Menu]=true
#===============================================================================
# ☆ Updates
#
# D /M /Y
# o4/o4/2o13 - Added Switch Restrictions, (all keys)
# 29/o3/2o13 - Compatibility, (Key Menu HUD)
# - Bugfix, (scene re-trigger if long key press)
# 28/o3/2o13 - Finished,
# 27/o3/2o13 - Started
#
#===============================================================================
# ☆ Introduction
#
# This script allows the use of other keys to trigger various scenes,
# Such as 'M' Key triggering the menu, 'S' Key Triggering the Status Screen,
# 'I' key Triggering Items. ect..
# And of course allows easy removal of the default Menu calling key.
#
#===============================================================================
# ★☆★☆★☆★☆★☆★☆★☆★ TERMS AND CONDITIONS: ☆★☆★☆★☆★☆★☆★☆★☆★☆
#===============================================================================
# 1. You MUST give credit to "Dekita" !!
# 2. You are NOT allowed to repost this script.(or modified versions)
# 3. You are NOT allowed to convert this script.
# 4. You are NOT allowed to use this script for Commercial games.
# 5. ENJOY!
#
# "FINE PRINT"
# By using this script you hereby agree to the above terms and conditions,
# if any violation of the above terms occurs "legal action" may be taken.
# Not understanding the above terms and conditions does NOT mean that
# they do not apply to you.
# If you wish to discuss the terms and conditions in further detail you can
# contact me at http://dekitarpg.wordpress.com/
#
#===============================================================================
# ☆ Instructions
#
# Place Below " ▼ Materials " and Above " ▼ Main " in your script editor.
#
#===============================================================================
# ☆ HELP
#
# For a list of possible key symbols check the help section of the
# $D13x core script.
#
#===============================================================================
module Key_Menu
#===============================================================================

#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# ☆ Key Settings
#
# Make this true to disable the default Vx Ace menu key.
Disable_Menu_Call = true

# Menu Item = [ :KEY , Switch ]
Menu_Key = [ :NONE , 0 ] # Triggers Menu :NONE = no trigger
Items_Key = [ :I , 0 ] # Triggers Items
Skills_Key = [ :M , 0 ] # Triggers Skills
Equips_Key = [ :G , 0 ] # Triggers Equip
Status_Key = [ :P , 0 ] # Triggers Status
Save_Key = [ :N , 0 ] # Triggers Save
Pause_Key = [ :O , 0 ] # Triggers Game End

end #####################
# CUSTOMISATION END #
#####################
#☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★#
# #
# http://dekitarpg.wordpress.com/ #
# #
#★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆#
#===============================================================================#
# ARE YOU MODIFYING BEYOND THIS POINT? \.\. #
# YES?\.\. #
# OMG, REALLY? \| #
# WELL SLAP MY FACE AND CALL ME A DRAGONITE.\..\.. #
# I REALLY DIDN'T THINK YOU HAD IT IN YOU.\..\.. #
#===============================================================================#
class Scene_Map < Scene_Base
#===============================================================================
#
# Alias List
#
alias :update_my_KEYz :update_scene
alias :update_menu_key :update_call_menu
#
# Update Scene Transition
#
def update_scene
update_my_KEYz
update_de_keys
end
#
# Update Keys
#
def update_de_keys
return if scene_changing?
update_call_pause unless scene_changing?
update_new_call_menu unless scene_changing?
update__call_items unless scene_changing?
update__call_skills unless scene_changing?
update__call_equips unless scene_changing?
update__call_status unless scene_changing?
update__call_save unless scene_changing?
end
#
# Determine if Pause is being triggered
#
def update_call_pause
return unless !$game_map.interpreter.running?
return unless !$game_player.moving?
if (Key_Menu::Pause_Key[1] != 0)
return unless $game_switches[Key_Menu::Pause_Key[1]]
end
return unless Keys.trigger?(Keys::Key[Key_Menu::Pause_Key[0]])
SceneManager.call(Scene_End)
end
#
# Determine if Menu is Called due to Cancel Button
#
def update_call_menu
return if Key_Menu::Disable_Menu_Call
update_menu_key
end
#
# Determine if Menu is Called due to New Key
#
def update_new_call_menu
return unless Key_Menu::Disable_Menu_Call
return unless !$game_map.interpreter.running?
return unless !$game_player.moving?
if (Key_Menu::Menu_Key[1] != 0)
return unless $game_switches[Key_Menu::Menu_Key[1]]
end
return unless Keys.trigger?(Keys::Key[Key_Menu::Menu_Key[0]])
call_menu
end
#
# Determine if Menu is Called due to New Key
#
def update__call_items
return unless !$game_map.interpreter.running?
return unless !$game_player.moving?
if (Key_Menu::Items_Key[1] != 0)
return unless $game_switches[Key_Menu::Items_Key[1]]
end
return unless Keys.trigger?(Keys::Key[Key_Menu::Items_Key[0]])
SceneManager.call(Scene_Item)
end
#
# Determine if Menu is Called due to New Key
#
def update__call_skills
return unless !$game_map.interpreter.running?
return unless !$game_player.moving?
if (Key_Menu::Skills_Key[1] != 0)
return unless $game_switches[Key_Menu::Skills_Key[1]]
end
return unless Keys.trigger?(Keys::Key[Key_Menu::Skills_Key[0]])
SceneManager.call(Scene_Skill)
end
#
# Determine if Menu is Called due to New Key
#
def update__call_equips
return unless !$game_map.interpreter.running?
return unless !$game_player.moving?
if (Key_Menu::Equips_Key[1] != 0)
return unless $game_switches[Key_Menu::Equips_Key[1]]
end
return unless Keys.trigger?(Keys::Key[Key_Menu::Equips_Key[0]])
SceneManager.call(Scene_Equip)
end
#
# Determine if Menu is Called due to New Key
#
def update__call_status
return unless !$game_map.interpreter.running?
return unless !$game_player.moving?
if (Key_Menu::Status_Key[1] != 0)
return unless $game_switches[Key_Menu::Status_Key[1]]
end
return unless Keys.trigger?(Keys::Key[Key_Menu::Status_Key[0]])
SceneManager.call(Scene_Status)
end
#
# Determine if Menu is Called due to New Key
#
def update__call_save
return unless !$game_map.interpreter.running?
return unless !$game_player.moving?
if (Key_Menu::Save_Key[1] != 0)
return unless $game_switches[Key_Menu::Save_Key[1]]
end
return unless Keys.trigger?(Keys::Key[Key_Menu::Save_Key[0]])
SceneManager.call(Scene_Save)
end

end

#==============================================================================#
# http://dekitarpg.wordpress.com/ #
#==============================================================================#
end[/php]

Đang tìm 1 cái script mở các scene_item rồi skill rồi status bẳng cách ấn các phím trên keyboard.
Cái bên trên chạy bị lỗi các kiểu.
Ai fix đc hoặc có cái khác ko ? :(
«1345678

Comments

  • DeathDeath Posts: 732Registered, Moderators
    ^ Copy thiếu script rồi.
    Thêm cái Core này vào nữa nhé:
    http://pastebin.com/QeXkeEJw
  • Focker_cFocker_c Posts: 1,577Registered
    Hiện nay mình đang xài Script light-effect của Khas.
    Tức là tạo màn đêm và chỉ sáng ở nơi có đèn điện.

    Script đây:

    [php]#
    # * [ACE] Khas Awesome Light Effects
    #
    # * By Khas Arcthunder - arcthunder.site40.net
    # * Version: 1.0 EN
    # * Released on: 17/01/2012
    #
    #
    # * Terms of Use
    #
    # When using any Khas script, you agree with the following terms:
    # 1. You must give credit to Khas;
    # 2. All Khas scripts are licensed under a Creative Commons license;
    # 3. All Khas scripts are for non-commercial projects. If you need some script
    # for your commercial project (I accept requests for this type of project),
    # send an email to nilokruch@live.com with your request;
    # 4. All Khas scripts are for personal use, you can use or edit for your own
    # project, but you are not allowed to post any modified version;
    # 5. You can’t give credit to yourself for posting any Khas script;
    # 6. If you want to share a Khas script, don’t post the direct download link,
    # please redirect the user to arcthunder.site40.net
    #
    #
    # * Features
    #
    # - Realistic Light
    # - Light does not pass over walls, blocks and roofs
    # - Static Light Sources
    # - Dynamic Light Sources (like a player's lantern)
    # - Multiple effects
    # - Easy to use (comments)
    #
    #
    # * WARNING - Performance
    #
    # This script may be too heavy to old processors! The Awesome Light Effects was
    # tested on a Core 2 Duo E4500 and on a Core i5, without any lag. However,
    # there's other factors that may influence the script performance:
    #
    # 1. Map size
    # This script searches surfaces on the map, in order to cut the light pictures.
    # In a huge map, the number of surfaces may increase a lot, affecting the
    # DYNAMIC LIGHT SOURCE only. Map size does not influence the static sources.
    #
    # 2. Number of effects
    # This script draws the effects on the screen, but before drawing, it checks
    # if the effect is out of screen (in this case, the script will skip the
    # light drawing). Too much effects may cause lag, but this is just a prevision.
    #
    # 3. Effect's picture size
    # The picture size of the DYNAMIC LIGHT SOURCE influences directly on your
    # game's performace. The bigger is the picture, the slower it will be to
    # draw it dynamically. The recommended maximum size is 200x200 pixels
    #
    #
    # * WARNING - Light pictures
    #
    # In order to run this script correctly, the light pictures MUST obey the
    # following conditions:
    # 1. The picture's size MUST be multiple of 2. Example: 150x150
    # 2. The picture's width MUST be equal to it's height. Example: 156x156
    # 3. The picture's colors MUST be inverted! This is necessary because
    # the script inverts the colors to draw the effect. The black color
    # will be transparent!
    #
    #
    # * Instructions - 1. Setup your effects!
    #
    # In order to setup your static effects, go to the setup part and define your
    # effects inside the Effects hash. Do as the following mode:
    #
    # X => [picture,opacity,variation,cut], <= Remember to put a comma here!
    #
    # Where:
    # picture => Picture's name, inside the Graphics/Lights folder;
    # opacity => Effect's opacity;
    # variation => Effect's opacity variation;
    # cut => Put true to cut the effect or false to don't;
    # X => The effect's ID, it will be used on events.
    #
    # Check the default effects to understand how they work.
    #
    #
    # * Instructions - 2. Use your effects!
    #
    # In order to use a effect, put the following comment on a event:
    #
    # [light x]
    #
    # Where x must be the Effect's ID.
    #
    #
    # * Instructions - 3. Use an awesome lantern!
    #
    # The dynamic light source (lantern) is initialized invisible by default.
    # You may call the following commands:
    #
    # l = $game_map.lantern
    # Gets the lantern into a variable

    # l.set_graphic(i)
    # Sets the lantern's graphic to i, where i must be the picture's file name on
    # Graphics/Lights folder.
    #
    # l.set_multiple_graphics(h)
    # Sets the lantern's graphics to h, where h must be a hash with the following
    # structure:
    #
    # h = {2=>"ld",4=>"ll",6=>"lr",8=>"lu"}
    #
    # Where:
    # "ld" is the name of the picture when the lantern's owner is looking down;
    # "ll" is the name of the picture when the lantern's owner is looking left;
    # "lr" is the name of the picture when the lantern's owner is looking right;
    # "lu" is the name of the picture when the lantern's owner is looking up.
    #
    # l.change_owner(char)
    # Sets the lantern's owner to char. Char must be ONE of the following commands:
    # $game_player <= The player itself;
    # self_event <= The event where the command was called;
    # $game_map.events[x] <= The event ID x.
    #
    # l.set_opacity(o,p)
    # Sets the lantern's opacity, where:
    # o is the opacity itself;
    # p is the opacity variation.
    #
    # l.show
    # After setting the lantern with the commands above, you may set it to visible
    # using this command.
    #
    # l.hide
    # Use this command to set the lantern as invisible.
    #
    #
    # * Instructions - 4. Use the effect's surface!
    #
    # The Awesome Light Effects draws the effects on a surface. In order to make
    # the effects visible, the effect's surface MUST be visible. The Effect's
    # Surface is initialized with it's opacity set to zero. You can call the
    # following commands:
    #
    # s = $game_map.effect_surface
    # Gets the Effect's Surface into a variable
    #
    # s.set_color(r,g,b)
    # Changes the Effect's Surface color instantly, where:
    # r => red level;
    # g => green level;
    # b => blue level;
    #
    # s.set_alpha(a)
    # Changes the Effect's Surface opacity instantly to a.
    #
    # s.change_color(time,r,g,b)
    # Changes the Effect's Surface color ONLY in a certain time, where:
    # time => The change's time (frames);
    # r => red level;
    # g => green level;
    # b => blue level;
    #
    # s.change_color(time,r,g,b,a)
    # Changes the Effect's Surface color and it's opacity in a certain time, where:
    # time => The change's time (frames);
    # r => red level;
    # g => green level;
    # b => blue level;
    # a => opacity
    #
    # s.change_alpha(time,a)
    # Changes the Effect's Surface opacity in a certain time, where:
    # time => The change's time (frames);
    # a => opacity
    #
    #
    # * Instructions - 5. Use the effect's surface with Tone command!
    #
    # You can access the Effect's Surface with the "Screen Tone" command. In order
    # to turn this feature on, set the "Surface_UE" constant to true.
    #
    # If you decided to use this feature, please note some details:
    # 1. The colors values must be between 0 and 255;
    # 2. The time is in frames;
    # 3. The "gray" value will be sent as the opacity value
    #
    #
    # * Instructions - 6. Setup your Tileset Tags!
    #
    # In order to cut the effect's picture correctly, there's 3 types of behavior
    # for a tile: wall, block and roof. Walls will make shadows as real walls,
    # blocks as blocks and roofs as roofs. So, the tileset tags MUST be configured.
    # Check the demo to understand how this system works. If the tilesets aren't
    # configured correctly, the script won't cut the effects correctly.
    #
    #
    # * Setup Part
    #
    module Light_Core
    Effects = { # <= DON'T change this!
    #
    # PUT YOUR EFFECTS HERE!
    #
    0 => ["light",255,0,true],
    1 => ["torch",200,20,true],
    2 => ["torch_m",180,30,true],
    3 => ["light_s",255,0,true],

    #
    # End of effecs configuration
    #
    } # <= DON'T change this!

    # Z coordinate of the Effect's Surface
    Surface_Z = 180

    # Enable Effect's Surface control by "Screen Tone" command?
    Surface_UE = true

    # Roof behavior tag
    Roof_Tag = 5
    # Wall behavior tag
    Wall_Tag = 6
    # Block behavior tag
    Block_Tag = 7

    # Don't change this!
    ACC = Math.tan(Math::PI/26)
    end
    #
    # Script
    #
    module Cache
    def self.light(filename)
    load_bitmap("Graphics/Lights/", filename)
    end
    end
    module Light_Bitcore
    include Light_Core
    def self.initialize
    @buffer = {}
    Effects.values.each { |effect| Light_Bitcore.push(effect[0])}
    end
    def self::[](key)
    @buffer[key]
    end
    def self.push(key)
    @buffer.keys.include?(key)
    @buffer[key] = Cache.light(key)
    end
    end
    Light_Bitcore.initialize
    class Light_SSource
    attr_reader :real_x
    attr_reader :real_y
    attr_reader :range
    attr_accessor :bitmap
    attr_reader :w
    attr_reader :h
    attr_reader :hs
    def initialize(char,bitmap,opacity,plus,hs)
    sync(char)
    @key = bitmap
    @bitmap = Light_Bitcore[@key].clone
    @range = @bitmap.width/2
    @w = @bitmap.width
    @h = @bitmap.height
    @mr = @range - 16
    @opacity = opacity
    @plus = plus
    @hs = hs
    render if @hs
    end
    def render
    tx = x
    ty = y
    tsx = x + @range
    tsy = y + @range
    dr = @range*2
    for s in $game_map.surfaces
    next if !s.visible?(tsx,tsy) || !s.within?(tx,tx+dr,ty,ty+dr)
    s.render_shadow(tx,ty,tsx,tsy,@range,@bitmap)
    end
    end
    def restore
    return unless @bitmap.nil?
    @bitmap = Light_Bitcore[@key].clone
    render if @hs
    end
    def opacity
    @plus == 0 ? @opacity : (@opacity + rand(@plus))
    end
    def sx
    return $game_map.adjust_x(@real_x)*32-@mr
    end
    def sy
    return $game_map.adjust_y(@real_y)*32-@mr
    end
    def sync(char)
    @real_x = char.real_x
    @real_y = char.real_y
    end
    def x
    return (@real_x*32 - @mr).to_f
    end
    def y
    return (@real_y*32 - @mr).to_f
    end
    def dispose
    return if @bitmap.nil?
    @bitmap.dispose
    @bitmap = nil
    end
    end
    class Light_DSource < Light_SSource
    attr_reader :bitmap
    attr_reader :visible
    def initialize
    @key = nil
    @bitmap = nil
    @opacity = 255
    @plus = 0
    @char = $game_player
    @visible = false
    end
    def set_opacity(o,p)
    @opacity = o
    @plus = p
    end
    def set_graphic(sb)
    dispose
    @key = {2=>sb,4=>sb,6=>sb,8=>sb}
    Light_Bitcore.push(sb)
    @bitmap = {2=>Light_Bitcore[@key[2]].clone,4=>Light_Bitcore[@key[4]].clone,6=>Light_Bitcore[@key[6]].clone,8=>Light_Bitcore[@key[8]].clone}
    @range = @bitmap[2].width/2
    @w = @bitmap[2].width
    @h = @bitmap[2].height
    @mr = @range - 16
    end
    def set_multiple_graphics(ba)
    dispose
    @key = ba
    @key.values.each {|key| Light_Bitcore.push(key)}
    @bitmap = {2=>Light_Bitcore[@key[2]].clone,4=>Light_Bitcore[@key[4]].clone,6=>Light_Bitcore[@key[6]].clone,8=>Light_Bitcore[@key[8]].clone}
    @range = @bitmap[2].width/2
    @w = @bitmap[2].width
    @h = @bitmap[2].height
    @mr = @range - 16
    end
    def get_graphic
    return @bitmap[@char.direction].clone
    end
    def show
    return if @bitmap.nil?
    @visible = true
    end
    def hide
    @visible = false
    end
    def restore
    return if @key.nil?
    @key.values.each {|key| Light_Bitcore.push(key)}
    @bitmap = {2=>Light_Bitcore[@key[2]].clone,4=>Light_Bitcore[@key[4]].clone,6=>Light_Bitcore[@key[6]].clone,8=>Light_Bitcore[@key[8]].clone}
    end
    def dispose
    return if @bitmap.nil?
    @bitmap.values.each { |b| b.dispose }
    @bitmap = nil
    end
    def change_owner(char)
    @char = char
    end
    def render
    end
    def sx
    return $game_map.adjust_x(@char.real_x)*32-@mr
    end
    def sy
    return $game_map.adjust_y(@char.real_y)*32-@mr
    end
    def x
    return (@char.real_x*32 - @mr).to_f
    end
    def y
    return (@char.real_y*32 - @mr).to_f
    end
    end
    class Light_Surface
    def initialize
    @ta = @a = 0
    @tr = @r = 255
    @tg = @g = 255
    @tb = @b = 255
    @va = @vr = @vg = @vb = 0.0
    @timer = 0
    end
    def refresh
    return if @timer == 0
    @a += @va
    @r += @vr
    @g += @vg
    @b += @vb
    $game_map.light_surface.opacity = @a
    @timer -= 1
    end
    def change_color(time,r,g,b,a=nil)
    r = 0 if r < 0; r = 255 if r > 255
    g = 0 if g < 0; g = 255 if g > 255
    b = 0 if b < 0; b = 255 if b > 255
    unless a.nil?
    a = 0 if a < 0; a = 255 if a > 255
    end
    @timer = time
    @tr = 255-r
    @tg = 255-g
    @tb = 255-b
    @va = (a.nil? ? 0 : (a-@a).to_f/@timer)
    @vr = (@tr - @r).to_f/@timer
    @vg = (@tg - @g).to_f/@timer
    @vb = (@tb - @b).to_f/@timer
    end
    def change_alpha(time,a)
    a = 0 if a < 0; a = 255 if a > 255
    @timer = time
    @ta = a
    @vr = @vg = @vb = 0.0
    @va = (a-@a).to_f/@timer
    end
    def set_color(r,g,b)
    r = 0 if r < 0; r = 255 if r > 255
    g = 0 if g < 0; g = 255 if g > 255
    b = 0 if b < 0; b = 255 if b > 255
    @tr = @r = 255-r
    @tg = @g = 255-g
    @tb = @b = 255-b
    @va = @vr = @vg = @vb = 0.0
    @timer = 0
    end
    def set_alpha(a)
    a = 0 if a < 0; a = 255 if a > 255
    @ta = @a = a
    $game_map.light_surface.opacity = @a
    @va = @vr = @vg = @vb = 0.0
    @timer = 0
    end
    def alpha
    return @a
    end
    def color
    return Color.new(@r,@g,@b)
    end
    end
    class Game_Map
    include Light_Core
    attr_accessor :light_surface
    attr_accessor :light_sources
    attr_accessor :surfaces
    attr_accessor :effect_surface
    attr_accessor :lantern
    alias kbl_setup_events setup_events
    alias kbl_initialize initialize
    alias kbl_update update
    def initialize
    kbl_initialize
    @effect_surface = Light_Surface.new
    @lantern = Light_DSource.new
    end
    def update(arg)
    @effect_surface.refresh if arg
    kbl_update(arg)
    end
    def first_tag(x,y)
    tag = tileset.flags[tile_id(x,y,0)] >> 12
    return tag > 0 ? tag : 0
    end
    def setup_events
    @light_sources.nil? ? @light_sources = [] : @light_sources.clear
    setup_surfaces
    merge_surfaces
    kbl_setup_events
    end
    def setup_surfaces
    @surfaces = []
    for x in 0..(width-1)
    for y in 0..(height-1)
    tag = first_tag(x,y)
    if tag == Wall_Tag
    i = tile_id(x,y,0)
    if i & 0x02 == 0x02
    @surfaces << Block_SD.new(x*32,y*32,x*32+32,y*32)
    end
    if i & 0x04 == 0x04
    @surfaces << Block_WR.new(x*32+31,y*32,x*32+31,y*32+32)
    @surfaces << Block_IL.new(x*32+32,y*32,x*32+32,y*32+32)
    end
    if i & 0x01 == 0x01
    @surfaces << Block_IR.new(x*32-1,y*32,x*32-1,y*32+32)
    @surfaces << Block_WL.new(x*32,y*32,x*32,y*32+32)
    end
    elsif tag == Roof_Tag
    i = tile_id(x,y,0)
    @surfaces << Block_SU.new(x*32,y*32,x*32+32,y*32) if i & 0x02 == 0x02
    @surfaces << Block_SR.new(x*32+31,y*32,x*32+31,y*32+32) if i & 0x04 == 0x04
    @surfaces << Block_SL.new(x*32,y*32,x*32,y*32+32) if i & 0x01 == 0x01
    elsif tag == Block_Tag
    f = tileset.flags[tile_id(x,y,0)]
    @surfaces << Block_SL.new(x*32,y*32,x*32,y*32+32) if f & 0x02 == 0x02
    @surfaces << Block_SR.new(x*32+31,y*32,x*32+31,y*32+32) if f & 0x04 == 0x04
    @surfaces << Block_SU.new(x*32,y*32,x*32+32,y*32) if f & 0x08 == 0x08
    end
    end
    end
    end
    def merge_surfaces
    new_surfaces = []
    hs = []; vs = []
    ws = []; is = []
    for surface in @surfaces
    if surface.type & 0x05 == 0
    hs << surface
    else
    if surface.type & 0x010 == 0
    vs << surface
    else
    if surface.type & 0x08 == 0
    ws << surface
    else
    is << surface
    end
    end
    end
    end
    for surface in hs
    surface.ready ? next : surface.ready = true
    for s in hs
    next if s.ready || s.y1 != surface.y1 || surface.type != s.type
    if s.x2 == surface.x1
    surface.x1 = s.x1
    s.trash = true
    s.ready = true
    surface.ready = false
    elsif s.x1 == surface.x2
    surface.x2 = s.x2
    s.trash = true
    s.ready = true
    surface.ready = false
    end
    end
    end
    hs.each { |s| @surfaces.delete(s) if s.trash}
    for surface in vs
    surface.ready ? next : surface.ready
    for s in vs
    next if s.ready || s.x1 != surface.x1
    if s.y2 == surface.y1
    surface.y1 = s.y1
    s.trash = true
    s.ready = true
    surface.ready = false
    elsif s.y1 == surface.y2
    surface.y2 = s.y2
    s.trash = true
    s.ready = true
    surface.ready = false
    end
    end
    end
    vs.each { |s| @surfaces.delete(s) if s.trash}
    for surface in ws
    surface.ready ? next : surface.ready
    for s in ws
    next if s.ready || s.x1 != surface.x1
    if s.y2 == surface.y1
    surface.y1 = s.y1
    s.trash = true
    s.ready = true
    surface.ready = false
    elsif s.y1 == surface.y2
    surface.y2 = s.y2
    s.trash = true
    s.ready = true
    surface.ready = false
    end
    end
    end
    ws.each { |s| @surfaces.delete(s) if s.trash}
    for surface in is
    surface.ready ? next : surface.ready
    for s in is
    next if s.ready || s.x1 != surface.x1
    if s.y2 == surface.y1
    surface.y1 = s.y1
    s.trash = true
    s.ready = true
    surface.ready = false
    elsif s.y1 == surface.y2
    surface.y2 = s.y2
    s.trash = true
    s.ready = true
    surface.ready = false
    end
    end
    end
    is.each { |s| @surfaces.delete(s) if s.trash}
    end
    end
    class Game_Event < Game_Character
    alias kbl_initialize initialize
    alias kbl_setup_page setup_page
    def initialize(m,e)
    @light = nil
    kbl_initialize(m,e)
    end
    def setup_page(np)
    kbl_setup_page(np)
    setup_light(np.nil?)
    end
    def setup_light(dispose)
    unless @light.nil?
    $game_map.light_sources.delete(self)
    @light.dispose
    @light = nil
    end
    unless dispose && @list.nil?
    for command in @list
    if command.code == 108 && command.parameters[0].include?("[light")
    command.parameters[0].scan(/\[light ([0.0-9.9]+)\]/)
    effect = Light_Core::Effects[$1.to_i]
    @light = Light_SSource.new(self,effect[0],effect[1],effect[2],effect[3])
    $game_map.light_sources << self
    return
    end
    end
    end
    end
    def draw_light
    sx = @light.sx
    sy = @light.sy
    w = @light.w
    h = @light.h
    return if sx > 640 && sy > 416 && sx + w < 0 && sy + h < 0
    $game_map.light_surface.bitmap.blt(sx,sy,@light.bitmap,Rect.new(0,0,w,h),@light.opacity)
    end
    def dispose_light
    @light.dispose
    end
    def restore_light
    @light.restore
    end
    end
    if Light_Core::Surface_UE
    class Game_Interpreter
    def command_223
    $game_map.effect_surface.change_color(@params[1],@params[0].red,@params[0].green,@params[0].blue,@params[0].gray)
    wait(@params[1]) if @params[2]
    end
    end
    end
    class Game_Interpreter
    def self_event
    return $game_map.events[@event_id]
    end
    end
    class Block_Surface
    include Light_Core
    attr_accessor :x1
    attr_accessor :y1
    attr_accessor :x2
    attr_accessor :y2
    attr_accessor :ready
    attr_accessor :trash
    def initialize(x1,y1,x2,y2)
    @x1 = x1
    @y1 = y1
    @x2 = x2
    @y2 = y2
    @ready = false
    @trash = false
    end
    def within?(min_x,max_x,min_y,max_y)
    return @x2 > min_x && @x1 < max_x && @y2 > min_y && @y1 < max_y
    end
    end
    class Block_SL < Block_Surface
    attr_reader :type
    def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x01
    end
    def visible?(sx,sy)
    return sx < @x1
    end
    def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = sy - @m1*sx
    @m2 = (@y2-sy)/(@x2-sx)
    @n2 = sy - @m2*sx
    for x in @x1..(sx+range)
    init = shadow_iy(x)
    bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+3)
    end
    end
    def shadow_iy(x)
    return @m1*x+@n1
    end
    def shadow_fy(x)
    return @m2*x+@n2
    end
    end
    class Block_SR < Block_Surface
    attr_reader :type
    def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x04
    end
    def visible?(sx,sy)
    return sx > @x1
    end
    def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = sy - @m1*sx
    @m2 = (@y2-sy)/(@x2-sx)
    @n2 = sy - @m2*sx
    for x in (sx-range).to_i..@x1
    init = shadow_iy(x)
    bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+3)
    end
    end
    def shadow_iy(x)
    return @m1*x+@n1
    end
    def shadow_fy(x)
    return @m2*x+@n2
    end
    end
    class Block_IL < Block_Surface
    attr_reader :type
    def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x019
    end
    def visible?(sx,sy)
    return sx < @x1 && sy > @y1
    end
    def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = @y1 - @m1*@x1
    @m2 = (@y2-sy)/(@x2-sx)
    @m2 = 0 if @m2 > 0
    @n2 = @y2 - @m2*@x2
    for x in @x1..(sx+range)
    init = shadow_iy(x).floor
    bitmap.clear_rect(x-phx,init-3-phy,1,shadow_fy(x)-init+3)
    end
    end
    def shadow_iy(x)
    return @m1*x+@n1
    end
    def shadow_fy(x)
    return @m2*x+@n2
    end
    end
    class Block_IR < Block_Surface
    attr_reader :type
    def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x01c
    end
    def visible?(sx,sy)
    return sx > @x1 && sy > @y1
    end
    def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = @y1 - @m1*@x1
    @m2 = (@y2-sy)/(@x2-sx)
    @m2 = 0 if @m2 < 0
    @n2 = @y2 - @m2*@x2
    for x in (sx-range).to_i..@x1
    init = shadow_iy(x).floor
    bitmap.clear_rect(x-phx,init-3-phy,1,shadow_fy(x)-init+3)
    end
    end
    def shadow_iy(x)
    return @m1*x+@n1
    end
    def shadow_fy(x)
    return @m2*x+@n2
    end
    end
    class Block_WL < Block_Surface
    attr_reader :type
    def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x011
    end
    def visible?(sx,sy)
    return sx < @x1 && sy < @y2
    end
    def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = sy - @m1*sx
    @m2 = (@y2-sy)/(@x2-sx)
    @n2 = sy - @m2*sx
    for x in @x1..(sx+range)
    init = shadow_iy(x)
    bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+2)
    end
    end
    def shadow_iy(x)
    return @m1*x+@n1
    end
    def shadow_fy(x)
    return @m2*x+@n2
    end
    end
    class Block_WR < Block_Surface
    attr_reader :type
    def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x014
    end
    def visible?(sx,sy)
    return sx > @x1 && sy < @y2
    end
    def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = sy - @m1*sx
    @m2 = (@y2-sy)/(@x2-sx)
    @n2 = sy - @m2*sx
    for x in (sx-range).to_i..@x1
    init = shadow_iy(x)
    bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+2)
    end
    end
    def shadow_iy(x)
    return @m1*x+@n1
    end
    def shadow_fy(x)
    return @m2*x+@n2
    end
    end
    class Block_SU < Block_Surface
    attr_reader :type
    def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x02
    end
    def visible?(sx,sy)
    return sy < @y1
    end
    def render_shadow(phx,phy,sx,sy,range,bitmap)
    if @x1 == sx
    @m1 = nil
    else
    @m1 = (@y1-sy)/(@x1-sx)
    @m1 += ACC if @m1 < -ACC
    @n1 = @y1 - @m1*@x1
    end
    if @x2 == sx
    @m2 = nil
    else
    @m2 = (@y2-sy)/(@x2-sx)
    @n2 = sy - @m2*sx
    end
    for y in @y1..(sy+range)
    init = shadow_ix(y)
    bitmap.clear_rect(init-phx,y-phy,shadow_fx(y)-init+1,1)
    end
    end
    def shadow_ix(y)
    return @m1.nil? ? @x1 : (y-@n1)/@m1
    end
    def shadow_fx(y)
    return @m2.nil? ? @x2 : (y-@n2)/@m2
    end
    end
    class Block_SD < Block_Surface
    attr_reader :type
    def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x08
    end
    def visible?(sx,sy)
    return sy > @y1
    end
    def render_shadow(phx,phy,sx,sy,range,bitmap)
    if @x1 == sx
    @m1 = nil
    else
    @m1 = (@y1-sy)/(@x1-sx)
    @m1 -= ACC if @m1 > ACC
    @n1 = sy - @m1*sx
    end
    if x2 == sx
    @m2 = nil
    else
    @m2 = (@y2-sy)/(@x2-sx)
    @n2 = sy - @m2*sx
    end
    for y in (sy-range).to_i..@y1
    init = shadow_ix(y)
    bitmap.clear_rect(init-phx,y-phy,shadow_fx(y)-init+1,1)
    end
    end
    def shadow_ix(y)
    return @m1.nil? ? @x1 : (y-@n1)/@m1
    end
    def shadow_fx(y)
    return @m2.nil? ? @x2 : (y-@n2)/@m2
    end
    end
    class Spriteset_Map
    include Light_Core
    alias kbl_initialize initialize
    alias kbl_update update
    alias kbl_dispose dispose
    def initialize
    setup_lights
    kbl_initialize
    end
    def update
    kbl_update
    update_lights
    end
    def dispose
    kbl_dispose
    dispose_lights
    end
    def dispose_lights
    $game_map.lantern.dispose
    $game_map.light_sources.each { |source| source.dispose_light }
    $game_map.light_surface.bitmap.dispose
    $game_map.light_surface.dispose
    $game_map.light_surface = nil
    end
    def update_lights
    $game_map.light_surface.bitmap.clear
    $game_map.light_surface.bitmap.fill_rect(0,0,640,416,$game_map.effect_surface.color)
    $game_map.light_sources.each { |source| source.draw_light }
    return unless $game_map.lantern.visible
    @btr = $game_map.lantern.get_graphic
    x = $game_map.lantern.x
    y = $game_map.lantern.y
    r = $game_map.lantern.range
    sx = x + r
    sy = y + r
    dr = r*2
    $game_map.surfaces.each { |s| s.render_shadow(x,y,sx,sy,r,@btr) if s.visible?(sx,sy) && s.within?(x,x+dr,y,y+dr) }
    $game_map.light_surface.bitmap.blt($game_map.lantern.sx,$game_map.lantern.sy,@btr,Rect.new(0,0,dr,dr),$game_map.lantern.opacity)
    end
    def setup_lights
    @btr = nil
    $game_map.lantern.restore
    $game_map.light_sources.each { |source| source.restore_light }
    $game_map.light_surface = Sprite.new
    $game_map.light_surface.bitmap = Bitmap.new(640,416)
    $game_map.light_surface.bitmap.fill_rect(0,0,640,416,$game_map.effect_surface.color)
    $game_map.light_surface.blend_type = 2
    $game_map.light_surface.opacity = $game_map.effect_surface.alpha
    $game_map.light_surface.z = Surface_Z
    end
    end[/php]

    Mình tạo bóng tối bằng lệnh call này :
    [php]s = $game_map.effect_surface
    s.change_color(300,0,0,0,0)[/php]

    Nhưng có một số vấn đề xảy ra, cái nền bóng tối được tạo ra tuy ko phủ lên Game_Message nhưng lại phủ lên rất nhiều các window khác, điển hình như Choices :

    10428562_1486877284880877_1507534504408055668_n.jpg

    Hay mình sử dụng đoạn script sau để hiện một window luôn hiện theo ý mình thì nó bị phủ đen :

    10298671_1486877274880878_3941927637448939693_n.jpg

    Script này :

    [php]class Window_Text < Window_Base
    #
    # * Object Initialization
    #
    def initialize(x, y)
    super(x, y, 160, 64)
    self.contents = Bitmap.new(width - 32, height - 32)
    end
    #
    # * Draw text
    #
    def drawText(i_text, i_color)
    self.contents.clear
    self.contents.font.color = text_color(i_color)
    self.contents.draw_text(4, 0, 120, 32, i_text)
    end
    end[/php]
  • NagiNagi Posts: 589Registered
    Surface_Z = 180 <~ Chỉnh còn 50 nhé... hoặc bao nhiêu cảm thấy ưng ý là được.
    :caocao:
  • Focker_cFocker_c Posts: 1,577Registered
    Oh`, thì ra Z là độ sâu . Haiz, vẫn có cái khái niệm bên GM , Z là độ cao trong không gian 3D, haiz ^^
    Được rồi, cảm ơn Nagi ^^
  • Dang_KhoaDang_Khoa Posts: 3,861Administrators
    Z gọi là độ ưu tiên cũng được
    :cuoideu:
  • Focker_cFocker_c Posts: 1,577Registered
    Lệnh nào sẽ trả về rằng Scene nào đó có đang mở hay ko ?

    Ví dụ mình muốn kiểm tra xem menu item có đang mở hay ko..
  • DeathDeath Posts: 732Registered, Moderators
    SceneManager.scene_is?(Scene_Item)
    Trả về true/false
  • Focker_cFocker_c Posts: 1,577Registered
    Mới kiếm được một cái scipt giúp mình spawn event một cách đa năng

    [php]# EventSpawn 1.2
    # by Kal (github.com/kl)
    #
    # --- Changelog ----
    #
    # 1.2 - Can now execute common event on spawn.
    # 1.1.2 - Fix event_name_not_found_msg typo.
    # 1.1.1 - Fix absolute positioning bug.
    # 1.1 - Can now spawn using an event id as well as an event name.
    # 1.0.2 - Improved error messages.
    # 1.0.1 - Fix a bug where <spawn-max> would spawn one less than specified.
    # 1.0 - Initial release.
    #
    # --- How To Use ----
    #
    # First create an event on the map that will act as the spawner event.
    # Now you can add various spawn tags to this event (using the Comment function)
    # to let the script know what you want it to do.
    #
    # The spawn tag comments can be added to any event page.
    #
    # The following commands are available (note do not put in the [ and ])
    #
    # (NOTE: all the below tags are optional, except for spawn-event and spawn-timer)
    #
    # <spawn-event [name of event to spawn]>
    # <spawn-timer [number]>
    # <spawn-pos [position string]>
    # <spawn-type [type name]>
    # <spawn-switch [switch ID]>
    # <spawn-max [number]>
    # <spawn-life [number]>
    # <spawn-on-passable [boolean]>
    # <spawn-common-event [common event id]>
    #
    # <spawn-event> takes the name of the event to spawn (the name can be found
    # in the upper left corner of the event box)
    #
    # <spawn-timer> takes the number of frames between each spawn (60 frames = 1 sec)
    #
    # <spawn-pos> takes a string that defines where to spawn the events. It can take
    # either a relative or an absolute position. To specify a relative position,
    # use up, down, left and right. Then the event will be spawned relative to
    # the spawner on tile in that direction.
    # To use an absolute position you can give the map coordinate like this
    # x,y for example 13,49.
    # You can also set the events to spawn a random distance from the spawner
    # event. To do that use the tag like this: <spawn-pos random:[number]>
    # The number after the colon is the max distance from the spawner that
    # events should be able to spawn. If you omit this number the max distance
    # is set to 1.
    # If you do not set the spawn-pos, the event will be spawned on the same
    # tile as the spawner is on.
    #
    # <spawn-type> takes the type of spawner to use. Currently this script supports
    # the normal type (which you get if you don't use this tag) and the
    # "loop" type which will keep track of the events that have been spawned,
    # and if any of them dies it will be able to spawn again (if it is using
    # the spawn-max tag that is)
    #
    # <spawn-switch> takes the ID of a switch and the spawner will only spawn if
    # this switch is on.
    #
    # <spawn-max> takes the maximum number of events the spawner should spawn.
    # Once this number has been reached the spawner will stop spawning.
    #
    # <spawn-life> takes the number of frames a spawned event should exist.
    # After the time is up, the spawned event will be automatically
    # despawned (erased). If you don't set this options the spawned
    # events will not be despawned at all.
    #
    # <spawn-on-passable> takes true or false and determines whether the spawner
    # should be able to spawn events on unpassable tiles or not (note if you use
    # absolute positioning this attribute does nothing). The default is true.
    # So if you set spawn-pos to 'up' and the tile above the spawner event is
    # unpassable, the event will spawn on an adjecent passable tile.
    # If no adjecent tile is passable, it will spawn on the same tile as
    # the spawner event.
    #
    # <spawn-common-event> takes the ID of a common event that should be
    # executed every time the spawner spawns an event.
    # When the common event executes, you can access the spawner object from
    # the Script event command by calling @fiber.spawner. You can then set various
    # options using the spawner.options hash. An example: (the following is a script
    # that is put in to the Script event command box in the common event)
    #
    # spawner = @fiber.spawner
    # spawner.options[:timer] += 30
    #
    # This code will get the spawner object and then access the options hash where
    # it increments the timer with 30. So every time the common event is executed,
    # the timer will be incremented by 30. You can use the following symbols to
    # access the options data (they correspond with the <spawn> tags):
    #
    # options[:timer]
    # options[:event_name]
    # options[:event_id]
    # options[:switch]
    # options[:max]
    # options[:life]
    # options[:passable]
    # options[:type]
    # options[:common_event]
    #
    # --- Example ---
    #
    # Here is what an example event comment for a spawner could look like:
    #
    # <spawn-event EV004>
    # <spawn-timer 120>
    # <spawn-switch 1>
    # <spawn-pos random:4>
    # <spawn-max 3>
    # <spawn-life 400>
    # <spawn-type loop>
    # <spawn-on-passable false>
    # <spawn-common-event 10>
    #
    # --- License ---
    #
    # MIT license
    # http://opensource.org/licenses/MIT
    #

    module Kal
    module EventSpawn

    module CONFIG

    # You can set this constant to a map id and the script will look
    # for events to spawn on that map. That way you can put all your spawn
    # events on one map, and they don't need to present on the map they
    # are spawned on.
    SPAWN_MAP_ID = nil
    end

    # <<< END CONFIGURATION >>>

    class SpawnError < StandardError; end

    #
    # The Factory module is used to parse the spawn tags and create the
    # spawner events.
    #
    module Factory
    module_function

    #
    # Creates and returns a spawner given a Game_Event (which is the event
    # that the spawner will spawn) and an RPG::Event (which is the RPG::Event
    # for the spawner event and it holds things such as event comments).
    #
    # This method is called for every event on the map inside Game_Event's
    # constructor. If the event it is called for is not a spawner event
    # then this method returns nil.
    #
    def make_spawner(game_event, rpg_event)

    tags = get_spawn_tags(rpg_event)

    return nil if tags.empty?

    options = make_options_hash(tags.join)

    check_requirements(options, game_event.id)

    select_spawner_object(game_event, options)
    end

    # ***** HELPER METHODS *****

    #
    # Takes an RPG::Event object and returns an array with all the spawn
    # tag comments (e.g. <spawn-timer 120>) for the event.
    #
    def get_spawn_tags(rpg_event)
    # Returns an array with all comments on all pages.
    comments = rpg_event.pages.each_with_object([]) do |page, array|
    array << page.list.select do |cmd|
    cmd.code == 108 || cmd.code == 408
    end
    end

    # Selects the comments that are spawn comments and return them.
    spawns = comments.flatten.select { |c| c.parameters.first =~ /^<spawn-/ }
    spawns.map { |c| c.parameters.first }
    end

    #
    # Parses a spawn string (all spawn comments as one string) and returns
    # an options hash.
    #
    def make_options_hash(spawn_string)

    timer = spawn_string[/<spawn-timer\s+(\d+)>/i, 1]
    event_name = spawn_string[/<spawn-event\s+([\d\w]+)>/i, 1]
    event_id = spawn_string[/spawn-id\s+(\d+[Xx]?)>/i, 1]
    max = spawn_string[/<spawn-max\s+(\d+)>/i, 1]
    switch = spawn_string[/<spawn-switch\s+(\d+)>/i, 1]
    life = spawn_string[/<spawn-life\s+(\d+)>/i, 1]
    not_passable = spawn_string[/<spawn-on-passable\s+(false)/i, 1]
    type = spawn_string[/<spawn-type\s+(\w+)>/i, 1]
    pos = spawn_string[/<spawn-pos\s+([\d\w,:]+?)>/i, 1]
    common_event = spawn_string[/spawn-common-event\s+(\d+)/i, 1]

    options = {}
    options[:timer] = timer.to_i if timer
    options[:event_name] = event_name
    options[:event_id] = event_id
    options[:switch] = switch.to_i if switch
    options[:max] = max.to_i if max
    options[:life] = life.to_i if life
    options[:passable] = false if not_passable
    options[:type] = type
    options[:common_event] = common_event.to_i if common_event

    if match = pos && pos.match(/(\d+),(\d+)/)
    options[:position] = :absolute
    options[:x] = match[1].to_i
    options[:y] = match[2].to_i
    else
    options[:position] = :relative
    case pos
    when "up"
    options[:y_adjust] = -1
    when "down"
    options[:y_adjust] = 1
    when "left"
    options[:x_adjust] = -1
    when "right"
    options[:x_adjust] = 1
    when /random/
    distance = pos[/random:(\d+)/, 1] || 1
    options[:random_pos] = distance.to_i
    end
    end

    options
    end

    #
    # Checks to see if the user set the <spawn-event>/<spawn-id>
    # and <spawn-timer> tags. If not raise exceptions.
    #
    def check_requirements(options, event_id)
    event_msg = "not set for EVENT:" + "%03d" % event_id
    if !options[:event_name] && !options[:event_id]
    raise ArgumentError.new("<spawn-event> or <spawn-id> #{event_msg}")
    elsif !options[:timer]
    raise ArgumentError.new("<spawn-timer> #{event_msg}")
    end
    end

    #
    # Selects the Spawner type to use.
    #
    def select_spawner_object(game_event, options)
    case options[:type]
    when "loop"
    LoopSpawner.new(game_event, options)
    else # when no type was selected
    Spawner.new(game_event, options)
    end
    end
    end

    #
    # Spawner is the class that keeps track of what event should be spawned,
    # when it should be spawned and where it should be spawned.
    # Each Game_Event that is a spawner will have it's own reference to a
    # Spawner object.
    #
    class Spawner
    include Kal::EventSpawn::CONFIG

    attr_reader :options

    #
    # Sets initial values. game_event is the event that will be spawned.
    #
    def initialize(game_event, options_hash)
    @game_event = game_event
    @options = {x_adjust: 0, y_adjust: 0, passable: true} # default options
    @options.merge!(options_hash)
    @timer = @options[:timer]
    @spawn_count = 0
    @spawn_map_events = load_spawn_map_events
    @common_event_runner = CommonEventRunner.new
    end

    #
    # Updates a the spawner event's timer (if it should spawn or not).
    #
    def update
    return if @options[:switch] && !$game_switches[@options[:switch]]

    @timer -= 1
    if @timer <= 0
    @should_spawn = true
    @timer = @options[:timer]
    end
    end

    #
    # Spawns a new event.
    #
    def spawn
    run_common_event
    set_spawn_pos # set the position the spawned event will have.

    if name = @options[:event_name]
    event = event_from_name(name)
    elsif id = @options[:event_id]
    event = event_from_id(id)
    end

    cloned_event = clone_event(event)
    cloned_event.life_es_kal = @options[:life]
    cloned_event.moveto(@x, @y) # move the spawned event to it's position.

    # Add the spawned event to the Game_Map and the current Spriteset:

    $game_map.events[cloned_event.id] = cloned_event

    spriteset = SceneManager.scene.instance_eval { @spriteset }
    spriteset.instance_eval do
    @character_sprites << Sprite_Character.new(@viewport1, cloned_event)
    end

    @spawn_count += 1
    @should_spawn = false
    end

    #
    # Checks if it is time for the Spawner to spawn or not.
    #
    def should_spawn?
    max = @options[:max]
    max ? @spawn_count < max && @should_spawn : @should_spawn
    end


    # ***** HELPER METHODS *****
    private

    #
    # Runs the common event if specified.
    #
    def run_common_event
    id = @options[:common_event]
    @common_event_runner.run(id, self) if id
    end

    #
    # Sets the position that will be used for the next event that
    # should be spawned.
    #
    def set_spawn_pos
    set_absolute_position if @options[:position] == :absolute
    set_relative_position if @options[:position] == :relative
    end

    #
    # Sets an absolute position.
    #
    def set_absolute_position
    set_pos(@options[:x], @options[:y])
    end

    #
    # Shortcut method to set the @x and @y position variables.
    #
    def set_pos(x, y)
    @x = x
    @y = y
    end

    #
    # Sets a relative position. The position can be relative to the
    # position of the spawner (up, down etc) or a random position.
    #
    def set_relative_position
    event_x = @game_event.x
    event_y = @game_event.y

    x = event_x + @options[:x_adjust]
    y = event_y + @options[:y_adjust]

    if @options[:random_pos]
    set_random_position(event_x, event_y)
    else
    if @options[:passable] && !passable?(x, y)
    set_passable_position(event_x, event_y)
    else
    set_pos(x, y)
    end
    end
    end

    #
    # Sets @x and @y to passable tile in a one-tile distance from x,y.
    # If no passable tile exists, sets @x and @y to x,y.
    #
    def set_passable_position(x, y)
    y - 1, x], [y + 1, x], [x - 1, y], [x + 1, y.each do |coord|
    if passable?(coord[0], coord[1])
    @x = coord[0]
    @y = coord[1]
    return
    end
    end
    @x, @y = x, y
    end

    #
    # Sets the position to a random coordinate given a start x
    # and a start y.
    #
    def set_random_position(start_x, start_y)

    distance = @options[:random_pos]
    coords = get_possible_coords(start_x, start_y, distance).shuffle

    if @options[:passable]
    pass = coords.find { |c| passable?(c[0], c[1]) }
    pass ? set_pos(pass[0], pass[1]) : set_pos(start_x, start_y)
    else
    x, y = coords.first
    set_pos(x, y)
    end
    end

    #
    # Returns an array of all the coords within distance tiles
    # of x,y excluding x,y itself.
    #
    def get_possible_coords(start_x, start_y, distance)
    coords = []

    left_most = start_x - distance
    right_most = start_x + distance
    up_most = start_y - distance
    down_most = start_y + distance

    (left_most..right_most).each do |x|
    (up_most..down_most).each do |y|
    coords << [x, y] unless x == start_x && y == start_y
    end
    end
    coords
    end

    #
    # Check if a tile is passable on the map.
    #
    def passable?(x, y)
    $game_map.passable?(x, y, 2)
    end

    #
    # Does a deep clone of the given Game_Event object and sets
    # it's spawn event IDs.
    #
    def clone_event(event)
    id = generate_valid_id
    cloned_event = Marshal.load(Marshal.dump(event))
    cloned_event.set_ids_es_kal(id)
    cloned_event.set_spawn_name_es_kal(@game_event, id)
    cloned_event
    end

    #
    # Finds a Game_Event object given an event name.
    # Searches for events on the current map and the spawn map.
    # Raises an exception if the event could not be found.
    #
    def event_from_name(name)
    events = $game_map.events.values + (@spawn_map_events || [])
    event = events.find { |e| e.event.name == name }
    event || raise(SpawnError, event_name_not_found_msg(name))
    end

    #
    # Returns an error message if an event could not be found.
    # identifier is either the Game_Event's id or name.
    #
    def event_name_not_found_msg(name)
    "Event with name '#{name}' could not be found on the current map " +
    "(ID = #{$game_map.map_id})" +
    (SPAWN_MAP_ID ? ", or on the spawn map (ID = #{SPAWN_MAP_ID})." : ".")
    end

    #
    # Finds a Game_Event object given an event id.
    # The id is a number (string) with an optional S attached.
    # The S indicates that the id refers to and event id on the spawn map.
    # Raises an exception if the event could not be found.
    #
    def event_from_id(id)
    if id_num = id[/^(\d+)[Xx]/, 1]
    check_spawn_map_set
    event = @spawn_map_events.find { |e| e.id == id_num.to_i }
    event || raise(SpawnError, "Event with id #{id_num} could not " +
    "be found on the spawn map (ID = #{SPAWN_MAP_ID})")
    else
    event = $game_map.events.values.find { |e| e.id == id.to_i }
    event || raise(SpawnError, "Event with id #{id} could not " +
    "be found on the current map (ID = #{$game_map.map_id})")
    end
    end

    def check_spawn_map_set
    SPAWN_MAP_ID || raise(SpawnError, "Tried to spawn with a spawn map " +
    "event ID, but SPAWN_MAP_ID is not set. Set it in the script CONFIG.")
    end

    #
    # Generates a valid id based on the number of events already on the map.
    #
    def generate_valid_id
    $game_map.events.keys.max + 1
    end

    #
    # Returns an array with all the Game_Events located on the spawn map.
    #
    def load_spawn_map_events
    id = SPAWN_MAP_ID
    if id.is_a?(Numeric) && id > 0
    begin
    map = load_data(sprintf("Data/Map%03d.rvdata2", id))
    rescue Errno::ENOENT => e
    raise LoadError, "ERROR: Could not find a map with ID #{id}\n" +
    "(SPAWN_EVENT_ID = #{id})"
    end
    this_map_id = $game_map.map_id
    map.events.values.map { |event| Game_Event.new(this_map_id, event) }
    end
    end
    end

    #
    # LoopSpawner is a spawner that will check if any of the events it
    # spawned are erased, and if so it will decrement the @spawn_count
    # variable for that event.
    #
    class LoopSpawner < Spawner

    def update
    super
    check_dead_events
    end

    def check_dead_events
    alive = $game_map.events.values.select do |game_event|
    game_event.event.name =~ /spawn:#{@game_event.event.id}/ &&
    !game_event.erased
    end
    @spawn_count = alive.size
    end
    end

    #
    # Class that makes it easy to execute a common from the map scene.
    #
    class CommonEventRunner

    #
    # Runs the common event with the given ID and passes in the spawner
    # to the internal fiber object.
    #
    def run(common_event_id, spawner)
    page = make_page(common_event_id)
    setup_event(page, spawner)
    end

    private

    #
    # Returns an event page for a given common event id.
    #
    def make_page(id)
    page = RPG::Troop::Page.new
    # 117 => common event code, 0 => indent, id => id of common event
    page.list.unshift(RPG::EventCommand.new(117, 0, [id]))
    page
    end

    #
    # A big hack in order to not having to change the setup_event method
    # in the Game_Interpreter class.
    #
    def setup_event(page, spawner)
    $game_map.interpreter.instance_eval do
    clear
    @map_id = $game_map.map_id
    @event_id = 0
    @list = page.list
    @fiber = SpawnerFiberEsKal.new(spawner) { run } if @list
    end
    end
    end

    end # end EventSpawn
    end # end Kal


    class Game_Event
    attr_accessor :spawner_es_kal, :life_es_kal
    attr_reader :event, :erased, :spawned_info_es_kal

    #
    # Overrides initialize to create a Spawner instance for this event
    # (or nil if it is not a spawner event).
    #
    alias_method :initialize_es_kal, :initialize
    def initialize(*args)
    initialize_es_kal(*args)
    @spawner_es_kal = Kal::EventSpawn::Factory.make_spawner(self, @event)
    end

    #
    # Updates the Spawner and the spawned event's life (if applicable).
    #
    alias_method :update_es_kal, :update
    def update
    update_es_kal
    @spawner_es_kal.update if @spawner_es_kal
    update_life_es_kal
    end

    #
    # Checks the spawned event's life and erases it if life becomes zero.
    #
    def update_life_es_kal
    if @life_es_kal
    @life_es_kal -= 1
    erase if @life_es_kal <= 0
    end
    end

    #
    # Sets IDs.
    #
    def set_ids_es_kal(id)
    @event.id = id
    @id = id
    end

    #
    # Sets the event's name.
    #
    def set_spawn_name_es_kal(game_event, id)
    @event.name = "#{@event.name} spawn:#{game_event.event.id}:#{id}"
    end
    end

    class Game_Map
    attr_reader :map_id

    #
    # Gets all Spawner events on the map that should spawn and spawn them.
    #
    alias_method :update_events_es_kal, :update_events
    def update_events
    need_to_spawn = @events.values.select do |event|
    event.spawner_es_kal && event.spawner_es_kal.should_spawn?
    end
    need_to_spawn.each { |event| event.spawner_es_kal.spawn }

    update_events_es_kal
    end
    end

    class SpawnerFiberEsKal < Fiber
    attr_accessor :spawner

    def initialize(spawner)
    @spawner = spawner
    super()
    end
    end

    class Game_Interpreter

    #
    # Checks to see if the current fiber is a spawner fiber when this
    # method is called. If so, the new game interpreter is setup to also
    # use a spawner fiber with the same spawner object. This fiber is
    # accessible from the common event via @fiber.
    #
    alias_method :command_117_es_kal, :command_117
    def command_117
    if @fiber.is_a?(SpawnerFiberEsKal)
    common_event = $data_common_events[@params[0]]

    if common_event
    child = Game_Interpreter.new(@depth + 1)

    fiber = @fiber
    child.instance_eval do
    clear
    @map_id = $game_map.map_id
    @event_id = same_map? ? @event_id : 0
    @list = common_event.list
    @fiber = SpawnerFiberEsKal.new(fiber.spawner) { run } if @list
    end

    child.run
    end
    else
    command_117_es_kal
    end
    end
    end[/php]

    Nhưng phải cái mỗi lần spawn nó cứ kéo camera qua chỗ spawn , tìm hoài trong script mà ko biết bỏ cái này đi sao -_-
  • Focker_cFocker_c Posts: 1,577Registered
    [php]x = ( x == nil ? ( 640 - w ) / 2 : ( x < 0 ? ( 640 + x - w ) : x ) )[/php]


    ^


    Đầu tiên là rẽ nhánh : x có bằng 0 ko.
    Nếu có thì :
    x sẽ = ( 640 - w ) / 2
    Nếu ko thì lại đặt yêu cầu tiếp xem có nhỏ hơn 0 ko,
    Nếu nhỏ hơn thì :
    x sẽ = ( 640 + x - w )


    Mọi người giải thích giúp :)
  • slucis7593slucis7593 Posts: 544Registered
    Focker_c wrote:
    [php]x = ( x == nil ? ( 640 - w ) / 2 : ( x < 0 ? ( 640 + x - w ) : x ) )[/php]

    1. x < 0 ?
    a. Đúng : trả lại 640 + x - W
    b. Sai : trả lại x

    2. x == nil ? (nil là rỗng chứ không phải 0 nhé)
    a. Đúng: trả lại (640 - w) / 2
    b. Sai: trả lại "giá trị được trả lại" ở bước 1


    3. x = "giá trị được trả lại" ở bước 2
  • NagiNagi Posts: 589Registered
    Tên Victor script của hắn die sạch sẽ như Yanfly rồi. :cuoideu:
  • Focker_cFocker_c Posts: 1,577Registered
    Thế bây giờ phải down sẵn về ủ hàng trước khi link die hết ? ^^

    ___


    Bây giờ còn yếu tố script cuối cùng cho dự án của mình, đó là party
    Party về số lượng thì vẫn bình thường , nhưng lúc battle chỉ số người số 1 và số 2 tham chiến.
    Ở trên map cũng chỉ hiện người 2 đi theo người 1 thôi. Tức là ẩn các mem còn lại đi.

    Mọi người giúp đỡ với
    Chí ít thì cũng chỉ cho phương pháp.
  • NagiNagi Posts: 589Registered
    Search def max_battler member ấy trong script ấy, đâu đó trong game_battler thì phải... Chỉnh 4 thành 2 (chắc thế). Onl đt nên không kiếm đc... Còn không thì yanfly hình như cũng có script party manager thì phải.#
    # * Get Maximum Number of Battle Members
    #
    def max_battle_members
    return 4
    end

    Chỉnh cái này lại thành 2 thử xem, trong game_party ấy.
  • Focker_cFocker_c Posts: 1,577Registered
    Để dễ hiểu hơn thì mình muốn nói tới cái hệ thống pet của hầu hết các game online bây giờ ấy ^^
    Chỉ xuất ra 1 con đi theo được thôi, những con khác vẫn có nhưng để dự bị ^^
  • NagiNagi Posts: 589Registered
    Focker_c wrote:
    Để dễ hiểu hơn thì mình muốn nói tới cái hệ thống pet của hầu hết các game online bây giờ ấy ^^
    Chỉ xuất ra 1 con đi theo được thôi, những con khác vẫn có nhưng để dự bị ^^
    Chỉnh thử cái max_battle_members bằng 2 coi được ko, mình chỉnh nó hơn 4 thì nó hiện hơn 4 con theo nên chỉnh thấp lại thì cũng tương tự.
Sign In or Register to comment.