Issue 439: Plugin Menu/Tutorial
Status:  New
Owner: ----
Reported by Steven.W...@gmail.com, Apr 14, 2012
I heard the sad news that evolve was going to die soon and would like to see either a plugin construction menu added for creating our own plugins or making some sort of tutorial on the basics of making a plugin for evolve I think if more people knew how to make plugins the popularity would skyrocket
Apr 19, 2012
#1 DilanoDr...@gmail.com
This is from evolve.overvprojects.nl

Plugin name

You start creating a new plugin by creating a new Lua file in addons/evolve/lua/ev_plugins/. The name should look like one of these:

sv_pluginname.lua
cl_pluginname.lua
sh_pluginname.lua

The first two letters are quite important. They define in which environments your plugin will run. sv means your plugin will only run serverside, cl only clientside and sh means your plugin will be both ran on the server and sent to clients.

Basic plugin layout

Plugins will always start with the following:

/*------------------------------------------------------------------------------------------------
	Plugin description
------------------------------------------------------------------------------------------------*/

local PLUGIN = {}
PLUGIN.Title = "Plugin name"
PLUGIN.Description = "Plugin description"
PLUGIN.Author = "Your name"
PLUGIN.ChatCommand = "The chat command"
PLUGIN.Usage = "The expected arguments"
PLUGIN.Privileges = { "The privileges this plugin uses" }

function PLUGIN:Call( ply, args )
	
end

evolve:RegisterPlugin( PLUGIN )

The first few lines define the properties of the plugin, such as the name and the expected arguments when it has a chat command. Plugins don't need to have a chat command, but most do. If you write a plugin that for example just displays something on the HUD, you don't need a chat command and you can simply leave out PLUGIN.ChatCommand, PLUGIN.Usage and the whole PLUGIN.Call function. The privileges specified in PLUGIN.Privileges will automatically be added to the rank menu.

Doing stuff

Now, how would you go about creating a plugin that just kills everyone you've specified? Evolve provides a few useful functions, like evolve:FindPlayer and ply:EV_HasPrivilege. Of course, we first check if the player is allowed to run the command. We do that this way:

if ( ply:EV_HasPrivilege( "Kill privilege" ) ) then

end

If the player doesn't have the required privilege, we want to tell them they don't, just like the official plugins do. Evolve provides three things that will help us do that, evolve:Notify, evolve.colors.red and evolve.constants.notallowed:

if ( ply:EV_HasPrivilege( "Kill privilege" ) ) then

else
	evolve:Notify( ply, evolve.colors.red, evolve.constants.notallowed )
end

As of the latest revision, this will print in red "No matching players found." Now, when the player is allowed to run the command, we first need to check if we found any players based on the arguments. Evolve provides evolve:FindPlayer for that:

local players = evolve:FindPlayer( args, ply )

The player using the plugin is specified for two reasons here. The first is that it automatically checks if the specified players have a lower than or equal immunity as the calling player and if no players were specified, it will automatically target the calling player! That's how !slay slays yourself when you pass no players.

After that, it's quite trivial what to do:

if ( #players == 0 ) then
	evolve:Notify( ply, evolve.colors.red, evolve.noplayers )
	return
else
	for _, pl in ipairs( players ) do
		pl:Kill()
	end
end

However, we're missing something! All of the official plugins show a nice message like "X slayed Y and Z." How do we do that? It's simple with evolve:CreatePlayerList!

evolve:Notify( evolve.colors.blue, ply:Nick(), evolve.colors.white, " has killed ", evolve.colors.red, evolve:CreatePlayerList( players ), evolve.colors.white, "." )

Registering your plugin

After you've created your plugin, it would be nice if Evolve actually loads it. You do that by calling evolve:RegisterPlugin( PLUGIN ). When you think more users would like the functionality your plugin provides, you can submit it to the plugins page!
Adding your plugin to the menu

Adding your plugin to the menu is easy. All you have to do is provide a PLUGIN:Menu function, like so:

function PLUGIN:Menu( arg, players )
	if ( arg ) then
		RunConsoleCommand( "ev", "kill", unpack( players ) )
	else
		return "Kill", evolve.category.punishment
	end
end

arg holds the argument that the player picked in the menu out of the ones you specified. You can add arguments this way:

return "Kill", evolve.category.punishment, { "Drop container", "Drown", "Burn" }

The argument the player picked will be passed as arg, otherwise it will be nil. If you want the names in the menu to differ from the actual value passed, like with the speed plugin, you'd do this:

return "Kill", evolve.category.punishment, { { "Drop container", "method1" }, { "Drown", "method2" }, { "Burn", "method3" } }

Then "method1" would be passed as arg when the user selected "Drop container".

Using hooks in plugins

Of course, far from all plugins only do something when they're called using their command. That's why hooks were invented. You might initially do something like:

hook.Add( "PlayerSpawn", "MyPluginHook", function( ply )
	PLUGIN:TellPlayerTheyHaveSpawned( ply )
end )

But with Evolve's plugin system, we can do better!

function PLUGIN:PlayerSpawn( ply )
		evolve:Notify( ply, evolve.colors.white, "You've spawned!" )
end

This works with every hook, even custom ones found in some gamemodes! They'll even run before all else, so if you want, you can override gamemode functionality. 
Apr 20, 2012
#2 Steven.W...@gmail.com
Thank you for posting the information. :) I'm a bit confused over reading it right now but it's just a lot of trial and error I'm sure. And I'm sure it will help others who read it who may know more than me to make some truly amazing plugins to share :D