Jump to content
Darkness Void

Need Help With Detection Script

Recommended Posts

I recently found this script posted here back in 2013, sadly that topic only had 2 replies and neither went in detail. I understand it but, and keep in mind I read it carefully, I don't know what to do in terms of turning on the switches. For example it says:

 

"Tracer (n): Anything that is searching for the player, e.g., a guard.
#   Designate which events are a tracer by including "tracer" in its name.
#   When a tracer event sees the player, the Alert Switch it turned ON.
#   When the Alert Switch is turned on, a countdown begins. If the player
#   remains out of site for 1800 frames, the Alert Switch is turned OFF.
ALERT_SWITCH = 242        # any game switch

ALERT_COUNTDOWN = 1800  # frames (60 frames is 1 second; 1800 frames is 30 sec)"

 

However it doesn't say how the switch is turned on, I just assumed if you're in range it auto turns on but didn't work. I also assumed the 242 was an switch number, so I changed it to "ALERT_SWITCH = 97" as I made a switch "Seen" which is number 97. Did I misunderstood something or am I'm missing an script command that isn't in the script but I'm supposed to know what?

 

The main and biggest reason I can't create scripts is because I just don't understand them, so many ways to do them and everything has to be just right, not a good memory so have to write everything down just to remember it. I think I can get this to work fairly well, I just can't figure out how to turn on the switches the script lists.

 

