Difference between revisions of "Category:Detection"

5,798 bytes added ,  06:20, 9 December 2014
m
imported>Csimbi
m (Typos again)
imported>Saebel
 
(27 intermediate revisions by 7 users not shown)
Line 1: Line 1:
Detection is a complicated process involving many variables, and always exactly two actors. It is important to note that the engine does not calculate successful "sneak rolls" for the actor who is sneaking: it is vice versa; the engine calculates successful "detection rolls" for the actor being stalked (''origin'') vs. the sneaking actor (''target''). Therefore, detection is always calculated between two actors: the ''origin'' and the ''target''.
Detection is Oblivion's stealth mechanic.  The concept isn't complicated: every actor has a degree of awareness of every other nearby actor, called a ''detection level''. If this detection level is above a certain threshold then the searching actor (the "detector") is fully aware of the hiding actor (the "target"). The detector can then attack, offer a greeting, report the target's crimes, etc. If the detection level falls below the threshold again, the detector "loses" the target and can no longer interact with it.


The variables involved break down into three categories: '''Base''', '''Skill''', '''Light''', '''Sound'''. These variables are simply combined together to calculate the end-result. If the end-result is higher than [[fSneakSeenMin]] (default: 0), the ''target'' is detected. When an actor is detected, it can be ''target''ed as well, therefore the hostile units will engage the ''target'' in combat, while non-hostile units will only "notice" the ''target'' - which usually results in looking directly at the ''target'' and making a comment/greeting towards him/her.
Quite a few variables go into calculating detection levels.  They fall into three basic categories: Sight, Sound, and Sneak Skill.  Sight describes how well the detector can see the target, and only matter if the detector actually has a direct line-of-sight. Sound measures how much noise the target is making from movement and from being in combat. Skill measures the sneak skills of the detector  and the target.  In all three categories the distance from the detector to target plays a very important role.  


Once detected, the ''target'' remains detected until he/she can get his/her detection end-result below a certain threshold vs. the ''origin''. This threshold varies based on the relation of the ''origin'' and the ''target'':
Some of the conditions in the formula are still under investigation. In particular, the detection does not always correctly recognize when the target is in combat.  Whether this is specific to the player or due to some other bug is not yet known.
*"Non-hostile" meaning that the origin does not care much about the fact that the target is trying to hide. It uses the [[fSneakUnseenMin]] value (default: 0.0) as threshold.
*"Hostile" relation has two variants:
The complete formula for Detection Level is given below. Because the formula is so complicated, it is broken into smaller pieces and organized in a table. Conditional terms are enclosed in square brackets, e.g. "[ + 400, if target is yellow]" means "add 400 if the target is yellow, otherwise ignore this term".
**"Cautious" meaning that the hostile unit is looking for the target - typically saying warning lines during the process. It uses the [[fSneakLostMin]] value (default: -20.0) as threshold.
**"Combat" meaning that the hostile unit is actually engaged in combat with the target. It uses the [[iAICombatMinDetection]] value (default: -50.0) as threshold.
Again, this is quite logical because it is easy to hide from someone who does not care, while it is pretty hard to fade out of sight during combat.


