Pathfinding

Venima

Treasure experiences and sensations, not progress.
Veteran
Joined
Oct 8, 2013
Messages
128
Reaction score
48
First Language
English
Primarily Uses
N/A
Forget parallel processing, you don't need it. I'm not sure which version of the script you have, so here's the up to date one I use:

#===============================================================================# Pathfinding & Event formations

# By Jet10985(Jet) & Venima

#===============================================================================

# This script will allow you to use a pathfinder to move players or events.

# Modification: This script will also allow you to use a pathfinder which 

# incorporates formation handling.

# This script has: 2 customization options.

#

# Modifications:

# Pathfinder:

# Goal location may now be inpassable, pathfinder will still reach it.

# Pathfinder still works "as intended" when the move route is set to repeat.

# Added parameter: distance (explained below).

# Added parameter: jump (set to true if the moves should be jumps instead of

# walking).

# Added parameter: commonEvent (provide the common event id for the pathfinder

# to run the event before each move (useful for adding sound or effects to 

# movements)

# Added parameters: 

# catchup (provide a value to indicate how far from the target the event 

#   should be before it speeds up its movement)

# catchupSpeed (provide a value for the speed when catching up)

# normalSpeed (provide a value for the speed after its caught up)

# Note: Pathfinder is a bit more processor heavy when used with a repeating 

# move route (it was useless before, so this is only a benefit)

# Formations:

# Added find_formation_path function

# Added turn_with_player function

#

#===============================================================================

# Overwritten Methods:

# None

#-------------------------------------------------------------------------------

# Aliased methods:

# None

#===============================================================================

=begin

 

===============================================================================

 Instructions:

 

===============================================================================

 Standard pathfinder:

-------------------------------------------------------------------------------

 

To move a player or event, use this in a move route's "Script..." command:

 

find_path(x, y, distance = 0, jump = false, commonEvent = 0, catchup = 0, 

      catchupSpeed = 5, normalSpeed = 4)

 

x is the target x

 

y is the targey y

 

distance is set to 0 by default and can be omitted to keep the default value.

While x and y represent the target location, the event will only be moved 

up to the specified distance from the target. This makes it easier to have 

an event follow the player, without getting in the player's way. This could 

be used as an alternative to following, except it works on any events, 

not just party members.

 

jump is set to false by default and can be omitted. Jump specifies that 

instead of the event "moving" to the target, the event will make small "jumps" 

to the target. If you specify jump, you cannot omit any previous parameters.

 

commonEvent is set to 0 by default and can be omitted. This specifies the 

id of a common event that you want executed before each move step. Currently

this only applies to repeating paths. When set to 0, no common event is called.

If you specify commonEvent you cannot omit any previous parameters.

 

catchup is set to 0 by default and can be omitted. Catchup specifies that if

the event is equal to or past the catchup distance, they will move faster to 

"catch up". Their speed becomes the catchUp speed. Once caught up, they will 

return to the normalSpeed. If you specify catchup you cannot omit any previous 

parameters.

 

catchupSpeed is set to 5 by default and can be omitted. It is used when catchup 

is specified to a value above 0. (see catchup for details). If you specify 

catchupSpeed you cannot omit any previous parameters.

 

normalSpeed is set to 5 by default and can be omitted. It is used when catchup 

is specified to a value above 0. (see catchup for details). If you specify 

normalSpeed you cannot omit any previous parameters.

 

 

 

Running the script outside of a move route (as a standalone script call)

has two extra parameters after x and y called "ev" and "wait" but has no 

commonEvent or catcup parameters.

 

find_path(x, y, ev = 0, wait = false, distance = 0, jump = false)

 

ev is set to 0 by default and can be omitted like so: find_path(9, 4).

Ev represents which character is to be moved. -1 is the player, 0 is the

calling event, and anything above is an event on the map whose ID is the ev.

 

wait is set to false by default and can be omitted like so: 

find_path(9, 4) or find_path(9, 4, -1)

find_path(x, y) or find_path(x, y, ev)

wait specifies if the player will have to wait for the move route to finish

to start moving again.

 

-------------------------------------------------------------------------------

 Examples:

 

Example of following the player at a distance:

 

In event's custom move route or specified move route (on repeat): 

  find_path($game_player.x, $game_player.y, 3)

  

Example of an event following an event with id 2 and catching up:

  find_path($game_events[2].x, $game_events[2].y, 0, false, 0, 3)

 

===============================================================================

 Formation handling:

-------------------------------------------------------------------------------

 

To move an event using a formation use this in a move route:

 

find_formation_path(followId, shiftX, shiftY, catchup = FORM_CATCHUP_DIST, 

      catchupSpeed = 5, normalSpeed = 4)

      

followId is the character that this event is in formation with. -1 = player,

0 = current event (although this is pointless) and above 0 is the event id.

 

shiftX is the relational x position from the followId character WHEN that 

character faces "down". If you enter -1, this event will move to the left if 

its facing down, or right if its facing up.

 

shiftY is the relational y position from the followId character WHEN that

character faces "down". If you enter -1, this event will move above if its 

facing down, or below if it's facing up.

 

catchup's default value is specified by the parameter FORM_CATCHUP_DIST and

can be omitted. This specifies how far behind this event can get before it 

speeds up to catch up.

 

catchupSpeed's default value is 5 and can be omitted. This specifies how fast 

this event will move when it's "catching up". If you specify catchupSpeed, you 

cannot omit any previous parameters.

 

normalSpeed's default value is 4 and can be omitted. This specifies how fast 

this event will move when it isn't "catching up". If you specify normalSpeed, 

you cannot omit any previous parameters.

 

 

You also have another command for formations:

Entering "turn_with_leader" as a separate script after find_formation_path

will cause the event to turn the same way the player is turned after arriving 

at their formation position.

Entering "turn_with_leader(1)" will turn the same way as event with id 1.

Turn_with_leader also has a second optional parameter. Entering "left" or -1

will turn this event left of the leader's direction, entering "right" or 1

will turn this event right of the leader's direction, and entering "back" or 2 

will turn this event opposite of the leader's direction. Again, if you specify 

this parameter, you cannot omit the previous one. 

 

-------------------------------------------------------------------------------

 Examples:

 

Example of 2 events acting similar to followers behind the player:

In a repeating move-route for Event 01:

find_formation_path(-1,0,-1)

In a repeating move_route for Event 02:

find_formation_path(1,0,-1)

 

Example of an event covering the player's back 2 spaces away:

In a repeating move-route:

find_formation_path(-1,0,-2)

turn_with_leader(-1,"back")

 

Example of an event with a formation determined by in-game variables:

In a repeating move-route:

find_formation_path(-1, $game_variables[1], $game_variables[2])

 

=end

 

#===============================================================================

# Customisation options below:

#===============================================================================

module Venima

  module Formations

    #

    FORM_CATCHUP_DIST = 3

  end

end

 