I added the range for sight inside a cutscene's para-event with a script command so that should be on. The cutscene also begins the killer's path finding WHICH I removed completely until I get the sight working. Also just for the sake of it, how should the event's name be? I have it as "tracer (Other Killer)" since the script said "Tracer (n):" but every instance of tracer underneath the creator's explanation is undercase so again, I just assumed.

 

 

  1. module Trace # <= don't touch this
  2. #==============================================================================
  3. # ? ??-VX ? Trace Stealth System ? version 2.2 ? Prof. Meow Meow
  4. # Converted to VXA by LiTTleDRAgo
  5. #------------------------------------------------------------------------------
  6. # 1.0
  7. # ? Initial release
  8. # 1.1
  9. # ? Alert no longer counts down while a message is displayed
  10. # ? Revised the trace method, slimming it down and fixing the following bugs:
  11. # ? Fixed a bug where tracers' vision would sometimes be blocked by itself
  12. # ? Fixed a bug where tracers would see through Same As Characters events
  13. # 2.0
  14. # ? Added the sound stealth system
  15. # ? Changed the way the trace range is handled
  16. # ? Added ability to disable a tracer's senses
  17. # 2.1
  18. # ? Patched minors bugs
  19. # 2.2
  20. # ? Rewrote trace method using Bresenham's Line Algorithm
  21. #==============================================================================
  22. # ? Tracing With Style - please read everything!
  23. #------------------------------------------------------------------------------
  24. # Tracer (n): Anything that is searching for the player, e.g., a guard.
  25. # Designate which events are a tracer by including "tracer" in its name.
  26. # When a tracer event sees the player, the Alert Switch it turned ON.
  27. # When the Alert Switch is turned on, a countdown begins. If the player
  28. # remains out of site for 1800 frames, the Alert Switch is turned OFF.
  29. ALERT_SWITCH = 242 # any game switch
  30. ALERT_COUNTDOWN = 1800 # frames (60 frames is 1 second; 1800 frames is 30 sec)
  31. #==============================================================================
  32. # ? Change How Far Your Guards Can See
  33. #------------------------------------------------------------------------------
  34. # By default, tracers have an average range of vision: 5 tiles.
  35. # A tracer's range should be odd: 3, 5, 7, 9, etc.
  36. # An even value will be the next odd number, e.g., 4 will be a range of 5.
  37. TRACE_RANGE_DEFAULT = 5 # any odd value
  38. # You can change the range at any time by calling this line:
  39. # ? $game_map.trace_range = n where n is the new sight range
  40. # You may want to change the trace range when the lighting changes:
  41. # ? For a dark room, or during the night, use 3 or 5.
  42. # ? For a lit room, or during the day, use 5 or higher.
  43. #==============================================================================
  44. # ? Three Ways To Hide The Player From Sight
  45. #------------------------------------------------------------------------------
  46. # There are three methods that can be used to hide the player:
  47. # ? Make the player transparent
  48. # ? Make the player's opacity to HIDE_OPACITY or lower
  49. # ? Change the Hide Switch to ON
  50. HIDE_OPACITY = 50 # 0~255 (for realism, keep it low)
  51. HIDE_SWITCH = 243 # any game switch
  52. #==============================================================================
  53. # ? 2.0 Feature ? Making a Ruckus: a guide to sound stealth ?
  54. #------------------------------------------------------------------------------
  55. # All noises have a loudness value which is it's range. For example, a
  56. # noise with a loudness of 4 will be heard by all guards within 4 tiles.
  57. # To make a noise, call the following line from within a Move Route command:
  58. # ? tss_noise(n) where n is the range of the noise
  59. # When a tracer hears a noise, its Caution Self Swith is set ON.
  60. # To have the tracer move toward the source the sound, call the following
  61. # line from within it's custom autonomous movement:
  62. # ? tss_investigate
  63. # Once the tracer reaches the source, its Caution Self Switch is set OFF.
  64. CAUTION_SELF_SWITCH = "C" # "A", "B", "C", or "D"
  65. # When the player sprints, he or she makes some noise!
  66. # You can change how much noise is made at any time by calling this line:
  67. # ? $game_player.sprint_noise = n where n is the range of the noise
  68. DEFAULT_SPRINT_NOISE = 3 # any value (set this to 0 to disable)
  69. # Here are some example of noises and their estimated range:
  70. # ? Creaking Floor............ 1~2
  71. # ? Carefully Closing a Door.. 2~3
  72. # ? Sneezing or Coughing...... 4~5
  73. # ? Bumping Into Something.... 4~5
  74. # ? Tripping Over Furniture... 6~7
  75. # ? Breaking Glass............ 8~9
  76. # Sprinting:
  77. # ? Thief Sprinting........... 2~3
  78. # ? Civilian Sprinting........ 4~6
  79. # ? Soldier Sprinting......... 7~9
  80. # Dialogue:
  81. # ? Whispering................ 2~3
  82. # ? Talking................... 4~6
  83. # ? Shouting.................. 7~9
  84. #==============================================================================
  85. # ? 2.0 Feature ? Two Ways To Disable a Tracer's Senses
  86. #------------------------------------------------------------------------------
  87. # There are two methods that can be used to disable a tracer's "senses":
  88. # ? Erase the tracer event
  89. # ? Change it's Disabling Self Switch to ON
  90. # Prof tip: "D" is for many things- dead, disabled.... When you knock out a
  91. # guard, erase or turn it's "D" self switch ON so he can't see or hear you!
  92. ALLOW_SELF_SWITCH_DISABLING = true # true~false
  93. DISABLING_SELF_SWITCH = "D" # "A", "B", "C", or "D"
  94. #==============================================================================
  95. # ? Special Effects
  96. #------------------------------------------------------------------------------
  97. # When a guard sees you, an ! appears above all heads and an ME plays.
  98. SHOW_ALERT = true # Do you want the ! to display? true~false
  99. PLAY_ALERT = true # Do you want an ME to play? true~false
  100. ALERT_ME = "Audio/ME/Shock" # Which ME do you want to play? any ME
  101. ALERT_VOLUME = 100 # At what volume? 0~100
  102. ALERT_PITCH = 100 # At what pitch? 50~150
  103. # When the guards call off the search, a ? appears above all heads.
  104. SHOW_QUIT = true # Do you want the ? to display? true~false
  105. # 2.0 Feature ? When a guards hears a noise, a ? appears above it's head
  106. # and an ME plays.
  107. SHOW_CAUTION = true # Do you want the ? to display? true~false
  108. PLAY_CAUTION = true # Do you want an ME to play? true~false
  109. CAUTION_ME = "Audio/ME/Mystery" # Which ME do you want to play? any ME
  110. CAUTION_VOLUME = 100 # At what volume? 0~100
  111. CAUTION_PITCH = 100 # At what pitch? 50~150
  112. #==============================================================================
  113. # ? 2.0 Feature ? Something For Fun
  114. #------------------------------------------------------------------------------
  115. # You can call huh? or hey! through an event script to display '?' or '!'
  116. # above all active tracer heads!
  117. #==============================================================================
  118. # ? DO NOT TOUCH ANYTHING BELOW THIS POINT - this is for your own safety!
  119. #==============================================================================
  120. CHECK_INTERVAL = 16 # 16
  121. end
  122. #==============================================================================
  123. # Game System
  124. #==============================================================================
  125. class Game_Map
  126. #----------------------------------------------------------------------------
  127. # Local Variables
  128. #----------------------------------------------------------------------------
  129. attr_accessor :trace_range
  130. attr_accessor :alert_countdown
  131. #----------------------------------------------------------------------------
  132. # Update
  133. #----------------------------------------------------------------------------
  134. alias trace_system_update update unless $@
  135. def update(*args)
  136. trace_system_update(*args)
  137. @trace_range ||= Trace::TRACE_RANGE_DEFAULT
  138. @alert_countdown ||= 0
  139. if @alert_countdown > 0 and !$game_message.visible
  140. @alert_countdown -= 1
  141. elsif @alert_countdown <= 0 and $game_switches[Trace::ALERT_SWITCH]
  142. if Trace::SHOW_QUIT
  143. for i in $game_map.events.keys
  144. event = $game_map.events[i]
  145. if event.name.include?("tracer") and !event.erased
  146. next if Trace::ALLOW_SELF_SWITCH_DISABLING and
  147. event.get_self_switch(Trace::DISABLING_SELF_SWITCH)
  148. event.balloon_id = 2
  149. end
  150. end
  151. end
  152. $game_switches[Trace::ALERT_SWITCH] = false
  153. $game_map.need_refresh = true
  154. end
  155. end
  156. end
  157. #==============================================================================
  158. # Game Character
  159. #==============================================================================
  160. class Game_Character
  161. #----------------------------------------------------------------------------
  162. # Local Variables
  163. #----------------------------------------------------------------------------
  164. attr_accessor :old_x
  165. attr_accessor :old_y
  166. attr_accessor :old_player_x
  167. attr_accessor :old_player_y
  168. attr_accessor :attention_x
  169. attr_accessor :attention_y
  170. #----------------------------------------------------------------------------
  171. # Initialize
  172. #----------------------------------------------------------------------------
  173. alias trace_initialize initialize unless $@
  174. def initialize
  175. trace_initialize
  176. @old_x = @x
  177. @old_y = @y
  178. @old_player_x = 0
  179. @old_player_y = 0
  180. @attention_x = @x
  181. @attention_y = @y
  182. end
  183. #----------------------------------------------------------------------------
  184. # Update
  185. #----------------------------------------------------------------------------
  186. alias trace_update update unless $@
  187. def update
  188. trace_update
  189. if @id > 0 # if an event
  190. if name.include?("tracer") and not @erased
  191. if @old_x != @x or @old_y != @y or
  192. @old_player_x != $game_player.x or @old_player_y != $game_player.y
  193. if !$game_switches[Trace::ALERT_SWITCH]
  194. if tss_trace
  195. if Trace::PLAY_ALERT
  196. name = Trace::ALERT_ME
  197. volume = Trace::ALERT_VOLUME
  198. pitch = Trace::ALERT_PITCH
  199. Audio.me_play(name, volume, pitch)
  200. end
  201. if Trace::SHOW_ALERT
  202. for event in $game_map.events.values
  203. if event.name.include?("tracer") and !event.erased
  204. next if Trace::ALLOW_SELF_SWITCH_DISABLING and
  205. event.get_self_switch(Trace::DISABLING_SELF_SWITCH)
  206. event.balloon_id = 1
  207. end
  208. end
  209. end
  210. $game_switches[Trace::ALERT_SWITCH] = true
  211. $game_map.alert_countdown = Trace::ALERT_COUNTDOWN
  212. $game_map.need_refresh = true
  213. end
  214. end
  215. @old_x = @x
  216. @old_y = @y
  217. @old_player_x = $game_player.x
  218. @old_player_y = $game_player.y
  219. end
  220. if [(@x - @attention_x).abs, (@y - @attention_y).abs].max < 2 and
  221. get_self_switch(Trace::CAUTION_SELF_SWITCH)
  222. @balloon_id = 2 if Trace::SHOW_QUIT
  223. set_self_switch(Trace::CAUTION_SELF_SWITCH, false)
  224. end
  225. end
  226. end
  227. end
  228. #----------------------------------------------------------------------------
  229. # Trace
  230. #----------------------------------------------------------------------------
  231. def tss_trace(range = $game_map.trace_range)
  232. return false if Trace::ALLOW_SELF_SWITCH_DISABLING and
  233. get_self_switch(Trace::DISABLING_SELF_SWITCH)
  234. return false if $game_player.transparent
  235. return false if $game_switches[Trace::HIDE_SWITCH]
  236. return false if $game_player.opacity <= Trace::HIDE_OPACITY
  237. return false if (range||0) > 0 and !player_in_sight_field?
  238. x0, y0 = @x * 32 + 16, @y * 32 + 16
  239. x1, y1 = $game_player.x * 32 + 16, $game_player.y * 32 + 16
  240. line_points = get_line(x0, y0, x1, y1)
  241. check_countdown = Trace::CHECK_INTERVAL
  242. line_points.each do |point|
  243. if check_countdown > 0
  244. check_countdown -= 1
  245. else
  246. check_countdown = Trace::CHECK_INTERVAL
  247. x, y = point[:x]/32, point[:y]/32
  248. break if !$game_player.passable?(x, y, @direction) and !pos?(x, y)
  249. return true if $game_player.pos?(x, y)
  250. end
  251. end
  252. return false
  253. end
  254. #----------------------------------------------------------------------------
  255. # Player In Sight Field?
  256. #----------------------------------------------------------------------------
  257. def player_in_sight_field?
  258. # Find the center of the range because the range is radial
  259. range = 1 + $game_map.trace_range / 2
  260. # Find the center of the field of vision
  261. center_vision_x = @x
  262. center_vision_y = @y
  263. center_vision_y += range if @direction == 2
  264. center_vision_x -= range if @direction == 4
  265. center_vision_x += range if @direction == 6
  266. center_vision_y -= range if @direction == 8
  267. # Calculate the X & Y distances between the center of vision and player
  268. sx = center_vision_x - $game_player.x
  269. sy = center_vision_y - $game_player.y
  270. # Return true if the player is within the field of vision
  271. return true if [sx.abs,sy.abs].max < range
  272. # Otherwise, return false
  273. return false
  274. end
  275. #----------------------------------------------------------------------------
  276. # Noise
  277. #----------------------------------------------------------------------------
  278. def tss_noise(range = 0)
  279. if $game_switches[Trace::ALERT_SWITCH] == false
  280. for event in $game_map.events.values
  281. if event.name.include?("tracer") and !event.erased
  282. next if Trace::ALLOW_SELF_SWITCH_DISABLING and
  283. event.get_self_switch(Trace::DISABLING_SELF_SWITCH)
  284. sx = event.x - @x
  285. sy = event.y - @y
  286. if [sx.abs, sy.abs].max <= range
  287. if Trace::PLAY_CAUTION
  288. name = Trace::CAUTION_ME
  289. volume = Trace::CAUTION_VOLUME
  290. pitch = Trace::CAUTION_PITCH
  291. Audio.me_play(name, volume, pitch)
  292. end
  293. event.attention_x = @x
  294. event.attention_y = @y
  295. event.balloon_id = 2 if Trace::SHOW_CAUTION
  296. event.set_self_switch(Trace::CAUTION_SELF_SWITCH, true)
  297. end
  298. end
  299. end
  300. end
  301. end
  302. #--------------------------------------------------------------------------
  303. # * Investigate
  304. #--------------------------------------------------------------------------
  305. def tss_investigate
  306. sx = @x - @attention_x
  307. sy = @y - @attention_y
  308. if sx.abs + sy.abs >= 20
  309. move_random
  310. else
  311. case rand(6)
  312. when 0..3; move_toward_position(@attention_x,@attention_y)
  313. when 4; move_random
  314. when 5; move_forward
  315. end
  316. end
  317. end
  318. #--------------------------------------------------------------------------
  319. # * Move Toward Position
  320. #--------------------------------------------------------------------------
  321. def move_toward_position(x,y)
  322. sx = @x - x
  323. sy = @y - y
  324. if sx != 0 or sy != 0
  325. if sx.abs > sy.abs # Horizontal distance is longer
  326. sx > 0 ? move_left : move_right # Prioritize left-right
  327. if @move_failed and sy != 0
  328. sy > 0 ? move_up : move_down
  329. end
  330. else # Vertical distance is longer
  331. sy > 0 ? move_up : move_down # Prioritize up-down
  332. if @move_failed and sx != 0
  333. sx > 0 ? move_left : move_right
  334. end
  335. end
  336. end
  337. end
  338. #----------------------------------------------------------------------------
  339. # Get Self Switch
  340. #----------------------------------------------------------------------------
  341. def get_self_switch(switch)
  342. key = [@map_id, @id, switch]
  343. return $game_self_switches[key]
  344. end
  345. #----------------------------------------------------------------------------
  346. # Set Self Switch
  347. #----------------------------------------------------------------------------
  348. def set_self_switch(switch,true_false)
  349. key = [@map_id, @id, switch]
  350. $game_self_switches[key] = true_false
  351. $game_map.need_refresh = true
  352. end
  353. #----------------------------------------------------------------------------
  354. # Get Line
  355. #----------------------------------------------------------------------------
  356. # Algorithm by.. Bresenham
  357. # Written by.... RogueBasin
  358. #----------------------------------------------------------------------------
  359. def get_line(x0,y0,x1,y1)
  360. original_x0, original_y0 = x0, y0
  361. points = []
  362. steep = ((y1-y0).abs) > ((x1-x0).abs)
  363. if steep
  364. x0,y0 = y0,x0
  365. x1,y1 = y1,x1
  366. end
  367. if x0 > x1
  368. x0,x1 = x1,x0
  369. y0,y1 = y1,y0
  370. end
  371. deltax = x1-x0
  372. deltay = (y1-y0).abs
  373. error = (deltax / 2).to_i
  374. y = y0
  375. ystep = nil
  376. if y0 < y1
  377. ystep = 1
  378. else
  379. ystep = -1
  380. end
  381. for x in x0..x1
  382. if steep
  383. points << {:x => y, :y => x}
  384. else
  385. points << {:x => x, :y => y}
  386. end
  387. error -= deltay
  388. if error < 0
  389. y += ystep
  390. error += deltax
  391. end
  392. end
  393. if original_x0 != points[0][:x] or original_y0 != points[0][:y]
  394. points.reverse!
  395. end
  396. return points
  397. end
  398. end
  399. #==============================================================================
  400. # Game Event
  401. #==============================================================================
  402. class Game_Event < Game_Character
  403. #----------------------------------------------------------------------------
  404. # Name (get name)
  405. #----------------------------------------------------------------------------
  406. def name
  407. return @event.name
  408. end
  409. #----------------------------------------------------------------------------
  410. # Erased (get erased)
  411. #----------------------------------------------------------------------------
  412. def erased
  413. return @erased
  414. end
  415. end
  416. #==============================================================================
  417. # Game Player
  418. #==============================================================================
  419. class Game_Player < Game_Character
  420. #----------------------------------------------------------------------------
  421. # Local Variables
  422. #----------------------------------------------------------------------------
  423. attr_accessor :old_steps
  424. attr_accessor :sprint_noise
  425. #----------------------------------------------------------------------------
  426. # Update
  427. #----------------------------------------------------------------------------
  428. alias trace_player_update update unless $@
  429. def update(*args)
  430. trace_player_update(*args)
  431. @old_steps ||= 0
  432. @sprint_noise ||= Trace::DEFAULT_SPRINT_NOISE
  433. if $game_party.steps > @old_steps + 5 and moving? and dash?
  434. tss_noise(@sprint_noise)
  435. @old_steps = $game_party.steps
  436. end
  437. end
  438. end
  439. #==============================================================================
  440. # Game Interpreter
  441. #==============================================================================
  442. class Game_Interpreter
  443. #----------------------------------------------------------------------------
  444. # Huh?
  445. #----------------------------------------------------------------------------
  446. def huh?
  447. for event in $game_map.events.values
  448. if event.name.include?("tracer") and !event.erased
  449. next if Trace::ALLOW_SELF_SWITCH_DISABLING and
  450. event.get_self_switch(Trace::DISABLING_SELF_SWITCH)
  451. event.balloon_id = 2 # display ?
  452. end
  453. end
  454. end
  455. #----------------------------------------------------------------------------
  456. # Hey!
  457. #----------------------------------------------------------------------------
  458. def hey!
  459. for event in $game_map.events.values
  460. if event.name.include?("tracer") and !event.erased
  461. next if Trace::ALLOW_SELF_SWITCH_DISABLING and
  462. event.get_self_switch(Trace::DISABLING_SELF_SWITCH)
  463. event.balloon_id = 1 # display !
  464. end
  465. end
  466. end
  467. end
  468.  
  469. class Game_Character
  470.  
  471. unless method_defined?(:move_upper_right)
  472. define_method(:move_down) {|*args| move_straight(2)}
  473. define_method(:move_left) {|*args| move_straight(4)}
  474. define_method(:move_right) {|*args| move_straight(6)}
  475. define_method(:move_up) {|*args| move_straight(8)}
  476. define_method(:move_lower_left) {|*args| move_diagonal(4, 2)}
  477. define_method(:move_lower_right) {|*args| move_diagonal(6, 2)}
  478. define_method(:move_upper_left) {|*args| move_diagonal(4, 8)}
  479. define_method(:move_upper_right) {|*args| move_diagonal(6, 8)}
  480. end
  481. end

