响应系统

From Valve Developer Community
Jump to: navigation, search
English 简体中文

本页面由大康正在翻译中。


The Response System(响应系统)用于决定 NPC(或玩家)在想要说什么或是否说什么时应该使用哪种语言(和/或动画)。

Note.png 注意:本文大部分内容基于 Source 2013 分支。Left 4 Dead Left 4 Dead 介绍了一个重写的响应系统,它执行大部分相同的功能,但具有不同的优化、路径和实用程序,本文尚未完整记录。此增强系统也适用于 Left 4 Dead 之后发布的所有游戏,包括 Left 4 Dead 2 Left 4 Dead 2 。该系统的代码在异形丛生(Alien Swarm)的创作工具中公开可用。

大多数响应系统用户都是为了响应游戏中发生的事件而发言。语音可以从代码或地图的输入中触发。触发语音涉及响应概念,它对应于系统中的响应。概念是用于特定事件的语音类别,例如注意到危险 (TLK_DANGER) 或看到敌人 (TLK_STARTCOMBAT)。虽然一个概念可以单独用于基本和简单的对话,但语音也可以通过各种标准来触发,这些标准描述了与该概念和/或说话者的当前状态和周围世界相关的事物。这允许复杂的对话树涉及不同情况下的不同台词。

例如,当玩家杀死敌方 NPC 时,HL2 情节系列中的npc_alyx会说出TLK_PLAYER_KILLED_NPC概念。这个概念对于与 NPC 相关的条件或它被杀死的方式有额外的标准。如果玩家通过爆头杀死了 NPC,则响应系统将选择需要该标准的响应,这通常会导致艾利克斯称赞玩家的射击或评价这是爆头。

响应系统通常使用scripts/talker目录中的脚本。当它接收到一个概念及其标准时,它会在响应脚本中搜索与其概念和标准相匹配的规则(rules)。当它找到一个时,它会使用该规则的响应(response)或响应选择。响应可以是声音脚本句子,甚至是实例化的排编场景

尽管有这些优点,但大多数 NPC 默认不使用此系统。例如,npc_pigeon默认只使用声音脚本,不使用响应系统。

以下是使用响应系统的地方的快速列表:

关于代码的注释:响应系统通常用于从具有CAI_ExpresserHost<>模板类的CBaseFlex派生的类上,该模板类在CAI_BaseActor上自动实现。所有 NPC 和玩家都已从CBaseFlex派生,因此您通常只想使用CAI_ExpresserHost<>,但响应系统可以使用DispatchResponse()函数以更有限的方式在任何实体上使用,这就是env_speaker的工作方式。GetResponseSystem()可用于使概念搜索特定的响应系统树,如果您计划在没有CAI_ExpresserHost<>的情况下使用DispatchResponse(),则必须将其覆盖。

Purpose

The Response System was created so NPCs, players, etc. use a united and robust system for managing speech. It not only allows developers and writers to create complex dialogue trees, but it also allows modders to easily modify or add new speech to the game without having to write code or modify a BSP file while still having complete control over how and when speech will be used.

This system is best used for speech that comes out of the AI system, since those lines will be spoken many times throughout a game. (e.g. Citizens say something when they reload their weapon. A lot of citizens will reload their weapons during the course of the game.)

Here's an example of a complex dialogue tree from a NPC utilizing the Response System:

  • I just killed an enemy.
  • Did I use a shotgun?
  • "Eat shotgun!"
  • Was the enemy really close?
  • "You got too close!"
  • "Thanks for getting close!"
  • "You're not getting MY head!"
  • "I hate headcrabs!"

You could also use combinations of criteria.

  • Did I use a shotgun against a npc_headcrab really close to me?
  • "You got too close to my shotgun, headcrab!"

You can also control individual lines so they aren't repeated for a set amount of time, or never repeat at all.

Structure

Note.png 注意:'Criterion' is the singular form of 'Criteria'.

