[Script] [ACE] [VXA] Topic hỏi-đáp về script VXA
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 ?
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 ?

Comments
Thêm cái Core này vào nữa nhé:
http://pastebin.com/QeXkeEJw
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 :
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 :
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]
:caocao:
Được rồi, cảm ơn Nagi ^^
:cuoideu:
THAM GIA GROUP CỦA TTC TRÊN FACEBOOK
Ví dụ mình muốn kiểm tra xem menu item có đang mở hay ko..
Trả về true/false
[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 -_-
^
Đầ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
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
___
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.
# * 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.
Chỉ xuất ra 1 con đi theo được thôi, những con khác vẫn có nhưng để dự bị ^^