Share this post


Link to post
Share on other sites

The number 242 (ALERT_SWITCH) is a global switch. It is "automatically" turned ON when you are detected (in proximity and within line of sight) by events as long as they have the name "tracer" on it.

e.g. "GUARDtracer", "tracerMonster", "cooltracerguy"

The switch is then turned OFF when the tracers couldn't find you after 1800 frames (ALERT_COUNTDOWN).

Alternatively you can turn it ON/OFF using the "Control Switches..." command. It's on the first tab under "Game Progression".

 

I know this script and I own one as well. Works awesome. The only flaw I've found is the tracers getting back on their original positions. Nothing a little pathfinding can handle. :)

 

I'm going to have to apologize if I may sound a bit rough but I suggest that before you dive into working on a project with custom scripts, make a simple game without any custom scripts instead. You seem to be impatient to start from the bottom and see how things work around.

 

Projects will still be amazing with just the provided event commands and you'll learn eventing this way.

Please. Just take it as a friendly advice. I mean it that way so I'll apologize again. There's a good reason why houses are built from the ground up. Good day, mate.

Edited by Pokémon Trainer

Share this post


Link to post
Share on other sites

On tablet so forgive me for spelling. This isn't my first RPG Maker game, I began with XP ver many years ago but that project wasn't going anywhere. A few years later I rebooted the project but as the story in mind would be a rather long and full RPG, I knew I couldn't do it as needed help I couldn't afford.

 

So I put it on hold once again to further work on my writing and this current project started itself as had ideas flowing. I'm still fairy new but this isn't my first project. I appreciate your advice but I've already been there, and you weren't harsh. My best friend apologise for the same reason and I always tell him he's not.

 

As for what you answered, it'll be tomorrow before I can test and see if it'll work. Keep in mind I have OCD and I'm not a scripter, I'm not impatient I'm just asking for help which I never got for my original project. Again you weren't harsh, I see why you're suggesting that but I already been there twice.

 

I know that effort takes time and I'm asking for help so I won't blindly rush my game. Thanks for being concerned.

Share this post


Link to post
Share on other sites

From what I get you are not supposed to modify the value of alert switch yourself , it exist so that you can read the information if you need it, but the script turns the switch on and off by itself.

It should be OFF by default

Share this post


Link to post
Share on other sites

@Pokémon Trainer

Thanks. ^^ I'm about to test what you told me so let's see how that goes. Hm got the ? and ! to appear so that's good, let me re-read something right quick as need to see how to get the tracer to move when in caution mode. Hm, he doesn't say how the tracer moves so looking through the script's coding to see if its there.

 

I know I'll have to delete like 2 pages in the killer's event due to caution/disabled, before I had it where you can attack/knock him out from behind so that'll need to be in caution. Question, with the "HIDE_OPACITY = 50" does that turns on by making the player's opacity 50 via move route?

Share this post


Link to post
Share on other sites

When tracer is in caution, he will not move unless you use

tss_investigate

on his custom autonomous movement.

This will make him approach the "noise". He doesn't really follow you.

 

Yeah, you can use the Set Opacity command there. Equal value or lower. Alternatively, use the script's default switch 243 or set Transparent ON <- I wouldn't go for this last one unless I have some indicator where the player is like some character shadow.

 

Since this script is using a self switch for disabling and you're worrying about the need to use more than A to D, this next script works well with the stealth script. (Place this above stealth script)

 

More Self Switches

Credits to: gameguy

 

 

#===============================================================================
# More Self-Switches (VX Ace Edition)
# Version 1.0
# Author game_guy
# Really small edit by Bird Eater
#-------------------------------------------------------------------------------
# Intro:
# Ever need more than 4 self switches? With this small script, you can now
# have as many self switches you want. You aren't just limited to letters
# either. You can have names for them.
#
# Features:
# -More Self Switches
# -Name them whatever
#
# Instructions:
# -First, lets create a self switch for our event. Anywhere in the event, add
# a comment and type this,
# Switch:switch_name.
# switch_name can be whatever you want to name the switch. Thats all you have
# to do to create a self switch for that page.
# There cannot be any spaces between the colon and the switch name.
# e.g. Switch: switch - Does not work.
# e.g. Switch:switch - Does work.
#
# -Now to turn this switch of or on, call this in a script call.
# self_switch("switch", true/false) or 
# self_switch("switch", true/false, event_id)
# switch is the switch name, this must be in double " " or single ' ' quotes.
# true/false tells the script whether to turn it off or on. true = on, 
# false = off. Event_id is the id of the event you want to change the 
# self switch of, but it isn't necessary to add if it's for the event running
# this command.
#
# -If you want to see if a self switch is on/off, use this script in a
# condtional branch.
# self_switch_state("switch") == true/false
# switch is the switch name, this must be in double " " or single ' ' quotes.
# true = on, false = off
#
# Compatibility:
# Should work with anything.
#
# Credits:
# game_guy ~ For creating it.
#===============================================================================

class Game_Event < Game_Character
  alias gg_init_more_switches_lat initialize
  def initialize(map_id, event)
    gg_init_more_switches_lat(map_id, event)
    @event.pages.each {|page| page.list.each {|command|
      if [108, 408].include?(command.code)
        command.parameters.each {|p| check_custom_switch(page, p) }
      end}}
    refresh
  end
  def check_custom_switch(page, code)
    a = code.split(':')
    if !a[0].nil? && a[0].downcase == "switch" && a[1] != nil
      page.condition.self_switch_ch = a[1]  
      page.condition.self_switch_valid = true
    end
  end
end

class Game_Interpreter
  def self_switch(switch, state, evid=@event_id)
    if @event_id > 0
      key = [$game_map.map_id, evid, switch]
      $game_self_switches[key] = state
    end
    $game_map.need_refresh = true
  end
  
  def self_switch_state(switch)
    key = [$game_map.map_id, @event_id, switch]
    return $game_self_switches[key]
  end
end

 

 

Edited by Pokémon Trainer

Share this post


Link to post
Share on other sites

-Create a new event page on the tracer. He will use the caution self switch (script default = C).

-Add the script call:

tss_investigate

 on the tracer's Custom Autonomous Movement.

-I also recommend using the Freq (Frequency) of 5: Highest.

Edited by Pokémon Trainer

Share this post


Link to post
Share on other sites

@Pokémon Trainer

 

Custom Autonomous Movement? And it is a large map he has to walk about, in case you need  a ref for it.

 

 

5v2jqu.jpg

 

 

I can use pathfinding whenever his caution page isn't on.

Edited by Darkness Void

Share this post


Link to post
Share on other sites

That's one flaw that I see on this script. It doesn't have a smart pathfinding. It just tries to "dislodge" the tracer from his position and then try another route via a dice roll.

Going with a pathfinding script? Your call.

 

I have a few here. Use whatever you deem good.

 

cozziekuns

 

 

#===============================================================================
# [VXA] Pathfinding
#-------------------------------------------------------------------------------
# Version: 1.0
# Author: cozziekuns (rmrk)
# Last Date Updated: 12/31/2011 (MM/DD/YYYY)
#===============================================================================
# Description:
#-------------------------------------------------------------------------------
# This script allows you to move any character to another tile using the  
# shortest path possible. It takes a significantly longer time on large maps.
#===============================================================================
# Updates
# ------------------------------------------------------------------------------
# o 12/31/2011 - Started Script 
#===============================================================================
# To-do List
#------------------------------------------------------------------------------- 
# o Allow for dynamic recalculation if one wants to repeat the pathfinding 
#   process for any reason.
#===============================================================================
# Instructions
#-------------------------------------------------------------------------------
# To use, create a move route event and as a script command use: 
#
# find_path(target_x, target_y)
#
# Additionally, one can force a path through a script using the following call:
# 
# force_path(target_x, target_y)
#
# There is a known bug that is present in Modern Algebra's script regarding the 
# recalculation of a path once found. Since some of this script is simply
# a convert from his VX version (only the algorithm is different by being
# slightly slower and sloppier ), the bug is also found in this script.
#===============================================================================