module Jet

  module Pathfinder

    

    # While mainly for coders, you may change this value to allow the

    # pathfinder more time to find a path. 1000 is default, as it is enough for

    # a 100x100 MAZE so, yeah.

    # Note from Venima, you probably don't want to change this value too much

    MAXIMUM_ITERATIONS = 500

    

  end

end

#===============================================================================

# Customisation end

#===============================================================================

 

class Node

  

  include Comparable

 

  attr_accessor :point, :parent, :cost, :cost_estimated

 

  def initialize(point)

    @point = point

    @cost = 0

    @cost_estimated = 0

    @on_path = false

    @parent = nil

  end

 

  def mark_path

    @on_path = true

    @parent.mark_path if @parent

  end

   

  def total_cost

    cost + cost_estimated

  end

 

  def <=>(other)

    total_cost <=> other.total_cost

  end

   

  def ==(other)

    point == other.point

  end

end

 

class Point

  

  attr_accessor :x, :y

  

  def initialize(x, y)

    @x, @y = x, y

  end

 

  def ==(other)

    return false unless Point === other

    @x == other.x && @y == other.y

  end

 

  def distance(other)

    (@x - other.x).abs + (@y - other.y).abs

  end

 

  def relative(xr, yr)

    Point.new(x + xr, y + yr)

  end

end

 

class Game_Map

  

  def each_neighbor(node, char = $game_player)

    x = node.point.x

    y = node.point.y

    nodes = []

    4.times {|i|

      i += 1

      new_x = round_x_with_direction(x, i * 2)

      new_y = round_y_with_direction(y, i * 2)

      next unless char.passable?(x, y, i * 2)

      #removed line below (technically, if your goal is an inpassable block,

      # e.g. an event, you can still reach it)

      #next unless char.passable?(new_x, new_y, 10 - i * 2)

      nodes.push(Node.new(Point.new(new_x, new_y)))

    }

    nodes

  end

  

  def find_path(tx, ty, sx, sy, dist, jump, char = $game_player)

    start = Node.new(Point.new(sx, sy))

    goal = Node.new(Point.new(tx, ty))

    return [] if start == goal or (dist > 0 and start.point.distance(goal.point) <= dist)

    return [] if ![2, 4, 6, 8].any? {|i| char.passable?(tx, ty, i) }

    open_set = [start]

    closed_set = []

    path = []

    iterations = 0

    loop do

      return [] if iterations == Jet::pathfinder::MAXIMUM_ITERATIONS

      iterations += 1

      current = open_set.min

      return [] unless current

      each_neighbor(current, char).each {|node|

        if node == goal or (dist > 0 and node.point.distance(goal.point) <= dist)

          node.parent = current

          node.mark_path

          return recreate_path(node, jump)

        end

        next if closed_set.include?(node)

        cost = current.cost + 1

        if open_set.include?(node)

          if cost < node.cost

            node.parent = current

            node.cost = cost

          end

        else

          open_set << node

          node.parent = current

          node.cost = cost

          node.cost_estimated = node.point.distance(goal.point)

        end

      }

      closed_set << open_set.delete(current)

    end

  end

  

  def recreate_path(node, jump)

    path = []

    hash = {[1, 0] => 6, [-1, 0] => 4, [0, 1] => 2, [0, -1] => 8}

    until node.nil?

      pos = node.point

      node = node.parent

      next if node.nil?

      ar = [pos.x <=> node.point.x, pos.y <=> node.point.y]

      if jump

        path.push(RPG::MoveCommand.new(14,ar))

      else

        path.push(RPG::MoveCommand.new(hash[ar] / 2))

      end

    end

    return path

  end

end

 

class Game_Character

  

  #modified function (added handling for repeated move route (recalculates path 

  # each step so it doesn't just loop it's old path route and will revalidate  

  # if x or y changes, will follow variable value if x and y are set to it)

  def find_path(x, y, dist = 0, jump = false, commonEvent = 0, catchup = 0, catchupSpeed = 5, normalSpeed = 4)

    path = $game_map.find_path(x, y, self.x, self.y, dist, jump).reverse

    if !@move_route.repeat

      @move_route.list.delete_at(@move_route_index)

      @move_route.list.insert(@move_route_index, *path)

      @move_route_index -= 1

    elsif path.length > 0

      if commonEvent > 0

        $game_temp.reserve_common_event(commonEvent)

      end

      if catchup > 0

        if @move_speed < catchupSpeed && path.length >= catchup

          process_move_command(RPG::MoveCommand.new(29,[catchupSpeed]))

        elsif @move_speed >= catchupSpeed && path.length < 2

          process_move_command(RPG::MoveCommand.new(29,[normalSpeed]))

        end

      end

      process_move_command(path[0])

      @move_route_index -= 1

    end

    return path.length

  end

 

  def get_character(i)

    if i == -1

      return $game_player

    end

    if i == 0

      return $game_map.events[@event_id]

    end

    if i > 0

      return $game_map.events

    end

  end

  

  def find_formation_path(followId, shiftX, shiftY, catchup = Venima::Formations::FORM_CATCHUP_DIST, catchupSpeed = 5, normalSpeed = 4)

    x = shift_follow_x(followId, shiftX, shiftY)

    y = shift_follow_y(followId, shiftX, shiftY)

    if find_path(x,y,0,false,0,catchup,catchupSpeed,normalSpeed) == 0

      char = get_character(followId)

      find_path(char.x,char.y,3,false,0,catchup,catchupSpeed,normalSpeed)

    end

  end

  

  def shift_follow_x(followId, shiftX, shiftY)

    char = get_character(followId)

    case char.direction

    when 2

      return char.x + shiftX

    when 4

      return char.x - shiftY

    when 6

      return char.x + shiftY

    when 8

      return char.x - shiftX

    end

    return char.x

  end

  

  def shift_follow_y(followId, shiftX, shiftY)

    char = get_character(followId)

    case char.direction

    when 2

      return char.y + shiftY

    when 4

      return char.y - shiftX

    when 6

      return char.y + shiftX

    when 8

      return char.y - shiftY

    end

    return char.y

  end

  

  def turn_with_leader(eventId = -1, dirmod = "")

    dir = get_character(eventId).direction

    mod = 0

    if dirmod == "left" || dirmod == -1

      case dir

      when 2

        set_direction(4)

      when 4

        set_direction(2)

      when 6

        set_direction(8)

      when 8

        set_direction(6)

      end

    elsif dirmod == "right" || dirmod == 1

      case dir

      when 2

        set_direction(6)

      when 4

        set_direction(8)

      when 6

        set_direction(2)

      when 8

        set_direction(4)

      end

    elsif dirmod == "back" || dirmod == 2

      case dir

      when 2

        set_direction(8)

      when 4

        set_direction(6)

      when 6

        set_direction(4)

      when 8

        set_direction(2)

      end

    else

      set_direction(dir) 

    end

  end