<u>Description of the variables in the equation:</u>
=== Detection Level Formula ===
*'''Base''' The basis for the calculation of the end-result, independent of any other value.
{| cellpadding=3 cellspacing=0 border=1 style="text-align:center"
**Sneak penalty governed by [[fSneakBaseValue]] (default: -25). This value is an absolute base value that is always applied, in order to indicate the intent to sneak. Basically it means that if the ''target'' makes no noise at all AND hiding in a very dark place AND does not make a move, the detection will fail (e.g. the ''target'' can successfully hide) even with a very low [[Sneak]] skill.
 
**Combat bonus governed by [[fSneakTargetAttackBonus]] (default: 100). This values is added to the base only for a moment when the target initiates combat, making it a virtual certainty that for a moment the actor will detect his assailant. In that moment, the origin can decide to enter combat or not.
|- style="background:#efefef;"
*'''Skill''' The difference between the actors' sneak skills (''origin'' vs. ''target''); governed by [[fSneakSkillMult]] (default: 0.5)
! scope="col" width="100" | Factor
**The variable is modified by the distance between the actors.
! scope="col" width="100%" | Value
*'''Light''' The amount of light shining on the sneaking actor; governed by [[fSneakLightMult]] (default: 1.4)
 
**[[Invisibility]] and [[Chameleon]] effects improve this variable.
|-
**The variable is modified by the distance between the actors.
| '''Detection Level'''
*'''Sound''' The level of noise that the ''target'' is making; governed by [[fSneakSoundsMult]] (default: 1.6), [[fSneakSoundLosMult]] (default: 1.0)
| align="left" |
**Moving makes more noise than standing still.
If target is farther from the detector than MaxDetectionRange, and has not attacked the detector:
**Running makes more noise than walking; governed by [[fSneakRunningMult]] (default: 1.3)
0
**Heavy boots make more noise than bare feet; governed by [[fSneakBootWeightBase]] (default: 14.0), [[fSneakBootWeightMult]] (default: 1.0)
If target is invisible or has 100% Chameleon:
**Fighting makes ultimately high noise; governed by [[fSneakTargetInCombatBonus]] (default: 25.0)
-100
**The variable is modified by the distance between the actors
Otherwise:
[[fSneakBaseValue]]
[ + [[fSneakTargetAttackBonus]], for a single frame the first time the target attacks the detector]
[ + SoundBonus, if target is not swimming]
[ + [[fSneakSleepBonus]], if detector is sleeping]
[ + SightBonus, if detector is awake and has line-of-sight to target]
+ SkillBonus
 
|-
| '''Sound Bonus'''
| align="left" |
[[fSneakSoundsMult]] * DistanceFactor *
(
  [ MovementFactor, if target is moving and target Sneak mastery < Expert]
  [ + [[fSneakTargetInCombatBonus]], if target is in combat]
)
[ * [[fSneakSoundLosMult]], if detector has no line of sight to target]
The sound bonus cannot be negative. If it is less than zero, it is set to zero.  
|-
| Movement Factor
| align="left" |
(
  [[fSneakBootWeightBase]]
  [ + ([[fSneakBootWeightMult]] * (tgt boot weight)), if tgt Sneak mastery < Journeyman ]
)
[ * [[fSneakRunningMult]], if target is running ]
 
|-
| '''Sight Bonus'''
| align="left" |
[[fSneakLightMult]] * DistanceFactor * LightFactor * ChameleonFactor * BlindnessFactor
[ * [[fSneakSwimmingLightMult]], if target is swimming]
The sight bonus cannot be negative. If it is less than zero, it is set to zero.
|-
| Light Factor
| align="left" |
[[fDetectionSneakLightMod]] +
(
  (light level on target)
  [ * [[fDetectionNightEyeBonus]], if detector has Night Eye]
)
 
'light level on target' measures the ambient light, plus changes from the Darkness effect.  Falls in range from 0 to 100.
 
|-
| Chameleon Factor
| align="left" |
1 - (Chameleon level of target)/100
Chameleon Factor is forced into the range [0 - 1]
 
|-
| Blindness Factor
| align="left" |
1 - (Blindness level of detector)/100
Blindness Factor is forced into the range [0 - 1]
 
|-
| '''Skill Bonus'''
| align="left" |
[[fSneakSkillMult]] *
(
  (detector Sneak skill * DistanceFactor)
  [ - target Sneak skill, if target is sneaking and not in combat]
)
 
|-
| '''Distance Factor'''
| align="left" |
1 - (distance between detector and target) / MaxDetectionRange
 
|-
| '''Max Detection Range'''
| align="left" |
[[fSneakMaxDistance]]
[ * [[fSneakExteriorDistanceMult]], if in exterior cell]
 
|}
 
