Skip to main content

GSC references in Lua

Calling GSC functions

Calling GSC functions from the Lua scripting is made easy thanks to fed. To do so, you need to use the H1 GSC dump and figure out what the file and function names. If the file/function you are looking for has a _ID<decimal> or _id_<hex> prefix, this is most likely new code in H1 that isn't found in IW6 (Ghosts) or S1 (Advanced Warfare).

The scriptcall function for Lua scripting is usually called on any sort of player entity or the level entity. To call on a player, doing player:scriptcall(file, function, args) will work. However, if the function you are calling is from the level entity, you would use game:scriptcall(file, function, args) from the game object.

In this example, we are going to be calling maps/mp/_utility::_unsetPerk on last stand, martyrdom, and juggernaut perks. This code should be ran in a function that has access to a player variable.

function entity:player_spawned()
self:scriptcall("maps/mp/_utility", "_unsetperk", "specialty_pistoldeath")
self:scriptcall("maps/mp/_utility", "_unsetperk", "specialty_grenadepulldeath")
self:scriptcall("maps/mp/_utility", "_unsetperk", "specialty_armorvest")
end

level:onnotify("connected", function(player)
player:onnotify("spawned_player", function()
player:player_spawned()
end)
end)

"Include" functions

To "include" functions from files like in GSC, you can use the game:include(file) function from the game object.

game:include("maps/mp/_utility")

function entity:player_spawned()
-- Included function names are lowercase
self:_unsetperk("specialty_pistoldeath")
self:_unsetperk("specialty_grenadepulldeath")
self:_unsetperk("specialty_armorvest")
end

level:onnotify("connected", function(player)
player:onnotify("spawned_player", function()
player:player_spawned()
end)
end)

Or, you could use the game:getfunctions(file) function from the game object.

local utility = game:getfunctions("maps/mp/_utility")

function entity:player_spawned()
utility._unsetperk(self, "specialty_pistoldeath")
utility._unsetperk(self, "specialty_grenadepulldeath")
utility._unsetperk(self, "specialty_armorvest")
end

level:onnotify("connected", function(player)
player:onnotify("spawned_player", function()
player:player_spawned()
end)
end)

Functions in variables

Functions in variables, such as structs or arrays, will be automatically converted to a Lua function. The first argument must always be the entity to call the function on.

Hooking (detouring) GSC functions

Same as above, you need to know what a file may be named and what a function may be named.

Detouring a function redirects the function's call to the function callback you provide. The game:detour function is always from the game object. The first parameter of the detour will always be the entity that called it. (as defined self_ in example)

In this example, we will be hooking codecallback_playerkilled and checking who the attacker is.

-- we define a variable so we can use this in our callback function
local playerkilled_hook = nil

-- our callback function for the detour
function playerkilled_stub(self_, einflictor, eattacker, idamage, smeansofdeath, sweapon, vdir, shitloc, timeoffset, deathanimduration)
if eattacker ~= nil or game:isplayer(eattacker) == 1 then
print("The attacker is " .. eattacker.name)
else
print("The attacker is invalid or isn't a player")
end

-- [...]

-- the invoke function will call the original function from the game's stock GSC. we can modify parameters here too!
playerkilled_hook.invoke(self_, einflictor, eattacker, idamage, smeansofdeath, sweapon, vdir, shitloc, timeoffset, deathanimduration)
end

playerkilled_hook = game:detour("maps/mp/gametypes/_callbacksetup", "codecallback_playerkilled", playerkilled_stub)

To disable or enable a detour, the .disable and .enable methods exist.

Incorrect/missing symbols on H1-Mod

This GSC dump may contain symbols that H1-Mod may or may not have named or is not correctly named. Navigating to the function table and finding the function_map, method_map, & token_map maps will help you. CTRL + F (Find) and search your desired value (ex: isplayer) and see if it exists.

If the symbol you are trying to call isn't named, then you have to the _func_<hex> or _meth_<hex> prefix. For example, if isplayer wasn't properly named, then you would refer to the hexdecimal value (0x1AD). You would call this function as game:_func_1AD(player).