求生之路2关卡设计/自定义结局
< Zh | L4D2 Level Design
本页面由大康翻译于2022年1月2日。部分内容由机器翻译。
Contents
- 1 组成内容
- 2 牺牲结局
- 3 解密的官方结局脚本
- 3.1 c1m4_atrium_finale.nuc
- 3.2 c1m4_finale_wave_1.nuc
- 3.3 c1m4_delay.nuc
- 3.4 c2m5_concert_finale.nuc
- 3.5 c3m4_plantation_finale.nuc
- 3.6 c4m5_milltown_escape_finale.nuc
- 3.7 c6m3_port_finale.nuc
- 3.8 c7m3_port_finale.nuc
- 3.9 c8m5_rooftop_finale.nuc
- 3.10 c9m2_lots_finale.nuc
- 3.11 c10m5_houseboat_finale.nuc
- 3.12 c11m5_runway_finale.nuc
- 3.13 c12m5_cornfield_finale.nuc
- 3.14 c14m1_lighthouse_finale.nuc
- 3.15 c14m2_lighthouse_finale.nuc
- 3.16 director_gauntlet.nuc (为所有长途救援结局共享)
- 4 另请参阅
自定义结局 会自动从包含阶段列表的脚本(VScript) 中读取:<地图名称>_finale.nut。该系统具有在满足任意条件(即终极感染者、Aztec tomb puzzles、feats of strength 等)时增强结局阶段的能力。一旦所有阶段都完成,trigger_finale 会触发 FinaleEscapeStarted 输出。
自定义结局地图包括 c2m5_concert、c3m4_plantation、c4m5_milltown_escape、c7m3_port,假设求生之路1的结局也一样(毫不留情已被确认是使用自定义结局的)。官方地图不使用Standard
(标准) 结局类型。
组成内容
地图
最起码,所有需要改变的是 trigger_finale 的 Finale Type (结局类型),从Standard
到Custom
。你还应该考虑其他选项和细节:
- 除非通过脚本 EntFire(直接或间接)或简单地在游戏中使用 I/O 为导演 提供输入 EndCustomScriptedStage,否则猛攻(Onslaught)阶段类型不会结束。
- info_director: 在自定义结局事件时,OnCustomPanicStageFinished, OnPanicEventFinished (也许只是为了渐强事件),和 OnUserDefinedScriptEvent(1-4) 输出可用,链接到 vscript 阶段状态或方法,如 .UserDefinedEvent1()-.UserDefinedEvent4().
- trigger_finale: AdvanceFinaleState 输入可用。
脚本
正如 L4D2 脚本文章中所讨论的,有四种阶段类型、附加的自定义结局特定导演选项和可用的特殊功能。
以下是带有附加注释的自定义结局脚本:
c2m5_concert_finale.nut
//-----------------------------------------------------------------------------
// 阶段类型的列举
ERROR <- -1 //这个枚举并不总是使用,但到底是什么!
PANIC <- 0
TANK <- 1
DELAY <- 2
ONSLAUGHT <- 3
//-----------------------------------------------------------------------------
// 将提供给 DirectorOptions 的表的初始化
SharedOptions <-
{
A_CustomFinale_StageCount = 9 //阶段数。也被导演VS评分用了??
A_CustomFinale1 = PANIC
A_CustomFinaleValue1 = 1 //1 个尸潮
A_CustomFinale2 = PANIC
A_CustomFinaleValue2 = 1
A_CustomFinale3 = DELAY
A_CustomFinaleValue3 = 15 //15秒的延迟
A_CustomFinale4 = TANK
A_CustomFinaleValue4 = 1 //1 TANK
A_CustomFinaleMusic4 = "" //自定义音乐条目在脚本中关闭,在游戏中播放
A_CustomFinale5 = DELAY
A_CustomFinaleValue5 = 15
A_CustomFinale6 = PANIC
A_CustomFinaleValue6 = 2
A_CustomFinale7 = DELAY
A_CustomFinaleValue7 = 10
A_CustomFinale8 = TANK
A_CustomFinaleValue8 = 1
A_CustomFinaleMusic8 = ""
A_CustomFinale9 = DELAY
A_CustomFinaleValue9 = RandomInt( 5, 10 ) //5-10 秒之间的随机延迟
// 其他导演选项
PreferredMobDirection = SPAWN_LARGE_VOLUME
PreferredSpecialDirection = SPAWN_LARGE_VOLUME
ShouldConstrainLargeVolumeSpawn = false
ZombieSpawnRange = 3000
SpecialRespawnInterval = 20
}
InitialPanicOptions <- //与阶段 1 的 SharedOptions 分开的表
{
ShouldConstrainLargeVolumeSpawn = true
}
PanicOptions <- //一般的尸潮选项
{
CommonLimit = 25
}
TankOptions <- //TANK 阶段时使用的另一个单独的表
{
ShouldAllowSpecialsWithTank = true
SpecialRespawnInterval = 30
}
DirectorOptions <- clone SharedOptions //DirectorOptions 使用 SharedOptions
{
}
//-----------------------------------------------------------------------------
// 经常用于将表复制到另一个表
function AddTableToTable( dest, src )
{
foreach( key, val in src )
{
dest[key] <- val
}
}
//-----------------------------------------------------------------------------
// 使用自定义逻辑操作 DirectorOptions
// 在这种情况下,DirectorOptions 仅在新阶段开始时更改
function OnBeginCustomFinaleStage( num, type ) //特殊功能,当每个新的结局阶段开始时
{
if ( developer() > 0 ) //如果开发者模式打开,-dev
{
printl("========================================================");
printl( "Beginning custom finale stage " + num + " of type " + type );
}
//设置/确定 WAVEOPTIONS
local waveOptions = null
if ( num == 1 ) //如果第一阶段(假设是 PANIC)
{
waveOptions = InitialPanicOptions
}
else if ( type == PANIC ) //一般的尸潮(又名“恐慌事件”,"Panic Event")事件
{
waveOptions = PanicOptions
/* Change MegaMobSize if MegaMobMinSize is available in PanicOptions is available.
Was this ever used?? */
if ( "MegaMobMinSize" in PanicOptions )
{
waveOptions.MegaMobSize <- RandomInt( PanicOptions.MegaMobMinSize, MegaMobMaxSize )
}
}
else if ( type == TANK ) //TANK 时间!
{
waveOptions = TankOptions
}
//---------------------------------
// 完成确定 WAVEOPTIONS。现在,实际转到 DirectorOptions
MapScript.DirectorOptions.clear() //清除所有 DirectorOptions 表的值
AddTableToTable( MapScript.DirectorOptions, SharedOptions ); //返回到 SharedOptions
if ( waveOptions != null ) //最后添加依赖于阶段的选项(WAVEOPTIONS)
{
AddTableToTable( MapScript.DirectorOptions, waveOptions );
}
//---------------------------------
if ( developer() > 0 ) //更多开发输出 (-dev)
{
Msg( "\n*****\nMapScript.DirectorOptions:\n" );
foreach( key, value in MapScript.DirectorOptions )
{
Msg( " " + key + " = " + value + "\n" );
}
if ( LocalScript.rawin( "DirectorOptions" ) ) //RAWIN 检查 DirectorOptions 是否存在
{
Msg( "\n*****\nLocalScript.DirectorOptions:\n" );
foreach( key, value in LocalScript.DirectorOptions )
{
Msg( " " + key + " = " + value + "\n" );
}
}
printl("========================================================");
}
}
|
牺牲结局
牺牲结局基于自定义结局,并在牺牲更新中引入了额外的硬编码修改。
待完善: 分解、解释、指导
c7m3_port_finale.nut
这比其他自定义结局更复杂,但本质上是为了自定义体验。该脚本表明牺牲结局类型主要取决于新的游戏内实体和实体功能。
//-----------------------------------------------------
// This script handles the logic for the Port / Bridge
// finale in the River Campaign.
//
//-----------------------------------------------------
Msg("Initiating c7m3_port_finale script\n");
//-----------------------------------------------------
// Enumerations
ERROR <- -1
PANIC <- 0
TANK <- 1
DELAY <- 2
//-----------------------------------------------------
// This keeps track of the number of times the generator button has been pressed.
// Init to 1, since one button press has been used to start the finale and run
// this script.
ButtonPressCount <- 1
// This stores the stage number that we last
// played the "Press the Button!" VO
LastVOButtonStageNumber <- 0
// We use this to keep from running a bunch of queued advances really quickly.
// Init to true because we are starting a finale from a button press in the pre-finale script
// see GeneratorButtonPressed in c7m3_port.nut
PendingWaitAdvance <- true
// We use three generator button presses to push through
// 8 stages. We have to queue up state advances
// depending on the state of the finale when buttons are pressed
QueuedDelayAdvances <- 0
// Tracking current finale states
CurrentFinaleStageNumber <- ERROR
CurrentFinaleStageType <- ERROR
// The finale is 3 phases.
// We randomize the event types in the first two
local RandomFinaleStage1 = 0
local RandomFinaleStage2 = 0
local RandomFinaleStage4 = 0
local RandomFinaleStage5 = 0
// PHASE 1 EVENTS
if ( RandomInt( 1, 100 ) < 50 )
{
RandomFinaleStage1 = PANIC
RandomFinaleStage2 = TANK
}
else
{
RandomFinaleStage1 = TANK
RandomFinaleStage2 = PANIC
}
// PHASE 2 EVENTS
if ( RandomInt( 1, 100 ) < 50 )
{
RandomFinaleStage4 = PANIC
RandomFinaleStage5 = TANK
}
else
{
RandomFinaleStage4 = TANK
RandomFinaleStage5 = PANIC
}
// We want to give the survivors a little of extra time to
// get on their feet before the escape, since you have to fight through
// the sacrifice.
PreEscapeDelay <- 0
if ( Director.GetGameMode() == "coop" )
{
PreEscapeDelay <- 5
}
else if ( Director.GetGameMode() == "versus" )
{
PreEscapeDelay <- 15
}
DirectorOptions <-
{
A_CustomFinale_StageCount = 8
// PHASE 1
A_CustomFinale1 = RandomFinaleStage1
A_CustomFinaleValue1 = 1
A_CustomFinale2 = RandomFinaleStage2
A_CustomFinaleValue2 = 1
A_CustomFinale3 = DELAY
A_CustomFinaleValue3 = 9999
// PHASE 2
A_CustomFinale4 = RandomFinaleStage4
A_CustomFinaleValue4 = 1
A_CustomFinale5 = RandomFinaleStage5
A_CustomFinaleValue5 = 1
A_CustomFinale6 = DELAY
A_CustomFinaleValue6 = 9999
// PHASE 3
A_CustomFinale7 = TANK
A_CustomFinaleValue7 = 1
A_CustomFinale8 = DELAY
A_CustomFinaleValue8 = PreEscapeDelay
TankLimit = 4
WitchLimit = 0
CommonLimit = 20
HordeEscapeCommonLimit = 15
EscapeSpawnTanks = false
//SpecialRespawnInterval = 80
}
function OnBeginCustomFinaleStage( num, type )
{
printl( "*!* Beginning custom finale stage " + num + " of type " + type );
printl( "*!* PendingWaitAdvance " + PendingWaitAdvance + ", QueuedDelayAdvances " + QueuedDelayAdvances );
// Store off the state...
CurrentFinaleStageNumber = num
CurrentFinaleStageType = type
// Acknowledge the state advance
PendingWaitAdvance = false
}
function GeneratorButtonPressed()
{
printl( "*!* GeneratorButtonPressed finale stage " + CurrentFinaleStageNumber + " of type " +CurrentFinaleStageType );
printl( "*!* PendingWaitAdvance " + PendingWaitAdvance + ", QueuedDelayAdvances " + QueuedDelayAdvances );
ButtonPressCount++
local ImmediateAdvances = 0
if ( CurrentFinaleStageNumber == 1 || CurrentFinaleStageNumber == 4 )
{
// First stage of a phase, so next stage is an "action" stage too.
// Advance to next action stage, and then queue an advance to the
// next delay.
QueuedDelayAdvances++
ImmediateAdvances = 1
}
else if ( CurrentFinaleStageNumber == 2 || CurrentFinaleStageNumber == 5 )
{
// Second stage of a phase, so next stage is a "delay" stage.
// We need to immediately advance past the delay and into an action state.
//QueuedDelayAdvances++ // NOPE!
ImmediateAdvances = 2
}
else if ( CurrentFinaleStageNumber == 3 || CurrentFinaleStageNumber == 6 )
{
// Wait states... (very long delay)
// Advance immediately into an action state
//QueuedDelayAdvances++
ImmediateAdvances = 1
}
else if ( CurrentFinaleStageNumber == -1 ||
CurrentFinaleStageNumber == 0 )
{
// the finale is *just* about to start...
// we can get this if all the buttons are hit at once at the beginning
// Just queue a wait advance
QueuedDelayAdvances++
ImmediateAdvances = 0
}
else
{
printl( "*!* Unhandled generator button press! " );
}
if ( ImmediateAdvances > 0 )
{
EntFire( "generator_start_model", "Enable" )
if ( ImmediateAdvances == 1 )
{
printl( "*!* GeneratorButtonPressed Advancing State ONCE");
EntFire( "generator_start_model", "AdvanceFinaleState" )
}
else if ( ImmediateAdvances == 2 )
{
printl( "*!* GeneratorButtonPressed Advancing State TWICE");
EntFire( "generator_start_model", "AdvanceFinaleState" )
EntFire( "generator_start_model", "AdvanceFinaleState" )
}
EntFire( "generator_start_model", "Disable" )
PendingWaitAdvance = true
}
}
function Update() //Called every 0.100 seconds
{
// Should we advance the finale state?
// 1. If we are in a DELAY state
// 2. And we have queued advances....
// 3. And we have not just tried to advance the advance the state....
if ( CurrentFinaleStageType == DELAY && QueuedDelayAdvances > 0 && !PendingWaitAdvance )
{
// If things are calm (relatively), jump to the next state
if ( !Director.IsTankInPlay() && !Director.IsAnySurvivorInCombat() )
{
if ( Director.GetPendingMobCount() < 1 && Director.GetCommonInfectedCount() < 5 )
{
printl( "*!* Update Advancing State finale stage " + CurrentFinaleStageNumber + " of type " +CurrentFinaleStageType );
printl( "*!* PendingWaitAdvance " + PendingWaitAdvance + ", QueuedDelayAdvances " + QueuedDelayAdvances );
QueuedDelayAdvances--
EntFire( "generator_start_model", "Enable" )
EntFire( "generator_start_model", "AdvanceFinaleState" )
EntFire( "generator_start_model", "Disable" )
PendingWaitAdvance = true
}
}
}
// Should we fire the director event to play the "Press the button!" Nag VO?
// If we are on an infinite delay stage...
if ( CurrentFinaleStageType == DELAY && CurrentFinaleStageNumber > 1 && CurrentFinaleStageNumber < 7 )
{
// 1. We have not nagged for this stage yet
// 2. There are button presses remaining
if ( CurrentFinaleStageNumber != LastVOButtonStageNumber && ButtonPressCount < 3 )
{
// We are not about to process a wait advance..
if ( QueuedDelayAdvances == 0 && !PendingWaitAdvance )
{
// If things are pretty calm, run the event
if ( Director.GetPendingMobCount() < 1 && Director.GetCommonInfectedCount() < 1 )
{
if ( !Director.IsTankInPlay() && !Director.IsAnySurvivorInCombat() )
{
printl( "*!* Update firing event 1 (VO Prompt)" )
LastVOButtonStageNumber = CurrentFinaleStageNumber
Director.UserDefinedEvent1()
}
}
}
}
}
}
function EnableEscapeTanks()
// This is called in-game via logic_relay at info_director
// enable the escape tanks at a different time.
// Input: Runscriptcode
// Parm: DirectorScript.MapScript.LocalScript.EnableEscapeTanks()
{
printl( "*!* EnableEscapeTanks finale stage " + CurrentFinaleStageNumber + " of type " +CurrentFinaleStageType );
//Msg( "\n*****\nMapScript.DirectorOptions:\n" );
//foreach( key, value in MapScript.DirectorOptions )
//{
// Msg( " " + key + " = " + value + "\n" );
//}
MapScript.DirectorOptions.EscapeSpawnTanks <- true
}
|
解密的官方结局脚本
这是所有的结局脚本,于 2021 年 8 月 2 日解密。
这些尚未修改以提供任何附加信息,某些部分可能会造成混淆。
c1m4_atrium_finale.nuc
Msg("----------------------FINALE SCRIPT------------------\n")
//-----------------------------------------------------
PANIC <- 0
TANK <- 1
DELAY <- 2
ONSLAUGHT <- 3
//-----------------------------------------------------
SharedOptions <-
{
A_CustomFinale1 = ONSLAUGHT
A_CustomFinaleValue1 = ""
A_CustomFinale2 = PANIC
A_CustomFinaleValue2 = 1
A_CustomFinale3 = ONSLAUGHT
A_CustomFinaleValue3 = "c1m4_delay"
A_CustomFinale4 = PANIC
A_CustomFinaleValue4 = 1
A_CustomFinale5 = ONSLAUGHT
A_CustomFinaleValue5 = "c1m4_delay"
A_CustomFinale6 = TANK
A_CustomFinaleValue6 = 1
A_CustomFinale7 = ONSLAUGHT
A_CustomFinaleValue7 = "c1m4_delay"
A_CustomFinale8 = PANIC
A_CustomFinaleValue8 = 1
A_CustomFinale9 = ONSLAUGHT
A_CustomFinaleValue9 = "c1m4_delay"
A_CustomFinale10 = PANIC
A_CustomFinaleValue10 = 1
A_CustomFinale11 = ONSLAUGHT
A_CustomFinaleValue11 = "c1m4_delay"
A_CustomFinale12 = PANIC
A_CustomFinaleValue12 = 1
A_CustomFinale13 = ONSLAUGHT
A_CustomFinaleValue13 = "c1m4_delay"
A_CustomFinale14 = TANK
A_CustomFinaleValue14 = 1
A_CustomFinale15 = ONSLAUGHT
A_CustomFinaleValue15 = "c1m4_delay"
A_CustomFinale16 = PANIC
A_CustomFinaleValue16 = 1
A_CustomFinale17 = ONSLAUGHT
A_CustomFinaleValue17 = "c1m4_delay"
A_CustomFinale18 = PANIC
A_CustomFinaleValue18 = 1
A_CustomFinale19 = ONSLAUGHT
A_CustomFinaleValue19 = "c1m4_delay"
A_CustomFinale20 = PANIC
A_CustomFinaleValue20 = 1
A_CustomFinale21 = ONSLAUGHT
A_CustomFinaleValue21 = "c1m4_delay"
A_CustomFinale22 = TANK
A_CustomFinaleValue22 = 1
A_CustomFinale23 = ONSLAUGHT
A_CustomFinaleValue23 = "c1m4_delay"
A_CustomFinale24 = PANIC
A_CustomFinaleValue24 = 1
A_CustomFinale25 = ONSLAUGHT
A_CustomFinaleValue25 = "c1m4_delay"
A_CustomFinale26 = PANIC
A_CustomFinaleValue26 = 1
A_CustomFinale27 = ONSLAUGHT
A_CustomFinaleValue27 = "c1m4_delay"
A_CustomFinale28 = PANIC
A_CustomFinaleValue28 = 1
A_CustomFinale29 = ONSLAUGHT
A_CustomFinaleValue29 = "c1m4_delay"
A_CustomFinale30 = PANIC
A_CustomFinaleValue30 = 1
A_CustomFinale31 = ONSLAUGHT
A_CustomFinaleValue31 = "c1m4_delay"
//-----------------------------------------------------
PreferredMobDirection = SPAWN_LARGE_VOLUME
PreferredSpecialDirection = SPAWN_LARGE_VOLUME
// BoomerLimit = 0
// SmokerLimit = 2
// HunterLimit = 1
// SpitterLimit = 1
// JockeyLimit = 0
// ChargerLimit = 1
ProhibitBosses = true
ZombieSpawnRange = 3000
MobRechargeRate = 0.5
HordeEscapeCommonLimit = 15
BileMobSize = 15
MusicDynamicMobSpawnSize = 8
MusicDynamicMobStopSize = 2
MusicDynamicMobScanStopSize = 1
}
InitialOnslaughtOptions <-
{
LockTempo = 0
IntensityRelaxThreshold = 1.1
RelaxMinInterval = 2
RelaxMaxInterval = 4
SustainPeakMinTime = 25
SustainPeakMaxTime = 30
MobSpawnMinTime = 4
MobSpawnMaxTime = 8
MobMinSize = 2
MobMaxSize = 6
CommonLimit = 5
SpecialRespawnInterval = 100
}
PanicOptions <-
{
MegaMobSize = 0 // randomized in OnBeginCustomFinaleStage
MegaMobMinSize = 20
MegaMobMaxSize = 40
CommonLimit = 15
SpecialRespawnInterval = 40
}
TankOptions <-
{
ShouldAllowMobsWithTank = true
ShouldAllowSpecialsWithTank = true
MobSpawnMinTime = 10
MobSpawnMaxTime = 20
MobMinSize = 3
MobMaxSize = 5
CommonLimit = 7
SpecialRespawnInterval = 60
}
DirectorOptions <- clone SharedOptions
{
}
//-----------------------------------------------------
// number of cans needed to escape.
NumCansNeeded <- 13
// fewer cans in single player since bots don't help much
if ( Director.IsSinglePlayerGame() )
{
NumCansNeeded <- 8
}
// duration of delay stage.
DelayMin <- 10
DelayMax <- 20
// Number of touches and/or pours allowed before a delay is aborted.
DelayPourThreshold <- 1
DelayTouchedOrPouredThreshold <- 2
// Once the delay is aborted, amount of time before it progresses to next stage.
AbortDelayMin <- 1
AbortDelayMax <- 3
// Number of touches and pours it takes to transition out of c1m4_finale_wave_1
GimmeThreshold <- 4
// console overrides
if ( Director.IsPlayingOnConsole() )
{
DelayMin <- 20
DelayMax <- 30
// Number of touches and/or pours allowed before a delay is aborted.
DelayPourThreshold <- 2
DelayTouchedOrPouredThreshold <- 4
TankOptions.ShouldAllowSpecialsWithTank = false
}
//-----------------------------------------------------
// INIT
//-----------------------------------------------------
GasCansTouched <- 0
GasCansPoured <- 0
DelayTouchedOrPoured <- 0
DelayPoured <- 0
EntFire( "timer_delay_end", "LowerRandomBound", DelayMin )
EntFire( "timer_delay_end", "UpperRandomBound", DelayMax )
EntFire( "timer_delay_abort", "LowerRandomBound", AbortDelayMin )
EntFire( "timer_delay_abort", "UpperRandomBound", AbortDelayMax )
// this is too late. Moved to c1m4_atrium.nut
//EntFire( "progress_display", "SetTotalItems", NumCansNeeded )
function AbortDelay(){} // only defined during a delay, in c1m4_delay.nut
function EndDelay(){} // only defined during a delay, in c1m4_delay.nut
NavMesh.UnblockRescueVehicleNav()
//-----------------------------------------------------
function GasCanTouched()
{
GasCansTouched++
Msg(" Touched: " + GasCansTouched + "\n")
EvalGasCansPouredOrTouched()
}
function GasCanPoured()
{
GasCansPoured++
DelayPoured++
Msg(" Poured: " + GasCansPoured + "\n")
if ( GasCansPoured == NumCansNeeded )
{
Msg(" needed: " + NumCansNeeded + "\n")
EntFire( "relay_car_ready", "trigger" )
}
EvalGasCansPouredOrTouched()
}
function EvalGasCansPouredOrTouched()
{
TouchedOrPoured <- GasCansPoured + GasCansTouched
Msg(" Poured or touched: " + TouchedOrPoured + "\n")
DelayTouchedOrPoured++
Msg(" DelayTouchedOrPoured: " + DelayTouchedOrPoured + "\n")
Msg(" DelayPoured: " + DelayPoured + "\n")
if (( DelayTouchedOrPoured >= DelayTouchedOrPouredThreshold ) || ( DelayPoured >= DelayPourThreshold ))
{
AbortDelay()
}
switch( TouchedOrPoured )
{
case GimmeThreshold:
EntFire( "@director", "EndCustomScriptedStage" )
break
}
}
//-----------------------------------------------------
function AddTableToTable( dest, src )
{
foreach( key, val in src )
{
dest[key] <- val
}
}
function OnBeginCustomFinaleStage( num, type )
{
printl( "Beginning custom finale stage " + num + " of type " + type );
local waveOptions = null
if ( num == 1 )
{
waveOptions = InitialOnslaughtOptions
}
else if ( type == PANIC )
{
waveOptions = PanicOptions
waveOptions.MegaMobSize = PanicOptions.MegaMobMinSize + rand()%( PanicOptions.MegaMobMaxSize - PanicOptions.MegaMobMinSize )
Msg("*************************" + waveOptions.MegaMobSize + "\n")
}
else if ( type == TANK )
{
waveOptions = TankOptions
}
//---------------------------------
MapScript.DirectorOptions.clear()
AddTableToTable( MapScript.DirectorOptions, SharedOptions );
if ( waveOptions != null )
{
AddTableToTable( MapScript.DirectorOptions, waveOptions );
}
Director.ResetMobTimer()
if ( developer() > 0 )
{
Msg( "\n*****\nMapScript.DirectorOptions:\n" );
foreach( key, value in MapScript.DirectorOptions )
{
Msg( " " + key + " = " + value + "\n" );
}
if ( LocalScript.rawin( "DirectorOptions" ) )
{
Msg( "\n*****\nLocalScript.DirectorOptions:\n" );
foreach( key, value in LocalScript.DirectorOptions )
{
Msg( " " + key + " = " + value + "\n" );
}
}
}
}
//-----------------------------------------------------
if ( Director.GetGameModeBase() == "versus" )
{
SharedOptions.ProhibitBosses = false
}
|
c1m4_finale_wave_1.nuc
Msg("Atrium Finale Wave " + ( CurrentWave + 1 ) + "\n");
|
c1m4_delay.nuc
Msg("**Delay started**\n")
DirectorOptions <-
{
MobMinSize = 2
MobMaxSize = 3
BoomerLimit = 0
SmokerLimit = 0
HunterLimit = 0
SpitterLimit = 0
JockeyLimit = 0
ChargerLimit = 0
MinimumStageTime = 15
CommonLimit = 5
}
Director.ResetMobTimer()
// start the delay timer
EntFire( "timer_delay_end", "enable" )
//reset
DelayTouchedOrPoured <- 0
DelayPoured <- 0
//-------------------------------------------------
// abort the delay if a survivor picks up or pours a gas can
function AbortDelay()
{
Msg("**Delay aborted early**\n")
EntFire( "timer_delay_abort", "enable" )
}
function EndDelay()
{
Msg("**Delay ended**\n")
EntFire( "timer_delay_end", "Disable" )
EntFire( "timer_delay_end", "ResetTimer" )
EntFire( "timer_delay_abort", "Disable" )
EntFire( "timer_delay_abort", "ResetTimer" )
EntFire( "@director", "EndCustomScriptedStage" )
}
|
c2m5_concert_finale.nuc
//-----------------------------------------------------------------------------
PANIC <- 0
TANK <- 1
DELAY <- 2
ONSLAUGHT <- 3
//-----------------------------------------------------------------------------
SharedOptions <-
{
A_CustomFinale_StageCount = 9
A_CustomFinale1 = PANIC
A_CustomFinaleValue1 = 1
A_CustomFinale2 = PANIC
A_CustomFinaleValue2 = 1
A_CustomFinale3 = DELAY
A_CustomFinaleValue3 = 15
A_CustomFinale4 = TANK
A_CustomFinaleValue4 = 1
A_CustomFinaleMusic4 = ""
A_CustomFinale5 = DELAY
A_CustomFinaleValue5 = 15
A_CustomFinale6 = PANIC
A_CustomFinaleValue6 = 2
A_CustomFinale7 = DELAY
A_CustomFinaleValue7 = 10
A_CustomFinale8 = TANK
A_CustomFinaleValue8 = 1
A_CustomFinaleMusic8 = ""
A_CustomFinale9 = DELAY
A_CustomFinaleValue9 = RandomInt( 5, 10 )
PreferredMobDirection = SPAWN_LARGE_VOLUME
PreferredSpecialDirection = SPAWN_LARGE_VOLUME
ShouldConstrainLargeVolumeSpawn = false
ZombieSpawnRange = 3000
SpecialRespawnInterval = 20
}
InitialPanicOptions <-
{
ShouldConstrainLargeVolumeSpawn = true
}
PanicOptions <-
{
CommonLimit = 25
}
TankOptions <-
{
ShouldAllowSpecialsWithTank = true
SpecialRespawnInterval = 30
}
DirectorOptions <- clone SharedOptions
{
}
//-----------------------------------------------------------------------------
function AddTableToTable( dest, src )
{
foreach( key, val in src )
{
dest[key] <- val
}
}
//-----------------------------------------------------------------------------
function OnBeginCustomFinaleStage( num, type )
{
if ( developer() > 0 )
{
printl("========================================================");
printl( "Beginning custom finale stage " + num + " of type " + type );
}
local waveOptions = null
if ( num == 1 )
{
waveOptions = InitialPanicOptions
}
else if ( type == PANIC )
{
waveOptions = PanicOptions
if ( "MegaMobMinSize" in PanicOptions )
{
waveOptions.MegaMobSize <- RandomInt( PanicOptions.MegaMobMinSize, MegaMobMaxSize )
}
}
else if ( type == TANK )
{
waveOptions = TankOptions
}
//---------------------------------
MapScript.DirectorOptions.clear()
AddTableToTable( MapScript.DirectorOptions, SharedOptions );
if ( waveOptions != null )
{
AddTableToTable( MapScript.DirectorOptions, waveOptions );
}
//---------------------------------
if ( developer() > 0 )
{
Msg( "\n*****\nMapScript.DirectorOptions:\n" );
foreach( key, value in MapScript.DirectorOptions )
{
Msg( " " + key + " = " + value + "\n" );
}
if ( LocalScript.rawin( "DirectorOptions" ) )
{
Msg( "\n*****\nLocalScript.DirectorOptions:\n" );
foreach( key, value in LocalScript.DirectorOptions )
{
Msg( " " + key + " = " + value + "\n" );
}
}
printl("========================================================");
}
}
|
c3m4_plantation_finale.nuc
//-----------------------------------------------------
local PANIC = 0
local TANK = 1
local DELAY = 2
//-----------------------------------------------------
DirectorOptions <-
{
//-----------------------------------------------------
A_CustomFinale_StageCount = 8
A_CustomFinale1 = PANIC
A_CustomFinaleValue1 = 2
A_CustomFinale2 = DELAY
A_CustomFinaleValue2 = 12
A_CustomFinale3 = TANK
A_CustomFinaleValue3 = 1
A_CustomFinale4 = DELAY
A_CustomFinaleValue4 = 12
A_CustomFinale5 = PANIC
A_CustomFinaleValue5 = 2
A_CustomFinale6 = DELAY
A_CustomFinaleValue6 = 15
A_CustomFinale7 = TANK
A_CustomFinaleValue7 = 2
A_CustomFinale8 = DELAY
A_CustomFinaleValue8 = 10
SpecialRespawnInterval = 55
//-----------------------------------------------------
}
|
c4m5_milltown_escape_finale.nuc
//-----------------------------------------------------
local PANIC = 0
local TANK = 1
local DELAY = 2
//-----------------------------------------------------
// default finale patten - for reference only
/*
CustomFinale1 <- PANIC
CustomFinaleValue1 <- 2
CustomFinale2 <- DELAY
CustomFinaleValue2 <- 10
CustomFinale3 <- TANK
CustomFinaleValue3 <- 1
CustomFinale4 <- DELAY
CustomFinaleValue4 <- 10
CustomFinale5 <- PANIC
CustomFinaleValue5 <- 2
CustomFinale6 <- DELAY
CustomFinaleValue6 <- 10
CustomFinale7 <- TANK
CustomFinaleValue7 <- 1
CustomFinale8 <- DELAY
CustomFinaleValue8 <- 2
*/
DirectorOptions <-
{
//-----------------------------------------------------
// 3 waves of mobs in between tanks
A_CustomFinale_StageCount = 8
A_CustomFinale1 = PANIC
A_CustomFinaleValue1 = 1
A_CustomFinale2 = DELAY
A_CustomFinaleValue2 = 10
A_CustomFinale3 = TANK
A_CustomFinaleValue3 = 1
A_CustomFinale4 = DELAY
A_CustomFinaleValue4 = 10
A_CustomFinale5 = PANIC
A_CustomFinaleValue5 = 1
A_CustomFinale6 = DELAY
A_CustomFinaleValue6 = 10
A_CustomFinale7 = TANK
A_CustomFinaleValue7 = 1
A_CustomFinale8 = DELAY
A_CustomFinaleValue8 = 15
HordeEscapeCommonLimit = 15
CommonLimit = 20
SpecialRespawnInterval = 80
}
if ( "DirectorOptions" in LocalScript && "ProhibitBosses" in LocalScript.DirectorOptions )
{
delete LocalScript.DirectorOptions.ProhibitBosses
}
/*
*/
|
c6m3_port_finale.nuc
Msg("----------------------FINALE SCRIPT------------------\n")
//-----------------------------------------------------
PANIC <- 0
TANK <- 1
DELAY <- 2
ONSLAUGHT <- 3
//-----------------------------------------------------
SharedOptions <-
{
A_CustomFinale1 = ONSLAUGHT
A_CustomFinaleValue1 = ""
A_CustomFinale2 = PANIC
A_CustomFinaleValue2 = 1
A_CustomFinale3 = ONSLAUGHT
A_CustomFinaleValue3 = "c1m4_delay"
A_CustomFinale4 = PANIC
A_CustomFinaleValue4 = 1
A_CustomFinale5 = ONSLAUGHT
A_CustomFinaleValue5 = "c1m4_delay"
A_CustomFinale6 = TANK
A_CustomFinaleValue6 = 1
A_CustomFinale7 = ONSLAUGHT
A_CustomFinaleValue7 = "c1m4_delay"
A_CustomFinale8 = PANIC
A_CustomFinaleValue8 = 1
A_CustomFinale9 = ONSLAUGHT
A_CustomFinaleValue9 = "c1m4_delay"
A_CustomFinale10 = PANIC
A_CustomFinaleValue10 = 1
A_CustomFinale11 = ONSLAUGHT
A_CustomFinaleValue11 = "c1m4_delay"
A_CustomFinale12 = PANIC
A_CustomFinaleValue12 = 1
A_CustomFinale13 = ONSLAUGHT
A_CustomFinaleValue13 = "c1m4_delay"
A_CustomFinale14 = TANK
A_CustomFinaleValue14 = 2
A_CustomFinale15 = ONSLAUGHT
A_CustomFinaleValue15 = "c1m4_delay"
A_CustomFinale16 = PANIC
A_CustomFinaleValue16 = 1
A_CustomFinale17 = ONSLAUGHT
A_CustomFinaleValue17 = "c1m4_delay"
A_CustomFinale18 = PANIC
A_CustomFinaleValue18 = 1
A_CustomFinale19 = ONSLAUGHT
A_CustomFinaleValue19 = "c1m4_delay"
A_CustomFinale20 = PANIC
A_CustomFinaleValue20 = 1
A_CustomFinale21 = ONSLAUGHT
A_CustomFinaleValue21 = "c1m4_delay"
A_CustomFinale22 = TANK
A_CustomFinaleValue22 = 1
A_CustomFinale23 = ONSLAUGHT
A_CustomFinaleValue23 = "c1m4_delay"
A_CustomFinale24 = PANIC
A_CustomFinaleValue24 = 1
A_CustomFinale25 = ONSLAUGHT
A_CustomFinaleValue25 = "c1m4_delay"
A_CustomFinale26 = PANIC
A_CustomFinaleValue26 = 1
A_CustomFinale27 = ONSLAUGHT
A_CustomFinaleValue27 = "c1m4_delay"
A_CustomFinale28 = PANIC
A_CustomFinaleValue28 = 1
A_CustomFinale29 = ONSLAUGHT
A_CustomFinaleValue29 = "c1m4_delay"
A_CustomFinale30 = PANIC
A_CustomFinaleValue30 = 1
A_CustomFinale31 = ONSLAUGHT
A_CustomFinaleValue31 = "c1m4_delay"
A_CustomFinale32 = TANK
A_CustomFinaleValue32 = 2
A_CustomFinale33 = ONSLAUGHT
A_CustomFinaleValue33 = "c1m4_delay"
A_CustomFinale34 = PANIC
A_CustomFinaleValue34 = 1
A_CustomFinale35 = ONSLAUGHT
A_CustomFinaleValue35 = "c1m4_delay"
A_CustomFinale36 = PANIC
A_CustomFinaleValue36 = 1
A_CustomFinale37 = ONSLAUGHT
A_CustomFinaleValue37 = "c1m4_delay"
A_CustomFinale38 = PANIC
A_CustomFinaleValue38 = 1
A_CustomFinale39 = ONSLAUGHT
A_CustomFinaleValue39 = "c1m4_delay"
A_CustomFinale40 = PANIC
A_CustomFinaleValue40 = 1
A_CustomFinale41 = ONSLAUGHT
A_CustomFinaleValue41 = "c1m4_delay"
A_CustomFinale42 = TANK
A_CustomFinaleValue42 = 1
A_CustomFinale43 = ONSLAUGHT
A_CustomFinaleValue43 = "c1m4_delay"
A_CustomFinale44 = PANIC
A_CustomFinaleValue44 = 1
A_CustomFinale45 = ONSLAUGHT
A_CustomFinaleValue45 = "c1m4_delay"
A_CustomFinale46 = PANIC
A_CustomFinaleValue46 = 1
A_CustomFinale47 = ONSLAUGHT
A_CustomFinaleValue47 = "c1m4_delay"
A_CustomFinale48 = PANIC
A_CustomFinaleValue48 = 1
A_CustomFinale49 = ONSLAUGHT
A_CustomFinaleValue49 = "c1m4_delay"
A_CustomFinale50 = PANIC
A_CustomFinaleValue50 = 1
A_CustomFinale51 = ONSLAUGHT
A_CustomFinaleValue51 = "c1m4_delay"
//-----------------------------------------------------
PreferredMobDirection = SPAWN_LARGE_VOLUME
PreferredSpecialDirection = SPAWN_LARGE_VOLUME
// BoomerLimit = 0
// SmokerLimit = 2
// HunterLimit = 1
// SpitterLimit = 1
// JockeyLimit = 0
// ChargerLimit = 1
ProhibitBosses = true
ZombieSpawnRange = 3000
MobRechargeRate = 0.5
HordeEscapeCommonLimit = 15
BileMobSize = 15
SpecialRespawnInterval = 20
MusicDynamicMobSpawnSize = 8
MusicDynamicMobStopSize = 2
MusicDynamicMobScanStopSize = 1
}
InitialOnslaughtOptions <-
{
LockTempo = 0
IntensityRelaxThreshold = 1.1
RelaxMinInterval = 2
RelaxMaxInterval = 4
SustainPeakMinTime = 25
SustainPeakMaxTime = 30
MobSpawnMinTime = 4
MobSpawnMaxTime = 8
MobMinSize = 2
MobMaxSize = 6
CommonLimit = 5
SpecialRespawnInterval = 100
}
PanicOptions <-
{
MegaMobSize = 0 // randomized in OnBeginCustomFinaleStage
MegaMobMinSize = 20
MegaMobMaxSize = 40
MaxSpecials = 5
BoomerLimit = 1
SmokerLimit = 2
HunterLimit = 2
SpitterLimit = 1
JockeyLimit = 1
ChargerLimit = 1
CommonLimit = 25
SpecialRespawnInterval = 25
}
TankOptions <-
{
ShouldAllowMobsWithTank = true
ShouldAllowSpecialsWithTank = true
MobSpawnMinTime = 20
MobSpawnMaxTime = 40
MobMinSize = 3
MobMaxSize = 5
MaxSpecials = 3
CommonLimit = 5
SpecialRespawnInterval = 50
}
DirectorOptions <- clone SharedOptions
{
}
//-----------------------------------------------------
// number of cans needed to escape.
NumCansNeeded <- 16
// fewer cans in single player since bots don't help much
if ( Director.IsSinglePlayerGame() )
{
NumCansNeeded <- 10
}
// duration of delay stage.
DelayMin <- 10
DelayMax <- 20
// Number of touches and/or pours allowed before a delay is aborted.
DelayPourThreshold <- 1
DelayTouchedOrPouredThreshold <- 2
// Once the delay is aborted, amount of time before it progresses to next stage.
AbortDelayMin <- 1
AbortDelayMax <- 3
// Number of touches and pours it takes to transition out of c1m4_finale_wave_1
GimmeThreshold <- 4
// console overrides
if ( Director.IsPlayingOnConsole() )
{
DelayMin <- 20
DelayMax <- 30
// Number of touches and/or pours allowed before a delay is aborted.
DelayPourThreshold <- 2
DelayTouchedOrPouredThreshold <- 4
TankOptions.ShouldAllowSpecialsWithTank = false
}
//-----------------------------------------------------
// INIT
//-----------------------------------------------------
GasCansTouched <- 0
GasCansPoured <- 0
DelayTouchedOrPoured <- 0
DelayPoured <- 0
EntFire( "timer_delay_end", "LowerRandomBound", DelayMin )
EntFire( "timer_delay_end", "UpperRandomBound", DelayMax )
EntFire( "timer_delay_abort", "LowerRandomBound", AbortDelayMin )
EntFire( "timer_delay_abort", "UpperRandomBound", AbortDelayMax )
// this is too late. Moved to c1m4_atrium.nut
//EntFire( "progress_display", "SetTotalItems", NumCansNeeded )
function AbortDelay(){} // only defined during a delay, in c1m4_delay.nut
function EndDelay(){} // only defined during a delay, in c1m4_delay.nut
NavMesh.UnblockRescueVehicleNav()
//-----------------------------------------------------
function GasCanTouched()
{
GasCansTouched++
Msg(" Touched: " + GasCansTouched + "\n")
EvalGasCansPouredOrTouched()
}
function GasCanPoured()
{
GasCansPoured++
DelayPoured++
Msg(" Poured: " + GasCansPoured + "\n")
if ( GasCansPoured == NumCansNeeded )
{
Msg(" needed: " + NumCansNeeded + "\n")
EntFire( "relay_car_ready", "trigger" )
}
EvalGasCansPouredOrTouched()
}
function EvalGasCansPouredOrTouched()
{
TouchedOrPoured <- GasCansPoured + GasCansTouched
Msg(" Poured or touched: " + TouchedOrPoured + "\n")
DelayTouchedOrPoured++
Msg(" DelayTouchedOrPoured: " + DelayTouchedOrPoured + "\n")
Msg(" DelayPoured: " + DelayPoured + "\n")
if (( DelayTouchedOrPoured >= DelayTouchedOrPouredThreshold ) || ( DelayPoured >= DelayPourThreshold ))
{
AbortDelay()
}
switch( TouchedOrPoured )
{
case GimmeThreshold:
EntFire( "@director", "EndCustomScriptedStage" )
break
}
}
//-----------------------------------------------------
function AddTableToTable( dest, src )
{
foreach( key, val in src )
{
dest[key] <- val
}
}
function OnBeginCustomFinaleStage( num, type )
{
printl( "Beginning custom finale stage " + num + " of type " + type );
local waveOptions = null
if ( num == 1 )
{
waveOptions = InitialOnslaughtOptions
}
else if ( type == PANIC )
{
waveOptions = PanicOptions
waveOptions.MegaMobSize = PanicOptions.MegaMobMinSize + rand()%( PanicOptions.MegaMobMaxSize - PanicOptions.MegaMobMinSize )
Msg("*************************" + waveOptions.MegaMobSize + "\n")
}
else if ( type == TANK )
{
waveOptions = TankOptions
EntFire( "bonus_relay", "Trigger", 0 )
}
// give out items at certain stages
if ( num == 3 || num == 7 || num == 15 || num == 23 )
{
Director.L4D1SurvivorGiveItem()
}
//---------------------------------
MapScript.DirectorOptions.clear()
AddTableToTable( MapScript.DirectorOptions, SharedOptions );
if ( waveOptions != null )
{
AddTableToTable( MapScript.DirectorOptions, waveOptions );
}
Director.ResetMobTimer()
if ( developer() > 0 )
{
Msg( "\n*****\nMapScript.DirectorOptions:\n" );
foreach( key, value in MapScript.DirectorOptions )
{
Msg( " " + key + " = " + value + "\n" );
}
if ( LocalScript.rawin( "DirectorOptions" ) )
{
Msg( "\n*****\nLocalScript.DirectorOptions:\n" );
foreach( key, value in LocalScript.DirectorOptions )
{
Msg( " " + key + " = " + value + "\n" );
}
}
}
}
//-----------------------------------------------------
if ( Director.GetGameModeBase() == "versus" )
{
SharedOptions.ProhibitBosses = false
}
|
c7m3_port_finale.nuc
//-----------------------------------------------------
// This script handles the logic for the Port / Bridge
// finale in the River Campaign.
//
//-----------------------------------------------------
Msg("Initiating c7m3_port_finale script\n");
//-----------------------------------------------------
ERROR <- -1
PANIC <- 0
TANK <- 1
DELAY <- 2
//-----------------------------------------------------
// This keeps track of the number of times the generator button has been pressed.
// Init to 1, since one button press has been used to start the finale and run
// this script.
ButtonPressCount <- 1
// This stores the stage number that we last
// played the "Press the Button!" VO
LastVOButtonStageNumber <- 0
// We use this to keep from running a bunch of queued advances really quickly.
// Init to true because we are starting a finale from a button press in the pre-finale script
// see GeneratorButtonPressed in c7m3_port.nut
PendingWaitAdvance <- true
// We use three generator button presses to push through
// 8 stages. We have to queue up state advances
// depending on the state of the finale when buttons are pressed
QueuedDelayAdvances <- 0
// Tracking current finale states
CurrentFinaleStageNumber <- ERROR
CurrentFinaleStageType <- ERROR
// The finale is 3 phases.
// We randomize the event types in the first two
local RandomFinaleStage1 = 0
local RandomFinaleStage2 = 0
local RandomFinaleStage4 = 0
local RandomFinaleStage5 = 0
// PHASE 1 EVENTS
if ( RandomInt( 1, 100 ) < 50 )
{
RandomFinaleStage1 = PANIC
RandomFinaleStage2 = TANK
}
else
{
RandomFinaleStage1 = TANK
RandomFinaleStage2 = PANIC
}
// PHASE 2 EVENTS
if ( RandomInt( 1, 100 ) < 50 )
{
RandomFinaleStage4 = PANIC
RandomFinaleStage5 = TANK
}
else
{
RandomFinaleStage4 = TANK
RandomFinaleStage5 = PANIC
}
// We want to give the survivors a little of extra time to
// get on their feet before the escape, since you have to fight through
// the sacrifice.
PreEscapeDelay <- 0
if ( Director.GetGameModeBase() == "coop" || Director.GetGameModeBase() == "realism" )
{
PreEscapeDelay <- 5
}
else if ( Director.GetGameModeBase() == "versus" )
{
PreEscapeDelay <- 15
}
DirectorOptions <-
{
A_CustomFinale_StageCount = 8
// PHASE 1
A_CustomFinale1 = RandomFinaleStage1
A_CustomFinaleValue1 = 1
A_CustomFinale2 = RandomFinaleStage2
A_CustomFinaleValue2 = 1
A_CustomFinale3 = DELAY
A_CustomFinaleValue3 = 9999
// PHASE 2
A_CustomFinale4 = RandomFinaleStage4
A_CustomFinaleValue4 = 1
A_CustomFinale5 = RandomFinaleStage5
A_CustomFinaleValue5 = 1
A_CustomFinale6 = DELAY
A_CustomFinaleValue6 = 9999
// PHASE 3
A_CustomFinale7 = TANK
A_CustomFinaleValue7 = 1
A_CustomFinale8 = DELAY
A_CustomFinaleValue8 = PreEscapeDelay
TankLimit = 4
WitchLimit = 0
CommonLimit = 20
HordeEscapeCommonLimit = 15
EscapeSpawnTanks = false
//SpecialRespawnInterval = 80
}
function OnBeginCustomFinaleStage( num, type )
{
printl( "*!* Beginning custom finale stage " + num + " of type " + type );
printl( "*!* PendingWaitAdvance " + PendingWaitAdvance + ", QueuedDelayAdvances " + QueuedDelayAdvances );
// Store off the state...
CurrentFinaleStageNumber = num
CurrentFinaleStageType = type
// Acknowledge the state advance
PendingWaitAdvance = false
}
function GeneratorButtonPressed()
{
printl( "*!* GeneratorButtonPressed finale stage " + CurrentFinaleStageNumber + " of type " +CurrentFinaleStageType );
printl( "*!* PendingWaitAdvance " + PendingWaitAdvance + ", QueuedDelayAdvances " + QueuedDelayAdvances );
ButtonPressCount++
local ImmediateAdvances = 0
if ( CurrentFinaleStageNumber == 1 || CurrentFinaleStageNumber == 4 )
{
// First stage of a phase, so next stage is an "action" stage too.
// Advance to next action stage, and then queue an advance to the
// next delay.
QueuedDelayAdvances++
ImmediateAdvances = 1
}
else if ( CurrentFinaleStageNumber == 2 || CurrentFinaleStageNumber == 5 )
{
// Second stage of a phase, so next stage is a "delay" stage.
// We need to immediately advance past the delay and into an action state.
//QueuedDelayAdvances++ // NOPE!
ImmediateAdvances = 2
}
else if ( CurrentFinaleStageNumber == 3 || CurrentFinaleStageNumber == 6 )
{
// Wait states... (very long delay)
// Advance immediately into an action state
//QueuedDelayAdvances++
ImmediateAdvances = 1
}
else if ( CurrentFinaleStageNumber == -1 ||
CurrentFinaleStageNumber == 0 )
{
// the finale is *just* about to start...
// we can get this if all the buttons are hit at once at the beginning
// Just queue a wait advance
QueuedDelayAdvances++
ImmediateAdvances = 0
}
else
{
printl( "*!* Unhandled generator button press! " );
}
if ( ImmediateAdvances > 0 )
{
EntFire( "generator_start_model", "Enable" )
if ( ImmediateAdvances == 1 )
{
printl( "*!* GeneratorButtonPressed Advancing State ONCE");
EntFire( "generator_start_model", "AdvanceFinaleState" )
}
else if ( ImmediateAdvances == 2 )
{
printl( "*!* GeneratorButtonPressed Advancing State TWICE");
EntFire( "generator_start_model", "AdvanceFinaleState" )
EntFire( "generator_start_model", "AdvanceFinaleState" )
}
EntFire( "generator_start_model", "Disable" )
PendingWaitAdvance = true
}
}
function Update()
{
// Should we advance the finale state?
// 1. If we're in a DELAY state
// 2. And we have queued advances....
// 3. And we haven't just tried to advance the advance the state....
if ( CurrentFinaleStageType == DELAY && QueuedDelayAdvances > 0 && !PendingWaitAdvance )
{
// If things are calm (relatively), jump to the next state
if ( !Director.IsTankInPlay() && !Director.IsAnySurvivorInCombat() )
{
if ( Director.GetPendingMobCount() < 1 && Director.GetCommonInfectedCount() < 5 )
{
printl( "*!* Update Advancing State finale stage " + CurrentFinaleStageNumber + " of type " +CurrentFinaleStageType );
printl( "*!* PendingWaitAdvance " + PendingWaitAdvance + ", QueuedDelayAdvances " + QueuedDelayAdvances );
QueuedDelayAdvances--
EntFire( "generator_start_model", "Enable" )
EntFire( "generator_start_model", "AdvanceFinaleState" )
EntFire( "generator_start_model", "Disable" )
PendingWaitAdvance = true
}
}
}
// Should we fire the director event to play the "Press the button!" Nag VO?
// If we're on an infinite delay stage...
if ( CurrentFinaleStageType == DELAY && CurrentFinaleStageNumber > 1 && CurrentFinaleStageNumber < 7 )
{
// 1. We haven't nagged for this stage yet
// 2. There are button presses remaining
if ( CurrentFinaleStageNumber != LastVOButtonStageNumber && ButtonPressCount < 3 )
{
// We're not about to process a wait advance..
if ( QueuedDelayAdvances == 0 && !PendingWaitAdvance )
{
// If things are pretty calm, run the event
if ( Director.GetPendingMobCount() < 1 && Director.GetCommonInfectedCount() < 1 )
{
if ( !Director.IsTankInPlay() && !Director.IsAnySurvivorInCombat() )
{
printl( "*!* Update firing event 1 (VO Prompt)" )
LastVOButtonStageNumber = CurrentFinaleStageNumber
Director.UserDefinedEvent1()
}
}
}
}
}
}
function EnableEscapeTanks()
{
printl( "*!* EnableEscapeTanks finale stage " + CurrentFinaleStageNumber + " of type " +CurrentFinaleStageType );
//Msg( "\n*****\nMapScript.DirectorOptions:\n" );
//foreach( key, value in MapScript.DirectorOptions )
//{
// Msg( " " + key + " = " + value + "\n" );
//}
MapScript.DirectorOptions.EscapeSpawnTanks <- true
}
|
c8m5_rooftop_finale.nuc
//-----------------------------------------------------
//
//
//-----------------------------------------------------
Msg("Initiating c8m5_rooftop_finale script\n");
//-----------------------------------------------------
ERROR <- -1
PANIC <- 0
TANK <- 1
DELAY <- 2
SCRIPTED <- 3
//-----------------------------------------------------
StageDelay <- 0
PreEscapeDelay <- 0
if ( Director.GetGameModeBase() == "coop" || Director.GetGameModeBase() == "realism" )
{
StageDelay <- 5
PreEscapeDelay <- 5
}
else if ( Director.GetGameModeBase() == "versus" )
{
StageDelay <- 10
PreEscapeDelay <- 15
}
DirectorOptions <-
{
A_CustomFinale_StageCount = 8
A_CustomFinale1 = PANIC
A_CustomFinaleValue1 = 2
A_CustomFinale2 = DELAY
A_CustomFinaleValue2 = StageDelay
A_CustomFinale3 = TANK
A_CustomFinaleValue3 = 1
A_CustomFinale4 = DELAY
A_CustomFinaleValue4 = StageDelay
A_CustomFinale5 = PANIC
A_CustomFinaleValue5 = 2
A_CustomFinaleMusic5 = "Event.FinaleWave4"
A_CustomFinale6 = DELAY
A_CustomFinaleValue6 = StageDelay
A_CustomFinale7 = TANK
A_CustomFinaleValue7 = 1
A_CustomFinale8 = DELAY
A_CustomFinaleValue8 = PreEscapeDelay
TankLimit = 1
WitchLimit = 0
CommonLimit = 20
HordeEscapeCommonLimit = 15
EscapeSpawnTanks = false
//SpecialRespawnInterval = 80
MusicDynamicMobSpawnSize = 8
MusicDynamicMobStopSize = 2
MusicDynamicMobScanStopSize = 1
}
function EnableEscapeTanks()
{
printl( "Chase Tanks Enabled!" );
MapScript.DirectorOptions.EscapeSpawnTanks <- true
}
function OnBeginCustomFinaleStage( num, type )
{
//printl( "Beginning custom finale stage " + num + " of type " + type );
if ( type == 2 )
EntFire( "pilot", "SpeakResponseConcept", "hospital_radio_intransit" );
}
|
c9m2_lots_finale.nuc
//-----------------------------------------------------
//
//
//-----------------------------------------------------
Msg("Initiating c9m2_lots_finale script\n");
//-----------------------------------------------------
ERROR <- -1
PANIC <- 0
TANK <- 1
DELAY <- 2
SCRIPTED <- 3
//-----------------------------------------------------
StageDelay <- 0
PreEscapeDelay <- 0
if ( Director.GetGameModeBase() == "coop" || Director.GetGameModeBase() == "realism" )
{
StageDelay <- 5
PreEscapeDelay <- 5
}
else if ( Director.GetGameModeBase() == "versus" )
{
StageDelay <- 10
PreEscapeDelay <- 15
}
DirectorOptions <-
{
A_CustomFinale_StageCount = 8
A_CustomFinale1 = PANIC
A_CustomFinaleValue1 = 2
A_CustomFinale2 = DELAY
A_CustomFinaleValue2 = StageDelay
A_CustomFinale3 = TANK
A_CustomFinaleValue3 = 1
A_CustomFinale4 = DELAY
A_CustomFinaleValue4 = StageDelay
A_CustomFinale5 = PANIC
A_CustomFinaleValue5 = 2
A_CustomFinaleMusic5 = "Event.FinaleWave4"
A_CustomFinale6 = DELAY
A_CustomFinaleValue6 = StageDelay
A_CustomFinale7 = TANK
A_CustomFinaleValue7 = 1
A_CustomFinale8 = DELAY
A_CustomFinaleValue8 = PreEscapeDelay
TankLimit = 1
WitchLimit = 0
CommonLimit = 20
HordeEscapeCommonLimit = 15
EscapeSpawnTanks = false
//SpecialRespawnInterval = 80
MusicDynamicMobSpawnSize = 8
MusicDynamicMobStopSize = 2
MusicDynamicMobScanStopSize = 1
}
function EnableEscapeTanks()
{
printl( "Chase Tanks Enabled!" );
MapScript.DirectorOptions.EscapeSpawnTanks <- true
}
|
c10m5_houseboat_finale.nuc
//-----------------------------------------------------
//
//
//-----------------------------------------------------
Msg("Initiating c10m5_houseboat_finale script\n");
//-----------------------------------------------------
ERROR <- -1
PANIC <- 0
TANK <- 1
DELAY <- 2
SCRIPTED <- 3
//-----------------------------------------------------
StageDelay <- 0
PreEscapeDelay <- 0
if ( Director.GetGameModeBase() == "coop" || Director.GetGameModeBase() == "realism" )
{
StageDelay <- 5
PreEscapeDelay <- 5
}
else if ( Director.GetGameModeBase() == "versus" )
{
StageDelay <- 10
PreEscapeDelay <- 15
}
DirectorOptions <-
{
A_CustomFinale_StageCount = 8
A_CustomFinale1 = PANIC
A_CustomFinaleValue1 = 2
A_CustomFinale2 = DELAY
A_CustomFinaleValue2 = StageDelay
A_CustomFinale3 = TANK
A_CustomFinaleValue3 = 1
A_CustomFinale4 = DELAY
A_CustomFinaleValue4 = StageDelay
A_CustomFinale5 = PANIC
A_CustomFinaleValue5 = 2
A_CustomFinaleMusic5 = "Event.FinaleWave4"
A_CustomFinale6 = DELAY
A_CustomFinaleValue6 = StageDelay
A_CustomFinale7 = TANK
A_CustomFinaleValue7 = 1
A_CustomFinale8 = DELAY
A_CustomFinaleValue8 = PreEscapeDelay
TankLimit = 1
WitchLimit = 0
CommonLimit = 20
HordeEscapeCommonLimit = 15
EscapeSpawnTanks = false
//SpecialRespawnInterval = 80
MusicDynamicMobSpawnSize = 8
MusicDynamicMobStopSize = 2
MusicDynamicMobScanStopSize = 1
}
function EnableEscapeTanks()
{
printl( "Chase Tanks Enabled!" );
MapScript.DirectorOptions.EscapeSpawnTanks <- true
}
function OnBeginCustomFinaleStage( num, type )
{
//printl( "Beginning custom finale stage " + num + " of type " + type );
if ( type == 2 )
EntFire( "orator_boat_radio", "SpeakResponseConcept", "boat_radio_intransit" );
}
|
c11m5_runway_finale.nuc
//-----------------------------------------------------
//
//
//-----------------------------------------------------
Msg("Initiating c11m5_runway_finale script\n");
//-----------------------------------------------------
ERROR <- -1
PANIC <- 0
TANK <- 1
DELAY <- 2
SCRIPTED <- 3
//-----------------------------------------------------
StageDelay <- 0
PreEscapeDelay <- 0
if ( Director.GetGameModeBase() == "coop" || Director.GetGameModeBase() == "realism" )
{
StageDelay <- 5
PreEscapeDelay <- 5
}
else if ( Director.GetGameModeBase() == "versus" )
{
StageDelay <- 10
PreEscapeDelay <- 15
}
DirectorOptions <-
{
A_CustomFinale_StageCount = 8
A_CustomFinale1 = PANIC
A_CustomFinaleValue1 = 2
A_CustomFinale2 = DELAY
A_CustomFinaleValue2 = StageDelay
A_CustomFinale3 = TANK
A_CustomFinaleValue3 = 1
A_CustomFinale4 = DELAY
A_CustomFinaleValue4 = StageDelay
A_CustomFinale5 = PANIC
A_CustomFinaleValue5 = 2
A_CustomFinaleMusic5 = "Event.FinaleWave4"
A_CustomFinale6 = DELAY
A_CustomFinaleValue6 = StageDelay
A_CustomFinale7 = TANK
A_CustomFinaleValue7 = 1
A_CustomFinale8 = DELAY
A_CustomFinaleValue8 = PreEscapeDelay
TankLimit = 1
WitchLimit = 0
CommonLimit = 20
HordeEscapeCommonLimit = 15
EscapeSpawnTanks = false
//SpecialRespawnInterval = 80
MusicDynamicMobSpawnSize = 8
MusicDynamicMobStopSize = 2
MusicDynamicMobScanStopSize = 1
}
function EnableEscapeTanks()
{
printl( "Chase Tanks Enabled!" );
MapScript.DirectorOptions.EscapeSpawnTanks <- true
}
function OnBeginCustomFinaleStage( num, type )
{
//printl( "Beginning custom finale stage " + num + " of type " + type );
if ( type == 2 )
EntFire( "orator_plane_radio", "SpeakResponseConcept", "plane_radio_intransit" );
}
|
c12m5_cornfield_finale.nuc
//-----------------------------------------------------
//
//
//-----------------------------------------------------
Msg("Initiating c12m5_cornfield_finale script\n");
//-----------------------------------------------------
ERROR <- -1
PANIC <- 0
TANK <- 1
DELAY <- 2
SCRIPTED <- 3
//-----------------------------------------------------
StageDelay <- 0
PreEscapeDelay <- 0
if ( Director.GetGameModeBase() == "coop" || Director.GetGameModeBase() == "realism" )
{
StageDelay <- 5
PreEscapeDelay <- 5
}
else if ( Director.GetGameModeBase() == "versus" )
{
StageDelay <- 10
PreEscapeDelay <- 15
}
DirectorOptions <-
{
A_CustomFinale_StageCount = 8
A_CustomFinale1 = PANIC
A_CustomFinaleValue1 = 2
A_CustomFinale2 = DELAY
A_CustomFinaleValue2 = StageDelay
A_CustomFinale3 = TANK
A_CustomFinaleValue3 = 1
A_CustomFinale4 = DELAY
A_CustomFinaleValue4 = StageDelay
A_CustomFinale5 = PANIC
A_CustomFinaleValue5 = 2
A_CustomFinaleMusic5 = "Event.FinaleWave4"
A_CustomFinale6 = DELAY
A_CustomFinaleValue6 = StageDelay
A_CustomFinale7 = TANK
A_CustomFinaleValue7 = 1
A_CustomFinale8 = DELAY
A_CustomFinaleValue8 = PreEscapeDelay
TankLimit = 1
WitchLimit = 0
CommonLimit = 20
HordeEscapeCommonLimit = 15
EscapeSpawnTanks = false
//SpecialRespawnInterval = 80
MusicDynamicMobSpawnSize = 8
MusicDynamicMobStopSize = 2
MusicDynamicMobScanStopSize = 1
}
function EnableEscapeTanks()
{
printl( "Chase Tanks Enabled!" );
MapScript.DirectorOptions.EscapeSpawnTanks <- true
}
function OnBeginCustomFinaleStage( num, type )
{
//printl( "Beginning custom finale stage " + num + " of type " + type );
if ( type == 2 )
EntFire( "orator_farm_radio", "SpeakResponseConcept", "farm_radio_intransit" );
}
|
c14m1_lighthouse_finale.nuc
Msg("----------------------FINALE SCRIPT------------------\n")
StageDelay <- 0
PreEscapeDelay <- 0
if ( Director.GetGameModeBase() == "coop" || Director.GetGameModeBase() == "realism" )
{
StageDelay <- 5
PreEscapeDelay <- 5
}
else if ( Director.GetGameModeBase() == "versus" )
{
StageDelay <- 10
PreEscapeDelay <- 15
}
//-----------------------------------------------------
PANIC <- 0
TANK <- 1
DELAY <- 2
ONSLAUGHT <- 3
//-----------------------------------------------------
DirectorOptions <-
{
A_CustomFinale_StageCount = 14
A_CustomFinale1 = ONSLAUGHT
A_CustomFinaleValue1 = "c14m1_gauntlet"
A_CustomFinale2 = DELAY
A_CustomFinaleValue2 = StageDelay
A_CustomFinale3 = TANK
A_CustomFinaleValue3 = 1
A_CustomFinale4 = DELAY
A_CustomFinaleValue4 = StageDelay
A_CustomFinale5 = PANIC
A_CustomFinaleValue5 = 2
A_CustomFinale6 = DELAY
A_CustomFinaleValue6 = StageDelay
A_CustomFinale7 = ONSLAUGHT
A_CustomFinaleValue7 = "c14m1_gauntlet"
A_CustomFinale8 = DELAY
A_CustomFinaleValue8 = StageDelay
A_CustomFinale9 = TANK
A_CustomFinaleValue9 = 1
A_CustomFinale10 = DELAY
A_CustomFinaleValue10 = StageDelay
A_CustomFinale11 = PANIC
A_CustomFinaleValue11 = 2
A_CustomFinale12 = DELAY
A_CustomFinaleValue12 = StageDelay
A_CustomFinale13 = TANK
A_CustomFinaleValue13 = 2
A_CustomFinaleMusic13 = "Event.TankMidpoint_Metal"
A_CustomFinale14 = DELAY
A_CustomFinaleValue14 = PreEscapeDelay
//-----------------------------------------------------
ProhibitBosses = true
}
//-----------------------------------------------------
// number of cans needed to escape.
NumCansNeeded <- 8
// fewer cans in single player since bots don't help much
/*if ( Director.IsSinglePlayerGame() )
{
NumCansNeeded <- 6
}*/
//-----------------------------------------------------
// INIT
//-----------------------------------------------------
GasCansTouched <- 0
GasCansPoured <- 0
//NavMesh.UnblockRescueVehicleNav()
//-----------------------------------------------------
function GasCanTouched()
{
GasCansTouched++
Msg(" Touched: " + GasCansTouched + "\n")
EvalGasCansPouredOrTouched()
}
function GasCanPoured()
{
GasCansPoured++
Msg(" Poured: " + GasCansPoured + "\n")
if ( GasCansPoured == NumCansNeeded )
{
Msg(" needed: " + NumCansNeeded + "\n")
EntFire( "relay_generator_ready", "Trigger" )
}
EvalGasCansPouredOrTouched()
}
function EvalGasCansPouredOrTouched()
{
TouchedOrPoured <- GasCansPoured + GasCansTouched
Msg(" Poured or touched: " + TouchedOrPoured + "\n")
}
//-----------------------------------------------------
function OnBeginCustomFinaleStage( num, type )
{
printl( "Beginning custom finale stage " + num + " of type " + type );
if ( num == 7 )
{
EntFire( "relay_lighthouse_off", "Trigger" );
}
}
|
c14m2_lighthouse_finale.nuc
Msg("Initiating c14m2_lighthouse_finale script\n");
StageDelay <- 15
PreEscapeDelay <- 10
//-----------------------------------------------------
PANIC <- 0
TANK <- 1
DELAY <- 2
ONSLAUGHT <- 3
//-----------------------------------------------------
DirectorOptions <-
{
A_CustomFinale_StageCount = 8
A_CustomFinale1 = PANIC
A_CustomFinaleValue1 = 2
A_CustomFinale2 = DELAY
A_CustomFinaleValue2 = StageDelay
A_CustomFinale3 = TANK
A_CustomFinaleValue3 = 1
A_CustomFinale4 = DELAY
A_CustomFinaleValue4 = StageDelay
A_CustomFinale5 = ONSLAUGHT
A_CustomFinaleValue5 = "c14m2_gauntlet"
A_CustomFinale6 = DELAY
A_CustomFinaleValue6 = StageDelay
A_CustomFinale7 = TANK
A_CustomFinaleValue7 = 2
A_CustomFinaleMusic7 = "Event.TankMidpoint_Metal"
A_CustomFinale8 = DELAY
A_CustomFinaleValue8 = PreEscapeDelay
//-----------------------------------------------------
ProhibitBosses = true
HordeEscapeCommonLimit = 20
EscapeSpawnTanks = false
}
local difficulty = Convars.GetStr( "z_difficulty" ).tolower();
if ( Director.GetGameModeBase() == "versus" )
{
DirectorOptions.rawdelete("A_CustomFinaleMusic7");
DirectorOptions.A_CustomFinale_StageCount = 11;
DirectorOptions.A_CustomFinale6 = ONSLAUGHT;
DirectorOptions.A_CustomFinaleValue6 = "c14m2_gauntlet_vs";
DirectorOptions.A_CustomFinale7 = ONSLAUGHT;
DirectorOptions.A_CustomFinaleValue7 = "c14m2_gauntlet_vs";
DirectorOptions.A_CustomFinale8 = ONSLAUGHT;
DirectorOptions.A_CustomFinaleValue8 = "c14m2_gauntlet_vs";
DirectorOptions.A_CustomFinale9 <- DELAY;
DirectorOptions.A_CustomFinaleValue9 <- StageDelay;
DirectorOptions.A_CustomFinale10 <- TANK;
DirectorOptions.A_CustomFinaleValue10 <- 1;
DirectorOptions.A_CustomFinaleMusic10 <- "Event.TankMidpoint_Metal";
DirectorOptions.A_CustomFinale11 <- DELAY;
DirectorOptions.A_CustomFinaleValue11 <- PreEscapeDelay;
difficulty = "normal";
}
else
{
if ( difficulty == "hard" || difficulty == "impossible" )
{
DirectorOptions.rawdelete("A_CustomFinaleMusic7");
DirectorOptions.A_CustomFinale_StageCount = 12;
DirectorOptions.A_CustomFinaleValue7 = 1;
DirectorOptions.A_CustomFinaleValue8 = StageDelay;
DirectorOptions.A_CustomFinale9 <- PANIC;
DirectorOptions.A_CustomFinaleValue9 <- 2;
DirectorOptions.A_CustomFinale10 <- DELAY;
DirectorOptions.A_CustomFinaleValue10 <- StageDelay;
DirectorOptions.A_CustomFinale11 <- TANK;
DirectorOptions.A_CustomFinaleValue11 <- 2;
DirectorOptions.A_CustomFinaleMusic11 <- "Event.TankMidpoint_Metal"
DirectorOptions.A_CustomFinale12 <- DELAY;
DirectorOptions.A_CustomFinaleValue12 <- PreEscapeDelay;
}
}
//-----------------------------------------------------
function SpawnScavengeCans( difficulty )
{
local function SpawnCan( gascan )
{
local can_origin = gascan.GetOrigin();
local can_angles = gascan.GetAngles();
gascan.Kill();
local kvs =
{
angles = can_angles.ToKVString()
body = 0
disableshadows = 1
glowstate = 3
model = "models/props_junk/gascan001a.mdl"
skin = 2
weaponskin = 2
solid = 0
spawnflags = 2
targetname = "scavenge_gascans"
origin = can_origin.ToKVString()
connections =
{
OnItemPickedUp =
{
cmd1 = "director�RunScriptCode�DirectorScript.MapScript.LocalScript.GasCanTouched()�0�-1"
//Editors Note: These � characters will not copy over properly. Websites cannot display them.
//In Notepad++ replace them by selecting them, holding down ALT and entering 027 on Numblock. You'll get a black ESC character.
}
}
}
local can_spawner = SpawnEntityFromTable( "weapon_scavenge_item_spawn", kvs );
if ( can_spawner )
DoEntFire( "!self", "SpawnItem", "", 0, null, can_spawner );
}
switch( difficulty )
{
case "impossible":
{
local gascan = null;
while ( gascan = Entities.FindByName( gascan, "gascans_finale_expert" ) )
{
if ( gascan.IsValid() )
SpawnCan( gascan );
}
}
case "hard":
{
local gascan = null;
while ( gascan = Entities.FindByName( gascan, "gascans_finale_advanced" ) )
{
if ( gascan.IsValid() )
SpawnCan( gascan );
}
}
case "normal":
{
local gascan = null;
while ( gascan = Entities.FindByName( gascan, "gascans_finale_normal" ) )
{
if ( gascan.IsValid() )
SpawnCan( gascan );
}
}
case "easy":
{
local gascan = null;
while ( gascan = Entities.FindByName( gascan, "gascans_finale_easy" ) )
{
if ( gascan.IsValid() )
SpawnCan( gascan );
}
break;
}
default:
break;
}
EntFire( "gascans_finale_*", "Kill" );
}
// number of cans needed to escape.
NumCansNeeded <- 8
switch( difficulty )
{
case "easy":
{
NumCansNeeded = 6;
EntFire( "relay_outro_easy", "Enable" );
break;
}
case "normal":
{
NumCansNeeded = 8;
EntFire( "relay_outro_normal", "Enable" );
break;
}
case "hard":
{
NumCansNeeded = 10;
EntFire( "relay_outro_advanced", "Enable" );
break;
}
case "impossible":
{
NumCansNeeded = 12;
EntFire( "relay_outro_expert", "Enable" );
break;
}
default:
break;
}
EntFire( "progress_display", "SetTotalItems", NumCansNeeded );
EntFire( "radio", "AddOutput", "FinaleEscapeStarted director:RunScriptCode:DirectorScript.MapScript.LocalScript.DirectorOptions.TankLimit <- 3:0:-1" );
local c14m2_tankspawntime = 0.0;
local c14m2_tankspawner = null;
while ( c14m2_tankspawner = Entities.FindByClassname( c14m2_tankspawner, "commentary_zombie_spawner" ) )
{
if ( c14m2_tankspawner.IsValid() )
{
c14m2_tankspawner.ValidateScriptScope();
local spawnerScope = c14m2_tankspawner.GetScriptScope();
spawnerScope.SpawnedTankTime <- 0.0;
spawnerScope.InputSpawnZombie <- function()
{
if ( (caller) && (caller.GetName() == "escapetanktrigger") )
{
if ( !c14m2_tankspawntime )
c14m2_tankspawntime = Time();
}
if ( SpawnedTankTime )
{
if ( Time() - c14m2_tankspawntime < 1 )
return false;
else
{
delete this.SpawnedTankTime;
delete this.InputSpawnZombie;
return true;
}
}
SpawnedTankTime = Time();
return true;
}
}
}
//-----------------------------------------------------
// INIT
//-----------------------------------------------------
GasCansTouched <- 0
GasCansPoured <- 0
ScavengeCansPoured <- 0
ScavengeCansNeeded <- 2
local EscapeStage = DirectorOptions.A_CustomFinale_StageCount;
//-----------------------------------------------------
function GasCanTouched()
{
GasCansTouched++;
if ( developer() > 0 )
Msg(" Touched: " + GasCansTouched + "\n");
}
function GasCanPoured()
{
GasCansPoured++;
ScavengeCansPoured++;
if ( developer() > 0 )
Msg(" Poured: " + GasCansPoured + "\n");
if ( GasCansPoured == 1 )
EntFire( "explain_fuel_generator", "Kill" );
else if ( GasCansPoured == NumCansNeeded )
{
if ( developer() > 0 )
Msg(" needed: " + NumCansNeeded + "\n");
EntFire( "relay_generator_ready", "Trigger", "", 0.1 );
EntFire( "weapon_scavenge_item_spawn", "TurnGlowsOff" );
EntFire( "weapon_scavenge_item_spawn", "Kill" );
EntFire( "director", "EndCustomScriptedStage", "", 5 );
}
if ( Director.GetGameModeBase() == "versus" && ScavengeCansPoured == 2 && GasCansPoured < NumCansNeeded )
{
ScavengeCansPoured = 0;
EntFire( "radio", "AdvanceFinaleState" );
}
}
//-----------------------------------------------------
function OnBeginCustomFinaleStage( num, type )
{
if ( developer() > 0 )
printl( "Beginning custom finale stage " + num + " of type " + type );
if ( num == 4 )
{
EntFire( "relay_boat_coming2", "Trigger" );
// Delay lasts 10 seconds, next stage turns off lights immediately
EntFire( "lighthouse_light", "SetPattern", "mmamammmmammamamaaamammma", 7.0 );
EntFire( "lighthouse_light", "SetPattern", "", 9.5 );
EntFire( "lighthouse_light", "TurnOff", "", 10 );
EntFire( "spotlight_beams", "LightOff", "", 7.0 );
EntFire( "spotlight_glow", "HideSprite", "", 7.0 );
EntFire( "brush_light", "Enable", "", 7.0 );
EntFire( "spotlight_beams", "LightOn", "", 7.5 );
EntFire( "spotlight_glow", "ShowSprite", "", 7.5 );
EntFire( "brush_light", "Disable", "", 7.5 );
EntFire( "spotlight_beams", "LightOff", "", 8.0 );
EntFire( "spotlight_glow", "HideSprite", "", 8.0 );
EntFire( "brush_light", "Enable", "", 8.0 );
EntFire( "spotlight_beams", "LightOn", "", 8.5 );
EntFire( "spotlight_glow", "ShowSprite", "", 8.5 );
EntFire( "brush_light", "Disable", "", 8.5 );
}
else if ( num == 5 )
{
EntFire( "relay_lighthouse_off", "Trigger" );
SpawnScavengeCans( difficulty );
}
else if ( num == EscapeStage )
EntFire( "relay_start_boat", "Trigger" );
}
function GetCustomScriptedStageProgress( defvalue )
{
local progress = ScavengeCansPoured.tofloat() / ScavengeCansNeeded.tofloat();
if ( developer() > 0 )
Msg( "Progress was " + defvalue + ", now: " + ScavengeCansPoured + " poured / " + ScavengeCansNeeded + " needed = " + progress + "\n" );
return progress;
}
|
director_gauntlet.nuc (为所有长途救援结局共享)
Msg("Initiating Gauntlet\n");
DirectorOptions <-
{
PanicForever = true
PausePanicWhenRelaxing = true
IntensityRelaxThreshold = 0.99
RelaxMinInterval = 25
RelaxMaxInterval = 35
RelaxMaxFlowTravel = 400
LockTempo = 0
SpecialRespawnInterval = 20
PreTankMobMax = 20
ZombieSpawnRange = 3000
ZombieSpawnInFog = true
MobSpawnSize = 5
CommonLimit = 5
GauntletMovementThreshold = 500.0
GauntletMovementTimerLength = 5.0
GauntletMovementBonus = 2.0
GauntletMovementBonusMax = 30.0
// length of bridge to test progress against.
BridgeSpan = 20000
MobSpawnMinTime = 5
MobSpawnMaxTime = 5
MobSpawnSizeMin = 5
MobSpawnSizeMax = 20
minSpeed = 50
maxSpeed = 200
speedPenaltyZAdds = 15
CommonLimitMax = 30
function RecalculateLimits()
{
//Increase common limit based on progress
local progressPct = ( Director.GetFurthestSurvivorFlow() / BridgeSpan )
if ( progressPct < 0.0 ) progressPct = 0.0;
if ( progressPct > 1.0 ) progressPct = 1.0;
MobSpawnSize = MobSpawnSizeMin + progressPct * ( MobSpawnSizeMax - MobSpawnSizeMin )
//Increase common limit based on speed
local speedPct = ( Director.GetAveragedSurvivorSpeed() - minSpeed ) / ( maxSpeed - minSpeed );
if ( speedPct < 0.0 ) speedPct = 0.0;
if ( speedPct > 1.0 ) speedPct = 1.0;
MobSpawnSize = MobSpawnSize + speedPct * ( speedPenaltyZAdds );
CommonLimit = MobSpawnSize * 1.5
if ( CommonLimit > CommonLimitMax ) CommonLimit = CommonLimitMax;
}
}
function Update()
{
DirectorOptions.RecalculateLimits();
}
|
另请参阅
介绍
文档
其他
← 求生之路2关卡设计/长途救援结局 | Return to 求生之路2关卡设计 |