可以利用这一机制来让你的地图更动态化,根据玩家水平的不同做出响应。一个简单的例子是,在地图中分别创建几条长度/难度不同的路径,然后使用一个导演查询实体来控制某条路径的开闭。在对抗模式中,系统会在阵营互换时自动地重复第一局的选择,以保证游戏的公平性。
导演会持续地更新自身内部的状态,但出于地图编辑考虑,你必须通过某种触发器来显式地查询导演的状态。查询事件能反馈当前导演的愤怒值,让我们得以根据这个值设置不同的游戏逻辑。
在这个例子中,我们在生还者到达地图的特定点时发起一次查询。来,我们把一个触发器(trigger)固实体放在走廊中。关卡一开始就进行导演查询通常并没有什么卵用,因为此时生还者都是满血的,而导演的愤怒值通常也是最大的。但对于学习地图制作来说,这也足够了。
那需要多大的随机性呢?这点视不同情况而定。对于不同的剧情,兴趣区的设置也是不同的,不是随随便便就能做好的。建议有计划的循环地观察玩家状态,调整地图行为,再次观察,再次调整……
图中是一个逻辑定时器(logic_timer),每隔固定时间触发一次 info_query。条件选择器(logic_case)计算愤怒值并启用对应笔刷的显示。这样就能将导演查询出的值就能以数字形式展现给玩家了。
当然,除了数字以外,你可以用它来做出更好玩的东西。人们通常会有“呈现出相关性的事物一定具有因果关系”的错觉,可以利用人们的这一心态来制造娱乐效果,或是拿来吓人。(甚至有可能实现盈利(profit)。)
死亡二号线示例的第一张地图使用了这一技术来实现路线选择,一条路短而直,另一条则较为曲折蜿蜒。还有一个放在生还者必经之路上的刷怪器,根据导演愤怒值的不同,会生成一只Boomer或是Witch,在这种狭窄的空间里,不论刷出哪个都够让玩家好受的了。
logic_director_query is a new L4D2-specific entity that, when triggered, returns a value that corresponds with how "angry" the A.I. Director is at that moment. The better survivors are doing, the angrier the Director will be, and the more aggressive the game will be in spawning infected.
You can take advantage of this to make your maps more dynamic and responsive to player skill level. A simple example would be to create multiple paths through an area of varying length/difficulty, then using a Director query to open and close the appropriate paths. In versus, the system will automatically repeat the decision when teams swap, thus providing for an even playing context.
Firing a query
Let's look at how this works.
A solid to trigger the query.
The Director is constantly updating its state internally, but for map-editing purposes, you must explicitly query it with some kind of trigger. The query gives us a snapshot of the Director's anger value and allows our game logic setup to respond accordingly.
For this example, let's fire off the query once the survivors reach a certain point in the map. Go ahead and place a trigger volume in the hallway. Querying the Director so close to the very beginning of a first map is not always useful, since survivors will be at full health and the Director will always be at its most angry. But for learning purposes, this will do.
Place a solid, then select it and choose Tools > Tie to entity from the menu bar. Change the entity class to "trigger_once" and assign it the material "tools/toolstrigger
"
Filter what can activate the trigger.
We'll want this trigger to happen for survivors only, so we'll need to filter its output. To do so, let's place a new entity of class "filter_activator_team" and name it "filter_survivor
".
Select the trigger volume and under properties, set its filter name to "
filter_survivor
" The trigger will now only be activated by survivors, and not by infected.
A new info_director_query is born.
Next, let's move down the other end of the hallway to the ladder leading up to the safe room. Place a new entity of class "logic_director_query". For a name, use "director_query_zombie
".
Under Properties, set the Min. Anger Range to 0
, and the Max Anger Range to 9
. The Director itself keeps track of anger between 0 and 50, but for our purposes we will want to divide it into 10 cases. These settings remap the values that the Director query reports back to a scale between 0 and 10.
Noise in the anger value is a very important part of gameplay. A little bit of unpredictability is necessary to keep players on their toes. For tutorial purposes, let's set Noise to "Pure
". This effectively turns off the built-in in randomness in the anger system. You typically will not want to do this, as it removes the element of procedural surprise, making gameplay boring and predictable.
Go ahead and select the trigger volume at the start of the map and add an output "OnStartTouch" which will target "director_query_zombie
" with an input of "HowAngry
".
Hit F9 to run the map. Once it loads, step into the hallway to trigger the volume and then immediately bring up the console. The Director query will have spit out something like the following:
TRUE Anger: 50.00 Processed Anger: 50 Out Anger: 9
So your query is now firing for players. While working on your map, you will want to set sv_cheats
to 1, thus allowing you to manually trigger the Director query from the console. For us that would be:
ent_fire director_query_zombie howangry
Reacting to the query
Now that we can have information about the Director, we need to do something with it, and that will typically be some kind of change in the world. Let's spawn an infected, but have the type vary depending on the anger.
Place a new entity of class
commentary_zombie_spawner
just above the
director_query
.
Next, let's create a new logic_case
entity named "zombie_case
" and put in property values for each of the conditions we want to respond to. In this example, we've set it up to be able to respond to 10 different conditions.
Once the Properties are set up, we move on to the Outputs and signal the zombie spawner to do different things depending on the case.
Now, go back to your logic_query_director
entity and go to Outputs there. Choose OutAnger as your output, "zombie_case
" as your target, and InValue as your input. This will tell your logic_query_director to send the exact value of its remapped anger values to the logic_case. The logic_case will take this number and will correspond it to the cases you have set up.
If the case doesn't match the property, it won't do anything. So in this example, if the Director anger is 5 or below, it won't do anything.
Above 6, the case signals the spawner to force spawn a zombie, which will be either a common infected, a boomer, a charger, or a tank, depending on what the anger level was.
Other uses
When you're developing your maps, you'll want to carefully tune your map logic so that each Director-responsive scenario is FUN FOR PLAYERS. If your setup is too predictable, players will be able to anticipate it, and that's not fun. If it's so random that it's not clear that how well they are doing has some correlation with what happens, then they will not be motivated to do what you're asking them to do.
How much randomness should you use? It depends. The fun zone is different for each scenario, and achieving it seldom happens straight off. It is recommended that you plan for several iterations of observing players, tweaking the behavior, observing again.
Here's an example that you may find useful in developing and debugging your maps:
Open the file:
sdk_content\mapsrc\Your_First_L4D_Level_Tutorial\tutorial07_complete.vmf
Here we have a logic timer that has the info_query fire off a query at regular intervals. The logic_case evaluates the anger and enables the appropriate func_brush number. This gives a numerical readout of the anger value directly to players based on the Director query.
Of course, instead of numbers, you can do more subtle things. People often assume that correlation equals causality. You can use this to your advantage for entertainment and thrills. (And eventually perhaps even profit.)
Here's another example you should check out:
sdk_content/Deadline2/mapsrc/l4d_deadline01.vmf
The first map of Deadline2 example add-on campaign uses this to select alternate paths, one short and direct, one less direct and kinked. There is also a spawner that may place in the survivors path, depending on anger, a boomer or a witch, neither of which is good to have in a tight constrained space.