Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require("datastream")
- require("glon")
- SELL = {}
- /************************************************ EDIT BELOW THIS LINE ***********************************************/
- SELL.SellersFile = "npc_sellers.txt" -- This is the data file the seller info will save to
- SELL.WeaponsFile = "npc_weapons.txt " -- This is the data file the weapon info will save to
- --[[ SELL.Info is the information about where the NPCs are, what they look like, and what they can sell
- Here's how it should look:
- ["mapname_lowercase_only"] = {
- {
- pos = Vector( x, y, z ),
- ang = Angle( pitch, yaw, roll ),
- model = "your_model",
- allowed = {
- "weapon_name",
- "weapon_name_2",
- },
- },
- }
- It is VERY VERY VERY important that you get the syntax EXACTLY RIGHT, or this WILL BREAK AND FAIL ENTIRELY! I would recommend
- finding a Lua coder to do it for you, or anyone who understands the syntax of Lua tables. ALL VARIABLE NAMES SHOULD BE THE SAME AS SHOWN!
- Note: The model can only be that of a citizen's (for now, at least). ]]--
- SELL.Info = {
- ["rp_downtown_v2"] = {
- {
- pos = Vector( 78.5428, -2400.1790, -191.9688 ),
- ang = Angle( 0, 135, 0 ),
- model = "models\Humans/Group03m/male_03.mdl",
- allowed = {
- "ak47",
- }
- },
- {
- pos = Vector( 123.8559, 257.2510, -199.9688 ),
- ang = Angle( 0, 90, 0 ),
- model = "models/Humans/Group01/Male_05.mdl",
- allowed = {
- "mp5",
- }
- },
- {
- pos = Vector( -1948.2770, -2604.4736, -879.9688 ),
- ang = Angle( 0, 26, 0 ),
- model = "models\Humans/Group03m/Female_02.mdl",
- allowed = {
- "mp5",
- "ak47",
- }
- },
- },
- }
- --[[ SELL.Weapons is the information about the weapons each NPC can sell
- Here's how it should look:
- ["unique_print_name"] = {
- model = "weapon_model.mdl",
- class = "weapon_class",
- cost = 1500,
- desc = "A description, tabbing is removed",
- }
- Once again, the syntax MUST BE CORRECT and the variables MUST STAY THE SAME NAME.
- Note: The "key" used (in the brackets) is how you will refer to the weapon in the above NPC information, so it must be unique. Casing is irrelevant,
- but that name is also what will show up on the Seller's menu. ]]--
- SELL.Weapons = {
- ["AK47"] = {
- model = "models/sickness/bmw-m5.mdl",
- class = "scripts/vehicles/bmwm5.txt",
- var = ak47
- cost = 1200,
- name = "BMW M5",
- desc = [[Entertain your friends and
- kill your enemies
- with this one of a kind weapon!]],
- ammo = { type = "smg1", amount = 50 },
- },
- ["MP5"] = {
- model = "models/sickness/360spyder.mdl",
- class = "scripts/vehicles/360.txt",
- var = mp5
- cost = 600,
- desc = [[Pew pew pew]],
- ammo = { type = "smg1", amount = 50 },
- },
- }
- /************************************************ EDIT ABOVE THIS LINE ************************************************/
- SELL.MaxDist = 200
- SELL.Sellers = {}
- function SELL:GetWeaponByClass( class ) for _,v in pairs(self.Weapons) do if v.class == class then return v end end end
- if SERVER then
- AddCSLuaFile( "npc_sellers.lua" )
- function SELL:Initialize()
- print("NPC SELLERS Initializing [SERVER]")
- local mapinfo = self.Info[string.lower(game.GetMap())]
- if not mapinfo then
- print("NPCSELLERS: No data found for this map!")
- return
- end
- for _,v in pairs( ents.FindByClass( "npc_citizen" ) ) do
- if string.find( v:GetName(), "npcseller" ) then v:Remove() end
- end
- for k,v in pairs(mapinfo) do
- self:CreateSeller( { pos = v.pos, ang = v.ang, model = v.model, allowed = v.allowed, id = k, created = (v.created or false) } )
- end
- hook.Add("KeyPress","SELLDetectUse",function( pl, key )
- if key == IN_USE then
- local ent = pl:GetEyeTrace().Entity
- if ValidEntity( ent ) and self:WithinRange( pl ) and table.HasValue( self.Sellers, ent ) then
- pl:ConCommand("sell_menu")
- end
- end
- end)
- hook.Add("ScaleNPCDamage","SELLInvulnSellers",function( npc, hit, dmg )
- if table.HasValue( self.Sellers, npc ) then dmg:SetDamage( 0 ) end
- end)
- hook.Add("PlayerAuthed","SELLSendInfo",function( pl )
- self:SendSellerInfo( pl )
- end)
- concommand.Add("sell_buyweapon",function( pl, cmd, args )
- if not self:WithinRange( pl ) then return end
- local wep,seller = self:GetWeaponByClass( args[2] ), pl:GetEyeTrace().Entity
- print( wep, wep.cost, pl:CanAfford( wep.cost ) )
- if not self:CanSell( seller, string.lower(args[1]) ) then Notify(pl, 1, 4, "That Seller cannot sell that car!") return end
- if not wep then Notify(pl, 1, 4, string.format(LANGUAGE.unavailable, "car")) return end
- if not pl:CanAfford( wep.cost ) then Notify(pl, 1, 4, string.format(LANGUAGE.cant_afford, string.lower(args[1]))) return end
- local cartype = wep.class
- if pl.string.lower(args[1]) == false then ply.string.lower(args[1]) = true pl:SetPData(args[1], "true") end
- car = ents.Create("prop_vehicle_jeep")
- car:SetModel(wep.model)
- car:SetKeyValue("vehiclescript", cartype)
- car:SetPos(pl:GetPos() + Vector(200, 200, 0))
- car.nodupe = true
- car:Spawn()
- car:Activate()
- car:PhysWake()
- car:Own(pl)
- pl:AddMoney( -wep.cost )
- Notify(pl, 1, 4, string.format(LANGUAGE.you_bought_x, wep.name, tostring(wep.cost)))
- /*local weapon = ents.Create("spawned_weapon")
- weapon:SetModel(wep.model)
- weapon.weaponclass = wep.class
- weapon.ShareGravgun = true
- weapon:SetPos( util.TraceLine({start=ply:EyePos(),endpos=trace.start+ply:GetAimVector() * 85,filter=ply}).HitPos )
- weapon.nodupe = true
- weapon:Spawn()*/
- end)
- hook.Add("AcceptStream","SELLAllowRegister",function( pl, handle, id )
- if pl:IsAdmin() and handle == "SELLRegister" then return true end
- end)
- datastream.Hook("SELLRegister",function(pl,hand,id,enc,args)
- if not pl:IsAdmin() then pl:ChatPrint("You must be an admin to do this!") return end
- local npc = self:CreateSeller( { pos = args.pos, ang = args.ang, model = args.model, allowed = args.allowed, id = table.Count(self.Sellers) + 1 } )
- npc:SetNWBool("SELLCreated",true)
- table.insert(self.Info[string.lower(game.GetMap())],{ pos = args.pos, ang = args.ang, model = npc:GetModel(), allowed = args.allowed} )
- pl:ChatPrint("Seller successfully created!")
- self:SaveSellers()
- self:SendSellerInfo( player.GetAll() )
- end)
- concommand.Add("sell_removeseller",function(pl,cmd,args)
- if not pl:IsAdmin() then pl:ChatPrint("You must be an admin to do this!") return end
- local e = pl:GetEyeTrace().Entity
- if not ValidEntity( e ) || not table.HasValue( self.Sellers, e ) then pl:ChatPrint("That is not an NPC Seller!") return end
- self:RemoveSeller( e, pl )
- end)
- self:SendSellerInfo( player.GetAll() )
- end
- function SELL:LoadSellers()
- if not file.Exists(self.SellersFile) then file.Write(self.SellersFile,glon.encode({}))
- else
- local info = glon.decode(file.Read(self.SellersFile))[string.lower(game.GetMap())]
- if not info then return end
- for _,v in pairs( info ) do v.created = true end
- table.Add( self.Info[string.lower(game.GetMap())], info )
- end
- end
- function setwhatcarsyouown()
- for k, v in pairs(self.Weapons) do local a = ply:GetPData(v.var);
- if a == true then ply.a = true end end
- hook.Add("PlayerInitialSpawn", "broomcheesecake", setwhatcarsyouown)
- function SELL:SaveSellers()
- local data = table.Copy(self.Info)
- local mapinfo = self.Info[string.lower(game.GetMap())]
- if not mapinfo then return end
- local to_save = {}
- for _,v in pairs( self.Sellers ) do
- local sellerinfo = mapinfo[v:GetNWInt("SellerID")]
- if v:GetNWBool("SELLCreated") then table.insert(to_save,sellerinfo) end
- end
- data[string.lower(game.GetMap())] = to_save
- file.Write(self.SellersFile,glon.encode(data))
- self:SendSellerInfo( player.GetAll() )
- end
- function SELL:RemoveSeller( seller, pl )
- if not ValidEntity( seller ) then pl:ChatPrint("Invalid entity!") return end
- if not seller:GetNWBool("SELLCreated") then pl:ChatPrint("You cannot remove that seller! Edit the npc_sellers.lua to do that.") return end
- table.remove(self.Info[string.lower(game.GetMap())],seller:GetNWInt("SellerID"))
- for k,v in pairs( self.Sellers ) do if v == seller then table.remove( self.Sellers, k ) end end
- seller:Remove()
- self:SaveSellers()
- pl:ChatPrint("Seller successfully removed!")
- self:SendSellerInfo( player.GetAll() )
- end
- function SELL:SendSellerInfo( obj )
- datastream.StreamToClients( obj, "SELLGetInfo", self.Info[string.lower(game.GetMap())] )
- end
- function SELL:CreateSeller( args )
- local npc = ents.Create("npc_citizen")
- npc:SetPos( args.pos or Vector(0,0,0) )
- npc:SetAngles( args.ang or Angle(0,0,0) )
- npc:SetModel( args.model or "models/Humans/Group02/male_07.mdl" )
- npc:SetSkin( args.skin or 0 )
- npc:SetKeyValue("expressiontype","3")
- npc:Spawn()
- npc:Activate()
- npc:SetName( "npcseller"..tonumber(#self.Sellers) )
- npc:SetAnimation( ACT_IDLE_ANGRY )
- npc:CapabilitiesClear()
- npc:CapabilitiesAdd( CAP_ANIMATEDFACE | CAP_TURN_HEAD )
- npc.SellerInfo = args
- npc:SetNWInt("SellerID",args.id)
- npc:SetNWBool("SELLCreated",args.created)
- for _,v in pairs( ents.GetAll() ) do npc:AddEntityRelationship( v, D_LI, 99 ) end
- self.Sellers[ npc:EntIndex() ] = npc
- return npc
- end
- function SELL:WithinRange( pl )
- local e = pl:GetEyeTrace().Entity
- return ValidEntity( e ) and pl:GetShootPos():Distance( pl:GetEyeTrace().HitPos ) <= self.MaxDist and table.HasValue( self.Sellers, e )
- end
- function SELL:CanSell( seller, name ) return table.HasValue(seller.SellerInfo.allowed,name) end
- SELL:LoadSellers()
- concommand.Add("sell_init_sv",function( pl ) if pl:IsAdmin() then SELL:Initialize() end end)
- end
- if CLIENT then
- function SELL:Initialize()
- print("NPC SELLERS Initializing [CLIENT]")
- concommand.Add("sell_menu",function( pl )
- if not self:WithinRange( pl ) then return end
- local seller = pl:GetEyeTrace().Entity
- local fr = vgui.Create("DFrame")
- fr:SetSize( 300, 340 )
- fr:Center()
- fr:SetTitle("")
- fr:MakePopup()
- function fr:Paint()
- draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 30, 30, 30, 220 ) )
- draw.DrawText( "Car Dealer", "ScoreboardText", self:GetWide() / 2, 4, color_white, 1 )
- end
- local itempan = vgui.Create("DPanel",fr)
- itempan:SetSize( 165, 290 )
- itempan:SetPos( 20, 30 )
- local itemtext,itemdesc,itemclass,itemcost = "NPC Shop", "Click on an item to see it","", ""
- function itempan:Paint()
- draw.RoundedBox(0,0,0,self:GetWide(),self:GetTall(),Color(50,50,50,255))
- draw.DrawText( itemtext .. (itemcost != "" && ": $" ..itemcost || "" ), "ScoreboardText", self:GetWide() / 2, 5, color_white, 1 )
- draw.DrawText( string.gsub(itemdesc,"\t",""), "Default", self:GetWide() / 2, 20, color_white, 1 )
- end
- local itemmdl = vgui.Create("DModelPanel",itempan)
- itemmdl:SetSize( itempan:GetWide() - 20, itempan:GetWide() - 20 )
- itemmdl:SetPos( 10, 80 )
- local function ModelSet(mdl,mdlname)
- mdl:SetModel(mdlname)
- local prop = ents.Create("prop_physics")
- prop:SetModel(mdlname)
- function mdl:LayoutEntity(Entity)
- Entity:SetAngles( Angle( -60, math.fmod(CurTime(),360)*50, 0) )
- end
- mdl:SetCamPos(prop:OBBCenter()-Vector(prop:BoundingRadius()*1.3,prop:BoundingRadius() * 1,-prop:BoundingRadius() / 1))
- mdl:SetLookAt(prop:OBBCenter()-Vector(0,0,-prop:BoundingRadius()/13))
- prop:Remove()
- end
- local buybtn = vgui.Create("DButton",itempan)
- buybtn:SetSize( itempan:GetWide() - 20, 20 )
- buybtn:SetPos( 10, itempan:GetTall() - 30 )
- if LocalPlayer().itemvar == true then
- buybtn:SetText("Spawn Car")
- else buybtn:SetText("Buy car") end
- buybtn.DoClick = function()
- if itemclass == "" then LocalPlayer():ChatPrint("Select a car first!") return end
- RunConsoleCommand( "sell_buyweapon", itemtext, itemclass )
- fr:Close()
- end
- local weps = vgui.Create("DPanelList",fr)
- weps:SetSize( (table.Count(self.Weapons) < 3 && 85 || 100 ), 290 )
- weps:SetPos( fr:GetWide() - weps:GetWide() - 20, 30 )
- weps:SetPadding( 5 )
- weps:SetSpacing( 5 )
- weps:EnableVerticalScrollbar( true )
- for k,v in pairs( self.Weapons ) do
- if self:CanSell( seller, string.lower(k) ) then
- local pan = vgui.Create("DPanel")
- pan:SetSize( weps:GetWide() - 10, (table.Count(self.Weapons) < 3 && weps:GetWide() || weps:GetWide() - 10 ) )
- function pan:Paint()
- draw.DrawText( k, "Default", self:GetWide() / 2, 2, color_white, 1 )
- draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 100, 100, 100, 100 ) )
- end
- local icon = vgui.Create("SpawnIcon",pan)
- icon:SetModel( v.model )
- icon:SetPos( 5, 15 )
- icon:SetTooltip( k ..": $" .. v.cost )
- icon.OnMousePressed = function()
- ModelSet(itemmdl,v.model)
- itemtext = k
- itemdesc = v.desc
- itemvar = v.var
- itemclass = v.class
- itemcost = v.cost
- end
- weps:AddItem( pan )
- end
- end
- end)
- concommand.Add("sell_admin",function()
- if !LocalPlayer():IsAdmin() then LocalPlayer():ChatPrint("You must be an admin to access this!") return end
- local fr = vgui.Create("DFrame")
- fr:SetSize( 250, 65 )
- fr:Center()
- fr:SetTitle("")
- fr:MakePopup()
- function fr:Paint()
- draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 30, 30, 30, 220 ) )
- draw.DrawText( "Modify Sellers", "ScoreboardText", self:GetWide() / 2, 3, color_white, 1 )
- end
- local npc = vgui.Create("DButton",fr)
- npc:SetPos( 20, 30 )
- npc:SetSize( 100, 20 )
- npc:SetText("Add a Seller")
- npc.DoClick = function()
- self:AddSellerMenu()
- fr:Close()
- end
- local wpn = vgui.Create("DButton",fr)
- wpn:SetPos( 130, 30 )
- wpn:SetSize( 100, 20 )
- wpn:SetText("Add a Weapon")
- wpn.DoClick = function()
- LocalPlayer():ChatPrint("That is not yet implemented. Contact your local developer for more information.")
- end
- end)
- end
- function SELL:AddSellerMenu()
- local fr = vgui.Create("DFrame")
- fr:SetSize( 450,200 )
- fr:Center()
- fr:SetTitle("")
- fr:MakePopup()
- function fr:Paint()
- draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 30, 30, 30, 220 ) )
- draw.DrawText( "Add Seller", "ScoreboardText", self:GetWide() / 2, 3, color_white, 1 )
- draw.DrawText("Model:","Default", 20, 173, color_white, 0 )
- end
- local pPos = vgui.Create("DPanel",fr)
- pPos:SetPos( 20, 25 )
- pPos:SetSize( 130, 135 )
- function pPos:Paint()
- draw.RoundedBox(0,0,0,self:GetWide(),self:GetTall(),Color(100,100,100,255))
- end
- local pos = { "X", "Y", "Z" }
- for k,v in pairs( pos ) do
- local text = vgui.Create("DTextEntry", pPos )
- text:SetPos( 25, 10 + ( k - 1 ) * 30 )
- text:SetSize( 70, 20 )
- local lbl = vgui.Create("DLabel", pPos )
- lbl:SetPos( 10, 10 + (k - 1) * 30 )
- lbl:SetText( v..":" )
- pos[k] = text
- end
- local current = vgui.Create("DButton",pPos)
- current:SetPos( 10, 105 )
- current:SetSize( pPos:GetWide() - 20, 20 )
- current:SetText("Get Current Position")
- current.DoClick = function()
- local curpos = LocalPlayer():GetPos()
- pos[1]:SetValue( math.Round(curpos.x) )
- pos[2]:SetValue( math.Round(curpos.y) )
- pos[3]:SetValue( math.Round(curpos.z) )
- end
- local pAng= vgui.Create("DPanel",fr)
- pAng:SetPos( 160, 25 )
- pAng:SetSize( 130, 135 )
- function pAng:Paint()
- draw.RoundedBox(0,0,0,self:GetWide(),self:GetTall(),Color(100,100,100,255))
- end
- local ang = { "P", "Y", "R" }
- for k,v in pairs( ang ) do
- local text = vgui.Create("DTextEntry", pAng )
- text:SetPos( 25, 10 + ( k - 1 ) * 30 )
- text:SetSize( 70, 20 )
- local lbl = vgui.Create("DLabel", pAng )
- lbl:SetPos( 10, 10 + (k - 1) * 30 )
- lbl:SetText( v..":" )
- ang[k] = text
- end
- local current = vgui.Create("DButton",pAng)
- current:SetPos( 10, 105 )
- current:SetSize( pAng:GetWide() - 20, 20 )
- current:SetText("Get Current Angles")
- current.DoClick = function()
- local curang = LocalPlayer():GetAngles()
- ang[1]:SetValue( math.Round(curang.x) )
- ang[2]:SetValue( math.Round(curang.y) )
- ang[3]:SetValue( math.Round(curang.z) )
- end
- local pWep= vgui.Create("DPanel",fr)
- pWep:SetPos( 300, 25 )
- pWep:SetSize( 130, 135 )
- function pWep:Paint()
- draw.RoundedBox(0,0,0,self:GetWide(),self:GetTall(),Color(100,100,100,255))
- end
- local weps = vgui.Create("DPanelList",pWep)
- weps:SetPos( 10, 10 )
- weps:SetSize( pWep:GetWide() - 20, pWep:GetTall() - 20 )
- weps:EnableVerticalScrollbar( true )
- weps:SetPadding(2)
- weps:SetSpacing(2)
- for k,v in pairs( self.Weapons ) do
- local pan = vgui.Create("DPanel")
- function pan:Paint()
- draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 100, 100, 100, 100 ) )
- end
- local chb = vgui.Create("DCheckBoxLabel",pan)
- chb:SetPos( 5, 5 )
- chb:SetText( k )
- pan.Item = k
- pan.chb = chb
- weps:AddItem( pan )
- end
- local model = vgui.Create("DTextEntry",fr)
- model:SetPos( 60, 170 )
- model:SetSize(175, 20 )
- local submit = vgui.Create("DButton",fr)
- submit:SetSize( 75, 20 )
- submit:SetText("Submit")
- submit:SetPos( fr:GetWide() - submit:GetWide() - 20, 170 )
- submit.DoClick = function()
- local x,y,z,p,yaw,r = tonumber(pos[1]:GetValue()),tonumber(pos[2]:GetValue()),tonumber(pos[3]:GetValue()),tonumber(ang[1]:GetValue()),tonumber(ang[2]:GetValue()),tonumber(ang[3]:GetValue())
- if not x or not y or not z or not p or not yaw or not r then LocalPlayer():ChatPrint("Malformed number!") return end
- local data = {
- pos = Vector(x,y,z),
- ang = Angle(p,yaw,r),
- model = model:GetValue(),
- allowed = {}
- }
- for _,v in pairs( weps:GetItems() ) do if v.chb:GetChecked() then
- table.insert(data.allowed,string.lower(v.Item))
- end end
- if not data.allowed[1] then LocalPlayer():ChatPrint("Select at least one weapon!") return end
- datastream.StreamToServer("SELLRegister",data)
- end
- end
- function SELL:WithinRange( pl )
- local e = pl:GetEyeTrace().Entity
- return ValidEntity( e ) and pl:GetShootPos():Distance( pl:GetEyeTrace().HitPos ) <= self.MaxDist and e:GetClass() == "npc_citizen"
- end
- function SELL:CanSell( seller, name ) return table.HasValue( self.Info[string.lower(game.GetMap())][seller:GetNWInt("SellerID")].allowed, name) end
- concommand.Add("sell_init_cl",function() SELL:Initialize() end)
- datastream.Hook("SELLGetInfo",function(hand,id,enc,dec) SELL.Info[string.lower(game.GetMap())] = dec end)
- end
- hook.Add("InitPostEntity","SELLInitialize",function() SELL:Initialize() end)
- --lua_openscript autorun/npc_sellers.lua
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement