Zh/Left 4 Dead 2/Scripting: Difference between revisions
(Created page with "{{subst:#if: Translation of 'Left 4 Dead 2/Scripting' to '中文' via Template:LanguageBar buttons * * * * * * * * * * * * * * * * * * * * * * * * * * * *...") |
mNo edit summary |
||
(One intermediate revision by the same user not shown) | |||
Line 1: | Line 1: | ||
{{ | {{LanguageBar|title=脚本}} | ||
{{TabsBar|main=Scripting}} | {{TabsBar|main=Scripting}} | ||
{{back|Left 4 Dead 2/Docs}} | {{back|Zh/Left 4 Dead 2/Docs|回到求生之路2/文档}} | ||
{{toc-right}} | {{toc-right}} | ||
此页面由[[User:世凪Yonagi|世凪Yonagi]]个人汉化,欢迎大家添加新内容或修复错误。 | |||
<hr> | |||
== 有用链接 == | |||
* {{L|/Game Events|游戏事件列表}} | |||
* {{L|/Script Functions|脚本函数列表}} | |||
* {{L|/Director Scripts|导演脚本}} | |||
* {{L|/Expanded Mutation System|扩展突变系统}} | |||
* {{L|/Mutation Gametype|突变游戏类型}} | |||
* {{L|/Decrypted mutations|解密突变}} | |||
== | == 概述 == | ||
{{sq}}{{l4d2}} '''Left 4 Dead 2 {{L|VScripts}}''' 是在游戏内虚拟机中运行的服务器端脚本。它们使用 {{L|Squirrel}} 编写,这是一种类似于 [http://www.lua.org/ Lua] 的编译型脚本语言。当前运行的是 Squirrel 3.0.4 版本。 | |||
{{sq}}{{l4d2}} '''Left 4 Dead 2 | |||
== | == 用途 == | ||
=== | === {{L|L4D2_Director_Scripts|导演脚本}} === | ||
在《Left 4 Dead 2》中,{{L|VScript}} 最常见的用途是临时影响 AI 导演的行为。这些脚本的范围可以从简单的特感生成调整和 {{L|L4D2_Level_Design/Boss_Prohibition|禁止BOSS特感}},到自定义事件如猛攻和考验事件,甚至复杂的分阶段恐慌事件和完整的 {{L|L4D2_Level_Design/Custom_Finale|自定义结局}}。官方战役中的大多数事件主要是通过这种方式实现的。 | |||
导演脚本主要通过将导演使用的各种变量的覆盖值写入一个 <code>DirectorOptions</code> 表来工作。 | |||
一次只能运行一个导演脚本。执行新的脚本将终止任何先前运行的脚本,并移除它在 <code>DirectorOptions</code> 中设置的任何值。 | |||
=== [[#Entity Scripts 2| | === [[#Entity Scripts 2|实体脚本 ↓]] === | ||
另一个常见用途是将脚本附加到实体上。该脚本提供了读取和修改实体许多属性的便捷方法,甚至可以编写新的 {{L|KeyValues}}。这使得能够以在 Hammer 中使用实体 I/O 系统非常复杂或不可能的方式控制实体。 | |||
任何实体都能够运行脚本,并且能够设置一个指定的 ''think'' 函数每 0.1 秒运行一次,以及作为实体输出执行脚本代码。 | |||
一些实体还具有针对 VScript 的专用函数,其中最突出的是 {{ent|point_script_use_target}},它允许将其他实体变成完全可编程的定时按钮。 | |||
=== [[#Global Scripts 2| | === [[#Global Scripts 2|全局脚本 ↓]] === | ||
脚本也可以设置为在地图加载时运行,基于游戏模式并可选择地图名称。这些脚本通常用于创建纯脚本插件和为 {{L|Mutation_Gametype_(L4D2)|突变}} 修改全局导演选项。 | |||
全局脚本可以添加 {{L|Left 4 Dead 2/Script Functions#Scripted_Mode_hooks|脚本钩子函数}},这些函数在特定事件(如玩家/对象受到伤害时)从游戏中被调用。 | |||
这些脚本有许多现成的实用函数和功能,包括资源和建筑系统,以及自定义恐慌波生成。请参阅 Valve 的 {{L|L4D2_EMS|扩展突变系统教程}} 以获取更多信息。 | |||
=== | === 其他用途 === | ||
所有脚本都可以访问许多功能的函数,包括 {{L|L4D2_EMS/Appendix:_Spawning|生成实体}}(从预编译列表或编程方式)、{{L|L4D2_EMS/Appendix:_Spawning_Infected|生成特感}}、{{L|L4D2_EMS/Appendix:_HUD|HUD 系统}}、跨关卡和磁盘{{L|L4D2_EMS/Appendix:_Table_Save_Restore|存储数据}}等等。 | |||
请参阅 {{L|L4D2 Vscript Examples}} 以获取更多示例和想法。 | |||
== | == 脚本文件 == | ||
脚本从文件扩展名为 <code>.nut</code> 和 <code>.nuc</code> 的文本文件加载,其中 <code>.nuc</code> 表示对纯文本 <code>.nut</code> 的加密。自定义脚本从 '''\left 4 dead 2\left4dead2\scripts\vscripts\''' 读取,以及在打包到 <code>.vpk</code> 文件时从 '''\scripts\vscripts\''' 读取。 | |||
=== | === 位置 === | ||
; | ;官方的 <code>.nuc</code> 脚本文件位于多个位置的 '''scripts/vscripts''' 目录中 | ||
{{note| | {{note|使用 {{L|GCFScape}} 等第三方程序浏览和提取 {{L|VPK}} 文件。}} | ||
*'''left 4 dead 2\left4dead2\pak01_dir.vpk''' | *'''left 4 dead 2\left4dead2\pak01_dir.vpk''' | ||
;*'''left 4 dead 2\left4dead2_dlc1\pak01_dir.vpk''' | ;*'''left 4 dead 2\left4dead2_dlc1\pak01_dir.vpk''' | ||
: | :2010年4月22日 The Passing 更新 | ||
;*'''left 4 dead 2\left4dead2_dlc2\pak01_dir.vpk''' | ;*'''left 4 dead 2\left4dead2_dlc2\pak01_dir.vpk''' | ||
: | :2010年10月5日 The Sacrifice 更新 | ||
;*'''left 4 dead 2\left4dead2_dlc3\pak01_dir.vpk''' | ;*'''left 4 dead 2\left4dead2_dlc3\pak01_dir.vpk''' | ||
: | :2011年3月22日 Cold Stream Beta / L4D1 过渡项目更新 | ||
;*'''left 4 dead 2\update\pak01_dir.vpk''' | ;*'''left 4 dead 2\update\pak01_dir.vpk''' | ||
: | :这是突变每两周更新/替换的地方。也包含 2020年9月24日 The Last Stand 社区更新引入的文件。 | ||
;*'''left 4 dead 2\sdk_content\scripting\scripts\vscripts\''' | ;*'''left 4 dead 2\sdk_content\scripting\scripts\vscripts\''' | ||
: | :EMS 更新中引入的许多脚本的纯文本版本。 | ||
=== | === 解密 NUC 文件 === | ||
.nuc | .nuc 文件是 ICE 加密的 .nut 文件。加密密钥是 '''SDhfi878'''。你可以使用 {{L|VICE}} 来解码它们。<br> | ||
你可以在 {{L|L4D2_Decrypted_mutations|这里}} 找到解密的突变 vscripts。 | |||
== | == 加载 VScripts == | ||
VScripts | VScripts 有多种加载方式,取决于它们的上下文。它们也可以使用控制台命令 <code>script_execute ''文件名''</code> 手动加载。 | ||
=== | === 导演脚本 === | ||
;*{{ent|info_director}} | ;*{{ent|info_director}} 输入 | ||
{{I|BeginScript|param=scriptlist| | {{I|BeginScript|param=scriptlist|执行通用导演脚本,无论是用于猛攻事件还是改变生成行为。}} | ||
: | :它们被放置在 <code>LocalScript</code> 脚本作用域中。 | ||
{{I|EndScript| | {{I|EndScript|结束当前运行的本地脚本,然后将导演选项重置为地图特定值或默认值。}} | ||
{{I|ScriptedPanicEvent|param=scriptlist| | {{I|ScriptedPanicEvent|param=scriptlist|使用给定的脚本,设置 {{L|L4D2 Director Scripts#Finales and Scripted Panic Events|脚本化恐慌事件}} 的结构。}} | ||
: | :它们被放置在 <code>LocalScript</code> 脚本作用域中。 | ||
{{note| | {{note|这些输入的脚本''必须''位于 "vscripts" 子文件夹下。否则事件将只播放 1 秒延迟的"阶段 0"。}} | ||
;* | ;*{{subst:LAuto|L4D2 Director Scripts#Finales and Scripted Panic Events|结局脚本]] | ||
: | :当 {{ent|trigger_finale}} 结局开始时,它会加载此格式的脚本:<code>[地图名]_finale.nut</code>。 | ||
: | :它们被放置在 <code>g_MapScript</code> 脚本作用域中。 | ||
=== | === 实体脚本 === | ||
;* | ;*键值 | ||
{{KV|Entity Scripts|intn=vscripts|scriptlist| | {{KV|Entity Scripts|intn=vscripts|scriptlist|在实体生成前准备自身时,将运行该键值中的 VScript 路径名称。(更多信息请参见 {{L|L4D2_Vscripts#Entity_Scripts_3|实体脚本}}。)}} | ||
;* | ;*输入 | ||
{{I|RunScriptFile|param=script| | {{I|RunScriptFile|param=script|将给定脚本插入实体的作用域,然后运行它。}} | ||
实体脚本被放置在 <code>_<唯一ID>_<实体名称></code> 脚本作用域中。 | |||
=== | === 全局脚本 === | ||
;* | ;*模式脚本 | ||
: | :与当前 {{subst:LAuto|Mutation_Gametype_(L4D2)|游戏模式]] 同名的脚本。在设置新模式时加载。 | ||
: | :它们被放置在 <code>g_ModeScript</code> 脚本作用域中。 | ||
:{{tip| | :{{tip|<code>map</code> 命令也可以设置游戏模式。例如,<code>map <地图名> mutation12</code> 加载写实对抗模式脚本 <code>mutation12.nuc</code>。}} | ||
:{{note| | :{{note|为模式添加脚本将启用脚本模式。}} | ||
;* | ;*特定地图的模式脚本 | ||
: | :当地图在指定游戏模式下加载时的每地图脚本。它们的名称格式为:''<nowiki>[地图名]_[模式名].nut</nowiki>''。 | ||
: | :它们被放置在 <code>g_MapScript</code> 脚本作用域中。 | ||
;* | ;*插件脚本 | ||
: | :这些脚本的上下文各不相同,但它们都有一个共同的大属性:它们不会覆盖同名的文件,而是与它们一起加载。它们按以下顺序执行,每个都在其各自的基础脚本(不带 <code>_addon</code> 后缀)之后执行。如果脚本被命名为以下之一,则被视为"插件脚本": | ||
:# <code>mapspawn_addon.nut</code> | :# <code>mapspawn_addon.nut</code>(每章节运行一次)- <code>getroottable()</code> 作用域 | ||
:# <code>response_testbed_addon.nut</code> | :# <code>response_testbed_addon.nut</code>(每章节运行一次)- <code>g_rr</code> 作用域 | ||
:# <code>scriptedmode_addon.nut</code> | :# <code>scriptedmode_addon.nut</code>(每回合运行两次)- <code>g_MapScript</code> 作用域 | ||
:# <code>director_base_addon.nut</code> | :# <code>director_base_addon.nut</code>(每回合运行两次)- <code>DirectorScript</code> 作用域 | ||
== | == 脚本环境 == | ||
''' | '''请参阅 {{L|Left 4 Dead 2/Script Functions}} 了解内置类和函数。''' | ||
当脚本加载时,它被放置在一个表或脚本作用域中。全局脚本和导演脚本被放入设定的作用域,而为每个实体脚本生成唯一的作用域。更多信息请参阅 {{L|Vscript Fundamentals}}。 | |||
=== | === 表结构 === | ||
<source lang=cpp> | <source lang=cpp> | ||
DirectorScript = // | DirectorScript = // 基础导演作用域。 | ||
{ | { | ||
DirectorOptions // | DirectorOptions // 基础 DirectorOptions 表。 | ||
MapScript = // | MapScript = // 地图脚本或 trigger_finale 脚本的作用域 | ||
{ | { | ||
DirectorOptions | DirectorOptions | ||
BaseScriptedDOTable // | BaseScriptedDOTable // 脚本模式的默认 DirectorOptions | ||
ChallengeScript = // | ChallengeScript = // 模式脚本的作用域 | ||
{ | { | ||
DirectorOptions // | DirectorOptions // 使用 BaseScriptedDOTable、MutationOptions 和 MapOptions 填充;如果存在相同的键,则最右边的表优先。 | ||
MutationState // | MutationState // 使用 MapState 覆盖先前值填充 | ||
MutationOptions // | MutationOptions // 如果在模式脚本中定义则使用初始值 | ||
} | } | ||
LocalScript = // | LocalScript = // 通过 info_director 'BeginScript' 或 'ScriptedPanicEvent' 输入执行的脚本的作用域 | ||
{ | { | ||
DirectorOptions // | DirectorOptions // 当前导演脚本的 DirectorOptions(如猛攻)。仅在脚本活动时可用 | ||
} | } | ||
MapOptions // | MapOptions // 如果在地图脚本中定义则使用初始值 | ||
MapState // | MapState // 如果在地图脚本中定义则使用初始值 | ||
} | } | ||
} | } | ||
g_MapScript // | g_MapScript // 对地图脚本作用域 (DirectorScript.MapScript) 的全局引用。 | ||
g_ModeScript // | g_ModeScript // 对模式脚本作用域 (DirectorScript.MapScript.ChallengeScript) 的全局引用。 | ||
SessionOptions // | SessionOptions // 对 g_ModeScript.DirectorOptions 的全局引用(仅限脚本模式)。 | ||
SessionState // | SessionState // 对 g_ModeScript.MutationState 的全局引用(仅限脚本模式)。 | ||
g_rr // | g_rr // 持有响应规则系统的作用域。 | ||
g_RoundState // | g_RoundState // 待办 | ||
</source> | </source> | ||
=== | === 委托 === | ||
一些表设置了 [http://squirrel-lang.org/doc/squirrel3.html#d0e2038 委托],因此如果键不在其中,则从其委托(通常是父)表中读取。 | |||
这些表的委托关系如下(委托在右侧): | |||
; | ; 导演作用域 | ||
: <code>(DirectorScript.MapScript.ChallengeScript | : <code>(DirectorScript.MapScript.ChallengeScript 或 DirectorScript.MapScript.LocalScript) < DirectorScript.MapScript < DirectorScript < ::</code> | ||
; DirectorOptions | ; DirectorOptions | ||
: <code>DirectorScript.MapScript.ChallengeScript.DirectorOptions ( | : <code>DirectorScript.MapScript.ChallengeScript.DirectorOptions (仅限脚本模式) < DirectorScript.MapScript.LocalScript.DirectorOptions (当导演脚本活动时) < DirectorScript.MapScript.DirectorOptions < DirectorScript.DirectorOptions</code> | ||
: | : 请参阅 {{ent|director_base.nut}} 中的 GetDirectorOptions。 | ||
== | == 实体脚本 == | ||
使用脚本作用域 <code>_<唯一 ID>_<实体名称></code> | |||
将脚本添加到服务器端实体的 '''实体脚本''' 键值中,会将脚本作为实体脚本加载。脚本在实体生成时执行,并加载到一个由唯一标识符后跟实体名称或类名组成的唯一脚本作用域中。 | |||
可以使用 <code>thinkfunction</code> {{L|Keyvalue|键值}} 设置一个 think 函数,指定的脚本函数每 0.1 秒运行一次。虽然它有变得昂贵的潜力,但程序员能够限制执行的代码量。函数也可以通过 I/O 系统使用输入 <code>RunScriptCode ''函数名(参数, …)</code> 手动调用。 | |||
实体脚本有一个 <code>self</code> 引用指向其拥有的实体句柄,允许脚本通过其类方法轻松控制实体。根据实体类,还有可用的钩子函数。两种方法和钩子都在 {{L|Left 4 Dead 2/Script Functions#Classes|这里}} 有文档记录。 | |||
一些实体具有额外的脚本功能: | |||
*{{ent|point_script_use_target}} - | *{{ent|point_script_use_target}} - 具有控制按钮的方法和钩子。 | ||
*{{ent|logic_script}} - | *{{ent|logic_script}} - 可以将多个实体名称作为名为 <code>EntityGroup</code> 的数组传递给脚本。 | ||
*{{ent|point_template}} | *{{ent|point_template}} | ||
*{{ent|env_entity_maker}} | *{{ent|env_entity_maker}} | ||
*{{ent|info_item_position}} | *{{ent|info_item_position}} | ||
可以使用控制台命令 <code>ent_fire <实体名> runscriptfile ''<相对 vscript 路径>''</code> 重新加载脚本。这对于快速重新加载脚本很有用。 | |||
=== | === {{L|Inputs_and_Outputs|I/O 系统}} 交互 === | ||
任何脚本都可以使用 <code>EntFire()</code> 和 <code>DoEntFire()</code> 函数向地图实体触发输出。由于 <code>DoEntFire()</code> 中的 ''<code>activator</code>'' 和 ''<code>caller</code>'' 参数接受脚本句柄,因此可以使用它来使用 {{ent|!self}} 或 {{ent|!activator}} 关键字向实体触发输出,即使不必知道其名称,只要实体句柄可用。 | |||
<source lang=cpp> | <source lang=cpp> | ||
EntFire( "church_bell_relay", "Trigger", 0 ); // | EntFire( "church_bell_relay", "Trigger", 0 ); // 向命名实体的 Trigger 输入触发输出。 | ||
player <- null; | player <- null; | ||
while(player = Entities.FindByClassname(player, "player")) // | while(player = Entities.FindByClassname(player, "player")) // 遍历玩家的脚本句柄。 | ||
{ | { | ||
DoEntFire("!self", "speakresponseconcept", "PlayerLaugh", 0, null, player); // | DoEntFire("!self", "speakresponseconcept", "PlayerLaugh", 0, null, player); // 让每个玩家大笑。 | ||
} | } | ||
</source> | </source> | ||
相反,<code>{{L|Left 4 Dead 2/Script Functions#CBaseEntity|CBaseEntity}}::ConnectOutput()</code> 和 <code>DisconnectOutput()</code> 函数可用于在指定的实体输出触发时调用脚本函数。 | |||
此外,可以使用所有实体中可用的 <code>RunScriptCode</code> 输入从 I/O 系统运行任意 VScript 代码。代码将在当前实体的脚本作用域中运行。 | |||
{{warning| | {{warning|切勿在任何 Hammer 输出中使用双引号,因为它会损坏地图文件。这意味着无法使用 <code>RunScriptCode</code> 传递字符串。}} | ||
== | == 全局脚本 == | ||
将脚本文件命名为游戏模式名称会使其成为模式特定脚本,每次在指定模式下加载地图时都会执行。如果存在模式脚本,则也可以加载后跟下划线和模式名的地图特定脚本。 | |||
=== | === 模式脚本 === | ||
使用脚本作用域 <code>g_ModeScript</code> | |||
==== | ==== 表 ==== | ||
;<code>MutationState</code> | ;<code>MutationState</code> | ||
: | :<code>SessionState</code> 表的初始值。 | ||
;<code>MutationOptions</code> | ;<code>MutationOptions</code> | ||
: | :<code>SessionOptions</code> 表的初始值。 | ||
=== | === 地图脚本 === | ||
使用脚本作用域 <code>g_MapScript</code> | |||
==== | ==== 表 ==== | ||
;<code>MapState</code> | ;<code>MapState</code> | ||
: | :<code>SessionState</code> 表的地图特定值。 | ||
;<code>MapOptions</code> | ;<code>MapOptions</code> | ||
: | :<code>SessionOptions</code> 表的地图特定值。 | ||
=== | === 脚本模式 === | ||
添加模式脚本将为该游戏模式启用脚本模式。这也适用于游戏中包含的基础游戏模式。 | |||
脚本模式将实用函数加载到 <code>g_MapScript</code> 作用域中,禁用 <code>MaxSpecials</code> 导演选项上硬编码的 2 值,并启用 {{L|L4D2_EMS/Appendix:_Game_Events|游戏事件回调}} 和 {{L|Left 4 Dead 2/Script Functions#Scripted_Mode_hooks|脚本钩子函数}}。它似乎还会破坏 Dark Carnival 中的结局坦克音乐。 | |||
{{todo| | {{todo|启用脚本模式还有其他后果吗?}} | ||
==== | ==== 可用函数 ==== | ||
{{todo| | {{todo|记录可用的实用功能。}} | ||
=== | === 共享表 === | ||
;<code>SessionState</code> | ;<code>SessionState</code> | ||
: | :用于存储会话特定变量的表。不跨关卡过渡保留。 | ||
;<code>SessionOptions</code> | ;<code>SessionOptions</code> | ||
: | :游戏模式的活跃 {{L|L4D2_Director_Scripts#DirectorOptions|导演选项}}。 | ||
== | == 术语表 == | ||
;DirectorOptions | ;DirectorOptions | ||
: | :一个命名变量表,用于覆盖 AI 导演行为。 | ||
; | ;实体句柄 | ||
: | :也称为 EHANDLE。{{todo|看起来像是某种指向实体的指针引用。}} | ||
; | ;脚本句柄 | ||
: | :具有对 C++ 实体对象的访问器和修改器的实体实例。也称为 HScript。 | ||
; | ;脚本作用域 | ||
: | :放置 VScript 的变量、函数和类的表。 | ||
== | == 导演选项 == | ||
''' | '''请参阅 {{L|L4D2 Director Scripts#DirectorOptions|L4D2 导演脚本}} 了解可用选项表。''' | ||
== | == 第三方工具 == | ||
===VSLib=== | ===VSLib=== | ||
'''VSLib''' | '''VSLib'''(''V''Script ''Lib''rary)是一个用于 L4D2 的 VScript 突变系统的简单、轻量级库。它通过处理许多繁琐的工作,极大地简化了 VScript 的编码。它用于几个流行的模组中,如 [http://steamcommunity.com/sharedfiles/filedetails/?id=214630948 Rayman1103 的管理员系统] 和 [http://steamcommunity.com/sharedfiles/filedetails/?id=157525096 Stranded]。阅读更多关于 {{L|VSLib}} 的信息。 | ||
== | == 另请参阅 == | ||
=== | === 介绍 === | ||
* | *{{L|VScript}} | ||
* | *{{L|Mutation Gametype (L4D2)}} | ||
=== | === 文档 === | ||
* | *{{L|VSLib}} | ||
* | *{{L|L4D2 Vscript Examples}} | ||
* | *{{L|L4D2_Director_Scripts|L4D2 导演脚本}} | ||
* | *{{L|Left 4 Dead 2/Script Functions|L4D2 脚本函数}} | ||
* | *{{L|L4D2_Decrypted_mutations|解密突变 Vscripts}} | ||
* | *{{L|L4D2_Level_Design/Boss_Prohibition|L4D2 关卡设计/BOSS 禁止}} | ||
* | *{{L|L4D2_Level_Design/Custom_Finale|自定义结局}} ''包含所有原始结局脚本作为参考。'' | ||
* | *{{L|L4D2 EMS|扩展突变系统}} | ||
* | *{{L|Left_4_Dead_2_Tool_Updates|Left 4 Dead 2 工具更新}} | ||
=== | === 杂项 === | ||
*{{ent|logic_script}} | *{{ent|logic_script}} | ||
*{{ent|trigger_finale}} | *{{ent|trigger_finale}} | ||
*{{ent|info_director}} | *{{ent|info_director}} | ||
== | == 外部链接 == | ||
; | ;替代工具 | ||
* [http://www.mediafire.com/?q4dqbs554p494vk (mediafire)L4D2 VScript | * [http://www.mediafire.com/?q4dqbs554p494vk (mediafire) L4D2 VScript 编辑器 Beta 0.5 by Cynick:支持 nut (反)编译 for l4d2] | ||
; | ;替代文档 | ||
* [http://forums.steampowered.com/forums/showthread.php?t=1128303 | * [http://forums.steampowered.com/forums/showthread.php?t=1128303 导演脚本 - .nuc 文件 (Steam 论坛)] {{deadlink}} | ||
* [http://forums.steampowered.com/forums/showthread.php?t=1238461 | * [http://forums.steampowered.com/forums/showthread.php?t=1238461 这是 vscript'ing 文档 FAQ! (Steam 论坛)] {{deadlink}} | ||
* [http://forums.steampowered.com/forums/showthread.php?t=1242468 | * [http://forums.steampowered.com/forums/showthread.php?t=1242468 教程 - 编写一个小游戏 - 井字棋 - 第一部分 (Steam 论坛)] {{deadlink}} | ||
**[http://leeland.stores.yahoo.net/l4d2-scripts-play-tic-tac-toe.html | **[http://leeland.stores.yahoo.net/l4d2-scripts-play-tic-tac-toe.html 编写一个小游戏 - 井字棋 - 第一部分] - 作者网站 {{deadlink}} | ||
**[http://www.youtube.com/watch?v=B9hASsoHK54 l4d2 - Vscript | **[http://www.youtube.com/watch?v=B9hASsoHK54 l4d2 - Vscript 示例 - 井字棋] - 早期原型视频 | ||
**[http://www.youtube.com/watch?v=mvDFEoA0ib0 l4d2 - Vscript | **[http://www.youtube.com/watch?v=mvDFEoA0ib0 l4d2 - Vscript 示例 - 井字棋 - 更新] - 当前版本视频,带有"残忍厌世 AI" | ||
* [http://forums.steampowered.com/forums/showthread.php?t=1238004 | * [http://forums.steampowered.com/forums/showthread.php?t=1238004 突变脚本 (Steam 论坛)] {{deadlink}} | ||
* [http://modulatum.wordpress.com/2008/03/20/squirrel-binary-for-windows/ Squirrel | * [http://modulatum.wordpress.com/2008/03/20/squirrel-binary-for-windows/ Squirrel Windows 二进制文件] | ||
* [http://en.wikipedia.org/wiki/Squirrel_(programming_language) Squirrel ( | * [http://en.wikipedia.org/wiki/Squirrel_(programming_language) Squirrel (编程语言)] - Wikipedia 关于 Squirrel 的文章 | ||
* {{sq}}[http://squirrel-lang.org/ Squirrel: | * {{sq}}[http://squirrel-lang.org/ Squirrel: 编程语言 - 文档和示例代码] | ||
* [https://steamcdn-a.akamaihd.net/apps/valve/2009/ai_systems_of_l4d_mike_booth.pdf | * [https://steamcdn-a.akamaihd.net/apps/valve/2009/ai_systems_of_l4d_mike_booth.pdf Left 4 Dead 的 AI 系统 by Michael Booth (PDF)] | ||
* {{as}}[http://swarmarmory.com/forums/viewtopic.php?f=19&t=541 " | * {{as}}[http://swarmarmory.com/forums/viewtopic.php?f=19&t=541 "创建"金钱"/点数系统"] - Swarm Armory | ||
; | ;解密的官方脚本: | ||
*[http://www.mediafire.com/?k280fhwjsp21sn8 | *[http://www.mediafire.com/?k280fhwjsp21sn8 版本 2.1.3.6 和所有突变] | ||
*[http://ata4.info/downloads/left4dead2/scriptsrc.zip | *[http://ata4.info/downloads/left4dead2/scriptsrc.zip 版本 2.0.8.4 (2011年8月16日)] | ||
<div style="text-align: right; direction: ltr; margin-left: 1em;">{{sq}}+ {{l4d2}} = [[File:PinkHeartCensor.png|16px]]</div> | <div style="text-align: right; direction: ltr; margin-left: 1em;">{{sq}}+ {{l4d2}} = [[File:PinkHeartCensor.png|16px]]</div> | ||
{{ACategory|Left 4 Dead 2}} | |||
{{ACategory|VScript}} | |||
{{ACategory|Scripting}} |
Latest revision as of 07:43, 3 October 2025
此页面由世凪Yonagi个人汉化,欢迎大家添加新内容或修复错误。
有用链接
概述
Left 4 Dead 2 VScripts 是在游戏内虚拟机中运行的服务器端脚本。它们使用 Squirrel 编写,这是一种类似于 Lua 的编译型脚本语言。当前运行的是 Squirrel 3.0.4 版本。
用途
导演脚本
在《Left 4 Dead 2》中,VScript 最常见的用途是临时影响 AI 导演的行为。这些脚本的范围可以从简单的特感生成调整和 禁止BOSS特感 ,到自定义事件如猛攻和考验事件,甚至复杂的分阶段恐慌事件和完整的 自定义结局 。官方战役中的大多数事件主要是通过这种方式实现的。
导演脚本主要通过将导演使用的各种变量的覆盖值写入一个 DirectorOptions
表来工作。
一次只能运行一个导演脚本。执行新的脚本将终止任何先前运行的脚本,并移除它在 DirectorOptions
中设置的任何值。
实体脚本 ↓
另一个常见用途是将脚本附加到实体上。该脚本提供了读取和修改实体许多属性的便捷方法,甚至可以编写新的 KeyValues 。这使得能够以在 Hammer 中使用实体 I/O 系统非常复杂或不可能的方式控制实体。
任何实体都能够运行脚本,并且能够设置一个指定的 think 函数每 0.1 秒运行一次,以及作为实体输出执行脚本代码。
一些实体还具有针对 VScript 的专用函数,其中最突出的是 point_script_use_target,它允许将其他实体变成完全可编程的定时按钮。
全局脚本 ↓
脚本也可以设置为在地图加载时运行,基于游戏模式并可选择地图名称。这些脚本通常用于创建纯脚本插件和为 突变 修改全局导演选项。
全局脚本可以添加 脚本钩子函数 ,这些函数在特定事件(如玩家/对象受到伤害时)从游戏中被调用。
这些脚本有许多现成的实用函数和功能,包括资源和建筑系统,以及自定义恐慌波生成。请参阅 Valve 的 扩展突变系统教程 以获取更多信息。
其他用途
所有脚本都可以访问许多功能的函数,包括 生成实体 (从预编译列表或编程方式)、生成特感 、HUD 系统 、跨关卡和磁盘存储数据 等等。
请参阅 L4D2 Vscript Examples 以获取更多示例和想法。
脚本文件
脚本从文件扩展名为 .nut
和 .nuc
的文本文件加载,其中 .nuc
表示对纯文本 .nut
的加密。自定义脚本从 \left 4 dead 2\left4dead2\scripts\vscripts\ 读取,以及在打包到 .vpk
文件时从 \scripts\vscripts\ 读取。
位置
- 官方的
.nuc
脚本文件位于多个位置的 scripts/vscripts 目录中
- left 4 dead 2\left4dead2\pak01_dir.vpk
- left 4 dead 2\left4dead2_dlc1\pak01_dir.vpk
- 2010年4月22日 The Passing 更新
- left 4 dead 2\left4dead2_dlc2\pak01_dir.vpk
- 2010年10月5日 The Sacrifice 更新
- left 4 dead 2\left4dead2_dlc3\pak01_dir.vpk
- 2011年3月22日 Cold Stream Beta / L4D1 过渡项目更新
- left 4 dead 2\update\pak01_dir.vpk
- 这是突变每两周更新/替换的地方。也包含 2020年9月24日 The Last Stand 社区更新引入的文件。
- left 4 dead 2\sdk_content\scripting\scripts\vscripts\
- EMS 更新中引入的许多脚本的纯文本版本。
解密 NUC 文件
.nuc 文件是 ICE 加密的 .nut 文件。加密密钥是 SDhfi878。你可以使用 VICE 来解码它们。
你可以在 这里 找到解密的突变 vscripts。
加载 VScripts
VScripts 有多种加载方式,取决于它们的上下文。它们也可以使用控制台命令 script_execute 文件名
手动加载。
导演脚本
- BeginScript <脚本列表 >
- 执行通用导演脚本,无论是用于猛攻事件还是改变生成行为。
- 它们被放置在
LocalScript
脚本作用域中。
- EndScript
- 结束当前运行的本地脚本,然后将导演选项重置为地图特定值或默认值。

- {{subst
- LAuto|L4D2 Director Scripts#Finales and Scripted Panic Events|结局脚本]]
- 当 trigger_finale 结局开始时,它会加载此格式的脚本:
[地图名]_finale.nut
。 - 它们被放置在
g_MapScript
脚本作用域中。
实体脚本
- 键值
- 输入
- RunScriptFile <脚本 >
- 将给定脚本插入实体的作用域,然后运行它。
实体脚本被放置在 _<唯一ID>_<实体名称>
脚本作用域中。
全局脚本
- 模式脚本
- 与当前 {{subst:LAuto|Mutation_Gametype_(L4D2)|游戏模式]] 同名的脚本。在设置新模式时加载。
- 它们被放置在
g_ModeScript
脚本作用域中。 提示:
map
命令也可以设置游戏模式。例如,map <地图名> mutation12
加载写实对抗模式脚本mutation12.nuc
。注意:为模式添加脚本将启用脚本模式。
- 特定地图的模式脚本
- 当地图在指定游戏模式下加载时的每地图脚本。它们的名称格式为:[地图名]_[模式名].nut。
- 它们被放置在
g_MapScript
脚本作用域中。
- 插件脚本
- 这些脚本的上下文各不相同,但它们都有一个共同的大属性:它们不会覆盖同名的文件,而是与它们一起加载。它们按以下顺序执行,每个都在其各自的基础脚本(不带
_addon
后缀)之后执行。如果脚本被命名为以下之一,则被视为"插件脚本":mapspawn_addon.nut
(每章节运行一次)-getroottable()
作用域response_testbed_addon.nut
(每章节运行一次)-g_rr
作用域scriptedmode_addon.nut
(每回合运行两次)-g_MapScript
作用域director_base_addon.nut
(每回合运行两次)-DirectorScript
作用域
脚本环境
请参阅 Left 4 Dead 2/Script Functions 了解内置类和函数。
当脚本加载时,它被放置在一个表或脚本作用域中。全局脚本和导演脚本被放入设定的作用域,而为每个实体脚本生成唯一的作用域。更多信息请参阅 Vscript Fundamentals 。
表结构
DirectorScript = // 基础导演作用域。
{
DirectorOptions // 基础 DirectorOptions 表。
MapScript = // 地图脚本或 trigger_finale 脚本的作用域
{
DirectorOptions
BaseScriptedDOTable // 脚本模式的默认 DirectorOptions
ChallengeScript = // 模式脚本的作用域
{
DirectorOptions // 使用 BaseScriptedDOTable、MutationOptions 和 MapOptions 填充;如果存在相同的键,则最右边的表优先。
MutationState // 使用 MapState 覆盖先前值填充
MutationOptions // 如果在模式脚本中定义则使用初始值
}
LocalScript = // 通过 info_director 'BeginScript' 或 'ScriptedPanicEvent' 输入执行的脚本的作用域
{
DirectorOptions // 当前导演脚本的 DirectorOptions(如猛攻)。仅在脚本活动时可用
}
MapOptions // 如果在地图脚本中定义则使用初始值
MapState // 如果在地图脚本中定义则使用初始值
}
}
g_MapScript // 对地图脚本作用域 (DirectorScript.MapScript) 的全局引用。
g_ModeScript // 对模式脚本作用域 (DirectorScript.MapScript.ChallengeScript) 的全局引用。
SessionOptions // 对 g_ModeScript.DirectorOptions 的全局引用(仅限脚本模式)。
SessionState // 对 g_ModeScript.MutationState 的全局引用(仅限脚本模式)。
g_rr // 持有响应规则系统的作用域。
g_RoundState // 待办
委托
一些表设置了 委托,因此如果键不在其中,则从其委托(通常是父)表中读取。
这些表的委托关系如下(委托在右侧):
- 导演作用域
(DirectorScript.MapScript.ChallengeScript 或 DirectorScript.MapScript.LocalScript) < DirectorScript.MapScript < DirectorScript < ::
- DirectorOptions
DirectorScript.MapScript.ChallengeScript.DirectorOptions (仅限脚本模式) < DirectorScript.MapScript.LocalScript.DirectorOptions (当导演脚本活动时) < DirectorScript.MapScript.DirectorOptions < DirectorScript.DirectorOptions
- 请参阅 director_base.nut 中的 GetDirectorOptions。
实体脚本
使用脚本作用域 _<唯一 ID>_<实体名称>
将脚本添加到服务器端实体的 实体脚本 键值中,会将脚本作为实体脚本加载。脚本在实体生成时执行,并加载到一个由唯一标识符后跟实体名称或类名组成的唯一脚本作用域中。
可以使用 thinkfunction
键值 设置一个 think 函数,指定的脚本函数每 0.1 秒运行一次。虽然它有变得昂贵的潜力,但程序员能够限制执行的代码量。函数也可以通过 I/O 系统使用输入 RunScriptCode 函数名(参数, …)
手动调用。
实体脚本有一个 self
引用指向其拥有的实体句柄,允许脚本通过其类方法轻松控制实体。根据实体类,还有可用的钩子函数。两种方法和钩子都在 这里 有文档记录。
一些实体具有额外的脚本功能:
- point_script_use_target - 具有控制按钮的方法和钩子。
- logic_script - 可以将多个实体名称作为名为
EntityGroup
的数组传递给脚本。 - point_template
- env_entity_maker
- info_item_position
可以使用控制台命令 ent_fire <实体名> runscriptfile <相对 vscript 路径>
重新加载脚本。这对于快速重新加载脚本很有用。
I/O 系统 交互
任何脚本都可以使用 EntFire()
和 DoEntFire()
函数向地图实体触发输出。由于 DoEntFire()
中的 activator
和 caller
参数接受脚本句柄,因此可以使用它来使用 !self 或 !activator 关键字向实体触发输出,即使不必知道其名称,只要实体句柄可用。
EntFire( "church_bell_relay", "Trigger", 0 ); // 向命名实体的 Trigger 输入触发输出。
player <- null;
while(player = Entities.FindByClassname(player, "player")) // 遍历玩家的脚本句柄。
{
DoEntFire("!self", "speakresponseconcept", "PlayerLaugh", 0, null, player); // 让每个玩家大笑。
}
相反,CBaseEntity ::ConnectOutput()
和 DisconnectOutput()
函数可用于在指定的实体输出触发时调用脚本函数。
此外,可以使用所有实体中可用的 RunScriptCode
输入从 I/O 系统运行任意 VScript 代码。代码将在当前实体的脚本作用域中运行。

RunScriptCode
传递字符串。全局脚本
将脚本文件命名为游戏模式名称会使其成为模式特定脚本,每次在指定模式下加载地图时都会执行。如果存在模式脚本,则也可以加载后跟下划线和模式名的地图特定脚本。
模式脚本
使用脚本作用域 g_ModeScript
表
MutationState
SessionState
表的初始值。MutationOptions
SessionOptions
表的初始值。
地图脚本
使用脚本作用域 g_MapScript
表
MapState
SessionState
表的地图特定值。MapOptions
SessionOptions
表的地图特定值。
脚本模式
添加模式脚本将为该游戏模式启用脚本模式。这也适用于游戏中包含的基础游戏模式。
脚本模式将实用函数加载到 g_MapScript
作用域中,禁用 MaxSpecials
导演选项上硬编码的 2 值,并启用 游戏事件回调 和 脚本钩子函数 。它似乎还会破坏 Dark Carnival 中的结局坦克音乐。
可用函数
共享表
SessionState
- 用于存储会话特定变量的表。不跨关卡过渡保留。
SessionOptions
- 游戏模式的活跃 导演选项 。
术语表
- DirectorOptions
- 一个命名变量表,用于覆盖 AI 导演行为。
- 实体句柄
- 也称为 EHANDLE。待完善: 看起来像是某种指向实体的指针引用。
- 脚本句柄
- 具有对 C++ 实体对象的访问器和修改器的实体实例。也称为 HScript。
- 脚本作用域
- 放置 VScript 的变量、函数和类的表。
导演选项
请参阅 L4D2 导演脚本 了解可用选项表。
第三方工具
VSLib
VSLib(VScript Library)是一个用于 L4D2 的 VScript 突变系统的简单、轻量级库。它通过处理许多繁琐的工作,极大地简化了 VScript 的编码。它用于几个流行的模组中,如 Rayman1103 的管理员系统 和 Stranded。阅读更多关于 VSLib 的信息。
另请参阅
介绍
文档
- VSLib
- L4D2 Vscript Examples
- L4D2 导演脚本
- L4D2 脚本函数
- 解密突变 Vscripts
- L4D2 关卡设计/BOSS 禁止
- 自定义结局 包含所有原始结局脚本作为参考。
- 扩展突变系统
- Left 4 Dead 2 工具更新
杂项
外部链接
- 替代工具
- 替代文档
- 导演脚本 - .nuc 文件 (Steam 论坛) [dead link]
- 这是 vscript'ing 文档 FAQ! (Steam 论坛) [dead link]
- 教程 - 编写一个小游戏 - 井字棋 - 第一部分 (Steam 论坛) [dead link]
- 编写一个小游戏 - 井字棋 - 第一部分 - 作者网站 [dead link]
- l4d2 - Vscript 示例 - 井字棋 - 早期原型视频
- l4d2 - Vscript 示例 - 井字棋 - 更新 - 当前版本视频,带有"残忍厌世 AI"
- 突变脚本 (Steam 论坛) [dead link]
- Squirrel Windows 二进制文件
- Squirrel (编程语言) - Wikipedia 关于 Squirrel 的文章
Squirrel: 编程语言 - 文档和示例代码
- Left 4 Dead 的 AI 系统 by Michael Booth (PDF)
"创建"金钱"/点数系统" - Swarm Armory
- 解密的官方脚本