295 lines
8.7 KiB
Lua
295 lines
8.7 KiB
Lua
AddCSLuaFile()
|
|
DEFINE_BASECLASS( "base_wire_entity" )
|
|
ENT.PrintName = "Wire Ranger"
|
|
ENT.RenderGroup = RENDERGROUP_BOTH
|
|
ENT.WireDebugName = "Ranger"
|
|
|
|
function ENT:SetupDataTables()
|
|
self:NetworkVar( "Float", 0, "BeamLength" )
|
|
self:NetworkVar( "Bool", 0, "ShowBeam" )
|
|
self:NetworkVar( "Float", 1, "SkewX" )
|
|
self:NetworkVar( "Float", 2, "SkewY" )
|
|
end
|
|
|
|
if CLIENT then return end -- No more client
|
|
|
|
function ENT:Initialize()
|
|
self:PhysicsInit( SOLID_VPHYSICS )
|
|
self:SetMoveType( MOVETYPE_VPHYSICS )
|
|
self:SetSolid( SOLID_VPHYSICS )
|
|
self:StartMotionController()
|
|
|
|
self.Inputs = WireLib.CreateInputs(self, { "X", "Y", "SelectValue","Length"})
|
|
self.Outputs = WireLib.CreateOutputs(self, { "Dist" })
|
|
self.hires = false
|
|
end
|
|
|
|
function ENT:Setup( range, default_zero, show_beam, ignore_world, trace_water, out_dist, out_pos, out_vel, out_ang, out_col, out_val, out_sid, out_uid, out_eid, out_hnrm, hiRes )
|
|
--for duplication
|
|
self.default_zero = default_zero
|
|
self.show_beam = show_beam
|
|
self.ignore_world = ignore_world
|
|
self.trace_water = trace_water
|
|
self.out_dist = out_dist
|
|
self.out_pos = out_pos
|
|
self.out_vel = out_vel
|
|
self.out_ang = out_ang
|
|
self.out_col = out_col
|
|
self.out_val = out_val
|
|
self.out_sid = out_sid
|
|
self.out_uid = out_uid
|
|
self.out_eid = out_eid
|
|
self.out_hnrm = out_hnrm
|
|
self.hires = hiRes
|
|
|
|
self.PrevOutput = nil
|
|
|
|
if range then self:SetBeamLength(math.min(range, 64000)) end
|
|
if show_beam ~= nil then self:SetShowBeam(show_beam) end
|
|
|
|
self:SetNWBool("TraceWater", trace_water)
|
|
|
|
local onames, otypes = {}, {}
|
|
|
|
|
|
local function add(...)
|
|
local args = {...}
|
|
for i=1,#args,2 do
|
|
onames[#onames+1] = args[i]
|
|
otypes[#otypes+1] = args[i+1]
|
|
end
|
|
end
|
|
|
|
|
|
if (out_dist) then add("Dist","NORMAL") end
|
|
if (out_pos) then
|
|
add("Pos", "VECTOR",
|
|
"Pos X", "NORMAL",
|
|
"Pos Y", "NORMAL",
|
|
"Pos Z", "NORMAL")
|
|
end
|
|
if (out_vel) then
|
|
add("Vel","VECTOR",
|
|
"Vel X","NORMAL",
|
|
"Vel Y","NORMAL",
|
|
"Vel Z","NORMAL")
|
|
end
|
|
if (out_ang) then
|
|
add("Ang","ANGLE",
|
|
"Ang Pitch","NORMAL",
|
|
"Ang Yaw","NORMAL",
|
|
"Ang Roll","NORMAL")
|
|
end
|
|
if (out_col) then
|
|
add("Col RGB","VECTOR",
|
|
"Col R","NORMAL",
|
|
"Col G","NORMAL",
|
|
"Col B","NORMAL",
|
|
"Col A","NORMAL")
|
|
end
|
|
if (out_val) then add("Val","NORMAL","ValSize","NORMAL") end
|
|
if (out_sid) then add( "SteamID", "STRING" ) end
|
|
if (out_uid) then add( "UniqueID","NORMAL" ) end
|
|
if (out_eid) then add( "EntID", "NORMAL", "Entity", "ENTITY" ) end
|
|
if (out_hnrm) then
|
|
add("HitNormal","VECTOR",
|
|
"HitNormal X","NORMAL",
|
|
"HitNormal Y","NORMAL",
|
|
"HitNormal Z","NORMAL")
|
|
end
|
|
add( "RangerData", "RANGER" )
|
|
WireLib.AdjustSpecialOutputs(self, onames, otypes)
|
|
|
|
self:TriggerOutput(0, Vector(0, 0, 0), Vector(0, 0, 0), Angle(0, 0, 0), Color(255, 255, 255, 255),nil,0,0,NULL, Vector(0, 0, 0),nil)
|
|
self:ShowOutput(0, Vector(0, 0, 0), Vector(0, 0, 0), Angle(0, 0, 0), Color(255, 255, 255, 255),nil,0,0,NULL, Vector(0, 0, 0),nil)
|
|
end
|
|
|
|
function ENT:TriggerInput(iname, value)
|
|
if (iname == "X") then
|
|
self:SetSkewX(value)
|
|
elseif (iname == "Y") then
|
|
self:SetSkewY(value)
|
|
elseif (iname == "Length") then
|
|
self:SetBeamLength(math.min(value, 64000))
|
|
end
|
|
end
|
|
|
|
function ENT:Think()
|
|
BaseClass.Think(self)
|
|
|
|
local tracedata = {}
|
|
tracedata.start = self:GetPos()
|
|
if (self.Inputs.X.Value == 0 and self.Inputs.Y.Value == 0) then
|
|
tracedata.endpos = tracedata.start + self:GetUp() * self:GetBeamLength()
|
|
else
|
|
local skew = Vector(self.Inputs.X.Value, self.Inputs.Y.Value, 1)
|
|
skew = skew*(self:GetBeamLength()/skew:Length())
|
|
local beam_x = self:GetRight()*skew.x
|
|
local beam_y = self:GetForward()*skew.y
|
|
local beam_z = self:GetUp()*skew.z
|
|
tracedata.endpos = tracedata.start + beam_x + beam_y + beam_z
|
|
end
|
|
tracedata.filter = { self }
|
|
if (self.trace_water) then tracedata.mask = -1 end
|
|
local trace = util.TraceLine(tracedata)
|
|
trace.RealStartPos = tracedata.start
|
|
|
|
local dist = 0
|
|
local pos = Vector(0, 0, 0)
|
|
local vel = Vector(0, 0, 0)
|
|
local ang = Angle(0, 0, 0)
|
|
local col = Color(255, 255, 255, 255)
|
|
local ent = NULL
|
|
local sid = ""
|
|
local uid = 0
|
|
local val = {}
|
|
local hnrm = Vector(0,0,0)
|
|
|
|
if (trace.Hit) then
|
|
dist = trace.Fraction * self:GetBeamLength()
|
|
pos = trace.HitPos
|
|
hnrm = trace.HitNormal
|
|
ent = trace.Entity
|
|
|
|
if (ent:IsValid()) then
|
|
|
|
vel = ent:GetVelocity()
|
|
ang = ent:GetAngles()
|
|
col = ent:GetColor()
|
|
|
|
if (self.out_sid or self.out_uid) and (ent:IsPlayer()) then
|
|
sid = ent:SteamID() or ""
|
|
uid = tonumber(ent:UniqueID()) or -1
|
|
end
|
|
|
|
if (self.out_val and ent.Outputs) then
|
|
local i = 1
|
|
for k,v in pairs(ent.Outputs) do
|
|
if (v.Value != nil and type(v.Value) == "number") then
|
|
val[i] = v.Value
|
|
i = i + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif(self.ignore_world) then
|
|
if (trace.HitWorld) then
|
|
if (self.default_zero) then
|
|
dist = 0
|
|
else
|
|
dist = self:GetBeamLength()
|
|
end
|
|
pos = Vector(0,0,0)
|
|
end
|
|
end
|
|
|
|
else
|
|
if (not self.default_zero) then
|
|
dist = self:GetBeamLength()
|
|
end
|
|
end
|
|
|
|
if (COLOSSAL_SANDBOX) then
|
|
vel = vel * 6.25
|
|
pos = pos * 6.25
|
|
dist = dist * 6.25
|
|
end
|
|
|
|
self:TriggerOutput(dist, pos, vel, ang, col, val, sid, uid, ent, hnrm, trace)
|
|
self:ShowOutput(dist, pos, vel, ang, col, val, sid, uid, ent, hnrm, trace)
|
|
|
|
if (self.hires) then
|
|
self:NextThink(CurTime())
|
|
else
|
|
self:NextThink(CurTime()+0.04)
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
local round = math.Round
|
|
|
|
function ENT:ShowOutput(dist, pos, vel, ang, col, val, sid, uid, ent, hnrm, trace)
|
|
local txt = "Max Range: " .. self:GetBeamLength()
|
|
|
|
if (self.out_dist) then txt = txt .. "\nRange = " .. round(dist,3) end
|
|
if (self.out_pos) then txt = txt .. string.format("\nPosition = %s, %s, %s", round(pos.x,3), round(pos.y,3), round(pos.z,3)) end
|
|
if (self.out_vel) then txt = txt .. string.format("\nVelocity = %s, %s, %s", round(vel.x,3), round(vel.y,3), round(vel.z,3)) end
|
|
if (self.out_ang) then txt = txt .. string.format("\nAngles = %s, %s, %s", round(ang.pitch,3), round(ang.yaw,3), round(ang.roll,3)) end
|
|
if (self.out_col) then txt = txt .. string.format("\nColor = %s, %s, %s, %s", round(col.r), round(col.g), round(col.b), round(col.a)) end
|
|
if (self.out_val) then txt = txt .. string.format("\nValue = %s ValSize = %s", round(self.Outputs["Val"].Value or 0,3), #(val or {}) ) end
|
|
if (self.out_sid) then txt = txt .. "\nSteamID = " .. (sid or "") end
|
|
if (self.out_uid) then txt = txt .. "\nUniqueID = " .. (uid or 0) end
|
|
if (self.out_eid) then txt = txt .. "\nEntID = " .. ent:EntIndex() end
|
|
if (self.out_hnrm) then txt = txt .. string.format("\nHitNormal = %s, %s, %s", round(hnrm.x,3), round(hnrm.y,3), round(hnrm.z,3)) end
|
|
|
|
self:SetOverlayText(txt)
|
|
end
|
|
|
|
function ENT:TriggerOutput(dist, pos, vel, ang, col, val, sid, uid, ent, hnrm, trace)
|
|
|
|
if (self.out_dist) then
|
|
WireLib.TriggerOutput(self, "Dist", dist)
|
|
end
|
|
|
|
if (self.out_pos) then
|
|
WireLib.TriggerOutput(self, "Pos", pos)
|
|
WireLib.TriggerOutput(self, "Pos X", pos.x)
|
|
WireLib.TriggerOutput(self, "Pos Y", pos.y)
|
|
WireLib.TriggerOutput(self, "Pos Z", pos.z)
|
|
end
|
|
|
|
if (self.out_vel) then
|
|
WireLib.TriggerOutput(self, "Vel", vel)
|
|
WireLib.TriggerOutput(self, "Vel X", vel.x)
|
|
WireLib.TriggerOutput(self, "Vel Y", vel.y)
|
|
WireLib.TriggerOutput(self, "Vel Z", vel.z)
|
|
end
|
|
|
|
if (self.out_ang) then
|
|
WireLib.TriggerOutput(self, "Ang", ang)
|
|
WireLib.TriggerOutput(self, "Ang Pitch", ang.p)
|
|
WireLib.TriggerOutput(self, "Ang Yaw", ang.y)
|
|
WireLib.TriggerOutput(self, "Ang Roll", ang.r)
|
|
end
|
|
|
|
if (self.out_col) then
|
|
WireLib.TriggerOutput(self, "Col RGB", Vector(col.r, col.g, col.b))
|
|
WireLib.TriggerOutput(self, "Col R", col.r)
|
|
WireLib.TriggerOutput(self, "Col G", col.g)
|
|
WireLib.TriggerOutput(self, "Col B", col.b)
|
|
WireLib.TriggerOutput(self, "Col A", col.a)
|
|
end
|
|
|
|
if (self.out_sid) then
|
|
WireLib.TriggerOutput(self, "SteamID", sid)
|
|
end
|
|
|
|
if (self.out_uid) then
|
|
WireLib.TriggerOutput(self, "UniqueID", uid)
|
|
end
|
|
|
|
if (self.out_eid) then
|
|
WireLib.TriggerOutput(self, "EntID", ent:EntIndex())
|
|
WireLib.TriggerOutput(self, "Entity", ent)
|
|
end
|
|
|
|
if (self.out_hnrm and hnrm) then
|
|
WireLib.TriggerOutput(self, "HitNormal", hnrm)
|
|
WireLib.TriggerOutput(self, "HitNormal X", hnrm.x)
|
|
WireLib.TriggerOutput(self, "HitNormal Y", hnrm.y)
|
|
WireLib.TriggerOutput(self, "HitNormal Z", hnrm.z)
|
|
end
|
|
|
|
if (val ~= nil and #val > 0 and self.Inputs.SelectValue.Value <= #val) then
|
|
WireLib.TriggerOutput(self, "Val", val[self.Inputs.SelectValue.Value])
|
|
WireLib.TriggerOutput(self, "ValSize", #val)
|
|
else
|
|
WireLib.TriggerOutput(self, "Val", 0)
|
|
WireLib.TriggerOutput(self, "ValSize", 0)
|
|
end
|
|
WireLib.TriggerOutput(self, "RangerData", trace)
|
|
|
|
end
|
|
|
|
duplicator.RegisterEntityClass("gmod_wire_ranger", WireLib.MakeWireEnt, "Data", "range", "default_zero", "show_beam", "ignore_world", "trace_water", "out_dist", "out_pos", "out_vel", "out_ang", "out_col", "out_val", "out_sid", "out_uid", "out_eid", "out_hnrm", "hires")
|