Logic
From Mod Wiki
Revision as of 12:43, 20 July 2008 (edit) Don Reba (Talk | contribs) (→sniper scheme - translated) ← Previous diff |
Current revision (19:28, 6 August 2008) (edit) (undo) Don Reba (Talk | contribs) m (→Sr_light - minor formatting) |
||
(116 intermediate revisions not shown.) | |||
Line 34: | Line 34: | ||
====Configuration==== | ====Configuration==== | ||
+ | |||
+ | [[Image:Logic01.png]] | ||
For each walker, you should place onto the map: | For each walker, you should place onto the map: | ||
Line 54: | Line 56: | ||
A character patrols territory around two houses. Here is how the route is made: | A character patrols territory around two houses. Here is how the route is made: | ||
+ | |||
+ | [[Image:Logic02.png]] | ||
What to do to make the character run or sneak between certain points? There are flags in <tt>path_walk</tt> just for this purpose. | What to do to make the character run or sneak between certain points? There are flags in <tt>path_walk</tt> just for this purpose. | ||
Line 64: | Line 68: | ||
====Example 2==== | ====Example 2==== | ||
+ | |||
+ | [[Image:Logic03.png]] | ||
A character conversation. | A character conversation. | ||
- | To make a character speak while moving along a path, each point must have a list of topic he can speak about. There | + | To make a character speak while moving along a path, each point must have a list of topic he can speak about. There is the following field for this: <tt>s = sound_scheme_name</tt> (off by default). Several topics can be separated by commas.t |
====Example 3==== | ====Example 3==== | ||
- | + | [[Image:Logic04.png]] | |
+ | |||
+ | Example 3 uses only the field <tt>s</tt> to set conversation topics. | ||
It is NOT RECOMMENDED to set the other parameters (sp, sf, st). The default values are acceptable for most scripts. | It is NOT RECOMMENDED to set the other parameters (sp, sf, st). The default values are acceptable for most scripts. | ||
Line 81: | Line 89: | ||
====Example 4==== | ====Example 4==== | ||
- | + | Improve Example 1, so that when the character passes a space between houses, stopped and looked inside it: | |
- | + | [[Image:Logic05.png]] | |
- | + | What is new? There is now a <tt>path_look</tt> path with two points. It is recommended to remove the link between these two points of the path in the editor right away, since it is not used anyway. | |
- | + | Forethermore, lets set some flags at the points of <tt>path_walk</tt> and <tt>path_look</tt> that are circled with a dashed line. For instance, in the upper pair of points, set the flag 0, and in the lower pair — flag 1. | |
- | + | Now the character will stop at points of <tt>path_walk</tt> marked with a flag, look towards the point of <tt>path_look</tt> marked with the same flag. | |
- | + | If a point of <tt>path_walk</tt> is not marked with a flag, the character will pass it without stopping. | |
- | + | One point of <tt>path_walk</tt> can correspond to several points of <tt>path_look</tt>. If this is the case, the character will randomly choose one of the suitable points. | |
- | + | Similarily to <tt>path_walk</tt> you can use various flags in points of <tt>path_look</tt> to modify behavior: | |
- | + | ; p = 100 | |
- | + | : Probability with which the character will look at that point. The values of all suitable <tt>p</tt> are added, so if one point has <tt>p = 100</tt> and another 300, the character will look twards the point with probability 25% (100 out of 100 + 300). | |
- | + | : To avoid confusion, you should set <tt>p</tt> such that they add up to 100. | |
- | + | : By default, all points have <tt>p = 100</tt>. | |
- | t = | + | ; t = time in milliseconds |
+ | : Duration of time for which the character will stop at this point. | ||
+ | : By default, the value is 5000. | ||
====Example 5==== | ====Example 5==== | ||
- | + | [[Image:Logic06.png]] | |
- | + | In this example, as the character passes point wp00, he will look at the point wp00 for 5 seconds with probability 30% or at the point wp01 for 10 seconds with probability 70%. | |
- | + | By default, the character plays the <tt>idle</tt> animation when he stops if he is not crouching, or animation <tt>hide</tt> if he is crouching. | |
- | a | + | If you need a different animation, you can set it with this flag: |
- | + | a = animation name (defaults to <tt>idle</tt>). | |
- | + | Write a=anim, where anim – is the name of an animation from 2.4.4. of the actual documentation. If we write a=hide, the character will enter the alert mode, if a=guard, will stand with his weapon on ready, etc. | |
+ | |||
+ | :Note: ''You can only use animations from the section "standing and crouching animations" for <tt>path_look</tt>!'' | ||
==Stalker behaviour schemes== | ==Stalker behaviour schemes== | ||
- | + | There is a certain set of schemes that describe a character's behavior. They are set in his custom_data or, in case of a gulag, in corresponding flags, describing the function of a given gulag. The list of these scheme follows. | |
- | + | ||
+ | All of the loaded schemes are listed in the file \gamedata\scripts\modules.script | ||
===walker scheme=== | ===walker scheme=== | ||
Line 149: | Line 162: | ||
===remark scheme=== | ===remark scheme=== | ||
- | + | This scheme is used for synchronization and binding with other schemes. | |
- | + | '''[remark]''' | |
- | [remark] | + | |
snd_anim_synс = true либо false. По умолчанию false. Указывает на то необходимо ли синхронизировать звук с анимацией либо нет | snd_anim_synс = true либо false. По умолчанию false. Указывает на то необходимо ли синхронизировать звук с анимацией либо нет | ||
- | snd | + | ; snd |
- | anim | + | : remark sounds; <tt>nil</tt> by default |
- | target | + | ; anim |
- | + | : remark animation; <tt>wait</tt> by default | |
- | + | ; target | |
- | + | : where the stalker looks; there are the following options | |
- | + | :; story_id | |
- | < | + | :: a number |
- | Example: | + | :; actor |
+ | :: no comment | ||
+ | :; nil | ||
+ | :: position automatically calculated by the AI | ||
+ | :; <job name>, <gulag name> | ||
+ | :: look at a stalker that has a certain job in a certain gulag (the second parameter is not required, if omitted, the gulag of the stalker to which the given section applies is used). Example: | ||
+ | ::<source lang="ini">target = logic@cit_killers_base_guard, cit_killers</source> | ||
+ | :; <path name>, <point number> | ||
+ | :: you can tell him to look at a vertex of a patrolling path | ||
- | < | + | ''Note: that if this value is not set, it will be equal <tt>nil</tt> not <tt>actor</tt>. If you want to make a character look at an actor in a remark, you have to specify it explicitely. Given <tt>nil</tt> the character will return to an AI-calculated position.'' |
- | + | ||
- | </ | + | |
- | < | + | |
- | + | Standard signals for <tt>remark</tt>: | |
+ | ; sound_end | ||
+ | : when the sounds finish playing | ||
+ | ; anim_end | ||
+ | : when the animations finish playing | ||
+ | ; action_end | ||
+ | : when both finish, if synchronized | ||
- | + | An example of using animation and sound in a <tt>remark</tt> scheme: | |
- | + | ||
- | + | ||
- | + | ||
- | + | <source lang="ini"> | |
[remark] | [remark] | ||
- | anim = | + | anim = animation |
- | snd = | + | snd = sound |
snd_anim_sync = true | snd_anim_sync = true | ||
- | on_signal = action_end | | + | on_signal = action_end | next scheme |
+ | </source> | ||
+ | |||
===sleeper scheme=== | ===sleeper scheme=== | ||
Line 221: | Line 243: | ||
Camper properties: | Camper properties: | ||
- | * | + | * campter stands at a spot and looks in the direction in which you set him in the editor or moves along patrol paths |
- | * | + | * campers switch to all-purpose combat when they see an enemy closer than 30 meters away. If a camper survives, he returns to <tt>camper</tt> mode. |
- | * | + | * In all other situations act according to their own scripting scheme. If an enemy is in sight — shoot. If danger is heard — look in its direction. If a grenade is spotted — run away from the grenade. If an enemy was in sight, but disappeard, look in the direction of last sighting of the enemy. |
- | * | + | * campers do not move and attack. If they see an enemy, they stop, shoot, then continue movement. |
- | [camper] | + | '''[camper]''' |
- | + | ; '''path_walk''' = patrol_path | |
- | + | ; '''path_look''' = patrol_path | |
- | + | ; '''radius''' = number | |
- | + | : distance in meters; if the distance between the camper and the enemy is less, camper switches to all-purpose combat mode; 20 by default | |
- | + | ; '''no_retreat''' = true/false | |
- | + | : <tt>true</tt> if the character will not go towards the nearest <tt>path_walk</tt> point upon enemy sighting, but starts attacking him immediately. Needed in case you wont to create a scene with some guys hitting on some others. Set this flag for the campers. They walk along their patrol points and take out the enemies. | |
- | + | ; '''def_state_moving''' = state manager state | |
- | + | : a state in which we move to the nearest point upon an enemy sighting | |
- | + | ; '''def_state_moving_fire''' state manager state (sneak_fire) | |
- | + | : state in which we shoot the enemy while moving towards the nearest path point | |
- | + | ; '''def_state_campering''' = state manager state (hide) | |
- | + | : state in which we ambush an enemy while remaining on the path | |
- | + | ; '''def_state_campering_fire''' = state manager state (hide_fire) | |
- | + | : state in which we shoot an enemy while moving along the path | |
- | + | ; '''attack_sound''' = sound scheme name | |
+ | ability to overwrite attack sound for snipers/campers; it can be disabled by writing "<tt>attack_sound=</tt>"; <tt>fight_attack</tt> by default | ||
+ | ; '''shoot''' - type | ||
+ | : attack type | ||
+ | :; always | ||
+ | :: shoot whenever possible; default value | ||
+ | :; none | ||
+ | :: do not shoot | ||
+ | :; terminal | ||
+ | :: shoot only at the last path point; added to make scripted scene creation easier | ||
- | + | The camper has a large drawback — when he is hit and he does not know where the hit comes from (because he does not see the enemy or does not hear the shot), he daftly remains standing at the old spot and wait for the next bullet. In sight of this, you should not set campers to guard a position if there are several directions from which the player or other stalkers can attack the camper. Use walkers in such cases; while setting campers to attack along paths or using them as snipers. | |
===sniper scheme=== | ===sniper scheme=== | ||
Line 260: | Line 291: | ||
===follower scheme=== | ===follower scheme=== | ||
- | + | NPC follows an NPC leader. If the leader is closer than 5 meters, he walks, if 5 to 20 — runs, if more than 20 — sprints. Paths are not set. | |
- | NPC | + | |
- | [follower] | + | '''[follower]''' |
- | + | ; leader = number | |
- | + | : story id of the leader from game.ltx | |
- | + | ; formation_line = true/false | |
- | + | : try to stay to the side of the leader, otherwise walk behind | |
- | + | ; distance | |
- | + | : distance in meters to keep away from the leader at; 1.5 meters by default, if walks in a chain, then 5 meters | |
- | + | ; state_if_leader_in_meet | |
+ | : a string with a state name from state_manager, which will be set by the follower if the leader is in the <tt>meet</tt> state | ||
+ | ; anim_walk | ||
+ | : state for the follower to walk behind the leader in | ||
+ | ; anim_run | ||
+ | : state for the follower to run after the leader in | ||
+ | ; anim_sprint | ||
+ | : state for the follower to sprint after the leader in | ||
File: \gamedata\scripts\xr_ attendant.script | File: \gamedata\scripts\xr_ attendant.script | ||
- | + | If all of this happens in a gulag, then story_id of the leader should be replaced by his logic sections in the script file. Example: | |
<source lang="lua"> | <source lang="lua"> | ||
Line 290: | Line 327: | ||
===zoneguard scheme=== | ===zoneguard scheme=== | ||
- | NPC | + | There are two zones for the NPC (or one). He walks along paths, but when the player enters the first zone, drops everything, runs up to the player, points a weapon at him (might also yell or talk), if the player enters the second zone — attacks him |
- | [zoneguard] | + | '''[zoneguard]''' |
- | + | ||
- | + | ; path_walk | |
- | + | ; path_look | |
- | + | ; team | |
- | + | : name of a team of synchronized zoneguards (only one from the team will react to the player) | |
- | + | ; zone_guard | |
- | + | : the name of the zone in which the player will be attacked | |
- | + | ; zone_warn | |
- | + | : the name of the zone in which to start a conversation with the player | |
- | + | ; walker_team | |
- | + | : team to set it in walker mode (will be the same as <tt>team</tt> if not set) | |
- | + | ; no_move | |
- | + | : will yell to the player from the spot, and not run towards him | |
+ | ; snd_greet | ||
+ | : name of the sound scheme from which to play a sound on finding the player | ||
+ | ; ignore_friends | ||
+ | : if true, will ignore friendly characters | ||
+ | ; ignore_cond | ||
+ | : {+info -info =func !func} conditions for ignoring the player | ||
+ | ; no_danger | ||
+ | : if true, will not play the threat animation to neutrals | ||
+ | ; anim | ||
+ | : animation to play if not hostile to the player | ||
+ | ; snd_anim_sync | ||
+ | : if true, will synchronize sound with animation | ||
File: \gamedata\scripts\xr_zoneguard.script | File: \gamedata\scripts\xr_zoneguard.script | ||
Line 319: | Line 368: | ||
[wounded] | [wounded] | ||
- | hp_state | + | hp_state = HP|condstate@condsound|HP|condstate@condsound |
- | hp_state_see | + | hp_state_see = HP|condstate@condsound|HP|condstate@condsound |
- | psy_state | + | psy_state = PSY|condstate@condsound|PSY|condstate@condsound |
- | hp_victim | + | hp_victim = HP|condvictim|HP|condvictim |
- | hp_cover | + | hp_cover = HP|condbool|HP|condbool |
- | hp_fight | + | hp_fight = HP|condbool|HP|condbool |
- | + | syndata = state@sound|state@sound | |
- | + | help_dialog = story_id | |
- | + | help_start_dialog = story_id | |
</source> | </source> | ||
- | + | Where: | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ; condstate | |
- | + | : condition list returning the character's state, or <tt>true</tt>. The NPC will become mad at the player if <tt>true</tt> is returned. | |
- | + | ; condsound | |
- | + | : condition list returning the sound scheme | |
- | + | ; HP | |
- | + | : health point bounding values | |
- | + | ; PSY | |
- | + | : psychological state boundary values | |
- | + | ; condvictim | |
- | + | : condition list returning the direction to look at. Possible values: <tt>nil</tt>, actor, number. In case of a number, will look at the player with the corresponding id. | |
+ | ; condbool | ||
+ | : condition list returning <tt>true</tt> or <tt>false</tt> | ||
- | + | Field values: | |
+ | |||
+ | ; hp_state | ||
+ | : character's behavior in absense of the player in site | ||
+ | ; hp_state_see | ||
+ | : character's behavior on seeing the player | ||
+ | ; psy_state | ||
+ | : character's behavior on psy attacks | ||
+ | ; hp_victim | ||
+ | : point to look at depedning on HP | ||
+ | ; hp_cover | ||
+ | : go to cover or not, based on HP | ||
+ | ; hp_fight | ||
+ | : combat allowed or not, based on HP | ||
+ | ; syndata | ||
+ | : synch pairs, for effect | ||
+ | ; help_dialog | ||
+ | : <tt>story_id</tt> of a dialog to use instead of teh default <tt>actor_help_wounded</tt>. If the plot demands that you replace this dialog with another, you specify the id in this field. | ||
+ | : We also add a dialog for the wounded. If we set it, all actor's dialogs for the wounded should have this precondition: <tt>dialogs.allow_wounded_dialog</tt>. | ||
+ | |||
+ | The default settings for example: | ||
<source lang="ini"> | <source lang="ini"> | ||
- | hp_state = 30|help_me@help|10|wounded_heavy@help_heavy | + | hp_state = 30|help_me@help|10|wounded_heavy@help_heavy |
hp_state_see = 30|wounded@help_see|10|wounded_heavy@help_heavy | hp_state_see = 30|wounded@help_see|10|wounded_heavy@help_heavy | ||
- | psy_state = 50|{=best_pistol}psy_armed,psy_pain@wounded_psy|20| {=best_pistol}psy_shoot,psy_pain@{=best_pistol}wounded_psy_shoot,wounded_psy | + | psy_state = 50|{=best_pistol}psy_armed,psy_pain@wounded_psy|20| {=best_pistol}psy_shoot,psy_pain@{=best_pistol}wounded_psy_shoot,wounded_psy |
- | hp_victim = 30|actor|10|nil | + | hp_victim = 30|actor|10|nil |
- | hp_cover = 30|true|10|false | + | hp_cover = 30|true|10|false |
- | hp_fight = 30|true|10|false | + | hp_fight = 30|true|10|false |
- | syndata = wounded@help | + | syndata = wounded@help |
</source> | </source> | ||
- | + | Where: | |
- | + | ||
+ | ; best_pistol | ||
+ | : a check to make sure the NPC's best weapon is not a pistol | ||
File: \gamedata\scripts\xr_wounded.script | File: \gamedata\scripts\xr_wounded.script | ||
Line 376: | Line 443: | ||
===heli_hunter scheme=== | ===heli_hunter scheme=== | ||
- | + | Helihunter might shoot or not shoot at a helicopter, depending on conditions. This is how it works: | |
<source lang="ini"> | <source lang="ini"> | ||
[camper@bar_freedom_attack_sniper_1] | [camper@bar_freedom_attack_sniper_1] | ||
- | path_walk = camper_1_walk | + | path_walk = camper_1_walk |
- | path_look = camper_1_look | + | path_look = camper_1_look |
- | on_info = {+bar_freedom_attack_ecolog} camper1@bar_freedom_attack_sniper_1 %=bar_freedom_angry_actor% | + | on_info = {+bar_freedom_attack_ecolog} camper1@bar_freedom_attack_sniper_1 %= bar_freedom_angry_actor% |
meet_talk_enabled = true | meet_talk_enabled = true | ||
- | meet_dialog = bar_svoboda_dialog | + | meet_dialog = bar_svoboda_dialog |
- | heli_hunter = {-bar_ecolog_crush_heli_down} true, false | + | heli_hunter = {-bar_ecolog_crush_heli_down} true, false |
</source> | </source> | ||
- | |||
- | Если раньше оверрайд хелихантера понимал только значения true либо false, то сейчас он понимает кондлист, который если возвращает true - то стрельба по вертолету в данной схеме разрешена. | ||
===patrol scheme=== | ===patrol scheme=== | ||
- | + | Here is a preliminary patrol system. It is a variety of <tt>kamp</tt>, except in walking mode. To make it work, add the following to custom data: | |
- | + | '''[patrol]''' | |
- | [patrol] | + | ; path_walk = path_walk |
- | path_walk = path_walk | + | ; path_look = path_look |
- | path_look = path_look | + | ; formation = back |
- | + | : describes the formation type, and is required. Can be one of the following | |
- | *commander = true | + | :* back |
- | + | :* line | |
- | </ | + | :* around |
+ | ; commander = true | ||
+ | : sets the commander; there should be only one | ||
+ | ; move_type = patrol | ||
+ | : sets the initial movement mode, <tt>patrol</tt> by default. This value is a walking animation from <tt>state_mgr_lib</tt> | ||
- | + | When the commander stops at <tt>meet</tt>, the guys stop | |
- | + | ||
- | + | ||
- | + | ||
- | + | If the commander dies, another one is chosen automatically. The first to enter the scheme is chosen. Formation at waypoints is done like this: | |
+ | ; ret=0...2 | ||
+ | * 0 - line | ||
+ | * 1 – around | ||
+ | * 2 – to the sides | ||
- | + | When the commander moves, he works like a regular walker, and the others follow his actions. That is, if the waypoint is set to <tt>a=assault</tt>, the commander will rush forward with his weapon at ready, and the others copy him. | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | What does not really work: | |
- | + | * there is no way to modify formation | |
- | + | * everyone is quiet | |
- | * | + | * commander does not give commands |
- | * | + | * it is not recommended to use sprinting |
- | * | + | |
- | * | + | |
==Sections== | ==Sections== | ||
Line 428: | Line 492: | ||
===combat section=== | ===combat section=== | ||
- | + | Shows what happens when the NPC goes into battle. | |
+ | |||
+ | <source lang="ini"> | ||
on_combat = combat | on_combat = combat | ||
+ | </source> | ||
- | [combat] | + | '''[combat]''' |
- | on_info = %+info -info =func% | + | ; on_info = %+info -info =func% |
+ | : affects for each round of combat | ||
- | + | To set up the various types of scripted battles use the parameter <tt>combat_type</tt> | |
- | + | In the following example, the stalker fights: | |
- | * | + | * as a campter, if <tt>enemy=actor</tt> and is further than X meters |
- | * | + | * as Monolith, if any enemy is further than Y meters |
- | * | + | * engine-controlled otherwise |
<source lang="ini"> | <source lang="ini"> | ||
[logic] | [logic] | ||
- | active = walker | + | active = walker |
on_combat = combat | on_combat = combat | ||
Line 453: | Line 521: | ||
</source> | </source> | ||
- | + | An example of such a function: we need the NPC to switch to campter combat when distance is above 20 meters. | |
+ | |||
+ | <source lang="lua"> | ||
function fighting_dist_ge_20(actor, npc) | function fighting_dist_ge_20(actor, npc) | ||
return db.storage[npc:id()].enemy:position():distance_to ( npc:position() ) >= 400 | return db.storage[npc:id()].enemy:position():distance_to ( npc:position() ) >= 400 | ||
end | end | ||
- | 400 | + | </source> |
+ | |||
+ | 400 is 20 m. We specify the square of the necessary distance to conserve system resources. | ||
- | + | One more example. The stalker moves under the simulation, but his combat is not engine-controlled, but always zombie-style. | |
<source lang="ini"> | <source lang="ini"> | ||
Line 470: | Line 542: | ||
</source> | </source> | ||
- | + | If different character sections require different types of combat or different conditions, you can use the override <tt>combat_type</tt>. | |
- | + | ||
+ | ''Remember: the override will always take priority over the <tt>combat</tt> section settings. That is, if you have logic for five sections and you need camper combat, but monolith combat in fifth, you can do it like this:'' | ||
<source lang="ini"> | <source lang="ini"> | ||
Line 492: | Line 565: | ||
[combat] | [combat] | ||
combat_type = camper | combat_type = camper | ||
- | (scheme - задает тип боя (monolith, camper, zombied), иначе - универсальный бой) | ||
</source> | </source> | ||
- | disable_combat_handler | + | ; scheme |
+ | : sets combat type: monolith, camper, zombied; otherwise, all-purpose combat is used | ||
+ | |||
+ | ; disable_combat_handler | ||
+ | : the function disables the <tt>combat</tt> section. | ||
+ | |||
File: \gamedata\scripts\xr_combat.script | File: \gamedata\scripts\xr_combat.script | ||
Line 515: | Line 592: | ||
===hit section=== | ===hit section=== | ||
- | + | Shows what happens when an NPC is damaged. Note that <tt>on_hit</tt> '''does not''' react to the sound of a shot, but only a direct hit! This is done, because the sound of a shot should not be percieved as aggression in general (the player might be shooting dogs, but ending up provoking guards, for example). | |
+ | |||
+ | <source lang="ini"> | ||
on_hit = hit | on_hit = hit | ||
+ | </source> | ||
<source lang="ini"> | <source lang="ini"> | ||
Line 527: | Line 607: | ||
===actor_dialogs section=== | ===actor_dialogs section=== | ||
- | + | Shows which dialogs will be available to the player when speaking with this NPC. Can be used in almost any scheme. | |
+ | |||
+ | <source lang="ini"> | ||
actor_dialogs = actor_dialogs | actor_dialogs = actor_dialogs | ||
+ | </source> | ||
+ | |||
+ | '''[actor_dialogs]''' | ||
+ | ; id | ||
+ | : comma-separated list of available dialogs | ||
+ | ; disable | ||
+ | : comma-separated list of disbled dialogs | ||
- | [actor_dialogs] | ||
- | id = доступные диалоги через запятую. | ||
- | disable = запрещенные диалоги, тоже через запятую. | ||
File: \gamedata\scripts\xr_meet.script | File: \gamedata\scripts\xr_meet.script | ||
===use section=== | ===use section=== | ||
- | + | This section shows what will happen if the player tried to "use" the NPC. | |
+ | <source lang="ini"> | ||
on_use = use | on_use = use | ||
+ | </source> | ||
<source lang="ini"> | <source lang="ini"> | ||
Line 550: | Line 638: | ||
===combat_ignore section=== | ===combat_ignore section=== | ||
- | + | If an NPC is in this scheme, then he enters into combat mode. In any other scheme: | |
- | [walker] | + | '''[walker]''' |
- | combat_ignore_cond = {+info –info =func !func} | + | ; combat_ignore_cond = {+info –info =func !func} |
+ | : condition for ignoring combat (if you write <tt>always</tt> then the character will always ignore combat in this schema, untill switching to a scheme that does not ignore combat) | ||
- | + | There are no additional fields in the scheme: | |
- | + | ||
- | + | ||
- | [ | + | '''[walker]''' |
+ | ; combat_ignore = combat ignore | ||
- | + | '''[combat_ignore]''' | |
- | + | ||
- | + | ||
- | + | Functions used for wark with the combat ignore condition list: | |
- | check_fighting | + | |
+ | ; fighting_dist_ge_20 | ||
+ | : current enemy at distance equal to or greater than 20 m | ||
+ | ; fighting_dist_ge(distance in meters) | ||
+ | : all-purpose function for combat_ignore, checks for distance from the player | ||
+ | ; fighting_actor | ||
+ | : is actor the current enemy? | ||
+ | ; check_fighting | ||
+ | : check (by story_id) to see if anyone from the list is an enemy | ||
File: \gamedata\scripts\xr_combat_ignore.script | File: \gamedata\scripts\xr_combat_ignore.script | ||
Line 572: | Line 666: | ||
===dont_spawn_character_supplies section=== | ===dont_spawn_character_supplies section=== | ||
- | + | If this section is set, then the standard set of loot specified in the profile won't span inside him. | |
[dont_spawn_character_supplies] | [dont_spawn_character_supplies] | ||
Line 586: | Line 680: | ||
===treshhold section=== | ===treshhold section=== | ||
- | + | There is a way to change stalkers' parameters that determine how they attack monsters. There are two such patameters: | |
- | + | ||
- | + | ||
- | + | ; max_ignore_monster_distance | |
+ | : (currently 15 m by default). The stalker will always attack monsters within a certain radius. | ||
+ | ; ignore_monstre_threshold | ||
+ | : (currently 0 by default) Parameter 0 to 1. If the monster is evaluated at below this parameter, and the monster is outside the given radius, it will be attacked. Currently, stalkers never attack anything outside the 15-meter radius. | ||
+ | In the logic section or in the current sheme set: | ||
+ | |||
+ | <source lang="ini"> | ||
threshold = threshold@tratata | threshold = threshold@tratata | ||
[threshold@tratata] | [threshold@tratata] | ||
max_ignore_distance = <number> | max_ignore_distance = <number> | ||
- | ignore_monster = <number> | + | ignore_monster = <number> |
+ | </source> | ||
- | + | Be '''very''' careful about changing the second parameter. | |
===Danger section=== | ===Danger section=== | ||
- | + | Settings can only be set in some scheme, such as: | |
+ | <source lang="ini"> | ||
[walker] | [walker] | ||
danger = danger_condition | danger = danger_condition | ||
[danger_condition] | [danger_condition] | ||
- | ignore_distance = 50 | + | ignore_distance = 50 |
- | + | ignore_distance_grenade = | |
- | + | ignore_distance_corpse = | |
- | + | ignore_distance_hit = | |
- | + | ignore_distance_sound = | |
+ | </source> | ||
- | + | Distance is set in meters. You can also set the amount of time to wait for danger, depending on type: | |
+ | <source lang="ini"> | ||
danger_inertion_time_grenade = | danger_inertion_time_grenade = | ||
- | danger_inertion_time_corpse = | + | danger_inertion_time_corpse = |
- | danger_inertion_time_hit = | + | danger_inertion_time_hit = |
- | danger_inertion_time_sound = | + | danger_inertion_time_sound = |
+ | </source> | ||
- | + | Default setings: | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | <source lang="ini"> | |
+ | danger_inertion_time_grenade = 20000 | ||
+ | danger_inertion_time_corpse = 10000 | ||
+ | danger_inertion_time_hit = 60000 | ||
+ | danger_inertion_time_sound = 15000 | ||
+ | </source> | ||
- | + | ''Note! These settings also apply to the <tt>camper</tt> scheme. That is, <tt>danger_radius</tt> does not work in camper settings. The data is taken from the <tt>danger</tt> section.'' | |
- | + | The algorithm works like this: first check if distance to the source of danger is not matched by <tt>ignore_danger</tt>. If the danger is closer, then its type is analyzed and is matched against the corresponding distance. If the danger is closer, then reaction to it is permitted. | |
- | + | The following defaults are currently used: | |
- | + | ||
- | + | <source lang="ini"> | |
- | + | ignore_distance = 50 | |
- | + | ignore_distance_grenade = 15 | |
+ | ignore_distance_corpse = 10 | ||
+ | ignore_distance_hit = 50 | ||
+ | ignore_distance_sound = 50 | ||
+ | </source> | ||
- | + | ''Note: if you need a stalker to react to different types of dangers in different situations, create several <tt>danger</tt> sections: <tt>danger_condition@1</tt>, <tt>danger_condition@2</tt>, etc.'' | |
- | + | ; danger_expiration_time | |
- | + | : the amount of time after which danger can be disregarded; 5000 by default | |
+ | ; danger_inertion_time | ||
+ | : the amount of time after which a character can forget about a danger he has reacted to; 10000 by default | ||
===stories section=== | ===stories section=== | ||
- | + | Camps do not tell stories automatically. You have to "teach" certain stalkers a few stories. To do this, add the following section to custom data: | |
- | + | ||
<source lang="ini"> | <source lang="ini"> | ||
Line 654: | Line 763: | ||
</source> | </source> | ||
- | + | The quotation marks contain a comma-separated list of stories and legends. There are currently the following stories and legends: | |
- | story_01 | + | ; story_01 : edge of the Zone and grenade in one move |
- | story_02 | + | ; story_02 : about the anomaly and the rocks |
- | story_03 | + | ; story_03 : about Vilnov's group's return |
- | story_04 | + | ; story_04 : about the time Kostia Fedorin encountered an artifact and disappeared from the radar |
- | story_05 | + | ; story_05 : about the fight with a controller |
- | story_06 | + | ; story_06 : about the door, the vodka, and the house |
- | legend_01 | + | ; legend_01 : about the alien experiment in the Zone |
- | legend_02 | + | ; legend_02 : about secret laboratories in the Zone |
- | legend_03 | + | ; legend_03 : legend of the guide |
- | legend_04 | + | ; legend_04 : legend of the Dark Stalker |
- | legend_05 | + | ; legend_05 : legend about not sleeping deep in the Zone |
- | + | ||
- | + | ||
===dont_spawn_loot section=== | ===dont_spawn_loot section=== | ||
- | + | All sorts of storyline characters might have to be empty after dying; for example: the wounded and the captive. To accomplish this, use the section: | |
+ | |||
+ | <source lang="ini"> | ||
[dont_spawn_loot] | [dont_spawn_loot] | ||
+ | </source> | ||
==Overrides== | ==Overrides== | ||
- | Settings | + | Settings that modify behavior of general schemes, depending on the currently active scheme (all optional). |
- | + | ||
- | + | ; meet_enabled = true | |
- | + | : fire a flare for a metting | |
- | + | ; meet_talk_enabled = true | |
- | + | : adds a possibility of a dialog to the current scheme | |
- | + | ; meet_dialog = <dialog name> | |
- | + | : dialog to fire on use | |
- | + | ; meet_state = <state name> | |
- | + | : sets the character's state for when a dialog opens | |
- | + | ; wounded_enabled = true | |
+ | : enables the NPC to use the <tt>wounded</tt> scheme | ||
+ | ; combat_ignore_cond | ||
+ | : see above | ||
+ | ; combat_ignore_keep_when_attacked = true | ||
+ | : the character ignores combat, even if shot at (but only if shot at by the player!) | ||
+ | ; combat_type = {condition} scheme | ||
+ | : combat type to be used NPCs from this scheme | ||
+ | ; on_combat | ||
+ | : see above | ||
+ | ; companion_enabled = true | ||
+ | : free stalkers will join you as companions (will also charge for it in future) | ||
==Monster schemes== | ==Monster schemes== | ||
Line 693: | Line 814: | ||
===mob_walker scheme=== | ===mob_walker scheme=== | ||
- | + | Works the same way as the regular walker, except for a few differences: | |
+ | |||
+ | <tt>path_walk</tt> flags: | ||
+ | ; s=sound scheme | ||
+ | : (idle, eat, attack, attack_hit, take_damage, die, threaten, steal, panic, growling) | ||
+ | ; с | ||
+ | : crouch from then on | ||
+ | ; r | ||
+ | : run | ||
+ | ; sig=signal_name | ||
+ | : set the given signal for <tt>xr_logic</tt> | ||
+ | |||
+ | <tt>path_look</tt> flags: | ||
+ | ; t=time | ||
+ | : time to wain in milliseconds while looking at a point | ||
+ | ; a=anim_set | ||
+ | : animation (stand_idle, sit_idle, lie_idle, eat, sleep, rest, attack, look_around, turn) | ||
+ | |||
+ | In custom data set: | ||
+ | |||
+ | '''[walker]''' | ||
+ | ; path_walk | ||
+ | ; path_look | ||
+ | ; no_reset = true/false | ||
+ | : (required) do not reset the action of the previous scheme (sound, for instance); false by default | ||
+ | ; actor_friendly = true/false | ||
+ | : (required) the monster never attacks first, although if the monster is attacked by the player, this flags is disabled; false by default | ||
+ | ; npc_friendly = true/false | ||
+ | : (required) the monster never attacks first, even if the player is hostile | ||
+ | ; friendly = true/false | ||
+ | : (required) the monster does not attack the player or other monsters. If they act aggressive, remembers them as enemeies and remains friendly to all; false by default | ||
- | Флаги пути движения | ||
- | s=звуковая_схема (idle, eat, attack, attack_hit, take_damage, die, threaten, steal, panic, growling) с - идти дальше в присяде r - дальше бежать sig=signal_name - установить заданный сигнал для xr_logic | ||
- | Флаги пути обзора: | ||
- | t=время_мсек - время в миллисекундах, которое нужно ждать, смотря в точку a=anim_set - анимация (stand_idle, sit_idle, lie_idle, eat, sleep, rest, attack, look_around, turn) | ||
- | В customdata персонажа задайте (* отмечены обязательные поля): | ||
- | [walker] | ||
- | path_walk = путь перемещения | ||
- | path_look = путь обзора | ||
- | *no_reset = true/false - не сбрасывать action предыдущей схемы (если нужно сохранить, например, звук). По умолчанию false. | ||
- | *actor_friendly = true/false - монстр никогда первым не нападает на игрока, но если игрок хоть раз атакует монстра - этот режим навсегда отключится. По умолчанию false. | ||
- | *npc_friendly = true/false - монстр никогда первым не нападет на другого монстра (даже враждебного). | ||
- | *friendly = true/false - монстр не нападает ни на игрока, ни на монстров. В случае агрессии с их стороны, не запоминает их как врагов и остается дружественным ко всем. По умолчанию false. | ||
File: \gamedata\scripts\mob_walker.script | File: \gamedata\scripts\mob_walker.script | ||
- | + | You can also control the bloodsucker's invisibility: | |
- | [mob_walker] | + | |
+ | '''[mob_walker]''' | ||
... | ... | ||
- | state = vis | + | ; state = vis |
- | + | or | |
- | state = invis | + | ; state = invis |
- | + | ||
- | + | Also, the flag <tt>b</tt> (behavior) can be used in a mod_walker's path with the same parameters: | |
- | ( | + | |
+ | <source lang="ini"> | ||
wp00|b=vis | wp00|b=vis | ||
wp00|b=invis | wp00|b=invis | ||
+ | </source> | ||
===mob_eluder scheme=== | ===mob_eluder scheme=== | ||
- | + | The monster moves along the patrol waypoints (without considering connections between points), keeping at a distance from the player, keeping its course, exiting the scheme upon getting too close to the player and returning back when the distance increases. | |
- | path | + | |
- | + | ; path | |
- | + | : works as <tt>path_walk</tt> | |
- | + | ; Time_capture | |
- | + | : (required) the time in seconds the monster spends in this scheme; 10 by default | |
- | + | ; Time_release | |
+ | : (required) the time in seconds the monster spends in the all-purpose scheme; 10 by default | ||
+ | ; Min_dist | ||
+ | : (required) distance in meters under which the monster switches to the all-purpose scheme; 5 by default | ||
+ | ; Max_dist | ||
+ | : (required) distance in meters over which the monster switches to the eluder scheme; 10 by default | ||
+ | |||
+ | Note: unstable. | ||
+ | |||
File: \gamedata\scripts\mob_eluder.script | File: \gamedata\scripts\mob_eluder.script | ||
===mob_remark scheme=== | ===mob_remark scheme=== | ||
- | + | Remarking scheme, but for monsters, not stalkers. | |
+ | |||
+ | ; state | ||
+ | : a specific state for the given monster (invisibility for a bloodsucker) | ||
+ | ; dialog_cond = {+info, =func, -info, !func} | ||
+ | : conditions for opening a dialog | ||
+ | ; anim | ||
+ | : comma-separated list of monster's animations | ||
+ | ; anim.head | ||
+ | : comma-separated list of head animations | ||
+ | ; tip | ||
+ | : which symbol is highlighted when the cursor is over it | ||
+ | ; snd | ||
+ | : which sound it emits | ||
+ | ; time | ||
+ | : animation playback time, used only for debugging | ||
+ | |||
+ | File: \gamedata\scripts\mob_remark.script | ||
- | + | The trader is made using this scheme. | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
===mob_combat, mob_death schemes=== | ===mob_combat, mob_death schemes=== | ||
- | + | Works exactly the same way as the corresponding schemes for stalkers. | |
Files: \gamedata\scripts\mob_combat.script, \gamedata\scripts\mob_death.script | Files: \gamedata\scripts\mob_combat.script, \gamedata\scripts\mob_death.script | ||
Line 755: | Line 913: | ||
===mob_jump scheme=== | ===mob_jump scheme=== | ||
- | + | Serves to make monsters jump without any checks and limitations (such as distance, angle). Position is set with a patrol path, offset and the physical jump factor. | |
Example: | Example: | ||
Line 770: | Line 928: | ||
</source> | </source> | ||
- | path_jump | + | ; path_jump |
- | offset | + | : path, wich which we set 1 target jump point (with zero index). The real point accounts for the position <tt>path_jump[0] + offset</tt>. |
- | ph_jump_factor | + | ; offset |
+ | : displacement along axes x,y,z, with which the a real point in space is set (might not be located at an AI node) | ||
+ | ; ph_jump_factor | ||
+ | : affects jump timing. Visually, it sets the curve of the jump. The higher it is, the sharper and faster the jump. This scheme allows creating a jump from one roof to another, jumping out a window, jumping over a barrier, etc. 1.8 by default | ||
- | + | Note: <tt>mob_jump</tt> is more of an action than a state. When a monster switches into it, it turns in the direction of the jump and jumps, raising the signal <tt>jumped</tt>. That is, <tt>on_signal=jumped|<scheme name or nil></tt> is a necessary parameter in the scheme, so that it is known what to transition to next. | |
- | + | ||
- | + | The first point of the path (0 index) is used to pick the position. | |
===Mob_camp=== | ===Mob_camp=== | ||
- | + | Mechanic: | |
- | # | + | # Crouches, looks at a point. |
- | # | + | # Can set several positions and times of changing position. |
- | # | + | # Runs between positions. |
- | # | + | # Switches to an all-purpose scheme (combat, panic) at the sight of an enemy. |
- | # | + | # Minimum and maximum distances from the enemy to the current camp position are set. |
- | # | + | # If the enemy walks away too far, the monster returns to position. |
- | + | Usage: | |
<source lang="ini"> | <source lang="ini"> | ||
Line 795: | Line 956: | ||
[mob_camp] | [mob_camp] | ||
- | path_look = way_look | + | path_look = way_look |
- | path_home = way_home | + | path_home = way_home |
time_change_point = 30000 | time_change_point = 30000 | ||
- | home_min_radius | + | home_min_radius = 20 |
- | home_max_radius = 50 | + | home_max_radius = 50 |
</source> | </source> | ||
- | skip_transfer_enemy | + | ; skip_transfer_enemy |
+ | : if this is added to custom data, the monster will not get an enemy from other monsters, if sees him (monsters have to be in different groups for this) | ||
- | + | Parameters: | |
- | + | ; path_home | |
- | path_look | + | : path consisting of the monster's locations |
- | + | ; path_look | |
- | + | : path consisting of locations for the monster to look at | |
- | + | ; time_change_point | |
+ | : time in milliseconds to change the current camp point; 10000 by default | ||
+ | ; home_min_radius | ||
+ | : minimum radius in meters from the enemy to the camp point; 30 by default | ||
+ | ; home_max_radius | ||
+ | : maximum radius in meters from the enemy to the camp point; 40 by default | ||
+ | |||
+ | Special features: | ||
+ | |||
+ | Minimum and maximum radii are necessary for ignoring enemies that run too far away to return to the current position. The enemy's distance to the current position is considered. If the distance is greater than <tt>home_min_radius</tt>, attack the enemy until the enemy disappears or distance exceeds <tt>home_max_radius</tt>. Two distances are needed to avoid the situation in which the player stands on the border of the radius and enters/exits the zone, and makes the monster run off and back. | ||
+ | * the current position is chosen randomly | ||
+ | * <tt>path_home</tt> and <tt>path_look</tt> path indices must coincide (monster sits at a point of <tt>path_home</tt> and looks at a point of <tt>path_look</tt>) | ||
- | + | The only required parameter is <tt>path_look</tt>. If <tt>path_home</tt> is not set, then the current node and the object's spawn node are concidered. | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | To make the monster look in different points at a camp position, path_look can consist of several points. | |
- | + | ||
- | + | Requirements: | |
+ | * <tt>home_min_radius</tt> < <tt>home_max_radius</tt> | ||
+ | * <tt>path_look</tt> and <tt>path_home</tt> must have equal number points | ||
- | + | P.S.: <tt>mob_camp</tt> can be used as an alternative to monsters under restrictors | |
- | + | ||
- | + | ||
- | P.S. | + | |
===Mob_home=== | ===Mob_home=== | ||
- | + | This scheme is another way to replace restrictors. I recommend to make all monster gulags with <tt>mob_home</tt>. | |
Example: | Example: | ||
Line 840: | Line 1,007: | ||
</source> | </source> | ||
- | aggressive_home | + | ; aggressive_home |
+ | : monsters run, not walk towards the designated <tt>path_home</tt> | ||
- | + | Monsters keep the <tt>path_home</tt> points. They attack an enemy if the enemy is within the home_min radius, otherwise hide. This implies that <tt>home_min</tt> should be made such that there would be enough covers inside. In idle they typically also go to cover. <tt>Home_max</tt> should be made like the largest restrictor in the "nest" scheme. | |
- | + | Added the ability to set minimum and maximum radius for the <tt>mob_home</tt> scheme in flags of the first point (<tt>path_home</tt>). Flags <tt>minr</tt> and <tt>maxr</tt> have been added for this purpose. In case radii are set both in the section and in the flags, the radius is taken from the section. Is neither is set, the values 20 and 40 are used, respectively. | |
- | + | ||
- | + | ||
===Mob_fake_death=== | ===Mob_fake_death=== | ||
Line 866: | Line 1,032: | ||
==Monster overrides== | ==Monster overrides== | ||
- | + | ; actor_friendly | |
- | + | : if true, the monster does not attack the player until attacked first | |
- | + | ; npc_friendly | |
- | + | : if true, does not attach the player or other monsters until attacked first | |
+ | ; friendly | ||
+ | : if true, does not attack anyone until attacked first | ||
+ | ; braindead | ||
+ | : if true, ignores all attacks | ||
+ | |||
+ | Monster sections: | ||
- | Секции для монстров | ||
[mob_death], [mob_hit] | [mob_death], [mob_hit] | ||
==spawner section== | ==spawner section== | ||
- | + | This section, which both NPCs and monsters have, spawns them (makes online) with a given codition. To make them appear in a given point, they should have the flag <tt>no_move_in_offline</tt> in the level editor and <tt>can_switch_offline</tt> should be off. The spawner is added to custom data before the <tt>logic</tt> section. It works like this: | |
- | + | ||
<source lang="ini"> | <source lang="ini"> | ||
Line 884: | Line 1,054: | ||
</source> | </source> | ||
- | + | Note: if the spawn condition is not met, the object is not spawned, but if it has been spawned and the condition stops being met, the object will be made offline by the spawner. | |
Example: | Example: | ||
Line 890: | Line 1,060: | ||
<source lang="ini"> | <source lang="ini"> | ||
[spawner] | [spawner] | ||
- | cond = {=is_day} ; | + | cond = {=is_day} ; object spawns during the day and moves into offline during the night |
</source> | </source> | ||
- | + | After the object is spawned, it is taken under control by the <tt>logic</tt> script. | |
===Spawning day and night monsters=== | ===Spawning day and night monsters=== | ||
- | + | '''[spawner]''' | |
- | [spawner] | + | ; cond = {=is_day} |
- | cond = {=is_day} | + | : only spawn the monster at day; to make it night only, write !is_day |
- | check_distance = true ; | + | ; check_distance = true |
- | min_distance = 100 | + | : check to see if the player is nearby |
- | + | ; min_distance = 100 | |
+ | : do not spawn if the player is closer than this (150 by default, but this is really too much) | ||
- | == | + | ==Logic script== |
- | + | ===Overview=== | |
- | + | :''Note: If you want to spawn some object for an NPC from custom data, the description for this is in the "general" section of character profile settings (do not write the <tt>supplies</tt> tag!)'' | |
- | + | ||
- | + | Script <tt>logic</tt> controls scheme switching. Customdata for every character (except the free ones) must have a <tt>[logic]</tt> section. | |
- | + | Functions references by the <tt>[logic]</tt> section must be placed in files \gamedata\scripts\xr_effects.script or \gamedata\scripts\xr_conditions.script. | |
- | + | ||
- | + | ||
- | + | The section must contain one of the fields: | |
- | + | ; active | |
+ | : the active scheme to be ran first | ||
+ | ; cfg | ||
+ | : name of the [[Ltx]] file with settings | ||
+ | If <tt>cfg</tt> is set, then the file contents will be used for the character's settings. For example, settings of a regular walker: | ||
+ | |||
+ | <source lang="ini"> | ||
[logic] | [logic] | ||
active = walker | active = walker | ||
Line 926: | Line 1,100: | ||
path_walk = walk1 | path_walk = walk1 | ||
path_look = look1 | path_look = look1 | ||
+ | </source> | ||
- | + | Scheme switching is carried out with the additional conditions of the <tt>logic</tt> scheme, which are set in the section of the current active scheme. There exist the following switch conditions: | |
- | + | ||
- | + | ||
- | + | : Note: If logic switches between several schemes having the same names (such as several walkers), then they can be numbered (walker1, walker2) or more informative names can be given after @ (walker@day, walker@alarm). | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ; on_actor_dist_le = number | scheme | |
- | on_info = {....} %...% | + | : distance to the player <= <tt>number</tt> |
+ | ; on_actor_dist_le_nvis = number | scheme | ||
+ | : distance to the player <= <tt>number</tt> without a visibility check | ||
+ | ; on_actor_dist_ge = number | scheme | ||
+ | : distance to the player > <tt>number</tt> | ||
+ | ; on_actor_dist_ge_nvis = number | scheme | ||
+ | : distance to the player > <tt>number</tt> without a visibility check | ||
+ | ; on_signal = signal | scheme | ||
+ | : fires on signal from the active scheme | ||
+ | ; on_info = scheme | ||
+ | : always fires | ||
+ | ; on_timer = msec | scheme | ||
+ | : fires after the given number of ms after the scheme becomes active | ||
+ | ; on_game_timer = sec| scheme | ||
+ | : fires after the given number of game seconds after the scheme becomes active | ||
+ | ; on_actor_in_zone = restrictor_name | scheme | ||
+ | : if the actor is in the zone (restrictor name is given) | ||
+ | ; on_actor_not_in_zone = restrictor_name | scheme | ||
+ | : if the actor is not in the zone (restrictor name is given) | ||
+ | ; on_npc_in_zone = npc_story_id | restrictor_name | scheme | ||
+ | : if an NPC is in the zone (NPC id and restrictor name is given) | ||
+ | ; on_npc_not_in_zone = npc_story_id | restrictor_name | scheme | ||
+ | : if an NPC is not in the zone (NPC id and restrictor name is given) | ||
+ | ; on_actor_inside = scheme | ||
+ | : the zone checks if the player is inside | ||
+ | ; on_actor_outside = scheme | ||
+ | : the zone checks if teh player is outside | ||
+ | |||
+ | You can work with any of the parameters listed above like this: | ||
+ | |||
+ | <source lang="ini"> | ||
+ | on_info = {....} %...% | ||
on_info2 = {....} %...% | on_info2 = {....} %...% | ||
on_info3 = {...} %...% | on_info3 = {...} %...% | ||
- | + | </source> | |
- | + | And so on. | |
+ | |||
+ | You can also use conditions: | ||
+ | |||
+ | <source lang="ini"> | ||
combat_ignore_cond = | combat_ignore_cond = | ||
- | on_hit = | + | on_hit = |
- | on_death = | + | on_death = |
- | on_combat = | + | on_combat = |
- | on_use = | + | on_use = |
+ | </source> | ||
===Logic script syntax=== | ===Logic script syntax=== | ||
- | Example: | + | Example: to make a character walk along the path <tt>walk1</tt>, but switch to path <tt>walk2</tt> when the player comes within the distance of 5 meters (given that he sees the player), you should write the following: |
<source lang="ini"> | <source lang="ini"> | ||
Line 968: | Line 1,164: | ||
[walker1] | [walker1] | ||
- | path_walk = walk1 | + | path_walk = walk1 |
- | path_look = look1 | + | path_look = look1 |
on_actor_dist_le = 5 | walker2 | on_actor_dist_le = 5 | walker2 | ||
Line 977: | Line 1,173: | ||
</source> | </source> | ||
- | + | That was unconditional section switching. Before the section name in curly braces {} you can set additional conditions, and after the section name the so-called "effects", which should be enclosed between percent signs %%. Effects will be applied only in case a section is activated. You can omit section name and only set conditions and/or effects. Then only the old section will remain active, but the conditions and effects will nevertheless be processed. If all conditions in curly braces fail, the section will not be activated. | |
Example: | Example: | ||
<source lang="ini"> | <source lang="ini"> | ||
- | on_actor_dist_le = 5 | {условие} walker2 % | + | on_actor_dist_le = 5 | {условие} walker2 %effects% |
</source> | </source> | ||
- | + | You can have the following conditions: | |
- | + | ; +infoportion | |
- | + | : the actor must have the infoportion | |
- | + | ; -infoportion | |
- | + | : the actor must not have the infoportion | |
+ | ; =func | ||
+ | : the function must return <tt>true</tt> | ||
+ | ; !func | ||
+ | : the function must return <tt>false</tt> | ||
- | + | You can have the following effects: | |
- | + | ; +infoportion | |
- | + | : the actor will get this infoportion | |
- | + | ; -infoportion | |
+ | : the actor will loose this infoportion | ||
+ | ; =func | ||
+ | : the function will be executed | ||
- | + | Several conditions or effects should be separated with spaces: | |
+ | <source lang="ini"> | ||
on_actor_dist_le = 5 | {+info1 -info2 +info3} walker2 %+info4 =func% | on_actor_dist_le = 5 | {+info1 -info2 +info3} walker2 %+info4 =func% | ||
+ | </source> | ||
- | + | You can set several sections separated by commas. They will be hanled from left to right. After the first condition fires, the handling stops. In the example below, if <tt>info1</tt> is set, then <tt>walker2</tt> is enabled, if <tt>info2</tt> is set, then <tt>walker2</tt>, otherwise <tt>walker4</tt>: | |
+ | <source lang="ini"> | ||
on_actor_dist_le = 5 | {+info1} walker2, {+info2} walker3, walker4 | on_actor_dist_le = 5 | {+info1} walker2, {+info2} walker3, walker4 | ||
+ | </source> | ||
- | + | You can calso set conditions in the above field <tt>active</tt> of section <tt>logic</tt>, such us: | |
<source lang="ini"> | <source lang="ini"> | ||
Line 1,013: | Line 1,220: | ||
</source> | </source> | ||
- | + | You can use the keyword <tt>never</tt> in logic sections, which means that the condition is false. For example: | |
- | + | ||
- | + | <source lang="ini"> | |
+ | combat_ignore_cond = {=actor_enemy =actor_has_suit} always, {=actor_enemy} never %...effects...% | ||
+ | </source> | ||
+ | |||
+ | The above section enables combat ignoring if the NPC's enemy is the player is wearing a suit, but disables it if the player is not wearing suit. In this case the effects of the <tt>never</tt> section will work. Choosing the <tt>never</tt> section is equivalent to not having a section, but effects between percentage signs work. | ||
- | + | Here is an example of work with the <tt>nil</tt> section. The <tt>nil</tt> section takes a character, monster, or object from under a scripted scene and puts him in the engine's control. This is necessary if some condition does not need to be checked again after firing off once. This saves resources that would otherwise be wasted on checking the condition. | |
<source lang="ini"> | <source lang="ini"> | ||
Line 1,028: | Line 1,238: | ||
</source> | </source> | ||
- | + | That is, after the actor enters the restrictor, he gets an infoportion, and the restrictor moves into the <tt>nil</tt> section, not checking for the player anymore. | |
- | + | ||
- | + | ''Note: scripts cannot be returned from the <tt>nil</tt> section!'' | |
===An example of fairly complex logic=== | ===An example of fairly complex logic=== | ||
Line 1,036: | Line 1,246: | ||
<source lang="ini"> | <source lang="ini"> | ||
[logic] | [logic] | ||
- | active = walker | + | active = walker |
combat_ignore = combat_ignore | combat_ignore = combat_ignore | ||
- | on_hit = hit | + | on_hit = hit |
- | on_death = death | + | on_death = death |
[hit] | [hit] | ||
Line 1,048: | Line 1,258: | ||
[walker] | [walker] | ||
- | path_walk = walk_svoboda3 | + | path_walk = walk_svoboda3 |
- | path_look = look_svoboda3 | + | path_look = look_svoboda3 |
combat_ignore_cond = {-alert} | combat_ignore_cond = {-alert} | ||
- | on_timer = 25000 | remark | + | on_timer = 25000 | remark |
[remark] | [remark] | ||
- | anim = idle | + | anim = idle |
- | snd = stalker_talk_kampfire | + | snd = stalker_talk_kampfire |
- | no_move = true | + | no_move = true |
- | no_rotate = true | + | no_rotate = true |
- | on_hit = hit | + | on_hit = hit |
- | on_death = death | + | on_death = death |
combat_ignore_cond = {-alert} | combat_ignore_cond = {-alert} | ||
Line 1,065: | Line 1,275: | ||
</source> | </source> | ||
- | + | Lets look at this step by step. At first, the stalker works according to the <tt>walker</tt> scheme. While at it, he ignores combat until the <tt>alert</tt> infoportion is set. Then he waits 25 seconds and switches to the <tt>remark</tt> scheme. In <tt>remark</tt> he plays an idle animation, chats on specified subjects, does not turn, does not move, still ignores combat. If he is hit or killed (<tt>on_death</tt>), he will get an <tt>alert</tt> infoportion and stops ignoring combat (obviously, if he is a corpse, that won't help, but there are three of them on the scene, and then the rest will spring into action). If he is killed, he will also get a <tt>trup3</tt> infoportion, which will announce that this stalker is dead. | |
- | + | Now, here is his opponent's logic: | |
<source lang="ini"> | <source lang="ini"> | ||
[logic] | [logic] | ||
- | active = walker | + | active = walker |
combat_ignore = combat_ignore | combat_ignore = combat_ignore | ||
[walker] | [walker] | ||
- | path_walk = soldier_walk1 | + | path_walk = soldier_walk1 |
- | path_look = soldier_look1 | + | path_look = soldier_look1 |
combat_ignore_cond = always | combat_ignore_cond = always | ||
- | team = assault_group | + | team = assault_group |
- | on_signal = assault | camper | + | on_signal = assault | camper |
[camper] | [camper] | ||
path_walk = soldier_walk1_2 | path_walk = soldier_walk1_2 | ||
path_look = soldier_look1_2 | path_look = soldier_look1_2 | ||
- | radius = 5 | + | radius = 5 |
- | on_info = {+trup1 +trup2 +trup3} walker2 | + | on_info = {+trup1 +trup2 +trup3} walker2 |
[walker2] | [walker2] | ||
Line 1,094: | Line 1,304: | ||
</source> | </source> | ||
- | + | He is in the <tt>walker</tt> scheme, ignores combat (in any situation, by the way). He is part of the <tt>assault_group</tt>. When he comes to the endpoint of his route (where he is synchronized with the rest of the group, as is specified in the paths) he gets the <tt>assault</tt> signal and switches to the <tt>camper</tt> scheme. In this scheme he does not have <tt>combat_ignore</tt> specified and, therefore, starts shooting at the enemy. After all three oppponents are dead, with them setting infoportions <tt>trup1</tt>, <tt>trup</tt>, and <tt>trup3</tt> upon dying, he switches to <tt>walker2</tt> (goes to the campfire). | |
==space_restrictor logic scheme== | ==space_restrictor logic scheme== | ||
- | + | General comment: to avoid situations, in which the actor rushes through a restrictor before it goes off, try to make restrictors at least 2 meters wide. | |
===[sr_idle] scheme=== | ===[sr_idle] scheme=== | ||
- | + | ||
- | + | The purpose of this scheme is to switch to another scheme when one of the standard logic conditions is met. It does not do anything on its own. Example of a restrictor's settings: | |
- | + | ||
<source lang="ini"> | <source lang="ini"> | ||
Line 1,113: | Line 1,322: | ||
</source> | </source> | ||
- | + | Note that when the check goes off, the active scheme switches to <tt>nil</tt>, so that it does not continue the useless check on each update. You do not have to set <tt>nil</tt>. Often this scheme works together with a spawner. The restrictor gives out an infoportion upon entry into the zone, and the spawner uses it to spawn something. | |
- | + | ||
- | + | File \gamedata\scripts\sr_idle.script | |
===[sr_no_weapon] scheme=== | ===[sr_no_weapon] scheme=== | ||
- | + | This scheme removes the player's weapon uponn entry into its zone. Example of a restrictor's settings: | |
- | + | ||
+ | <source lang="ini"> | ||
[logic] | [logic] | ||
active = sr_no_weapon | active = sr_no_weapon | ||
+ | </source> | ||
- | [sr_no_weapon] | + | '''[sr_no_weapon]''' |
- | + | File \gamedata\scripts\sr_no_weapon.script | |
===[sr_sound] scheme=== | ===[sr_sound] scheme=== | ||
- | snd = | + | ; snd |
+ | : comma-separated list of all sound names | ||
+ | ; type | ||
+ | : comma separated list of sound types. For convenience, sound sets were introduced. For instance, to avoid listing the full set of wood floor sound types, you can specify <tt>floor_wooden</tt>. | ||
+ | ; delay | ||
+ | : delay before playing the sounds in seconds of real time; 0 by default | ||
+ | ; idle | ||
+ | : duration of time to ignore entry into the zone after the last sound begins. For instance, to make sure howling is no more frequent than once every few minutes. In seconds of real time. 0 by default. | ||
+ | ; rnd | ||
+ | : percent probability of playing the sound; 100 by default | ||
+ | ; position | ||
+ | : name of the path the points of which to play the sound at. Could be <tt>random</tt>, meaning a random place in the radius of 15-50 meters of the player. If this parameter is not set, then the player's position is assumed. | ||
+ | ; slide_velocity | ||
+ | : speed of movement of the sound along the path; 3 by default | ||
+ | ; slide_sound_once = true\false | ||
+ | : true - play the sound once, even if it does not reach the last point | ||
+ | : false – if the sound has ended, but not reached the last point, play it again | ||
+ | : false by default | ||
+ | ; play_at_actor = true/false | ||
+ | : forces the sound play continuosly at actor's location. If this is true and the path is set (or is random) the game will crash. | ||
- | + | This scheme is meant to be used to play sounds at the actor's entrance in a restrictor. | |
- | + | Supports <tt>sound_end</tt>. | |
- | + | You must set either <tt>snd</tt> or <tt>type</tt>. You can set both. The list of sounds is created based on these parameters. When the actor enters a restrictor, a random sound from this list is played. | |
- | + | Example: | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
+ | <source lang="ini"> | ||
[logic] | [logic] | ||
active = sr_sound | active = sr_sound | ||
[sr_sound] | [sr_sound] | ||
- | type = floor_wooden | + | type = floor_wooden |
- | snd = ambient\wind1, ambient\sparks1 | + | snd = ambient\wind1, ambient\sparks1 |
- | rnd = 50 | + | rnd = 50 |
position = random | position = random | ||
- | idle = 120 | + | idle = 120 |
- | delay = 3 | + | delay = 3 |
+ | </source> | ||
- | + | You can make a "sliding" sound. You need a patrol path. The sound will start playing at the beginning of the path and move from one point to another (in the order they are set in the path) with the speed <tt>slid_velocity</tt>. | |
+ | <source lang="ini"> | ||
[logic] | [logic] | ||
active = sr_sound | active = sr_sound | ||
[sr_sound] | [sr_sound] | ||
- | type = random | + | type = random |
- | position = way | + | position = way |
- | slide_velocity = 8 | + | slide_velocity = 8 |
slide_sound_once = true | slide_sound_once = true | ||
+ | </source> | ||
- | + | File \gamedata\scripts\sr_sound.script | |
===[sr_tip] scheme=== | ===[sr_tip] scheme=== | ||
- | + | The purpose of this scheme is to give the player a tip on entry into a restrictor. | |
- | name | + | ; name |
- | type | + | : news name |
- | + | ; type | |
- | + | : <tt>news</tt> to send as global news, <tt>tips</tt> to send with the sender's name; <tt>news</tt> by default | |
+ | ; sender | ||
+ | : if <tt>type</tt> is <tt>tips</tt> then this is the string identifier of the sender character's icon; the dealer's icon by default | ||
+ | ; cond | ||
+ | : condition for firing; set to entry into the restrictor by default | ||
+ | ; single = true/false | ||
+ | : whether the tip should only be given once; <tt>false</tt> by default | ||
- | + | Example: | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
+ | <source lang="ini"> | ||
[logic] | [logic] | ||
active = sr_tip | active = sr_tip | ||
[sr_tip] | [sr_tip] | ||
- | name = tips_esc_trader_about_pda | + | name = tips_esc_trader_about_pda |
- | type = tips | + | type = tips |
- | cond = {+infoportion1 –infoportion2 } | + | cond = {+infoportion1 –infoportion2 } |
- | + | showtime = msec ; time in seconds the tip will be displayed for; does not work properly | |
+ | </source> | ||
- | + | If it should be played only once, and this happens often, you can add the following line: | |
+ | |||
+ | <source lang="ini"> | ||
on_actor_inside = nil | on_actor_inside = nil | ||
+ | </source> | ||
- | + | File \gamedata\scripts\sr_tip.script | |
===Sr_light=== | ===Sr_light=== | ||
- | + | Zone in which NPCs turn on their flashlights no matter what time of day it is. | |
- | + | Works like this: | |
<source lang="ini"> | <source lang="ini"> | ||
Line 1,229: | Line 1,445: | ||
[sr_light] | [sr_light] | ||
- | light_on = true/false | + | light_on = true/false |
</source> | </source> | ||
- | + | Also works with a condition list: | |
<source lang="ini"> | <source lang="ini"> | ||
Line 1,239: | Line 1,455: | ||
[sr_light] | [sr_light] | ||
- | light_on = true/false | + | light_on = true/false |
- | on_info = {+info1} section %+info2% | + | on_info = {+info1} section %+info2% |
</source> | </source> | ||
===Sr_territory=== | ===Sr_territory=== | ||
- | + | Catches various events within a restrictor. | |
- | + | ||
+ | Right now, it only catches hits and stalker deaths. It can be used somewhat like this: | ||
<source lang="ini"> | <source lang="ini"> | ||
Line 1,262: | Line 1,479: | ||
</source> | </source> | ||
- | + | You can see that when the player is inside the restrictor, the number of hits is counted, and also whether anyone died is considered. Since the scheme only works with the player, only the player's death and hits are counted. | |
===Sr_mapspot=== | ===Sr_mapspot=== | ||
- | + | When entering a restrictor, it highlights itself on the map. | |
- | + | Parameters: | |
- | + | ||
- | + | ; hint | |
+ | : hint id in string table (required) | ||
+ | ; location | ||
+ | : highlight type name; <tt>crlc_small</tt> by default | ||
Example: | Example: | ||
Line 1,279: | Line 1,499: | ||
[sr_mapspot] | [sr_mapspot] | ||
- | hint = “gar_swamp” | + | hint = “gar_swamp” |
location = crcl_big | location = crcl_big | ||
</source> | </source> | ||
Line 1,285: | Line 1,505: | ||
===Sr_particle=== | ===Sr_particle=== | ||
- | + | This scheme shows particles, static or moving, in the given place at the given time. It works like this: | |
- | + | ====For a particle system with a camera path==== | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | path | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | '''[sr_particle]''' | |
- | + | ; name = explosions\campfire_03 | |
+ | : particle system name | ||
+ | ; path = particle_test.anm | ||
+ | : camera path | ||
+ | ; mode = 1 | ||
+ | : (required !!!) | ||
+ | ; looped = true/false | ||
+ | : whether the partcle playback should loop | ||
+ | |||
+ | (must have extension ANM !!!) Here particles will silently move along a path. | ||
+ | |||
+ | ====For a particle system with a regular patrol path==== | ||
+ | |||
+ | '''[sr_particle]''' | ||
+ | |||
+ | ; name = explosions\campfire_03 | ||
+ | : particle system name | ||
+ | ; path = part_points | ||
+ | : patrol path name | ||
+ | ; mode = 2 | ||
+ | : (required !!!) | ||
+ | ; looped = true/false | ||
+ | : whether the particle playback should loop | ||
+ | |||
+ | You can set the <tt>s=<sound scheme name></tt> and <tt>d=<delay time in milliseconds></tt> at waypoints. A sound will be rendomly chosen from the specified scheme. Sound does not loop and plays only once. As a result, particles play in all waypoints simultaneously (with delay, as described above). | ||
+ | |||
+ | When <tt>looped=true</tt> particles will play again after finishing, but without a delay. There will be no <tt>particle_end</tt> signal. When <tt>looped=false</tt> there will be a signal when all particle sources finish playing. | ||
+ | |||
+ | Condition list is supported. If a restrictor switches to a different section, then particles stop playing automatically and their sounds die. This restrictor is an object tracking particles, and there is no reason for the player to enter it. | ||
===Sr_sound_act=== | ===Sr_sound_act=== | ||
- | + | Scheme playing sounds in the actor's head. Various PDA conversations and other fakes. | |
- | + | '''[sr_sound_act]''' | |
- | [sr_sound_act] | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ; snd = ambient\random\new_drone1 | |
+ | : sound file name | ||
+ | ; delay = 2000 | ||
+ | : delay before playback | ||
+ | ; delay_max = 4000 | ||
+ | : a random interval between <tt>delay</tt> and <tt>delay_max</tt> will be used | ||
+ | ; on_signal = sound_end | nil | ||
+ | : we can move to another section on signal | ||
+ | ; theme = < | ||
+ | : from <tt>ph_sound_themes</tt> | ||
+ | ; stereo = true/false | ||
+ | : When this parameter is set for a file that is set using the single parameter <tt>snd</tt>, the sound scheme will be automatically appended with suffexes <tt>_r</tt> and <tt>_l</tt> for left and right channels, and all that junk will be played; <tt>false</tt> by default | ||
- | + | If a theme is set, then the sound will loop, randomly choosing one of the sounds from the theme. If a sound is set, then it is played once. The scheme supports a condition list. | |
===Sr_timer=== | ===Sr_timer=== | ||
- | + | Example of use: | |
<source lang="ini"> | <source lang="ini"> | ||
Line 1,341: | Line 1,570: | ||
[sr_timer@1] | [sr_timer@1] | ||
- | type = dec | + | type = dec |
start_value = 10000 | start_value = 10000 | ||
- | on_value = 0 | sr_timer@2 | + | on_value = 0 | sr_timer@2 |
[sr_timer@2] | [sr_timer@2] | ||
- | type = inc | + | type = inc |
on_value = 15000 | nil %+info1% | on_value = 15000 | nil %+info1% | ||
</source> | </source> | ||
- | + | Fields: | |
- | + | ; type | |
- | + | : counter type: <tt>inc</tt> or <tt>dec</tt>; <tt>inc</tt> by default | |
- | + | ; start_value | |
+ | : starting value in REAL milliseconds. For decrementing counters, settings this is required. For incrementing it is 0 by default. | ||
- | + | Switches from section <tt>sr_timer</tt> can be caused by regular conditons (<tt>on_timer</tt>, <tt>on_info</tt>) or by the special condition <tt>on_value</tt>. In general, <tt>on_value</tt> should be used for performing some actions based on the counter's state. For example: | |
+ | <source lang="ini"> | ||
on_value = 5000| %+info1% | 1000| %+info2% | on_value = 5000| %+info1% | 1000| %+info2% | ||
+ | </source> | ||
===Sr_psy_antenna=== | ===Sr_psy_antenna=== | ||
- | + | Zones with this section can control psy-control effects (on Yantar and Radar). Right now you can control radiation intensity and hit intensity. | |
- | + | To use: set the zones, in each zone specify percentage increase/decrease for radiation and intensity. Zones can be nested inside each other and intersect each other. | |
- | + | ; eff_intensity | |
- | + | : increase or decrease % of radiation relative to base intensity | |
+ | ; hit_ intensity | ||
+ | : increase or decrease % of hits relative to base intensity | ||
- | + | Example of a zone that adds 70% of radiation: | |
<source lang="ini"> | <source lang="ini"> | ||
Line 1,376: | Line 1,610: | ||
[sr_psy_antenna] | [sr_psy_antenna] | ||
- | =_intensity | + | =_intensity = 70 |
hit_ intensity = 70 | hit_ intensity = 70 | ||
</source> | </source> | ||
- | + | Example of a zone that removes 30% of radiation: | |
<source lang="ini"> | <source lang="ini"> | ||
Line 1,392: | Line 1,626: | ||
===Sr_teleport=== | ===Sr_teleport=== | ||
- | + | A teleporter. Is configured like this: | |
<source lang="ini"> | <source lang="ini"> | ||
Line 1,402: | Line 1,636: | ||
point1 = point1 | point1 = point1 | ||
- | look1 = look1 | + | look1 = look1 |
- | prob1 = 10 | + | prob1 = 10 |
point2 = point2 | point2 = point2 | ||
- | look2 = look2 | + | look2 = look2 |
- | prob2 = 20 | + | prob2 = 20 |
</source> | </source> | ||
- | + | where: | |
- | timeout | + | ; timeout |
- | point - | + | : delay in milliseconds before the teleporter activates |
- | look - | + | ; point |
+ | : one-point patrol path to teleport into | ||
+ | ; look | ||
+ | : one-point patrol path to turn towards | ||
- | + | Settings for destination points with weights follow. That is, in the example above the probability of teleportation into the second point is twice as high as into the first. The maximum number of destination points is 10. Teleporters should be set together with a special anomalous zone. | |
===Sr_sleep and sleep configuration=== | ===Sr_sleep and sleep configuration=== | ||
- | + | Makes it possible to set sleep zones. | |
- | [sr_sleep] | + | '''[sr_sleep]''' |
- | + | ; cond = <condlist> | |
- | + | ; type = nightmare/normal/happy/all | |
- | + | : Sets the type of sleep allowed in the current zone; affects only non-storyline sleep; <tt>all</tt> by default | |
+ | ; dream_prob = <number 0 from 100> | ||
+ | : probability of non-storyline dreams in the given zone; 80 by default | ||
- | + | The optional field <tt>cond</tt> sets a condition for sleeping in this zone. There is currently an indicator for zones in which sleep is allwed. In bottom left corner a small lungs icon is shown upon entry into such a zone. This icon will possibly be replaced later. | |
- | + | ||
- | + | Dreamcast can be either storyline or not. Storline dreams are played when necessary conditions are met. Regular dreams are played when there is no storyline dreams or none of the conditions for them have been met. It is possible to set probabilty of playing regular dreams in general, and also set likelyhood of seening any given dream separately. Regular dreams can have set types, and types can be used to limit sleeps in <tt>sr_sleep</tt>. | |
- | + | Dream settings are set in file misc\dream.ltx | |
- | + | ||
- | + | ====Videos section==== | |
- | + | ||
- | + | ||
- | + | ||
- | + | Fields set paths to video fiels with dreams. | |
- | + | ||
- | + | ||
- | + | ||
- | + | ====Dreams section feilds==== | |
- | + | ||
- | + | ||
- | + | ||
- | = | + | ; regular_probability = <number from 0 to 100> |
+ | : probability of playing regular dreams in general | ||
+ | ; regular | ||
+ | : a list of sections with settings for regular dreams | ||
+ | ; scene | ||
+ | : a list of sections with settings for storyline dreams | ||
- | + | ====Settings for regular dreams==== | |
- | + | ||
- | + | ; dream | |
- | + | : name of a field from the <tt>videos</tt> section | |
- | + | ; probability = <number greater than 0> | |
- | + | ; type = nightmare/normal/happy | |
- | + | ||
- | + | ||
- | + | ||
- | == | + | ====Settings for storyline dreams==== |
- | + | ; dream | |
+ | : name of a field from the <tt>videos</tt> section | ||
+ | ; cond = <condlist> | ||
+ | ; to_regular = <probability, type> | ||
+ | : an optional field; gives you the ability to convert a storyline dream into a regular dream; <tt>probability</tt> and <tt>type</tt> are analogous to those for regular dreams | ||
- | === | + | ===Sr_cutscene=== |
- | + | This scheme is for animating camera with certain effects. | |
- | + | (pp_effector). Sequence of actions carried out by the scheme consists of immediate placement of the player into the beginning of that path and orientation of his sight towards the look path. The player looses control until <tt>cam_effector</tt> finishes. | |
- | + | ||
- | + | '''[sr_cutscene]''' | |
- | + | ; point = <path name> | |
+ | : path into the beginning of which the player is placed | ||
+ | ; look = <path name> | ||
+ | : path towards which the player faces | ||
+ | ; pp_effector = <effect filename> | ||
+ | : file located in folder gamedata\anims and containing an effect (filename is written without the extension) | ||
+ | ; cam_effector = <camera animation filename> | ||
+ | : file located in the folder gamedata\anims\camera_effects and containing a camera animation (filename is written without the extension) | ||
- | + | ==Various settings for objects== | |
- | + | ||
- | + | ===[ph_idle]=== | |
- | + | ||
- | + | A section for all physical objects. Supports a condlist. Could be used to transfer objects into when needed. | |
- | + | ===Doors, [ph_door] section=== | |
- | + | All folding doors work the same way. | |
- | + | ; locked = false\true | |
+ | : false by default | ||
+ | ; Closed = false\true | ||
+ | : true by default | ||
+ | ; tip_open = (if locked == false, then tip_door_open, else tip_door_locked) | ||
+ | : the tip that shows up when the door is targeted if the door is closed | ||
+ | ; tip_close = (if locked == false, then tip_door_close, else empty value) | ||
+ | : the tip that shows up when the door is targeted if the door is open | ||
+ | ; snd_init | ||
+ | : the sound that will be played when the scheme is initiated | ||
+ | ; snd_open_start | ||
+ | : the sound that will be played on attempts to open the door | ||
+ | ; snd_close_start | ||
+ | : the sound that will be played on attempts to close the door | ||
+ | ; snd_close_stop | ||
+ | : the sound that will be played when the door is closed shut | ||
- | + | Example: | |
- | + | ||
+ | If you need to make a door that will open with a click on some event, then you can use the <tt>snd_init</tt> field and switching schemes. In this example, when the <tt>ph_door@unlocked</tt> is iniated, the <tt>snd_init</tt> sound is played, that is, <tt>trader_door_unlock</tt>: | ||
+ | |||
+ | <source lang="ini"> | ||
[logic] | [logic] | ||
active = ph_door@locked | active = ph_door@locked | ||
[ph_door@locked] | [ph_door@locked] | ||
- | locked = true | + | locked = true |
snd_open_start = trader_door_locked | snd_open_start = trader_door_locked | ||
- | on_info = {+esc_trader_can_leave} ph_door@unlocked | + | on_info = {+esc_trader_can_leave} ph_door@unlocked |
[ph_door@unlocked] | [ph_door@unlocked] | ||
- | locked = false | + | locked = false |
- | snd_init = trader_door_unlock | + | snd_init = trader_door_unlock |
- | snd_open_start = trader_door_open_start | + | snd_open_start = trader_door_open_start |
snd_close_start = trader_door_close_start | snd_close_start = trader_door_close_start | ||
- | snd_close_stop = trader_door_close_stop | + | snd_close_stop = trader_door_close_stop |
- | + | </source> | |
+ | |||
+ | File \gamedata\scripts\ph_door.script | ||
===Buttons, [ph_button] section=== | ===Buttons, [ph_button] section=== | ||
- | + | When you press a button, this switches sections and gives out an infoportion. | |
+ | <source lang="ini"> | ||
[logic] | [logic] | ||
- | active | + | active = ph_button@locked |
[ph_button@locked] | [ph_button@locked] | ||
Line 1,520: | Line 1,777: | ||
anim = button_false | anim = button_false | ||
on_press = ph_button@unlocked %+cit_jail_door_opened% | on_press = ph_button@unlocked %+cit_jail_door_opened% | ||
+ | </source> | ||
- | on_press | + | ; on_press |
- | anim | + | : what happens when the button is pressed |
- | anim_blend | + | ; anim |
+ | : animation to play when the button is pressed | ||
+ | ; anim_blend | ||
+ | : smooth animation | ||
- | + | File \Gamedata\scripts\ph_button.script | |
- | + | ; tooltip | |
- | + | : is there to show a textual hint when the button is targeted. The hint is needed to at least explain that it can be presseed. | |
+ | Example: | ||
+ | |||
+ | <source lang="ini"> | ||
[logic] | [logic] | ||
active = ph_button@active | active = ph_button@active | ||
[ph_button@active] | [ph_button@active] | ||
- | anim = lab_switcher_idle | + | anim = lab_switcher_idle |
- | tooltip = tips_labx16switcher_press | + | tooltip = tips_labx16switcher_press |
on_press = ph_button@deactivated %+terrain_test% | on_press = ph_button@deactivated %+terrain_test% | ||
[ph_button@deactivated] | [ph_button@deactivated] | ||
anim = lab_switcher_off | anim = lab_switcher_off | ||
+ | </source> | ||
- | + | To make sure the message stays valid with different keyboard settings, you should use tokens. For example: | |
<source lang="xml"> | <source lang="xml"> | ||
<string id="tips_labx16switcher_press"> | <string id="tips_labx16switcher_press"> | ||
- | <text> | + | <text>To disable this magical contraption press ($$ACTION_USE$$)</text> |
</string> | </string> | ||
</source> | </source> | ||
- | + | Here is an example of a button that does not work each time, but only if a certain condition is met: | |
<source lang="ini"> | <source lang="ini"> | ||
Line 1,556: | Line 1,821: | ||
[ph_button@locked] | [ph_button@locked] | ||
- | anim = button_false | + | anim = button_false; an animation for disabled buttons |
- | on_info = {+val_prisoner_door_unlocked} ph_button@unlocked | + | on_info = {+val_prisoner_door_unlocked} ph_button@unlocked |
on_press = ph_button@unlocked %+val_prisoner_door_unlocked% | on_press = ph_button@unlocked %+val_prisoner_door_unlocked% | ||
[ph_button@unlocked] | [ph_button@unlocked] | ||
- | anim = button_true | + | anim = button_true |
- | on_info = {-val_prisoner_door_unlocked} ph_button@locked | + | on_info = {-val_prisoner_door_unlocked} ph_button@locked |
on_press = ph_button@locked %-val_prisoner_door_unlocked% | on_press = ph_button@locked %-val_prisoner_door_unlocked% | ||
</source> | </source> | ||
Line 1,568: | Line 1,833: | ||
===Projector=== | ===Projector=== | ||
- | + | In points of the path towards which the projector points you should write: | |
- | sl= | + | |
+ | <source lang="ini"> | ||
+ | sl=<projector name> | ||
+ | </source> | ||
- | + | For instance: <tt>wp00|sl=esc_sl1</tt>. | |
- | wp00|sl=esc_sl1 | + | |
- | + | Then when the character turns towards this point, so will the projector. | |
===Combination locks=== | ===Combination locks=== | ||
- | + | When a certain code is entered, gives out an infoportion. | |
+ | <source lang="ini"> | ||
[logic] | [logic] | ||
active = ph_code@lock | active = ph_code@lock | ||
[ph_code@lock] | [ph_code@lock] | ||
- | code = 1243 | + | code = 1243 |
on_code = %+infoportion% | on_code = %+infoportion% | ||
+ | </source> | ||
File: \gamedata\scripts\ph_code.script | File: \gamedata\scripts\ph_code.script | ||
- | ===Ph_gate | + | ===Ph_gate=== |
- | + | Same as <tt>ph_door</tt>, but for gates made from two halves. | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ; state | |
- | stick | + | : state in which the door is in after initialization |
+ | :; open | ||
+ | :; closed | ||
+ | :; none | ||
+ | :: current (default or remaining after the previous scheme) | ||
+ | ; locking | ||
+ | : <tt>none</tt> by default | ||
+ | ; stick | ||
+ | : whether the door is attracted to the farmost positions (this is still being set up) | ||
+ | ; soft | ||
+ | : the door is blocked by force, so it can be forced or broken through | ||
+ | :; open | ||
+ | :: blocked in open state | ||
+ | :; closed | ||
+ | :: blocked in closed state | ||
+ | :; none | ||
+ | :: unused | ||
+ | ; hard | ||
+ | : the door is blocked with boundaries; can only be broken | ||
+ | :; open | ||
+ | :: blocked in open state | ||
+ | :; closed | ||
+ | :: blocked in closed state | ||
+ | :; none | ||
+ | :: blocked in current state | ||
+ | ; none | ||
+ | : the door is unblocked | ||
- | + | General parameters: | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ; left_limit, right_limit | |
- | + | : sets the angle [0-180] for opening each half of the gate; 100 by default | |
- | + | ; breakable = true/false | |
- | + | : determines whether the gate can be broken; <tt>true</tt> by default | |
- | + | ||
- | + | The sound parameters are the same as for <tt>ph_door</tt>. | |
- | + | Examples: | |
- | + | ||
- | + | ||
- | Звуковые параметры аналогичны ph_door | ||
- | |||
- | Examples: | ||
<source lang="ini"> | <source lang="ini"> | ||
- | [ph_gate@locked] ; | + | [ph_gate@locked] ; blocks in open mode, undestructable |
- | state = opened | + | state = opened |
- | locking = soft | + | locking = soft |
left_limit = 130 | left_limit = 130 | ||
rigt_limit = 60 | rigt_limit = 60 | ||
- | breakable = false | + | breakable = false |
[ph_gate@opened] | [ph_gate@opened] | ||
- | state = opened | + | state = opened |
locking = stick | locking = stick | ||
Line 1,642: | Line 1,922: | ||
===Ph_sound=== | ===Ph_sound=== | ||
- | + | Is specified for every physical object to emit sounds (was initially made for swearning). | |
- | [ph_sound] | + | '''[ph_sound]''' |
- | snd | + | ; snd |
- | + | : name of a theme from file sound_theme.script from table ph_snd_themes | |
- | + | ; looped = true/false | |
- | + | ; min_idle | |
- | + | : minimum idle time before the sound is turned on, in ms | |
+ | ; max_idle | ||
+ | : maximum idle time before the sound is turned on, in ms | ||
+ | ; random | ||
+ | : if <tt>true</tt>, then random sounds will be picked from the theme | ||
+ | |||
+ | ''Note! Setting <tt>random=true</tt> and <tt>looped=true</tt> will crash the game.'' | ||
- | + | A condition list is also supported. | |
- | + | This scheme works through the ass, so the looping sound will continue playing, even if the object becomes <tt>nil</tt>. This means that you should create a new section to play a single short sound, after which (since it will play again and again) set <tt>on_signal=sound_end|nil</tt>. | |
- | + | ||
An example of such twisted logic: | An example of such twisted logic: | ||
Line 1,663: | Line 1,948: | ||
[ph_sound] | [ph_sound] | ||
- | snd = gar_seryi_shooting | + | snd = gar_seryi_shooting |
- | looped = true | + | looped = true |
- | max_idle = 5000 | + | max_idle = 5000 |
on_actor_in_zone = gar_seryi_factory| ph_sound@end | on_actor_in_zone = gar_seryi_factory| ph_sound@end | ||
[ph_sound@end] | [ph_sound@end] | ||
- | snd = gar_seryi_shooting_2 | + | snd = gar_seryi_shooting_2 |
- | looped = false | + | looped = false |
on_signal = sound_end| nil | on_signal = sound_end| nil | ||
</source> | </source> | ||
- | + | Besides, the sound scheme is created in a particular way. In sound_theme.script at the beginning of the file there is section <tt>ph_themes</tt> in which themes for physical objects are described. | |
- | + | ||
For example: | For example: | ||
- | ph_snd_themes["gar_seryi_shooting"] = {[[characters_voice\human_01\scenario\garbage\distance_shooting]]} | ||
- | + | <source lang="ini"> | |
+ | ph_snd_themes["gar_seryi_shooting"] = {[[characters_voice\human_01\scenario\garbage\distance_shooting]]} | ||
+ | </source> | ||
+ | |||
+ | Besides, (undocumented feature) <tt>ph_sounds</tt> can be set for restrictors. Although, no one is responsible for this working correctly. | ||
File: \gamedata\scripts\ph_sound.script | File: \gamedata\scripts\ph_sound.script | ||
Line 1,685: | Line 1,973: | ||
===Ph_force=== | ===Ph_force=== | ||
- | + | This scheme allows one to kick an object in a given direction. Is written in custom data of an object. | |
- | + | ; force | |
- | + | : force applied to the object, measured in dead badgers | |
- | + | ; time | |
- | + | : durationi of time the force is applied to the object, measured in seconds | |
- | + | ; delay | |
+ | : delay in seconds before the force is applied | ||
+ | ; point | ||
+ | : name of a patrol path that is to be used as the target (where the object will point) | ||
+ | ; point_index | ||
+ | : index of a point of the patrol path towards which the object will fly | ||
===Ph_on_death=== | ===Ph_on_death=== | ||
- | + | Scheme for tracking destruction of physical objects and producing various effects. | |
+ | |||
Example: | Example: | ||
Line 1,703: | Line 1,997: | ||
[ph_on_death] | [ph_on_death] | ||
- | on_info = % | + | on_info = %effects% |
</source> | </source> | ||
- | + | To be used only with destructable physical objects. | |
===Ph_car=== | ===Ph_car=== | ||
- | + | Settings to let the player control a car. | |
- | + | ||
- | + | ||
- | usable | + | '''[ph_car]''' |
+ | |||
+ | ; usable = condtion list | ||
+ | : list of conditions returning <tt>true</tt> (by default) or <tt>false</tt> | ||
Example: | Example: | ||
Line 1,726: | Line 2,021: | ||
</source> | </source> | ||
- | + | Based on this scheme, you can make a car that will start only if the actor has a key for it. | |
===Ph_heavy=== | ===Ph_heavy=== | ||
- | + | Is set for physical objects, which are forbidden for throwing by burers and poltergeists. For instance, they should lay in a certain place (such as storyline-related documents) or are too massive to be thrown nicely. | |
В кастом дате пишем: | В кастом дате пишем: | ||
Line 1,739: | Line 2,034: | ||
===Ph_oscillate=== | ===Ph_oscillate=== | ||
- | + | This scheme is meant for gentle rocking of physical objects (lamps, hanging zombies, etc). | |
+ | |||
Logic example: | Logic example: | ||
<source lang="ini"> | <source lang="ini"> | ||
[ph_oscillate] | [ph_oscillate] | ||
- | joint = provod ; | + | joint = provod ; name of the bone to which force is applied |
- | force = 5 ; | + | force = 5 ; force (in newtons) |
- | period = 1000 ; | + | period = 1000 ; time at which force is applied |
</source> | </source> | ||
- | + | The force is applied to a bone of the object with linear increase. That is, during a period of time the force grows from 0 to the specified magnitude. After this a pause is made (force is not applied) for the time <tt>period/2</tt>. After the pause ends, the force is applied at the same place, but in opposite direction. | |
==Smart terrains and gulags== | ==Smart terrains and gulags== | ||
Line 1,755: | Line 2,051: | ||
===Smart terrain=== | ===Smart terrain=== | ||
- | + | By a smart terrain we mean a zone that, upon entry, captures a stalker in a gulag and makes him do work for this gulag. After a period of time he escapes the gulag and walks free. | |
- | + | How to set a smart terrain? For every smart terrain you have to: | |
- | + | # Set a smart terrain with the required shape. It is not recommended to make them large, since size affects performance. | |
- | # | + | # Specify the settings in its custom data. |
- | # | + | # Set paths for the corresponding behavior schemes. |
- | # | + | |
- | + | Custom data parameters: | |
- | [gulag1] | + | |
- | type | + | '''[gulag1]''' |
- | capacity | + | |
- | + | ; type | |
- | + | ; capacity | |
- | + | : max number of people | |
- | + | ; offline | |
- | + | : if the gulag can go offline; <tt>false</tt> by default | |
- | + | ; squad | |
+ | : the squad to set for all stalkers in the gulag (level #) | ||
+ | ; groups | ||
+ | : comma-separated list of groups | ||
+ | ; stay | ||
+ | : duration of time the NPC remains under the smart terrain; permanently by default | ||
+ | ; idle = min, max | ||
+ | : duration of time the smart terrain remains active after the last NPC leaves | ||
+ | ; cond | ||
+ | : list of conditions necessary to create a gulag | ||
+ | : {+info -info = func !func} - if the condition is not met, the gulag is disbanded and all its inmates begin to be controlled by logic specified in their custom_data | ||
- | + | Gulag type should not be quoted. If either <tt>squad</tt> or <tt>groups</tt> is not set, then the corresponding properties of stalkers will not change. All time is set in hours of game time and can be fractional | |
- | + | ||
- | + | ||
- | + | Path names should always start with the name of the given smart terrain. For instance: <tt>esc_smart_ambush_vagon_sleep</tt>. | |
- | + | ||
- | + | If paths for a smart terrain are for several people (campers, walkers), then their names should always end with a number (esc_smart_ambush_vagon_walk1, esc_smart_ambush_vagon_walk2). | |
- | + | There can be several gulags under a single smart terrain. They can be set in several sections [gulag2], [gulag3], etc. After a stalker enters the smart terrain, one of the available gulags will be chosen at random. | |
====Standard smart terrain types==== | ====Standard smart terrain types==== | ||
Line 1,862: | Line 2,164: | ||
===Gulags=== | ===Gulags=== | ||
- | Гулаг - средство объединения нескольких сталкеров под централизованным управлением. Основные особенности: | ||
- | # Есть список работ гулага. Работа - настроенная схема поведения (или цепочка схем поведения); | ||
- | # Работы имеют приоритеты; | ||
- | # Гулаг назначает на работы сталкеров входящих в гулаг, начиная с работ с наивысшим приоритетом; | ||
- | # Гулаг имеет состояния. Каждое состояние характеризуется своим набором работ, отличным от набора работ в любом другом состоянии гулага. | ||
- | + | A gulag is a means of joining several stalkers under centralized control. Main features: | |
- | + | # A gulag has a task list. A task is a set behavioral scheme, or a chain of schemes. | |
+ | # Tasks have priorities. | ||
+ | # A gulag assigns entering stalkers to jobs with highest priority first. | ||
+ | # Gulags have states. Each condition corresponds to a unique set of tasks, different from the set of any other condition. | ||
- | + | A gulag is created like this: | |
- | + | 1. First, a list of states for the gulag has to be determined: day, night, calm, active, etc. Simple gulags might have only one state, a complex one should have many. This introduces more variety and looks better. | |
- | + | 2. Determine the maximum number of people that can be controlled by the gulag. That is, determine the gulag's capacity. It should be such that in any state the gulag should be able to find a task for every person. | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | 3. For every state the gulag should have a list of tasks. These tasks can be active (centry, patrol, etc) or passive (sitting at a campfire, sleep). Each job has its own priority. Correspondingly, passive tasks should have lower priority. | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | 4. Use the editor to set the number of people to be in the gulag and cover it with a smart terrain (it is an error to use space_restictor). The terrain should be given a meaningful name. This name will also serve as a prefix for all patrol paths for this gulag. For instance, if you call the terrain esc_blockpost, then all patrol paths should start with this prefix, as esc_blockpost_guard_walk, for instance. Custom data for the zone should contain settings for the gulag. | |
- | + | ||
- | + | ||
- | + | ||
- | + | '''[gulag1]''' | |
- | + | ; type | |
+ | ; capacity | ||
+ | : maximum number of people | ||
+ | ; offline = true/false | ||
+ | : whether the gulag can go offline | ||
+ | ; squad = squad | ||
+ | : the squad stalkers under the gulag are assigned to | ||
+ | ; groups | ||
+ | : comma-delimeted list of groups | ||
+ | ; stay | ||
+ | : duration of time the NPC remains under the smart terrain; permanently by default | ||
+ | ; idle = min, max | ||
+ | : duration of time the smart terrain remains active after the last NPC leaves | ||
+ | ; cond | ||
+ | : list of conditions necessary to create a gulag | ||
+ | : <tt>{+info -info = func !func}</tt> - if the condition is not met, the gulag is disbanded and all its inmates begin to be controlled by logic specified in their custom_data | ||
+ | ; respawn | ||
+ | : respawn name (calls the respawner with the given name every time someone from the smart terrain starts working on a task) | ||
+ | <tt>Capacity</tt> should always be set. It should be less than or equal to the number of tasks. | ||
+ | |||
+ | Gulag type should be unquoted. | ||
+ | |||
+ | The <tt>offline</tt> field could be used to prevent the gulag from going offline. That is, it can exist in offline mode, but cannot go into it. | ||
+ | |||
+ | Gulag type should not be quoted. If either squad or groups is not set, then the corresponding properties of stalkers will not change. All time is set in hours of game time and can be fractional | ||
+ | |||
+ | 5. In script \gamedata\scripts\gulag_<level name>.script you should set the condition under which stalkers are captured by the gulag. The function checkNPC should be appended with the condition: | ||
+ | |||
+ | <source lang="lua"> | ||
+ | if gulag_type == "gar_dolg" then | ||
+ | return npc_community == "dolg" | ||
+ | end | ||
+ | </source> | ||
+ | |||
+ | This function takes two parameters: gulag type and character's community. In this case, the the gulag with type <tt>gar_dold</tt> will accept all characters in faction Dolg. | ||
+ | |||
+ | 6. In file \gamedata\scripts\gulag_<level name>.script you should desribe how gulag states should switch. | ||
+ | |||
+ | <source lang="lua"> | ||
function loadStates(gname, type) | function loadStates(gname, type) | ||
- | + | </source> | |
+ | |||
+ | Takes the name of a zone and gulag type. The gulag's state is described as a function returning gulag state number. For example: | ||
<source lang="lua"> | <source lang="lua"> | ||
Line 1,910: | Line 2,233: | ||
return function(gulag) | return function(gulag) | ||
if level.get_time_hours() >= 7 and level.get_time_hours() <= 22 then | if level.get_time_hours() >= 7 and level.get_time_hours() <= 22 then | ||
- | return 0 -- | + | return 0 -- day |
else | else | ||
- | return 1 -- | + | return 1 -- night |
end | end | ||
end | end | ||
Line 1,918: | Line 2,241: | ||
</source> | </source> | ||
- | + | In this case, if it is between 07 and 22 hours, the gulag is in daytime mode, otherwise in nighttime mode. | |
- | 8. | + | 8. In file \gamedata\scripts\gulag_<level name>.script you should describe a gulag's tasks. The function loadJob loads all the allowed tasks. The function itself takes the following parameters: |
+ | |||
+ | <source lang="lua"> | ||
function loadJob(sj, gname, type, squad, groups) | function loadJob(sj, gname, type, squad, groups) | ||
- | sj | + | </source> |
- | gname | + | |
- | + | ; sj | |
- | + | : the gulag task table itself | |
+ | ; gname | ||
+ | : smart terrain name; used as a prefix | ||
+ | ; type | ||
+ | ; squad, groups | ||
+ | : squad and group table, if we need to override the native stalker groups with some other ones. For each task you should set a squad and a group to assign a stalker to upon recieving a task. | ||
+ | |||
+ | Approximate description of gulag tasks: | ||
- | + | The following gulag describes behavior of a single person, but there is usually many more. The given person in zero state (daytime) performs one task, in first state (nighttime) another task. | |
- | + | ||
<source lang="lua"> | <source lang="lua"> | ||
Line 1,954: | Line 2,285: | ||
Field descriptions: | Field descriptions: | ||
- | + | ; Idle | |
- | + | : pause between repeated execution of the same tasks. There is no pause in this case. Pause is usually set for patrols. | |
- | + | ; Prior | |
- | + | : task priority. At first stalkers occupy the higher priority tasks. The higher the number, the higher the priority. | |
- | + | ; In_rest, out_rest | |
- | + | : restrictors set for the character for this task | |
+ | ; Section | ||
+ | : section in \gamedata\config\misc\gulag_<level name>.ltx, in which the real behavior scheme corresponding to this task is set. | ||
+ | : the stalker's group will be chosen from the group array set in custom data. The array is indexed starting with 1. | ||
+ | ; Info_rest | ||
+ | : sets the name of the restrictor, inside of which the person performing the task is guarded from all dangers | ||
- | + | The task description may also contain additional conditions for when the stalker can recieve the task. For example: | |
<source lang="lua"> | <source lang="lua"> | ||
Line 1,969: | Line 2,305: | ||
</source> | </source> | ||
- | + | That is, the given task can only be carried out by a person with the <tt>soldier_commander</tt> profile. | |
- | 9. В \gamedata\config\misc\ | + | 9. В:\gamedata\config\misc\gulag_<level name>.ltx you should specify which behavior schemes correspond to each task. FOr instance, for the aforementioned gar_maniac: |
<source lang="ini"> | <source lang="ini"> | ||
Line 1,989: | Line 2,325: | ||
[sleeper@gar_maniac_sleeper] | [sleeper@gar_maniac_sleeper] | ||
path_main = sleep | path_main = sleep | ||
- | wakeable = true | + | wakeable = true |
</source> | </source> | ||
- | + | Here settings correspond to regular stalker custom data, with the followin differene: | |
- | # | + | # paths should be specified without a prefix. THat is, if the zone was called <tt>gar_maniac</tt>, a path on the level might be called <tt>gar_maniac_walk1</tt>, but gamedata\config\misc\gulag_<level name>.ltx should be specified as simply <tt>walk1</tt>. |
- | # | + | # section names should be appended with @ and the gulag name and, possibly, additional information (such as walker2@rad_antena_gate) |
- | # | + | # for each taask, <tt>logic</tt> section names should be appended @ and the gulag name, additional data, and active behavior scheme for (such as logic@rad_antena_gate_walker2 |
- | + | There is no <tt>leader</tt> field for gulag tasks. There is the <tt>dependent</tt> field. A task can only be taken if the dependent task is taken first. For instance, <tt>follower</tt> can be set only after someone is set to work as the leader (leader's name is now in the <tt>dependent</tt> field). Correspondingly, the task priority for tasks on which others dpeend should be greater than theirs. | |
===New smart terrain capabilities=== | ===New smart terrain capabilities=== | ||
- | + | ====New capabilities==== | |
- | + | * Does not keep stalkers online. The standard online radius works. | |
- | + | * Stalkers go to the nearest task. | |
- | + | * Stalkers go to their workplaces without respect to whether they are online or offline. | |
- | + | * In offline an ST works the same way as in online: switches states, allocates tasks. | |
- | + | * Stalkers can be given conditions for entering certain STs (see below). If a stalker enters an ST, then he will remain in it until his time elapses and the condition is met. | |
- | + | * Tasks can be located in different levels. | |
- | + | * Scripting ST zone is not used for capturing characters anymore. | |
- | + | * Simulation is manifested in migration of characters between different STs. | |
- | + | ====Allowing characters to enter certain ST==== | |
- | + | Permissions for characters to enter sertain STs are set in the <tt>[smart_terrains]</tt> section. In it you can set pairs <tt>ST_name = condlist</tt>, such as: | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
<source lang="ini"> | <source lang="ini"> | ||
[smart_terrains] | [smart_terrains] | ||
- | strn_1 = | + | strn_1 = condition1 |
- | strn_2 = | + | strn_2 = condition2 |
</source> | </source> | ||
- | + | If a condition is met for some smart terrain, it is called exclusive. | |
- | + | ||
- | + | ||
- | + | If a character has at least one exclusive smart terrain, then he will only agree to go to that one. | |
- | + | If he has no exclusive ones, he will agree to go to any. | |
+ | |||
+ | There is a reserved combination <tt>none=true</tt>. If it is set, then the character will not go to any ST. This character will only rely on his own logic. | ||
+ | |||
+ | It is also possible to specify who is accepted by a ST. In addition to the old mechanism (function <tt>checkNpc()</tt> in files gulag_*.script) you can write in custom data for ST: | ||
+ | |||
+ | <source lang="ini"> | ||
+ | communities = group1, group2, ... | ||
+ | </source> | ||
- | + | If this field is not set, then the old mechanism is used. If it is set, then the ST will only accept characters from the specified groups (but the old mechanism will also be called). | |
- | + | ====Modifying predicate() functions==== | |
- | + | In these functions a character information table will be passed instead of game_object. There are fields: | |
- | + | * name | |
- | name | + | * community |
- | community | + | * class_id |
- | class_id | + | * story_id |
- | story_id | + | * profile_name |
- | profile_name | + | |
- | + | If you only need snipers to take the task, write the following in the predicate: | |
<source lang="lua"> | <source lang="lua"> | ||
Line 2,062: | Line 2,392: | ||
</source> | </source> | ||
- | + | ====Online and offline work modes==== | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
<source lang="lua"> | <source lang="lua"> | ||
Line 2,078: | Line 2,404: | ||
</source> | </source> | ||
- | + | Options for this field: | |
- | online = true | + | ; online = true |
- | online = false | + | : the character is always online on this job |
- | online | + | ; online = false |
+ | : the character is always offline on this job | ||
+ | ; online not set | ||
+ | : the character might switch between online and offline as deems appropriate | ||
====A more accessible description of smart terrains==== | ====A more accessible description of smart terrains==== | ||
- | + | Now, smart terrains for designers. That is, no LUA, just plain English. | |
- | + | ||
+ | To move a smart terrain to a new scheme, do the following: | ||
<ol> | <ol> | ||
<li> | <li> | ||
- | + | Change inside custom data <tt>[gulag1] -> [smart_terrain]</tt> | |
</li> | </li> | ||
<li> | <li> | ||
- | + | In custom data of comrades by smart terrain write: | |
<source lang="ini"> | <source lang="ini"> | ||
[smart_terrains] | [smart_terrains] | ||
- | + | sar_monolith_sklad(gulag name) = {condition list} | |
- | + | ||
- | sar_monolith_sklad( | + | |
[smart_terrains] | [smart_terrains] | ||
none = true | none = true | ||
Line 2,106: | Line 2,434: | ||
==Helicopter logic== | ==Helicopter logic== | ||
- | General information | + | ===General information=== |
- | * | + | * The helicopter has "logic" |
- | * | + | * The helicopter does not react to anomalies |
- | * | + | * The helicopter cannot collide with level geometry until shot down |
- | * | + | * Hits in the area of the cabin in which the first pilot sits are dozens of times more damaging for the helicopter |
- | * | + | * Like stalkers, the helicopter has an all-purpose combat scheme |
- | * | + | * Helicopter pilots have replicas for the following events: hit, enemy sited, damaged (smoking), falling. |
===heli_move scheme=== | ===heli_move scheme=== | ||
- | + | ====General information==== | |
- | + | ||
- | + | Allows the helicopter to fly along a patrol path, control speed, hover, shoot at various targets. The scheme must have <tt>path_move</tt> set — the path along which the helicopter will fly. It may contain just one point, if the helicopter should hover. It is allowed, but not necessary to set <tt>path_look</tt> — the path into the points of which the helicopter should look. | |
- | + | The vertices of these points can be anywhere within the boundaries of the level's bounding box. They do not depend on AI nodes. | |
- | + | The helicopter will fly along points without respect of connections between them. It will fly from vertex to vertex in order of increasing number (that is, in the order they were set in the level). | |
- | + | The helicopter will try to follow path vertices exactly. If needed, it can fly precisely under a bridge. | |
- | + | The helicopter will fly as fast as possible. That is, if you set its speed at the next vertex at 10 m/s, while its maximum speed is set to 30 m/s, then it will not start flying 10 m/s right away. It will first speed up to 30 m/s, then on approach of the vertex it will slow down such that it gets to the vertex at 10 m/s. | |
- | + | If a <tt>path_move</tt> vertex has some flags, the helicopter will look into any of the <tt>path_look</tt> vertices for which the same set of flags is specified. It will start turning towards the point starting at the previous point of the path. The helicopter cannot currently look towards several <tt>path_look</tt> points while hovering. | |
- | + | ====Settings==== | |
- | + | ; engine_sound = true/false | |
+ | ; invulnerable = true/false | ||
+ | ; immortal = true/false | ||
+ | : if <tt>true</tt> the helicopter will calculate damage, but not recieve it | ||
+ | ; mute = true/false | ||
+ | : disable default helicopter phrases | ||
+ | ; rocket_delay = msec | ||
+ | : is taken from [[ltx]] by default; currently 1250 | ||
+ | ; default_velocity = m/sec | ||
+ | : the helicopter speed, unless other parameters are set | ||
- | + | <tt>path_move</tt> point parameters: | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ; e | |
- | + | : sets enemy. The helicopter will start firing at this target starting at the previous vertex. If the value is not set, it will fire at the point form <tt>path_look</tt> corresponding to the given vertex. If <tt>e=actor</tt> (or <tt>e=a</tt>) is set, then fire will target the actor. If <tt>e=number</tt> fire will target the object with the given id. | |
- | + | ; w | |
- | + | : which weapon to use. The possible values are: <tt>w=1</tt> to use the machien gun only; <tt>w=2</tt> to use rockets only. Shoots with everything by default. | |
- | + | ; v | |
- | + | : maximum speed in m/s on the path from the given vertex to the next. If this parameter is not set, the value from helicopter.ltx is taken by default. | |
- | + | ; dv | |
+ | : destination velocity in m/s that the helicopter should have on arriving at the given vertex | ||
+ | ; die | ||
+ | : kill the helicopter | ||
+ | ; flame | ||
+ | : set the helicopter on fire, as if it was damaged | ||
- | + | <tt>path_look</tt> point parameters: | |
- | + | ||
- | + | ; e | |
- | + | : works the same way as in <tt>path_move</tt>. The difference is that the helicopter will only start firing at it when it gets to the point of <tt>path_move</tt> that corresponds to the given vertex. | |
+ | ; w | ||
+ | : works the same way as in <tt>path_move</tt> | ||
+ | ; t | ||
+ | : duration of time during which the helicopter will look at the given point. If this parameter is nto set, then the helicopter will fly by without stopping, but will try to face the vertex while moving. | ||
===All-purpose combat scheme=== | ===All-purpose combat scheme=== | ||
- | + | ====General information==== | |
- | + | In the general combat scheme, a helicopter is not tied to a path. | |
- | + | The helicopter does not see anyone. The helicopter can only find someone upon recieval of damaged or from a parameter in <tt>custom data</tt>. | |
- | + | The helicopter shoots at an enemy upon detection. Until then, looks for him, circling the points of last citings. If it does not see the enemy for a long time — forgets him. If the enemy is specified in the current behavior section, he will not be forgotten while the section is in effect. | |
- | Settings | + | ====Settings==== |
- | + | There is no separate section for this behavior scheme. Therefore, settings are given in the current behavior scheme: | |
- | combat_ignore = true/false | + | ; combat_ignore = true/false |
- | true | + | : <tt>true</tt> means ignore hits. That is, the helicopter will not try to "take revenge" on whoever hits it. |
+ | ; combat_enemy = nil/actor/StoryID | ||
+ | : This parameter could be used to give the helicopter a specific enemy: | ||
+ | :; nil | ||
+ | :: no enemy | ||
+ | :; actor | ||
+ | :: player | ||
+ | :; SID | ||
+ | :: id number of the enemy | ||
+ | ; combat_use_rocket = true/false | ||
+ | : Whether the helicopter is authorized to use rockets. | ||
+ | ; combat_use_mgun = true/false | ||
+ | : Whether the helicopter is authorized to use the machine gun | ||
+ | ; combat_velocity = <number> | ||
+ | : Speed in m/s at which the helicopter will circle. | ||
+ | ; combat_safe_altitude = <number> | ||
+ | : Height, relative to the highest point of the geometry of the level, below which the helicopter will not decend (can be negative) | ||
- | + | The helicopter has the <tt>xr_hit</tt> scheme. It words the same way as for stalkers. There is a group of functions for working with a helicopter and its custom data in <tt>xr_effects</tt>: | |
- | + | ||
- | + | ; heli_set_enemy_actor | |
- | + | : make the actor the helicopter's enemy | |
- | + | ; heli_start_flame | |
- | + | : set the helicopter on fire | |
- | + | ; heli_die | |
- | + | : destroy the helicopter | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
==Meet_manager== | ==Meet_manager== | ||
- | + | ====Syntax==== | |
<source lang="ini"> | <source lang="ini"> | ||
Line 2,225: | Line 2,562: | ||
</source> | </source> | ||
- | + | All of the meeting settings are in a single section. The <tt>logic</tt> section or the current scheme can be used which section to use. The section set in the <tt>logic</tt> section affects processing of meetings for free stalkers. | |
- | + | Fields: | |
- | + | ; meet_state, meet_state_wpn | |
- | + | : sets animation and voicing for the character, depending on distance to the actor; for when the actor is unarmed or armed, respectively | |
- | + | ; victim, victim_wpn | |
- | + | : sets the object at which the character will look; can be: | |
- | + | :; nil | |
- | + | :: does not look anywhere | |
- | + | :; actor | |
+ | :: looks at the player | ||
+ | :; story_id | ||
+ | :: number of the character at which to look | ||
+ | ; use, use_wpn | ||
+ | : use settings; can be one of: <tt>true</tt>, <tt>false</tt>, <tt>self</tt>; if <tt>self</tt> is used, the NPC will use the player | ||
+ | ; zone | ||
+ | : contains a set of restrictor names, as well as animations an sounds the NPC will play, if the player is sighted within a restrictor | ||
+ | ; meet_dialog | ||
+ | : starting dialog for the NPC | ||
+ | ; synpairs | ||
+ | : contains a set of pairs <tt>body_state@sound_theme</tt>. If at some set of conditions the meeting plays this condition and this sound theme, they will be synchronized via random body state animations | ||
+ | ; аbuse | ||
+ | : <tt>true</tt> by default; if false, unused opponent will not become bitter | ||
- | + | Any line can be set via a condlist. ( {+info1 –info2} ward %+info% ) | |
- | + | To make meetings easier to set up, there is a simplified default: | |
<source lang="ini"> | <source lang="ini"> | ||
Line 2,245: | Line 2,595: | ||
</source> | </source> | ||
- | + | You do not have to set the <tt>[default_meet]</tt> section itself. All of the settings will be used as default, anyway. | |
- | + | Now to explain how all of this can be used to construct the reaction to the actor that you need. | |
- | + | ====Situation 1==== | |
- | + | ||
+ | The character beckons us with his hand, on approach asks us to hide our weapon, then agrees to talk. | ||
<source lang="ini"> | <source lang="ini"> | ||
Line 2,262: | Line 2,613: | ||
</source> | </source> | ||
- | + | ====Situation 2==== | |
- | + | ||
+ | On sight the stalker asks us to hide our weapon. After this he approaches and talks to us. If we start to walk away or take the weapon out — starts shooting at us. | ||
<source lang="ini"> | <source lang="ini"> | ||
Line 2,275: | Line 2,627: | ||
</source> | </source> | ||
- | Here: info | + | Here: |
- | + | ; info | |
- | Killactor | + | : infoportion that says that we have lowered the weapon or are close enough to the NPC |
+ | ; info2 | ||
+ | : infoportion that is set in the dialog and records that the character has said to us everything he wanted | ||
+ | ; Killactor | ||
+ | : function in <tt>xr_effects</tt> that makes the NPC hostile | ||
+ | |||
+ | ====Situation 3==== | ||
- | + | The character walks along a patrol path on camp guard. If the player has a pass to the camp, greets him and lets him pass, otherwise first warns, then, if the player gets into the camp, becomes hostile. The dialog depends on whether the player has a pass into the camp or not. | |
- | + | ||
<source lang="ini"> | <source lang="ini"> | ||
Line 2,301: | Line 2,658: | ||
Here: | Here: | ||
- | + | ; true | |
- | + | : attack the player instead of animation | |
- | + | ; info | |
- | + | : infoportion saying that we have a pass to the camp | |
- | + | ; warnzone | |
- | + | : restrictor within which he warns us | |
+ | ; kampzone | ||
+ | : restrictor in which he kills us | ||
+ | ; dialog1 | ||
+ | : starting dialog if we have a pass | ||
+ | ; dialog2 | ||
+ | : starting dialog if we do not have a pass | ||
- | + | ====Default settings==== | |
- | + | By default, meeting has the following parameters: | |
<source lang="ini"> | <source lang="ini"> | ||
Line 2,322: | Line 2,685: | ||
</source> | </source> | ||
- | + | ''Note: if you need to make it so that a stalker does not speak to the player in this section, set <tt>meet=no_meet</tt>.'' | |
==Minimap marks== | ==Minimap marks== | ||
- | + | There is a way to avoid showing stalkers on the minimap and the map (hide blue and red dots). For this, the logic section or the current scheme should have the parameter: | |
- | [camper] | + | '''[camper]''' |
- | show_spot = false | + | ; show_spot = false |
+ | : to hide stalkers in this section | ||
- | [walker] | + | '''[walker]''' |
- | show_spot = {+info1} false | + | ; show_spot = {+info1} false |
- | + | : a stalker will be hidden if he has infoportion info1 | |
- | + | ||
==Function arguments== | ==Function arguments== | ||
- | + | Below we list the set of functions that can be accessed from custom data and to which variables can be passed. | |
- | + | ===xr_conditions=== | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
+ | ; fighting_dist_ge(<nowiki>p</nowiki>) | ||
+ | : all-purpose function for <tt>combat_ignore</tt>, checks distance to the player (in meters) | ||
+ | ; distance_to_obj_le(<nowiki>sid:dist</nowiki>) | ||
+ | : checks distance to the object with the given <tt>story_id</tt> | ||
+ | : this can be used, for instance in the <tt>follower</tt> section to switch to another section when a stalker walks within a certain distance of the leader (the leader is then somwehere in <tt>remark</tt>). This situationi occurs when one stalker should approach another while we do not know their positions. If this is used in the <tt>follower</tt> section, <tt>dist</tt> should be larger than the follower's <tt>distance</tt>, since if they are the same, this function will not always work. | ||
+ | ; health_le(<nowiki>health</nowiki>) | ||
+ | : checks that NPC's HP <= health | ||
+ | ; heli_health_le(<nowiki>health</nowiki>) | ||
+ | : like the above, but for a helicopter | ||
+ | ; enemy_group(<nowiki>group1:group2:...</nowiki>) | ||
+ | : checks membership of the enemy to a group (we did not check whether it works correctly) | ||
+ | ; hitted_by(<nowiki>sid1:sid2:...</nowiki>) | ||
+ | :checks if a hit was made by one of the listed NPCs. The NPCs are set using their <tt>story_id</tt>. This function is convenient for in the <tt>hit</tt> section. Example: | ||
<source lang="ini"> | <source lang="ini"> | ||
[hit] | [hit] | ||
on_info = {=hitted_by(407:408)} %+val_escort_combat% | on_info = {=hitted_by(407:408)} %+val_escort_combat% | ||
</source> | </source> | ||
+ | ; killed_by(<nowiki>sid1:sid2:...</nowiki>) | ||
+ | : like the preceeding, but for a kill; used in the <tt>death</tt> section | ||
+ | ; is_alive(<nowiki>sid</nowiki>) | ||
+ | ; is_alive_one(<nowiki>sid1:sid2:...</nowiki>) | ||
+ | ; is_alive_all(<nowiki>sid1:sid2:...</nowiki>) | ||
+ | : checks if one, one of serveral, or all NPCs in a list are alive | ||
+ | ; is_dead(<nowiki>sid</nowiki>) | ||
+ | ; is_dead_one(<nowiki>sid1:sid2:...</nowiki>) | ||
+ | ; is_dead_all(<nowiki>sid1:sid2:...</nowiki>) | ||
+ | : like the preceeding, but for death | ||
+ | ; check_fighting(<nowiki>sid1:sid2:...</nowiki>) | ||
+ | : checks if any from the list are enemies of the current NPC; typically used in <tt>combat_ignore_cond</tt> | ||
+ | ; gulag_empty(<nowiki>gulag_name</nowiki>) | ||
+ | : checks if a gulag is empty or non-existant | ||
+ | ; gulag_population_le(<nowiki>gulag_name, num</nowiki>) | ||
+ | : checks if the number of people in the gulag is <tt><= num</tt> | ||
+ | ; gulag_casualities_ge(<nowiki>gulag_name:num</nowiki>) | ||
+ | : checks that the casualties in the gulag are <tt>=> num</tt> | ||
+ | : Note! Gulag casualties are not reset, so you should be careful with this function | ||
+ | ; signal(<nowiki>string</nowiki>) | ||
+ | : checks if the NPC has the given signal set in the current scheme | ||
- | + | ===xr_effects=== | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | xr_effects | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
+ | ; heli_set_enemy(<nowiki>story_id</nowiki>) | ||
+ | : make the NPC with the given <tt>story_id</tt> an enemy of the helicopter. Only one enemy can be set in one section. | ||
+ | ; set_gulag_enemy_actor(<nowiki>gulag_name</nowiki>) | ||
+ | : make the actor an enemy of the current gulag | ||
+ | ; hit_npc(<nowiki>direction:bone:power:impulse:reverse=false</nowiki>) | ||
+ | : incur a hit to the NPC. Parameters: | ||
+ | :; direction = string/number | ||
+ | :: the name of path in the direction of first point of which to hit or the <tt>story_id</tt> number of a character from which the hit originates | ||
+ | :; bone = string | ||
+ | :: the name of the bone that is hit | ||
+ | :; power | ||
+ | :; impulse | ||
+ | :; reverse = true/false | ||
+ | :: whether the direction should be reversed; <tt>false</tt> by default | ||
+ | : Example: | ||
<source lang="ini"> | <source lang="ini"> | ||
[death] | [death] | ||
on_info = {=killed_by(404)} %=hit_npc(404:bip01_spine1:100:2000)%, {=killed_by(405)} %=hit_npc(405:bip01_spine1:100:2000)% | on_info = {=killed_by(404)} %=hit_npc(404:bip01_spine1:100:2000)%, {=killed_by(405)} %=hit_npc(405:bip01_spine1:100:2000)% | ||
</source> | </source> | ||
+ | ; set_friends(<nowiki>sid1:sid2:...</nowiki>) | ||
+ | ; set_enemies(<nowiki>sid1:sid2:...</nowiki>) | ||
+ | : set the character with the listed <tt>story_id</tt> numbers friends or enemies of the given NPC | ||
+ | ; play_snd(<nowiki>snd_name:delay=0</nowiki>) | ||
+ | : play a sound in the actor's head | ||
+ | ; snd_name | ||
+ | : sound path relative to the <tt>sounds</tt> folder | ||
+ | ; delay | ||
+ | : delay before playback; <tt>0</tt> by default, to start playback immediately | ||
+ | ; play_snd_now (<nowiki>sid:snd_name</nowiki>) | ||
+ | : play the sound from the given object | ||
+ | : the sound is played from the object with the given <tt>story_id</tt> without delay with volume 1; the file name, not sound schme name is specified | ||
+ | ; hit_obj(<nowiki>sid, bone, power, impulse, hit_src=npc:position(</nowiki>)) | ||
+ | : incur a hit on the object with the given <tt>story_id</tt>. Is distinguished by being able to be specified in any custom data. Parameters: actor, npc, p[sid, bone, power, impulse, hit_src=npc:position()] | ||
+ | :; sid | ||
+ | :: <tt>story_id</tt> of the object to incur the hit on | ||
+ | :; bone | ||
+ | :: name of the bone that is hit | ||
+ | :; power | ||
+ | :; impulse | ||
+ | :; hit_src | ||
+ | :: optional; the waypoint from which the hit is made on the object; if it is not specified, then the position of the object calling the function is taken | ||
+ | ; actor_has_item(<nowiki>section</nowiki>) | ||
+ | : check if the player has this object; the check is made via the ltx section | ||
- | + | ===Functions for working with HUD=== | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ; disable_ui_elements(...), enable_ui_elements(...) | |
- | + | : enables/disables HUD elements | |
- | + | :; weapon | |
- | + | :: show/hide hands with the weapon | |
- | + | :; input | |
+ | :: enable/disable keyboard | ||
+ | :; hud | ||
+ | :: show/hide screen indicators | ||
+ | :; all | ||
+ | :: enable/disable all elements | ||
Example: | Example: | ||
Line 2,440: | Line 2,809: | ||
</source> | </source> | ||
- | + | There are also shortened versions: | |
- | disable_ui, enable_ui | + | ; disable_ui, enable_ui |
- | + | : called without parentheses and parameters | |
+ | : analogous to the calls disable_ui_elements(all), enable_ui_elements(all), respectively | ||
Example: | Example: | ||
Line 2,451: | Line 2,821: | ||
</source> | </source> | ||
- | + | ===Function for running camera_effector=== | |
- | run_cam_effector( | + | ; run_cam_effector(file_name) |
- | + | : | |
- | + | :; file_name | |
- | + | :: animation file name from folder s:\gamedata\anims\camera_effects without extension | |
Example: | Example: | ||
Line 2,464: | Line 2,834: | ||
</source> | </source> | ||
- | + | ===Functions for running postprocessing=== | |
- | + | There are two functions for working with postprocessors: | |
- | + | ||
- | run_postprocess(file_name:id:loop) | + | ; run_postprocess(<nowiki>file_name:id:loop</nowiki>) |
+ | : starts posprocessing | ||
+ | :; file_name | ||
+ | ::name of a postprocessing file (without extension) from folder s:\gamedata\anims. Write without the extension. | ||
+ | :; id | ||
+ | :: number of the postprocess; optional; is used in <tt>stop_postprocess</tt> | ||
+ | :; loop - true/false | ||
+ | :: whether the posprocess should loop; optional; <tt>false</tt> by default | ||
+ | ; stop_postprocess(id) | ||
+ | : forces postprocessing to stop | ||
+ | :; id | ||
+ | ::number of the postprocess set in <tt>run_postprocess</tt> | ||
- | + | ===Function for emptying the actor's inventory into a certain spot=== | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ; drop_actor_inventory(path_name) | |
- | + | ||
- | drop_actor_inventory( | + | |
- | + | ||
- | + | ||
- | + | ||
Example: | Example: | ||
Line 2,492: | Line 2,863: | ||
==Sound group configuration== | ==Sound group configuration== | ||
- | + | The way to create sound groups: | |
- | + | ||
- | + | * Each character is considered to be in a unique soundgroup by default. | |
- | + | * To put several characters into a single sound group, the logic section of each one must contain <tt>soundgroup = <text string></tt> | |
- | + | * Sound groups must be unique within each level, or, better yet, within the whole game. For this, add level and scene identifiers to the name of the group, as in: <tt>soundgroup = bar_dolg_kampfire1</tt>. | |
- | + | * Characters sitting at a camp or walking together in patrol groups or in such similar situations should be put into sound groups. | |
- | + | * To avoid errors, all NPCs logically belonging to a group should have the same <tt>team</tt>, <tt>squad</tt>, <tt>group</tt>. | |
Example: | Example: | ||
Line 2,505: | Line 2,876: | ||
[kamp@esc_bridge_post1] | [kamp@esc_bridge_post1] | ||
center_point = kamp_point | center_point = kamp_point | ||
- | soundgroup = esc_bridge_soldiers | + | soundgroup = esc_bridge_soldiers |
</source> | </source> | ||
Line 2,520: | Line 2,891: | ||
[[ru:Настройка логики (часть 1)]] | [[ru:Настройка логики (часть 1)]] | ||
+ | |||
+ | [[Category:Articles]] |
Current revision
Flag system
Waypoints can have flags modifying a character's behavior. Flags are set right in the waypoint's name. For instance, for the point named "wp00": wp00|flag1|flag2.
path_walk, path_look
Flags for path_walk waypoints:
- a=state
- Chooses body state for movement
- The list can be found in gamedata\scripts\state_lib.script.
- p=percent
- Probability of stopping at the point as a percentage (0-100). It is 100 by default. That is, the character never passes the point by.
- sig=name
- Set signal with the given name on arrival at the point (before turning) for the following check with the logic system field on_signal. To set a signal after turning, use the corresponding flag for a path_look waypoint.
Flags for path_look waypoints:
- a=state
- Chooses body state for standing (or sitting) at the spot.
- The list can be found in gamedata\scripts\state_lib.script.
- t=msec
- time in milliseconds to look at the point
- '*' means unlimited time. Valid values are in the range [1000, 30000], 5000 by default.
- For terminal waypoints of path_walk that have no more than one corresponding path_look, the value of t is always considered infinite and does not have to be set.
- sig=name
- Set the signal with the given name after turning towards the point.
- syn
- This flag will halt setting the signal until all characters with the given team arrive. The team is set as a text string in customdata. The given character will be play its idle animation until the others arrive.
- sigtm=signal
- Sets a signal when the time_callback is called by the state manager. If t=0, then the signal will be set after playing the init animation. This is used, for instance, with the press animation, which consists of two parts: 1 — pressing the button, 2 — lowering the arm.
- path_look can do: wp00|a=press|t=0|sigtm=pressed.
- Then switch the scheme: on_signal = pressed | other_scheme.
Paths in-depth
Configuration
For each walker, you should place onto the map:
- path path_walk, used to walk along
- path path_look, consisting of points to look towards
There can be one or more walkers. They can act independently, or interract with each other.
[walker]
- team
- team name — an arbitrary text string. All walkers in a team must have the same team. It is desirable to specify level name and location in team; for instance: escape_bridge, escape_factory — this will reduce the chance of error of giving different teams the same name.
- path_walk
- name of the path described in "1"
- path_look
- (optional) name of the path described in "2". If a character needs to only walk along a path, path_look can be ommitted. If a character should stand at places, it needs a path_walk point and at least one path_look point.
The rules for setting flags with examples:
Example 1
A character patrols territory around two houses. Here is how the route is made:
What to do to make the character run or sneak between certain points? There are flags in path_walk just for this purpose.
Each waypoint has a name: wp00, wp01, etc.
Flags are set in the name. They should be separated from the name using the symbol '|'. Write a=anim, where anim is the name of an animation from 2.4.4 of original documentation. If we write a=thread, the character will enter danger mode, if a=raid will run with his weapon at ready, etc.
Note: only animations from the "walk states" section can be used!
Example 2
A character conversation.
To make a character speak while moving along a path, each point must have a list of topic he can speak about. There is the following field for this: s = sound_scheme_name (off by default). Several topics can be separated by commas.t
Example 3
Example 3 uses only the field s to set conversation topics.
It is NOT RECOMMENDED to set the other parameters (sp, sf, st). The default values are acceptable for most scripts.
It is also NOT RECOMMENDED to use the parameter sa. If a sound must be run at the same time as an animation, you should use fields in path_look, which will be described later in this document.
If a character not only walks along the path, but must also stop and play animations, you should set the path_look path.
Example 4
Improve Example 1, so that when the character passes a space between houses, stopped and looked inside it:
What is new? There is now a path_look path with two points. It is recommended to remove the link between these two points of the path in the editor right away, since it is not used anyway.
Forethermore, lets set some flags at the points of path_walk and path_look that are circled with a dashed line. For instance, in the upper pair of points, set the flag 0, and in the lower pair — flag 1.
Now the character will stop at points of path_walk marked with a flag, look towards the point of path_look marked with the same flag.
If a point of path_walk is not marked with a flag, the character will pass it without stopping.
One point of path_walk can correspond to several points of path_look. If this is the case, the character will randomly choose one of the suitable points.
Similarily to path_walk you can use various flags in points of path_look to modify behavior:
- p = 100
- Probability with which the character will look at that point. The values of all suitable p are added, so if one point has p = 100 and another 300, the character will look twards the point with probability 25% (100 out of 100 + 300).
- To avoid confusion, you should set p such that they add up to 100.
- By default, all points have p = 100.
- t = time in milliseconds
- Duration of time for which the character will stop at this point.
- By default, the value is 5000.
Example 5
In this example, as the character passes point wp00, he will look at the point wp00 for 5 seconds with probability 30% or at the point wp01 for 10 seconds with probability 70%.
By default, the character plays the idle animation when he stops if he is not crouching, or animation hide if he is crouching.
If you need a different animation, you can set it with this flag:
a = animation name (defaults to idle).
Write a=anim, where anim – is the name of an animation from 2.4.4. of the actual documentation. If we write a=hide, the character will enter the alert mode, if a=guard, will stand with his weapon on ready, etc.
- Note: You can only use animations from the section "standing and crouching animations" for path_look!
Stalker behaviour schemes
There is a certain set of schemes that describe a character's behavior. They are set in his custom_data or, in case of a gulag, in corresponding flags, describing the function of a given gulag. The list of these scheme follows.
All of the loaded schemes are listed in the file \gamedata\scripts\modules.script
walker scheme
This is the basic scheme that moves a character along waypoints (path_walk) and stops at certain points and executes certain actions.
[walker]
- path_walk = <path name>
- the main path the NPC traverses
- path_look = <path name>
- path the NPC looks towards
- team
- team to synchronize
The characters stops and looks at a certain points at path_walk points with corresponding path_look points, while playing (or not playing) a certain animation.
- def_state_moving1
- state in which the NPC moves towards the first point if it is nearby (patrol by default)
- def_state_moving2
- state in which the NPC moves towards the first point if it is further (rush by default)
- def_state_moving3
- state in which the NPC moves towards the first point if it is far away (sprint by default)
- def_state_standing
- default state in which the NPC stands at the point and looks, unless a different state is specified for the point
File: \gamedata\scripts\xr_walker.script
remark scheme
This scheme is used for synchronization and binding with other schemes.
[remark] snd_anim_synс = true либо false. По умолчанию false. Указывает на то необходимо ли синхронизировать звук с анимацией либо нет
- snd
- remark sounds; nil by default
- anim
- remark animation; wait by default
- target
- where the stalker looks; there are the following options
- story_id
- a number
- actor
- no comment
- nil
- position automatically calculated by the AI
- <job name>, <gulag name>
- look at a stalker that has a certain job in a certain gulag (the second parameter is not required, if omitted, the gulag of the stalker to which the given section applies is used). Example:
target = logic@cit_killers_base_guard, cit_killers
- <path name>, <point number>
- you can tell him to look at a vertex of a patrolling path
Note: that if this value is not set, it will be equal nil not actor. If you want to make a character look at an actor in a remark, you have to specify it explicitely. Given nil the character will return to an AI-calculated position.
Standard signals for remark:
- sound_end
- when the sounds finish playing
- anim_end
- when the animations finish playing
- action_end
- when both finish, if synchronized
An example of using animation and sound in a remark scheme:
[remark] anim = animation snd = sound snd_anim_sync = true on_signal = action_end | next scheme
sleeper scheme
Scheme for a sitting or slipping NPC. It must have a path consisting of at least one waypoint. The sleeper will sit down at the zeroth point of the path and face in the direction of the first point.
[sleeper]
- path_main
- path name
- wakeable = true
- whether the character can wake up quickly (if true, he will sleep squatting and will mumble in his sleep)
If the path constsists of two points, there should be a link from the first to the zeroth (or a bidirectional one).
File: \gamedata\scripts\xr_sleeper.script
kamp scheme
Scheme for a stalker sitting in a given radius from a given point (by a campfire) and facing this point.
[kamp]
- center_point = kamp_center
- name of the point at which the NPC will be dislocated
- radius = 2
- how far the NPC will be from the camp center; 2 by default
- def_state_moving = run
- default state in which the stalker will go towards the point
File: \gamedata\scripts\xr_kamp.script
If the camp point is inside a campfire, then in offline mode stalkers will approach it, then in online mode they will be inside the fire and will be damaged. To avoid this, in the camp section set path_walk from a point called <path_camp_name>_task.
path_walk = <path_camp_name>_task
If the camp point is located in an open field, then there is no need for adding path_walk.
camper scheme
Camper properties:
- campter stands at a spot and looks in the direction in which you set him in the editor or moves along patrol paths
- campers switch to all-purpose combat when they see an enemy closer than 30 meters away. If a camper survives, he returns to camper mode.
- In all other situations act according to their own scripting scheme. If an enemy is in sight — shoot. If danger is heard — look in its direction. If a grenade is spotted — run away from the grenade. If an enemy was in sight, but disappeard, look in the direction of last sighting of the enemy.
- campers do not move and attack. If they see an enemy, they stop, shoot, then continue movement.
[camper]
- path_walk = patrol_path
- path_look = patrol_path
- radius = number
- distance in meters; if the distance between the camper and the enemy is less, camper switches to all-purpose combat mode; 20 by default
- no_retreat = true/false
- true if the character will not go towards the nearest path_walk point upon enemy sighting, but starts attacking him immediately. Needed in case you wont to create a scene with some guys hitting on some others. Set this flag for the campers. They walk along their patrol points and take out the enemies.
- def_state_moving = state manager state
- a state in which we move to the nearest point upon an enemy sighting
- def_state_moving_fire state manager state (sneak_fire)
- state in which we shoot the enemy while moving towards the nearest path point
- def_state_campering = state manager state (hide)
- state in which we ambush an enemy while remaining on the path
- def_state_campering_fire = state manager state (hide_fire)
- state in which we shoot an enemy while moving along the path
- attack_sound = sound scheme name
ability to overwrite attack sound for snipers/campers; it can be disabled by writing "attack_sound="; fight_attack by default
- shoot - type
- attack type
- always
- shoot whenever possible; default value
- none
- do not shoot
- terminal
- shoot only at the last path point; added to make scripted scene creation easier
The camper has a large drawback — when he is hit and he does not know where the hit comes from (because he does not see the enemy or does not hear the shot), he daftly remains standing at the old spot and wait for the next bullet. In sight of this, you should not set campers to guard a position if there are several directions from which the player or other stalkers can attack the camper. Use walkers in such cases; while setting campers to attack along paths or using them as snipers.
sniper scheme
A variety of camper. Differs by shooting only single shots and not looking along patrol points, but rather scanning space between them. Scan speed between two points is fixed at 20 seconds. Note: set only two look points for a sniper.
Write the following in custom data:
sniper = true
File: \gamedata\scripts\xr_camper.script
follower scheme
NPC follows an NPC leader. If the leader is closer than 5 meters, he walks, if 5 to 20 — runs, if more than 20 — sprints. Paths are not set.
[follower]
- leader = number
- story id of the leader from game.ltx
- formation_line = true/false
- try to stay to the side of the leader, otherwise walk behind
- distance
- distance in meters to keep away from the leader at; 1.5 meters by default, if walks in a chain, then 5 meters
- state_if_leader_in_meet
- a string with a state name from state_manager, which will be set by the follower if the leader is in the meet state
- anim_walk
- state for the follower to walk behind the leader in
- anim_run
- state for the follower to run after the leader in
- anim_sprint
- state for the follower to sprint after the leader in
File: \gamedata\scripts\xr_ attendant.script
If all of this happens in a gulag, then story_id of the leader should be replaced by his logic sections in the script file. Example:
t = { section = "logic@bar_arena_follower_2", idle = 0, prior = 7, state = {0}, squad = squad, group = groups[0], in_rest = "", out_rest = "", dependent = "logic@bar_arena_leader", predicate = function(obj) return obj:character_community() == "dolg" end }
zoneguard scheme
There are two zones for the NPC (or one). He walks along paths, but when the player enters the first zone, drops everything, runs up to the player, points a weapon at him (might also yell or talk), if the player enters the second zone — attacks him
[zoneguard]
- path_walk
- path_look
- team
- name of a team of synchronized zoneguards (only one from the team will react to the player)
- zone_guard
- the name of the zone in which the player will be attacked
- zone_warn
- the name of the zone in which to start a conversation with the player
- walker_team
- team to set it in walker mode (will be the same as team if not set)
- no_move
- will yell to the player from the spot, and not run towards him
- snd_greet
- name of the sound scheme from which to play a sound on finding the player
- ignore_friends
- if true, will ignore friendly characters
- ignore_cond
- {+info -info =func !func} conditions for ignoring the player
- no_danger
- if true, will not play the threat animation to neutrals
- anim
- animation to play if not hostile to the player
- snd_anim_sync
- if true, will synchronize sound with animation
File: \gamedata\scripts\xr_zoneguard.script
wounded scheme
[logic] wounded = wounded [walker] wounded = wounded [wounded] hp_state = HP|condstate@condsound|HP|condstate@condsound hp_state_see = HP|condstate@condsound|HP|condstate@condsound psy_state = PSY|condstate@condsound|PSY|condstate@condsound hp_victim = HP|condvictim|HP|condvictim hp_cover = HP|condbool|HP|condbool hp_fight = HP|condbool|HP|condbool syndata = state@sound|state@sound help_dialog = story_id help_start_dialog = story_id
Where:
- condstate
- condition list returning the character's state, or true. The NPC will become mad at the player if true is returned.
- condsound
- condition list returning the sound scheme
- HP
- health point bounding values
- PSY
- psychological state boundary values
- condvictim
- condition list returning the direction to look at. Possible values: nil, actor, number. In case of a number, will look at the player with the corresponding id.
- condbool
- condition list returning true or false
Field values:
- hp_state
- character's behavior in absense of the player in site
- hp_state_see
- character's behavior on seeing the player
- psy_state
- character's behavior on psy attacks
- hp_victim
- point to look at depedning on HP
- hp_cover
- go to cover or not, based on HP
- hp_fight
- combat allowed or not, based on HP
- syndata
- synch pairs, for effect
- help_dialog
- story_id of a dialog to use instead of teh default actor_help_wounded. If the plot demands that you replace this dialog with another, you specify the id in this field.
- We also add a dialog for the wounded. If we set it, all actor's dialogs for the wounded should have this precondition: dialogs.allow_wounded_dialog.
The default settings for example:
hp_state = 30|help_me@help|10|wounded_heavy@help_heavy hp_state_see = 30|wounded@help_see|10|wounded_heavy@help_heavy psy_state = 50|{=best_pistol}psy_armed,psy_pain@wounded_psy|20| {=best_pistol}psy_shoot,psy_pain@{=best_pistol}wounded_psy_shoot,wounded_psy hp_victim = 30|actor|10|nil hp_cover = 30|true|10|false hp_fight = 30|true|10|false syndata = wounded@help
Where:
- best_pistol
- a check to make sure the NPC's best weapon is not a pistol
File: \gamedata\scripts\xr_wounded.script
rest scheme
The dude walks, eats, sleeps.
Does not really work yet.
File: \gamedata\scripts\xr_rest.script
heli_hunter scheme
Helihunter might shoot or not shoot at a helicopter, depending on conditions. This is how it works:
[camper@bar_freedom_attack_sniper_1] path_walk = camper_1_walk path_look = camper_1_look on_info = {+bar_freedom_attack_ecolog} camper1@bar_freedom_attack_sniper_1 %= bar_freedom_angry_actor% meet_talk_enabled = true meet_dialog = bar_svoboda_dialog heli_hunter = {-bar_ecolog_crush_heli_down} true, false
patrol scheme
Here is a preliminary patrol system. It is a variety of kamp, except in walking mode. To make it work, add the following to custom data:
[patrol]
- path_walk = path_walk
- path_look = path_look
- formation = back
- describes the formation type, and is required. Can be one of the following
- back
- line
- around
- commander = true
- sets the commander; there should be only one
- move_type = patrol
- sets the initial movement mode, patrol by default. This value is a walking animation from state_mgr_lib
When the commander stops at meet, the guys stop
If the commander dies, another one is chosen automatically. The first to enter the scheme is chosen. Formation at waypoints is done like this:
- ret=0...2
- 0 - line
- 1 – around
- 2 – to the sides
When the commander moves, he works like a regular walker, and the others follow his actions. That is, if the waypoint is set to a=assault, the commander will rush forward with his weapon at ready, and the others copy him.
What does not really work:
- there is no way to modify formation
- everyone is quiet
- commander does not give commands
- it is not recommended to use sprinting
Sections
combat section
Shows what happens when the NPC goes into battle.
on_combat = combat
[combat]
- on_info = %+info -info =func%
- affects for each round of combat
To set up the various types of scripted battles use the parameter combat_type
In the following example, the stalker fights:
- as a campter, if enemy=actor and is further than X meters
- as Monolith, if any enemy is further than Y meters
- engine-controlled otherwise
[logic] active = walker on_combat = combat [walker] path_walk = ... [combat] combat_type = {=fighting_actor =fighting_ge_X_meters} camper, {=fighting_ge_Y_meters} monolith
An example of such a function: we need the NPC to switch to campter combat when distance is above 20 meters.
function fighting_dist_ge_20(actor, npc) return db.storage[npc:id()].enemy:position():distance_to ( npc:position() ) >= 400 end
400 is 20 m. We specify the square of the necessary distance to conserve system resources.
One more example. The stalker moves under the simulation, but his combat is not engine-controlled, but always zombie-style.
[logic] active = nil on_combat = combat [combat] combat_type = zombied
If different character sections require different types of combat or different conditions, you can use the override combat_type.
Remember: the override will always take priority over the combat section settings. That is, if you have logic for five sections and you need camper combat, but monolith combat in fifth, you can do it like this:
[logic] active = walker1 on_combat = combat [walker1] ... [walker2] ... [walker3] ... [walker4] ... [walker5] ... combat_type = monolith [combat] combat_type = camper
- scheme
- sets combat type: monolith, camper, zombied; otherwise, all-purpose combat is used
- disable_combat_handler
- the function disables the combat section.
File: \gamedata\scripts\xr_combat.script
death section
The section shows what happens when an NPC dies.
on_death = death
[death] on_info = %+info -info =func%
File: \gamedata\scripts\xr_death.script
hit section
Shows what happens when an NPC is damaged. Note that on_hit does not react to the sound of a shot, but only a direct hit! This is done, because the sound of a shot should not be percieved as aggression in general (the player might be shooting dogs, but ending up provoking guards, for example).
on_hit = hit
[hit] on_info = %+info -info =func%
File: \gamedata\scripts\xr_hit.script
actor_dialogs section
Shows which dialogs will be available to the player when speaking with this NPC. Can be used in almost any scheme.
actor_dialogs = actor_dialogs
[actor_dialogs]
- id
- comma-separated list of available dialogs
- disable
- comma-separated list of disbled dialogs
File: \gamedata\scripts\xr_meet.script
use section
This section shows what will happen if the player tried to "use" the NPC.
on_use = use
[use] on_info = %+info -info =func%
File: \gamedata\scripts\xr_use.script
combat_ignore section
If an NPC is in this scheme, then he enters into combat mode. In any other scheme:
[walker]
- combat_ignore_cond = {+info –info =func !func}
- condition for ignoring combat (if you write always then the character will always ignore combat in this schema, untill switching to a scheme that does not ignore combat)
There are no additional fields in the scheme:
[walker]
- combat_ignore = combat ignore
[combat_ignore]
Functions used for wark with the combat ignore condition list:
- fighting_dist_ge_20
- current enemy at distance equal to or greater than 20 m
- fighting_dist_ge(distance in meters)
- all-purpose function for combat_ignore, checks for distance from the player
- fighting_actor
- is actor the current enemy?
- check_fighting
- check (by story_id) to see if anyone from the list is an enemy
File: \gamedata\scripts\xr_combat_ignore.script
dont_spawn_character_supplies section
If this section is set, then the standard set of loot specified in the profile won't span inside him.
[dont_spawn_character_supplies]
no_smart section
If this section is present, the NPC cannot be controlled by the smart terrain, even if it fits all the parameters.
[no_smart]
treshhold section
There is a way to change stalkers' parameters that determine how they attack monsters. There are two such patameters:
- max_ignore_monster_distance
- (currently 15 m by default). The stalker will always attack monsters within a certain radius.
- ignore_monstre_threshold
- (currently 0 by default) Parameter 0 to 1. If the monster is evaluated at below this parameter, and the monster is outside the given radius, it will be attacked. Currently, stalkers never attack anything outside the 15-meter radius.
In the logic section or in the current sheme set:
threshold = threshold@tratata [threshold@tratata] max_ignore_distance = <number> ignore_monster = <number>
Be very careful about changing the second parameter.
Danger section
Settings can only be set in some scheme, such as:
[walker] danger = danger_condition [danger_condition] ignore_distance = 50 ignore_distance_grenade = ignore_distance_corpse = ignore_distance_hit = ignore_distance_sound =
Distance is set in meters. You can also set the amount of time to wait for danger, depending on type:
danger_inertion_time_grenade = danger_inertion_time_corpse = danger_inertion_time_hit = danger_inertion_time_sound =
Default setings:
danger_inertion_time_grenade = 20000 danger_inertion_time_corpse = 10000 danger_inertion_time_hit = 60000 danger_inertion_time_sound = 15000
Note! These settings also apply to the camper scheme. That is, danger_radius does not work in camper settings. The data is taken from the danger section.
The algorithm works like this: first check if distance to the source of danger is not matched by ignore_danger. If the danger is closer, then its type is analyzed and is matched against the corresponding distance. If the danger is closer, then reaction to it is permitted.
The following defaults are currently used:
ignore_distance = 50 ignore_distance_grenade = 15 ignore_distance_corpse = 10 ignore_distance_hit = 50 ignore_distance_sound = 50
Note: if you need a stalker to react to different types of dangers in different situations, create several danger sections: danger_condition@1, danger_condition@2, etc.
- danger_expiration_time
- the amount of time after which danger can be disregarded; 5000 by default
- danger_inertion_time
- the amount of time after which a character can forget about a danger he has reacted to; 10000 by default
stories section
Camps do not tell stories automatically. You have to "teach" certain stalkers a few stories. To do this, add the following section to custom data:
[game_info] stories = "story_01, legend_01"
The quotation marks contain a comma-separated list of stories and legends. There are currently the following stories and legends:
- story_01
- edge of the Zone and grenade in one move
- story_02
- about the anomaly and the rocks
- story_03
- about Vilnov's group's return
- story_04
- about the time Kostia Fedorin encountered an artifact and disappeared from the radar
- story_05
- about the fight with a controller
- story_06
- about the door, the vodka, and the house
- legend_01
- about the alien experiment in the Zone
- legend_02
- about secret laboratories in the Zone
- legend_03
- legend of the guide
- legend_04
- legend of the Dark Stalker
- legend_05
- legend about not sleeping deep in the Zone
dont_spawn_loot section
All sorts of storyline characters might have to be empty after dying; for example: the wounded and the captive. To accomplish this, use the section:
[dont_spawn_loot]
Overrides
Settings that modify behavior of general schemes, depending on the currently active scheme (all optional).
- meet_enabled = true
- fire a flare for a metting
- meet_talk_enabled = true
- adds a possibility of a dialog to the current scheme
- meet_dialog = <dialog name>
- dialog to fire on use
- meet_state = <state name>
- sets the character's state for when a dialog opens
- wounded_enabled = true
- enables the NPC to use the wounded scheme
- combat_ignore_cond
- see above
- combat_ignore_keep_when_attacked = true
- the character ignores combat, even if shot at (but only if shot at by the player!)
- combat_type = {condition} scheme
- combat type to be used NPCs from this scheme
- on_combat
- see above
- companion_enabled = true
- free stalkers will join you as companions (will also charge for it in future)
Monster schemes
mob_walker scheme
Works the same way as the regular walker, except for a few differences:
path_walk flags:
- s=sound scheme
- (idle, eat, attack, attack_hit, take_damage, die, threaten, steal, panic, growling)
- с
- crouch from then on
- r
- run
- sig=signal_name
- set the given signal for xr_logic
path_look flags:
- t=time
- time to wain in milliseconds while looking at a point
- a=anim_set
- animation (stand_idle, sit_idle, lie_idle, eat, sleep, rest, attack, look_around, turn)
In custom data set:
[walker]
- path_walk
- path_look
- no_reset = true/false
- (required) do not reset the action of the previous scheme (sound, for instance); false by default
- actor_friendly = true/false
- (required) the monster never attacks first, although if the monster is attacked by the player, this flags is disabled; false by default
- npc_friendly = true/false
- (required) the monster never attacks first, even if the player is hostile
- friendly = true/false
- (required) the monster does not attack the player or other monsters. If they act aggressive, remembers them as enemeies and remains friendly to all; false by default
File: \gamedata\scripts\mob_walker.script
You can also control the bloodsucker's invisibility:
[mob_walker] ...
- state = vis
or
- state = invis
Also, the flag b (behavior) can be used in a mod_walker's path with the same parameters:
wp00|b=vis wp00|b=invis
mob_eluder scheme
The monster moves along the patrol waypoints (without considering connections between points), keeping at a distance from the player, keeping its course, exiting the scheme upon getting too close to the player and returning back when the distance increases.
- path
- works as path_walk
- Time_capture
- (required) the time in seconds the monster spends in this scheme; 10 by default
- Time_release
- (required) the time in seconds the monster spends in the all-purpose scheme; 10 by default
- Min_dist
- (required) distance in meters under which the monster switches to the all-purpose scheme; 5 by default
- Max_dist
- (required) distance in meters over which the monster switches to the eluder scheme; 10 by default
Note: unstable.
File: \gamedata\scripts\mob_eluder.script
mob_remark scheme
Remarking scheme, but for monsters, not stalkers.
- state
- a specific state for the given monster (invisibility for a bloodsucker)
- dialog_cond = {+info, =func, -info, !func}
- conditions for opening a dialog
- anim
- comma-separated list of monster's animations
- anim.head
- comma-separated list of head animations
- tip
- which symbol is highlighted when the cursor is over it
- snd
- which sound it emits
- time
- animation playback time, used only for debugging
File: \gamedata\scripts\mob_remark.script
The trader is made using this scheme.
mob_combat, mob_death schemes
Works exactly the same way as the corresponding schemes for stalkers.
Files: \gamedata\scripts\mob_combat.script, \gamedata\scripts\mob_death.script
mob_jump scheme
Serves to make monsters jump without any checks and limitations (such as distance, angle). Position is set with a patrol path, offset and the physical jump factor.
Example:
[logic] active = mob_jump [mob_jump] path_jump = path ph_jump_factor = 2.8 offset = 0,10,0 on_signal = jumped | nil
- path_jump
- path, wich which we set 1 target jump point (with zero index). The real point accounts for the position path_jump[0] + offset.
- offset
- displacement along axes x,y,z, with which the a real point in space is set (might not be located at an AI node)
- ph_jump_factor
- affects jump timing. Visually, it sets the curve of the jump. The higher it is, the sharper and faster the jump. This scheme allows creating a jump from one roof to another, jumping out a window, jumping over a barrier, etc. 1.8 by default
Note: mob_jump is more of an action than a state. When a monster switches into it, it turns in the direction of the jump and jumps, raising the signal jumped. That is, on_signal=jumped|<scheme name or nil> is a necessary parameter in the scheme, so that it is known what to transition to next.
The first point of the path (0 index) is used to pick the position.
Mob_camp
Mechanic:
- Crouches, looks at a point.
- Can set several positions and times of changing position.
- Runs between positions.
- Switches to an all-purpose scheme (combat, panic) at the sight of an enemy.
- Minimum and maximum distances from the enemy to the current camp position are set.
- If the enemy walks away too far, the monster returns to position.
Usage:
[logic] active = mob_camp [mob_camp] path_look = way_look path_home = way_home time_change_point = 30000 home_min_radius = 20 home_max_radius = 50
- skip_transfer_enemy
- if this is added to custom data, the monster will not get an enemy from other monsters, if sees him (monsters have to be in different groups for this)
Parameters:
- path_home
- path consisting of the monster's locations
- path_look
- path consisting of locations for the monster to look at
- time_change_point
- time in milliseconds to change the current camp point; 10000 by default
- home_min_radius
- minimum radius in meters from the enemy to the camp point; 30 by default
- home_max_radius
- maximum radius in meters from the enemy to the camp point; 40 by default
Special features:
Minimum and maximum radii are necessary for ignoring enemies that run too far away to return to the current position. The enemy's distance to the current position is considered. If the distance is greater than home_min_radius, attack the enemy until the enemy disappears or distance exceeds home_max_radius. Two distances are needed to avoid the situation in which the player stands on the border of the radius and enters/exits the zone, and makes the monster run off and back.
- the current position is chosen randomly
- path_home and path_look path indices must coincide (monster sits at a point of path_home and looks at a point of path_look)
The only required parameter is path_look. If path_home is not set, then the current node and the object's spawn node are concidered.
To make the monster look in different points at a camp position, path_look can consist of several points.
Requirements:
- home_min_radius < home_max_radius
- path_look and path_home must have equal number points
P.S.: mob_camp can be used as an alternative to monsters under restrictors
Mob_home
This scheme is another way to replace restrictors. I recommend to make all monster gulags with mob_home.
Example:
[mob_home] path_home = path1 home_min_radius = 10 home_max_radius = 30
- aggressive_home
- monsters run, not walk towards the designated path_home
Monsters keep the path_home points. They attack an enemy if the enemy is within the home_min radius, otherwise hide. This implies that home_min should be made such that there would be enough covers inside. In idle they typically also go to cover. Home_max should be made like the largest restrictor in the "nest" scheme.
Added the ability to set minimum and maximum radius for the mob_home scheme in flags of the first point (path_home). Flags minr and maxr have been added for this purpose. In case radii are set both in the section and in the flags, the radius is taken from the section. Is neither is set, the values 20 and 40 are used, respectively.
Mob_fake_death
Is necessary for scenes in which zombies rise around the player as he walks.
Usage:
[logic] active = mob_fake_death [mob_fake_death] on_actor_dist_le = 5 | nil
The zombie stands up when the scheme begins, falls down when it ends.
Monster overrides
- actor_friendly
- if true, the monster does not attack the player until attacked first
- npc_friendly
- if true, does not attach the player or other monsters until attacked first
- friendly
- if true, does not attack anyone until attacked first
- braindead
- if true, ignores all attacks
Monster sections:
[mob_death], [mob_hit]
spawner section
This section, which both NPCs and monsters have, spawns them (makes online) with a given codition. To make them appear in a given point, they should have the flag no_move_in_offline in the level editor and can_switch_offline should be off. The spawner is added to custom data before the logic section. It works like this:
[spawner] cond = {+info -info =func !func}
Note: if the spawn condition is not met, the object is not spawned, but if it has been spawned and the condition stops being met, the object will be made offline by the spawner.
Example:
[spawner] cond = {=is_day} ; object spawns during the day and moves into offline during the night
After the object is spawned, it is taken under control by the logic script.
Spawning day and night monsters
[spawner]
- cond = {=is_day}
- only spawn the monster at day; to make it night only, write !is_day
- check_distance = true
- check to see if the player is nearby
- min_distance = 100
- do not spawn if the player is closer than this (150 by default, but this is really too much)
Logic script
Overview
- Note: If you want to spawn some object for an NPC from custom data, the description for this is in the "general" section of character profile settings (do not write the supplies tag!)
Script logic controls scheme switching. Customdata for every character (except the free ones) must have a [logic] section.
Functions references by the [logic] section must be placed in files \gamedata\scripts\xr_effects.script or \gamedata\scripts\xr_conditions.script.
The section must contain one of the fields:
- active
- the active scheme to be ran first
- cfg
- name of the Ltx file with settings
If cfg is set, then the file contents will be used for the character's settings. For example, settings of a regular walker:
[logic] active = walker [walker] path_walk = walk1 path_look = look1
Scheme switching is carried out with the additional conditions of the logic scheme, which are set in the section of the current active scheme. There exist the following switch conditions:
- Note: If logic switches between several schemes having the same names (such as several walkers), then they can be numbered (walker1, walker2) or more informative names can be given after @ (walker@day, walker@alarm).
- on_actor_dist_le = number | scheme
- distance to the player <= number
- on_actor_dist_le_nvis = number | scheme
- distance to the player <= number without a visibility check
- on_actor_dist_ge = number | scheme
- distance to the player > number
- on_actor_dist_ge_nvis = number | scheme
- distance to the player > number without a visibility check
- on_signal = signal | scheme
- fires on signal from the active scheme
- on_info = scheme
- always fires
- on_timer = msec | scheme
- fires after the given number of ms after the scheme becomes active
- on_game_timer = sec| scheme
- fires after the given number of game seconds after the scheme becomes active
- on_actor_in_zone = restrictor_name | scheme
- if the actor is in the zone (restrictor name is given)
- on_actor_not_in_zone = restrictor_name | scheme
- if the actor is not in the zone (restrictor name is given)
- on_npc_in_zone = npc_story_id | restrictor_name | scheme
- if an NPC is in the zone (NPC id and restrictor name is given)
- on_npc_not_in_zone = npc_story_id | restrictor_name | scheme
- if an NPC is not in the zone (NPC id and restrictor name is given)
- on_actor_inside = scheme
- the zone checks if the player is inside
- on_actor_outside = scheme
- the zone checks if teh player is outside
You can work with any of the parameters listed above like this:
on_info = {....} %...% on_info2 = {....} %...% on_info3 = {...} %...%
And so on.
You can also use conditions:
combat_ignore_cond = on_hit = on_death = on_combat = on_use =
Logic script syntax
Example: to make a character walk along the path walk1, but switch to path walk2 when the player comes within the distance of 5 meters (given that he sees the player), you should write the following:
[logic] active = walker1 [walker1] path_walk = walk1 path_look = look1 on_actor_dist_le = 5 | walker2 [walker2] path_walk = walk2 path_look = look2
That was unconditional section switching. Before the section name in curly braces {} you can set additional conditions, and after the section name the so-called "effects", which should be enclosed between percent signs %%. Effects will be applied only in case a section is activated. You can omit section name and only set conditions and/or effects. Then only the old section will remain active, but the conditions and effects will nevertheless be processed. If all conditions in curly braces fail, the section will not be activated.
Example:
on_actor_dist_le = 5 | {условие} walker2 %effects%
You can have the following conditions:
- +infoportion
- the actor must have the infoportion
- -infoportion
- the actor must not have the infoportion
- =func
- the function must return true
- !func
- the function must return false
You can have the following effects:
- +infoportion
- the actor will get this infoportion
- -infoportion
- the actor will loose this infoportion
- =func
- the function will be executed
Several conditions or effects should be separated with spaces:
on_actor_dist_le = 5 | {+info1 -info2 +info3} walker2 %+info4 =func%
You can set several sections separated by commas. They will be hanled from left to right. After the first condition fires, the handling stops. In the example below, if info1 is set, then walker2 is enabled, if info2 is set, then walker2, otherwise walker4:
on_actor_dist_le = 5 | {+info1} walker2, {+info2} walker3, walker4
You can calso set conditions in the above field active of section logic, such us:
[logic] active = {=actor_friend} walker@friendly, walker@enemy
You can use the keyword never in logic sections, which means that the condition is false. For example:
combat_ignore_cond = {=actor_enemy =actor_has_suit} always, {=actor_enemy} never %...effects...%
The above section enables combat ignoring if the NPC's enemy is the player is wearing a suit, but disables it if the player is not wearing suit. In this case the effects of the never section will work. Choosing the never section is equivalent to not having a section, but effects between percentage signs work.
Here is an example of work with the nil section. The nil section takes a character, monster, or object from under a scripted scene and puts him in the engine's control. This is necessary if some condition does not need to be checked again after firing off once. This saves resources that would otherwise be wasted on checking the condition.
[logic] active = sr_idle [sr_idle] on_actor_inside = nil %+esc_actor_inside%
That is, after the actor enters the restrictor, he gets an infoportion, and the restrictor moves into the nil section, not checking for the player anymore.
Note: scripts cannot be returned from the nil section!
An example of fairly complex logic
[logic] active = walker combat_ignore = combat_ignore on_hit = hit on_death = death [hit] on_info = %+alert% [death] on_info = %+alert +trup3% [walker] path_walk = walk_svoboda3 path_look = look_svoboda3 combat_ignore_cond = {-alert} on_timer = 25000 | remark [remark] anim = idle snd = stalker_talk_kampfire no_move = true no_rotate = true on_hit = hit on_death = death combat_ignore_cond = {-alert} [combat_ignore]
Lets look at this step by step. At first, the stalker works according to the walker scheme. While at it, he ignores combat until the alert infoportion is set. Then he waits 25 seconds and switches to the remark scheme. In remark he plays an idle animation, chats on specified subjects, does not turn, does not move, still ignores combat. If he is hit or killed (on_death), he will get an alert infoportion and stops ignoring combat (obviously, if he is a corpse, that won't help, but there are three of them on the scene, and then the rest will spring into action). If he is killed, he will also get a trup3 infoportion, which will announce that this stalker is dead.
Now, here is his opponent's logic:
[logic] active = walker combat_ignore = combat_ignore [walker] path_walk = soldier_walk1 path_look = soldier_look1 combat_ignore_cond = always team = assault_group on_signal = assault | camper [camper] path_walk = soldier_walk1_2 path_look = soldier_look1_2 radius = 5 on_info = {+trup1 +trup2 +trup3} walker2 [walker2] path_walk = soldier_walk1_3 path_look = soldier_look1_3 [combat_ignore]
He is in the walker scheme, ignores combat (in any situation, by the way). He is part of the assault_group. When he comes to the endpoint of his route (where he is synchronized with the rest of the group, as is specified in the paths) he gets the assault signal and switches to the camper scheme. In this scheme he does not have combat_ignore specified and, therefore, starts shooting at the enemy. After all three oppponents are dead, with them setting infoportions trup1, trup, and trup3 upon dying, he switches to walker2 (goes to the campfire).
space_restrictor logic scheme
General comment: to avoid situations, in which the actor rushes through a restrictor before it goes off, try to make restrictors at least 2 meters wide.
[sr_idle] scheme
The purpose of this scheme is to switch to another scheme when one of the standard logic conditions is met. It does not do anything on its own. Example of a restrictor's settings:
[logic] active = sr_idle [sr_idle] on_actor_inside = nil %+esc_actor_inside%
Note that when the check goes off, the active scheme switches to nil, so that it does not continue the useless check on each update. You do not have to set nil. Often this scheme works together with a spawner. The restrictor gives out an infoportion upon entry into the zone, and the spawner uses it to spawn something.
File \gamedata\scripts\sr_idle.script
[sr_no_weapon] scheme
This scheme removes the player's weapon uponn entry into its zone. Example of a restrictor's settings:
[logic] active = sr_no_weapon
[sr_no_weapon]
File \gamedata\scripts\sr_no_weapon.script
[sr_sound] scheme
- snd
- comma-separated list of all sound names
- type
- comma separated list of sound types. For convenience, sound sets were introduced. For instance, to avoid listing the full set of wood floor sound types, you can specify floor_wooden.
- delay
- delay before playing the sounds in seconds of real time; 0 by default
- idle
- duration of time to ignore entry into the zone after the last sound begins. For instance, to make sure howling is no more frequent than once every few minutes. In seconds of real time. 0 by default.
- rnd
- percent probability of playing the sound; 100 by default
- position
- name of the path the points of which to play the sound at. Could be random, meaning a random place in the radius of 15-50 meters of the player. If this parameter is not set, then the player's position is assumed.
- slide_velocity
- speed of movement of the sound along the path; 3 by default
- slide_sound_once = true\false
- true - play the sound once, even if it does not reach the last point
- false – if the sound has ended, but not reached the last point, play it again
- false by default
- play_at_actor = true/false
- forces the sound play continuosly at actor's location. If this is true and the path is set (or is random) the game will crash.
This scheme is meant to be used to play sounds at the actor's entrance in a restrictor.
Supports sound_end.
You must set either snd or type. You can set both. The list of sounds is created based on these parameters. When the actor enters a restrictor, a random sound from this list is played.
Example:
[logic] active = sr_sound [sr_sound] type = floor_wooden snd = ambient\wind1, ambient\sparks1 rnd = 50 position = random idle = 120 delay = 3
You can make a "sliding" sound. You need a patrol path. The sound will start playing at the beginning of the path and move from one point to another (in the order they are set in the path) with the speed slid_velocity.
[logic] active = sr_sound [sr_sound] type = random position = way slide_velocity = 8 slide_sound_once = true
File \gamedata\scripts\sr_sound.script
[sr_tip] scheme
The purpose of this scheme is to give the player a tip on entry into a restrictor.
- name
- news name
- type
- news to send as global news, tips to send with the sender's name; news by default
- sender
- if type is tips then this is the string identifier of the sender character's icon; the dealer's icon by default
- cond
- condition for firing; set to entry into the restrictor by default
- single = true/false
- whether the tip should only be given once; false by default
Example:
[logic] active = sr_tip [sr_tip] name = tips_esc_trader_about_pda type = tips cond = {+infoportion1 –infoportion2 } showtime = msec ; time in seconds the tip will be displayed for; does not work properly
If it should be played only once, and this happens often, you can add the following line:
on_actor_inside = nil
File \gamedata\scripts\sr_tip.script
Sr_light
Zone in which NPCs turn on their flashlights no matter what time of day it is.
Works like this:
[logic] active = sr_light [sr_light] light_on = true/false
Also works with a condition list:
[logic] active = sr_light [sr_light] light_on = true/false on_info = {+info1} section %+info2%
Sr_territory
Catches various events within a restrictor.
Right now, it only catches hits and stalker deaths. It can be used somewhat like this:
[logic] active = sr_territory@outside [sr_territory@outside] on_actor_inside = sr_territory@inside [sr_territory@inside] on_actor_outside = sr_territory@outside territory_hit = {-bar_dolg_territory_1_hit} %+bar_dolg_territory_1_hit%, {-bar_dolg_territory_2_hit} %+bar_dolg_territory_2_hit%, {-bar_dolg_territory_3_hit} %+bar_dolg_territory_3_hit% territory_death = {-bar_dolg_territory_kill} %+bar_dolg_territory_kill%
You can see that when the player is inside the restrictor, the number of hits is counted, and also whether anyone died is considered. Since the scheme only works with the player, only the player's death and hits are counted.
Sr_mapspot
When entering a restrictor, it highlights itself on the map.
Parameters:
- hint
- hint id in string table (required)
- location
- highlight type name; crlc_small by default
Example:
[logic] active = sr_mapspot [sr_mapspot] hint = “gar_swamp” location = crcl_big
Sr_particle
This scheme shows particles, static or moving, in the given place at the given time. It works like this:
For a particle system with a camera path
[sr_particle]
- name = explosions\campfire_03
- particle system name
- path = particle_test.anm
- camera path
- mode = 1
- (required !!!)
- looped = true/false
- whether the partcle playback should loop
(must have extension ANM !!!) Here particles will silently move along a path.
For a particle system with a regular patrol path
[sr_particle]
- name = explosions\campfire_03
- particle system name
- path = part_points
- patrol path name
- mode = 2
- (required !!!)
- looped = true/false
- whether the particle playback should loop
You can set the s=<sound scheme name> and d=<delay time in milliseconds> at waypoints. A sound will be rendomly chosen from the specified scheme. Sound does not loop and plays only once. As a result, particles play in all waypoints simultaneously (with delay, as described above).
When looped=true particles will play again after finishing, but without a delay. There will be no particle_end signal. When looped=false there will be a signal when all particle sources finish playing.
Condition list is supported. If a restrictor switches to a different section, then particles stop playing automatically and their sounds die. This restrictor is an object tracking particles, and there is no reason for the player to enter it.
Sr_sound_act
Scheme playing sounds in the actor's head. Various PDA conversations and other fakes.
[sr_sound_act]
- snd = ambient\random\new_drone1
- sound file name
- delay = 2000
- delay before playback
- delay_max = 4000
- a random interval between delay and delay_max will be used
- on_signal = sound_end | nil
- we can move to another section on signal
- theme = <
- from ph_sound_themes
- stereo = true/false
- When this parameter is set for a file that is set using the single parameter snd, the sound scheme will be automatically appended with suffexes _r and _l for left and right channels, and all that junk will be played; false by default
If a theme is set, then the sound will loop, randomly choosing one of the sounds from the theme. If a sound is set, then it is played once. The scheme supports a condition list.
Sr_timer
Example of use:
[logic] active = sr_timer@1 [sr_timer@1] type = dec start_value = 10000 on_value = 0 | sr_timer@2 [sr_timer@2] type = inc on_value = 15000 | nil %+info1%
Fields:
- type
- counter type: inc or dec; inc by default
- start_value
- starting value in REAL milliseconds. For decrementing counters, settings this is required. For incrementing it is 0 by default.
Switches from section sr_timer can be caused by regular conditons (on_timer, on_info) or by the special condition on_value. In general, on_value should be used for performing some actions based on the counter's state. For example:
on_value = 5000| %+info1% | 1000| %+info2%
Sr_psy_antenna
Zones with this section can control psy-control effects (on Yantar and Radar). Right now you can control radiation intensity and hit intensity.
To use: set the zones, in each zone specify percentage increase/decrease for radiation and intensity. Zones can be nested inside each other and intersect each other.
- eff_intensity
- increase or decrease % of radiation relative to base intensity
- hit_ intensity
- increase or decrease % of hits relative to base intensity
Example of a zone that adds 70% of radiation:
[logic] active = sr_psy_antenna [sr_psy_antenna] =_intensity = 70 hit_ intensity = 70
Example of a zone that removes 30% of radiation:
[logic] active = sr_psy_antenna [sr_psy_antenna] intensity = -30
Sr_teleport
A teleporter. Is configured like this:
[logic] active = sr_teleport [sr_teleport] timeout = 0 point1 = point1 look1 = look1 prob1 = 10 point2 = point2 look2 = look2 prob2 = 20
where:
- timeout
- delay in milliseconds before the teleporter activates
- point
- one-point patrol path to teleport into
- look
- one-point patrol path to turn towards
Settings for destination points with weights follow. That is, in the example above the probability of teleportation into the second point is twice as high as into the first. The maximum number of destination points is 10. Teleporters should be set together with a special anomalous zone.
Sr_sleep and sleep configuration
Makes it possible to set sleep zones.
[sr_sleep]
- cond = <condlist>
- type = nightmare/normal/happy/all
- Sets the type of sleep allowed in the current zone; affects only non-storyline sleep; all by default
- dream_prob = <number 0 from 100>
- probability of non-storyline dreams in the given zone; 80 by default
The optional field cond sets a condition for sleeping in this zone. There is currently an indicator for zones in which sleep is allwed. In bottom left corner a small lungs icon is shown upon entry into such a zone. This icon will possibly be replaced later.
Dreamcast can be either storyline or not. Storline dreams are played when necessary conditions are met. Regular dreams are played when there is no storyline dreams or none of the conditions for them have been met. It is possible to set probabilty of playing regular dreams in general, and also set likelyhood of seening any given dream separately. Regular dreams can have set types, and types can be used to limit sleeps in sr_sleep.
Dream settings are set in file misc\dream.ltx
Videos section
Fields set paths to video fiels with dreams.
Dreams section feilds
- regular_probability = <number from 0 to 100>
- probability of playing regular dreams in general
- regular
- a list of sections with settings for regular dreams
- scene
- a list of sections with settings for storyline dreams
Settings for regular dreams
- dream
- name of a field from the videos section
- probability = <number greater than 0>
- type = nightmare/normal/happy
Settings for storyline dreams
- dream
- name of a field from the videos section
- cond = <condlist>
- to_regular = <probability, type>
- an optional field; gives you the ability to convert a storyline dream into a regular dream; probability and type are analogous to those for regular dreams
Sr_cutscene
This scheme is for animating camera with certain effects.
(pp_effector). Sequence of actions carried out by the scheme consists of immediate placement of the player into the beginning of that path and orientation of his sight towards the look path. The player looses control until cam_effector finishes.
[sr_cutscene]
- point = <path name>
- path into the beginning of which the player is placed
- look = <path name>
- path towards which the player faces
- pp_effector = <effect filename>
- file located in folder gamedata\anims and containing an effect (filename is written without the extension)
- cam_effector = <camera animation filename>
- file located in the folder gamedata\anims\camera_effects and containing a camera animation (filename is written without the extension)
Various settings for objects
[ph_idle]
A section for all physical objects. Supports a condlist. Could be used to transfer objects into when needed.
Doors, [ph_door] section
All folding doors work the same way.
- locked = false\true
- false by default
- Closed = false\true
- true by default
- tip_open = (if locked == false, then tip_door_open, else tip_door_locked)
- the tip that shows up when the door is targeted if the door is closed
- tip_close = (if locked == false, then tip_door_close, else empty value)
- the tip that shows up when the door is targeted if the door is open
- snd_init
- the sound that will be played when the scheme is initiated
- snd_open_start
- the sound that will be played on attempts to open the door
- snd_close_start
- the sound that will be played on attempts to close the door
- snd_close_stop
- the sound that will be played when the door is closed shut
Example:
If you need to make a door that will open with a click on some event, then you can use the snd_init field and switching schemes. In this example, when the ph_door@unlocked is iniated, the snd_init sound is played, that is, trader_door_unlock:
[logic] active = ph_door@locked [ph_door@locked] locked = true snd_open_start = trader_door_locked on_info = {+esc_trader_can_leave} ph_door@unlocked [ph_door@unlocked] locked = false snd_init = trader_door_unlock snd_open_start = trader_door_open_start snd_close_start = trader_door_close_start snd_close_stop = trader_door_close_stop
File \gamedata\scripts\ph_door.script
Buttons, [ph_button] section
When you press a button, this switches sections and gives out an infoportion.
[logic] active = ph_button@locked [ph_button@locked] anim_blend = false anim = button_false on_press = ph_button@unlocked %+cit_jail_door_opened%
- on_press
- what happens when the button is pressed
- anim
- animation to play when the button is pressed
- anim_blend
- smooth animation
File \Gamedata\scripts\ph_button.script
- tooltip
- is there to show a textual hint when the button is targeted. The hint is needed to at least explain that it can be presseed.
Example:
[logic] active = ph_button@active [ph_button@active] anim = lab_switcher_idle tooltip = tips_labx16switcher_press on_press = ph_button@deactivated %+terrain_test% [ph_button@deactivated] anim = lab_switcher_off
To make sure the message stays valid with different keyboard settings, you should use tokens. For example:
<string id="tips_labx16switcher_press"> <text>To disable this magical contraption press ($$ACTION_USE$$)</text> </string>
Here is an example of a button that does not work each time, but only if a certain condition is met:
[logic] active = ph_button@locked [ph_button@locked] anim = button_false; an animation for disabled buttons on_info = {+val_prisoner_door_unlocked} ph_button@unlocked on_press = ph_button@unlocked %+val_prisoner_door_unlocked% [ph_button@unlocked] anim = button_true on_info = {-val_prisoner_door_unlocked} ph_button@locked on_press = ph_button@locked %-val_prisoner_door_unlocked%
Projector
In points of the path towards which the projector points you should write:
sl=<projector name>
For instance: wp00|sl=esc_sl1.
Then when the character turns towards this point, so will the projector.
Combination locks
When a certain code is entered, gives out an infoportion.
[logic] active = ph_code@lock [ph_code@lock] code = 1243 on_code = %+infoportion%
File: \gamedata\scripts\ph_code.script
Ph_gate
Same as ph_door, but for gates made from two halves.
- state
- state in which the door is in after initialization
- open
- closed
- none
- current (default or remaining after the previous scheme)
- locking
- none by default
- stick
- whether the door is attracted to the farmost positions (this is still being set up)
- soft
- the door is blocked by force, so it can be forced or broken through
- open
- blocked in open state
- closed
- blocked in closed state
- none
- unused
- hard
- the door is blocked with boundaries; can only be broken
- open
- blocked in open state
- closed
- blocked in closed state
- none
- blocked in current state
- none
- the door is unblocked
General parameters:
- left_limit, right_limit
- sets the angle [0-180] for opening each half of the gate; 100 by default
- breakable = true/false
- determines whether the gate can be broken; true by default
The sound parameters are the same as for ph_door.
Examples:
[ph_gate@locked] ; blocks in open mode, undestructable state = opened locking = soft left_limit = 130 rigt_limit = 60 breakable = false [ph_gate@opened] state = opened locking = stick [ph_gate@closed] state = closeded
File: \gamedata\scripts\ph_gate.script
Ph_sound
Is specified for every physical object to emit sounds (was initially made for swearning).
[ph_sound]
- snd
- name of a theme from file sound_theme.script from table ph_snd_themes
- looped = true/false
- min_idle
- minimum idle time before the sound is turned on, in ms
- max_idle
- maximum idle time before the sound is turned on, in ms
- random
- if true, then random sounds will be picked from the theme
Note! Setting random=true and looped=true will crash the game.
A condition list is also supported.
This scheme works through the ass, so the looping sound will continue playing, even if the object becomes nil. This means that you should create a new section to play a single short sound, after which (since it will play again and again) set on_signal=sound_end|nil.
An example of such twisted logic:
[logic] active = ph_sound [ph_sound] snd = gar_seryi_shooting looped = true max_idle = 5000 on_actor_in_zone = gar_seryi_factory| ph_sound@end [ph_sound@end] snd = gar_seryi_shooting_2 looped = false on_signal = sound_end| nil
Besides, the sound scheme is created in a particular way. In sound_theme.script at the beginning of the file there is section ph_themes in which themes for physical objects are described.
For example:
ph_snd_themes["gar_seryi_shooting"] = {[[characters_voice\human_01\scenario\garbage\distance_shooting]]}
Besides, (undocumented feature) ph_sounds can be set for restrictors. Although, no one is responsible for this working correctly.
File: \gamedata\scripts\ph_sound.script
Ph_force
This scheme allows one to kick an object in a given direction. Is written in custom data of an object.
- force
- force applied to the object, measured in dead badgers
- time
- durationi of time the force is applied to the object, measured in seconds
- delay
- delay in seconds before the force is applied
- point
- name of a patrol path that is to be used as the target (where the object will point)
- point_index
- index of a point of the patrol path towards which the object will fly
Ph_on_death
Scheme for tracking destruction of physical objects and producing various effects.
Example:
[logic] active = ph_on_death [ph_on_death] on_info = %effects%
To be used only with destructable physical objects.
Ph_car
Settings to let the player control a car.
[ph_car]
- usable = condtion list
- list of conditions returning true (by default) or false
Example:
[logic] active = ph_car [ph_car] usable = {+val_actor_has_car_key}
Based on this scheme, you can make a car that will start only if the actor has a key for it.
Ph_heavy
Is set for physical objects, which are forbidden for throwing by burers and poltergeists. For instance, they should lay in a certain place (such as storyline-related documents) or are too massive to be thrown nicely. В кастом дате пишем:
[ph_heavy]
Ph_oscillate
This scheme is meant for gentle rocking of physical objects (lamps, hanging zombies, etc).
Logic example:
[ph_oscillate] joint = provod ; name of the bone to which force is applied force = 5 ; force (in newtons) period = 1000 ; time at which force is applied
The force is applied to a bone of the object with linear increase. That is, during a period of time the force grows from 0 to the specified magnitude. After this a pause is made (force is not applied) for the time period/2. After the pause ends, the force is applied at the same place, but in opposite direction.
Smart terrains and gulags
Smart terrain
By a smart terrain we mean a zone that, upon entry, captures a stalker in a gulag and makes him do work for this gulag. After a period of time he escapes the gulag and walks free.
How to set a smart terrain? For every smart terrain you have to:
- Set a smart terrain with the required shape. It is not recommended to make them large, since size affects performance.
- Specify the settings in its custom data.
- Set paths for the corresponding behavior schemes.
Custom data parameters:
[gulag1]
- type
- capacity
- max number of people
- offline
- if the gulag can go offline; false by default
- squad
- the squad to set for all stalkers in the gulag (level #)
- groups
- comma-separated list of groups
- stay
- duration of time the NPC remains under the smart terrain; permanently by default
- idle = min, max
- duration of time the smart terrain remains active after the last NPC leaves
- cond
- list of conditions necessary to create a gulag
- {+info -info = func !func} - if the condition is not met, the gulag is disbanded and all its inmates begin to be controlled by logic specified in their custom_data
Gulag type should not be quoted. If either squad or groups is not set, then the corresponding properties of stalkers will not change. All time is set in hours of game time and can be fractional
Path names should always start with the name of the given smart terrain. For instance: esc_smart_ambush_vagon_sleep.
If paths for a smart terrain are for several people (campers, walkers), then their names should always end with a number (esc_smart_ambush_vagon_walk1, esc_smart_ambush_vagon_walk2).
There can be several gulags under a single smart terrain. They can be set in several sections [gulag2], [gulag3], etc. After a stalker enters the smart terrain, one of the available gulags will be chosen at random.
Standard smart terrain types
If you want to prevent a stalker from being captured, add the following line to his custom data:
[smart_terrains] none = true
If the stalker is already under some smart terrain's control, he will ignore the others.
campers
Custom data:
[gulag1] type = campers capacity = от 1 до 3
Paths:
- camper_walk1, camper_look1
- camper_walk2, camper_look2
- camper_walk3, camper_look3
walkers
Could be used to conduct searches, and lots of other stuff.
Custom data:
[gulag1] type = walkers capacity = от 1 до 3
Paths:
- walker_walk1, walker_look1
- walker_walk2, walker_look2
- walker_walk3, walker_look3
search
Custom data:
[gulag1] type = search capacity = 1
Paths:
- search_walk, search_look
Works like this:
- The character walks through waypoints, looks about.
- Stops at certain points, searches (caution, search, hide)
- Utters some phrases while at that
rest
A stalker switches between sleeper, walker, and rest (eats, drinks vodka).
Custom data:
[gulag1] type = rest capacity = 1
Paths:
- rest – two-vertex path (possibly one). He sits in one, looks towards the other.
- sleep - two-vertex path (possibly one). He sleeps in one, looks towards the other.
- rest_walk, rest_look
Gulags
A gulag is a means of joining several stalkers under centralized control. Main features:
- A gulag has a task list. A task is a set behavioral scheme, or a chain of schemes.
- Tasks have priorities.
- A gulag assigns entering stalkers to jobs with highest priority first.
- Gulags have states. Each condition corresponds to a unique set of tasks, different from the set of any other condition.
A gulag is created like this:
1. First, a list of states for the gulag has to be determined: day, night, calm, active, etc. Simple gulags might have only one state, a complex one should have many. This introduces more variety and looks better.
2. Determine the maximum number of people that can be controlled by the gulag. That is, determine the gulag's capacity. It should be such that in any state the gulag should be able to find a task for every person.
3. For every state the gulag should have a list of tasks. These tasks can be active (centry, patrol, etc) or passive (sitting at a campfire, sleep). Each job has its own priority. Correspondingly, passive tasks should have lower priority.
4. Use the editor to set the number of people to be in the gulag and cover it with a smart terrain (it is an error to use space_restictor). The terrain should be given a meaningful name. This name will also serve as a prefix for all patrol paths for this gulag. For instance, if you call the terrain esc_blockpost, then all patrol paths should start with this prefix, as esc_blockpost_guard_walk, for instance. Custom data for the zone should contain settings for the gulag.
[gulag1]
- type
- capacity
- maximum number of people
- offline = true/false
- whether the gulag can go offline
- squad = squad
- the squad stalkers under the gulag are assigned to
- groups
- comma-delimeted list of groups
- stay
- duration of time the NPC remains under the smart terrain; permanently by default
- idle = min, max
- duration of time the smart terrain remains active after the last NPC leaves
- cond
- list of conditions necessary to create a gulag
- {+info -info = func !func} - if the condition is not met, the gulag is disbanded and all its inmates begin to be controlled by logic specified in their custom_data
- respawn
- respawn name (calls the respawner with the given name every time someone from the smart terrain starts working on a task)
Capacity should always be set. It should be less than or equal to the number of tasks.
Gulag type should be unquoted.
The offline field could be used to prevent the gulag from going offline. That is, it can exist in offline mode, but cannot go into it.
Gulag type should not be quoted. If either squad or groups is not set, then the corresponding properties of stalkers will not change. All time is set in hours of game time and can be fractional
5. In script \gamedata\scripts\gulag_<level name>.script you should set the condition under which stalkers are captured by the gulag. The function checkNPC should be appended with the condition:
if gulag_type == "gar_dolg" then return npc_community == "dolg" end
This function takes two parameters: gulag type and character's community. In this case, the the gulag with type gar_dold will accept all characters in faction Dolg.
6. In file \gamedata\scripts\gulag_<level name>.script you should desribe how gulag states should switch.
function loadStates(gname, type)
Takes the name of a zone and gulag type. The gulag's state is described as a function returning gulag state number. For example:
if type == "gar_maniac" then return function(gulag) if level.get_time_hours() >= 7 and level.get_time_hours() <= 22 then return 0 -- day else return 1 -- night end end end
In this case, if it is between 07 and 22 hours, the gulag is in daytime mode, otherwise in nighttime mode.
8. In file \gamedata\scripts\gulag_<level name>.script you should describe a gulag's tasks. The function loadJob loads all the allowed tasks. The function itself takes the following parameters:
function loadJob(sj, gname, type, squad, groups)
- sj
- the gulag task table itself
- gname
- smart terrain name; used as a prefix
- type
- squad, groups
- squad and group table, if we need to override the native stalker groups with some other ones. For each task you should set a squad and a group to assign a stalker to upon recieving a task.
Approximate description of gulag tasks:
The following gulag describes behavior of a single person, but there is usually many more. The given person in zero state (daytime) performs one task, in first state (nighttime) another task.
--' Garbage maniac if type == "gar_maniac" then t = { section = "logic@gar_maniac_camper", idle = 0, prior = 5, state = {0}, squad = squad, groups = groups[1], in_rest = "", out_rest = "", info_rest = "" } table.insert(sj, t) t = { section = "logic@gar_maniac_sleeper", idle = 0, prior = 5, state = {1}, squad = squad, groups = groups[1], in_rest = "", out_rest = "", info_rest = "" } table.insert(sj, t) end
Field descriptions:
- Idle
- pause between repeated execution of the same tasks. There is no pause in this case. Pause is usually set for patrols.
- Prior
- task priority. At first stalkers occupy the higher priority tasks. The higher the number, the higher the priority.
- In_rest, out_rest
- restrictors set for the character for this task
- Section
- section in \gamedata\config\misc\gulag_<level name>.ltx, in which the real behavior scheme corresponding to this task is set.
- the stalker's group will be chosen from the group array set in custom data. The array is indexed starting with 1.
- Info_rest
- sets the name of the restrictor, inside of which the person performing the task is guarded from all dangers
The task description may also contain additional conditions for when the stalker can recieve the task. For example:
predicate = function(obj) return obj:profile_name() == "soldier_commander" end
That is, the given task can only be carried out by a person with the soldier_commander profile.
9. В:\gamedata\config\misc\gulag_<level name>.ltx you should specify which behavior schemes correspond to each task. FOr instance, for the aforementioned gar_maniac:
;---------------------------- ;-- GARBAGE MANIAC ;---------------------------- [logic@gar_maniac_camper] active = camper@gar_maniac_camper [camper@gar_maniac_camper] path_walk = walk1 path_look = look1 [logic@gar_maniac_sleeper] active = sleeper@gar_maniac_sleeper [sleeper@gar_maniac_sleeper] path_main = sleep wakeable = true
Here settings correspond to regular stalker custom data, with the followin differene:
- paths should be specified without a prefix. THat is, if the zone was called gar_maniac, a path on the level might be called gar_maniac_walk1, but gamedata\config\misc\gulag_<level name>.ltx should be specified as simply walk1.
- section names should be appended with @ and the gulag name and, possibly, additional information (such as walker2@rad_antena_gate)
- for each taask, logic section names should be appended @ and the gulag name, additional data, and active behavior scheme for (such as logic@rad_antena_gate_walker2
There is no leader field for gulag tasks. There is the dependent field. A task can only be taken if the dependent task is taken first. For instance, follower can be set only after someone is set to work as the leader (leader's name is now in the dependent field). Correspondingly, the task priority for tasks on which others dpeend should be greater than theirs.
New smart terrain capabilities
New capabilities
- Does not keep stalkers online. The standard online radius works.
- Stalkers go to the nearest task.
- Stalkers go to their workplaces without respect to whether they are online or offline.
- In offline an ST works the same way as in online: switches states, allocates tasks.
- Stalkers can be given conditions for entering certain STs (see below). If a stalker enters an ST, then he will remain in it until his time elapses and the condition is met.
- Tasks can be located in different levels.
- Scripting ST zone is not used for capturing characters anymore.
- Simulation is manifested in migration of characters between different STs.
Allowing characters to enter certain ST
Permissions for characters to enter sertain STs are set in the [smart_terrains] section. In it you can set pairs ST_name = condlist, such as:
[smart_terrains] strn_1 = condition1 strn_2 = condition2
If a condition is met for some smart terrain, it is called exclusive.
If a character has at least one exclusive smart terrain, then he will only agree to go to that one.
If he has no exclusive ones, he will agree to go to any.
There is a reserved combination none=true. If it is set, then the character will not go to any ST. This character will only rely on his own logic.
It is also possible to specify who is accepted by a ST. In addition to the old mechanism (function checkNpc() in files gulag_*.script) you can write in custom data for ST:
communities = group1, group2, ...
If this field is not set, then the old mechanism is used. If it is set, then the ST will only accept characters from the specified groups (but the old mechanism will also be called).
Modifying predicate() functions
In these functions a character information table will be passed instead of game_object. There are fields:
- name
- community
- class_id
- story_id
- profile_name
If you only need snipers to take the task, write the following in the predicate:
predicate = function(npc_info) return npc_info.is_sniper == true end
Online and offline work modes
t = { section = "logic@ЧЧЧЧЧЧЧЧ", idle = 0, prior = 5, state = {0}, squad = squad, group = groups[1], online = true, in_rest = "", out_rest = "" } table.insert(sj, t)
Options for this field:
- online = true
- the character is always online on this job
- online = false
- the character is always offline on this job
- online not set
- the character might switch between online and offline as deems appropriate
A more accessible description of smart terrains
Now, smart terrains for designers. That is, no LUA, just plain English.
To move a smart terrain to a new scheme, do the following:
- Change inside custom data [gulag1] -> [smart_terrain]
-
In custom data of comrades by smart terrain write:
[smart_terrains] sar_monolith_sklad(gulag name) = {condition list} [smart_terrains] none = true
Helicopter logic
General information
- The helicopter has "logic"
- The helicopter does not react to anomalies
- The helicopter cannot collide with level geometry until shot down
- Hits in the area of the cabin in which the first pilot sits are dozens of times more damaging for the helicopter
- Like stalkers, the helicopter has an all-purpose combat scheme
- Helicopter pilots have replicas for the following events: hit, enemy sited, damaged (smoking), falling.
heli_move scheme
General information
Allows the helicopter to fly along a patrol path, control speed, hover, shoot at various targets. The scheme must have path_move set — the path along which the helicopter will fly. It may contain just one point, if the helicopter should hover. It is allowed, but not necessary to set path_look — the path into the points of which the helicopter should look.
The vertices of these points can be anywhere within the boundaries of the level's bounding box. They do not depend on AI nodes.
The helicopter will fly along points without respect of connections between them. It will fly from vertex to vertex in order of increasing number (that is, in the order they were set in the level).
The helicopter will try to follow path vertices exactly. If needed, it can fly precisely under a bridge.
The helicopter will fly as fast as possible. That is, if you set its speed at the next vertex at 10 m/s, while its maximum speed is set to 30 m/s, then it will not start flying 10 m/s right away. It will first speed up to 30 m/s, then on approach of the vertex it will slow down such that it gets to the vertex at 10 m/s.
If a path_move vertex has some flags, the helicopter will look into any of the path_look vertices for which the same set of flags is specified. It will start turning towards the point starting at the previous point of the path. The helicopter cannot currently look towards several path_look points while hovering.
Settings
- engine_sound = true/false
- invulnerable = true/false
- immortal = true/false
- if true the helicopter will calculate damage, but not recieve it
- mute = true/false
- disable default helicopter phrases
- rocket_delay = msec
- is taken from ltx by default; currently 1250
- default_velocity = m/sec
- the helicopter speed, unless other parameters are set
path_move point parameters:
- e
- sets enemy. The helicopter will start firing at this target starting at the previous vertex. If the value is not set, it will fire at the point form path_look corresponding to the given vertex. If e=actor (or e=a) is set, then fire will target the actor. If e=number fire will target the object with the given id.
- w
- which weapon to use. The possible values are: w=1 to use the machien gun only; w=2 to use rockets only. Shoots with everything by default.
- v
- maximum speed in m/s on the path from the given vertex to the next. If this parameter is not set, the value from helicopter.ltx is taken by default.
- dv
- destination velocity in m/s that the helicopter should have on arriving at the given vertex
- die
- kill the helicopter
- flame
- set the helicopter on fire, as if it was damaged
path_look point parameters:
- e
- works the same way as in path_move. The difference is that the helicopter will only start firing at it when it gets to the point of path_move that corresponds to the given vertex.
- w
- works the same way as in path_move
- t
- duration of time during which the helicopter will look at the given point. If this parameter is nto set, then the helicopter will fly by without stopping, but will try to face the vertex while moving.
All-purpose combat scheme
General information
In the general combat scheme, a helicopter is not tied to a path.
The helicopter does not see anyone. The helicopter can only find someone upon recieval of damaged or from a parameter in custom data.
The helicopter shoots at an enemy upon detection. Until then, looks for him, circling the points of last citings. If it does not see the enemy for a long time — forgets him. If the enemy is specified in the current behavior section, he will not be forgotten while the section is in effect.
Settings
There is no separate section for this behavior scheme. Therefore, settings are given in the current behavior scheme:
- combat_ignore = true/false
- true means ignore hits. That is, the helicopter will not try to "take revenge" on whoever hits it.
- combat_enemy = nil/actor/StoryID
- This parameter could be used to give the helicopter a specific enemy:
- nil
- no enemy
- actor
- player
- SID
- id number of the enemy
- combat_use_rocket = true/false
- Whether the helicopter is authorized to use rockets.
- combat_use_mgun = true/false
- Whether the helicopter is authorized to use the machine gun
- combat_velocity = <number>
- Speed in m/s at which the helicopter will circle.
- combat_safe_altitude = <number>
- Height, relative to the highest point of the geometry of the level, below which the helicopter will not decend (can be negative)
The helicopter has the xr_hit scheme. It words the same way as for stalkers. There is a group of functions for working with a helicopter and its custom data in xr_effects:
- heli_set_enemy_actor
- make the actor the helicopter's enemy
- heli_start_flame
- set the helicopter on fire
- heli_die
- destroy the helicopter
Meet_manager
Syntax
[logic] meet = meet [walker] meet = meet [meet] meet_state = 30| state@sound| 20| state@sound| 10| state@sound meet_state_wpn = 30| state@sound| 20| state@sound| 10| state@sound victim = 30| nil| 20| actor victim_wpn = 30| nil| 20| actor use = self use_wpn = false zone = name| state@sound meet_dialog = dialog_id synpairs = state@sound|state@sound abuse = true/false
All of the meeting settings are in a single section. The logic section or the current scheme can be used which section to use. The section set in the logic section affects processing of meetings for free stalkers.
Fields:
- meet_state, meet_state_wpn
- sets animation and voicing for the character, depending on distance to the actor; for when the actor is unarmed or armed, respectively
- victim, victim_wpn
- sets the object at which the character will look; can be:
- nil
- does not look anywhere
- actor
- looks at the player
- story_id
- number of the character at which to look
- use, use_wpn
- use settings; can be one of: true, false, self; if self is used, the NPC will use the player
- zone
- contains a set of restrictor names, as well as animations an sounds the NPC will play, if the player is sighted within a restrictor
- meet_dialog
- starting dialog for the NPC
- synpairs
- contains a set of pairs body_state@sound_theme. If at some set of conditions the meeting plays this condition and this sound theme, they will be synchronized via random body state animations
- аbuse
- true by default; if false, unused opponent will not become bitter
Any line can be set via a condlist. ( {+info1 –info2} ward %+info% )
To make meetings easier to set up, there is a simplified default:
[walker] meet = default_meet
You do not have to set the [default_meet] section itself. All of the settings will be used as default, anyway.
Now to explain how all of this can be used to construct the reaction to the actor that you need.
Situation 1
The character beckons us with his hand, on approach asks us to hide our weapon, then agrees to talk.
[meet] meet_state = 50| hello@talk_hello| 20| wait@wait| 10| ward@wait meet_state_wpn = 50| hello@talk_hello| 20| threat@threat_weap victim = 50| actor victim_wpn = 50| actor use = true use_wpn = false
Situation 2
On sight the stalker asks us to hide our weapon. After this he approaches and talks to us. If we start to walk away or take the weapon out — starts shooting at us.
[meet] meet_state = 50| {+info} threat_fire %= killactor%, walk@ {+info} talk_abuse, wait | 10 | walk %+info%; wait | 2 | threat;state meet_state_wpn = 50| {+info} threat_fire %= killactor%, threat@ {+info} talk_abuse, wait victim = 50| actor victim_wpn = 50| actor use = {-info2} self, false use_wpn = false
Here:
- info
- infoportion that says that we have lowered the weapon or are close enough to the NPC
- info2
- infoportion that is set in the dialog and records that the character has said to us everything he wanted
- Killactor
- function in xr_effects that makes the NPC hostile
Situation 3
The character walks along a patrol path on camp guard. If the player has a pass to the camp, greets him and lets him pass, otherwise first warns, then, if the player gets into the camp, becomes hostile. The dialog depends on whether the player has a pass into the camp or not.
[camper] path_walk = path_walk path_look = path_look meet = meet [meet] meet_state = 30| {+info} wait, threat@ {+info} talk_hello, threat_back meet_state_wpn = 30| {+info} wait, threat@ {+info} talk_hello, threat_back victim = 30| actor victim_wpn = 30| actor use = true use_wpn = true zone = warnzone| {-info} threat@ {-info} threat_back|kampzone| {-info} true@ {-info} talk_abuse meet_dialog = {+info} dialog1, dialog2
Here:
- true
- attack the player instead of animation
- info
- infoportion saying that we have a pass to the camp
- warnzone
- restrictor within which he warns us
- kampzone
- restrictor in which he kills us
- dialog1
- starting dialog if we have a pass
- dialog2
- starting dialog if we do not have a pass
Default settings
By default, meeting has the following parameters:
meet_state = 30|hello@hail|20|wait@wait meet_state_wpn = 30|backoff@threat_weap victim = 30|actor victim_wpn = 30|actor use = true use_wpn = false syndata = hello@hail|backoff@threat_weap
Note: if you need to make it so that a stalker does not speak to the player in this section, set meet=no_meet.
Minimap marks
There is a way to avoid showing stalkers on the minimap and the map (hide blue and red dots). For this, the logic section or the current scheme should have the parameter:
[camper]
- show_spot = false
- to hide stalkers in this section
[walker]
- show_spot = {+info1} false
- a stalker will be hidden if he has infoportion info1
Function arguments
Below we list the set of functions that can be accessed from custom data and to which variables can be passed.
xr_conditions
- fighting_dist_ge(p)
- all-purpose function for combat_ignore, checks distance to the player (in meters)
- distance_to_obj_le(sid:dist)
- checks distance to the object with the given story_id
- this can be used, for instance in the follower section to switch to another section when a stalker walks within a certain distance of the leader (the leader is then somwehere in remark). This situationi occurs when one stalker should approach another while we do not know their positions. If this is used in the follower section, dist should be larger than the follower's distance, since if they are the same, this function will not always work.
- health_le(health)
- checks that NPC's HP <= health
- heli_health_le(health)
- like the above, but for a helicopter
- enemy_group(group1:group2:...)
- checks membership of the enemy to a group (we did not check whether it works correctly)
- hitted_by(sid1:sid2:...)
- checks if a hit was made by one of the listed NPCs. The NPCs are set using their story_id. This function is convenient for in the hit section. Example:
[hit] on_info = {=hitted_by(407:408)} %+val_escort_combat%
- killed_by(sid1:sid2:...)
- like the preceeding, but for a kill; used in the death section
- is_alive(sid)
- is_alive_one(sid1:sid2:...)
- is_alive_all(sid1:sid2:...)
- checks if one, one of serveral, or all NPCs in a list are alive
- is_dead(sid)
- is_dead_one(sid1:sid2:...)
- is_dead_all(sid1:sid2:...)
- like the preceeding, but for death
- check_fighting(sid1:sid2:...)
- checks if any from the list are enemies of the current NPC; typically used in combat_ignore_cond
- gulag_empty(gulag_name)
- checks if a gulag is empty or non-existant
- gulag_population_le(gulag_name, num)
- checks if the number of people in the gulag is <= num
- gulag_casualities_ge(gulag_name:num)
- checks that the casualties in the gulag are => num
- Note! Gulag casualties are not reset, so you should be careful with this function
- signal(string)
- checks if the NPC has the given signal set in the current scheme
xr_effects
- heli_set_enemy(story_id)
- make the NPC with the given story_id an enemy of the helicopter. Only one enemy can be set in one section.
- set_gulag_enemy_actor(gulag_name)
- make the actor an enemy of the current gulag
- hit_npc(direction:bone:power:impulse:reverse=false)
- incur a hit to the NPC. Parameters:
- direction = string/number
- the name of path in the direction of first point of which to hit or the story_id number of a character from which the hit originates
- bone = string
- the name of the bone that is hit
- power
- impulse
- reverse = true/false
- whether the direction should be reversed; false by default
- Example:
[death] on_info = {=killed_by(404)} %=hit_npc(404:bip01_spine1:100:2000)%, {=killed_by(405)} %=hit_npc(405:bip01_spine1:100:2000)%
- set_friends(sid1:sid2:...)
- set_enemies(sid1:sid2:...)
- set the character with the listed story_id numbers friends or enemies of the given NPC
- play_snd(snd_name:delay=0)
- play a sound in the actor's head
- snd_name
- sound path relative to the sounds folder
- delay
- delay before playback; 0 by default, to start playback immediately
- play_snd_now (sid:snd_name)
- play the sound from the given object
- the sound is played from the object with the given story_id without delay with volume 1; the file name, not sound schme name is specified
- hit_obj(sid, bone, power, impulse, hit_src=npc:position())
- incur a hit on the object with the given story_id. Is distinguished by being able to be specified in any custom data. Parameters: actor, npc, p[sid, bone, power, impulse, hit_src=npc:position()]
- sid
- story_id of the object to incur the hit on
- bone
- name of the bone that is hit
- power
- impulse
- hit_src
- optional; the waypoint from which the hit is made on the object; if it is not specified, then the position of the object calling the function is taken
- actor_has_item(section)
- check if the player has this object; the check is made via the ltx section
Functions for working with HUD
- disable_ui_elements(...), enable_ui_elements(...)
- enables/disables HUD elements
- weapon
- show/hide hands with the weapon
- input
- enable/disable keyboard
- hud
- show/hide screen indicators
- all
- enable/disable all elements
Example:
on_info = %=disable_ui_elements(weapon:input)%
There are also shortened versions:
- disable_ui, enable_ui
- called without parentheses and parameters
- analogous to the calls disable_ui_elements(all), enable_ui_elements(all), respectively
Example:
on_info = %=enable_ui%
Function for running camera_effector
- run_cam_effector(file_name)
-
- file_name
- animation file name from folder s:\gamedata\anims\camera_effects without extension
Example:
on_info = %=run_cam_effector(prison_0)%
Functions for running postprocessing
There are two functions for working with postprocessors:
- run_postprocess(file_name:id:loop)
- starts posprocessing
- file_name
- name of a postprocessing file (without extension) from folder s:\gamedata\anims. Write without the extension.
- id
- number of the postprocess; optional; is used in stop_postprocess
- loop - true/false
- whether the posprocess should loop; optional; false by default
- stop_postprocess(id)
- forces postprocessing to stop
- id
- number of the postprocess set in run_postprocess
Function for emptying the actor's inventory into a certain spot
- drop_actor_inventory(path_name)
Example:
on_info = %=drop_actor_inventory(drop_point)%
Sound group configuration
The way to create sound groups:
- Each character is considered to be in a unique soundgroup by default.
- To put several characters into a single sound group, the logic section of each one must contain soundgroup = <text string>
- Sound groups must be unique within each level, or, better yet, within the whole game. For this, add level and scene identifiers to the name of the group, as in: soundgroup = bar_dolg_kampfire1.
- Characters sitting at a camp or walking together in patrol groups or in such similar situations should be put into sound groups.
- To avoid errors, all NPCs logically belonging to a group should have the same team, squad, group.
Example:
[kamp@esc_bridge_post1] center_point = kamp_point soundgroup = esc_bridge_soldiers
Author
GSC Game World