document.write('
Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. //=============================================================================
  2. // Stealth.js
  3. //=============================================================================
  4.  
  5. /*:
  6.  * @plugindesc Adds stealth detection (hearing and vision) to selected events.
  7.  * @author whitesphere
  8.  *
  9.  * @param Base Visual Radius
  10.  * @desc By default, how many tiles must separate the player from an Event
  11.  * before the player cannot be seen/noticed at all, assuming the enemy Perception
  12.  * equals the Actor\'s Stealth ability, and assuming the party is not Dashing.
  13.  * @default 8
  14.  *
  15.  * @param Base Hearing Radius
  16.  * @desc By default, how many tiles must separate the player from an Event
  17.  * before the player cannot be heard at all, assuming the enemy Perception
  18.  * equals the Actor\' Stealth ability and assuming the party is not Dashing.
  19.  * @default 6
  20.  *
  21.  * @param Visual Cone
  22.  * @desc In degrees, how wide is the visual "cone."  If someone is outside that
  23.  * cone, they cannot be seen (but they can still be heard)
  24.  * @default 90
  25.  *
  26.  * @param Stealth Gauge
  27.  * @desc If true, show a small window at the top center which indicates how close the
  28.  * party is to being detected.
  29.  * @default True
  30.  *
  31.  * @param Detection Cooldown
  32.  * @desc After how many turns, assuming no further detections, will the
  33.  * Actor be "forgotten" by the Events.  Set to 0 to never cooldown.
  34.  * @default 10
  35.  *
  36.  * @param Default Stealth
  37.  * @desc A numeric value used for any unspecified Actor\'s Stealth skill
  38.  * as well as an enemy\'s Perception.  
  39.  * @default 50
  40.  *
  41.  * @param Detection Variable
  42.  * @desc Numeric value which identifies the Variable which will contain
  43.  * the party\'s current Detection level.  The value of 0=Not detected.
  44.  * higher values mean the player is more seen/heard.
  45.  * @default 10
  46.  *
  47.  * @param Search Threshold
  48.  * @desc When this search "score" is met or exceeded, an event will start
  49.  * Searching for the players.  This sets Self Switch C on the event and turns
  50.  * off Self Switch D.
  51.  * @default 30
  52.  *
  53.  * @param Detection Threshold
  54.  * @desc When this search "score" is met or exceeded, an event will
  55.  * have found the players.  This sets Self Switch D on the event and turns off
  56.  * Self Switch C.
  57.  * @default 60
  58.  *
  59.  * @param Noise Floor
  60.  * @desc Moving players make at least this much noise when standing still.
  61.  * This can be raised or lowered by modifiers.
  62.  * @default 10
  63.  *
  64.  * @param Max Stealth Score
  65.  * @desc This is the highest stealth score allowed.  Used to draw the gauge
  66.  * as well as for internal stealth calculations.
  67.  * @default 100
  68.  *
  69.  * @help To enable Stealth for a map, set the appropriate Stealth tag in the
  70.  * Map and at least one Stealth tag for one Event.  The way Stealth works is
  71.  * as follows:
  72.  *
  73.  * Either type of detection (sight or sound) starts with the appropriate Radius.
  74.  * Vision confirms the target is in the source\'s visual cone based on the direction
  75.  * the source is facing.  It also confirms the Line of Sight contains no non-passable
  76.  * tiles.  Finally, it compares the Brightness of the source\'s tile to the Brightness
  77.  * of the target\'s tile.  The brighter the target, relative to the source, the easier
  78.  * it is to see.
  79.  *
  80.  * Hearing just confirms the target is in range and applies modifiers based on the
  81.  * loudness of the target\'s tile.
  82.  *
  83.  * All of these then degrade the "detection result" over distance, add a stiff
  84.  * 200% penalty if the party is Dashing.  Finally, it adds in any other modifiers in the
  85.  * Equipment, Actor, Class, States and so on.
  86.  *
  87.  * Also, the appropriate Perception difference modifies this Radius --- higher
  88.  * Perception = more likely detection.    This plug-in compares Perception score to the
  89.  * target\'s Stealth Skill level to create another modifier.
  90.  *
  91.  * The end result is a Detection Score.  The plug-in picks the highest Detection Score
  92.  * if you have multiple party members.
  93.  *
  94.  * NOTE: ALL modifiers are multipliers and they ALL stack.  Therefore, using very large
  95.  * multipliers is not a good idea in most cases.
  96.  *
  97.  * ============================================================================
  98.  * Plug-in Commands
  99.  * ============================================================================
  100.  *
  101.  * Stealth noise <loudness> <brightness> - creates a burst of noise and light at
  102.  * the party\'s location, where loudness and brightness 100 = normal player
  103.  * movement.
  104.  * Stealth gauge (on or off) - Turns the on-screen gauge on or off
  105.  * Stealth reset - Resets the detection state for all events
  106.  *
  107.  * ============================================================================
  108.  * Notetags
  109.  * ============================================================================
  110.  *
  111.  * You can use this notetag inside of your maps.
  112.  *
  113.  * Map Notetags:
  114.  *   <Brightness: 3=250,5=50> <Loudness: 4=200>
  115.  *   Brightness is a set of Region ID paired with an adjustment factor.  The factor
  116.  *   identifies the brightness of a tile with that Region ID.  This is compared with
  117.  *   the brightness of the party leader\'s tile, defaulting to 100.
  118.  *
  119.  *   Loudness is a Region ID paired with an adjustment factor.  The factor
  120.  *   lists the loudness of a tile with that Region ID, defaulting to 100.  This allows
  121.  *   carpet to be softer than stone.
  122.  *
  123.  * Actor specific Notetag:
  124.  *  <Stealth: 10+a.lvl*2>
  125.  *  Stealth - Function which sets the Detection skill based on a formula which is
  126.  *  evaluated every time the Actor changes level.
  127.  *
  128.  * Armor/Weapon/Item/State/Actor/Class Notetag:
  129.  *  <Detection: 3 Brightness: 50 Loudness: 125>
  130.  *   Detection - Modifies the Detection skill.  This is an absolute value.
  131.  *   Brightness - Modifies Vision check.  50 = 50% harder to detect.
  132.  *   Loudness - Modifies Hearing check.  125 = 25% harder to detect than base.
  133.  * All of these are optional.
  134.  *
  135.  * Event Notetag:
  136.  *   <Patrol: 1 Brightness: 100 Loudness: 125 Detection: 0 BypassSwitch: 3>
  137.  *   Patrol is a Region ID used for patrolling.  Each Event will seek out the
  138.  *   Region ID nearest to its current location and move towards it.  When it
  139.  *   reaches the location, it looks for the next nearest one which has not yet
  140.  *   been reached.  When all have been reached, the Event starts over with
  141.  *   the entire list.  This is optional.  When the Player is detected or Searching
  142.  *   the event leaves Patrol.
  143.  *   BypassSwitch is optional.  If it is set and the appropriate switch is ON, the
  144.  *   event will not find the player.  Nor will it have a Stealth score.
  145.  *   The Detection, Vision and Hearing work the same as they do for the
  146.  *   Item/State/Actor/Class notetags.
  147.  *   If none of these notetags are present, the Event will not do anything related
  148.  *   to Stealth.
  149.  */
  150. (function() {
  151.  
  152. WS_StealthConfig = {};
  153.  
  154. WS_StealthConfig.Parameters = PluginManager.parameters(\'Stealth\');
  155. WS_StealthConfig.Param = {};
  156.  
  157. //=============================================================================
  158. // The plug-in parameters
  159. //=============================================================================
  160. WS_StealthConfig.Param.maxStealthScore = parseInt(WS_StealthConfig.Parameters[\'Max Stealth Score\']);
  161. WS_StealthConfig.Param.stealthGauge = WS_StealthConfig.Parameters[\'Stealth Gauge\'];
  162. WS_StealthConfig.Param.baseVisualRadius = parseInt(WS_StealthConfig.Parameters[\'Base Visual Radius\']);
  163. WS_StealthConfig.Param.baseAudioRadius = parseInt(WS_StealthConfig.Parameters[\'Base Hearing Radius\']);
  164. WS_StealthConfig.Param.visualCone = parseInt(WS_StealthConfig.Parameters[\'Visual Cone\']);
  165. WS_StealthConfig.Param.detectionCooldown = parseInt(WS_StealthConfig.Parameters[\'Detection Cooldown\']);
  166. WS_StealthConfig.Param.defaultStealth = parseInt(WS_StealthConfig.Parameters[\'Default Stealth\']);
  167. WS_StealthConfig.Param.detectionVariable = parseInt(WS_StealthConfig.Parameters[\'Detection Variable\']);
  168. WS_StealthConfig.Param.searchThreshold = parseInt(WS_StealthConfig.Parameters[\'Search Threshold\']);
  169. WS_StealthConfig.Param.detectionThreshold = parseInt(WS_StealthConfig.Parameters[\'Detection Threshold\']);
  170. WS_StealthConfig.Param.noiseFloor = parseInt(WS_StealthConfig.Parameters[\'Noise Floor\']);
  171. WS_StealthConfig.Param.noiseDecay = parseInt(WS_StealthConfig.Parameters[\'Noise Decay\']);
  172.  
  173.  
  174. //=============================================================================
  175. // Globals - THESE ARE NOT SAVED
  176. //=============================================================================
  177.  
  178. var $stealthWindow=null;
  179. var $stealth=null;
  180.  
  181. //=============================================================================
  182. // Object which confirms if a particular angle in radians is within the
  183. // specified vision cone
  184. // angle1 = Start of first range
  185. // angle2 - End of first range
  186. // angle3 - Start of second range, if defined.
  187. // angle3 - End of second range, if defined.
  188. //=============================================================================
  189. function VisionCone(angle1, angle2, angle3, angle4) {
  190.     this.angles=[];
  191.     this.angles[0]=angle1;
  192.     this.angles[1]=angle2;
  193.     if (angle3 !== undefined && angle4 !== undefined)
  194.     {
  195.         this.angles[2]=angle3;
  196.         this.angles[3]=angle4;
  197.     }
  198. }
  199.  
  200. //=============================================================================
  201. // For debugging
  202. //=============================================================================
  203. VisionCone.prototype.toString = function() {
  204.     result="cone: range 1="+this.angles[0]+" to "+this.angles[1];
  205.     if (this.angles.length > 2)
  206.     {
  207.         result +=", range 2="+this.angles[2]+" to "+this.angles[3];
  208.     }
  209.     return result;
  210. }
  211.  
  212. //=============================================================================
  213. // Returns true if the angle passed in is within the vision cone
  214. // angle - The angle to check
  215. //=============================================================================
  216. VisionCone.prototype.contains = function(angle) {
  217.     if (angle >= this.angles[0] && angle <= this.angles[1])
  218.         return true;
  219.     if (this.angles.length < 3)
  220.         return false;
  221.     if (angle >= this.angles[2] && angle <= this.angles[3])
  222.         return true;
  223.     return false;
  224. }
  225.  
  226. //=============================================================================
  227. // Object which contains stealth oriented functions.  All of the functions here
  228. // are, in effect, static since they take in all required parameters for each
  229. // method.
  230. //=============================================================================
  231. function Stealth() {
  232.    
  233.     this.initialize.apply(this,arguments);
  234. }
  235.  
  236.  
  237. //=============================================================================
  238. // The real constructor
  239. //=============================================================================
  240. Stealth.prototype.initialize = function() {
  241.    
  242.     /* Holds the last stealth score for each stealth event */
  243.     this.lastStealthScores=[];
  244.    
  245.     /* These caches hold StealthModifiers for items, states and so on.
  246.         This avoids having to regenerate them each check.
  247.     */
  248.     this.item_cache=[];
  249.     this.state_cache=[];
  250.     this.class_cache=[];
  251.     this.actor_cache=[];
  252.    
  253.     gauge_setting=WS_StealthConfig.Param.stealthGauge;
  254.     if (!gauge_setting)
  255.     {
  256.         this.stealth_gauge=$gameSwitches.getValue(-999);
  257.     }
  258.     else
  259.     {
  260.         gauge_setting=gauge_setting.toLowerCase();
  261.         if (gauge_setting == "on" || gauge_setting == "true" || gauge_setting == "yes") {
  262.             console.log("Stealth gauge is enabled");
  263.             this.stealth_gauge=true;
  264.         }
  265.         else
  266.         {
  267.             console.log("Stealth gauge is disabled");
  268.             this.stealth_gauge=false;
  269.         }
  270.     }
  271.     $gameSwitches.setValue(-999, this.stealth_gauge);
  272.    
  273.     /* Holds the VisionCone objects for each direction */
  274.     this.vision_cones=[];
  275.    
  276.     /* Calculate the VisionCones for the 4 cardinal directions */
  277.     /* DIRECTION VALUES: 2 = down, 4 = left, 6 = right, 8 = up */
  278.     visual_cone=WS_StealthConfig.Param.visualCone;
  279.    
  280.     /* Convert to radians.  However, we want 1/2 of the value,
  281.     because we will be adding and subtracting it from the central
  282.     angle
  283.     */
  284.     visual_cone *= 2*Math.PI/360;
  285.     visual_cone /= 2;
  286.    
  287.     /* Facing downwards */
  288.     central_angle=Math.PI/2;
  289.     this.vision_cones[2] = new VisionCone(central_angle-visual_cone, central_angle+visual_cone);
  290.    
  291.     /* Upwards */
  292.     central_angle=-Math.PI/2;
  293.     this.vision_cones[8] = new VisionCone(central_angle-visual_cone, central_angle+visual_cone);
  294.    
  295.     /* To the left */
  296.     this.vision_cones[4] = new VisionCone(Math.PI-visual_cone, Math.PI,
  297.     -Math.PI, -Math.PI+visual_cone);
  298.    
  299.     /* To the right */
  300.     central_angle=0;
  301.     this.vision_cones[6] = new VisionCone(0, visual_cone, central_angle-visual_cone, 0);
  302. }
  303.  
  304. //=============================================================================
  305. // For debugging
  306. //=============================================================================
  307. Stealth.prototype.toString = function() {
  308.     result="Stealth: lastStealthScore="+this.stealthScore();
  309.     return result;
  310. }
  311.  
  312. //=============================================================================
  313. // Returns the current stealth score
  314. //=============================================================================
  315. Stealth.prototype.stealthScore = function() {
  316.     max_stealth_score=0;
  317.     for (index=0; index<this.lastStealthScores.length; index++)
  318.     {
  319.         if (this.lastStealthScores[index] > max_stealth_score)
  320.             max_stealth_score=this.lastStealthScores[index];
  321.     }
  322.     return max_stealth_score;
  323. }
  324.  
  325. //=============================================================================
  326. // Plug-in commands
  327. //=============================================================================
  328. var _Stealth_pluginCommand =
  329.         Game_Interpreter.prototype.pluginCommand;
  330. Game_Interpreter.prototype.pluginCommand = function(command, args) {
  331.     _Stealth_pluginCommand.call(this, command, args);
  332.     command_lower=command.toLowerCase();
  333.     if (command_lower === \'stealth\' && args.length > 0) {
  334.         switch (args[0].toLowerCase()) {
  335.         /* Makes noise and a flash of light - forcing all patrolling guards to look. */
  336.         case \'noise\':
  337.             console.log("Creating noise: loudness="+args[1]+" brightness="+args[2]);
  338.             $stealth.checkAllEvents(parseInt(args[1]), parseInt(args[2]));
  339.             $stealth.updateGauge();
  340.             break;
  341.         /* Resets the stealth state of all of the events */
  342.         case \'reset\':
  343.             console.log("Resetting all events");
  344.             $stealth.resetEvents();
  345.             $stealth.updateGauge();
  346.            
  347.             /* We aren\'t moving right now so there\'s no noise to check */
  348.             $stealth.checkAllEvents(0, 100);
  349.             $stealth.updateGauge();
  350.             break;
  351.         case \'gauge\':
  352.             if (args[1].toLowerCase() == "on")
  353.             {
  354.                 console.log("Turning onscreen gauge on");
  355.                 $stealth.setGauge(true);
  356.                 $stealth.updateGauge();
  357.             }
  358.             else
  359.             {
  360.                 console.log("Turning onscreen gauge off");
  361.                 $stealth.setGauge(false);
  362.                 $stealth.updateGauge();
  363.             }
  364.         break;
  365.         }
  366.     }
  367. };
  368.  
  369. //=============================================================================
  370. // Class which will perform all of the logic for patrol routes
  371. //=============================================================================
  372. function Patrol() {
  373.     this.initialize.apply(this,arguments);
  374. }
  375.  
  376. //=============================================================================
  377. // The constructor.  One of these per event.
  378. // event - The event to patrol
  379. // region_id - Region ID associated with the route
  380. //=============================================================================
  381. Patrol.prototype.initialize = function(event, region_id) {
  382.     this.region_id=region_id;
  383.     this.remaining_set=[];
  384.     this.full_region_set=[];
  385.     this.event=event;
  386.     this.load_route();
  387.     this.reset_route();
  388.     this.reported_critical_error=false;
  389.     this.current_destination=this.next_point();
  390. }
  391.  
  392. //=============================================================================
  393. // Create the patrol route
  394. //=============================================================================
  395. Patrol.prototype.load_route = function() {
  396.     width=$gameMap.width();
  397.     height=$gameMap.height();
  398.     this.full_region_set=[];
  399.     for (x=0; x<width; x++) {
  400.         for (y=0; y<height; y++) {
  401.             if ($gameMap.regionId(x, y) == this.region_id) {
  402.                 newPoint=[];
  403.                 newPoint[0]=x;
  404.                 newPoint[1]=y;
  405.                 this.full_region_set.push(newPoint);
  406.             }
  407.         }
  408.     }
  409.     if (this.full_region_set.length == 0) {
  410.         console.log("Stealth: Region ID "+this.region_id+" not on map - patrol disabled");
  411.     }
  412. }
  413.  
  414. //=============================================================================
  415. // Reset a patrol route.  This reloads the "remaining" set.
  416. //=============================================================================
  417. Patrol.prototype.reset_route = function() {
  418.     this.remaining_set=[];
  419.     this.current_destination=null;
  420.     for (index=0; index<this.full_region_set.length; index++) {
  421.         this.remaining_set.push(this.full_region_set[index]);
  422.     }
  423. }
  424.  
  425. //=============================================================================
  426. // Returns true if this event can patrol.  This is false if there is no
  427. // available patrol route (i.e. region ID 7 selected but not on map)
  428. //=============================================================================
  429. Patrol.prototype.isActive = function() {
  430.     return (this.full_region_set.length > 0);
  431. }
  432.  
  433. //=============================================================================
  434. // Returns the next way point (the closest one to the current location)
  435. // and removes it from the remaining_set.
  436. //=============================================================================
  437. Patrol.prototype.next_point = function() {
  438.     smallest_distance=null;
  439.     result=null;
  440.     if (this.full_region_set.length == 0) {
  441.         if (!this.reported_critical_error) {
  442.             this.reported_critical_error=true;
  443.         }
  444.         return;
  445.     }
  446.    
  447.     if (!this.remaining_set || this.remaining_set.length == 0) {
  448.         this.reset_route();
  449.     }
  450.     this.current_destination=null;
  451.     matched_index=null;
  452.     for (pointIndex=0; pointIndex<this.remaining_set.length; pointIndex++) {
  453.         current=this.remaining_set[pointIndex];
  454.         if (!current)
  455.             continue;
  456.         current_distance=(this.event.x-current[0])*(this.event.x-current[0]);
  457.         current_distance+=(this.event.y-current[1])*(this.event.y-current[1]);
  458.         if (smallest_distance === null || current_distance < smallest_distance)
  459.         {
  460.             smallest_distance=current_distance;
  461.             result=current;
  462.             matched_index=pointIndex;
  463.         }
  464.     }
  465.    
  466.     /* Every entry in the array has been erased */
  467.     if (!result || matched_index === null)
  468.     {
  469.         this.reset_route();
  470.         return null;
  471.     }
  472.     this.current_destination=result;
  473.     this.remaining_set.splice(matched_index, 1);
  474.     return this.current_destination;
  475. }
  476.  
  477.  
  478. //=============================================================================
  479. // Move a single step on our patrol route
  480. //=============================================================================
  481. Patrol.prototype.move = function() {
  482.    
  483.     // If we are at the destination, we need to get a new one
  484.     if (this.current_destination) {
  485.         if (this.event.x == this.current_destination[0] &&
  486.             this.event.y == this.current_destination[1]) {
  487.                 this.current_destination=null;
  488.             }
  489.     }
  490.     if (!this.current_destination) {
  491.         if (!this.next_point() && !this.next_point())
  492.         {
  493.             console.log("Failed to get next route waypoint for "+this.event.eventId());
  494.             return;
  495.         }
  496.     }
  497.     new_dir=this.event.findDirectionTo(this.current_destination[0], this.current_destination[1]);
  498.     this.event.moveStraight(new_dir);
  499. }
  500.  
  501. //=============================================================================
  502. // Core object representing the various modifiers which are
  503. // associated with Stealth
  504. //=============================================================================
  505. function StealthModifier(parent) {
  506.     this.initialize(parent);
  507. }
  508.  
  509. StealthModifier.prototype.initialize= function(meta) {
  510.     this.meta=meta;
  511.     if (this.meta) {
  512.         this.detection_skill=meta.Detection || 0;
  513.         this.vision_modifier=this.meta.Brightness || 100;
  514.         this.hearing_modifier=this.meta.Loudness || 100;
  515.     }
  516.     else
  517.     {
  518.         this.detection_skill=0;
  519.         this.vision_modifier=100;
  520.         this.hearing_modifier=100;
  521.     }
  522.     this.vision_modifier /= 100;
  523.     this.hearing_modifier /= 100;
  524. }
  525.  
  526. StealthModifier.prototype.detection = function() {
  527.     return this.detection_skill;
  528. }
  529.  
  530. StealthModifier.prototype.vision = function() {
  531.     return this.vision_modifier;
  532. }
  533.  
  534. StealthModifier.prototype.hearing = function() {
  535.     return this.hearing_modifier;
  536. }
  537.  
  538. StealthModifier.prototype.toString = function() {
  539.     result="detection="+this.detection();
  540.     result += ", vision="+this.vision();
  541.     result += ", hearing="+this.hearing();
  542.     return result;
  543. }
  544.  
  545.  
  546.  
  547. //=============================================================================
  548. // Returns a modifier based on relative brightness at source and target\'s location
  549. // source = Source doing the looking
  550. // target = What is being looked for
  551. // target_x = Target\'s X position
  552. // target_y = Target\'s Y position
  553. //=============================================================================
  554. Stealth.prototype.vision_modifier = function(source, target, target_x, target_y) {
  555.     /* Calculate a modifier for the brightness at the source and target\'s location */
  556.     source_brightness=$gameMap.brightness(source.x,source.y);
  557.     target_brightness=$gameMap.brightness(target_x,target_y);
  558.     if (!source_brightness)
  559.         source_brightness=100;
  560.     if (!target_brightness)
  561.         target_brightness=100;
  562.     if (target_brightness < 1)
  563.         target_brightness=1;
  564.     brightness_mod=100*source_brightness/target_brightness;
  565.     return brightness_mod;
  566. }
  567.  
  568. //=============================================================================
  569. // Returns a modifier based on relative noise level at the target\'s location
  570. // source = Source doing the looking
  571. // target = What is being looked for
  572. // target_x = Target\'s X position
  573. // target_y = Target\'s Y position
  574. //=============================================================================
  575. Stealth.prototype.hearing_modifier = function(source, target, target_x, target_y) {
  576.     /* Return the loudness modifier from the map at the target\'s location */
  577.     return $gameMap.loudness(target_x,target_y);
  578. }
  579.  
  580. //=============================================================================
  581. // Checks to see if the source can see the target.  This checks line-of-sight,
  582. // tile passability and vision cone
  583. // source = Source doing the looking
  584. // target = What is being looked for
  585. // modifier = Current modifier value for the check
  586. // distance = Distance between source and target
  587. // x = Target\'s X location
  588. // y = Target\'s Y location
  589. //=============================================================================
  590. Stealth.prototype.vision_check = function(source, target, modifier, distance, x, y) {
  591.    
  592.     /* Find the angle between source and target */
  593.    
  594.     /* NOTE: atan2 returns values as follows, on a unit circle with radius 1:
  595.             (1,0) = 0 = 0
  596.             (0,1) = PI/2 = 90
  597.             (-1,0) = PI and -PI = 180 and -180
  598.             (0-,1) = -PI/2 = -90
  599.             */
  600.            
  601.     angle=Math.atan2(y-source.y,x-source.x);
  602.  
  603.     /* DIRECTION VALUES: 2 = down, 4 = left, 6 = right, 8 = up */
  604.    
  605.     /* First, check the visual cone.  If we are outside it, we cannot be seen */
  606.     cone_object=this.vision_cones[source.direction()];
  607.     if (cone_object)
  608.     {
  609.         /* Visual cone is out of range */
  610.         switch (source.direction())
  611.         {
  612.             case 8:
  613.             dir_string="up";
  614.             break;
  615.            
  616.             case 2:
  617.             dir_string="down";
  618.             break;
  619.            
  620.             case 4:
  621.             dir_string="left";
  622.             break;
  623.            
  624.             case 6:
  625.             dir_string="right";
  626.             break;
  627.         }
  628.         if (!cone_object.contains(angle))
  629.         {
  630.             console.log("WS: DIR="+dir_string+" ANGLE (RAD)="+angle+" IS OUTSIDE "+this.vision_cones[source.direction()]);
  631.             console.log("WS: EVENT=("+source.x+","+source.y+") PLAYER=("+x+","+y+")");
  632.             return false;
  633.         }
  634.         /*
  635.         up (Delta X=0, Delta Y: Event=13, Player=6), ANGLE=-180 = -PI/2
  636.         */
  637.         console.log("WS: DIR="+dir_string+" ANGLE (RAD)="+angle+" IS INSIDE "+this.vision_cones[source.direction()]);
  638.         console.log("WS: EVENT=("+source.x+","+source.y+") PLAYER=("+x+","+y+")");
  639.     }
  640.    
  641.     check_x=source.x;
  642.     check_y=source.y;
  643.     x_delta=Math.cos(angle);
  644.     y_delta=Math.sin(angle);
  645.     a=angle*360.0/(2*Math.PI);
  646.     console.log("WS: XD="+x_delta+", YD="+y_delta+" ANGLE (DEGREES)="+a);
  647.    
  648.     if (Math.abs(x_delta) > Math.abs(y_delta))
  649.     {
  650.         /* Moving to left */
  651.         if (x_delta < 0)
  652.         {
  653.             direction=4;
  654.         }
  655.         else
  656.         {
  657.             /* Moving to right */
  658.             direction=6;
  659.         }
  660.     }
  661.     else
  662.     {
  663.         /* Moving up */
  664.         if (y_delta < 0)
  665.         {
  666.             direction=8;
  667.         }
  668.         else
  669.         {
  670.             /* Moving down */
  671.             direction=2;
  672.         }
  673.     }
  674.    
  675.     /* Finally, we need to trace the Line of Sight and make sure
  676.     it is Passable */
  677.     loop=distance-1;
  678.     while (loop > 0)
  679.     {
  680.         --loop;
  681.         if (!$gameMap.isPassable(Math.round(check_x),Math.round(check_y),direction))
  682.         {
  683.             console.log("WS: CANT PASS: "+Math.round(check_x)+","+Math.round(check_y)+" BY "+direction);
  684.             return false;
  685.         }
  686.         check_x+=x_delta;
  687.         check_y+=y_delta;
  688.     }
  689.     return true;
  690. }
  691.  
  692. //=============================================================================
  693. // Resets the states of all of the events
  694. //=============================================================================
  695. Stealth.prototype.resetEvents = function()
  696. {
  697.         for (eventLoop=0; eventLoop<$stealth.events.length; eventLoop++) {
  698.             event=$stealth.events[eventLoop];
  699.             $stealth.resetEvent(event);
  700.         }
  701. }
  702.  
  703. //=============================================================================
  704. // Resets the states of a specific event
  705. //=============================================================================
  706. Stealth.prototype.resetEvent = function(event)
  707. {
  708.     console.log("Resetting an event");
  709.     event.search = {};
  710.     event.search["state"]=1;
  711.     event.search["cooldown"]=0;
  712.     var key = [$gameMap.mapId(), event.eventId(), \'C\'];
  713.     $gameSelfSwitches.setValue(key, \'false\');
  714.     key[2]=\'D\';
  715.     $gameSelfSwitches.setValue(key, \'false\');
  716. }
  717.  
  718. //=============================================================================
  719. // Performs the actual Search and returns an array with a detection score from 0 to Max Stealth Score (or more)
  720. // for the first member, and the target for the second member.  Returns null if there were
  721. // no detections.
  722. // source = Source performing the Search
  723. // targets = Array of the target(s) being searched for
  724. // base_signals = Base vision values or noise levels
  725. // modifier_function = A function which generates a modifier (for a single target)
  726. // check_function = Function which performs additional checks assuming the target is
  727. // in range of the source
  728. // x = X position of the target (since targets are Game_Actors, they have no position)
  729. // Y = Y position of the target (since targets are Game_Actors, they have no position)
  730. //=============================================================================
  731. Stealth.prototype.searchBase = function(source, targets, base_signals, radius, modifier_function, check_function, x, y) {
  732.     if (!radius)
  733.     {
  734.         radius=1.0;
  735.     }
  736.    
  737.     max_possible_stealth_score=WS_StealthConfig.Param.maxStealthScore;
  738.     event_meta=this.getEventMeta(source);
  739.    
  740.     /* Check for a bypass switch */
  741.     if (event_meta && event_meta.BypassSwitch) {
  742.         switch_id=parseInt(event_meta.BypassSwitch);
  743.         if ($gameSwitches.value(switch_id)) {
  744.             return null;
  745.         }
  746.     }
  747.    
  748.     event_stealth_skill=WS_StealthConfig.Param.defaultStealth;
  749.     if (event_meta && event_meta.Detection) {
  750.         event_stealth_skill+=event_meta.Detection;
  751.     }
  752.     step_scale=max_possible_stealth_score/radius;
  753.     max_stealth_score=0;
  754.     detected_target=null;
  755.     stealth_score=0.0;
  756.     for (index=0; index<targets.length; index++) {
  757.         target=targets[index];
  758.         actor_stealth_skill=target.stealth();
  759.         if (!actor_stealth_skill)
  760.             actor_stealth_skill=WS_StealthConfig.Param.defaultStealth;
  761.         search_radius=radius;
  762.         modifier=modifier_function.call(this, source, target, x, y) || 100.0;
  763.         if (modifier == 0)
  764.             continue;
  765.         modifier /= 100.0;
  766.         step_scale=max_possible_stealth_score/radius;
  767.         step_scale /= modifier;
  768.        
  769.         /* Adjust for the relative skill levels */
  770.         step_scale /= event_stealth_skill/actor_stealth_skill;
  771.         /* Find the distance */
  772.         distance=(source.x-x)*(source.x-x);
  773.         distance += (source.y-y)*(source.y-y);
  774.         distance=Math.sqrt(distance);
  775.         if (!base_signals)
  776.         {
  777.             stealth_score=max_possible_stealth_score-(step_scale*distance);
  778.         }
  779.         else
  780.         {
  781.             stealth_score=base_signals[index]-(step_scale*distance);
  782.         }
  783.        
  784.         /* This is more important for vision checks, since audio does no
  785.          special checks after the modifiers
  786.          */
  787.         if (check_function &&
  788.             !check_function.call(this, source, target, modifier, distance, x, y))
  789.         {
  790.             continue;
  791.         }
  792.         if (stealth_score > max_stealth_score)
  793.         {
  794.             detected_target=target;
  795.             max_stealth_score=stealth_score;
  796.         }
  797.        
  798.     }
  799.     if (!detected_target)
  800.     {
  801.         return null;
  802.     }
  803.     result=[];
  804.     result.push(max_stealth_score);
  805.     result.push(target);
  806.     return result;
  807. }
  808.  
  809. //=============================================================================
  810. // Turns the on-screen gauge on or off
  811. //=============================================================================
  812. Stealth.prototype.setGauge = function(enabled)
  813. {
  814.     $stealth.stealth_gauge=enabled;
  815.     /* Store this for saving */
  816.     $gameSwitches.setValue(-999, enabled);
  817. }
  818.  
  819. //=============================================================================
  820. // Updates the event\'s self-switches and so on based on the detection result
  821. // event - Event to update
  822. // result - The detection result from a search
  823. //=============================================================================
  824. Stealth.prototype.updateDetectionStatus = function(event, result)
  825. {
  826.     if (!event)
  827.     {
  828.         return;
  829.     }
  830.     if (result)
  831.     {
  832.         current_score=result[0];
  833.         if (current_score >=  WS_StealthConfig.Param.detectionThreshold)
  834.         {
  835.             /* Detected */
  836.             console.log("Detected player!");
  837.             event.search=event.search || {};
  838.             event.search["state"]=3;
  839.             event.search["cooldown"]=WS_StealthConfig.Param.detectionCooldown;
  840.             var key = [$gameMap.mapId(), event.eventId(), \'C\'];
  841.             $gameSelfSwitches.setValue(key, \'false\');
  842.             key[2]=\'D\';
  843.             $gameSelfSwitches.setValue(key, \'true\');
  844.             return;
  845.         }
  846.         else if (current_score >=  WS_StealthConfig.Param.searchThreshold)
  847.         {
  848.             console.log("Searching for player.");
  849.             /* Searching but not detected */
  850.             event.search=event.search || {};
  851.             event.search["state"]=2;
  852.             event.search["cooldown"]=WS_StealthConfig.Param.detectionCooldown;
  853.             var key = [$gameMap.mapId(), event.eventId(), \'C\'];
  854.             $gameSelfSwitches.setValue(key, \'true\');
  855.             key[2]=\'D\';
  856.             $gameSelfSwitches.setValue(key, \'false\');
  857.             return;
  858.         }
  859.     }
  860.    
  861.     /* Do a cool down */
  862.     if (event.search)
  863.     {
  864.         if (event.search["cooldown"])
  865.         {
  866.             --event.search["cooldown"];
  867.             if (!event.search["cooldown"])
  868.             {
  869.                 event.search["state"]=1;
  870.                 var key = [$gameMap.mapId(), event.eventId(), \'C\'];
  871.                 $gameSelfSwitches.setValue(key, \'false\');
  872.                 key[2]=\'D\';
  873.                 $gameSelfSwitches.setValue(key, \'false\');
  874.             }
  875.         }
  876.     }
  877. }
  878.  
  879. //=============================================================================
  880. // Return event specific meta-data
  881. //=============================================================================
  882. Stealth.prototype.getEventMeta = function(event)
  883. {
  884.     if (!event)
  885.         return null;
  886.     if (!$dataMap.events[event.eventId()])
  887.         return null;
  888.     return $dataMap.events[event.eventId()].meta;
  889. }
  890.  
  891. //=============================================================================
  892. // Returns true if the event has stealth features enabled, false if not
  893. //=============================================================================
  894. Stealth.prototype.isEventStealthy = function(event)
  895. {
  896.     if (!event || !event.eventId || !$dataMap[events.eventId()])
  897.         return false;
  898.     eventMeta=$dataMap.events[event.eventId()].meta;
  899.     if (!eventMeta)
  900.     {
  901.         return false;
  902.     }
  903.     /* If we have at least one valid meta-key (Patrol: 1 Vision: 100 Hearing: 125 Detection: 0), this is a stealthy event */
  904.     return eventMeta.Detection || eventMeta.Patrol || eventMeta.Hearing ||
  905.         event.meta.Vision;
  906. }
  907.  
  908. //=============================================================================
  909. // Performs the actual visual and acoustic Search and returns an array with a detection score from 0 to 100 (or more)
  910. // for the first member, and the target for the second member.  Returns null if there were
  911. // no detections.
  912. // source = Source performing the Search
  913. // targets = Array of the target(s) being searched for.  Usually a Game_Actors
  914. // array
  915. // noises = Noise level the targets are making.  These correspond to the targets
  916. // entries.  0=Silence, 100=Normal movement, etc.
  917. // brightness = Brightness level the targets are emitting.  These correspond to the targets
  918. // entries.  0=Invisible, 100=Normal, etc.
  919. // x = X location of the target
  920. // y = Y location of the target
  921. //=============================================================================
  922. Stealth.prototype.search = function(source, targets, noises, brightness, x, y)
  923. {
  924.     result=[];
  925.    
  926.     vision_result=[];
  927.     hearing_result=[];
  928.    
  929.     /* First, perform visual check using default brightness level for targets */
  930.     vision_result=this.searchBase(source, targets, brightness, WS_StealthConfig.Param.baseVisualRadius, this.vision_modifier, Stealth.prototype.vision_check, x, y);
  931.    
  932.     /* Second, perform listening check using passed in noise levels */
  933.     hearing_result=this.searchBase(source, targets, noises, WS_StealthConfig.Param.baseAudioRadius, this.hearing_modifier, null, x, y);
  934.    
  935.     if (!vision_result && !hearing_result)
  936.         return null;
  937.     if (!vision_result && hearing_result)
  938.         return hearing_result;
  939.     if (vision_result && !hearing_result)
  940.         return vision_result;
  941.     if (vision_result[0] > hearing_result[0])
  942.         return vision_result;
  943.     return hearing_result;
  944. }
  945.  
  946. //=============================================================================
  947. // Adds any events from the current map which have stealth enabled to a cache.
  948. // Called when the map is setup
  949. //=============================================================================
  950. Stealth.prototype.addEvents = function() {
  951.     this.events = [];
  952.     this.eventMeta = [];
  953.     this.eventPatrols = {};
  954.     events=$gameMap.events();
  955.     for (loop=0; loop<events.length; loop++) {
  956.         event=events[loop];
  957.         if (!event || event.eventId() === undefined)
  958.             continue;
  959.         meta=this.getEventMeta(event);
  960.         if (!meta)
  961.             continue;
  962.         /* If we have at least one valid meta-key (Patrol: 1 Vision: 100 Hearing: 125 Detection: 0), this is a stealthy event */
  963.         if (meta.Detection || meta.Patrol || meta.Hearing || meta.Vision)
  964.         {
  965.             this.events.push(event);
  966.             this.eventMeta.push(meta);
  967.             if (meta.Patrol)
  968.             {
  969.                 this.eventPatrols[event.eventId()]= new Patrol(event, meta.Patrol);
  970.             }
  971.         }
  972.     }
  973. }
  974.  
  975. //=============================================================================
  976. // Handle patrol movement for the passed in event
  977. //=============================================================================
  978. Stealth.prototype.patrol = function(event) {
  979.     if (!event)
  980.         return;
  981.     patrol=this.eventPatrols[event.eventId()];
  982.     var key = [$gameMap.mapId(), event.eventId(), \'C\'];
  983.    
  984.     /* Don\'t patrol if we are already Searching or Detected */
  985.     if ($gameSelfSwitches.value(key))
  986.         return;
  987.     key[2]=\'D\';
  988.     if ($gameSelfSwitches.value(key))
  989.         return;
  990.     if (patrol) {
  991.         patrol.move();
  992.     }
  993. }
  994.  
  995. //=============================================================================
  996. // Window to display stealth gauge
  997. //=============================================================================
  998.  
  999. Window_Stealth= function() {
  1000.     this.initialize.apply(this, arguments);
  1001.     Window_Base.prototype.initialize.call(this, this.gaugeX, 0, 200, 200);
  1002.     this.opacity = 0;
  1003.     this.contentsOpacity = 192;
  1004. };
  1005.  
  1006. Window_Stealth.prototype = Object.create(Window_Base.prototype);
  1007.  
  1008. Window_Stealth.prototype.constructor = Window_Stealth;
  1009.  
  1010.  
  1011. Window_Stealth.prototype.initialize = function() {
  1012.     this.minValue=0;
  1013.     this.maxValue=WS_StealthConfig.Param.maxStealthScore;
  1014.     this.gaugeWidth=Math.floor(Graphics.boxWidth/5);
  1015.     this.gaugeValue=0;
  1016.     this.gaugeX=Math.floor(Graphics.boxWidth/2-Graphics.boxWidth/10);
  1017. }
  1018.  
  1019. Window_Stealth.prototype.refresh = function() {
  1020.     v=this.gaugeValue-this.minValue;
  1021.     this.drawGauge(1, 10, this.gaugeWidth, v/(this.maxValue-this.minValue),
  1022.     this.textColor(3), this.textColor(2));
  1023. };
  1024.  
  1025.  
  1026. //=============================================================================
  1027. //=============================================================================
  1028. Window_Stealth.prototype.setGauge = function(value)
  1029. {
  1030.     if (value == this.gaugeValue)
  1031.         return;
  1032.     if (value < this.minValue)
  1033.         value=this.minValue;
  1034.     if (value > this.maxValue)
  1035.         value=this.maxValue;
  1036.     if ($stealth && !$stealth.stealth_gauge)
  1037.         return;
  1038.     this.gaugeValue=value;
  1039.     this.refresh();
  1040. }
  1041.  
  1042.  
  1043. //=============================================================================
  1044. // If enabled, this shows the stealth gauge onscreen
  1045. //=============================================================================
  1046. Stealth.prototype.updateGauge = function() {
  1047.     drawScore=this.stealthScore();
  1048.     drawScore=Math.round(drawScore);
  1049.     if (drawScore < 0)
  1050.         drawScore=0;
  1051.     max_possible_stealth_score=WS_StealthConfig.Param.maxStealthScore;
  1052.     if (drawScore > max_possible_stealth_score)
  1053.         drawScore=max_possible_stealth_score;
  1054.     if (this.stealth_gauge)
  1055.     {
  1056.         if ($stealthWindow)
  1057.         {
  1058.             $stealthWindow.show();
  1059.             $stealthWindow.setGauge(drawScore);
  1060.         }
  1061.     }
  1062.     else
  1063.     {
  1064.         if ($stealthWindow)
  1065.             $stealthWindow.hide();
  1066.     }
  1067.  
  1068.     console.log("Stealth Score:"+drawScore);
  1069.     $gameVariables.setValue(WS_StealthConfig.Param.detectionVariable, drawScore);
  1070.    
  1071. }
  1072.  
  1073. //=============================================================================
  1074. // Returns a single detection score, based on a single, passed-in event
  1075. // and the party\'s battle members
  1076. // event - The event doing the check
  1077. // party_noise - Party\'s base noise level
  1078. // party_brightness - Party\'s base brightness level
  1079. //=============================================================================
  1080. Stealth.prototype.checkForEvent = function(event, party_noise, party_brightness) {
  1081.    
  1082.     noise=[];
  1083.     brightness=[];
  1084.     party_noise = party_noise || WS_StealthConfig.Param.noiseFloor;
  1085.     party_brightness = party_brightness || 100;
  1086.     members=$gameParty.battleMembers();
  1087.     for (index=0; index<members.length; index++)
  1088.     {
  1089.         current=members[index];
  1090.         starting_noise=party_noise;
  1091.         modifiers=current.stealthModifiers();
  1092.         modifier_result=1.0;
  1093.         vision_modifier=1.0;
  1094.         if (modifiers)
  1095.         {
  1096.             for (var l=0; l<modifiers.length; l++)
  1097.             {
  1098.                 modifier_result *= modifiers[l].hearing();
  1099.                 vision_modifier *= modifiers[l].vision();
  1100.             }
  1101.         }
  1102.         noise.push(party_noise*modifier_result);
  1103.         brightness.push(party_brightness*vision_modifier);
  1104.     }
  1105.     result=this.search(event, $gameParty.battleMembers(), noise,
  1106.         brightness, $gamePlayer.x, $gamePlayer.y);
  1107.     this.updateDetectionStatus(event, result);
  1108.     if (result)
  1109.     {
  1110.         this.lastStealthScores[event.eventId()]=result[0];
  1111.     }
  1112.     else
  1113.         this.lastStealthScores[event.eventId()]=0;
  1114.    
  1115.     /* If the event is Searching or has Detected the player, we force the
  1116.     state here */
  1117.     if (event.search && event.search["state"])
  1118.     {
  1119.         if (event.search["state"] == 2)
  1120.         {
  1121.             /* Searching, force score to Searching level */
  1122.             this.lastStealthScores[event.eventId()]=WS_StealthConfig.Param.searchThreshold;
  1123.             return this.lastStealthScores[event.eventId()];
  1124.         }
  1125.         else if (event.search["state"] == 3)
  1126.         {
  1127.             /* Detected */
  1128.             this.lastStealthScores[event.eventId()]=WS_StealthConfig.Param.detectionThreshold;
  1129.             return this.lastStealthScores[event.eventId()];
  1130.         }
  1131.     }
  1132.     if (!result)
  1133.         return 0;
  1134.     return result[0];
  1135. }
  1136.  
  1137. //=============================================================================
  1138. // Return true if the event_id passed in is patrolling
  1139. //=============================================================================
  1140. Stealth.prototype.isPatrolling = function(event_id) {
  1141.     if (this.eventPatrols[event_id] && this.eventPatrols[event_id].isActive())
  1142.     {
  1143.         /* If self-switch C or D is on, we do NOT do patrolling */
  1144.         var key = [$gameMap.mapId(), event_id, \'C\'];
  1145.         if ($gameSelfSwitches.value(key))
  1146.         {
  1147.             return false;
  1148.         }
  1149.         key[2]=\'D\';
  1150.         if ($gameSelfSwitches.value(key))
  1151.         {
  1152.             return false;
  1153.         }
  1154.         return true;
  1155.     }
  1156.     return false;
  1157. }
  1158.  
  1159. //=============================================================================
  1160. // Do patrol processing for the passed in event
  1161. //=============================================================================
  1162. Stealth.prototype.patrol = function(event_id) {
  1163.     if (this.eventPatrols[event_id])
  1164.     {
  1165.         this.eventPatrols[event_id].move();
  1166.     }
  1167.     return false;
  1168. }
  1169.  
  1170.  
  1171. //=============================================================================
  1172. // Returns a single detection score, based on all of the stealthy events on the map
  1173. // and the party\'s battle members.  This does NOT update detection status for each
  1174. // event and so on.
  1175. // party_noise - Party\'s base noise level
  1176. // brightness - Party\'s brightness level (defaults to 100)
  1177. //=============================================================================
  1178. Stealth.prototype.checkAllEvents = function(party_noise, brightness) {
  1179.         final_result=0;
  1180.        
  1181.         brightness = brightness || 100;
  1182.         for (eventLoop=0; eventLoop<$stealth.events.length; eventLoop++) {
  1183.             event=$stealth.events[eventLoop];
  1184.             temp_result=this.checkForEvent(event, party_noise, brightness);
  1185.             if (temp_result > final_result)
  1186.                 final_result=temp_result;
  1187.         }
  1188.         return final_result;
  1189. }
  1190.  
  1191. //=============================================================================
  1192. // Both Players and Events do visual checks when they move, but Player
  1193. // movement forces checks for every Event
  1194. //=============================================================================
  1195.  
  1196. //=============================================================================
  1197. // Scene_Map
  1198. //=============================================================================
  1199.  
  1200. var WS_Scene_Map_Onload=Scene_Map.prototype.onMapLoaded;
  1201.  
  1202. Scene_Map.prototype.onMapLoaded = function() {
  1203.     WS_Scene_Map_Onload.call(this, arguments);
  1204.     $stealthWindow=new Window_Stealth();
  1205.     this.addWindow($stealthWindow);
  1206.     $stealthWindow.refresh();
  1207.     $stealthWindow.activate();
  1208.     if ($stealth)
  1209.         $stealth.updateGauge();
  1210. }
  1211.  
  1212. //=============================================================================
  1213. // Game_Map
  1214. //=============================================================================
  1215.  
  1216. var WS_Game_Map_setup=Game_Map.prototype.setup;
  1217.  
  1218. //=============================================================================
  1219. // Reset the Stealth object for this map
  1220. //=============================================================================
  1221. Game_Map.prototype.setup = function(mapId) {
  1222.     WS_Game_Map_setup.call(this, mapId);
  1223.     $stealth=new Stealth();
  1224.     /* Add all of the Events which have stealth of some type defined */
  1225.     $stealth.addEvents();
  1226.     this._brightness=[];
  1227.     this._loudness=[];
  1228.     $stealth.updateGauge();
  1229.    
  1230.     /* Load the Brightness and Loudness maps */
  1231.     if ($dataMap.meta)
  1232.     {
  1233.         value=$dataMap.meta.Brightness;
  1234.         if (value)
  1235.         {
  1236.             nvPairs=value.split(",");
  1237.             for (index=0; index<nvPairs.length; index++) {
  1238.                 entry=nvPairs[index];
  1239.                 pair=entry.split("=");
  1240.                 console.log("Stealth: map Brightness: Region ID="+pair[0]+", Modifier="+pair[1]+"%");
  1241.                 this._brightness[parseInt(pair[0])]=pair[1];
  1242.             }
  1243.         }
  1244.         value=$dataMap.meta.Loudness;
  1245.         if (value)
  1246.         {
  1247.             nvPairs=value.split(",");
  1248.             for (index=0; index<nvPairs.length; index++) {
  1249.                 entry=nvPairs[index];
  1250.                 pair=entry.split("=");
  1251.                 console.log("Stealth: map Loudness: Region ID="+pair[0]+", Modifier="+pair[1]+"%");
  1252.                 this._loudness[parseInt(pair[0])]=pair[1];
  1253.             }
  1254.         }
  1255.     }
  1256. }
  1257.  
  1258. //=============================================================================
  1259. // Returns a brightness factor at the given coordinates
  1260. //=============================================================================
  1261. Game_Map.prototype.brightness = function(x, y) {
  1262.     id=$gameMap.regionId(x,y);
  1263.     result=this._brightness[id];
  1264.     if (result === null || result === undefined)
  1265.     {
  1266.         return 100;
  1267.     }
  1268.     return result;
  1269. }
  1270.  
  1271. //=============================================================================
  1272. // Returns a loudness factor at the given coordinates
  1273. //=============================================================================
  1274. Game_Map.prototype.loudness = function(x, y) {
  1275.     id=$gameMap.regionId(x,y);
  1276.     result=this._loudness[id];
  1277.     if (result === null || result === undefined)
  1278.     {
  1279.         return 100;
  1280.     }
  1281.     return result;
  1282. }
  1283.  
  1284.  
  1285. //=============================================================================
  1286. // Game_Actor
  1287. //=============================================================================
  1288.  
  1289. //=============================================================================
  1290. // Return the current stealth skill setting
  1291. //=============================================================================
  1292. Game_Actor.prototype.stealth =function() {
  1293.     this._stealth=this._stealth || WS_StealthConfig.Param.defaultStealth;
  1294.     return this._stealth;
  1295. }
  1296.  
  1297. //=============================================================================
  1298. // Change the current stealth skill setting.  
  1299. // stealthFunction is an expression which is passed into eval to
  1300. // return the new value
  1301. //=============================================================================
  1302. Game_Actor.prototype.setStealth = function(stealthFunction) {
  1303.     this._stealth=Math.max(eval(stealthFunction), 0);
  1304. }
  1305.  
  1306. //=============================================================================
  1307. // Advance Stealth skill according to a formula
  1308. //=============================================================================
  1309. var WS_Game_Actor_changeLevel=Game_Actor.prototype.changeLevel;
  1310. Game_Actor.prototype.changeLevel = function(level, show) {
  1311.     WS_Game_Actor_changeLevel.call(this, level, show);
  1312.    
  1313.     if (this.meta)
  1314.     {
  1315.         // Update the Stealth skill if applicable
  1316.         stealth(this.meta.stealth);
  1317.     }
  1318. }
  1319.  
  1320. //=============================================================================
  1321. // Get an overall stealth modifier for a current Actor.  Returns null if there are none.
  1322. //=============================================================================
  1323. Game_Actor.prototype.stealthModifiers = function() {
  1324.     modifier_list=[];
  1325.    
  1326.     // Start with anything tagged to the Actor
  1327.     if (!$stealth.actor_cache[this.actorId()]) {
  1328.         meta=$dataActors[this.actorId()].meta;
  1329.         $stealth.actor_cache[this.actorId()]=new StealthModifier(meta);
  1330.     }
  1331.     modifier_list.push($stealth.actor_cache[this.actorId()]);
  1332.    
  1333.     // The current class
  1334.     if (this._classId)
  1335.     {
  1336.         if (!$stealth.class_cache[this._classId])
  1337.         {
  1338.             meta=$dataClasses[this._classId].meta;
  1339.             $stealth.class_cache[this._classId] =
  1340.             new StealthModifier(meta);
  1341.         }
  1342.     }
  1343.    
  1344.     modifier=$stealth.class_cache[this._classId];
  1345.     if (modifier)
  1346.         modifier_list.push(modifier);
  1347.    
  1348.     // List of currently equipped items
  1349.     items=this.equips();
  1350.     for (mod=0; mod<items.length; mod++)
  1351.     {
  1352.         current=items[mod];
  1353.         if (current === null)
  1354.             continue;
  1355.         if ($stealth.item_cache[current.id] === undefined)
  1356.         {
  1357.             meta={};
  1358.             if (DataManager.isWeapon(current))
  1359.                 meta=$dataWeapons[current.id].meta;
  1360.             else if (DataManager.isArmor(current))
  1361.                 meta=$dataArmors[current.id].meta;
  1362.             else
  1363.                 meta=$dataItems[current.id].meta;
  1364.             $stealth.item_cache[current.id]=new StealthModifier(meta);
  1365.         }
  1366.         modifier=$stealth.item_cache[current.id];
  1367.         modifier_list.push(modifier);
  1368.     }
  1369.    
  1370.     // List of the current states
  1371.     states=this.states();
  1372.     for (mod=0; mod<states.length; mod++)
  1373.     {
  1374.         current=states[mod];
  1375.         if (current === null)
  1376.             continue;
  1377.         if (!$stealth.state_cache[current.id])
  1378.         {
  1379.             $stealth.state_cache[current.id]=new StealthModifier($dataStates[current.id].meta);
  1380.         }
  1381.         modifier=$stealth.state_cache[current.id];
  1382.         modifier_list.push(modifier);
  1383.     }
  1384.    
  1385.     // Add from the current Class
  1386.     if (this.currentClass.stealth)
  1387.         modifier_list.push(current.stealth);
  1388.    
  1389.     if (modifier_list.length === 0)
  1390.         return null;
  1391.    
  1392.     return modifier_list;
  1393.    
  1394. }
  1395.  
  1396. //=============================================================================
  1397. // Game_CharacterBase
  1398. //=============================================================================
  1399. var WS_GC_moveStraight=Game_CharacterBase.prototype.moveStraight;
  1400. var WS_GC_moveDiagonally=Game_CharacterBase.prototype.moveDiagonally;
  1401.  
  1402. //=============================================================================
  1403. // Do a stealth check when an Event or the Party moves
  1404. //=============================================================================
  1405. Game_CharacterBase.prototype.moveStraight = function(d) {
  1406.     WS_GC_moveStraight.call(this, d);
  1407.     if (!this.isMovementSucceeded())
  1408.     {
  1409.         return;
  1410.     }
  1411.    
  1412.     if (this instanceof Game_Event)
  1413.     {
  1414.         // We do the search
  1415.         $stealth.checkForEvent(this, 10);
  1416.         $stealth.updateGauge();
  1417.     }
  1418.     else if (this instanceof Game_Player)
  1419.     {
  1420.         // Trigger every OTHER event to do the search
  1421.         $stealth.checkAllEvents(100, 100);
  1422.         $stealth.updateGauge();
  1423.     }
  1424. }
  1425.  
  1426. //=============================================================================
  1427. // Do a stealth check when an Event or the Party moves
  1428. //=============================================================================
  1429. Game_CharacterBase.prototype.moveDiagonally = function(horz, vert) {
  1430.     WS_GC_moveDiagonally.call(this, horz, vert);
  1431.     if (!this.isMovementSucceeded())
  1432.     {
  1433.         return;
  1434.     }
  1435.    
  1436.     if (this instanceof Game_Event)
  1437.     {
  1438.         // We do the search
  1439.         $stealth.checkForEvent(this, 10);
  1440.         $stealth.updateGauge();
  1441.     }
  1442.     else if (this instanceof Game_Player)
  1443.     {
  1444.         // Trigger every OTHER event to do the search
  1445.         $stealth.checkAllEvents(100+(100*$gamePlayer.isDashing()), 100);
  1446.         $stealth.updateGauge();
  1447.     }
  1448. }
  1449. //=============================================================================
  1450. // Game_Event
  1451. //=============================================================================
  1452. WS_GE_updateSelf=Game_Event.prototype.updateSelfMovement;
  1453.  
  1454. //=============================================================================
  1455. // See if we are patrolling.  If so, use that for the movement
  1456. //=============================================================================
  1457. Game_Event.prototype.updateSelfMovement = function() {
  1458.     if (!this.eventId) {
  1459.         WS_GE_updateSelf.call(this);
  1460.         return;
  1461.     }
  1462.     if (!$stealth) {
  1463.         $stealth=new Stealth();
  1464.         /* Add all of the Events which have stealth of some type defined */
  1465.         $stealth.addEvents();
  1466.     }
  1467.     if ($stealth.isPatrolling(this.eventId()))
  1468.     {
  1469.         patrol_object=$stealth.eventPatrols[this.eventId()];
  1470.         if (patrol_object)
  1471.         {
  1472.             console.log("WS: PATROL "+this.eventId());
  1473.             patrol_object.move();
  1474.         }
  1475.         else
  1476.         {
  1477.             WS_GE_updateSelf.call(this);
  1478.         }
  1479.     }
  1480.     else
  1481.     {
  1482.         WS_GE_updateSelf.call(this);
  1483.     }
  1484. }
  1485.  
  1486. //=============================================================================
  1487. // DataManager
  1488. //=============================================================================
  1489.  
  1490.  
  1491.  
  1492. //=============================================================================
  1493. // Remove the stealth window when we save
  1494. //=============================================================================
  1495.  
  1496. /*
  1497. var WS_Stealth_DM_makeSaveContents = DataManager.makeSaveContents;
  1498. DataManager.makeSaveContents = function() {
  1499.     console.log("WS: MAKE NEW SC");
  1500.     return WS_Stealth_DM_makeSaveContents.call(this, arguments);
  1501. }
  1502. */
  1503.  
  1504. //=============================================================================
  1505. // Load the stealth window when we load
  1506. //=============================================================================
  1507. /*
  1508. var WS_Stealth_DM_extractSaveContents = DataManager.extractSaveContents;
  1509.  DataManager.extractSaveContents = function() {
  1510.      WS_Stealth_DM_extractSaveContents.call(this, arguments);
  1511.  }
  1512. */
  1513. })();
  1514. //=============================================================================
  1515. // End of File
  1516. //=============================================================================
');