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
|
---Lets huntable monsters drop loot!
-- Register what monsters drop what loot
--@module sv_huntingspawner.lua
--[[
This file spawns the huntable npc's in their zones.
]]
if not nrequire("sh_zones.lua") then return end
local track = nrequire("core/inventory/sv_invtracker.lua")
local itm = nrequire("core/inventory/item.lua")
local o = {}
local huntablenodes = {}
function o.CreateSpawnNode(tbl)
huntablenodes[#huntablenodes + 1] = tbl
local e = ents.Create("info_huntablespawn")
e:SetPos(tbl.Position)
e:Spawn()
end
local function SpawnMonsterFor(ply,zone)
--Check what hunting ground we're in
--print("I want to attack",ply)
if zone == nil then return end
--print("I am in a zone!")
local possiblenpcs = zone.npctbl
--PrintTable(possiblenpcs)
local randnum = math.random(0,100)
--print("Random num was",randnum)
local npctype
for k,v in pairs(possiblenpcs) do
randnum = randnum - v
--print("Subtracting ", v , " for ",k)
--print(randnum)
if randnum < 0 then
npctype = k
break
end
end
if npctype == nil then
--print(ply,"got lucky this time...")
return
end
--print("I will spawn a ",npctype,"to attack ",ply,"!")
--Find a place for the npc to spawn that's out of sight!
local potentialspots = ents.FindInSphere( ply:GetPos(), 4000 )
for k,v in pairs(potentialspots) do
--print("Checking spot",v)
if v:GetClass() ~= "info_huntablespawn" then
--print("Was not an info_huntablespawn")
potentialspots[k] = nil
else
local tr = util.TraceLine({
start = v:GetPos() + Vector(0,0,50),
endpos = ply:GetPos() + Vector(0,0,64),
})
if tr.Hit and tr.Entity == ply then
potentialspots[k] = nil
--print("Player could see this point")
end
end
end
local a = {}
for k,v in pairs(potentialspots) do a[#a + 1] = v end
--Choose a random spot!
local spawnpos = a[math.random(1,#a)]
--print("I want to spawn a monster at", spawnpos)
if spawnpos == nil then
--print("Couldn't find a spot to spawn an NPC around",ply,"at",ply:GetPos(),"make sure there are enough info_huntablespawn entities around in little corners and stuff")
return
end
--Do a trace up to hit the skybox,
local npc = ents.Create(npctype)
npc:SetPos(spawnpos:GetPos())
npc:SetEnemy(ply)
npc:Spawn()
end
local lastspawned = {}
for k,v in pairs(player.GetAll()) do lastspawned[v] = CurTime() end
hook.Add("PlayerInitialSpawn","add_to_huntable_tbl",function(ply)
lastspawned[ply] = CurTime()
end)
hook.Add("Tick","occasionally_spawn_monsters",function()
for _,ply in pairs(player.GetAll()) do
local zone = ply:GetCurrentZone( "artery_huntingground" )
if zone == nil then continue end
if CurTime() - lastspawned[ply] > zone.SpawnRate then
SpawnMonsterFor(ply,zone)
lastspawned[ply] = CurTime()
end
end
end)
local external_drops = {}
---Register a monster's loot.
-- Register a table of loot to probability of dropping to a monster. Will warn if you try to register the same monster twice. An npc can define it's own drops, but if you're using npcs from elsewhere, use this function to tell the gamemode what to drop on each npc's death.
--@tparam string npcname The name of the npc to give loot to
--@tparam table tbl The table of {"item\_name"=number\_drop_chance}, drop chance should be in the range 0 < x <= 100. 100 is always drop, 0 is never drop.
function o.RegisterDrops(npcname,tbl)
if not external_drops[npcname] == nil then
MsgC(Color(255,255,0),"WARNING: Tried to register 2 drop tables for " .. npcname)
end
--assert(external_drops[npcname] == nil, string.format("Tried to register 2 drop tables for the npc %q",npcname))
external_drops[npcname] = tbl
end
hook.Add("OnNPCKilled","droplootforexnpcs",function(npc,attacker,inflictor)
local d = external_drops[npc:GetClass()]
if d == nil then return end
for k, v in pairs(d) do
local rng = math.random(0, 100)
local itemname = v[1]
local itemchance = v[2]
if rng < itemchance then
local drop = itm.GetItemByName(itemname)
print("Createing a drop of",drop)
track.DropItem(drop, npc:GetPos())
end
end
end)
return o
|