#==============================================================================
# ** Game_Map
#==============================================================================

class Game_Map
  
  def find_path(target_x, target_y, sx, sy, passable, char)
    path = []
    max_elements = width * height + 2
    checked_items = 0
    @open_list_items = 0
    @open_list = Table.new(max_elements)
    @nodes = Table.new(max_elements, 2)
    open = Table.new(width, height)
    closed = Table.new(width, height)
    parent = Table.new(width, height, 3)
    @f_cost = Table.new(width, height)
    @open_list[0] = 0
    @nodes[0, 0] = sx
    @nodes[0, 1] = sy
    next_point = [sx, sy]
    closed[sx, sy] = 1
    loop do
      next_point = delete_from_heap if not next_point == [sx, sy]
      return path if next_point.nil?
      open[next_point[0], next_point[1]] = 0
      closed[next_point[0], next_point[1]] = 2 if not next_point == [sx, sy]
      parent_x, parent_y = next_point[0], next_point[1]
      for i in 1..4
        x, y = case i * 2 
        when 2; [parent_x, parent_y + 1]
        when 4; [parent_x - 1, parent_y]
        when 6; [parent_x + 1, parent_y]
        when 8; [parent_x, parent_y - 1]
        end
        next if closed[x, y] == 2
        next unless char.passable?(parent_x, parent_y, i * 2) 
        if not open[x, y] == 1
          open[x, y] = 1
          parent[x, y, 0] = parent_x
          parent[x, y, 1] = parent_y
          parent[x, y, 2] = parent[parent_x, parent_y, 2] + 10
          g = parent[x, y, 2] + 10
          h = ((target_x - x).abs + (target_y - y).abs) * 10
          @f_cost[x, y] = g 
          checked_items += 1
          @open_list_items += 1
          @nodes[checked_items, 0] = x
          @nodes[checked_items, 1] = y
          add_to_heap(checked_items)
        else
          old_g = parent[x, y, 2] + 10
          new_g = parent[parent_x, parent_y, 2] + 20
          next if old_g < new_g
          parent[x, y, 0] = parent_x
          parent[x, y, 1] = parent_y
          parent[x, y, 2] = new_g
          g = parent[x, y, 2] + 10
          h = ((target_x - x).abs + (target_y - y).abs) * 10
          @f_cost[x, y] = g 
        end
      end
      next_point = nil
      break if closed[target_x, target_y] == 2
    end    
    path_x, path_y = target_x, target_y    
    loop do   
      parent_x = parent[path_x, path_y, 0]
      parent_y = parent[path_x, path_y, 1]
      if path_x < parent_x
        code = 2
      elsif path_x > parent_x
        code = 3
      else
        code = path_y < parent_y ? 4 : 1
      end      
      path.push(RPG::MoveCommand.new(code))
      path_x, path_y = parent_x, parent_y      
      break if path_x == sx and path_y == sy
    end
    return path
  end
  
  def add_to_heap(value)
    m = @open_list_items
    @open_list[m] = value
    while m != 1
      if fcost(@open_list[m]) < fcost(@open_list[m / 2])
        temp = @open_list[m / 2]
        @open_list[m / 2] = @open_list[m]
        @open_list[m] = temp
        m /= 2
      else
        break
      end
    end
  end
  
  def delete_from_heap
    next_point = @open_list[0]
    @open_list[0] = @open_list[@open_list_items]
    @open_list_items -= 1
    v = 1
    loop do
      u = v
      w = 2 * u
      if w + 1 <= @open_list_items
        v = w if fcost(@open_list[u - 1]) >= fcost(@open_list[w - 1])
        v = w + 1 if fcost(@open_list[v - 1]) >= fcost(@open_list[w]) 
      elsif w <= @open_list_items
        v = w if fcost(@open_list[u - 1]) >= fcost(@open_list[w - 1])
      end
      if u != v
        temp = @open_list[u - 1]
        @open_list[u - 1] = @open_list[v - 1]
        @open_list[v - 1] = temp 
      else
        break
      end
    end
    return @nodes[next_point, 0], @nodes[next_point, 1]
  end
  
  def fcost(point)
    x = @nodes[point, 0]
    y = @nodes[point, 1]
    return @f_cost[x, y]
  end
  
end

#==============================================================================
# ** Game_CharacterBase
#==============================================================================

class Game_CharacterBase

  def find_path(target_x, target_y)
    path = $game_map.find_path(target_x, target_y, @x, @y, false, self)
    @move_route.list.delete_at(@move_route_index)
    path.each { |i| @move_route.list.insert(@move_route_index, i) }
    @move_route_index -= 1
  end
  
  def force_path(target_x, target_y)
    path = $game_map.find_path(target_x, target_y, @x, @y, false, self)
    path.reverse!
    path.push (RPG::MoveCommand.new(0))
    move_route = RPG::MoveRoute.new
    move_route.list = path
    move_route.repeat = false
    force_move_route(move_route)
  end
  
  def count_iterations(target_x, target_y)
    path = $game_map.find_path(target_x, target_y, @x, @y, true, self)
    return path.size
  end
  
end

 

 

 

Jet

 

 

#===============================================================================
# Pathfinding
# By Jet10985(Jet)
# Minor modifications by Venima
#===============================================================================
# This script will allow you to use a pathfinder to move players or events.
# This script has: 0 customization options.
#
# Modifications: 
# 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).
# 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)
#===============================================================================
# Overwritten Methods:
# None
#-------------------------------------------------------------------------------
# Aliased methods:
# None
#===============================================================================
=begin
To move a player or event, use this in an event "Script..." command:

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

x is the target x
y is the targey y

ev is set to 0 by default and can be omitted like so: find_path(9, 0)
ev represents what 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 if set to false and can be ommitted like so: 
find_path(9, 0) or find_path(9, 0, -1)
wait specifies if the player will have to wait for the move route to finish
to start moving again.

distance is set to 0 by default and can be omitted in the same way as above.
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. If you do specify distance, you must also specify 
all optional parameters.

Example of following the player at a distance, either using:

Event's custom move route (on repeat): 
  find_path($game_player.x, $game_player.y, 3)
Or set move route command in a loop: 
  find_path($game_player.x, $game_player.y, 0, true, 3)



You may also use find_path(x, y) (no ev or wait) inside of an event's
"Set Move Route..." command, using the "Script..." tab. This does the same
as above, but takes on the properties of the move route you are making,
including the affected character.
=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.
    MAXIMUM_ITERATIONS = 1000
    
  end
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
  
  #modified line below (added distance parameter)
  def find_path(tx, ty, sx, sy, dist, char = $game_player)
    start = Node.new(Point.new(sx, sy))
    goal = Node.new(Point.new(tx, ty))
    #modified line below (added distance handling)
    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|
        #modified line below (added distance handling)
        if node == goal or (dist > 0 and node.point.distance(goal.point) <= dist)
          node.parent = current
          node.mark_path
          return recreate_path(node)
        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)
    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]
      path.push(RPG::MoveCommand.new(hash[ar] / 2))
    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)
    path = $game_map.find_path(x, y, self.x, self.y, dist).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
      process_move_command(path[0])
      @move_route_index -= 1
    end
    
  end
end

class Game_Interpreter
  
  #modified line below (added distance parameter)
  def find_path(x, y, ev = 0, wait = false, dist = 0)
    char = get_character(ev)
    #modified line below (added distance parameter)
    path = $game_map.find_path(x, y, char.x, char.y, dist)
    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 

 

 

 

Karanum

 

 

#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# - Pathfinding script by Karanum -
#----------------------------------------------------------------------------
# This pathfinding script is based off a simplified version of Dijkstra's
# algorithm. It's mainly made for calculating paths over small distances,
# but also provides some methods for longer calculations.
#
# It adds 4 different methods for calculating the path and 1 method to check
# whether an event is pathfinding or not.
# For all of these methods, the x and y are the end coordinates and the id is
# the id of the event that has to run the pathfinding method. When left out, the
# id will always default to 0. **
# Setting through? allows you to change the pathfinding event's passability.
# This setting defaults to true if you don't set it.
#
#
#   - walk_to_straight( x, y, id, through? )
#	   This performs simple pathfinding, using only a part of the map.
#	   It can't find long detours, but it's the least expensive method.
#	   This should be used for basic events that don't require advanced
#	   pathfinding.
#
#   - walk_to( x, y, id, through? )
#	   This is the most basic form of the pathfinding algorithm, although it
#	   can lag when using large maps or when there is no path to the endpoint.
#	   This is the most balanced pathfinding method, able to find paths of up
#	   to a 1000 tiles.
#
#   - walk_to_short( x, y, id, through? )
#	   Basically a lesser version of the walk_to method.
#	   It can find paths of up to a 100 tiles and is best for larger maps.
#
#   - walk_to_long( x, y, max_steps, id, through? )
#	   This method lets you specify the maximum amount of tiles the path can
#	   be, but will take a while to calculate the path. This method is best
#	   for pathfinding over long distances, although it takes the longest.
#	   This method will only lag the calling event, not your entire game.
#
#   - pathfinding?( id )
#	   This method returns true when the specified event is currently going
#	   through one of the above methods. Otherwise it returns false.
#
#
# ** NOTE: As event id, you can use 0 for 'This Event' and -1 for 'Player'
#
# Don't change anything past this point if you don't know what you're doing.
# It can make your game crash when you try to call one of the methods.
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# - Game_Character -
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
class Game_Character
  attr_accessor :target_x
  attr_accessor :target_y
  attr_reader   :path_through
  attr_reader   :pathfinding
  attr_reader   :distance_map

  #--------------------------------------------------------------------------
  # Game_CharacterBase's update override
  # May cause incompatibility with other scripts that also override this
  #--------------------------------------------------------------------------
  def update
	update_animation
	return update_jump if jumping?
	return update_move if moving?
	return update_path if pathfinding?
	return update_stop
  end

  #--------------------------------------------------------------------------
  # Update pathfinding movement
  #--------------------------------------------------------------------------
  def update_path
	if !@distance_map
	  return
	end

	if (@x == @target_x) and (@y == @target_y)
	  puts "[Pathfinding] Pathfinding completed"
	  @through = false if @path_through
	  @pathfinding = false
	  return
	end

	next_dir = find_next_tag(@distance_map, @x, @y)
	if next_dir == 0
	  puts "[Pathfinding] Could not find path to endpoint"
	  puts "[Pathfinding] If a path exists, try increasing the amount of iterations"
	  @through = false if @path_through
	  @pathfinding = false
	  return
	end

	move_straight(next_dir)
  end

  #--------------------------------------------------------------------------
  # Check if currently pathfinding
  #--------------------------------------------------------------------------
  def pathfinding?
	if @pathfinding
	  return @pathfinding
	else
	  return false
	end
  end

  #--------------------------------------------------------------------------
  # Obtain array with distance map from $game_map
  #--------------------------------------------------------------------------
  def walk_to(x, y, iterations=1000, long_mode=false, short_mode=false, passthrough=true)
	puts "[Pathfinding] Starting pathfinding"
	@pathfinding = true
	@path_through = passthrough
	@through = true if @path_through

	@target_x = x
	@target_y = y

	@distance_map = $game_map.find_path(self, x, y, iterations, long_mode, short_mode)
	puts "[Pathfinding] Distance map generated"
  end

  #--------------------------------------------------------------------------
  # Find next tile to walk to
  #--------------------------------------------------------------------------
  def find_next_tag(map, x, y)
	current_tag = map[y][x]
	if(current_tag == -1)
	  return 0
	end

	if y != (map.length - 1)
	  if map[y+1][x] == current_tag - 1
		return 2
	  end
	end

	if x != 0
	  if map[y][x-1] == current_tag - 1
		return 4
	  end
	end

	if y != 0
	  if map[y-1][x] == current_tag - 1
		return 8
	  end
	end

	if x != (map[y].length - 1)
	  if map[y][x+1] == current_tag - 1
		return 6
	  end
	end

	return 0

  end
end

#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# - Game_Map -
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
class Game_Map

  #--------------------------------------------------------------------------
  # Check adjacent tiles for passability
  #--------------------------------------------------------------------------
  def check_adjacent_panels(x, y)
	adjacent_panels = Array.new(4, false)

	if y != (height - 1)
	  if passable?(x, y, 2) and passable?(x, y+1, 8) #Down
		adjacent_panels[0] = true
	  end
	end

	if y != 0
	  if passable?(x, y, 8) and passable?(x, y-1, 2) #Up
		adjacent_panels[2] = true
	  end
	end

	if x != (width - 1)
	  if passable?(x, y, 6) and passable?(x+1, y, 4) #Right
		adjacent_panels[3] = true
	  end
	end

	if x != 0
	  if passable?(x, y, 4) and passable?(x-1, y, 6) #Left
		adjacent_panels[1] = true
	  end
	end

	return adjacent_panels
  end

  #--------------------------------------------------------------------------
  # Create an array with a distance map to the endpoint
  #--------------------------------------------------------------------------
  def find_path(event, x, y, iterations=1000, long_mode=false, short_mode=false)
	map_array = Array.new(height) { Array.new(width, -1) }
	map_array[y][x] = 0
	current_tag = 0
	current_iteration = 0

	low_x = 0
	low_y = 0
	high_x = width - 1
	high_y = height - 1

	if short_mode
	  low_x = [event.x, x].min - 2
	  low_y = [event.y, y].min - 2
	  high_x = [event.x, x].max + 2
	  high_y = [event.y, y].max + 2
	end

	iterations.times do
	  current_iteration = current_iteration + 1
	  for map_y in (low_y..high_y)
		for map_x in (low_x..high_x)
		  if map_array[map_y][map_x] == current_tag
			adjacent_panels = check_adjacent_panels(map_x, map_y)
			if adjacent_panels[0]
			  if map_array[map_y+1][map_x] == -1
				map_array[map_y+1][map_x] = current_tag + 1
			  end
			end
			if adjacent_panels[1]
			  if map_array[map_y][map_x-1] == -1
				map_array[map_y][map_x-1] = current_tag + 1
			  end
			end
			if adjacent_panels[2]
			  if map_array[map_y-1][map_x] == -1
				map_array[map_y-1][map_x] = current_tag + 1
			  end
			end
			if adjacent_panels[3]
			  if map_array[map_y][map_x+1] == -1
				map_array[map_y][map_x+1] = current_tag + 1
			  end
			end
		  end
		end
	  end
	  current_tag = current_tag + 1
	  if map_array[event.y][event.x] != -1
		return map_array
	  end
	  if (current_iteration % 20 == 0) and long_mode
		Fiber.yield
	  end
	end

	return map_array
  end
end

#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# - Game_Interpreter -
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Changes:
#   - Added walk_to(x, y, id)
#   - Added walk_to_short(x, y, id)
#   - Added walk_to_long(x, y, iterations, id)
#   - Added walk_to_straight(x, y, id)
#   - Added pathfinding?(id)
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
class Game_Interpreter
  def walk_to(x, y, id=0, passthrough=true)
	character = get_character(id)
	character.walk_to(x, y, 1000, false, false, passthrough)
  end

  def walk_to_short(x, y, id=0, passthrough=true)
	character = get_character(id)
	character.walk_to(x, y, 100, false, false, passthrough)
  end

  def walk_to_long(x, y, iterations, id=0, passthrough=true)
	character = get_character(id)
	character.walk_to(x, y, iterations, true, false, passthrough)
  end

  def walk_to_straight(x, y, id=0, passthrough=true)
	character = get_character(id)
	character.walk_to(x, y, 1000, false, true, passthrough)
  end

  def pathfinding?(id=0)
	character = get_character(id)
	return character.pathfinding?
  end
end 

 

 

 

TheoAllen

 

 

#==============================================================================
# TheoAllen - A* Pathfinding
# Version : 1.0
# Language : English
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Contact :
#------------------------------------------------------------------------------
# *> http://www.rpgmakerid.com
# *> http://www.rpgmakervxace.net
# *> http://www.theolized.com
#==============================================================================
($imported ||= {})[:Theo_Pathfinding] = true
#===============================================================================
# Change Logs:
# ------------------------------------------------------------------------------
# 2015.01.08 - English translation
# 2015.01.07 - Added A* Pathfinding
#            - Map loop support pathfinding
# 2015.01.06 - Finished
# 2014.05.08 - Initial prototype
#===============================================================================
=begin

  =================================
  *) Introduction :
  ---------------------------------
  This script simply for determine the shortest path from started from a
  character position to target coodrinate.
  
  =================================
  *) How to use :
  ---------------------------------
  Simply put the script below material.
  
  ----------------------
  *) SCRIPT CALL
  ----------------------
  - find_path(x,y)
  Use this script call in set move route. Where (x,y) are the target coordinate.
  If path not found, character won't move.
  
  - goto_event(id)
  Use this script call in set move route. Where id is event id
  
  - goto_player
  Use this script call in set move route to make an event go to the player
  position.
  
  ----------------------
  *) EVENT COMMENT
  ----------------------
  <chase player>.
  Use this tag in event comment to make player chase the event. It behave like
  autonomous movement.
  
  <stop chase>
  script
  </stop chase>
  Use this tag if you want to stop the event from chasing the player. Script
  is a valid ruby script to determine stop condition. For example, if you have
  safe zone marked by region ID 1, you could add comment like this
  
  <stop chase>
  $game_player.region_id == 1
  </stop chase>
  
  =================================
  *) Important notes :
  ---------------------------------
  Chase player is still experimental. There's a chance that there will be
  discovered bugs. This pathfinding is exluce the diagonal movement and only
  support 4 direction at the moment. And there's a chance that it won't work
  in pixel movement as well.
  
  =================================
  *) Terms of use :
  ---------------------------------
  Credit me, TheoAllen. You are free to edit this script by your own. As long 
  as you don't claim it's yours. For commercial purpose, don't forget to give me
  a free copy of the game.

=end
#===============================================================================
# Below this line is sacred place to visit. Unless you have enough skill,
# do not try to enter or any risk is yours.
#===============================================================================

#===============================================================================
# ** Pathfinding Queue
#===============================================================================

