Monday, November 4, 2013

Molotovs in The Last Of Us

Molotovs In The Last Of Us: Part I
One of the more interesting effects I worked on in this project were the Molotovs. In action it's just some fire effects and who hasn't see that before. What I find particularly interesting is what it took to bring it all together. There are many components to the Molotovs and while working on them I learned a ton about our scripting engine and how powerful it can be. But the point of this post isn't to talk up our scripting engine, rather to walk you through how we put it together in hopes of broadening your perception on what it takes to put something like this in the game.

Rootvars and Particler:
So, jumping right into it. Particler is our in house particle authoring tool. During production our dedicated fx programmer Marshall Robin added some new, really cool functionality to how we interact with our particles at runtime. Using a system referred to as rootvars, we were able to create variables in our expressions during the authoring stage that we could set the value for at runtime and update as well.

the rootvar __root.alpha here is being used as a float to modulate the opacity value of the particles

Using these I was able to make a single effect and manipulate attributes of the effect based on conditions I set in script. An example is demonstrated in the video below. The player can obtain upgrades by reading manuals that will increase the effectiveness of Molotovs the player creates. For instance the damage radius is increased with each upgrade. Rather than create an entirely new effect based on the upgrade, I've passed the upgrade level as an int and, based on that number, at creation I set conditions so I can set values in my single effect to represent the upgrade like sprite size and emitter radius among other visual aspects.


The concept for the Molotov and its need for flexibility:
The easy way for the Molotov to work would have been the old method. In a specific file, we can define what effects to spawn specific to certain weapon types and explosions. This is an oversimplification of how that all works. For example, in this specific file there would be some definition for the general gameplay behavior of the Molotov and in this location there would be a space where we can define what single particle effect we would like to play when the Molotov explosion is triggered in gameplay. Molotov goes boom, spawn some effect. The simple way to create the Molotov would have been to simply say spawn my Molotov effect when this explosion happens. The Molotov however needed to be flexible. For instance after watching a lot of reference I noticed that the way it spawns differs greatly depending on the angle of the surface it explodes on. So we had four possible explosions that could be defined. One for the floor, one for walls, one for ceilings, and one for impacting characters directly.


Floor Impact Molotov
Ceiling Impact Molotov
Direct Hit on Enemy Impact Molotov
The fiery bits spit out by a Molotov would need to react based on the angle of the surface it impacted and take into account other information and conditions. On top of this the player would be able to upgrade the Molotov damage radius so the effects would have to reflect these upgrades. This all would have meant we would need to author a new effect for every upgrade possible for all four effects if we stuck with the traditional method. So I went with a more technical setup but far more flexible.

State Scripts:
State scripts are built using our internal scripting language. The syntax is based on lisp. You can think of it like Unreal Script and LUA. A state script is very flexible and can be used for a number of tasks, ranging from controlling how objects behave when attacked to setting up logic for combat. I had used state scripts loosely on Uncharted 3 and had continued to become familiar with them as I saw a lot of potential for setting up effects using them. We also have a large number of user and programmer created functions that support them. When spawning an effect in particler we can send collision events that carry information that can be used by state scripts. So I'll detail the information I used to interpret the behavior for Molotovs.

State Script Example

Collision events and the state scripts for Molotovs:
So the most flexible way I could think to setup the Molotovs was to instead have a state script spawned in place of a particle effect and that state script would spawn the particle effect and control all the aspects of its behavior. So this is how It all went down.
  • Lead Programmer Travis Mcintosh setup the lower level code to spawn the state script and pass the script a world space position and a quat that I could use when spawning the effects. He also sent an event to the script so that I could have all the variables setup before spawning the effects. This created a one frame delay but you don't really notice it.
  • I created an effect for each of the 4 types of Molotov bursts that contained fiery particles that fly out and collide with surfaces. Each time a particle collides with some geo it sends out a collision event.
  • The script listens for these events and using the information contained within the event sets up some conditions to further control how the Molotov behaves. 
  • All 4 effects spawn the same effects when they collide with geo but each script determines how those parts behave differently.
  • There are 3 parts that result from the collision of the Molotovs components. The small fire bits. The large fire bits. And the smoke, light, and scorch all in one effect.
  • Using functions inside our scripting language I was able to check for the level upgrade set on the player at the time the Molotov script spawns.
  • I set rootvars for scale and rate along with the speed at which components flew away from the center of the Molotov.
  • Additionally I check the y component of the normal that the collision takes place at. If the value is greater than 0.8 I don't spawn the normal fire bit and instead spawn another effect to creates some simple spreading. This spreading is purely a visual thing and does not contribute to gameplay but it was a nice touch.
  • I also check the surface type of the collision. If it's water I don't spawn the fire. If it's deep snow I spawn a different scorch mark entirely. So it would look like the snow was melting.

Here is a quick run through of the Molotov being used in gameplay. I have character invincibility on and I also have some infinite ammo set so I can just demonstrate how all of this looks in execution.

Gameplay Demonstration: Molotov

Conclusion:
The Molotov was a huge learning experience for me and allowed to explore all of my options for implementation. In retrospect there are some things I wish I could have done early on knowing what I know now. As with all things, I learned a lot about our scripting engine and continue to use it to implement some crazy effects. There is no greater feeling than setting up a bunch of conditions and then watching it all work and happen right in front of you. Seeing people lob these bad boys at each other and just imagining all the crazy crap going on under the hood, it's great. In part 2, I'll go over how I used some of the same techniques to control how fire spreads in infected as they walk through fire elements of the Molotov.