GMod SWEP Trace

Hi Facepunchers!

How do I check if the traceres is an prop, or a SENT? Like, to check if its a vehicle, you do tr.Entity:IsVehicle()

Thanks in advantage!

Oliver

[lua]
if(tr.Entity:IsVehicle()) then
– Vehicle price settings
elseif – tr.Entity:IsSENT()
elseif – tr.Entity:IsProp()
end
[/lua]

Noone?

Are you sure IsProp and IsSENT are real functions? But the IsVehicle bit would work

Thats my question, are there functions like IsSENT and IsProp? or are there other ways to check, if the traceres is a prop, or a sent?

entity:GetClass() returns the class of the entity. So if it’s a prop it’ll return prop_physics, if it’s a Combine NPC it’ll return npc_combine_s and so on.

eg
[lua]
if ent:GetClass() == “prop_physics” then
print(“holy fuck it’s a prop”)
end
[/lua]

But the problem with SENTs is that they can have any class name they like, so you can’t really look at the class name to see whether or not it’s a SENT. What’s the bigger picture on this entity type checking stuff? Maybe another way would be more appropriate.

Im making a price gun for my gamemode, I want it set the price of the SENT, Prop or Vehicle, and that requires 3 hooks, which I made into 3 files ( that keeps the prices ), so I dont want it to open and edit the props file if its a SENT.

You could have two definite categories (props and vehicles) and then an ‘other’ category for everything else.

But using SQL is miles better than trying to work with files. GMod has a builtin database and SQL implementation. You should use that instead of writing code to interpret a file.

Well, that would be a good idea, never tho’d of that :-). Thanks!

[editline]01:47PM[/editline]

But what about my hooks then?

[lua]
hook.Add(“PlayerSpawnProp”, “payForProp”, payForProp)
hook.Add(“PlayerSpawnVehicle”, “payForVehicle”, payForVehicle)
hook.Add(“PlayerSpawnSENT”, “payForSENT”, payForEntity)
[/lua]

[lua]
function payForEntity(ply, ent) --i’m not sure if that’s what the arguments really are but you get the idea
local queryResult = sql.Query(“SELECT price, classname FROM other_ents_prices WHERE classname = “…ent:GetClass()…”;”)
ply:TakeMoneyAway(queryResult[1][“price”])
end
[/lua]
That’s a very bare-bones draft of the function, just to give you an idea. When a player spawns a SENT it finds out the price of the entity by looking up its class name in the ‘other entities’ table. Then takes the money away from the player.

When you do a ‘find me some data’ query in sql.Query you put the results in a return variable (in this case I called it queryResult). Then you have a 2D table where you can access each result in this format:

queryResult[id][fieldname]

So putting queryResult[3][“beans”] would find the value of the beans field in the third record returned by the SQL function.

I think that’s how it works but I’ve not tried using the library myself or playing around with it yet, but I’ve looked over the functions on the wiki and that’s how it seems to be. I know how to use SQL code in general though, so let me know if you need any help with that.

Also now that I look at it, because you’ve got a hook that gets fired when a player spawns a SENT, you could do ent.imaSENT = true to store a variable showing that the entity is a SENT.

I know SQL, i programming websites too. But, I dont get it where you say

What I wanted to know was, if I change the checks, so it checks for vehicles, props, and then the new category, others, then what should I do with my hooks in my GAMEMODE?

Theres no such hook like, PlayerSpawnOther.

[editline]06:46PM[/editline]

Its more because the SQL server on my friends srcds doesnt work, so im doing it with files (dunno why it doesnt work).

I’m not terribly sure what you mean by the line immediately after the quote. If you use PlayerSpawnProp, PlayerSpawnVehicle or PlayerSpawnSENT you can assume the spawned entity is a prop, vehicle or SENT respectively. So you don’t really need to check it.

Yes, I know, but thats for my gamemode, where the player has to pay for the prop, vehicle or entity. But, the trace I asked you about is a price gun, for the gamemode, to set the price.

To you understand now? Im terribly sorry for my bad english, im danish.