class Pathfinding_Queue
  #----------------------------------------------------------------------------
  # * Initialize
  #----------------------------------------------------------------------------
  def initialize(tx, ty, first_node)
    @astar = !$game_map.any_loop?
    @tx = tx
    @ty = ty
    clear
    @front_queue.push(first_node)
    @range_cache = {}
  end
  
  #----------------------------------------------------------------------------
  # * Range
  #----------------------------------------------------------------------------
  def range(node)
    unless @range_cache[node]
      range_x = node.x - @tx
      range_y = node.y - @ty
      @range_cache[node] = Math.sqrt((range_x**2) + (range_y**2))
    end
    return @range_cache[node]
  end
  
  #----------------------------------------------------------------------------
  # * Push
  #----------------------------------------------------------------------------
  def push(new_node, parent_node)
    if @astar && range(new_node) < range(parent_node)
      @front_queue.push(new_node)
      @front_queue.sort! {|a,b| range(a) <=> range(}
    else
      @back_queue.push(new_node)
    end
  end
  
  #----------------------------------------------------------------------------
  # * Shift
  #----------------------------------------------------------------------------
  def shift
    result = @front_queue.shift
    return result if result
    return @back_queue.shift
  end
  
  #----------------------------------------------------------------------------
  # * Empty
  #----------------------------------------------------------------------------
  def empty?
    @front_queue.empty? && @back_queue.empty?
  end
  
  #----------------------------------------------------------------------------
  # * Clear
  #----------------------------------------------------------------------------
  def clear
    @front_queue = []
    @back_queue = []
  end
  
end

#===============================================================================
# ** MapNode
#===============================================================================

class MapNode
  #----------------------------------------------------------------------------
  # * Public attributes
  #----------------------------------------------------------------------------
  attr_accessor :parent   
  attr_accessor :visited
  attr_reader :expanded 
  attr_reader :nodes    
  attr_reader :x
  attr_reader :y
  
  #----------------------------------------------------------------------------
  # * Initialize
  #----------------------------------------------------------------------------
  def initialize(x,y)
    @x, @y = x, y
    @nodes = {}
    @visited = false
    @expanded = false
  end
  
  #----------------------------------------------------------------------------
  # * Expand node
  #----------------------------------------------------------------------------
  def expand_node(mapnodes, char)
    dir = [2,4,6,8]
    dir.each do |d|
      next unless char.pathfinding_passable?(@x, @y, d)
      xpos = $game_map.round_x_with_direction(@x, d)
      ypos = $game_map.round_y_with_direction(@y, d)
      key = [xpos, ypos]
      next_node = mapnodes[key]
      if next_node.nil?
        next_node = MapNode.new(xpos, ypos)
        mapnodes[key] = next_node
      elsif next_node.visited
        next
      end
      next_node.parent = self
      self.nodes[d] = next_node
    end
    @expanded = true
  end
  
  #----------------------------------------------------------------------------
  # * Get Parent Direction
  #----------------------------------------------------------------------------
  def get_parent_dir
    parent.nodes.index(self)
  end
  
end

#===============================================================================
# ** Game_Map
#===============================================================================

class Game_Map
  def any_loop?
    loop_horizontal? || loop_vertical?
  end
end

#===============================================================================
# ** Game_Character
#===============================================================================

class Game_Character
  #----------------------------------------------------------------------------
  # * Find path (x, y)
  #   Do not set clear to true in move route script
  #----------------------------------------------------------------------------
  def find_path(tx, ty, clear = false)
    return if x == tx && y == ty
    return unless [2,4,6,8].any? {|dir| passable?(tx, ty, dir)}
    
    # Initialize
    @move_code = nil
    @mapnodes = {}
    @target_findx = tx
    @target_findy = ty
    
    # Make first node to check
    first_node = MapNode.new(self.x, self.y)
    first_node.expand_node(@mapnodes, self)
    first_node.visited = true
    @mapnodes[[self.x, self.y]] = first_node
    @queue = Pathfinding_Queue.new(tx, ty, first_node)
    
    # breadth first seach iteration
    until @queue.empty?
      bfsearch(@queue.shift)
    end
    
    # Execute move code
    if clear
      unless @move_code
        process_route_end
        return
      end
      route = RPG::MoveRoute.new
      route.repeat = false
      route.list = @move_code
      force_move_route(route)
    elsif @move_code
      mv_list = @move_route.list.clone
      insert_index = @move_route_index 
      @move_code.each do |li|
        mv_list.insert(insert_index, li)
        insert_index += 1
      end
      @move_route.list = mv_list
      @move_route_index -= 1
    end
    @target_findx = @target_findy = nil
  end
  
  #----------------------------------------------------------------------------
  # * Breadth First Search
  #----------------------------------------------------------------------------
  def bfsearch(node)
    dir = [2,4,6,8]
    dir.shuffle.each do |d|
      next_node = node.nodes[d]
      next unless next_node
      next if next_node.visited
      if next_node.x == @target_findx && next_node.y == @target_findy
        @move_code = generate_route(next_node)
        @queue.clear
        return
      end
      next_node.expand_node(@mapnodes, self) unless next_node.expanded
      next_node.visited = true
      @queue.push(next_node, node)
    end
  end
  
  #----------------------------------------------------------------------------
  # * Generate move command list based on node
  #----------------------------------------------------------------------------
  def generate_route(node)
    list = []
    while node.parent
      command = RPG::MoveCommand.new
      command.code = node.get_parent_dir/2
      list.unshift(command)
      node = node.parent
    end
    return list
  end
  
  #----------------------------------------------------------------------------
  # * Chase character
  #----------------------------------------------------------------------------
  def goto_character(char, clear = false)
    return unless char
    find_path(char.x, char.y, clear)
  end
  
  #----------------------------------------------------------------------------
  # * Chase player
  #----------------------------------------------------------------------------
  def goto_player(clear = false)
    goto_character($game_player, clear)
  end
  
  #----------------------------------------------------------------------------
  # * Chase event
  #----------------------------------------------------------------------------
  def goto_event(id, clear = false)
    goto_character($game_map.events[id], clear)
  end
  
  #----------------------------------------------------------------------------
  # * Target point?
  #----------------------------------------------------------------------------
  def target_point?(x, y)
    @target_findx == x && @target_findy == y
  end
  
  #----------------------------------------------------------------------------
  # * Pathfinding Passable?
  #----------------------------------------------------------------------------
  def pathfinding_passable?(x, y, d)
    x2 = $game_map.round_x_with_direction(x, d)
    y2 = $game_map.round_y_with_direction(y, d)
    if target_point?(x2, y2)
      return true if @through
      return map_passable?(x, y, d) && map_passable?(x2, y2, reverse_dir(d))
    end
    passable?(x, y, d)
  end
  
end

#===============================================================================
# ** Game_Event
#===============================================================================

class Game_Event
  #----------------------------------------------------------------------------
  # * Regular expression for chase player
  #----------------------------------------------------------------------------
  REGX_ChasePlayer = /<chase[\s_]player>/i
  REGX_ChaseCondS  = /<stop[\s_]chase>/i
  REGX_ChaseCondE  = /<\/stop[\s_]chase>/i
  
  #----------------------------------------------------------------------------
  # * Alias : Setup page settings
  #----------------------------------------------------------------------------
  alias theo_pathfind_setup_page_settings setup_page_settings
  def setup_page_settings
    theo_pathfind_setup_page_settings
    init_chase_variables
    return unless @list
    load = false
    @list.each do |cmd|
      next unless [108, 408].include?(cmd.code)
      case cmd.parameters[0]
      when REGX_ChasePlayer
        setup_chase($game_player, 45)
      when REGX_ChaseCondS
        load = true
        @chase_condition = ""
        next
      when REGX_ChaseCondE
        load = false
      else 
        if load
          @chase_condition += cmd.parameters[0]
        end
      end
    end
  end
  
  #----------------------------------------------------------------------------
  # * Init chase variables
  #----------------------------------------------------------------------------
  def init_chase_variables
    @target_object = nil
    @path_refresh_rate = 0
    @path_refresh_count = 0
    @chase_condition = "false"
    @player_lastpost = []
  end
  
  #----------------------------------------------------------------------------
  # * Setup chase
  #----------------------------------------------------------------------------
  def setup_chase(char, rate)
    @target_object = char
    @path_refresh_rate = rate
  end
  
  #----------------------------------------------------------------------------
  # * Alias : Update
  #----------------------------------------------------------------------------
  alias theo_pathfind_update update
  def update
    theo_pathfind_update
    return unless @target_object 
    return if $game_map.interpreter.running?
    @path_refresh_count -= 1
    return if @path_refresh_count > 0 || moving? || playerpos_not_changed?
    update_pathfinding
  end
  
  #----------------------------------------------------------------------------
  # * Update pathfinding
  #----------------------------------------------------------------------------
  def update_pathfinding
    @path_refresh_count = @path_refresh_rate
    @player_lastpost = [$game_player.x, $game_player.y]
    unless eval(@chase_condition)        
      goto_character(@target_object, true)
    else
      process_route_end
    end
  end
  
  #----------------------------------------------------------------------------
  # * Player position not changed?
  #----------------------------------------------------------------------------
  def playerpos_not_changed?
    @player_lastpost == [$game_player.x, $game_player.y]
  end
  
end
 

 

 

 

You may also want to ask script support. To make LiTTleDRago's script "co-operate" with another pathfinder script.

Edited by Pokémon Trainer

Share this post


Link to post
Share on other sites

I'll let you read something. I'm also checking this one right now so don't ask me just yet about this. :)

 

Stealth System

Credits: Jet, TouchFuzzy

 

 

#===============================================================================
# Stealth System
# By Jet10985 (Jet)
# Inspired By: Touchfuzzy
#===============================================================================
# This script will implement a realistic stealth detection system for use
# with events. All measurements are interpreted as metres.
# This script has: 20 customization options.
#===============================================================================
# Overwritten Methods:
# None
#-------------------------------------------------------------------------------
# Aliased methods:
# Game_System: initialize
# Game_Player: update
#===============================================================================
=begin
To set an event's height, use this Comment in their event page:

HEIGHT = number
--------------------------------------------------------------------------------
To set the player's default camo rating, use this in an event "Script...":

change_player_camo(number)
--------------------------------------------------------------------------------
To give an equipment a bonus to camo rating, use this in the armor's notebox:

<camo = number>
--------------------------------------------------------------------------------
To change the player's height, use this in an event "Script...":

change_player_height(number)
--------------------------------------------------------------------------------
To manually set a region or terrain tag's camo or height for a map, use these in
an event's "Script..." command:

set_region_height(region_id, number)
set_terrain_height(terrain_id, number)
set_region_camo(region_id, number)
set_terrain_camo(terrain_id, number)
--------------------------------------------------------------------------------
You can check for sighting of any event or the player using this
in an event's Conditional Branch "Script...":

can_see?(char_id)

char_id by default is -1, which means the Player
0 is the calling event
anything above 0 is the id of an event on the map
=end

module Jet
  module Stealth
    
    # This is the button used for the player to enter a "ducking" position.
    DUCK_BUTTON = :ALT
    
    # This is the suffix of the sprite that the player's will be changed to when
    # ducking. If the player's sprite name is "Jimmy" and the suffix is "_duck"
    # then the game will look for "Jimmy_duck"
    DUCK_SUFFIX = "_duck"
    
    # This is how many metres a single tile represents.
    TILE_METRE_DIST = 75
    
    # this is how tall events are by default.
    DEFAULT_EVENT_HEIGHT = 1.7
    
    # This is how tall the player is by default.
    PLAYER_HEIGHT = 1.7
    
    # this is how much "camo" rating is gained from ducking.
    DUCKING_CAMO_GAINED = 20
    
    # This is how much "camo" rating is lost when moving while dashing.
    DASHING_CAMO_LOST = 15
    
    # This is how much "camo" is lost when just moving without dashing.
    MOVEMENT_CAMO_LOST = 10
    
    # This is how much movement speed is lost when ducking.
    DUCKING_SPEED_LOST = 2
    
    # This is how many metres away a character has to be to have the
    # detector begin to lose some vision per metre.
    POINT_OF_VISION_LOSS = TILE_METRE_DIST * 5
    
    # This is how much "camo" is gained per metre once distance has passed the
    # POINT_OF_VISION_LOSS mark.
    VISION_LOSS_PER_METRE = 0.00271
    
    # How tall are unpassable tiles by default? This only applies if there are
    # no events on the tile.
    UNPASSABLE_HEIGHT = (1.0 / 0.0)
    
    # These are the default heights of Region IDs for every map.
    # A map's specific region height can be changed by using a script command
    # found in the instructions above.
    # This follows the format: region_id => height
    REGION_HEIGHTS = {
    
      #1 => 0,
      #2 => 2,
      #3 => 0.2
      
    }
    
    # This is the default height of any undefined region above.
    REGION_HEIGHTS.default = 0
    
    # These are the default heights of Terrains for every map.
    # A map's specific terrain height can be changed by using a script command
    # found in the instructions above.
    # This follows the format: terrain_id => height
    TERRAIN_HEIGHTS = {
    
      #1 => 0,
      #2 => 2,
      #3 => 0.2
      
    }
    
    # This is the default height of any undefined terrain above.
    TERRAIN_HEIGHTS.default = 0
    
    # These are the default camo of Region IDs for every map.
    # A map's specific region camo can be changed by using a script command
    # found in the instructions above.
    # This follows the format: region_id => camo
    REGION_CAMOS = {}
    
    # This is the default camo of any undefined region above.
    REGION_CAMOS.default = 0
    
    # These are the default camo of Terrains for every map.
    # A map's specific terrain camo can be changed by using a script command
    # found in the instructions above.
    # This follows the format: terrain_id => camo
    TERRAIN_CAMOS = {}
    
    # This is the default camo of any undefined terrain above.
    TERRAIN_CAMOS.default = 0
    
  end
end

#===============================================================================
# DON'T EDIT FURTHER UNLESS YOU KNOW WHAT TO DO.
#===============================================================================

module Math
  
  module_function
  
  def dist_form(x, y, x2, y2)
    sqrt((x2 - x).abs ** 2 + (y2 - y).abs ** 2)
  end
  
  def horizon(metres)
    3.856 * sqrt(metres) * 1000
  end
  
  def rad_to_deg(rads)
    rads * 180 / PI
  end
end

class RPG::Armor
  
  def camo
    @camoflague ||= (
      f = self.note.match(/<CAMO[ ]*(\:|=)[ ]*(\d+)>/i)
      f.nil? ? 0 : f[2].to_f
    )
  end
end

class Game_Actor
  
  def character_name
    @character_name + ($game_player.ducking? ? Jet::Stealth::DUCK_SUFFIX : "")
  end
end

class Game_Event
  
  def check_for_comment(regexp)
    return false if empty?
    @list.select {|a| 
      [108, 408].include?(a.code) 
    }.collect {|a|
      a.parameters[0]
    }.each {|a|
      if !a[regexp].nil?
        return a.match(regexp)
      end
    }
    return false
  end
  
  def height
    f = check_for_comment(/HEIGHT[ ]*(\:|=)[ ]*(\d+)/i)
    f == false ? Jet::Stealth::DEFAULT_EVENT_HEIGHT : f[2].to_f
  end
  
  def movable?
    return false if moving?
    return false if @move_route_forcing
    return false if $game_message.busy? || $game_message.visible
    return true
  end
end

class Game_Player
  
  def height
    if ducking?
      if moving?
        f = (2.0 / 3.0)
      else
        f = (1.0 / 3.0)
      end
    else
      f = 1.0
    end
    $game_system.player_height * f
  end
  
  def ducking?
    Input.press?(Jet::Stealth::DUCK_BUTTON)
  end
  
  def camoflague
    camo = 0
    camo += $game_system.player_camo
    camo += $game_map.xy_camo(self.x, self.y)
    begin
      camo += $game_party.members[0].armors.inject {|a, b| a.camo + b.camo }
    rescue
    end
    if moving?
      if dash?
        camo -= Jet::Stealth::DASHING_CAMO_LOST
      else
        camo -= Jet::Stealth::MOVEMENT_CAMO_LOST
      end
    end
    camo += Jet::Stealth::DUCKING_CAMO_GAINED if ducking?
    [camo, 0].max
  end
  
  def real_move_speed
    super - (ducking? ? Jet::Stealth::DUCKING_SPEED_LOST : 0)
  end
  
  alias jet3745_update update
  def update(*args, &block)
    jet3745_update(*args, &block)
    @in_duck ||= false
    if ducking? && !@in_duck
      refresh
      @in_duck = true
    elsif !ducking? && @in_duck
      refresh
      @in_duck = false
    end
  end
end

class Game_Character
  
  attr_writer :sighted
  
  def camoflague
    camo = 0
    camo += $game_map.xy_camo(self.x, self.y)
    camo -= Jet::Stealth::MOVEMENT_CAMO_LOST if moving?
    [camo, 0].max
  end
  
  def sight_range
    map_height = $game_map.xy_height(self.x, self.y)
    Math.horizon(self.height + map_height)
  end
  
  def true_height
    self.height + $game_map.xy_height(self.x, self.y)
  end
  
  def horizontal_angle_from(char)
    x_dist = self.x - char.x
    y_dist = self.y - char.y
    hypo = Math.hypot(x_dist, y_dist)
    (Math.rad_to_deg(Math.atan2(y_dist, x_dist)) - 180).abs
  end
  
  def viewing_angle_horizontal
    case self.direction
    when 2
      [210, 330]
    when 4
      [120, 240]
    when 6
      10
    when 8
      [30, 150]
    end
  end
  
  def vertical_angle_from(char)
    height = (self.true_height - $game_map.xy_height(char.x, char.y)).abs
    distance = Math.dist_form(self.x, self.y, char.x, char.y)
    distance *= Jet::Stealth::TILE_METRE_DIST
    hypo = Math.hypot(height, distance)
    Math.rad_to_deg(Math.asin(height / hypo.to_f))
  end
  
  def tiles_seen(x, y, x1, y1, char = nil)
    tiles = {}
    sx = x - x1
    sy = y - y1
    if sx.abs > sy.abs
      direction = sx > 0 ? 4 : 6
    elsif sy != 0
      direction = sy > 0 ? 8 : 2
    end
    x_distance = x1 - x
    y_distance = y1 - y
    total_distance = Math.dist_form(x, y, x1, y1)
    x_per_tile = x_distance / total_distance
    y_per_tile = y_distance / total_distance
    x_dist_t = 0.0
    y_dist_t = 0.0
    if !char.nil?
      vert_angle = vertical_angle_from(char)
    end
    self_height = self.true_height
    until x_dist_t.abs >= x_distance.abs && y_dist_t.abs >= y_distance.abs
      x_dist_t += x_per_tile
      y_dist_t += y_per_tile
      x_tile = (x + x_dist_t).to_i
      y_tile = (y + y_dist_t).to_i
      height = $game_map.total_height(x_tile, y_tile, direction)
      tiles[[x_tile, y_tile]] = [height]
      if !char.nil?
        dist = (x_dist_t.abs + y_dist_t.abs) - total_distance
        dist = dist.abs
        viewing_height = self.height * dist - height
        tiles[[x_tile, y_tile]].push(viewing_height)
      end
    end
    tiles
  end
  
  def sighted?(char)
    distance = Math.dist_form(self.x, self.y, char.x, char.y)
    distance *= Jet::Stealth::TILE_METRE_DIST
    return false if distance > sight_range
    h_angle = horizontal_angle_from(char)
    case viewing_angle_horizontal
    when Array
      h_viewing_angle = viewing_angle_horizontal
      return false if !h_angle.between?(*h_viewing_angle)
    when 10
      return false unless h_angle.between?(0, 60) || h_angle.between?(320, 360)
    end
    v_angle = vertical_angle_from(char)
    if self.true_height >= $game_map.xy_height(char.x, char.y)
      return false unless v_angle <= 75
      v_viewing_angle = 75
    else
      return false unless v_angle <= 60
      v_viewing_angle = 60
    end
    camo = char.camoflague
    distance += (self.true_height - $game_map.xy_height(char.x, char.y)).abs
    if distance.between?(Jet::Stealth::POINT_OF_VISION_LOSS, sight_range)
      add = (distance - Jet::Stealth::POINT_OF_VISION_LOSS)
      add *= Jet::Stealth::VISION_LOSS_PER_METRE
      camo += add
    elsif distance > sight_range
      return false
    elsif distance < Jet::Stealth::POINT_OF_VISION_LOSS
      camo /= 4
    end
    camo = [camo, 0].max
    return false if rand(100) + 1 <= camo
    tiles = tiles_seen(self.x, self.y, char.x, char.y, char)
    tiles.each {|coords, heights|
      next if coords == [self.x, self.y]
      if heights[1] <= 0
        return false
      end
    }
    return true
  end
end

class Game_System
  
  attr_accessor :player_height, :player_camo
  
  alias jet3745_initialize initialize
  def initialize(*args, &block)
    jet3745_initialize(*args, &block)
    @player_height = Jet::Stealth::PLAYER_HEIGHT
    @player_camo = 0
  end
end

class Game_Map
  
  def xy_height(x, y, dir = 0)
    reg = region_id(x, y)
    reg_h = region_heights(reg)
    ter = terrain_tag(x, y)
    ter_h = terrain_heights(ter)
    pas_h = $game_map.passable?(x, y, dir) ? 0 : Jet::Stealth::UNPASSABLE_HEIGHT
    reg_h + ter_h + pas_h
  end
  
  def xy_camo(x, y)
    reg = region_id(x, y)
    reg_c = region_camos(reg)
    ter = terrain_tag(x, y)
    ter_c = terrain_camos(ter)
    reg_c + ter_c
  end
  
  def total_height(x, y, dir = 0)
    xy = xy_height(x, y, dir)
    evs = $game_map.events_xy(x, y)
    ev_height = evs.sort {|a, b| a.height <=> b.height }
    ev_height = (ev_height[-1].true_height rescue 0)
    xy + (ev_height || 0)
  end
  
  def region_heights(reg)
    (@map_region_heights ||= {})[@map_id] ||= Jet::Stealth::REGION_HEIGHTS
    @map_region_heights[@map_id][reg]
  end
  
  def set_region_height(reg, height)
    (@map_region_heights ||= {})[@map_id] ||= Jet::Stealth::REGION_HEIGHTS
    @map_region_heights[@map_id][reg] = height
  end
  
  def terrain_heights(ter)
    (@map_terrain_heights ||= {})[@map_id] ||= Jet::Stealth::TERRAIN_HEIGHTS
    @map_terrain_heights[@map_id][ter]
  end
  
  def set_region_height(ter, height)
    (@map_terrain_heights ||= {})[@map_id] ||= Jet::Stealth::TERRAIN_HEIGHTS
    @map_terrain_heights[@map_id][ter] = height
  end
  
  def region_camos(reg)
    (@map_region_camos ||= {})[@map_id] ||= Jet::Stealth::REGION_CAMOS
    @map_region_camos[@map_id][reg]
  end
  
  def set_region_camo(reg, camo)
    (@map_region_camos ||= {})[@map_id] ||= Jet::Stealth::REGION_CAMOS
    @map_region_camos[@map_id][reg] = camo
  end
  
  def terrain_camos(ter)
    (@map_terrain_camos ||= {})[@map_id] ||= Jet::Stealth::TERRAIN_CAMOS
    @map_terrain_camos[@map_id][ter]
  end
  
  def set_region_camo(ter, camo)
    (@map_terrain_camos ||= {})[@map_id] ||= Jet::Stealth::TERRAIN_CAMOS
    @map_terrain_camos[@map_id][ter] = camo
  end
end

class Game_Interpreter
  
  def set_region_height(reg, height)
    $game_map.set_right_height(reg, height)
  end
  
  def set_terrain_height(ter, height)
    $game_map.set_terrain_height(ter, height)
  end
  
  def set_region_camo(reg, camo)
    $game_map.set_right_height(reg, camo)
  end
  
  def set_terrain_camo(ter, camo)
    $game_map.set_terrain_height(ter, camo)
  end
  
  def change_player_height(height)
    $game_system.player_height = height
  end
  
  def change_player_camo(camo)
    $game_system.player_camo = camo
  end
  
  def can_see?(ev = -1)
    return true if ev == 0
    get_character(0).sighted?(get_character(ev))
  end
end 

 

 

Edited by Pokémon Trainer

Share this post


Link to post
Share on other sites

@Pokémon Trainer

 

I'm already using Jet's script. It was the only one I could get to work. XD And sorry I was a bit out of it last night, but I know where Custom Autonomous Movement is, just I never actually noticed it was called that. XD But had to face palm sadly as I added tss_investigate as a para-script command, you meant using the script command inside the event's custom move route. XD

 

Alert switch, hm....wait does that mean Self Switch A is Alert? I got him moving towards the noise but now need him to move towards the player. Wait just had a thought...when Self Switch C is off I could just his custom move route for the pathfinding script! Why didn't I think about that before?

 

 

#===============================================================================
# Pathfinding
# By Jet10985(Jet)
# Minor modifications by Venima
#===============================================================================
# This script will allow you to use a pathfinder to move players or events.
# This script has: 0 customization options.
#
# Modifications:
# 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).
# 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)
#===============================================================================
# Overwritten Methods:
# None
#-------------------------------------------------------------------------------
# Aliased methods:
# None
#===============================================================================
=begin
To move a player or event, use this in an event "Script..." command:

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

x is the target x
y is the targey y

ev is set to 0 by default and can be omitted like so: find_path(9, 0)
ev represents what 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 if set to false and can be ommitted like so:
find_path(9, 0) or find_path(9, 0, -1)
wait specifies if the player will have to wait for the move route to finish
to start moving again.

distance is set to 0 by default and can be omitted in the same way as above.
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. If you do specify distance, you must also specify
all optional parameters.

Example of following the player at a distance, either using:

Event's custom move route (on repeat):
  find_path($game_player.x, $game_player.y, 3)
Or set move route command in a loop:
  find_path($game_player.x, $game_player.y, 0, true, 3)



You may also use find_path(x, y) (no ev or wait) inside of an event's
"Set Move Route..." command, using the "Script..." tab. This does the same
as above, but takes on the properties of the move route you are making,
including the affected character.
=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.
    MAXIMUM_ITERATIONS = 1000
    
  end
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
 
  #modified line below (added distance parameter)
  def find_path(tx, ty, sx, sy, dist, char = $game_player)
    start = Node.new(Point.new(sx, sy))
    goal = Node.new(Point.new(tx, ty))
    #modified line below (added distance handling)
    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|
        #modified line below (added distance handling)
        if node == goal or (dist > 0 and node.point.distance(goal.point) <= dist)
          node.parent = current
          node.mark_path
          return recreate_path(node)
        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)
    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]
      path.push(RPG::MoveCommand.new(hash[ar] / 2))
    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)
    path = $game_map.find_path(x, y, self.x, self.y, dist).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
      process_move_command(path[0])
      @move_route_index -= 1
    end
    
  end
