mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
Upload
This commit is contained in:
264
lua/includes/modules/properties.lua
Normal file
264
lua/includes/modules/properties.lua
Normal file
@@ -0,0 +1,264 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
module( "properties", package.seeall )
|
||||
|
||||
local meta = {
|
||||
MsgStart = function( self )
|
||||
|
||||
net.Start( "properties" )
|
||||
net.WriteString( self.InternalName )
|
||||
|
||||
end,
|
||||
|
||||
MsgEnd = function( self )
|
||||
|
||||
net.SendToServer()
|
||||
|
||||
end
|
||||
}
|
||||
|
||||
meta.__index = meta
|
||||
|
||||
List = {}
|
||||
-- .MenuLabel [string] Label to show on opened menu
|
||||
-- .Filter( ent ) [function] Return true if we should show a menu for this entity
|
||||
-- .Action( ent ) [function] On menu choice selected
|
||||
-- .Order [int] The order in which it should be shown on the menu
|
||||
-- .Receive( len, ply ) [function] A message has been received from the clientside version
|
||||
|
||||
function Add( name, tab )
|
||||
|
||||
name = name:lower()
|
||||
tab.InternalName = name
|
||||
setmetatable( tab, meta )
|
||||
|
||||
List[ name ] = tab
|
||||
|
||||
end
|
||||
|
||||
local function AddToggleOption( data, menu, ent, ply, tr )
|
||||
|
||||
if ( !menu.ToggleSpacer ) then
|
||||
menu.ToggleSpacer = menu:AddSpacer()
|
||||
menu.ToggleSpacer:SetZPos( 500 )
|
||||
end
|
||||
|
||||
local option = menu:AddOption( data.MenuLabel, function() data:Action( ent, tr ) end )
|
||||
option:SetChecked( data:Checked( ent, ply ) )
|
||||
option:SetZPos( 501 )
|
||||
return option
|
||||
|
||||
end
|
||||
|
||||
local function AddOption( data, menu, ent, ply, tr )
|
||||
|
||||
if ( data.Type == "toggle" ) then return AddToggleOption( data, menu, ent, ply, tr ) end
|
||||
|
||||
if ( data.PrependSpacer ) then
|
||||
menu:AddSpacer()
|
||||
end
|
||||
|
||||
local option = menu:AddOption( data.MenuLabel, function() data:Action( ent, tr ) end )
|
||||
|
||||
if ( data.MenuIcon ) then
|
||||
option:SetImage( data.MenuIcon )
|
||||
end
|
||||
|
||||
if ( data.MenuOpen ) then
|
||||
data.MenuOpen( data, option, ent, tr )
|
||||
end
|
||||
|
||||
return option
|
||||
|
||||
end
|
||||
|
||||
function OpenEntityMenu( ent, tr )
|
||||
|
||||
local menu = DermaMenu()
|
||||
|
||||
for k, v in SortedPairsByMemberValue( List, "Order" ) do
|
||||
|
||||
if ( !v.Filter ) then continue end
|
||||
if ( !v:Filter( ent, LocalPlayer() ) ) then continue end
|
||||
|
||||
local option = AddOption( v, menu, ent, LocalPlayer(), tr )
|
||||
|
||||
if ( v.OnCreate ) then v:OnCreate( menu, option ) end
|
||||
|
||||
end
|
||||
|
||||
menu:Open()
|
||||
|
||||
end
|
||||
|
||||
function OnScreenClick( eyepos, eyevec )
|
||||
|
||||
local ent, tr = GetHovered( eyepos, eyevec )
|
||||
if ( !IsValid( ent ) ) then return end
|
||||
|
||||
OpenEntityMenu( ent, tr )
|
||||
|
||||
end
|
||||
|
||||
-- Use this check in your properties to see if given entity can be affected by it
|
||||
-- Ideally this should be done automatically for you, but due to how this system was set up, its now impossible
|
||||
function CanBeTargeted( ent, ply )
|
||||
if ( !IsValid( ent ) ) then return false end
|
||||
if ( ent:IsPlayer() ) then return false end
|
||||
|
||||
-- Check the range if player object is given
|
||||
-- This is not perfect, but it is close enough and its definitely better than nothing
|
||||
if ( IsValid( ply ) ) then
|
||||
local mins = ent:OBBMins()
|
||||
local maxs = ent:OBBMaxs()
|
||||
local maxRange = math.max( math.abs( mins.x ) + maxs.x, math.abs( mins.y ) + maxs.y, math.abs( mins.z ) + maxs.z )
|
||||
local pos = ent:LocalToWorld( ent:OBBCenter() ) --ent:GetPos()
|
||||
|
||||
if ( pos:Distance( ply:GetShootPos() ) > maxRange + 1024 ) then return false end
|
||||
end
|
||||
|
||||
return !( ent:GetPhysicsObjectCount() < 1 && ent:GetSolid() == SOLID_NONE && bit.band( ent:GetSolidFlags(), FSOLID_USE_TRIGGER_BOUNDS ) == 0 && bit.band( ent:GetSolidFlags(), FSOLID_CUSTOMRAYTEST ) == 0 )
|
||||
end
|
||||
|
||||
function GetHovered( eyepos, eyevec )
|
||||
|
||||
local ply = LocalPlayer()
|
||||
local filter = ply:GetViewEntity()
|
||||
|
||||
if ( filter == ply ) then
|
||||
local veh = ply:GetVehicle()
|
||||
|
||||
if ( veh:IsValid() && ( !veh:IsVehicle() || !veh:GetThirdPersonMode() ) ) then
|
||||
-- A dirty hack for prop_vehicle_crane. util.TraceLine returns the vehicle but it hits phys_bone_follower - something that needs looking into
|
||||
filter = { filter, veh, unpack( ents.FindByClass( "phys_bone_follower" ) ) }
|
||||
end
|
||||
end
|
||||
|
||||
local trace = util.TraceLine( {
|
||||
start = eyepos,
|
||||
endpos = eyepos + eyevec * 1024,
|
||||
filter = filter
|
||||
} )
|
||||
|
||||
-- Hit COLLISION_GROUP_DEBRIS and stuff
|
||||
if ( !trace.Hit || !IsValid( trace.Entity ) ) then
|
||||
trace = util.TraceLine( {
|
||||
start = eyepos,
|
||||
endpos = eyepos + eyevec * 1024,
|
||||
filter = filter,
|
||||
mask = MASK_ALL
|
||||
} )
|
||||
end
|
||||
|
||||
if ( !trace.Hit || !IsValid( trace.Entity ) ) then return end
|
||||
|
||||
return trace.Entity, trace
|
||||
|
||||
end
|
||||
|
||||
-- Receives commands from clients
|
||||
if ( SERVER ) then
|
||||
|
||||
util.AddNetworkString( "properties" )
|
||||
|
||||
net.Receive( "properties", function( len, client )
|
||||
if ( !IsValid( client ) ) then return end
|
||||
|
||||
local name = net.ReadString()
|
||||
if ( !name ) then return end
|
||||
|
||||
local prop = List[ name ]
|
||||
if ( !prop ) then return end
|
||||
if ( !prop.Receive ) then return end
|
||||
|
||||
prop:Receive( len, client )
|
||||
|
||||
end )
|
||||
|
||||
end
|
||||
|
||||
if ( CLIENT ) then
|
||||
|
||||
local lastEyePos = vector_origin
|
||||
local function UpdateEyePos()
|
||||
-- A bit of a hack due to EyePos() being affected by other rendering functions
|
||||
-- So we cache the value when we know it is the correct value for the frame
|
||||
lastEyePos = EyePos()
|
||||
end
|
||||
|
||||
hook.Add( "PreDrawHalos", "PropertiesHover", function()
|
||||
|
||||
if ( !IsValid( vgui.GetHoveredPanel() ) || !vgui.GetHoveredPanel():IsWorldClicker() ) then return end
|
||||
|
||||
UpdateEyePos()
|
||||
|
||||
local ent = GetHovered( lastEyePos, LocalPlayer():GetAimVector() )
|
||||
if ( !IsValid( ent ) ) then return end
|
||||
|
||||
local c = Color( 255, 255, 255, 255 )
|
||||
c.r = 200 + math.sin( RealTime() * 50 ) * 55
|
||||
c.g = 200 + math.sin( RealTime() * 20 ) * 55
|
||||
c.b = 200 + math.cos( RealTime() * 60 ) * 55
|
||||
|
||||
local t = { ent }
|
||||
if ( ent.GetActiveWeapon && IsValid( ent:GetActiveWeapon() ) ) then table.insert( t, ent:GetActiveWeapon() ) end
|
||||
halo.Add( t, c, 2, 2, 2, true, false )
|
||||
|
||||
end )
|
||||
|
||||
hook.Add( "PreDrawEffects", "PropertiesUpdateEyePos", function()
|
||||
UpdateEyePos()
|
||||
end )
|
||||
|
||||
hook.Add( "GUIMousePressed", "PropertiesClick", function( code, vector )
|
||||
|
||||
if ( !IsValid( vgui.GetHoveredPanel() ) || !vgui.GetHoveredPanel():IsWorldClicker() ) then return end
|
||||
|
||||
if ( code == MOUSE_RIGHT && !input.IsButtonDown( MOUSE_LEFT ) ) then
|
||||
OnScreenClick( lastEyePos, vector )
|
||||
end
|
||||
|
||||
end )
|
||||
|
||||
local wasPressed = false
|
||||
hook.Add( "PreventScreenClicks", "PropertiesPreventClicks", function()
|
||||
|
||||
if ( !input.IsButtonDown( MOUSE_RIGHT ) ) then wasPressed = false end
|
||||
|
||||
if ( wasPressed && input.IsButtonDown( MOUSE_RIGHT ) && !input.IsButtonDown( MOUSE_LEFT ) ) then return true end
|
||||
|
||||
if ( !IsValid( vgui.GetHoveredPanel() ) || !vgui.GetHoveredPanel():IsWorldClicker() ) then return end
|
||||
|
||||
local ply = LocalPlayer()
|
||||
if ( !IsValid( ply ) ) then return end
|
||||
|
||||
--
|
||||
-- Are we pressing the right mouse button?
|
||||
-- (We check whether we're pressing the left too, to allow for physgun freezes)
|
||||
--
|
||||
if ( input.IsButtonDown( MOUSE_RIGHT ) && !input.IsButtonDown( MOUSE_LEFT ) ) then
|
||||
|
||||
--
|
||||
-- Are we hovering an entity? If so, then stomp the action
|
||||
--
|
||||
local hovered = GetHovered( lastEyePos, ply:GetAimVector() )
|
||||
|
||||
if ( IsValid( hovered ) ) then
|
||||
wasPressed = true
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end )
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user