end

 

class Game_Interpreter

  

  #modified line below (added distance parameter)

  def find_path(x, y, ev = 0, wait = false, dist = 0, jump = false)

    char = get_character(ev)

    #modified line below (added distance parameter)

    path = $game_map.find_path(x, y, char.x, char.y, dist, jump)

    path.reverse!

    path.push(RPG::MoveCommand.new(0))

    route = RPG::MoveRoute.new

    route.list = path

    route.wait = wait

    route.skippable = true

    route.repeat = false

    char.force_move_route(route)

  end

end
 

And how to call it making use of the inbuilt common-event call: find_path($game_player.x, $game_player.y, 0, false, 0); Change the last '0' to the id of the common event you wish to call. (This common event is called every time the event makes a step)
 
Last edited by a moderator:

Blue001

Veteran
Veteran
Joined
Jan 13, 2014
Messages
231
Reaction score
112
First Language
English
Primarily Uses
RMMV
I set it all up with your script... but Instead of using a common event, I just put a 'wait' after the move event (which has only your suggested call in it), and after 20ms, had a blank move event which stopped the enemy after one move. So that worked fine...

So it looks like this...

Move Event with script find_path($game_player.x, $game_player.y, 0, false, 0)

Wait 20ms

Move Event with nothing in it.

The odd thing is though. After the player moves again, the monster repeats his first move, over and over. He basically goes straight up... or down... depending on where my player went from the start. Not sure whats going on. Is it not clearing the original move route info even though I have another move route override it?

EDIT  : Nevermind... even though I dont actually want it to repeat, nor will it be able to since I cut it off, I saw your mention of the repeat fix... so I set that on and it works perfectly. THANKS!
 
Last edited by a moderator:

Venima

Treasure experiences and sensations, not progress.
Veteran
Joined
Oct 8, 2013
Messages
128
Reaction score
48
First Language
English
Primarily Uses
N/A
EDIT  : Nevermind... even though I dont actually want it to repeat, nor will it be able to since I cut it off, I saw your mention of the repeat fix... so I set that on and it works perfectly. THANKS!
Yeah, it's not very intuitive, but not having repeat on is pretty much just for cutscene type stuff.
 

Zerphoon

Veteran
Veteran
Joined
Jul 30, 2012
Messages
31
Reaction score
4
First Language
English
Primarily Uses
Is there a way to get them to use transfers? like If I had them in a castle and wanted them to move to a certain area in a garden level by going through the exit to the garden without interrupting the move sequence??
 

Venima

Treasure experiences and sensations, not progress.
Veteran
Joined
Oct 8, 2013
Messages
128
Reaction score
48
First Language
English
Primarily Uses
N/A
Is there a way to get them to use transfers? like If I had them in a castle and wanted them to move to a certain area in a garden level by going through the exit to the garden without interrupting the move sequence??
No, events belong to the map, which means they cannot leave the map. Either transfer the player and set up an event to run right away (use find path a second time), or make the garden part of the first map.
 

Zerphoon

Veteran
Veteran
Joined
Jul 30, 2012
Messages
31
Reaction score
4
First Language
English
Primarily Uses
No, events belong to the map, which means they cannot leave the map. Either transfer the player and set up an event to run right away (use find path a second time), or make the garden part of the first map.
So It also won't work if I wanted to move the event to a spot on the map that was blocked off by walls or something that the player would have to traverse through other levels to return to the original map where the event had to move? (Keeping the event on the same map but blocked movement routes)
 

Venima

Treasure experiences and sensations, not progress.
Veteran
Joined
Oct 8, 2013
Messages
128
Reaction score
48
First Language
English
Primarily Uses
N/A
So It also won't work if I wanted to move the event to a spot on the map that was blocked off by walls or something that the player would have to traverse through other levels to return to the original map where the event had to move? (Keeping the event on the same map but blocked movement routes)
Move routes and events have a 'through' option. Look, I'm not here to teach you the basics of RPG Maker. I suggest you go through some tutorials and play around with all the little checkboxes and buttons you find to get a gist of what you can and can't do with it.
 

Zerphoon

Veteran
Veteran
Joined
Jul 30, 2012
Messages
31
Reaction score
4
First Language
English
Primarily Uses
Move routes and events have a 'through' option. Look, I'm not here to teach you the basics of RPG Maker. I suggest you go through some tutorials and play around with all the little checkboxes and buttons you find to get a gist of what you can and can't do with it.
Sorry if I'm annoying you and I know what I "can and can't do" I've been using "rpg maker" probably well before you have. I'm just asking a simple question you don't have to be rude.
 

Venima