end

class Game_Interpreter
 
  #modified line below (added distance parameter)
  def find_path(x, y, ev = 0, wait = false, dist = 0)
    char = get_character(ev)
    #modified line below (added distance parameter)
    path = $game_map.find_path(x, y, char.x, char.y, dist)
    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

 

Edited by Darkness Void

Share this post


Link to post
Share on other sites

Sigh. If only it had a better pathfinding.

Well, it's your game. Do as you please.

Which could most probably mean that I'm the only person who won't be able to throw a pebble across the room and then sneeze right away; and let the NPC decide which one of the two noises he should follow if he's ever going to use a pathfinding script since he only has one darn caution switch without any further customization.

 

Phew! That was a long outrage. You'll do fine.

But me? I am so trapped on this problem. I'll have to work another way around with the script.

Have a pleasant day. I'm out. :)

Share this post


Link to post
Share on other sites

@Pokémon Trainer

 

Well he wasn't moving towards to player, he just stayed frozen solid even when I walked close enough for the ! to appear. And I tested my idea but it didn't work, seems a para-pathfinding based on his  X/Y won't work as need it to be turned off.

 

I wasn't saying I was ignoring your advise, I had a pathfinding script that worked extremely well so why shouldn't I try it with this detection script? Should I be forced to scarp it from all events in the game with it inside them just to use another pathfinding script I might or might not get to working for moving and following the player?

 

