Zh/L4D2 Vscripts: Difference between revisions
Dazainerau (talk | contribs) (→脚本环境) |
Dazainerau (talk | contribs) |
||
Line 151: | Line 151: | ||
: <code>DirectorScript.MapScript.LocalScript.DirectorOptions (When Director Script active) < DirectorScript.MapScript.ChallengeScript.DirectorOptions (Scripted mode only) < DirectorScript.DirectorOptions</code> | : <code>DirectorScript.MapScript.LocalScript.DirectorOptions (When Director Script active) < DirectorScript.MapScript.ChallengeScript.DirectorOptions (Scripted mode only) < DirectorScript.DirectorOptions</code> | ||
== | == 实体脚本 == | ||
脚本域为 <code>_<unique ID>_<entity name></code> | |||
把一个脚本添加到一个服务器端的实体的'''Entity Scripts'''的键值中可以将其以实体脚本加载. 脚本会在实体产生时被执行,并加载到一个唯一的脚本域内,该范围由唯一标识符后跟实体名称或种类名组成. | |||
Think函数可以在 <code>thinkfunction</code> [[Keyvalue|键值]]中设置, 指定的脚本函数会以0.1秒一次的频率被执行. 函数也可以通过I/O系统以<code>RunScriptCode ''function_name(argument, ...)</code>的形式手动调用. | |||
Entity Scripts have a <code>self</code> reference to their owning entity handle, allowing the script easy access to control the entity through its class methods. There are also hook functions available depending on the entity class. Both methods and hooks are documented [[List_of_L4D2_Script_Functions#Classes|here]]. | Entity Scripts have a <code>self</code> reference to their owning entity handle, allowing the script easy access to control the entity through its class methods. There are also hook functions available depending on the entity class. Both methods and hooks are documented [[List_of_L4D2_Script_Functions#Classes|here]]. | ||
Line 188: | Line 188: | ||
In addition, arbitrary VScript code can be run from the I/O system, using the <code>RunScriptCode</code> input available in all entities. The code will run in the current entities script scope. | In addition, arbitrary VScript code can be run from the I/O system, using the <code>RunScriptCode</code> input available in all entities. The code will run in the current entities script scope. | ||
{{warning|Never use double-quotation marks in any Hammer Output, since it will corrupt the map file. This means that strings cannot be passed with <code>RunScriptCode</code>.}} | {{warning|Never use double-quotation marks in any Hammer Output, since it will corrupt the map file. This means that strings cannot be passed with <code>RunScriptCode</code>.}} | ||
== Global Scripts == | == Global Scripts == |
Revision as of 21:33, 13 January 2019
求生之路2 脚本 是可以在游戏中的虚拟机里被运行的服务器端的脚本。它们使用Squirrel语音编写, 这是一种类似于Lua的脚本编译语言.
用途
导演脚本
VScripts在求生之路2中的最通常的用处是用来指挥人工智能导演系统。 这些脚本的用途包括但不限于调整普通感染者的数量或者禁止BOSS感染者的产生, 或者用以自定义诸如onslaughts和gauntlets之类的游戏事件, 甚至是复杂的尸潮事件和完全定制的
自定义结局。 大多数官方活动也是通过这种方式制作的。导演脚本的主要工作是将导演系统所使用的各种变量的值覆盖写入DirectorOptions
表.
一次只能运行一个导演脚本。执行新的导演脚本将终止先前运行的任何脚本并删除它在DirectorOptions
表中设置的任何值。
实体脚本
另一个常见的用途是将脚本附加到实体上。 脚本提供了轻松便捷的途径以修改或读取大多数实体的属性,甚至可以写入新的KeyValues(键值)。这便使得在Hammer中不可能实现的对实体I/O系统的复杂控制成为了可能。
任何实体都能运行脚本,并且拥有以0.1秒运行一次think函数的能力,也可以将脚本代码作为实体输出以执行.
一些实体还拥有VScripts的专用功能,最显著的例子是point_script_use_target,它能将其他实体转换为完全可编程的定时按钮。
全局脚本
脚本也可以被设定成在地图加载时执行,基于特定的游戏模式或者可选的地图名。 这些脚本通常用于为突变模式创造剧本或者修改全局导演系统设置,当然也可以用于对地图的自定义。
全局脚本可以添加脚本钩子函数,这些函数会在游戏中的特定时间发生时被调用,比如当玩家/物件造成伤害。
这些脚本有许多实用功能和功能,包括资源和建造系统,以及产生自定义尸潮。请阅读EMS教程了解详情。
其他用途
总而言之,这些脚本拥有各种各样的超能力,包括从预编译的列表中或者程序性地产生实体,产生感染者,自定义一个 HUD系统,
跨层次地存储数据至硬盘,以及其他数不胜数的功能。
请阅读求生之路2 Vscript 范例了解详情。
脚本文件
脚本以文本文件的形式被读取, 脚本的扩展名为.nut
和 .nuc
, 其中 .nuc
是对纯文本形式的 .nut
的加密. 自定义脚本会从 \left 4 dead 2\left4dead2\scripts\vscripts\中被读取, 包括.vpk文件中的也是这样。
位置
- 官方的 .nuc 脚本文件位于 scripts/vscripts
- left 4 dead 2\left4dead2\pak01_dir.vpk
- left 4 dead 2\left4dead2_dlc1\pak01_dir.vpk
- April 22, 2010 The Passing update
- left 4 dead 2\left4dead2_dlc2\pak01_dir.vpk
- October 5, 2010 The Sacrifice update
- left 4 dead 2\left4dead2_dlc3\pak01_dir.vpk
- March 22, 2011 Cold Stream Beta / L4D1 Transition Project update
- left 4 dead 2\update\pak01_dir.vpk
- This is where mutations were updated/replaced bi-weekly.
- left 4 dead 2\sdk_content\scripting\scripts\vscripts\
- Plaintext versions of many of the scripts introduced in the EMS update.
解密NUC文件
.nuc 文件是经过ICE加密的 .nut 文件. 其秘钥是 SDhfi878. 你可以使用 VICE 对它们进行解码.
Packages with deciphered official scripts are also available.
加载脚本
VScripts以不同的方式加载,具体取决于它们的用途. 它们也可以通过在控制台手动输入script filename
的方式加载.
导演脚本
- 使用info_director实体进行如下输入(inputs)
BeginScript <script name>
- 执行一个普通的导演脚本, 比如为了onslaught事件而设计的脚本.
EndScript
- 结束执行脚本并重置导演系统设置中的变量值.
BeginScriptedPanicEvent <script name>
- 执行一次脚本化的尸潮

BeginScriptedPanicEvent
一起使用的脚本将无法工作,即使你能在其他脚本的内容中使用子目录. 它们必须位于vscripts文件夹下,否则它们只会简单地以1个阶段1秒的延迟运作.导演脚本(结局)
<map name>_finale.nut
会在结局地图加载时被自动读取. 这个脚本也可以因trigger_finale的使用而被触发, 或者通过玩家手动触发, 或者通过ForceFinaleStart
这一输入触发.- 待完善: trigger_finale 还有一个指定结局脚本的选项,但它似乎不起作用.
所有的导演脚本存在于DirectorScript
这一脚本域(script scope)之中.
实体脚本
- 方式1:地图加载时自动读取
- 通过设置实体中的Entity Scripts键值加载脚本
- 方式2:手动加载
- 使用
RunScriptFile
这一输入
实体脚本位于_<unique ID>_<entity name>
这一脚本域中
全局脚本
- 方式1:通过模式指定脚本
- 与游戏模式同名的脚本将会自动运行. 比如运行一个地图
map <map name> mutation12
将会自动加载mutation12.nuc
这一写实对抗脚本. - 全局脚本位于
g_ModeScript
这一脚本域中

- 方式2:通过地图指定脚本(只在脚本化模式中有效)
- 每个地图的脚本可以被在当地图运行指定模式时被创建和执行, 使用
<map name>_<mode name>.nut
这一格式的指令, 比如,c1m4_atrium_mutation12.nut
. - 它们位于
g_MapScript
这一脚本域中
脚本环境
请阅读含有类(classes)和函数(functions)的L4D2脚本函数列表以了解详情.
当一个脚本被加载,它会被放入一个表,我们称之为脚本域(Script Scope).模式、地图和导演脚本会被放入设置域中,同时会为每个实体脚本生成独一无二的域. 有关更多信息,请参阅Vscript的基本原理.
表的结构
DirectorScript = // Base Director Scope.
{
DirectorOptions // Base DirectorOptions table.
MapScript = // Map Script scope.
{
BaseScriptedDOTable // Hardcoded DirectorOptions.
ChallengeScript = // Mode Script scope.
{
MutationState // Initial values for SessionState.
MutationOptions // Initial values for SessionOptions.
}
LocalScript = // Script Scope Director Scripts are placed in.
{
DirectorOptions // DirectorOptions for current Director Script (like onslaughts). Only availabe when a script is active.
}
MapOptions // Initial values for SessionOptions.
MapState // Initial values for SessionState.
}
}
g_MapScript // Global reference to the Map Script scope (DirectorScript.MapScript).
g_ModeScript // Global reference to the Mode Script scope (DirectorScript.MapScript.ChallengeScript).
g_rr // Scope holding the Response Rule system.
g_RoundState // TODO
SessionOptions //Global Director options (Scripted mode only).
SessionState //State variables for game modes (Scripted mode only).
委托
一些表已经设置了委托, 所以如果一个键值缺省, 就会从其父表中读取该值.
表的委托长成这样:(右边是父表)
- The Director Scope
(DirectorScript.MapScript.ChallengeScript; DirectorScript.MapScript.LocalScript) < DirectorScript.MapScript < DirectorScript < ::
- DirectorOptions
DirectorScript.MapScript.LocalScript.DirectorOptions (When Director Script active) < DirectorScript.MapScript.ChallengeScript.DirectorOptions (Scripted mode only) < DirectorScript.DirectorOptions
实体脚本
脚本域为 _<unique ID>_<entity name>
把一个脚本添加到一个服务器端的实体的Entity Scripts的键值中可以将其以实体脚本加载. 脚本会在实体产生时被执行,并加载到一个唯一的脚本域内,该范围由唯一标识符后跟实体名称或种类名组成.
Think函数可以在 thinkfunction
键值中设置, 指定的脚本函数会以0.1秒一次的频率被执行. 函数也可以通过I/O系统以RunScriptCode function_name(argument, ...)
的形式手动调用.
Entity Scripts have a self
reference to their owning entity handle, allowing the script easy access to control the entity through its class methods. There are also hook functions available depending on the entity class. Both methods and hooks are documented here.
Some entities have additional script functionality:
- point_script_use_target - Has both methods and hooks for controlling the button.
- logic_script - Can pass multiple entity names to the script as an array called
EntityGroup
. - point_template
- env_entity_maker
- info_item_position
The script can be reloaded with console command ent_fire <name of entity> runscriptfile <relative vscript path>
. This is useful for quick script reloading.
I/O system interaction
Any script can use the EntFire()
and DoEntFire()
functions to fire outputs to map entities. Since the activator
and caller
arguments in DoEntFire()
take a script handle, it can be used to fire an output to an entity using the "!self" or "!activator" keyword, even without having to know its name, as long as the entity handle is available.
EntFire( "church_bell_relay", "Trigger", 0 ); // Fires an output to the Trigger input of the named entity.
player <- null;
while(player = Entities.FindByClassname(player, "player")) // Iterate through the script handles of the players.
{
DoEntFire("!self", "speakresponseconcept", "PlayerLaugh", 0, null, player); // Make each player laugh.
}
Conversely, the CBaseEntity::ConnectOutput()
and DisconnectOutput()
functions can be used to call a script function when the specified entity output fires.
In addition, arbitrary VScript code can be run from the I/O system, using the RunScriptCode
input available in all entities. The code will run in the current entities script scope.

RunScriptCode
.Global Scripts
Naming a script file with a game mode name a mode specific script, and makes it execute every time a map is loaded in the specified mode. If a Mode Script exists, a map specific script with the map name followed by an underscore and the mode name can also be loaded.
Scripted Mode
Adding a Mode Script will enable Scripted Mode for the game mode. This works on the base game modes included in the game as well.
Scripted Mode loads utility functions into the g_ModeScript
scope, disables the hardcoded setting of 2 on the MaxSpecials
Director Option, and enables game event callbacks and script hook functions. It also seems to break the finale tank music in Dark Carnival.
SessionState
- A table for storing session specific variables. Not preserved across level transitions.
SessionOptions
- Base Director Options for the game mode.
Available Functions
Mode Scripts
Use script scope g_ModeScript
Tables
MutationState
- Initial values for the
SessionState
table. MutationOptions
- Initial values for the
SessionOptions
table.
Map Scripts
Use script scope g_MapScript
Tables
MapState
- Map specific values for the
SessionState
table. MapOptions
- Map specific values for the
SessionOptions
table.
Glossary
- DirectorOptions
- A table of named variables that override the AI Director behavior.
- Entity handle
- Also known as EHANDLE. 待完善: Looks like some sort of pointer reference to an entity.
- Script handle
- An entity instance with accessors and mutators to the C++ entity object. Also known as HScript.
- Script scope
- The table where the variables, functions and classes of a VScript are placed.
Director options
Please see L4D2 Director Scripts for a table of available options.
Third party tools
VSLib
VSLib (VScript Library) is a simple, lightweight library for L4D2's VScript mutation system. It greatly simplifies coding VScripts by taking care of a lot of tedious work for you. It is used in several popular mods like Rayman1103's Admin System and Stranded. Read more about VSLib.
See also
- L4D2 Vscript Examples
- List of L4D2 Script Functions
- Extended Mutation System
- L4D2 Level Design/Boss Prohibition
- Left 4 Dead 2 Tool Updates
- Mutation Gametype (L4D2)
- trigger_finale
- info_director
- logic_script
- vscripts
- VSLib
External links
- Alternative Tool
- Alternative Documentation
- Director Scripts - .nuc files (Steam forums)
- It's the vscript'ing documentation FAQ! (Steam forums)
- Tutorial - Writing a Mini Game - Tic Tac Toe - Part One (Steam Forums)
- Writing a Mini Game - Tic Tac Toe - Part One - Author's Website
- l4d2 - Vscript example - Tic-Tac-Toe - Video of early Prototype
- l4d2 - Vscript example - Tic-Tac-Toe - updated - Video of current version with "brutally misanthropic AI"
- Mutation scripts (Steam forums)
- Squirrel Binary for Windows
- Squirrel (programming language) - Wikipedia Article on Squirrel
Squirrel: The Programming Language - Documentation and Sample Code
- The AI Systems of Left 4 Dead by Michael Booth (PDF)
"Creating a "Money"/Point System" - Swarm Armory
- Deciphered Official Scripts