Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #==============================================================================
- #
- # GaryCXJk - Free Movement v0.86
- # * Last Updated: 2013.08.02
- # * Level: Medium
- # * Requires: N/A
- # * Optional: CXJ - AnimEx v1.01+
- #
- #==============================================================================
- $imported = {} if $imported.nil?
- $imported["CXJ-FreeMovement"] = true
- #==============================================================================
- #
- # Changelog:
- #
- #------------------------------------------------------------------------------
- # 2013.08.02 - v0.86
- #
- # * Added: Follow types
- # * Fixed: Jumping not going in the right direction
- #
- #------------------------------------------------------------------------------
- # 2013.07.06 - v0.85
- #
- # * Fixed: Touch events get triggered when moving after transfers
- #
- #------------------------------------------------------------------------------
- # 2013.06.09 - v0.84
- #
- # * Added: Capabilities to disable Free Movement per map
- #
- #------------------------------------------------------------------------------
- # 2013.01.12 - v0.83
- #
- # * Added: Option to only let the closest event get triggered
- # * Added: Event comment tags for event collision boxes
- #
- #------------------------------------------------------------------------------
- # 2013.01.12 - v0.82
- #
- # * Added: Map notetags for event collision boxes
- # * Fixed: In case the initializor of Game_CharacterBase gets overridden, the
- # script would fail on a certain check
- #
- #------------------------------------------------------------------------------
- # 2013.01.11 - v0.81
- #
- # * Fixed: Vehicles could be boarded even if not on the map
- #
- #------------------------------------------------------------------------------
- # 2013.01.11 - v0.80
- #
- # * Initial release
- #
- #==============================================================================
- #
- # RPG Maker VX Ace is mainly constrained to the grid. Luckily there are quite
- # some scripts that add off-the-grid movement, mainly called "pixel movement".
- # As that's kind of a BS term for something like that (it implies you can only
- # travel per pixel, and most of the time it skips a few pixels anyway), I just
- # give it a more general term.
- #
- # Free Movement gives you freedom of movement in eight directions. I'd love to
- # implement free movement in three dimensions, but the engine isn't built on
- # 3D. Yet.
- #
- #==============================================================================
- #
- # Installation:
- #
- # Make sure to put this below Materials, but above Main Process.
- #
- # This script overrides several methods. If you are sure no method that is
- # used by other scripts get overridden, you can place it anywhere, otherwise,
- # make sure this script is loaded first. Do know that there is a possibility
- # that this script will stop working due to that.
- #
- # This script adds aliases for several methods. If you are sure no method that
- # is used by other scripts get overridden, you can place it anywhere,
- # otherwise, make sure this script is loaded after any other script overriding
- # these methods, otherwise this script stops working.
- #
- # This script has additional functionality and / or compatibility with other
- # scripts. In order to benefit the most out of it, it is advised to place this
- # script after the others.
- #
- #------------------------------------------------------------------------------
- # Overridden functions:
- #
- # * class Game_Player
- # - move_by_input
- #
- #------------------------------------------------------------------------------
- # Aliased methods:
- #
- # * class Game_Map
- # - setup(map_id)
- # - check_passage(x, y, bit)
- # - refresh setup_events
- # - round_x_with_direction(x, d)
- # - round_y_with_direction(y, d)
- # * class Game_CharacterBase
- # - initialize
- # - update
- # - check_event_trigger_touch_front
- # - passable?(x, y, d)
- # - diagonal_passable?(x, y, horz, vert)
- # - set_direction(d)
- # - move_straight(d, turn_ok = true)
- # - move_diagonal(horz, vert)
- # - collide_with_events?(x, y)
- # - collide_with_vehicles?(x, y)
- # - update_jump
- # - jump_height
- # * class Game_Character
- # - process_move_command(command)
- # - move_random
- # - move_toward_character(character)
- # - move_away_from_character(character)
- # - move_forward
- # - move_backward
- # - jump(x_plus, y_plus)
- # * class Game_Player
- # - initialize
- # - refresh
- # - perform_transfer
- # - make_encounter_count
- # - update_nonmoving(last_moving)
- # - start_map_event(x, y, triggers, normal, rect = collision_rect)
- # - check_event_trigger_there(triggers)
- # - get_on_vehicle
- # - get_off_vehicle
- # - map_passable_rect?(x, y, d, rect)
- # - move_diagonal(horz, vert)
- # - collide_with_vehicles?(x, y)
- # * class Game_Event
- # - init_public_members
- # - update
- # - refresh
- # - collide_with_player_characters?(x, y)
- # - check_event_trigger_touch(x, y)
- # * class Game_Followers
- # - move
- # * class Game_Follower
- # - initialize(member_index, preceding_character)
- # - refresh
- # - chase_preceding_character
- # * class Game_Vehicle
- # - land_ok?(x, y, d)
- # * class Spriteset_Map (When debug is enabled)
- # - create_characters
- # - update_characters
- #
- #==============================================================================
- #
- # Usage:
- #
- # In essence, this script is plug-and-play, however, one can make minor to
- # big tweaks to this script without having to touch the actual script. Most of
- # the settings in the script are self-explanatory, however, there are two
- # things that need explaining.
- #
- # This script uses collision boxes to determine collisions. As not every sprite
- # is of the same size, and even events have different shapes, I wanted to add
- # a way to allow for these differences in size. At the moment there are only
- # collision boxes for characters and events.
- #
- # There are two kinds of collision boxes, the regular collision boxes and the
- # interaction boxes, the latter being reserved for active player characters.
- #
- # Collision boxes are for the regular collisions, like passability on terrain,
- # or just regular touch events. There are four ways you can define a collsion
- # box.
- #
- # The first is using this script, and by either altering the default settings
- # or creating a new collision list. This same collision list is used for the
- # vehicles. To actually be able to use this list, you'll need to call it by
- # using the following notetag on the actor:
- #
- # <collisionbox: string>
- #
- # You can also directly set the collision box on the actor:
- #
- # <collisionbox: x, y, width, height>
- #
- # Finally, since events don't use notetags, you can set the collisions using
- # either a script, notetags placed on the map itself or comment tags on the
- # event itself. For the script method I've added a method to the interpreter,
- # so you can just run it directly from the event without having to find the
- # event itself. There are two ways you can use the method.
- #
- # set_collision_rect(string)
- # set_collision_rect(x, y, width, height)
- #
- # The first way calls the collision box from the collision list. The second
- # directly sets the collision. Do note that collision boxes set this way aren't
- # persistent, so when the map is reloaded, the script must be run again.
- #
- # You can also use notetags on the map to define the collision box of the
- # event. You'll also need to supply the event name so that it can identify
- # which event should get the new collision box.
- #
- # <collisionbox eventname: string>
- # <collisionbox eventname: x, y, width, height>
- #
- # To make it even more easy to implement collision boxes, you can use the
- # following comment tags on the comment blocks in the event itself:
- #
- # <collisionbox: string>
- # <collisionbox: x, y, width, height>
- #
- # You can use this in two ways. When placed on the first page, it acts as the
- # default collision box. This can still be overridden by the map notetag or
- # a script, but it's used as the default. However, when placed on a different
- # page, it will use that comment page whenever that page is available. That
- # means that you can actually use switches or variables to dynamically set
- # the collision box without having to use scripts.
- #
- # There are two ways to set an interaction box. One is by using the interaction
- # list, just like how you set a collision list. Do note that each interaction
- # entry contains eight values, each representing a direction. Note that the
- # collisions are relative to the origin position plus 32 in the direction the
- # interaction box is set, so you don't have to correct for that. To use a
- # certain list, you can use the following notetag on the actor:
- #
- # <interactionbox: string>
- #
- # You can also directly set the collision box on the actor:
- #
- # <interactionbox d: x, y, width, height>
- #
- # Note that d is a number, representing a direction.
- #
- # As it is sometimes hard to see if the collisions work as expected, you can
- # enable debugging, which actually shows the collision boxes. Green boxes
- # represent collision boxes, while the red box represents the interaction box.
- #
- # Finally, there might be reasons to disable this script on certain maps. You
- # can do so by changing the settings for auto-enable to false, or by using the
- # following notetag in the map:
- #
- # <free-movement-enabled true|false>
- #
- # This setting has precedence over the global settings.
- #
- #==============================================================================
- #
- # License:
- #
- # Creative Commons Attribution 3.0 Unported
- #
- # The complete license can be read here:
- # http://creativecommons.org/licenses/by/3.0/legalcode
- #
- # The license as it is described below can be read here:
- # http://creativecommons.org/licenses/by/3.0/deed
- #
- # You are free:
- #
- # to Share — to copy, distribute and transmit the work
- # to Remix — to adapt the work
- # to make commercial use of the work
- #
- # Under the following conditions:
- #
- # Attribution — You must attribute the work in the manner specified by the
- # author or licensor (but not in any way that suggests that they endorse you or
- # your use of the work).
- #
- # With the understanding that:
- #
- # Waiver — Any of the above conditions can be waived if you get permission from
- # the copyright holder.
- #
- # Public Domain — Where the work or any of its elements is in the public domain
- # under applicable law, that status is in no way affected by the license.
- #
- # Other Rights — In no way are any of the following rights affected by the
- # license:
- #
- # * Your fair dealing or fair use rights, or other applicable copyright
- # exceptions and limitations;
- # * The author's moral rights;
- # * Rights other persons may have either in the work itself or in how the work
- # is used, such as publicity or privacy rights.
- #
- # Notice — For any reuse or distribution, you must make clear to others the
- # license terms of this work. The best way to do this is with a link to this
- # web page.
- #
- #------------------------------------------------------------------------------
- # Extra notes:
- #
- # Despite what the license tells you, I will not hunt down anybody who doesn't
- # follow the license in regards to giving credits. However, as it is common
- # courtesy to actually do give credits, it is recommended that you do.
- #
- # As I picked this license, you are free to share this script through any
- # means, which includes hosting it on your own website, selling it on eBay and
- # hang it in the bathroom as toilet paper. Well, not selling it on eBay, that's
- # a dick move, but you are still free to redistribute the work.
- #
- # Yes, this license means that you can use it for both non-commercial as well
- # as commercial software.
- #
- # You are free to pick the following names when you give credit:
- #
- # * GaryCXJk
- # * Gary A.M. Kertopermono
- # * G.A.M. Kertopermono
- # * GARYCXJK
- #
- # Personally, when used in commercial games, I prefer you would use the second
- # option. Not only will it actually give me more name recognition in real
- # life, which also works well for my portfolio, it will also look more
- # professional. Also, do note that I actually care about capitalization if you
- # decide to use my username, meaning, capital C, capital X, capital J, lower
- # case k. Yes, it might seem stupid, but it's one thing I absolutely care
- # about.
- #
- # Finally, if you want my endorsement for your product, if it's good enough
- # and I have the game in my posession, I might endorse it. Do note that if you
- # give me the game for free, it will not affect my opinion of the game. It
- # would be nice, but if I really did care for the game I'd actually purchase
- # it. Remember, the best way to get any satisfaction is if you get people to
- # purchase the game, so in a way, I prefer it if you don't actually give me
- # a free copy.
- #
- # This script was originally hosted on:
- # http://area91.multiverseworks.com
- #
- #==============================================================================
- #
- # The code below defines the settings of this script, and are there to be
- # modified.
- #
- #==============================================================================
- module Euphoria
- module EventCollisionFix
- EVENT_COLL_BOX_X = 8 #X-position of the events collision box, 0 will
- #probably start it at the very left of the event 32
- #will set it on the far right.
- EVENT_COLL_BOX_Y = 8 #Y-position of the events collision box, 0 will
- #probably start it at the very top of the event 32
- #will set it at the bottom.
- EVENT_COLL_BOX_W = 16 #Width of the events collision box, self-explanatory
- EVENT_COLL_BOX_H = 16 #Height of the events collision box, self-explanatory
- end
- end
- module CXJ
- module FREE_MOVEMENT
- # Auto-enable Free Movement
- AUTO_ENABLE = true
- # Enables diagonal movement.
- ENABLE_DIAGONAL = true
- #------------------------------------------------------------------------
- # The collision box for actors and vehicles.
- # The key defines the name of the list. The values themselves represent
- # the x and y of the starting position, and the width and height of the
- # box.
- #------------------------------------------------------------------------
- COLLISION = {}
- COLLISION["DEFAULT"] = [8, 12, 16, 20]
- COLLISION["BOAT"] = [4, 4, 24, 24]
- COLLISION["SHIP"] = [2, 2, 28, 28]
- COLLISION["AIRSHIP"] = [4, 4, 24, 24]
- #------------------------------------------------------------------------
- # The interaction boxes for player characters.
- # The key defines the name of the list. Each list contains eight values,
- # each being separate key-value pairs, where the key is a direction and
- # the values the x and y of the starting position, and the width and
- # height of the box.
- #------------------------------------------------------------------------
- INTERACTION = {}
- INTERACTION["DEFAULT"] = {
- 1 => [24, -8, 24, 24],
- 2 => [4, 0, 24, 24],
- 3 => [-16, -8, 24, 24],
- 4 => [16, 10, 24, 24],
- 6 => [-8, 10, 24, 24],
- 7 => [24, 28, 24, 24],
- 8 => [4, 20, 24, 24],
- 9 => [-16, 28, 24, 24],
- }
- # The amount of pixels per step the character can move.
- PIXELS_PER_STEP = 2
- # The distance between followers.
- FOLLOWERS_DISTANCE = 32
- # The margin between which followers try to correct their distance.
- FOLLOWERS_DISTANCE_MARGIN = 2
- # The speed of the jump animation, in relationship to the original jump
- # speed.
- JUMP_SPEED = 0.5
- # Jump height. Set to 0 to let the jump height be dependent on the jump
- # length. In pixels.
- MAX_JUMP_HEIGHT = 32
- # Determines if only the closest event is triggered.
- ONLY_TRIGGER_CLOSEST = true
- # Allows you to enable or disable follower collision.
- FOLLOWER_THROUGH = false
- # The way followers follow. Set to nil or a non-existent type to make
- # followers use the shortest distance.
- # :trace - Followers always retrace your steps
- FOLLOW_TYPE = :trace
- # Debug variables.
- SHOW_COLLISION_BOXES = false
- end
- end
- #==============================================================================
- #
- # The code below should not be altered unless you know what you're doing.
- #
- #==============================================================================
- #==============================================================================
- # ** Game_Map
- #------------------------------------------------------------------------------
- # This class handles maps. It includes scrolling and passage determination
- # functions. The instance of this class is referenced by $game_map.
- #==============================================================================
- class Game_Map
- #--------------------------------------------------------------------------
- # * Override: Setup
- #--------------------------------------------------------------------------
- alias game_map_setup_fm setup
- def setup(map_id)
- game_map_setup_fm(map_id)
- fm_enabled = 0
- @map.note.split(/[\r\n]+/).each { |line|
- if line =~ /\s*<free[ -]movement[ -]enabled (true|false)>\s*/i
- fm_enabled = ($1 == "true" ? 1 : -1);
- end
- }
- if(fm_enabled == 0)
- @free_movement_enabled = CXJ::FREE_MOVEMENT::AUTO_ENABLE
- else
- @free_movement_enabled = (fm_enabled > 0 ? true : false)
- end
- end
- #--------------------------------------------------------------------------
- # * New: Check if it's the Free Movement map class
- #--------------------------------------------------------------------------
- def free_movement_enabled?
- return @free_movement_enabled
- end
- #--------------------------------------------------------------------------
- # * New: Determine Valid Coordinates
- #--------------------------------------------------------------------------
- def valid_rect?(x, y, rect)
- x2 = x + (rect.x / 32.0)
- y2 = y + (rect.y / 32.0)
- x3 = x2 + ((rect.width - 1) / 32.0)
- y3 = y2 + ((rect.height - 1) / 32.0)
- round_x(x2) >= 0 && round_x(x3) < width && round_y(y2) >= 0 && round_y(y3) < height
- end
- #--------------------------------------------------------------------------
- # * Alias: Check Passage
- # bit: Inhibit passage check bit
- #--------------------------------------------------------------------------
- alias game_map_check_passage_cxj_fm check_passage
- def check_passage(x, y, bit)
- if(free_movement_enabled?)
- x = round_x(x)
- y = round_y(y)
- all_tiles(x.floor, y.floor).each do |tile_id|
- flag = tileset.flags[tile_id]
- next if flag & 0x10 != 0 # [☆]: No effect on passage
- return true if flag & bit == 0 # [○] : Passable
- return false if flag & bit == bit # [×] : Impassable
- end
- return false # Impassable
- else
- return game_map_check_passage_cxj_fm(x, y, bit)
- end
- end
- #--------------------------------------------------------------------------
- # * New: Determine Passability of Normal Character
- # d: direction (2,4,6,8)
- # Determines whether the tile at the specified coordinates is passable
- # in the specified direction.
- #--------------------------------------------------------------------------
- def passable_rect?(x, y, d, rect)
- x2 = x + (rect.x / 32.0)
- y2 = y + (rect.y / 32.0)
- x3 = x2 + ((rect.width - 1) / 32.0)
- y3 = y2 + ((rect.height - 1) / 32.0)
- x4 = (x2 + x3) / 2.0
- y4 = (y2 + y3) / 2.0
- if((x2.floor != x3.floor && [1, 3, 4, 6, 7, 9].include?(d)) || (y2.floor != y3.floor && [1, 2, 3, 7, 8, 9].include?(d)))
- return false if ([1, 2, 3].include?(d) && !check_passage(x2, y2, 1)) || ([3, 6, 9].include?(d) && !check_passage(x2, y2, 4))
- return false if ([3, 6, 9].include?(d) && !check_passage(x2, y3, 4)) || ([7, 8, 9].include?(d) && !check_passage(x2, y3, 8))
- return false if ([1, 2, 3].include?(d) && !check_passage(x3, y2, 1)) || ([1, 4, 7].include?(d) && !check_passage(x3, y2, 2))
- return false if ([1, 4, 7].include?(d) && !check_passage(x3, y3, 2)) || ([7, 8, 9].include?(d) && !check_passage(x3, y3, 8))
- end
- return true
- end
- #--------------------------------------------------------------------------
- # * New: Determine if Passable by Boat
- #--------------------------------------------------------------------------
- def boat_passable_rect?(x, y, rect)
- x2 = x + (rect.x / 32.0)
- y2 = y + (rect.y / 32.0)
- x3 = x2 + ((rect.width - 1) / 32.0)
- y3 = y2 + ((rect.height - 1) / 32.0)
- return false unless check_passage(x2, y2, 0x0200)
- return false unless check_passage(x2, y3, 0x0200)
- return false unless check_passage(x3, y2, 0x0200)
- return check_passage(x3, y3, 0x0200)
- end
- #--------------------------------------------------------------------------
- # * New: Determine if Passable by Ship
- #--------------------------------------------------------------------------
- def ship_passable_rect?(x, y, rect)
- x2 = x + (rect.x / 32.0)
- y2 = y + (rect.y / 32.0)
- x3 = x2 + ((rect.width - 1) / 32.0)
- y3 = y2 + ((rect.height - 1) / 32.0)
- return false unless check_passage(x2, y2, 0x0400)
- return false unless check_passage(x2, y3, 0x0400)
- return false unless check_passage(x3, y2, 0x0400)
- return check_passage(x3, y3, 0x0400)
- end
- #--------------------------------------------------------------------------
- # * New: Determine if Airship can Land
- #--------------------------------------------------------------------------
- def airship_land_ok_rect?(x, y, rect)
- x2 = x + (rect.x / 32.0)
- y2 = y + (rect.y / 32.0)
- x3 = x2 + ((rect.width - 1) / 32.0)
- y3 = y2 + ((rect.height - 1) / 32.0)
- return false unless check_passage(x2, y2, 0x0800) && check_passage(x2, y2, 0x0f)
- return false unless check_passage(x2, y3, 0x0800) && check_passage(x2, y3, 0x0f)
- return false unless check_passage(x3, y2, 0x0800) && check_passage(x3, y2, 0x0f)
- return check_passage(x3, y3, 0x0800) && check_passage(x3, y3, 0x0f)
- end
- #--------------------------------------------------------------------------
- # * Alias: Refresh
- #--------------------------------------------------------------------------
- alias game_map_refresh_cxj_fm refresh
- def refresh
- game_map_refresh_cxj_fm
- refresh_event_collision
- end
- #--------------------------------------------------------------------------
- # * Alias: Event Setup
- #--------------------------------------------------------------------------
- alias game_map_setup_events_cxj_fm setup_events
- def setup_events
- game_map_setup_events_cxj_fm
- refresh_event_collision
- end
- #--------------------------------------------------------------------------
- # * New: Refresh Event Collision
- #--------------------------------------------------------------------------
- def refresh_event_collision
- if(free_movement_enabled?)
- temp_list = {}
- @map.note.split(/[\r\n]+/).each { |line|
- collision = []
- event_name = ''
- case line
- when /<collisionbox (.+?):[ ]*(\d+),[ ]*(\d+),[ ]*(\d+),[ ]*(\d+)>/i
- collision = [$2, $3, $4, $5]
- event_name = $1
- when /<collisionbox (.+?):[ ]*(.+?)>/i
- collision = CXJ::FREE_MOVEMENT::COLLISION[$2] if !CXJ::FREE_MOVEMENT::COLLISION[$2].nil?
- event_name = $1
- end
- if !event_name.empty? && !collision.empty?
- temp_list[event_name] = collision
- end
- }
- @events.each_value {|event|
- if temp_list.has_key?(event.name)
- collision = temp_list[event.name]
- event.set_collision_rect(collision[0], collision[1], collision[2], collision[3])
- end
- }
- end
- end
- #--------------------------------------------------------------------------
- # * New: Get Array of Events at Designated Coordinates
- #--------------------------------------------------------------------------
- def events_xy_rect(x, y, rect)
- @events.values.select {|event| event.pos_rect?(x, y, rect) }
- end
- #--------------------------------------------------------------------------
- # * New: Get Array of Events at Designated Coordinates (Except Pass-Through)
- #--------------------------------------------------------------------------
- def events_xy_rect_nt(x, y, rect)
- @events.values.select {|event| event.pos_rect_nt?(x, y, rect) }
- end
- #--------------------------------------------------------------------------
- # * New: Get Array of Tile-Handling Events at Designated Coordinates
- # (Except Pass-Through)
- #--------------------------------------------------------------------------
- def tile_events_xy_rect(x, y, rect)
- @tile_events.select {|event| event.pos_rect_nt?(x, y, rect) }
- end
- #--------------------------------------------------------------------------
- # * Alias: Calculate X Coordinate Shifted One Tile in Specific Direction
- # (With Loop Adjustment)
- #--------------------------------------------------------------------------
- alias game_map_round_x_with_direction_cxj_fm round_x_with_direction
- def round_x_with_direction(x, d)
- if(free_movement_enabled?)
- round_x(x + ((d - 1) % 3 - 1))
- else
- game_map_round_x_with_direction_cxj_fm(x, d)
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Calculate Y Coordinate Shifted One Tile in Specific Direction
- # (With Loop Adjustment)
- #--------------------------------------------------------------------------
- alias game_map_round_y_with_direction_cxj_fm round_y_with_direction
- def round_y_with_direction(y, d)
- if(free_movement_enabled?)
- round_y(y + (1 - ((d - 1) / 3)))
- else
- game_map_round_y_with_direction_cxj_fm(y, d)
- end
- end
- end
- #==============================================================================
- # ** Game_CharacterBase
- #------------------------------------------------------------------------------
- # This base class handles characters. It retains basic information, such as
- # coordinates and graphics, shared by all characters.
- #==============================================================================
- class Game_CharacterBase
- attr_accessor :move_poll
- #--------------------------------------------------------------------------
- # * Alias: Object Initialization
- #--------------------------------------------------------------------------
- alias game_characterbase_initialize_cxj_fm initialize
- def initialize
- game_characterbase_initialize_cxj_fm
- @old_x = @real_x
- @old_y = @real_y
- @pos_list = []
- @move_poll = []
- end
- #--------------------------------------------------------------------------
- # * Alias: Frame Update
- #
- # Added processing of movement being polled.
- #--------------------------------------------------------------------------
- alias game_characterbase_update_cxj_fm update
- def update
- @old_x = @real_x
- @old_y = @real_y
- if($game_map.free_movement_enabled?)
- interpret_move unless moving?
- end
- game_characterbase_update_cxj_fm
- end
- #--------------------------------------------------------------------------
- # * New: Get Pos List Length
- #--------------------------------------------------------------------------
- def pos_list_size
- @pos_list.size
- end
- #--------------------------------------------------------------------------
- # * New: Get Coordinates From Pos List
- #--------------------------------------------------------------------------
- def get_coords_from_pos_list
- return @pos_list.shift
- end
- #--------------------------------------------------------------------------
- # * New: Clear Pos List
- #--------------------------------------------------------------------------
- def clear_pos_list
- @pos_list.clear
- end
- #--------------------------------------------------------------------------
- # * New: Movement Interpreting
- # Interprets the polled movement.
- #--------------------------------------------------------------------------
- def interpret_move(step_left = distance_per_frame)
- @move_poll = [] if @move_poll.nil?
- if @move_poll.size > 0
- current_move = @move_poll.shift()
- d = current_move[0]
- horz = (d - 1) % 3 - 1
- vert = 1 - ((d - 1) / 3)
- turn_ok = current_move[1]
- set_direction(d) if turn_ok
- check_event_trigger_touch_front
- processed = false
- if (d % 2 == 0 && passable?(@x, @y, d)) || (d % 2 != 0 && diagonal_passable?(@x, @y, horz, vert))
- process_move(horz, vert)
- processed = true
- elsif d % 2 != 0 && !diagonal_passable?(@x, @y, horz, vert)
- if passable?(@x, @y, horz + 5)
- set_direction(horz + 5) if turn_ok
- process_move(horz, 0)
- processed = true
- end
- if passable?(@x, @y, 5 - vert * 3)
- set_direction(5 - vert * 3) if turn_ok
- process_move(0, vert)
- processed = true
- end
- end
- if(processed)
- pixelstep = CXJ::FREE_MOVEMENT::PIXELS_PER_STEP / 32.0
- if(step_left > pixelstep && !@move_poll.empty?)
- interpret_move(step_left - pixelstep)
- elsif(jumping? && !@move_poll.empty?)
- interpret_move(0)
- end
- else
- @move_poll.clear
- end
- current_move
- end
- end
- #--------------------------------------------------------------------------
- # * New: Processes Movement
- #--------------------------------------------------------------------------
- def process_move(horz, vert)
- pixelstep = CXJ::FREE_MOVEMENT::PIXELS_PER_STEP / 32.0
- @x = @x + horz * pixelstep
- @y = @y + vert * pixelstep
- @pos_list.push({:x => @real_x, :y => @real_y})
- @pos_list.shift if @pos_list.size > CXJ::FREE_MOVEMENT::FOLLOWERS_DISTANCE * 2
- if(!jumping?)
- @x = $game_map.round_x(@x)
- @y = $game_map.round_y(@y)
- @real_x = @x - horz * pixelstep
- @real_y = @y - vert * pixelstep
- increase_steps
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Determine Triggering of Frontal Touch Event
- #--------------------------------------------------------------------------
- alias game_characterbase_check_event_trigger_touch_front_cxj_fm check_event_trigger_touch_front
- def check_event_trigger_touch_front
- if $game_map.free_movement_enabled?
- d = @direction
- horz = (d - 1) % 3 - 1
- vert = 1 - ((d - 1) / 3)
- pixelstep = CXJ::FREE_MOVEMENT::PIXELS_PER_STEP / 32.0
- x2 = $game_map.round_x(x + horz * pixelstep)
- y2 = $game_map.round_y(y + vert * pixelstep)
- check_event_trigger_touch(x2, y2)
- else
- game_characterbase_check_event_trigger_touch_front_cxj_fm
- end
- end
- #--------------------------------------------------------------------------
- # * New: Collision Rectangle
- # Gets the collision rectangle.
- #--------------------------------------------------------------------------
- def collision_rect
- collision = CXJ::FREE_MOVEMENT::COLLISION["DEFAULT"]
- return Rect.new(collision[0], collision[1], collision[2], collision[3])
- end
- #--------------------------------------------------------------------------
- # * Alias: Determine if Passable
- # d : Direction (2,4,6,8)
- #--------------------------------------------------------------------------
- alias game_characterbase_passable_cxj_fm? passable?
- def passable?(x, y, d)
- if $game_map.free_movement_enabled?
- horz = (d - 1) % 3 - 1
- vert = 1 - ((d - 1) / 3)
- pixelstep = CXJ::FREE_MOVEMENT::PIXELS_PER_STEP / 32.0
- x2 = $game_map.round_x(x + horz * pixelstep)
- y2 = $game_map.round_y(y + vert * pixelstep)
- return false unless $game_map.valid_rect?(x2, y2, collision_rect)
- return true if @through || debug_through?
- return false unless map_passable_rect?(x, y, d, collision_rect)
- return false unless map_passable_rect?(x2, y2, reverse_dir(d), collision_rect)
- return false if collide_with_characters?(x2, y2)
- return true
- else
- return game_characterbase_passable_cxj_fm?(x, y, d)
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Determine Diagonal Passability
- # horz : Horizontal (4 or 6)
- # vert : Vertical (2 or 8)
- #--------------------------------------------------------------------------
- alias game_characterbase_diagonal_passable_cxj_fm? diagonal_passable?
- def diagonal_passable?(x, y, horz, vert)
- if $game_map.free_movement_enabled?
- pixelstep = CXJ::FREE_MOVEMENT::PIXELS_PER_STEP / 32.0
- x2 = $game_map.round_x(x + horz * pixelstep)
- y2 = $game_map.round_y(y + vert * pixelstep)
- d = (horz == 4 ? -1 : 1) + (vert == 2 ? -3 : 3) + 5
- return passable?(x2, y2, d) && passable?(x2, y2, horz) && passable?(x2, y2, vert)
- else
- return game_characterbase_diagonal_passable_cxj_fm?(x, y, horz, vert)
- end
- end
- #--------------------------------------------------------------------------
- # * New: Determine if Map is Passable
- # d : Direction (2,4,6,8)
- #--------------------------------------------------------------------------
- def map_passable_rect?(x, y, d, rect)
- $game_map.passable_rect?(x, y, d, rect)
- end
- #--------------------------------------------------------------------------
- # * Alias: Change Direction to Designated Direction
- # d : Direction (2,4,6,8)
- #
- # Fix for diagonal movement.
- #--------------------------------------------------------------------------
- alias game_characterbase_set_direction_cxj_fm set_direction
- def set_direction(d)
- if $game_map.free_movement_enabled?
- if !@direction_fix && d != 0
- @direction = d
- if d % 2 != 0 && (!$imported["CXJ-AnimEx"] || !@has_diagonal)
- @direction+= 1
- @direction-= 2 if d > 5
- @direction = 10 - direction if d > 2 && d < 8
- end
- end
- @stop_count = 0
- else
- game_characterbase_set_direction_cxj_fm(d)
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Move Straight
- # d: Direction (2,4,6,8)
- # turn_ok : Allows change of direction on the spot
- #
- # Polls the movement instead of processing them immediately.
- #--------------------------------------------------------------------------
- alias game_characterbase_move_straight_cxj_fm move_straight
- def move_straight(d, turn_ok = true)
- if $game_map.free_movement_enabled?
- pixelstep = CXJ::FREE_MOVEMENT::PIXELS_PER_STEP / 32.0
- @move_poll+= [[d, turn_ok]] * (distance_per_frame / pixelstep).ceil
- else
- game_characterbase_move_straight_cxj_fm(d, turn_ok)
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Move Diagonally
- # horz: Horizontal (4 or 6)
- # vert: Vertical (2 or 8)
- #
- # Polls the movement instead of processing them immediately.
- #--------------------------------------------------------------------------
- alias game_characterbase_move_diagonal_cxj_fm move_diagonal
- def move_diagonal(horz, vert)
- if $game_map.free_movement_enabled?
- pixelstep = CXJ::FREE_MOVEMENT::PIXELS_PER_STEP / 32.0
- @move_poll+= [[vert + (horz > 5 ? 1 : -1), true]] * (distance_per_frame / pixelstep).ceil
- else
- game_characterbase_move_diagonal_cxj_fm(horz, vert)
- end
- end
- #--------------------------------------------------------------------------
- # * New: Determine Coordinate Match
- #--------------------------------------------------------------------------
- def pos_rect?(x, y, rect)
- main_left = @x + collision_rect.x / 32.0
- main_top = @y + collision_rect.y / 32.0
- main_right = main_left + (collision_rect.width - 1) / 32.0
- main_bottom = main_top + (collision_rect.height - 1) / 32.0
- other_left = x + rect.x / 32.0
- other_top = y + rect.y / 32.0
- other_right = other_left + (rect.width - 1) / 32.0
- other_bottom = other_top + (rect.height - 1) / 32.0
- coltest = true
- coltest = false if main_right < other_left
- coltest = false if main_left > other_right
- coltest = false if main_bottom < other_top
- coltest = false if main_top > other_bottom
- if coltest == false && ($game_map.loop_horizontal? || $game_map.loop_vertical?) && x <= $game_map.width && y <= $game_map.height
- return true if $game_map.loop_horizontal? && pos_rect?(x + $game_map.width, y, rect)
- return true if $game_map.loop_vertical? && pos_rect?(x, y + $game_map.height, rect)
- end
- return coltest
- end
- #--------------------------------------------------------------------------
- # * New: Determine if Coordinates Match and Pass-Through Is Off (nt = No Through)
- #--------------------------------------------------------------------------
- def pos_rect_nt?(x, y, rect)
- pos_rect?(x, y, rect) && !@through
- end
- #--------------------------------------------------------------------------
- # * Alias: Detect Collision with Event
- #--------------------------------------------------------------------------
- alias game_characterbase_collide_with_events_cxj_fm? collide_with_events?
- def collide_with_events?(x, y)
- if $game_map.free_movement_enabled?
- $game_map.events_xy_rect_nt(x, y, collision_rect).any? do |event|
- (event.normal_priority? || self.is_a?(Game_Event)) && event != self
- end
- else
- game_characterbase_collide_with_events_cxj_fm?(x, y)
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Detect Collision with Vehicle
- #--------------------------------------------------------------------------
- alias game_characterbase_collide_with_vehicles_cxj_fm? collide_with_vehicles?
- def collide_with_vehicles?(x, y)
- if $game_map.free_movement_enabled?
- $game_map.boat.pos_rect_nt?(x, y, collision_rect) || $game_map.ship.pos_rect_nt?(x, y, collision_rect)
- else
- game_characterbase_collide_with_vehicles_cxj_fm?(x, y)
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Update While Jumping
- #--------------------------------------------------------------------------
- alias game_characterbase_update_jump_cxj_fm update_jump
- def update_jump
- if $game_map.free_movement_enabled?
- @jump_count -= 1
- diff_x = @real_x
- @real_x = (@real_x * @jump_count + @x) / (@jump_count + 1.0)
- @real_y = (@real_y * @jump_count + @y) / (@jump_count + 1.0)
- update_bush_depth
- if @jump_count == 0
- @real_x = @x = $game_map.round_x(@x)
- @real_y = @y = $game_map.round_y(@y)
- end
- else
- game_characterbase_update_jump_cxj_fm
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Calculate Jump Height
- #--------------------------------------------------------------------------
- alias game_characterbase_jump_height_cxj_fm jump_height
- def jump_height
- if $game_map.free_movement_enabled?
- ((@jump_peak * @jump_peak - (@jump_count * CXJ::FREE_MOVEMENT::JUMP_SPEED - @jump_peak).abs ** 2) / 2) * (CXJ::FREE_MOVEMENT::MAX_JUMP_HEIGHT > 0 && @jump_peak > 0 ? (CXJ::FREE_MOVEMENT::MAX_JUMP_HEIGHT * 2.0) / (@jump_peak ** 2) : 1)
- else
- game_characterbase_jump_height_cxj_fm
- end
- end
- end
- #==============================================================================
- # ** Game_Character
- #------------------------------------------------------------------------------
- # A character class with mainly movement route and other such processing
- # added. It is used as a super class of Game_Player, Game_Follower,
- # GameVehicle, and Game_Event.
- #==============================================================================
- class Game_Character < Game_CharacterBase
- #--------------------------------------------------------------------------
- # * Alias: Move at Random
- #--------------------------------------------------------------------------
- alias game_character_move_random_cxj_fm move_random
- def move_random
- if $game_map.free_movement_enabled?
- @move_poll+= [[2 + rand(4) * 2, true]] * ((24.0 + (rand(160) / 10) ) / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- else
- game_character_move_random_cxj_fm
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Move Toward Character
- #--------------------------------------------------------------------------
- alias game_character_move_toward_character_cxj_fm move_toward_character
- def move_toward_character(character)
- if $game_map.free_movement_enabled?
- sx = distance_x_from(character.x)
- sy = distance_y_from(character.y)
- if sx.abs > sy.abs
- if passable?(@x, @y, (sx > 0 ? 4 : 6))
- @move_poll+= [[sx > 0 ? 4 : 6, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- else
- @move_poll+= [[sy > 0 ? 8 : 2, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- end
- elsif sy != 0
- if passable?(@x, @y, (sy > 0 ? 8 : 2))
- @move_poll+= [[sy > 0 ? 8 : 2, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- else
- @move_poll+= [[sx > 0 ? 4 : 6, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- end
- end
- else
- game_character_move_toward_character_cxj_fm(character)
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Move Away from Character
- #--------------------------------------------------------------------------
- alias game_character_move_away_from_character_cxj_fm move_away_from_character
- def move_away_from_character(character)
- if $game_map.free_movement_enabled?
- sx = distance_x_from(character.x)
- sy = distance_y_from(character.y)
- if sx.abs > sy.abs
- if passable?(@x, @y, (sx > 0 ? 6 : 4))
- @move_poll+= [[sx > 0 ? 6 : 4, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- else
- @move_poll+= [[sy > 0 ? 2 : 8, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- end
- elsif sy != 0
- if passable?(@x, @y, (sy > 0 ? 2 : 8))
- @move_poll+= [[sy > 0 ? 2 : 8, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- else
- @move_poll+= [[sx > 0 ? 6 : 4, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- end
- end
- else
- game_character_move_away_from_character_cxj_fm(character)
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: 1 Step Forward
- #--------------------------------------------------------------------------
- alias game_character_move_forward_cxj_fm move_forward
- def move_forward
- if $game_map.free_movement_enabled?
- @move_poll+= [[@direction, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- else
- game_character_move_forward_cxj_fm
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: 1 Step Backward
- #--------------------------------------------------------------------------
- alias game_character_move_backward_cxj_fm move_backward
- def move_backward
- if $game_map.free_movement_enabled?
- last_direction_fix = @direction_fix
- @direction_fix = true
- @move_poll+= [[reverse_dir(@direction), false]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- @direction_fix = last_direction_fix
- else
- game_character_move_backward_cxj_fm
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Jump
- # x_plus : x-coordinate plus value
- # y_plus : y-coordinate plus value
- #--------------------------------------------------------------------------
- alias game_character_jump_cxj_fm jump
- def jump(x_plus, y_plus)
- if $game_map.free_movement_enabled?
- #if x_plus.abs > y_plus.abs
- # set_direction(x_plus < 0 ? 4 : 6) if x_plus != 0
- #else
- # set_direction(y_plus < 0 ? 8 : 2) if y_plus != 0
- #end
- distance = Math.sqrt(x_plus * x_plus + y_plus * y_plus).round
- pollcount = distance * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- #@move_poll+= [[(x_plus < 0 ? -1 : x_plus > 0 ? 1 : 0) + (y_plus < 0 ? 8 : y_plus > 0 ? 2 : 5), false]] * pollcount
- @x+= x_plus
- @y+= y_plus
- @jump_peak = 10 + distance - @move_speed
- @jump_count = @jump_peak / CXJ::FREE_MOVEMENT::JUMP_SPEED * 2
- @stop_count = 0
- straighten
- else
- game_character_jump_cxj_fm
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Process Move Command
- #--------------------------------------------------------------------------
- alias game_character_process_move_command_cxj_fm process_move_command
- def process_move_command(command)
- if $game_map.free_movement_enabled?
- case command.code
- when ROUTE_MOVE_DOWN; @move_poll+= [[2, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- when ROUTE_MOVE_LEFT; @move_poll+= [[4, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- when ROUTE_MOVE_RIGHT; @move_poll+= [[6, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- when ROUTE_MOVE_UP; @move_poll+= [[8, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- when ROUTE_MOVE_LOWER_L; @move_poll+= [[1, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- when ROUTE_MOVE_LOWER_R; @move_poll+= [[3, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- when ROUTE_MOVE_UPPER_L; @move_poll+= [[7, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- when ROUTE_MOVE_UPPER_R; @move_poll+= [[9, true]] * (32.0 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP).ceil
- else; game_character_process_move_command_cxj_fm(command)
- end
- else
- game_character_process_move_command_cxj_fm(command)
- end
- end
- end
- #==============================================================================
- # ** Game_Player
- #------------------------------------------------------------------------------
- # This class handles the player. It includes event starting determinants and
- # map scrolling functions. The instance of this class is referenced by
- # $game_player.
- #==============================================================================
- class Game_Player < Game_Character
- #--------------------------------------------------------------------------
- # * Alias: Object Initialization
- #--------------------------------------------------------------------------
- alias game_player_initialize_cxj_fm initialize
- def initialize
- @last_poll = []
- game_player_initialize_cxj_fm
- @custom_collision = nil
- @interaction = CXJ::FREE_MOVEMENT::INTERACTION["DEFAULT"]
- end
- #--------------------------------------------------------------------------
- # * Alias: Refresh
- #--------------------------------------------------------------------------
- alias game_player_refresh_cxj_fm refresh
- def refresh
- game_player_refresh_cxj_fm
- return if actor.nil? || !$game_map.free_movement_enabled?
- @custom_collision = nil
- @interaction = CXJ::FREE_MOVEMENT::INTERACTION["DEFAULT"]
- actor.actor.note.split(/[\r\n]+/).each { |line|
- case line
- when /<collisionbox:[ ]*(\d+),[ ]*(\d+),[ ]*(\d+),[ ]*(\d+)>/i
- @custom_collision = Rect.new($1, $2, $3, $4)
- when /<collisionbox:[ ]*(.+?)>/i
- collision = CXJ::FREE_MOVEMENT::COLLISION[$1] if !CXJ::FREE_MOVEMENT::COLLISION[$1].nil?
- @custom_collision = Rect.new(collision[0], collision[1], collision[2], collision[3])
- when /<interactionbox (\d+):[ ]*(\d+),[ ]*(\d+),[ ]*(\d+),[ ]*(\d+)>/i
- @interaction[$1] = [$2, $3, $4, $5] if $1 > 0 && $1 < 10
- when /<interactionbox:[ ]*(.+?)>/i
- @interaction = CXJ::FREE_MOVEMENT::INTERACTION[$1] if !CXJ::FREE_MOVEMENT::INTERACTION[$1].nil?
- end
- }
- end
- #--------------------------------------------------------------------------
- # * Alias: Execute Player Transfer
- #--------------------------------------------------------------------------
- alias game_player_perform_transfer_cxj_fm perform_transfer
- def perform_transfer
- is_transfer = transfer?
- game_player_perform_transfer_cxj_fm
- if is_transfer && $game_map.free_movement_enabled?
- @pos_list.clear
- @followers.clear_pos_list
- $game_map.events_xy_rect(x, y, collision_rect).each do |event|
- if event.trigger_in?([1,2]) && event.normal_priority? == false
- event.add_touch(self)
- end
- end
- end
- end
- #--------------------------------------------------------------------------
- # * New: Movement Interpreting
- # Interprets the polled movement.
- #--------------------------------------------------------------------------
- def interpret_move(step_left = distance_per_frame)
- current_move = super(step_left)
- @last_poll.push(current_move) if !current_move.nil?
- end
- #--------------------------------------------------------------------------
- # * New: Collision Rectangle
- # Gets the collision rectangle.
- #--------------------------------------------------------------------------
- def collision_rect
- key = @vehicle_type.id2name.upcase
- if @vehicle_type != :walk && !CXJ::FREE_MOVEMENT::COLLISION[key].nil?
- collision = CXJ::FREE_MOVEMENT::COLLISION[key]
- return Rect.new(collision[0], collision[1], collision[2] - 1, collision[3] - 1)
- end
- return @custom_collision if !@custom_collision.nil?
- return super
- end
- #--------------------------------------------------------------------------
- # * New: Interaction Rectangle
- # Gets the interaction rectangle.
- #--------------------------------------------------------------------------
- def interaction_rect
- collision = @interaction[@direction]
- if collision.nil?
- return collision_rect
- end
- return Rect.new(collision[0], collision[1], collision[2], collision[3])
- end
- #--------------------------------------------------------------------------
- # * Override: Processing of Movement via Input from Directional Buttons
- #
- # Added diagonal movement.
- #--------------------------------------------------------------------------
- def move_by_input
- return if !movable? || $game_map.interpreter.running?
- if CXJ::FREE_MOVEMENT::ENABLE_DIAGONAL && Input.dir8 > 0 && Input.dir8 % 2 != 0
- d = Input.dir8
- horz = (d == 1 || d == 7 ? 4 : 6)
- vert = (d == 1 || d == 3 ? 2 : 8)
- move_diagonal(horz, vert)
- elsif Input.dir4 > 0
- move_straight(Input.dir4)
- end
- end
- #--------------------------------------------------------------------------
- # * New: Detect Collision (Including Followers)
- #--------------------------------------------------------------------------
- def collide_rect?(x, y, rect)
- !@through && (pos_rect?(x, y, rect) || followers.collide_rect?(x, y, rect))
- end
- #--------------------------------------------------------------------------
- # * Alias: Trigger Map Event
- # triggers : Trigger array
- # normal : Is priority set to [Same as Characters] ?
- #--------------------------------------------------------------------------
- alias game_player_start_map_event_cxj_fm start_map_event
- def start_map_event(x, y, triggers, normal, rect = collision_rect)
- if $game_map.free_movement_enabled?
- return if $game_map.interpreter.running?
- event_list = {}
- $game_map.events_xy_rect(x, y, rect).each do |event|
- if event.trigger_in?(triggers) && event.normal_priority? == normal
- if !CXJ::FREE_MOVEMENT::ONLY_TRIGGER_CLOSEST
- event.start unless event.is_touching?(self)
- event.add_touch(self)
- else
- dist_x = event.distance_x_from(@x)
- dist_y = event.distance_y_from(@y)
- event_list[event] = Math.hypot(dist_x, dist_y) unless event.is_touching?(self)
- end
- end
- end
- if !event_list.empty?
- current_event = nil
- current_dist = -1
- event_list.each do |event, dist|
- if current_event == nil || current_dist > dist
- current_event = event
- current_dist = dist
- end
- end
- current_event.start
- current_event.add_touch(self)
- end
- else
- game_player_start_map_event_cxj_fm(x, y, triggers, normal)
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Determine if Front Event is Triggered
- #--------------------------------------------------------------------------
- alias game_player_check_event_trigger_there_cxj_fm check_event_trigger_there
- def check_event_trigger_there(triggers)
- if $game_map.free_movement_enabled?
- x2 = $game_map.round_x_with_direction(@x, @direction)
- y2 = $game_map.round_y_with_direction(@y, @direction)
- start_map_event(x2, y2, triggers, true, interaction_rect)
- return if $game_map.any_event_starting?
- return unless $game_map.counter?(x2, y2)
- x3 = $game_map.round_x_with_direction(x2, @direction)
- y3 = $game_map.round_y_with_direction(y2, @direction)
- start_map_event(x3, y3, triggers, true, interaction_rect)
- else
- game_player_check_event_trigger_there_cxj_fm(triggers)
- end
- end
- #--------------------------------------------------------------------------
- # * Override: Board Vehicle
- # Assumes that the player is not currently in a vehicle.
- #--------------------------------------------------------------------------
- alias game_player_get_on_vehicle_cxj_fm get_on_vehicle
- def get_on_vehicle
- if $game_map.free_movement_enabled?
- front_x = $game_map.round_x_with_direction(@x, @direction)
- front_y = $game_map.round_y_with_direction(@y, @direction)
- @vehicle_type = :boat if $game_map.boat.pos_rect?(front_x, front_y, interaction_rect)
- @vehicle_type = :ship if $game_map.ship.pos_rect?(front_x, front_y, interaction_rect)
- @vehicle_type = :airship if $game_map.airship.pos_rect?(@x, @y, collision_rect)
- if vehicle
- @vehicle_getting_on = true
- horz = (@x > vehicle.x ? -1 : @x < vehicle.x ? 1 : 0)
- vert = (@y > vehicle.y ? -3 : @y < vehicle.y ? 3 : 0)
- d = 5 + horz - vert
- set_direction(d)
- @x = vehicle.x
- @y = vehicle.y
- @followers.gather
- @pos_list.clear
- @followers.clear_pos_list
- end
- @vehicle_getting_on
- else
- game_player_get_on_vehicle_cxj_fm
- end
- end
- #--------------------------------------------------------------------------
- # * Override: Get Off Vehicle
- # Assumes that the player is currently riding in a vehicle.
- #--------------------------------------------------------------------------
- alias game_player_get_off_vehicle_cxj_fm get_off_vehicle
- def get_off_vehicle
- if $game_map.free_movement_enabled?
- if vehicle.land_ok?(@x, @y, @direction)
- set_direction(2) if in_airship?
- @followers.synchronize(@x, @y, @direction)
- vehicle.get_off
- unless in_airship?
- @x = $game_map.round_x_with_direction(@x, @direction)
- @y = $game_map.round_y_with_direction(@y, @direction)
- @transparent = false
- end
- @vehicle_getting_off = true
- @move_speed = 4
- @through = false
- make_encounter_count
- @followers.gather
- @pos_list.clear
- @followers.clear_pos_list
- end
- @vehicle_getting_off
- else
- game_player_get_off_vehicle_cxj_fm
- end
- end
- #--------------------------------------------------------------------------
- # * New: Determine if Map is Passable
- # d: Direction (2,4,6,8)
- #--------------------------------------------------------------------------
- def map_passable_rect?(x, y, d, rect)
- case @vehicle_type
- when :boat
- $game_map.boat_passable_rect?(x, y, vehicle.collision_rect)
- when :ship
- $game_map.ship_passable_rect?(x, y, vehicle.collision_rect)
- when :airship
- true
- else
- super
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Move Diagonally
- #--------------------------------------------------------------------------
- alias game_player_move_diagonal_cxj_fm move_diagonal
- def move_diagonal(horz, vert)
- if $game_map.free_movement_enabled?
- @followers.move if diagonal_passable?(@x, @y, horz, vert) || passable?(@x, @y, horz + 5) || passable?(@x, @y, 5 - vert * 3)
- super
- else
- game_player_move_diagonal_cxj_fm(horz, vert)
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Create Encounter Count
- #--------------------------------------------------------------------------
- alias game_player_make_encounter_count_cxj_fm make_encounter_count
- def make_encounter_count
- game_player_make_encounter_count_cxj_fm
- @encounter_count*= (32 / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP) + (32 / 2 < CXJ::FREE_MOVEMENT::PIXELS_PER_STEP ? 1 : 0) if $game_map.free_movement_enabled?
- end
- #--------------------------------------------------------------------------
- # * Alias: Detect Collision with Vehicle
- #--------------------------------------------------------------------------
- alias game_player_collide_with_vehicles_cxj_fm? collide_with_vehicles?
- def collide_with_vehicles?(x, y)
- return (@vehicle_type != :boat && $game_map.boat.pos_rect_nt?(x, y, collision_rect)) || (@vehicle_type != :ship && $game_map.ship.pos_rect_nt?(x, y, collision_rect)) if $game_map.free_movement_enabled?
- return game_player_collide_with_vehicles_cxj_fm?(x, y)
- end
- #--------------------------------------------------------------------------
- # * Alias: Processing When Not Moving
- # last_moving : Was it moving previously?
- #--------------------------------------------------------------------------
- alias game_player_update_nonmoving_cxj_fm update_nonmoving
- def update_nonmoving(last_moving)
- game_player_update_nonmoving_cxj_fm(last_moving || @old_x != @real_x || @old_y != @real_y)
- return if $game_map.free_movement_enabled?
- update_encounter if !last_moving && !@last_poll.empty?
- @last_poll.clear
- end
- end
- #==============================================================================
- # ** Game_Followers
- #------------------------------------------------------------------------------
- # This is a wrapper for a follower array. This class is used internally for
- # the Game_Player class.
- #==============================================================================
- class Game_Followers
- #--------------------------------------------------------------------------
- # * New: Detect Collision
- #--------------------------------------------------------------------------
- def collide_rect?(x, y, rect)
- visible_folloers.any? {|follower| follower.pos_rect?(x, y, rect) }
- end
- #--------------------------------------------------------------------------
- # * New: Clear Pos List
- #--------------------------------------------------------------------------
- def clear_pos_list
- reverse_each do |follower|
- follower.clear_pos_list
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Movement
- #--------------------------------------------------------------------------
- alias game_followers_move_cxj_fm move
- def move
- if $game_map.free_movement_enabled?
- reverse_each do |follower|
- if gathering?
- follower.board
- end
- follower.chase_preceding_character
- end
- else
- game_followers_move_cxj_fm
- end
- end
- end
- #==============================================================================
- # ** Game_Vehicle
- #------------------------------------------------------------------------------
- # This class handles vehicles. It's used within the Game_Map class. If there
- # are no vehicles on the current map, the coordinates are set to (-1,-1).
- #==============================================================================
- class Game_Vehicle < Game_Character
- #--------------------------------------------------------------------------
- # * New: Collision Rectangle
- # Gets the collision rectangle.
- #--------------------------------------------------------------------------
- def collision_rect
- collision = CXJ::FREE_MOVEMENT::COLLISION["DEFAULT"]
- key = @type.id2name.upcase
- collision = CXJ::FREE_MOVEMENT::COLLISION[key] if !CXJ::FREE_MOVEMENT::COLLISION[key].nil?
- return Rect.new(collision[0], collision[1], collision[2], collision[3])
- end
- #--------------------------------------------------------------------------
- # * New: Determine Coordinate Match
- #--------------------------------------------------------------------------
- def pos_rect?(x, y, rect)
- on_map? && super(x, y, rect)
- end
- #--------------------------------------------------------------------------
- # * New: Determine If On Map
- #--------------------------------------------------------------------------
- def on_map?
- @map_id == $game_map.map_id
- end
- #--------------------------------------------------------------------------
- # * Alias: Determine if Docking/Landing Is Possible
- # d: Direction (2,4,6,8)
- #--------------------------------------------------------------------------
- alias game_vehicle_land_ok_cxj_fm? land_ok?
- def land_ok?(x, y, d)
- return game_vehicle_land_ok_cxj_fm?(x, y, d) if !$game_map.free_movement_enabled?
- if @type == :airship
- return false unless $game_map.airship_land_ok_rect?(x, y, collision_rect)
- return false unless $game_map.events_xy_rect(x, y, collision_rect).empty?
- else
- x2 = $game_map.round_x_with_direction(x, d)
- y2 = $game_map.round_y_with_direction(y, d)
- return false unless $game_map.valid_rect?(x2, y2, collision_rect)
- return false unless $game_map.passable_rect?(x2, y2, reverse_dir(d), collision_rect)
- return false if collide_with_characters?(x2, y2)
- end
- return true
- end
- end
- #==============================================================================
- # ** Game_Event
- #------------------------------------------------------------------------------
- # This class handles events. Functions include event page switching via
- # condition determinants and running parallel process events. Used within the
- # Game_Map class.
- #==============================================================================
- class Game_Event < Game_Character
- #--------------------------------------------------------------------------
- # * Alias: Initialize Public Member Variables
- #--------------------------------------------------------------------------
- alias game_event_init_public_members_cxj_fm init_public_members
- def init_public_members
- game_event_init_public_members_cxj_fm
- @collisionbox = Rect.new(Euphoria::EventCollisionFix::EVENT_COLL_BOX_X,
- Euphoria::EventCollisionFix::EVENT_COLL_BOX_Y, Euphoria::EventCollisionFix::EVENT_COLL_BOX_W,
- Euphoria::EventCollisionFix::EVENT_COLL_BOX_H)
- @touch_chars = []
- end
- #--------------------------------------------------------------------------
- # * Alias: Frame Update
- #--------------------------------------------------------------------------
- alias game_event_update_cxj_fm update
- def update
- if $game_map.free_movement_enabled?
- temp_chars = []
- @touch_chars.each do |character|
- temp_chars.push(character) if character.pos_rect?(@x, @y, collision_rect)
- end
- @touch_chars = temp_chars
- end
- game_event_update_cxj_fm
- end
- #--------------------------------------------------------------------------
- # * Alias: Refresh
- #--------------------------------------------------------------------------
- alias game_event_refresh_cxj_fm refresh
- def refresh
- if !@event.pages.empty? && $game_map.free_movement_enabled?
- get_collision_from_comment(@event.pages[0].list)
- end
- game_event_refresh_cxj_fm
- set_current_collision if $game_map.free_movement_enabled?
- end
- #--------------------------------------------------------------------------
- # * New: Set Current Collision
- #--------------------------------------------------------------------------
- def set_current_collision
- @event.pages.each do |page|
- if conditions_met?(page)
- get_collision_from_comment(page.list)
- end
- end
- end
- #--------------------------------------------------------------------------
- # * New: Set Collision From Comment Tags
- #--------------------------------------------------------------------------
- def get_collision_from_comment(list)
- list.each do |command|
- if command.code == 108 || command.code == 408
- case command.parameters[0]
- when /<collisionbox:[ ]*(\d+),[ ]*(\d+),[ ]*(\d+),[ ]*(\d+)>/i
- @collisionbox = Rect.new($1, $2, $3, $4)
- when /<collisionbox:[ ]*(.+?)>/i
- collision = CXJ::FREE_MOVEMENT::COLLISION[$1] if !CXJ::FREE_MOVEMENT::COLLISION[$1].nil?
- @collisionbox = Rect.new(collision[0], collision[1], collision[2], collision[3])
- end
- end
- end
- end
- #--------------------------------------------------------------------------
- # * New: Initialize Public Member Variables
- #--------------------------------------------------------------------------
- def set_collision_rect(*args)
- return if args.empty?
- x = 0
- y = 0
- width = 32
- height = 32
- if args[0].instance_of?(String)
- collision = CXJ::FREE_MOVEMENT::COLLISION[args[0]]
- if !collision.nil? && !collision.empty?
- x = collision[0]
- y = collision[1]
- width = collision[2]
- height = collision[3]
- end
- else
- x = args[0]
- y = args[1] if args.size >=2
- width = args[2] if args.size >= 3
- height = args[3] if args.size >= 4
- end
- @collisionbox = Rect.new(x, y, width, height)
- end
- #--------------------------------------------------------------------------
- # * New: Collision Rectangle
- # Gets the collision rectangle.
- #--------------------------------------------------------------------------
- def collision_rect
- return @collisionbox
- end
- #--------------------------------------------------------------------------
- # * Alias: Detect Collision with Player (Including Followers)
- #--------------------------------------------------------------------------
- alias game_event_collide_with_player_characters_cxj_fm? collide_with_player_characters?
- def collide_with_player_characters?(x, y)
- return game_event_collide_with_player_characters_cxj_fm?(x, y) if !$game_map.free_movement_enabled?
- normal_priority? && $game_player.collide_rect?(x, y, collision_rect)
- end
- #--------------------------------------------------------------------------
- # * Alias: Determine if Touch Event is Triggered
- #--------------------------------------------------------------------------
- alias game_event_check_event_trigger_touch_cxj_fm check_event_trigger_touch
- def check_event_trigger_touch(x, y)
- if $game_map.free_movement_enabled?
- return if $game_map.interpreter.running?
- if @trigger == 2 && $game_player.pos_rect?(x, y, $game_player.collision_rect)
- start if !jumping? && normal_priority?
- end
- else
- game_event_check_event_trigger_touch_cxj_fm(x, y)
- end
- end
- #--------------------------------------------------------------------------
- # * New: Add Character to Touch List
- # Keeps track of characters already touching this event.
- #--------------------------------------------------------------------------
- def add_touch(character)
- @touch_chars.push(character) unless is_touching?(character)
- end
- #--------------------------------------------------------------------------
- # * New: Checks if the current event is touching.
- #--------------------------------------------------------------------------
- def is_touching?(character)
- @touch_chars.include?(character)
- end
- #--------------------------------------------------------------------------
- # * New: Event Name
- #--------------------------------------------------------------------------
- def name
- @event.name
- end
- end
- #==============================================================================
- # ** Game_Follower
- #------------------------------------------------------------------------------
- # This class handles followers. A follower is an allied character, other than
- # the front character, displayed in the party. It is referenced within the
- # Game_Followers class.
- #==============================================================================
- class Game_Follower < Game_Character
- #--------------------------------------------------------------------------
- # * Alias: Object Initialization
- #--------------------------------------------------------------------------
- alias game_follower_initialize_cxj_fm initialize
- def initialize(member_index, preceding_character)
- game_follower_initialize_cxj_fm(member_index, preceding_character)
- @force_chase = false
- @board = false
- @through = CXJ::FREE_MOVEMENT::FOLLOWER_THROUGH
- @custom_collision = nil
- end
- #--------------------------------------------------------------------------
- # * Alias: Refresh
- #--------------------------------------------------------------------------
- alias game_follower_refresh_cxj_fm refresh
- def refresh
- game_follower_refresh_cxj_fm
- return if actor.nil? || !$game_map.free_movement_enabled?
- @custom_collision = nil
- @interaction = CXJ::FREE_MOVEMENT::INTERACTION["DEFAULT"]
- actor.actor.note.split(/[\r\n]+/).each { |line|
- case line
- when /<collisionbox:[ ]*(\d+),[ ]*(\d+),[ ]*(\d+),[ ]*(\d+)>/i
- @custom_collision = Rect.new($1, $2, $3, $4)
- when /<collisionbox:[ ]*(.+?)>/i
- collision = CXJ::FREE_MOVEMENT::COLLISION[$1] if !CXJ::FREE_MOVEMENT::COLLISION[$1].nil?
- @custom_collision = Rect.new(collision[0], collision[1], collision[2], collision[3])
- end
- }
- end
- #--------------------------------------------------------------------------
- # * New: Collision Rectangle
- # Gets the collision rectangle.
- #--------------------------------------------------------------------------
- def collision_rect
- return @custom_collision if !@custom_collision.nil?
- return super
- end
- #--------------------------------------------------------------------------
- # * Alias: Pursue Preceding Character
- #--------------------------------------------------------------------------
- alias game_follower_chase_preceding_character_cxj_fm chase_preceding_character
- def chase_preceding_character
- if $game_map.free_movement_enabled?
- unless moving?
- if @board
- @x = @preceding_character.x
- @y = @preceding_character.y
- @board = false
- elsif CXJ::FREE_MOVEMENT::FOLLOW_TYPE == :trace && !@force_chase
- max_list_size = CXJ::FREE_MOVEMENT::FOLLOWERS_DISTANCE / CXJ::FREE_MOVEMENT::PIXELS_PER_STEP
- if(@preceding_character.pos_list_size > max_list_size)
- while @preceding_character.pos_list_size > max_list_size
- pos = @preceding_character.get_coords_from_pos_list
- unless pos.nil?
- sx = distance_x_from(pos[:x])
- sy = distance_y_from(pos[:y])
- horz = (sx > 0 ? -1 : sx < 0 ? 1 : 0)
- vert = (sy > 0 ? -1 : sy < 0 ? 1 : 0)
- d = horz + (vert == 0 && horz == 0 ? 0 : 5 - vert * 3)
- set_direction(d)
- pixelstep = CXJ::FREE_MOVEMENT::PIXELS_PER_STEP / 32.0
- @x = @x + horz * pixelstep
- @y = @y + vert * pixelstep
- @pos_list.push({:x => @real_x, :y => @real_y})
- @pos_list.shift if @pos_list.size > CXJ::FREE_MOVEMENT::FOLLOWERS_DISTANCE * 2
- if(!jumping?)
- @x = $game_map.round_x(@x)
- @y = $game_map.round_y(@y)
- @real_x = @x - horz * pixelstep
- @real_y = @y - vert * pixelstep
- increase_steps
- end
- end
- end
- end
- elsif @force_chase
- dist = CXJ::FREE_MOVEMENT::FOLLOWERS_DISTANCE / 32.0
- mrgn = CXJ::FREE_MOVEMENT::FOLLOWERS_DISTANCE_MARGIN / 32.0
- sx = distance_x_from(@preceding_character.x)
- sy = distance_y_from(@preceding_character.y)
- sd = Math.hypot(sx, sy)
- if(sd > dist && sx.abs > mrgn && sy.abs > mrgn)
- @move_poll+=[[(sx > 0 ? -1 : 1) + (sy > 0 ? 8 : 2), true]]
- elsif sx.abs > dist && sx.abs > sy.abs
- @move_poll+=[[sx > 0 ? 4 : 6, true]]
- elsif sy.abs > dist && sx.abs < sy.abs
- @move_poll+=[[sy > 0 ? 8 : 2, true]]
- end
- end
- end
- else
- game_follower_chase_preceding_character_cxj_fm
- end
- end
- #--------------------------------------------------------------------------
- # * New: The Distance To Preceding Character
- #--------------------------------------------------------------------------
- def distance_preceding_character
- sx = distance_x_from(@preceding_character.x)
- sy = distance_y_from(@preceding_character.y)
- return Math.hypot(sx, sy)
- end
- #--------------------------------------------------------------------------
- # * New: Processes Movement
- #--------------------------------------------------------------------------
- def process_move(horz, vert)
- super(horz, vert)
- dist = CXJ::FREE_MOVEMENT::FOLLOWERS_DISTANCE / 32.0
- if distance_preceding_character > dist && @move_poll.size == 0
- @force_chase = true
- chase_preceding_character
- @force_chase = false
- end
- end
- #--------------------------------------------------------------------------
- # * New: Sets the Character To Board
- #--------------------------------------------------------------------------
- def board
- @board = true
- end
- end
- #==============================================================================
- # ** Game_Interpreter
- #------------------------------------------------------------------------------
- # An interpreter for executing event commands. This class is used within the
- # Game_Map, Game_Troop, and Game_Event classes.
- #==============================================================================
- class Game_Interpreter
- #--------------------------------------------------------------------------
- # * New: Set Collision Rectangle From Event Script
- #--------------------------------------------------------------------------
- def set_collision_rect(*args)
- $game_map.events[@event_id].set_collision_rect(*args)
- end
- end
- if(CXJ::FREE_MOVEMENT::SHOW_COLLISION_BOXES)
- #============================================================================
- # ** Sprite_CollisionBox
- #----------------------------------------------------------------------------
- # This sprite is used to display collision boxes. It's mainly used for
- # debugging purposes.
- #============================================================================
- class Sprite_CollisionBox < Sprite
- #------------------------------------------------------------------------
- # * New: Initialization
- #------------------------------------------------------------------------
- def initialize(viewport, parent_sprite = nil)
- super(viewport)
- @color = Color.new(0, 255, 0, 128)
- @icolor = Color.new(255, 0, 0, 128)
- @parent_sprite = parent_sprite
- self.bitmap = Bitmap.new(96, 96)
- update
- end
- #------------------------------------------------------------------------
- # * New: Update Per Frame
- #------------------------------------------------------------------------
- def update
- self.x = @parent_sprite.x
- self.y = @parent_sprite.y
- draw_box
- end
- #------------------------------------------------------------------------
- # * New: Draw Collision Box
- #------------------------------------------------------------------------
- def draw_box
- self.ox = 48
- self.oy = 60
- self.bitmap.clear
- return if @parent_sprite.character.through && @parent_sprite.character.transparent
- return if @parent_sprite.character.instance_of?(Game_Vehicle) && !@parent_sprite.character.on_map?
- col_rect = @parent_sprite.character.collision_rect
- self.bitmap.fill_rect(col_rect.x + 32, col_rect.y + 32, col_rect.width, col_rect.height, @color)
- if(@parent_sprite.character == $game_player)
- int_rec = $game_player.interaction_rect
- d = $game_player.direction
- horz = (d - 1) % 3 - 1
- vert = 1 - ((d - 1) / 3)
- int_rect = Rect.new(int_rec.x + 32 + 32 * horz, int_rec.y + 32 + 32 * vert, int_rec.width, int_rec.height)
- self.bitmap.fill_rect(int_rect, @icolor)
- end
- end
- end
- #============================================================================
- # ** Spriteset_Map
- #----------------------------------------------------------------------------
- # This class brings together map screen sprites, tilemaps, etc. It's used
- # within the Scene_Map class.
- #============================================================================
- class Spriteset_Map
- #--------------------------------------------------------------------------
- # * Alias: Create Character Sprite
- #--------------------------------------------------------------------------
- alias spriteset_map_create_characters_cxj_fm create_characters
- def create_characters
- spriteset_map_create_characters_cxj_fm
- @collision_sprites = []
- @character_sprites.each do |char|
- @collision_sprites.push(Sprite_CollisionBox.new(@viewport, char))
- end
- end
- #--------------------------------------------------------------------------
- # * Alias: Update Character Sprite
- #--------------------------------------------------------------------------
- alias spriteset_map_update_characters_cxj_fm update_characters
- def update_characters
- spriteset_map_update_characters_cxj_fm
- @collision_sprites.each {|sprite| sprite.update }
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement