生还者游戏模式(求生之路)

From Valve Developer Community
Jump to navigation Jump to search
English (en)Español (es)Русский (ru)中文 (zh)Translate (Translate)

This updated page was translated by DaKang233 on February 12, 2024 (UTC+8). Anyone is welcome to add new content or fix errors. Some of the content was translated by machine.


本文包括为求生之路(en)创建生还者模式地图的基本指导。

开始生还者模式

生存回合通过触发任何形式的恐慌事件开始。
任何能够告诉导演强制触发恐慌事件(en)的实体都有效。比如func_button(en)func_button_timed(en)trigger_finale(en)trigger_once(en)prop_car_alarm(en),甚至是自动点唱机上的某首歌。
这与启动结局事件或高潮事件(crescendo event)的设置方法相同。

导航网格

所有生还者模式地图都依赖于使用「Finale」或「Battlefield」以及可选的「Battlestation」属性在导航网格上定义生还者模式的游戏空间。
根据地图是专为生还者模式设计,还是在已经用于战役的地图中添加生还者模式,导航网格的设置方法有所不同。

Tip.png提示:使用Nav_mode.cfg(en)可以更轻松地编辑导航网格。

纯生还者模式地图

仅用于支持生还者游戏模式的地图只需要三个nav_mesh 属性(en):Player_Start、Battlefield 和 Finale。

  1. 进入Nav编辑模式(en),使用控制台命令nav_add_to_selected_set选择玩家起始点周围的区域,选择一个导航方块,或使用nav_begin_drag_selecting接着使用nav_end_drag_selecting进行框选多个方块。
  2. 使用控制台命令mark player_start标记为玩家起始区域。
  3. 使用控制台命令nav_select_radius 99999999999999选择整个导航网格并将其标记为BattlefieldNOT_CLEARABLE
  4. 使用控制台命令nav_clear_selected_set取消整个导航网格的选择。
  5. 在生存开始触发器周围(或任何地方)选择几个导航网格方块,并将这些面标记为Finale
  6. 使用控制台命令nav_save保存导航网格。
  7. 一旦确定导航网格完成,使用nav_analyze进行完整分析。

其他有用的属性:

  • Battlestation - 使生还者机器人在战斗时保持靠近该区域。
  • Obscured - 将一个区域标记为始终无法看到。非常有用,用来告诉导演可以在此区域自由生成感染者。
  • No_Mobs - 强制导演在该导航区域内不生成任何普通感染者。适用于「竞技场类」地图,感染者应通过门进入。

多模式地图

现有的高潮事件或结局事件,如果使用了「Battlefield」或「Finale」导航属性,通常可以在不修改导航网格的情况下直接使用。

如果你的地图在合作模式地图中添加了生存部分,请添加一个func_nav_attribute_region(en),将生存区域以及感染者应该生成的区域围住。
将其命名为「survival_nav_battlefield」,并启用「Battlefield」和「Not_Clearable」标记。你还可以添加多个具有相同名称的「func_nav_attribute_region」实体,用于更多属性,如「Battlestation」,这是生还者机器人通常停留的区域。

Note.png注意:在多模式地图中,无法在同一区域同时使用「Player_start」和「Finale」属性。

要启用这些导航属性,你需要一个info_gamemode(en)实体,强制生成一个带有输出「OnSurvivalPostIO」的point_template(en)实体。

  My Output Target Entity Target Input Parameter Delay Only Once
Io11.png OnSurvivalPostIO Point_template ForceSpawn <none> 0.0 No

这个point_template可以用来生成所有生还者模式所需的实体,如所有武器和阻挡路径的道具。

info_survivor_position

生还者会在info_survivor_position(en)实体处生成。
不幸的是,结局地图使用相同的实体在生还者接近逃生车辆时将其「传送」走。如果你的生还者模式地图也是战役的结局,或者你的地图将info_survivor_position用于生存起点之外的其他用途,你需要删除这些实体。否则,玩家可能会生成到错误的位置。
通过Info_gamemode(en)实体删除额外的info_survivor_position实体,使用以下输出

  My Output Target Entity Target Input Parameter Delay Only Once
Io11.png OnSurvival 救援中使用的 info_survivor_position kill <none> 0.0 No

道具

在L4D中,地图中放置的所有道具在生还者模式中都会生成,无论其他模式中允许的道具密度如何。如果你希望更改道具的放置或数量,可以使用info_gamemode来生成或删除道具。

在L4D2中,生还者模式下会删除所有道具生成。
为了生成道具,你必须为每个预定的生存道具命名。你可以将所有道具命名为相同的名称以便管理。

Note.png注意:导演控制的实体,如weapon_spawn(en)weapon_item_spawn(en)不起作用。


添加一个point_template(en),为其指定一个唯一的名称,并在其「Template」行中列出所有生存道具的名称。
添加一个info_gamemode(en)实体,并设置以下输出

  My Output Target Entity Target Input Parameter Delay Only Once
Io11.png OnSurvivalPostIO Point_template ForceSpawn <none> 0.0 No
Warning.png警告:使用「OnSurvival」代替「OnSurvivalPostIO」将导致弹药和弹药升级无法生成。

info_gamemode - 其他用途

地图可以根据运行的游戏模式加载不同的实体。如前一节所述,L4D2中的生还者模式需要info_gamemode和point_template来生成任何生还者模式中的道具。
这两个实体还可以用于加载func_brush(en)墙体、碰撞刷、prop_dynamic(en)、道具或任何其他类型的实体到你的生还者模式地图中。例如,添加屏障道具来阻止玩家进入结束地图的安全房间。
或者,你可以使用info_gamemode与logic_relay(en)配合,删除你不希望在生还者模式中出现的道具,如警报车(en),它们在被射击时会提前启动生存回合。

任务文件和测试

在你测试生还者模式地图之前,你必须将你的地图添加到任务文件的“生存”模式部分。

Note.png注意:你可以通过开发者控制台更方便地进入地图,使用命令map [mapnamehere] survival。当然,在发布地图之前,你仍然需要创建任务文件。

示例:

"modes"
{
 	"survival"
 	{
 		"1"
 		{
 		"Map" "mymap"
 		"DisplayName" "我的生还者模式地图"
 		"Image" "maps/preview_01"	
 		}
 	}
}

地图可以通过主菜单加载到生还者模式,或者通过控制台使用命令“map mapname_here survival”加载。后者允许你在生还者模式下使用 sv_cheats 1。

通过Vscript更改默认设置

生还者模式的大部分设置,甚至可以说是所有设置,都是一组控制台命令。这意味着我们几乎可以完全改变生还者模式的行为。
以下Vscript(en)可以添加到任何point_entity(en)的Vscript变量中。最好是info_director。地图启动后,它将用你定义的设置替换所有默认设置。

PlacementTip.png示例:survival_horde_stage_interval_decay 设置为0将停止军团在更短间隔内的出现。
Note.png注意:Mutation15,即“对抗生存”,也会在地图启动时移除所有weapon_upgradepack_explosive
// 生存控制变量
Convars.SetValue("director_survival_setup_time",         	 0) //默认值: 0 - 自动开始之前的设置时间限制。
Convars.SetValue("survival_boomer_limit_increase",       	 0) //默认值: 0 - 每个特殊波之后,增加最大Boomer数量。
Convars.SetValue("survival_charger_limit_increase",      	 0)	//默认值: 0 - 每个特殊波之后,增加最大Charger数量。
Convars.SetValue("survival_horde_stage_interval",        	60) //默认值: 60 - 军团攻击之间的间隔秒数。
Convars.SetValue("survival_horde_stage_interval_decay",  	 2) //默认值: 2 - 每次军团攻击后,将间隔减少的秒数。
Convars.SetValue("survival_hunter_limit_increase",       	 1) //默认值: 1 - 每个特殊波之后,增加最大Hunter数量。
Convars.SetValue("survival_jockey_limit_increase",       	 1) //默认值: 1 - 每个特殊波之后,增加最大Jockey数量。
Convars.SetValue("survival_lull_time",                   	15) //默认值: 15 - 生存波之间的平静时长。
Convars.SetValue("survival_lull_time_increment",         	15) //默认值: 15 - 每波生存时,平静时长的增量。
Convars.SetValue("survival_lull_time_max",               	60) //默认值: 60 - 平静时长的最大值。
Convars.SetValue("survival_max_boomers",                 	 2) //默认值: 2 - 同时存在的最大Boomer数量。
Convars.SetValue("survival_max_chargers",                	 2) //默认值: 2 - 同时存在的最大Charger数量。
Convars.SetValue("survival_max_hunters",                 	 3) //默认值: 3 - 同时存在的最大Hunter数量。
Convars.SetValue("survival_max_jockeys",                 	 2) //默认值: 2 - 同时存在的最大Jockey数量。
Convars.SetValue("survival_max_smokers",                 	 4) //默认值: 4 - 同时存在的最大Smoker数量。
Convars.SetValue("survival_max_specials",                	 8) //默认值: 8 - 同时存在的最大特殊感染者数量。
Convars.SetValue("survival_max_spitters",                	 3) //默认值: 3 - 同时存在的最大Spitter数量。
Convars.SetValue("survival_round_restart_delay",         	15) //默认值: 15 - 失败后,重新开始这一轮的延迟秒数。
Convars.SetValue("survival_smoker_limit_increase",       	 1) //默认值: 1 - 每个特殊波之后,增加最大Smoker数量。
Convars.SetValue("survival_special_limit_increase",      	 1) //默认值: 1 - 每个特殊波之后,增加最大特殊感染者数量。
Convars.SetValue("survival_special_spawn_interval",      	20) //默认值: 20 - 特殊感染者生成波之间的间隔秒数。
Convars.SetValue("survival_special_spawn_interval_decay",	 1)	//默认值: 1 - 每个特殊波后,减少生成间隔的秒数。
Convars.SetValue("survival_special_stage_interval",      	60) //默认值: 60 - 在经过多少秒后,增加特殊感染者数量限制。
Convars.SetValue("survival_spitter_limit_increase",      	 1)	//默认值: 1 - 每个特殊波后,增加最大Spitter数量。
Convars.SetValue("survival_tank_multiple_spawn_delay",   	10) //默认值: 10 - 双重生成时,两只Tank之间的延迟。
Convars.SetValue("survival_tank_stage_interval",         	80) //默认值: 80 - Tank攻击之间的间隔秒数。
Convars.SetValue("survival_tank_stage_interval_decay",   	20) //默认值: 20 - 若干波后,减少Tank攻击间隔的秒数。

DirectorOptions <- {
// 故意留空。 
// 必须有以下的 Mutation15 相关内容才能生效。
}

// Mutation15 (对抗生存) 的控制台变量。只有在 Mutation15 激活时才会更改这些设置。

if ( Director.GetGameMode() == "mutation15" )
{ 
    DirectorOptions.ActiveChallenge <- 1; 
    DirectorOptions.cm_ProhibitBosses <- 0; 
    DirectorOptions.cm_CommonLimit <- 25; 
    DirectorOptions.cm_TankLimit <- 1; 
    DirectorOptions.ZombieTankHealth <- 2667; 

    // Mutation 15 会在 90 秒后强制启动生存计时器。但这只会触发“PanicEvent”输出。
    // 如果你的生存启动按钮也触发声音、粒子效果或其他事件,这些事件将不会被触发。
    // 要确保这些事件被触发,你必须使用以下函数来自动触发按钮。
    // 请注意,如果你的生存启动按钮有在计时器上触发“ForcePanicEvent”,你需要将其包含到计算中。
    // 举个例子,“SurvivalSetupTime”在 90 秒后触发。
    // “Survival_Start_relay”在 89 秒后触发,但还需要 1 秒延迟来强制触发 PanicEvent。因此两个 PanicEvent 会同时触发。
    
    DirectorOptions.SurvivalSetupTime <- 90; // 在 90 秒后触发 PanicEvent。
    function OnGameEvent_round_start_post_nav(params){
        DoEntFire("Survival_Start_relay", "trigger", "", 89, null, null) // 在 89 秒后触发此继电器。
    }

    Convars.SetValue("director_special_initial_spawn_delay_max", 10)   // coop 默认: 60    -   mutation15 默认: 10    
    Convars.SetValue("director_special_initial_spawn_delay_min", 2)    // coop 默认: 30    -   mutation15 默认: 2    
    Convars.SetValue("tongue_break_from_damage_amount", 300)           // coop 默认: 50    -   mutation15 默认: 300    
    Convars.SetValue("tongue_choke_damage_amount", 5)                  // coop 默认: 10    -   mutation15 默认: 5    
    Convars.SetValue("tongue_dropping_to_ground_time", 0.5)            // coop 默认: 2     -   mutation15 默认: 0.5  
    Convars.SetValue("tongue_hit_delay", 15)                           // coop 默认: 20    -   mutation15 默认: 15    
    Convars.SetValue("tongue_los_forgiveness_time", 1.5)               // coop 默认: 1     -   mutation15 默认: 1.5  
    Convars.SetValue("tongue_miss_delay", 3)                           // coop 默认: 15    -   mutation15 默认: 3    
    Convars.SetValue("tongue_no_progress_choke_early_delay", 1.0)      // coop 默认: 1.5   -   mutation15 默认: 1.0  
    Convars.SetValue("z_ghost_los_expected_progress", 2000)             // coop 默认: 1500  -   mutation15 默认: 2000    
    Convars.SetValue("z_hunter_limit", 2)                               // coop 默认: 1     -   mutation15 默认: 2    
    Convars.SetValue("z_jockey_ride_damage", 2)                        // coop 默认: 4     -   mutation15 默认: 2    
    Convars.SetValue("z_jockey_ride_damage_interval", 0.5)             // coop 默认: 1     -   mutation15 默认: 0.5  
    Convars.SetValue("z_max_stagger_duration", 0.9)                     // coop 默认: 6     -   mutation15 默认: 0.9  
    Convars.SetValue("z_pounce_damage_interrupt", 150)                  // coop 默认: 50    -   mutation15 默认: 150    
    Convars.SetValue("z_pounce_stumble_radius", 160)                    // coop 默认: 0     -   mutation15 默认: 160    
    Convars.SetValue("z_scrimmage_creep_delay", 0)                      // coop 默认: 30    -   mutation15 默认: 0    
    Convars.SetValue("z_scrimmage_creep_rate", 100)                     // coop 默认: 30    -   mutation15 默认: 100    
    Convars.SetValue("z_smoker_limit", 2)                               // coop 默认: 1     -   mutation15 默认: 2    
    Convars.SetValue("z_spawn_safety_range", 200)                       // coop 默认: 550   -   mutation15 默认: 200    
}

另请参阅