I had to test it with this new script, but it gave a error inside the tracer's custom move route and won't even turn off when you're seen or heard. I find this as a massive error on the creator's part. Failing to explain how to get the tracer to move towards the player and how to do pathfinding. Didn't this guy at most thought that the tracer needs to return to it's original spot?

 

As I was testing this I realized that the map might be just too big. I wanted this to be where the killer walks about the map and you have to sneak by him, and being so large I have to use quite a lot of pathfinding depending on where his X/Y was so he'll keep going in the right route and circling the map basically.

 

I don't think I can do that with this script as it fails to explain it, as well as how to get the tracer to move towards the player. I could just use "find_path($game_player.x, $game_player.y)" or "move towards player" but both of those wouldn't work for staying out of sight. I read the script more than once, but it does not mention, period, how the tracer move towards where he saw the player, he just sits there doing nothing. Now sound he moves towards, but the player? Well that wonders the script useless. XD

 

Sorry for my tone, I just hate finding something useful and tying it out just to hit brick wall after brick wall. I'm not scraping Jet's pathfinding script, it just works too well. If I could a second pathfinding, one that'll work where with the detection script, I'll do that. Just be too much of a pain scraping and replacing. I'll look at your linked/shared scripts above and see if I can/can't use them.

Edited by Darkness Void

Share this post


Link to post
Share on other sites

Ah, no worries. I didn't took a hit. I'm thinking you should ask around script support and hopefully someone would be gracious enough to add a snippet to this script cause we both just run into a bit of a snag.

My artistry doesn't do well with coding. :P

I'll be looking forward to anything you find. This script isn't really on my main game. So, until then. :)

Share this post


Link to post
Share on other sites

@Pokémon Trainer

 

I'll ask then, this script could work very well but for a event that needs to walk a good distance----yeah I thinkt his was only meant for a guard that just stands still. XD

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×