Super Wire Mod

I’m all up for a new wiremod. I’m sick and tired of having the wire keyboard run a console command every other frame even when it isn’t on the map at all >_>

Fair point.

It does that already. The buttons are just fancy-painted VGUI inside a DPanelList.

I will hopefully comment every basic thing for a beginner to start wiremodding.

A new wired keyboard could easily be done by hooking onto the gamemode’s KeyPressed instead of concommands.

Edit: Nevermind, KeyPressed is for IN_'s only. I guess you could datastream :stuck_out_tongue:
Ooh, that gave me an idea. I’ll convert all my usermessages into datastreams. I feel that is easier to handle then making a bunch of overcomplicated tables and then converting them into strings and then sending them over to the client and finally to have them slowly parse it.

Here’s the indicator made with SuperWiremod:
[lua]AddCSLuaFile( “cl_init.lua” )
AddCSLuaFile( “shared.lua” )
include(‘shared.lua’)

function ENT:WireInit()
self.Entity:CreateInput(“Switch”)
self.Entity:HookFunction(“Switch”,ChangeColor)
end

function ChangeColor(ent,arg)
if arg then
ent:SetColor(0,255,0,255)
else
ent:SetColor(255,255,255,255)
end
end
[/lua]

Here is normal Wire:
[lua]
AddCSLuaFile( “cl_init.lua” )
AddCSLuaFile( “shared.lua” )

include(‘shared.lua’)

ENT.WireDebugName = “Indicator”

function ENT:Initialize()
self.Entity:PhysicsInit( SOLID_VPHYSICS )
self.Entity:SetMoveType( MOVETYPE_VPHYSICS )
self.Entity:SetSolid( SOLID_VPHYSICS )

self.a = 0
self.ar = 0
self.ag = 0
self.ab = 0
self.aa = 0
self.b = 0
self.br = 0
self.bg = 0
self.bb = 0
self.ba = 0

self.Inputs = Wire_CreateInputs(self.Entity, { "A" })

end

function ENT:Setup(a, ar, ag, ab, aa, b, br, bg, bb, ba)
self.a = a or 0
self.ar = ar or 255
self.ag = ag or 0
self.ab = ab or 0
self.aa = aa or 255
self.b = b or 1
self.br = br or 0
self.bg = bg or 255
self.bb = bb or 0
self.ba = ba or 255

local factor = math.max(0, math.min(self.Inputs.A.Value-self.a/(self.b-self.a), 1))
self:TriggerInput("A", 0)

end

function ENT:TriggerInput(iname, value)
if (iname == “A”) then
local factor = math.Clamp((value-self.a)/(self.b-self.a), 0, 1)
self:ShowOutput(factor)

	local r = math.Clamp((self.br-self.ar)*factor+self.ar, 0, 255)
	local g = math.Clamp((self.bg-self.ag)*factor+self.ag, 0, 255)
	local b = math.Clamp((self.bb-self.ab)*factor+self.ab, 0, 255)
	local a = math.Clamp((self.ba-self.aa)*factor+self.aa, 0, 255)
	self.Entity:SetColor(r, g, b, a)
end

end

function ENT:ShowOutput(value)
if (value ~= self.PrevOutput) then
self:SetOverlayText( “Color = " … string.format(”%.1f", (value * 100)) … “%” )
self.PrevOutput = value
end
end

function MakeWireIndicator( pl, Model, Ang, Pos, a, ar, ag, ab, aa, b, br, bg, bb, ba, material, nocollide, Vel, aVel, frozen )
if ( !pl:CheckLimit( “wire_indicators” ) ) then return false end

local wire_indicator = ents.Create( "gmod_wire_indicator" )
if (!wire_indicator:IsValid()) then return false end

wire_indicator:SetModel( Model )
wire_indicator:SetMaterial( material )
wire_indicator:SetAngles( Ang )
wire_indicator:SetPos( Pos )
wire_indicator:Spawn()

wire_indicator:Setup(a, ar, ag, ab, aa, b, br, bg, bb, ba)
wire_indicator:SetPlayer(pl)