Oh you mean a price toolgun that would be for admins only? Make it so that when an entity has it’s price set with it you save it’s class name and model along with it’s price in your database or update it if it’s already there. Then when spawning check if it’s already in the database.

Uhm, how to check if its an entity Crazy Quebec, but yes, your correct.

Its just how I check if its an entity, thats my question.

Of course, I get it now.

In an autorun/server script:
[lua]
function iSpawnedASent(ply, ent)
–make him pay for the SENT
ent.ImASent = true
end
hook.Add(“PlayerSpawnSENT”, “payforsent”, iSpawnedASent)
[/lua]
So that makes it so that when you spawn a SENT you make a variable in it called ImASent. We can check to see if the variable exists from our tool/SWEP code:

[lua]
function TOOL:LeftClick(tr)
if tr.Entity.ImASent == true then
–update the price
end
return trace.Hit
end
[/lua]

Yup, that would check if it’s something from the SENT menu. To simply check if it’s an entity do this :
if ValidEntity(tr.Entity) and !if tr.Entity:IsWorld() then

Lol, yay finally! :-D. Gonna check when I get home, at school atm.

Okay, the check works, but when I set the price, it says this in the chat:

Updated the price! (New price = 3, Entity)
Updated the price! (New price = 0, Entity)

Why does it auto set it to 0?

[lua]
local priceGunPrice = 0

function SWEP:PrimaryAttack()

local tr = self.Owner:GetEyeTrace()
if ( tr.HitWorld ) then return end
if ( tr.Entity:IsPlayer() ) then return end
if ( tr.Entity:IsWeapon() ) then return end
if ( tr.Entity:IsNPC() ) then return end

if(tr.Entity:IsVehicle()) then
	RunConsoleCommand("setVehiclePrice", tr.Entity:GetModel(), priceGunPrice)
	self.Owner:PrintMessage(HUD_PRINTTALK, "Updated the price! (New price = " .. tonumber(priceGunPrice) .. ", Vehicle)")
elseif(tr.Entity:GetClass() == "prop_physics") then
	RunConsoleCommand("setPropPrice", tr.Entity:GetModel(), priceGunPrice)
	self.Owner:PrintMessage(HUD_PRINTTALK, "Updated the price! (New price = " .. tonumber(priceGunPrice) .. ", Prop)")
elseif(ValidEntity(tr.Entity)) then
	RunConsoleCommand("setEntityPrice", tr.Entity:GetClass(), priceGunPrice)
	self.Owner:PrintMessage(HUD_PRINTTALK, "Updated the price! New price = " .. tonumber(priceGunPrice) .. ", Entity / SENT)")
end
self:EmitSound( ShootSound )

self:ShootEffects( self )


// The rest is only done on the server
if (!SERVER) then return end

end

function SWEP:SecondaryAttack()
if(CLIENT) then
prWidth = 400
prHeight = 60
PriceSettings = vgui.Create(“DFrame”)
PriceSettings:SetPos(ScrW() / 2 - prWidth / 2, ScrH() / 2 - prHeight)
PriceSettings:SetSize(prWidth, prHeight)
PriceSettings:SetTitle( “Price gun - Set price” )
PriceSettings:SetVisible( true )
PriceSettings:SetDraggable( true )
PriceSettings:ShowCloseButton( true )
PriceSettings:SetBackgroundBlur( true )
PriceSettings:MakePopup()

	priceSetter = vgui.Create( "DTextEntry", PriceSettings )
	priceSetter:SetPos( 25, 25 )
	priceSetter:SetWide( prWidth - 50 )
	priceSetter:SetValue(priceGunPrice)
	priceSetter.OnEnter = function()
		priceGunPrice = tonumber(priceSetter:GetValue())
		PriceSettings:SetVisible( false )
	end
end

end
[/lua]

I think I see what’s going on. The code for the Derma panel is only running on the client, so when you hit enter on the text box it only changes the value of priceGunPrice on the client, not the server.