The Response System is made up of four core pieces: Concepts, Criteria, Rules, and Response Groups. The way these are used is as follows:

  1. An NPC requests a line of speech for a speech concept.
    • For example, let's say our NPC requests a line of speech for theTLK_SHOTconcept. An NPC speaks this concept whenever they're shot by an enemy.
  2. The NPC gathers a bunch of criteria reflecting the NPC's current state and other relevant data about the state of the world. Many concepts also have modifiers, which are criteria unique to specific concepts which usually reflect the event itself.
    • When the NPC requests a line for theTLK_SHOTconcept, the game assembles the NPC's current health, etc. as part of the default criteria set. Then, it appends the concept's modifiers, which may include the type of enemy that shot them, the amount of damage they took, etc.
  3. The concept and criteria are passed into the NPC's response system, which is normally a single global instance shared by all NPCs.
  4. The Response System searches through its big list of rules.
    • Each rule contains a list of criteria which is tested against the criteria assembled by the NPC. Note that the concept is treated as a high-priority criterion in this phase.
    • Each rule gets a score based upon how many of the criteria are true. If at least one criterion is marked as required and isn't satisfied, the rule will never be chosen. Most criteria are set to be required, but criteria that aren't required simply boost the rule's score.
      • In ourTLK_SHOTexample, there might be multipleTLK_SHOTrules which contain different lines. One rule might contain criteria that test to see if the NPC is very close to the enemy who shot him. Another rule might test to see if it was a specific type of enemy that shot him (such as a Combine Soldier). Another rule might test to see if the NPC has <25% of its health left after the shot.
  5. The Response System scores all of the rules in its list and chooses the one that scores highest. The rule that scores the highest specifies a response group.
  6. A response group is simply a list of possible responses, each of which might be a line of speech and/or animation. One response is selected based on the settings of the response group and the individual responses. When a valid response is chosen, the NPC plays the response.
    • In ourTLK_SHOTexample, let's say the <25% health rule was chosen. This rule would have a response group which might contain a list of lines like "One more shot like that, and I'm done for!", "Oh man, I'm in trouble!", or "I need medical attention over here!"
    • Another rule forTLK_SHOTcould check if the enemy shooting them is a Combine soldier and point to a response group with lines like "That Combine soldier's got me pinned down!" or "Help me with this soldier!". Another rule could check if the enemy is a Combine gunship and point to a group with "That gunship is kicking my butt!" and "Someone help me take down that gunship before it kills me!"
  7. If no rule matches the given criteria (or the chosen response group doesn't repeat itself and has been exhausted), the NPC doesn't say anything.

Concepts

A concept is a string that represents the high-level reason for the character's speech attempt. There are a set of concepts defined inside the code which will be called automatically, but a concept is technically just a special, high-level criterion that characters keep track of. They aren't tied to anything and you can freely create your own in the response file. You can invoke concepts in the code or with an actor'sDispatchResponseorSpeakResponseConceptinput.

Here's a list of some of the predefined NPC concepts used in Half-Life 2:

TLK_HELLO		When I first meet the player.
TLK_IDLE		When I have been idle for a while.
TLK_USE			When the player tries to +USE me.
TLK_PLPUSH		When the player pushes me away.
TLK_STARE		When the player stares at me for a while.
TLK_DANGER		When I sense something nearby that's dangerous (e.g. a grenade).
TLK_WOUND		When I've taken damage.
TLK_HIDEANDRELOAD	When I decide to hide and reload my gun.
TLK_PLYR_PHYSATK	When I've been hit by an object thrown by the player.

Not all NPCs speak all concepts, and not all NPCs speak concepts under the same circumstances. See list of response concepts for a full list.

Criteria Set

Criteria is a set of conditions that contain data related to the speaker's current state and the circumstances of the concept whenever a speech attempt is made. It can be interpreted as a set of KeyValues. Here is an example of a criteria set created by a npc_alyx who's trying to speak because she just killed her current enemy:

concept                = TLK_ENEMY_DEAD          The concept the NPC is trying to speak.
map                    = d3_c17_07               The name of the current map.
classname              = npc_alyx                The classname of the speaking NPC.
name                   = alyx                    The targetname of the speaking NPC.
health                 = 75                      The health of the speaking NPC.
healthfrac             = 0.9375                  The health of the speaking NPC, as a fraction of the NPC's max. (npc_alyx's max health is 80 by default)
skill.cfg              = 1                       The current skill level.
timesinceseenplayer    = 0.090000                The amount of time since the speaking NPC has seen the player.
distancetoenemy        = 312.639679              The distance from the speaking NPC to its current enemy.
activity               = ACT_RUN                 The animation activity the speaking NPC is running.
npcstate               = [NPCState::Combat]      The AI state of the speaking NPC.
enemy                  = npc_combine_s           The classname of the speaking NPC's current enemy.
speed                  = 79.235                  The movement speed of the speaking NPC.
weapon                 = weapon_alyxgun          The current weapon being held by the speaking NPC.
distancetoplayer       = 211.240692              The distance from the speaking NPC to the player.
seeplayer              = 1                       Whether or not the speaking NPC can see the player.
seenbyplayer           = 0                       Whether or not the speaking NPC is within the player's view.
readiness              = agitated                The readiness level of the speaking NPC.
playerhealth           = 100                     The player's current health.
playerhealthfrac       = 1.000                   The player's current health, as a fraction of the player's max.
playerweapon           = weapon_shotgun          The current weapon being held by the player.
playeractivity         = ACT_WALK                The animation activity the player is running.
playerspeed            = 0.000                   The movement speed of the player.

