Trying to create an NPC gunshop for Darkrp, couple questions
31 replies, posted
Here's the code I'm using. I got it from the gmod lua wiki tutorial on npc shops but for whatever reason the shop won't open when the SNPC is spawned.
cl_init.lua
[lua]include('shared.lua') -- At this point the contents of shared.lua are ran on the client only.
function NPCShopMenu()
local DButton3
local SpawnIcon1TNGV
local DButton2
local SpawnIcon1KHFJ
local DButton1
local SpawnIcon1
local DFrame1
local DLabel1
local DSysButton1
DButton3 = vgui.Create('DButton')
DButton3:SetSize(80, 25)
DButton3:SetPos(375, 280)
DButton3:SetText('P228 - $550')
DButton3.DoClick = function()
if (ply:CanAfford(550) == true) then
ply:AddMoney(-550)
ply:Give("weapon_mad_p228")
end
SpawnIcon1TNGV = vgui.Create('SpawnIcon')
SpawnIcon1TNGV:SetPos(385, 215)
DButton2 = vgui.Create('DButton')
DButton2:SetSize(80, 25)
DButton2:SetPos(285, 280)
DButton2:SetText('Glock - $450')
DButton2.DoClick = function()
if (ply:CanAfford(450) == true) then
ply:AddMoney(-450)
ply:Give("weapon_mad_glock")
end
SpawnIcon1KHFJ = vgui.Create('SpawnIcon')
SpawnIcon1KHFJ:SetPos(295, 215)
SpawnIcon1KHFJ:SetModel('models/weapons/w_pist_p228.mdl')
DButton1 = vgui.Create('DButton')
DButton1:SetSize(80, 25)
DButton1:SetPos(195, 280)
DButton1:SetText('AK-47 - $800')
DButton1.DoClick = function()
if (ply:CanAfford(800) == true) then
ply:AddMoney(-800)
ply:Give("weapon_mad_ak")
end
SpawnIcon1 = vgui.Create('SpawnIcon')
SpawnIcon1:SetPos(205, 215)
SpawnIcon1:SetToolTip('AK47 - $800')
SpawnIcon1:SetModel('models/weapons/w_rif_ak47.mdl')
DFrame1 = vgui.Create('DFrame')
DFrame1:SetSize(275, 124)
DFrame1:SetPos(188, 188)
DFrame1:SetTitle('Gunshop')
DFrame1:SetDeleteOnClose(false)
DFrame1:SetBackgroundBlur(true)
DFrame1:MakePopup()
-- We can also do anything else the client can do, like using the chat!
chat.AddText(Color(255,255,128), "Merchant: ",Color(255,255,255), "Welcome to my shop, how can I help you?" )
end
usermessage.Hook("ShopNPCUsed", NPCShopMenu) --Hook to messages from the server so we know when to display the menu.[/lua]
init.lua
[lua]AddCSLuaFile( "cl_init.lua" ) -- This means the client will download these files
AddCSLuaFile( "shared.lua" )
include('shared.lua') -- At this point the contents of shared.lua are ran on the server only.
function ENT:Initialize( ) --This function is run when the entity is created so it's a good place to setup our entity.
self:SetModel( "models/player/monk.mdl" ) -- Sets the model of the NPC.
self:SetHullType( HULL_HUMAN ) -- Sets the hull type, used for movement calculations amongst other things.
self:SetHullSizeNormal( )
self:SetNPCState( NPC_STATE_SCRIPT )
self:SetSolid( SOLID_BBOX ) -- This entity uses a solid bounding box for collisions.
self:CapabilitiesAdd( CAP_ANIMATEDFACE | CAP_TURN_HEAD ) -- Adds what the NPC is allowed to do ( It cannot move in this case ).
self:SetUseType( SIMPLE_USE ) -- Makes the ENT.Use hook only get called once at every use.
self:DropToFloor()
self:SetMaxYawSpeed( 90 ) --Sets the angle by which an NPC can rotate at once.
end
function ENT:OnTakeDamage()
return false -- This NPC won't take damage from anything.
end
function ENT:AcceptInput( Name, Activator, Caller )
if Name == "Use" and Caller:IsPlayer() then
umsg.Start("ShopNPCUsed", Caller) -- Prepare the usermessage to that same player to open the menu on his side.
umsg.End() -- We don't need any content in the usermessage so we're sending it empty now.
end
end
[/lua]
shared.lua
[lua]ENT.Base = "base_ai" -- This entity is based on "base_ai"
ENT.Type = "ai" -- What type of entity is it, in this case, it's an AI.
ENT.AutomaticFrameAdvance = true -- This entity will animate itself.
ENT.PrintName = "Gunshop SNPC"
ENT.Author = "Zambriskie"
ENT.Contact = "trentroolz@gmail.com"
ENT.Purpose = "Sells 3 guns for high prices. (To make sure people want to buy from players)"
ENT.Instructions = "Spawn him, go press E on him."
ENT.Spawnable = false
ENT.AdminSpawnable = true
ENT.Category = "Zambriskie SNPC's"
function ENT:SetAutomaticFrameAdvance( bUsingAnim ) -- This is called by the game to tell the entity if it should animate itself.
self.AutomaticFrameAdvance = bUsingAnim
end
-- Since this file is ran by both the client and the server, both will share this information.[/lua]
My other question is how to make him spawn when the server starts. I have no idea how to go about doing this.
Are there any errors returned in console?
[b][url=http://wiki.garrysmod.com/?title=Ents.Create]Ents.Create [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b]
[lua]
hook.Add( "InitPostEntity", "SpawnNPC", function()
local position = Vector(0,0,0) --Vector Here
local ent = ents.Create("SHOP_KEEPER") --Shop Keeper Entity Here
ent:SetPos(position) -- Sets the position
ent:Spawn() -- Spawns It
end)
[/lua]
No errors, it just doesn't do anything when I press E. And he spawns in that weird arms-out pose. And I'm sorry if this is a dumb question, but in the code you posted, the vector is just the world pos of where I want him to spawn, correct?
Yes, You can get the position by typing in console:
[code]getpos[/code]
Ill Revise your code now, Give me one minute.
First Thing, Change this in the [B]init.lua[/B]
[lua]function ENT:AcceptInput( Name, Activator, Caller )
if Name == "Use" and Caller:IsPlayer() then
umsg.Start("ShopNPCUsed", Caller) -- Prepare the usermessage to that same player to open the menu on his side.
umsg.End() -- We don't need any content in the usermessage so we're sending it empty now.
end
[/lua]
[highlight]To[/highlight]
[lua]
function ENT:Use( act, call )
if act:IsPlayer() then
umsg.Start("ShopNPCUsed", act)
umsg.End()
end
end
[/lua]
[b][url=wiki.garrysmod.com/?title=ENT.Use]ENT.Use [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b]
You should also add some [b][url=http://wiki.garrysmod.com/?title=G.Msg]G.Msg [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b] functions throughout the script to check were it is failing and not responding to your functions or Usermessages.
Wait, in the lua code you posted
[lua]hook.Add( "InitPostEntity", "SpawnNPC", function()
local position = Vector(0,0,0) --Vector Here
local ent = ents.Create("SHOP_KEEPER") --Shop Keeper Entity Here
ent:SetPos(position) -- Sets the position
ent:Spawn() -- Spawns It
end)[/lua]
I know what to put for vector now but what do i put for the position?
You do not need to put anything in the position.
Alright, cool. Also, where do I put the angle I want the npc placed at?
You could also put after [B]ent:SetPos()[/B]
[b][url=http://wiki.garrysmod.com/?title=Entity.SetAngles]Entity.SetAngles [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b]
Your current angle is returned by using the [B]getpos[/B] command.
In This Format:
[code]
Position X, Position Y, Position Z;Angle Yaw, Angle Roll, Angle Yaw
[/code]
I think that is the correct format.
You are doing serverside in clientside.
[editline]22nd April 2011[/editline]
Create a comcommand to buy a pistol that traces to see if you are looking at an NPC seller. Then make the buttons run it.
Not sure if this would work but could you do like an authorisation key.
So the console command ran would be [B]buyweapon ak47 436FD345@!F[/B]
And the server does a check like:
[lua]
concommand.Add("buyweapon", function (ply, cmd, args)
if args[2] != "436FD345@!F" then return end
--Rest of code
[/lua]
How easy would it be to crack a hardcoded string like that?
Just check if the player is looking at one.
Still doesn't work, I have no idea why. He doesn't give an error, it just doesn't do anything.
Post the new code.
[editline]22nd April 2011[/editline]
Position is a variable defined above. All you need to skis define the vector.
[QUOTE=trent_roolz;29360518]Wait, in the lua code you posted
[lua]hook.Add( "InitPostEntity", "SpawnNPC", function()
local position = Vector(0,0,0) --Vector Here
local ent = ents.Create("SHOP_KEEPER") --Shop Keeper Entity Here
ent:SetPos(position) -- Sets the position
ent:Spawn() -- Spawns It
end)[/lua]
I know what to put for vector now but what do i put for the position?[/QUOTE]
[QUOTE=cis.joshb;29362269]Just check if the player is looking at one.[/QUOTE]
But for future reference and not just for this system, other things i may use this on. How useful is this tactic?
and also, adding _ before a concommand.Add, does it make it not apear in console as one of the quick commands or something?
Code is the same as what Science posted but the NPC still doesnt do anything when he's clicked on. I wish there was at least an error to tell us what was wrong.
Have you done as I said?
On every Vital part so from the spawn of the npc to the derma menu loading, place a print function.
Post the code with the prints and your console when you are done.
[editline]23rd April 2011[/editline]
Problems with your derma.
Ply is not defined and cannot be defined clientside.
Please send stuff to the server and run the checks serverside.
Also, you have not parented anything anywhere, and your Dframe should be up the top.
One more thing that is recommended, do this instead of setting the pos.
[Lua]DFrame1:Center()[/Lua]
[QUOTE=Science;29362620]But for future reference and not just for this system, other things i may use this on. How useful is this tactic?
and also, adding _ before a concommand.Add, does it make it not apear in console as one of the quick commands or something?[/QUOTE]
So you didn't listen to what I said? You can't just use those functions clientside. Create a concommand.
[QUOTE=Science;29362237]Not sure if this would work but could you do like an authorisation key.
So the console command ran would be [B]buyweapon ak47 436FD345@!F[/B]
And the server does a check like:
[lua]
concommand.Add("buyweapon", function (ply, cmd, args)
if args[2] != "436FD345@!F" then return end
--Rest of code
[/lua]
How easy would it be to crack a hardcoded string like that?[/QUOTE]
It would be very easy. All you would have to do is look in your cache files and find the clientside script that runs that command, and it would be written there in plain text. You really shouldn't use a system like that. You'd be better off using a regular console command and have the client run that console command, after which the server checks if the player is near the NPC and looking at the NPC. cis.joshb already said this, but I am just trying to make it more clear.
Also, ply can be defined clientside, althought it would be better to just use LocalPlayer().
[CODE] ply = LocalPlayer() [/CODE]
I know this but if i was going to do it for other situations, not involving npcs.
Would it be better if at the start of each game a random key is picked and passed to the client in a usermessage then it is authed with the server.
[QUOTE=Science;29376542]I know this but if i was going to do it for other situations, not involving npcs.
Would it be better if at the start of each game a random key is picked and passed to the client in a usermessage then it is authed with the server.[/QUOTE]
Or you could just add serverside checks
Yes I could, but some things need to be secret and rely on clientside things only.
[QUOTE=Science;29377002]Yes I could, but some things need to be secret and rely on clientside things only.[/QUOTE]
Give me one good example
[QUOTE=Science;29376542]I know this but if i was going to do it for other situations, not involving npcs.
Would it be better if at the start of each game a random key is picked and passed to the client in a usermessage then it is authed with the server.[/QUOTE]
Harder than serverside checks.
[editline]23rd April 2011[/editline]
[QUOTE=Science;29377002]Yes I could, but some things need to be secret and rely on clientside things only.[/QUOTE]
Not really? Clientside is the least secret, seeing as it is downloaded by every single client.
Put the canafford and addmoney functions into the init.lua and hook it to the buttons do click function.
if you still need help ill give you an example.
[QUOTE=leet frog;29380133]Put the canafford and addmoney functions into the init.lua and hook it to the buttons do click function.
if you still need help ill give you an example.[/QUOTE]
This makes no sence.
You need to run a console command from when the client presses the button so that it sends the console command such as [B]buyitem ak47[/B] then on the server check if the player has the money, deduct it and give the weapon to the player running the command.
[B]Clientside[/B]
[lua]DButton1.DoClick = function()
RunConsoleCommand("buyitem", "ak47")
end[/lua]
[B]Serverside[/B]
[lua]concommand.Add("buyitem", function(ply, cmd, args)
if args[1] == "ak47" then
if ply:CanAfford(800) then
ply:AddMoney(-800)
ply:Give("weapon_ak47")
else
Notify(ply, 1, 4, "You cannot afford an ak47!")
end
end
end)
[/lua]
[QUOTE=Science;29380478]This makes no sence.
You need to run a console command from when the client presses the button so that it sends the console command such as [B]buyitem ak47[/B] then on the server check if the player has the money, deduct it and give the weapon to the player running the command.
[B]Clientside[/B]
[lua]DButton1.DoClick = function()
RunConsoleCommand("buyitem", "ak47")
end[/lua]
[B]Serverside[/B]
[lua]concommand.Add("buyitem", function(ply, cmd, args)
if args[1] == "ak47" then
if ply:CanAfford(800) then
ply:AddMoney(-800)
ply:Give("weapon_ak47")
else
Notify(ply, 1, 4, "You cannot afford an ak47!")
end
end
end)
[/lua][/QUOTE]
That's not what you're supposed to do. The lua is fine, but this is the [b]Questions[/b] section, not requests. Please let people learn themselves.
[editline]23rd April 2011[/editline]
Oh and you might want to add:
[lua]
local tr = ply:GetEyeTrace()
if tr.Entity:GetClass() == "npc_shop" then
<rest of code>
[/lua]
[QUOTE=cis.joshb;29380723]That's not what you're supposed to do. The lua is fine, but this is the [b]Questions[/b] section, not requests. Please let people learn themselves.
[editline]23rd April 2011[/editline]
Oh and you might want to add:
[lua]
local tr = ply:GetEyeTrace()
if tr.Entity:GetClass() == "npc_shop" then
<rest of code>
[/lua][/QUOTE]
Sorry, i was just giving him an example of one so he hopefully can grasp it himself.
[QUOTE=Science;29380768]Sorry, i was just giving him an example of one so he hopefully can grasp it himself.[/QUOTE]
Yeah, it's fine. Your a pretty good helper, for a noobie.
[editline]23rd April 2011[/editline]
[QUOTE=leet frog;29380133]Put the canafford and addmoney functions into the init.lua and hook it to the buttons do click function.
if you still need help ill give you an example.[/QUOTE]
You can't hook a clientside button press to a serverside function.
I know this isn't the request section, but could somebody post a working code and explain why it works but mine doesn't? I'm reading through the thread and I get a lot of what people are saying but it's not clicking for me how to fix it. I just need a working code.
And thanks for all your help by the way, you guys are great :D
[QUOTE=trent_roolz;29399619]this isn't the request section[/QUOTE]
Sorry, you need to Log In to post a reply to this thread.