Krótki opis:
Skrypt daje inteligentne szukanie ścierzek przez zdarzenia
Autor:
Blizzard
Kompatybilność:
RPG Maker XP
Skrypt:
Spoiler:
Kod:
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# Lagless Path Finder by Blizzard
# Version: 1.0
# Type: Pathfinding System
# Date: 9.2.2013
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# This work is protected by the following license:
# #----------------------------------------------------------------------------
# #
# # Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
# # ( http://creativecommons.org/licenses/by-nc-sa/3.0/ )
# #
# # You are free:
# #
# # to Share - to copy, distribute and transmit the work
# # to Remix - to adapt 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).
# #
# # Noncommercial. You may not use this work for commercial purposes.
# #
# # Share alike. If you alter, transform, or build upon this work, you may
# # distribute the resulting work only under the same or similar license to
# # this one.
# #
# # - 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.
# #
# # - Any of the above conditions can be waived if you get permission from the
# # copyright holder.
# #
# # - Nothing in this license impairs or restricts the author's moral rights.
# #
# #----------------------------------------------------------------------------
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# IMPORTANT NOTE:
#
# This Path Finder is a derived version of Blizz-ABS's original Path Finder.
# If you are using Blizz-ABS, please remove this script. Blizz-ABS has a
# Path Finder already built-in.
#
#
# Compatibility:
#
# 99% compatible with SDK v1.x. 90% compatible with SDK v2.x. May cause
# incompatibility issues with exotic map systems.
#
#
# Features:
#
# - calculates path from point A to point B on the map
# - allows immediate calculation as well as path calculation requests that
# are done over the course of a few frames in order to reduce lag
# - supports dynamic calculation that is done every step to ensure the
# character reaches its targets
# - can assign other characters as targets so dynamic calculation with a
# moving will cause the character to find the target regardless of his
# changed position
#
#
# Instructions:
#
# - Explanation:
#
# This script will allow your characters to walk from point A to point B,
# navigating by themselves, finding the shortest path and all that without
# you having to manually specify their moving route. They can also navigate
# through dynamically changing environments or track a dynamically moving
# target.
#
# - Configuration:
#
# MAX_NODES_PER_FRAME - maximum number of node calculation per frame when
# using path requests instead of immediate calculations
# DIRECTIONS_8_WAY - if set to true, it will smooth out corner movement
# and use a diagonal movement step wherever possible
# (this does NOT mean that the path finder will do
# 8-directional path finding!)
#
# - Script calls:
#
# This path finder offers you several script calls in order to designate path
# finding to characters on the map. Following script calls are at your
# disposal:
#
# PathFinder.find(C_ID, X, Y)
# PathFinder.find(C_ID, X, Y, RANGE)
# PathFinder.find(C_ID, TARGET)
# PathFinder.find(C_ID, TARGET, RANGE)
# PathFinder.request(C_ID, X, Y)
# PathFinder.request(C_ID, X, Y, RANGE)
# PathFinder.request(C_ID, TARGET)
# PathFinder.request(C_ID, TARGET, RANGE)
# PathFinder.dyn_find(C_ID, X, Y)
# PathFinder.dyn_find(C_ID, X, Y, RANGE)
# PathFinder.dyn_find(C_ID, TARGET)
# PathFinder.dyn_find(C_ID, TARGET, RANGE)
# PathFinder.dyn_request(C_ID, X, Y)
# PathFinder.dyn_request(C_ID, X, Y, RANGE)
# PathFinder.dyn_request(C_ID, TARGET)
# PathFinder.dyn_request(C_ID, TARGET, RANGE)
#
# C_ID - either an event ID, 0 for the player character or an actual
# character (e.g. $game_map.events[ID])
# X - X target coordinate
# Y - Y target coordinate
# RANGE - range within which the target should be located (greater than 0)
# TARGET - an actual target character
#
# This is how the 4 different script calls behave:
#
# - The "find" variants always calculate the path immediately.
# - The "request" variants always request a path calculation to be done over
# the course of several frames in order to avoid lag. Requesting paths for
# multiple characters will cause the calculation to take longer as each
# frame only a certain number of nodes is calculated (can be configured).
# So if there are more characters requesting a path, naturally each one
# will consume a part of the allowed node calculations every frame.
# - The "dyn" variants (dynamic) will recalculate/request a calculation every
# step in order to keep a path up to date with an ever-changing
# environment. You won't need to use these calls if there are no moving
# events on the map or if there are no environmental passability changes.
# - When using a "dyn" variant, if actual coordinates (X, Y) are used, the
# character will find its path to these fixed coordinates. If an actual
# target character is being used, the path finder will track the character
# instead of fixed coordinates. If the character changes its position, the
# path calculation will attempt to find a path to the new position of the
# target.
# - Using "dyn_find" a lot, with many characters at the same time and/or for
# long paths may cause performance issue and lag. Use it wisely.
# - Using "dyn_request" is much more performance-friendly, but it will also
# cause characters to "stop and think". This can also cause problems in a
# constantly changing environment as the environment may change during the
# few frames while the calculation is being done. Use it wisely.
#
# In order to cancel dynamic path calculation for a character, use following
# script call:
#
# character.clear_path_target
#
# Example:
#
# $game_map.events[23].clear_path_target
#
# In order to check if a character has a dynamic path calculation for a
# target, use following script call:
#
# character.has_path_target?
#
# Example:
#
# if $game_map.events[23].has_path_target?
#
#
# Notes:
#
# - This path finder is an implementation fo the A* Search Algorithm.
# - The PathFinder module is being updated during the call of $game_system.update.
# Keep this in mind if you are using specific exotic scripts.
#
#
# If you find any bugs, please report them here:
# http://forum.chaos-project.com
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
def self.find(char, x, y = nil, range = 0)
char, x, y, range = self.check_args(char, x, y, range)
self._find(char, x, y, range, false)
return true
end
def self.dyn_find(char, x, y = nil, range = 0)
tx, ty = x, y
char, x, y, range = self.check_args(char, x, y, range)
self._find(char, x, y, range, true)
char.set_path_target(tx, ty, range, true)
return true
end
def self.request(char, x, y = nil, range = 0)
char, x, y, range = self.check_args(char, x, y, range)
self._request(char, x, y, range, false)
return true
end
def self.dyn_request(char, x, y = nil, range = 0)
char, x, y, range = self.check_args(char, x, y, range)
self._request(char, x, y, range, true)
char.set_path_target(tx, ty, range, false)
return true
end
def self.check_args(char, x, y, range)
if x.is_a?(Game_Character)
range = (y != nil ? y : 0)
y = x.y
x = x.x
end
range = 0 if range < 0
if char.is_a?(Numeric)
char = (char > 0 ? $game_map.events[char] : $game_player)
end
p "Warning! Character to move does not exist!" if $DEBUG && char == nil
return [char, x, y, range]
end
def self._find(char, x, y, range, dynamic)
@requests[char] = PathRequest.new(char.x, char.y, x, y, range, dynamic)
result = nil
result = self.calc_node(char) while result == nil
@requests.delete(char)
if $DEBUG && result == []
p "Warning! Path Finder could not find path for character at (#{x},#{y})!"
end
char.set_found_path(result)
end
def self._request(char, x, y, range, dynamic)
if @requests[char] == nil
@requests[char] = PathRequest.new(char.x, char.y, x, y, range, dynamic)
end
end
def self.update
@requests = {} if @requests == nil
characters = @requests.keys
count = BlizzCFG::MAX_NODES_PER_FRAME
while characters.size > 0 && count > 0
char = characters.shift
result = self.calc_node(char)
result != nil ? char.set_found_path(result) : characters.push(char)
count -= 1
end
end
def self.calc_node(char)
request = @requests[char]
if request.open.size == 0
@requests.delete(char)
return []
end
found = false
key = request.open.keys.min {|a, b|
a[2] > b[2] ? 1 : (a[2] < b[2] ? -1 :
(Math.hypot_squared(a[0] - request.tx, a[1] - request.ty) <=>
Math.hypot_squared(b[0] - request.tx, b[1] - request.ty)))}
request.closed[key[0], key[1]] = request.open[key]
request.open.delete(key)
kx, ky = 0, 0
passable = false
passable_checked = false
PATH_DIRS.each {|dir|
kx, ky = key[0] + dir[0], key[1] + dir[1]
if request.range == 0 && kx == request.tx && ky == request.ty
request.closed[kx, ky] = dir[2]
found = true
break
end
passable = false
passable_checked = false
if request.range > 0 &&
(kx - request.tx).abs + (ky - request.ty).abs <= request.range
passable = char.passable?(key[0], key[1], dir[2])
passable_checked = true
if passable
request.closed[kx, ky] = dir[2]
found = true
break
end
end
if request.closed[kx, ky] == 0
passable = char.passable?(key[0], key[1], dir[2]) if !passable_checked
if passable
request.open[[kx, ky, key[2] + 1]] = dir[2]
end
end}
return nil if !found
result = request.backtrack(kx, ky)
@requests.delete(char)
return result
end
def set_found_path(path)
return if path.size == 0
route = RPG::MoveRoute.new
route.repeat = false
# each move command code equals direction / 2
path.reverse.each {|dir| route.list.unshift(RPG::MoveCommand.new(dir / 2))}
self.force_move_route(route)
end
alias update_move_lagless_path_finder_later update_move
def update_move
update_move_lagless_path_finder_later
return if self.moving? || !self.has_path_target?
x, y = @path_x, @path_y
x, y = @path_x.x, @path_x.y if @path_x.is_a?(Game_Character)
if @x == x && @y == y
#p @x, x, @y, y
#p @path_x
self.clear_path_target
elsif @path_immediate
PathFinder.dyn_find(self, @path_x, @path_y, @path_range)
else
PathFinder.dyn_request(self, @path_x, @path_y, @path_range)
end
end
Nie możesz pisać nowych tematów Nie możesz odpowiadać w tematach Nie możesz zmieniać swoich postów Nie możesz usuwać swoich postów Nie możesz głosować w ankietach Nie możesz załączać plików na tym forum Możesz ściągać załączniki na tym forum