This concept does not have any modifiers by default. All criteria in the above list are general and gathered for each concept.

Criteria such as the ones in the list above can be checked by a rule's list of criteria, and used to make decisions about which response group to use for the desired concept. For instance:

  • The enemy criterion could be used to pick the right response to the TLK_ENEMY_DEAD concept. Instead of making a general statement, Alyx could say "I took care of that soldier!" or "I took care of that headcrab!".
  • The healthfrac field could be used to choose a "Phew, that was close!" line if her health was <20% when she finished off her enemy.
  • The distancetoenemy field could be used to choose different lines for when she killed her enemy at long or short range. i.e. "Those guys are scary when they get that close!" or "It's not easy hitting 'em at that range."

Even though the criteria listed above are general and not concept-specific, the criteria will always vary under different circumstances and might not always be available (i.e. NPCs that aren't in combat won't have enemy or distancetoenemy criteria). Additionally, mapmakers can append extra criteria to specific NPCs, or to all NPCs in the game. See #Response contexts for more info.

Rule Criteria

Rules have a list of criteria that are tested against the character's criteria set. When a rule is scored, each criterion is checked against the given data, and the rule receives points for criteria that successfully match. The amount of points a criterion earns for the rule is determined by the criterion's weight.

Criteria are defined inside the script files (see below). The following format is used:

criterion <criterion name> <key to check> <desired value> <optional: weight X> <optional: required>

The parameters are as follows:

criterion name
The name of the criterion. Must not match an existing criterion.
key to check
The key within the character's criteria set that this criterion will check.
desired value
The desired value of the key within the criteria set. This can take multiple forms:
  • Numeric values: "0", "1", or "100".
  • Inverse Numeric values: "!=0" would match if the value is not equal to 0.
  • String value: "npc_alyx", "weapon_alyxgun", or "npc_combine_s".
  • Enumerated value: "[NPCState::Combat]".
  • Ranges:
    • ">0" : Match if the value is greater than 0.
    • "<=0.5" : Match if the value is less than, or equal to, 0.5.
    • ">10,<=50" : Match if the value is greater than 10 and less than, or equal to, 50.
    • ">0,<[NPCState::Alert] : Match if the value is greater than 0 and less then the value of enumeration for NPCState::Alert.
Note.png 注意:Does not support wildcards by default.
weight X
An optional parameter, where X is the amount of points this criterion is worth if it matches. If unspecified, criterion are worth 1 point by default.
required
An optional parameter that states that this criterion is required for rules containing it to be used at all. If a required criterion does not match successfully, rules containing it score 0 and are immediately skipped. Most criteria use this parameter.

Some examples from Half-Life 2:

  • This defines a criterion named PlayerNear, which checks to make sure the player is within 500 units of the speaking NPC.
criterion "PlayerNear" "distancetoplayer" "<500" required
  • This defines a criterion named IsCitizen, which checks to make sure the speaking NPC is a npc_citizen.
criterion "IsCitizen" "classname" "npc_citizen" "required"
  • This defines a criterion named IsMap_d3_c17_12, which checks to make sure the game is currently on d3_c17_12.bsp. Useful for making all the citizens in one map say different lines than other maps.
criterion "IsMap_d3_c17_12" "map" "d3_c17_12" "required"
  • This defines a criterion named IsBob, which checks to make sure the speaking NPC has a targetname of "bob". This is a unique citizen in the game, and this criteria makes it easy to have him say unique lines.
criterion "IsBob" "targetname" "bob" required
Tip.png Tip: A concept is a criterion which almost always has a weight of 5.

Rules

A rule contains a list of criteria and at least one response group. The rule receives points for each of the criteria that successfully matches the speaker's criteria set. The highest scoring rule will direct to one of its response groups, which is used to determine the exact speech the NPC will use. Rules are defined inside the script files (see below). The following format is used:

rule <rule name>
{
   criteria <criterion name 1> [optional: <criterion name 2> <criterion name 3> etc.]
   response <response group name> [optional: <response group name 2> etc.]
   [optional: matchonce]
   [optional: applyContext <data>]
}

