lua/caf/core/shared/caf_tools.lua
--
-- Custom Addon Framework TOOLS HAPPY-FUN TIME-SAVER FUNCTIONS
--
if ( SERVER ) then
AddCSLuaFile( "vgui/caf_gui.lua" )
AddCSLuaFile( "vgui/caf_gui_button.lua" )
-- Global list of callbacks
CAF_CallbackFuncs = {}
--DO NOT register this function with the duplication, you MUST wrap this function in another one as to add CheckLimit (ther is a generic function to generate these functions below)
function CAF_MakeCAFEnt( ply, Ang, Pos, system_type, system_class, model, frozen )
local ent = ents.Create( system_class )
if !ent:IsValid() then return false end
ent:SetModel( model )
ent:SetAngles(Ang)
ent:SetPos(Pos)
ent:SetPlayer(ply)
ent:Spawn() --run ENT:Initialize()
local rtable, maxhealth, mass = {}, 0, 0
local SupFunction = list.Get( "CAF_MakeCAFEnt" )[system_class] --supplement function
if (SupFunction) then
--[[ == read me ==
This part allow 3rd party ents to use this function too
Just make a function that takes (ply, ent, system_type, system_class, model) and returns an ent merge table, maxhealth and mass
maxheath is only needed for lsents, set it >1 to use the DamageLS hook on the ent
Your function just needs to do what's done in these ifs (RD_AddResource and/or LS_RegisterEnt)
Register this function like this: list.Set( "LS_MakeRDEnt", system_class, Function )
Example: this would do the air_compressor
local function air_comp(ply, ent, system_class, model)
local rtable = {}
local maxhealth = 600
local mass = 5500 -- return 0 to not set
RD_AddResource(ent, "air", 0)
RD_AddResource(ent, "energy", 0)
return rtable, maxhealth, mass
end
list.Set( "CAF_MakeCAFEnt", "air_compressor", air_comp )
]]--
--Msg("found MakeCAFEntSupFunction for "..system_class.."\n")
local noerror, rt, mh, ma = pcall( SupFunction, ply, ent, system_type, system_class, model )
if (!noerror) then
CAF.WriteToDebugFile("caf_tool_error", "MakeCAFEntSupFunction errored: '"..tostring(rt).."'. Removing.\n")
list.Get( "CAF_MakeCAFEnt" )[system_class] = nil --nuke that shit, someone fucked up
else --saftey
rtable = rt or {}
maxhealth = mh or 0
mass = ma or 0
end
end
if (maxhealth > 0) then
rtable.health = maxhealth
rtable.maxhealth = maxhealth
end
--rtable[system_type] = system_class --this is silly, we don't have to do this, just use "Class" for that arg with the duplicator.
table.Merge(ent:GetTable(), rtable )
if (mass > 0) or (frozen) then
local phys = ent:GetPhysicsObject()
if (phys:IsValid()) then
if (mass > 0) then
phys:SetMass(mass)
phys:Wake()
end
if (frozen) then
phys:EnableMotion( false )
ply:AddFrozenPhysicsObject( ent, phys )
end
end
end
return ent
end
function CAF_GenerateMakeFunction( ToolName )
-- Check to see if we already have a generic function for this tool
if (CAF_CallbackFuncs[ToolName]) then
--Msg('Stool CallBack [Existing] -> '..ToolName..'\n')
return CAF_CallbackFuncs[ToolName]
end
local MakeFunction = function( ply, Ang, Pos, type, model, Frozen )
if not ply:CheckLimit( ToolName ) then return nil end
local ent = CAF_MakeCAFEnt( ply, Ang, Pos, ToolName, type, model, frozen )
if not (ent and ent:IsValid()) then return nil end
ply:AddCount( ToolName, ent )
return ent
end
CAF_CallbackFuncs[ToolName] = MakeFunction
--Msg('\nStool CallBack [Created] -> '..ToolName..'\n')
return MakeFunction
end
function CAF_SetToolMakeFunc( ToolName, EntClass, EntMakeFunct )
if not (ToolName and EntClass) then return end
if (!EntMakeFunct) then
EntMakeFunct = CAF_GenerateMakeFunction( ToolName ) -- Thats checks to see if a function already exists for this tool or it will make a new one
duplicator.RegisterEntityClass( EntClass, EntMakeFunct, "Ang", "Pos", "Class", "model", "frozen" )
else
--Msg('Stool CallBack [Argument] -- '..EntClass..' -> '..tostring(EntMakeFunct)..'\n')
end
list.Set( ToolName.."_Funcs", EntClass, EntMakeFunct )
end
function CAF_AddMakeCAFEntSupFunction( EntClass, MakeCAFEntSupFunction )
if not (EntClass and MakeCAFEntSupFunction) then return end
--Msg('MakeCAFEntSupFunction set for - '..EntClass..' -\n')
list.Set( "CAF_MakeCAFEnt", EntClass, MakeCAFEntSupFunction ) --tell CAF_MakeCAFEnt how to set up this ent
end
end
--CAF_AddStoolItem('cdsweapons', "Heat Gun", 'models/props_junk/TrafficCone001a.mdl', 'gun_heat')
function CAF_AddStoolItem( ToolName, EntPrintName, EntModel, EntClass, EntMakeFunct, MakeCAFEntSupFunction )
if not (ToolName and EntPrintName and EntModel and EntClass) then
--Msg('Error when calling CAF_AddStoolItem -- ToolName: -'..tostring(ToolName)..'- EntPrintName: -'..tostring(EntPrintName)..'- Model: -'..tostring(Model)..'- EntClass: -'..tostring(EntClass)..'-\n')
return
end
list.Set( ToolName.."_Models", EntPrintName, { name = EntPrintName, model = EntModel, type = EntClass } )
util.PrecacheModel( EntModel )
if (SERVER) then
CAF_SetToolMakeFunc( ToolName, EntClass, EntMakeFunct ) --EntMakeFunct should not be in client scope, ever (sloppy)
CAF_AddMakeCAFEntSupFunction( EntClass, MakeCAFEntSupFunction )
end
end
--This fucntion saves your day by setting up 95% of your stool for you with a few vars
--TOOL: toolobj
--Models_List: list of ent info used to make the panel options and do ghosting, each member uses this template: { 'EntPrintName', 'EntModel', 'EntClass' } (only needed if you don't set this someother way)
--MakeFunc: function used to make ents in Models_List (not needed if you set Models_List someother way)
--ToolName: name of the tool (ie. filename) (needed
--ToolLimit: for simple tools that limit all ents it make by this number (ie. all ents made by this tool use the same MakeFunc)
--MakeCAFEntSupFunctionList: list of functions used by MakeCAFEnt to setup an EntClass, list is indexed with EntClass (only needed if you're using MakeCAFEnt to make your ents)
function CAF_ToolRegister( TOOL, Models_List, MakeFunc, ToolName, ToolLimit, MakeCAFEntSupFunctionList)
if (ToolLimit ~= nil and type(ToolLimit) == "number" and ToolLimit >=0) then
local sbox = 'sbox_max'..ToolName
Msg(sbox..' -> '..ToolLimit..'\n')
CreateConVar(sbox, ToolLimit)
end
cleanup.Register(ToolName)
TOOL.ClientConVar['AllowWorldWeld'] = '0'
TOOL.ClientConVar['DontWeld'] = '0'
TOOL.ClientConVar['Frozen'] = '0'
TOOL.ClientConVar['name'] = ''
TOOL.ClientConVar['type'] = ''
TOOL.ClientConVar['model'] = ''
if not (Models_List == nil) then
for k, v in pairs(Models_List) do
CAF_AddStoolItem(ToolName, v[1], v[2], v[3], MakeFunc, v[4]) --v[4] can be a MakeCAFEntSupFunction or nil
end
end
if (SERVER and MakeCAFEntSupFunctionList) then
for EntClass, MakeCAFEntSupFunction in pairs(MakeCAFEntSupFunctionList) do
CAF_AddMakeCAFEntSupFunction( EntClass, MakeCAFEntSupFunction )
end
end
function TOOL:LeftClick( trace )
if trace.Entity and (trace.Entity:IsPlayer() ) then return false end
if(CLIENT) then return true end
return CAF_ToolLeftClick( self, trace, ToolName )
end
function TOOL:RightClick( trace )
if (!trace.Entity:IsValid()) then return false end
if (CLIENT) then return true end
if (not trace.Entity:GetTable().Repair) then
self:GetOwner():SendLua("GAMEMODE:AddNotify('Object cannot be repaired!', NOTIFY_GENERIC, 7); surface.PlaySound(\"ambient/water/drip"..math.random(1, 4)..".wav\")")
return
end
trace.Entity:Repair()
return true
end
if (CLIENT) then
function TOOL.BuildCPanel( cp )
CAF_BuildCPanel( cp, ToolName, ToolName.."_Models", custom )
end
end
function TOOL:Think()
if (CAF_UpdateToolGhost) then CAF_UpdateToolGhost( self ) end
end
function TOOL:Deploy()
if not CAF then
self:GetOwner():PrintMessage( HUD_PRINTCENTER, "Please Install the Custom Addon Framework.\nThis mod requires it to function." )
end
end
end
if ( SERVER ) then
function CAF_ToolLeftClick( tool, trace, ToolName )
local FuncListName = ToolName.."_Funcs"
local ply = tool:GetOwner()
local Pos = trace.HitPos
local Ang = trace.HitNormal:Angle()
Ang.pitch = Ang.pitch + 90
local type = tool:GetClientInfo('type')
local model = tool:GetClientInfo('model')
local AllowWorldWeld = tool:GetClientNumber('AllowWorldWeld') == 1
local DontWeld = tool:GetClientNumber('DontWeld') == 1
local Frozen = (tool:GetClientNumber('Frozen') == 1) or (AllowWorldWeld and not trace.Entity:IsValid())
if (!type or type == '') then
CAF.WriteToDebugFile("caf_tool_error", "CAF: GetClientInfo('type') is nil!\n")
return false
end
local func = list.Get( FuncListName )[type]
if (func == nil) then Error("CAF: Unable to find make function for '"..type.."'\n") end
local ent = func( ply, Ang, Pos, type, model, Frozen)
if (not ent) then return false end
ent:SetPos( trace.HitPos - trace.HitNormal * ent:OBBMins().z)
--CAF.OnEntitySpawn(ent , "SENT" , ply) --Calls the CAF SentSpawn Hook
local const
if (!DontWeld) and ( trace.Entity:IsValid() or AllowWorldWeld ) then
local const = constraint.Weld(ent, trace.Entity,0, trace.PhysicsBone, 0, true ) --add true to turn DOR on
end
undo.Create( ToolName )
undo.AddEntity( ent )
undo.AddEntity( const )
undo.SetPlayer( ply )
undo.Finish()
ply:AddCleanup( ToolName, ent )
return true
end
end
if (game.SinglePlayer() and SERVER) or (!game.SinglePlayer() and CLIENT) then --server side in singleplayer, client side in multiplayer
function CAF_UpdateToolGhost( tool, model, min, GetOffset, offset )
local model = model or tool:GetClientInfo('model')
if (model == '') then return end
if (!tool.GhostEntity or !tool.GhostEntity:IsValid() or tool.GhostEntity:GetModel() ~= model) then
tool:MakeGhostEntity( model, Vector(0,0,0), Angle(0,0,0) )
end
if ( !tool.GhostEntity ) then return end
if ( !tool.GhostEntity:IsValid() ) then return end
local tr = util.GetPlayerTrace( tool:GetOwner(), tool:GetOwner():GetAimVector() )
local trace = util.TraceLine( tr )
if (!trace.Hit) then return end
if ( trace.Entity:IsPlayer() ) then
tool.GhostEntity:SetNoDraw( true )
return
end
local Ang = trace.HitNormal:Angle()
if (!min or min == "z") then
Ang.pitch = Ang.pitch + 90
end
tool.GhostEntity:SetAngles( Ang )
local Pos = trace.HitPos
if (offset) then
Pos = Pos + GetOffset( trace.HitNormal:Angle(), offset )
else
Pos = Pos - trace.HitNormal * tool.GhostEntity:OBBMins()[ min or "z" ]
end
tool.GhostEntity:SetPos( Pos )
tool.GhostEntity:SetNoDraw( false )
end
end