if wire_indicator:GetPhysicsObject():IsValid() then
	wire_indicator:GetPhysicsObject():EnableMotion(!frozen)
end
if nocollide == true then 
	wire_indicator:SetCollisionGroup(COLLISION_GROUP_WORLD)
end

local ttable = {
	material = material,
	pl	= pl,
	nocollide = nocollide
}
table.Merge(wire_indicator:GetTable(), ttable )

pl:AddCount( "wire_indicators", wire_indicator )

return wire_indicator

end

duplicator.RegisterEntityClass(“gmod_wire_indicator”, MakeWireIndicator, “Model”, “Ang”, “Pos”, “a”, “ar”, “ag”, “ab”, “aa”, “b”, “br”, “bg”, “bb”, “ba”, “material”, “nocollide”, “Vel”, “aVel”, “frozen”)

function MakeWire7Seg( pl, Model, Ang, Pos, Norm, a, ar, ag, ab, aa, b, br, bg, bb, ba, nocollide, Vel, aVel, frozen )

if ( !pl:CheckLimit( "wire_indicators" ) ) then return false end

local wire_indicators = {}

//make the center one first so we can get use its OBBMins/OBBMaxs
wire_indicators[1] = ents.Create( "gmod_wire_indicator" )
if (!wire_indicators[1]:IsValid()) then return false end
wire_indicators[1]:SetModel( Model )
wire_indicators[1]:SetAngles( Ang + Angle(90, 0, 0) )
wire_indicators[1]:SetPos( Pos )
wire_indicators[1]:Spawn()
wire_indicators[1]:Setup(a, ar, ag, ab, aa, b, br, bg, bb, ba)
wire_indicators[1]:SetPlayer(pl)
wire_indicators[1]:SetNetworkedString("WireName", "G")
pl:AddCount( "wire_indicators", wire_indicators[1] )
local min = wire_indicators[1]:OBBMins(wire_indicators[1])
Pos = Pos - Norm * min.x //correct Pos for thichness of segment
wire_indicators[1]:SetPos( Pos + Ang:Up() )

if wire_indicators[1]:GetPhysicsObject():IsValid() then
	wire_indicators[1]:GetPhysicsObject():EnableMotion(!frozen)
end
if nocollide == true then 
	wire_indicators[1]:SetCollisionGroup(COLLISION_GROUP_WORLD)
end
	
local ttable = {
	pl	= pl,
	nocollide = nocollide
}
table.Merge(wire_indicators[1]:GetTable(), ttable )

local max = wire_indicators[1]:OBBMaxs(wire_indicators[1])

local angles = {Angle( 90, 0, 90 ), Angle( 90, 0, 90 ), Angle( 90, 0, 90 ), Angle( 90, 0, 90 ), Angle( 90, 0, 0 ), Angle( 90, 0, 0 )}
local vectors = {Vector( 1, (-1 * max.y), max.y ), Vector( 1, (-1 * max.y), (-1 * max.y) ), Vector( 1, max.y, max.y ), Vector( 1, max.y, (-1 * max.y) ), Vector( 1, 0, (2 * max.y) ), Vector( 1, 0, (-2 * max.y) ) }
local segname = {"B", "C", "F", "E", "A", "D"}

for x=2, 7 do
	wire_indicators[x] = ents.Create( "gmod_wire_indicator" )
	if (!wire_indicators[x]:IsValid()) then return false end
	wire_indicators[x]:SetModel( Model )
	wire_indicators[x]:SetPos( Pos + Ang:Up() * vectors[x-1].X + Ang:Forward() * -1 * vectors[x-1].Z + Ang:Right() * vectors[x-1].Y )
	wire_indicators[x]:SetAngles( Ang + angles[x-1] )
	wire_indicators[x]:Spawn()
	wire_indicators[x]:Setup(cmin, ar, ag, ab, aa, cmax, br, bg, bb, ba)
	wire_indicators[x]:SetPlayer(pl)
	wire_indicators[x]:SetNetworkedString("WireName", segname[x-1])
	if wire_indicators[x]:GetPhysicsObject():IsValid() then
		wire_indicators[x]:GetPhysicsObject():EnableMotion(!frozen)
	end
	if nocollide == true then 
		wire_indicators[x]:SetCollisionGroup(COLLISION_GROUP_WORLD)
	end
	table.Merge(wire_indicators[x]:GetTable(), ttable )
	pl:AddCount( "wire_indicators", wire_indicators[x] )
	
	//weld this segment to eveyone before it
	for y=1,x do
		const = constraint.Weld( wire_indicators[x], wire_indicators[y], 0, 0, 0, true, true )
	end
	wire_indicators[x-1]:DeleteOnRemove( wire_indicators[x] ) //when one is removed, all are. a linked chain