The parameters are as follows:

  • rule name : The name of the rule. Must not match an existing rule.
  • criteria : The list of criteria the rule should score with.
  • response : The list of response groups that should be chosen if this rule scores the highest.
  • matchonce : An optional parameter which, if specified, causes this rule to be deactivated once it has been chosen once.
  • applyContext : An optional parameter which applies a response context. See #Response contexts for more information.

For example, the following text defines a rule called CitizenTalkStare. ConceptTalkStare is a criterion that checks to make sure the concept the speaking NPC wants to speak is "TLK_STARE". IsCitizen is a criterion that checks to make sure the speaking NPC is a citizen. NPCIdle is a criterion that checks to make sure the NPC's state is "NPCState::Idle". If this rule scores highest, the response group that will be used is CitizenTalkStare.

rule CitizenTalkStare
{
   criteria     ConceptTalkStare IsCitizen NPCIdle
   response     CitizenTalkStare
}

Note that the rule name and the response group name can be identical because rule names need only be unique amongst rules, and response groups names only unique amongst groups.

Response Groups

A response group contains a set of possible responses, along with some optional data that defines how the responses should be used. When a response group is chosen by a rule, a response is chosen from the list and given back to the speaker to use. Response groups are defined inside the script files (see below). The following format is used:

response <response name>
{
   [optional: permitrepeats]
   [optional: sequential]	  
   [optional: norepeat]		  

   <response type> <response> <optional: ...>
   <response type> <response> <optional: ...>
   <response type> <response> <optional: ...>
}

The response group parameters are as follows:

  • permitrepeats : If specified, responses in this group are allowed to repeat. If unspecified, the default behavior is to use all responses in the list before repeating any,
  • sequential : If specified, responses will be used in the order they're listed in the group. If unspecified, the default behavior is to randomly choose responses from the list.
  • norepeat : If specified, once all responses in the list have been played, the response group will be disabled. Any rules that choose this response group will return no response to the speaker.

Responses

The response is the actual response which is selected by the system and then used by the speaker. A response group can list as many responses as desired, with each response being one of the following types:

  • speak : The response is a soundscript or raw audio file.
  • sentence : The response is a sentence name from sentences.txt.
  • scene : The response is a.vcdfile. See Choreography Implementation for more information.
  • response : The response is a reference to another response group which should be selected instead.
  • print : The response is some text that should be printed at the speaker's position indeveloper 1(used for placeholder responses).
    Note.png 注意:Mapbase Mapbase replaces this with game_text-like screen messages by default.
  • entityio (in all games since Left 4 Dead)[confirm] : The response is an I/O event which fires on a specific entity with the speaker as the activator. The format isentityio "<name> <input> <param>". This is different from followup responses, which are covered in more detail farther below.

Post-response delay parameters

Each response supports a variety of optional parameters.

    • nodelay : After the response has finished, the speaker is allowed to speak again immediately.
    • defaultdelay : After the response has finished, the speaker won't be allowed to speak for a random amount, between 2.8 & 3.2 seconds.
    • delay X : After the response has finished, the speaker won't be allowed to speak for X seconds. X can also be a range, e.g. "5.5,7.5"
  • weapondelay X : When the response starts, the speaker will not fire their weapon for X seconds. Only available on HL2 NPC allies by default.
  • speakonce : Prevents the response from being used more than once.
  • odds X : If specified, then when this response is chosen, there is a chance the speaker will say nothing instead of saying the response. The odds is a (0-100)% the chance of cancelling the response, meaning an odds of 25 gives a 25% chance of saying nothing.
  • respeakdelay : If specified, this response may not be used unless the concept hasn't been spoken in at least X seconds. X can also be a range, e.g. "5.5,7.5"
  • soundlevel : If specified, this soundlevel should be used for the response instead of the default SNDLVL_TALKING.
  • displayfirst : If specified, this response should be used first (ignores the weight parameter).
  • displaylast : If specified, this response should be used last (ignores the weight parameter).
  • weight : If specified, used to weight the selection of the responses in the list. By default, all responses have a weight of 1. Please note that responses won't be repeated until all of the other responses have been chosen, meaning once all of the high-weight responses are chosen, the system will only count the responses of less weight. This can be counteracted with permitrepeats.
  • noscene : Stops the Response System from creating an auto-generated scene for a speak response.
  • stop_on_nonidle : When the response is spoken, stops the scene when the NPC enters a non-idle state. In Source 2013, only works in HL2 episodic mods on scene responses.
  • predelay : When the response is chosen, it won't actually be spoken until X seconds have passed. Only works on scene responses. X can also be a range, e.g. "5.5,7.5"