Treasure experiences and sensations, not progress.
Veteran
Joined
Oct 8, 2013
Messages
128
Reaction score
48
First Language
English
Primarily Uses
N/A
Sorry if I'm annoying you and I know what I "can and can't do" I've been using "rpg maker" probably well before you have. I'm just asking a simple question you don't have to be rude.
You could try it? I honestly have no idea. I remember it has some handling for events with 'through' checked... but seriously, why bother with a pathfinder, script the move route if you want it to go through stuff (the whole point of a pathfinder is that there are obstacles that a simple 'move towards' can't handle). Maybe pathfind it to a known position and then script the rest of the move?

Or do you mean pathfind across maps? That's sadly impossible, only the current map exists, the rest is just saved data.
 
Last edited by a moderator:

ClockworksGod

Villager
Member
Joined
Mar 13, 2013
Messages
19
Reaction score
0
First Language
English
Primarily Uses
I'm trying to set up an event that will move away from the player toward a specific point, but stop and wait if the player gets too far away. The intent is to create a sort of guide that the player is meant to follow out of a dark cave. Could I accomplish that with this script? 
 

Venima

Treasure experiences and sensations, not progress.
Veteran
Joined
Oct 8, 2013
Messages
128
Reaction score
48
First Language
English
Primarily Uses
N/A
I'm trying to set up an event that will move away from the player toward a specific point, but stop and wait if the player gets too far away. The intent is to create a sort of guide that the player is meant to follow out of a dark cave. Could I accomplish that with this script? 
Yes you can. It will take some playing around but you can do it. The script calls a common event of your choosing after every step (somewhere at the top of the script should explain how to do this), enabling you to do or check whatever you want. In that common event you can add up the distance to the player and check it using a conditional branch.

Getting the distance to the player is probably easier picking the script option and entering something like: $game_variables[0] = ($game_events[0].x - $game_player.x) ** 2 + ($game_events[0].y - $game_player.y) ** 2 and then the conditional branch is the script: $game_variables[0] >= 5 ** 2. Note that 5 is the distance here, (the ** 2 is squaring the numbers which is Pythagoras' theorem for achieving euclidean distance) and the game variable and game event numbers should be chosen according to the ones you want to use.

Inside the conditional branch you'll have to do some playing around to figure out the best way to have the distance repeatedly checked while stationary, if you want the event to continue on of its own accord or the player hits space on him when ready; but to get the event to stop just give him a new blank move route.
 
Last edited by a moderator:

Bex

Veteran
Veteran
Joined
Aug 2, 2013
Messages
1,492
Reaction score
408
First Language
German
Primarily Uses
RMMV
Quick Question, does this Script:

Pathfinding to Event or Player within a Range of 20 to 30 Tiles would be enough for me.

Also to perform this Action to atleast 50 Events on the same Map.

For example in some kind of DayZ Game where Players get Chased by Horde of Infected.

I know it possible with Aproach to Player, but not always good if there are some Obstacles on the Map, like Trees.

Pathfinding to Static Map X,Y per Call per Event would also be ok. 

Dynamic Pathfinding to Player or Event Map X,Y which is changing would be cool.

And i wonder if the Performance cost would difference much?
 
Last edited by a moderator:

Venima

Treasure experiences and sensations, not progress.
Veteran
Joined
Oct 8, 2013
Messages
128
Reaction score
48
First Language
English
Primarily Uses
N/A
 

Quick Question, does this Script:

Pathfinding to Event or Player within a Range of 20 to 30 Tiles would be enough for me.
Uhm, you can very easily combine this script with another that checks distances, which you could write yourself using the code I demonstrated in my previous reply. Use an invisible event that has a parallel process running to check for all your zombie's distances. Give it a wait time like one or two seconds so it's not running too frequently (it will automatically rerun once it's finished the process).

Also to perform this Action to atleast 50 Events on the same Map.

For example in some kind of DayZ Game where Players get Chased by Horde of Infected.

I know it possible with Aproach to Player, but not always good if there are some Obstacles on the Map, like Trees.
To make things more efficient, you could have them set to approach the player first but then when they collide with an obstacle, change their move route to pathfind. There is a script which enables event-to-event triggers, if you're interested I can look that up for you.

Pathfinding to Static Map X,Y per Call per Event would also be ok. 

Dynamic Pathfinding to Player or Event Map X,Y which is changing would be cool.

And i wonder if the Performance cost would difference much?
The performance difference between static pathfinding and dynamic pathfinding (with this simple script) is immense. Essentially in the case of dynamic pathfinding, this script recalculates a new path after every step, whereas in the case of static it only calculates it once.

It is possible for pathfinding to be optimised for dynamic changes, so that it doesn't need to recalculate the whole path, however this script doesn't do that. Instead, you can optimise it in a few ways: I mentioned above you could have the zombie use a simple approach method first and then pathfind once it touches an obstacle. That way the majority of zombies won't even need to perform any pathfinding. Another way would be to use a static pathfinding first to reach the player's old coordinates, and THEN use the dynamic pathfinding to chase him, (simply putting the dynamic pathfinding script below the static one in the move route will do this).This means that by the time the processing-heavy dynamic pathfinder kicks in, the distance from the player is minimised.

You will find even the leading AAA games use optimisation techniques like these, if they can get away with it.
 
Last edited by a moderator:

Bex

Veteran
Veteran
Joined
Aug 2, 2013
Messages
1,492
Reaction score
408
First Language
German
Primarily Uses
RMMV
Static Pthfinding would be enough for me^^ and i could always manualy update the command to another position.

Thanks for answering, wanted to know before Testing it all.
 

SvenVI

Warper
Member
Joined
Dec 20, 2014
Messages
4
Reaction score
0
First Language
English
Primarily Uses
Great script, very useful. But I noticed something which might not have been adressed or come up. When the player is passable (through = ON), the events that use pathfinding won't evade obstacles any more and go in a straight path to their target, bump into something and stop. Took me a while to figure that one out, but I think this shouldn't be the case ;)

Also, is there a way to stop targetfinding if the target is impossible to get to? For instance when the target walks into a corner and gets locked in by 2 other events. Because right now, the whole game just freezes.
 

Venima

Treasure experiences and sensations, not progress.
Veteran
Joined
Oct 8, 2013
Messages
128
Reaction score
48
First Language
English
Primarily Uses
N/A
I'm not developing for this anymore. You may not have my latest version of the code (which will be in a zip in one of my replies). If the problem persists, you'll just have to find your own way around it.

Don't be shy of looking at the code yourself though, if you can do event-ing, it's not that big a leap to tweak/fix a script. You can always revert if you break it ^_^

With regards to the impossible path bug, you could probably check it using event-ing if all else fails.

With regards to the through bug, I reckon the problem is referencing the player but forgetting to check which event is doing the pathfinding. If you want to look into it, hunt for 'through' or 'thru' or whatever they call it in the script. Ctrl+F should help you find it.
 

SvenVI

Warper
Member
Joined
Dec 20, 2014
Messages
4
Reaction score
0
First Language
English
Primarily Uses
Thanks for the reply if you're not working on the script anymore. I adjusted two lines with regards to the the through bug.
 
In the class Game_Character I adjusted the following:
 
path = $game_map.find_path(x, y, self.x, self.y, dist, jump).reverse
became:
path = $game_map.find_path(x, y, self.x, self.y, dist, jump, self).reverse
 
 
And in Game_Interpreter I did the same thing:
 
path = $game_map.find_path(x, y, char.x, char.y, dist, jump)
became:
path = $game_map.find_path(x, y, char.x, char.y, dist, jump, char)
 
 
Without this the path would be determined with regards to the $game_player's statistics and not the actual event's.
 
What also changes besides the throuh bug, is:
- The event will now evade the player.
- The event won't try to move over other events who's priority is "Below Characters". (Events with through selected can still be passed)
 
I added the updated script below. (I used the script you posted at #61. I believe that one was the latest version)

#===============================================================================

# Pathfinding & Event formations
# By Jet10985(Jet) & Venima
#===============================================================================
# This script will allow you to use a pathfinder to move players or events.
# Modification: This script will also allow you to use a pathfinder which
# incorporates formation handling.
# This script has: 2 customization options.
#
# Modifications:
# Pathfinder:
# Goal location may now be inpassable, pathfinder will still reach it.
# Pathfinder still works "as intended" when the move route is set to repeat.
# Added parameter: distance (explained below).
# Added parameter: jump (set to true if the moves should be jumps instead of
# walking).
# Added parameter: commonEvent (provide the common event id for the pathfinder
# to run the event before each move (useful for adding sound or effects to
# movements)
# Added parameters:
# catchup (provide a value to indicate how far from the target the event
# should be before it speeds up its movement)
# catchupSpeed (provide a value for the speed when catching up)
# normalSpeed (provide a value for the speed after its caught up)
# Note: Pathfinder is a bit more processor heavy when used with a repeating
# move route (it was useless before, so this is only a benefit)
# Formations:
# Added find_formation_path function
# Added turn_with_player function
#
#===============================================================================
# Overwritten Methods:
# None
#-------------------------------------------------------------------------------
# Aliased methods:
# None
#===============================================================================
=begin

===============================================================================
Instructions:

===============================================================================
Standard pathfinder:
-------------------------------------------------------------------------------

To move a player or event, use this in a move route's "Script..." command:

find_path(x, y, distance = 0, jump = false, commonEvent = 0, catchup = 0,
catchupSpeed = 5, normalSpeed = 4)

x is the target x

y is the targey y

distance is set to 0 by default and can be omitted to keep the default value.
While x and y represent the target location, the event will only be moved
up to the specified distance from the target. This makes it easier to have
an event follow the player, without getting in the player's way. This could
be used as an alternative to following, except it works on any events,
not just party members.

jump is set to false by default and can be omitted. Jump specifies that
instead of the event "moving" to the target, the event will make small "jumps"
to the target. If you specify jump, you cannot omit any previous parameters.

commonEvent is set to 0 by default and can be omitted. This specifies the
id of a common event that you want executed before each move step. Currently
this only applies to repeating paths. When set to 0, no common event is called.
If you specify commonEvent you cannot omit any previous parameters.

catchup is set to 0 by default and can be omitted. Catchup specifies that if
the event is equal to or past the catchup distance, they will move faster to
"catch up". Their speed becomes the catchUp speed. Once caught up, they will
return to the normalSpeed. If you specify catchup you cannot omit any previous
parameters.

catchupSpeed is set to 5 by default and can be omitted. It is used when catchup
is specified to a value above 0. (see catchup for details). If you specify
catchupSpeed you cannot omit any previous parameters.

normalSpeed is set to 5 by default and can be omitted. It is used when catchup
is specified to a value above 0. (see catchup for details). If you specify
normalSpeed you cannot omit any previous parameters.



Running the script outside of a move route (as a standalone script call)
has two extra parameters after x and y called "ev" and "wait" but has no
commonEvent or catcup parameters.

find_path(x, y, ev = 0, wait = false, distance = 0, jump = false)

ev is set to 0 by default and can be omitted like so: find_path(9, 4).
Ev represents which character is to be moved. -1 is the player, 0 is the
calling event, and anything above is an event on the map whose ID is the ev.

wait is set to false by default and can be omitted like so:
find_path(9, 4) or find_path(9, 4, -1)
find_path(x, y) or find_path(x, y, ev)
wait specifies if the player will have to wait for the move route to finish
to start moving again.

-------------------------------------------------------------------------------
Examples:

Example of following the player at a distance:

In event's custom move route or specified move route (on repeat):
find_path($game_player.x, $game_player.y, 3)

Example of an event following an event with id 2 and catching up:
find_path($game_events[2].x, $game_events[2].y, 0, false, 0, 3)

===============================================================================
Formation handling:
-------------------------------------------------------------------------------

To move an event using a formation use this in a move route:

find_formation_path(followId, shiftX, shiftY, catchup = FORM_CATCHUP_DIST,
catchupSpeed = 5, normalSpeed = 4)

followId is the character that this event is in formation with. -1 = player,
0 = current event (although this is pointless) and above 0 is the event id.

shiftX is the relational x position from the followId character WHEN that
character faces "down". If you enter -1, this event will move to the left if
its facing down, or right if its facing up.

shiftY is the relational y position from the followId character WHEN that
character faces "down". If you enter -1, this event will move above if its
facing down, or below if it's facing up.

catchup's default value is specified by the parameter FORM_CATCHUP_DIST and
can be omitted. This specifies how far behind this event can get before it
speeds up to catch up.

catchupSpeed's default value is 5 and can be omitted. This specifies how fast
this event will move when it's "catching up". If you specify catchupSpeed, you
cannot omit any previous parameters.

normalSpeed's default value is 4 and can be omitted. This specifies how fast
this event will move when it isn't "catching up". If you specify normalSpeed,
you cannot omit any previous parameters.


You also have another command for formations:
Entering "turn_with_leader" as a separate script after find_formation_path
will cause the event to turn the same way the player is turned after arriving
at their formation position.
Entering "turn_with_leader(1)" will turn the same way as event with id 1.
Turn_with_leader also has a second optional parameter. Entering "left" or -1
will turn this event left of the leader's direction, entering "right" or 1
will turn this event right of the leader's direction, and entering "back" or 2
will turn this event opposite of the leader's direction. Again, if you specify
this parameter, you cannot omit the previous one.

-------------------------------------------------------------------------------
Examples:

Example of 2 events acting similar to followers behind the player:
In a repeating move-route for Event 01:
find_formation_path(-1,0,-1)
In a repeating move_route for Event 02:
find_formation_path(1,0,-1)

Example of an event covering the player's back 2 spaces away:
In a repeating move-route:
find_formation_path(-1,0,-2)
turn_with_leader(-1,"back")

Example of an event with a formation determined by in-game variables:
In a repeating move-route:
find_formation_path(-1, $game_variables[1], $game_variables[2])

=end

#===============================================================================
# Customisation options below:
#===============================================================================
module Venima
module Formations
#
FORM_CATCHUP_DIST = 3
end
end

module Jet
module Pathfinder

# While mainly for coders, you may change this value to allow the
# pathfinder more time to find a path. 1000 is default, as it is enough for
# a 100x100 MAZE so, yeah.
# Note from Venima, you probably don't want to change this value too much
MAXIMUM_ITERATIONS = 500

end
end
#===============================================================================
# Customisation end
#===============================================================================

class Node

include Comparable

attr_accessor :point, :parent, :cost, :cost_estimated

def initialize(point)
@point = point
@cost = 0
@cost_estimated = 0
@on_path = false
@parent = nil
end

def mark_path
@on_path = true
@parent.mark_path if @parent
end

def total_cost
cost + cost_estimated
end

def <=>(other)
total_cost <=> other.total_cost
end

def ==(other)
point == other.point
end
end

class Point

attr_accessor :x, :y

def initialize(x, y)
@x, @y = x, y
end

def ==(other)
return false unless Point === other
@x == other.x && @y == other.y
end

def distance(other)
(@x - other.x).abs + (@y - other.y).abs
end

def relative(xr, yr)
Point.new(x + xr, y + yr)
end
end

class Game_Map

def each_neighbor(node, char = $game_player)
x = node.point.x
y = node.point.y
nodes = []
4.times {|i|
i += 1
new_x = round_x_with_direction(x, i * 2)
new_y = round_y_with_direction(y, i * 2)
next unless char.passable?(x, y, i * 2)
#removed line below (technically, if your goal is an inpassable block,
# e.g. an event, you can still reach it)
#next unless char.passable?(new_x, new_y, 10 - i * 2)
nodes.push(Node.new(Point.new(new_x, new_y)))
}
nodes
end

def find_path(tx, ty, sx, sy, dist, jump, char = $game_player)
start = Node.new(Point.new(sx, sy))
goal = Node.new(Point.new(tx, ty))
return [] if start == goal or (dist > 0 and start.point.distance(goal.point) <= dist)
return [] if ![2, 4, 6, 8].any? {|i| char.passable?(tx, ty, i) }
open_set = [start]
closed_set = []
path = []
iterations = 0
loop do
return [] if iterations == Jet::pathfinder::MAXIMUM_ITERATIONS
iterations += 1
current = open_set.min
return [] unless current
each_neighbor(current, char).each {|node|
if node == goal or (dist > 0 and node.point.distance(goal.point) <= dist)
node.parent = current
node.mark_path
return recreate_path(node, jump)
end
next if closed_set.include?(node)
cost = current.cost + 1
if open_set.include?(node)
if cost < node.cost
node.parent = current
node.cost = cost
end
else
open_set << node
node.parent = current
node.cost = cost
node.cost_estimated = node.point.distance(goal.point)
end
}
closed_set << open_set.delete(current)
end
end

def recreate_path(node, jump)
path = []
hash = {[1, 0] => 6, [-1, 0] => 4, [0, 1] => 2, [0, -1] => 8}
until node.nil?
pos = node.point
node = node.parent
next if node.nil?
ar = [pos.x <=> node.point.x, pos.y <=> node.point.y]
if jump
path.push(RPG::MoveCommand.new(14,ar))
else
path.push(RPG::MoveCommand.new(hash[ar] / 2))
end
end
return path
end
end

class Game_Character

#modified function (added handling for repeated move route (recalculates path
# each step so it doesn't just loop it's old path route and will revalidate
# if x or y changes, will follow variable value if x and y are set to it)
def find_path(x, y, dist = 0, jump = false, commonEvent = 0, catchup = 0, catchupSpeed = 5, normalSpeed = 4)#SvenVI: modified line below (added event (self) parameter)
path = $game_map.find_path(x, y, self.x, self.y, dist, jump, self).reverse
if !@move_route.repeat
@move_route.list.delete_at(@move_route_index)
@move_route.list.insert(@move_route_index, *path)
@move_route_index -= 1
elsif path.length > 0
if commonEvent > 0
$game_temp.reserve_common_event(commonEvent)
end
if catchup > 0
if @move_speed < catchupSpeed && path.length >= catchup
process_move_command(RPG::MoveCommand.new(29,[catchupSpeed]))
elsif @move_speed >= catchupSpeed && path.length < 2
process_move_command(RPG::MoveCommand.new(29,[normalSpeed]))
end
end
process_move_command(path[0])
@move_route_index -= 1
end
return path.length
end

def get_character(i)
if i == -1
return $game_player
end
if i == 0
return $game_map.events[@event_id]
end
if i > 0
return $game_map.events
end
end

def find_formation_path(followId, shiftX, shiftY, catchup = Venima::Formations::FORM_CATCHUP_DIST, catchupSpeed = 5, normalSpeed = 4)
x = shift_follow_x(followId, shiftX, shiftY)
y = shift_follow_y(followId, shiftX, shiftY)
if find_path(x,y,0,false,0,catchup,catchupSpeed,normalSpeed) == 0
char = get_character(followId)
find_path(char.x,char.y,3,false,0,catchup,catchupSpeed,normalSpeed)
end
end

def shift_follow_x(followId, shiftX, shiftY)
char = get_character(followId)
case char.direction
when 2
return char.x + shiftX
when 4
return char.x - shiftY
when 6
return char.x + shiftY
when 8
return char.x - shiftX
end
return char.x
end

def shift_follow_y(followId, shiftX, shiftY)
char = get_character(followId)
case char.direction
when 2
return char.y + shiftY
when 4
return char.y - shiftX
when 6
return char.y + shiftX
when 8
return char.y - shiftY
end
return char.y
end

def turn_with_leader(eventId = -1, dirmod = "")
dir = get_character(eventId).direction
mod = 0
if dirmod == "left" || dirmod == -1
case dir
when 2
set_direction(4)
when 4
set_direction(2)
when 6
set_direction(8)
when 8
set_direction(6)
end
elsif dirmod == "right" || dirmod == 1
case dir
when 2
set_direction(6)
when 4
set_direction(8)
when 6
set_direction(2)
when 8
set_direction(4)
end
elsif dirmod == "back" || dirmod == 2
case dir
when 2
set_direction(8)
when 4
set_direction(6)
when 6
set_direction(4)
when 8
set_direction(2)
end
else
set_direction(dir)
end
end
end

class Game_Interpreter

#modified line below (added distance parameter)
def find_path(x, y, ev = 0, wait = false, dist = 0, jump = false)
char = get_character(ev)
#modified line below (added distance parameter)

#SvenVI: modified line below (added event (char) parameter)
path = $game_map.find_path(x, y, char.x, char.y, dist, jump, char)
path.reverse!
path.push(RPG::MoveCommand.new(0))
route = RPG::MoveRoute.new
route.list = path
route.wait = wait
route.skippable = true
route.repeat = false
char.force_move_route(route)
end

end
 

I fixed the impossible path bug with some eventing like you suggested, so thanks for that. The fact that it froze my game was due to a poor setup on my end, so nothing to do with the script.
 
Last edited by a moderator:

Venima

Treasure experiences and sensations, not progress.
Veteran
Joined
Oct 8, 2013
Messages
128
Reaction score
48
First Language
English
Primarily Uses
N/A
Well done on that SvenVI :)

Could you just make 'updated script below' bold? Will be easier for other people to see that the script's updated.
 

Mhin Ra

Veteran
Veteran
Joined
Aug 17, 2015
Messages
65
Reaction score
19
First Language
English
Primarily Uses
RMVXA
The script is awesome!   I was playing with it and I think it might have a bug in one particular case.   If you have an event walking down a corridor of width one and are telling the event to go to the last square before something that's blocked.   So, something like this:

--------------------------------------------------

Ev                                                       X-

--------------------------------------------------

Where you're telling the event to go to square X (right before a wall).   I think the problem is that when the Ev gets to the space right in front of X and attempts to call $game_map.find_path, it can't find any exits from X.   This is, I believe, because the Event itself is standing on the only exit square, so it looks impassable.   The particular line that causes the issue is this one, from $game_map.find_path:

    return [] if ![2, 4, 6, 8].any? {|i| char.passable?(tx, ty, i) }

I am not at all an expert in Ruby, so this is probably not too elegant, but if you create a function that looks something like this:

  def isPassable(tx, ty, dir, char)

    x2 = round_x_with_direction(tx, dir)

    y2 = round_y_with_direction(ty, dir)

    return true if char.x == x2 and char.y == y2

    return char.passable?(tx, ty, dir)

  end

 

and call that instead of char.passable? in the offending line, things seem to work.   You do need SvenVI's fix as well, so that you can pass the event char into the isPassable function.   Otherwise, it'll compare to the player - which won't help much ;)

 

Anyway, took me a bit to figure this out, so if someone could update the root copy of the script, it might save others some headaches.
 

Venima

Treasure experiences and sensations, not progress.
Veteran
Joined
Oct 8, 2013
Messages
128
Reaction score
48
First Language
English
Primarily Uses
N/A
Well, Jet has moved on so I have no way of updating the script on the first page. However, I can keep posting the latest version as replies come in, which is what I've been doing (see below).

Were you using the latest version or the original? I don't know why the script would ever look at the tile the event's already on, but I'm glad you've found a solution :)

The updated script below has some extra functionality, check the comments if you want to use it.

Code:
#=============================================================================== # Pathfinding & Event formations# By Jet10985(Jet) & Venima#===============================================================================# This script will allow you to use a pathfinder to move players or events.# Modification: This script will also allow you to use a pathfinder which # incorporates formation handling.# This script has: 2 customization options.## Modifications:# Pathfinder:# Goal location may now be inpassable, pathfinder will still reach it.# Pathfinder still works "as intended" when the move route is set to repeat.# Added parameter: distance (explained below).# Added parameter: jump (set to true if the moves should be jumps instead of# walking).# Added parameter: commonEvent (provide the common event id for the pathfinder# to run the event before each move (useful for adding sound or effects to # movements)# Added parameters: # catchup (provide a value to indicate how far from the target the event #   should be before it speeds up its movement)# catchupSpeed (provide a value for the speed when catching up)# normalSpeed (provide a value for the speed after its caught up)# Note: Pathfinder is a bit more processor heavy when used with a repeating # move route (it was useless before, so this is only a benefit)# Formations:# Added find_formation_path function# Added turn_with_player function##===============================================================================# Overwritten Methods:# None#-------------------------------------------------------------------------------# Aliased methods:# None#================================================================================begin =============================================================================== Instructions: =============================================================================== Standard pathfinder:------------------------------------------------------------------------------- To move a player or event, use this in a move route's "Script..." command: find_path(x, y, distance = 0, jump = false, commonEvent = 0, catchup = 0,       catchupSpeed = 5, normalSpeed = 4) x is the target x y is the targey y distance is set to 0 by default and can be omitted to keep the default value.While x and y represent the target location, the event will only be moved up to the specified distance from the target. This makes it easier to have an event follow the player, without getting in the player's way. This could be used as an alternative to following, except it works on any events, not just party members. jump is set to false by default and can be omitted. Jump specifies that instead of the event "moving" to the target, the event will make small "jumps" to the target. If you specify jump, you cannot omit any previous parameters. commonEvent is set to 0 by default and can be omitted. This specifies the id of a common event that you want executed before each move step. Currentlythis only applies to repeating paths. When set to 0, no common event is called.If you specify commonEvent you cannot omit any previous parameters. catchup is set to 0 by default and can be omitted. Catchup specifies that ifthe event is equal to or past the catchup distance, they will move faster to "catch up". Their speed becomes the catchUp speed. Once caught up, they will return to the normalSpeed. If you specify catchup you cannot omit any previous parameters. catchupSpeed is set to 5 by default and can be omitted. It is used when catchup is specified to a value above 0. (see catchup for details). If you specify catchupSpeed you cannot omit any previous parameters. normalSpeed is set to 5 by default and can be omitted. It is used when catchup is specified to a value above 0. (see catchup for details). If you specify normalSpeed you cannot omit any previous parameters.   Running the script outside of a move route (as a standalone script call)has two extra parameters after x and y called "ev" and "wait" but has no commonEvent or catcup parameters. find_path(x, y, ev = 0, wait = false, distance = 0, jump = false) ev is set to 0 by default and can be omitted like so: find_path(9, 4).Ev represents which character is to be moved. -1 is the player, 0 is thecalling event, and anything above is an event on the map whose ID is the ev. wait is set to false by default and can be omitted like so: find_path(9, 4) or find_path(9, 4, -1)find_path(x, y) or find_path(x, y, ev)wait specifies if the player will have to wait for the move route to finishto start moving again. ------------------------------------------------------------------------------- Examples: Example of following the player at a distance: In event's custom move route or specified move route (on repeat):   find_path($game_player.x, $game_player.y, 3)  Example of an event following an event with id 2 and catching up:  find_path($game_events[2].x, $game_events[2].y, 0, false, 0, 3) =============================================================================== Formation handling:------------------------------------------------------------------------------- To move an event using a formation use this in a move route: find_formation_path(followId, shiftX, shiftY, catchup = FORM_CATCHUP_DIST,       catchupSpeed = 5, normalSpeed = 4)      followId is the character that this event is in formation with. -1 = player,0 = current event (although this is pointless) and above 0 is the event id. shiftX is the relational x position from the followId character WHEN that character faces "down". If you enter -1, this event will move to the left if its facing down, or right if its facing up. shiftY is the relational y position from the followId character WHEN thatcharacter faces "down". If you enter -1, this event will move above if its facing down, or below if it's facing up. catchup's default value is specified by the parameter FORM_CATCHUP_DIST andcan be omitted. This specifies how far behind this event can get before it speeds up to catch up. catchupSpeed's default value is 5 and can be omitted. This specifies how fast this event will move when it's "catching up". If you specify catchupSpeed, you cannot omit any previous parameters. normalSpeed's default value is 4 and can be omitted. This specifies how fast this event will move when it isn't "catching up". If you specify normalSpeed, you cannot omit any previous parameters.  You also have another command for formations:Entering "turn_with_leader" as a separate script after find_formation_pathwill cause the event to turn the same way the player is turned after arriving at their formation position.Entering "turn_with_leader(1)" will turn the same way as event with id 1.Turn_with_leader also has a second optional parameter. Entering "left" or -1will turn this event left of the leader's direction, entering "right" or 1will turn this event right of the leader's direction, and entering "back" or 2 will turn this event opposite of the leader's direction. Again, if you specify this parameter, you cannot omit the previous one.  ------------------------------------------------------------------------------- Examples: Example of 2 events acting similar to followers behind the player:In a repeating move-route for Event 01:find_formation_path(-1,0,-1)In a repeating move_route for Event 02:find_formation_path(1,0,-1) Example of an event covering the player's back 2 spaces away:In a repeating move-route:find_formation_path(-1,0,-2)turn_with_leader(-1,"back") Example of an event with a formation determined by in-game variables:In a repeating move-route:find_formation_path(-1, $game_variables[1], $game_variables[2]) =end #===============================================================================# Customisation options below:#===============================================================================module Venima  module Formations    #    FORM_CATCHUP_DIST = 3  endend module Jet  module Pathfinder        # While mainly for coders, you may change this value to allow the    # pathfinder more time to find a path. 1000 is default, as it is enough for    # a 100x100 MAZE so, yeah.    # Note from Venima, you probably don't want to change this value too much    MAXIMUM_ITERATIONS = 500      endend#===============================================================================# Customisation end#=============================================================================== class Node    include Comparable   attr_accessor :point, :parent, :cost, :cost_estimated   def initialize(point)    @point = point    @cost = 0    @cost_estimated = 0    @on_path = false    @parent = nil  end   def mark_path    @on_path = true    @parent.mark_path if @parent  end     def total_cost    cost + cost_estimated  end   def <=>(other)    total_cost <=> other.total_cost  end     def ==(other)    point == other.point  endend class Point    attr_accessor :x, :y    def initialize(x, y)    @x, @y = x, y  end   def ==(other)    return false unless Point === other    @x == other.x && @y == other.y  end   def distance(other)    (@x - other.x).abs + (@y - other.y).abs  end   def relative(xr, yr)    Point.new(x + xr, y + yr)  endend class Game_Map    def each_neighbor(node, char = $game_player)    x = node.point.x    y = node.point.y    nodes = []    4.times {|i|      i += 1      new_x = round_x_with_direction(x, i * 2)      new_y = round_y_with_direction(y, i * 2)      next unless char.passable?(x, y, i * 2)      #removed line below (technically, if your goal is an inpassable block,      # e.g. an event, you can still reach it)      #next unless char.passable?(new_x, new_y, 10 - i * 2)      nodes.push(Node.new(Point.new(new_x, new_y)))    }    nodes  end    def find_path(tx, ty, sx, sy, dist, jump, char = $game_player)    start = Node.new(Point.new(sx, sy))    goal = Node.new(Point.new(tx, ty))    return [] if start == goal or (dist > 0 and start.point.distance(goal.point) <= dist)    return [] if ![2, 4, 6, 8].any? {|i| char.passable?(tx, ty, i) }    open_set = [start]    closed_set = []    path = []    iterations = 0    loop do      return [] if iterations == Jet::Pathfinder::MAXIMUM_ITERATIONS      iterations += 1      current = open_set.min      return [] unless current      each_neighbor(current, char).each {|node|        if node == goal or (dist > 0 and node.point.distance(goal.point) <= dist)          node.parent = current          node.mark_path          return recreate_path(node, jump)        end        next if closed_set.include?(node)        cost = current.cost + 1        if open_set.include?(node)          if cost < node.cost            node.parent = current            node.cost = cost          end        else          open_set << node          node.parent = current          node.cost = cost          node.cost_estimated = node.point.distance(goal.point)        end      }      closed_set << open_set.delete(current)    end  end    def recreate_path(node, jump)    path = []    hash = {[1, 0] => 6, [-1, 0] => 4, [0, 1] => 2, [0, -1] => 8}    until node.nil?      pos = node.point      node = node.parent      next if node.nil?      ar = [pos.x <=> node.point.x, pos.y <=> node.point.y]      if jump        path.push(RPG::MoveCommand.new(14,ar))      else        path.push(RPG::MoveCommand.new(hash[ar] / 2))      end    end    return path  endend class Game_Character    #modified function (added handling for repeated move route (recalculates path   # each step so it doesn't just loop it's old path route and will revalidate    # if x or y changes, will follow variable value if x and y are set to it)  def find_path(x, y, dist = 0, jump = false, commonEvent = 0, catchup = 0, catchupSpeed = 5, normalSpeed = 4)    path = $game_map.find_path(x, y, self.x, self.y, dist, jump).reverse    if !@move_route.repeat      @move_route.list.delete_at(@move_route_index)      @move_route.list.insert(@move_route_index, *path)      @move_route_index -= 1    elsif path.length > 0      if commonEvent > 0        $game_temp.reserve_common_event(commonEvent)      end      if catchup > 0        if @move_speed < catchupSpeed && path.length >= catchup          process_move_command(RPG::MoveCommand.new(29,[catchupSpeed]))        elsif @move_speed >= catchupSpeed && path.length < 2          process_move_command(RPG::MoveCommand.new(29,[normalSpeed]))        end      end      process_move_command(path[0])      @move_route_index -= 1    end    return path.length  end   def get_character(i)    if i == -1      return $game_player    end    if i == 0      return $game_map.events[@event_id]    end    if i > 0      return $game_map.events[i]    end  end    def find_formation_path(followId, shiftX, shiftY, catchup = Venima::Formations::FORM_CATCHUP_DIST, catchupSpeed = 5, normalSpeed = 4)    x = shift_follow_x(followId, shiftX, shiftY)    y = shift_follow_y(followId, shiftX, shiftY)    if find_path(x,y,0,false,0,catchup,catchupSpeed,normalSpeed) == 0      char = get_character(followId)      find_path(char.x,char.y,3,false,0,catchup,catchupSpeed,normalSpeed)    end  end    def shift_follow_x(followId, shiftX, shiftY)    char = get_character(followId)    case char.direction    when 2      return char.x + shiftX    when 4      return char.x - shiftY    when 6      return char.x + shiftY    when 8      return char.x - shiftX    end    return char.x  end    def shift_follow_y(followId, shiftX, shiftY)    char = get_character(followId)    case char.direction    when 2      return char.y + shiftY    when 4      return char.y - shiftX    when 6      return char.y + shiftX    when 8      return char.y - shiftY    end    return char.y  end    def turn_with_leader(eventId = -1, dirmod = "")    dir = get_character(eventId).direction    mod = 0    if dirmod == "left" || dirmod == -1      case dir      when 2        set_direction(4)      when 4        set_direction(2)      when 6        set_direction(8)      when 8        set_direction(6)      end    elsif dirmod == "right" || dirmod == 1      case dir      when 2        set_direction(6)      when 4        set_direction(8)      when 6        set_direction(2)      when 8        set_direction(4)      end    elsif dirmod == "back" || dirmod == 2      case dir      when 2        set_direction(8)      when 4        set_direction(6)      when 6        set_direction(4)      when 8        set_direction(2)      end    else      set_direction(dir)     end  endend class Game_Interpreter    #modified line below (added distance parameter)  def find_path(x, y, ev = 0, wait = false, dist = 0, jump = false)    char = get_character(ev)    #modified line below (added distance parameter)    path = $game_map.find_path(x, y, char.x, char.y, dist, jump)    path.reverse!    path.push(RPG::MoveCommand.new(0))    route = RPG::MoveRoute.new    route.list = path    route.wait = wait    route.skippable = true    route.repeat = false    char.force_move_route(route)  endend
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Are we allowed to post about non-RPG Maker games. and, if so, would any of you be interested in a short, proof of concept type non-euclidian puzzle game?
I should realize that error was produced by a outdated version of MZ so that's why it pop up like that
Ami
i can't wait to drink some ice after struggling with my illness in 9 days. 9 days is really bad for me,i can't focus with my shop and even can't do something with my project
How many hours have you got in mz so far?

A bit of a "sparkle" update to the lower portion of the world map. :LZSexcite:

Forum statistics

Threads
105,883
Messages
1,017,232
Members
137,607
Latest member
Maddo
Top