end
wire_indicators[7]:DeleteOnRemove( wire_indicators[1] ) //loops chain back to first

return wire_indicators

end

[/lua]

Wait what.

Oh that is just nothing except me explaining how easy it is to bind lua to source.

The hard part is the order in running Lua files. It’s off topic, though.

I would download this for that wiring tool :stuck_out_tongue:

We’ll talk privately about it later BoingBoing, it’s not my wish to derail your thread.

Anywho, brilliant coding BoingBoing.

One of my major problems with Wiremod is how DISGUSTING their coding is. I’m sorry, but even my OCD gets a boner looking at that pile of crap.

Where is the “?” rating when you need one.

If you don’t understand, then ask, or be quiet?

I must say that i am looking forward to this, the current wiremod just has to much shit in it.

I just realized that most people don’t want to use a base entity for wires, so I made a little function that hooks onto the entity.

Functions have longer names, but are more efficient and can applied to any entity, even SWEPs! Except it won’t do shit with SWEPs.

init.lua:
[lua]AddCSLuaFile( “cl_init.lua” )
AddCSLuaFile( “shared.lua” )
include(‘shared.lua’)

function ENT:Initialize()
swire.RegisterEntity(self)
self.SuperWire:CreateInput(“Switch”)
self.SuperWire:HookFunction(“Switch”,ChangeColor)
end

function ChangeColor(ent,arg)
if arg then
ent:SetColor(0,255,0,255)
else
ent:SetColor(255,255,255,255)
end
end
[/lua]

shared.lua:
[lua]ENT.Type = “anim”
ENT.Base = “base_gmod”

ENT.PrintName = “”
ENT.Author = “”
ENT.Contact = “”
ENT.Purpose = “”
ENT.Instructions = “”

ENT.Spawnable = false
ENT.AdminSpawnable = false

[/lua]
cl_init.lua:
[lua]include(‘shared.lua’)

function ENT:Draw()
self.Entity:DrawModel()
self.SuperWire:DrawRope()
end

[/lua]

Nice job Boing, and I’m quite interested to see how this plays out, but to defend wiremod a little:

Most of the bloat in wire ents can be explained. For example, every wire ent contains in its init.lua a MakeWireIndicator function, which would logically be inside the creation stool (I assume you’re still using an entity-making-stool system?), but is instead in the init.lua for adv duplicator support. May I suggest deciding on a method of saving contraptions now, before you get too far in?
In your indicator example, you’re just setting the colour, while the Wiremod equivalent also stores the variables for outputting. While it could just call GetColor when necessary, and your nice system of only outputting when necessary helps too, technically it would be slightly more efficient to recall the variables than GetColor each time.
Theres many upsides to the way Wiremod is coded, except virtually nothing is commented so its hell to realize. But most of the bloat does have its reasons.

Regardless, that is a DAMN short Sent you got there, nice job.

Well done, you have made an entity which snaps from white to green and used less code than an entity which fades from one user-selected colour to another user-selected colour and displays information when looked at.
…What’s your point?

Oh, fine.

[lua]
AddCSLuaFile( “cl_init.lua” )
AddCSLuaFile( “shared.lua” )
include(‘shared.lua’)

function ENT:Initialize()
swire.RegisterEntity(self)
self.SuperWire:CreateInput(“Switch”)
self.SuperWire:HookFunction(“Switch”,ChangeColor)
self.a = 0
self.b = 0
self.aCol = Color(255,255,255,255)
self.bCol = Color(255,255,255,255)
end

