I've seen many questions in the
Developers Corner and other sections about people asking for help with hooks: what are they, how do they work, et cetera. So, I decided I'd make a (not so quick) guide. Welcome to:
Hooks 101: What are they, what do they do, and how do I use them?.
What are hooks?In the simplest terms I can think of: hooks are blocks of code that is called whenever a certain action happens in-game. In other words, they "hook" into certain game events. Each hook has a specific purpose. For example, the
GM:PlayerDeath hook is called whenever a player dies, and the
GM:PlayerSay hook is called whenever a player sends a message in chat. Hooks are extremely versatile tools that allows you to perform custom actions when a default event occurs.
Hooks follow the following format:
hook.Add( "TheHookToAdd", "A unique identifier", the function to execute )
What do they do?Like I previously said, hooks allow you to perform specific scripts when a game event occurs. Each hook has a specific set of
parameters, or variables that let the hook access specific information. For the example I used in the previous section, the
PlayerDeath hook allows you to perform actions when someone dies. Each hook contains a set of parameters that are automatically filled whenever the event occurs. The
PlayerDeath hook takes three parameters: "victim", "inflictor", and "attacker". As with any function, these parameters could be of any name ("v", "i", "a" would work the same as the former). You can find more about what parameters each hook takes on the
Wiki Page.
Example: Print in everyone's chat "A player has died" when someone dies.
hook.Add( "PlayerDeath", "Hooks101Example1", function( victim, inflictor, attacker ) -- Inits the hook to wait for someone dies.
PrintMessage( HUD_PRINTTALK, "A player has died" ) -- Uses the PrintMessage() function to let everyone know a player has died.
end ) -- Ends the function and the hook.
You could also say
who died by including the player's name:
hook.Add( "PlayerDeath", "Hooks101Example2", function( victim, inflictor, attacker )
PrintMessage( HUD_PRINTTALK, victim:Nick() .. " has died." ) -- Uses the Player:Nick() function to get the player's nickname.
end )
Note: Keep in mind that
Player:Nick won't actually do anything unless the actual value of the parameter is "Player". The wiki uses "Player:" before any player function because it requires a player object in that position. In the example hook above, that Player object is "victim".
You also don't have to write the function
inside the hook. You can make the hook use a defined function, and you don't even have to include all the parameters.
For example, if you only wanted to print the victim's name, you only need to include the first parameter.
hook.Add( "PlayerDeath", "Hooks101Example2", function( victim, inflictor, attacker )
PrintMessage( HUD_PRINTTALK, victim:Nick() .. " has died." )
end )
-- Both of these are equivalent, but the bottom one only has one parameter.
function announceDeath( victim )
PrintMessage( HUD_PRINTTALK, victim:Nick() .. " has died." )
end
hook.Add( "PlayerDeath", "Hooks101Example3", announceDeath )
The only issue with this, however, is the parameters
MUST be in the correct order.
PlayerDeath takes three parameters: the victim, the inflictor (or the weapon that killed the victim) and the attacker. If you only needed the victim and attacker, however, you have to include inflictor there.
For example:
hook.Add( "PlayerDeath", "Hooks101Example4", function( victim, attacker )
PrintMessage( HUD_PRINTTALK, victim:Nick() .. " was killed by " .. attacker:Nick() )
end )
will not work, because it expects the second parameter to be an Entity, and since you can't kill someone with a player (the actual inflictor of the death, not the person who controlled the inflictor), you cannot call the Nick() function on it. A version of this that would work:
Note: To clarify: yes, a Player is an Entity, but an Entity is not a Player. This has to do with inheritance. It goes Entity -> Player, which means Player inherits from Entity. Think of it like fish; all Goldfish are fish, but not all fish are Goldfish.
hook.Add( "PlayerDeath", "Hooks101Example5", function( victim, inflictor, attacker )
PrintMessage( HUD_PRINTTALK, victim:Nick() .. " was killed by " .. attacker:Nick() )
end )
How do I use them?Hooks are very simple to use, and I've already described the format above. Of course, Hooks need to be loaded in order to be used, so place them in "addons/<your_custom_addon_folder>/lua/autorun/(server or shared or client)". If your hook can only be used serverside (check the Wiki page for it, if the icon next to it is blue, then it is server-only, orange means it is client-only, and blue/orange means it is shared, or that it can be used on either the client or the server), then after "autorun" put "shared", "server", or "client", depending on the need. Or, you can make a file "addons/<your_custom_addon_folder>/lua/<some_name>/hook.lua" (hook.lua can be replaced by anything else) and then put your hook/code in there, and then make an autorun file that includes that file:
-- Prints out when a player dies (server only)
-- File: addons/hook_example/lua/hooks/hook.lua
local function playerDeath( victim, inflictor, attacker ) -- Only local because it doesn't need to be called anywhere else.
PrintMessage( HUD_PRINTTALK, victim:Nick() .. " was killed by " .. attacker:Nick() .. " using a " .. inflictor:GetName() .. "!" ) -- Utilizes Player:Nick() and Entity:GetName()
end -- Ends the function
hook.Add( "PlayerDeath", "Hooks101Example6", playerDeath ) -- Adds the hook to call the function when a Player dies. You don't need to include the parameters in the "playerDeath" call, as the hook will do it for you.
Then, in an autorun file:
-- File: addons/hook_example/lua/autorun/server/include_hook.lua
include "hooks/hook.lua"
Note: I didn't include parentheses around surrounding "hooks/hook.lua" because Lua does not require parentheses on a single-argument literal string or table constructor parameter. This is simply a stylistic choice because I like how it looks. include "something" is equivalent to include( "something" ). Read more:
https://www.lua.org/pil/5.html.
I hope I answered most of your questions. I understand this guide might not be complete, so please, if you have any further questions feel free to leave them in the comments below. I have a reserved post under this that I will use to fill in with answers to questions.
Edit: If I've made a mistake anywhere, please let me know and I'll fix it.
Edit2: More (official) information on Hooks:
http://wiki.garrysmod.com/page/Category:EFFECT_Hookshttp://wiki.garrysmod.com/page/Category:ENTITY_Hookshttp://wiki.garrysmod.com/page/Category:NEXTBOT_Hookshttp://wiki.garrysmod.com/page/Category:GM_Hooks These are the most commonhttp://wiki.garrysmod.com/page/Category:PANEL_Hooks Used for a lot of clientside codehttp://wiki.garrysmod.com/page/Category:PLAYER_Hooks Primarily for gamemode usehttp://wiki.garrysmod.com/page/Category:SANDBOX_Hookshttp://wiki.garrysmod.com/page/Category:WEAPON_Hookshttp://wiki.garrysmod.com/page/Category:TOOL_Hooks