Advertisement
LiTTleDRAgo

[RGSS3] Prof. Meow Meow's Trace Stealth System

Aug 3rd, 2013
462
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 20.31 KB | None | 0 0
  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 = 1        # 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 = 100      # 0~255 (for realism, keep it low)
  51. HIDE_SWITCH = 2         # 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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement