aboutsummaryrefslogtreecommitdiff
path: root/gamemode/core/npc/sv_huntingspawner.lua
blob: 99ed75479886aa66007393c9d94e444299221075 (plain)
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
--@server 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