PDA

View Full Version : Altering functions without overwriting them


squeek.
11-17-2011, 02:11 AM
Usually, when you create a Lua script and you need to alter a function that is defined in an include (the startup() function, for example) you'd have to copy it from the included file and then alter it, so as not to lose any functionality that the include had. This becomes especially bothersome when you need to alter things like baseflag:touch. It also creates a problem if the dev team updates that function in a base Lua, as your map will still have the old code overwriting any changes we made.

There is an alternative to overwriting, though. You can save the old function first, and then call the saved function from inside your new function. For example:


-- save the old function in a variable
startup_base = startup

-- overwrite the function
function startup()
-- check to make sure the saved function is actually a function
if type(startup_base) == "function" then
-- call the saved function
startup_base()
end

-- do whatever it is that you wanted to do
end


There are a few problems, though. One, this isn't useful if you need to alter what the function actually does (for example, if you want to change all capture points to make them play a different sound when a player caps). It is only useful when you want to add to what the function does while keeping the original behavior intact. This first problem I'm not sure how to get around without restructuring FF's base Lua files entirely (which would be a nice thing to do eventually). Two, it is possible that the saved functions can be overwritten by other files (for example, base_ctf saves startup() as base_startup and then ff_mapname.lua saves startup() as base_startup; one of those startup()'s would be lost). This second problem can easily be avoided by, among many other solutions, using a file-specific table to store the saved functions.

This next bit of code shows how to use a table to save the functions and how to save/call nested functions


-- File: /includes/base_test.lua

-- save all the functions in a table with the same name as the Lua file
-- so we don't accidentally overwrite any saved functions in other files
local base_test = {}

--------------------------------------------------------------
-- Example: Saving a global function
--------------------------------------------------------------

-- save the function in the table
base_test.startup = startup

function startup()
-- check to make sure the saved function is actually a function
if type(base_test.startup) == "function" then
-- call the saved function
base_test.startup()
end

-- do something
end

--------------------------------------------------------------
-- Example: Saving a nested function
--------------------------------------------------------------

-- save the function in the table
base_test.genericbackpack = {} -- need to make this a table before adding a key to it, otherwise Lua fails silently for some reason
base_test.genericbackpack.touch = genericbackpack.touch

function genericbackpack:touch( touch_entity )
if type(base_test.genericbackpack.touch) == "function" then
-- call the saved function
base_test.genericbackpack.touch( self, touch_entity )
end

-- do something
end


Hope this helps. By the way, this is most useful in conjunction with sv_globalluascript, which loads the specified Lua file from /maps/globalscripts/<filename>.lua. Importantly, it does this AFTER all the other Lua files are loaded, which guarantees that it will overwrite any functions that were defined in the map's Lua and any of its includes.