Security Camera (2.10+): Difference between revisions
Replace references to "player" with "enemy". Update descriptions of damage behaviour. |
Update with new script events. |
||
Line 192: | Line 192: | ||
* getSecurityCameraState() - Returns the security camera's state. 1 = unalerted, 2 = partially alerted, 3 = fully alerted, 4 = inactive (power off), 5 = destroyed, 0 = not a security camera. | * getSecurityCameraState() - Returns the security camera's state. 1 = unalerted, 2 = partially alerted, 3 = fully alerted, 4 = inactive (power off), 5 = destroyed, 0 = not a security camera. | ||
* getShaderParm(7) - Returns the current value of shaderParm7 on the camera model. 0 = unalerted, 1 = about to resume sweep after a partial alert, 2 = partially alerted, 3 = fully alerted. | * getShaderParm(7) - Returns the current value of shaderParm7 on the camera model. 0 = unalerted, 1 = about to resume sweep after a partial alert, 2 = partially alerted, 3 = fully alerted. | ||
* | * On() and Off() - Switch the camera's power on or off (note the capitalisation). | ||
* activate() and trigger() - Toggle the camera's power. | |||
* getHealth() and setHealth(float newHealth) - As per the name. Setting health to 0 or lower will destroy the security camera, which is irreversible. setHealth() will make an invincible camera vulnerable. | * getHealth() and setHealth(float newHealth) - As per the name. Setting health to 0 or lower will destroy the security camera, which is irreversible. setHealth() will make an invincible camera vulnerable. | ||
* setSightThreshold() - This changes how lit up the player's lightgem has to be for the security camera to see him, from 0.0 to 1.0. | * setSightThreshold() - This changes how lit up the player's lightgem has to be for the security camera to see him, from 0.0 to 1.0. | ||
* state_light(boolean set) - Switch the camera's spotlight on/off, if the camera has one. | |||
* state_sweep(boolean set) - Switch the camera's sweep on/off. This will also affect enemy tracking. | |||
* state_see_player(boolean set) - Toggle whether the camera is able to detect the player. An alternative is just to set "seePlayer" to "1" or "0", since the code monitors this spawnarg. | |||
* toggle_light() - Toggle the spotlight on/off, if the camera has one. | * toggle_light() - Toggle the spotlight on/off, if the camera has one. | ||
* toggle_sweep() - Toggle the camera's sweep on/off. This will also affect | * toggle_sweep() - Toggle the camera's sweep on/off. This will also affect enemy tracking. | ||
* toggle_see_player() - Toggle whether the camera is able to detect the player. An alternative is just to set "seePlayer" to "1" or "0", since the code monitors this spawnarg. | * toggle_see_player() - Toggle whether the camera is able to detect the player. An alternative is just to set "seePlayer" to "1" or "0", since the code monitors this spawnarg. | ||
Revision as of 13:39, 16 July 2022
Security Camera
This article documents the security camera as it will be from 2.10 onwards. See Security Camera if you're currently working with TDM 2.09 or older versions.
The security camera provides the following features:
- It can either sweep back and forth between two angles or remain stationary.
- If the camera sees the player or an AI on a hostile AI, it initially plays a short alert sound that is silent to nearby guards. If the enemy is still in view several seconds later, an alarm sounds. This alarm will play intermittently for a while, even if the enemy moves out of sight.
- The camera is able to track its enemy, making it much harder to escape its view.
- An optional spotlight that points forward, lighting the area in the direction the camera faces. You can instead let the camera use a light you created.
- The ability to toggle the camera power on/off by triggering it. Alternatively, the above described subsystems can be toggled individually.
- If the camera has targets, these will be activated when the camera is fully alerted. This gives the map author the ability to play a more powerful alarm than the one given off by the camera (or to do a variety of other things.)
- The camera will sound an alarm if it detects bodies.
- Sending what it sees to a separate, func_static display screen. Alternatively, it can send what another entity (typically a target_null) sees.
The Security Camera: Entities and Prefabs
Security camera entities can be found in AI/Machines/Security Camera and inherit from func_securitycamera. Prefabs can be found in AI/Machines.
Place the camera entity in your map, and orient it toward its starting direction. A rotating camera will sweep clockwise, halt a moment, then sweep back counter-clockwise.
Some cameras may be designed to use additional parts, i.e. a ceiling pivot entity with scripted gears. See the entity descriptions inside DR for more.
Spawnargs
Movement Spawnargs
- "rotate" - If "1" (default) the camera will rotate. If "0", the camera is stationary.
- "sweepSpeed" - Horizontal rotation speed in degrees per second.
- "sweepAngle" - The number of degrees the camera covers during its sweep. You can cause a camera to initially sweep in the counter-clockwise direction by setting this to a negative number.
- "sweepWait" - How long the pause is after a sweep completes and starting the return sweep. Default is 0.5 seconds.
Detection Spawnargs
These spawnargs govern how the security camera detects and reacts to the player: up to what distance, at what light intensity, how long the alarm lasts, whether to trigger anything and so on.
- "scanDist" - The distance limit for spotting the enemy.
- "scanFov" - The camera's field of view.
- "seePlayer" - Whether the camera will react to the player.
- "seeAI" - Whether the camera will react to AIs.
- "seeBodies" - Whether the camera will react to bodies.
- "seeAnimals" - Whether the camera will react to animals.
- "sight_threshold" - From 0.0 to 1.0, how lit up the lightgem has to be for the player to be detected.
- "sightTime" - After seeing the enemy (partial alert), the camera will wait this amount of time. If it still sees the enemy, it will sound the alarm. This gives the enemy some time to hide.
- "sightResume" - If the camera can't see the enemy anymore after a partial alert, pause for this amount of time. When this expires, the camera will resume sweeping.
- "alarm_duration" - Minimum duration of the fully alert state. Will be extended by half if the enemy is still in view at the end or was recently seen.
- "alarm_interval" - Amount of time inbetween each activation of the alarm sound, when fully alerted.
- "trigger_alarm_start" - Trigger targets when an alarm begins.
- "trigger_alarm_end" - Trigger targets when an alarm ends.
Follow Spawnargs
The security camera can track the enemy's movements. For as long as the security camera is partially or fully alerted, it will turn to the closest enemy it can see. The models for the camera and mount should be able to support this without clipping into each other. A ceiling-mounted camera will generally have much more freedom to turn than a wall-mounted camera.
- "follow" - Enable to let the camera track the enemy horizontally.
- "follow_tolerance" - How far in degrees the enemy has to move before the camera readjusts its rotation, horizontally.
- "follow_speed_mult" - Speed up horizontal movements by this multiplier when the camera is following the enemy.
- "follow_incline" - The camera will also track the enemy vertically.
- "follow_incline_tolerance" - How far in degrees the enemy has to move before the camera readjusts its rotation, vertically.
- "follow_incline_speed" - Speed of vertical movements to track the enemy. Not affected by 'follow_speed_mult'.
- "follow_incline_max_up" - Limit how far the camera can turn upwards from its starting orientation.
- "follow_incline_max_down" - Limit how far the camera can turn downwards from its starting orientation.
Spotlight Spawnargs
If "spotLight" is set to 1, the security camera's code will spawn a spotlight and align it with its view. This dates back to the Doom3 days, so it follows different rules from the def_attach systems. If "useColors" is enabled, the spotlight's color will change depending on alert state. Otherwise it will look for a "_color" spawnarg on the camera.
Alternatively you can specify an existing light with the spawnarg "spotlight_custom". Apart from "spotLight" and "useColors", all other spotlight-relevant spawnargs are ignored. If no valid entity of spawnclass idLight is found, it'll spawn a spotlight instead.
- "spotLight" - If "1" the camera will use a spotlight.
- "spotlight_range" - Reach of the spotlight.
- "spotlight_diameter" - Diameter of the spotlight's projection. If 0, will automatically be calculated to match spotlight_range and scanFov, for scanFov up to 90°.
- "spotlight_texture" - Texture used by the spotlight. You should use a texture that's designed for projected lights: one that uses a gradient as its falloff image. This ensures that light intensity gradually fades to black, rather than abruptly cutting to black.
Color Spawnargs
- "useColors" - If "1" the camera will change the colour of its model and spotlight depending on its alert state.
- "color_sweeping" - Color when the camera is sweeping = unalerted. Default green.
- "color_sighted" - Color when the camera has noticed an enemy = partially alerted. Default yellow.
- "color_alerted" - Color when the camera has sounded the alarm = fully alerted. Default red.
- "_color" - If "useColors" is disabled, the model and spotlight will always have this color.
As an alternative or complement to color spawnargs, you may make use of shaderParm7 in materials used by the security camera. shaderParm7 represents the alert state of the camera:
- 0 = unalerted
- 1 = was partially alerted for "sightTime" seconds but the enemy has disappeared, now waiting "sightResume" seconds before resuming sweeping.
- 2 = partially alerted
- 3 = fully alerted
Damage Spawnargs
- "health" - amount of damage the camera can take before being destroyed. Setting to 0 will make the camera invincible. Setting to 0 will make the camera invincible. Default base damage per hit: sword - 42; broadhead - 35; fire arrow direct hit - 400.
- "damage_blackjack" - how much damage the security camera takes from blackjack hits, default: 0.
- "damage_mult_" - a series of spawnargs to multiply how much damage the security camera takes from various damage sources. You can name specific weapon classnames or damageDefs in the spawnarg, i.e. "damage_mult_atdm:weapon_shortsword" "0.5".
- "damage_splash_falloff" - how quickly splash damage from fire arrows exponentially decreases with distance, default: 3.
- "damage_flinderize" - if a security camera is destroyed and the destroying hit (or post-destruction hit) is greater than this value, the security camera explodes into pieces. Default: 90.
- "def_flinder1" - the classname of the flinder pieces generated when a camera is flinderized by a heavy hit. Use "def_flinder2" etc. to generate more flinders.
- "flinder_offset1" - specifies the spawn point of the respective flinder piece relative to the camera's origin. Takes the camera's current rotation into account.
- "broken" - the security camera switches to this model when destroyed
- "broken_flinderized" - Optional. Specify the model of the security camera when destroyed + flinderized.
- "skin_broken" - the security camera switches to this skin when destroyed
- "skin_flinderized" - Optional. Specify the skin of the security camera when destroyed + flinderized.
- "hideModelOnBreak" - the security camera will be hidden when destroyed, default: 0.
- "notice_destroyed" - Whether AIs will become alerted if they find this security camera destroyed.
- "fx_damage" - Fx to play whenever the camera is damaged while power is on.
- "fx_damage_nopower" - Fx to play whenever the camera is damaged while power is off.
- "fx_destroyed" - Fx to play whenever the camera is destroyed while power is on.
- "fx_destroyed_nopower" - Fx to play whenever the camera is destroyed while power is off.
- "break_up_script" - This script is called when the camera is destroyed.
- "break_up_target" - This entity is triggered if the camera is destroyed.
Sound Spawnargs
- "snd_sight" - Sound emitted when the camera notices an enemy.
- "snd_moving" - Sound emitted when the camera is rotating.
- "snd_stationary" - Sound emitted by a stationary type of camera.
- "snd_alert" - Alarm sound emitted when fully alerted.
- "snd_end" - Sound emitted when the camera is about to reach the end point of a sweep.
- "snd_death" - Sound emitted when the camera is destroyed.
- "snd_death_nopower" - Sound emitted when the camera is destroyed while power is off.
- "snd_sparks" - Sound emitted when the camera emits sparks after it was destroyed.
- "sprS_alert" - How far snd_alert propagates to AIs, at default this is a few rooms. Higher settings than mild can cause large framedrops due to mass AI alerts.
Sparks Spawnargs
The security camera spawns a particle emitter when it's destroyed. By default it uses a single-cycle spark particle which is periodically triggered at random intervals. When power to the camera is switched off, the sparks stop appearing.
- "sparks" - Whether to spawn a particle emitter at all.
- "sparks_particle" - Particle that is spawned.
- "sparks_delay" - Time taken for the particle emitter to spawn initially.
- "sparks_power_dependent" - Only show the particle if power to the (dead) camera is on.
- "sparks_periodic" - Set to '0' if you use a looping particle and sound. For single-cycle particles and sounds, set to '1' so that they are regularly triggered.
- "sparks_interval" - For non-looping particles, minimum time between triggers.
- "sparks_interval_rand" - For non-looping particles, additional random factor added to the time between triggers.
Model Spawnargs
These spawnargs are important if you change the camera model:
- "broken" - Use this model when the camera is destroyed.
- "clipmodel" - Assign a simplified collision mesh to this camera. Should be under 32 tris (as of TDM 2.10), have only convex angles and use textures/common/collision.
- "viewOffset" - A vector that defines the offset of the camera's 'eye' from the camera's origin.
- "lightOffset" - A vector that defines the spotlight offset from the camera's origin.
- "flipAxis" - This and the next spawnarg can be used to turn a model such that it faces forwards. Not needed if the model was created forward-facing.
- "modelAxis"
- "skin" - This is the "on" skin. It may contain materials that make use of the colored keyword or shaderParm7, to change depending on alert state.
- "skin_on_spotlight_off" - This is the "on" skin, but with the spotlight toggled off. This is useful if your model contains inbuilt lightrays that should represent the spotlight.
- "skin_off" - This is the "off" skin. It should not contain materials with the colored keyword or shaderParm7.
- "skin_broken" - When the camera is destroyed it will switch to this skin.
Misc Spawnargs
- "start_off" - Whether the camera starts powered on or off.
- "cameraTarget" - Use the view from this entity instead of from self if sending a view to the display screen. See section The Display Screen for more.
- "gearSpeed" - This spawnarg is set on the ceiling pivot of the 2nd type of security camera. It controls how fast the gears turn when the security camera turns.
The security camera uses spawnargs to place its 'eye' and spotlight in front of the model to ensure the view and spotlight aren't blocked by the model. If you use a different model, you might need to change these.
- "lightOffset"
- "viewOffset"
Damaging the Camera
Damage sources
By default the security camera is vulnerable only to fire arrows (direct & splash damage). The "damage_" and "damage_mult_" spawnargs allow you to to specify how much damage security cameras take from each weapon, but be sure to communicate the camera's vulnerabilities to the player. You can create your own "damage_mult_" spawnargs by adding the name of a specific weapon classname or damageDef, i.e. "damage_mult_atdm:weapon_shortsword" "0.5". Unfortunately it does not appear to be possible to make water damage the camera, since TDM will crash upon load when a water response is applied to the camera.
Setting "health" to 0 will make the camera totally invicible. Alternatively, you can make the camera immune to everything but fire arrow splash damage by binding a tight-fitting nodrawsolid_metal brush. A similar approach is to bind a brush that leaves parts of the camera exposed, i.e. the lens or face. Note that it will weaken fire arrows considerably if they hit from the wrong angle. A direct hit does up to 400 damage, while the splash does a distance-dependent amount of damage below 100. Note that collision detection is done using the camera's clipmodel, which has a different shape than the visual model.
The player will receive feedback that the camera took damage in the form of spark effects, specified in spawnargs beginning with fx_. An .fx definiton is basically an instruction to emit a sequence of particles and sounds.
Destroying the Camera
Security cameras can not only be destroyed, but also be flinderized (burst apart into pieces) which occurs when the security camera takes a hit whose damage is higher than the value of the "damage_flinderize" spawnarg. The "broken" and "skin_broken" spawnargs let you set the model and skin when the camera is destroyed, while the optional "broken_flinderized" and "skin_flinderized" let you set the model and skin when the camera has been flinderized. The "def_flinder" and "flinder_offset" spawnargs allow you to specify the flinder pieces and their spawn point relative to the camera's origin.
Scripting
Script Events
The security camera supports the following script events:
- getSecurityCameraState() - Returns the security camera's state. 1 = unalerted, 2 = partially alerted, 3 = fully alerted, 4 = inactive (power off), 5 = destroyed, 0 = not a security camera.
- getShaderParm(7) - Returns the current value of shaderParm7 on the camera model. 0 = unalerted, 1 = about to resume sweep after a partial alert, 2 = partially alerted, 3 = fully alerted.
- On() and Off() - Switch the camera's power on or off (note the capitalisation).
- activate() and trigger() - Toggle the camera's power.
- getHealth() and setHealth(float newHealth) - As per the name. Setting health to 0 or lower will destroy the security camera, which is irreversible. setHealth() will make an invincible camera vulnerable.
- setSightThreshold() - This changes how lit up the player's lightgem has to be for the security camera to see him, from 0.0 to 1.0.
- state_light(boolean set) - Switch the camera's spotlight on/off, if the camera has one.
- state_sweep(boolean set) - Switch the camera's sweep on/off. This will also affect enemy tracking.
- state_see_player(boolean set) - Toggle whether the camera is able to detect the player. An alternative is just to set "seePlayer" to "1" or "0", since the code monitors this spawnarg.
- toggle_light() - Toggle the spotlight on/off, if the camera has one.
- toggle_sweep() - Toggle the camera's sweep on/off. This will also affect enemy tracking.
- toggle_see_player() - Toggle whether the camera is able to detect the player. An alternative is just to set "seePlayer" to "1" or "0", since the code monitors this spawnarg.
Object Functions
The security camera's scriptobject contains the following object functions:
- toggleSCSpotlight() - calls toggle_light() on the camera if it has a spotlight (spawnarg "spotLight" = "1")
- toggleSCSweep() - calls toggle_sweep() on the camera
- toggleSCPlayer() - calls toggle_see_player() on the camera
As you can see, these object functions simply call the toggle script events on the camera they belong to. This allows you to call the script events from i.e. buttons without scripting. To set this up:
- create an atdm:target_callobjectfunction entity
- give it the spawnarg "call" with the name of the desired object function, i.e. "toggleSCSpotlight"
- let it target the security camera
- when desired, trigger this entity (from a script, from a button etc.).
Scriptobjects
The security camera's scriptobject only consists of the 3 object functions mentioned above. Beyond some added utility, this scriptobject has no importance for the security camera and you can easily give it your own scriptobject instead.
Upon Destruction
You may call a script when the camera is destroyed, as per the spawnarg "break_up_script". This script should be able to receive the name of the destroyed security camera as input, i.e.:
void camera_destroyed ( entity camera )
An alternative is to use the spawnarg "break_up_target" to name an entity that calls the script when triggered, but this will not pass the name of the destroyed security camera unless you use an atdm:target_callscriptfunction entity with the spawnarg "forEach" "1".
Sending the camera's view to a Display Screen
You can create a display screen that shows that the camera sees: all that's needed is a func_static patch that uses a texture like textures/common/camera/camera1. It's recommended to put another patch behind it, since this func_static will get hidden if it's switched off. The screen then needs to be given a spawnarg "cameraTarget" that names either a security camera or a different entity, typically a target_null. The screen will display what that entity sees.
To change the screen's field of view, apply the spawnargs "cameraFovX" and "cameraFovY" to the entity sending the view. Otherwise it will default to "scanFov" for security cameras or 120 for other entities.
The screen is hidden or shown automatically if the screen is displaying a security camera's view. The screen can also be switched on/off manually by triggering it, but this requires the screen to start with the spawnarg "hide" "0" or "hide" "1".
Multiple Display Screens / Reflective Water / Skybox
If you plan to have multiple security cameras sending to multiple display screens in your mission, or if the camera display will appear in the same player POV as the sky or reflective water surfaces, you'll need to use unique camera materials for each screen. You can find 9 additional camera materials in the textures/common/camera/ folder. If you should need even more, you can simply clone one of the materials and change the name after the map keyword.
Examining a Test Map
You can obtain a test map with sample cameras in it here: camerawiki2.pk4. Similar setups can be found as prefabs in AI/Machines.
Open the map camerawiki.map in Dark Radiant. In this map, we have examples of the different cameras.
A rotating camera that sweeps back and forth
This camera (cam1) starts its rotation at 135 degrees (assuming +X is 0 degrees), and sweeps clockwise until it reaches 45 degrees. It pauses for a moment, then return-sweeps back to 135 degrees. It has a spotlight.
The display for cam1 is on the wall behind it. (Don't worry about the material being displayed backward in the screenshot.)
The display patch uses the material camera1 (provided in the camerawiki/materials/tdm_camera.mtr file).
The four buttons below the display do the following (from left to right):
- Toggle Power - targets cam1 directly. When power is off, the display screen is hidden. You can simulate an "off" screen by making sure there's a black material behind the display. You could also place a glass material behind the display.
- Toggle Spotlight - calls the toggleSCSpotlight() object function in the camera's scriptobject, turning the spotlight on/off
- Toggle Player Sighting - calls the toggleSCPlayer() object function in the camera's scriptobject, turning Player detection on/off
- Toggle Sweep - calls the toggleSCSweep() object function in the camera's scriptobject, turning camera sweep on/off
A stationary camera that doesn't move
This camera (cam2) is stationary, w/o a spotlight.
Its display, to its left, uses the material camera2.
The two buttons below the display do the following (from left to right):
- Toggle Power - targets cam2 directly. When power is off, the display screen is hidden.
- Toggle Player Sighting - calls the toggleSCPlayer() object function in the camera's scriptobject, turning player detection on/off
A screen showing the view from another entity (a target_null)
This is simply a screen referencing a target_null as its cameraTarget. The target_null is in a separate room pointed at a guard.
If you look in the room where the guard is standing, you'll see that the target_null has the spawnargs cameraFovX and cameraFovY. These were set because the default field of view for a view from a non-camera entity is 120 by 120, which looks quite zoomed out. For a small screen like this one, 60 by 60 is much better.
Also notice that the screen itself has the spawnarg hide 0. This makes it respond to triggers by hiding or showing itself, allowing you to switch it on or off at the push of a button (see below).
The button below the display does the following:
- Toggle Power - targets the screen directly to show or hide it. This only works because the screen has a hide spawnarg.