aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--LISCENSE9
-rw-r--r--README.md6
-rw-r--r--doc/for_developers/structs/inventories.md5
-rw-r--r--entities/entities/art_droppeditem/cl_init.lua2
-rw-r--r--entities/entities/info_huntablespawn/cl_init.lua69
-rw-r--r--entities/entities/info_huntablespawn/init.lua16
-rw-r--r--entities/entities/info_huntablespawn/shared.lua23
-rw-r--r--entities/entities/npc_huntable/init.lua13
-rw-r--r--entities/entities/npc_huntable/shared.lua51
-rw-r--r--gamemode/cl_init.lua9
-rw-r--r--gamemode/client/cl_inventory.lua2
-rw-r--r--gamemode/client/cl_legs.lua1
-rw-r--r--gamemode/config/sv_newplayer.lua3
-rw-r--r--gamemode/core/combat/cl_weaponswing.lua57
-rw-r--r--gamemode/core/combat/sv_weaponswing.lua99
-rw-r--r--gamemode/core/database/sv_setup.lua13
-rw-r--r--gamemode/core/inventory/common/items.lua5
-rw-r--r--gamemode/core/inventory/sv_invtracker.lua36
-rw-r--r--gamemode/core/npc/sv_common.lua38
-rw-r--r--gamemode/core/npc/sv_huntingspawner.lua118
-rw-r--r--gamemode/core/npc/sv_npcsystem.lua40
-rw-r--r--gamemode/core/pac/cl_pac.lua10
-rw-r--r--gamemode/core/pac/sv_pac.lua6
-rw-r--r--gamemode/init.lua23
-rw-r--r--gamemode/inventorysystem/cl_common.lua4
-rw-r--r--gamemode/itemsystem/weapons/rustyaxe.lua31
-rw-r--r--gamemode/npcsystem/sv_blockingdummy.lua4
-rw-r--r--gamemode/npcsystem/sv_dummy.lua8
-rw-r--r--gamemode/npcsystem/sv_zombie.lua187
30 files changed, 813 insertions, 76 deletions
diff --git a/AUTHORS b/AUTHORS
index b935dc1..b2a9fa2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -8,6 +8,7 @@ Built using work from:
JetBoom - AnimBoneLib (Lua Animation API)
CapsAdmin - Pac3
MiBShidobu - SVG renderer
+ bobbleheadbob - Zones
Art & graphics:
opengameart.org user "Emerald" - Art/icons
diff --git a/LISCENSE b/LISCENSE
index e69de29..2b4768a 100644
--- a/LISCENSE
+++ b/LISCENSE
@@ -0,0 +1,9 @@
+Copyright 2016-2017 Alexander "Apickx" Pickering
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
index 8c08df9..15068d5 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,7 @@
Oh boy! A readme file!
+
+As of now, artery depends on the following addons:
+ bobbleheadbob's zone tool
+ artery_editor
+ skyrim NPCs
+ Fallout NPCs
diff --git a/doc/for_developers/structs/inventories.md b/doc/for_developers/structs/inventories.md
new file mode 100644
index 0000000..d965597
--- /dev/null
+++ b/doc/for_developers/structs/inventories.md
@@ -0,0 +1,5 @@
+# Inventories
+
+A player starts off with 2 inventories, a equipment inventory, and a shaped inventory (5x5)
+
+the equipment inventory is in the first slot, the shaped inventory in the second.
diff --git a/entities/entities/art_droppeditem/cl_init.lua b/entities/entities/art_droppeditem/cl_init.lua
index ceebc7f..83f8087 100644
--- a/entities/entities/art_droppeditem/cl_init.lua
+++ b/entities/entities/art_droppeditem/cl_init.lua
@@ -18,7 +18,7 @@ local sentrequests = {}
hook.Add("Tick","pickupitemstick",function()
lp = (lp and lp:IsValid()) and lp or LocalPlayer()
if not lp:IsValid() then return end
- local ae = ents.FindInSphere(lp:GetPos(),5)
+ local ae = ents.FindInSphere(lp:GetPos(),10)
for k,v in pairs(ae) do
local ei = v:EntIndex()
if (not sentrequests[ei]) and v.GetClass and v:GetClass() == "art_droppeditem" then
diff --git a/entities/entities/info_huntablespawn/cl_init.lua b/entities/entities/info_huntablespawn/cl_init.lua
new file mode 100644
index 0000000..f851bf9
--- /dev/null
+++ b/entities/entities/info_huntablespawn/cl_init.lua
@@ -0,0 +1,69 @@
+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/entities/entities/info_huntablespawn/init.lua b/entities/entities/info_huntablespawn/init.lua
new file mode 100644
index 0000000..9fa7f7e
--- /dev/null
+++ b/entities/entities/info_huntablespawn/init.lua
@@ -0,0 +1,16 @@
+--[[
+ 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/entities/entities/info_huntablespawn/shared.lua b/entities/entities/info_huntablespawn/shared.lua
new file mode 100644
index 0000000..8b42e7f
--- /dev/null
+++ b/entities/entities/info_huntablespawn/shared.lua
@@ -0,0 +1,23 @@
+ENT.Base = "base_entity"
+
+//WS stuff
+ENT.Drops = nil
+ENT.OnDammage = nil
+ENT.Speed = 0
+ENT.Model = nil
+
+ENT.Behave = nil
+ENT.Act = nil
+
+/*---------------------------------------------------------
+ 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/entities/entities/npc_huntable/init.lua b/entities/entities/npc_huntable/init.lua
index a21e565..31d6ea8 100644
--- a/entities/entities/npc_huntable/init.lua
+++ b/entities/entities/npc_huntable/init.lua
@@ -6,7 +6,8 @@ local applyfields = {"Model", "Stats"}
function ENT:Initialize()
--print("NPC spawned!")
--self:SetMoveType(MOVETYPE_STEP)
- self:SetSolid(SOLID_OBB)
+ --self:SetSolid(SOLID_OBB)
+ self:SetCollisionGroup(COLLISION_GROUP_PUSHAWAY )
--self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
for _, v in pairs(applyfields) do
@@ -32,6 +33,10 @@ function ENT:Initialize()
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()
@@ -59,9 +64,9 @@ function ENT:OnKilled(dmg)
local heightoffset = 10
if rng < itemchance then
- local drop = ART.GetItemByName(itemname)
- print("Createing a drop of",drop)
- ART.CreateDroppedItem(drop, self:GetPos())
+ --local drop = ART.GetItemByName(itemname)
+ --print("Createing a drop of",drop)
+ --ART.CreateDroppedItem(drop, self:GetPos())
end
end
diff --git a/entities/entities/npc_huntable/shared.lua b/entities/entities/npc_huntable/shared.lua
index 279199f..4c4c535 100644
--- a/entities/entities/npc_huntable/shared.lua
+++ b/entities/entities/npc_huntable/shared.lua
@@ -6,6 +6,7 @@ ENT.Speed = 0
ENT.Model = nil
ENT.Behave = nil
ENT.Act = nil
+ENT.AutomaticFrameAdvance = true
--[[---------------------------------------------------------
Name: OnRemove
@@ -16,22 +17,44 @@ 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)
+ local delta = CurTime() - self.lastrun
+ self:AI(delta)
while (true) do
--print("Inside defaultbehaviour")
- local delta = CurTime() - self.lastrun
- self:AI(delta)
+
+ --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
+ if delta > 0.1 then
+ self:AI(delta)
+ end
+
if self.TargetPos ~= nil then
- self:MoveToPos(self.TargetPos,{
- ["lookahead"] = 5,
- ["tolerance"] = 50,
- ["draw"] = true,
- ["maxage"] = 20,
- ["repath"] = 4,
- })
+ 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
self.lastrun = CurTime()
coroutine.yield()
@@ -125,11 +148,21 @@ function ENT:AI(num)
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()
diff --git a/gamemode/cl_init.lua b/gamemode/cl_init.lua
index 6b5d18a..2f80ddd 100644
--- a/gamemode/cl_init.lua
+++ b/gamemode/cl_init.lua
@@ -1 +1,10 @@
+--Find out where all our prints are comming from!
+local oldprint = print
+print = function(...)
+ oldprint(unpack({...}))
+ oldprint(debug.traceback())
+end
+
include( "shared.lua" )
+
+print = oldprint
diff --git a/gamemode/client/cl_inventory.lua b/gamemode/client/cl_inventory.lua
index 0c84e5c..7fab07c 100644
--- a/gamemode/client/cl_inventory.lua
+++ b/gamemode/client/cl_inventory.lua
@@ -10,7 +10,7 @@
]]
local qinv = nrequire("cl_qinventory.lua")
local state = nrequire("cl_state.lua") --Holds weather or not player is in inventory
-local itm = nrequire("core/inventory/item.lua")
+local itm = nrequire("core/inventory/common/items.lua")
--local qpray = nrequire("cl_qprayers.lua")
local inv = {}
diff --git a/gamemode/client/cl_legs.lua b/gamemode/client/cl_legs.lua
index c9703e1..506a0a9 100644
--- a/gamemode/client/cl_legs.lua
+++ b/gamemode/client/cl_legs.lua
@@ -1,3 +1,4 @@
+do return end
--[[
The purpose of this file is to render the client's legs
diff --git a/gamemode/config/sv_newplayer.lua b/gamemode/config/sv_newplayer.lua
index 9bb1420..fc66c82 100644
--- a/gamemode/config/sv_newplayer.lua
+++ b/gamemode/config/sv_newplayer.lua
@@ -5,7 +5,8 @@ local itm = nrequire("inventory/item.lua")
np.newdata = function()
return {
inventories = {
- {"Equipment", inv.CreateInventory("Equipment"):Serialize()}
+ {"Equipment", inv.CreateInventory("Equipment"):Serialize()},
+ {"Shaped Inventory",inv.CreateInventory("Shaped Inventory"):Serialize()}
},
skills = {},
prayers = {},
diff --git a/gamemode/core/combat/cl_weaponswing.lua b/gamemode/core/combat/cl_weaponswing.lua
new file mode 100644
index 0000000..8ed9637
--- /dev/null
+++ b/gamemode/core/combat/cl_weaponswing.lua
@@ -0,0 +1,57 @@
+local CLIENT_PAC_DIR = "artery/client/pacs"
+
+local ball
+function finddmgpoint(name)
+ local filepath = string.format(CLIENT_PAC_DIR .. "/%s.txt",name)
+ local filetext = file.Read(filepath,"DATA")
+ local outfit = CompileString(string.format("return {%s}",filetext),name)()
+ ball = LocalPlayer():FindPACPart(outfit, "wep_point")
+ print("point is",ball,type(ball))
+end
+
+local swingtbl = {}
+local tracking = false
+
+net.Receive("artery_doanimation",function()
+ local animname = net.ReadString()
+ local animtime = net.ReadDouble()
+ local wepname = net.ReadString()
+ local animdir = net.ReadString()
+
+ swingtbl = {}
+ tracking = true
+ finddmgpoint(wepname)
+ print("Doing animation:",animname,animtime,echoname)
+ LocalPlayer():SetLuaAnimation(animname)
+ timer.Simple(animtime,function()
+ tracking = false
+ LocalPlayer():StopLuaAnimation(animname)
+ net.Start("artery_notifyserverofswing")
+ net.WriteString(wepname)
+ net.WriteString(animdir)
+ print("Seding swingtbl:")
+ PrintTable(swingtbl)
+ net.WriteTable(swingtbl)
+ net.SendToServer()
+ end)
+end)
+
+concommand.Add("artery_startanimation",function(ply,cmd,args)
+ swingtbl = {}
+ ply:SetLuaAnimation(args[1])
+ timer.Simple(args[2],function()
+ ply:StopLuaAnimation(args[1])
+ end)
+end)
+
+local lastpos
+hook.Add("Tick","trace_weppos",function()
+ if not ball then return end
+ if lastpos == nil then lastpos = ball.Entity:GetPos() end
+ --`print("Distance between ", ball.Entity:GetPos(), "and", lastpos, " is" ,ball.Entity:GetPos():Distance(lastpos))
+ if ball.Entity:GetPos():Distance(lastpos) > 2 and tracking then
+ swingtbl[#swingtbl + 1] = ball.Entity:GetPos() - LocalPlayer():GetPos()
+ print(ball.Entity:GetPos() - LocalPlayer():GetPos())
+ end
+ lastpos = ball.Entity:GetPos()
+end)
diff --git a/gamemode/core/combat/sv_weaponswing.lua b/gamemode/core/combat/sv_weaponswing.lua
new file mode 100644
index 0000000..f238497
--- /dev/null
+++ b/gamemode/core/combat/sv_weaponswing.lua
@@ -0,0 +1,99 @@
+--[[
+ This file tells you what weapons need their swings recalculated
+]]
+local itm = nrequire("core/inventory/item.lua")
+local ws = {}
+
+--Cache swing hits, if we used one once, we'll probably use it again soon
+local swingcache_size = 30
+local swingcache = {} --Swing arc cache
+
+--A table of all the items that are swingable
+local swingable = {}
+
+util.AddNetworkString("artery_notifyserverofswing")
+util.AddNetworkString("artery_doanimation")
+
+net.Receive("artery_notifyserverofswing",function()
+ local weapon = net.ReadString()
+ local anim = net.ReadString()
+ local data = net.ReadTable()
+
+ print("Got swing data for ",weapon,anim)
+ PrintTable(data)
+
+ --Get the data that already exists for this weapon
+ local olddata = file.Read("artery/dynamic/swingdata/" .. weapon .. ".txt","DATA")
+ if olddata == nil then olddata = {}
+ else olddata = util.JSONToTable(util.Decompress(olddata)) end
+
+ --Add our new data
+ olddata[anim] = data
+
+ --And save back
+ file.Write("artery/dynamic/swingdata/" .. weapon .. ".txt",util.Compress(util.TableToJSON(olddata)))
+end)
+
+function ws.makeSwingable(tbl)
+ assert(tbl.Name,"Tried to make a swingable weapon out of an item with no name!")
+ assert(tbl.attacks,"Tried to make a swingable weapon out of an item with no attacks! See rustyaxe.lua for example")
+ assert(tbl.pacname,"Tried to make a swingable weapon without a pac name! see rustyaxe.lua for example")
+ swingable[tbl.Name] = tbl
+end
+
+concommand.Add("artery_recordanimations",function(ply,cmd,args)
+ local animqueuetime = 0
+ for k,v in pairs(swingable) do
+ --equip the right item
+ print("equipable inventory:")
+ local eqi = ply.data.inventories[1]
+ print(ply.data.inventories[1])
+ local itm = eqi:Get({v.Equipable})
+ if itm ~= nil then
+ eqi:Remove({v.Equipable})
+ end
+ eqi:Put({v.Equipable},v)
+
+ --queue up each attack for the player to do
+ for i,j in pairs(v.attacks) do
+ timer.Simple(animqueuetime,function()
+ print("Doing attack:")
+ print(i,":",j)
+ net.Start("artery_doanimation")
+ net.WriteString(j.anim)
+ net.WriteDouble(j.time)
+ net.WriteString(v.Name)
+ net.WriteString(i)
+ net.Send(ply)
+ end)
+ animqueuetime = animqueuetime + j.time + 1
+ end
+
+ end
+end)
+
+
+
+concommand.Add("artery_checkSwingable",function(ply,cmd,args)
+ local nitms = 0
+ local noswingdata = {}
+ for k,v in pairs(swingable) do
+ --Make sure we have a weapon path for everything
+ if file.Exists( "artery/dynamic/swingdata/" .. k, "DATA" ) then
+ MsgC(Color(0,255,0),"Found data for " .. k .. "\n")
+ else
+ MsgC(Color(255,0,0),"Couldn't find data for " .. k .. "\n")
+ noswingdata[#noswingdata + 1] = k
+ end
+ nitms = nitms + 1
+ end
+
+ print("Scanned ",nitms,"swingable items, could not find data for:\n\t",table.concat(noswingdata,"\n\t"))
+end)
+
+concommand.Add("artery_clearswingable",function(ply,cmd,args)
+ swingable = {}
+end)
+
+
+return ws
diff --git a/gamemode/core/database/sv_setup.lua b/gamemode/core/database/sv_setup.lua
index 2fb7ed7..2cb69d1 100644
--- a/gamemode/core/database/sv_setup.lua
+++ b/gamemode/core/database/sv_setup.lua
@@ -34,13 +34,18 @@ local function connect()
MySQLite.initialize(config)
end
hook.Add("DatabaseInitialized","setup_table",function()
+ assert(MySQLite.isMySQL(),"Database wasn't mysqloo, something is probably wrong!")
local setup_success = function(res,li)
print("Set up connection to db")
end
print("Setup query:",setup_db)
MySQLite.query(setup_db,setup_success,q_fai)
end)
-connect()
+
+hook.Add("Initialize","initalizedbconnection",function()
+ connect()
+end)
+
--Retruns (PlayerData, MetaData) or nil
function sql.GetPlayerData(ply)
@@ -65,7 +70,7 @@ function sql.GetPlayerData(ply)
return
end
print("We were on the right server")
- --[[
+
print("Before finding data in the metatable, mtbl was ")
PrintTable(mtbl)
print(type(mtbl.lastlocation))
@@ -74,8 +79,8 @@ function sql.GetPlayerData(ply)
for k,v in pairs(vec) do vec[k] = tonumber(v) end
print("setting player pos to")
PrintTable(vec)
- ]]
- ply:SetPos(mtbl.lastlocation)
+
+ ply:SetPos(Vector(unpack(vec)))
q.deserialize_player(ply,plyd)
end
end
diff --git a/gamemode/core/inventory/common/items.lua b/gamemode/core/inventory/common/items.lua
index 03113f5..95a507c 100644
--- a/gamemode/core/inventory/common/items.lua
+++ b/gamemode/core/inventory/common/items.lua
@@ -14,15 +14,18 @@ local function drop_self(tbl)
end
+--Client requests the item be droped from the ent, invid, and inv position
function items.DropItem(ent_or_tbl,invid,frompos)
+ --[[
if type(ent_or_tbl) == "table" then
drop_self(ent_or_tbl)
else
drop_provided(ent_or_tbl,invid,frompos)
end
+ ]]
assert(CLIENT,"requested to drop an item when we are not the client!")
net.Start("art_RequestInvDrop")
- net.WriteEntity(ent)
+ net.WriteEntity(ent_or_tbl)
net.WriteUInt(invid,32)
net.WriteTable(frompos)
net.SendToServer()
diff --git a/gamemode/core/inventory/sv_invtracker.lua b/gamemode/core/inventory/sv_invtracker.lua
index 4c1fc1b..47dd164 100644
--- a/gamemode/core/inventory/sv_invtracker.lua
+++ b/gamemode/core/inventory/sv_invtracker.lua
@@ -63,19 +63,47 @@ net.Receive("art_RequestInvMove",function(len,ply)
toinv:Put(topos,item)
end)
+function track.DropItem(item,pos)
+ local e = ents.Create("art_droppeditem")
+ e.Item = {Name = item.Name, Data = item:Serialize()}
+ e:SetPos(pos)
+ e:Spawn()
+end
+
net.Receive("art_RequestInvDrop",function(len,ply)
local froment = net.ReadEntity()
local frominvid = net.ReadUInt(32)
local frompos = net.ReadTable()
assert(not froment:IsPlayer() or froment == ply, "Player tried to drop an item that was from another players inventory")
+ print("Using data for drop:")
+ PrintTable({
+ ["froment"] = froment,
+ ["frominvid"] = frominvid,
+ ["frompos"] = frompos
+ })
+ print("Player's data is:")
+ PrintTable(froment.data)
local frominv = froment.data.inventories[frominvid]
local item = frominv:Get(frompos)
frominv:Remove(frompos)
- local e = ents.Create("art_droppeditem")
- e.Item = {Name = item.Name, Data = item:Serialize()}
- e:SetPos((ply:GetForward() * 20) + ply:GetPos())
- e:Spawn()
+ local placetodrop
+ --Find somewhere to drop this
+ local tr = ply:GetEyeTrace()
+ if tr.Hit then
+ if tr.HitPos:Distance(ply:GetPos()) < 200 then
+ placetodrop = tr.HitPos
+ else
+ local tr2 = util.TraceLine({
+ start = (tr.Normal*200) + tr.StartPos,
+ endpos = ((tr.Normal*200) + tr.StartPos) + Vector(-2000),
+ })
+ placetodrop = tr2.HitPos
+ end
+ else
+ placetodrop = ply:GetForward() * 200
+ end
+ track.DropItem(item,placetodrop)
end)
function track.ClearInventories(ply)
diff --git a/gamemode/core/npc/sv_common.lua b/gamemode/core/npc/sv_common.lua
new file mode 100644
index 0000000..e37a5f8
--- /dev/null
+++ b/gamemode/core/npc/sv_common.lua
@@ -0,0 +1,38 @@
+--[[
+ Some common functions that a lot of npcs use, take out here to make fixing bugs easier.
+]]
+
+local com = {}
+
+com.pausefor10sec = function(npc)
+ npc.StartActionTime = CurTime() + 10
+ npc:SetSequence(npc:LookupSequence("idle"))
+ npc.loco:FaceTowards(Vector(-343, 148, 565))
+ local oyaw,oacc = npc.loco:GetMaxYawRate(), npc.loco:GetAcceleration()
+ timer.Simple(0,function()
+ npc.loco:SetMaxYawRate(0)
+ npc.loco:SetAcceleration(0)
+ npc.loco:SetVelocity(Vector(0,0,0))
+ end)
+ timer.Simple(10, function()
+ npc.loco:SetMaxYawRate(oyaw)
+ npc.loco:SetAcceleration(oacc)
+ end)
+end
+
+com.is10secdone = function(npc)
+ return npc.StartActionTime < CurTime()
+end
+
+com.Rumors = {
+ "This is a rumor!",
+ "Here is another!",
+ "And yet another!",
+}
+
+com.GetRumor = function()
+ local rng = math.random(#com.Rumors)
+ return com.Rumors[rng]
+end
+
+return com
diff --git a/gamemode/core/npc/sv_huntingspawner.lua b/gamemode/core/npc/sv_huntingspawner.lua
new file mode 100644
index 0000000..283b27f
--- /dev/null
+++ b/gamemode/core/npc/sv_huntingspawner.lua
@@ -0,0 +1,118 @@
+--[[
+ This file spawns the huntable npc's in their zones.
+]]
+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)
+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)
+ 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 = {}
+function o.RegisterDrops(npcname,tbl)
+ 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]
+ local heightoffset = 10
+
+ if rng < itemchance then
+ local drop = itm.GetItemByName(itemname)
+ print("Createing a drop of",drop)
+ track.CreateDroppedItem(drop, self:GetPos()+Vector(math.random(20),math.random(20),20))
+ end
+ end
+end)
+
+return o
diff --git a/gamemode/core/npc/sv_npcsystem.lua b/gamemode/core/npc/sv_npcsystem.lua
index 1abbc67..78b041f 100644
--- a/gamemode/core/npc/sv_npcsystem.lua
+++ b/gamemode/core/npc/sv_npcsystem.lua
@@ -11,6 +11,7 @@ function n.RegisterNPC(npc)
end
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 npctbl = npcs[npcname]
local npc = ents.Create("npc_huntable")
@@ -66,23 +67,32 @@ for k, v in pairs(removeents) do
end
end
-local mapfields = {"navnodes", "npcs"}
+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
--- "chests",
local function loadMap()
- for k, v in ipairs(mapfields) do
- local mapname = game.GetMap()
- local fpath = string.format("artery/maps/%s/%s/*", mapname, v)
- local files, dirs = file.Find(fpath, "DATA")
-
- for i, j in pairs(files) do
- if string.GetExtensionFromFilename(j) ~= "lua" then continue end
- local itempath = string.format("artery/maps/%s/%s/%s", mapname, v, j)
- local itemtxt = file.Read(itempath, "DATA")
- assert(itemtxt ~= nil, "Found a file, but it looks like it can't be compiled:" .. itempath)
- CompileString(itemtxt, itempath)()
- 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)
+ CompileString(filetxt,path)()
+ print("I want to execute",path)
+ end)
end
hook.Add("InitPostEntity", "artery_spawnmapnpcs", function()
diff --git a/gamemode/core/pac/cl_pac.lua b/gamemode/core/pac/cl_pac.lua
index 9163d82..4f1890c 100644
--- a/gamemode/core/pac/cl_pac.lua
+++ b/gamemode/core/pac/cl_pac.lua
@@ -27,11 +27,13 @@ timer.Simple(0,function()
net.SendToServer()
end)
-file.CreateDir("artery/pacs")
+local CLIENT_PAC_DIR = "artery/client/pacs"
+
+file.CreateDir(CLIENT_PAC_DIR)
local function loadpac(ent,name,hash)
print("Told to apply pac", name, "to ent", ent)
- local filepath = string.format("artery/pacs/%s.txt",name)
+ local filepath = string.format(CLIENT_PAC_DIR .. "/%s.txt",name)
local filetext = file.Read(filepath,"DATA")
if ent.AttachPACPart == nil then
pac.SetupENT(ent)
@@ -52,7 +54,7 @@ local function loadpac(ent,name,hash)
end
local function unloadpac(ent,name,hash)
- local filepath = string.format("artery/pacs/%s.txt",name)
+ local filepath = string.format(CLIENT_PAC_DIR .. "/%s.txt",name)
local filetext = file.Read(filepath,"DATA")
local pactbl = CompileString(string.format("return {%s}",filetext),name)()
ent:RemovePACPart(pactbl)
@@ -62,7 +64,7 @@ net.Receive("artery_downloadpac",function()
local pac_name = net.ReadString()
local pac_txt = net.ReadString()
local pac_hash = net.ReadUInt(32)
- local filepath = string.format("artery/pacs/%s.txt",pac_name)
+ local filepath = string.format(CLIENT_PAC_DIR .."/%s.txt",pac_name)
file.Write(filepath,pac_txt)
end)
diff --git a/gamemode/core/pac/sv_pac.lua b/gamemode/core/pac/sv_pac.lua
index 3c5c6be..482dea6 100644
--- a/gamemode/core/pac/sv_pac.lua
+++ b/gamemode/core/pac/sv_pac.lua
@@ -108,12 +108,16 @@ local function cacheload(key)
--If it's already in the cache, just update the time it was last used and return the pac.
if pac_cache[key] ~= nil then
pac_cache[key].time = CurTime()
+ if pac_cache[key].pac == nil then
+ PrintTable(pac_cache)
+ error("Pac was loaded, but the txt was nil!")
+ end
return pac_cache[key].pac
end
--Otherwise, we need to load it.
local pacpath = string.format("artery/pacs/%s.txt",key)
- local pacfile = file.Read(pacpath,"LUA")
+ local pacfile = file.Read(pacpath,"DATA")
--If we haven't reached max cache yet, just put it in
if pacs_in_cache < max_pacs_in_cache then
diff --git a/gamemode/init.lua b/gamemode/init.lua
index 5b28d32..ac530f1 100644
--- a/gamemode/init.lua
+++ b/gamemode/init.lua
@@ -4,25 +4,4 @@ AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile("nrequire.lua")
include( "shared.lua" )
-local pmeta = FindMetaTable("Player")
-
---- Loads a player's inventory
--- @param json The JSON string to create the player's inventory from
-function pmeta:LoadInventory(json)
- local reinv = util.JSONToTable(json)
- for k,v in pairs(reinv) do
- self.Inventory[k] = v
- end
- print("After loading inventory, player's inventory was")
- PrintTable(self.Inventory)
- self:SynchronizeInventory()
- self:SynchPrayers()
- if self:HasPrayer("Noob Help") then
- print("Player had Noob Help, equiping!")
- net.Start("equiphelpprayer")
- net.Send(self)
- else
- error("Player did not have noob help, inventory was:")
- PrintTable(self.Inventory)
- end
-end
+print("Hello from init.lua")
diff --git a/gamemode/inventorysystem/cl_common.lua b/gamemode/inventorysystem/cl_common.lua
index 15f67b4..5b461d3 100644
--- a/gamemode/inventorysystem/cl_common.lua
+++ b/gamemode/inventorysystem/cl_common.lua
@@ -8,9 +8,11 @@ function com.CreateMenuFor(menu, tbl)
for k,v in pairs(tbl) do
if isfunction(v) then --This is a dead-end, add the menu
menu:AddOption(k,v)
- else --Otherwise it should be a table, recursively call to create
+ elseif istable(v) then --Otherwise it should be a table, recursively call to create
local submenu = menu:AddSubMenu(k)
CreateMenuFor(submenu,v)
+ else
+ error("I got wanted to make a menu for something not a function or a table:" + type(v))
end
end
end
diff --git a/gamemode/itemsystem/weapons/rustyaxe.lua b/gamemode/itemsystem/weapons/rustyaxe.lua
index 00547c8..4f613de 100644
--- a/gamemode/itemsystem/weapons/rustyaxe.lua
+++ b/gamemode/itemsystem/weapons/rustyaxe.lua
@@ -1,15 +1,17 @@
--[[
An axe that you can swing around!
]]
-local pac
+local pac,swi
if SERVER then
pac = nrequire("core/pac/sv_pac.lua")
+ swi = nrequire("core/combat/sv_weaponswing.lua")
end
local reg = nrequire("core/inventory/item.lua")
local com = nrequire("core/inventory/common/weapons.lua")
local itm = nrequire("core/inventory/common/items.lua")
+
local item = {}
--Required, a name, all item names must be unique
@@ -56,6 +58,29 @@ item.Shape = {
--Optional, If this item can be equiped in any player slots, put them here.
item.Equipable = "Right Hand"
+item.attacks = {
+ ["forward"] = {
+ time = 2.33,
+ anim = "axe_swing_up",
+ },
+ ["left"] = {
+ time = 2.33,
+ anim = "axe_swing_left",
+ },
+ ["left"] = {
+ time = 2.33,
+ anim = "axe_swing_right",
+ },
+}
+
+--The path garrysmod/data/artery/pacs/<pacname>.txt must be a pac file
+item.pacname = "rustyaxe"
+
+if SERVER then
+ --Before makeSwingable is called, an item needs a .Name field and a .attacks field and a .pacname field
+ swi.makeSwingable(item)
+end
+--[[
local swingdata = {
["fwd"] = {
{0.011,Vector(-25,-3,-11)},
@@ -212,7 +237,9 @@ item.onClick = function(self,owner)
print("At time of doing playermovedir, com is", com)
movementtbl[com.playermovedir(owner)]()
end
+]]
+--[[
--Optional, if we should do something special on equip(like draw the PAC for this weapon)
item.onEquip = function(self,who)
print("onEquip",who)
@@ -234,7 +261,7 @@ item.onUnEquip = function(self,who)
who:GetActiveWeapon():SetHoldType("normal")
if SERVER then pac.RemovePac(who,"rustyaxe") end
end
-
+]]
item.onDropped = function(self, ent)
if SERVER then pac.ApplyPac(ent,"rustyaxe") end
end
diff --git a/gamemode/npcsystem/sv_blockingdummy.lua b/gamemode/npcsystem/sv_blockingdummy.lua
index 2b98b97..c40fc54 100644
--- a/gamemode/npcsystem/sv_blockingdummy.lua
+++ b/gamemode/npcsystem/sv_blockingdummy.lua
@@ -29,7 +29,7 @@ NPC.Drops = {
--Attacks should be formated as [i]={function attackpriority() = function doattack()}
local checknothing = function(self,ply)
- return 1
+ return -1
end
local donothing = function(self,ply)
@@ -79,7 +79,7 @@ function NPC:OnDammage(ammount)
print("Blocking is now",self.Blocking)
end
---These are just here to tell the editors/develoeprs what functions are available.. dont un-comment them out, as this could affect all the items.
+--These are just here to tell the editors/develoeprs what functions are available.
/*
function NPC:OnSpawn()
end
diff --git a/gamemode/npcsystem/sv_dummy.lua b/gamemode/npcsystem/sv_dummy.lua
index 6c5acae..0bfa063 100644
--- a/gamemode/npcsystem/sv_dummy.lua
+++ b/gamemode/npcsystem/sv_dummy.lua
@@ -4,7 +4,7 @@ local NPC = {}
NPC.Name = "Training Dummy"
NPC.Desc = "A man made of straw. His dream is to have a brain."
NPC.Class = "Ambient" --Ambient, Agressive, Boss
-NPC.Model = "models/headcrab.mdl"
+NPC.Model = "models/props/tools/humans/training_dummy/training_dummy.mdl"
NPC.Stats = {
["Vitality"] = 100000,
@@ -18,8 +18,7 @@ NPC.Stats = {
--Some npc's like birds have diffent names for their idle sequences
NPC.IdleSequences = {
- [0] = "lookaround",
- [1] = "Idle01",
+ [0] = "idle",
}
--Drops should be formated as [index]={["item name"], percent_drop} where percent_drop is a number from 0 to 100
@@ -88,7 +87,8 @@ end
function NPC:OnFindEnemy(enemy)
end
-
+c:\program files (x86)\steam\steamapps\common\garrysmod\garrysmod\addons\fantasy_rp_content_6_520361093\materials\models\training_dummy\training_dummy.vtf
+682 Kb 1024x1024 DXT1
--Called when the npc is attacking anything with any attack
function NPC:OnAttack(target)
end
diff --git a/gamemode/npcsystem/sv_zombie.lua b/gamemode/npcsystem/sv_zombie.lua
new file mode 100644
index 0000000..7f7e496
--- /dev/null
+++ b/gamemode/npcsystem/sv_zombie.lua
@@ -0,0 +1,187 @@
+local n = nrequire("sv_npcsystem.lua")
+local ncom = nrequire("sv_common.lua")
+local NPC = {}
+NPC.Name = "Zombie"
+NPC.Desc = "The living dead, argh!"
+NPC.Class = "Ambient" --Ambient, Agressive, Boss
+NPC.Model = "models/Zombie/Classic.mdl"
+--[[
+models/Zombie/Fast.mdl
+models/Zombie/Poison.mdl
+models/Humans/corpse1.mdl
+models/Humans/Charple01.mdl
+models/fallout/tunneler.mdl
+models/fallout/streettrog.mdl
+models/fallout/deathclaw.mdl
+models/fallout/deathclaw_alphamale.mdl
+models/fallout/deathclaw_baby.mdl
+models/fallout/deathclaw_mother.mdl
+models/fallout/gecko.mdl
+models/fallout/giantrat.mdl
+models/fallout/sporecarrier.mdl
+]]
+
+NPC.Stats = {
+ ["Vitality"] = 400,
+ ["Speed"] = 40,
+ ["AwareDist"] = 1000,
+ ["Accel"] = 25,
+ ["Decel"] = 40,
+ ["Step"] = 20, --Step height
+ ["Hull"] = HULL_HUMAN
+}
+
+--Some npc's like birds have diffent names for their idle sequences
+NPC.IdleSequences = {
+ [0] = "idle",
+}
+
+--Drops should be formated as [index]={["item name"], percent_drop} where percent_drop is a number from 0 to 100
+
+NPC.Drops = {
+ [0] = {"Rat Meat",100},--Rats will drop at least 1 meat, and have a 50% chance of dropping 2
+ [1] = {"Rat Meat",50},
+}
+
+local checkattack = function(self,ply)
+ print("Checking attack")
+ if not ply or not self then return -1 end
+ local pp,sp = ply:GetPos(),self:GetPos()
+ local isnear = (pp:Distance(sp) < 100) and (math.abs(pp.z - sp.z) < 20)
+ local canattack = CurTime() - self.lastattack > 2
+ if isnear and canattack then
+ local tr = util.TraceLine({
+ start = self:GetPos() + Vector(0,0,50),
+ endpos = ply:GetPos() + Vector(0,0,50),
+ filter = self,
+ })
+ if tr.Hit and tr.Entity == ply then
+ return 2
+ else
+ return 0
+ end
+ else
+ return 0
+ end
+end
+
+local doattack = function(self,ply)
+ print("Doing attack")
+ self.lastattack = CurTime()
+ self:StartActivity(ACT_MELEE_ATTACK1)
+ timer.Simple(1,function() --It looks like you're hit about 1/2s after animation start
+ if (not IsValid(self)) or( not IsValid(ply)) then return end --Make sure we're both still alive!
+ local sp,pp = self:GetPos(),ply:GetPos()
+ local cross = sp:Cross(pp)
+ local fppj = cross:GetNormalized():Dot(self:GetForward())
+ if math.abs(fppj) < 0.1 and sp:Distance(pp) < 75 then --If the player is still in front of us, do a trace
+ local tr = util.TraceLine({
+ start = sp + Vector(0,0,50),
+ endpos = pp + Vector(0,0,50),
+ filter = self,
+ })
+ if tr.Hit and tr.Entity == ply then
+ ply:TakeDamage(20,self,self)
+ else
+ print("tr.hit was",tr.Hit,"entity was",tr.Entity)
+ end
+ else
+ print('Player was not in front, or distance too great')
+ print(fppj)
+ print(sp:Distance(pp))
+ end
+ end)
+end
+
+--At least 1 check function must return greater than -1
+local checkrun = function(self,ply)
+ local isnearby = (1000 - ply:GetPos():Distance(self:GetPos()))/1000 --Zombies work on smell or something, idk, line of sight is hard to do cheaply
+ --But we want attack priority to override this, so only return a max of 1
+ return isnearby
+end
+
+local dorun = function(self,ply)
+ if CurTime() - self.lastwalk > 3 then
+ self:StartActivity( ACT_WALK )
+ self.lastwalk = CurTime()
+ end
+ if not ply or not ply:IsValid() then return end
+ local ppos = ply:GetPos()
+ self.TargetPos = ppos
+ if self.TargetPos ~= nil then
+ self.loco:Approach(self.TargetPos,1)
+ end
+end
+
+NPC.Attacks = {
+ [1] = {--attack the player if they're in front of us
+ [checkattack] = doattack
+ },
+ [2] = {--Run at the player
+ [checkrun] = dorun
+ }
+}
+
+--A function that takes a position and returns true if this is an acceptable place to spawn
+function NPC:SpawnLocations(pos)
+ return true
+end
+
+--The entity that is this npc's current target, if it has one. Nil otherwise
+NPC.Target = nil
+
+--All enemies that this NPC is aware of
+NPC.AwareEnemies = {}
+--Attack priority is a fucntion that takes a player, and returns an int describing it's prority to attack (higher = more important) NPC will always attack the player with the highest priority
+function NPC:AttackPriority(ply)
+ if not ply then return 0 end
+ local plypos = ply:GetPos()
+ local mypos = self:GetPos()
+ if not plypos then return 0 end
+ local dist = plypos:Distance(mypos)
+ return self.Stats["AwareDist"] - dist
+end
+
+--What to replace the ENT:RunBehaviour with
+function NPC:Act(deltat)
+end
+
+--What to replace ENT:OnStuck with
+function NPC:Stuck()
+ --Find out what we're stuck on
+ local tr = util.TraceLine({
+ start = self:GetPos() + Vector(0,0,50), --Start at about waist height
+ endpos =( self:GetForward()*50) + self:GetPos() + Vector(0,0,50),
+ filter = self
+ })
+
+end
+
+--These are just here to tell the editors/develoeprs what functions are available.. dont un-comment them out, as this could affect all the items.
+
+function NPC:OnSpawn()
+ self.lastattack = CurTime()
+ self.lastwalk = CurTime()
+end
+/*
+--If we need to do more than just reduce health on dammage
+function NPC:OnDammage(ammount)
+end
+
+--If we need to do more than just drop items on death
+function NPC:OnDeath()
+end
+
+--A particular spell was cast on this npc by player
+function NPC:OnSpell(spell, player)
+end
+
+function NPC:OnFindEnemy(enemy)
+end
+
+--Called when the npc is attacking anything with any attack
+function NPC:OnAttack(target)
+end
+*/
+
+n.RegisterNPC(NPC)