1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
---Various functions for npcs.
-- Helps you spawn monsters, townies, and shopkeepers
--@server sv_npcsystem.lua
--@alias n
local f = nrequire("concommands.lua")
local log = nrequire("log.lua")
local n = {}
local npcs = {} --Master table of npcs
local npc_metas = {}
local autocompletef
function npc_tostring(npctbl)
return function(self)
return string.format("<NPC %q : %s",npctbl.Name,self.Name)
end
end
---Registers an NPC.
-- Adds an npc to the global table. NPC's should have unique .Name fields, if they don't, this function will error.
--@see npctbl
--@tparam table npc The npc's table.
function n.RegisterNPC(npc)
assert(npc ~= nil, "Attempted to register a nil npc")
assert(type(npc) == "table", "Attempted to regsiter an npc that was not a table, it was a " .. type(npc))
assert(npc.Name ~= nil, "Attempted to register an npc without a name")
log.info("Added npc:",npc.Name)
npcs[npc.Name] = npc
npc_metas[npc.Name] = {__index = npc, __tostring = npc_tostring(npc)}
autocompletef = f.AutocompleteFunction(npcs)
end
function n.GetNPC(name)
assert(npcs[name] ~= nil, "Tried to get npc without name")
return npcs[name]
end
--Ents to remove when refreshing the npc map
local removeents = {"art_npc", "info_townienode", "npc_shop"}
if SERVER then
---Creates an NPC.
-- Creates an npc, by name
--@tparam string npcname The npc's name
--@tparam vector3 pos The position to spawn the npc
function n.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 npc = {Pos = pos}
setmetatable(npc,npc_metas[npcname])
npc:Spawn()
return npc
end
---Creats a shop npc.
-- Creates a shop npc from a shop npc table
--@see shopnpctbl
--@tparam table npc The shop npc's table.
function n.CreateShop(npc)
local npc = {}
setmetatable(npc,npc_metas["Shopkeep"])
npc:Spawn()
return npc
end
---Creates a townie.
-- Creates a new townie that wanders around his areas of intrest
--@see townienpctbl
--@tparam table npc The townie npc's table.
function n.CreateTownie(tbl)
local npc = {}
setmetatable(tbl,npc_metas["Townie"])
npc:Spawn()
return npc
end
---Create an area of intrest.
-- Creates an point that you can use in a townie's locations of intrest.
--@see navnodetbl
--@tparam table tbl The table for the nav node
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
for k, v in pairs(removeents) do
local eot = ents.FindByClass(v)
for i, j in pairs(eot) do
j:Remove()
end
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)
local filename = path:match("/([^/]+)$")
print("I want to run",path, ";", filename)
local is_server = filename:match("^sv_")
local is_client = filename:match("^cl_")
if (is_client and CLIENT) or (is_server and SERVER) or (not is_server and not is_client) then
local filetxt = file.Read(path,"DATA")
--print("File text is", filetxt)
CompileString(filetxt,path)()
--print("I want to execute",path)
end
end)
end
hook.Add("InitPostEntity", "artery_spawnmapnpcs", function()
loadMap()
end)
---Reloads the entities on the map.
-- Removes and then reload all of the entities on the level
--@concommand artery_reloadmap
concommand.Add("artery_reloadmap", function(ply,cmd,args)
if not ply:IsAdmin() then return end
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)
---Create a new npc.
-- Creates a new npc a the point the player is looking
--@usage artery_makenpc <npc_name>
--@concommand artery_makenpc
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
|