ko đc :D , mình ẩn menu_command mà, ko muốn cho người chơi tự tiện switch vì nếu vậy nó sẽ có thể switch thằng đầu tiên
Chứ ko có cách nào để call script kiểu switch formation đó à ?
Bước cuối cùng bây giờ là draw 1 cái window Pet , cho phép xuất pet và thu hồi pet (chính là switch bằng cái script trên)
Nhưng thiết kế một cái window như vậy cũng khá khó chỉ hiện danh sách các member còn lại ngoài thằng leader
Và chắc phải xài window_command để thực hiện ra lệnh xuất ra - thu về.
Cái đó xem qua rồi, nhưng nó là dạng pet làm cảnh, trong battle đứng đằng sau cho đẹp mắt :D
Mình cần con pet vẫn là 1 actor , vẫn equip và có stat bình thường và trong battle vẫn chiến đấu như player.
Cái đó xem qua rồi, nhưng nó là dạng pet làm cảnh, trong battle đứng đằng sau cho đẹp mắt :D
Mình cần con pet vẫn là 1 actor , vẫn equip và có stat bình thường và trong battle vẫn chiến đấu như player.
Bước cuối cùng bây giờ là draw 1 cái window Pet , cho phép xuất pet và thu hồi pet (chính là switch bằng cái script trên)
Nhưng thiết kế một cái window như vậy cũng khá khó chỉ hiện danh sách các member còn lại ngoài thằng leader
Và chắc phải xài window_command để thực hiện ra lệnh xuất ra - thu về.
Bước cuối cùng bây giờ là draw 1 cái window Pet , cho phép xuất pet và thu hồi pet (chính là switch bằng cái script trên)
Nhưng thiết kế một cái window như vậy cũng khá khó chỉ hiện danh sách các member còn lại ngoài thằng leader
Và chắc phải xài window_command để thực hiện ra lệnh xuất ra - thu về.
Haiz....
Ủa không để ý, cái cuối thì sao không dùng 1 event chạy paracell process để check và khi ấn nút thì nó sẽ thu hồi và xuất pet ra... Cái này đâu như Game Maker, đâu nhất thiết cái gì cũng phải tự làm.
Rồi bây giờ làm sao để 3 dòng này có thể đưa cursor vào để lựa chọn từng dòng như 1 menu vậy ?
À ! Mà khi draw được nó rồi thì game vẫn ko bị ngưng , làm sao để khi window này được draw thì tạm thơi ngưng game như mở menu vậy.
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)
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]]
#
# 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
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)
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..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 -_-
Comments
Nếu làm được thì thằng mem4 cũng tương tự ..
Chứ ko có cách nào để call script kiểu switch formation đó à ?
ĐÃ thử cái này
[php]
class Game_Party < Game_Unit
def pt_switch_3to2
@member[2] = @member[3]
$game_player.refresh
end
end
[/php]
@Đã tự giải quyết được vs Script này :
http://forums.rpgmakerweb.com/index.php?/topic/3060-switch-party/
Bước cuối cùng bây giờ là draw 1 cái window Pet , cho phép xuất pet và thu hồi pet (chính là switch bằng cái script trên)
Nhưng thiết kế một cái window như vậy cũng khá khó
Và chắc phải xài window_command để thực hiện ra lệnh xuất ra - thu về.
Haizzzzz
Mình cần con pet vẫn là 1 actor , vẫn equip và có stat bình thường và trong battle vẫn chiến đấu như player.
https://dl.dropboxusercontent.com/u/36246420/RGSS3 Scripts Master Host/Simple Player Swapping.txt
http://forums.rpgmakerweb.com/index.php?/topic/3060-switch-party/ , cái này thấy khá phù hợp
Bây giờ còn :
__
Nảy sinh một câu hỏi thế này :
Draw một window text thì ok rồi,
Bây giờ vẽ ra 3 dòng chữ như srcipt sau :
[php]class Window_Text < Window_Base
#
# * Object Initialization
#
def initialize(i_left, i_top, i_width, i_height) # base : w=160 , h=64
super(i_left, i_top, i_width, i_height)
self.contents = Bitmap.new(width - 32, height - 32)
end
#
# * Draw 3 lines
#
def draw_3_lines
self.contents.clear
self.contents.font.color = text_color(0)
self.contents.draw_text(32, 0, 120, 32, 'Dong 1')
self.contents.draw_text(32, 64, 120, 32, 'Dong 2')
self.contents.draw_text(32, 96, 120, 32, 'Dong 3')
end
end[/php]
Rồi bây giờ làm sao để 3 dòng này có thể đưa cursor vào để lựa chọn từng dòng như 1 menu vậy ?
À ! Mà khi draw được nó rồi thì game vẫn ko bị ngưng , làm sao để khi window này được draw thì tạm thơi ngưng game như mở menu vậy.
[php]class Window_Command_Custom < Window_MenuCommand
def make_command_list
add_command("Line 1", :Line1)
add_command("Line 2", :Line2)
end
class Scene_Custom < Scene_MenuBase
def start
super
create_background
create_window
end
def create_window
@make_choice = Window_Command_Custom(32,32)
@make_choice.set_handler(:Line1 , method(:Action1))
end
def Action1
# Action here
end
end[/php]
Nhưng giờ ko biết sao để thoát cái scene này nhỉ ?
@death @nagi
Thử SceneManager.return xem
Help