function ChangeColor(ent,arg)
if arg == self.a then
ent:SetColor(aCol)
ent:SetNWString(“WireBubble”,“Color: (”…aCol.r…","…aCol.g…","…aCol.b…","…aCol.a…")")
elseif arg == self.b
ent:SetColor(bCol)
ent:SetNWString(“WireBubble”,“Color: (”…bCol.r…","…bCol.g…","…bCol.b…","…bCol.a…")")
end
end[/lua]

Hell, it’s only smaller since its the same basis and could be done on the regular wire.

Just a FYI: entity:SetColor() takes r,g,b,a rather than a colour object, because Garry likes pointless inconsistencies.

I might as well make an ent:SetColorC() that does it for me :B but its not so difficult to type in aCol.r,aCol.g etc.

I wrote it in notepad in the morning on a school computer so you get the point, but it should work with minor changes.

I could practically create a GUI for Wiremod, but where’s the fun in that?

How many tools u made already ?

Color objects tend to create more garbage, so there is an advantage to not using it. Precedents kind of screw everything up, though.

However, they’re also the easiest way to store the 4 values you need to store if you want to set colours from variables.

wiremod itself already has support for comments.
it’s just that most inputs are uncommented :smiley:

[editline]12:52AM[/editline]

hover vehicles.
the variety that keeps the distance to the ground

[editline]12:53AM[/editline]

It’s not supposed to do that and I thought I fixed that some months ago.
I’ll look into it later.

[editline]01:03AM[/editline]

Indicator isn’t the best example of good Lua coding.
But it’s kept that way because it works perfectly and doesn’t have any side-effects either.
And as you can probably see it has lots of features yours lacks:

  • duplicator support
  • the ability to form a 7-seg together with other indicators (including proper DOR)
  • color selection

I do like your input registration scheme though.
It lacks some kind of type system, however.
And one problem with that kind of system: Since the hook is registered in an Initialize function, it won’t be updated by lua_reloadent (which doesn’t call Initialize)

an alternative idea which I’ve had on my mind (for wiremod) for a while:
[lua]function ENT.TriggerInput:InputName(value)
–stuff
end[/lua]

EDIT: wee, got the first dumb rating while I’m still writing this post!

[editline]01:33AM[/editline]

wire indicator that actually works, but with about the same amount of functionality as yours:
[lua]AddCSLuaFile( “cl_init.lua” )

include(‘cl_init.lua’)

ENT.WireDebugName = “Simple Indicator”

function ENT:Initialize()
self.Entity:PhysicsInit( SOLID_VPHYSICS )
self.Entity:SetMoveType( MOVETYPE_VPHYSICS )
self.Entity:SetSolid( SOLID_VPHYSICS )

self.Inputs = Wire_CreateInputs(self.Entity, { "A" })
self:TriggerInput("A", 0)

end

function ENT:TriggerInput(iname, value)
if iname == “A” then
if value == 0 then
self.Entity:SetColor(255, 0, 0, 255)
self:SetOverlayText( “Color = 0%” )
else
self.Entity:SetColor(0, 255, 0, 255)
self:SetOverlayText( “Color = 100%” )
end
end
end

function ENT:SpawnFunction( ply, tr )
if (not tr.Hit) then return end
local ent = ents.Create(“gmod_wire_simple_indicator”)
ent:SetModel(“models/props_wasteland/coolingtank02.mdl”)
local SpawnPos = tr.HitPos-tr.HitNormal*ent:OBBMins().z
ent:SetPos(SpawnPos)
ent:Spawn()
return ent
end[/lua]

And cl_init.lua:
[lua]-- shared part
ENT.Type = “anim”
ENT.Base = “base_wire_entity”

ENT.PrintName = “Simple Wire Indicator”
ENT.Author = “TomyLobo”
ENT.Spawnable = true
ENT.AdminSpawnable = true

if SERVER then return end

– client part
ENT.RenderGroup = RENDERGROUP_BOTH[/lua]
I don’t think yours works, unless you moved all initialization to the tool code.
which you shouldn’t really do if you want duplicator compatibility and have generic tool code like wiremod
generic tool code means we have one file for many tools, saving the user download time.