#==============================================================================#
# Multiplayer.
#==============================================================================#
# Plataforma: RPGMAKER VX ACE
# Dificultad: Medio
# Version : 1.2
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# 21-08-2013 - Version 1.1 => Implementacion pantalla dividida.
# 19-08-2013 - Version 1.1 => mejora del codigo.
# 14-04-2013 - Version 1.0 => version inicial.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Permite crear a un segundo jugador.
#==============================================================================#
module NeoGab
module DirPlayer2
#==============================================================================#
# Configuraciones.
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
DOWN = Input::Y # S en el teclado.
LEFT = Input::X # A en el teclado.
RIGHT = Input::Z # D en el teclado.
UP = Input::R # W en el teclado.
ENTER = Input::L # Q en el teclado.
RUN = Input::A # Shift en el teclado.
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
# Fin de las configuraciones.
#==============================================================================#
end
end
#==============================================================================
# • Input.
#==============================================================================
module Input
extend self
def self.dir4_player2
return 2 if self.press?(NeoGab::DirPlayer2::DOWN)
return 4 if self.press?(NeoGab::DirPlayer2::LEFT)
return 6 if self.press?(NeoGab::DirPlayer2::RIGHT)
return 8 if self.press?(NeoGab::DirPlayer2::UP)
return 0
end
def self.dir8_player2
if self.press?(NeoGab::DirPlayer2::UP)
return 9 if self.press?(NeoGab::DirPlayer2::RIGHT)
return 7 if self.press?(NeoGab::DirPlayer2::LEFT)
return 8
end
if self.press?(NeoGab::DirPlayer2::DOWN)
return 3 if self.press?(NeoGab::DirPlayer2::RIGHT)
return 1 if self.press?(NeoGab::DirPlayer2::LEFT)
return 2
end
return 6 if self.press?(NeoGab::DirPlayer2::RIGHT)
return 4 if self.press?(NeoGab::DirPlayer2::LEFT)
return 0
end
end
#==============================================================================
# ■ Game Multiplayer
#==============================================================================
class Game_Multiplayer < Game_Player
def actor
$game_party.battle_members[1]
end
def dash?
return false if @move_route_forcing
return false if $game_map.disable_dash?
return Input.press?(NeoGab::DirPlayer2::RUN)
end
def move_by_input
return unless movable?
return if $game_map.interpreter.running?
move_straight(Input.dir4_player2) if Input.dir4_player2 > 0
end
def update_nonmoving(last_moving)
return if $game_map.interpreter.running?
if last_moving
$game_party.on_player_walk
return if check_touch_event
end
if movable? && Input.trigger?(NeoGab::DirPlayer2::ENTER)
return if check_action_event
end
update_encounter if last_moving
end
def center(x, y)
$game_map.set_display_pos_p2(x - center_x, y - center_y)
end
def moveto(x, y)
super
center(x, y)
make_encounter_count
end
def update_scroll(last_real_x, last_real_y)
ax1 = $game_map.adjust_x_p2(last_real_x)
ay1 = $game_map.adjust_y_p2(last_real_y)
ax2 = $game_map.adjust_x_p2(@real_x)
ay2 = $game_map.adjust_y_p2(@real_y)
$game_map.scroll_down_p2 (ay2 - ay1) if ay2 > ay1 && ay2 > center_y
$game_map.scroll_left_p2 (ax1 - ax2) if ax2 < ax1 && ax2 < center_x
$game_map.scroll_right_p2(ax2 - ax1) if ax2 > ax1 && ax2 > center_x
$game_map.scroll_up_p2 (ay1 - ay2) if ay2 < ay1 && ay2 < center_y
end
def collide_with_other_player?(x, y)
$game_player.collide?(x, y)
end
end
#==============================================================================
# ■ Game Player
#==============================================================================
class Game_Player < Game_Character
alias :nmp_collidewith :collide_with_characters?
#~ def center_x
#~ (Graphics.width / 32 - 1) / 4.0
#~ end
def center_y
(Graphics.height / 32 - 1) / 4.0
end
def perform_transfer
if transfer?
set_direction(@new_direction)
$game_player2.sync_with($game_player)
if @new_map_id != $game_map.map_id
$game_map.setup(@new_map_id)
$game_map.autoplay
end
moveto(@new_x, @new_y)
$game_player2.moveto(@new_x, @new_y)
clear_transfer_info
end
end
def start_map_event(x, y, triggers, normal)
$game_map.events_xy(x, y).each do |event|
if event.trigger_in?(triggers) && event.normal_priority? == normal
event.turn_toward_character(self)
event.start
end
end
end
def collide_with_other_player?(x, y)
$game_player2.collide?(x, y)
end
def collide_with_characters?(x, y)
return true if collide_with_other_player?(x, y)
nmp_collidewith(x, y)
end
end
#==============================================================================
# ■ Game Character
#==============================================================================
class Game_Character < Game_CharacterBase
def sync_with(target)
@x = target.x
@y = target.y
@real_x = target.real_x
@real_y = target.real_y
@direction = target.direction
update_bush_depth
end
end
#==============================================================================
# ■ Game_Followers
#==============================================================================
class Game_Followers
def initialize(leader)
@visible = $data_system.opt_followers
@gathering = false
@data = []
@data.push(Game_Follower.new(2, leader))
(3...$game_party.max_battle_members).each do |index|
@data.push(Game_Follower.new(index, @data[-1]))
end
end
end
#==============================================================================
# ■ DataManager.
#==============================================================================
module DataManager
class << self
alias :multiplayer_create_game_objects :create_game_objects
alias :multiplayer_make_save_contents :make_save_contents
alias :multiplayer_extract_save_contents :extract_save_contents
end
def self.create_game_objects
multiplayer_create_game_objects
$game_player2 = Game_Multiplayer.new
end
def self.make_save_contents
contents = multiplayer_make_save_contents
contents[:player2] = $game_player2
contents
end
def self.extract_save_contents(contents)
multiplayer_extract_save_contents(contents)
$game_player2 = contents[:player2]
end
def self.setup_new_game
create_game_objects
$game_party.setup_starting_members
$game_map.setup($data_system.start_map_id)
$game_player.moveto($data_system.start_x, $data_system.start_y)
$game_player.refresh
$game_player2.moveto($data_system.start_x, $data_system.start_y)
$game_player2.refresh
Graphics.frame_count = 0
end
end
#==============================================================================
# ■ Game Party.
#==============================================================================
class Game_Party
alias :multiplayer_add_actor :add_actor
alias :multiplayer_remove_actor :remove_actor
def add_actor(actor_id)
multiplayer_add_actor(actor_id)
$game_player2.refresh if $game_player2
end
def remove_actor(actor_id)
multiplayer_remove_actor(actor_id)
$game_player2.refresh if $game_player2
end
end
#==============================================================================
# ■ Scene_Menu
#==============================================================================
class Scene_Menu < Scene_MenuBase
alias :multiplayer_on_formation_ok :on_formation_ok
def on_formation_ok
multiplayer_on_formation_ok
$game_player2.refresh if $game_player2
end
end
#==============================================================================
# ■ Game Map.
#==============================================================================
class Game_Map
attr_accessor :display_x2
attr_accessor :display_y2
alias :nmp_initialize :initialize
def initilaize
@display_x2 = 0
@display_y2 = 0
nmp_initialize
end
alias :nmp_setup :setup
def setup(map_id)
@display_x2 = 0
@display_y2 = 0
@scroll_direction_2 = 2
@scroll_rest_2 = 0
@scroll_speed_2 = 4
nmp_setup(map_id)
end
def scroll_down_p2(distance)
if loop_vertical?
@display_y2 += distance
@display_y2 %= @map.height
@parallax_y += distance if @parallax_loop_y
else
last_y = @display_y2
@display_y2 = [@display_y2 + distance, height - screen_tile_y].min
@parallax_y += @display_y2 - last_y
end
end
def scroll_left_p2(distance)
if loop_horizontal?
@display_x2 += @map.width - distance
@display_x2 %= @map.width
@parallax_x -= distance if @parallax_loop_x
else
last_x = @display_x2
@display_x2 = [@display_x2 - distance, 0].max
@parallax_x += @display_x2 - last_x
end
end
def scroll_right_p2(distance)
if loop_horizontal?
@display_x2 += distance
@display_x2 %= @map.width
@parallax_x += distance if @parallax_loop_x
else
last_x = @display_x2
@display_x2 = [@display_x2 + distance, (width - screen_tile_x)].min
@parallax_x += @display_x2 - last_x
end
end
def scroll_up_p2(distance)
if loop_vertical?
@display_y2 += @map.height - distance
@display_y2 %= @map.height
@parallax_y -= distance if @parallax_loop_y
else
last_y = @display_y2
@display_y2 = [@display_y2 - distance, 0].max
@parallax_y += @display_y2 - last_y
end
end
def start_scroll_p2(direction, distance, speed)
@scroll_direction_2 = direction
@scroll_rest_2 = distance
@scroll_speed_2 = speed
end
def scrolling_2?
@scroll_rest_2 > 0
end
def update_scroll
return unless scrolling_2?
last_x = @display_x2
last_y = @display_y2
do_scroll_p2(@scroll_direction_2, scroll_distance_p2)
if @display_x2 == last_x && @display_y2 == last_y
@scroll_rest_2 = 0
else
@scroll_rest_2 -= scroll_distance_p2
end
end
def do_scroll_p2(direction, distance)
case direction
when 2; scroll_down_p2 (distance)
when 4; scroll_left_p2 (distance)
when 6; scroll_right_p2(distance)
when 8; scroll_up_p2 (distance)
end
end
def scroll_distance_p2
2 ** @scroll_speed_2 / 256.0
end
def set_display_pos_p2(x, y)
x = [0, [x, width - screen_tile_x].min].max unless loop_horizontal?
y = [0, [y, height - screen_tile_y].min].max unless loop_vertical?
@display_x2 = (x + width) % width
@display_y2 = (y + height) % height
@parallax_x2 = x
@parallax_y = y
end
def adjust_x_p2(x)
if loop_horizontal? && x < @display_x2 - (width - screen_tile_x) / 2
x - @display_x2 + @map.width
else
x - @display_x2
end
end
def adjust_y_p2(y)
if loop_vertical? && y < @display_y2 - (height - screen_tile_y) / 2
y - @display_y2 + @map.height
else
y - @display_y2
end
end
#~ def screen_tile_x
#~ Graphics.width / 64
#~ end
def screen_tile_y
Graphics.height / 64
end
end
#==============================================================================
# ■ Game_CharacterBase.
#==============================================================================
class Game_CharacterBase
def screen_x_p2
$game_map.adjust_x_p2(@real_x) * 32 + 16
end
def screen_y_p2
$game_map.adjust_y_p2(@real_y) * 32 + 32 - shift_y - jump_height
end
def screen_z_p2
@priority_type * 100
end
def jumpto_tile(x, y)
jumpto(0, [x, y])
end
def jumpto(char_id, tilexy=nil)
if char_id > 0
char = $game_map.events[char_id]
elsif char_id < 0
char = $game_player2
else
char = $game_player
end
tilexy.nil? ? condxy = [char.x, char.y] : condxy = [tilexy[0], tilexy[1]]
jx = + eval_distance(tilexy.nil? ? char : tilexy)[0] if condxy[0] >= @x
jy = - eval_distance(tilexy.nil? ? char : tilexy)[1] if condxy[1] <= @y
jx = - eval_distance(tilexy.nil? ? char : tilexy)[0] if condxy[0] <= @x
jy = - eval_distance(tilexy.nil? ? char : tilexy)[1] if condxy[1] <= @y
jx = - eval_distance(tilexy.nil? ? char : tilexy)[0] if condxy[0] <= @x
jy = + eval_distance(tilexy.nil? ? char : tilexy)[1] if condxy[1] >= @y
jx = + eval_distance(tilexy.nil? ? char : tilexy)[0] if condxy[0] >= @x
jy = + eval_distance(tilexy.nil? ? char : tilexy)[1] if condxy[1] >= @y
jump(jx, jy)
end
def eval_distance(target)
if target.is_a?(Array)
distance_x = (@x - target[0]).abs
distance_y = (@y - target[1]).abs
else
distance_x = (@x - target.x).abs
distance_y = (@y - target.y).abs
end
return [distance_x, distance_y]
end
end
#==============================================================================
# ■ Game_Event
#==============================================================================
class Game_Event < Game_Character
alias :nmp_collidewith :collide_with_characters?
def collide_with_characters?(x, y)
return true if collide_with_player2?(x, y)
nmp_collidewith(x, y)
end
def collide_with_player2?(x, y)
normal_priority? && $game_player2.collide?(x, y)
end
def lock
unless @locked
@prelock_direction = @direction
@locked = true
end
end
end
#==============================================================================
# ■ Scene Map.
#==============================================================================
class Scene_Map < Scene_Base
alias :multiplayer_map_start :start
alias :multiplayer_map_updt :update
alias :multiplayer_map_disp :dispose_spriteset
alias :multiplayer_map_updtforfade :update_for_fade
def start
super
multiplayer_map_start
@spriteset2 = Spriteset_Map2.new
end
def update
multiplayer_map_updt
$game_player2.update if $game_player2
@spriteset2.update
end
def dispose_spriteset
multiplayer_map_disp
@spriteset2.dispose
end
def update_call_menu
if $game_system.menu_disabled || $game_map.interpreter.running?
@menu_calling = false
else
@menu_calling ||= Input.trigger?(:B)
call_menu if @menu_calling && !$game_player.moving?
end
end
def update_for_fade
multiplayer_map_updtforfade
@spriteset2.update
end
end
#==============================================================================
# ■ Spriteset_Map.
#==============================================================================
class Spriteset_Map
alias :multiplayer_create_characters :create_characters
def create_characters
multiplayer_create_characters
@character_sprites.push(Sprite_Character.new(@viewport1, $game_player2))
end
def create_viewports
@viewport1 = Viewport.new(0, 0, Graphics.width, (Graphics.height/2)-1)
@viewport2 = Viewport.new(0, 0, Graphics.width, (Graphics.height/2)-1)
@viewport3 = Viewport.new(0, 0, Graphics.width, (Graphics.height/2)-1)
@viewport2.z = 50
@viewport3.z = 100
end
end
#==============================================================================
# ■ Spriteset_Map.
#==============================================================================
class Spriteset_Map2
def initialize
create_viewports
create_tilemap
create_parallax
create_characters
create_shadow
create_weather
create_timer
update
end
def create_viewports
@viewport1 = Viewport.new(0,(Graphics.height/2)+1,Graphics.width,(Graphics.height/2)-1)
@viewport2 = Viewport.new(0,(Graphics.height/2)+1,Graphics.width,(Graphics.height/2)-1)
@viewport3 = Viewport.new(0,(Graphics.height/2)+1,Graphics.width,(Graphics.height/2)-1)
@viewport2.z = 50
@viewport3.z = 100
end
def create_tilemap
@tilemap = Tilemap.new(@viewport1)
@tilemap.map_data = $game_map.data
load_tileset
end
def load_tileset
@tileset = $game_map.tileset
@tileset.tileset_names.each_with_index do |name, i|
@tilemap.bitmaps[i] = Cache.tileset(name)
end
@tilemap.flags = @tileset.flags
end
def create_parallax
@parallax = Plane.new(@viewport1)
@parallax.z = -100
end
def create_characters
@character_sprites = []
$game_map.events.values.each do |event|
@character_sprites.push(Sprite_Character2.new(@viewport1, event))
end
$game_map.vehicles.each do |vehicle|
@character_sprites.push(Sprite_Character2.new(@viewport1, vehicle))
end
$game_player.followers.reverse_each do |follower|
@character_sprites.push(Sprite_Character2.new(@viewport1, follower))
end
@character_sprites.push(Sprite_Character2.new(@viewport1, $game_player))
@character_sprites.push(Sprite_Character2.new(@viewport1, $game_player2))
@map_id = $game_map.map_id
end
def create_shadow
@shadow_sprite = Sprite.new(@viewport1)
@shadow_sprite.bitmap = Cache.system("Shadow")
@shadow_sprite.ox = @shadow_sprite.bitmap.width / 2
@shadow_sprite.oy = @shadow_sprite.bitmap.height
@shadow_sprite.z = 180
end
def create_weather
@weather = Spriteset_Weather.new(@viewport2)
end
def create_timer
@timer_sprite = Sprite_Timer.new(@viewport2)
end
def dispose
dispose_tilemap
dispose_parallax
dispose_characters
dispose_shadow
dispose_weather
dispose_timer
dispose_viewports
end
def dispose_tilemap
@tilemap.dispose
end
def dispose_parallax
@parallax.bitmap.dispose if @parallax.bitmap
@parallax.dispose
end
def dispose_characters
@character_sprites.each {|sprite| sprite.dispose }
end
def dispose_shadow
@shadow_sprite.dispose
end
def dispose_weather
@weather.dispose
end
def dispose_timer
@timer_sprite.dispose
end
def dispose_viewports
@viewport1.dispose
@viewport2.dispose
@viewport3.dispose
end
def refresh_characters
dispose_characters
create_characters
end
def update
update_tileset
update_tilemap
update_parallax
update_characters
update_shadow
update_weather
update_timer
update_viewports
end
def update_tileset
if @tileset != $game_map.tileset
load_tileset
refresh_characters
end
end
def update_tilemap
@tilemap.map_data = $game_map.data
@tilemap.ox = $game_map.display_x2 * 32
@tilemap.oy = $game_map.display_y2 * 32
@tilemap.update
end
def update_parallax
if @parallax_name != $game_map.parallax_name
@parallax_name = $game_map.parallax_name
@parallax.bitmap.dispose if @parallax.bitmap
@parallax.bitmap = Cache.parallax(@parallax_name)
Graphics.frame_reset
end
@parallax.ox = $game_map.parallax_ox(@parallax.bitmap)
@parallax.oy = $game_map.parallax_oy(@parallax.bitmap)
end
def update_characters
refresh_characters if @map_id != $game_map.map_id
@character_sprites.each {|sprite| sprite.update }
end
def update_shadow
airship = $game_map.airship
@shadow_sprite.x = airship.screen_x_p2
@shadow_sprite.y = airship.screen_y_p2 + airship.altitude
@shadow_sprite.opacity = airship.altitude * 8
@shadow_sprite.update
end
def update_weather
@weather.type = $game_map.screen.weather_type
@weather.power = $game_map.screen.weather_power
@weather.ox = $game_map.display_x2 * 32
@weather.oy = $game_map.display_y2 * 32
@weather.update
end
def update_timer
@timer_sprite.update
end
def update_viewports
@viewport1.tone.set($game_map.screen.tone)
@viewport1.ox = $game_map.screen.shake
@viewport2.color.set($game_map.screen.flash_color)
@viewport3.color.set(0, 0, 0, 255 - $game_map.screen.brightness)
@viewport1.update
@viewport2.update
@viewport3.update
end
end
#==============================================================================
# ■ Sprite_Character2.
#==============================================================================
class Sprite_Character2 < Sprite_Base
attr_accessor :character
def initialize(viewport, character = nil)
super(viewport)
@character = character
update
end
def update
super
update_bitmap
update_src_rect
update_position
update_other
end
def tileset_bitmap(tile_id)
Cache.tileset($game_map.tileset.tileset_names[5 + tile_id / 256])
end
def update_bitmap
if graphic_changed?
@tile_id = @character.tile_id
@character_name = @character.character_name
@character_index = @character.character_index
if @tile_id > 0
set_tile_bitmap
else
set_character_bitmap
end
end
end
def graphic_changed?
@tile_id != @character.tile_id ||
@character_name != @character.character_name ||
@character_index != @character.character_index
end
def set_tile_bitmap
sx = (@tile_id / 128 % 2 * 8 + @tile_id % 8) * 32;
sy = @tile_id % 256 / 8 % 16 * 32;
self.bitmap = tileset_bitmap(@tile_id)
self.src_rect.set(sx, sy, 32, 32)
self.ox = 16
self.oy = 32
end
def set_character_bitmap
self.bitmap = Cache.character(@character_name)
sign = @character_name[/^[\!\$]./]
if sign && sign.include?('$')
@cw = bitmap.width / 3
@ch = bitmap.height / 4
else
@cw = bitmap.width / 12
@ch = bitmap.height / 8
end
self.ox = @cw / 2
self.oy = @ch
end
def update_src_rect
if @tile_id == 0
index = @character.character_index
pattern = @character.pattern < 3 ? @character.pattern : 1
sx = (index % 4 * 3 + pattern) * @cw
sy = (index / 4 * 4 + (@character.direction - 2) / 2) * @ch
self.src_rect.set(sx, sy, @cw, @ch)
end
end
def update_position
self.x = @character.screen_x_p2
self.y = @character.screen_y_p2
self.z = @character.screen_z_p2
end
def update_other
self.opacity = @character.opacity
self.blend_type = @character.blend_type
self.bush_depth = @character.bush_depth
self.visible = !@character.transparent
end
end