SteamVR/Environments/Scripting/Linking Lua with Hammer

This tutorial shows how to link functions in a VScript Lua script to Hammer entity logic.
== Scripts Called by Map Entities ==
If you would like entities in your map to call script functions (such as triggers), you’ll need to create another Lua script file to your scripts\vscripts directory.
Launch Hammer from the SteamVR Workshop Tools and create a new map from File > New.
Create a logic_script with the Entity Tool (light bulb icon on the tools bar). The location does not matter, but it will be easy to find if you place it near the world origin. Double click on it to open its properties:
In the Name field, call it what you want. This is what other entities on your scene will reference it as. 
:
Click on the + sign next to Misc and put the name of the Lua file you want to call (you will not need the .lua extension).
Create the basic map requirements such as the floor, an info_player_start, and a light_omni.
Create a trigger_multiple (again, you can use the Turret Tutorial for instructions on creating mesh entities). Open its properties by double-clicking on it or selecting it and pressing +.
In the Outputs tab, add an output named "OnStartTouch". Set the logic_script as the target. The input should be "CallScriptFunction" and the parameter should be the name of the function you want to be called.
::
	My Output 	Target Entity 	Target Input 	Parameter 	Delay	Only Once
	OnStartTouch	logic_script_name	CallScriptFunction	MyFunction	0.00 	No
In your Lua file referenced by your logic_script, add a simple function to print a message in the console:
function MyFunction()
	print("Trigger has been activated")
end
Compile the map and you should now be able to walk into the trigger_multiple in the game and see the message printed in the console.
=== Example 1 ===
There’s a trigger_multiple that detects if a player has crossed the line to throw balls into the targets. It’s called “red_team_check”. 
You can find it in the outliner in Hammer by typing “red_team_check” in the filter field:
If you double click on it and click on the Outputs tab, you can see it references the logic_script and uses CallScriptFunction with a parameter override of the name of the function you want to call in the Lua file.
You will then need to create a function in the Lua script that matches the one you are calling in the Entity I/O:
---------------------------------------------------------------------------
--Red Team
---------------------------------------------------------------------------
function RedTeamCheckStartTouch()
	--A player is over the line on the Red Team side
	red_team_counter = red_team_counter + 1
end
function RedTeamCheckEndTouch()
	red_team_counter = red_team_counter - 1
end
To create a function, you'll need to follow this same syntax with function MyFunction() and end to close it.
In this example, there’s an integer variable in the script called red_team_counter and it starts at 0. 
-- Global Variables
local red_team_counter = 0 -- Players behind the Red Team Line
local blue_team_counter = 0 -- Players behind the Blue Team Line
When a player touches the trigger, the number increases by 1. When a player is no longer touching the trigger, the number decreases by 1. 
The think function shown in the Lua Scripting Intro checks every second if the counter is higher than 0. If so, no points are awarded and there’s a message displayed on the board.
This chunk in the Think function in Arcade Toss checks if any player is over the line:
	if red_team_counter > 0 then
 	print("Red Team is over the line!")
 	RedTeamOverTheLine()
 else
 	RedTeamBehindTheLine()
 end
These functions are called if a player is over the line or if all players are in legal positions:
function RedTeamOverTheLine()
	bIsRedTeamBehindTheLine = false
	--Panel popup for notification
	DoEntFire( "red_team_check_panel", "AddCSSClass", "Activated", 0, self, self )
end
function RedTeamBehindTheLine()
	bIsRedTeamBehindTheLine = true
	DoEntFire( "red_team_check_panel", "RemoveCSSClass", "Activated", 0, self, self )
end
=== Example 2 ===
There's a trigger_multiple in each of the target holes for the balls to make contact with to tell the script when the player has scored.
Open the trigger_multiple in the green target hole on the Team Blue side (named “blue_team_hole_1”). Find this trigger in Hammer and double click on it or select it and press +.
Each of the fields that have a + mark beside it can be expanded:
It is set to trigger when Physics Objects touch it. It also has a filter (filter_activator_name) that says it will only trigger when an object named “blue_ball” touches it.
This is what the filter_activator_name looks like:
This tells it that it will only activate when a physics object named “blue_ball” collides with it.
The output of the trigger_multiple calls the CallScriptFunction in the logic_script file and in the parameter is the name of the function you want to call in the Lua script.
::
	My Output 	Target Entity 	Target Input 	Parameter 	Delay	Only Once
	OnStartTouch	arcade_toss_script	CallScriptFunction	BlueHoopRow1	0.00 	No
In the Lua file, you wil need to create any function you call in the entity logic. In this example, you’ll need to create a function called BlueHoopRow1.
Note: You don’t need to include the () in the Hammer I/O, just in the Lua function.
function BlueHoopRow1(trigger)
	--Calls another function for scoring with the parameters for the team and the number of points
	UpdateScoreboard(2, 5)
	--Specifies which info_particle_system to start for the scoring effects
	local hoop = "blue_trigger_bot_particle"
	HoopEffects(hoop, 2)
end
== Spawning Entities ==
Many times you will need to spawn entities into the world.
For example, in Arcade Toss, the Think function checks every second to see how many red balls exist. If there are less than 4, it will spawn more unless red balls exist in the spawner locations.
See the BallReplenish function in the Arcade Toss script.
To spawn an object, you will need to create a table that contains the Raw Data for the entity you wish to spawn. To make this easier, you can place one of the entities you want to spawn in Hammer and then open its properties.
Click on the settings icon to view the Raw Data.
This is the properties box with Raw Data enabled:
From this, we know what to call the keys in the table:
function RedBallLeftSpawner()
	--print("Spawning a Red Ball")
	local ballTable = 
	{
		origin = "224 128 24",
		targetname = "red_ball",
		model = "models/props_gameplay/red_ball001.vmdl"
	}
	ballTable["spawnflags#6"] = "1"
	local redBall = SpawnEntityFromTableSynchronous( "prop_physics_override", ballTable )
	redBall:Attribute_SetIntValue( "objectID", 1 )
	EmitSoundOn( "ball_spawn", redBall )
end
You don’t need to include the keys and values for the default properties.
Note: For the prop_physics_override entity used in the example above, a change in the spawnflags was required. Because of Lua’s scripting syntax, the # symbol could not be read except as an insert later. 
To change a spawnflag, you will need to have a similar method with “1” being checked on and “0” being checked off.
=== Precaching Resources ===
If you spawn an entity that does not exist in your Hammer map, you will need to precache the resources. For example, spawning the red and blue balls in Arcade Toss needed this code in the arcade_toss.lua file:
function Precache( context )
	PrecacheModel( "models/props_gameplay/red_ball001.vmdl", context )
	PrecacheModel( "models/props_gameplay/blue_ball001.vmdl", context )
end
Other resources can be precached with these functions:
Function 	Signature 	Description
PrecacheModel 	( string modelName, context ) 	Manually precache a single model.
PrecacheModelFolder 	( string folderName, context ) 	Recursively precache models within a folder.
PrecacheParticle 	( string particleName, context ) 	Manually precache a single particle.
PrecacheParticleFolder	( string folderName, context ) 	Recursively precache particles within a folder
PrecacheSoundFile 	( string soundFileName, context )	Manually precache a single sound file
Category:SteamVR
Category:SteamVR Home
Category:Scripting