dobrograd-13-06-2022/garrysmod/addons/feature-wire/lua/wire/stools/gates.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

324 lines
9 KiB
Lua

-- Made by Divran 06/01/2012
WireToolSetup.setCategory( "Chips, Gates" )
WireToolSetup.open( "gates", "Gates", "gmod_wire_gate", nil, "Gates" )
WireToolSetup.SetupMax(100)
if SERVER then
ModelPlug_Register("gate")
end
if CLIENT then
----------------------------------------------------------------------------------------------------
-- Tool Info
----------------------------------------------------------------------------------------------------
language.Add( "Tool.wire_gates.name", "Gates Tool (Wire)" )
language.Add( "Tool.wire_gates.desc", "Spawns gates for use with the wire system." )
TOOL.ClientConVar["model"] = "models/jaanus/wiretool/wiretool_gate.mdl"
TOOL.ClientConVar["parent"] = 0
TOOL.ClientConVar["noclip"] = 1
TOOL.ClientConVar["angleoffset"] = 0
TOOL.ClientConVar["action"] = "+"
TOOL.ClientConVar["searchresultnum"] = 28
language.Add( "WireGatesTool_action", "Gate action" )
language.Add( "WireGatesTool_noclip", "NoCollide" )
language.Add( "WireGatesTool_parent", "Parent" )
language.Add( "WireGatesTool_angleoffset", "Spawn angle offset" )
language.Add( "sboxlimit_wire_gates", "You've hit your gates limit!" )
WireToolSetup.setToolMenuIcon( "bull/gates/gate_logic_and" )
TOOL.Information = {
{ name = "left", text = "Create/Update Gate" },
{ name = "right", text = "Copy Gate" },
{ name = "reload", text = "Increase angle offset by 45 degrees" },
{ name = "reload_shift", text = "Shift+Reload: Unparent gate (If parented)" },
}
function TOOL.BuildCPanel( panel )
----------------- GATE SELECTION & SEARCHING
-- Create panels
local searchbox = vgui.Create( "DTextEntry" )
searchbox:SetValue( "Search..." )
local oldOnGetFocus = searchbox.OnGetFocus
function searchbox:OnGetFocus()
if self:GetValue() == "Search..." then -- If "Search...", erase it
self:SetValue( "" )
end
oldOnGetFocus( self )
end
-- On lose focus
local oldOnLoseFocus = searchbox.OnLoseFocus
function searchbox:OnLoseFocus()
if self:GetValue() == "" then -- if empty, reset "Search..." text
timer.Simple( 0, function() self:SetValue( "Search..." ) end )
end
oldOnLoseFocus( self )
end
local holder = vgui.Create( "DPanel" )
holder:SetTall( 500 )
local tree = vgui.Create( "DTree", holder )
local searchlist = vgui.Create( "DListView", holder )
searchlist:AddColumn( "Gate Name" )
searchlist:AddColumn( "Category" )
local string_find = string.find
local table_SortByMember = table.SortByMember
local string_lower = string.lower
-- Searching algorithm
local function Search( text )
text = string_lower(text)
local results = {}
for action,gate in pairs( GateActions ) do
local name = gate.name
local lowname = string_lower(name)
if string_find( lowname, text, 1, true ) then -- If it has ANY match at all
results[#results+1] = { name = gate.name, group = gate.group, action = action, dist = WireLib.levenshtein( text, lowname ) }
end
end
table_SortByMember( results, "dist", true )
return results
end
-- Main searching
local searching
function searchbox:OnTextChanged()
local text = searchbox:GetValue()
if text ~= "" then
if not searching then
searching = true
local x,y = tree:GetPos()
local w,h = tree:GetSize()
searchlist:SetPos( x + w, y )
searchlist:MoveTo( x, y, 0.1, 0, 1 )
searchlist:SetSize( w, h )
searchlist:SetVisible( true )
end
local results = Search( text )
searchlist:Clear()
for i=1,#results do
local result = results[i]
local line = searchlist:AddLine( result.name, result.group )
local action = GetConVarString("wire_gates_action")
if action == result.action then
line:SetSelected( true )
end
line.action = result.action
end
else
if searching then
searching = false
local x,y = tree:GetPos()
local w,h = tree:GetSize()
searchlist:SetPos( x, y )
searchlist:MoveTo( x + w, y, 0.1, 0, 1 )
searchlist:SetSize( w, h )
timer.Create( "wire_customspawnmenu_hidesearchlist", 0.1, 1, function()
if IsValid( searchlist ) then
searchlist:SetVisible( false )
end
end )
end
searchlist:Clear()
end
end
function searchlist:OnClickLine( line )
-- Deselect old
local t = searchlist:GetSelected()
if t and next(t) then
t[1]:SetSelected(false)
end
line:SetSelected(true) -- Select new
RunConsoleCommand( "wire_gates_action", line.action )
end
function searchbox:OnEnter()
if #searchlist:GetLines() > 0 then
searchlist:OnClickLine( searchlist:GetLine( 1 ) )
end
end
panel:AddItem( searchbox )
tree:Dock( FILL )
-- Set sizes & other settings
searchlist:SetVisible( false )
searchlist:SetMultiSelect( false )
local function FillSubTree( tree, node, temp )
node.Icon:SetImage( "icon16/folder.png" )
local subtree = {}
for k,v in pairs( temp ) do
subtree[#subtree+1] = { action = k, gate = v, name = v.name }
end
table_SortByMember(subtree, "name", true )
for index=1, #subtree do
local action, gate = subtree[index].action, subtree[index].gate
local node2 = node:AddNode( gate.name or "No name found :(" )
node2.name = gate.name
node2.action = action
function node2:DoClick()
RunConsoleCommand( "wire_gates_Action", self.action )
end
node2.Icon:SetImage( "icon16/newspaper.png" )
end
tree:InvalidateLayout()
end
local CategoriesSorted = {}
for gatetype, gatefuncs in pairs( WireGatesSorted ) do
local allowed_gates = {}
local any_allowed = false
for k,v in pairs(gatefuncs) do
if not v.is_banned then
allowed_gates[k] = v
any_allowed = true
end
end
if any_allowed then
CategoriesSorted[#CategoriesSorted+1] = { gatetype = gatetype, gatefuncs = allowed_gates }
end
end
table.sort( CategoriesSorted, function( a, b ) return a.gatetype < b.gatetype end )
for i=1,#CategoriesSorted do
local gatetype = CategoriesSorted[i].gatetype
local gatefuncs = CategoriesSorted[i].gatefuncs
local node = tree:AddNode( gatetype )
node.Icon:SetImage( "icon16/folder.png" )
FillSubTree( tree, node, gatefuncs )
function node:DoClick()
self:SetExpanded( not self.m_bExpanded )
end
end
-- add it all to the main panel
panel:AddItem( holder )
-- MISCELLANEOUS PLACEMENT OPTIONS, AND MODEL
local nocollidebox = panel:CheckBox("#WireGatesTool_noclip", "wire_gates_noclip")
local parentbox = panel:CheckBox("#WireGatesTool_parent","wire_gates_parent")
panel:Help("When parenting, you should check the nocollide box, or adv duplicator might not dupe the gate.")
panel:NumSlider( "#WireGatesTool_angleoffset","wire_gates_angleoffset", 0, 360, 0 )
WireDermaExts.ModelSelect(panel, "wire_gates_model", list.Get("Wire_gate_Models"), 3, true)
function nocollidebox.Button:DoClick()
self:Toggle()
end
function parentbox.Button:DoClick() -- when you check the parent box, check the nocollide box
self:Toggle()
if (self:GetChecked() == true) then
nocollidebox:SetValue(1)
end
end
end
end
WireToolSetup.BaseLang()
if SERVER then
function TOOL:GetConVars()
return self:GetClientInfo( "action" ), self:GetClientNumber( "noclip" ) == 1
end
function TOOL:MakeEnt( ply, model, Ang, trace )
return WireLib.MakeWireGate( ply, trace.HitPos, Ang, model, self:GetConVars() )
end
end
--------------------
-- RightClick
-- Copy gate
--------------------
function TOOL:RightClick( trace )
if CLIENT then return true end
if self:CheckHitOwnClass(trace) then
local action = GateActions[trace.Entity.action]
assert(action, "Attempted to copy gate " .. tostring(trace.Entity) .. " with no action!")
self:GetOwner():ConCommand( "wire_gates_action " .. trace.Entity.action )
self:GetOwner():ChatPrint( "Gate copied ('" .. action.name .. "')." )
return true
else
return false
end
end
--------------------
-- Reload
-- Increase angle offset by 45 degrees
--------------------
function TOOL:Reload( trace )
if self:GetOwner():KeyDown( IN_SPEED ) then -- Unparent
if not trace or not trace.Hit then return false end
if (CLIENT and trace.Entity) then return true end
if (trace.Entity:GetParent():IsValid()) then
-- Get its position
local pos = trace.Entity:GetPos()
-- Unparent
trace.Entity:SetParent()
-- Teleport it back to where it was before unparenting it (because unparenting causes issues which makes the gate teleport to random wierd places)
trace.Entity:SetPos( pos )
-- Wake
local phys = trace.Entity:GetPhysicsObject()
if (phys) then
phys:Wake()
end
-- Notify
self:GetOwner():ChatPrint("Entity unparented.")
return true
end
return false
else
if game.SinglePlayer() and SERVER then
self:GetOwner():ConCommand( "wire_gates_angleoffset " .. (self:GetClientNumber( "angleoffset" ) + 45) % 360 )
elseif CLIENT then
RunConsoleCommand( "wire_gates_angleoffset", (self:GetClientNumber( "angleoffset" ) + 45) % 360 )
end
end
return false
end
function TOOL:GetAngle( trace )
local ang = WireToolObj.GetAngle(self, trace)
ang:RotateAroundAxis( trace.HitNormal, self:GetClientNumber( "angleoffset" ) )
return ang
end