脚本

From Valve Developer Community
< Zh‎ | Left 4 Dead 2
Revision as of 07:39, 3 October 2025 by 世凪Yonagi (talk | contribs) (汉化代码修正监察。)
Jump to navigation Jump to search
English (en)中文 (zh)Translate (Translate)
<(en)
edit
Left 4 Dead 2/Docs

此页面由世凪Yonagi个人汉化,欢迎大家添加新内容或修复错误。


有用链接

概述

Squirrel求生之路2 Left 4 Dead 2 VScripts(en) 是在游戏内虚拟机中运行的服务器端脚本。它们使用 Squirrel(en) 编写,这是一种类似于 Lua 的编译型脚本语言。当前运行的是 Squirrel 3.0.4 版本。

用途

导演脚本(en)

在《Left 4 Dead 2》中,VScript(en) 最常见的用途是临时影响 AI 导演的行为。这些脚本的范围可以从简单的特感生成调整和 禁止BOSS特感(en),到自定义事件如猛攻和考验事件,甚至复杂的分阶段恐慌事件和完整的 自定义结局(en)。官方战役中的大多数事件主要是通过这种方式实现的。

导演脚本主要通过将导演使用的各种变量的覆盖值写入一个 DirectorOptions 表来工作。

一次只能运行一个导演脚本。执行新的脚本将终止任何先前运行的脚本,并移除它在 DirectorOptions 中设置的任何值。

实体脚本 ↓

另一个常见用途是将脚本附加到实体上。该脚本提供了读取和修改实体许多属性的便捷方法,甚至可以编写新的 KeyValues(en)。这使得能够以在 Hammer 中使用实体 I/O 系统非常复杂或不可能的方式控制实体。

任何实体都能够运行脚本,并且能够设置一个指定的 think 函数每 0.1 秒运行一次,以及作为实体输出执行脚本代码。

一些实体还具有针对 VScript 的专用函数,其中最突出的是 point_script_use_target,它允许将其他实体变成完全可编程的定时按钮。

全局脚本 ↓

脚本也可以设置为在地图加载时运行,基于游戏模式并可选择地图名称。这些脚本通常用于创建纯脚本插件和为 突变(en) 修改全局导演选项。

全局脚本可以添加 脚本钩子函数(en),这些函数在特定事件(如玩家/对象受到伤害时)从游戏中被调用。

这些脚本有许多现成的实用函数和功能,包括资源和建筑系统,以及自定义恐慌波生成。请参阅 Valve 的 扩展突变系统教程(en) 以获取更多信息。

其他用途

所有脚本都可以访问许多功能的函数,包括 生成实体(en)(从预编译列表或编程方式)、生成特感(en)HUD 系统(en)、跨关卡和磁盘存储数据(en)等等。

请参阅 L4D2 Vscript Examples(en) 以获取更多示例和想法。

脚本文件

脚本从文件扩展名为 .nut.nuc 的文本文件加载,其中 .nuc 表示对纯文本 .nut 的加密。自定义脚本从 \left 4 dead 2\left4dead2\scripts\vscripts\ 读取,以及在打包到 .vpk 文件时从 \scripts\vscripts\ 读取。

位置

官方的 .nuc 脚本文件位于多个位置的 scripts/vscripts 目录中
Note.png注意:使用 GCFScape(en) 等第三方程序浏览和提取 VPK(en) 文件。
  • 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(en) 来解码它们。
你可以在 这里(en) 找到解密的突变 vscripts。

加载 VScripts

VScripts 有多种加载方式,取决于它们的上下文。它们也可以使用控制台命令 script_execute 文件名 手动加载。

导演脚本