When you left click the code runs on both client and server. Because the value of priceGunPrice changed on the client, it shows you the ‘new price is 3’ line. But on the server the value never changed, it was always 0. So it prints ‘new price is 0’.

The solution is to make a console variable on the client. Here’s your SWEP, but with a possible solution:
[lua]
local priceGunPrice = 0

function SWEP:Initialize()
if CLIENT then
priceGunPriceConvar = CreateClientConvar(“pricegun_price”, “0”, false, true)
end
end

function SWEP:PrimaryAttack()

self:EmitSound( ShootSound )

self:ShootEffects( self )


// The rest is only done on the server
if (!SERVER) then return end

local tr = self.Owner:GetEyeTrace()
if ( tr.HitWorld ) then return end
if ( tr.Entity:IsPlayer() ) then return end
if ( tr.Entity:IsWeapon() ) then return end
if ( tr.Entity:IsNPC() ) then return end

priceGunPrice = self.Owner:GetInfo("pricegun_price")

if(tr.Entity:IsVehicle()) then
	RunConsoleCommand("setVehiclePrice", tr.Entity:GetModel(), priceGunPrice)
	self.Owner:PrintMessage(HUD_PRINTTALK, "Updated the price! (New price = " .. tonumber(priceGunPrice) .. ", Vehicle)")
elseif(tr.Entity:GetClass() == "prop_physics") then
	RunConsoleCommand("setPropPrice", tr.Entity:GetModel(), priceGunPrice)
	self.Owner:PrintMessage(HUD_PRINTTALK, "Updated the price! (New price = " .. tonumber(priceGunPrice) .. ", Prop)")
elseif(ValidEntity(tr.Entity)) then
	RunConsoleCommand("setEntityPrice", tr.Entity:GetClass(), priceGunPrice)
	self.Owner:PrintMessage(HUD_PRINTTALK, "Updated the price! New price = " .. tonumber(priceGunPrice) .. ", Entity / SENT)")
end

end

function SWEP:SecondaryAttack()
if(CLIENT) then
prWidth = 400
prHeight = 60
local PriceSettings = vgui.Create(“DFrame”)
PriceSettings:SetPos(ScrW() / 2 - prWidth / 2, ScrH() / 2 - prHeight)
PriceSettings:SetSize(prWidth, prHeight)
PriceSettings:SetTitle( “Price gun - Set price” )
PriceSettings:SetVisible( true )
PriceSettings:SetDraggable( true )
PriceSettings:ShowCloseButton( true )
PriceSettings:SetBackgroundBlur( true )
PriceSettings:MakePopup()

	local priceSetter = vgui.Create( "DTextEntry", PriceSettings )
	priceSetter:SetPos( 25, 25 )
	priceSetter:SetWide( prWidth - 50 )
	priceSetter:SetValue(priceGunPriceConvar:GetString())
	priceSetter:SetConVar("pricegun_price")
	priceSetter.OnEnter = function()
		PriceSettings:Remove()
	end
end

end
[/lua]

So in the SWEP:Initialize at the top we make sure we’re only running on the client, then we create the convar for the price.

In your SWEP:PrimaryAttack, the if !SERVER then return end line has been moved up near the top, because we only want to run the price setting code on the server. The shooting effects and sound still run on both client and server. Just before it actually sets the price, on line 25, the server sets the price variable to whatever the client has on the convar.

And on line 58 we give the text entry a convar of pricegun_price. This means when you type something in and hit enter it has exactly the same effect as if the client opened the console and typed in ‘pricegun_price something’. The variables for PriceSettings and priceSetter have been made local and the panel actually removes itself when you hit enter rather than just turning invisible. I think yours made a new panel each time and didn’t remove it.

So when you want to set a price you right click, and the client opens the derma panel. You put in a number, hit enter and it closes the panel and sends the information to the server using the convar. Then when you left click, the server finds out what the client last put in the price box and sets the price to that.

Thanks, again, im gonna try it when I get home. At school, but it seems possible, and if its true, that it creates a new panel, I need to change alot of code :-P.