diff options
44 files changed, 971 insertions, 925 deletions
@@ -4,13 +4,12 @@ Apickx - Most of artery Built using work from: Code: FTPje - MySQLite - TheMaw - Various ideas & item system structure JetBoom - AnimBoneLib (Lua Animation API) CapsAdmin - Pac3 bobbleheadbob - Zones Art & graphics: - opengameart.org user "Emerald" - Art/icons + opengameart.org user "Emerald" Massive amounts of icons by game-icons.net users: - Lorc, http://lorcblog.blogspot.com - Delapouite, http://delapouite.com @@ -34,3 +33,9 @@ Built using work from: - Aussiesim - Sparker, http://citizenparker.com - Zeromancer - CC0 + +Various inspirations and references in no particular order: +- TheMaw's GearFox game mode base for Garry's Mod +- Simon Tatham's Portable Puzzle Collection (https://www.chiark.greenend.org.uk/~sgtatham/puzzles/) +- Puzzle Pirates (http://www.puzzlepirates.com/) +- Various rougelikes and all the cool kids at www.roguebasin.com @@ -1,7 +1,6 @@ Oh boy! A readme file! As of now, artery depends on the following addons: - bobbleheadbob's zone tool - artery_editor - skyrim NPCs - Fallout NPCs + +* bobbleheadbob's zone tool +* artery_editor diff --git a/console.ans b/console.ans Binary files differnew file mode 100644 index 0000000..9404045 --- /dev/null +++ b/console.ans diff --git a/console.txt b/console.txt new file mode 100644 index 0000000..d7f8b6f --- /dev/null +++ b/console.txt @@ -0,0 +1,16 @@ +▄█▀▀█▄ + ▀█ ▄ ▄ ▄ ▄ + ▄▀█▄█████ ▄▄█ █▄▄ ██ + ██ ██ ██ + █ ██ ▀▀█ █▀▀ ██ + █▀ ██ ▀ ▀ ██ ▄▄ + █▀▀▀▀▀██ ▄█████████▀ ▄▀ ▀█▄ ▀██▄ ▄▀██▄ ▀██▄ ▄▀██▄ + █████████ ██ ██ ▄▀ ██▀ ▀▀▀ ▀██ ▀██ + ▄█ ██ ██ ██ ▄▀ ██ ██ ██ + █ ██ ██ ██▀ ██ ██ ██ + ▄█ ██ ██ ██ ██ ██ ██ +▄█▄█ ██▄ ▄ ▀███ ▀███ ▀███ ▀███ ▄▀ +█ ███ ▀█▀ ▀██▄ ▀██▄ ▀██▄ ▀██▀ ▄▀▀▄ + ▀▀ ▀█ █ +▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▄▀ +████████████████████████████████████████████████████████████████████████▀ diff --git a/entities/entities/art_serverchanger/cl_init.lua b/entities/entities/art_serverchanger/cl_init.lua deleted file mode 100644 index ae9d143..0000000 --- a/entities/entities/art_serverchanger/cl_init.lua +++ /dev/null @@ -1,66 +0,0 @@ -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/entities/entities/art_serverchanger/init.lua b/entities/entities/art_serverchanger/init.lua deleted file mode 100644 index b72d03c..0000000 --- a/entities/entities/art_serverchanger/init.lua +++ /dev/null @@ -1,39 +0,0 @@ - -AddCSLuaFile( "cl_init.lua" ) -AddCSLuaFile( "shared.lua" ) - -include("shared.lua") - -function ENT:Initialize() - --print("NPC spawned!") - --self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE) - --self:SetUseType(SIMPLE_USE) - - if self.Model then self:SetModel(self.Model) - else print("Server changer created without model, this might be a bug!") end - - if self.Pos then self:SetPos(self.Pos) - else print("Server changer created without a position, this might be a bug!") end - - if self.OnHit then self.PhysicsCollide = self.OnHit - else print("Server changer created without an OnHit, this might be a bug!") end - - self.talking = false - - if self.Name then self:SetName(self.Name) - else print("NPC created without a name! They won't be able to open doors!") end - - if self.OnSpawn then self.OnSpawn(self) end - - self:SetMoveType(MOVETYPE_NONE) - self:PhysicsInit(SOLID_OBB) - self:SetSolid(SOLID_VPHYSICS) - - constraint.Weld(self,game.GetWorld(),0,0,0,true,true) - -end - -function ENT:PhysicsCollide(coldata,obj) - print("Physics collide detected") - if self.OnHit then self.OnHit(coldata,obj) end -end diff --git a/entities/entities/art_serverchanger/shared.lua b/entities/entities/art_serverchanger/shared.lua deleted file mode 100644 index b7fc605..0000000 --- a/entities/entities/art_serverchanger/shared.lua +++ /dev/null @@ -1,21 +0,0 @@ -ENT.Base = "base_entity" -ENT.Type = "anim" -//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:Use() - -end diff --git a/gamemode/client/cl_inventory.lua b/gamemode/client/cl_inventory.lua index 4e2545d..df0f453 100644 --- a/gamemode/client/cl_inventory.lua +++ b/gamemode/client/cl_inventory.lua @@ -54,6 +54,7 @@ end) local function CreateSheetTree(tabs,dpropertysheet) print("Createing sheet tree!") PrintTable(tabs) + local observers = {} for k,v in pairs(tabs) do if type(k) == "string" then print("Makeing inventory ", k) @@ -64,7 +65,8 @@ local function CreateSheetTree(tabs,dpropertysheet) print("Makeing inventory number ", k) local tsheet = vgui.Create("DPanel") dpropertysheet:AddSheet(v.Name,tsheet,"icon16/user.png") - v:DrawOnDPanel(tsheet) + local prox = v:DrawOnDPanel(tsheet) + v:AddObserver(prox) else error("k was not a number or string, it was a " .. type(k)) end @@ -114,7 +116,8 @@ local function BuildInventory() initalsheet:Dock(FILL) CreateSheetTree(clt.known_inventories,initalsheet) - + print("After createing sheet tree, known inventories was") + PrintTable(clt.known_inventories) end function inv.ShowInventory() @@ -140,10 +143,7 @@ function inv.ShowInventory() end,{}) end - - -hook.Add("OnSpawnMenuOpen","ArteryOpenInventory",inv.ShowInventory) -hook.Add("OnSpawnMenuClose","ArteryCloseInventory",function() +function inv.HideInventory() droppanel:Remove() state.invopen = false qframe:Hide() @@ -155,14 +155,18 @@ hook.Add("OnSpawnMenuClose","ArteryCloseInventory",function() v.panel:Close() LocalPlayer().invdisplays[k] = nil end -end) +end + + +hook.Add("OnSpawnMenuOpen","ArteryOpenInventory",inv.ShowInventory) +hook.Add("OnSpawnMenuClose","ArteryCloseInventory",inv.HideInventory) concommand.Add("showinventory",inv.ShowInventory) local viewdistance = 100 local rotatespeed = 65 local bone = nil local previousheadscale = Vector(1,1,1) -local toggle_arteryview = true +local toggle_arteryview = false hook.Add("CalcView","ArteryInventoryView",function(ply,pos,ang,fov,nearz,farz) if not toggle_arteryview then return end if bone == nil then diff --git a/gamemode/client/qtabs/cl_qprayers.lua b/gamemode/client/qtabs/cl_qprayers.lua index 9f1b9ab..af2b29f 100644 --- a/gamemode/client/qtabs/cl_qprayers.lua +++ b/gamemode/client/qtabs/cl_qprayers.lua @@ -1,4 +1,4 @@ - +do return end local p = {} function p.CreatePrayerSheet(dpanel_parent) diff --git a/gamemode/core/animation/sh_animations.lua b/gamemode/core/animation/sh_animations.lua new file mode 100644 index 0000000..3846fcc --- /dev/null +++ b/gamemode/core/animation/sh_animations.lua @@ -0,0 +1,4 @@ +if not RegisterLuaAnimation then + error("JetBoom's libanimbone is required for animations. (It's bundeled with PAC3)") + return +end diff --git a/gamemode/core/combat/sv_weaponswing.lua b/gamemode/core/combat/sv_weaponswing.lua index ea43f0b..2d45d31 100644 --- a/gamemode/core/combat/sv_weaponswing.lua +++ b/gamemode/core/combat/sv_weaponswing.lua @@ -26,8 +26,8 @@ net.Receive("artery_notifyserverofswing",function() local anim = net.ReadString() local data = net.ReadTable() - print("Got swing data for ",weapon,anim) - PrintTable(data) + --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") @@ -42,8 +42,8 @@ net.Receive("artery_notifyserverofswing",function() end) function ws.makeSwingable(tbl) - print("Makeing a swingable out of:") - PrintTable(tbl) + --print("Makeing a swingable out of:") + --PrintTable(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") diff --git a/gamemode/core/database/sv_queries.lua b/gamemode/core/database/sv_queries.lua index 07b54ac..6ef1201 100644 --- a/gamemode/core/database/sv_queries.lua +++ b/gamemode/core/database/sv_queries.lua @@ -4,7 +4,7 @@ local fn = nrequire("utility/fn.lua") local track = nrequire("core/inventory/sv_invtracker.lua") - +local log = nrequire("log.lua") local q = {} function q.serialize_player(ply) @@ -25,10 +25,14 @@ function q.serialize_player(ply) end function q.deserialize_player(ply,str) + log.debug("Deserializing player's data : " .. ply:Nick() .. "\n" .. str) track.ClearInventories(ply) ply.data = ply.data or {} ply.data.inventories = ply.data.inventories or {} local tbl = util.JSONToTable(str) + if not tbl then + log.error("Failed to deserialize player " .. ply:Nick() .. "\n" .. str) + end local invs = tbl.inventories print("Inventories was", invs) PrintTable(invs) diff --git a/gamemode/core/database/sv_setup.lua b/gamemode/core/database/sv_setup.lua index 756fb20..1fac11f 100644 --- a/gamemode/core/database/sv_setup.lua +++ b/gamemode/core/database/sv_setup.lua @@ -57,6 +57,7 @@ function sql.GetPlayerData(ply) print("Was nil, createing player data") sql.CreatePlayerTable(ply) else + PrintTable(res) assert(#res == 1,"Not unique!") local meta = res[1].MetaData local plyd = res[1].PlayerData @@ -68,7 +69,7 @@ function sql.GetPlayerData(ply) net.Start("art_sendtoserver") net.WriteString(mtbl.lastserver) net.Send(ply) - return + return nil end local _,_,x,y,z = string.find(mtbl.lastlocation,"([-%d%.]+) ([-%d%.]+) ([-%d%.]+)") local vec = {x,y,z} @@ -92,7 +93,11 @@ function sql.CreatePlayerTable(ply) --print("steamid was", s64) local plytbl = data.newdata() local plymet = data.newmeta() - local plydata = util.TableToJSON(plytbl) + print("creating player, before uttj, plytbl is") + PrintTable(plytbl) + local plydata =util.TableToJSON(plytbl) + print("after, plydata is") + print(plydata) local metdata = util.TableToJSON(plymet) print("plydata", plydata) print("metdata", metdata) @@ -106,17 +111,17 @@ function sql.CreatePlayerTable(ply) end function sql.SendPlayerToInstance(ply,ls,ll) -local s64 = ply:SteamID64() -local plydata = q.serialize_player(ply) -local plymeta = util.TableToJSON({ - lastserver = ls, - lastlocation = ll -}) -local q_str = q.s_fmt(save_player_query,plymeta,plydata,s64) -local q_suc = function(res,li) - --print("Successfully saved player data") -end -MySQLite.query(q_str,q_suc,q_fai) + local s64 = ply:SteamID64() + local plydata = q.serialize_player(ply) + local plymeta = util.TableToJSON({ + lastserver = ls, + lastlocation = ll + }) + local q_str = q.s_fmt(save_player_query,plymeta,plydata,s64) + local q_suc = function(res,li) + --print("Successfully saved player data") + end + MySQLite.query(q_str,q_suc,q_fai) end concommand.Add("DoQuery",function(ply,cmd,args) diff --git a/gamemode/core/dataloader/cl_loadglobals.lua b/gamemode/core/dataloader/cl_loadglobals.lua index 3c15e63..d286f36 100644 --- a/gamemode/core/dataloader/cl_loadglobals.lua +++ b/gamemode/core/dataloader/cl_loadglobals.lua @@ -1,4 +1,4 @@ - +local log = nrequire("log.lua") net.Receive("artery_respondfile",function() local filename = net.ReadString() local filetext = net.ReadString() @@ -27,6 +27,11 @@ net.Receive("artery_loadfile",function() net.SendToServer() else assert(#cache > 0, "File was size 0 on: " .. filename) - CompileString(cache,filename)() + local err = CompileString(cache,filename,false) + if type(err) == "function" then + err() + else + log.error(err) + end end end) diff --git a/gamemode/core/dataloader/sv_loadglobals.lua b/gamemode/core/dataloader/sv_loadglobals.lua index cf6f838..7689c54 100644 --- a/gamemode/core/dataloader/sv_loadglobals.lua +++ b/gamemode/core/dataloader/sv_loadglobals.lua @@ -5,6 +5,11 @@ local function ExecuteOnFolder(dir, recursive, func) local path = "data/artery/" local fpath = table.concat({path,dir,"/*"}) local files, directories = file.Find(fpath,"GAME") + print("Looking for files in ", fpath, "Found:") + print("files:") + PrintTable(files) + print("dirs:") + PrintTable(directories) for k,v in pairs(files) do local callpath = table.concat({path,dir,"/",v}) func(callpath) @@ -25,17 +30,30 @@ local co local function loadglobals() co = coroutine.create(function() ExecuteOnFolder("global",true,function(f) - print("Loading global file:", f) + log.debug("Loading global file : " .. f) local filetxt = file.Read(f,"GAME") local filename = string.GetFileFromFilename(f) if string.find(filename,"^cl_") then - print("Added",f,"to be loaded clientside") coroutine.yield(f,filetxt) elseif string.find(filename,"^sv_") then - CompileString(filetxt,f)() + local func = CompileString(filetxt,f,false) + if type(func) == "function" then + xpcall(func,function(e) + log.error(string.format("%s : %s",f,e)) + end) + else + log.error(string.format("Failed to compile file %s :\n%s"),filename,func) + end coroutine.yield() else - CompileString(filetxt,f)() + local func = CompileString(filetxt,f,false) + if type(func) == "function" then + xpcall(func,function(e) + log.error(string.format("%s : %s",f,e)) + end) + else + log.error(string.format("Failed to compile file %s :\n%s",filename,func)) + end coroutine.yield(f,filetxt) end end) @@ -44,12 +62,11 @@ end local csco = {} local function load_cs_files(ply) - print("Told to load csfiles for", ply:Nick()) + log.debug("Told to load csfiles for", ply:Nick()) csco[ply] = coroutine.create(function() - print("Loading cs files, toload is") for k,v in pairs(toload) do print(k) end for k,v in pairs(toload) do - print("Loading cs file:", k,"for",ply:Nick()) + log.debug("Loading cs file:", k,"for",ply:Nick()) net.Start("artery_loadfile") net.WriteString(k) local hash = util.CRC(v) @@ -64,7 +81,6 @@ local state = "done" local n timer.Create("inc_load_timer",0.1,0,function() if state == "loading_sv" then - print("co is", co) if coroutine.status(co) == "suspended" then local _,fn,t = coroutine.resume(co) if fn and t then @@ -106,7 +122,7 @@ end) loadglobals() state = "loading_sv" hook.Add("PlayerInitialSpawn","artery_loadglobals",function(ply) - print("Doing player inital span, loading globals for " , ply:Nick()) + log.debug("Doing player inital spawn, loading globals for " , ply:Nick()) timer.Simple(1,function() load_cs_files(ply) state = "loading_cl" diff --git a/gamemode/core/inventory/cl_invtracker.lua b/gamemode/core/inventory/cl_invtracker.lua index 258a271..1e75ef2 100644 --- a/gamemode/core/inventory/cl_invtracker.lua +++ b/gamemode/core/inventory/cl_invtracker.lua @@ -48,13 +48,13 @@ local drawsheeton = function(id,inventory,higharchy) -- draw.RoundedBox( 4, 0, 0, w, h, Color( 0, 128, 255 ) ) --end if inventory.DrawOnDPanel then - --print("Has drawondpanel") + print("Has drawondpanel") local prox = inventory:DrawOnDPanel(tpanel) - --print("Prox returned was",prox) - --PrintTable(prox) + print("Prox returned was",prox) + PrintTable(prox) known_inventories[id]:AddObserver(prox) - --print("Oservers is now") - --PrintTable(known_inventories[id].observers) + print("Oservers is now") + PrintTable(known_inventories[id].observers) end invsheet:AddSheet( inventory.Name, tpanel, "icon16/tab.png" ) end @@ -91,17 +91,23 @@ net.Receive("art_UpdateInventory",function() local position = net.ReadTable() if isput then local item_name = net.ReadString() - --print("Putting ", item_name, "into inventory ",id, " at position") - --PrintTable(position) + print("Putting ", item_name, "into inventory ",id, " at position") + PrintTable(position) local item_data = net.ReadData(net.ReadUInt(32)) local item = itm.GetItemFromData(item_name,item_data) known_inventories[id]:Put(position,item) + for k,v in pairs(known_inventories[id].observers) do + v:Put(position,item) + end --print("Inventorie's observers:") --PrintTable(known_inventories[id].observers) --print("Inventory is now") --PrintTable(known_inventories[id]) else known_inventories[id]:Remove(position) + for k,v in pairs(known_inventories[id].observers) do + v:Remove(position) + end end end) diff --git a/gamemode/core/inventory/common/animations/sh_swing_mele.lua b/gamemode/core/inventory/common/animations/sh_swing_mele.lua index 4521ddd..09f79e7 100644 --- a/gamemode/core/inventory/common/animations/sh_swing_mele.lua +++ b/gamemode/core/inventory/common/animations/sh_swing_mele.lua @@ -1,5 +1,5 @@ -print("Hello from sh_swing_mele.lua!") - +nrequire("sh_animations.lua") + RegisterLuaAnimation('swing_onehand_left', { FrameData = { { diff --git a/gamemode/core/inventory/sv_invtracker.lua b/gamemode/core/inventory/sv_invtracker.lua index 7df4175..f1f3c3d 100644 --- a/gamemode/core/inventory/sv_invtracker.lua +++ b/gamemode/core/inventory/sv_invtracker.lua @@ -226,8 +226,11 @@ function plymeta:GiveItem(tbl) if type(p) == "table" then v:Put(p,tbl) return + else + log.debug("inventory " .. k .. " couldn't fit it...") end end + PrintTable(tbl) error("Unable to find place to put item") end diff --git a/gamemode/core/logo.lua b/gamemode/core/logo.lua new file mode 100644 index 0000000..05c8841 --- /dev/null +++ b/gamemode/core/logo.lua @@ -0,0 +1,16 @@ +local ngm = GM or GAMEMODE +timer.Simple(5,function() + local logo = [[ + ___ + - -_, , +( ~/|| || +( / || ,._-_ =||= _-_ ,._-_ '\\/\\ + \/==|| || || || \\ || || ;' + /_ _|| || || ||/ || ||/ +( - \\, \\, \\, \\,/ \\, |/ + ( + -_- + ]] + print(logo) + print(string.format("Version %d.%d.%d",unpack(ngm.Version))) +end) diff --git a/gamemode/core/mapstich/cl_mapstich.lua b/gamemode/core/mapstich/cl_mapstich.lua index 62cad3f..6f85eeb 100644 --- a/gamemode/core/mapstich/cl_mapstich.lua +++ b/gamemode/core/mapstich/cl_mapstich.lua @@ -1,9 +1,14 @@ --[[ The client constantly cheks to see if we're in a serverchnage zone ]] -nrequire("sh_zones.lua") +if not nrequire("sh_zones.lua") then return end hook.Add("Think","artery_checklevelchange",function() - local z = LocalPlayer():GetCurrentZone() + local z + pcall(function() + z = LocalPlayer():GetCurrentZone() + end,function() + --This happens ocasionally when the player has loaded, and is running lua, but the LocalPlayer() entity isn't valid yet. + end) --print("looks like i'm in zone",z) if z then net.Start("art_zonechange") diff --git a/gamemode/core/mapstich/sv_mapstich.lua b/gamemode/core/mapstich/sv_mapstich.lua index 0a20828..91b4ec2 100644 --- a/gamemode/core/mapstich/sv_mapstich.lua +++ b/gamemode/core/mapstich/sv_mapstich.lua @@ -1,6 +1,6 @@ --Make sure zones are loaded already nrequire("sv_mysqlite.lua") -nrequire("sh_zones.lua") +if not nrequire("sh_zones.lua") then return end local q = nrequire("core/database/sv_queries.lua") --if not zones then error("This thing needs zones to function!") end diff --git a/gamemode/core/npc/cl_npcmap.lua b/gamemode/core/npc/cl_npcmap.lua index ddbd3cd..8e4477d 100644 --- a/gamemode/core/npc/cl_npcmap.lua +++ b/gamemode/core/npc/cl_npcmap.lua @@ -1,14 +1,12 @@ --local tblf = include("/../gamemodes/artery/gamemode/utility/mapfuncs.lua") -print("Hello from cl_ncpmap in core") +local log = nrequire("log.lua") local drawmap = false hook.Add( "ScoreboardShow", "ShowNPCMap", function() - print("Showing npc map") drawmap = true return true end ) hook.Add( "ScoreboardHide", "ShowNPCMap", function() - print("Hiding npc map") drawmap = false end ) local white = Color( 255, 255, 255, 255 ) @@ -26,16 +24,11 @@ local mapicons = --[[mapicons or]] { hook.Add( "HUDPaint", "paintsprites", function() local function drawsubarea(node) - print("drawing") - PrintTable(node) if node.isleaf then render.SetMaterial( node.material ) render.DrawSprite( node.pos, 64, 64, white ) - print("Actually drawing") - PrintTable(node) else if not node.icons then - print("found area without any icons!") for k,v in pairs(node) do print(k,":",v) end end for k,v in pairs(node.icons or {}) do @@ -44,11 +37,9 @@ hook.Add( "HUDPaint", "paintsprites", function() end end if drawmap then - print("starting this draw") cam.Start3D() drawsubarea(mapicons["global"]) cam.End3D() - print("done with this draw") end end ) @@ -91,8 +82,7 @@ end) --Add an icon to the map local function addmapicon(material, subarea, position) - print("adding map icon, material:",material,"subarea:",subarea,"bordertbl:",bordertbl) - print("mat",material,"subarea",subarea,"position",position) + log.debug("adding map icon, material:",material,"subarea:",subarea,"bordertbl:",bordertbl) local parts = string.Explode(":",subarea) -- print("parts:",parts) -- PrintTable(parts) @@ -156,17 +146,14 @@ addmaparea("","global",{ ]] net.Receive("addmapicon",function() - print("got recieve for map icon") local matstr = net.ReadString() local subarea = net.ReadString() local matpos = net.ReadVector() addmapicon(matstr,subarea,matpos) - print("MapIcons is now") - PrintTable(mapicons) end) net.Receive("addmaparea",function() - print("got receive for map area") + --print("got receive for map area") -- local matstr = net.ReadString() -- local subarea = net.ReadString() -- local boarders = net.ReadTable() diff --git a/gamemode/core/npc/cl_shop.lua b/gamemode/core/npc/cl_shop.lua index 873a37c..9c5ffb2 100644 --- a/gamemode/core/npc/cl_shop.lua +++ b/gamemode/core/npc/cl_shop.lua @@ -1,6 +1,5 @@ local inv = nrequire("client/cl_inventory.lua") local itm = nrequire("core/inventory/item.lua") -print("in cl_shop inv is", inv) local w,h = ScrW(),ScrH() local function DrawShopItemOnDPanel(dp,itemtbl,cost) --An item is a string, and int cost diff --git a/gamemode/core/npc/sv_huntingspawner.lua b/gamemode/core/npc/sv_huntingspawner.lua index 279d834..153b961 100644 --- a/gamemode/core/npc/sv_huntingspawner.lua +++ b/gamemode/core/npc/sv_huntingspawner.lua @@ -1,6 +1,7 @@ --[[ 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 = {} @@ -34,7 +35,7 @@ local function SpawnMonsterFor(ply,zone) end if npctype == nil then - print(ply,"got lucky this time...") + --print(ply,"got lucky this time...") return end --print("I will spawn a ",npctype,"to attack ",ply,"!") diff --git a/gamemode/core/pac/cl_pac.lua b/gamemode/core/pac/cl_pac.lua index fc55eb1..063e1b1 100644 --- a/gamemode/core/pac/cl_pac.lua +++ b/gamemode/core/pac/cl_pac.lua @@ -7,7 +7,7 @@ --If the player dosen't have PAC3 installed, then overwrite all pac-related network events to display an error. if pac == nil then local function no_pac_panic() - error("This gamemode require PAC3 to display armor/cloths, please be sure clients are downloading this addon from somewhere (perferably the workshop!)") + error("CapsAdmin's PAC3 is required for items, please download it from somewhere (perferably the workshop!)") end local networkmsgs = { "artery_downloadpac", diff --git a/gamemode/core/zones/sh_zones.lua b/gamemode/core/zones/sh_zones.lua index ca66abb..69c6e04 100644 --- a/gamemode/core/zones/sh_zones.lua +++ b/gamemode/core/zones/sh_zones.lua @@ -1,611 +1,6 @@ -local version = 1.20 -- Older versions will not run if a newer version is used in another script. ---[[ - ZONES - by Bobbleheadbob with help from Zeh Matt - WARNING: If you edit any of these files, make them use a different namespace. Multiple scripts may depend on this library so modifying it can break other scripts. - - Purpose: - For easy in-game designation of persistent polygonal zones which are used by any script. - - How to Use: - All zones are saved in zones.List; see an example below. - Zone creation is handled with weapon_zone_designator and ent_zone_point, but can be done in code as well. - When a zone is created, changed, or removed all zones are synced to clients. When clients join they are also synced. - Any extra details can be saved to a zone. Everything is written to a txt file and is persistent to the map. - - Since multiple scripts might use the zones system, don't assume that every zone is related to your script. - To register a zone class, use zones.RegisterClass(class, color); use a unique string like "Scriptname Room". - When a zone class is registered, admins can use the tool to create new ones. - When a new zone is created, the "OnZoneCreated" hook is called serverside. See the example file for documentation. - When a zone is loaded into the game, the "OnZoneLoaded" hook is called serverside. See the example file for documentation. - When a player edits a zone's properties, the "ShowZoneOptions" hook is called clientside. See the example file for documentation. - - Use zones.FindByClass() to find all zones which are of a given class. - Use ply:GetCurrentZone() to find the zone that a player is standing in. - - Installation: - This is a shared file so include it in any shared environment. Also include ent_zone_point and weapon_zone_designator as a shared ent and weapon. - You should not put this file directly in lua/autorun. - - License: - YOU MAY use/edit this however you want, as long as you give proper attribution. - YOU MAY distribute this with other scripts whether they are paid or free. - YOU MAY NOT distribute this on its own. It must accompany another script. - - Enjoy! ~Bobbleheadbob -]] - -local table, math, Vector, pairs, ipairs, ents, bit = table, math, Vector, pairs, ipairs, ents, bit - -if zones then - local diff = math.abs(math.floor(version)-math.floor(zones.version)) > 0 - if diff then - ErrorNoHalt("WARNING! Two scripts use VERY different versions of the zones API. Please tell one of them to update their script!\n") - end - if zones.version > version then - if diff then - print("The outdated version of zones is located at: "..debug.getinfo(1,"S").short_src) - end - print("A new version of zones exists. Using version "..zones.version.." instead of "..version) - return - elseif zones.version < version then - if diff then - print("The outdated version of zones is located at: "..debug.getinfo(zones.RegisterClass,"S").short_src) - end - print("A new version of zones exists. Using version "..version.." instead of "..zones.version) - end - -else - print("Loaded zones " ..version) -end - -zones = zones or {} -zones.version = version - -zones.Classes = zones.Classes or {} -zones.List = zones.List or {} -zones.Map = zones.Map or {} - - -//Common interface functions: - --- Registers a zone class which can then be created using weapon_zone_designator -function zones.RegisterClass(class,color) - zones.Classes[class] = color -end - - -local plymeta = FindMetaTable("Player") ---returns one of the zones a player is found in. Also returns that zone's ID. Class is optional to filter the search. -function plymeta:GetCurrentZone(class) - local c = zones.Cache[self][class or "___"] - if c then return unpack(c) end - local z,id = zones.GetZoneAt(self:GetPos(), class) - zones.Cache[self][class or "___"] = {z,id} - return z,id -end - ---returns a table of zones the player is in. Class is optional to filter the search. -function plymeta:GetCurrentZones(class) - return zones.GetZonesAt(self:GetPos(),class) -end - -function zones.GetZoneAt(pos,class) --works like above, except uses any point. - - local nearby = zones.GetNearbyZones(pos) - - for k,zone in pairs(nearby) do - - if class and class != zone.class then continue end - if not pos:WithinAABox(zone.bounds.mins, zone.bounds.maxs) then - continue - end - - for k1, points in pairs(zone.points) do - if zones.PointInPoly(pos,points) then - local z = points[1].z - if pos.z >= z and pos.z < z + zone.height[k1] then - return zone,k - end - end - end - end - - return nil, -1 - -end - -function zones.GetZonesAt(pos,class) --works like above, except uses any point. - local tbl = {} - local nearby = zones.GetNearbyZones(pos) - for k,zone in pairs(nearby) do - if class and class != zone.class then continue end - if not pos:WithinAABox(zone.bounds.mins,zone.bounds.maxs) then continue end - for k1, points in pairs(zone.points) do - if zones.PointInPoly(pos,points) then - local z = points[1].z - if pos.z >= z and pos.z < z + zone.height[k1] then - tbl[k] = zone - end - end - end - end - return tbl -end - ---Gets a list of all zones which are of the specified class. -function zones.FindByClass(class) - local tbl = {} - - for k,v in pairs(zones.List) do - if v.class == class then - tbl[k] = v - end - end - - return tbl -end - ---Returns the numerical ID of a zone. -function zones.GetID(zone) - return table.KeyFromValue(zones.List,zone) -end - - - - -//Getting into the meat of the API: -local mapMins = -16000 -local mapMaxs = 16000 -local mapSize = 32000 -local chunkSize = 128 - -local function GetZoneIndex(pos) - - local x = pos.x + mapMaxs - local y = pos.y + mapMaxs - local z = pos.z + mapMaxs - - local idxX = math.floor(x / chunkSize) - local idxY = math.floor(y / chunkSize) - local idxZ = math.floor(z / chunkSize) - local idx = bit.bor(bit.lshift(idxX, 24), bit.lshift(idxY, 14), idxZ) - - return idx - -end - -local function Floor(x,to) - return math.floor(x / to) * to -end -local function Ceil(x,to) - return math.ceil(x / to) * to -end - -function zones.CreateZoneMapping() - zones.Map = {} - for _, zone in pairs(zones.List) do - local mins = zone.bounds.mins - local maxs = zone.bounds.maxs - for x = Floor(mins.x,chunkSize), Ceil(maxs.x + 1,chunkSize), chunkSize do - for y = Floor(mins.y,chunkSize), Ceil(maxs.y + 1,chunkSize), chunkSize do - for z = Floor(mins.z,chunkSize), Ceil(maxs.z + 1,chunkSize), chunkSize do - local idx = GetZoneIndex(Vector(x, y, z)) - zones.Map[idx] = zones.Map[idx] or {} - table.insert(zones.Map[idx], zone) - end - end - end - end -end - -function zones.GetNearbyZones(pos) - //This system isn't working. - -- local idx = GetZoneIndex(pos) - -- return zones.Map[idx] or {} - return zones.List -end - -zones.Cache = {} -local function ClearCache() - for k,v in pairs(player.GetAll()) do - zones.Cache[v] = {} - end -end -ClearCache() -hook.Add("Tick","zones_cache",ClearCache) - -if SERVER then - util.AddNetworkString("zones_sync") - util.AddNetworkString("zones_class") - - function zones.SaveZones() - if not file.Exists("zones","DATA") then - file.CreateDir("zones") - end - file.Write("zones/"..game.GetMap():gsub("_","-"):lower()..".txt", util.TableToJSON(zones.List)) - end - concommand.Add("zone_save",function(ply,c,a) - if not ply:IsAdmin() then return end - zones.SaveZones() - end) - - function zones.LoadZones() - local tbl = file.Read("zones/"..game.GetMap():gsub("_","-"):lower()..".txt", "DATA") - zones.List = tbl and util.JSONToTable(tbl) or {} - - //Update legacy files: - for k,v in pairs(zones.List)do - if not v.bounds then - zones.CalcBounds(v) - end - - hook.Run("OnZoneLoaded",v,v.class,k) - end - end - - local sync = false - local syncply - - function zones.Sync(ply) - sync = true - syncply = ply - end - - hook.Add("Tick","zones_sync",function() - if sync then - net.Start("zones_sync") - net.WriteTable(zones.List) - if syncply then - net.Send(syncply) - syncply = nil - else - net.Broadcast() - zones.CreateZoneMapping() - end - sync = false - end - end) - - function zones.CreateZoneFromPoint(ent) - - local zone = { - points = {{}}, --only 1 area when creating a new zone. - height = {ent:GetTall()}, - class = ent:GetZoneClass(), - bounds = {} - } - - local id = table.maxn(zones.List) + 1 - local cur = ent - repeat - local pos = cur:GetPos() - Vector(0,0,2) - zone.points[1][#zone.points[1]+1] = pos - - cur:SetZoneID(id) - cur = cur:GetNext() - - until (cur == ent) - - zones.CalcBounds(zone,true) - - zones.List[id] = zone - hook.Run("OnZoneCreated",zone,zone.class,id) - - zones.Sync() - - - return zone, id - - end - - function zones.CalcBounds(zone,newZone) - local mins,maxs = Vector(10000000,10000000,10000000), Vector(-10000000,-10000000,-10000000) - for areanum,area in pairs(zone.points)do - for k,pos in pairs(area) do - maxs.x = math.max(pos.x, maxs.x) - maxs.y = math.max(pos.y, maxs.y) - maxs.z = math.max(pos.z+zone.height[areanum], maxs.z) - mins.x = math.min(pos.x, mins.x) - mins.y = math.min(pos.y, mins.y) - mins.z = math.min(pos.z, mins.z) - end - end - zone.bounds = {["mins"]=mins,["maxs"]=maxs} - if not newZone then - hook.Run("OnZoneChanged",zone,zone.class,zones.GetID(zone)) - end - end - - function zones.Remove(id) - hook.Run("OnZoneRemoved",zones.List[id],zones.List[id].class,id) - zones.List[id] = nil - zones.Sync() - end - - function zones.CreatePointEnts(removeThese) --removeThese is optional. - for k,v in pairs(removeThese or ents.FindByClass("ent_zone_point")) do --remove old - v:Remove() - end - - --create new - for id,zone in pairs(zones.List)do - - for k, area in pairs(zone.points) do - - local first - local curr - for k2,point in ipairs(area)do - - local next = ents.Create("ent_zone_point") - - if IsValid(curr) then - next:SetPos(point+Vector(0,0,1)) - curr:SetNext(next) - -- curr:DeleteOnRemove(next) - else - first = next - next:SetPos(point+Vector(0,0,1)) - end - - next.LastPoint = curr - curr = next - next:SetTall(zone.height[k]) - next:SetZoneClass(zone.class) - next:Spawn() - next:SetZoneID(id) - next:SetAreaNumber(k) - - end - - curr:SetNext(first) - -- curr:DeleteOnRemove(first) - first.LastPoint = curr - - end - end - - end - - function zones.Merge(from,to) - - local zfrom, zto = zones.List[from], zones.List[to] - - table.Add(zto.points, zfrom.points) - table.Add(zto.height, zfrom.height) - - zones.CalcBounds(zto) - zones.Remove(from) - - hook.Run("OnZoneMerged",zto,zto.class,to,zfrom,zfrom.class,from) - - zones.Sync() - - end - - function zones.Split(id,areanum) - local zone = zones.List[id] - local pts, h, bound = zone.points[areanum], zone.height[areanum] - - table.remove(zone.points,areanum) - table.remove(zone.height,areanum) - - if #zone.points == 0 then - zones.Remove(id) - end - - local new = table.Copy(zone) - new.points = {pts} - new.height = {h} - - local id = table.maxn(zones.List)+1 - zones.List[id] = new - - zones.CalcBounds(zone) - zones.CalcBounds(new) - - hook.Run("OnZoneSplit",new,new.class,id,zone,id) - - zones.Sync() - - return new,id - - end - - function zones.ChangeClass(id,class) - local zone,new = zones.List[id],{} - new.points = zone.points - new.height = zone.height - new.bounds = zone.bounds - new.class = class - - zones.List[id] = new - - hook.Run("OnZoneCreated",new,class,id) - - zones.Sync() - end - - - local mapMins = -16000 - local mapMaxs = 16000 - local mapSize = 32000 - local chunkSize = 128 - - function zones.GetZoneIndex(pos) - - local x = math.Remap(pos.x, mapMins, mapMaxs, 0, mapSize) - local y = math.Remap(pos.y, mapMins, mapMaxs, 0, mapSize) - local z = math.Remap(pos.z, mapMins, mapMaxs, 0, mapSize) - - local idxX = math.floor(x / chunkSize) - local idxY = math.floor(y / chunkSize) - local idxZ = math.floor(z / chunkSize) - local idx = bit.bor(bit.lshift(idxX, 24), bit.lshift(idxY, 14), idxZ) - - return idx - - end - - hook.Add("InitPostEntity","zones_load",function() - zones.LoadZones() - end) - hook.Add("PlayerInitialSpawn","zones_sync",function(ply) - zones.Sync(ply) - end) - - net.Receive("zones_class",function(len,ply) - if not ply:IsAdmin() then return end - local id = net.ReadFloat() - local class = net.ReadString() - - for k,v in pairs(ents.FindByClass("ent_zone_point"))do - if v:GetZoneID() == id then - v:SetZoneClass(class) - end - end - - zones.ChangeClass(id,class) - - end) - -else - net.Receive("zones_sync",function(len) - zones.List = net.ReadTable() - zones.CreateZoneMapping() - end) - - function zones.ShowOptions(id) - - local zone = zones.List[id] - local class = zone.class - - local frame = vgui.Create("DFrame") - zones.optionsFrame = frame - frame:MakePopup() - frame:SetTitle("Zone Settings") - - local ztitle = vgui.Create("DLabel",frame) - ztitle:Dock(TOP) - ztitle:DockMargin(2,0,5,5) - ztitle:SetText("Zone Class:") - ztitle:SizeToContents() - - local zclass = vgui.Create("DComboBox",frame) - zclass:Dock(TOP) - zclass:DockMargin(0,0,0,5) - for k,v in pairs(zones.Classes) do - zclass:AddChoice(k,nil,k == class) - end - function zclass:OnSelect(i,class) - net.Start("zones_class") - net.WriteFloat(id) - net.WriteString(class) - net.SendToServer() - - frame.content:Remove() - - frame.content = vgui.Create("DPanel",frame) - frame.content:Dock(FILL) - frame.content:DockPadding(5,5,5,5) - - local w,h = hook.Run("ShowZoneOptions",zone,class,frame.content,id,frame) - frame:SizeTo((w or 100)+8,(h or 2)+78, .2) - frame:MoveTo(ScrW()/2-((w or 292)+8)/2,ScrH()/2-((h or 422)+78)/2, .2) - end - - frame.content = vgui.Create("DPanel",frame) - frame.content:Dock(FILL) - frame.content:DockPadding(5,5,5,5) - - local w,h = hook.Run("ShowZoneOptions",zone,class,frame.content,id,frame) - frame:SetSize((w or 100)+8,(h or 2)+78) - frame:Center() - - end - -end - - - -//returns the point of intersection between two infinite lines. -local function IntersectPoint(line1, line2) - - local x1,y1,x2,y2,x3,y3,x4,y4 = line1.x1,line1.y1,line1.x2,line1.y2,line2.x1,line2.y1,line2.x2,line2.y2 - - local m1,m2 = (y1-y2)/((x1-x2)+.001),(y3-y4)/((x3-x4)+.001) --get the slopes - local yint1,yint2 = (-m1*x1)+y1,(-m2*x3)+y3 --get the y-intercepts - local x = (yint1-yint2)/(m2-m1) --calculate x pos - local y = m1*x+yint1 --plug in x pos to get y pos - - return x,y - -end -//Returns a bool if two SEGEMENTS intersect or not. -local function Intersect(line1, line2) - - local x,y = IntersectPoint(line1, line2) - - local sx,sy = tostring(x), tostring(y) - if (sx == "-inf" or sx == "inf" or sx == "nan") then - return false - end - - local minx1, maxx1 = math.min(line1.x1,line1.x2)-.1, math.max(line1.x1,line1.x2)+.1 - local minx2, maxx2 = math.min(line2.x1,line2.x2)-.1, math.max(line2.x1,line2.x2)+.1 - local miny1, maxy1 = math.min(line1.y1,line1.y2)-.1, math.max(line1.y1,line1.y2)+.1 - local miny2, maxy2 = math.min(line2.y1,line2.y2)-.1, math.max(line2.y1,line2.y2)+.1 - - if (x >= minx1) and (x <= maxx1) and (x >= minx2) and (x <= maxx2) then - - if (y >= miny1) and (y <= maxy1) and (y >= miny2) and (y <= maxy2) then - - --debugoverlay.Sphere( Vector(x,y,LocalPlayer():GetPos().z), 3, FrameTime()+.01, Color(255,0,0), true) - - return true - - end - - end - +if not zones then + error("Bobbleheadbob's Zone's api is required for cross-server teleportation and npc spawning") return false - end -function zones.PointInPoly(point,poly) //True if point is within a polygon. - - local ray = { - x1 = point.x, - y1 = point.y, - x2 = 100000, - y2 = 100000 - } - - local inside = false - - local line = { - x1 = 0, - y1 = 0, - x2 = 0, - y2 = 0 - } - - //Perform ray test - for k1, v in pairs(poly) do - local v2 = poly[k1+1] - if not v2 then - v2 = poly[1] - end - - line["x1"] = v.x - line["y1"] = v.y - line["x2"] = v2.x - line["y2"] = v2.y - - if Intersect(ray,line) then - inside = !inside - end - - end - - return inside -end +return true diff --git a/gamemode/init.lua b/gamemode/init.lua index ac530f1..15f9885 100644 --- a/gamemode/init.lua +++ b/gamemode/init.lua @@ -3,5 +3,3 @@ AddCSLuaFile( "shared.lua" ) AddCSLuaFile( "cl_init.lua" ) AddCSLuaFile("nrequire.lua") include( "shared.lua" ) - -print("Hello from init.lua") diff --git a/gamemode/inventorysystem/prayers/cl_prayers.lua b/gamemode/inventorysystem/prayers/cl_prayers.lua index aba778e..afea1cc 100644 --- a/gamemode/inventorysystem/prayers/cl_prayers.lua +++ b/gamemode/inventorysystem/prayers/cl_prayers.lua @@ -20,6 +20,13 @@ function pray:DrawOnDPanel(panel) local ap = self.activeprayers[i] explain:SetText(ap ~= nil and ap.Description or "Select a prayer") end + rec:Receiver("prayer",function(s,tbl,dropped,mi,x,y) + if not dropped then return end + self.activeprayers[i] = tbl.item + if tbl.item.DoOnPanel then + tbl.item.DoOnPanel(s) + end + end,{}) agrid:AddItem(rec) end agrid:Dock(TOP) @@ -38,15 +45,31 @@ function pray:DrawOnDPanel(panel) grid:SetCols(4) grid:SetColWide(w) grid:SetRowHeight(w) - for k,v in pairs(self.track) do + local function drawprayer(prayer) local rec = vgui.Create("DImageButton",grid) - rec:SetText(v.Name) + rec:SetText(prayer.Name) rec:SetSize(w,w) - if(v.DoOnPanel) then - v:DoOnPanel(rec) + if(prayer.DoOnPanel) then + prayer:DoOnPanel(rec) end + rec.item = prayer + rec:Droppable("prayer") grid:AddItem(rec) end + + for k,v in pairs(self.track) do + drawprayer(v) + end + + local observer = {} + observer.Put = function(obs,pos,item) + print("Prayer observer got request to put") + drawprayer(item) + end + observer.Remove = function(obs,pos,item) + print("I should never remove a prayer!") + end + return observer end --Rebind f1, f2, f3, f4 to prayers diff --git a/gamemode/inventorysystem/prayers/sh_prayers.lua b/gamemode/inventorysystem/prayers/sh_prayers.lua index 15cd2af..e1e7347 100644 --- a/gamemode/inventorysystem/prayers/sh_prayers.lua +++ b/gamemode/inventorysystem/prayers/sh_prayers.lua @@ -14,7 +14,10 @@ end inv.Name = "Prayers" inv.track = {} function inv:FindPlaceFor(item) - return {#track} + if item.isprayer then + return {#self.track} + end + return nil end function inv:CanFitIn(pos,item) return pos[1] == #self.track diff --git a/gamemode/inventorysystem/shapedinventory/sh_shaped.lua b/gamemode/inventorysystem/shapedinventory/sh_shaped.lua index 66aa24b..69e18ca 100644 --- a/gamemode/inventorysystem/shapedinventory/sh_shaped.lua +++ b/gamemode/inventorysystem/shapedinventory/sh_shaped.lua @@ -11,7 +11,7 @@ if CLIENT then inv = nrequire("cl_shaped.lua") end inv.Name = "Shaped Inventory" inv.tracker = {} inv.width = 5 -inv.height = 5 +inv.height = 10 local function calcposition(width,height,row,col) return ((row-1) * width) + col @@ -32,6 +32,7 @@ local function canfitin(self,arow,acol,shape) end function inv:FindPlaceFor(item) + if item.Shape == nil then return nil end for row = 1, self.height do for col = 1, self.width do if canfitin(self,row,col,item.Shape) then @@ -43,6 +44,7 @@ function inv:FindPlaceFor(item) end function inv:CanFitIn(tbl,item) + if item.Shape == nil then return false end if canfitin(self,tbl[1],tbl[2],item.Shape) then return true else diff --git a/gamemode/inventorysystem/skills/cl_skills.lua b/gamemode/inventorysystem/skills/cl_skills.lua index c324a49..d4dbf65 100644 --- a/gamemode/inventorysystem/skills/cl_skills.lua +++ b/gamemode/inventorysystem/skills/cl_skills.lua @@ -1,53 +1,6 @@ local inv = {} ---[[ -inv.allskills = { - ["forageing"] = { - "hunting", - "butchering", - "woodcutting", - "plant identification", - }, - ["farming"] = { - "domestication", - "sowing", - "arboriculture", - "apiarism", - "reaping", - "fishing", - }, - ["artisanship"] = { - "pottery", - "glass blowing", - "cooking", - "tanning", - "tailoring", - "metalworking", - "lockpicking", - "herbalism", - "alchemy", - "jewlery", - }, - ["culture"] = { - "litteracy", - "writeing", - "speech", - "negotiation", - "painting", - "performing", - }, - ["adventuring"] = { - "polearm", - "axeplay", - "swordplay", - "knifeing", - "fenceing", - "lockpicking", - "archery", - "throwing", - }, -} -]] +local sc = nrequire("sh_skillcommon.lua") --the gui elements local elements = {} @@ -63,17 +16,21 @@ local levelfunc = function(val) end local set_xp_of = function(name,ammt) + print("setting xp of", name," to ", ammt) local lvl,frac = levelfunc(ammt) - elements[name].label:SetText(string.format("%s : %d (%d%%)",name,lvl,frac)) + elements[name].label:SetText(string.format("%s : %d (%2.5f%%)",name,lvl,frac)) elements[name].bar:SetFraction(frac) end inv.DrawOnDPanel = function(self,panel) print("Drawing skills on panel") + PrintTable(sc.SkillList()) + print("with") + PrintTable(self.skills) local sheet = vgui.Create( "DColumnSheet", panel ) sheet:Dock( FILL ) - for k,v in pairs(self.allskills) do + for k,v in pairs(sc.SkillList()) do local spanel = vgui.Create("DPanel", sheet) spanel:Dock(FILL) local layout = vgui.Create("DListLayout", spanel) @@ -89,7 +46,7 @@ inv.DrawOnDPanel = function(self,panel) ["label"] = label, ["bar" ] = bar, } - set_xp_of(j,self.skills[j]) + set_xp_of(j,self.skills[j] or 0) ipanel:Add(label) ipanel:Add(bar) ipanel:InvalidateLayout() @@ -102,11 +59,15 @@ inv.DrawOnDPanel = function(self,panel) local prox = {} prox.Put = function(s,position,item) - set_xp_of(position[1],s[position[1]]) + print("Calling inventory's put") + print("At time of call, skill was") + PrintTable(self) + set_xp_of(position[1],self.skills[position[1]]) end prox.Remove = function(s,position) - set_xp_of(position[1],s[position[1]]) + print("Calling inventory's remove") + set_xp_of(position[1],self.skills[position[1]]) end return prox diff --git a/gamemode/inventorysystem/skills/sh_skillcommon.lua b/gamemode/inventorysystem/skills/sh_skillcommon.lua new file mode 100644 index 0000000..d48fb98 --- /dev/null +++ b/gamemode/inventorysystem/skills/sh_skillcommon.lua @@ -0,0 +1,68 @@ +--[[ + Common functions since skills are a special inventory, adding skills need to be a special item +]] +local itm = nrequire("item.lua") + +--Common things +--Make sure items have a "name" and "ammt" attribute +local item = {} + +item.Name = "Skill" + +item.isskill = true + +item.Serialize = function(self) + return util.TableToJSON({ + name = self.name, + ammt = self.ammt + }) +end + +item.DeSerialize = function(self,data) + local tbl = util.JSONToTable(data) + tbl.isskill = true + return tbl +end + +itm.RegisterItem(item) + +local pmeta = FindMetaTable("Player") + +function pmeta:AddSkill(name, ammt) + local item = itm.GetItemByName("Skill") + item.name = name + item.ammt = ammt + self:GiveItem(item) +end + +local lib = {} +local skills = {} +--Skillname is a table of {string_group,string_name} +function lib.RegisterSkill(skillname) + print("funcs.RegisterSkill called with") + PrintTable(skillname) + local group,name = skillname[1],skillname[2] + if not skills[group] then + skills[group] = {} + end + local alin = false + for k,v in pairs(skills[group]) do + if v == name then + alin = true + break + end + end + if alin then + log.warn("Re-registering skill: " .. skillname) + else + skills[group][#skills[group] + 1] = name + end + print("After registering skill, skills is") + PrintTable(skills) +end + +function lib.SkillList() + return skills +end + +return lib diff --git a/gamemode/inventorysystem/skills/sh_skills.lua b/gamemode/inventorysystem/skills/sh_skills.lua index 27c3bad..9b6edd5 100644 --- a/gamemode/inventorysystem/skills/sh_skills.lua +++ b/gamemode/inventorysystem/skills/sh_skills.lua @@ -4,23 +4,29 @@ --local itm = nrequire("item.lua") --local ste = nrequire("utility/stream.lua") local inventory = nrequire("inventory/inventory.lua") +local log = nrequire("log.lua") --local col = nrequire("config/colortheme.lua") +local sc = nrequire("skills/sh_skillcommon.lua") local inv = {} if CLIENT then inv = nrequire("cl_skills.lua") end -inv.allskills = { +--TODO: uncomment these as their minigames are implemented +inv.allskills = {} +--[[ ["forageing"] = { - "hunting", - "butchering", - "woodcutting", - "plant identification", - "archery", +-- "Hunting", +-- "Butchering", +-- "Woodcutting", +-- "plant identification", +-- "archery", +-- "fishing", +-- "Mineing", }, ["farming"] = { - "domestication", - "sowing", - "arboriculture", - "apiarism", - "reaping", +-- "domestication", +-- "sowing", +-- "arboriculture", +-- "apiarism", +-- "reaping", }, ["artisanship"] = { "pottery", @@ -44,6 +50,8 @@ inv.allskills = { "painting", "performing", "faith", + "engraving", + "architect", }, ["adventuring"] = { "evasion", @@ -51,6 +59,7 @@ inv.allskills = { "lockpicking", "willpower", "dexterity", + "swimming", "sailing", }, ["fighting"] = { @@ -66,14 +75,20 @@ inv.allskills = { "archery", } } - +]] inv.Name = "Skills" inv.skills = {} -for k,v in pairs(inv.allskills) do - for i,j in pairs(v) do - inv.skills[j] = 0 +local function calculate_skills() + for k,v in pairs(sc.SkillList()) do + for i,j in pairs(v) do + print("settings inv's skills' ", j, " to 0") + inv.skills[j] = 0 + end end + print("After calculating skills, inv was") + PrintTable(inv) end +calculate_skills() --[[ item should be @@ -84,11 +99,16 @@ item should be } ]] inv.FindPlaceFor = function(self, item) - if item.isskill == nil then + print("finding place for ") + PrintTable(item) + if not item.isskill then return nil end - - if self.skills[item.name] then + print("Skill inventory trying to find place for, looking in ") + PrintTable(inv.skills) + print("for") + print(item.name) + if inv.skills[item.name] then return {item.name} else return nil @@ -96,11 +116,13 @@ inv.FindPlaceFor = function(self, item) end inv.CanFitIn = function(self,position,item) - return self.skills[position[1]] != nil + return sc.SkillList()[position[1]] != nil end inv.Put = function(self,position,item) - self.skills[position[1]] = self.skills[position[1]] + item.ammt + print("item is") + PrintTable(item) + self.skills[position[1]] = (self.skills[position[1]] or 0) + item.ammt end inv.Has = function(self,string_or_compare_func) @@ -130,10 +152,20 @@ end inv.DeSerialize = function(self,data) if data == nil or data == '' then - return table.Copy(self) + return table.Copy(inv) end + calculate_skills() + print("At the time we deserialized, sc.skilllist was") + PrintTable(sc.SkillList()) + print("Before making a copy of, inv is") + PrintTable(inv) local cpy = table.Copy(self) - cpy.skills = util.JSONToTable(data) + local gen = util.JSONToTable(data) + for k,v in pairs(gen) do + cpy.skills[k] = v + end + print("AFter deserializing inventory, it is") + PrintTable(cpy) return cpy end diff --git a/gamemode/itemsystem/exampleitem.lua b/gamemode/itemsystem/exampleitem.lua index d7af511..269e2d6 100644 --- a/gamemode/itemsystem/exampleitem.lua +++ b/gamemode/itemsystem/exampleitem.lua @@ -3,6 +3,9 @@ ]] local item = {} +--Make sure we identify ourselves as a prayer +item.isprayer = true + --Required, a name, all item names must be unique item.Name = "Test item" diff --git a/gamemode/nrequire.lua b/gamemode/nrequire.lua index 1ec4fb7..29e350d 100644 --- a/gamemode/nrequire.lua +++ b/gamemode/nrequire.lua @@ -6,7 +6,6 @@ ]] --Don't run ourselves, or we'll get stuck in a recursive loop! if nrequire ~= nil then return end -print("hello from nrequire!") local path = (GM or GAMEMODE).Folder:gsub("gamemodes/","") .. "/gamemode" --[[ Calls func on all the files under dir. @@ -161,6 +160,7 @@ function nrequire(req) --Deal with bookkeeping dealing with circular dependancies, and include pathstack[#pathstack + 1] = tpath reqtbl[tpath] = include(tpath) + hook.Call("artery_file_included",nil,tpah) --[[ co = coroutine.create(function() reqtbl[tpath] = include(tpath) @@ -192,7 +192,6 @@ hook.Call("artery_nrequire_defined") If the file starts with cl_ it will only be included on the client, if it starts with sv_ it will only be included on the server. If it starts with anything else, it will be shared. Will detect and error on circuar dependancy. ]] local function doincludes() - print("doing includes") paths = {} TraverseFolder("",ins) ntbl = rebuild_include_table(paths) diff --git a/gamemode/shared.lua b/gamemode/shared.lua index 588b81f..6304bce 100644 --- a/gamemode/shared.lua +++ b/gamemode/shared.lua @@ -1,6 +1,7 @@ include("nrequire.lua") local ngm = GM or GAMEMODE +ngm.Version = {0,7,2} ngm.Name = "Artery" ngm.Author = "Alexander \"Apickx\" Pickering" -ngm.Email = "apickx@cogarr.org" +ngm.Email = "alex@cogarr.net" ngm.Website = "cogarr.net" diff --git a/gamemode/shared/animations/move_evade.lua b/gamemode/shared/animations/move_evade.lua index a5595aa..c4afa59 100644 --- a/gamemode/shared/animations/move_evade.lua +++ b/gamemode/shared/animations/move_evade.lua @@ -1,3 +1,5 @@ +nrequire("sh_animations.lua") + RegisterLuaAnimation('evade_left', { FrameData = { { diff --git a/gamemode/shared/animations/swing_axe.lua b/gamemode/shared/animations/swing_axe.lua index 60133b5..9e8ddb4 100644 --- a/gamemode/shared/animations/swing_axe.lua +++ b/gamemode/shared/animations/swing_axe.lua @@ -1,3 +1,5 @@ +nrequire("sh_animations.lua") + RegisterLuaAnimation('axe_swing_up', { FrameData = { { diff --git a/gamemode/shared/animations/swing_fists.lua b/gamemode/shared/animations/swing_fists.lua index b0c77b5..8c0f106 100644 --- a/gamemode/shared/animations/swing_fists.lua +++ b/gamemode/shared/animations/swing_fists.lua @@ -1,3 +1,5 @@ +nrequire("sh_animations.lua") + RegisterLuaAnimation('fist_swing_up', { FrameData = { { diff --git a/gamemode/shared/animations/swing_hammer.lua b/gamemode/shared/animations/swing_hammer.lua index efb8e34..2152709 100644 --- a/gamemode/shared/animations/swing_hammer.lua +++ b/gamemode/shared/animations/swing_hammer.lua @@ -1,3 +1,5 @@ +nrequire("sh_animations.lua") + RegisterLuaAnimation('hammer_swing_up', { FrameData = { { diff --git a/gamemode/shared/animations/swing_knife.lua b/gamemode/shared/animations/swing_knife.lua index f0bdec1..cf78bb5 100644 --- a/gamemode/shared/animations/swing_knife.lua +++ b/gamemode/shared/animations/swing_knife.lua @@ -1,3 +1,5 @@ +nrequire("sh_animations.lua") + RegisterLuaAnimation('knife_swing_up', { FrameData = { { diff --git a/gamemode/shared/animations/swing_mele.lua b/gamemode/shared/animations/swing_mele.lua index a0cd065..4a38876 100644 --- a/gamemode/shared/animations/swing_mele.lua +++ b/gamemode/shared/animations/swing_mele.lua @@ -1,3 +1,5 @@ +nrequire("sh_animations.lua") + RegisterLuaAnimation('swing_onehand_left', { FrameData = { { diff --git a/gamemode/shared/log.lua b/gamemode/shared/log.lua index 92bb349..618fd0c 100644 --- a/gamemode/shared/log.lua +++ b/gamemode/shared/log.lua @@ -2,39 +2,28 @@ local fn = nrequire("fn.lua") local col = nrequire("colortheme.lua") local log = {} +local domain +if SERVER then + domain = "[SERVER]" +elseif CLIENT then + domain = "[CLIENT]" +end -log.debug = fn.compose( - fn.curry( - MsgC, - col.console.cyan - ), - fn.curry( - string.format, - "[DEBUG] %s\n" - ) -) +function log.debug(...) + MsgC(col.console.gray,domain,"[DEBUG]",...,"\n") +end -log.info = fn.compose( - fn.curry( - MsgC, - col.console.blue - ), - fn.curry( - string.format, - "[INFO] %s\n" - ) -) +function log.info(...) + MsgC(col.console.cyan,domain,"[INFO]",...,"\n") +end -log.warn = fn.compose( - fn.curry( - MsgC, - col.console.yellow - ), - fn.curry( - string.format, - "[WARNING] %s\n" - ) -) +function log.warn(...) + MsgC(col.console.yellow,domain,"[WARNING]",...,"\n") +end + +function log.error(...) + MsgC(col.console.red,domain,"[ERROR]",...,"\n") +end log.report = fn.curry( file.Append, diff --git a/gamemode/zones.lua b/gamemode/zones.lua new file mode 100644 index 0000000..f95d6f2 --- /dev/null +++ b/gamemode/zones.lua @@ -0,0 +1,611 @@ +local version = 1.20 -- Older versions will not run if a newer version is used in another script. +--[[ + ZONES - by Bobbleheadbob with help from Zeh Matt + WARNING: If you edit any of these files, make them use a different namespace. Multiple scripts may depend on this library so modifying it can break other scripts. + + Purpose: + For easy in-game designation of persistent polygonal zones which are used by any script. + + How to Use: + All zones are saved in zones.List; see an example below. + Zone creation is handled with weapon_zone_designator and ent_zone_point, but can be done in code as well. + When a zone is created, changed, or removed all zones are synced to clients. When clients join they are also synced. + Any extra details can be saved to a zone. Everything is written to a txt file and is persistent to the map. + + Since multiple scripts might use the zones system, don't assume that every zone is related to your script. + To register a zone class, use zones.RegisterClass(class, color); use a unique string like "Scriptname Room". + When a zone class is registered, admins can use the tool to create new ones. + When a new zone is created, the "OnZoneCreated" hook is called serverside. See the example file for documentation. + When a zone is loaded into the game, the "OnZoneLoaded" hook is called serverside. See the example file for documentation. + When a player edits a zone's properties, the "ShowZoneOptions" hook is called clientside. See the example file for documentation. + + Use zones.FindByClass() to find all zones which are of a given class. + Use ply:GetCurrentZone() to find the zone that a player is standing in. + + Installation: + This is a shared file so include it in any shared environment. Also include ent_zone_point and weapon_zone_designator as a shared ent and weapon. + You should not put this file directly in lua/autorun. + + License: + YOU MAY use/edit this however you want, as long as you give proper attribution. + YOU MAY distribute this with other scripts whether they are paid or free. + YOU MAY NOT distribute this on its own. It must accompany another script. + + Enjoy! ~Bobbleheadbob +]] + +local table, math, Vector, pairs, ipairs, ents, bit = table, math, Vector, pairs, ipairs, ents, bit + +if zones then + local diff = math.abs(math.floor(version)-math.floor(zones.version)) > 0 + if diff then + ErrorNoHalt("WARNING! Two scripts use VERY different versions of the zones API. Please tell one of them to update their script!\n") + end + if zones.version > version then + if diff then + print("The outdated version of zones is located at: "..debug.getinfo(1,"S").short_src) + end + print("A new version of zones exists. Using version "..zones.version.." instead of "..version) + return + elseif zones.version < version then + if diff then + print("The outdated version of zones is located at: "..debug.getinfo(zones.RegisterClass,"S").short_src) + end + print("A new version of zones exists. Using version "..version.." instead of "..zones.version) + end + +else + print("Loaded zones " ..version) +end + +zones = zones or {} +zones.version = version + +zones.Classes = zones.Classes or {} +zones.List = zones.List or {} +zones.Map = zones.Map or {} + + +//Common interface functions: + +-- Registers a zone class which can then be created using weapon_zone_designator +function zones.RegisterClass(class,color) + zones.Classes[class] = color +end + + +local plymeta = FindMetaTable("Player") +--returns one of the zones a player is found in. Also returns that zone's ID. Class is optional to filter the search. +function plymeta:GetCurrentZone(class) + local c = zones.Cache[self][class or "___"] + if c then return unpack(c) end + local z,id = zones.GetZoneAt(self:GetPos(), class) + zones.Cache[self][class or "___"] = {z,id} + return z,id +end + +--returns a table of zones the player is in. Class is optional to filter the search. +function plymeta:GetCurrentZones(class) + return zones.GetZonesAt(self:GetPos(),class) +end + +function zones.GetZoneAt(pos,class) --works like above, except uses any point. + + local nearby = zones.GetNearbyZones(pos) + + for k,zone in pairs(nearby) do + + if class and class != zone.class then continue end + if not pos:WithinAABox(zone.bounds.mins, zone.bounds.maxs) then + continue + end + + for k1, points in pairs(zone.points) do + if zones.PointInPoly(pos,points) then + local z = points[1].z + if pos.z >= z and pos.z < z + zone.height[k1] then + return zone,k + end + end + end + end + + return nil, -1 + +end + +function zones.GetZonesAt(pos,class) --works like above, except uses any point. + local tbl = {} + local nearby = zones.GetNearbyZones(pos) + for k,zone in pairs(nearby) do + if class and class != zone.class then continue end + if not pos:WithinAABox(zone.bounds.mins,zone.bounds.maxs) then continue end + for k1, points in pairs(zone.points) do + if zones.PointInPoly(pos,points) then + local z = points[1].z + if pos.z >= z and pos.z < z + zone.height[k1] then + tbl[k] = zone + end + end + end + end + return tbl +end + +--Gets a list of all zones which are of the specified class. +function zones.FindByClass(class) + local tbl = {} + + for k,v in pairs(zones.List) do + if v.class == class then + tbl[k] = v + end + end + + return tbl +end + +--Returns the numerical ID of a zone. +function zones.GetID(zone) + return table.KeyFromValue(zones.List,zone) +end + + + + +//Getting into the meat of the API: +local mapMins = -16000 +local mapMaxs = 16000 +local mapSize = 32000 +local chunkSize = 128 + +local function GetZoneIndex(pos) + + local x = pos.x + mapMaxs + local y = pos.y + mapMaxs + local z = pos.z + mapMaxs + + local idxX = math.floor(x / chunkSize) + local idxY = math.floor(y / chunkSize) + local idxZ = math.floor(z / chunkSize) + local idx = bit.bor(bit.lshift(idxX, 24), bit.lshift(idxY, 14), idxZ) + + return idx + +end + +local function Floor(x,to) + return math.floor(x / to) * to +end +local function Ceil(x,to) + return math.ceil(x / to) * to +end + +function zones.CreateZoneMapping() + zones.Map = {} + for _, zone in pairs(zones.List) do + local mins = zone.bounds.mins + local maxs = zone.bounds.maxs + for x = Floor(mins.x,chunkSize), Ceil(maxs.x + 1,chunkSize), chunkSize do + for y = Floor(mins.y,chunkSize), Ceil(maxs.y + 1,chunkSize), chunkSize do + for z = Floor(mins.z,chunkSize), Ceil(maxs.z + 1,chunkSize), chunkSize do + local idx = GetZoneIndex(Vector(x, y, z)) + zones.Map[idx] = zones.Map[idx] or {} + table.insert(zones.Map[idx], zone) + end + end + end + end +end + +function zones.GetNearbyZones(pos) + //This system isn't working. + -- local idx = GetZoneIndex(pos) + -- return zones.Map[idx] or {} + return zones.List +end + +zones.Cache = {} +local function ClearCache() + for k,v in pairs(player.GetAll()) do + zones.Cache[v] = {} + end +end +ClearCache() +hook.Add("Tick","zones_cache",ClearCache) + +if SERVER then + util.AddNetworkString("zones_sync") + util.AddNetworkString("zones_class") + + function zones.SaveZones() + if not file.Exists("zones","DATA") then + file.CreateDir("zones") + end + file.Write("zones/"..game.GetMap():gsub("_","-"):lower()..".txt", util.TableToJSON(zones.List)) + end + concommand.Add("zone_save",function(ply,c,a) + if not ply:IsAdmin() then return end + zones.SaveZones() + end) + + function zones.LoadZones() + local tbl = file.Read("zones/"..game.GetMap():gsub("_","-"):lower()..".txt", "DATA") + zones.List = tbl and util.JSONToTable(tbl) or {} + + //Update legacy files: + for k,v in pairs(zones.List)do + if not v.bounds then + zones.CalcBounds(v) + end + + hook.Run("OnZoneLoaded",v,v.class,k) + end + end + + local sync = false + local syncply + + function zones.Sync(ply) + sync = true + syncply = ply + end + + hook.Add("Tick","zones_sync",function() + if sync then + net.Start("zones_sync") + net.WriteTable(zones.List) + if syncply then + net.Send(syncply) + syncply = nil + else + net.Broadcast() + zones.CreateZoneMapping() + end + sync = false + end + end) + + function zones.CreateZoneFromPoint(ent) + + local zone = { + points = {{}}, --only 1 area when creating a new zone. + height = {ent:GetTall()}, + class = ent:GetZoneClass(), + bounds = {} + } + + local id = table.maxn(zones.List) + 1 + local cur = ent + repeat + local pos = cur:GetPos() - Vector(0,0,2) + zone.points[1][#zone.points[1]+1] = pos + + cur:SetZoneID(id) + cur = cur:GetNext() + + until (cur == ent) + + zones.CalcBounds(zone,true) + + zones.List[id] = zone + hook.Run("OnZoneCreated",zone,zone.class,id) + + zones.Sync() + + + return zone, id + + end + + function zones.CalcBounds(zone,newZone) + local mins,maxs = Vector(10000000,10000000,10000000), Vector(-10000000,-10000000,-10000000) + for areanum,area in pairs(zone.points)do + for k,pos in pairs(area) do + maxs.x = math.max(pos.x, maxs.x) + maxs.y = math.max(pos.y, maxs.y) + maxs.z = math.max(pos.z+zone.height[areanum], maxs.z) + mins.x = math.min(pos.x, mins.x) + mins.y = math.min(pos.y, mins.y) + mins.z = math.min(pos.z, mins.z) + end + end + zone.bounds = {["mins"]=mins,["maxs"]=maxs} + if not newZone then + hook.Run("OnZoneChanged",zone,zone.class,zones.GetID(zone)) + end + end + + function zones.Remove(id) + hook.Run("OnZoneRemoved",zones.List[id],zones.List[id].class,id) + zones.List[id] = nil + zones.Sync() + end + + function zones.CreatePointEnts(removeThese) --removeThese is optional. + for k,v in pairs(removeThese or ents.FindByClass("ent_zone_point")) do --remove old + v:Remove() + end + + --create new + for id,zone in pairs(zones.List)do + + for k, area in pairs(zone.points) do + + local first + local curr + for k2,point in ipairs(area)do + + local next = ents.Create("ent_zone_point") + + if IsValid(curr) then + next:SetPos(point+Vector(0,0,1)) + curr:SetNext(next) + -- curr:DeleteOnRemove(next) + else + first = next + next:SetPos(point+Vector(0,0,1)) + end + + next.LastPoint = curr + curr = next + next:SetTall(zone.height[k]) + next:SetZoneClass(zone.class) + next:Spawn() + next:SetZoneID(id) + next:SetAreaNumber(k) + + end + + curr:SetNext(first) + -- curr:DeleteOnRemove(first) + first.LastPoint = curr + + end + end + + end + + function zones.Merge(from,to) + + local zfrom, zto = zones.List[from], zones.List[to] + + table.Add(zto.points, zfrom.points) + table.Add(zto.height, zfrom.height) + + zones.CalcBounds(zto) + zones.Remove(from) + + hook.Run("OnZoneMerged",zto,zto.class,to,zfrom,zfrom.class,from) + + zones.Sync() + + end + + function zones.Split(id,areanum) + local zone = zones.List[id] + local pts, h, bound = zone.points[areanum], zone.height[areanum] + + table.remove(zone.points,areanum) + table.remove(zone.height,areanum) + + if #zone.points == 0 then + zones.Remove(id) + end + + local new = table.Copy(zone) + new.points = {pts} + new.height = {h} + + local id = table.maxn(zones.List)+1 + zones.List[id] = new + + zones.CalcBounds(zone) + zones.CalcBounds(new) + + hook.Run("OnZoneSplit",new,new.class,id,zone,id) + + zones.Sync() + + return new,id + + end + + function zones.ChangeClass(id,class) + local zone,new = zones.List[id],{} + new.points = zone.points + new.height = zone.height + new.bounds = zone.bounds + new.class = class + + zones.List[id] = new + + hook.Run("OnZoneCreated",new,class,id) + + zones.Sync() + end + + + local mapMins = -16000 + local mapMaxs = 16000 + local mapSize = 32000 + local chunkSize = 128 + + function zones.GetZoneIndex(pos) + + local x = math.Remap(pos.x, mapMins, mapMaxs, 0, mapSize) + local y = math.Remap(pos.y, mapMins, mapMaxs, 0, mapSize) + local z = math.Remap(pos.z, mapMins, mapMaxs, 0, mapSize) + + local idxX = math.floor(x / chunkSize) + local idxY = math.floor(y / chunkSize) + local idxZ = math.floor(z / chunkSize) + local idx = bit.bor(bit.lshift(idxX, 24), bit.lshift(idxY, 14), idxZ) + + return idx + + end + + hook.Add("InitPostEntity","zones_load",function() + zones.LoadZones() + end) + hook.Add("PlayerInitialSpawn","zones_sync",function(ply) + zones.Sync(ply) + end) + + net.Receive("zones_class",function(len,ply) + if not ply:IsAdmin() then return end + local id = net.ReadFloat() + local class = net.ReadString() + + for k,v in pairs(ents.FindByClass("ent_zone_point"))do + if v:GetZoneID() == id then + v:SetZoneClass(class) + end + end + + zones.ChangeClass(id,class) + + end) + +else + net.Receive("zones_sync",function(len) + zones.List = net.ReadTable() + zones.CreateZoneMapping() + end) + + function zones.ShowOptions(id) + + local zone = zones.List[id] + local class = zone.class + + local frame = vgui.Create("DFrame") + zones.optionsFrame = frame + frame:MakePopup() + frame:SetTitle("Zone Settings") + + local ztitle = vgui.Create("DLabel",frame) + ztitle:Dock(TOP) + ztitle:DockMargin(2,0,5,5) + ztitle:SetText("Zone Class:") + ztitle:SizeToContents() + + local zclass = vgui.Create("DComboBox",frame) + zclass:Dock(TOP) + zclass:DockMargin(0,0,0,5) + for k,v in pairs(zones.Classes) do + zclass:AddChoice(k,nil,k == class) + end + function zclass:OnSelect(i,class) + net.Start("zones_class") + net.WriteFloat(id) + net.WriteString(class) + net.SendToServer() + + frame.content:Remove() + + frame.content = vgui.Create("DPanel",frame) + frame.content:Dock(FILL) + frame.content:DockPadding(5,5,5,5) + + local w,h = hook.Run("ShowZoneOptions",zone,class,frame.content,id,frame) + frame:SizeTo((w or 100)+8,(h or 2)+78, .2) + frame:MoveTo(ScrW()/2-((w or 292)+8)/2,ScrH()/2-((h or 422)+78)/2, .2) + end + + frame.content = vgui.Create("DPanel",frame) + frame.content:Dock(FILL) + frame.content:DockPadding(5,5,5,5) + + local w,h = hook.Run("ShowZoneOptions",zone,class,frame.content,id,frame) + frame:SetSize((w or 100)+8,(h or 2)+78) + frame:Center() + + end + +end + + + +//returns the point of intersection between two infinite lines. +local function IntersectPoint(line1, line2) + + local x1,y1,x2,y2,x3,y3,x4,y4 = line1.x1,line1.y1,line1.x2,line1.y2,line2.x1,line2.y1,line2.x2,line2.y2 + + local m1,m2 = (y1-y2)/((x1-x2)+.001),(y3-y4)/((x3-x4)+.001) --get the slopes + local yint1,yint2 = (-m1*x1)+y1,(-m2*x3)+y3 --get the y-intercepts + local x = (yint1-yint2)/(m2-m1) --calculate x pos + local y = m1*x+yint1 --plug in x pos to get y pos + + return x,y + +end +//Returns a bool if two SEGEMENTS intersect or not. +local function Intersect(line1, line2) + + local x,y = IntersectPoint(line1, line2) + + local sx,sy = tostring(x), tostring(y) + if (sx == "-inf" or sx == "inf" or sx == "nan") then + return false + end + + local minx1, maxx1 = math.min(line1.x1,line1.x2)-.1, math.max(line1.x1,line1.x2)+.1 + local minx2, maxx2 = math.min(line2.x1,line2.x2)-.1, math.max(line2.x1,line2.x2)+.1 + local miny1, maxy1 = math.min(line1.y1,line1.y2)-.1, math.max(line1.y1,line1.y2)+.1 + local miny2, maxy2 = math.min(line2.y1,line2.y2)-.1, math.max(line2.y1,line2.y2)+.1 + + if (x >= minx1) and (x <= maxx1) and (x >= minx2) and (x <= maxx2) then + + if (y >= miny1) and (y <= maxy1) and (y >= miny2) and (y <= maxy2) then + + --debugoverlay.Sphere( Vector(x,y,LocalPlayer():GetPos().z), 3, FrameTime()+.01, Color(255,0,0), true) + + return true + + end + + end + + return false + +end +function zones.PointInPoly(point,poly) //True if point is within a polygon. + + local ray = { + x1 = point.x, + y1 = point.y, + x2 = 100000, + y2 = 100000 + } + + local inside = false + + local line = { + x1 = 0, + y1 = 0, + x2 = 0, + y2 = 0 + } + + //Perform ray test + for k1, v in pairs(poly) do + + local v2 = poly[k1+1] + if not v2 then + v2 = poly[1] + end + + line["x1"] = v.x + line["y1"] = v.y + line["x2"] = v2.x + line["y2"] = v2.y + + if Intersect(ray,line) then + inside = !inside + end + + end + + return inside +end
\ No newline at end of file |