=== Detection Thresholds ===
 
If the '''Detection Level''' is greater than a certain threshold, the detector can becomes aware of the target.  The thresholds are:
{|border="1" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" | <center> Threshold </center>
! style="background:#efefef;" | <center> Used By </center>
|-
| 0
| Zero seems to be an upper limit for detection thresholds. If the detection level is greater than zero, the target is always(?) detected.
|-
| [[fSneakUnseenMin]]
| all actors that are unaware of target
all non-hostile actors
|-
| [[fSneakNoticedMin]]
| actors are aware that target is near and speak accordingly
|-
| [[fSneakLostMin]]
| hostile actors that are searching for target
|-
| [[iAICombatMinDetection]]
| hostile actors that are in combat with target
|-
|}
 
A final note: The target-is-in-combat bonus is fairly significant.  Combined with the much lower combat threshold, this can make it ''very'' difficult for an actor to return to hiding once a hostile actor has seen them.
 
==Performance==
Every NPC/Creature that is high processing makes a round of detection calls every .3 seconds.  Those detection calls will be made against everyone within the detection range of the actor, not just against the player.  It also doesn't matter whether the target is sneaking or not.  Sneaking merely modifies the target's ability to be detected.
 
Therefore, as the number of active actors in an area increase, the number of detection calls made increases exponentially.
{|border="1" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" | <center> # of actors in the area </center>
! style="background:#efefef;" | <center> # of detection calls </center>
! style="background:#efefef;" | <center> ~ # per second </center>
|-
| 1 actor + player
| 1
1 call vs player
| 3
|-
| 2 actors + player
| 4
2 calls vs player, 1 call per NPC vs other NPC
| 12
|-
| 3 actors + player
| 9
3 calls vs player, 2 calls per NPC vs other NPCs
| 27
|-
| 4 actors + player
| 16
4 calls vs player, 3 calls per NPC vs other NPCs
| 48
|-
| 10 actors + player
| 100
10 calls vs player, 9 calls per NPC vs other NPCs
| 300
|-
| 15 actors + player
| 225
15 calls vs player, 14 calls per NPC vs other NPCs
| 675
|-
| 20 actors + player
| 400
20 calls vs player, 19 calls per NPC vs other NPCs
| 1200
|-
| 30 actors + player
| 900
30 calls vs player, 29 calls per NPC vs other NPCs
| 2700
|}
 
In the above examples, this assumes that everyone is within the detection range of everyone else.
 
In exterior locations, actors are rarely so clumped together except in high traffic areas such as the Market District.  But then again, exteriors have default range of 2x the interior detection distance, which is roughly four times the area.
 
With default Oblivion, you will rarely run into large numbers of NPCs/creatures that are densely packed.  But in a heavily modded Oblivion, this can have a noticeable effect on performance when the player enters highly populated areas.  Detection is probably not the only Oblivion feature that behaves like this, but it's the one that we for sure know behaves this way consistently all the time.
 
Any mod that alters the detection formula (such as SDR) in combination with mods that increase the population density will therefore potentially impact performance as well, depending on how the mod is designed and implemented.
 
==Detection Functions==
 
[[IsActorDetected]] does not appear to call the detection formula, since it does not require both the target and detector to function.  It is the simplest method of determining whether an actor is being detected at any given time.
 
[[GetDetectionLevel]] does not appear to call the detection formula either, and may be the most efficient method of determining the detection result of a detector/target pair, especially when a mod that alters detection (like SDR) is in the load order.  Although it is unknown whether or not the result is based on Oblivion's native detection results or the detection altering mod's results. The theory is that each detection result of target to detector is tracked internally, and is merely looked up by the GetDetectionLevel function.
 
[[GetDetected]], on the other hand, forces Oblivion to run the entire detection formula, and therefore any mod that alters or hooks that formula will have its sub-scripts called.  Depending on how often it is used, this could potentially cause performance issues.
 
==Notes==
 