For example, the following response group is used by citizens to respond to the TLK_STARE concept. Citizens will use the responses in the list in the order they're listed (due to the sequential parameter). Each response, when chosen, stops the NPC from talking for a random amount of time between 10 & 20 seconds.

response "CitizenTalkStare"
{
   sequential
   scene "scenes/npc/$gender01/doingsomething.vcd" delay "10,20"
   scene "scenes/npc/$gender01/getgoingsoon.vcd"  delay "10,20"
   scene "scenes/npc/$gender01/waitingsomebody.vcd"  delay "10,20"
}

Script files

The/scripts/talker/response_rules.txtis the base script file that contains all the criteria, rules, and response groups used by the Response Rules System. The file can also include other files using the #include keyword, which allows you to cleanly divide the rules up according to NPC, map, and so on. Note that some entities, like the env_speaker, specify their own script files that contain a subset of the criteria, rules, and response groups for the entity to use. Seescripts/talker/terminal_pa.txtfor an example used by the terminal announcement at the train station.

Response contexts

Response contexts are like criteria set by the mapper. They are set through the "Response Contexts" (ResponseContext) keyvalue or theAddContextinput in the following format:key:value;key:value;key:value;..and so on.

To do: Unique section on response contexts, there's more to clarify about response contexts!

Followup responses

Left 4 Dead Left 4 Dead introduced "followups", events which occur following the response. They are triggered as response parameters similar to odds, predelay, etc.

Code: The code for the followup system is available in the Alien Swarm SDK, along with the rest of the rewritten response system.
  • fire : Fires an input through the I/O system with the speaker as the activator and caller. Format isfire <target> <input> <delay>. Does not support parameters.
  • then : Causes another response to be dispatched on an entity. Format isthen <target> <concept> <response contexts> <delay>. Used for making characters dynamically respond to each other.
Note.png 注意:A negative delay causes the followup to be dispatched X amount of time after the speaker starts speaking, as opposed to when they're finished speaking.

A few unique targetnames can be used:

  • self : The entity speaking the response.
  • subject : Uses the entity name found in the speaker's "Subject" context, if it exists. The game sets this for info_remarkable responses.
  • from : Uses the entity name found in the speaker's "From" context, if it exists. The game sets this to the name of the previous followup respondent, allowing followups to bounce back and forth.
  • any : Dispatched to any valid respondent within the range stored inrr_followup_maxdist(1800 by default).
  • all : Dispatched to all valid respondents within the range stored inrr_followup_maxdist(1800 by default).
Note.png 注意:The "Subject" and "From" contexts only store entity names, so be careful when there's multiple potential targets with the same name!

Example from Left 4 Dead 2 incoach.txt:

Response _c1m4startelevator4bCoach
{
	scene "scenes/Coach/WorldC1M4B01.vcd"  then mechanic _c1m4startelevator5a foo:0 -2.313 //Son, you got a DEAL.
	scene "scenes/Coach/WorldC1M4B02.vcd"  then mechanic _c1m4startelevator5a foo:0 -5.790 //Ha HA! All the way to New Orleans! Baby, that sounds like a PLAN.
	scene "scenes/Coach/WorldC1M4B05.vcd"  then mechanic _c1m4startelevator5b foo:0 -6.334 //Normally I wouldn't do this. But in these circumstances, I think Mr. Gibbs, Jr. ain't gonna mind.
	scene "scenes/Coach/WorldC1M4B10.vcd"  then mechanic _c1m4startelevator5b foo:0 -2.685 //Forgive us Jimmy, but we need your car.
}

Advanced response rules usage

The Response System can be used in many advanced and specialized ways. Here's a few tips and tricks for advanced usage of the system:

Firing custom responses withDispatchResponse
Absolutely anything can be passed to an NPC as a response concept, so long as it is to be found somewhere in the script files. You aren't limited to the AI's predefined TLK_* concepts at all.
For example, you might want NPCs from a onlooking group to speak congratulatory response concepts when a player successfully solves part of a puzzle.
Player allies in HL2 also have aSpeakResponseConceptinput with more advanced handling and conditions.

See the response scripts for Alyx in EP1/EP2 or the response scripts for the L4D survivors for more examples of advanced response system usage.

Debugging

To do: sv_debugresponses

Notes

  • To be able to use the Response Rules system, an NPC must be derived from the CAI_BaseActor class.
  • See thescripts/talker/npc_*.txtfiles for examples of specific NPC response rules.
  • Thescripts/talker/response_rules.txtis the manifest for the response rules system. If you add new response rule script files for your new NPC, make sure you #include it at the end of thescripts/talker/response_rules.txtfile.

See also

External links