BeginScript <脚本列表(en)>
执行通用导演脚本,无论是用于猛攻事件还是改变生成行为。
它们被放置在 LocalScript 脚本作用域中。
EndScript
结束当前运行的本地脚本,然后将导演选项重置为地图特定值或默认值。
ScriptedPanicEvent <脚本列表(en)>
使用给定的脚本,设置 脚本化恐慌事件(en) 的结构。
它们被放置在 LocalScript 脚本作用域中。
Note.png注意:这些输入的脚本必须位于 "vscripts" 子文件夹下。否则事件将只播放 1 秒延迟的"阶段 0"。
{{subst
  • LAuto|L4D2 Director Scripts#Finales and Scripted Panic Events|结局脚本]]
trigger_finale 结局开始时,它会加载此格式的脚本:[地图名]_finale.nut
它们被放置在 g_MapScript 脚本作用域中。

实体脚本

  • 键值
Entity Scripts (vscripts) <脚本列表(en)>
在实体生成前准备自身时,将运行该键值中的 VScript 路径名称。(更多信息请参见 实体脚本(en)。)
  • 输入
RunScriptFile <脚本(en)>
将给定脚本插入实体的作用域,然后运行它。

实体脚本被放置在 _<唯一ID>_<实体名称> 脚本作用域中。

全局脚本

  • 模式脚本
与当前 {{subst:LAuto|Mutation_Gametype_(L4D2)|游戏模式]] 同名的脚本。在设置新模式时加载。
它们被放置在 g_ModeScript 脚本作用域中。
Tip.png提示:map 命令也可以设置游戏模式。例如,map <地图名> mutation12 加载写实对抗模式脚本 mutation12.nuc
Note.png注意:为模式添加脚本将启用脚本模式。
  • 特定地图的模式脚本
当地图在指定游戏模式下加载时的每地图脚本。它们的名称格式为:[地图名]_[模式名].nut
它们被放置在 g_MapScript 脚本作用域中。
  • 插件脚本
这些脚本的上下文各不相同,但它们都有一个共同的大属性:它们不会覆盖同名的文件,而是与它们一起加载。它们按以下顺序执行,每个都在其各自的基础脚本(不带 _addon 后缀)之后执行。如果脚本被命名为以下之一,则被视为"插件脚本":
  1. mapspawn_addon.nut(每章节运行一次)- getroottable() 作用域
  2. response_testbed_addon.nut(每章节运行一次)- g_rr 作用域
  3. scriptedmode_addon.nut(每回合运行两次)- g_MapScript 作用域
  4. director_base_addon.nut(每回合运行两次)- DirectorScript 作用域

脚本环境

请参阅 Left 4 Dead 2/Script Functions(en) 了解内置类和函数。

当脚本加载时,它被放置在一个表或脚本作用域中。全局脚本和导演脚本被放入设定的作用域,而为每个实体脚本生成唯一的作用域。更多信息请参阅 Vscript Fundamentals(en)

表结构

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 键值(en) 设置一个 think 函数,指定的脚本函数每 0.1 秒运行一次。虽然它有变得昂贵的潜力,但程序员能够限制执行的代码量。函数也可以通过 I/O 系统使用输入 RunScriptCode 函数名(参数, …) 手动调用。

实体脚本有一个 self 引用指向其拥有的实体句柄,允许脚本通过其类方法轻松控制实体。根据实体类,还有可用的钩子函数。两种方法和钩子都在 这里(en) 有文档记录。

一些实体具有额外的脚本功能:

可以使用控制台命令 ent_fire <实体名> runscriptfile <相对 vscript 路径> 重新加载脚本。这对于快速重新加载脚本很有用。

I/O 系统(en) 交互

任何脚本都可以使用 EntFire()DoEntFire() 函数向地图实体触发输出。由于 DoEntFire() 中的 activatorcaller 参数接受脚本句柄,因此可以使用它来使用 !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(en)::ConnectOutput()DisconnectOutput() 函数可用于在指定的实体输出触发时调用脚本函数。 此外,可以使用所有实体中可用的 RunScriptCode 输入从 I/O 系统运行任意 VScript 代码。代码将在当前实体的脚本作用域中运行。

Warning.png警告:切勿在任何 Hammer 输出中使用双引号,因为它会损坏地图文件。这意味着无法使用 RunScriptCode 传递字符串。

全局脚本

将脚本文件命名为游戏模式名称会使其成为模式特定脚本,每次在指定模式下加载地图时都会执行。如果存在模式脚本,则也可以加载后跟下划线和模式名的地图特定脚本。

模式脚本

使用脚本作用域 g_ModeScript

MutationState
SessionState 表的初始值。
MutationOptions
SessionOptions 表的初始值。

地图脚本

使用脚本作用域 g_MapScript

MapState
SessionState 表的地图特定值。
MapOptions
SessionOptions 表的地图特定值。

脚本模式

添加模式脚本将为该游戏模式启用脚本模式。这也适用于游戏中包含的基础游戏模式。

脚本模式将实用函数加载到 g_MapScript 作用域中,禁用 MaxSpecials 导演选项上硬编码的 2 值,并启用 游戏事件回调(en)脚本钩子函数(en)。它似乎还会破坏 Dark Carnival 中的结局坦克音乐。

待完善: 启用脚本模式还有其他后果吗?

可用函数

待完善: 记录可用的实用功能。

共享表

SessionState
用于存储会话特定变量的表。不跨关卡过渡保留。
SessionOptions
游戏模式的活跃 导演选项(en)

术语表

DirectorOptions
一个命名变量表,用于覆盖 AI 导演行为。
实体句柄
也称为 EHANDLE。
待完善: 看起来像是某种指向实体的指针引用。
脚本句柄
具有对 C++ 实体对象的访问器和修改器的实体实例。也称为 HScript。
脚本作用域
放置 VScript 的变量、函数和类的表。

导演选项

请参阅 L4D2 导演脚本(en) 了解可用选项表。

第三方工具

VSLib

VSLibVScript Library)是一个用于 L4D2 的 VScript 突变系统的简单、轻量级库。它通过处理许多繁琐的工作,极大地简化了 VScript 的编码。它用于几个流行的模组中,如 Rayman1103 的管理员系统Stranded。阅读更多关于 VSLib(en) 的信息。

另请参阅

介绍

文档

杂项

外部链接

替代工具
替代文档
解密的官方脚本
Squirrel+ 求生之路2 = PinkHeartCensor.png