* Dead actors seem to have their detection status "locked in" at whatever value it was when they died. This means an actor aware of the player when the player kills him, will ''always'' be considered aware of the player (though this does not matter since the actor is dead). It is therefore important in scripts which check detection levels to also make sure that the "detector" is, in fact, alive, in addition to checking other detection settings.
* The bug above also applies when [[SetUnconscious]] is used on an actor, until the effects of that command are reverted.
 
==See Also==
[[Sneak]]
 
[[GetDetectionLevel]]
 
[[GetDetected]]
 
[[IsActorDetected]]
 
 
<div><span style="font-size: 142%; font-weight: bold;">Articles in category "Detection"</span></div>
----<div>
There are 20 articles in this category.
{| border="0" cellpadding="0" cellspacing="0"
|width="5"|
|width="285"|<span style="font-size: 132%; font-weight: bold;">D</span>
|width="5"|
|width="200"|<span style="font-size: 132%; font-weight: bold;">F cont.</span>
|width="5"|
|width="200"|<span style="font-size: 132%; font-weight: bold;">F cont.</span>
|-
|
|<li type="square">[[Detection]]
|
|<li type="square">[[FSneakLostMin]]
|
|<li type="square">[[FSneakSoundsMult]]
|-
|
|width="285" rowspan="2"|<span style="font-size: 132%; font-weight: bold;">F</span>
|
|<li type="square">[[FSneakMaxDistance]]
|
|<li type="square">[[FSneakSwimmingLightMult]]
|-
|
 
|
|<li type="square">[[FSneakNoticedMin]]
|
|<li type="square">[[FSneakTargetAttackBonus]]
|-
|
|<li type="square">[[FSneakBaseValue]]
|
|<li type="square">[[FSneakRunningMult]]
|
|<li type="square">[[FSneakTargetInCombatBonus]]
|-
|
|<li type="square">[[FSneakBootWeightBase]]
|
|<li type="square">[[FSneakSeenMin]]
|
|<li type="square">[[FSneakUnseenMin]]
|-
|
|<li type="square">[[FSneakBootWeightMult]]
|
|<li type="square">[[FSneakSkillMult]]
|
|width="285" rowspan="2"|<span style="font-size: 132%; font-weight: bold;">I</span>
|-
|
|<li type="square">[[FSneakExteriorDistanceMult]]
|
|<li type="square">[[FSneakSleepBonus]]
|
 
|-
|
|<li type="square">[[FSneakLightMult]]
|
|<li type="square">[[FSneakSoundLosMult]]
|
|<li type="square">[[IAICombatMinDetection]]
|-
 
|}


As You can see, all variables except '''Base''' are subject to distance attenuation. The distance is always measured between the ''target'' and the ''origin''. The distance attenuation is always applied to the '''Skill''', '''Light''', '''Sound''' variables before calculating the end-result. The further away the ''target'' is, the less significant the variable is. It is quite logical: while I am far away,
*I do not need good [[Sneak]] skill,
*it does not matter whether I am in the darkest corner, and
*it does not matter whether I make a little noise.
Obviously the minimum distance is always zero, however the maximum distance is limited. In [[interior cells]] the maximum distance where detection applies is [[fSneakMaxDistance]] (default: 1500). The maximum distance in [[exterior cells]] is calculated from [[fSneakMaxDistance]] and [[fSneakExteriorDistanceMult]] (default: 2) like this: '''OutDoorDistance = [[fSneakMaxDistance]] * [[fSneakExteriorDistanceMult]]'''; applying the default values this formula gives us 3000. Any actors outside this distance cannot take part in detection rolls - so if You start wondering why can't You hide in combat, this is one of the reasons: You are too far away to trigger detection calculations.


[[Category:Actor Behavior]]
[[Category:Actor Behavior]]
[[Category:Gameplay]]
[[Category:Gameplay]]
[[Category:Settings]]
[[Category:Settings By Concept]]
Anonymous user