summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorAlexander Pickering <alexandermpickering@gmail.com>2017-08-07 18:22:29 -0400
committerAlexander Pickering <alexandermpickering@gmail.com>2017-08-07 18:22:29 -0400
commitdaa59a7835c350a09dcb207c714acf57828137f3 (patch)
treeae2c00da0e546447ca17a9c5d8492310e5e93f27 /lua
downloadartery_editor-daa59a7835c350a09dcb207c714acf57828137f3.tar.gz
artery_editor-daa59a7835c350a09dcb207c714acf57828137f3.tar.bz2
artery_editor-daa59a7835c350a09dcb207c714acf57828137f3.zip
Inital Commit
Diffstat (limited to 'lua')
-rw-r--r--lua/autorun/gcompute_plugin.lua130
-rw-r--r--lua/autorun/setupzones.lua14
-rw-r--r--lua/autorun/sv_npc.lua121
-rw-r--r--lua/autorun/tab.lua16
-rw-r--r--lua/autorun/town.lua141
-rw-r--r--lua/autorun/zone_dungeon.lua146
-rw-r--r--lua/autorun/zone_huntingground.lua176
-rw-r--r--lua/autorun/zone_serverchanger.lua84
-rw-r--r--lua/autorun/zone_town.lua62
-rw-r--r--lua/entities/info_edit_townienode/cl_init.lua74
-rw-r--r--lua/entities/info_edit_townienode/init.lua54
-rw-r--r--lua/entities/info_edit_townienode/shared.lua13
-rw-r--r--lua/entities/info_huntablespawn/cl_init.lua71
-rw-r--r--lua/entities/info_huntablespawn/init.lua18
-rw-r--r--lua/entities/info_huntablespawn/shared.lua27
-rw-r--r--lua/entities/info_programmable_base/cl_init.lua124
-rw-r--r--lua/entities/info_programmable_base/init.lua148
-rw-r--r--lua/entities/info_programmable_base/shared.lua12
-rw-r--r--lua/entities/info_townieshop/cl_init.lua173
-rw-r--r--lua/entities/info_townieshop/init.lua59
-rw-r--r--lua/entities/info_townieshop/shared.lua13
-rw-r--r--lua/entities/info_towniespawn/cl_init.lua109
-rw-r--r--lua/entities/info_towniespawn/init.lua125
-rw-r--r--lua/entities/info_towniespawn/shared.lua12
-rw-r--r--lua/entities/npc_huntable/cl_init.lua66
-rw-r--r--lua/entities/npc_huntable/init.lua80
-rw-r--r--lua/entities/npc_huntable/shared.lua180
27 files changed, 2248 insertions, 0 deletions
diff --git a/lua/autorun/gcompute_plugin.lua b/lua/autorun/gcompute_plugin.lua
new file mode 100644
index 0000000..02d0e6e
--- /dev/null
+++ b/lua/autorun/gcompute_plugin.lua
@@ -0,0 +1,130 @@
+if SERVER then return end
+if engine.ActiveGamemode() ~= "sandbox" then return end
+print('Hello from the gcompute plugin!')
+
+local self, info = GCompute.IDE.ViewTypes:CreateType ("NavView")
+info:SetAutoCreate (true)
+info:SetDefaultLocation ("Bottom/Right")
+self.Title = "Nav View"
+self.Icon = "icon16/heart.png"
+self.Hideable = true
+
+local function find_selected_code()
+ local i = GCompute.IDE:GetInstance()
+ local selectedpanel
+ for k,v in pairs(i.ViewManager.ViewsById) do
+ if v.CodeEditor ~= nil and v.Container:IsVisible() then
+ selectedpanel = v
+ break
+ end
+ end
+ print("Found selected panel!")
+end
+
+--Returns an array of nav nodes
+local function find_nav_nodes()
+
+end
+
+--Returns the name of the npc, "???" if undetermined
+local function find_name()
+ local sp = find_selected_code()
+ print("Found sp:",sp)
+end
+
+--Create the thing that shows possible nav nodes
+function self:ctor (container)
+ local editor = vgui.Create("DPanel",editorframe)
+ editor:Dock(FILL)
+
+ --Edit name
+ local namelabel = vgui.Create("DLabel",editor)
+ namelabel:SetText("Townie Name:")
+ namelabel:Dock(TOP)
+ namelabel:SetDark(true)
+ local nameentry = vgui.Create("DTextEntry",editor)
+ nameentry:Dock(TOP)
+ nameentry:SetText(data.Name)
+ nameentry:SetUpdateOnType(true)
+ nameentry.OnValueChange = function(self,value)
+ data.Name = value
+ end
+
+ --Edit model
+ local modellabel = vgui.Create("DLabel",editor)
+ modellabel:SetText("Townie Model:")
+ modellabel:Dock(TOP)
+ modellabel:SetDark(true)
+ local modelentry = vgui.Create("DTextEntry",editor)
+ modelentry:Dock(TOP)
+ modelentry:SetText(data.Model)
+ modelentry:SetUpdateOnType(true)
+ modelentry.OnValueChange = function(self,value)
+ data.Model = value
+ end
+
+ --Edit navnodes
+ local navnodelist = vgui.Create("DListLayout",editor)
+ navnodelist:Dock(FILL)
+ local allnavents = ents.FindByClass("info_townienode")
+
+ local function create_navnode_panel(v)
+ local navnodeitm = vgui.Create("DPanel")
+
+ local navname = vgui.Create("DComboBox",navnodeitm)
+ for i,j in pairs(navnode_info) do
+ navname:AddChoice(j.Name)
+ end
+ navname:SetValue(v)
+ navname:Dock(LEFT)
+ navname.OnSelect = function(self,index,value)
+ data.NavNodes[index] = value
+ end
+
+ local navdelete = vgui.Create("DButton",navnodeitm)
+ navdelete:SetText("-")
+ navdelete.DoClick = function()
+ print('Tryint to get rid of nav node', v)
+ --delete it from the data
+ for i,j in pairs(data.NavNodes) do
+ if j == v then
+ for k = i, #data.NavNodes do
+ data.NavNodes[i] = data.NavNodes[i+1]
+ end
+ break
+ end
+ end
+ --and remove the panel
+ navnodeitm:Remove()
+ end
+ navdelete:Dock(RIGHT)
+
+ return navnodeitm
+ end
+
+ for k,v in pairs(data.NavNodes) do
+ local navnodeitm = create_navnode_panel(v)
+ navnodelist:Add(navnodeitm)
+ end
+ local addbutton = vgui.Create("DButton",editor)
+ addbutton:SetText("+")
+ addbutton.DoClick = function()
+ local navnodeitm = create_navnode_panel("select")
+ navnodelist:Add(navnodeitm)
+ end
+ addbutton:Dock(BOTTOM)
+end
+
+function self:dtor ()
+ if self.HTMLPanel and self.HTMLPanel:IsValid () then
+ self.HTMLPanel:Remove ()
+ end
+ self.HTMLPanel = nil
+end
+
+-- Persistance
+function self:LoadSession (inBuffer)
+end
+
+function self:SaveSession (outBuffer)
+end
diff --git a/lua/autorun/setupzones.lua b/lua/autorun/setupzones.lua
new file mode 100644
index 0000000..bf1da4a
--- /dev/null
+++ b/lua/autorun/setupzones.lua
@@ -0,0 +1,14 @@
+--[[
+ Add a few differnt zone types to sandbox that can be placed around
+]]
+AddCSLuaFile("zones.lua")
+include("zones.lua")
+
+print("Hello from artery_editor.lua")
+if not zones then error("You must have the zones addon installed for artery_editor to work!") return end
+
+
+zones.RegisterClass("artery_town",Color(0,255,255))
+zones.RegisterClass("artery_outpost",Color(0,255,0))
+zones.RegisterClass("artery_huntingground",Color(255,255,0))
+zones.RegisterClass("artery_dungon",Color(255,0,255))
diff --git a/lua/autorun/sv_npc.lua b/lua/autorun/sv_npc.lua
new file mode 100644
index 0000000..2d7322d
--- /dev/null
+++ b/lua/autorun/sv_npc.lua
@@ -0,0 +1,121 @@
+if CLIENT then return end
+include("town.lua")
+local f = nrequire("concommands.lua")
+local npcs = {} --Master table of npcs
+local autocompletef
+
+function RegisterNPC(npc)
+ assert(npc ~= nil, "Attempted to register a nil npc")
+ assert(npc.Name ~= nil, "Attempted to register an npc without a name")
+ npcs[npc.Name] = npc
+ autocompletef = f.AutocompleteFunction(npcs)
+end
+
+function CreateNPCByName(npcname, pos)
+ assert(npcs[npcname],string.format("No npc named %q, valid names are:\n%s",npcname,table.concat(table.GetKeys(npcs),"\n")))
+ --print("Createing a ", npcname, " at ", pos)
+ local npctbl = npcs[npcname]
+ local npc = ents.Create("npc_huntable")
+ npc:SetPos(pos)
+
+ for k, v in pairs(npctbl) do
+ npc[k] = v
+ end
+
+ npc:Spawn()
+
+ return npc
+end
+
+--Creates a shop npc with this tbl
+function n.CreateShop(npc)
+ --print("Createing shop npc")
+ local npcent = ents.Create("npc_shop")
+ for k,v in pairs(npc) do
+ npcent[k] = v
+ end
+ npcent:Spawn()
+ --print("Called spawn")
+end
+
+--Creates a townie npc with this tbl
+function n.CreateTownie(tbl)
+ local npcent = ents.Create("npc_townie")
+ for k, v in pairs(tbl) do
+ npcent[k] = v
+ end
+ npcent:Spawn()
+end
+
+--Creates a new navigation node for npc's
+function n.CreateNavNode(tbl)
+ local nodeent = ents.Create("info_townienode")
+ assert(tbl ~= nil, "Tried to create a nil navnode")
+ for k, v in pairs(tbl) do
+ nodeent[k] = v
+ end
+ nodeent:Spawn()
+end
+
+--Ents to remove when refreshing the npc map
+local removeents = {"npc_townie", "info_townienode", "npc_shop"}
+
+-- "art_chest",
+for k, v in pairs(removeents) do
+ local eot = ents.FindByClass(v)
+ for i, j in pairs(eot) do
+ j:Remove()
+ end
+end
+
+local function ExecuteOnFolder(dir, recursive, func)
+ local path = ""
+ local fpath = table.concat({path,dir,"/*"})
+ local files, directories = file.Find(fpath,"DATA")
+ for k,v in pairs(files) do
+ local callpath = table.concat({path,dir,"/",v})
+ func(callpath)
+ end
+ if not recursive then return end
+ for k,v in pairs(directories) do
+ local npath = table.concat({dir,"/",v})
+ ExecuteOnFolder(npath,true,func)
+ end
+end
+
+local function loadMap()
+ local mapname = game.GetMap()
+
+ local foldername = "artery/maps/" .. mapname
+ ExecuteOnFolder(foldername,true,function(path)
+ --print("I want to run",path)
+ local filetxt = file.Read(path,"DATA")
+ --print("File text is", filetxt)
+ CompileString(filetxt,path)()
+ --print("I want to execute",path)
+ end)
+end
+
+hook.Add("InitPostEntity", "artery_spawnmapnpcs", function()
+ loadMap()
+end)
+
+concommand.Add("artery_reloadmap", function()
+ for k, v in pairs(removeents) do
+ local eot = ents.FindByClass(v)
+
+ for i, j in pairs(eot) do
+ j:Remove()
+ end
+ end
+
+ loadMap()
+end)
+
+concommand.Add("artery_makenpc", function(ply, cmd, args)
+ if not ply:IsAdmin() then return end
+ local na = args[1]
+ n.CreateNPCByName(na, ply:GetEyeTrace().HitPos)
+end, autocompletef)
+
+return n
diff --git a/lua/autorun/tab.lua b/lua/autorun/tab.lua
new file mode 100644
index 0000000..358715e
--- /dev/null
+++ b/lua/autorun/tab.lua
@@ -0,0 +1,16 @@
+print("Hello from a lua refresh!")
+if CLIENT then
+
+ spawnmenu.AddCreationTab( "Artery", function(...)
+
+ local panel = vgui.Create("DPanel")
+
+ local zoneeditor = vgui.Create("DButton", panel)
+ zoneeditor:SetText("Zone Editor Tool")
+ zoneeditor:SetConsoleCommand("give","weapon_zone_designator")
+ zoneeditor:SizeToContents()
+
+
+ return panel
+ end )
+end
diff --git a/lua/autorun/town.lua b/lua/autorun/town.lua
new file mode 100644
index 0000000..2805f7c
--- /dev/null
+++ b/lua/autorun/town.lua
@@ -0,0 +1,141 @@
+--[[
+ This file loads and saves towns and stuff
+]]
+if engine.ActiveGamemode() ~= "sandbox" then return end
+print("Hello from town.lua!")
+local currentfile
+--A fake nrequire
+local npcs = {}
+local fakes = {
+ ["sv_npcsystem.lua"] = {
+ CreateTownie = function(tbl)
+ print("got create townie table:")
+ PrintTable(tbl)
+ print("Spawning townie!")
+ --Make sure this townie dosen't already exist
+ for k,v in pairs(ents.FindByClass("info_towniespawn")) do
+ if v.File == currentfile then return end
+ end
+ --Spawn the townie editor
+ local e = ents.Create("info_towniespawn")
+ e:SetPos(tbl.Pos)
+ e:Spawn()
+ e.File = currentfile
+ e.data = {}
+ for k,v in pairs(tbl.NavNodes) do
+ e.data[#e.data + 1] = k
+ end
+ print("Ent's data is")
+ PrintTable(e.data)
+ end,
+ CreateNavNode = function(tbl)
+ print("got navnode table:",tbl)
+ PrintTable(tbl)
+ --Make sure this nav node dosen't already exist
+ for k,v in pairs(ents.FindByClass("info_edit_townienode")) do
+ print("Looking for nodes that connect to ", currentfile, v.File)
+ if v.File == currentfile then return end
+ end
+ --Spawn this navnode
+ local e = ents.Create("info_edit_townienode")
+ e:SetPos(tbl.Position)
+ e:Spawn()
+ e.File = currentfile
+ e.Name = tbl.Name
+ end,
+ CreateShop = function(tbl)
+ --Make sure this townie dosen't already exist
+ for k,v in pairs(ents.FindByClass("info_townieshop")) do
+ if v.File == currentfile then return end
+ end
+ --Spawn the townie editor
+ local e = ents.Create("info_towniespawn")
+ e:SetPos(tbl.Pos)
+ e:Spawn()
+ e.File = currentfile
+ end,
+ RegisterNPC = function(npc)
+ assert(npc ~= nil, "Attempted to register a nil npc")
+ assert(npc.Name ~= nil, "Attempted to register an npc without a name")
+ npcs[npc.Name] = npc
+ --autocompletef = f.AutocompleteFunction(npcs)
+ end,
+ CreateNPCByName = function(npcname, pos)
+ assert(npcs[npcname],string.format("No npc named %q, valid names are:\n%s",npcname,table.concat(table.GetKeys(npcs),"\n")))
+ --print("Createing a ", npcname, " at ", pos)
+ local npctbl = npcs[npcname]
+ local npc = ents.Create("npc_huntable")
+ npc:SetPos(pos)
+
+ for k, v in pairs(npctbl) do
+ npc[k] = v
+ end
+
+ npc:Spawn()
+
+ return npc
+ end
+ },
+ ["inventory/item.lua"] = {
+ GetItemByName = function(string)
+ return {}
+ end
+ }
+}
+fakes["core/npc/sv_npcsystem.lua"] = fakes["sv_npcsystem.lua"]
+local calls = {}
+function nrequire(string)
+ print("nrequire called")
+
+ local ntbl = {}
+ local nmeta = {}
+ nmeta.__index = function(self,key)
+ print("a table from nrequire was called",string,key)
+ local record = calls[string]
+ record[#record+1] = key
+ print("REturning", fakes[string][key])
+ return fakes[string][key]
+ end
+ setmetatable(ntbl,nmeta)
+ calls[string] = ntbl
+ return ntbl
+end
+
+local function ExecuteOnFolder(dir, recursive, func)
+ local path = ""
+ local fpath = table.concat({path,dir,"/*"})
+ local files, directories = file.Find(fpath,"DATA")
+ for k,v in pairs(files) do
+ local callpath = table.concat({path,dir,"/",v})
+ func(callpath)
+ end
+ if not recursive then return end
+ for k,v in pairs(directories) do
+ local npath = table.concat({dir,"/",v})
+ ExecuteOnFolder(npath,true,func)
+ end
+end
+
+function loadtownies()
+ --Remove any current townie things
+ for k,v in pairs(fakes) do
+ for i,j in pairs(ents.FindByClass(k)) do
+ j:Remove()
+ end
+ end
+
+ local mapname = game.GetMap()
+
+ local foldername = "artery/maps/" .. mapname
+ ExecuteOnFolder(foldername,true,function(path)
+ print("I want to run",path)
+ local filetxt = file.Read(path,"DATA")
+ print("File text is", filetxt)
+ currentfile = path
+ CompileString(filetxt,path)()
+ print("I want to execute",path)
+ end)
+end
+
+concommand.Add("artery_loadtownies",loadtownies)
+hook.Add("InitPostEntity","load_lua",loadtownies)
diff --git a/lua/autorun/zone_dungeon.lua b/lua/autorun/zone_dungeon.lua
new file mode 100644
index 0000000..2e0d6b0
--- /dev/null
+++ b/lua/autorun/zone_dungeon.lua
@@ -0,0 +1,146 @@
+--[[
+ A hunting ground zone will occasionally spawn a monster near a player that will go attack the player
+]]
+zones.RegisterClass("artery_dungeon",Color(255,0,255))
+
+--Use this to set default properties. Only called on server.
+hook.Add("OnZoneCreated","artery_dungeon",function(zone,class,zoneID)
+ if class == "artery_dungeon" then
+ zone.dungeoncontrol = nil
+ end
+end)
+
+local monsters = scripted_ents.GetList()
+
+-- Use this hook to let a player change a zone after making it or with the edit tool.
+-- class is zone.class, zone is the zone's full table, DPanel is a panel to parent your things to, zoneID is the zone's ID, DFrame is the whole frame.
+-- Return your preferred width and height for the panel and the frame will size to it.
+hook.Add("ShowZoneOptions","artery_huntingground",function(zone,class,DPanel,zoneID,DFrame)
+ if class == "artery_huntingground" then
+ local w,h = 500, 400
+
+ local scroll = vgui.Create( "DScrollPanel",DPanel)
+ scroll:Dock(FILL)
+
+ function synctbl()
+ net.Start("artery_hunting_settbl")
+ net.WriteFloat(zoneID)
+ net.WriteTable(zone.npctbl)
+ net.WriteString(zone.Name)
+ net.WriteUInt(zone.SpawnRate,16)
+ net.SendToServer()
+ end
+
+ print("Displaying table, my table is")
+ PrintTable(zone.npctbl)
+
+ local headerbar = vgui.Create("DPanel",scroll)
+ headerbar:Dock(TOP)
+ local monsterlb = vgui.Create("DLabel",headerbar)
+ monsterlb:Dock(LEFT)
+ monsterlb:SetText("Monster Type:")
+ monsterlb:SetDark(true)
+ monsterlb:SizeToContents()
+ local freqlb = vgui.Create("DLabel",headerbar)
+ freqlb:Dock(RIGHT)
+ freqlb:SetText("Spawn frequence (0-100)")
+ freqlb:SetDark(true)
+ freqlb:SizeToContents()
+
+ local groundslb = vgui.Create("DLabel",DPanel)
+ groundslb:Dock(TOP)
+ groundslb:SetText("Hunting ground name:")
+ groundslb:SetDark(true)
+ groundslb:SizeToContents()
+ local groundsname = vgui.Create("DTextEntry",DPanel)
+ groundsname:SetText(zone.Name or "")
+ groundsname:Dock(TOP)
+ groundsname.OnEnter = function()
+ zone.Name = groundsname:GetValue()
+ synctbl()
+ end
+
+ local spawnratelb = vgui.Create("DLabel",DPanel)
+ spawnratelb:Dock(TOP)
+ spawnratelb:SetText("Spawn Rate (in seconds, around 20 is good, lower is more frequent):")
+ spawnratelb:SetDark(true)
+ spawnratelb:SizeToContents()
+ local spawnrate = vgui.Create("DTextEntry",DPanel)
+ spawnrate:SetText(zone.SpawnRate or "20")
+ spawnrate:Dock(TOP)
+ spawnrate:SetNumeric(true)
+ spawnrate.OnEnter = function()
+ zone.SpawnRate = tonumber(spawnrate:GetValue())
+ synctbl()
+ end
+
+ local function mkrow(name,freq)
+ local thisbar = vgui.Create("DPanel",scroll)
+ thisbar:Dock(TOP)
+
+ local monstertype = vgui.Create("DComboBox",thisbar)
+ monstertype:Dock(LEFT)
+ for i,j in pairs(monsters) do
+ monstertype:AddChoice(j)
+ end
+ monstertype:SetValue(name)
+ monstertype.OnSelect = function(panel,index,value)
+ zone.npctbl[name] = nil
+ zone.npctbl[value] = freq
+ synctbl()
+ end
+ monstertype:SetSize(120,20)
+
+ local frequency = vgui.Create("DTextEntry",thisbar)
+ frequency:SetText(freq)
+ frequency:SetNumeric( true )
+ frequency:Dock(RIGHT)
+ frequency:SizeToContents()
+
+ local delete = vgui.Create("DButton",thisbar)
+ delete:SetText("-")
+ delete:Dock(RIGHT)
+ delete.DoClick = function()
+ print("Attempting to remove",thisbar)
+ zone.npctbl[name] = nil
+ thisbar:Remove()
+ end
+
+ function frequency.OnEnter()
+ zone.npctbl[name] = tonumber(frequency:GetValue())
+ synctbl()
+ end
+ end
+
+ print("Before drawing npctbl was")
+ PrintTable(zone.npctbl)
+ for k,v in pairs(zone.npctbl) do
+ mkrow(k,v)
+ end
+
+ local newpanelbut = vgui.Create("DButton",DPanel)
+ newpanelbut:SetText("+")
+ newpanelbut:Dock(BOTTOM)
+ newpanelbut.DoClick = function()
+ mkrow("Rat",0)
+ end
+
+ return w, h -- Specify the width and height for the DPanel container. The frame will resize accordingly.
+
+ end
+end)
+
+if SERVER then
+ util.AddNetworkString("artery_hunting_settbl")
+ net.Receive("artery_hunting_settbl",function(len,ply)
+ print("Server change received!")
+ local id, new, name, rate = net.ReadFloat(), net.ReadTable(), net.ReadString(), net.ReadUInt(16)
+ print("New table is:")
+ PrintTable(new)
+ if not ply:IsAdmin() then return end
+ zones.List[id].Name = name
+ zones.List[id].npctbl = new
+ zones.List[id].SpawnRate = rate
+ zones.Sync()
+ end)
+end
diff --git a/lua/autorun/zone_huntingground.lua b/lua/autorun/zone_huntingground.lua
new file mode 100644
index 0000000..cc494a1
--- /dev/null
+++ b/lua/autorun/zone_huntingground.lua
@@ -0,0 +1,176 @@
+--[[
+ A hunting ground zone will occasionally spawn a monster near a player that will go attack the player
+]]
+zones.RegisterClass("artery_huntingground",Color(255,255,0))
+
+--Use this to set default properties. Only called on server.
+hook.Add("OnZoneCreated","artery_huntingground",function(zone,class,zoneID)
+ if class == "artery_huntingground" then
+ zone.npctbl = {}
+ end
+end)
+
+--[[
+local monsters = {
+ --Skyrim
+ "npc_draugr_wight",
+ "npc_draugr",
+ "npc_draugr_deathlord",
+ "npc_draugr_overlord",
+ "npc_draugr_scourge",
+ "npc_draugr_wight",
+ "npc_draugr_restless",
+ "npc_scrib",
+ "npc_falmer",
+ "npc_falmer_gloomlurker",
+ "npc_falmer_nightprowler",
+ "npc_falmer_shadowmaster",
+ "npc_falmer_skulker",
+ "npc_mudcrab",
+ "npc_deathclaw",
+ --Fallout
+ "npc_tunneler",
+ "npc_tunneler_queen",
+}
+]]
+local monsters = scripted_ents.GetList()
+local sub = {}
+for k,v in pairs(monsters) do
+ if k:find("npc_") then
+ sub[#sub+1] = k
+ end
+end
+monsters = sub
+
+-- Use this hook to let a player change a zone after making it or with the edit tool.
+-- class is zone.class, zone is the zone's full table, DPanel is a panel to parent your things to, zoneID is the zone's ID, DFrame is the whole frame.
+-- Return your preferred width and height for the panel and the frame will size to it.
+hook.Add("ShowZoneOptions","artery_huntingground",function(zone,class,DPanel,zoneID,DFrame)
+ if class == "artery_huntingground" then
+ local w,h = 500, 400
+
+ local scroll = vgui.Create( "DScrollPanel",DPanel)
+ scroll:Dock(FILL)
+
+ function synctbl()
+ net.Start("artery_hunting_settbl")
+ net.WriteFloat(zoneID)
+ net.WriteTable(zone.npctbl or {})
+ net.WriteString(zone.Name or "")
+ net.WriteUInt(zone.SpawnRate or 0,16)
+ net.SendToServer()
+ end
+
+ print("Displaying table, my table is")
+ PrintTable(zone.npctbl)
+
+ local headerbar = vgui.Create("DPanel",scroll)
+ headerbar:Dock(TOP)
+ local monsterlb = vgui.Create("DLabel",headerbar)
+ monsterlb:Dock(LEFT)
+ monsterlb:SetText("Monster Type:")
+ monsterlb:SetDark(true)
+ monsterlb:SizeToContents()
+ local freqlb = vgui.Create("DLabel",headerbar)
+ freqlb:Dock(RIGHT)
+ freqlb:SetText("Spawn frequency (0-100)")
+ freqlb:SetDark(true)
+ freqlb:SizeToContents()
+
+ local groundslb = vgui.Create("DLabel",DPanel)
+ groundslb:Dock(TOP)
+ groundslb:SetText("Hunting ground name:")
+ groundslb:SetDark(true)
+ groundslb:SizeToContents()
+ local groundsname = vgui.Create("DTextEntry",DPanel)
+ groundsname:SetText(zone.Name or "")
+ groundsname:Dock(TOP)
+ groundsname.OnEnter = function()
+ zone.Name = groundsname:GetValue()
+ synctbl()
+ end
+
+ local spawnratelb = vgui.Create("DLabel",DPanel)
+ spawnratelb:Dock(TOP)
+ spawnratelb:SetText("Spawn Rate (in seconds, around 20 is good, lower is more frequent):")
+ spawnratelb:SetDark(true)
+ spawnratelb:SizeToContents()
+ local spawnrate = vgui.Create("DTextEntry",DPanel)
+ spawnrate:SetText(zone.SpawnRate or "20")
+ spawnrate:Dock(TOP)
+ spawnrate:SetNumeric(true)
+ spawnrate.OnEnter = function()
+ zone.SpawnRate = tonumber(spawnrate:GetValue())
+ synctbl()
+ end
+
+ local function mkrow(name,freq)
+ local thisbar = vgui.Create("DPanel",scroll)
+ thisbar:Dock(TOP)
+
+ local monstertype = vgui.Create("DComboBox",thisbar)
+ monstertype:Dock(LEFT)
+ for i,j in pairs(monsters) do
+ monstertype:AddChoice(j)
+ end
+ monstertype:SetValue(name)
+ monstertype.OnSelect = function(panel,index,value)
+ zone.npctbl[name] = nil
+ zone.npctbl[value] = freq
+ synctbl()
+ end
+ monstertype:SetSize(120,20)
+
+ local frequency = vgui.Create("DTextEntry",thisbar)
+ frequency:SetText(freq)
+ frequency:SetNumeric( true )
+ frequency:Dock(RIGHT)
+ frequency:SizeToContents()
+
+ local delete = vgui.Create("DButton",thisbar)
+ delete:SetText("-")
+ delete:Dock(RIGHT)
+ delete.DoClick = function()
+ print("Attempting to remove",thisbar)
+ zone.npctbl[name] = nil
+ thisbar:Remove()
+ end
+
+ function frequency.OnEnter()
+ zone.npctbl[name] = tonumber(frequency:GetValue())
+ synctbl()
+ end
+ end
+
+ print("Before drawing npctbl was")
+ PrintTable(zone.npctbl)
+ for k,v in pairs(zone.npctbl) do
+ mkrow(k,v)
+ end
+
+ local newpanelbut = vgui.Create("DButton",DPanel)
+ newpanelbut:SetText("+")
+ newpanelbut:Dock(BOTTOM)
+ newpanelbut.DoClick = function()
+ mkrow(monsters[1],0)
+ end
+
+ return w, h -- Specify the width and height for the DPanel container. The frame will resize accordingly.
+
+ end
+end)
+
+if SERVER then
+ util.AddNetworkString("artery_hunting_settbl")
+ net.Receive("artery_hunting_settbl",function(len,ply)
+ print("Server change received!")
+ local id, new, name, rate = net.ReadFloat(), net.ReadTable(), net.ReadString(), net.ReadUInt(16)
+ print("New table is:")
+ PrintTable(new)
+ if not ply:IsAdmin() then return end
+ zones.List[id].Name = name
+ zones.List[id].npctbl = new
+ zones.List[id].SpawnRate = rate
+ zones.Sync()
+ end)
+end
diff --git a/lua/autorun/zone_serverchanger.lua b/lua/autorun/zone_serverchanger.lua
new file mode 100644
index 0000000..afb92a6
--- /dev/null
+++ b/lua/autorun/zone_serverchanger.lua
@@ -0,0 +1,84 @@
+--[[
+ A server changer will "teleport" the player between instances
+]]
+
+zones.RegisterClass("artery_serverchange",Color(255,255,255))
+
+--Use this to set default properties. Only called on server.
+hook.Add("OnZoneCreated","artery_serverchange",function(zone,class,zoneID)
+ if class == "artery_serverchange" then
+ zone.toserver = game.GetIPAddress()
+ zone.topos = Vector(0,0,0)
+
+ end
+end)
+
+-- Use this hook to let a player change a zone after making it or with the edit tool.
+-- class is zone.class, zone is the zone's full table, DPanel is a panel to parent your things to, zoneID is the zone's ID, DFrame is the whole frame.
+-- Return your preferred width and height for the panel and the frame will size to it.
+hook.Add("ShowZoneOptions","artery_serverchange",function(zone,class,DPanel,zoneID,DFrame)
+ if class == "artery_serverchange" then
+ local w,h = 500, 400
+
+ local tobl = Label("To Server:")
+ tobl:SetParent(DPanel)
+ tobl:Dock(TOP)
+ tobl:SetTextColor(color_black)
+ tobl:SizeToContents()
+
+ local to = vgui.Create("DTextEntry",DPanel) --parent to the panel.
+ to:Dock(TOP)
+ to:SetValue(zone.toserver)
+ function to:OnChange(new)
+ print("server's onvaluechanged has been called")
+ net.Start("artery_serverchange")
+ net.WriteFloat(zoneID)
+ net.WriteString(new)
+ net.SendToServer()
+ end
+
+ local poslbl = Label("To position:")
+ poslbl:SetParent(DPanel)
+ poslbl:Dock(TOP)
+ poslbl:SetTextColor(color_black)
+ poslbl:SizeToContents()
+
+ for k,v in pairs({"x","y","z"}) do
+ local post = vgui.Create("DTextEntry",DPanel)
+ post:SetValue(zone.topos[v])
+ post:Dock(TOP)
+ post:SetNumeric( true )
+ function post:OnChange(new)
+ print("Sending pos change")
+ net.Start("artery_poschange")
+ net.WriteFloat(zoneID)
+ net.WriteString(v)
+ net.WriteString(self:GetText())
+ net.SendToServer()
+ end
+ end
+ return w, h -- Specify the width and height for the DPanel container. The frame will resize accordingly.
+
+ end
+end)
+
+if SERVER then
+ util.AddNetworkString("artery_serverchange")
+ util.AddNetworkString("artery_poschange")
+ net.Receive("artery_serverchange",function(len,ply)
+ print("Server change received!")
+ local id, new = net.ReadFloat(), net.ReadString()
+ if not ply:IsAdmin() then return end
+ zones.List[id].toserver = new
+ zones.Sync()
+ end)
+ net.Receive("artery_poschange",function(len,ply)
+ print("poschange received!")
+ local id,v,w = net.ReadFloat(), net.ReadString(), net.ReadString()
+ if not ply:IsAdmin() then return end
+ zones.List[id].topos[v] = tonumber(w) or 0
+ zones.Sync()
+ print("zone",id,"is now set to")
+ PrintTable(zones.List[id])
+ end)
+end
diff --git a/lua/autorun/zone_town.lua b/lua/autorun/zone_town.lua
new file mode 100644
index 0000000..a068021
--- /dev/null
+++ b/lua/autorun/zone_town.lua
@@ -0,0 +1,62 @@
+--[[
+ A hunting ground zone will occasionally spawn a monster near a player that will go attack the player
+]]
+zones.RegisterClass("artery_town",Color(0,255,0))
+
+--Use this to set default properties. Only called on server.
+hook.Add("OnZoneCreated","artery_town",function(zone,class,zoneID)
+ if class == "artery_town" then
+ zone.npctbl = {}
+ end
+end)
+
+-- Use this hook to let a player change a zone after making it or with the edit tool.
+-- class is zone.class, zone is the zone's full table, DPanel is a panel to parent your things to, zoneID is the zone's ID, DFrame is the whole frame.
+-- Return your preferred width and height for the panel and the frame will size to it.
+hook.Add("ShowZoneOptions","artery_town",function(zone,class,DPanel,zoneID,DFrame)
+ if class == "artery_town" then
+ local w,h = 500, 400
+
+ local scroll = vgui.Create( "DScrollPanel",DPanel)
+ scroll:Dock(FILL)
+
+ function synctbl()
+ net.Start("artery_town_settbl")
+ net.WriteFloat(zoneID)
+ net.WriteTable(zone.npctbl)
+ net.SendToServer()
+ end
+
+ print("Displaying table, my table is")
+ PrintTable(zone.npctbl)
+
+ local monsterlb = vgui.Create("DLabel",DPanel)
+ monsterlb:Dock(TOP)
+ monsterlb:SetText("Town name:")
+ monsterlb:SetDark(true)
+ monsterlb:SizeToContents()
+ local groundsname = vgui.Create("DTextEntry",DPanel)
+ groundsname:SetText(zone.npctbl.Name or "")
+ groundsname:Dock(TOP)
+ groundsname.OnEnter = function()
+ zone.npctbl.Name = groundsname:GetValue()
+ synctbl()
+ end
+
+ return w, h -- Specify the width and height for the DPanel container. The frame will resize accordingly.
+
+ end
+end)
+
+if SERVER then
+ util.AddNetworkString("artery_town_settbl")
+ net.Receive("artery_town_settbl",function(len,ply)
+ print("Server change received!")
+ local id, new = net.ReadFloat(), net.ReadTable()
+ print("New table is:")
+ PrintTable(new)
+ if not ply:IsAdmin() then return end
+ zones.List[id].npctbl = new
+ zones.Sync()
+ end)
+end
diff --git a/lua/entities/info_edit_townienode/cl_init.lua b/lua/entities/info_edit_townienode/cl_init.lua
new file mode 100644
index 0000000..87d4201
--- /dev/null
+++ b/lua/entities/info_edit_townienode/cl_init.lua
@@ -0,0 +1,74 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+include("shared.lua")
+
+ENT.RenderGroup = RENDERGROUP_BOTH
+
+function ENT:Draw()
+ render.SetColorMaterial()
+ render.DrawSphere( self:GetPos(), 10, 30, 30, Color( 0, 175, 175, 100 ) )
+
+end
+
+local function syncentity(ent,data)
+ print("sending data to server")
+ net.Start("edit_townienode_update")
+ net.WriteEntity(ent)
+ net.WriteTable(data)
+ net.SendToServer()
+end
+
+net.Receive("edit_navnode",function()
+ local who = net.ReadEntity()
+ local data = net.ReadTable()
+
+ local editorframe = vgui.Create("DFrame")
+ editorframe:SetSize(640,480)
+ editorframe:SetDraggable(true)
+ editorframe:MakePopup()
+ editorframe.OnClose = function(self)
+ syncentity(who,data)
+ end
+
+ local editor = vgui.Create("DPanel",editorframe)
+ editor:Dock(FILL)
+
+ local namelabel = vgui.Create("DLabel",editor)
+ namelabel:SetText("Name:")
+ namelabel:SetDark(true)
+ namelabel:Dock(TOP)
+ local nametext = vgui.Create("DTextEntry",editor)
+ nametext:Dock(TOP)
+ nametext:SetText(data.Name)
+ nametext:SetUpdateOnType(true)
+ nametext.OnValueChange = function(self,value)
+ data.Name = value
+ end
+
+ local onreachedlabel = vgui.Create("DLabel",editor)
+ onreachedlabel:SetText("OnReached()")
+ onreachedlabel:SetDark(true)
+ onreachedlabel:Dock(TOP)
+ local onreachedtext = vgui.Create("DTextEntry",editor)
+ onreachedtext:SetHeight(150)
+ onreachedtext:Dock(TOP)
+ onreachedtext:SetMultiline(true)
+ onreachedtext:SetText(data.OnReached)
+ onreachedtext:SetTabbingDisabled(true)
+ onreachedtext.OnValueChange = function(self,value)
+ data.OnReached = value
+ end
+
+ local isfinlabel = vgui.Create("DLabel",editor)
+ isfinlabel:SetText("IsFinished()")
+ isfinlabel:SetDark(true)
+ isfinlabel:Dock(TOP)
+ local isfintext = vgui.Create("DTextEntry",editor)
+ isfintext:SetHeight(150)
+ isfintext:Dock(TOP)
+ isfintext:SetMultiline(true)
+ isfintext:SetText(data.IsDone)
+ isfintext.OnValueChange = function(self,value)
+ data.IsDone = value
+ end
+end)
diff --git a/lua/entities/info_edit_townienode/init.lua b/lua/entities/info_edit_townienode/init.lua
new file mode 100644
index 0000000..e4702da
--- /dev/null
+++ b/lua/entities/info_edit_townienode/init.lua
@@ -0,0 +1,54 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+AddCSLuaFile( "cl_init.lua" ) -- Make sure clientside
+AddCSLuaFile( "shared.lua" ) -- and shared scripts are sent.
+
+include('shared.lua')
+
+ENT.default_data = {
+ Model = "models/humans/Group02/Male_03.mdl",
+ NavNodes = {},
+ Pos = nil
+}
+
+ENT.edit_data = {
+ Size = HULL_TINY,
+ Type = "navnode",
+ Model = "models/editor/ground_node.mdl",
+ get_default_code = function(who)
+ local default_navnode = [[
+
+
+
+
+local node = {
+ ["Name"] = "%s", --@tagname
+ ["Position"] = Vector(%f, %f, %f), --@tagpos
+ ["OnReached"] = function(npc)
+
+ end,
+ ["IsDone"] = function(npc)
+
+ end,
+}
+nrequire("sv_npcsystem.lua").CreateNavNode(node)
+ ]]
+ local pos = who:GetPos()
+ local name = "Default Node"
+ return string.format(default_navnode,name,pos.x,pos.y,pos.z)
+ end
+}
+local init = ENT.Initalize
+function ENT:Initalize()
+ print("In towniespawn's initalize")
+ init(self)
+end
+
+function ENT:OnSave()
+ print("Node's OnSave was called")
+ local newtxt = file.Read(self.File,"DATA")
+ print("new text was",newtxt)
+ local newname = newtxt:match("%[\"Name\"%] = \"(.-)\", %-%-@tagname")
+ print("new name is,",newname)
+ self.Name = newname
+end
diff --git a/lua/entities/info_edit_townienode/shared.lua b/lua/entities/info_edit_townienode/shared.lua
new file mode 100644
index 0000000..2197cb6
--- /dev/null
+++ b/lua/entities/info_edit_townienode/shared.lua
@@ -0,0 +1,13 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+ENT.Type = "anim"
+ENT.Base = "info_programmable_base"
+
+ENT.PrintName= "Townie Node"
+ENT.Author= "Apickx"
+ENT.Contact= "cogarr.net"
+ENT.Purpose= "Set a point of intrest"
+ENT.Instructions= "Make sure the npc knows to go to this node"
+ENT.Spawnable = true
+ENT.AdminSpawnable = false
+ENT.Category = "Artery"
diff --git a/lua/entities/info_huntablespawn/cl_init.lua b/lua/entities/info_huntablespawn/cl_init.lua
new file mode 100644
index 0000000..6a96b80
--- /dev/null
+++ b/lua/entities/info_huntablespawn/cl_init.lua
@@ -0,0 +1,71 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+include('shared.lua')
+
+ENT.RenderGroup = RENDERGROUP_BOTH
+
+/*---------------------------------------------------------
+ Name: Draw
+ Desc: Draw it!
+---------------------------------------------------------*/
+function ENT:Draw()
+ --self:DrawModel()
+ render.SetColorMaterial()
+ render.DrawSphere( self:GetPos(), 10, 30, 30, Color( 255, 0, 0, 100 ) )
+
+end
+
+/*---------------------------------------------------------
+ Name: DrawTranslucent
+ Desc: Draw translucent
+---------------------------------------------------------*/
+function ENT:DrawTranslucent()
+
+ // This is here just to make it backwards compatible.
+ // You shouldn't really be drawing your model here unless it's translucent
+
+ --self:Draw()
+
+end
+
+/*---------------------------------------------------------
+ Name: BuildBonePositions
+ Desc:
+---------------------------------------------------------*/
+function ENT:BuildBonePositions( NumBones, NumPhysBones )
+
+ // You can use this section to position the bones of
+ // any animated model using self:SetBonePosition( BoneNum, Pos, Angle )
+
+ // This will override any animation data and isn't meant as a
+ // replacement for animations. We're using this to position the limbs
+ // of ragdolls.
+
+end
+
+
+
+/*---------------------------------------------------------
+ Name: SetRagdollBones
+ Desc:
+---------------------------------------------------------*/
+function ENT:SetRagdollBones( bIn )
+
+ // If this is set to true then the engine will call
+ // DoRagdollBone (below) for each ragdoll bone.
+ // It will then automatically fill in the rest of the bones
+
+ self.m_bRagdollSetup = bIn
+
+end
+
+
+/*---------------------------------------------------------
+ Name: DoRagdollBone
+ Desc:
+---------------------------------------------------------*/
+function ENT:DoRagdollBone( PhysBoneNum, BoneNum )
+
+ // self:SetBonePosition( BoneNum, Pos, Angle )
+
+end
diff --git a/lua/entities/info_huntablespawn/init.lua b/lua/entities/info_huntablespawn/init.lua
new file mode 100644
index 0000000..20cac81
--- /dev/null
+++ b/lua/entities/info_huntablespawn/init.lua
@@ -0,0 +1,18 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+--[[
+ This entity gives townies things to do
+]]
+AddCSLuaFile( "cl_init.lua" )
+AddCSLuaFile( "shared.lua" )
+
+include("shared.lua")
+
+function ENT:Initialize()
+ self:SetModel("models/error.mdl")
+ self:SetMoveType(MOVETYPE_NONE)
+ self:SetSolid(SOLID_NONE)
+ self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
+ --self:SetNoDraw(true)
+ self:SetPos(self.Position)
+end
diff --git a/lua/entities/info_huntablespawn/shared.lua b/lua/entities/info_huntablespawn/shared.lua
new file mode 100644
index 0000000..4fd0019
--- /dev/null
+++ b/lua/entities/info_huntablespawn/shared.lua
@@ -0,0 +1,27 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+ENT.Base = "base_entity"
+
+//WS stuff
+ENT.Drops = nil
+ENT.OnDammage = nil
+ENT.Speed = 0
+ENT.Model = nil
+
+ENT.Behave = nil
+ENT.Act = nil
+
+ENT.Editable = true
+
+/*---------------------------------------------------------
+ Name: OnRemove
+ Desc: Called just before entity is deleted
+---------------------------------------------------------*/
+function ENT:OnRemove()
+end
+
+function ENT:DoActivity(npc)
+ if not self.onActivity() then
+ print("Node without activity, this might be an error!")
+ end
+end
diff --git a/lua/entities/info_programmable_base/cl_init.lua b/lua/entities/info_programmable_base/cl_init.lua
new file mode 100644
index 0000000..fc1ada0
--- /dev/null
+++ b/lua/entities/info_programmable_base/cl_init.lua
@@ -0,0 +1,124 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+include('shared.lua')
+
+--Don't draw our hull model
+function ENT:Draw()
+end
+
+local function draw_edit_panel(filename,who)
+ if not GCompute then error("GCompute not installed!") end
+ if not GCompute.IDE then error("GCompute was initalized wrong or has changed, update this file!") end
+ local inst = GCompute.IDE.GetInstance()
+ inst:SetVisible (true)
+
+ print("Opening file browser!")
+
+ --Remove donation panel
+ for k,v in pairs(inst.ViewManager.Views) do
+ if type(k) == "table" and k.Title == "Donate!" then
+ k:SetVisible(false)
+ end
+ end
+
+ local fileuri = "game/data/" .. filename
+ print("Trying to open","game/data/" .. filename)
+
+ --Open up this npc's file
+ inst:OpenFile(fileuri,function(succ,res,view)
+ view:Select()
+ end)
+
+ --Set our file browser to the right place
+ for k,v in pairs(inst.ViewManager.Views) do
+ if k.Title == "File Browser" then
+
+ k.FolderListView:SetPath(string.GetPathFromFilename(fileuri))
+ end
+ end
+
+ --Detour it's save to let the server know the file was saved.
+ local doc = inst.DocumentManager.DocumentsByUri[fileuri]
+ print("Doc was",doc)
+ doc:AddEventListener("Saved",function()
+ print("Saved",doc)
+ net.Start("edit_sendsave")
+ net.WriteString(doc.Uri)
+ net.WriteEntity(who)
+ net.SendToServer()
+ end)
+
+
+end
+
+function Reload_Gcompute(what)
+ print("attempting to refresh instances of ", what)
+ local inst = GCompute.IDE:GetInstance()
+ for k,v in pairs(inst.ViewManager.ViewsById) do
+ if v.Title == what then
+ v:CreateFileChangeNotificationBar ()
+ v.FileChangeNotificationBar:DispatchEvent("ReloadRequested")
+ local oldvisible = v.FileChangeNotificationBar.SetVisible
+ v.FileChangeNotificationBar.SetVisible = function(self,bool)
+ if bool then
+ self.SetVisible = oldvisible
+ end
+ end
+ break
+ end
+ end
+end
+
+net.Receive("edit_notify_file_changed",function()
+ local what = net.ReadString()
+ Reload_Gcompute(what)
+end)
+
+net.Receive("edit_confirmremove",function()
+ local who = net.ReadString()
+ local frame = vgui.Create( "DFrame" )
+ frame:SetSize( 300, 250 )
+ frame:Center()
+ frame:MakePopup()
+
+ local but = vgui.Create( "DButton", frame )
+ but:SetText( "\nYes, I want to remove\n" .. who .. "\n")
+ but:Dock(TOP)
+ but.DoClick = function() // A custom function run when clicked ( note the . instead of : )
+ net.Start("edit_removeconfirmed")
+ net.WriteString(who)
+ net.SendToServer()
+ frame:Close()
+ end
+
+ local but2 = vgui.Create("DButton",frame)
+ but2:SetText("\nNo I don't want to remove\n" .. who .. "\n")
+ but2:Dock(BOTTOM)
+ but2.DoClick = function() // A custom function run when clicked ( note the . instead of : )
+ net.Start("edit_removedeny")
+ net.WriteString(who)
+ net.SendToServer()
+ frame:Close()
+ end
+ but:SizeToContents()
+ but2:SizeToContents()
+end)
+
+net.Receive("edit_sendopen",function()
+
+ print('got request to edit someone')
+ local file = net.ReadString()
+ local who = net.ReadEntity()
+ print(file)
+ draw_edit_panel(file,who)
+end)
+
+hook.Add( "Think", "edit_type_tip", function()
+ local tr = LocalPlayer():GetEyeTrace()
+ local e = tr.Entity
+ if e.Entity then
+ AddWorldTip( nil, e:GetClass(), nil, tr.HitPos, e )
+ end
+
+
+end )
diff --git a/lua/entities/info_programmable_base/init.lua b/lua/entities/info_programmable_base/init.lua
new file mode 100644
index 0000000..9fed830
--- /dev/null
+++ b/lua/entities/info_programmable_base/init.lua
@@ -0,0 +1,148 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+AddCSLuaFile( "cl_init.lua" ) -- Make sure clientside
+AddCSLuaFile( "shared.lua" ) -- and shared scripts are sent.
+
+include('shared.lua')
+
+local file_base = string.format("artery/maps/%s",game.GetMap())
+
+local hulls = {
+ [HULL_HUMAN] = {
+ Model = "models/props_phx/construct/metal_tubex2.mdl",
+ Angle = Angle(0,0,0)
+ },
+ [HULL_TINY] = {
+ Model = "models/props_phx/construct/metal_tube.mdl",
+ Angle = Angle(0,0,0)
+ }
+}
+
+function ENT:Initialize()
+ --The hull
+ local thull = hulls[self.edit_data.Size]
+ self:SetModel(thull.Model)
+ self:SetAngles(thull.Angle)
+
+ --The entity
+ self:PhysicsInit( SOLID_VPHYSICS ) -- Make us work with physics,
+ self:SetMoveType( MOVETYPE_VPHYSICS ) -- after all, gmod is a physics
+ self:SetSolid( SOLID_VPHYSICS ) -- Toolbox
+ --[[
+ local phys = self:GetPhysicsObject()
+ if (phys:IsValid()) then
+ phys:Wake()
+ end
+ ]]
+ self:SetCollisionGroup(COLLISION_GROUP_WORLD)
+ self:SetUseType(SIMPLE_USE)
+
+ print("My edit data:",self)
+ PrintTable(self.edit_data)
+
+ --The visual
+ local e = ents.Create("prop_dynamic")
+ e:SetPos(self:GetPos())
+ e:SetModel(self.edit_data.Model)
+ if self.edit_data.OnSpawn ~= nil then
+ self.edit_data.OnSpawn(self)
+ end
+ e:SetParent(self)
+ e:Spawn()
+
+ --Make sure the folder we want to be in exists
+ local grouping = self.edit_data.Type or ""
+ local folder = string.format("%s/%s",file_base,grouping)
+ if not file.Exists(folder,"DATA") then
+ print("Createing dir",folder)
+ file.CreateDir(folder)
+ end
+
+ --Make sure whoever made us has attached a file
+ if self.File == nil then
+ print("Createing a new file for",self)
+ local c = self:GetClass()
+ local ind = #ents.FindByClass(c)
+ print("Found",ind,"number of",c)
+ self.File = string.format("%s/%s_%d.txt",folder,c,ind)
+ end
+ assert(self.File, "A programmable entity was made without a file attached!")
+
+end
+
+hook.Add("OnPhysgunFreeze","programmable_freezer",function(wep,phys,ent,ply)
+ print("I want to do something to ",ent)
+ if ent.RefreshChangeables ~= nil then
+ ent:RefreshChangeables()
+ end
+end)
+
+util.AddNetworkString("edit_notify_file_changed")
+function ENT:notify_file_changed(what)
+ net.Start("edit_notify_file_changed")
+ net.WriteString(string.GetFileFromFilename(what))
+ net.Broadcast()
+end
+
+function ENT:RefreshChangeables()
+ print("I",self,"Want to refresh my changeables in",self.File)
+ local filetxt = file.Read(self.File,"DATA")
+ print("filetxt was",filetxt)
+ if not filetxt then return end --We haven't pressed e to generate the file yet
+ --Oh god this is one hell of a pattern. Just trust that it works I guess
+ local pos = self:GetPos()
+ local ang = self:GetAngles()
+ local ntxt = filetxt
+ :gsub("Vector[^\n]*%-%-@tagpos",string.format("Vector(%f,%f,%f), --@tagpos",pos.x,pos.y,pos.z))
+ :gsub("Angle[^\n]*%-%-@tagang",string.format("Angle(%f,%f,%f), --@tagang",ang.p,ang.y,ang.r))
+ print("Writeing to",self.File,ntxt)
+ file.Write(self.File,ntxt)
+ self:notify_file_changed(self.File)
+end
+
+util.AddNetworkString("edit_confirmremove")
+util.AddNetworkString("edit_removeconfirmed")
+util.AddNetworkString("edit_removedeny")
+function ENT:OnRemove()
+ net.Start("edit_confirmremove")
+ net.WriteString(self.File)
+ net.Send(Entity(1))
+ return false
+end
+net.Receive("edit_removeconfirmed",function()
+ local who = net.ReadString()
+ file.Delete(who)
+end)
+net.Receive("edit_removedeny",function()
+ local who = net.ReadString()
+ loadtownies()
+end)
+
+util.AddNetworkString("edit_sendopen")
+function ENT:Use( activator, caller )
+ --Open up the npc's file (create it if it dosen't already exist)
+ if not file.Exists(self.File, "DATA") then
+ file.Write(self.File,self.edit_data.get_default_code(self))
+ end
+
+ net.Start("edit_sendopen");
+ net.WriteString(self.File)
+ net.WriteEntity(self)
+ net.Send(caller)
+end
+
+util.AddNetworkString("edit_sendsave")
+net.Receive("edit_sendsave",function()
+ local file = net.ReadString()
+ local who = net.ReadEntity()
+ print("I got a save for", file, who)
+ who:OnSave()
+end)
+
+function ENT:OnSave()
+ print("On save was called!")
+end
+
+function ENT:Think()
+-- We don't need to think, we are just a prop after all!
+end
diff --git a/lua/entities/info_programmable_base/shared.lua b/lua/entities/info_programmable_base/shared.lua
new file mode 100644
index 0000000..86de4d2
--- /dev/null
+++ b/lua/entities/info_programmable_base/shared.lua
@@ -0,0 +1,12 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+ENT.Base = "base_entity"
+
+ENT.PrintName= "Programmable base"
+ENT.Author= "Apickx"
+ENT.Contact= "cogarr.net"
+ENT.Purpose= "A base for other programmables"
+ENT.Instructions= "Don't use this probably!"
+ENT.Spawnable = false
+ENT.AdminSpawnable = false
+ENT.Category = "Artery"
diff --git a/lua/entities/info_townieshop/cl_init.lua b/lua/entities/info_townieshop/cl_init.lua
new file mode 100644
index 0000000..2caccd4
--- /dev/null
+++ b/lua/entities/info_townieshop/cl_init.lua
@@ -0,0 +1,173 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+include('shared.lua')
+
+function ENT:Draw()
+ --self:DrawModel() -- Draws Model Client Side
+end
+
+function ENT:Hint()
+ AddWorldTip( self:EntIndex(), "Spawnpoint", 0.5, self:GetPos(), self )
+end
+
+local function syncentity(ent,data)
+ print("sending data to server")
+ PrintTable(data)
+ net.Start("edit_towniespawn_update")
+ net.WriteEntity(ent)
+ net.WriteTable(data)
+ net.SendToServer()
+end
+
+local navnode_info = {}
+
+concommand.Add("artery_getnavnodes",function()
+ net.Start("edit_requestnavnodes")
+ net.SendToServer()
+end)
+
+net.Receive("edit_respondnavnodes",function()
+ navnode_info = net.ReadTable()
+ print("client received navnode info:")
+ PrintTable(navnode_info)
+end)
+
+local function draw_edit_panel(who, data)
+ if not GCompute then error("GCompute not installed!") end
+ if not GCompute.IDE then error("GCompute was initalized wrong or has changed, update this file!") end
+ local inst = GCompute.IDE.GetInstance()
+ inst:SetVisible (true)
+
+ print("Opening file browser!")
+ PrintTable(data)
+
+ --Remove donation panel
+ for k,v in pairs(inst.ViewManager.Views) do
+ if type(k) == "Table" and k.Title == "Donate!" then
+ k:SetVisible(false)
+ end
+ end
+
+ --Open up the npc's file (create it if it dosen't already exist)
+ local filename = "artery/maps/" .. game.GetMap() .. "/npcs/" .. data.Name .. ".txt"
+ if not file.Exists(filename, "DATA") then
+ local pos = who:GetPos()
+ local npctxt = string.format(default_townie,pos.x,pos.y,pos.z,data.Model,data.Name,table.concat(data.NavNodes),data.Name)
+ file.Write(filename,npctxt)
+ end
+
+ --Open up this npc's file
+ inst:OpenUri("game/data/" .. filename,function(succ,res,view)
+ view:Select()
+ end)
+
+ --Set our file browser to the right place
+ for k,v in pairs(inst.ViewManager.Views) do
+ if k.Title == "File Browser" then
+ k.FolderListView:SetPath("/game/data/artery/maps/" .. game.GetMap() .. "/npcs")
+ end
+ end
+
+ --Add a list of nav nodes we found
+ local p = ents.FindByClass("info_townienode")
+
+end
+
+net.Receive("edit_towniespawn",function()
+
+ print('got request to edit someone')
+ local who = net.ReadEntity()
+ local data = net.ReadTable()
+
+ draw_edit_panel(who,data)
+
+ --[[
+ local editorframe = vgui.Create("DFrame")
+ editorframe.OnClose = function(self)
+ syncentity(who,data)
+ end
+ editorframe:SetSize(640,640)
+ editorframe:SetTitle("Townie spawn")
+ editorframe:SetDraggable(true)
+ editorframe:MakePopup()
+ local editor = vgui.Create("DPanel",editorframe)
+ editor:Dock(FILL)
+
+ --Edit name
+ local namelabel = vgui.Create("DLabel",editor)
+ namelabel:SetText("Townie Name:")
+ namelabel:Dock(TOP)
+ namelabel:SetDark(true)
+ local nameentry = vgui.Create("DTextEntry",editor)
+ nameentry:Dock(TOP)
+ nameentry:SetText(data.Name)
+ nameentry:SetUpdateOnType(true)
+ nameentry.OnValueChange = function(self,value)
+ data.Name = value
+ end
+
+ --Edit model
+ local modellabel = vgui.Create("DLabel",editor)
+ modellabel:SetText("Townie Model:")
+ modellabel:Dock(TOP)
+ modellabel:SetDark(true)
+ local modelentry = vgui.Create("DTextEntry",editor)
+ modelentry:Dock(TOP)
+ modelentry:SetText(data.Model)
+ modelentry:SetUpdateOnType(true)
+ modelentry.OnValueChange = function(self,value)
+ data.Model = value
+ end
+
+ --Edit navnodes
+ local navnodelist = vgui.Create("DListLayout",editor)
+ navnodelist:Dock(FILL)
+ local allnavents = ents.FindByClass("info_townienode")
+
+ local function create_navnode_panel(v)
+ local navnodeitm = vgui.Create("DPanel")
+
+ local navname = vgui.Create("DComboBox",navnodeitm)
+ for i,j in pairs(navnode_info) do
+ navname:AddChoice(j.Name)
+ end
+ navname:SetValue(v)
+ navname:Dock(LEFT)
+ navname.OnSelect = function(self,index,value)
+ data.NavNodes[index] = value
+ end
+
+ local navdelete = vgui.Create("DButton",navnodeitm)
+ navdelete:SetText("-")
+ navdelete.DoClick = function()
+ print('Tryint to get rid of nav node', v)
+ --delete it from the data
+ for i,j in pairs(data.NavNodes) do
+ if j == v then
+ for k = i, #data.NavNodes do
+ data.NavNodes[i] = data.NavNodes[i+1]
+ end
+ break
+ end
+ end
+ --and remove the panel
+ navnodeitm:Remove()
+ end
+ navdelete:Dock(RIGHT)
+
+ return navnodeitm
+ end
+
+ for k,v in pairs(data.NavNodes) do
+ local navnodeitm = create_navnode_panel(v)
+ navnodelist:Add(navnodeitm)
+ end
+ local addbutton = vgui.Create("DButton",editor)
+ addbutton:SetText("+")
+ addbutton.DoClick = function()
+ local navnodeitm = create_navnode_panel("select")
+ navnodelist:Add(navnodeitm)
+ end
+ addbutton:Dock(BOTTOM)
+ ]]
+end)
diff --git a/lua/entities/info_townieshop/init.lua b/lua/entities/info_townieshop/init.lua
new file mode 100644
index 0000000..1e93d93
--- /dev/null
+++ b/lua/entities/info_townieshop/init.lua
@@ -0,0 +1,59 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+AddCSLuaFile( "cl_init.lua" ) -- Make sure clientside
+AddCSLuaFile( "shared.lua" ) -- and shared scripts are sent.
+
+include('shared.lua')
+
+ENT.default_data = {
+ Model = "models/humans/Group02/Male_03.mdl",
+ NavNodes = {},
+ Pos = nil
+}
+
+ENT.edit_data = {
+ Size = HULL_HUMAN,
+ Type = "npc",
+ Model = "models/editor/playerstart.mdl",
+ get_default_code = function(who)
+ local default_townie = [[
+
+
+
+
+local npc = {
+ ["Pos"] = Vector(%f,%f,%f),
+ ["Model"] = %q,
+ ["Name"] = "%s",
+ ["NavNodes"] = {},
+ ["OnSpawn"] = function(nnpc)
+ print("At time onspawn was called, nnpc was",nnpc)
+ nnpc:StartActivity(ACT_IDLE)
+ end
+}
+
+npc.shopitems = {
+ {"Scrap Hammer",10}, --Items of the form {string_itemname,number_cost}
+ {"Rat Meat",5},
+}
+
+nrequire("sv_npcsystem.lua").CreateShop(npc)
+ ]]
+ local pos = who:GetPos()
+ local model = "models/humans/Group02/Male_03.mdl"
+ local name = "Default Shopkeep"
+ return string.format(default_townie,pos.x,pos.y,pos.z,model,name,"{}",name)
+ end
+}
+--[[
+local init = ENT.Initalize
+function ENT:Initalize()
+ print("In towniespawn's initalize")
+ init(self)
+end
+]]
+
+hook.Add("OnPhysgunFreeze",function(wep,phys,ent,ply)
+ print("Detected freeze")
+ --See if we should update position and andgle
+end)
diff --git a/lua/entities/info_townieshop/shared.lua b/lua/entities/info_townieshop/shared.lua
new file mode 100644
index 0000000..8202b26
--- /dev/null
+++ b/lua/entities/info_townieshop/shared.lua
@@ -0,0 +1,13 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+ENT.Type = "anim"
+ENT.Base = "info_progammable_base"
+
+ENT.PrintName= "Townie Shopkeep"
+ENT.Author= "Apickx"
+ENT.Contact= "cogarr.net"
+ENT.Purpose= "Set a spawn point"
+ENT.Instructions= "Make sure there's a 32x32 box for players to spawn!"
+ENT.Spawnable = true
+ENT.AdminSpawnable = false
+ENT.Category = "Artery"
diff --git a/lua/entities/info_towniespawn/cl_init.lua b/lua/entities/info_towniespawn/cl_init.lua
new file mode 100644
index 0000000..178160c
--- /dev/null
+++ b/lua/entities/info_towniespawn/cl_init.lua
@@ -0,0 +1,109 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+include('shared.lua')
+
+function ENT:Draw()
+ --self:DrawModel() -- Draws Model Client Side
+end
+
+function ENT:Hint()
+ AddWorldTip( self:EntIndex(), "Spawnpoint", 0.5, self:GetPos(), self )
+end
+
+local navnodes = {}
+local selectors = {}
+
+local function sync_navnode_table(who)
+ print("Synching navnodes, table is")
+ PrintTable(navnodes)
+ net.Start("edit_townie_navchange")
+ net.WriteEntity(who)
+ net.WriteTable(navnodes)
+ net.SendToServer()
+end
+
+local function add_nav_item(layout,name,elist,who)
+ print("Adding nav item",layout,name,elist)
+ local holder = vgui.Create("DPanel",layout)
+
+ local selector = vgui.Create("DComboBox",holder)
+ selector.num = #navnodes + 1
+ print("adding the ", selector.num, "selector")
+ selectors[selector.num] = selector
+ selector:Dock(FILL)
+ for k,v in pairs(elist) do
+ print("Adding option",v)
+ selector:AddChoice(v)
+ end
+ if name ~= nil then
+ selector:SetValue(name)
+ navnodes[#navnodes+1] = name
+ end
+
+ selector:SetWidth(150)
+
+ selector.OnSelect = function(self,index,value)
+ print(value,"selected","on",selector.num)
+ navnodes[selector.num] = value
+ sync_navnode_table(who)
+ end
+
+ local delete = vgui.Create("DButton",holder)
+ delete:Dock(RIGHT)
+ delete:SetText("-")
+ delete.DoClick = function(self)
+ for i = selector.num,#navnodes do
+ navnodes[i] = navnodes[i+1]
+ selectors[i] = selectors[i+1]
+ if IsValid(selectors[i]) then
+ selectors[i].num = selectors[i].num - 1
+ end
+ end
+ holder:Remove()
+ sync_navnode_table(who)
+ end
+
+ layout:Add(holder)
+end
+
+net.Receive("edit_townie_use",function()
+ print("I want to make the edit panel for a townie")
+ navnodes = {}
+ local who = net.ReadEntity()
+ local tbl = net.ReadTable() --Current nav nodes for this townie
+ local posi = net.ReadTable() --A list of all nav nodes in the map
+ local editorframe = vgui.Create( "DFrame" )
+ editorframe:SetPos( 100, 100 )
+ editorframe:SetSize( 300, 200 )
+ editorframe:SetTitle( "Edit" .. tostring(who) )
+ editorframe:SetDraggable( true )
+ editorframe:MakePopup()
+
+ local editor = vgui.Create("DPanel",editorframe)
+ editor:Dock(FILL)
+
+ local layout = vgui.Create( "DListLayout", editor )
+ layout:Dock(FILL)
+
+ print("Already setup navnodes:",tbl)
+ PrintTable(tbl)
+
+ for k,v in pairs(tbl) do
+ print("adding",layout,v,slist)
+ add_nav_item(layout,v,posi,who)
+ end
+
+ print("After creation, navnodes are")
+ PrintTable(navnodes)
+
+ local addbutton = vgui.Create("DButton",layout)
+ addbutton:Dock(BOTTOM)
+ addbutton:SetText("+")
+ addbutton.DoClick = function()
+ add_nav_item(layout,nil,posi,who)
+ end
+
+ layout:SetSize( 100, 100 )
+ layout:SetPos( 20, 50 )
+
+end)
diff --git a/lua/entities/info_towniespawn/init.lua b/lua/entities/info_towniespawn/init.lua
new file mode 100644
index 0000000..a785212
--- /dev/null
+++ b/lua/entities/info_towniespawn/init.lua
@@ -0,0 +1,125 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+AddCSLuaFile( "cl_init.lua" ) -- Make sure clientside
+AddCSLuaFile( "shared.lua" ) -- and shared scripts are sent.
+
+include('shared.lua')
+
+ENT.default_data = {
+ Model = "models/humans/Group02/Male_03.mdl",
+ NavNodes = {},
+ Pos = nil
+}
+
+ENT.edit_data = {
+ Size = HULL_HUMAN,
+ Type = "npc",
+ Model = "models/editor/playerstart.mdl",
+ get_default_code = function(who)
+ local default_townie = [[
+
+
+
+
+local function ChatGreat(ply)
+ return {
+ Name = "You can change the name midway!",
+ Message = "That's wonderful!",
+ Options = {}
+ }
+end
+
+local npc = {
+ ["Pos"] = Vector(%f,%f,%f), --@tagpos
+ ["Ang"] = Angle(%f,%f,%f), --@tagang
+ ["Model"] = %q,
+ ["Name"] = "%s",
+ ["NavNodes"] = { --@tagnodes
+
+ },
+ ["getDialogFor"] = function(ply)
+ return {
+ ["Name"] = "%s",
+ ["Message"] = "Hey, how are you doing," .. ply:Nick(),
+ ["Options"] = {
+ ["Great!"] = ChatGreat
+ }
+ }
+ end
+}
+nrequire("sv_npcsystem.lua").CreateTownie(npc)
+ ]]
+ local pos = who:GetPos()
+ local ang = who:GetAngles()
+ local model = "models/humans/Group02/Male_03.mdl"
+ local name = "Default Townie"
+ return string.format(default_townie,pos.x,pos.y,pos.z,ang.p,ang.y,ang.r,model,name,name)
+ end,
+ OnSpawn = function(self)
+ print("Onspawn of", self, "called")
+ if not self.data then self.data = {} end
+ end
+}
+
+local last_townie_use = CurTime()
+hook.Add("FindUseEntity","hook_towniespawn_use",function(ply,defaultent)
+ --print("Looking at", IsValid(defaultent), ":", defaultent:GetClass(), ":", last_townie_use + 2, CurTime())
+ if not IsValid(defaultent) or defaultent:GetClass() ~= "info_towniespawn" or last_townie_use + 2 > CurTime() then return end
+ print("Townie's use is called!")
+ net.Start("edit_townie_use")
+ net.WriteEntity(defaultent)
+ local ntbl = {}
+ for k,v in pairs(defaultent.data) do
+ ntbl[#ntbl+1] = v
+ end
+ print("Sending data to client:")
+ PrintTable(ntbl)
+ net.WriteTable(ntbl)
+ local allnodes = ents.FindByClass("info_edit_townienode")
+ local stbl = {}
+ for k,v in pairs(allnodes) do
+ stbl[#stbl+1] = v.Name
+ end
+ net.WriteTable(stbl)
+ net.Send(ply)
+ last_townie_use = CurTime()
+end)
+
+util.AddNetworkString("edit_townie_navchange")
+net.Receive("edit_townie_navchange",function()
+ local who = net.ReadEntity()
+ local newnodes = net.ReadTable()
+ local thisfile = who.File
+ assert(thisfile,"Failed to find file for entity!")
+ local filetxt = file.Read(thisfile)
+ assert(filetxt,"No such file:" .. thisfile)
+ local stbl = {}
+ print("newnodes is:")
+ PrintTable(newnodes)
+ for k,v in pairs(newnodes) do
+ stbl[#stbl + 1] = string.format("[\"%s\"] = true",v)
+ end
+ print("nanodes to format are:")
+ PrintTable(stbl)
+ local nntxt = table.concat(stbl,",\n\t\t")
+ print("nntxt is", nntxt)
+ local subtxt = string.format([[
+["NavNodes"] = { --@tagnodes
+ %s
+ }]],nntxt)
+ local newtxt, count = filetxt:gsub("%[\"NavNodes\"%] = { %-%-@tagnodes.-}",subtxt)
+ assert(count > 0, "Failed to find text to replace.")
+ print("I want to write",newtxt)
+ file.Write(who.File,newtxt)
+ who.data = newnodes
+ who:notify_file_changed(who.File)
+end)
+
+util.AddNetworkString("edit_townie_use")
+--[[
+local init = ENT.Initalize
+function ENT:Initalize()
+ print("In towniespawn's initalize")
+ init(self)
+end
+]]
diff --git a/lua/entities/info_towniespawn/shared.lua b/lua/entities/info_towniespawn/shared.lua
new file mode 100644
index 0000000..ea7ac99
--- /dev/null
+++ b/lua/entities/info_towniespawn/shared.lua
@@ -0,0 +1,12 @@
+if engine.ActiveGamemode() ~= "sandbox" then return end
+
+ENT.Base = "info_programmable_base"
+
+ENT.PrintName= "Townie Spawn"
+ENT.Author= "Apickx"
+ENT.Contact= "cogarr.net"
+ENT.Purpose= "Set a spawn point"
+ENT.Instructions= "Make sure there's a 32x32 box for players to spawn!"
+ENT.Spawnable = true
+ENT.AdminSpawnable = false
+ENT.Category = "Artery"
diff --git a/lua/entities/npc_huntable/cl_init.lua b/lua/entities/npc_huntable/cl_init.lua
new file mode 100644
index 0000000..f941737
--- /dev/null
+++ b/lua/entities/npc_huntable/cl_init.lua
@@ -0,0 +1,66 @@
+include('shared.lua')
+
+ENT.RenderGroup = RENDERGROUP_BOTH
+
+/*---------------------------------------------------------
+ Name: Draw
+ Desc: Draw it!
+---------------------------------------------------------*/
+function ENT:Draw()
+ self:DrawModel()
+end
+
+/*---------------------------------------------------------
+ Name: DrawTranslucent
+ Desc: Draw translucent
+---------------------------------------------------------*/
+function ENT:DrawTranslucent()
+
+ // This is here just to make it backwards compatible.
+ // You shouldn't really be drawing your model here unless it's translucent
+
+ self:Draw()
+
+end
+
+/*---------------------------------------------------------
+ Name: BuildBonePositions
+ Desc:
+---------------------------------------------------------*/
+function ENT:BuildBonePositions( NumBones, NumPhysBones )
+
+ // You can use this section to position the bones of
+ // any animated model using self:SetBonePosition( BoneNum, Pos, Angle )
+
+ // This will override any animation data and isn't meant as a
+ // replacement for animations. We're using this to position the limbs
+ // of ragdolls.
+
+end
+
+
+
+/*---------------------------------------------------------
+ Name: SetRagdollBones
+ Desc:
+---------------------------------------------------------*/
+function ENT:SetRagdollBones( bIn )
+
+ // If this is set to true then the engine will call
+ // DoRagdollBone (below) for each ragdoll bone.
+ // It will then automatically fill in the rest of the bones
+
+ self.m_bRagdollSetup = bIn
+
+end
+
+
+/*---------------------------------------------------------
+ Name: DoRagdollBone
+ Desc:
+---------------------------------------------------------*/
+function ENT:DoRagdollBone( PhysBoneNum, BoneNum )
+
+ // self:SetBonePosition( BoneNum, Pos, Angle )
+
+end
diff --git a/lua/entities/npc_huntable/init.lua b/lua/entities/npc_huntable/init.lua
new file mode 100644
index 0000000..fcc8532
--- /dev/null
+++ b/lua/entities/npc_huntable/init.lua
@@ -0,0 +1,80 @@
+AddCSLuaFile("cl_init.lua")
+AddCSLuaFile("shared.lua")
+include("shared.lua")
+local applyfields = {"Model", "Stats"}
+
+function ENT:Initialize()
+ --print("NPC spawned!")
+ --self:SetMoveType(MOVETYPE_STEP)
+ --self:SetSolid(SOLID_OBB)
+ --self:SetCollisionGroup(COLLISION_GROUP_PUSHAWAY )
+
+ --self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
+ for _, v in pairs(applyfields) do
+ assert(self[v], "NPC created without " .. v .. " this might be a bug!")
+ end
+
+ self:SetModel(self.Model)
+
+ if (self.Stats["Vitality"]) then
+ self:SetHealth(self.Stats["Vitality"])
+ else
+ print("NPC created with no stat for vitality, this might be a bug!")
+ end
+
+ if (self.Stats["Accel"]) then
+ self.loco:SetAcceleration(self.Stats["Accel"])
+ end
+
+ if (self.Stats["Decel"]) then
+ self.loco:SetDeceleration(self.Stats["Decel"])
+ end
+
+ if (self.Stats["Step"]) then
+ self.loco:SetJumpHeight(self.Stats["Step"])
+ end
+
+ if self.Stats["Speed"] then
+ self.loco:SetDesiredSpeed(self.Stats["Speed"])
+ end
+
+ if (self.OnSpawn) then
+ self:OnSpawn()
+ end
+end
+
+function ENT:OnInjured(dmg)
+ print("Ent OnInjured fired! dmg was", dmg)
+ if self.OnDammage ~= nil then
+ self:OnDammage(dmg)
+ end
+end
+
+function ENT:OnContact(ent)
+ if self.OnCollide ~= nil then
+ self:OnCollide(ent)
+ end
+end
+
+function ENT:OnKilled(dmg)
+ if (CLIENT) then return end
+ if not self.Drops then return end
+ --print("Looks like we have some drops")
+ --error("You need to code how item drops work!")
+ local itemstodrop = {}
+
+ for k, v in pairs(self.Drops) do
+ local rng = math.random(0, 100)
+ local itemname = self.Drops[k][1]
+ local itemchance = self.Drops[k][2]
+ local heightoffset = 10
+
+ if rng < itemchance then
+ --local drop = ART.GetItemByName(itemname)
+ --print("Createing a drop of",drop)
+ --ART.CreateDroppedItem(drop, self:GetPos())
+ end
+ end
+
+ self:BecomeRagdoll(dmg)
+end
diff --git a/lua/entities/npc_huntable/shared.lua b/lua/entities/npc_huntable/shared.lua
new file mode 100644
index 0000000..e42c100
--- /dev/null
+++ b/lua/entities/npc_huntable/shared.lua
@@ -0,0 +1,180 @@
+ENT.Base = "base_nextbot"
+--ART stuff
+ENT.Drops = nil
+ENT.OnDammage = nil
+ENT.Speed = 0
+ENT.Model = nil
+ENT.Behave = nil
+ENT.Act = nil
+ENT.AutomaticFrameAdvance = true
+
+--[[---------------------------------------------------------
+Name: OnRemove
+Desc: Called just before entity is deleted
+---------------------------------------------------------]]
+function ENT:OnRemove()
+end
+
+
+function ENT:DefaultBehaviour()
+ print("In default behavior")
+ self.lastrun = CurTime()
+
+ --Set some stuff up for navigation
+ local path = Path( "Follow" )
+ path:SetMinLookAheadDistance( self.lookahead or 300 )
+ path:SetGoalTolerance( self.goaltolarance or 100)
+ path:Draw()
+ local delta = CurTime() - self.lastrun
+ self:AI(delta)
+ while (true) do
+ --print("Inside defaultbehaviour's while")
+
+ --Sets all the values needed for the rest of this function to do it's thing
+ --Main loop for ai
+
+ --print("Going into behavior for " .. self.Name)
+ --Update aware enemies
+ delta = CurTime() - self.lastrun
+ --print("delta was", delta)
+ if delta > 0.1 then
+ --print('Running ai')
+ self:AI(delta)
+ self.lastrun = CurTime()
+ end
+
+ if self.TargetPos ~= nil then
+ if ( !path:IsValid() ) then print("Path wasn't valid!") end
+ if ( path:GetAge() > 0.1 ) then -- Since we are following the player we have to constantly repath
+ path:Compute( self, self.TargetPos ) -- Compute the path towards the enemy's position again
+ path:Update( self ) -- This function moves the bot along the path
+ end
+
+
+ if ( true ) then path:Draw() end
+ -- If we're stuck then call the HandleStuck function and abandon
+ if ( self.loco:IsStuck() ) then
+ --self:HandleStuck()
+ --return "stuck"
+ end
+
+ --return "ok"
+ end
+ coroutine.yield()
+ end
+
+ coroutine.yield()
+end
+
+
+function ENT:AI(num)
+ --print("Inside ai")
+ local players = player.GetAll()
+
+ for k, v in pairs(players) do
+ local dist = v:GetPos():Distance(self:GetPos())
+ if (dist < self.Stats["AwareDist"]) then
+ table.insert(self.AwareEnemies, v)
+ end
+ end
+
+ --Find the enemy with the highest priority
+ local maxpriority = -1
+ local maxprioritytarget = nil
+
+ for k, v in pairs(self.AwareEnemies) do
+ local priority = self:AttackPriority(v)
+
+ if (priority == nil) then
+ --print("Nill priority hit after ")
+ --PrintTable(self)
+ end
+
+ if (priority > maxpriority) then
+ maxpriority = priority
+ maxprioritytarget = v
+ end
+ end
+
+ self.Target = maxprioritytarget
+ --print("My target is",self.Target)
+ --If we can't find anyone to attack, just stay idle
+ if (self.Target == nil) then
+ --print("Couldn't find anyone to attack!")
+ --Play an idle sequence
+ local randanim = math.Round(math.Rand(1, #self.IdleSequences))
+ print("Playing sequence",self.IdleSequences[randanim])
+ self:PlaySequenceAndWait(self.IdleSequences[randanim])
+ self:StartActivity(ACT_IDLE)
+ print("Acting idle")
+ --If there's noone within 4000 units, just remove ourselves to save server resources
+ local closest = 5000
+
+ for k, v in pairs(player.GetAll()) do
+ local thisdist = self:GetPos():Distance(v:GetPos())
+
+ if (thisdist < closest) then
+ closest = thisdist
+ end
+ end
+
+ if (closest > 4000) then
+ --print("Closes player is " .. closest .. " removeing self...")
+ self:BecomeRagdoll(DamageInfo())
+ end
+ else
+ --We have a target to attack!
+ --Find which attack will do the most dammage
+ local maxdammage = -1
+ local maxdammagefunc = nil
+
+ for k, v in pairs(self.Attacks) do
+ local dammagefunc = nil
+ local attackfunc = nil
+
+ for i, j in pairs(v) do
+ dammagefunc = i
+ attackfunc = j
+ end
+
+ local dammage = dammagefunc(self, self.Target)
+
+ if (dammage > maxdammage) then
+ maxdammage = dammage
+ maxdammagefunc = attackfunc
+ end
+ end
+
+ --Do that attack
+ if (maxdammagefunc) then
+ maxdammagefunc(self, self.Target)
+ end
+ end
+
+ --[[
+ print("Before running, behavethread was", self.BehaveThread)
+ local ok, message = coroutine.resume( self.BehaveThread )
+ if not ok then
+ self.BehaveThread = nil
+ Msg( self, "error: ", message, "\n" );
+ end
+ ]]
+
+ if (self.Act) then
+ self:Act(num)
+ else
+ print("NPC spawned without an Act function, this might be an error!")
+ end
+
+end
+
+function ENT:RunBehaviour()
+ print("Running behavior")
+ if (self.Behave) then
+ print("Doing self.behave")
+ self:Behave()
+ else
+ print("Doing default behavior")
+ self:DefaultBehaviour()
+ end
+end