This simple library file simply modifies a few features within the standard Clockwork command library to allow the addition of registering commands on the property menu. Its labeled as a hack because it replaces the standard Clockwork.command:New(name) method so it can edit the metatable manually, so lets hope that doesn't change in the near future. There was no real other way around this. (The property menu is the combobox-like menu that appears when you right click on entities while holding down the context-menu key) Paste this file into a shared library file (ex: schema\libraries\sh_propertycommand.lua)
Code:
local Clockwork = Clockwork;
CMDFILTER_PLAYER = function(player, entity) return (entity:IsPlayer()) end
CMDFILTER_PROP = function(player, entity) return (entity:GetClass() == "prop_physics") end
--[[ Set the __index meta function of the class. --]]
local CLASS_TABLE = {__index = CLASS_TABLE};
-- A function to register a new command.
function CLASS_TABLE:Register()
return Clockwork.command:Register(self, self.name);
end;
function CLASS_TABLE:RegisterProperty(Filter)
return Clockwork.command:RegisterProperty(self, self.name, Filter);
end;
-- A function to get a new command.
function Clockwork.command:New(name)
local object = Clockwork.kernel:NewMetaTable(CLASS_TABLE);
object.name = name or "Unknown";
return object;
end;
-- A function to register a new command for properties.
function Clockwork.command:RegisterProperty(data, name, Filter)
local realName = string.gsub(name, "%s", "");
local uniqueID = string.lower(realName);
if (!self.stored[uniqueID]) then
self.stored[uniqueID] = data;
self.stored[uniqueID].name = realName;
self.stored[uniqueID].text = data.text or "<none>";
self.stored[uniqueID].flags = data.flags or 0;
self.stored[uniqueID].access = data.access or "b";
self.stored[uniqueID].arguments = data.arguments or 0;
if (CLIENT) then
self:AddHelp(self.stored[uniqueID]);
end;
end;
self.stored[uniqueID].pOrder = data.pOrder or 0;
self.stored[uniqueID].pIcon = data.pIcon or nil;
self.stored[uniqueID].pLabel = data.pLabel or data.name;
self.stored[uniqueID].pFilter = Filter
local commandTable = self.stored[uniqueID];
properties.Add(uniqueID, {
MenuLabel = commandTable.pLabel,
Order = commandTable.pOrder,
MenuIcon = commandTable.pIcon,
Filter = function(self, ent, ply)
if (!Clockwork.player:HasFlags(ply, commandTable.access)) then return false end
if (!IsValid(ent)) then return false end
if (!commandTable.pFilter(ply, ent)) then return false end
return true
end,
Action = function( self, ent )
self:MsgStart()
net.WriteEntity( ent )
self:MsgEnd()
end,
Receive = function( self, length, player )
local ent = net.ReadEntity()
if (Clockwork.plugin:Call("PlayerCanUseCommand", player, commandTable, ent)) then
if (Clockwork.player:HasFlags(player, commandTable.access)) then
if (commandTable.OnRun) then
local bSuccess, value = pcall(commandTable.OnRun, commandTable, player, ent);
if (!bSuccess) then
ErrorNoHalt("[Clockwork] The "..commandTable.name.." (PROPERTY USE) command has failed to run.\n");
ErrorNoHalt(value.."\n");
elseif (Clockwork.player:GetDeathCode(player, true)) then
Clockwork.player:UseDeathCode(player, commandTable.name, ent);
end;
if (bSuccess) then
Clockwork.kernel:PrintLog(LOGTYPE_GENERIC, player:Name().." (PROPERTY USE) has used '"..commandTable.name.."'");
return value;
end;
end;
end
end
end
});
return commandTable
end;
We use this library to add a few simple admin commands to the context-menu, but it can really be used with any entity and any command. You can register it to already existing commands, too. The only difference is when someone uses it using the property method, an extra argument will be sent to the commands OnRun function containing the entity object.
![[IMG]](http://4st.me/iO2co.png)
Here's an example of a command that kills a player when you select the option in the menu. This command also has compatibility with typing /plykill <Name> as well!
Code:
local Clockwork = Clockwork;
local COMMAND = Clockwork.command:New("PlyKill");
COMMAND.tip = "Kill a player.";
COMMAND.text = "<string Name>";
COMMAND.flags = CMD_DEFAULT;
COMMAND.access = "o";
-- Called when the command has been run.
function COMMAND:OnRun(player, arguments, entity)
local target = entity or Clockwork.player:FindByID(arguments[1])
if (target:Alive()) then
target:Kill()
Clockwork.player:NotifyAll(player:Name().."has killed " ..target:Name()..".");
else
Clockwork.player:Notify(target, "The target is already dead.");
end
end;
COMMAND.pLabel = "Kill Player"
COMMAND.pIcon = "icon16/bomb.png"
COMMAND:RegisterProperty(CMDFILTER_PLAYER);
As you can see, there's a few simple things added. Firstly the entity argument passed to the command's OnRun method, as well as a few properties.
COMMAND.pLabel is basically the "fancy name" that'll appear on the menu itself, if you don't define this it'll just default to the command name, but it's suggested you add one.
COMMAND.pIcon [OPTIONAL] is a path to the icon that'll appear next to the label on the menu. This is an optional field.
COMMAND.pOrder [OPTIONAL] is an integer order of where it should appear on the menu. This is optional too, otherwise it'll just place it above the last one that's been registered. The higher the number, the more towards-the-bottom the menuitem will be.
Lastly, you'll want to call COMMAND:RegisterProperty(Filter) to register it as a Property command. The function argument is required, and it's the client-side filter function so the properties module knows what entity to display this menu item on. The Filter argument should be a function. I've provided two global convenience functions to check for players, and props. They look like this
Code:
CMDFILTER_PLAYER = function(player, entity) return (entity:IsPlayer()) end
CMDFILTER_PROP = function(player, entity) return (entity:GetClass() == "prop_physics") end
Say you wanted it to only appear on items, you could easily call your register method like so:
Code:
COMMAND:RegisterProperty(function(player, entity)
return (entity:GetClass() == "cw_item")
end);
I hope this is useful to someone! Enjoy!