A few weeks ago I discovered Amaranth's Mouse System for Ace and was pretty excited about this script, because it is a very good working mouse script with pathfinding. It is very easy to use
and what is really awesome is that you can change the cursor for events, fights and stuff.
So in my opinion, it is a very good good script, but it would be perfect if it would have another feature: An animated cursor.
For example it would be pretty cool if you hoover above a chest and the icons becomes a hand which is closing and oping slowly.
To see what I am imagining take a look at this Diablo3 youtube video: http://www.youtube.com/watch?v=ALui5NifoH4 (You can skip until 8:43 or 25:30 to see what I mean).
It would be awesome to see something like that in an RPG Maker Game. It gives the game a more professional look and adds more possibilites.
I have talked to Shaz at this topic http://forums.rpgmakerweb.com/index.php?/topic/17829-amaranths-super-simple-mouse-system-for-ace/page-17 and he said it is okay to ask for a script request
since he doesn't have the time to do it by himself.
I would be very grateful if anybody could make that change. Thanks in advance.
Spoiler
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# v1.10 by Shaz
#----------------------------------------------------------------------------
# This is a conversion of the XP Mouse script by Near Fantastica and
# SephirothSpawn modified by Amaranth Games, to run under VX Ace.
#----------------------------------------------------------------------------
# To Install:
# Copy and paste into a new slot in materials, below all other scripts
#----------------------------------------------------------------------------
# To Customize:
# Add keyword icon index pairs to the ICON hash (below this documentation).
# Each of the keywords can be used in an event comment to make the mouse
# cursor change into that icon when hovering over the event.
#----------------------------------------------------------------------------
# To Use:
# Add the following comment to an event page:
#
# where icon is the keyword from the ICON hash below
# x and y are the offsets to override player movement (optional)
# name is the text to display next to the icon when hovering over the event (optional)
#
# Examples:
#
# will change the cursor into the 'fight' icon when over the event
#
# will change the cursor into the 'touch' icon when over the event, and
# make the player walk to the tile below the event when the mouse button is
# clicked
#
# will change the cursor into the 'talk' icon and display the name Gloria
#
# will change the cursor into the 'talk' icon and display the name Henry Smith,
# and when the mouse button is clicked, the player will walk to the tile
# two below the event (good to use for shops where there's a counter in between)
#
# To force pathfinding on the player or an event, simply add a move route with
# the player or event as the subject, with a Script command, and call
# find_path(x, y) where x and y are the coordinates of the tile you want to move to
# Examples:
# Set Move Route (Player): Script: find_path(5, 8)
# will make the player find a path to tile 5, 8
# Set Move Route (This Event): Script: find_path(10, 5)
# will make the event find a path to tile 10, 5
#
# NOTE: The path will be ATTEMPTED. If there is no path TO that exact tile,
# a path to an adjacent tile will be attempted. If no path is found there
# either, no movement will occur.
# If a route is found, the player or event will begin moving towards it. But
# if their path is blocked while they are moving, movement will be cancelled.
#----------------------------------------------------------------------------
# Author's Notes:
# This script should work with any RTP script.
# I do not guarantee that it will work with ANY other script (especially anything
# that overrides player or event movement, such as pixel movement scripts, or
# custom window scripts).
#
# Script OVERWRITES the following methods:
# Game_Map.setup_starting_map_event
# Game_Map.setup_autorun_common_event
#
# If you have other scripts that ALIAS these methods, this mouse script should
# be placed above them.
#----------------------------------------------------------------------------
# Terms:
# Use in free and commercial games
# Credit: Near Fantastica, SephirothSpawn, Amaranth Games, Shaz
#----------------------------------------------------------------------------
# Versions:
# 1.0 - 6 Sept 2013 - initial release
# 1.02 - 7 Sept 2013 - fixed crash when loading games saved prior to adding script
# - fixed player gets stuck on impassable area on world map
# when clicking while leaving air ship
# 1.03 - 8 Sept 2013 - fixed actor moving to diagonal tile instead of adjacent
# 1.04 - 10 Sept 2013 - fixed vehicle pathfinding on world map
# - fixed event trigger when no path found
# 1.05 - 14 Sept 2013 - tweaked accessing of tilemap offset
# 1.06 - 3 Nov 2013 - disabled mouse movement when waiting for NPC move route
# - fixed events not triggering after player finishes walking
# 1.07 - 6 Nov 2013 - slow down mouse scrolling, and don't loop save files
# 1.08 - 24 Nov 2013 - cater for YEA Core large resolution with too-small maps
# - fixed early event activation bug introduced in 1.06
# - replaced calc of Windows_Selectable boundaries with item_rect
# - added ability to completely disable mouse
# 1.09 - 21 Dec 2013 - fixed mouse re-enable when calling common events
# 1.10 - 6 Apr 2014 - add interaction for top part of > 32pixel high event
# - activate an event without walking up to it
# (add comment at top of event page)
# - arrow keys override mouse movement when pathfinding
# - ignore mouse in menus when using keyboard
# - make player walk to counter opposite shopkeepers
#============================================================================
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Mouse Sprite
#============================================================================
# Add/remove/change icon names here. The icon name is what will be used in the
# event command to show a different mouse icon when hovering over
# the event. These MUST be in lower case here!
ICON = {'arrow' => 386, 'talk' => 4, 'look' => 3, 'fight' => 116,
'touch' => 491, 'exit' => 121}
DEFAULT_ICON = 'arrow'
class Sprite_Mouse < Sprite
#--------------------------------------------------------------------------
# * Initialization
#--------------------------------------------------------------------------
def initialize
super
self.z = 10100
self.ox = 4
update
@dummy = Bitmap.new(32, 32)
self.bitmap = Bitmap.new(32, 32)
@enabled = true
@ignored = false
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
return if !@enabled
super
if !SceneManager.scene.nil?
if !Mouse.position.nil?
mx, my = *Mouse.position
if @cursor == DEFAULT_ICON
self.x = mx unless mx.nil?
else
self.x = [mx, Graphics.width - self.bitmap.width].min unless mx.nil?
end
self.y = my unless my.nil?
end
if @scene != SceneManager.scene.class || Mouse.trigger?
@scene = SceneManager.scene.class
set_bitmap
end
end
end
#--------------------------------------------------------------------------
# * Set Bitmap
#--------------------------------------------------------------------------
def set_bitmap(cursor = DEFAULT_ICON, text = nil)
if @ignored
cursor = DEFAULT_ICON
text = nil
end
if @cursor != cursor || @text != text
@cursor = cursor
@text = text
item_cursor = ICON[cursor]
rect = Rect.new(item_cursor % 16 * 24, item_cursor / 16 * 24, 24, 24)
if @text.nil?
self.bitmap = Bitmap.new(24, 32)
self.bitmap.blt(0, 0, Cache.system('Iconset'), rect)
else
w = @dummy.text_size(@text).width
h = @dummy.font.size
bitmap = Bitmap.new(26 + w, [32, h+2].max)
bitmap.font.size = @dummy.font.size
bitmap.font.shadow = true
if self.x + 26 + w > Graphics.width
bitmap.draw_text(0, 0, w, h, @text)
bitmap.blt(w, 0, Cache.system('Iconset'), rect)
else
bitmap.blt(0, 0, Cache.system('Iconset'), rect)
bitmap.draw_text(26, 0, w, h, @text)
end
self.bitmap = bitmap
end
end
end
#--------------------------------------------------------------------------
# * Update Event Cursors
#--------------------------------------------------------------------------
def update_event_cursors
# Remove mouse icon and text if we're off the grid
if Mouse.grid.nil?
set_bitmap
return
end
# Set cursor and text according to event
x, y = *Mouse.grid
event = $game_map.lowest_mouse_event_xy(x, y)
unless event.nil? && y < 410
if !event.mouse_icon.nil? || !event.mouse_text.nil?
set_bitmap(event.mouse_icon, event.mouse_text)
return
end
end
# default bitmap if not over an event
set_bitmap
end
#--------------------------------------------------------------------------
# * Enable Mouse
#--------------------------------------------------------------------------
def enabled=(value)
@enabled = value
self.visible = value
end
#--------------------------------------------------------------------------
# * Mouse Enabled?
#--------------------------------------------------------------------------
def enabled?
@enabled
end
#--------------------------------------------------------------------------
# * Ignore Mouse
#--------------------------------------------------------------------------
def ignored=(value)
@ignored = value
end
#--------------------------------------------------------------------------
# * Mouse Ignored?
#--------------------------------------------------------------------------
def ignored?
@ignored
end
end
$mouse = Sprite_Mouse.new
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Mouse Module
#============================================================================
#==============================================================================
# ** Mouse Module
#------------------------------------------------------------------------------
# by Near Fantastica and SephirothSpawn
# adapted and converted to VX Ace by Shaz
#==============================================================================
module Mouse
#--------------------------------------------------------------------------
# * Mouse to Input Triggers
# key => Input::KeyCONSTANT (key: 0 - left, 1 - middle, 2 - right)
#--------------------------------------------------------------------------
Mouse_to_Input_Triggers = {0 => Input::C, 1 => Input::B, 2 => Input::A}
#--------------------------------------------------------------------------
# * API Declarations
#--------------------------------------------------------------------------
GAKS = Win32API.new('user32', 'GetAsyncKeyState', 'i', 'i')
GSM = Win32API.new('user32', 'GetSystemMetrics', 'i', 'i')
Cursor_Pos = Win32API.new('user32', 'GetCursorPos', 'p', 'i')
Scr2cli = Win32API.new('user32', 'ScreenToClient', %w(l p), 'i')
Client_rect = Win32API.new('user32', 'GetClientRect', %w(l p), 'i')
Findwindow = Win32API.new('user32', 'FindWindowA', %w(p p), 'l')
Readini = Win32API.new('kernel32', 'GetPrivateProfileStringA', %w(p p p p l p), 'l')
ShowCursor = Win32API.new('user32', 'ShowCursor', 'i', 'l')
#--------------------------------------------------------------------------
# * Module Variables
#--------------------------------------------------------------------------
@triggers = [[0, 1], [0, 2], [0, 4]]
@old_pos = 0
@pos_i = 0
@sys_cursor_visible = false
#--------------------------------------------------------------------------
# * Mouse Grid Position
#--------------------------------------------------------------------------
def self.grid
return nil if @pos.nil?
mx, my = SceneManager.scene.instance_variable_get:)@spriteset).tilemap_offset
x = (@pos[0] + mx) / 32
y = (@pos[1] + my) / 32
return [x, y]
end
#--------------------------------------------------------------------------
# * Mouse Position
#--------------------------------------------------------------------------
def self.position
return @pos.nil? ? [0, 0] : @pos
end
#--------------------------------------------------------------------------
# * Mouse Global Position
#--------------------------------------------------------------------------
def self.global_pos
pos = [0, 0].pack('ll')
return Cursor_Pos.call(pos) == 0 ? nil : pos.unpack('ll')
end
#--------------------------------------------------------------------------
# * Screen to Client
#--------------------------------------------------------------------------
def self.screen_to_client(x=0, y=0)
pos = [x, y].pack('ll')
return Scr2cli.call(self.hwnd, pos) == 0 ? nil : pos.unpack('ll')
end
#--------------------------------------------------------------------------
# * Mouse Position
#--------------------------------------------------------------------------
def self.pos
gx, gy = global_pos
x, y = screen_to_client(gx, gy)
# Test boundaries
begin
if (x >= 0 && y >= 0 && x <= Graphics.width && y <= Graphics.height)
return x, y
else
return -20, -20
end
rescue
return 0, 0
end
end
#--------------------------------------------------------------------------
# * Update Mouse Position
#--------------------------------------------------------------------------
def self.update
old_pos = @pos
@pos = self.pos
# Has mouse been moved?
if old_pos != @pos
Input.method = :mouse
end
# Which mouse to show - custom, or system?
if $mouse.enabled? == @sys_cursor_visible
@sys_cursor_visible = !@sys_cursor_visible
ShowCursor.call(@sys_cursor_visible ? 1 : 0)
end
return if !$mouse.enabled?
# Leaving / Entering Range?
if old_pos != [-20, -20] && @pos == [-20, -20] # leaving range
ShowCursor.call(1)
elsif old_pos == [-20, -20] && @pos != [-20, -20] # entering range
ShowCursor.call(0)
end
# Update Triggers
for i in @triggers
n = GAKS.call(i[1])
if [0, 1].include?(n)
i[0] = (i[0] > 0 ? i[0] * -1 : 0)
else
i[0] = (i[0] > 0 ? i[0] + 1 : 1)
end
end
end
#--------------------------------------------------------------------------
# * Trigger?
# id : 0:Left, 1:Right, 2:Center
#--------------------------------------------------------------------------
def self.trigger?(id = 0)
if pos != [-20, -20]
return @triggers[id][0] == 1
end
return false
end
#--------------------------------------------------------------------------
# * Repeat?
# id : 0:Left, 1:Right, 2:Center
#--------------------------------------------------------------------------
def self.repeat?(id = 0)
return @triggers[id][0] > 0 && @triggers[id][0] % 5 == 1
end
#--------------------------------------------------------------------------
# * Hwnd
#--------------------------------------------------------------------------
def self.hwnd
if @hwnd.nil?
title = "\0" * 256
Readini.call('Game', 'Title', '', title, 255, '.\\Game.ini')
title.delete!("\0")
@hwnd = Findwindow.call('RGSS Player', title)
ShowCursor.call(0)
end
return @hwnd
end
#--------------------------------------------------------------------------
# * Client Size
#--------------------------------------------------------------------------
def self.client_size
rect = [0, 0, 0, 0].pack('l4')
Client_rect.call(self.hwnd, rect)
return rect.unpack('l4')[2..3]
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Input
#============================================================================
class << Input
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :method
#--------------------------------------------------------------------------
# * Alias Listings
#--------------------------------------------------------------------------
alias :seph_mouse_input_update :update
alias :seph_mouse_input_trigger? :trigger?
alias :seph_mouse_input_repeat? :repeat?
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
$mouse.update
Mouse.update
seph_mouse_input_update
# Are we using the mouse or the keyboard?
@method = :keyboard if dir4 != 0 || dir8 != 0
end
#--------------------------------------------------------------------------
# * Trigger? Test
#--------------------------------------------------------------------------
def trigger?(constant)
return true if seph_mouse_input_trigger?(constant)
if $mouse.enabled? && !Mouse.pos.nil?
if Mouse::Mouse_to_Input_Triggers.has_value?(constant)
return true if Mouse.trigger?(Mouse::Mouse_to_Input_Triggers.index(constant))
end
end
return false
end
#--------------------------------------------------------------------------
# * Repeat? Test
#--------------------------------------------------------------------------
def repeat?(constant)
return true if seph_mouse_input_repeat?(constant)
if $mouse.enabled? && !Mouse.pos.nil?
if Mouse::Mouse_to_Input_Triggers.has_value?(constant)
return true if Mouse.repeat?(Mouse::Mouse_to_Input_Triggers.index(constant))
end
end
return false
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Map
#============================================================================
class Spriteset_Map
#--------------------------------------------------------------------------
# * Tilemap Offset
#--------------------------------------------------------------------------
def tilemap_offset
if $imported && $imported["YEA-CoreEngine"]
[@tilemap.ox - @viewport1.rect.x, @tilemap.oy - @viewport1.rect.y]
else
[@tilemap.ox, @tilemap.oy]
end
end
end
class Game_Map
#--------------------------------------------------------------------------
# * Detect/Set Up Starting Map Event
#--------------------------------------------------------------------------
def setup_starting_map_event
event = @events.values.find {|event| event.starting }
event.clear_starting_flag if event
@interpreter.setup(event.list, event.id, event.trigger_in?([0,1,2,3])) if event
event
end
#--------------------------------------------------------------------------
# * Detect/Set Up Autorun Common Event
#--------------------------------------------------------------------------
def setup_autorun_common_event
event = $data_common_events.find do |event|
event && event.autorun? && $game_switches[event.switch_id]
end
@interpreter.setup(event.list, 0, true) if event
event
end
#--------------------------------------------------------------------------
# * Get ID of Lowest Mouse-enabled Event at Designated Coordinates
#--------------------------------------------------------------------------
def lowest_mouse_event_xy(x, y)
list = events_xy(x, y) + events_xy(x, y+1)
list.sort! {|a, b| b.y - a.y}
evt = nil
list.each do |event|
if (event.pos?(x, y) || (event.pos?(x, y+1) && event.height > 32)) &&
(evt.nil? || event.y > evt.y)
evt = event
break
end
end
return evt
end
end
class Scene_Map
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
alias shaz_mouse_scene_map_update update
def update
$mouse.update_event_cursors
shaz_mouse_scene_map_update
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Event
#============================================================================
module RPG
class Event
class Page
#--------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------
attr_reader :mouse_icon
attr_reader :mouse_text
attr_reader :mouse_position
attr_reader :mouse_autoactivate
#--------------------------------------------------------------------
# * Build Stats
#--------------------------------------------------------------------
def build_stats
# Mouse icons (icon mandatory, others optional)
#
@mouse_icon = nil
@mouse_text = nil
@mouse_position = [0, 0]
@mouse_autoactivate = false
# look for mouse instructions
list.each do |command|
if [108, 408].include?(command.code)
comment = command.parameters[0]
case comment
when / params = //i.match(comment)[1].split(' ')
@mouse_icon = params.shift
if params.size > 1 && params[0] =~ /\d+/ && params[1] =~ /\d+/
@mouse_position = [params.shift.to_i, params.shift.to_i]
end
if params.size > 0
@mouse_text = params.join(' ')
end
when //
@mouse_autoactivate = true
end
end #if
end #do
end #def
end
end
end
class Game_Event < Game_Character
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_reader :mouse_icon
attr_reader :mouse_text
attr_reader :mouse_position
attr_reader :mouse_autoactivate
#--------------------------------------------------------------------------
# * Start Event
#--------------------------------------------------------------------------
alias shaz_mouse_game_event_start start
def start
$game_player.start_event(@id) if !empty?
shaz_mouse_game_event_start
end
#--------------------------------------------------------------------------
# * Clear Event Page Settings
#--------------------------------------------------------------------------
alias shaz_mouse_game_event_clear_page_settings clear_page_settings
def clear_page_settings
shaz_mouse_game_event_clear_page_settings
@mouse_icon = nil
@mouse_text = nil
@mouse_position = [0, 0]
@mouse_autoactivate = false
@height = 0
end
#--------------------------------------------------------------------------
# * Set Up Event Page Settings
#--------------------------------------------------------------------------
alias shaz_mouse_game_event_setup_page_settings setup_page_settings
def setup_page_settings
shaz_mouse_game_event_setup_page_settings
@page.build_stats
@mouse_icon = @page.mouse_icon
@mouse_text = @page.mouse_text
@mouse_position = @page.mouse_position
@mouse_autoactivate = @page.mouse_autoactivate
set_size
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Character
#============================================================================
class Game_CharacterBase
attr_reader :height # Height of character bitmap
#--------------------------------------------------------------------------
# * Initialize Public Member Variables
#--------------------------------------------------------------------------
alias shaz_mouse_game_characterbase_init_public_members init_public_members
def init_public_members
shaz_mouse_game_characterbase_init_public_members
@height = 0
end
#--------------------------------------------------------------------------
# * Change Graphics
# character_name : new character graphic filename
# character_index : new character graphic index
#--------------------------------------------------------------------------
alias shaz_mouse_game_characterbase_set_graphic set_graphic
def set_graphic(character_name, character_index)
shaz_mouse_game_characterbase_set_graphic(character_name, character_index)
set_size
end
#--------------------------------------------------------------------------
# * Set character width/height size
#--------------------------------------------------------------------------
def set_size
bw = Cache.character(@character_name).width
bh = Cache.character(@character_name).height
sign = @character_name[/^[\!\$]./]
if sign && sign.include?('$')
@width = bw / 3
@height = bh / 4
else
@width = bw / 12
@height = bh / 8
end
end
#--------------------------------------------------------------------------
# * Detect Collision with Event
#--------------------------------------------------------------------------
def collide_with_events?(x, y)
$game_map.events_xy_nt(x, y).any? do |event|
self != event && (event.normal_priority? || self.is_a?(Game_Event))
end
end
#--------------------------------------------------------------------------
# * Detect Collision with Vehicle
#--------------------------------------------------------------------------
def collide_with_vehicles?(x, y)
!self.is_a?(Game_Player) && ($game_map.boat.pos_nt?(x, y) || $game_map.ship.pos_nt?(x, y))
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
alias shaz_mouse_game_characterbase_update update
def update
run_path if @runpath
shaz_mouse_game_characterbase_update
end
#--------------------------------------------------------------------------
# * Run Path
#--------------------------------------------------------------------------
def run_path
return if moving?
@step = @map.nil? || @map[@x, @y].nil? ? 0 : @map[@x, @y] - 1
if @step < 1
clear_path
else
x, y = @x, @y
dirs = []
dirs.push(6) if @map[@x+1, @y] == @step && passable?(@x, @y, 6)
dirs.push(2) if @map[@x, @y+1] == @step && passable?(@x, @y, 2)
dirs.push(4) if @map[@x-1, @y] == @step && passable?(@x, @y, 4)
dirs.push(8) if @map[@x, @y-1] == @step && passable?(@x, @y, 8)
while dirs.size > 0
dir = dirs.delete_at(rand(dirs.size))
move_straight(dir)
break if x != @x || y != @y
end
# clear the path if we couldn't move
clear_path if x == @x && y == @y
end
end
#--------------------------------------------------------------------------
# * Find Path
#--------------------------------------------------------------------------
def find_path(x, y)
sx, sy = @x, @y
@tx, @ty = x, y
result = setup_map(sx, sy)
@runpath = result[0]
@map = result[1]
@map[sx, sy] = result[2] if result[2] != nil
end
#--------------------------------------------------------------------------
# * Clear Path
#--------------------------------------------------------------------------
def clear_path
@map = nil
@runpath = false
end
#--------------------------------------------------------------------------
# * Setup Map
#--------------------------------------------------------------------------
def setup_map(sx, sy)
map = Table.new($game_map.width, $game_map.height)
update_counter = 0
map[@tx, @ty] = 1
old_positions = [[@tx, @ty]]
new_positions = []
# if tile is impassable, but CAN move to adjacent tiles, use the adjacent tiles instead
if (!passable?(@tx, @ty, 2) && !passable?(@tx, @ty, 4) &&
!passable?(@tx, @ty, 6) && !passable?(@tx, @ty, 8)) ||
$game_map.events_xy_nt(@tx, @ty).any? { |evt| evt.normal_priority? && evt != self }
old_positions = []
# Can we move from the destination tile in any direction?
if map_passable?(@tx, @ty, 2)
map[@tx, @ty+1] = 1
old_positions.push([@tx, @ty+1])
end
if map_passable?(@tx, @ty, 8)
map[@tx, @ty-1] = 1
old_positions.push([@tx, @ty-1])
end
if map_passable?(@tx, @ty, 4)
map[@tx-1, @ty] = 1
old_positions.push([@tx-1, @ty])
end
if map_passable?(@tx, @ty, 6)
map[@tx+1, @ty] = 1
old_positions.push([@tx+1, @ty])
end
# If not, can we at least move up to the destination tile?
if old_positions.size == 0
if map_passable?(@tx-1,@ty,6)
map[@tx-1,@ty] = 1
old_positions.push([@tx-1,@ty])
end
if map_passable?(@tx+1,@ty,4)
map[@tx+1,@ty] = 1
old_positions.push([@tx+1,@ty])
end
if map_passable?(@tx,@ty-1,2)
map[@tx,@ty-1] = 1
old_positions.push([@tx,@ty-1])
end
if map_passable?(@tx,@ty+1,8)
map[@tx,@ty+1] = 1
old_positions.push([@tx,@ty+1])
end
end
end
# If there are any counters, can we move to the tile on the other side?
if map_passable?(@tx-2,@ty,6) && $game_map.counter?(@tx-1,@ty)
map[@tx-2,@ty] = 1
old_positions.push([@tx-2,@ty])
end
if map_passable?(@tx+2,@ty,4) && $game_map.counter?(@tx+1,@ty)
map[@tx+2,@ty] = 1
old_positions.push([@tx+2,@ty])
end
if map_passable?(@tx,@ty-2,2) && $game_map.counter?(@tx,@ty-1)
map[@tx,@ty-2] = 1
old_positions.push([@tx,@ty-2])
end
if map_passable?(@tx,@ty+2,2) && $game_map.counter?(@tx,@ty+1)
map[@tx,@ty+2] = 1
old_positions.push([@tx,@ty+2])
end
depth = 2
depth.upto(100) { |step|
break if old_positions[0].nil?
@step = step
loop do
break if old_positions[0].nil?
x, y = old_positions.shift
return [true, map, @step-1] if x == sx && y == sy
if map[x, y + 1] == 0 && passable?(x, y, 2)
map[x, y + 1] = @step
new_positions.push([x, y + 1])
end
if map[x - 1, y] == 0 && passable?(x, y, 4)
map[x - 1, y] = @step
new_positions.push([x - 1, y])
end
if map[x + 1, y] == 0 && passable?(x, y, 6)
map[x + 1, y] = @step
new_positions.push([x + 1, y])
end
if map[x, y - 1] == 0 && passable?(x, y, 8)
map[x, y - 1] = @step
new_positions.push([x, y - 1])
end
# Update graphics? (to reduce lag)
update_counter += 1
if update_counter > 50
Graphics.update
update_counter = 0
end
end
old_positions = new_positions
new_positions = []
}
return [false, nil, nil]
end
end
class Game_Character < Game_CharacterBase
#--------------------------------------------------------------------------
# * Force Move Route
#--------------------------------------------------------------------------
alias shaz_mouse_game_character_force_move_route force_move_route
def force_move_route(move_route)
clear_path
shaz_mouse_game_character_force_move_route(move_route)
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Player
#============================================================================
class Game_Player < Game_Character
#--------------------------------------------------------------------------
# * Trigger Map Event
# triggers : Trigger array
# normal : Is priority set to [same as Characters] ?
#--------------------------------------------------------------------------
alias shaz_mouse_game_player_start_map_event start_map_event
def start_map_event(x, y, triggers, normal)
@started_events = []
shaz_mouse_game_player_start_map_event(x, y, triggers, normal)
end
#--------------------------------------------------------------------------
# * Start Event
#--------------------------------------------------------------------------
def start_event(event_id)
@started_events = [] if @started_events.nil?
@started_events.push(event_id)
end
#--------------------------------------------------------------------------
# * Processing of Movement via Input from Directional Buttons
#--------------------------------------------------------------------------
alias shaz_mouse_game_player_move_by_input move_by_input
def move_by_input
if Input.dir4 > 0
clear_path
shaz_mouse_game_player_move_by_input
else
# Move by mouse input
if !$game_message.busy? && !$game_message.visible && !@move_route_forcing &&
!@vehicle_getting_on && !@vehicle_getting_off &&
Mouse.trigger?(0) && !Mouse.grid.nil? && !$mouse.ignored?
mx, my = *Mouse.grid
# turn in direction
if (@x - mx).abs >= (@y - my).abs
set_direction(@x > mx ? 4 : 6)
else
set_direction(@y > my ? 8 : 2)
end
# find path
@event = $game_map.lowest_mouse_event_xy(mx, my)
if @event.nil?
find_path(mx, my)
elsif @event.mouse_autoactivate
@event.start
@started_events = []
clear_path
else
find_path(@event.x + @event.mouse_position[0],
@event.y + @event.mouse_position[1])
end
end
end
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
alias shaz_mouse_game_player_update update
def update
shaz_mouse_game_player_update
update_pathfinding if !@event.nil? && !moving?
end
#--------------------------------------------------------------------------
# * Check event after pathfinding
#--------------------------------------------------------------------------
def update_pathfinding
if @map.nil? || @map[@x, @y] <= 1
dir = @x < @event.x ? 6 : @x > @event.x ? 4 : @y < @event.y ? 2 : @y > @event.y ? 8 : 0
# Face event and trigger it (only if not triggered by start_map_event)
turn_toward_character(@event) if !@event.pos?(@x, @y)
if !@started_events.include?(@event.id) && !@map.nil? && !in_airship?
@event.start
@started_events = []
end
clear_path
end
end
#--------------------------------------------------------------------------
# * Clear Path
#--------------------------------------------------------------------------
def clear_path
@event = nil
super
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Interpreter
#============================================================================
class Game_Interpreter
#--------------------------------------------------------------------------
# * Event Setup
#--------------------------------------------------------------------------
alias shaz_mouse_game_interpreter_setup setup
def setup(list, event_id = 0, lock_player = false)
shaz_mouse_game_interpreter_setup(list, event_id)
@lock_player = lock_player
end
#--------------------------------------------------------------------------
# * Execute
#--------------------------------------------------------------------------
alias shaz_mouse_game_interpreter_run run
def run
$mouse.ignored = true if @lock_player
shaz_mouse_game_interpreter_run
$mouse.ignored = false if @lock_player
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Windows
#============================================================================
class Window_Selectable < Window_Base
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
alias shaz_mouse_window_selectable_update update
def update
shaz_mouse_window_selectable_update
process_mouse_handling if Input.method == :mouse
end
#--------------------------------------------------------------------------
# * Mouse Movement Processing
#--------------------------------------------------------------------------
def process_mouse_handling
return unless $mouse.enabled? && cursor_movable?
# Add a delay to prevent too-fast scrolling
@delay = @delay ? @delay + 1 : 0
return if @delay % 3 > 0
mx, my = *Mouse.position
vx = self.viewport ? self.x - self.viewport.ox + self.viewport.rect.x : self.x
vy = self.viewport ? self.y - self.viewport.oy + self.viewport.rect.y : self.y
if mx.between?(vx, vx + self.width) &&
my.between?(vy, vy + self.height)
mx -= vx
mx -= padding
my -= vy
my -= padding
my += oy
for i in 0 ... item_max
rect = item_rect(i)
if mx.between?(rect.x, rect.x + rect.width) &&
my.between?(rect.y, rect.y + rect.height)
last_index = @index
select(i)
if @index != last_index
Sound.play_cursor
end
break
end
end
end
end
end
class Window_NameInput < Window_Selectable
#--------------------------------------------------------------------------
# * Mouse Movement Processing
#--------------------------------------------------------------------------
def process_mouse_handling
return unless $mouse.enabled?
# Add a delay to prevent too-fast scrolling
@delay = @delay ? @delay + 1 : 0
return if @delay % 3 > 0
mx, my = *Mouse.position
vx = (self.viewport ? self.x - self.viewport.ox + self.viewport.rect.x : self.x) + padding
vy = (self.viewport ? self.y - self.viewport.oy + self.viewport.rect.y : self.y) + padding
if mx.between?(vx, vx + self.width - padding * 2) &&
my.between?(vy, vy + self.height - padding * 2)
mx -= vx
my -= vy
x = (mx > 5*32+16 ? mx-16 : mx) / 32
y = my / line_height
last_index = @index
@index = y * 10 + x
Sound.play_cursor if @index != last_index
end
end
end
class Scene_File < Scene_MenuBase
#--------------------------------------------------------------------------
# * Update Cursor
#--------------------------------------------------------------------------
alias shaz_mouse_scene_file_update_cursor update_cursor
def update_cursor
shaz_mouse_scene_file_update_cursor
process_mouse_handling if Input.method == :mouse
end
#--------------------------------------------------------------------------
# * Mouse Movement Processing
#--------------------------------------------------------------------------
def process_mouse_handling
return unless $mouse.enabled?
# Add a delay to prevent too-fast scrolling
@delay = @delay ? @delay + 1 : 0
return if @delay % 3 > 0
mx, my = *Mouse.position
vx = @savefile_viewport.ox + mx
vy = @savefile_viewport.oy + my
last_index = @index
new_index = vy / savefile_height
if @index != new_index
if new_index > @index
cursor_down(false)
else
cursor_up(false)
end
Sound.play_cursor
@savefile_windows[last_index].selected = false
@savefile_windows[@index].selected = true
end
end
end
# SUPER SIMPLE MOUSE SCRIPT
# v1.10 by Shaz
#----------------------------------------------------------------------------
# This is a conversion of the XP Mouse script by Near Fantastica and
# SephirothSpawn modified by Amaranth Games, to run under VX Ace.
#----------------------------------------------------------------------------
# To Install:
# Copy and paste into a new slot in materials, below all other scripts
#----------------------------------------------------------------------------
# To Customize:
# Add keyword icon index pairs to the ICON hash (below this documentation).
# Each of the keywords can be used in an event comment to make the mouse
# cursor change into that icon when hovering over the event.
#----------------------------------------------------------------------------
# To Use:
# Add the following comment to an event page:
#
# where icon is the keyword from the ICON hash below
# x and y are the offsets to override player movement (optional)
# name is the text to display next to the icon when hovering over the event (optional)
#
# Examples:
#
# will change the cursor into the 'fight' icon when over the event
#
# will change the cursor into the 'touch' icon when over the event, and
# make the player walk to the tile below the event when the mouse button is
# clicked
#
# will change the cursor into the 'talk' icon and display the name Gloria
#
# will change the cursor into the 'talk' icon and display the name Henry Smith,
# and when the mouse button is clicked, the player will walk to the tile
# two below the event (good to use for shops where there's a counter in between)
#
# To force pathfinding on the player or an event, simply add a move route with
# the player or event as the subject, with a Script command, and call
# find_path(x, y) where x and y are the coordinates of the tile you want to move to
# Examples:
# Set Move Route (Player): Script: find_path(5, 8)
# will make the player find a path to tile 5, 8
# Set Move Route (This Event): Script: find_path(10, 5)
# will make the event find a path to tile 10, 5
#
# NOTE: The path will be ATTEMPTED. If there is no path TO that exact tile,
# a path to an adjacent tile will be attempted. If no path is found there
# either, no movement will occur.
# If a route is found, the player or event will begin moving towards it. But
# if their path is blocked while they are moving, movement will be cancelled.
#----------------------------------------------------------------------------
# Author's Notes:
# This script should work with any RTP script.
# I do not guarantee that it will work with ANY other script (especially anything
# that overrides player or event movement, such as pixel movement scripts, or
# custom window scripts).
#
# Script OVERWRITES the following methods:
# Game_Map.setup_starting_map_event
# Game_Map.setup_autorun_common_event
#
# If you have other scripts that ALIAS these methods, this mouse script should
# be placed above them.
#----------------------------------------------------------------------------
# Terms:
# Use in free and commercial games
# Credit: Near Fantastica, SephirothSpawn, Amaranth Games, Shaz
#----------------------------------------------------------------------------
# Versions:
# 1.0 - 6 Sept 2013 - initial release
# 1.02 - 7 Sept 2013 - fixed crash when loading games saved prior to adding script
# - fixed player gets stuck on impassable area on world map
# when clicking while leaving air ship
# 1.03 - 8 Sept 2013 - fixed actor moving to diagonal tile instead of adjacent
# 1.04 - 10 Sept 2013 - fixed vehicle pathfinding on world map
# - fixed event trigger when no path found
# 1.05 - 14 Sept 2013 - tweaked accessing of tilemap offset
# 1.06 - 3 Nov 2013 - disabled mouse movement when waiting for NPC move route
# - fixed events not triggering after player finishes walking
# 1.07 - 6 Nov 2013 - slow down mouse scrolling, and don't loop save files
# 1.08 - 24 Nov 2013 - cater for YEA Core large resolution with too-small maps
# - fixed early event activation bug introduced in 1.06
# - replaced calc of Windows_Selectable boundaries with item_rect
# - added ability to completely disable mouse
# 1.09 - 21 Dec 2013 - fixed mouse re-enable when calling common events
# 1.10 - 6 Apr 2014 - add interaction for top part of > 32pixel high event
# - activate an event without walking up to it
# (add comment at top of event page)
# - arrow keys override mouse movement when pathfinding
# - ignore mouse in menus when using keyboard
# - make player walk to counter opposite shopkeepers
#============================================================================
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Mouse Sprite
#============================================================================
# Add/remove/change icon names here. The icon name is what will be used in the
# event command to show a different mouse icon when hovering over
# the event. These MUST be in lower case here!
ICON = {'arrow' => 386, 'talk' => 4, 'look' => 3, 'fight' => 116,
'touch' => 491, 'exit' => 121}
DEFAULT_ICON = 'arrow'
class Sprite_Mouse < Sprite
#--------------------------------------------------------------------------
# * Initialization
#--------------------------------------------------------------------------
def initialize
super
self.z = 10100
self.ox = 4
update
@dummy = Bitmap.new(32, 32)
self.bitmap = Bitmap.new(32, 32)
@enabled = true
@ignored = false
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
return if !@enabled
super
if !SceneManager.scene.nil?
if !Mouse.position.nil?
mx, my = *Mouse.position
if @cursor == DEFAULT_ICON
self.x = mx unless mx.nil?
else
self.x = [mx, Graphics.width - self.bitmap.width].min unless mx.nil?
end
self.y = my unless my.nil?
end
if @scene != SceneManager.scene.class || Mouse.trigger?
@scene = SceneManager.scene.class
set_bitmap
end
end
end
#--------------------------------------------------------------------------
# * Set Bitmap
#--------------------------------------------------------------------------
def set_bitmap(cursor = DEFAULT_ICON, text = nil)
if @ignored
cursor = DEFAULT_ICON
text = nil
end
if @cursor != cursor || @text != text
@cursor = cursor
@text = text
item_cursor = ICON[cursor]
rect = Rect.new(item_cursor % 16 * 24, item_cursor / 16 * 24, 24, 24)
if @text.nil?
self.bitmap = Bitmap.new(24, 32)
self.bitmap.blt(0, 0, Cache.system('Iconset'), rect)
else
w = @dummy.text_size(@text).width
h = @dummy.font.size
bitmap = Bitmap.new(26 + w, [32, h+2].max)
bitmap.font.size = @dummy.font.size
bitmap.font.shadow = true
if self.x + 26 + w > Graphics.width
bitmap.draw_text(0, 0, w, h, @text)
bitmap.blt(w, 0, Cache.system('Iconset'), rect)
else
bitmap.blt(0, 0, Cache.system('Iconset'), rect)
bitmap.draw_text(26, 0, w, h, @text)
end
self.bitmap = bitmap
end
end
end
#--------------------------------------------------------------------------
# * Update Event Cursors
#--------------------------------------------------------------------------
def update_event_cursors
# Remove mouse icon and text if we're off the grid
if Mouse.grid.nil?
set_bitmap
return
end
# Set cursor and text according to event
x, y = *Mouse.grid
event = $game_map.lowest_mouse_event_xy(x, y)
unless event.nil? && y < 410
if !event.mouse_icon.nil? || !event.mouse_text.nil?
set_bitmap(event.mouse_icon, event.mouse_text)
return
end
end
# default bitmap if not over an event
set_bitmap
end
#--------------------------------------------------------------------------
# * Enable Mouse
#--------------------------------------------------------------------------
def enabled=(value)
@enabled = value
self.visible = value
end
#--------------------------------------------------------------------------
# * Mouse Enabled?
#--------------------------------------------------------------------------
def enabled?
@enabled
end
#--------------------------------------------------------------------------
# * Ignore Mouse
#--------------------------------------------------------------------------
def ignored=(value)
@ignored = value
end
#--------------------------------------------------------------------------
# * Mouse Ignored?
#--------------------------------------------------------------------------
def ignored?
@ignored
end
end
$mouse = Sprite_Mouse.new
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Mouse Module
#============================================================================
#==============================================================================
# ** Mouse Module
#------------------------------------------------------------------------------
# by Near Fantastica and SephirothSpawn
# adapted and converted to VX Ace by Shaz
#==============================================================================
module Mouse
#--------------------------------------------------------------------------
# * Mouse to Input Triggers
# key => Input::KeyCONSTANT (key: 0 - left, 1 - middle, 2 - right)
#--------------------------------------------------------------------------
Mouse_to_Input_Triggers = {0 => Input::C, 1 => Input::B, 2 => Input::A}
#--------------------------------------------------------------------------
# * API Declarations
#--------------------------------------------------------------------------
GAKS = Win32API.new('user32', 'GetAsyncKeyState', 'i', 'i')
GSM = Win32API.new('user32', 'GetSystemMetrics', 'i', 'i')
Cursor_Pos = Win32API.new('user32', 'GetCursorPos', 'p', 'i')
Scr2cli = Win32API.new('user32', 'ScreenToClient', %w(l p), 'i')
Client_rect = Win32API.new('user32', 'GetClientRect', %w(l p), 'i')
Findwindow = Win32API.new('user32', 'FindWindowA', %w(p p), 'l')
Readini = Win32API.new('kernel32', 'GetPrivateProfileStringA', %w(p p p p l p), 'l')
ShowCursor = Win32API.new('user32', 'ShowCursor', 'i', 'l')
#--------------------------------------------------------------------------
# * Module Variables
#--------------------------------------------------------------------------
@triggers = [[0, 1], [0, 2], [0, 4]]
@old_pos = 0
@pos_i = 0
@sys_cursor_visible = false
#--------------------------------------------------------------------------
# * Mouse Grid Position
#--------------------------------------------------------------------------
def self.grid
return nil if @pos.nil?
mx, my = SceneManager.scene.instance_variable_get:)@spriteset).tilemap_offset
x = (@pos[0] + mx) / 32
y = (@pos[1] + my) / 32
return [x, y]
end
#--------------------------------------------------------------------------
# * Mouse Position
#--------------------------------------------------------------------------
def self.position
return @pos.nil? ? [0, 0] : @pos
end
#--------------------------------------------------------------------------
# * Mouse Global Position
#--------------------------------------------------------------------------
def self.global_pos
pos = [0, 0].pack('ll')
return Cursor_Pos.call(pos) == 0 ? nil : pos.unpack('ll')
end
#--------------------------------------------------------------------------
# * Screen to Client
#--------------------------------------------------------------------------
def self.screen_to_client(x=0, y=0)
pos = [x, y].pack('ll')
return Scr2cli.call(self.hwnd, pos) == 0 ? nil : pos.unpack('ll')
end
#--------------------------------------------------------------------------
# * Mouse Position
#--------------------------------------------------------------------------
def self.pos
gx, gy = global_pos
x, y = screen_to_client(gx, gy)
# Test boundaries
begin
if (x >= 0 && y >= 0 && x <= Graphics.width && y <= Graphics.height)
return x, y
else
return -20, -20
end
rescue
return 0, 0
end
end
#--------------------------------------------------------------------------
# * Update Mouse Position
#--------------------------------------------------------------------------
def self.update
old_pos = @pos
@pos = self.pos
# Has mouse been moved?
if old_pos != @pos
Input.method = :mouse
end
# Which mouse to show - custom, or system?
if $mouse.enabled? == @sys_cursor_visible
@sys_cursor_visible = !@sys_cursor_visible
ShowCursor.call(@sys_cursor_visible ? 1 : 0)
end
return if !$mouse.enabled?
# Leaving / Entering Range?
if old_pos != [-20, -20] && @pos == [-20, -20] # leaving range
ShowCursor.call(1)
elsif old_pos == [-20, -20] && @pos != [-20, -20] # entering range
ShowCursor.call(0)
end
# Update Triggers
for i in @triggers
n = GAKS.call(i[1])
if [0, 1].include?(n)
i[0] = (i[0] > 0 ? i[0] * -1 : 0)
else
i[0] = (i[0] > 0 ? i[0] + 1 : 1)
end
end
end
#--------------------------------------------------------------------------
# * Trigger?
# id : 0:Left, 1:Right, 2:Center
#--------------------------------------------------------------------------
def self.trigger?(id = 0)
if pos != [-20, -20]
return @triggers[id][0] == 1
end
return false
end
#--------------------------------------------------------------------------
# * Repeat?
# id : 0:Left, 1:Right, 2:Center
#--------------------------------------------------------------------------
def self.repeat?(id = 0)
return @triggers[id][0] > 0 && @triggers[id][0] % 5 == 1
end
#--------------------------------------------------------------------------
# * Hwnd
#--------------------------------------------------------------------------
def self.hwnd
if @hwnd.nil?
title = "\0" * 256
Readini.call('Game', 'Title', '', title, 255, '.\\Game.ini')
title.delete!("\0")
@hwnd = Findwindow.call('RGSS Player', title)
ShowCursor.call(0)
end
return @hwnd
end
#--------------------------------------------------------------------------
# * Client Size
#--------------------------------------------------------------------------
def self.client_size
rect = [0, 0, 0, 0].pack('l4')
Client_rect.call(self.hwnd, rect)
return rect.unpack('l4')[2..3]
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Input
#============================================================================
class << Input
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :method
#--------------------------------------------------------------------------
# * Alias Listings
#--------------------------------------------------------------------------
alias :seph_mouse_input_update :update
alias :seph_mouse_input_trigger? :trigger?
alias :seph_mouse_input_repeat? :repeat?
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
$mouse.update
Mouse.update
seph_mouse_input_update
# Are we using the mouse or the keyboard?
@method = :keyboard if dir4 != 0 || dir8 != 0
end
#--------------------------------------------------------------------------
# * Trigger? Test
#--------------------------------------------------------------------------
def trigger?(constant)
return true if seph_mouse_input_trigger?(constant)
if $mouse.enabled? && !Mouse.pos.nil?
if Mouse::Mouse_to_Input_Triggers.has_value?(constant)
return true if Mouse.trigger?(Mouse::Mouse_to_Input_Triggers.index(constant))
end
end
return false
end
#--------------------------------------------------------------------------
# * Repeat? Test
#--------------------------------------------------------------------------
def repeat?(constant)
return true if seph_mouse_input_repeat?(constant)
if $mouse.enabled? && !Mouse.pos.nil?
if Mouse::Mouse_to_Input_Triggers.has_value?(constant)
return true if Mouse.repeat?(Mouse::Mouse_to_Input_Triggers.index(constant))
end
end
return false
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Map
#============================================================================
class Spriteset_Map
#--------------------------------------------------------------------------
# * Tilemap Offset
#--------------------------------------------------------------------------
def tilemap_offset
if $imported && $imported["YEA-CoreEngine"]
[@tilemap.ox - @viewport1.rect.x, @tilemap.oy - @viewport1.rect.y]
else
[@tilemap.ox, @tilemap.oy]
end
end
end
class Game_Map
#--------------------------------------------------------------------------
# * Detect/Set Up Starting Map Event
#--------------------------------------------------------------------------
def setup_starting_map_event
event = @events.values.find {|event| event.starting }
event.clear_starting_flag if event
@interpreter.setup(event.list, event.id, event.trigger_in?([0,1,2,3])) if event
event
end
#--------------------------------------------------------------------------
# * Detect/Set Up Autorun Common Event
#--------------------------------------------------------------------------
def setup_autorun_common_event
event = $data_common_events.find do |event|
event && event.autorun? && $game_switches[event.switch_id]
end
@interpreter.setup(event.list, 0, true) if event
event
end
#--------------------------------------------------------------------------
# * Get ID of Lowest Mouse-enabled Event at Designated Coordinates
#--------------------------------------------------------------------------
def lowest_mouse_event_xy(x, y)
list = events_xy(x, y) + events_xy(x, y+1)
list.sort! {|a, b| b.y - a.y}
evt = nil
list.each do |event|
if (event.pos?(x, y) || (event.pos?(x, y+1) && event.height > 32)) &&
(evt.nil? || event.y > evt.y)
evt = event
break
end
end
return evt
end
end
class Scene_Map
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
alias shaz_mouse_scene_map_update update
def update
$mouse.update_event_cursors
shaz_mouse_scene_map_update
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Event
#============================================================================
module RPG
class Event
class Page
#--------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------
attr_reader :mouse_icon
attr_reader :mouse_text
attr_reader :mouse_position
attr_reader :mouse_autoactivate
#--------------------------------------------------------------------
# * Build Stats
#--------------------------------------------------------------------
def build_stats
# Mouse icons (icon mandatory, others optional)
#
@mouse_icon = nil
@mouse_text = nil
@mouse_position = [0, 0]
@mouse_autoactivate = false
# look for mouse instructions
list.each do |command|
if [108, 408].include?(command.code)
comment = command.parameters[0]
case comment
when / params = //i.match(comment)[1].split(' ')
@mouse_icon = params.shift
if params.size > 1 && params[0] =~ /\d+/ && params[1] =~ /\d+/
@mouse_position = [params.shift.to_i, params.shift.to_i]
end
if params.size > 0
@mouse_text = params.join(' ')
end
when //
@mouse_autoactivate = true
end
end #if
end #do
end #def
end
end
end
class Game_Event < Game_Character
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_reader :mouse_icon
attr_reader :mouse_text
attr_reader :mouse_position
attr_reader :mouse_autoactivate
#--------------------------------------------------------------------------
# * Start Event
#--------------------------------------------------------------------------
alias shaz_mouse_game_event_start start
def start
$game_player.start_event(@id) if !empty?
shaz_mouse_game_event_start
end
#--------------------------------------------------------------------------
# * Clear Event Page Settings
#--------------------------------------------------------------------------
alias shaz_mouse_game_event_clear_page_settings clear_page_settings
def clear_page_settings
shaz_mouse_game_event_clear_page_settings
@mouse_icon = nil
@mouse_text = nil
@mouse_position = [0, 0]
@mouse_autoactivate = false
@height = 0
end
#--------------------------------------------------------------------------
# * Set Up Event Page Settings
#--------------------------------------------------------------------------
alias shaz_mouse_game_event_setup_page_settings setup_page_settings
def setup_page_settings
shaz_mouse_game_event_setup_page_settings
@page.build_stats
@mouse_icon = @page.mouse_icon
@mouse_text = @page.mouse_text
@mouse_position = @page.mouse_position
@mouse_autoactivate = @page.mouse_autoactivate
set_size
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Character
#============================================================================
class Game_CharacterBase
attr_reader :height # Height of character bitmap
#--------------------------------------------------------------------------
# * Initialize Public Member Variables
#--------------------------------------------------------------------------
alias shaz_mouse_game_characterbase_init_public_members init_public_members
def init_public_members
shaz_mouse_game_characterbase_init_public_members
@height = 0
end
#--------------------------------------------------------------------------
# * Change Graphics
# character_name : new character graphic filename
# character_index : new character graphic index
#--------------------------------------------------------------------------
alias shaz_mouse_game_characterbase_set_graphic set_graphic
def set_graphic(character_name, character_index)
shaz_mouse_game_characterbase_set_graphic(character_name, character_index)
set_size
end
#--------------------------------------------------------------------------
# * Set character width/height size
#--------------------------------------------------------------------------
def set_size
bw = Cache.character(@character_name).width
bh = Cache.character(@character_name).height
sign = @character_name[/^[\!\$]./]
if sign && sign.include?('$')
@width = bw / 3
@height = bh / 4
else
@width = bw / 12
@height = bh / 8
end
end
#--------------------------------------------------------------------------
# * Detect Collision with Event
#--------------------------------------------------------------------------
def collide_with_events?(x, y)
$game_map.events_xy_nt(x, y).any? do |event|
self != event && (event.normal_priority? || self.is_a?(Game_Event))
end
end
#--------------------------------------------------------------------------
# * Detect Collision with Vehicle
#--------------------------------------------------------------------------
def collide_with_vehicles?(x, y)
!self.is_a?(Game_Player) && ($game_map.boat.pos_nt?(x, y) || $game_map.ship.pos_nt?(x, y))
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
alias shaz_mouse_game_characterbase_update update
def update
run_path if @runpath
shaz_mouse_game_characterbase_update
end
#--------------------------------------------------------------------------
# * Run Path
#--------------------------------------------------------------------------
def run_path
return if moving?
@step = @map.nil? || @map[@x, @y].nil? ? 0 : @map[@x, @y] - 1
if @step < 1
clear_path
else
x, y = @x, @y
dirs = []
dirs.push(6) if @map[@x+1, @y] == @step && passable?(@x, @y, 6)
dirs.push(2) if @map[@x, @y+1] == @step && passable?(@x, @y, 2)
dirs.push(4) if @map[@x-1, @y] == @step && passable?(@x, @y, 4)
dirs.push(8) if @map[@x, @y-1] == @step && passable?(@x, @y, 8)
while dirs.size > 0
dir = dirs.delete_at(rand(dirs.size))
move_straight(dir)
break if x != @x || y != @y
end
# clear the path if we couldn't move
clear_path if x == @x && y == @y
end
end
#--------------------------------------------------------------------------
# * Find Path
#--------------------------------------------------------------------------
def find_path(x, y)
sx, sy = @x, @y
@tx, @ty = x, y
result = setup_map(sx, sy)
@runpath = result[0]
@map = result[1]
@map[sx, sy] = result[2] if result[2] != nil
end
#--------------------------------------------------------------------------
# * Clear Path
#--------------------------------------------------------------------------
def clear_path
@map = nil
@runpath = false
end
#--------------------------------------------------------------------------
# * Setup Map
#--------------------------------------------------------------------------
def setup_map(sx, sy)
map = Table.new($game_map.width, $game_map.height)
update_counter = 0
map[@tx, @ty] = 1
old_positions = [[@tx, @ty]]
new_positions = []
# if tile is impassable, but CAN move to adjacent tiles, use the adjacent tiles instead
if (!passable?(@tx, @ty, 2) && !passable?(@tx, @ty, 4) &&
!passable?(@tx, @ty, 6) && !passable?(@tx, @ty, 8)) ||
$game_map.events_xy_nt(@tx, @ty).any? { |evt| evt.normal_priority? && evt != self }
old_positions = []
# Can we move from the destination tile in any direction?
if map_passable?(@tx, @ty, 2)
map[@tx, @ty+1] = 1
old_positions.push([@tx, @ty+1])
end
if map_passable?(@tx, @ty, 8)
map[@tx, @ty-1] = 1
old_positions.push([@tx, @ty-1])
end
if map_passable?(@tx, @ty, 4)
map[@tx-1, @ty] = 1
old_positions.push([@tx-1, @ty])
end
if map_passable?(@tx, @ty, 6)
map[@tx+1, @ty] = 1
old_positions.push([@tx+1, @ty])
end
# If not, can we at least move up to the destination tile?
if old_positions.size == 0
if map_passable?(@tx-1,@ty,6)
map[@tx-1,@ty] = 1
old_positions.push([@tx-1,@ty])
end
if map_passable?(@tx+1,@ty,4)
map[@tx+1,@ty] = 1
old_positions.push([@tx+1,@ty])
end
if map_passable?(@tx,@ty-1,2)
map[@tx,@ty-1] = 1
old_positions.push([@tx,@ty-1])
end
if map_passable?(@tx,@ty+1,8)
map[@tx,@ty+1] = 1
old_positions.push([@tx,@ty+1])
end
end
end
# If there are any counters, can we move to the tile on the other side?
if map_passable?(@tx-2,@ty,6) && $game_map.counter?(@tx-1,@ty)
map[@tx-2,@ty] = 1
old_positions.push([@tx-2,@ty])
end
if map_passable?(@tx+2,@ty,4) && $game_map.counter?(@tx+1,@ty)
map[@tx+2,@ty] = 1
old_positions.push([@tx+2,@ty])
end
if map_passable?(@tx,@ty-2,2) && $game_map.counter?(@tx,@ty-1)
map[@tx,@ty-2] = 1
old_positions.push([@tx,@ty-2])
end
if map_passable?(@tx,@ty+2,2) && $game_map.counter?(@tx,@ty+1)
map[@tx,@ty+2] = 1
old_positions.push([@tx,@ty+2])
end
depth = 2
depth.upto(100) { |step|
break if old_positions[0].nil?
@step = step
loop do
break if old_positions[0].nil?
x, y = old_positions.shift
return [true, map, @step-1] if x == sx && y == sy
if map[x, y + 1] == 0 && passable?(x, y, 2)
map[x, y + 1] = @step
new_positions.push([x, y + 1])
end
if map[x - 1, y] == 0 && passable?(x, y, 4)
map[x - 1, y] = @step
new_positions.push([x - 1, y])
end
if map[x + 1, y] == 0 && passable?(x, y, 6)
map[x + 1, y] = @step
new_positions.push([x + 1, y])
end
if map[x, y - 1] == 0 && passable?(x, y, 8)
map[x, y - 1] = @step
new_positions.push([x, y - 1])
end
# Update graphics? (to reduce lag)
update_counter += 1
if update_counter > 50
Graphics.update
update_counter = 0
end
end
old_positions = new_positions
new_positions = []
}
return [false, nil, nil]
end
end
class Game_Character < Game_CharacterBase
#--------------------------------------------------------------------------
# * Force Move Route
#--------------------------------------------------------------------------
alias shaz_mouse_game_character_force_move_route force_move_route
def force_move_route(move_route)
clear_path
shaz_mouse_game_character_force_move_route(move_route)
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Player
#============================================================================
class Game_Player < Game_Character
#--------------------------------------------------------------------------
# * Trigger Map Event
# triggers : Trigger array
# normal : Is priority set to [same as Characters] ?
#--------------------------------------------------------------------------
alias shaz_mouse_game_player_start_map_event start_map_event
def start_map_event(x, y, triggers, normal)
@started_events = []
shaz_mouse_game_player_start_map_event(x, y, triggers, normal)
end
#--------------------------------------------------------------------------
# * Start Event
#--------------------------------------------------------------------------
def start_event(event_id)
@started_events = [] if @started_events.nil?
@started_events.push(event_id)
end
#--------------------------------------------------------------------------
# * Processing of Movement via Input from Directional Buttons
#--------------------------------------------------------------------------
alias shaz_mouse_game_player_move_by_input move_by_input
def move_by_input
if Input.dir4 > 0
clear_path
shaz_mouse_game_player_move_by_input
else
# Move by mouse input
if !$game_message.busy? && !$game_message.visible && !@move_route_forcing &&
!@vehicle_getting_on && !@vehicle_getting_off &&
Mouse.trigger?(0) && !Mouse.grid.nil? && !$mouse.ignored?
mx, my = *Mouse.grid
# turn in direction
if (@x - mx).abs >= (@y - my).abs
set_direction(@x > mx ? 4 : 6)
else
set_direction(@y > my ? 8 : 2)
end
# find path
@event = $game_map.lowest_mouse_event_xy(mx, my)
if @event.nil?
find_path(mx, my)
elsif @event.mouse_autoactivate
@event.start
@started_events = []
clear_path
else
find_path(@event.x + @event.mouse_position[0],
@event.y + @event.mouse_position[1])
end
end
end
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
alias shaz_mouse_game_player_update update
def update
shaz_mouse_game_player_update
update_pathfinding if !@event.nil? && !moving?
end
#--------------------------------------------------------------------------
# * Check event after pathfinding
#--------------------------------------------------------------------------
def update_pathfinding
if @map.nil? || @map[@x, @y] <= 1
dir = @x < @event.x ? 6 : @x > @event.x ? 4 : @y < @event.y ? 2 : @y > @event.y ? 8 : 0
# Face event and trigger it (only if not triggered by start_map_event)
turn_toward_character(@event) if !@event.pos?(@x, @y)
if !@started_events.include?(@event.id) && !@map.nil? && !in_airship?
@event.start
@started_events = []
end
clear_path
end
end
#--------------------------------------------------------------------------
# * Clear Path
#--------------------------------------------------------------------------
def clear_path
@event = nil
super
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Interpreter
#============================================================================
class Game_Interpreter
#--------------------------------------------------------------------------
# * Event Setup
#--------------------------------------------------------------------------
alias shaz_mouse_game_interpreter_setup setup
def setup(list, event_id = 0, lock_player = false)
shaz_mouse_game_interpreter_setup(list, event_id)
@lock_player = lock_player
end
#--------------------------------------------------------------------------
# * Execute
#--------------------------------------------------------------------------
alias shaz_mouse_game_interpreter_run run
def run
$mouse.ignored = true if @lock_player
shaz_mouse_game_interpreter_run
$mouse.ignored = false if @lock_player
end
end
#============================================================================
# SUPER SIMPLE MOUSE SCRIPT
# Windows
#============================================================================
class Window_Selectable < Window_Base
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
alias shaz_mouse_window_selectable_update update
def update
shaz_mouse_window_selectable_update
process_mouse_handling if Input.method == :mouse
end
#--------------------------------------------------------------------------
# * Mouse Movement Processing
#--------------------------------------------------------------------------
def process_mouse_handling
return unless $mouse.enabled? && cursor_movable?
# Add a delay to prevent too-fast scrolling
@delay = @delay ? @delay + 1 : 0
return if @delay % 3 > 0
mx, my = *Mouse.position
vx = self.viewport ? self.x - self.viewport.ox + self.viewport.rect.x : self.x
vy = self.viewport ? self.y - self.viewport.oy + self.viewport.rect.y : self.y
if mx.between?(vx, vx + self.width) &&
my.between?(vy, vy + self.height)
mx -= vx
mx -= padding
my -= vy
my -= padding
my += oy
for i in 0 ... item_max
rect = item_rect(i)
if mx.between?(rect.x, rect.x + rect.width) &&
my.between?(rect.y, rect.y + rect.height)
last_index = @index
select(i)
if @index != last_index
Sound.play_cursor
end
break
end
end
end
end
end
class Window_NameInput < Window_Selectable
#--------------------------------------------------------------------------
# * Mouse Movement Processing
#--------------------------------------------------------------------------
def process_mouse_handling
return unless $mouse.enabled?
# Add a delay to prevent too-fast scrolling
@delay = @delay ? @delay + 1 : 0
return if @delay % 3 > 0
mx, my = *Mouse.position
vx = (self.viewport ? self.x - self.viewport.ox + self.viewport.rect.x : self.x) + padding
vy = (self.viewport ? self.y - self.viewport.oy + self.viewport.rect.y : self.y) + padding
if mx.between?(vx, vx + self.width - padding * 2) &&
my.between?(vy, vy + self.height - padding * 2)
mx -= vx
my -= vy
x = (mx > 5*32+16 ? mx-16 : mx) / 32
y = my / line_height
last_index = @index
@index = y * 10 + x
Sound.play_cursor if @index != last_index
end
end
end
class Scene_File < Scene_MenuBase
#--------------------------------------------------------------------------
# * Update Cursor
#--------------------------------------------------------------------------
alias shaz_mouse_scene_file_update_cursor update_cursor
def update_cursor
shaz_mouse_scene_file_update_cursor
process_mouse_handling if Input.method == :mouse
end
#--------------------------------------------------------------------------
# * Mouse Movement Processing
#--------------------------------------------------------------------------
def process_mouse_handling
return unless $mouse.enabled?
# Add a delay to prevent too-fast scrolling
@delay = @delay ? @delay + 1 : 0
return if @delay % 3 > 0
mx, my = *Mouse.position
vx = @savefile_viewport.ox + mx
vy = @savefile_viewport.oy + my
last_index = @index
new_index = vy / savefile_height
if @index != new_index
if new_index > @index
cursor_down(false)
else
cursor_up(false)
end
Sound.play_cursor
@savefile_windows[last_index].selected = false
@savefile_windows[@index].selected = true
end
end
end