diff --git a/README.md b/README.md index ae0d3efc..611c2d15 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,58 @@ nZombies A GM13 Nazi Zombies style (WIP) gamemode -place in gamemodes/nzombies/ +Download folder and place it in garrysmod/garrysmod/addons +Make sure the structure has a path to addon.json like this: garrysmod/garrysmod/addons/nzombies/addon.json -I know the code is ugly. Planning on re-writing the whole thing soon. +Get the content pack with all models and materials here: +http://steamcommunity.com/sharedfiles/filedetails/?id=675138912 + +Get the collection of weapon packs used by the official configs here: +http://steamcommunity.com/sharedfiles/filedetails/?id=673266588 + +If you have bugs, suggestions, or general improvements, open up an issue with the issue button at the top. If you want to help, feel free to create pull requests with your changes. If you have questions, add me on steam :) + +This is an edited version from Aligs original featuring these changes: + +- Revival System & Health + - Fully working revival system, including crawling around and animations + +- Navigation Tools + - Lock areas of the maps based on doors, allowing Zombies to navigate around them + +- Additional Content + - All perks up until Black Ops 3; all DLC working! + - A proper HUD! + - More Powerups + - More sounds + - More effects + - Official configs w/ Full Easter Eggs + - Traps + - Better editing in creative mode + - Undo system + - Context Menu to quickly edit properties without equipping tool (Hold C) + - Many more props, light effects, sky/fog/sun editors, fire entities, and more ... + - Better tool system + +- Better Mapping! + - Decide weapons in box, music easter egg songs, boss rounds, special rounds + - Decide starting weapon and starting amount of points + - Support for many more types of doors + +- Better Zombie AI (Thanks Lolle!) + +- Easy Mismatch Correction System + - Loading configs using weapons you may not have installed creates an easy menu to replace them + - Applies to wall buys, random box list, perks (if scripted in), and more as new stuff is added + +- Better Mechanics + - Proper Weapon System + - Better Zombie health and speed curves + +- Misc changes + - Speed Cola and Double Tap now works on all weapons! + - Wall Buys are actual chalk-outlines! + - Zombies are actual Der Riese models w/ Animations and sound! + +- Workshop Release To-do list: + Check the Issues tab with the "Workshop Release" milestone. Feel free to discuss your opinion about the things in there, it would help greatly. \ No newline at end of file diff --git a/addon.json b/addon.json new file mode 100644 index 00000000..89b3deb4 --- /dev/null +++ b/addon.json @@ -0,0 +1,11 @@ +{ + "title" : "nZombies 3", + "type" : "gamemode", + "tags" : [ "fun", "realism" ], + "ignore" : + [ + "*.psd", + "*.vcproj", + "*.svn*" + ] +} \ No newline at end of file diff --git a/gamemodes/nzombies/entities/effects/lightning_aura/init.lua b/gamemodes/nzombies/entities/effects/lightning_aura/init.lua new file mode 100644 index 00000000..57c81886 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/lightning_aura/init.lua @@ -0,0 +1,197 @@ + +--EFFECT.MatCenter = Material( "lightning.png", "unlitgeneric smooth" ) +EFFECT.MatEdge = Material( "effects/tool_tracer" ) +EFFECT.MatCenter = Material( "sprites/physbeama" ) +EFFECT.MatGlow1 = Material( "sprites/physg_glow1" ) +EFFECT.MatGlow2 = Material( "sprites/physg_glow2" ) +EFFECT.MatGlowCenter = Material( "sprites/glow04_noz" ) + +--[[--------------------------------------------------------- + Init( data table ) +-----------------------------------------------------------]] +function EFFECT:Init( data ) + + self.Size = data:GetRadius() or 1 + if self.Size <= 0 then self.Size = 1 end + self.MaxArcs = 2 + self.Parent = data:GetEntity() + --self:SetParent(self.Parent) + self.Frequency = data:GetMagnitude() and data:GetMagnitude()/10 or 0.01 + self.Pos = self.Parent:WorldSpaceCenter() + local scale = data:GetScale() + + if IsValid(self.Parent.LightningAuraEffect) then + self.Parent.LightningAuraEffect.KILL = true + end + + if scale then + if scale >= 0 then + self.Parent.LightningAura = CurTime() + scale + else + self.Parent.LightningAura = true + end + else + self.Parent.LightningAura = CurTime() + 10 -- Default time for this effect + end + + self.Alpha = 255 + self.Life = 0 + self.NextArc = 0 + self.Arcs = {} + self.Queue = 1 + + self.Parent.LightningAuraEffect = self + + self:SetRenderBounds( Vector(0,0,0), Vector(0,0,0), Vector(50,50,50) ) + +end + +--[[--------------------------------------------------------- + THINK +-----------------------------------------------------------]] +function EFFECT:Think() + + if self.KILL then return false end + + if IsValid(self.Parent) then + self.Pos = self.Parent:WorldSpaceCenter() + self:SetPos(self.Pos) + end + + self.Life = self.Life + FrameTime() + --self.Alpha = 255 * ( 1 - self.Life ) + + if self.NextArc <= self.Life and self.Pos then + + local size = #self.Arcs + --add a arc to the array + while self.Arcs[size] do + size = size + 1 + end + self.Arcs[size] = self:GenerateArc(self.Pos + AngleRand():Forward()*10*self.Size, self.Pos + AngleRand():Forward()*10*self.Size, 0.01, 4) + self.NextArc = self.NextArc + self.Frequency + + if size >= self.MaxArcs then + local i = 1 + while not self.Arcs[i] and i <= size do + i = i + 1 + end + self.Arcs[i] = nil + end + end + + if IsValid(self.Parent) then + if !(type(self.Parent.LightningAura) == "number" and CurTime() < self.Parent.LightningAura or self.Parent.LightningAura == true) then + self.Parent.LightningAura = nil + return false + end + else + return false + end + + return true +end + +function EFFECT:GenerateArc(startPos, endPos, branchChance, detail) + -- MidPoint Displacement for arc lines + local points = {} + local maxPoints = 2^detail + + if maxPoints % 2 != 0 then + maxPoints = maxPoints + 1 + end + + points[0] = startPos + + local randVec = VectorRand() * 10 + + randVec.z = math.Clamp(randVec.z, 0, 10) + + points[maxPoints] = endPos + randVec + + local i = 1 + + while i < maxPoints do + local j = (maxPoints / i) / 2 + while j < maxPoints do + points[j] = ((points[j - (maxPoints / i) / 2] + points[j + (maxPoints / i) / 2]) / 2); + points[j] = points[j] + VectorRand() * 10 + if math.Rand(0,1) < branchChance then + points[#points + 1] = self:GenerateArc(points[j], points[j] + Vector(math.random(-50 * branchChance, 50 * branchChance), math.random(-50 * branchChance, 50 * branchChance), math.random(-50 * branchChance, 10 * branchChance)), branchChance/1.3, detail) + end + j = j + maxPoints / i + end + i = i * 2 + end + + points.size = math.random(1,3)*self.Size + points.color = Color(200, 240, math.random(230, 255), math.random(200, 255)) + points.dietime = CurTime() + 0.2 + + return points +end + +--[[--------------------------------------------------------- + Draw the effect +-----------------------------------------------------------]] +function EFFECT:Render() + + if ( self.KILL or self.Alpha < 1 or self.Parent:IsDormant() ) then return end + + render.SetMaterial( self.MatCenter ) + + for _, arc in pairs(self.Arcs) do + if arc.dietime <= CurTime() then + self.Arcs[_] = nil + else + self:RenderArc(arc) + end + end + + render.SetMaterial( self.MatEdge ) + + for _, arc in pairs(self.Arcs) do + self:RenderArc(arc, true) + end + + render.SetMaterial( self.MatGlow1 ) + render.DrawSprite( self.Pos, math.random(40,120)*self.Size, math.random(40,120)*self.Size, Color(math.random(50,150),math.random(100,200),255,math.random(100,200))) + + if math.random(0,10) == 0 then + render.SetMaterial( self.MatGlow2 ) + render.DrawSprite( self.Pos, math.random(20,60)*self.Size, math.random(40,120)*self.Size, Color(math.random(50,150),math.random(100,200),255,math.random(100,200))) + end + + render.SetMaterial( self.MatGlowCenter ) + render.DrawSprite( self.Pos, math.random(15,40)*self.Size, math.random(15,40)*self.Size, Color(math.random(50,150),math.random(100,200),255,math.random(200,250))) + + --if !self.Parent:GetNoDraw() then + --self.Parent:DrawModel() -- Always draw the model in front + --end +end + +function EFFECT:RenderArc(arc, edge) + for j = 1, #arc - 1 do + + if istable(arc[j]) then + self:RenderArc(arc[j]) + elseif !istable(arc[j+1]) then + + local texcoord = math.Rand( 0, 1 ) + + local startPos = arc[j] + local endPos = arc[j + 1] + + local size = arc.size * ((arc.dietime-CurTime())/0.2) + + render.DrawBeam( + startPos, + endPos, + (edge and size*3 or size), + texcoord, + texcoord + ((startPos - endPos):Length() / 128), + arc.color + ) + end + end +end diff --git a/gamemodes/nzombies/entities/effects/lightning_field/init.lua b/gamemodes/nzombies/entities/effects/lightning_field/init.lua new file mode 100644 index 00000000..41177e75 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/lightning_field/init.lua @@ -0,0 +1,194 @@ + +--EFFECT.MatCenter = Material( "lightning.png", "unlitgeneric smooth" ) +EFFECT.MatEdge = Material( "effects/tool_tracer" ) +EFFECT.MatCenter = Material( "sprites/physbeama" ) +EFFECT.MatGlow1 = Material( "sprites/physg_glow1" ) +EFFECT.MatGlow2 = Material( "sprites/physg_glow2" ) +EFFECT.MatGlowCenter = Material( "sprites/glow04_noz" ) + +--[[--------------------------------------------------------- + Init( data table ) +-----------------------------------------------------------]] +function EFFECT:Init( data ) + + self.Size = data:GetRadius() or 1 + self.MaxArcs = 2 + self.Parent = data:GetEntity() + self.Frequency = data:GetMagnitude()/10 or 0.01 + self.Pos = self.Parent:GetPos() + self.Parent:OBBCenter() + self.OBBMax = self.Parent:OBBMaxs() + self.OBBMin = self.Parent:OBBMins() + self.Angle = self.Parent:GetAngles() + + if self.Parent.LightningAura then + if data:GetScale() then + self.Parent.LightningAura = CurTime() + data:GetScale() + else + self.Parent.LightningAura = CurTime() + 10 -- Default time for this effect + end + self.KILL = true + else + if data:GetScale() then + self.Parent.LightningAura = CurTime() + data:GetScale() + else + self.Parent.LightningAura = CurTime() + 10 -- Default time for this effect + end + + self.Alpha = 255 + self.Life = 0 + self.NextArc = 0 + self.Arcs = {} + self.Queue = 1 + + self:SetRenderBoundsWS( self.Pos, self.Pos, Vector(100,100,100) ) + end + +end + +--[[--------------------------------------------------------- + THINK +-----------------------------------------------------------]] +function EFFECT:Think() + + if self.KILL then return false end + + if IsValid(self.Parent) then + --self.Pos = self.Parent:GetPos() + end + + self.Life = self.Life + FrameTime() + --self.Alpha = 255 * ( 1 - self.Life ) + + if self.NextArc <= self.Life then + + local size = #self.Arcs + --add a arc to the array + while self.Arcs[size] do + size = size + 1 + end + + local randx = math.Rand(self.OBBMin.x, self.OBBMax.x) + local randy = math.Rand(self.OBBMin.y, self.OBBMax.y) + local zdist = self.OBBMax.z - self.OBBMin.z + local offz = 0 + if zdist < 30 then + offz = 30 + end + + local startpos = self.Angle:Forward() * randx + self.Angle:Right() * randy + Vector(0,0,offz + self.OBBMax.z) + local originpos = self.Pos + startpos + local endpos = originpos - Vector(0,0, zdist + offz) + + self.Arcs[size] = self:GenerateArc(originpos, endpos, 0.01, 4) + self.NextArc = self.NextArc + self.Frequency + + if size >= self.MaxArcs then + local i = 1 + while not self.Arcs[i] and i <= size do + i = i + 1 + end + self.Arcs[i] = nil + end + end + + if IsValid(self.Parent) then + if !(type(self.Parent.LightningAura) == "number" and CurTime() < self.Parent.LightningAura or self.Parent.LightningAura == true) then + self.Parent.LightningAura = nil + return false + end + else + return false + end + + return true +end + +function EFFECT:GenerateArc(startPos, endPos, branchChance, detail) + -- MidPoint Displacement for arc lines + local points = {} + local maxPoints = 2^detail + + if maxPoints % 2 != 0 then + maxPoints = maxPoints + 1 + end + + points[0] = startPos + + local randVec = VectorRand() * 10 + + randVec.z = math.Clamp(randVec.z, 0, 10) + + points[maxPoints] = endPos + randVec + + local i = 1 + + while i < maxPoints do + local j = (maxPoints / i) / 2 + while j < maxPoints do + points[j] = ((points[j - (maxPoints / i) / 2] + points[j + (maxPoints / i) / 2]) / 2); + points[j] = points[j] + VectorRand() * 10 + if math.Rand(0,1) < branchChance then + points[#points + 1] = self:GenerateArc(points[j], points[j] + Vector(math.random(-50 * branchChance, 50 * branchChance), math.random(-50 * branchChance, 50 * branchChance), math.random(-50 * branchChance, 10 * branchChance)), branchChance/1.3, detail) + end + j = j + maxPoints / i + end + i = i * 2 + end + + points.size = math.random(1,3)*self.Size + points.color = Color(200, 240, math.random(230, 255), math.random(200, 255)) + points.dietime = CurTime() + 0.07 + + return points +end + +--[[--------------------------------------------------------- + Draw the effect +-----------------------------------------------------------]] +function EFFECT:Render() + + if ( self.KILL or self.Alpha < 1 ) then return end + + render.SetMaterial( self.MatCenter ) + + for _, arc in pairs(self.Arcs) do + if arc.dietime <= CurTime() then + self.Arcs[_] = nil + else + self:RenderArc(arc) + end + end + + render.SetMaterial( self.MatEdge ) + + for _, arc in pairs(self.Arcs) do + self:RenderArc(arc, true) + end + + --render.SetColorMaterial() + --render.DrawBox(self.Pos, Angle(0,0,0), self.OBBMin, self.OBBMax, Color(255,255,255,100),false) +end + +function EFFECT:RenderArc(arc, edge) + for j = 1, #arc - 1 do + + if istable(arc[j]) then + self:RenderArc(arc[j]) + elseif !istable(arc[j+1]) then + + local texcoord = math.Rand( 0, 1 ) + + local startPos = arc[j] + local endPos = arc[j + 1] + + render.DrawBeam( + startPos, + endPos, + (edge and arc.size*3 or arc.size), + texcoord, + texcoord + ((startPos - endPos):Length() / 128), + arc.color + ) + end + end +end diff --git a/gamemodes/nzombies/entities/effects/lightning_prespawn/init.lua b/gamemodes/nzombies/entities/effects/lightning_prespawn/init.lua new file mode 100644 index 00000000..46ee5936 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/lightning_prespawn/init.lua @@ -0,0 +1,162 @@ +--Name: Lightning strike using midpoint displacement +--Author: Lolle + +--EFFECT.MatCenter = Material( "lightning.png", "unlitgeneric smooth" ) +EFFECT.MatEdge = Material( "effects/tool_tracer" ) +EFFECT.MatCenter = Material( "sprites/physbeama" ) +EFFECT.MatGlow1 = Material( "sprites/physg_glow1_noz" ) +EFFECT.MatGlow2 = Material( "sprites/physg_glow2_noz" ) +EFFECT.MatGlowCenter = Material( "sprites/glow04_actual_noz" ) + +--[[--------------------------------------------------------- + Init( data table ) +-----------------------------------------------------------]] +function EFFECT:Init( data ) + + self.Pos = data:GetOrigin() + VectorRand() * 10 + self.Duration = data:GetMagnitude() or 2 + self.Count = self.Duration * 40 + self.MaxArcs = 2 + self.Radius = 30 + self.Parent = data:GetEntity() + + self.Alpha = 255 + self.Life = 0 + self.NextArc = 0 + self.Arcs = {} + self.Queue = 1 + + self:SetRenderBounds( Vector(0,0,0), Vector(0,0,0), Vector(100,100,100) ) + + sound.Play("nz/hellhound/spawn/prespawn.wav", self.Pos, 100, 100, 1) + +end + +--[[--------------------------------------------------------- + THINK +-----------------------------------------------------------]] +function EFFECT:Think() + + if IsValid(self.Parent) then + self.Pos = self.Parent:GetPos() + self:SetPos(self.Pos) + end + + self.Life = self.Life + FrameTime() + --self.Alpha = 255 * ( 1 - self.Life ) + + if self.NextArc <= self.Life and self.Life <= self.Duration - self.Duration * 0.25 then + + local size = #self.Arcs + --add a arc to the array + while self.Arcs[size] do + size = size + 1 + end + self.Arcs[size] = self:GenerateArc(self.Pos + AngleRand():Forward()*100, self.Pos + AngleRand():Forward()*100, 0.1, 4) + self.NextArc = self.NextArc + 0.1 + + if size >= self.MaxArcs then + local i = 1 + while not self.Arcs[i] and i <= size do + i = i + 1 + end + self.Arcs[i] = nil + end + end + + return ( self.Life < self.Duration ) +end + +function EFFECT:GenerateArc(startPos, endPos, branchChance, detail) + -- MidPoint Displacement for arc lines + local points = {} + local maxPoints = 2^detail + + if maxPoints % 2 != 0 then + maxPoints = maxPoints + 1 + end + + points[0] = startPos + + local randVec = VectorRand() * 10 + + randVec.z = math.Clamp(randVec.z, 0, 10) + + points[maxPoints] = endPos + randVec + + local i = 1 + + while i < maxPoints do + local j = (maxPoints / i) / 2 + while j < maxPoints do + points[j] = ((points[j - (maxPoints / i) / 2] + points[j + (maxPoints / i) / 2]) / 2); + points[j] = points[j] + VectorRand() * 10 + if math.Rand(0,1) < branchChance then + points[#points + 1] = self:GenerateArc(points[j], points[j] + Vector(math.random(-50 * branchChance, 50 * branchChance), math.random(-50 * branchChance, 50 * branchChance), math.random(-50 * branchChance, 10 * branchChance)), branchChance/1.3, detail) + end + j = j + maxPoints / i + end + i = i * 2 + end + + points.size = math.random(2,10) + points.color = Color(200, 240, math.random(230, 255), math.random(200, 255)) + + return points +end + +--[[--------------------------------------------------------- + Draw the effect +-----------------------------------------------------------]] +function EFFECT:Render() + + if ( self.Alpha < 1 ) then return end + + render.SetMaterial( self.MatCenter ) + + for _, arc in pairs(self.Arcs) do + self:RenderArc(arc) + end + + render.SetMaterial( self.MatEdge ) + + for _, arc in pairs(self.Arcs) do + self:RenderArc(arc, true) + end + + render.SetMaterial( self.MatGlow1 ) + render.DrawSprite( self.Pos + Vector(0,0,30), math.random(200,600), math.random(200,600), Color(255,255,255,math.random(0,100))) + + if math.random(0,10) == 0 then + render.SetMaterial( self.MatGlow2 ) + render.DrawSprite( self.Pos + Vector(0,0,30), math.random(200,600), math.random(200,600), Color(255,255,255,math.random(0,200))) + end + + render.SetMaterial( self.MatGlowCenter ) + render.DrawSprite( self.Pos + Vector(0,0,30), math.random(75,200), math.random(75,200), Color(255,255,255,math.random(200,250))) + +end + +function EFFECT:RenderArc(arc, edge) + for j = 1, #arc - 1 do + + if istable(arc[j]) then + self:RenderArc(arc[j]) + elseif !istable(arc[j+1]) then + + local texcoord = math.Rand( 0, 1 ) + + local startPos = arc[j] + local endPos = arc[j + 1] + + render.DrawBeam( + startPos, + endPos, + edge and arc.size*3 or arc.size, + texcoord, + texcoord + ((startPos - endPos):Length() / 128), + arc.color + ) + end + end +end diff --git a/gamemodes/nzombies/entities/effects/lightning_strike/init.lua b/gamemodes/nzombies/entities/effects/lightning_strike/init.lua new file mode 100644 index 00000000..85190844 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/lightning_strike/init.lua @@ -0,0 +1,164 @@ +--Name: Lightning strike using midpoint displacement +--Author: Lolle + +--EFFECT.MatCenter = Material( "lightning.png", "unlitgeneric smooth" ) +EFFECT.MatEdge = Material( "effects/tool_tracer" ) +EFFECT.MatCenter = Material( "sprites/physbeama" ) +EFFECT.MatGlow = Material( "sprites/glow04_actual_noz" ) + +--[[--------------------------------------------------------- + Init( data table ) +-----------------------------------------------------------]] +function EFFECT:Init( data ) + + self.StartPos = data:GetStart() + self.EndPos = data:GetOrigin() + VectorRand() * 10 + self.Duration = data:GetMagnitude() or 10 + self.Count = self.Duration * 40 + self.MaxArcs = 5 + self.Radius = 30 + + self.Flash = DynamicLight( LocalPlayer():EntIndex() ) + + self.Flash.pos = self.EndPos + self.Flash.r = 255 + self.Flash.g = 255 + self.Flash.b = 255 + self.Flash.brightness = 2 + self.Flash.Decay = 200 + self.Flash.Size = 1500 + self.Flash.style = 6 + self.Flash.DieTime = CurTime() + 0.2 + + + self.Alpha = 255 + self.Life = 0 + self.NextArc = 0 + self.Arcs = {} + self.Queue = 1 + + self:SetRenderBoundsWS( self.StartPos, self.EndPos ) + + sound.Play("nz/hellhound/spawn/strike.wav", self.EndPos, 100, 100, 1) + +end + +--[[--------------------------------------------------------- + THINK +-----------------------------------------------------------]] +function EFFECT:Think() + + + self.Life = self.Life + FrameTime() + --self.Alpha = 255 * ( 1 - self.Life ) + + if self.NextArc <= self.Life and self.Life <= self.Duration - self.Duration * 0.25 then + + local size = #self.Arcs + --add a arc to the array + while self.Arcs[size] do + size = size + 1 + end + self.Arcs[size] = self:GenerateArc(self.StartPos, self.EndPos, 0.1, 4) + self.NextArc = self.NextArc + 0.05 + + if size >= self.MaxArcs then + local i = 1 + while not self.Arcs[i] and i <= size do + i = i + 1 + end + self.Arcs[i] = nil + end + end + + return ( self.Life < self.Duration ) +end + +function EFFECT:GenerateArc(startPos, endPos, branchChance, detail) + -- MidPoint Displacement for arc lines + local points = {} + local maxPoints = 2^detail + + if maxPoints % 2 != 0 then + maxPoints = maxPoints + 1 + end + + points[0] = startPos + + local randVec = VectorRand() * 10 + + randVec.z = math.Clamp(randVec.z, 0, 10) + + points[maxPoints] = endPos + randVec + + local i = 1 + + while i < maxPoints do + local j = (maxPoints / i) / 2 + while j < maxPoints do + points[j] = ((points[j - (maxPoints / i) / 2] + points[j + (maxPoints / i) / 2]) / 2); + points[j] = points[j] + VectorRand() * 25 + if math.Rand(0,1) < branchChance then + points[#points + 1] = self:GenerateArc(points[j], points[j] + Vector(math.random(-5000 * branchChance, 5000 * branchChance), math.random(-5000 * branchChance, 5000 * branchChance), math.random(-5000 * branchChance, 100 * branchChance)), branchChance/1.3, detail) + end + j = j + maxPoints / i + end + i = i * 2 + end + + points.size = math.random(10,30) + points.color = Color(200, 240, math.random(230, 255), math.random(200, 255)) + + return points +end + +--[[--------------------------------------------------------- + Draw the effect +-----------------------------------------------------------]] +function EFFECT:Render() + + if ( self.Alpha < 1 ) then return end + + render.SetMaterial( self.MatCenter ) + + for _, arc in pairs(self.Arcs) do + self:RenderArc(arc) + end + + render.SetMaterial( self.MatEdge ) + + for _, arc in pairs(self.Arcs) do + self:RenderArc(arc, true) + end + + render.SetMaterial( self.MatGlow ) + + render.DrawSprite( self.EndPos + Vector(0,0,30), math.random(400,1000), math.random(400,1000), Color(255,255,255,math.random(0,250))) + + util.ScreenShake( EyePos(), 0.5, 1, 0.1, 10 ) + +end + +function EFFECT:RenderArc(arc, edge) + for j = 1, #arc - 1 do + + if istable(arc[j]) then + self:RenderArc(arc[j]) + elseif !istable(arc[j+1]) then + + local texcoord = math.Rand( 0, 1 ) + + local startPos = arc[j] + local endPos = arc[j + 1] + + render.DrawBeam( + startPos, + endPos, + edge and arc.size*1.5 or arc.size, + texcoord, + texcoord + ((startPos - endPos):Length() / 128), + arc.color + ) + end + end +end diff --git a/gamemodes/nzombies/entities/effects/lightning_strike_wunderfizz/init.lua b/gamemodes/nzombies/entities/effects/lightning_strike_wunderfizz/init.lua new file mode 100644 index 00000000..e96a6e7a --- /dev/null +++ b/gamemodes/nzombies/entities/effects/lightning_strike_wunderfizz/init.lua @@ -0,0 +1,162 @@ +--Name: Lightning strike using midpoint displacement +--Author: Lolle + +--EFFECT.MatCenter = Material( "lightning.png", "unlitgeneric smooth" ) +EFFECT.MatEdge = Material( "effects/tool_tracer" ) +EFFECT.MatCenter = Material( "sprites/physbeama" ) +EFFECT.MatGlow = Material( "sprites/glow04_actual_noz" ) + +--[[--------------------------------------------------------- + Init( data table ) +-----------------------------------------------------------]] +function EFFECT:Init( data ) + + self.StartPos = data:GetStart() + self.EndPos = data:GetOrigin() + VectorRand() * 10 + self.Duration = data:GetMagnitude() or 10 + self.Count = self.Duration * 10 + self.MaxArcs = 4 + self.Radius = 30 + + self.Flash = DynamicLight( LocalPlayer():EntIndex() ) + + self.Flash.pos = self.EndPos + self.Flash.r = 255 + self.Flash.g = 255 + self.Flash.b = 255 + self.Flash.brightness = 2 + self.Flash.Decay = 200 + self.Flash.Size = 1500 + self.Flash.style = 6 + self.Flash.DieTime = CurTime() + 0.2 + + + self.Alpha = 255 + self.Life = 0 + self.NextArc = 0 + self.Arcs = {} + self.Queue = 1 + + self:SetRenderBoundsWS( self.StartPos, self.EndPos ) + + sound.Play("nz/hellhound/spawn/strike.wav", self.StartPos, 100, 100, 1) + +end + +--[[--------------------------------------------------------- + THINK +-----------------------------------------------------------]] +function EFFECT:Think() + + + self.Life = self.Life + FrameTime() + --self.Alpha = 255 * ( 1 - self.Life ) + + if self.NextArc <= self.Life and self.Life <= self.Duration - self.Duration * 0.25 then + + local size = #self.Arcs + --add a arc to the array + while self.Arcs[size] do + size = size + 1 + end + self.Arcs[size] = self:GenerateArc(self.StartPos, self.EndPos, 0.1, 4) + self.NextArc = self.NextArc + 0.1 + + if size >= self.MaxArcs then + local i = 1 + while not self.Arcs[i] and i <= size do + i = i + 1 + end + self.Arcs[i] = nil + end + end + + return ( self.Life < self.Duration ) +end + +function EFFECT:GenerateArc(startPos, endPos, branchChance, detail) + -- MidPoint Displacement for arc lines + local points = {} + local maxPoints = 2^detail + + if maxPoints % 2 != 0 then + maxPoints = maxPoints + 1 + end + + points[0] = startPos + + local randVec = VectorRand() * 10 + + randVec.z = math.Clamp(randVec.z, 0, 10) + + points[maxPoints] = endPos + randVec + + local i = 1 + + while i < maxPoints do + local j = (maxPoints / i) / 2 + while j < maxPoints do + points[j] = ((points[j - (maxPoints / i) / 2] + points[j + (maxPoints / i) / 2]) / 2); + points[j] = points[j] + VectorRand() * 25 + if math.Rand(0,1) < branchChance then + points[#points + 1] = self:GenerateArc(points[j], points[j] + Vector(math.random(-5000 * branchChance, 5000 * branchChance), math.random(-5000 * branchChance, 5000 * branchChance), math.random(-5000 * branchChance, 100 * branchChance)), branchChance/1.3, detail) + end + j = j + maxPoints / i + end + i = i * 2 + end + + points.size = math.random(10,30) + points.color = Color(200, 240, math.random(230, 255), math.random(200, 255)) + + return points +end + +--[[--------------------------------------------------------- + Draw the effect +-----------------------------------------------------------]] +function EFFECT:Render() + + if ( self.Alpha < 1 ) then return end + + render.SetMaterial( self.MatCenter ) + + for _, arc in pairs(self.Arcs) do + self:RenderArc(arc) + end + + render.SetMaterial( self.MatEdge ) + + for _, arc in pairs(self.Arcs) do + self:RenderArc(arc, true) + end + + render.SetMaterial( self.MatGlow ) + + render.DrawSprite( self.EndPos + Vector(0,0,30), math.random(100,400), math.random(100,400), Color(255,255,255,math.random(0,200))) + +end + +function EFFECT:RenderArc(arc, edge) + for j = 1, #arc - 1 do + + if istable(arc[j]) then + self:RenderArc(arc[j]) + elseif !istable(arc[j+1]) then + + local texcoord = math.Rand( 0, 1 ) + + local startPos = arc[j] + local endPos = arc[j + 1] + + render.DrawBeam( + startPos, + endPos, + edge and arc.size*1.5 or arc.size, + texcoord, + texcoord + ((startPos - endPos):Length() / 128), + arc.color + ) + end + end +end diff --git a/gamemodes/nzombies/entities/effects/one_inch_punch_blow/init.lua b/gamemodes/nzombies/entities/effects/one_inch_punch_blow/init.lua new file mode 100644 index 00000000..975b9db3 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/one_inch_punch_blow/init.lua @@ -0,0 +1,66 @@ +local particles = { + Model("particle/particle_ring_wave_8"), +} + +local delay = 0.05 +local amount = 3 + +--Main function +function EFFECT:Init(data) + --Create particle emitter + local emitter = ParticleEmitter(data:GetOrigin()) + local bone = math.Round(data:GetMagnitude()) + local num = 0 + timer.Create("one_inch_punch_effect", delay, amount, function() + if IsValid(LocalPlayer()) and LocalPlayer():GetActiveWeapon():GetClass() == "nz_one_inch_punch" then + num = num + 1 + local pos = LocalPlayer():GetViewModel():GetBoneMatrix(bone):GetTranslation() + local particle = emitter:Add( table.Random(particles), pos ) + if (particle) then + particle:SetVelocity(LocalPlayer():GetVelocity()) + particle:SetLifeTime(0) + particle:SetDieTime(1.1) + particle:SetColor(200,200,200) + particle:SetLighting(false) + particle:SetStartAlpha(100) + particle:SetEndAlpha(0) + + local Size = math.Rand(5,10) + particle:SetStartSize(Size) + particle:SetEndSize(Size) + particle:SetRoll(math.Rand(-360, 360)) + particle:SetRollDelta(math.Rand(-2, 2)) + particle:SetAirResistance(math.Rand(200, 400)) + particle:SetGravity( Vector(0, 0, 0) ) + particle:SetCollide(false) + particle:SetBounce(0.42) + --particle:SetLighting(1) + end + + if num >= amount then + emitter:Finish() + timer.Destroy("one_inch_punch_effect") + end + else + emitter:Finish() + timer.Destroy("one_inch_punch_effect") + end + end) +end + +function EFFECT:Think() + if !self.NextParticle or self.NextParticle < CurTime() then + + self.NextParticle = CurTime() + delay + end + if self.KillTime and self.KillTime < CurTime() then + print("Done") + emitter:Finish() + return false + end + self:NextThink(CurTime()) +end + +--Not used +function EFFECT:Render() +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/effects/panzer_explode/init.lua b/gamemodes/nzombies/entities/effects/panzer_explode/init.lua new file mode 100644 index 00000000..d3e03b72 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/panzer_explode/init.lua @@ -0,0 +1,46 @@ +AddCSLuaFile() + +EFFECT.Mat = { + Model("particle/particle_smokegrenade"), + Model("particle/particle_noisesphere") +} + +function EFFECT:Init( data ) + local pos = data:GetOrigin() + local duration = data:GetMagnitude() + local em = ParticleEmitter( pos ) + for i = 0, 20 do + local p = em:Add( self.Mat[math.random(#self.Mat)] , pos ) + if p then + p:SetColor(math.random(100,120), math.random(100,150), math.random(150,170)) + p:SetStartAlpha(255) + p:SetEndAlpha(150) + local vel = VectorRand() * math.Rand(50,300) + vel.z = 0 + p:SetVelocity(vel) + p:SetLifeTime(0) + + p:SetDieTime(math.Rand(duration + 0.75, duration + 1.5)) + + p:SetStartSize(math.random(45, 50)) + p:SetEndSize(math.random(20, 30)) + p:SetRoll(math.random(-180, 180)) + p:SetRollDelta(math.Rand(-0.1, 0.1)) + p:SetAirResistance(100) + + p:SetCollide(true) + p:SetBounce(0.4) + + p:SetLighting(false) + end + end + em:Finish() +end + +function EFFECT:Think() + return false +end + +function EFFECT:Render() + return false +end diff --git a/gamemodes/nzombies/entities/effects/panzer_land_dust/init.lua b/gamemodes/nzombies/entities/effects/panzer_land_dust/init.lua new file mode 100644 index 00000000..d3e03b72 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/panzer_land_dust/init.lua @@ -0,0 +1,46 @@ +AddCSLuaFile() + +EFFECT.Mat = { + Model("particle/particle_smokegrenade"), + Model("particle/particle_noisesphere") +} + +function EFFECT:Init( data ) + local pos = data:GetOrigin() + local duration = data:GetMagnitude() + local em = ParticleEmitter( pos ) + for i = 0, 20 do + local p = em:Add( self.Mat[math.random(#self.Mat)] , pos ) + if p then + p:SetColor(math.random(100,120), math.random(100,150), math.random(150,170)) + p:SetStartAlpha(255) + p:SetEndAlpha(150) + local vel = VectorRand() * math.Rand(50,300) + vel.z = 0 + p:SetVelocity(vel) + p:SetLifeTime(0) + + p:SetDieTime(math.Rand(duration + 0.75, duration + 1.5)) + + p:SetStartSize(math.random(45, 50)) + p:SetEndSize(math.random(20, 30)) + p:SetRoll(math.random(-180, 180)) + p:SetRollDelta(math.Rand(-0.1, 0.1)) + p:SetAirResistance(100) + + p:SetCollide(true) + p:SetBounce(0.4) + + p:SetLighting(false) + end + end + em:Finish() +end + +function EFFECT:Think() + return false +end + +function EFFECT:Render() + return false +end diff --git a/gamemodes/nzombies/entities/effects/panzer_spawn_tp/init.lua b/gamemodes/nzombies/entities/effects/panzer_spawn_tp/init.lua new file mode 100644 index 00000000..86fdbf2f --- /dev/null +++ b/gamemodes/nzombies/entities/effects/panzer_spawn_tp/init.lua @@ -0,0 +1,230 @@ +AddCSLuaFile() + +EFFECT.MatEdge = Material( "effects/tool_tracer" ) +EFFECT.MatCenter = Material( "sprites/physbeama" ) +EFFECT.MatGlow1 = Material( "sprites/physg_glow1" ) +EFFECT.MatGlow2 = Material( "sprites/physg_glow2" ) +EFFECT.MatGlowCenter = Material( "sprites/glow04_noz" ) + +EFFECT.Mat = { + --Model("gmod/scope-refract"), + Model("particle/particle_sphere"), + Model("particle/particle_smokegrenade"), + Model("particle/particle_noisesphere") +} + +local mid = Model("models/effects/comball_glow1") + +local colors = { + {150, 100, 200}, + {160, 100, 150}, + {150, 60, 150}, + {170, 80, 150}, + {120, 60, 200}, + {50, 20, 200} +} + +function EFFECT:Init( data ) + + self.Size = 5 + self.MaxArcs = 2 + self.Frequency = 0.05 + + self.Alpha = 255 + self.Life = 0 + self.KillTime = CurTime() + 1.5 + self.NextArc = 0 + self.Arcs = {} + self.Queue = 1 + + local pos = data:GetOrigin() + self.Pos = pos + local duration = data:GetMagnitude() + + sound.Play("ambient/machines/teleport4.wav", self.Pos, 100, 100, 1) + + local em = ParticleEmitter( pos ) + for i = 0, 20 do + local p = em:Add( self.Mat[math.random(#self.Mat)] , pos ) + if p then + local col = math.random(1, #colors) + p:SetColor(colors[col][1], colors[col][2], colors[col][3]) + p:SetStartAlpha(255) + p:SetEndAlpha(150) + local vel = VectorRand() * math.Rand(150,200) + vel.z = math.random(-10, 10) + + p:SetPos(pos + vel) + p:SetVelocity(vel * -10) + p:SetLifeTime(0) + + p:SetDieTime(math.Rand(duration + 0.2, duration + 0.5)) + + p:SetStartSize(math.random(30, 40)) + p:SetEndSize(math.random(10, 20)) + p:SetRoll(math.random(-180, 180)) + p:SetRollDelta(math.Rand(-0.1, 0.1)) + p:SetAirResistance(350) + + p:SetCollide(true) + p:SetBounce(0.4) + + p:SetLighting(false) + end + end + local p = em:Add( mid, pos ) + p:SetStartAlpha(255) + p:SetEndAlpha(150) + + p:SetPos(pos) + p:SetLifeTime(0) + + p:SetDieTime(1.5) + + p:SetStartSize(0) + p:SetEndSize(400) + timer.Simple(0.2, function() + p:SetStartSize(60) + p:SetEndSize(60) + end) + timer.Simple(1.3, function() + p:SetStartSize(400) + p:SetEndSize(0) + end) + p:SetRoll(math.random(-180, 180)) + p:SetRollDelta(math.Rand(-0.1, 0.1)) + p:SetAirResistance(300) + + p:SetCollide(false) + + p:SetLighting(false) + em:Finish() +end + +--[[--------------------------------------------------------- + THINK +-----------------------------------------------------------]] +function EFFECT:Think() + + self.Life = self.Life + FrameTime() + --self.Alpha = 255 * ( 1 - self.Life ) + + if self.NextArc <= self.Life then + + local size = #self.Arcs + --add a arc to the array + while self.Arcs[size] do + size = size + 1 + end + self.Arcs[size] = self:GenerateArc(self.Pos + AngleRand():Forward()*10*self.Size, self.Pos + AngleRand():Forward()*10*self.Size, 0.01, 4) + self.NextArc = self.NextArc + self.Frequency + + if size >= self.MaxArcs then + local i = 1 + while not self.Arcs[i] and i <= size do + i = i + 1 + end + self.Arcs[i] = nil + end + end + + return CurTime() < self.KillTime +end + +function EFFECT:GenerateArc(startPos, endPos, branchChance, detail) + -- MidPoint Displacement for arc lines + local points = {} + local maxPoints = 2^detail + + if maxPoints % 2 != 0 then + maxPoints = maxPoints + 1 + end + + points[0] = startPos + + local randVec = VectorRand() * 10 + + randVec.z = math.Clamp(randVec.z, 0, 10) + + points[maxPoints] = endPos + randVec + + local i = 1 + + while i < maxPoints do + local j = (maxPoints / i) / 2 + while j < maxPoints do + points[j] = ((points[j - (maxPoints / i) / 2] + points[j + (maxPoints / i) / 2]) / 2); + points[j] = points[j] + VectorRand() * 10 + if math.Rand(0,1) < branchChance then + points[#points + 1] = self:GenerateArc(points[j], points[j] + Vector(math.random(-50 * branchChance, 50 * branchChance), math.random(-50 * branchChance, 50 * branchChance), math.random(-50 * branchChance, 10 * branchChance)), branchChance/1.3, detail) + end + j = j + maxPoints / i + end + i = i * 2 + end + + points.size = math.random(1,3)*self.Size + points.color = Color(200, 240, math.random(230, 255), math.random(200, 255)) + points.dietime = CurTime() + 0.07 + + return points +end + +--[[--------------------------------------------------------- + Draw the effect +-----------------------------------------------------------]] +function EFFECT:Render() + + if ( self.Alpha < 1 ) then return end + + render.SetMaterial( self.MatCenter ) + + for _, arc in pairs(self.Arcs) do + if arc.dietime <= CurTime() then + self.Arcs[_] = nil + else + self:RenderArc(arc) + end + end + + render.SetMaterial( self.MatEdge ) + + for _, arc in pairs(self.Arcs) do + self:RenderArc(arc, true) + end + + render.SetMaterial( self.MatGlow1 ) + render.DrawSprite( self.Pos, math.random(40,120)*self.Size, math.random(40,120)*self.Size, Color(math.random(50,150),math.random(100,200),255,math.random(100,200))) + + if math.random(0,10) == 0 then + render.SetMaterial( self.MatGlow2 ) + render.DrawSprite( self.Pos, math.random(20,60)*self.Size, math.random(40,120)*self.Size, Color(math.random(50,150),math.random(100,200),255,math.random(100,200))) + end + + render.SetMaterial( self.MatGlowCenter ) + render.DrawSprite( self.Pos, math.random(15,40)*self.Size, math.random(15,40)*self.Size, Color(math.random(50,150),math.random(100,200),255,math.random(200,250))) +end + +function EFFECT:RenderArc(arc, edge) + for j = 1, #arc - 1 do + + if istable(arc[j]) then + self:RenderArc(arc[j]) + elseif !istable(arc[j+1]) then + + local texcoord = math.Rand( 0, 1 ) + + local startPos = arc[j] + local endPos = arc[j + 1] + + render.DrawBeam( + startPos, + endPos, + (edge and arc.size*3 or arc.size), + texcoord, + texcoord + ((startPos - endPos):Length() / 128), + arc.color + ) + end + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/effects/pap_glow/init.lua b/gamemodes/nzombies/entities/effects/pap_glow/init.lua new file mode 100644 index 00000000..64cfd23b --- /dev/null +++ b/gamemodes/nzombies/entities/effects/pap_glow/init.lua @@ -0,0 +1,86 @@ +--Name: Lightning strike using midpoint displacement +--Author: Lolle + +--EFFECT.MatCenter = Material( "lightning.png", "unlitgeneric smooth" ) +EFFECT.MatEdge = Material( "effects/tool_tracer" ) +EFFECT.MatCenter = Material( "sprites/physbeama" ) +EFFECT.MatGlow1 = Material( "sprites/physg_glow1" ) +EFFECT.MatGlow2 = Material( "sprites/physg_glow2" ) +EFFECT.MatGlowCenter = Material( "sprites/glow04_noz" ) + +--[[--------------------------------------------------------- + Init( data table ) +-----------------------------------------------------------]] +function EFFECT:Init( data ) + + self.Parent = data:GetEntity() + self.Pos = self.Parent:GetPos() + self.Offset = data:GetOrigin() - self.Pos + self.DieTime = 1 + self.Duration = data:GetMagnitude() or 2 + self.Count = self.Duration * 40 + self.Radius = 30 + + self.Alpha = 1 + self.Life = 0 + + self:SetRenderBoundsWS( self.Pos, self.Pos, Vector(100,100,100) ) + + --sound.Play("nz/hellhound/spawn/prespawn.wav", self.Pos, 100, 100, 1) + +end + +--[[--------------------------------------------------------- + THINK +-----------------------------------------------------------]] +function EFFECT:Think() + + if IsValid(self.Parent) then + self.Pos = self.Parent:GetPos() + self.Offset + end + + self.Life = self.Life + FrameTime() + if self.Life > self.Duration then + self.Alpha = 1 - (self.Life - self.Duration)/self.DieTime + end + + return ( self.Life < self.Duration + self.DieTime ) +end + +--[[--------------------------------------------------------- + Draw the effect +-----------------------------------------------------------]] +function EFFECT:Render() + + if ( self.Alpha <= 0 ) then return end + + local dir = self.Offset:Angle():Right() + + + local col = Color(255,255,255,math.random(100,255) * self.Alpha) + local col2 = Color(255,255,255,math.random(230,255) * self.Alpha) + + render.SetMaterial( self.MatGlow1 ) + render.DrawSprite( self.Pos, math.random(50,100), math.random(50,100), col) + render.DrawSprite( self.Pos + dir*10, math.random(50,100), math.random(50,100), col) + render.DrawSprite( self.Pos - dir*10, math.random(50,100), math.random(50,100), col) + render.DrawSprite( self.Pos + dir*20, math.random(50,100), math.random(50,100), col) + render.DrawSprite( self.Pos - dir*20, math.random(50,100), math.random(50,100), col) + + if math.random(0,10) == 0 then + render.SetMaterial( self.MatGlow2 ) + render.DrawSprite( self.Pos, math.random(50,100), math.random(50,100), col) + render.DrawSprite( self.Pos + dir*10, math.random(50,100), math.random(50,100), col) + render.DrawSprite( self.Pos - dir*10, math.random(50,100), math.random(50,100), col) + render.DrawSprite( self.Pos + dir*20, math.random(50,100), math.random(50,100), col) + render.DrawSprite( self.Pos - dir*20, math.random(50,100), math.random(50,100), col) + end + + render.SetMaterial( self.MatGlowCenter ) + render.DrawSprite( self.Pos, math.random(50,75), math.random(50,75), col2) + render.DrawSprite( self.Pos + dir*10, math.random(50,75), math.random(50,75), col2) + render.DrawSprite( self.Pos - dir*10, math.random(50,75), math.random(50,75), col2) + render.DrawSprite( self.Pos + dir*20, math.random(50,75), math.random(50,75), col2) + render.DrawSprite( self.Pos - dir*20, math.random(50,75), math.random(50,75), col2) + +end diff --git a/gamemodes/nzombies/entities/effects/powerup_glow/init.lua b/gamemodes/nzombies/entities/effects/powerup_glow/init.lua new file mode 100644 index 00000000..03de612c --- /dev/null +++ b/gamemodes/nzombies/entities/effects/powerup_glow/init.lua @@ -0,0 +1,53 @@ +function EFFECT:Init( data ) + + local vOffset = data:GetOrigin() + + local NumParticles = 1 + + local emitter = ParticleEmitter( vOffset ) + + for i=0, NumParticles do + + local particle = emitter:Add( "sprites/physg_glow1", vOffset ) + if (particle) then + + particle:SetVelocity( Vector(0,0,0) ) + particle:SetColor(math.random(50,100), math.random(200,255), math.random(100,150)) + + particle:SetLifeTime( 0 ) + particle:SetDieTime( 0.3 ) + + particle:SetStartAlpha( 100 ) + particle:SetEndAlpha( 0 ) + + particle:SetStartSize( 25 ) + particle:SetEndSize( 25 ) + + particle:SetRoll( math.Rand(0, 36)*10 ) + --particle:SetRollDelta( math.Rand(-200, 200) ) + + particle:SetAirResistance( 400 ) + + particle:SetGravity( Vector( 0, 0, 0 ) ) + + end + + end + + emitter:Finish() + +end + + +--[[--------------------------------------------------------- + THINK +-----------------------------------------------------------]] +function EFFECT:Think( ) + return false +end + +--[[--------------------------------------------------------- + Draw the effect +-----------------------------------------------------------]] +function EFFECT:Render() +end diff --git a/gamemodes/nzombies/entities/effects/vulture_gascloud/init.lua b/gamemodes/nzombies/entities/effects/vulture_gascloud/init.lua new file mode 100644 index 00000000..2a2a481a --- /dev/null +++ b/gamemodes/nzombies/entities/effects/vulture_gascloud/init.lua @@ -0,0 +1,49 @@ +local gasparticles = { + Model("particle/particle_smokegrenade"), + Model("particle/particle_noisesphere") +} + +--Main function +function EFFECT:Init(data) + --Create particle emitter + local emitter = ParticleEmitter(data:GetOrigin()) + --Amount of particles to create + for i=0, 16 do + --Safeguard + if !emitter then return end + + local Pos = (data:GetOrigin() + Vector( math.Rand(-5,5), math.Rand(-5,5), math.Rand(-5,5) )) + local particle = emitter:Add( table.Random(gasparticles), Pos ) + if (particle) then + particle:SetVelocity(VectorRand() * math.Rand(100,200)) + particle:SetLifeTime(0) + particle:SetDieTime(math.Rand(4, 6)) + particle:SetColor(100,255,150) + particle:SetLighting(false) + particle:SetStartAlpha(255) + particle:SetEndAlpha(0) + + local Size = math.Rand(10,20) + particle:SetStartSize(Size) + particle:SetEndSize(Size) + particle:SetRoll(math.Rand(-360, 360)) + particle:SetRollDelta(math.Rand(-0.21, 0.21)) + particle:SetAirResistance(math.Rand(520,620)) + particle:SetGravity( Vector(0, 0, 0) ) + particle:SetCollide(false) + particle:SetBounce(0.42) + particle:SetLighting(1) + end + end + --We're done with this emitter + emitter:Finish() +end + +--Kill effect +function EFFECT:Think() +return false +end + +--Not used +function EFFECT:Render() +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/effects/web_aura/init.lua b/gamemodes/nzombies/entities/effects/web_aura/init.lua new file mode 100644 index 00000000..d246f3c6 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/web_aura/init.lua @@ -0,0 +1,101 @@ + +local mats = { + Material( "decals/glass/shot1" ), + Material( "decals/glass/shot2" ), + Material( "decals/glass/shot3" ), + Material( "decals/glass/shot4" ), + Material( "decals/glass/shot5" ), + nil +} + +--[[--------------------------------------------------------- + Init( data table ) +-----------------------------------------------------------]] +function EFFECT:Init( data ) + + self.Size = data:GetScale() or 1 + self.Parent = data:GetEntity() + self.Frequency = data:GetMagnitude() or 2 + self.Pos = self.Parent:GetPos() + if self.Parent.WebAura then -- Already have an aura + if data:GetScale() then + self.Parent.WebAura = CurTime() + data:GetScale() -- Extend to new time + else + self.Parent.WebAura = CurTime() + 20 + end + self.KILL = true -- and make sure to kill this effect + else + if data:GetScale() then + self.Parent.WebAura = CurTime() + data:GetScale() + else + self.Parent.WebAura = CurTime() + 20 -- Default time for this effect + end + + self:SetRenderBoundsWS( self.Pos, self.Pos, Vector(100,100,100) ) + self.MoveSpeed = 50 + + self.NextParticle = CurTime() + + self.Emitter = ParticleEmitter( self.Pos ) + end +end + +--[[--------------------------------------------------------- + THINK +-----------------------------------------------------------]] + +function EFFECT:Think( ) + if self.KILL then return false end + + if CurTime() >= self.NextParticle then + local diroffset = Vector(math.Rand(-1,1), math.Rand(-1,1),0):GetNormalized()*5 + local pos = self.Emitter:GetPos() + diroffset + Vector(0,0,20) + local particle = self.Emitter:Add(mats[math.random(#mats)], pos) + if (particle) then + particle:SetVelocity( Vector(0,0,0) ) + particle:SetColor( 255, 255, 255 ) + particle:SetLifeTime( 5 ) + particle:SetDieTime( 10 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 15 ) + particle:SetEndSize( 25 ) + particle:SetRoll( math.Rand(0, 360)*10 ) + particle:SetRollDelta( math.Rand(-10, 10) ) + particle:SetAirResistance( 400 ) + particle:SetGravity( Vector( 0, 0, 0 ) ) + + particle:SetNextThink(CurTime()) + particle.Dir = diroffset:Angle():Forward() + particle.Vel = 30 + particle:SetThinkFunction( function() + if !IsValid(self.Parent) and self.Emitter then self.Emitter:Finish() return end + particle.Dir:Rotate(Angle(0,3,0)) + particle:SetVelocity( Vector(particle.Dir.x * particle.Vel, particle.Dir.y * particle.Vel, 5) ) + particle.Vel = particle.Vel + 0.1 + particle:SetNextThink(CurTime() + 0.01) + end ) + + self.NextParticle = CurTime() + self.Frequency + end + end + if IsValid(self.Parent) then + if (type(self.Parent.WebAura) == "number" and CurTime() > self.Parent.WebAura) or !self.Parent.WebAura then + self.Emitter:Finish() + self.Parent.WebAura = nil + return false + else + self.Emitter:SetPos( self.Parent:GetPos() ) + return true + end + else + self.Emitter:Finish() + return false + end +end + +--[[--------------------------------------------------------- + Draw the effect +-----------------------------------------------------------]] +function EFFECT:Render() +end diff --git a/gamemodes/nzombies/entities/effects/web_aura2/init.lua b/gamemodes/nzombies/entities/effects/web_aura2/init.lua new file mode 100644 index 00000000..dca756c9 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/web_aura2/init.lua @@ -0,0 +1,169 @@ + +local stringdeathtime = 1 +local stringmat = Material( "trails/physbeam" ) +local stringspeed = 2 +local stringmax = 10 +local color = Color(255,255,255) +local downspeed = Vector(0,0,10) + +--[[--------------------------------------------------------- + Init( data table ) +-----------------------------------------------------------]] +function EFFECT:Init( data ) + + self.Size = data:GetScale() or 1 + self.Parent = data:GetEntity() + self.Frequency = data:GetMagnitude() or 2 + self.Pos = self.Parent:GetPos() + self.Hitbox = data:GetHitBox() or 0 + self.Bone = self.Parent:GetHitBoxBone(self.Hitbox, self.Hitbox) + + if IsValid(self.Parent.WebAuraEffect) then + self.Parent.WebAuraEffect.KILL = true + end + + local scale = data:GetScale() + if scale then + if scale >= 0 then + self.Parent.WebAura = CurTime() + scale + else + self.Parent.WebAura = true + end + else + self.Parent.WebAura = CurTime() + 20 -- Default time for this effect + end + + self:SetRenderBounds( Vector(0,0,0), Vector(0,0,0), Vector(50,50,50) ) + self.MoveSpeed = 50 + self.NextParticle = CurTime() + self.Emitter = ParticleEmitter( self.Pos ) + + self.Parent.WebAuraEffect = self + self.WebPoints = {} + self.DeadWebs = {} +end + +--[[--------------------------------------------------------- + THINK +-----------------------------------------------------------]] + +function EFFECT:Think( ) + if self.KILL then return false end + local ct = CurTime() + + if self.AutoKillTimer and ct >= self.AutoKillTimer then + return false + end + + if IsValid(self.Parent) then + if !self.AutoKillTimer and ((type(self.Parent.WebAura) == "number" and ct > self.Parent.WebAura) or !self.Parent.WebAura) then + self.Parent.WebAura = nil + self.Parent.WebAuraEffect = nil + + -- Kill all current webs rotating + for k,v in pairs(self.WebPoints) do + + end + self.AutoKillTimer = ct + 2 + + return true + else + self:SetPos( self.Parent:GetPos() ) + return true + end + else + return false + end +end + +--[[--------------------------------------------------------- + Draw the effect +-----------------------------------------------------------]] +function EFFECT:Render() + + local ent = self.Parent + local min,max = ent:GetHitBoxBounds(self.Hitbox, self.Hitbox) + local pos,ang = ent:GetBonePosition(self.Bone) + + local forward = ang:Forward() + local right = ang:Right()*(max.y + 5) + local up = ang:Up()*(max.x + 5) + + local ct = CurTime() + + if ct >= self.NextParticle and !self.AutoKillTimer then + local tbl = {} + tbl.time = ct + tbl.z = math.random(-10,10) + tbl.pointcount = math.random(2,4) + tbl.points = {} + local offset = math.Rand(-math.pi,math.pi) -- Full circular offset + local timeoffset = 0 + for i = 1, tbl.pointcount do + local new = math.Rand(0.3, 1) + offset = offset + new + timeoffset = timeoffset + new + tbl.points[i] = {offset = offset, falltime = stringdeathtime + math.Rand(0,0.2) + timeoffset} + end + + table.insert(self.WebPoints, tbl) + self.NextParticle = ct + 0.5 + end + + render.SetMaterial( stringmat ) + local count = table.Count(self.WebPoints) + for k,v in pairs(self.WebPoints) do + local diff = ct - v.time + + local pcount = #v.points + for k2,v2 in pairs(v.points) do + if pcount <= 1 then + table.remove(self.WebPoints, k) + break + end + + local pdiff = diff - v2.offset + local rotate = pdiff*stringspeed + local epos + + if diff <= v2.falltime then + epos = pos + math.cos(rotate)*up + math.sin(rotate)*right + v.z*forward + else + if !v2.deadtime then + v2.deaddur = math.Rand(1.8,2.5) + v2.deadtime = pdiff + v2.deaddur + end + if pdiff >= v2.deadtime then + table.remove(v.points, k2) + break + else + if v2.pos then + epos = v2.pos - downspeed*FrameTime() + else + epos = pos + end + end + end + v2.pos = epos + + local new = v.points[k2+1] + if new then + local pos1 = v2.pos + local pos2 = new.pos + if pos1 and pos2 then + local fade = v2.deadtime and (v2.deadtime - pdiff)/v2.deaddur * 255 + color.a = fade or 255 + render.DrawBeam( + pos1, + pos2, + 3, + 0, + ((pos1 - pos2):Length() / 128), + color + ) + end + end + end + end + +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/effects/web_explosion/init.lua b/gamemodes/nzombies/entities/effects/web_explosion/init.lua new file mode 100644 index 00000000..a093ea81 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/web_explosion/init.lua @@ -0,0 +1,52 @@ +AddCSLuaFile() + +local mats = { + Material( "decals/glass/shot1" ), + Material( "decals/glass/shot2" ), + Material( "decals/glass/shot3" ), + Material( "decals/glass/shot4" ), + Material( "decals/glass/shot5" ), + nil +} + +function EFFECT:Init( data ) + local pos = data:GetOrigin() + local mag = data:GetMagnitude() + + local em = ParticleEmitter( pos ) + for i = 0, 10 do + local p = em:Add( mats[math.random(#mats)], pos ) + if p then + p:SetColor(math.random(120,170), math.random(100,120), math.random(100,120)) + p:SetStartAlpha(255) + p:SetEndAlpha(150) + local vel = VectorRand() * math.Rand(50,300) + vel.z = 300 + p:SetVelocity(vel) + p:SetLifeTime(0) + + p:SetDieTime(math.Rand(0.5, 1)) + + p:SetStartSize(math.random(20, 30)) + p:SetEndSize(math.random(50, 70)) + p:SetRoll(math.random(-180, 180)) + p:SetRollDelta(math.Rand(-2, 2)) + p:SetAirResistance(200) + p:SetGravity(Vector(0,0,-100)) + + p:SetCollide(true) + p:SetBounce(0.4) + + p:SetLighting(false) + end + end + em:Finish() +end + +function EFFECT:Think() + return false +end + +function EFFECT:Render() + return false +end diff --git a/gamemodes/nzombies/entities/effects/zapper_lightning/init.lua b/gamemodes/nzombies/entities/effects/zapper_lightning/init.lua new file mode 100644 index 00000000..f01f3997 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/zapper_lightning/init.lua @@ -0,0 +1,53 @@ +--Name: Lightning strike using midpoint displacement +--Author: Lolle + +--EFFECT.MatCenter = Material( "lightning.png", "unlitgeneric smooth" ) +EFFECT.MatTracer = Material( "effects/tool_tracer" ) + +--[[--------------------------------------------------------- + Init( data table ) +-----------------------------------------------------------]] +function EFFECT:Init( data ) + + self.StartPos = data:GetStart() + self.EndPos = data:GetOrigin() + self.Duration = data:GetMagnitude() or 10 + + self.Flash = DynamicLight( LocalPlayer():EntIndex() ) + + self.Flash.pos = self.StartPos + self.Flash.r = 255 + self.Flash.g = 255 + self.Flash.b = 255 + self.Flash.brightness = 1 + self.Flash.Decay = 200 + self.Flash.Size = 200 + self.Flash.style = 6 + self.Flash.DieTime = CurTime() + self.Duration + + self.Life = 0 + + self:SetRenderBoundsWS( self.StartPos, self.EndPos ) +end + +function EFFECT:Think() + self.Life = self.Life + FrameTime() + --self.Alpha = 255 * ( 1 - self.Life ) + + return ( self.Life < self.Duration ) +end + +function EFFECT:Render() + local texcoord = math.Rand( 0, 1 ) + + render.SetMaterial(self.MatTracer) + + render.DrawBeam( + self.StartPos, + self.EndPos, + 12, + texcoord, + texcoord + ((self.StartPos - self.EndPos):Length() / 128), + Color(math.random(200, 255), math.random(220, 255), math.random(150, 200)) + ) +end diff --git a/gamemodes/nzombies/entities/effects/zombie_soul/init.lua b/gamemodes/nzombies/entities/effects/zombie_soul/init.lua new file mode 100644 index 00000000..3802b9a2 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/zombie_soul/init.lua @@ -0,0 +1,54 @@ +function EFFECT:Init( data ) + + self.Start = data:GetOrigin() + self.Catcher = data:GetEntity() + self.ParticleDelay = 0.1 + self.MoveSpeed = 50 + self.DistToCatch = 100 -- Squared (10) + + self.NextParticle = CurTime() + + self.Emitter = ParticleEmitter( self.Start ) + + print(self.Emitter, self.NextParticle, self, self.Catcher) + +end + + +--[[--------------------------------------------------------- + THINK +-----------------------------------------------------------]] +function EFFECT:Think( ) + if CurTime() >= self.NextParticle then + local particle = self.Emitter:Add("sprites/glow04_noz", self.Emitter:GetPos()) + if (particle) then + particle:SetVelocity( Vector(0,0,0) ) + particle:SetColor(math.random(200,255), math.random(100,200), math.random(100,150)) + particle:SetLifeTime( 0 ) + particle:SetDieTime( 0.3 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 25 ) + particle:SetEndSize( 25 ) + particle:SetRoll( math.Rand(0, 36)*10 ) + --particle:SetRollDelta( math.Rand(-200, 200) ) + particle:SetAirResistance( 400 ) + particle:SetGravity( Vector( 0, 0, 0 ) ) + + self.NextParticle = CurTime() + self.ParticleDelay + end + end + self.Emitter:SetPos( (self.Catcher:GetPos()-self.Emitter:GetPos()):GetNormal() * self.MoveSpeed * FrameTime() + self.Emitter:GetPos() ) + if self.Emitter:GetPos():DistToSqr(self.Catcher:GetPos()) <= self.DistToCatch then + self.Catcher:CollectSoul() + return false + else + return true + end +end + +--[[--------------------------------------------------------- + Draw the effect +-----------------------------------------------------------]] +function EFFECT:Render() +end diff --git a/gamemodes/nzombies/entities/effects/zombie_spawn_dust/init.lua b/gamemodes/nzombies/entities/effects/zombie_spawn_dust/init.lua new file mode 100644 index 00000000..9e3b6337 --- /dev/null +++ b/gamemodes/nzombies/entities/effects/zombie_spawn_dust/init.lua @@ -0,0 +1,81 @@ +AddCSLuaFile() + +local matground = { + Model("particle/particle_smokegrenade"), + Model("particle/particle_noisesphere") +} +local matshoot = { + Model("particle/particle_debris_01"), + Model("particle/particle_debris_02"), + Model("particle/particle_noisesphere"), + Model("particle/particle_smokegrenade") +} + + +function EFFECT:Init( data ) + local pos = data:GetOrigin() + local duration = data:GetMagnitude() + local em = ParticleEmitter( pos ) + for i = 0, 10 do + local p = em:Add( matshoot[math.random(#matshoot)] , pos ) + if p then + p:SetColor(math.random(45,55), math.random(40,50), math.random(40,50)) + p:SetStartAlpha(255) + p:SetEndAlpha(0) + local vel = VectorRand() * math.Rand(40,70) + vel.z = math.random(200,1000) + p:SetVelocity(vel) + p:SetGravity(Vector(0,0,-1000)) + p:SetLifeTime(0) + + p:SetDieTime(math.Rand(duration + 0.5, duration + 1)) + + p:SetStartSize(math.random(35, 40)) + p:SetEndSize(math.random(10, 20)) + p:SetRoll(math.random(-180, 180)) + p:SetRollDelta(math.Rand(-0.1, 0.1)) + p:SetAirResistance(100) + + p:SetCollide(true) + p:SetBounce(0.4) + + p:SetLighting(false) + end + end + for i = 0, 5 do + local p = em:Add( matground[math.random(#matground)] , pos ) + if p then + p:SetColor(math.random(45,55), math.random(40,50), math.random(40,50)) + p:SetStartAlpha(255) + p:SetEndAlpha(250) + local vel = VectorRand() * math.Rand(10,50) + vel.z = 0 + p:SetVelocity(vel) + p:SetLifeTime(0) + + p:SetDieTime(math.Rand(duration + 0.75, duration + 1.5)) + + p:SetStartSize(math.random(45, 50)) + p:SetEndSize(math.random(20, 30)) + p:SetRoll(math.random(-180, 180)) + p:SetRollDelta(math.Rand(-0.1, 0.1)) + p:SetAirResistance(100) + + p:SetCollide(true) + p:SetBounce(0.4) + + p:SetLighting(false) + end + end + em:Finish() + + sound.Play("nz/zombies/spawn/zm_spawn_dirt"..math.random(1,2)..".wav", pos, 75, 100, 1) +end + +function EFFECT:Think() + return false +end + +function EFFECT:Render() + return false +end diff --git a/gamemodes/nzombies/entities/entities/base_edit.lua b/gamemodes/nzombies/entities/entities/base_edit.lua new file mode 100644 index 00000000..840396b4 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/base_edit.lua @@ -0,0 +1,49 @@ + +AddCSLuaFile() +DEFINE_BASECLASS( "base_anim" ) + +ENT.PrintName = "" +ENT.Author = "" +ENT.Contact = "" +ENT.Purpose = "" +ENT.Instructions = "" + +ENT.Spawnable = false +ENT.AdminOnly = false +ENT.Editable = true + +function ENT:Initialize() + + if ( CLIENT ) then return end + + self:SetModel( "models/MaxOfS2D/cube_tool.mdl" ) + self:PhysicsInit( SOLID_VPHYSICS ) + self:SetUseType( ONOFF_USE ) + +end + +function ENT:SpawnFunction( ply, tr, ClassName ) + + if ( !tr.Hit ) then return end + + local SpawnPos = tr.HitPos + tr.HitNormal * 10 + local SpawnAng = ply:EyeAngles() + SpawnAng.p = 0 + SpawnAng.y = SpawnAng.y + 180 + + local ent = ents.Create( ClassName ) + ent:SetPos( SpawnPos ) + ent:SetAngles( SpawnAng ) + ent:Spawn() + ent:Activate() + + return ent + +end + + +function ENT:EnableForwardArrow() + + self:SetBodygroup( 1, 1 ) + +end diff --git a/gamemodes/nzombies/entities/entities/breakable_entry/shared.lua b/gamemodes/nzombies/entities/entities/breakable_entry/shared.lua new file mode 100644 index 00000000..172311c9 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/breakable_entry/shared.lua @@ -0,0 +1,148 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "breakable_entry" +ENT.Author = "Alig96" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +ENT.NZOnlyVisibleInCreative = true + +-- models/props_interiors/elevatorshaft_door01a.mdl +-- models/props_debris/wood_board02a.mdl +function ENT:Initialize() + + self:SetModel("models/props_c17/fence01b.mdl") + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + + --self:SetHealth(0) + self:SetCustomCollisionCheck(true) + self.NextPlank = CurTime() + + self.Planks = {} + + if SERVER then + self:ResetPlanks(true) + end +end + +function ENT:SetupDataTables() + + self:NetworkVar( "Int", 0, "NumPlanks" ) + self:NetworkVar( "Bool", 0, "HasPlanks" ) + self:NetworkVar( "Bool", 1, "TriggerJumps" ) + +end + +function ENT:AddPlank(nosound) + if !self:GetHasPlanks() then return end + self:SpawnPlank() + self:SetNumPlanks( (self:GetNumPlanks() or 0) + 1 ) + if !nosound then + self:EmitSound("nz/effects/board_slam_0"..math.random(0,5)..".wav") + end +end + +function ENT:RemovePlank() + + local plank = table.Random(self.Planks) + + if !IsValid(plank) and plank != nil then -- Not valid but not nil (NULL) + table.RemoveByValue(self.Planks, plank) -- Remove it from the table + self:RemovePlank() -- and try again + end + + if IsValid(plank) then + -- Drop off + plank:SetParent(nil) + plank:PhysicsInit(SOLID_VPHYSICS) + local entphys = plank:GetPhysicsObject() + if entphys:IsValid() then + entphys:EnableGravity(true) + entphys:Wake() + end + plank:SetCollisionGroup( COLLISION_GROUP_DEBRIS ) + -- Remove + timer.Simple(2, function() if IsValid(plank) then plank:Remove() end end) + end + + table.RemoveByValue(self.Planks, plank) + self:SetNumPlanks( self:GetNumPlanks() - 1 ) +end + +function ENT:ResetPlanks(nosoundoverride) + for i=1, table.Count(self.Planks) do + self:RemovePlank() + end + self.Planks = {} + self:SetNumPlanks(0) + if self:GetHasPlanks() then + for i=1, GetConVar("nz_difficulty_barricade_planks_max"):GetInt() do + self:AddPlank(!nosoundoverride) + end + end +end + +function ENT:Use( activator, caller ) + if CurTime() > self.NextPlank then + if self:GetHasPlanks() and self:GetNumPlanks() < GetConVar("nz_difficulty_barricade_planks_max"):GetInt() then + self:AddPlank() + activator:GivePoints(10) + activator:EmitSound("nz/effects/repair_ching.wav") + self.NextPlank = CurTime() + 1 + end + end +end + +function ENT:SpawnPlank() + -- Spawn + local angs = {-60,-70,60,70} + local plank = ents.Create("breakable_entry_plank") + local min = self:GetTriggerJumps() and 0 or -45 + plank:SetPos( self:GetPos()+Vector(0,0, math.random( min, 45 )) ) + plank:SetAngles( Angle(0,self:GetAngles().y, table.Random(angs)) ) + plank:Spawn() + plank:SetParent(self) + plank:SetCollisionGroup( COLLISION_GROUP_DEBRIS ) + table.insert(self.Planks, plank) +end + +function ENT:Touch(ent) + --if self:GetTriggerJumps() and self:GetNumPlanks() == 0 then + --if ent.TriggerBarricadeJump then ent:TriggerBarricadeJump(self, self:GetTouchTrace().HitNormal) end + --end +end + +hook.Add("ShouldCollide", "zCollisionHook", function(ent1, ent2) + if IsValid(ent1) and ent1:GetClass() == "breakable_entry" and nzConfig.ValidEnemies[ent2:GetClass()] and !ent1:GetTriggerJumps() and ent1:GetNumPlanks() == 0 then + if !ent1.CollisionResetTime then + ent1:SetSolid(SOLID_NONE) + end + ent1.CollisionResetTime = CurTime() + 0.1 + end + + if IsValid(ent2) and ent2:GetClass() == "breakable_entry" and nzConfig.ValidEnemies[ent1:GetClass()] and !ent2:GetTriggerJumps() and ent2:GetNumPlanks() == 0 then + if !ent2.CollisionResetTime then + ent2:SetSolid(SOLID_NONE) + end + ent2.CollisionResetTime = CurTime() + 0.1 + end +end) + +if CLIENT then + function ENT:Draw() + if ConVarExists("nz_creative_preview") and !GetConVar("nz_creative_preview"):GetBool() and nzRound:InState( ROUND_CREATE ) then + self:DrawModel() + end + end +else + function ENT:Think() + if self.CollisionResetTime and self.CollisionResetTime < CurTime() then + self:SetSolid(SOLID_VPHYSICS) + self.CollisionResetTime = nil + end + end +end diff --git a/nzombies3/entities/entities/breakable_entry_plank/shared.lua b/gamemodes/nzombies/entities/entities/breakable_entry_plank/shared.lua similarity index 84% rename from nzombies3/entities/entities/breakable_entry_plank/shared.lua rename to gamemodes/nzombies/entities/entities/breakable_entry_plank/shared.lua index 4db68eee..b7fe2eaa 100644 --- a/nzombies3/entities/entities/breakable_entry_plank/shared.lua +++ b/gamemodes/nzombies/entities/entities/breakable_entry_plank/shared.lua @@ -14,13 +14,12 @@ function ENT:Initialize() self:SetModel("models/props_debris/wood_board02a.mdl") self:SetMoveType( MOVETYPE_VPHYSICS ) self:SetSolid( SOLID_VPHYSICS ) + self:SetModelScale(1.25) end if CLIENT then function ENT:Draw() - //if nz.Rounds.Data.CurrentState == ROUND_CREATE then - self:DrawModel() - // end + self:DrawModel() end end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/buildable_table/shared.lua b/gamemodes/nzombies/entities/entities/buildable_table/shared.lua new file mode 100644 index 00000000..6857db6f --- /dev/null +++ b/gamemodes/nzombies/entities/entities/buildable_table/shared.lua @@ -0,0 +1,204 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "buildable_table" +ENT.Author = "Zet0r" +ENT.Contact = "" +ENT.Purpose = "" +ENT.Instructions = "" + +ENT.TablesBeingCrafted = {} -- Shared between all entities of this type! + +-- models/props_interiors/elevatorshaft_door01a.mdl +-- models/props_debris/wood_board02a.mdl +function ENT:Initialize() + + self:SetModel("models/nzprops/table_workbench.mdl") + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + if SERVER then + self:SetUseType( SIMPLE_USE ) + end + + self.Craftables = self.Craftables or {} + self.ValidItems = self.ValidItems or {} + self.Crafting = self.Crafting + +end + +function ENT:SetupDataTables() + + self:NetworkVar( "Bool", 0, "Completed" ) + self:NetworkVar( "Bool", 1, "WIP" ) -- When just 1 part has been added + self:NetworkVar( "String", 0, "CraftingID" ) + self:NetworkVar( "String", 1, "CompletedText" ) + +end + +--[[ Format for craft table: + { + model = "model/of/finished/item.mdl", + pos = Vector(), -- (Relative to tables own pos) + ang = Angle(), -- (Relative too) + parts = { + [id1] = {submaterials}, -- Submaterials to "unhide" when this part is added + [id2] = {submaterials}, -- id's are ItemCarry object IDs + [id3] = {submaterials}, + -- You can have as many as you want + }, + partadded = function(table, id, ply) -- When a part is added (optional) + + end, + finishfunc = function(table) -- When all parts have been added (optional) + + end, + usefunc = function(table, ply) -- When it's completed and a player presses E (optional) + + end, + text = "String" -- Text to display when player is looking (after finished) (optional) + } +]] + +function ENT:AddValidCraft(id, tbl) + if !self.Craftables then self.Craftables = {} end + if !self.ValidItems then self.ValidItems = {} end + if id then + if tbl and tbl.parts then + self.Craftables[id] = tbl + for k,v in pairs(tbl.parts) do + self.ValidItems[k] = id + end + else + self.Craftables[id] = nil -- Removes it + end + end +end + +function ENT:CanPlayerCraft(ply) + if !self.ValidItems then self.ValidItems = {} end + for k,v in pairs(ply:GetCarryItems()) do + local id = self.ValidItems[v] + local tbl = self.TablesBeingCrafted[id] -- The table that this item is being worked on + if id and (!IsValid(tbl) or tbl == self) then -- No other tables are being worked on with this! + return id, v + end + end +end + +function ENT:IsValidCraftingPart(id) + return self.ValidItems[id] +end + +function ENT:SetCraftedItem(id) + self.Crafting = id + self.TablesBeingCrafted[id] = self + self:SetCraftingID(id) + for k,v in pairs(self.ValidItems) do + if v != id then + self.ValidItems[k] = nil -- Remove all non-valids now + end + end + + if IsValid(self.CraftedModel) then self.CraftedModel:Remove() end + + local tbl = self:GetCraftTable(id) + if tbl and tbl.model then + self.CraftedModel = ents.Create("buildable_table_prop") + self.CraftedModel:SetWorkbench(self) + self.CraftedModel:SetModel(tbl.model) + self.CraftedModel:SetPos(self:GetPos() + tbl.pos) + self.CraftedModel:SetAngles(self:GetAngles() + tbl.ang) + for i = 0, (#self.CraftedModel:GetMaterials()-1) do + self.CraftedModel:SetSubMaterial(i, "color") -- Invisible + end + self.CraftedModel:SetMoveType(MOVETYPE_NONE) + self.CraftedModel:SetCollisionGroup(COLLISION_GROUP_DEBRIS_TRIGGER) + self.CraftedModel:Spawn() + self:SetCompletedText(tbl.text or "Workbench") + end +end + +function ENT:AddPart(item, ply) + if !self.Crafting then + self:SetCraftedItem(self.ValidItems[item]) -- Set targeted ID to what this item belongs to + self:SetWIP(true) + end + local tbl = self:GetCraftTable() + local part = tbl.parts[item] + if part then + for k,v in pairs(part) do + self.CraftedModel:SetSubMaterial(v, "") -- Visible again + end + if tbl.partadded then tbl.partadded(self, item, ply) end + self.ValidItems[item] = nil -- No longer valid here! + end + if table.Count(self.ValidItems) <= 0 then + self:FinishCrafting() + end +end + +function ENT:FinishCrafting() + self:SetWIP(false) + self:SetCompleted(true) + + local tbl = self:GetCraftTable() + if tbl.finishfunc then tbl.finishfunc(self) end +end + +function ENT:GetCraftTable(id) + if !self.Craftables then self.Craftables = {} end + return id and self.Craftables[id] or self.Craftables[self.Crafting] +end + +function ENT:StartTimedUse(ply) -- This function makes the entity use progress-based using instead of normal + if IsValid(ply) then + if self:GetCompleted() then + local tbl = self:GetCraftTable() + if tbl and tbl.usefunc then + tbl.usefunc(self, ply) -- Here it doesn't return a time; it becomes instant use + end + else + local id, item = self:CanPlayerCraft(ply) + if id and item then + ply:Give("nz_packapunch_arms") -- For the animation + return 2.5 -- We only return here, other cases it doesn't even use time + end + end + end + -- In no case there's no time either; instant use (doing nothing) +end +function ENT:StopTimedUse(ply) + ply:SetUsingSpecialWeapon(false) + ply:StripWeapon("nz_packapunch_arms") + ply:EquipPreviousWeapon() +end +function ENT:FinishTimedUse(ply) + if IsValid(ply) then + if !self:GetCompleted() then -- We do nothing if he can no longer craft + local id, item = self:CanPlayerCraft(ply) + if id and item then + self:AddPart(item) + ply:RemoveCarryItem(item) + end + end + end +end + +function ENT:OnRemove() + if IsValid(self.CraftedModel) then self.CraftedModel:Remove() end +end + +if CLIENT then + + function ENT:GetNZTargetText() + if self:GetCompleted() then + return self:GetCompletedText() + elseif self:GetWIP() then + return "Workbench ("..self:GetCraftingID()..")" + else + return "Workbench" + end + end + +end diff --git a/gamemodes/nzombies/entities/entities/buildable_table_prop/shared.lua b/gamemodes/nzombies/entities/entities/buildable_table_prop/shared.lua new file mode 100644 index 00000000..d7129119 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/buildable_table_prop/shared.lua @@ -0,0 +1,40 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "buildable_table_prop" +ENT.Author = "Zet0r" +ENT.Contact = "youtube.com/Zet0r" +ENT.Purpose = "Scriptable prop for nZombies" +ENT.Instructions = "" + +function ENT:SetupDataTables() + self:NetworkVar( "Entity", 0, "Workbench" ) +end + +function ENT:Initialize() + if SERVER then + --if !IsValid(self.Table) then self:Remove() end + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + --self:DrawShadow( false ) + self:SetUseType( SIMPLE_USE ) + self.RelayUse = self:GetWorkbench() + end +end + +function ENT:Use(arg1, arg2, arg3, arg4) + local tbl = self:GetWorkbench() + if IsValid(tbl) then + tbl:Use(arg1, arg2, arg3, arg4) -- Relay info + end +end + +if CLIENT then + function ENT:GetNZTargetText() + local tbl = self:GetWorkbench() + if IsValid(tbl) then + return tbl:GetNZTargetText() -- Relay info + end + end +end \ No newline at end of file diff --git a/nzombies3/entities/entities/button_elec/shared.lua b/gamemodes/nzombies/entities/entities/button_elec/shared.lua similarity index 87% rename from nzombies3/entities/entities/button_elec/shared.lua rename to gamemodes/nzombies/entities/entities/button_elec/shared.lua index bef56b5a..91c2b59f 100644 --- a/nzombies3/entities/entities/button_elec/shared.lua +++ b/gamemodes/nzombies/entities/entities/button_elec/shared.lua @@ -29,9 +29,9 @@ end function ENT:Use( activator ) if ( !activator:IsPlayer() ) then return end - if !IsElec() and (nz.Rounds.Data.CurrentState == ROUND_PREP or nz.Rounds.Data.CurrentState == ROUND_PROG) then + if !IsElec() and nzRound:InProgress() then self:SetSwitch(true) - nz.Elec.Functions.Activate() + nz.nzElec.Functions.Activate() end end diff --git a/gamemodes/nzombies/entities/entities/drop_bloodmoney/shared.lua b/gamemodes/nzombies/entities/entities/drop_bloodmoney/shared.lua new file mode 100644 index 00000000..711effb9 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/drop_bloodmoney/shared.lua @@ -0,0 +1,86 @@ +AddCSLuaFile() + +ENT.Type = "anim" + +ENT.PrintName = "drop_powerups" +ENT.Author = "Alig96" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + + self:NetworkVar( "String", 0, "Points" ) + +end + +function ENT:Initialize() + + self:SetModel("models/nzpowerups/bloodmoney.mdl") + --self:PhysicsInit(SOLID_VPHYSICS) + self:PhysicsInitSphere(60, "default_silent") + self:SetMoveType(MOVETYPE_NONE) + self:SetSolid(SOLID_NONE) + if SERVER then + self:SetTrigger(true) + self:SetUseType(SIMPLE_USE) + else + self.NextParticle = CurTime() + end + self:UseTriggerBounds(true, 0) + self:SetMaterial("models/shiny.vtf") + self:SetColor( Color(255,200,0) ) + --self:SetTrigger(true) + + --[[timer.Create( self:EntIndex().."_deathtimer", 30, 1, function() + if IsValid(self) then + timer.Destroy(self:EntIndex().."_deathtimer") + if SERVER then + self:Remove() + end + end + end)]] + + self.RemoveTime = CurTime() + 30 +end + +if SERVER then + function ENT:StartTouch(hitEnt) + if (hitEnt:IsValid() and hitEnt:IsPlayer()) then + hitEnt:GivePoints(self:GetPoints()) + self:Remove() + end + end + + function ENT:Think() + if self.RemoveTime and CurTime() > self.RemoveTime then + self:Remove() + end + end +end + +if CLIENT then + --local glow = Material ( "sprites/glow04_noz" ) + --local col = Color(0,200,255,255) + + local particledelay = 0.1 + + function ENT:Draw() + if CurTime() > self.NextParticle then + local effectdata = EffectData() + effectdata:SetOrigin( self:GetPos() ) + util.Effect( "powerup_glow", effectdata ) + self.NextParticle = CurTime() + particledelay + end + self:DrawModel() + end + + function ENT:Think() + if !self:GetRenderAngles() then self:SetRenderAngles(self:GetAngles()) end + self:SetRenderAngles(self:GetRenderAngles()+(Angle(0,50,0)*FrameTime())) + end + + --[[hook.Add( "PreDrawHalos", "drop_powerups_halos", function() + halo.Add( ents.FindByClass( "drop_powerup" ), Color( 0, 255, 0 ), 2, 2, 2 ) + end )]] +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/drop_powerup/shared.lua b/gamemodes/nzombies/entities/entities/drop_powerup/shared.lua new file mode 100644 index 00000000..10d8bacf --- /dev/null +++ b/gamemodes/nzombies/entities/entities/drop_powerup/shared.lua @@ -0,0 +1,87 @@ +AddCSLuaFile() + +ENT.Type = "anim" + +ENT.PrintName = "drop_powerups" +ENT.Author = "Alig96" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + + self:NetworkVar( "String", 0, "PowerUp" ) + +end + +function ENT:Initialize() + + //self:SetPowerUp("dp") + self:SetModelScale(nzPowerUps:Get(self:GetPowerUp()).scale, 0) + + --self:PhysicsInit(SOLID_VPHYSICS) + self:PhysicsInitSphere(60, "default_silent") + self:SetMoveType(MOVETYPE_NONE) + self:SetSolid(SOLID_NONE) + if SERVER then + self:SetTrigger(true) + self:SetUseType(SIMPLE_USE) + else + self.NextParticle = CurTime() + end + self:UseTriggerBounds(true, 0) + self:SetMaterial("models/shiny.vtf") + self:SetColor( Color(255,200,0) ) + --self:SetTrigger(true) + + --[[timer.Create( self:EntIndex().."_deathtimer", 30, 1, function() + if IsValid(self) then + timer.Destroy(self:EntIndex().."_deathtimer") + if SERVER then + self:Remove() + end + end + end)]] + self.RemoveTime = CurTime() + 30 +end + +if SERVER then + function ENT:StartTouch(hitEnt) + if (hitEnt:IsValid() and hitEnt:IsPlayer()) then + nzPowerUps:Activate(self:GetPowerUp(), hitEnt, self) + self:Remove() + end + end + + function ENT:Think() + if self.RemoveTime and CurTime() > self.RemoveTime then + self:Remove() + end + end +end + +if CLIENT then + --local glow = Material ( "sprites/glow04_noz" ) + --local col = Color(0,200,255,255) + + local particledelay = 0.1 + + function ENT:Draw() + if CurTime() > self.NextParticle then + local effectdata = EffectData() + effectdata:SetOrigin( self:GetPos() ) + util.Effect( "powerup_glow", effectdata ) + self.NextParticle = CurTime() + particledelay + end + self:DrawModel() + end + + function ENT:Think() + if !self:GetRenderAngles() then self:SetRenderAngles(self:GetAngles()) end + self:SetRenderAngles(self:GetRenderAngles()+(Angle(0,50,0)*FrameTime())) + end + + --[[hook.Add( "PreDrawHalos", "drop_powerups_halos", function() + halo.Add( ents.FindByClass( "drop_powerup" ), Color( 0, 255, 0 ), 2, 2, 2 ) + end )]] +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/drop_tombstone/shared.lua b/gamemodes/nzombies/entities/entities/drop_tombstone/shared.lua new file mode 100644 index 00000000..37035f60 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/drop_tombstone/shared.lua @@ -0,0 +1,107 @@ +AddCSLuaFile() + +ENT.Type = "anim" + +ENT.PrintName = "drop_tombstone" +ENT.Author = "Zet0r" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + + self:NetworkVar( "Entity", 0, "PerkOwner" ) + +end + +function ENT:Initialize() + + self:SetModel("models/props_c17/gravestone003a.mdl") + + --self:PhysicsInit(SOLID_VPHYSICS) + self:PhysicsInitSphere(60, "default_silent") + self:SetMoveType(MOVETYPE_NONE) + self:SetSolid(SOLID_NONE) + if SERVER then + self:SetTrigger(true) + end + self:UseTriggerBounds(true, 0) + self:DrawShadow(false) + self:SetMaterial("models/shiny.vtf") + self:SetColor( Color(255,200,0) ) + + self.OwnerData = {} + + if SERVER then + self:SetUseType(SIMPLE_USE) + end + + --[[timer.Create( self:EntIndex().."_deathtimer", 100, 1, function() + if self:IsValid() then + timer.Destroy(self:EntIndex().."_deathtimer") + if SERVER then + self:Remove() + end + end + end)]] + + --self.RemoveTime = CurTime() + 120 +end + +if SERVER then + function ENT:StartTouch(hitEnt) + --print("Collided") + if (IsValid(hitEnt) and hitEnt:IsPlayer() and hitEnt == self:GetPerkOwner()) then + --PrintTable(self.OwnerData) + + -- Weapons are completely replaced + hitEnt:StripWeapons() + for k,v in pairs(self.OwnerData.weps) do + local wep = hitEnt:Give(v.class) + if v.pap then + wep:ApplyNZModifier("pap") + end + end + for k,v in pairs(self.OwnerData.perks) do + if v != "tombstone" then + hitEnt:GivePerk(v) + end + end + hitEnt:GiveMaxAmmo() + + --timer.Destroy(self:EntIndex().."_deathtimer") + self:Remove() + end + end + + function ENT:Think() + if !self.RemoveTime then + local ply = self:GetPerkOwner() + if IsValid(ply) then + if ply:Alive() and ply:GetNotDowned() and (ply:IsPlaying() or ply:IsInCreative()) then + self.RemoveTime = CurTime() + 90 + end + else + -- Man, the player must've disconnected or crashed :/ + self:Remove() + end + elseif self.RemoveTime and CurTime() > self.RemoveTime then + self:Remove() + end + end +end + +if CLIENT then + function ENT:Draw() + self:DrawModel() + end + + function ENT:Think() + if !self:GetRenderAngles() then self:SetRenderAngles(self:GetAngles()) end + self:SetRenderAngles(self:GetRenderAngles()+(Angle(0,50,0)*FrameTime())) + end + + hook.Add( "PreDrawHalos", "drop_powerups_halos", function() + halo.Add( ents.FindByClass( "drop_powerup" ), Color( 0, 255, 0 ), 2, 2, 2 ) + end ) +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/drop_vulture/shared.lua b/gamemodes/nzombies/entities/entities/drop_vulture/shared.lua new file mode 100644 index 00000000..aa0e0fdb --- /dev/null +++ b/gamemodes/nzombies/entities/entities/drop_vulture/shared.lua @@ -0,0 +1,150 @@ +AddCSLuaFile() + +ENT.Type = "anim" + +ENT.PrintName = "drop_vulture" +ENT.Author = "Zet0r" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + + self:NetworkVar( "String", 0, "DropType" ) + +end + +local vulturedrops = { + ["points"] = { + id = "points", + model = Model("models/props_junk/garbage_bag001a.mdl"), + effect = function(ply) + ply:GivePoints(math.random(5,20)) + return true + end, + timer = 30, + draw = function(self) + self:DrawModel() + end, + initialize = function(self) + + end, + }, + ["ammo"] = { + id = "ammo", + model = Model("models/items/357ammo.mdl"), + effect = function(ply) + local wep = ply:GetActiveWeapon() + if IsValid(wep) then + local max = nzWeps:CalculateMaxAmmo(wep:GetClass()) + local give = max/math.Rand(9,11) + local ammo = wep.Primary.Ammo + local cur = ply:GetAmmoCount(ammo) + + --print(give, max, cur) + + if cur + give > max then give = max - cur end + if give <= 0 then return false end + ply:GiveAmmo(give, ammo) + return true + end + end, + timer = 30, + draw = function(self) + self:DrawModel() + end, + initialize = function(self) + + end, + }, + ["gas"] = { + id = "gas", + model = Model(""), + effect = function(ply) + ply:SetTargetPriority(TARGET_PRIORITY_NONE) + timer.Simple(3, function() + if IsValid(ply) then + ply:SetDefaultTargetPriority() + end + end) + end, + timer = 5, + draw = function(self) + + end, + initialize = function(self) + local sfx = EffectData() + sfx:SetOrigin(self:GetPos()) + util.Effect("vulture_gascloud",sfx) + end, + }, +} + +function ENT:Initialize() + + -- Random chance of any + if SERVER then + self:SetDropType(table.Random(vulturedrops).id) + end + self:SetModel(vulturedrops[self:GetDropType()].model) + + self:PhysicsInitSphere(60, "default_silent") + self:SetMoveType(MOVETYPE_NONE) + self:SetSolid(SOLID_NONE) + if SERVER then + self:SetTrigger(true) + self:SetUseType(SIMPLE_USE) + end + self:UseTriggerBounds(true, 0) + self:SetMaterial("models/shiny.vtf") + self:SetColor( Color(255,200,0) ) + self:DrawShadow(false) + self.DeathTimer = 30 + + --[[timer.Create( self:EntIndex().."_deathtimer", vulturedrops[self:GetDropType()].timer, 1, function() + if IsValid(self) then + timer.Destroy(self:EntIndex().."_deathtimer") + if SERVER then + self:Remove() + end + end + end)]] + + self.RemoveTime = CurTime() + vulturedrops[self:GetDropType()].timer + + vulturedrops[self:GetDropType()].initialize(self) +end + +if SERVER then + function ENT:StartTouch(hitEnt) + if (hitEnt:IsValid() and hitEnt:IsPlayer()) then + if hitEnt:HasPerk("vulture") then + -- The return value indicate whether to consume the drop or not + if vulturedrops[self:GetDropType()].effect(hitEnt) then + self:Remove() + end + end + end + end + + function ENT:Think() + if self.RemoveTime and CurTime() > self.RemoveTime then + self:Remove() + end + end +end + +if CLIENT then + function ENT:Draw() + vulturedrops[self:GetDropType()].draw(self) + end + + function ENT:Think() + if !self:GetRenderAngles() then self:SetRenderAngles(self:GetAngles()) end + self:SetRenderAngles(self:GetRenderAngles()+(Angle(0,50,0)*FrameTime())) + end + + hook.Add( "PreDrawHalos", "drop_powerups_halos", function() + halo.Add( ents.FindByClass( "drop_powerup" ), Color( 0, 255, 0 ), 2, 2, 2 ) + end ) +end diff --git a/gamemodes/nzombies/entities/entities/easter_egg/shared.lua b/gamemodes/nzombies/entities/entities/easter_egg/shared.lua new file mode 100644 index 00000000..0ffeb312 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/easter_egg/shared.lua @@ -0,0 +1,34 @@ +ENT.Type = "anim" + +ENT.PrintName = "easter_egg" +ENT.Author = "Alig96" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + + +AddCSLuaFile() + + + +function ENT:Initialize() + + self:SetModel( "models/props_lab/huladoll.mdl" ) + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + self:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + self.Used = false + if SERVER then + self:SetUseType(SIMPLE_USE) + end +end + +function ENT:Use( activator, caller ) + if !self.Used and nzRound:InProgress() then + nzEE:ActivateEgg( self, activator ) + end +end + +function ENT:Draw() + self:DrawModel() +end diff --git a/gamemodes/nzombies/entities/entities/edit_color.lua b/gamemodes/nzombies/entities/entities/edit_color.lua new file mode 100644 index 00000000..e15944b8 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/edit_color.lua @@ -0,0 +1,86 @@ + +AddCSLuaFile() +DEFINE_BASECLASS( "base_edit" ) + +ENT.Spawnable = true +ENT.AdminOnly = true + +ENT.PrintName = "Color Correction Editor" +ENT.Category = "Editors" + +ENT.NZOnlyVisibleInCreative = true + +function ENT:Initialize() + + BaseClass.Initialize( self ) + + --self:SetMaterial( Material("gmod/demo.png", "noclamp smooth") ) + + -- There can only be one! + if IsValid(ents.FindByClass("edit_color")[1]) and ents.FindByClass("edit_color")[1] != self then ents.FindByClass("edit_color")[1]:Remove() end + + if ( CLIENT ) then + hook.Add( "RenderScreenspaceEffects", self, self.DrawColorCorretion ) + end + +end + +function ENT:SetupDataTables() + + self:NetworkVar( "Float", 0, "AddRed", { KeyName = "addred", Edit = { type = "Float", min = -1, max = 1, order = 1 } } ); + self:NetworkVar( "Float", 1, "AddGreen", { KeyName = "addgreen", Edit = { type = "Float", min = -1, max = 1, order = 2 } } ); + self:NetworkVar( "Float", 2, "AddBlue", { KeyName = "addblue", Edit = { type = "Float", min = -1, max = 1, order = 3 } } ); + + self:NetworkVar( "Float", 3, "Brightness", { KeyName = "brightness", Edit = { type = "Float", min = -2, max = 2, order = 4 } } ); + self:NetworkVar( "Float", 4, "Contrast", { KeyName = "contrast", Edit = { type = "Float", min = 0, max = 2, order = 5 } } ); + self:NetworkVar( "Float", 5, "Colour", { KeyName = "colour", Edit = { type = "Float", min = -10, max = 10, order = 6 } } ); + + self:NetworkVar( "Float", 6, "MulRed", { KeyName = "mulred", Edit = { type = "Float", min = -1, max = 1, order = 7 } } ); + self:NetworkVar( "Float", 7, "MulGreen", { KeyName = "mulgreen", Edit = { type = "Float", min = -1, max = 1, order = 8 } } ); + self:NetworkVar( "Float", 8, "MulBlue", { KeyName = "mulblue", Edit = { type = "Float", min = -1, max = 1, order = 9 } } ); + + -- + -- TODO: Should skybox fog be edited seperately? + -- + + if ( SERVER ) then + + -- defaults + self:SetAddRed( 0.0 ) + self:SetAddGreen( 0.0 ) + self:SetAddBlue( 0.05 ) + + self:SetBrightness( 0 ) + self:SetContrast( 1.2 ) + self:SetColour( 2 ) + + self:SetMulRed( 0 ) + self:SetMulGreen( 0 ) + self:SetMulBlue( 0.02 ) + + end + +end + +function ENT:DrawColorCorretion() + local tbl = { + [ "$pp_colour_addr" ] = self:GetAddRed(), + [ "$pp_colour_addg" ] = self:GetAddGreen(), + [ "$pp_colour_addb" ] = self:GetAddGreen(), + [ "$pp_colour_brightness" ] = self:GetBrightness(), + [ "$pp_colour_contrast" ] = self:GetContrast(), + [ "$pp_colour_colour" ] = self:GetColour(), + [ "$pp_colour_mulr" ] = self:GetMulRed(), + [ "$pp_colour_mulg" ] = self:GetMulGreen(), + [ "$pp_colour_mulb" ] = self:GetMulBlue() + } + + DrawColorModify(tbl) +end + +-- +-- This edits something global - so always network - even when not in PVS +-- +function ENT:UpdateTransmitState() + return TRANSMIT_ALWAYS +end diff --git a/gamemodes/nzombies/entities/entities/edit_damage.lua b/gamemodes/nzombies/entities/entities/edit_damage.lua new file mode 100644 index 00000000..0038354a --- /dev/null +++ b/gamemodes/nzombies/entities/entities/edit_damage.lua @@ -0,0 +1,193 @@ + +AddCSLuaFile() +ENT.Type = "anim" + +ENT.PrintName = "" +ENT.Author = "" +ENT.Contact = "" +ENT.Purpose = "" +ENT.Instructions = "" +ENT.Spawnable = false +ENT.AdminOnly = false +ENT.Editable = true + +ENT.PrintName = "Radiation" +ENT.Category = "Editors" + +ENT.NZOnlyVisibleInCreative = true + +function ENT:Initialize() + + --BaseClass.Initialize( self ) + + -- Set it up just like a prop_effect + local Radius = 6 + local min = Vector( 1, 1, 1 ) * Radius * -0.5 + local max = Vector( 1, 1, 1 ) * Radius * 0.5 + + if ( SERVER ) then + + self:SetModel( "models/props_junk/watermelon01.mdl" ) + + -- Don't use the model's physics - create a box instead + self:PhysicsInitBox(min, max) + + -- Set up our physics object here + local phys = self:GetPhysicsObject() + if ( IsValid( phys ) ) then + phys:Wake() + phys:EnableGravity( false ) + phys:EnableDrag( false ) + end + + self:DrawShadow( false ) + self:SetCollisionGroup( COLLISION_GROUP_DEBRIS_TRIGGER ) + + --self:SetTrigger(true) + + else + + self.GripMaterial = Material( "sprites/grip" ) + + end + + self.NextDamage = 0 + + -- Set collision bounds exactly + self:SetCollisionBounds( min, max ) + +end + +function ENT:Draw() + + if !nzRound:InState( ROUND_CREATE ) then return end + + -- Don't draw the grip if there's no chance of us picking it up + local ply = LocalPlayer() + local wep = ply:GetActiveWeapon() + if ( !IsValid( wep ) ) then return end + + local weapon_name = wep:GetClass() + + if ( weapon_name != "weapon_physgun" && weapon_name != "weapon_physcannon" && weapon_name != "gmod_tool" ) then + return + end + + render.SetMaterial( self.GripMaterial ) + render.DrawSprite( self:GetPos(), 16, 16, color_white ) + +end + +function ENT:PhysicsUpdate( physobj ) + + if ( CLIENT ) then return end + + -- Don't do anything if the player isn't holding us + if ( !self:IsPlayerHolding() && !self:IsConstrained() ) then + + physobj:SetVelocity( Vector( 0, 0, 0 ) ) + physobj:Sleep() + + end + +end + +function ENT:OnRemove() + +end + + +function ENT:SetupDataTables() + + self:NetworkVar( "Bool", 0, "On", { KeyName = "on", Edit = { type = "Boolean", order = 1 } } ); + self:NetworkVar( "Int", 0, "Radius", { KeyName = "radius", Edit = { type = "Int", min = 0, max = 1000, order = 2 } } ); + self:NetworkVar( "Int", 1, "Damage", { KeyName = "damage", Edit = { type = "Int", min = 0, max = 250, order = 3 } } ); + self:NetworkVar( "Float", 0, "Delay", { KeyName = "delay", Edit = { type = "Float", min = 0, max = 10, order = 4 } } ); + self:NetworkVar( "Bool", 1, "Tesla", { KeyName = "tesla", Edit = { type = "Boolean", order = 5 } } ); + self:NetworkVar( "Bool", 2, "Poison", { KeyName = "poison", Edit = { type = "Boolean", order = 6 } } ); + self:NetworkVar( "Bool", 3, "Radiation", { KeyName = "radiation", Edit = { type = "Boolean", order = 7 } } ); + + if SERVER then + self:NetworkVarNotify("Radius", self.OnRadiusChanged) + + self:SetOn(true) + self:SetRadius(50) + self:SetDamage(1) + self:SetDelay(0.1) + self:SetTesla(false) + self:SetPoison(false) + self:SetRadiation(false) + end + +end + +function ENT:OnRadiusChanged(name, old, new) + self:UseTriggerBounds(true, new) + print("Trigger bounds changed to ".. new) +end + +function ENT:StartTouch(ent) + print("Start", ent) +end + +function ENT:Touch(ent) + print("Touch", ent) +end + +function ENT:EndTouch(ent) + print("End", ent) +end + +function ENT:Think() + + local ct = CurTime() + + if ct > self.NextDamage then + if self:GetOn() then + if SERVER then + local dmg = DamageInfo() + dmg:SetAttacker(self) + dmg:SetDamage(self:GetDamage()) + dmg:SetDamageType(DMG_RADIATION) + dmg:SetDamageForce(Vector(0,0,0)) + dmg:SetDamagePosition(self:GetPos()) + + for k,v in pairs(ents.FindInSphere(self:GetPos(), self:GetRadius())) do + if IsValid(v) and v:IsPlayer() and v:GetNotDowned() then + v:TakeDamageInfo(dmg) + end + end + else + local e = EffectData() + e:SetMagnitude(1.1) + e:SetScale(1.5) + for k,v in pairs(ents.FindInSphere(self:GetPos(), self:GetRadius())) do + if IsValid(v) and v:IsPlayer() and v:GetNotDowned() then + local islocal = v == LocalPlayer() + if self:GetTesla() then + if !v.LightningAura or v.LightningAura < ct then + e:SetEntity(v) + util.Effect("lightning_aura", e) + end + if islocal then + surface.PlaySound("weapons/physcannon/superphys_small_zap" .. math.random(1,4) .. ".wav") + end + v.LightningAura = ct + 1 + end + if islocal and self:GetRadiation() then + surface.PlaySound("player/geiger" .. math.random(1,3) .. ".wav") + end + end + end + end + end + + self.NextDamage = ct + self:GetDelay() + end + +end + +function ENT:UpdateTransmitState() + return TRANSMIT_PVS +end + diff --git a/gamemodes/nzombies/entities/entities/edit_dynlight.lua b/gamemodes/nzombies/entities/entities/edit_dynlight.lua new file mode 100644 index 00000000..04e4a617 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/edit_dynlight.lua @@ -0,0 +1,115 @@ + +AddCSLuaFile() +DEFINE_BASECLASS( "base_edit" ) + +ENT.Spawnable = true +ENT.AdminOnly = true + +ENT.PrintName = "Dynamic Light" +ENT.Category = "Editors" + +function ENT:Initialize() + + BaseClass.Initialize( self ) + + --self:SetMaterial( Material("gmod/demo.png", "noclamp smooth") ) + + local Radius = 6 + local min = Vector( 1, 1, 1 ) * Radius * -0.5 + local max = Vector( 1, 1, 1 ) * Radius * 0.5 + + if ( SERVER ) then + + self:SetModel( "models/props_junk/watermelon01.mdl" ) + + -- Don't use the model's physics - create a box instead + self:PhysicsInitBox( min, max ) + + -- Set up our physics object here + local phys = self:GetPhysicsObject() + if ( IsValid( phys ) ) then + phys:Wake() + phys:EnableGravity( false ) + phys:EnableDrag( false ) + end + + self:DrawShadow( false ) + self:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + else + + self.GripMaterial = Material( "sprites/grip" ) + + -- Get the attached entity so that clientside functions like properties can interact with it + local tab = ents.FindByClassAndParent( "prop_dynamic", self ) + if ( tab && IsValid( tab[ 1 ] ) ) then self.AttachedEntity = tab[ 1 ] end + + end + +end + +function ENT:SetupDataTables() + + self:NetworkVar( "Int", 0, "Brightness", { KeyName = "brightness", Edit = { type = "Int", min = 0, max = 5, order = 1 } } ) + self:NetworkVar( "Vector", 0, "LightColor", { KeyName = "color", Edit = { type = "VectorColor", order = 2 } } ) + self:NetworkVar( "Int", 1, "Size", { KeyName = "size", Edit = { type = "Int", min = 0, max = 1000, order = 3 } } ) + + self:NetworkVar( "Int", 2, "Style", { KeyName = "style", Edit = { type = "Int", min = 0, max = 12, order = 4 } } ) + + self:NetworkVar( "Bool", 0, "Elec", { KeyName = "electricity", Edit = { type = "Boolean" } } ) + + if ( SERVER ) then + + -- defaults + self:SetLightColor( Vector(1, 1, 1) ) -- White + self:SetBrightness( 2 ) + self:SetSize(256) + self:SetStyle(0) -- Standard bright all the time + self:SetElec(false) + + end + +end + +if CLIENT then + function ENT:Draw() + if !self:GetElec() or nzElec.Active then + local size = self:GetSize() + if !self.LightSize or self.LightSize != size then + self:SetRenderBounds(Vector(-size, -size, -size), Vector(size, size, size)) + self.LightSize = size + end + local color = self:GetLightColor() * 255 + local brightness = self:GetBrightness() + local style = self:GetStyle() + local dlight = DynamicLight( self:EntIndex() ) + if ( dlight ) then + dlight.pos = self:GetPos() + dlight.r = color[1] + dlight.g = color[2] + dlight.b = color[3] + dlight.brightness = brightness + dlight.Decay = 1000 + dlight.Size = size + dlight.DieTime = CurTime() + 1 + dlight.Style = style + end + end + + if !nzRound:InState( ROUND_CREATE ) then return end + + -- Don't draw the grip if there's no chance of us picking it up + local ply = LocalPlayer() + local wep = ply:GetActiveWeapon() + if ( !IsValid( wep ) ) then return end + + local weapon_name = wep:GetClass() + + if ( weapon_name != "weapon_physgun" && weapon_name != "weapon_physcannon" && weapon_name != "gmod_tool" ) then + return + end + + render.SetMaterial( self.GripMaterial ) + render.DrawSprite( self:GetPos(), 16, 16, color_white ) + end +end diff --git a/gamemodes/nzombies/entities/entities/edit_fog.lua b/gamemodes/nzombies/entities/entities/edit_fog.lua new file mode 100644 index 00000000..88c760f3 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/edit_fog.lua @@ -0,0 +1,58 @@ + +AddCSLuaFile() +DEFINE_BASECLASS( "base_edit" ) + +ENT.Spawnable = true +ENT.AdminOnly = true + +ENT.PrintName = "Fog Editor" +ENT.Category = "Editors" + +ENT.NZOnlyVisibleInCreative = true + +function ENT:Initialize() + + BaseClass.Initialize( self ) + + self:SetMaterial( "gmod/edit_fog" ) + + -- There can only be one! + if IsValid(ents.FindByClass("edit_fog")[1]) and ents.FindByClass("edit_fog")[1] != self then ents.FindByClass("edit_fog")[1]:Remove() end + + if ( CLIENT ) then + nzRound:EnableSpecialFog( false ) + end + +end + +function ENT:SetupDataTables() + + self:NetworkVar( "Float", 0, "FogStart", { KeyName = "fogstart", Edit = { type = "Float", min = 0, max = 100000, order = 1 } } ); + self:NetworkVar( "Float", 1, "FogEnd", { KeyName = "fogend", Edit = { type = "Float", min = 0, max = 100000, order = 2 } } ); + self:NetworkVar( "Float", 2, "Density", { KeyName = "density", Edit = { type = "Float", min = 0, max = 1, order = 3 } } ); + + self:NetworkVar( "Vector", 0, "FogColor", { KeyName = "fogcolor", Edit = { type = "VectorColor", order = 3 } } ); + + -- + -- TODO: Should skybox fog be edited seperately? + -- + + if ( SERVER ) then + + -- defaults + self:SetFogStart( 0.0 ) + self:SetFogEnd( 10000 ) + self:SetDensity( 0.9 ) + self:SetFogColor( Vector( 0.6, 0.7, 0.8 ) ) + + end + +end + +-- +-- This edits something global - so always network - even when not in PVS +-- +function ENT:UpdateTransmitState() + + return TRANSMIT_ALWAYS +end diff --git a/gamemodes/nzombies/entities/entities/edit_fog_special.lua b/gamemodes/nzombies/entities/entities/edit_fog_special.lua new file mode 100644 index 00000000..8682706e --- /dev/null +++ b/gamemodes/nzombies/entities/entities/edit_fog_special.lua @@ -0,0 +1,60 @@ + +AddCSLuaFile() +DEFINE_BASECLASS( "base_edit" ) + +ENT.Spawnable = false +ENT.AdminOnly = false + +ENT.PrintName = "Fog Editor for Special Rounds" +ENT.Category = "Editors" + +ENT.NZOnlyVisibleInCreative = true + +function ENT:Initialize() + + BaseClass.Initialize( self ) + + self:SetMaterial( "gmod/edit_fog" ) + + -- There can only be one! + if IsValid(ents.FindByClass("edit_fog_special")[1]) and ents.FindByClass("edit_fog_special")[1] != self then ents.FindByClass("edit_fog_special")[1]:Remove() end + + if ( CLIENT ) then + if nzRound:InState( ROUND_CREATE ) or nzRound:IsSpecial() then + --self:HookFogHooks() + end + end + +end + +function ENT:SetupDataTables() + + self:NetworkVar( "Float", 0, "FogStart", { KeyName = "fogstart", Edit = { type = "Float", min = 0, max = 100000, order = 1 } } ); + self:NetworkVar( "Float", 1, "FogEnd", { KeyName = "fogend", Edit = { type = "Float", min = 0, max = 100000, order = 2 } } ); + self:NetworkVar( "Float", 2, "Density", { KeyName = "density", Edit = { type = "Float", min = 0, max = 1, order = 3 } } ); + + self:NetworkVar( "Vector", 0, "FogColor", { KeyName = "fogcolor", Edit = { type = "VectorColor", order = 3 } } ); + + -- + -- TODO: Should skybox fog be edited seperately? + -- + + if ( SERVER ) then + + -- defaults + self:SetFogStart( 0.0 ) + self:SetFogEnd( 10000 ) + self:SetDensity( 0.9 ) + self:SetFogColor( Vector( 0.6, 0.7, 0.8 ) ) + + end + +end + +-- +-- This edits something global - so always network - even when not in PVS +-- +function ENT:UpdateTransmitState() + + return TRANSMIT_ALWAYS +end diff --git a/gamemodes/nzombies/entities/entities/edit_sky.lua b/gamemodes/nzombies/entities/entities/edit_sky.lua new file mode 100644 index 00000000..60c424e3 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/edit_sky.lua @@ -0,0 +1,102 @@ + +AddCSLuaFile() +DEFINE_BASECLASS( "base_edit" ) + +ENT.Spawnable = true +ENT.AdminOnly = true + +ENT.PrintName = "Sky Editor" +ENT.Category = "Editors" + +local oldsky + +ENT.NZOnlyVisibleInCreative = true + +function ENT:Initialize() + + BaseClass.Initialize( self ) + self:SetMaterial( "gmod/edit_sky" ) + + + + -- + -- Over-ride the sky controller with this. + -- + if ( CLIENT ) then + + if ( IsValid( g_SkyPaint ) ) then + -- TODO: Copy settings from `current` sky to here. + end + + g_SkyPaint = self + else + + if !oldsky then oldsky = GetConVar("sv_skyname"):GetString() end + print(oldsky) + RunConsoleCommand("sv_skyname", "painted") + if !IsValid(ents.FindByClass("env_skypaint")[1]) then + local ent = ents.Create("env_skypaint") + ent:Spawn() + end + + end + +end + +function ENT:Think() + + -- + -- Find an env_sun - if we don't already have one. + -- + if ( SERVER && self.EnvSun == nil ) then + + -- so this closure only gets called once - even if it fails + self.EnvSun = false; + + local list = ents.FindByClass( "env_sun" ) + if ( #list > 0 ) then + self.EnvSun = list[1] + end + + end + + -- + -- If we have a sun - force our sun normal to its value + -- + if ( SERVER && IsValid( self.EnvSun ) ) then + + local vec = self.EnvSun:GetInternalVariable( "m_vDirection" ); + + if ( isvector( vec ) ) then + self:SetSunNormal( vec ) + end + + end + +end + +-- +-- This needs to be a 1:1 copy of env_skypaint +-- +function ENT:SetupDataTables() + + local SetupDataTables = scripted_ents.GetMember( "env_skypaint", "SetupDataTables" ) + SetupDataTables( self ) + +end + +function ENT:OnRemove() + if SERVER then + if oldsky and #ents.FindByClass("edit_sky") <= 0 then + RunConsoleCommand("sv_skyname", oldsky) + end + end +end + +-- +-- This edits something global - so always network - even wjen not in PVS +-- +function ENT:UpdateTransmitState() + + return TRANSMIT_ALWAYS +end diff --git a/gamemodes/nzombies/entities/entities/edit_sun.lua b/gamemodes/nzombies/entities/entities/edit_sun.lua new file mode 100644 index 00000000..5d4ed9f1 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/edit_sun.lua @@ -0,0 +1,104 @@ + +AddCSLuaFile() +DEFINE_BASECLASS( "base_edit" ) + +ENT.Spawnable = true +ENT.AdminOnly = true + +ENT.PrintName = "Sun Editor" +ENT.Category = "Editors" + +ENT.NZOnlyVisibleInCreative = true + +function ENT:Initialize() + + BaseClass.Initialize( self ) + self:EnableForwardArrow() + + self:SetMaterial( "gmod/edit_sun" ) + + if ( SERVER ) then + + -- + -- Notify us when the entity angle changes, so we can update the sun entity + -- + self:AddCallback( "OnAngleChange", self.OnAngleChange ) + + + -- + -- Find an env_sun entity + -- + local list = ents.FindByClass( "env_sun" ) + if ( #list > 0 ) then + self.EnvSun = list[1] + end + + end + +end + +function ENT:SetupDataTables() + + self:NetworkVar( "Float", 0, "SunSize", { KeyName = "sunsize", Edit = { type = "Float", min = 0, max = 100, order = 1 } } ); + self:NetworkVar( "Float", 1, "OverlaySize", { KeyName = "overlaysize", Edit = { type = "Float", min = 0, max = 200, order = 2 } } ); + self:NetworkVar( "Vector", 0, "SunColor", { KeyName = "suncolor", Edit = { type = "VectorColor", order = 3 } } ); + self:NetworkVar( "Vector", 1, "OverlayColor", { KeyName = "overlaycolor", Edit = { type = "VectorColor", order = 4 } } ); + + + + if ( SERVER ) then + + -- defaults + self:SetSunSize( 20 ) + self:SetOverlaySize( 20 ) + self:SetOverlayColor( Vector( 1, 1, 1 ) ) + self:SetSunColor( Vector( 1, 1, 1 ) ) + + -- call this function when something changes these variables + self:NetworkVarNotify( "SunSize", self.OnVariableChanged ); + self:NetworkVarNotify( "OverlaySize", self.OnVariableChanged ); + self:NetworkVarNotify( "SunColor", self.OnVariableChanged ); + self:NetworkVarNotify( "OverlayColor", self.OnVariableChanged ); + + end + +end + +-- +-- Callback - serverside - added in :Initialize +-- +function ENT:OnAngleChange( newang ) + + if ( IsValid( self.EnvSun ) ) then + self.EnvSun:SetKeyValue( "sun_dir", tostring( newang:Forward() ) ); + end + +end + + +-- +-- Update all the variables on the sun, from our variables in this entity +-- +function ENT:OnVariableChanged() + + if ( !IsValid( self.EnvSun ) ) then return end + + self.EnvSun:SetKeyValue( "size", self:GetSunSize() ); + self.EnvSun:SetKeyValue( "overlaysize", self:GetOverlaySize() ); + + local vec = self:GetOverlayColor() + self.EnvSun:SetKeyValue( "overlaycolor", Format( "%i %i %i", vec.x * 255, vec.y * 255, vec.z * 255 ) ); + + local vec = self:GetSunColor() + self.EnvSun:SetKeyValue( "suncolor", Format( "%i %i %i", vec.x * 255, vec.y * 255, vec.z * 255 ) ); + + +end + +-- +-- This edits something global - so always network - even when not in PVS +-- +function ENT:UpdateTransmitState() + + return TRANSMIT_ALWAYS +end diff --git a/gamemodes/nzombies/entities/entities/invis_damage_wall/shared.lua b/gamemodes/nzombies/entities/entities/invis_damage_wall/shared.lua new file mode 100644 index 00000000..d1e8a6bb --- /dev/null +++ b/gamemodes/nzombies/entities/entities/invis_damage_wall/shared.lua @@ -0,0 +1,166 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "invis_wall" +ENT.Author = "Zet0r" +ENT.Contact = "youtube.com/Zet0r" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + -- Min bound is for now just the position + --self:NetworkVar("Vector", 0, "MinBound") + self:NetworkVar("Vector", 0, "MaxBound") + self:NetworkVar("Bool", 0, "Radiation") + self:NetworkVar("Bool", 1, "Poison") + self:NetworkVar("Bool", 2, "Tesla") + self:NetworkVar("Int", 0, "Damage") + self:NetworkVar("Float", 0, "Delay") +end + +function ENT:Initialize() + --self:SetMoveType( MOVETYPE_NONE ) + self:DrawShadow( false ) + self:SetRenderMode( RENDERMODE_TRANSCOLOR ) + if self.SetRenderBounds then + self:SetRenderBounds(Vector(0,0,0), self:GetMaxBound()) + end + + if SERVER then + self.PlayersInside = {} + else + self.NextPoisonCloud = 0 + end + + self.NextDamage = 0 + + --self:SetCustomCollisionCheck(true) + --self:SetFilter(true, true) +end + +function ENT:StartTouch(ent) + if ent:IsPlayer() and ent:GetNotDowned() and !table.HasValue(self.PlayersInside, ent) then + table.insert(self.PlayersInside, ent) + end +end + +function ENT:Touch(ent) + --print("Touch", ent) +end + +function ENT:EndTouch(ent) + if table.HasValue(self.PlayersInside, ent) then + table.RemoveByValue(self.PlayersInside, ent) + end +end + +function ENT:Think() + local ct = CurTime() + if ct > self.NextDamage then + + if SERVER then + local dmg = DamageInfo() + dmg:SetDamage(self:GetDamage()) + dmg:SetAttacker(self) + dmg:SetDamageType(DMG_RADIATION) + + for k,v in ipairs(self.PlayersInside) do + if !IsValid(v) or !v:GetNotDowned() then + self:EndTouch(v) + else + v:TakeDamageInfo(dmg) + end + end + else + local e = EffectData() + e:SetMagnitude(1.1) + e:SetScale(1.5) + + local pos1 = self:GetPos() + local pos2 = self:GetPos() + self:GetMaxBound() + OrderVectors(pos1, pos2) + + for k,v in pairs(player.GetAll()) do + if IsValid(v) and v:GetNotDowned() and (v:IsPlaying() or v:IsInCreative()) then + if v:GetPos():WithinAABox(pos1, pos2) then + local islocal = v == LocalPlayer() + if self:GetTesla() then + if !v.LightningAura or v.LightningAura < ct then + e:SetEntity(v) + util.Effect("lightning_aura", e, false, true) + end + if islocal then + surface.PlaySound("weapons/physcannon/superphys_small_zap" .. math.random(1,4) .. ".wav") + end + v.LightningAura = ct + 1 + end + if islocal and self:GetRadiation() then + surface.PlaySound("player/geiger" .. math.random(1,3) .. ".wav") + end + end + end + end + end + + self.NextDamage = ct + self:GetDelay() + end +end + +local mat = Material("color") +local white = Color(255,0,0,30) + +if CLIENT then + + if not ConVarExists("nz_creative_preview") then CreateClientConVar("nz_creative_preview", "0") end + + local particles = { + Model("particle/particle_smokegrenade"), + Model("particle/particle_noisesphere") + } + + function ENT:Draw() + if ConVarExists("nz_creative_preview") and !GetConVar("nz_creative_preview"):GetBool() and nzRound:InState( ROUND_CREATE ) then + cam.Start3D() + render.SetMaterial(mat) + render.DrawBox(self:GetPos(), self:GetAngles(), Vector(0,0,0), self:GetMaxBound(), white, true) + cam.End3D() + end + + if self:GetPoison() then + local size = self:GetMaxBound() + local scale = math.abs(size.x * size.y * size.z) + + if !IsValid(self.PoisonEmitter) then + self.PoisonEmitter = ParticleEmitter(self:GetPos()) + end + if self.NextPoisonCloud < CurTime() then + local count = math.Clamp(math.Round(0.00000001 * scale), 1, 100) + + for i = 1, count do + local pos = self:GetPos() + Vector(size.x * math.Rand(0,1), size.y * math.Rand(0,1), size.z * math.Rand(0,1)) + local p = self.PoisonEmitter:Add(particles[math.random(#particles)] , pos) + p:SetColor(math.random(30,40), math.random(40,70), math.random(0,30)) + p:SetStartAlpha(255) + p:SetEndAlpha(150) + p:SetLifeTime(0) + p:SetDieTime(math.Rand(1, 2.5)) + p:SetStartSize(math.random(45, 50)) + p:SetEndSize(math.random(20, 30)) + p:SetRoll(math.random(-180, 180)) + p:SetRollDelta(math.Rand(-0.1, 0.1)) + p:SetLighting(false) + end + self.NextPoisonCloud = CurTime() + 0.1 + end + end + end + + function ENT:OnRemove() + if self.PoisonEmitter then self.PoisonEmitter:Finish() end + end +end + +hook.Add("PhysgunPickup", "nzInvisWallDamageNotPickup", function(ply, wall) + if wall:GetClass() == "invis_damage_wall" then return false end +end) diff --git a/gamemodes/nzombies/entities/entities/invis_wall/shared.lua b/gamemodes/nzombies/entities/entities/invis_wall/shared.lua new file mode 100644 index 00000000..e0d21ee6 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/invis_wall/shared.lua @@ -0,0 +1,52 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "invis_wall" +ENT.Author = "Zet0r" +ENT.Contact = "youtube.com/Zet0r" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + -- Min bound is for now just the position + --self:NetworkVar("Vector", 0, "MinBound") + self:NetworkVar("Vector", 0, "MaxBound") +end + +function ENT:Initialize() + --self:SetMoveType( MOVETYPE_NONE ) + self:DrawShadow( false ) + self:SetRenderMode( RENDERMODE_TRANSCOLOR ) + if self.SetRenderBounds then + self:SetRenderBounds(Vector(0,0,0), self:GetMaxBound()) + end + self:SetCustomCollisionCheck(true) + --self:SetFilter(true, true) +end + +local mat = Material("color") +local white = Color(255,150,0,30) + +if CLIENT then + + if not ConVarExists("nz_creative_preview") then CreateClientConVar("nz_creative_preview", "0") end + + function ENT:Draw() + if ConVarExists("nz_creative_preview") and !GetConVar("nz_creative_preview"):GetBool() and nzRound:InState( ROUND_CREATE ) then + cam.Start3D() + render.SetMaterial(mat) + render.DrawBox(self:GetPos(), self:GetAngles(), Vector(0,0,0), self:GetMaxBound(), white, true) + cam.End3D() + end + end +end + +-- Causes collisions to completely disappear, not just traces :( +--[[function ENT:TestCollision(start, delta, hulltrace, bounds) + return nil -- Traces pass through it! +end]] + +hook.Add("PhysgunPickup", "nzInvisWallNotPickup", function(ply, wall) + if wall:GetClass() == "invis_wall" or wall:GetClass() == "invis_damage_wall" then return false end +end) diff --git a/gamemodes/nzombies/entities/entities/logic_points/init.lua b/gamemodes/nzombies/entities/entities/logic_points/init.lua new file mode 100644 index 00000000..47b3e3c5 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/logic_points/init.lua @@ -0,0 +1,79 @@ +ENT.Type = "point" + +function ENT:Initialize() + -- Remove it as soon as it spawns, if the gamemode hasn't been enabled in Map Settings + if !nzMapping.Settings.gamemodeentities then + self:Remove() + end +end + +-- We need to scale the point requirements up to what fits nZombies more +local conversionrate = 100 + +function ENT:Add(pl, amount) + -- Instead of a player team check, we check if the player is playing + if pl and pl:IsValid() and pl:IsPlayer() and pl:IsPlaying() then + amount = math.Round(amount) + if amount < 0 then + pl:TakePoints(-amount) + else + pl:GivePoints(amount, true) -- We ignore double points for this + end + end +end + +function ENT:Set(pl, amount) + -- You CANNOT set the player's points in nZombies! +end + +function ENT:GetAmount(pl) + return pl:GetPoints() +end + +function ENT:CallIf(pl, amount) + if pl and pl:IsValid() and pl:IsPlayer() and pl:IsPlaying() then + self:Input(pl:IsPlaying() and self:GetAmount(pl) >= amount and "onconditionpassed" or "onconditionfailed", pl, self, amount) + end +end + +function ENT:CallIfNot(pl, amount) + if pl and pl:IsValid() and pl:IsPlayer() and pl:IsPlaying() then + self:Input(pl:IsPlaying() and self:GetAmount(pl) >= amount and "onconditionfailed" or "onconditionpassed", pl, self, amount) + end +end + +function ENT:AcceptInput(name, activator, caller, args) + name = string.lower(name) + -- We multiply with our conversion rate and round to nearest 10 + local amount = math.Round(tonumber(args) * conversionrate, -1) or 0 + if string.sub(name, 1, 2) == "on" then + self:FireOutput(name, activator, caller, args) + elseif name == "addtoactivator" then + self:Add(activator, amount) + elseif name == "takefromactivator" then + self:Add(activator, -amount) + elseif name == "addtocaller" then + self:Add(caller, amount) + elseif name == "takefromcaller" then + self:Add(caller, -amount) + elseif name == "callifactivatorhave" then + self:CallIf(activator, amount) + elseif name == "callifactivatornothave" then + self:CallIfNot(activator, amount) + elseif name == "callifcallerhave" then + self:CallIf(caller, amount) + elseif name == "callifcallernothave" then + self:CallIfNot(caller, amount) + elseif name == "setactivatoramount" then + self:Set(activator, amount) + elseif name == "setcalleramount" then + self:Set(caller, amount) + end +end + +function ENT:KeyValue(key, value) + key = string.lower(key) + if string.sub(key, 1, 2) == "on" then + self:AddOnOutput(key, value) + end +end diff --git a/gamemodes/nzombies/entities/entities/logic_waves/cl_init.lua b/gamemodes/nzombies/entities/entities/logic_waves/cl_init.lua new file mode 100644 index 00000000..1d4ef513 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/logic_waves/cl_init.lua @@ -0,0 +1,14 @@ + +function ENT:Initialize() + self:DrawShadow(false) + self:SetMoveType(MOVETYPE_NONE) + self:SetSolid(SOLID_NONE) + self:SetCollisionGroup(COLLISION_GROUP_WORLD) +end + +local GripMaterial = Material( "sprites/grip" ) +function ENT:Draw() + if !nzRound:InState( ROUND_CREATE ) then return end + render.SetMaterial( GripMaterial ) + render.DrawSprite( self:GetPos(), 16, 16, color_white ) +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/logic_waves/init.lua b/gamemodes/nzombies/entities/entities/logic_waves/init.lua new file mode 100644 index 00000000..effa1bb3 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/logic_waves/init.lua @@ -0,0 +1,70 @@ +ENT.Type = "point" + +function ENT:Initialize() + -- Remove it as soon as it spawns, if gamemode extensions hasn't been enabled in Map Settings + if !nzMapping.Settings.gamemodeentities then + self:Remove() + end + self.Wave = self.Wave or -1 +end + +function ENT:Think() +end + +function ENT:AcceptInput(name, activator, caller, args) + name = string.lower(name) + if string.sub(name, 1, 2) == "on" then + self:FireOutput(name, activator, caller, args) + elseif name == "advancewave" then + -- We do not allow manually advancing rounds + return true + elseif name == "endwave" then + -- Or ending them + return true + elseif name == "setwave" then + -- Or changing which one we're on + return true + elseif name == "setwaves" then + SetGlobalInt("numwaves", tonumber(args) or GAMEMODE.NumberOfWaves) + return true + elseif name == "startwave" then + + return true + elseif name == "setwavestart" then + + return true + elseif name == "setwaveend" then + + return true + end +end + +function ENT:KeyValue(key, value) + key = string.lower(key) + if string.sub(key, 1, 2) == "on" then + self:AddOnOutput(key, value) + elseif key == "wave" then + self.Wave = tonumber(value) or -1 + end +end + +-- Rounds in nZombies are different than those on Zombie Survival +local conversionrate = 2 + +hook.Add("OnRoundStart", "nz_zsLogicWavesRoundStart", function(num) + local curwave = num / conversionrate + for _, ent in pairs(ents.FindByClass("logic_waves")) do + if ent.Wave == curwave or ent.Wave == -1 then + ent:Input("onwavestart", ent, ent, curwave) + end + end +end) + +hook.Add("OnRoundPreparation", "nz_zsLogicWavesRoundEnd", function(num) + local curwave = (num - 1) / conversionrate + for _, ent in pairs(ents.FindByClass("logic_waves")) do + if ent.Wave == curwave or ent.Wave == -1 then + ent:Input("onwaveend", ent, ent, curwave) + end + end +end) \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/logic_winlose/init.lua b/gamemodes/nzombies/entities/entities/logic_winlose/init.lua new file mode 100644 index 00000000..790d4a8f --- /dev/null +++ b/gamemodes/nzombies/entities/entities/logic_winlose/init.lua @@ -0,0 +1,66 @@ +ENT.Type = "point" + + +function ENT:Initialize() + -- Remove it as soon as it spawns, if the gamemode hasn't been enabled in Map Settings + if !nzMapping.Settings.gamemodeentities then + self:Remove() + end +end + +function ENT:Think() +end + +function ENT:AcceptInput(name, activator, caller, args) + name = string.lower(name) + if string.sub(name, 1, 2) == "on" then + self:FireOutput(name, activator, caller, args) + return true + elseif name == "win" then + nzRound:Win("You survived after "..nzRound:GetNumber().." rounds!") + return true + elseif name == "lose" then + nzRound:Lose("You got overwhelmed after "..nzRound:GetNumber().." rounds!") + return true + elseif name == "setendslomo" then + self:SetKeyValue("endslomo", args) + return true + elseif name == "setendcamera" then + self:SetKeyValue("endcamera", args) + return true + elseif name == "setendcamerapos" then + self:SetKeyValue("endcamerapos", args) + return true + elseif name == "setwinmusic" then + self:SetKeyValue("winmusic", args) + return true + elseif name == "setlosemusic" then + self:SetKeyValue("losemusic", args) + return true + end +end + +function ENT:KeyValue(key, value) + key = string.lower(key) + if string.sub(key, 1, 2) == "on" then + self:AddOnOutput(key, value) + elseif key == "endslomo" then + nzRound.OverrideEndSlomo = value == "1" + elseif key == "endcamera" then + SetGlobalBool("endcamera", value == "1") + elseif key == "setendcamerapos" then + SetGlobalVector("endcamerapos", Vector(value)) + elseif key == "winmusic" then + if value == "default" then + SetGlobalString("winmusic", nil) + else + SetGlobalString("winmusic", value) + end + elseif key == "losemusic" then + if value == "default" then + SetGlobalString("losemusic", nil) + else + SetGlobalString("losemusic", value) + end + end +end diff --git a/gamemodes/nzombies/entities/entities/nz_activatable.lua b/gamemodes/nzombies/entities/entities/nz_activatable.lua new file mode 100644 index 00000000..d01f7191 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_activatable.lua @@ -0,0 +1,134 @@ +AddCSLuaFile( ) + +-- Interface for stuff taht cna be activated by the player DO NOT USE THIS CLASS create subclasses! + +ENT.Type = "anim" +ENT.Base = "base_entity" +ENT.Editable = true + +ENT.PrintName = "nz_activatable" + +ENT.bIsActivatable = true +ENT.bPhysgunNoCollide = true + +function ENT:SetupDataTables() + self:NetworkVar( "String", 0, "NZName", {KeyName = "nz_name", Edit = {order = 1, type = "Generic"}} ) + + self:NetworkVar( "Bool", 0, "Active") + self:NetworkVar( "Bool", 1, "CooldownActive") + self:NetworkVar( "Bool", 2, "ElectircityNeeded", {KeyName = "nz_electircityneeded", Edit = {order = 3, type = "Boolean"}} ) + self:NetworkVar( "Bool", 3, "RemoteActivated", {KeyName = "nz_remoteactivated", Edit = {order = 5, type = "Boolean"}} ) + + self:NetworkVar( "Float", 0, "Duration", {KeyName = "nz_duration", Edit = {order = 7, type = "Float", min = 0, max = 100000}} ) + self:NetworkVar( "Float", 1, "Cooldown", {KeyName = "nz_cooldown", Edit = {order = 8, type = "Float", min = 0, max = 100000}} ) + + self:NetworkVar( "Int", 0, "Cost", {KeyName = "nz_cost", Edit = {order = 9, type = "Int", min = 0, max = 100000}} ) + + self:SetActive(false) + self:SetDuration(60) + self:SetCooldown(30) + self:SetCost(0) + self:SetCooldownActive(false) + self:SetElectircityNeeded(true) + self:SetRemoteActivated(false) + + if SERVER then + self:SetUseType(SIMPLE_USE) + end +end + +function ENT:IsActive() return self:GetActive() end + +function ENT:IsCooldownActive() return self:GetCooldownActive() end + +function ENT:IsElectircityNeeded() return self:GetElectircityNeeded() end + +function ENT:IsRemoteActivated() return self:GetRemoteActivated() end + +function ENT:Activation(activator, duration, cooldown) + self:SetDuration(duration) + self:SetCooldown(cooldown) + self:SetActive(true) + if self:GetDuration() > 0 then + timer.Create("nz.activatable.timer." .. self:EntIndex(), self:GetDuration(), 1, function() if IsValid(self) then self:Deactivation() end end) + end + self:OnActivation(activator, duration, cooldown) +end + +function ENT:Deactivation() + self:SetActive(false) + self:SetCooldownActive(true) + if self:GetCooldown() > 0 then + timer.Create("nz.activatable.cooldown.timer." .. self:EntIndex(), self:GetCooldown(), 1, function() if IsValid(self) then self:Ready() end end) + end + self:OnDeactivation() +end + +function ENT:Ready() + self:SetCooldownActive(false) + self:OnReady() +end + +function ENT:Use(act, caller, type, value ) + if not nzElec:IsOn() and self:IsElectircityNeeded() then return end + if IsValid(caller) and caller:IsPlayer() and not self:IsRemoteActivated() and not self:IsCooldownActive() and not self:IsActive() then + if caller:CanAfford(self:GetCost()) then + self:Activation(caller, self:GetDuration(), self:GetCooldown()) + if SERVER then + caller:TakePoints(self:GetCost()) + end + end + end +end + +-- IMPLEMENT ME +function ENT:OnActivation() end + +function ENT:OnDeactivation() end + +function ENT:OnReady() end + +function ENT:OnPoweredOff() end + +function ENT:GetNZTargetText() + if self:IsActive() then return "Already activated" end + if self:IsCooldownActive() then return "On cooldown" end + if not self:IsElectircityNeeded() and nzElec:IsOn() and self:IsRemoteActivated() then + return false + end + if self:IsElectircityNeeded() and not nzElec:IsOn() then + return "Electricity required!" + else + if self:IsRemoteActivated() then return false end + if self:GetCost() > 0 then + return "Press E to activate " .. self:GetNZName() .. " for " .. self:GetCost() .. " points." + else + return "Press E to activate " .. self:GetNZName() .. "." + end + end +end + +-- util +function ENT:GetEntsByNZName(name) + local result = {} + if not name or name == "" then return result end + for _, ent in pairs(ents.GetAll()) do + if ent:IsActivatable() then + if ent:GetNZName() == name then + table.insert(result, ent) + end + end + end + return result +end + +--Default stuff +if CLIENT then + + function ENT:Draw() + + self:DrawModel() + + end + +end diff --git a/gamemodes/nzombies/entities/entities/nz_button.lua b/gamemodes/nzombies/entities/entities/nz_button.lua new file mode 100644 index 00000000..732cc835 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_button.lua @@ -0,0 +1,168 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" +ENT.Base = "base_entity" + +nzLogic:Register("nz_button") +ENT.SpawnIcon = "models/nzprops/zapper_handle.mdl" +ENT.PrintName = "Button" +ENT.Description = "Simple Button that can trigger one or multiple other logic entities or traps." + +ENT.WireMat = Material( "cable/cable2" ) + +ENT.ModelTranslate = { + -- 1 + {model = "models/nzprops/zapper_handle.mdl", gmod_button = true}, -- This one is built like gmod buttons to flip + -- 2 + {model = "models/nzprops/zombies_power_lever_short.mdl"}, + -- 3 + {model = "models/maxofs2d/button_01.mdl", gmod_button = true}, + -- 4 + {model = "models/maxofs2d/button_02.mdl", gmod_button = true}, + -- 5 + {model = "models/maxofs2d/button_03.mdl", gmod_button = true}, + -- 6 + {model = "models/maxofs2d/button_04.mdl", gmod_button = true}, + -- 7 + {model = "models/maxofs2d/button_05.mdl", gmod_button = true}, + -- 8 + {model = "models/maxofs2d/button_06.mdl", gmod_button = true}, + -- 9 + {model = "models/maxofs2d/button_slider.mdl", gmod_button = true} +} + +DEFINE_BASECLASS("nz_activatable") + +function ENT:SetupDataTables() + BaseClass.SetupDataTables( self ) + + local modelTbl = {} + modelTbl["Trap Handle"] = 1 + modelTbl["Power Switch"] = 2 + modelTbl["Gmod Button 1"] = 3 + modelTbl["Gmod Button 2"] = 4 + modelTbl["Gmod Button 3"] = 5 + modelTbl["Gmod Button 4"] = 6 + modelTbl["Gmod Button 5"] = 7 + modelTbl["Gmod Button 6"] = 8 + modelTbl["Gmod Button 7"] = 9 + + self:NetworkVar( "Int", 1, "ModelID", {KeyName = "nz_model_id", Edit = {order = -1, type = "Combo", text = "Select a model!", values = modelTbl}} ) + + self:NetworkVarNotify( "ModelID", self.OnModelChange) + + self:SetModelID(1) + + --the name of the linked ents + self:ButtonSetupDataTables() +end + +function ENT:ButtonSetupDataTables() + self:NetworkVar( "String", 1, "LinkedNZName1", {KeyName = "nz_linked_name1", Edit = {order = 20, type = "Generic"}} ) + self:NetworkVar( "String", 2, "LinkedNZName2", {KeyName = "nz_linked_name2", Edit = {order = 21, type = "Generic"}} ) + self:NetworkVar( "String", 3, "LinkedNZName3", {KeyName = "nz_linked_name3", Edit = {order = 22, type = "Generic"}} ) +end + +function ENT:GetLinkedEnts() + local result = {} + table.insert(result, self:GetEntsByNZName(self:GetLinkedNZName1())) + table.insert(result, self:GetEntsByNZName(self:GetLinkedNZName2())) + table.insert(result, self:GetEntsByNZName(self:GetLinkedNZName3())) + + return result +end + +function ENT:OnModelChange(name, old, new) + if self.ModelTranslate[new] then + self:SetModel(self.ModelTranslate[new].model) + end +end + +function ENT:Initialize() + self:SetModel(self.ModelTranslate[self:GetModelID()].model) + + self:PhysicsInit( SOLID_VPHYSICS ) + self:SetSolid( SOLID_VPHYSICS ) + + local phys = self:GetPhysicsObject() + phys:EnableMotion(false) + self.PosePosition = 0 +end + +function ENT:Think() + BaseClass.Think(self) + + if CLIENT then + if self:GetModelInformation().gmod_button then + self:UpdateLever() + end + end +end + +if CLIENT then + function ENT:Draw() + BaseClass.Draw(self) + + if ConVarExists("nz_creative_preview") and !GetConVar("nz_creative_preview"):GetBool() and nzRound:InState( ROUND_CREATE ) then + -- draw "wires" in creative this is very resource intensive + for _, lEntsWithName in pairs(self:GetLinkedEnts()) do + for _, lEnt in pairs(lEntsWithName) do + if IsValid(lEnt) and !lEnt:IsPlayer() then + local texcoord = math.Rand( 0, 1 ) + render.SetMaterial(self.WireMat) + render.DrawBeam(self:GetPos() + self:OBBCenter(), lEnt:GetPos() + lEnt:OBBCenter(), 1, texcoord, texcoord + 1, Color( 20, 255, 30 ) ) + end + end + end + end + end +end + +function ENT:Activation(caller, duration, cooldown) + BaseClass.Activation(self, caller, duration, cooldown) + + nzDoors:OpenLinkedDoors(self:GetLinkedNZName1()) + nzDoors:OpenLinkedDoors(self:GetLinkedNZName2()) + nzDoors:OpenLinkedDoors(self:GetLinkedNZName3()) + + for _, lEntsWithName in pairs(self:GetLinkedEnts()) do + for _, lEnt in pairs(lEntsWithName) do + if IsValid(lEnt) and !lEnt:IsPlayer() then + lEnt:Activation(caller, duration, cooldown) + end + end + end +end + +function ENT:Ready() + BaseClass.Ready(self) +end + +-- IMPLEMENT ME +function ENT:OnActivation(caller, duration, cooldown) + self:SetSkin(2) +end + +function ENT:OnDeactivation() + self:SetSkin(3) +end + +function ENT:OnReady() + self:SetSkin(1) +end + +function ENT:GetModelInformation() + return self.ModelTranslate[self:GetModelID()] +end + +function ENT:UpdateLever() + + local TargetPos = 0.0 + if ( self:IsActive() ) then TargetPos = 1.0 end + + self.PosePosition = math.Approach( self.PosePosition, TargetPos, FrameTime() * 3.0 ) + + self:SetPoseParameter( "switch", self.PosePosition ) + self:InvalidateBoneCache() + +end diff --git a/gamemodes/nzombies/entities/entities/nz_button_and.lua b/gamemodes/nzombies/entities/entities/nz_button_and.lua new file mode 100644 index 00000000..dff964bb --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_button_and.lua @@ -0,0 +1,70 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" +ENT.Base = "base_entity" + +nzLogic:Register("nz_button_and") +ENT.SpawnIcon = "models/maxofs2d/button_03.mdl" +ENT.PrintName = "AND Gate/Button" +ENT.Description = "This Gate will trigger if all activators linked to this butoons are activate at the same time." + +DEFINE_BASECLASS("nz_button") + +function ENT:ButtonSetupDataTables() + self:SetModelID(5) + + self:NetworkVar( "String", 1, "ActivatorNZName1", {KeyName = "nz_activator_name1", Edit = {order = 20, type = "Generic"}} ) + self:NetworkVar( "String", 2, "ActivatorNZName2", {KeyName = "nz_activator_name2", Edit = {order = 21, type = "Generic"}} ) + self:NetworkVar( "String", 3, "LinkedNZName", {KeyName = "nz_linked_name1", Edit = {order = 22, type = "Generic"}} ) + + self:SetRemoteActivated(true) +end + +function ENT:GetLinkedEnts() + local result = {} + table.insert(result, self:GetEntsByNZName(self:GetLinkedNZName())) + return result +end + +function ENT:GetActivatorEnts() + local result = {} + table.insert(result, self:GetEntsByNZName(self:GetActivatorNZName1())) + table.insert(result, self:GetEntsByNZName(self:GetActivatorNZName2())) + return result +end + +function ENT:Activation(caller, duration, cooldown) + local shouldBeActivated = true + + -- only activated if all activators are active + for _, lEntsWithName in pairs(self:GetActivatorEnts()) do + for _, lEnt in pairs(lEntsWithName) do + if IsValid(lEnt) and not lEnt:IsPlayer() then + print(lEnt, lEnt:IsActive()) + if not lEnt:IsActive() then + shouldBeActivated = false + end + end + end + end + + if shouldBeActivated then + BaseClass.Activation(self, caller, duration, cooldown) + end +end + +function ENT:Ready() + BaseClass.Ready(self) +end + +function ENT:Use() + -- prevent using the and gate + return false +end + +-- IMPLEMENT ME +function ENT:OnActivation(caller, duration, cooldown) end + +function ENT:OnDeactivation() end + +function ENT:OnReady() end diff --git a/gamemodes/nzombies/entities/entities/nz_electricity.lua b/gamemodes/nzombies/entities/entities/nz_electricity.lua new file mode 100644 index 00000000..a892e716 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_electricity.lua @@ -0,0 +1,27 @@ + +ENT.Type = "point" +ENT.Base = "base_point" + +-- An entity to be used in Hammer that can turn the electricity on or off, and will fire outputs when this happens. +-- To use it, grab the nzombies.fgd from the gamemode and import it into Hammer. + +function ENT:Initialize() + -- Calling this when the entity is created so you can turn off the lights only if the gamemode is nZombies. + if engine.ActiveGamemode() == "nzombies3" then + self:TriggerOutput("OnInitialized", self) + end +end + +function ENT:KeyValue(k, v) + +end + +function ENT:AcceptInput(name, activator, caller, data) + if name == "TurnElectricityOn" then + nzElec:Activate(data == "1") + return true + elseif name == "TurnElectricityOff" then + nzElec:Reset(data == "1") + return true + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/nz_fire_effect.lua b/gamemodes/nzombies/entities/entities/nz_fire_effect.lua new file mode 100644 index 00000000..bedec7b8 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_fire_effect.lua @@ -0,0 +1,170 @@ + +AddCSLuaFile() +ENT.Type = "anim" + +ENT.PrintName = "" +ENT.Author = "" +ENT.Contact = "" +ENT.Purpose = "" +ENT.Instructions = "" +ENT.Spawnable = false +ENT.AdminOnly = false +ENT.Editable = false + +ENT.PrintName = "Fire Effect" +ENT.Category = "Editors" + +ENT.NZOnlyVisibleInCreative = true + +function ENT:Initialize() + + --BaseClass.Initialize( self ) + + //Set it up just like a prop_effect + local Radius = 6 + local min = Vector( 1, 1, 1 ) * Radius * -0.5 + local max = Vector( 1, 1, 1 ) * Radius * 0.5 + + if ( SERVER ) then + + self:SetModel( "models/props_junk/watermelon01.mdl" ) + + -- Don't use the model's physics - create a box instead + self:PhysicsInitBox( min, max ) + + -- Set up our physics object here + local phys = self:GetPhysicsObject() + if ( IsValid( phys ) ) then + phys:Wake() + phys:EnableGravity( false ) + phys:EnableDrag( false ) + end + + self:CreateFire() + + self:DrawShadow( false ) + self:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + else + + self.GripMaterial = Material( "sprites/grip" ) + + -- Get the attached entity so that clientside functions like properties can interact with it + local tab = ents.FindByClassAndParent( "prop_dynamic", self ) + if ( tab && IsValid( tab[ 1 ] ) ) then self.AttachedEntity = tab[ 1 ] end + + end + + -- Set collision bounds exactly + self:SetCollisionBounds( min, max ) + +end + +function ENT:CreateFire() + self.FireEffect = ents.Create("env_fire") + self.FireEffect:SetPos( self:GetPos() ) + self.FireEffect:SetParent( self ) + self.FireEffect:Spawn() + self.FireEffect:Activate() + self.FireEffect:Fire("StartFire") + self.FireEffect:SetKeyValue("spawnflags", "1") + --print(self.FireEffect) +end + +function ENT:Draw() + + if !nzRound:InState( ROUND_CREATE ) then return end + + -- Don't draw the grip if there's no chance of us picking it up + local ply = LocalPlayer() + local wep = ply:GetActiveWeapon() + if ( !IsValid( wep ) ) then return end + + local weapon_name = wep:GetClass() + + if ( weapon_name != "weapon_physgun" && weapon_name != "weapon_physcannon" && weapon_name != "gmod_tool" ) then + return + end + + render.SetMaterial( self.GripMaterial ) + render.DrawSprite( self:GetPos(), 16, 16, color_white ) + +end + +function ENT:PhysicsUpdate( physobj ) + + if ( CLIENT ) then return end + + -- Don't do anything if the player isn't holding us + if ( !self:IsPlayerHolding() && !self:IsConstrained() ) then + + physobj:SetVelocity( Vector( 0, 0, 0 ) ) + physobj:Sleep() + + end + +end + +if SERVER then + hook.Add("PostCleanupMap", "RestoreFireEffects", function() + for k,v in pairs(ents.FindByClass("nz_fire_effect")) do + v:CreateFire() + end + end) +end + + + // Doesn't work :( +--[[function ENT:SetupDataTables() + + self:NetworkVar( "Bool", 0, "On", { KeyName = "on", Edit = { type = "Boolean", order = 1 } } ); + self:NetworkVar( "Int", 0, "Size", { KeyName = "size", Edit = { type = "Int", min = 0, max = 1000, order = 2 } } ); + self:NetworkVar( "Float", 0, "DmgMultiplier", { KeyName = "dmgmultiplier", Edit = { type = "Float", min = 0, max = 10, order = 3 } } ); + self:NetworkVar( "Bool", 1, "Glow", { KeyName = "glow", Edit = { type = "Boolean", order = 4 } } ); + self:NetworkVar( "Bool", 2, "Smoke", { KeyName = "smoke", Edit = { type = "Boolean", order = 5 } } ); + + self:SetOn(true) + self:SetGlow(true) + self:SetSmoke(true) + + if SERVER then + self:NetworkVarNotify( "Glow", self.OnVarChanged ) + self:NetworkVarNotify( "DmgMultiplier", self.OnVarChanged ) + self:NetworkVarNotify( "Size", self.OnVarChanged ) + self:NetworkVarNotify( "On", self.OnVarChanged ) + self:NetworkVarNotify( "Smoke", self.OnVarChanged ) + end + +end + +function ENT:OnVarChanged(name, old, new) + if name == "On" then + if new then + self.FireEffect:Fire("StartFire") + else + self.FireEffect:Fire("Extinguish") + end + elseif name == "Size" then + self.FireEffect:SetKeyValue("firesize", tostring(new)) + elseif name == "DmgMultiplier" then + self.FireEffect:SetKeyValue("damage scale", tostring(new)) + elseif name == "Glow" then + if new then + self:SetKeyValue("spawnflags", tostring(1 + 32 + (!self:GetSmoke() and 2 or 0))) + else + self:SetKeyValue("spawnflags", tostring(1 + (!self:GetSmoke() and 2 or 0))) + end + elseif name == "Smoke" then + if new then + self:SetKeyValue("spawnflags", tostring(1 + 2 + (!self:GetGlow() and 32 or 0))) + print(1 + 2 + (!self:GetGlow() and 32 or 0)) + else + self:SetKeyValue("spawnflags", tostring(1 + (!self:GetGlow() and 32 or 0))) + end + end +end]] + +function ENT:UpdateTransmitState() + return TRANSMIT_PVS +end + diff --git a/gamemodes/nzombies/entities/entities/nz_fraggrenade.lua b/gamemodes/nzombies/entities/entities/nz_fraggrenade.lua new file mode 100644 index 00000000..435de2a6 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_fraggrenade.lua @@ -0,0 +1,108 @@ +ENT.Type = "anim" +ENT.Base = "base_entity" +ENT.PrintName = "Frag Grenade" +ENT.Author = "Zet0r" + +ENT.Spawnable = false +ENT.AdminSpawnable = false + +if SERVER then + AddCSLuaFile("nz_fraggrenade.lua") +end + +function ENT:Initialize() + if SERVER then + self:SetModel("models/weapons/w_grenade.mdl") + self:PhysicsInit(SOLID_VPHYSICS) + self:SetMoveType(MOVETYPE_VPHYSICS) + self:SetCollisionGroup(COLLISION_GROUP_NONE) + self:SetSolid(SOLID_VPHYSICS) + phys = self:GetPhysicsObject() + + if phys and IsValid(phys) then + phys:SetMass(8) + phys:Wake() + phys:SetAngleDragCoefficient(1000) + --print(phys:GetMass()) + end + + self:CollisionRulesChanged() + end +end + + +function ENT:PhysicsCollide(data, physobj) + if SERVER then + if self.WidowsWine then + physobj:SetVelocity(Vector(0,0,0)) + physobj:EnableMotion(false) + physobj:Sleep() + + --self:SetAngles(data.HitNormal:Angle()) + + if IsValid(data.HitEntity) then + self:SetParent(data.HitEntity) + end + else + local vel = physobj:GetVelocity():Length() + if vel > 100 then + self:EmitSound("weapons/hegrenade/he_bounce-1.wav", 75, 100) + end + + local LastSpeed = math.max( data.OurOldVelocity:Length(), data.Speed ) + local NewVelocity = physobj:GetVelocity() + NewVelocity:Normalize() + + LastSpeed = math.max( NewVelocity:Length(), LastSpeed ) + + local TargetVelocity = NewVelocity * LastSpeed * 0.8 + + physobj:SetVelocity( TargetVelocity ) + --physobj:SetLocalAngularVelocity( AngleRand() ) + end + end +end + +function ENT:SetExplosionTimer( time ) + + SafeRemoveEntityDelayed( self, time +1 ) --fallback + + timer.Simple(time, function() + if IsValid(self) then + local pos = self:GetPos() + local owner = self:GetOwner() + + util.BlastDamage(self, owner, pos, 350, 50) + + if self.WidowsWine then + local zombls = ents.FindInSphere(pos, 350) + + local e = EffectData() + e:SetMagnitude(1.5) + e:SetScale(20) -- The time the effect lasts + + local fx = EffectData() + fx:SetOrigin(pos) + fx:SetMagnitude(1) + util.Effect("web_explosion", fx) + + for k,v in pairs(zombls) do + if IsValid(v) and v:IsValidZombie() then + v:ApplyWebFreeze(20) + end + end + end + + local fx = EffectData() + fx:SetOrigin(pos) + fx:SetMagnitude(1) + util.Effect("Explosion", fx) + + self:Remove() + end + end) +end + +function ENT:Draw() + self:DrawModel() +end diff --git a/gamemodes/nzombies/entities/entities/nz_monkeybomb.lua b/gamemodes/nzombies/entities/entities/nz_monkeybomb.lua new file mode 100644 index 00000000..1942a214 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_monkeybomb.lua @@ -0,0 +1,117 @@ +ENT.Type = "anim" +ENT.Base = "base_entity" +ENT.PrintName = "Monkey Bomb" +ENT.Author = "Zet0r" + +ENT.Spawnable = false +ENT.AdminSpawnable = false + +ENT.ExplosionSounds = { + "nz/monkey/voice_explosion/explo_vox_00.wav", + "nz/monkey/voice_explosion/explo_vox_01.wav", + "nz/monkey/voice_explosion/explo_vox_02.wav", + "nz/monkey/voice_explosion/explo_vox_03.wav", + "nz/monkey/voice_explosion/explo_vox_04.wav", + "nz/monkey/voice_explosion/explo_vox_05.wav", + "nz/monkey/voice_explosion/explo_vox_06.wav", + "nz/monkey/voice_explosion/explo_vox_07.wav", + "nz/monkey/voice_explosion/explo_vox_08.wav", + "nz/monkey/voice_explosion/explo_vox_09.wav", + "nz/monkey/voice_explosion/explo_vox_10.wav", + "nz/monkey/voice_explosion/explo_vox_11.wav", +} + +if SERVER then + AddCSLuaFile() +end + +function ENT:Initialize() + if SERVER then + self:SetModel("models/nzprops/monkey_bomb.mdl") -- Change later + self:PhysicsInitSphere(1, "metal_bouncy") + self:SetMoveType(MOVETYPE_VPHYSICS) + self:SetCollisionGroup(COLLISION_GROUP_NONE) + self:SetSolid(SOLID_VPHYSICS) + phys = self:GetPhysicsObject() + + if phys and phys:IsValid() then + phys:Wake() + end + end +end + + +function ENT:PhysicsCollide(data, physobj) + if SERVER then + local vel = physobj:GetVelocity():Length() + if vel > 100 then + self:EmitSound("nz/monkey/voice_bounce/land_0"..math.random(0,3)..".wav", 75, 100) + end + + local LastSpeed = math.max( data.OurOldVelocity:Length(), data.Speed ) + local NewVelocity = physobj:GetVelocity() + NewVelocity:Normalize() + + LastSpeed = math.max( NewVelocity:Length(), LastSpeed ) + + local TargetVelocity = NewVelocity * LastSpeed * 0.75 + + physobj:SetVelocity( TargetVelocity ) + + if vel < 100 then + self:SetMoveType(MOVETYPE_NONE) + self:SetCollisionGroup(COLLISION_GROUP_DEBRIS) + self:ResetSequence("anim_play") + self:SetExplosionTimer(8) + end + end +end + +function ENT:SetExplosionTimer( time ) + + -- Make Zombies target this over players + self:SetTargetPriority(TARGET_PRIORITY_SPECIAL) + + UpdateAllZombieTargets(self) + + SafeRemoveEntityDelayed( self, time +1 ) --fallback + + self:EmitSound("nz/monkey/music/song"..math.random(1,3)..".wav", 100) + self.NextCymbal = CurTime() + + timer.Simple(time - 1.5, function() + if IsValid(self) then + local sound = self.ExplosionSounds[math.random(1,#self.ExplosionSounds)] + self:EmitSound(sound, 85) + end + end) + + timer.Simple(time, function() + if IsValid(self) then + local pos = self:GetPos() + local owner = self:GetOwner() + + util.BlastDamage(self, owner, pos, 400, 200) + + fx = EffectData() + fx:SetOrigin(pos) + fx:SetMagnitude(1) + util.Effect("Explosion", fx) + + self:Remove() + end + end) +end + +function ENT:Draw() + self:DrawModel() +end + +function ENT:Think() + if SERVER then + if self.NextCymbal and self.NextCymbal < CurTime() then + self:EmitSound("nz/monkey/cymbals/monk_cymb_m.wav") + self.NextCymbal = CurTime() + 0.2 + end + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/nz_panzer_claw.lua b/gamemodes/nzombies/entities/entities/nz_panzer_claw.lua new file mode 100644 index 00000000..ad8522ed --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_panzer_claw.lua @@ -0,0 +1,223 @@ +ENT.Type = "anim" +ENT.Base = "base_entity" +ENT.PrintName = "Panzer Claw" +ENT.Author = "Zet0r" + +ENT.Spawnable = false +ENT.AdminSpawnable = false + +if SERVER then + AddCSLuaFile() + util.AddNetworkString("nz_panzer_grab") +end + +function ENT:SetupDataTables() + self:NetworkVar("Entity", 0, "Panzer") +end + +function ENT:Initialize() + if SERVER then + self:SetModel("models/nz_zombie/panzer_claw.mdl") -- Change later + self:PhysicsInit(SOLID_OBB) + self:SetSolid(SOLID_NONE) + self:SetTrigger(true) + self:UseTriggerBounds(true, 0) + self:SetMoveType(MOVETYPE_FLY) + --self:SetCollisionGroup(COLLISION_GROUP_DEBRIS) + --self:SetSolid(SOLID_VPHYSICS) + phys = self:GetPhysicsObject() + + if phys and phys:IsValid() then + phys:Wake() + end + end +end + +function ENT:Launch(dir) + self:SetLocalVelocity(dir * 1000) + self:SetAngles((dir*-1):Angle()) + self:SetSequence(self:LookupSequence("anim_close")) + + self.AutoReturnTime = CurTime() + 5 +end + +function ENT:Grab(ply, pos) -- Pos is used for clients who may not have the Panzer valid yet + if !IsValid(ply) then return end + + self.HasGrabbed = true + + local panzer = self:GetPanzer() + local speed = 200 + local pos = pos or IsValid(panzer) and panzer:GetAttachment(panzer:LookupAttachment("clawlight")).Pos + + self.GrabbedPlayer = ply + local breaktime = CurTime() + 10 + local index = self:EntIndex() + + hook.Add("SetupMove", "PanzerGrab"..index, function(pl, mv, cmd) + if !IsValid(ply) then self:Release() end + + if pl == ply then + local dir = (pos - (pl:GetPos() + Vector(0,0,50))):GetNormalized() + mv:SetVelocity(dir * speed) + + if !IsValid(panzer) or !IsValid(Entity(index)) then + hook.Remove("SetupMove", "PanzerGrab"..index) + else + local dist = (pl:GetPos() + Vector(0,0,50)):Distance(pos) + if dist < 25 then + self:Reattach() + end + end + + if mv:GetVelocity():Length() > 100 then -- Keep a speed over 100 + breaktime = CurTime() + 3 -- Then we keep delaying when to "break" the hook + elseif CurTime() > breaktime then -- But if you haven't been over 100 speed for the time + self:Release() -- Break the hook! + end + + if SERVER then + self:SetPos(pl:GetPos() + Vector(0,0,50)) + end + end + end) + + if SERVER then + self:SetLocalVelocity(Vector(0,0,0)) + net.Start("nz_panzer_grab") + net.WriteBool(true) + net.WriteEntity(self) + net.WriteVector(pos) + net.Send(ply) + + self:SetSequence(self:LookupSequence("anim_open")) + end + +end + +function ENT:Release() + if IsValid(self.GrabbedPlayer) then + hook.Remove("SetupMove", "PanzerGrab"..self:EntIndex()) + + if SERVER then + net.Start("nz_panzer_grab") + net.WriteBool(false) + net.WriteEntity(self) + net.Send(self.GrabbedPlayer) + + self:SetSequence(self:LookupSequence("anim_open")) + self:Return() + end + else + if SERVER then + net.Start("nz_panzer_grab") + net.WriteBool(false) + net.WriteEntity(self) + net.Broadcast() + end + end + self.GrabbedPlayer = nil +end + +if CLIENT then + net.Receive("nz_panzer_grab", function() + local grab = net.ReadBool() + local ent = net.ReadEntity() + local pos + if grab then pos = net.ReadVector() end + + if IsValid(ent) then + if grab then + ent:Grab(LocalPlayer(), pos) + else + if IsValid(ent) then ent:Release() end + end + end + end) +end + +function ENT:Return() -- Emptyhanded return - Grab is with player + self.HasGrabbed = true + + local panzer = self:GetPanzer() + if !IsValid(panzer) then self:Remove() return end + + self:SetMoveType(MOVETYPE_FLY) + self:SetSolid(SOLID_NONE) + self:SetCollisionGroup(COLLISION_GROUP_DEBRIS) + self:SetNotSolid(true) + self:SetCollisionBounds(Vector(0,0,0), Vector(0,0,0)) + + local att = panzer:LookupAttachment("clawlight") + local pos = att and panzer:GetAttachment(att).Pos or panzer:GetPos() + self:SetLocalVelocity((pos - self:GetPos()):GetNormalized() * 1500) +end + +function ENT:Reattach(removed) + if !removed then self:Remove() end + + local panzer = self:GetPanzer() + if !IsValid(panzer) then return end + + panzer:GrabPlayer(self.GrabbedPlayer) +end + +function ENT:StartTouch(ent) + local panzer = self:GetPanzer() + if IsValid(panzer) and !self.HasGrabbed then + if ent:IsPlayer() and panzer:IsValidTarget(ent) then + self:Grab(ent) + elseif !IsValid(self.GrabbedPlayer) then + --print("Touched something else") + --self:Remove() + self:Return() + end + else + self:Remove() + end +end + +if CLIENT then + function ENT:Draw() + self:DrawModel() + end + + local col = Color(255,255,255,255) + local mat = Material("cable/cable2") + hook.Add( "PostDrawOpaqueRenderables", "panzer_claw_wires", function() + for k,v in pairs(ents.FindByClass("nz_panzer_claw")) do + local panzer = v:GetPanzer() + if IsValid(panzer) then + local Vector1 = panzer:GetAttachment(panzer:LookupAttachment("clawlight")).Pos + local Vector2 = v:GetPos() + v:GetAngles():Forward()*10 + render.SetMaterial( mat ) + render.DrawBeam( Vector1, Vector2, 3, 1, 1, col ) + end + end + end ) +end + + +function ENT:Think() + if SERVER then + if self.HasGrabbed then + local panzer = self:GetPanzer() + if !IsValid(panzer) then self:Remove() return end + + if !IsValid(self.GrabbedPlayer) and self:GetPos():DistToSqr(panzer:GetAttachment(panzer:LookupAttachment("clawlight")).Pos) <= 10000 then + self:Reattach() + end + + if IsValid(panzer) and self.GrabbedPlayer and !panzer:IsValidTarget(self.GrabbedPlayer) then + self:Release() + end + elseif CurTime() > self.AutoReturnTime then + self:Return() + end + end +end + +function ENT:OnRemove() + self:Release() + self:Reattach(true) +end diff --git a/gamemodes/nzombies/entities/entities/nz_prop_effect.lua b/gamemodes/nzombies/entities/entities/nz_prop_effect.lua new file mode 100644 index 00000000..2bf4685b --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_prop_effect.lua @@ -0,0 +1,162 @@ + +AddCSLuaFile() + +if ( CLIENT ) then + CreateConVar( "cl_draweffectrings", "1", 0, "Should the effect green rings be visible?" ) +end + +ENT.Type = "anim" + +ENT.PrintName = "" +ENT.Author = "" +ENT.Contact = "" +ENT.Purpose = "" +ENT.Instructions = "" +ENT.Spawnable = false +ENT.AdminOnly = false + +ENT.NZOnlyVisibleInCreative = true + +--[[--------------------------------------------------------- + Name: Initialize +-----------------------------------------------------------]] +function ENT:Initialize() + + local Radius = 6 + local min = Vector( 1, 1, 1 ) * Radius * -0.5 + local max = Vector( 1, 1, 1 ) * Radius * 0.5 + + if ( SERVER ) then + + self.AttachedEntity = ents.Create( "nz_prop_effect_attachment" ) + self.AttachedEntity:SetModel( self:GetModel() ) + self.AttachedEntity:SetAngles( self:GetAngles() ) + self.AttachedEntity:SetPos( self:GetPos() ) + self.AttachedEntity:SetSkin( self:GetSkin() ) + self.AttachedEntity:Spawn() + self.AttachedEntity:SetParent( self.Entity ) + self.AttachedEntity:DrawShadow( false ) + + self:SetModel( "models/props_junk/watermelon01.mdl" ) + + self:DeleteOnRemove( self.AttachedEntity ) + + -- Don't use the model's physics - create a box instead + self:PhysicsInitBox( min, max ) + + -- Set up our physics object here + local phys = self:GetPhysicsObject() + if ( IsValid( phys ) ) then + phys:Wake() + phys:EnableGravity( false ) + phys:EnableDrag( false ) + end + + self:DrawShadow( false ) + self:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + else + + self.GripMaterial = Material( "sprites/grip" ) + + -- Get the attached entity so that clientside functions like properties can interact with it + local tab = ents.FindByClassAndParent( "nz_prop_effect_attachment", self ) + if ( tab && IsValid( tab[ 1 ] ) ) then self.AttachedEntity = tab[ 1 ] end + + end + + -- Set collision bounds exactly + self:SetCollisionBounds( min, max ) + +end + + +--[[--------------------------------------------------------- + Name: Draw +-----------------------------------------------------------]] +function ENT:Draw() + + if !nzRound:InState( ROUND_CREATE ) then return end + + -- Don't draw the grip if there's no chance of us picking it up + local ply = LocalPlayer() + local wep = ply:GetActiveWeapon() + if ( !IsValid( wep ) ) then return end + + local weapon_name = wep:GetClass() + + if ( weapon_name != "weapon_physgun" && weapon_name != "weapon_physcannon" && weapon_name != "gmod_tool" ) then + return + end + + render.SetMaterial( self.GripMaterial ) + render.DrawSprite( self:GetPos(), 16, 16, color_white ) + +end + + +--[[--------------------------------------------------------- + Name: PhysicsUpdate +-----------------------------------------------------------]] +function ENT:PhysicsUpdate( physobj ) + + if ( CLIENT ) then return end + + -- Don't do anything if the player isn't holding us + if ( !self:IsPlayerHolding() && !self:IsConstrained() ) then + + physobj:SetVelocity( Vector( 0, 0, 0 ) ) + physobj:Sleep() + + end + +end + + +--[[--------------------------------------------------------- + Name: Called after entity 'copy' +-----------------------------------------------------------]] +function ENT:OnEntityCopyTableFinish( tab ) + + -- We need to store the model of the attached entity + -- Not the one we have here. + tab.Model = self.AttachedEntity:GetModel() + + -- Store the attached entity's table so we can restore it after being pasted + tab.AttachedEntityInfo = table.Copy( duplicator.CopyEntTable( self.AttachedEntity ) ) + tab.AttachedEntityInfo.Pos = nil -- Don't even save angles and position, we are a parented entity + tab.AttachedEntityInfo.Angle = nil + + -- Do NOT store the attached entity itself in our table! + -- Otherwise, if we copy-paste the prop with the duplicator, its AttachedEntity value will point towards the original prop's attached entity instead, and that'll break stuff + tab.AttachedEntity = nil + +end + + +--[[--------------------------------------------------------- + Name: PostEntityPaste +-----------------------------------------------------------]] +function ENT:PostEntityPaste( ply ) + + -- Restore the attached entity using the information we've saved + if ( IsValid( self.AttachedEntity ) ) and ( self.AttachedEntityInfo ) then + + -- Apply skin, bodygroups, bone manipulator, etc. + duplicator.DoGeneric( self.AttachedEntity, self.AttachedEntityInfo ) + + if ( self.AttachedEntityInfo.EntityMods ) then + self.AttachedEntity.EntityMods = table.Copy( self.AttachedEntityInfo.EntityMods ) + duplicator.ApplyEntityModifiers( ply, self.AttachedEntity ) + end + + if ( self.AttachedEntityInfo.BoneMods ) then + self.AttachedEntity.BoneMods = table.Copy( self.AttachedEntityInfo.BoneMods ) + duplicator.ApplyBoneModifiers( ply, self.AttachedEntity ) + end + + self.AttachedEntityInfo = nil + + end + +end diff --git a/gamemodes/nzombies/entities/entities/nz_prop_effect_attachment.lua b/gamemodes/nzombies/entities/entities/nz_prop_effect_attachment.lua new file mode 100644 index 00000000..c439558c --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_prop_effect_attachment.lua @@ -0,0 +1,14 @@ +AddCSLuaFile() + + +ENT.Type = "anim" + +ENT.PrintName = "" +ENT.Author = "" +ENT.Contact = "" +ENT.Purpose = "" +ENT.Instructions = "" +ENT.Spawnable = false +ENT.AdminOnly = false + +-- We have absolutely nothing here. That's right, this is just to differentiate it from normal prop_dynamics \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/nz_script_prop/shared.lua b/gamemodes/nzombies/entities/entities/nz_script_prop/shared.lua new file mode 100644 index 00000000..47758313 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_script_prop/shared.lua @@ -0,0 +1,28 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "nz_script_prop" +ENT.Author = "Zet0r" +ENT.Contact = "youtube.com/Zet0r" +ENT.Purpose = "Scriptable prop for nZombies" +ENT.Instructions = "" + +function ENT:Initialize() + if SERVER then + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + --self:DrawShadow( false ) + self:SetUseType( SIMPLE_USE ) + end +end + +function ENT:OnRemove() + hook.Call("nzmapscript_PropRemoved", nil, self) +end + +if CLIENT then + function ENT:Draw() + self:DrawModel() + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/nz_script_soulcatcher/shared.lua b/gamemodes/nzombies/entities/entities/nz_script_soulcatcher/shared.lua new file mode 100644 index 00000000..9b3225e9 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_script_soulcatcher/shared.lua @@ -0,0 +1,95 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "nz_script_soulcatcher" +ENT.Author = "Zet0r" +ENT.Contact = "youtube.com/Zet0r" +ENT.Purpose = "Scriptable soul catcher for nZombies" +ENT.Instructions = "" + +function ENT:Initialize() + if SERVER then + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + --self:DrawShadow( false ) + self:SetUseType( SIMPLE_USE ) + self.CurrentAmount = 0 + self:SetTargetAmount( self.TargetAmount or 20 ) + self:SetCondition(self.Condition or function(z, dmg) return true end) -- Always allow + self:SetCatchFunction(self.CatchFunc or function(z) end) -- Nothing by default + self:SetCompleteFunction(self.CompleteFunc or function(z) end) -- Nothing either + self:SetRange(self.Range or 500) -- Default range + self:SetEnabled(self.Enabled or true) + end +end + +function ENT:OnRemove() + hook.Call("nzmapscript_SoulCatcherRemoved", nil, self) +end + +function ENT:SetCatchFunction( func ) + self.CatchFunc = func +end +function ENT:SetCompleteFunction( func ) + self.CompleteFunc = func +end +function ENT:SetTargetAmount( num ) + self.TargetAmount = tonumber(num) +end +function ENT:SetCondition( func ) + self.Condition = func +end +function ENT:SetRange( num ) + self.Range = tonumber(num)^2 +end +function ENT:SetEnabled( bool ) + self.Enabled = tobool(bool) +end +function ENT:SetReleaseOverride( func ) + self.ReleaseOverride = func +end + +function ENT:SetCurrentAmount( num ) + self.CurrentAmount = tonumber(num) +end +function ENT:Reset() + self.CurrentAmount = 0 +end + +function ENT:ReleaseSoul( z ) + if self.ReleaseOverride then + self:ReleaseOverride(z) -- You can override the effect and count logic with this + else + if self.CurrentAmount >= self.TargetAmount then return end + local e = EffectData() + e:SetOrigin(z:GetPos() + Vector(0,0,50)) + e:SetEntity(self) + util.Effect("zombie_soul", e) + self.CurrentAmount = self.CurrentAmount + 1 + end +end + +function ENT:CollectSoul() + self:CatchFunc() + if self.CurrentAmount >= self.TargetAmount then + self:CompleteFunc() + end +end + +hook.Add("EntityTakeDamage", "SoulCatchZombies", function(ent, dmg) + if ent:IsValidZombie() and ent:Health() <= dmg:GetDamage() then + for k,v in pairs(ents.FindByClass("nz_script_soulcatcher")) do + if v.Enabled and ent:GetPos():DistToSqr(v:GetPos()) <= v.Range and v:Condition(ent, dmg) then + v:ReleaseSoul(ent) + break + end + end + end +end) + +if CLIENT then + function ENT:Draw() + self:DrawModel() + end +end diff --git a/gamemodes/nzombies/entities/entities/nz_script_triggerzone/shared.lua b/gamemodes/nzombies/entities/entities/nz_script_triggerzone/shared.lua new file mode 100644 index 00000000..7f059ccc --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_script_triggerzone/shared.lua @@ -0,0 +1,102 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "triggerzone" +ENT.Author = "Zet0r" +ENT.Contact = "" +ENT.Purpose = "" +ENT.Instructions = "" + +ENT.RenderGroup = RENDERGROUP_TRANSLUCENT + +function ENT:Initialize() + if SERVER then + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_NONE ) + self:DrawShadow( false ) + self:SetUseType( SIMPLE_USE ) + self.Boundone,self.Boundtwo = self:GetCollisionBounds() + self:SetBuyFunction( function() print(self, "was bought but has no buy function") end ) + end + self:SetRenderMode( RENDERMODE_TRANSALPHA ) + self:SetColor( Color(255,200,100,150) ) +end + + +function ENT:OnRemove() + if SERVER then + nzDoors:RemoveLink( self ) + else + self:SetLocked(false) + end +end + +function ENT:CreateZoneBuy(data) + if IsValid(self) then + self:SetDoorData(data) + self:SetLocked(true) + hook.Call("OnPropDoorLinkCreated", Doors, self, data) + end +end + +function ENT:SetBuyFunction(func) + self.BuyFunction = func +end + +function ENT:SetBounds(w, l, h) + self:SetSolid( SOLID_BBOX ) + self:SetCollisionBounds( Vector(-w/2, -l/2, -h/2), Vector(w/2, l/2, h/2) ) +end + +if CLIENT then + function ENT:Draw() + if nzRound:InState( ROUND_CREATE ) then + self:DrawModel() + end + end +end + +concommand.Add("nz_testbrush2", function(ply) + local ent = ents.Create("nz_triggerzone") + ent:SetPos(ply:GetPos()) + ent:SetBounds(1000,10,10) + ent:SetMaterial("debugtools/toolswhite") + ent:SetModel("models/hunter/blocks/cube4x4x4.mdl") + ent:Spawn() + ent:SetBuyFunction( function(ent) + ent:ChatPrint("Bought!") + end ) + + undo.Create( "Test Brush 2" ) + undo.SetPlayer( ply ) + undo.AddEntity( ent ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + + print(ent) +end) + +concommand.Add("nz_testbrush5", function(ply) + local t = SysTime() + for k,v in pairs(ents.FindByClass("nz_triggerzone_2")) do + if v:NearestPoint(Entity(1):GetPos()):DistToSqr(Entity(1):GetPos()) <= 1 then + print("Found", v) + break + end + end + local time = SysTime() - t + print("Time for FindByClass", time) + + local o = SysTime() + for k,v in pairs(ents.FindInSphere(Entity(1):GetPos(), 1)) do + if v:GetClass() == "nz_triggerzone_2" then + print("Found", v) + break + end + end + local time2 = SysTime()-o + print("Time for FindInSphere", time2) + + print(time2 < time and "Sphere is fastest" or "Class is fastest") +end) + diff --git a/gamemodes/nzombies/entities/entities/nz_spawn_zombie.lua b/gamemodes/nzombies/entities/entities/nz_spawn_zombie.lua new file mode 100644 index 00000000..84d68b36 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_spawn_zombie.lua @@ -0,0 +1,93 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" +ENT.Base = "base_entity" + +ENT.PrintName = "nz_spawn_zombie" + +AccessorFunc(ENT, "iSpawnWeight", "SpawnWeight", FORCE_NUMBER) +AccessorFunc(ENT, "tZombieData", "ZombieData") +AccessorFunc(ENT, "iZombiesToSpawn", "ZombiesToSpawn", FORCE_NUMBER) +AccessorFunc(ENT, "hSpawner", "Spawner") +AccessorFunc(ENT, "dNextSpawn", "NextSpawn", FORCE_NUMBER) + +ENT.NZOnlyVisibleInCreative = true + +function ENT:DecrementZombiesToSpawn() + self:SetZombiesToSpawn( self:GetZombiesToSpawn() - 1 ) +end + +function ENT:SetupDataTables() + + self:NetworkVar( "String", 0, "Link" ) + +end + +function ENT:Initialize() + self:SetModel( "models/player/odessa.mdl" ) + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + self:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + self:SetColor(Color(0, 255, 0)) + self:DrawShadow( false ) + self:SetSpawnWeight(0) + self:SetZombiesToSpawn(0) + self:SetNextSpawn(CurTime()) +end + +function ENT:IsSuitable() + local tr = util.TraceHull( { + start = self:GetPos(), + endpos = self:GetPos(), + filter = self, + mins = Vector( -20, -20, 0 ), + maxs = Vector( 20, 20, 70 ), + ignoreworld = true, + mask = MASK_NPCSOLID + } ) + + return not tr.Hit +end + +function ENT:Think() + if SERVER then + if nzRound:InState( ROUND_PROG ) and self:GetZombiesToSpawn() > 0 then + if self:GetSpawner() and self:GetSpawner():GetNextSpawn() < CurTime() and self:GetNextSpawn() < CurTime() then + if self:IsSuitable() and nzEnemies:TotalAlive() < GetConVar("nz_difficulty_max_zombies_alive"):GetInt() then + local class = nzMisc.WeightedRandom(self:GetZombieData(), "chance") + local zombie = ents.Create(class) + zombie:SetPos(self:GetPos()) + zombie:Spawn() + -- make a reference to the spawner object used for "respawning" + zombie:SetSpawner(self:GetSpawner()) + zombie:Activate() + -- reduce zombies in queue on self and spawner object + self:GetSpawner():DecrementZombiesToSpawn() + self:DecrementZombiesToSpawn() + + hook.Call("OnZombieSpawned", nzEnemies, zombie, self ) + + if nzRound:IsSpecial() then + local data = nzRound:GetSpecialRoundData() + if data and data.spawnfunc then + data.spawnfunc(zombie) + end + end + -- Global spawner timer only set if a successful spawn happens! + self:GetSpawner():SetNextSpawn(CurTime() + self:GetSpawner():GetDelay()) + end + -- This will prevent one spawner from becoming dominant. Called any time a spawn is attempted, even if not suitable + -- to prevent constant spamming and attempting. + self:SetNextSpawn(CurTime() + self:GetSpawner():GetDelay() * 2 + math.Rand(0,0.1)) + end + end + end +end + +if CLIENT then + function ENT:Draw() + if ConVarExists("nz_creative_preview") and !GetConVar("nz_creative_preview"):GetBool() and nzRound:InState( ROUND_CREATE ) then + self:DrawModel() + end + end +end diff --git a/gamemodes/nzombies/entities/entities/nz_spawn_zombie_normal.lua b/gamemodes/nzombies/entities/entities/nz_spawn_zombie_normal.lua new file mode 100644 index 00000000..d96d732f --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_spawn_zombie_normal.lua @@ -0,0 +1,6 @@ +AddCSLuaFile( ) + +ENT.Base = "nz_spawn_zombie" +ENT.PrintName = "nz_spawn_zombie_normal" + +ENT.NZOnlyVisibleInCreative = true \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/nz_spawn_zombie_special.lua b/gamemodes/nzombies/entities/entities/nz_spawn_zombie_special.lua new file mode 100644 index 00000000..4ab175b9 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_spawn_zombie_special.lua @@ -0,0 +1,18 @@ +AddCSLuaFile( ) + +ENT.Base = "nz_spawn_zombie" +ENT.PrintName = "nz_spawn_zombie_special" + +ENT.NZOnlyVisibleInCreative = true + +function ENT:Initialize() + self:SetModel( "models/player/odessa.mdl" ) + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + self:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + self:SetColor(Color(255, 0, 0)) + self:DrawShadow( false ) + self:SetSpawnWeight(0) + self:SetZombiesToSpawn(0) + self:SetNextSpawn(CurTime()) +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/nz_trap_turret.lua b/gamemodes/nzombies/entities/entities/nz_trap_turret.lua new file mode 100644 index 00000000..dbe372cb --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_trap_turret.lua @@ -0,0 +1,123 @@ +AddCSLuaFile( ) + +-- Register teh trap +nzTraps:Register("nz_trap_turret") +ENT.PrintName = "Turret" +ENT.SpawnIcon = "models/weapons/w_mach_m249para.mdl" +ENT.Description = "Simple Turret trap that will attack zombies around it." + +ENT.Type = "anim" +ENT.Base = "nz_trapbase" + +ENT.fFireRate = 0.1 + +DEFINE_BASECLASS("nz_trapbase") + +function ENT:SetupDataTables() + BaseClass.SetupDataTables(self) + + self:NetworkVar( "Int", 1, "AttackRange", {KeyName = "nz_turret_attack_range", Edit = {order = 10, type = "Int", min = 0, max = 100000}} ) + self:NetworkVar( "Int", 2, "DamagePerHit", {KeyName = "nz_turret_damage", Edit = {order = 11, type = "Int", min = 0, max = 100000}} ) + + self:SetAttackRange(1200) + self:SetDamagePerHit(20) +end + +function ENT:Initialize() + self:SetModel( "models/weapons/w_mach_m249para.mdl" ) + self:SetModelScale(1.5) + self:PhysicsInit( SOLID_VPHYSICS ) + self:SetSolid( SOLID_VPHYSICS ) + + local phys = self:GetPhysicsObject() + phys:EnableMotion(false) + + self.fLastTargetCheck = CurTime() + self.fNextFire = CurTime() +end + +-- IMPLEMENT ME +function ENT:OnActivation() + self:SetActive(true) +end + +function ENT:OnDeactivation() + self:SetActive(false) +end + +function ENT:OnReady() end + +function ENT:OnRemove() + +end + +function ENT:Think() + if SERVER then + if not self:GetActive() then return end + + if self.fLastTargetCheck + 0.5 < CurTime() and not self:HasValidTarget() then + self:SetTarget(self:GetPriorityTarget()) + end + + if self:HasValidTarget() then + local targetpos = self.eTarget:GetPos() + self.eTarget:OBBCenter() + local att = self:LookupAttachment( "muzzle" ) + local muzzlePos = self:GetAttachment( att ).Pos + + local angle = (targetpos - self:GetPos()):Angle() + + self:SetAngles(angle) + + if self.fNextFire < CurTime() then + local bullet = { + Damage = self:GetDamagePerHit(), + Force = 3, + Src = muzzlePos, + Dir = self:GetForward(), + Distance = self:GetAttackRange() * 2, + Spread = Vector(0.2,0.2,0), + AmmoType = "Pistol", + Tracer = 1, + TracerName + } + + self:EmitSound("npc/sniper/sniper1.wav") + + self:FireBullets(bullet) + + self.fNextFire = CurTime() + self.fFireRate + end + end + end +end + +function ENT:SetTarget( target ) + self.eTarget = target +end + +function ENT:GetTarget() + return self.eTarget +end + +function ENT:HasValidTarget() + return IsValid(self:GetTarget()) and self:GetTarget():IsValidZombie() and self:GetPos():Distance(self.eTarget:GetPos()) < self:GetAttackRange() and self.eTarget:Health() > 0 and self.eTarget:Visible(self) +end + +--Targetfinding +function ENT:GetPriorityTarget() + + self.fLastTargetCheck = CurTime() + + local possibleTargets = ents.FindInSphere(self:GetPos(), self:GetAttackRange()) + + local zombies = {} + + for _, ent in pairs(possibleTargets) do + if ent:IsValidZombie() and ent:Visible(self) then + table.insert(zombies, ent) + end + end + + return table.Random(zombies) + +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/nz_trap_zapper.lua b/gamemodes/nzombies/entities/entities/nz_trap_zapper.lua new file mode 100644 index 00000000..9e07168d --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_trap_zapper.lua @@ -0,0 +1,105 @@ +AddCSLuaFile( ) + +-- Register teh trap +nzTraps:Register("nz_trap_zapper") +ENT.PrintName = "Tesla Coil" +ENT.SpawnIcon = "models/nzprops/zapper_coil.mdl" +ENT.Description = "Tesla trap that will kill zombies in front of it." + +ENT.Type = "anim" +ENT.Base = "nz_trapbase" + +ENT.MatDebug = Material("cable/cable2") + +DEFINE_BASECLASS("nz_trapbase") + +function ENT:SetupDataTables() + BaseClass.SetupDataTables( self ) + + self:NetworkVar( "Float", 2, "ZapDelayMin", {KeyName = "nz_zap_delay_min", Edit = {order = 20, type = "Float", min = 0, max = 100000}} ) + self:NetworkVar( "Float", 3, "ZapDelayMax", {KeyName = "nz_zap_delay_max", Edit = {order = 21, type = "Float", min = 0, max = 100000}} ) + self:NetworkVar( "Float", 4, "NextZap" ) + + self:SetZapDelayMin(0.5) + self:SetZapDelayMax(1) +end + +function ENT:Initialize() + self:SetModel("models/nzprops/zapper_coil.mdl") + self:SetModelScale(1.2) + self:PhysicsInit( SOLID_VPHYSICS ) + self:SetSolid( SOLID_VPHYSICS ) + + local phys = self:GetPhysicsObject() + phys:EnableMotion(false) + + -- self:SetAngles(Angle(180, 0, 0)) +end + +-- IMPLEMENT ME +function ENT:OnActivation() + if SERVER then + self:SetNextZap(CurTime() + math.Rand(self:GetZapDelayMin(), self:GetZapDelayMax())) + + --[[local tr = util.TraceLine({ + start = self:GetPos(), + endpos = self:GetPos() + self:GetUp() * 500, + mask = MASK_SOLID_BRUSHONLY, + }) + + debugoverlay.Cross(tr.HitPos, 30, 5) + debugoverlay.Cross(self:GetPos(), 30, 5) + print("Yeh", self:GetPos(), tr.HitPos, Entity(1):GetPos()) + + + + self:SetCollisionBoundsWS(pos1, pos2)]] + end +end + +function ENT:OnDeactivation() + +end + +function ENT:OnReady() end + +function ENT:Think() + if SERVER and self:IsActive() and self:GetNextZap() < CurTime() then + self:Zap() + end +end + +if CLIENT then + function ENT:Draw() + BaseClass.Draw(self) + local texcoord = math.Rand( 0, 1 ) + render.SetMaterial(self.MatDebug) + render.DrawBeam(self:GetPos() + self:GetUp() * 10, self:GetPos() + self:GetUp() * 70, 1, texcoord, texcoord + 1, Color( 250, 150, 106 )) + end +end + +function ENT:Zap() + local tr = util.QuickTrace(self:GetPos(), self:GetUp() * 500, self) + + local ent = tr.Entity + self:ZapTarget(ent) + + self:SetNextZap(CurTime() + math.Rand(self:GetZapDelayMin(), self:GetZapDelayMax())) + + -- render effect + effectData = EffectData() + -- startpos + effectData:SetStart(self:GetPos() + self:GetUp() * 10) + -- end pos + effectData:SetOrigin(tr.HitPos) + -- duration + effectData:SetMagnitude(0.5) + + util.Effect("zapper_lightning", effectData) +end + +function ENT:ZapTarget(ent) + if IsValid(ent) and ent:IsValidZombie() then + ent:Kill() + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/nz_trapbase.lua b/gamemodes/nzombies/entities/entities/nz_trapbase.lua new file mode 100644 index 00000000..9ec6679b --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_trapbase.lua @@ -0,0 +1,23 @@ +-- Use this class as base when creating traps + +AddCSLuaFile( ) + +ENT.Type = "anim" +ENT.Base = "nz_activatable" + +ENT.PrintName = "nz_trapbase" + +DEFINE_BASECLASS("nz_activatable") + +function ENT:SetupDataTables() + BaseClass.SetupDataTables( self ) + + self:SetRemoteActivated(true) +end + +-- IMPLEMENT ME +function ENT:OnActivation() end + +function ENT:OnDeactivation() end + +function ENT:OnReady() end diff --git a/gamemodes/nzombies/entities/entities/nz_ytil_ball.lua b/gamemodes/nzombies/entities/entities/nz_ytil_ball.lua new file mode 100644 index 00000000..0bd7ddf5 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_ytil_ball.lua @@ -0,0 +1,214 @@ + +AddCSLuaFile() + +local BounceSound = Sound( "garrysmod/balloon_pop_cute.wav" ) + +DEFINE_BASECLASS( "base_anim" ) + +ENT.PrintName = "You Touched it Last Bouncy Ball" +ENT.Author = "Zet0r" +ENT.Information = "A bouncy ball that kill zombies! What could be better?! :D" + +ENT.Spawnable = false +ENT.AdminOnly = false +ENT.RenderGroup = RENDERGROUP_BOTH + +function ENT:SetupDataTables() + + self:NetworkVar( "Int", 0, "MaxKills" ) + self:NetworkVar( "Int", 1, "CurKills" ) + self:NetworkVar( "Entity", 0, "BallOwner" ) + self:NetworkVar( "Bool", 0, "Fragment" ) + self:NetworkVar( "Int", 2, "BallColor" ) + +end + +--[[--------------------------------------------------------- + Name: Initialize +-----------------------------------------------------------]] +function ENT:Initialize() + + if ( SERVER ) then + + local size = self:GetFragment() and 2 or 10 + + -- Use the helibomb model just for the shadow (because it's about the same size) + self:SetModel( "models/Combine_Helicopter/helicopter_bomb01.mdl" ) + + -- Don't use the model's physics - create a sphere instead + self:PhysicsInitSphere( size, "metal_bouncy" ) + + -- Wake the physics object up. It's time to have fun! + local phys = self:GetPhysicsObject() + if ( IsValid( phys ) ) then + phys:Wake() + end + + -- Set collision bounds exactly + self:SetCollisionBounds( Vector( -size, -size, -size ), Vector( size, size, size ) ) + + else + + self.LightColor = Vector( 0, 0, 0 ) + + end + +end + +if ( CLIENT ) then + + local mat = Material( "sprites/sent_ball" ) + function ENT:Draw() + local pos = self:GetPos() + --local vel = self:GetVelocity() + local size = self:GetFragment() and 4 or 20 + local pct = self:GetCurKills() / self:GetMaxKills() + + render.SetMaterial( mat ) + local c = self:GetBallColor() + local color = HSVToColor(self:GetBallColor(), 1 - pct, 1) + render.DrawSprite( pos, size, size, color ) + end + +end + + +--[[--------------------------------------------------------- + Name: PhysicsCollide +-----------------------------------------------------------]] +function ENT:PhysicsCollide( data, physobj ) + + -- Play sound on bounce + if ( data.Speed > 60 && data.DeltaTime > 0.2 ) then + + local size = self:GetFragment() and 4 or 20 + local pitch = 32 + 128 - size + self:EmitSound( BounceSound, 75, math.random( pitch - 10, pitch + 10 ) ) + + end + + -- Bounce like a crazy bitch + local LastSpeed = math.max( data.OurOldVelocity:Length(), data.Speed ) + local NewVelocity = physobj:GetVelocity() + NewVelocity:Normalize() + + LastSpeed = math.max( NewVelocity:Length(), LastSpeed ) + + local TargetVelocity = NewVelocity * LastSpeed * 0.7 + + physobj:SetVelocity( TargetVelocity ) + + if self.pap and !self.exploded then + local numfragments = math.Round((self:GetMaxKills() - self:GetCurKills())/2) + for i = 1, numfragments do + local dir = Angle(0, -180 + (360/numfragments)*i + math.random(-10, 10), -50):Forward() + + local frag = ents.Create("nz_ytil_ball") + frag:SetFragment(true) + frag:SetPos(self:GetPos() + dir * 5) + frag:SetMaxKills(3) + frag:SetCurKills(0) + frag:SetBallColor(self:GetBallColor()) + frag:SetBallOwner(self:GetBallOwner()) + frag:Spawn() + frag:Activate() + + local fragPhys = frag:GetPhysicsObject() + if IsValid(fragPhys) then + fragPhys:ApplyForceCenter(dir * math.random(100,250) + TargetVelocity/2) + end + end + + local pos = self:GetPos() + local effectdata = EffectData() + effectdata:SetOrigin( pos ) + util.Effect( "HelicopterMegaBomb", effectdata ) + self.exploded = true + self:SetCurKills(self:GetCurKills() + math.ceil((self:GetMaxKills() - self:GetCurKills())*0.33)) + end + +end + +--[[--------------------------------------------------------- + Name: OnTakeDamage +-----------------------------------------------------------]] +function ENT:OnTakeDamage( dmginfo ) + + -- React physically when shot/getting blown + self:TakePhysicsDamage( dmginfo ) + +end + + +--[[--------------------------------------------------------- + Name: Use +-----------------------------------------------------------]] +function ENT:Use( activator, caller ) + + if IsValid(activator) and self:GetBallOwner() == activator and !self:GetFragment() then + local wep + for k,v in pairs(activator:GetWeapons()) do + if v:GetClass() == "nz_touchedlast" then wep = v break end + end + if !IsValid(wep) then return end + if wep:Clip1() >= 1 then return end + wep:ReplenishBall(self:GetCurKills()) + self:Remove() + end + +end + +--[[--------------------------------------------------------- + Name: StartTouch +-----------------------------------------------------------]] +function ENT:StartTouch( ent ) + + if IsValid(ent) and nzConfig.ValidEnemies[ent:GetClass()] then + if self:GetCurKills() < self:GetMaxKills() then + local insta = DamageInfo() + insta:SetDamage( 500 ) + insta:SetAttacker( self:GetBallOwner() ) + insta:SetDamageType( DMG_BLAST_SURFACE ) + ent:TakeDamageInfo( insta ) + self:SetCurKills(self:GetCurKills() + 1) + + -- If it runs out of kills, we gotta kill it if it doesn't have an owner + if self:GetCurKills() >= self:GetMaxKills() then + if !IsValid(self:GetBallOwner()) or self:GetFragment() then + local pos = self:GetPos() + local effectdata = EffectData() + effectdata:SetOrigin( pos ) + util.Effect( "HelicopterMegaBomb", effectdata ) + self:Remove() + else + local exists = false + -- Or if the owner doesn't have a weapon with a free ball slot (max ammo or replaced) + for k,v in pairs(self:GetBallOwner():GetWeapons()) do + if v:GetClass() == "nz_touchedlast" then + if v:Clip1() < 1 then + exists = true + end + break + end + end + if !exists then + local pos = self:GetPos() + local effectdata = EffectData() + effectdata:SetOrigin( pos ) + util.Effect( "HelicopterMegaBomb", effectdata ) + self:Remove() + end + end + end + end + end + +end + +function ENT:UpdateTransmitState() + return TRANSMIT_ALWAYS +end + +function ENT:OnRemove() + +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/nz_zombie_boss_panzer.lua b/gamemodes/nzombies/entities/entities/nz_zombie_boss_panzer.lua new file mode 100644 index 00000000..b4755d96 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_zombie_boss_panzer.lua @@ -0,0 +1,711 @@ +AddCSLuaFile() + +ENT.Base = "nz_zombiebase" +ENT.PrintName = "Panzersoldat" +ENT.Category = "Brainz" +ENT.Author = "Zet0r" + +ENT.Models = { "models/nz_zombie/zombie_panzersoldat.mdl" } + +ENT.AttackRange = 80 +ENT.DamageLow = 90 +ENT.DamageHigh = 180 + +ENT.RedEyes = true + +ENT.AttackSequences = { + {seq = "nz_melee1"}, + {seq = "nz_melee2"}, +} + +ENT.DeathSequences = { + "nz_death", +} + +ENT.AttackSounds = { + "nz/panzer/attack/mech_swing_00.wav", + "nz/panzer/attack/mech_swing_01.wav", + "nz/panzer/attack/mech_swing_02.wav", +} + +ENT.AttackHitSounds = { + "nz/panzer/attack/mech_swing_00.wav", + "nz/panzer/attack/mech_swing_01.wav", + "nz/panzer/attack/mech_swing_02.wav", +} + +ENT.WalkSounds = { + "nz/panzer/ambient/mech_ambi_00.wav", + "nz/panzer/ambient/mech_ambi_01.wav", + "nz/panzer/ambient/mech_ambi_02.wav", +} + +ENT.ActStages = { + [1] = { + act = ACT_WALK, + minspeed = 5, + }, + [2] = { + act = ACT_WALK_ANGRY, + minspeed = 50, + }, + [3] = { + act = ACT_RUN, + minspeed = 150, + }, + [4] = { + act = ACT_RUN, + minspeed = 160, + }, +} + +-- We overwrite the Init function because we do not change bodygroups randomly! +function ENT:Initialize() + + self:Precache() + + self:SetModel( self.Models[math.random( #self.Models )] ) + + self:SetJumping( false ) + self:SetLastLand( CurTime() + 1 ) --prevent jumping after spawn + self:SetLastTargetCheck( CurTime() ) + self:SetLastTargetChange( CurTime() ) + + --sounds + self:SetNextMoanSound( CurTime() + 1 ) + + --stuck prevetion + self:SetLastPush( CurTime() ) + self:SetLastPostionSave( CurTime() ) + self:SetStuckAt( self:GetPos() ) + self:SetStuckCounter( 0 ) + + self:SetAttacking( false ) + self:SetLastAttack( CurTime() ) + self:SetAttackRange( self.AttackRange ) + self:SetTargetCheckRange(0) -- 0 for no distance restriction (infinite) + + --target ignore + self:ResetIgnores() + + self:SetHealth( 75 ) --fallback + + self:SetRunSpeed( self.RunSpeed ) --fallback + self:SetWalkSpeed( self.WalkSpeed ) --fallback + + self:SetCollisionBounds(Vector(-16,-16, 0), Vector(16, 16, 70)) + + self:SetActStage(0) + self:SetSpecialAnimation(false) + + self:StatsInitialize() + self:SpecialInit() + + -- Fallback for buggy tool + if !self:GetRunSpeed() then self:SetRunSpeed(150) end + + if SERVER then + self.loco:SetDeathDropHeight( self.DeathDropHeight ) + self.loco:SetDesiredSpeed( self:GetRunSpeed() ) + self.loco:SetAcceleration( self.Acceleration ) + self.loco:SetJumpHeight( self.JumpHeight ) + if GetConVar("nz_zombie_lagcompensated"):GetBool() then + self:SetLagCompensated(true) + end + + self.HelmetDamage = 0 -- Used to save how much damage the light has taken + self:SetUsingClaw(false) + + self.NextAction = 0 + self.NextClawTime = 0 + self.NextFlameTime = 0 + end + + self.ZombieAlive = true + +end + +function ENT:StatsInitialize() + if SERVER then + self:SetRunSpeed(150) + self:SetHealth(1000) + self:SetMaxHealth(1000) + end + self:SetCollisionBounds(Vector(-20,-20, 0), Vector(20, 20, 100)) + + --PrintTable(self:GetSequenceList()) +end + +function ENT:SpecialInit() + + if CLIENT then + --make them invisible for a really short duration to blend the emerge sequences + self:SetNoDraw(true) + self:TimedEvent( 0.15, function() + self:SetNoDraw(false) + end) + + self:SetRenderClipPlaneEnabled( true ) + self:SetRenderClipPlane(self:GetUp(), self:GetUp():Dot(self:GetPos())) + + self:TimedEvent( 2, function() + self:SetRenderClipPlaneEnabled(false) + end) + + end +end + +function ENT:InitDataTables() + self:NetworkVar("Entity", 0, "ClawHook") + self:NetworkVar("Bool", 1, "UsingClaw") + self:NetworkVar("Bool", 2, "Flamethrowing") +end + +function ENT:OnSpawn() + local seq = "nz_entry" + local tr = util.TraceLine({ + start = self:GetPos() + Vector(0,0,500), + endpos = self:GetPos(), + filter = self, + mask = MASK_SOLID_BRUSHONLY, + }) + if tr.Hit then seq = "nz_entry_instant" end + local _, dur = self:LookupSequence(seq) + + -- play emerge animation on spawn + -- if we have a coroutine else just spawn the zombie without emerging for now. + if coroutine.running() then + + local pos = self:GetPos() + (seq == "nz_entry_instant" and Vector(0,0,100) or Vector(0,0,450)) + + local effectData = EffectData() + effectData:SetStart( pos ) + effectData:SetOrigin( pos ) + effectData:SetMagnitude(dur) + util.Effect("panzer_spawn_tp", effectData) + + --[[effectData = EffectData() + effectData:SetStart( pos + Vector(0, 0, 1000) ) + effectData:SetOrigin( pos ) + effectData:SetMagnitude( 0.75 ) + util.Effect("lightning_strike", effectData)]] + + self:TimedEvent(dur - 2.1, function() + --dust cloud + local effectData = EffectData() + effectData:SetStart( self:GetPos() ) + effectData:SetOrigin( self:GetPos() ) + effectData:SetMagnitude(dur) + util.Effect("panzer_land_dust", effectData) + end) + self:PlaySequenceAndWait(seq) + end +end + +function ENT:OnZombieDeath(dmgInfo) + + self:ReleasePlayer() + self:StopFlames() + self:SetRunSpeed(0) + self.loco:SetVelocity(Vector(0,0,0)) + self:Stop() + self:SetCollisionGroup(COLLISION_GROUP_DEBRIS) + local seq, dur = self:LookupSequence(self.DeathSequences[math.random(#self.DeathSequences)]) + self:ResetSequence(seq) + self:SetCycle(0) + + timer.Simple(dur - 0.5, function() + if IsValid(self) then + self:EmitSound("nz/panzer/mech_explode.wav") + end + end) + timer.Simple(dur, function() + if IsValid(self) then + self:Remove() + local effectData = EffectData() + effectData:SetStart( self:GetPos() ) + effectData:SetOrigin( self:GetPos() ) + effectData:SetMagnitude(2) + util.Effect("Explosion", effectData) + end + end) + +end + +function ENT:BodyUpdate() + + self.CalcIdeal = ACT_IDLE + + local velocity = self:GetVelocity() + + local len2d = velocity:Length2D() + + if ( len2d > 60 ) then self.CalcIdeal = ACT_RUN elseif ( len2d > 5 ) then self.CalcIdeal = ACT_WALK end + + if self:IsJumping() and self:WaterLevel() <= 0 then + self.CalcIdeal = ACT_JUMP + end + + if !self:GetSpecialAnimation() and !self:IsAttacking() then + if self:GetActivity() != self.CalcIdeal and !self:GetStop() then self:StartActivity(self.CalcIdeal) end + + if self.ActStages[self:GetActStage()] then + self:BodyMoveXY() + end + end + + self:FrameAdvance() + +end + +function ENT:OnTargetInAttackRange() + local atkData = {} + atkData.dmglow = 90 + atkData.dmghigh = 180 + atkData.dmgforce = Vector( 0, 0, 0 ) + atkData.dmgdelay = 0.6 + self:Attack( atkData ) +end + +function ENT:IsValidTarget( ent ) + if !ent then return false end + return IsValid( ent ) and ent:GetTargetPriority() != TARGET_PRIORITY_NONE and ent:GetTargetPriority() != TARGET_PRIORITY_SPECIAL + -- Won't go for special targets (Monkeys), but still MAX, ALWAYS and so on +end + +-- This function is run every time a path times out, once every 1 seconds of pathing +function ENT:OnPathTimeOut() + local target = self:GetTarget() + if CurTime() < self.NextAction then return end + + if math.random(0,5) == 0 and CurTime() > self.NextClawTime then + -- Claw + if self:IsValidTarget(target) then + local tr = util.TraceLine({ + start = self:GetPos() + Vector(0,50,0), + endpos = target:GetPos() + Vector(0,0,50), + filter = self, + }) + + if IsValid(tr.Entity) and self:IsValidTarget(tr.Entity) and !IsValid(self.ClawHook) then + self:Stop() + self:PlaySequenceAndWait("nz_grapple_aim") + self.loco:SetDesiredSpeed(0) + --self:SetSequence(self:LookupSequence("nz_grapple_loop")) + self:SetBodygroup(2, 1) + + local clawpos = self:GetAttachment(self:LookupAttachment("clawlight")).Pos + self.ClawHook = ents.Create("nz_panzer_claw") + self.ClawHook:SetPos(clawpos) + self.ClawHook:Spawn() + self.ClawHook:Launch(((tr.Entity:GetPos() + Vector(0,0,50)) - self.ClawHook:GetPos()):GetNormalized()) + self:SetClawHook(self.ClawHook) + self:SetUsingClaw(true) + self.ClawHook:SetPanzer(self) + self:SetAngles((target:GetPos() - self:GetPos()):Angle()) + + self.NextAction = CurTime() + math.random(1, 5) + self.NextClawTime = CurTime() + math.random(3, 15) + end + end + elseif CurTime() > self.NextFlameTime then + -- Flamethrower + if self:IsValidTarget(target) and self:GetPos():DistToSqr(target:GetPos()) <= 75000 then + self:Stop() + self:PlaySequenceAndWait("nz_flamethrower_aim") + self.loco:SetDesiredSpeed(0) + local ang = (target:GetPos() - self:GetPos()):Angle() + self:SetAngles(Angle(ang[1], ang[2] + 10, ang[3])) + + self:StartFlames() + local seq = math.random(0,1) == 0 and "nz_flamethrower_loop" or "nz_flamethrower_sweep" + local id, dur = self:LookupSequence(seq) + self:ResetSequence(id) + self:SetCycle(0) + self:SetPlaybackRate(1) + self:SetVelocity(Vector(0,0,0)) + + self:TimedEvent(dur, function() + self.loco:SetDesiredSpeed(self:GetRunSpeed()) + self:SetSpecialAnimation(false) + self:SetBlockAttack(false) + self:StopFlames() + end) + + self.NextAction = CurTime() + math.random(1, 5) + self.NextFlameTime = CurTime() + math.random(1, 10) + end + end +end + +if CLIENT then + local eyeGlow = Material( "sprites/redglow1" ) + local white = Color( 255, 255, 255, 255 ) + local lightglow = Material( "sprites/physg_glow1_noz" ) + local lightyellow = Color( 255, 255, 200, 200 ) + local clawglow = Material( "sprites/orangecore1" ) + local clawred = Color( 255, 100, 100, 255 ) + function ENT:Draw() + self:DrawModel() + + local dlight = DynamicLight( self:EntIndex() ) + if ( dlight ) then + local bone = self:LookupBone("j_spinelower") + local pos, ang = self:GetBonePosition(bone) + pos = pos + ang:Right()*-8 + ang:Forward()*25 + dlight.pos = pos + dlight.r = 255 + dlight.g = 255 + dlight.b = 255 + dlight.brightness = 10 + dlight.Decay = 1000 + dlight.Size = 16 + dlight.DieTime = CurTime() + 1 + dlight.dir = ang:Right() + ang:Forward() + dlight.innerangle = 1 + dlight.outerangle = 1 + dlight.style = 0 + dlight.noworld = true + end + + if self.RedEyes then + --local eyes = self:GetAttachment(self:LookupAttachment("eyes")).Pos + --local leftEye = eyes + self:GetRight() * -1.5 + self:GetForward() * 0.5 + --local rightEye = eyes + self:GetRight() * 1.5 + self:GetForward() * 0.5 + + local leftEye = self:GetAttachment(self:LookupAttachment("lefteye")).Pos + local rightEye = self:GetAttachment(self:LookupAttachment("righteye")).Pos + cam.Start3D() + render.SetMaterial( eyeGlow ) + render.DrawSprite( leftEye, 4, 4, white) + render.DrawSprite( rightEye, 4, 4, white) + cam.End3D() + end + if GetConVar( "nz_zombie_debug" ):GetBool() then + render.DrawWireframeBox(self:GetPos(), Angle(0,0,0), self:OBBMins(), self:OBBMaxs(), Color(255,0,0), true) + render.DrawWireframeSphere(self:GetPos(), self:GetAttackRange(), 10, 10, Color(255,165,0), true) + end + + --debugoverlay.Cross(finalpos, 5) + --debugoverlay.Line(finalpos, finalpos + ang:Forward()*10, 1, Color(0,255,0)) + --debugoverlay.Line(finalpos, finalpos + ang:Right()*5, 1, Color(0,255,0)) + if self:GetBodygroup(1) == 0 then + local bone = self:LookupBone("j_helmet") + local pos, ang = self:GetBonePosition(bone) + local finalpos = pos + ang:Forward()*20 + ang:Up()*10 + + cam.Start3D2D(finalpos, ang, 1) + surface.SetMaterial(lightglow) + surface.SetDrawColor(lightyellow) + surface.DrawTexturedRect(-50,-10,100,20) + cam.End3D2D() + + ang:RotateAroundAxis(ang:Forward(),90) + + --debugoverlay.Line(finalpos, finalpos + ang:Forward()*15, 1, Color(255,0,0)) + --debugoverlay.Line(finalpos, finalpos + ang:Right()*5, 1, Color(255,0,0)) + + cam.Start3D2D(finalpos, ang, 1) + surface.SetMaterial(lightglow) + surface.SetDrawColor(lightyellow) + surface.DrawTexturedRect(-50,-10,100,20) + cam.End3D2D() + end + + if self:GetBodygroup(2) == 1 then + local att = self:GetAttachment(self:LookupAttachment("clawlight")) + local pos, ang = att.Pos, att.Ang + ang:RotateAroundAxis(ang:Right(),-90) + + --debugoverlay.Line(pos, pos + ang:Forward()*10, 1, Color(0,255,0)) + --debugoverlay.Line(pos, pos + ang:Right()*5, 1, Color(0,255,0)) + + cam.Start3D2D(pos, ang, 1) + surface.SetMaterial(clawglow) + surface.SetDrawColor(clawred) + surface.DrawTexturedRect(-5,-5,10,10) + cam.End3D2D() + end + + end +end + +function ENT:OnInjured( dmgInfo ) + local hitpos = dmgInfo:GetDamagePosition() + + if !self.HelmetLost then + local bone = self:LookupBone("j_helmet") + local pos, ang = self:GetBonePosition(bone) + local finalpos = pos + ang:Forward()*8 + ang:Up()*11 + + if hitpos:DistToSqr(finalpos) < 50 then + self.HelmetDamage = self.HelmetDamage + dmgInfo:GetDamage() + if self.HelmetDamage > (self:GetMaxHealth() * 0.01) then + self.HelmetLost = true + self:ManipulateBonePosition(bone, Vector(0,0,-75)) + self:SetBodygroup(1, 1) + self:SetSpecialAnimation(true) + self:SetBlockAttack(true) + self:ReleasePlayer() + self:StopFlames() + local id, dur = self:LookupSequence("nz_crit_head") + self:ResetSequence(id) + self:SetCycle(0) + self:SetPlaybackRate(1) + self.loco:SetDesiredSpeed(0) + self:SetVelocity(Vector(0,0,0)) + self:TimedEvent(dur, function() + self.loco:SetDesiredSpeed(self:GetRunSpeed()) + self:SetSpecialAnimation(false) + self:SetBlockAttack(false) + end) + end + end + + dmgInfo:ScaleDamage(0.1) -- When the helmet isn't lost, all damage only deals 10% + else + local bone = self:LookupBone("j_head") + local pos, ang = self:GetBonePosition(bone) + local finalpos = pos + ang:Up()*4 + + if hitpos:DistToSqr(finalpos) < 150 then + -- No damage scaling on headshot, we keep it at 1x + else + dmgInfo:ScaleDamage(0.1) -- When the helmet is lost, a non-headshot still only deals 10% + end + end + + if self:GetUsingClaw() then + local pos = self:GetAttachment(self:LookupAttachment("clawlight")).Pos + if hitpos:DistToSqr(pos) <= 25 then + self:SetSpecialAnimation(true) + self:SetBlockAttack(true) + self:ReleasePlayer() + self:StopFlames() + local id, dur = self:LookupSequence("nz_crit_grapple") + self:ResetSequence(id) + self:SetCycle(0) + self:SetPlaybackRate(1) + self.loco:SetDesiredSpeed(0) + self:SetVelocity(Vector(0,0,0)) + self:TimedEvent(dur, function() + self.loco:SetDesiredSpeed(self:GetRunSpeed()) + self:SetSpecialAnimation(false) + self:SetBlockAttack(false) + end) + end + end +end + +function ENT:OnRemove() + if IsValid(self.ClawHook) then self.ClawHook:Remove() end + if IsValid(self.GrabbedPlayer) then self.GrabbedPlayer:SetMoveType(MOVETYPE_WALK) end + if IsValid(self.FireEmitter) then self.FireEmitter:Finish() end +end + +function ENT:StartFlames(time) + self:Stop() + self:SetFlamethrowing(true) + + if time then self:TimedEvent(time, function() self:StopFlames() end) end +end + +function ENT:StopFlames() + self:SetFlamethrowing(false) + self:SetStop(false) +end + +function ENT:OnThink() + if self:GetFlamethrowing() then + if !self.NextFireParticle or self.NextFireParticle < CurTime() then + local bone = self:LookupBone("j_elbow_ri") + local pos, ang = self:GetBonePosition(bone) + pos = pos - ang:Forward() * 40 - ang:Up()*10 + if CLIENT then + if !IsValid(self.FireEmitter) then self.FireEmitter = ParticleEmitter(self:GetPos(), false) end + + local p = self.FireEmitter:Add("particles/fire1.vmt", pos) + if p then + p:SetColor(math.random(30,60), math.random(40,70), math.random(0,50)) + p:SetStartAlpha(255) + p:SetEndAlpha(0) + p:SetVelocity(ang:Forward() * -150 + ang:Up()*math.random(-5,5) + ang:Right()*math.random(-5,5)) + p:SetLifeTime(0.25) + + p:SetDieTime(math.Rand(0.75, 1.5)) + + p:SetStartSize(math.random(1, 5)) + p:SetEndSize(math.random(20, 30)) + p:SetRoll(math.random(-180, 180)) + p:SetRollDelta(math.Rand(-0.1, 0.1)) + p:SetAirResistance(50) + + p:SetCollide(false) + + p:SetLighting(false) + end + else + if IsValid(self.GrabbedPlayer) then + if self.GrabbedPlayer:GetPos():DistToSqr(self:GetPos()) > 10000 then + self:ReleasePlayer() + self:StopFlames() + self.loco:SetDesiredSpeed(self:GetRunSpeed()) + self:SetSpecialAnimation(false) + self:SetBlockAttack(false) + self:SetStop(false) + else + local dmg = DamageInfo() + dmg:SetAttacker(self) + dmg:SetInflictor(self) + dmg:SetDamage(2) + dmg:SetDamageType(DMG_BURN) + + self.GrabbedPlayer:TakeDamageInfo(dmg) + self.GrabbedPlayer:Ignite(1, 0) + end + else + local tr = util.TraceHull({ + start = pos, + endpos = pos - ang:Forward()*150, + filter = self, + --mask = MASK_SHOT, + mins = Vector( -5, -5, -10 ), + maxs = Vector( 5, 5, 10 ), + }) + + debugoverlay.Line(pos, pos - ang:Forward()*150) + + if self:IsValidTarget(tr.Entity) then + local dmg = DamageInfo() + dmg:SetAttacker(self) + dmg:SetInflictor(self) + dmg:SetDamage(2) + dmg:SetDamageType(DMG_BURN) + + tr.Entity:TakeDamageInfo(dmg) + tr.Entity:Ignite(2, 0) + end + end + end + + self.NextFireParticle = CurTime() + 0.05 + end + elseif CLIENT and self.FireEmitter then + self.FireEmitter:Finish() + self.FireEmitter = nil + end + + if SERVER and IsValid(self.GrabbedPlayer) and !self:IsValidTarget(self.GrabbedPlayer) then + self:ReleasePlayer() + self:StopFlames() + end +end + +function ENT:GrabPlayer(ply) + if CLIENT then return end + + self:SetBodygroup(2,0) + self:SetUsingClaw(false) + self:SetStop(false) + self.loco:SetDesiredSpeed(self:GetRunSpeed()) + + if self:IsValidTarget(ply) then + self.GrabbedPlayer = ply + + self:TimedEvent(0, function() + local att = self:GetAttachment(self:LookupAttachment("clawlight")) + local pos = att.Pos + att.Ang:Forward()*10 + + ply:SetPos(pos - Vector(0,0,50)) + ply:SetMoveType(MOVETYPE_NONE) + end) + + + self:SetSequence(self:LookupSequence("nz_grapple_flamethrower")) + self:SetCycle(0) + self:StartFlames() + --[[elseif ply then + self.loco:SetDesiredSpeed(self:GetRunSpeed()) + self:SetSpecialAnimation(false) + self:SetBlockAttack(false) + self:SetStop(false)]] + else + + end +end + +function ENT:ReleasePlayer() + if IsValid(self.GrabbedPlayer) then + self.GrabbedPlayer:SetMoveType(MOVETYPE_WALK) + end + if IsValid(self.ClawHook) then + self.ClawHook:Release() + end + if !self:GetFlamethrowing() then + self:SetStop(false) + end + self:SetUsingClaw(false) + self:SetStop(false) + self.loco:SetDesiredSpeed(self:GetRunSpeed()) +end + +function ENT:OnBarricadeBlocking( barricade ) + if (IsValid(barricade) and barricade:GetClass() == "breakable_entry" ) then + if barricade:GetNumPlanks() > 0 then + timer.Simple(0.3, function() + + for i = 1, barricade:GetNumPlanks() do + barricade:EmitSound("physics/wood/wood_plank_break" .. math.random(1, 4) .. ".wav", 100, math.random(90, 130)) + barricade:RemovePlank() + end + + end) + + self:SetAngles(Angle(0,(barricade:GetPos()-self:GetPos()):Angle()[2],0)) + + local seq, dur + + local attacktbl = self.ActStages[1] and self.ActStages[1].attackanims or self.AttackSequences + local target = type(attacktbl) == "table" and attacktbl[math.random(#attacktbl)] or attacktbl + + if type(target) == "table" then + seq, dur = self:LookupSequenceAct(target.seq) + elseif target then -- It is a string or ACT + seq, dur = self:LookupSequenceAct(target) + else + seq, dur = self:LookupSequence("swing") + end + + self:SetAttacking(true) + self:PlaySequenceAndWait(seq, 1) + self:SetLastAttack(CurTime()) + self:SetAttacking(false) + self:UpdateSequence() + if coroutine.running() then + coroutine.wait(2 - dur) + end + + -- this will cause zombies to attack the barricade until it's destroyed + local stillBlocked = self:CheckForBarricade() + if stillBlocked then + self:OnBarricadeBlocking(stillBlocked) + return + end + + -- Attacking a new barricade resets the counter + self.BarricadeJumpTries = 0 + elseif barricade:GetTriggerJumps() and self.TriggerBarricadeJump then + local dist = barricade:GetPos():DistToSqr(self:GetPos()) + if dist <= 3500 + (1000 * self.BarricadeJumpTries) then + self:TriggerBarricadeJump() + self.BarricadeJumpTries = 0 + else + -- If we continuously fail, we need to increase the check range (if it is a bigger prop) + self.BarricadeJumpTries = self.BarricadeJumpTries + 1 + -- Otherwise they'd get continuously stuck on slightly bigger props :( + end + else + self:SetAttacking(false) + end + end +end diff --git a/gamemodes/nzombies/entities/entities/nz_zombie_special_burning.lua b/gamemodes/nzombies/entities/entities/nz_zombie_special_burning.lua new file mode 100644 index 00000000..5646a544 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_zombie_special_burning.lua @@ -0,0 +1,43 @@ +AddCSLuaFile() + +ENT.Base = "nz_zombie_walker" +ENT.PrintName = "Burning Walker" +ENT.Category = "Brainz" +ENT.Author = "Lolle" + +function ENT:StatsInitialize() + if SERVER then + if nzRound:GetNumber() == -1 then + self:SetRunSpeed( math.random(20, 260) ) + self:SetHealth( math.random(75, 1000) ) + else + local speeds = nzRound:GetZombieSpeeds() + if speeds then + self:SetRunSpeed( nzMisc.WeightedRandom(speeds) - 20 ) -- A bit slower here + end + self:SetHealth( nzRound:GetZombieHealth() or 75 ) + end + self:Flames( true ) + + self:SetEmergeSequenceIndex(math.random(#self.EmergeSequences)) + end +end + +function ENT:OnTargetInAttackRange() + local atkData = {} + atkData.dmglow = 20 + atkData.dmghigh = 30 + atkData.dmgforce = Vector( 0, 0, 0 ) + self:Attack( atkData ) + self:TimedEvent( 0.45, function() + if self:IsValidTarget( self:GetTarget() ) and self:TargetInRange( self.AttackRange + 10 ) then + self:Explode( math.random( 50, 100 ) ) + end + end) +end + +function ENT:OnZombieDeath(dmgInfo) + self:Explode( math.random( 25, 50 )) + self:EmitSound(self.DeathSounds[ math.random( #self.DeathSounds ) ], 50, math.random(75, 130)) + self:BecomeRagdoll(dmgInfo) +end diff --git a/gamemodes/nzombies/entities/entities/nz_zombie_special_dog.lua b/gamemodes/nzombies/entities/entities/nz_zombie_special_dog.lua new file mode 100644 index 00000000..71698459 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_zombie_special_dog.lua @@ -0,0 +1,294 @@ +AddCSLuaFile() + +ENT.Base = "nz_zombiebase" +ENT.PrintName = "Hellhound" +ENT.Category = "Brainz" +ENT.Author = "Lolle" + +--ENT.Models = { "models/boz/killmeplease.mdl" } +ENT.Models = { "models/nz_zombie/zombie_hellhound.mdl" } + +ENT.AttackRange = 80 +ENT.DamageLow = 20 +ENT.DamageHigh = 35 + +ENT.AttackSequences = { + {seq = "nz_attack1"}, + {seq = "nz_attack2"}, + {seq = "nz_attack3"}, +} + +ENT.DeathSequences = { + "nz_death1", + "nz_death2", + "nz_death3", +} + +ENT.AttackSounds = { + "nz/hellhound/attack/attack_00.wav", + "nz/hellhound/attack/attack_01.wav", + "nz/hellhound/attack/attack_02.wav", + "nz/hellhound/attack/attack_03.wav", + "nz/hellhound/attack/attack_04.wav", + "nz/hellhound/attack/attack_05.wav", + "nz/hellhound/attack/attack_06.wav" +} + +ENT.AttackHitSounds = { + "nz/hellhound/bite/bite_00.wav", + "nz/hellhound/bite/bite_01.wav", + "nz/hellhound/bite/bite_02.wav", + "nz/hellhound/bite/bite_03.wav", +} + +ENT.WalkSounds = { + "nz/hellhound/dist_vox_a/dist_vox_a_00.wav", + "nz/hellhound/dist_vox_a/dist_vox_a_01.wav", + "nz/hellhound/dist_vox_a/dist_vox_a_02.wav", + "nz/hellhound/dist_vox_a/dist_vox_a_03.wav", + "nz/hellhound/dist_vox_a/dist_vox_a_04.wav", + "nz/hellhound/dist_vox_a/dist_vox_a_05.wav", + "nz/hellhound/dist_vox_a/dist_vox_a_06.wav", + "nz/hellhound/dist_vox_a/dist_vox_a_07.wav", + "nz/hellhound/dist_vox_a/dist_vox_a_08.wav", + "nz/hellhound/dist_vox_a/dist_vox_a_09.wav", + "nz/hellhound/dist_vox_a/dist_vox_a_10.wav", + "nz/hellhound/dist_vox_a/dist_vox_a_11.wav" +} + +ENT.PainSounds = { + "physics/flesh/flesh_impact_bullet1.wav", + "physics/flesh/flesh_impact_bullet2.wav", + "physics/flesh/flesh_impact_bullet3.wav", + "physics/flesh/flesh_impact_bullet4.wav", + "physics/flesh/flesh_impact_bullet5.wav" +} + +ENT.DeathSounds = { + "nz/hellhound/death2/death0.wav", + "nz/hellhound/death2/death1.wav", + "nz/hellhound/death2/death2.wav", + "nz/hellhound/death2/death3.wav", + "nz/hellhound/death2/death4.wav", + "nz/hellhound/death2/death5.wav", + "nz/hellhound/death2/death6.wav", +} + +ENT.SprintSounds = { + "nz/hellhound/close/close_00.wav", + "nz/hellhound/close/close_01.wav", + "nz/hellhound/close/close_02.wav", + "nz/hellhound/close/close_03.wav", +} + +ENT.JumpSequences = {seq = ACT_JUMP, speed = 30} + +ENT.ActStages = { + [1] = { + act = ACT_WALK, + minspeed = 5, + }, + [2] = { + act = ACT_WALK_ANGRY, + minspeed = 50, + }, + [3] = { + act = ACT_RUN, + minspeed = 150, + }, + [4] = { + act = ACT_RUN, + minspeed = 160, + }, +} + +function ENT:StatsInitialize() + if SERVER then + self:SetRunSpeed(250) + self:SetHealth(100) + self:SetNoDraw(true) + end + self:SetCollisionBounds(Vector(-14,-14, 0), Vector(14, 14, 48)) + self:SetSolid(SOLID_BBOX) + + --PrintTable(self:GetSequenceList()) +end + +function ENT:OnSpawn() + + --self:SetNoDraw(true) -- Start off invisible while in the prespawn effect + self:SetCollisionGroup(COLLISION_GROUP_DEBRIS) -- Don't collide in this state + self:Stop() -- Also don't do anything + + local effectData = EffectData() + effectData:SetOrigin( self:GetPos() ) + effectData:SetMagnitude( 2 ) + effectData:SetEntity(nil) + util.Effect("lightning_prespawn", effectData) + self:SetNoDraw(true) + self:SetInvulnerable(true) + + timer.Simple(1.4, function() + if IsValid(self) then + effectData = EffectData() + -- startpos + effectData:SetStart( self:GetPos() + Vector(0, 0, 1000) ) + -- end pos + effectData:SetOrigin( self:GetPos() ) + -- duration + effectData:SetMagnitude( 0.75 ) + --util.Effect("lightning_strike", effectData) + util.Effect("lightning_strike", effectData) + + self:SetNoDraw(false) + self:SetCollisionGroup(COLLISION_GROUP_NONE) + self:SetStop(false) + + self:SetTarget(self:GetPriorityTarget()) + self:SetInvulnerable(nil) + end + end) + + nzRound:SetNextSpawnTime(CurTime() + 2) -- This one spawning delays others by 3 seconds +end + +function ENT:OnZombieDeath(dmgInfo) + + self:SetRunSpeed(0) + self.loco:SetVelocity(Vector(0,0,0)) + self:Stop() + local seqstr = self.DeathSequences[math.random(#self.DeathSequences)] + local seq, dur = self:LookupSequence(seqstr) + -- Delay it slightly; Seems to fix it instantly getting overwritten + timer.Simple(0, function() + if IsValid(self) then + self:ResetSequence(seq) + self:SetCycle(0) + self:SetCollisionGroup(COLLISION_GROUP_DEBRIS) + end + end) + + timer.Simple(dur + 1, function() + if IsValid(self) then + self:Remove() + end + end) + self:EmitSound( self.DeathSounds[ math.random( #self.DeathSounds ) ], 100) + +end + +function ENT:BodyUpdate() + + self.CalcIdeal = ACT_IDLE + + local velocity = self:GetVelocity() + + local len2d = velocity:Length2D() + + if ( len2d > 150 ) then self.CalcIdeal = ACT_RUN elseif ( len2d > 50 ) then self.CalcIdeal = ACT_WALK_ANGRY elseif ( len2d > 5 ) then self.CalcIdeal = ACT_WALK end + + if self:IsJumping() and self:WaterLevel() <= 0 then + self.CalcIdeal = ACT_JUMP + end + + --if self:GetActivity() != self.CalcIdeal and !self:IsAttacking() and !self:GetStop() then self:StartActivity(self.CalcIdeal) end + + if !self:GetSpecialAnimation() and !self:IsAttacking() then + if self:GetActivity() != self.CalcIdeal and !self:GetStop() then self:StartActivity(self.CalcIdeal) end + + self:BodyMoveXY() + end + + self:FrameAdvance() + +end + +function ENT:OnTargetInAttackRange() + local atkData = {} + atkData.dmglow = 35 + atkData.dmghigh = 40 + atkData.dmgforce = Vector( 0, 0, 0 ) + atkData.dmgdelay = 0.3 + self:Attack( atkData ) +end + +-- Hellhounds target differently +function ENT:GetPriorityTarget() + + if GetConVar( "nz_zombie_debug" ):GetBool() then + print(self, "Retargeting") + end + + self:SetLastTargetCheck( CurTime() ) + + -- Well if he exists and he is targetable, just target this guy! + if IsValid(self:GetTarget()) and self:GetTarget():GetTargetPriority() > 0 then + local dist = self:GetRangeSquaredTo( self:GetTarget():GetPos() ) + if dist < 1000 then + if !self.sprinting then + self:EmitSound( self.SprintSounds[ math.random( #self.SprintSounds ) ], 100 ) + self.sprinting = true + end + self:SetRunSpeed(250) + self.loco:SetDesiredSpeed( self:GetRunSpeed() ) + elseif !self.sprinting then + self:SetRunSpeed(100) + self.loco:SetDesiredSpeed( self:GetRunSpeed() ) + end + return self:GetTarget() + end + + -- Otherwise, we just loop through all to try and target again + local allEnts = ents.GetAll() + + local bestTarget = nil + local lowest + + --local possibleTargets = ents.FindInSphere( self:GetPos(), self:GetTargetCheckRange()) + + for _, target in pairs(allEnts) do + if self:IsValidTarget(target) then + if target:GetTargetPriority() == TARGET_PRIORITY_ALWAYS then return target end + if !lowest then + lowest = target.hellhoundtarget -- Set the lowest variable if not yet + bestTarget = target -- Also mark this for the best target so he isn't ignored + end + + if lowest and (!target.hellhoundtarget or target.hellhoundtarget < lowest) then -- If the variable exists and this player is lower than that amount + bestTarget = target -- Mark him for the potential target + lowest = target.hellhoundtarget or 0 -- And set the new lowest to continue the loop with + end + + if !lowest then -- If no players had any target values (lowest was never set, first ever hellhound) + local players = player.GetAllTargetable() + bestTarget = players[math.random(#players)] -- Then pick a random player + end + end + end + + if self:IsValidTarget(bestTarget) then -- If we found a valid target + local targetDist = self:GetRangeSquaredTo( bestTarget:GetPos() ) + if targetDist < 1000 then -- Under this distance, we will break into sprint + self:EmitSound( self.SprintSounds[ math.random( #self.SprintSounds ) ], 100 ) + self.sprinting = true -- Once sprinting, you won't stop + self:SetRunSpeed(250) + else -- Otherwise we'll just search (towards him) + self:SetRunSpeed(100) + self.sprinting = nil + end + self.loco:SetDesiredSpeed( self:GetRunSpeed() ) + -- Apply the new target numbers + bestTarget.hellhoundtarget = bestTarget.hellhoundtarget and bestTarget.hellhoundtarget + 1 or 1 + self:SetTarget(bestTarget) -- Well we found a target, we kinda have to force it + + return bestTarget + else + self:TimeOut(0.2) + end +end + +function ENT:IsValidTarget( ent ) + if !ent then return false end + return IsValid( ent ) and ent:GetTargetPriority() != TARGET_PRIORITY_NONE and ent:GetTargetPriority() != TARGET_PRIORITY_SPECIAL + -- Won't go for special targets (Monkeys), but still MAX, ALWAYS and so on +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/nz_zombie_walker.lua b/gamemodes/nzombies/entities/entities/nz_zombie_walker.lua new file mode 100644 index 00000000..eb6fff78 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_zombie_walker.lua @@ -0,0 +1,269 @@ +AddCSLuaFile() + +ENT.Base = "nz_zombiebase" +ENT.PrintName = "Walker" +ENT.Category = "Brainz" +ENT.Author = "Lolle" + +function ENT:SetupDataTables() + self:NetworkVar("Int", 0, "EmergeSequenceIndex") + self:NetworkVar("Bool", 1, "Decapitated") +end + +ENT.Models = { + "models/nz_zombie/zombie_rerig_animated.mdl", +} + +local AttackSequences = { + {seq = "nz_stand_attack1", dmgtimes = {0.75, 1.25}}, + {seq = "nz_stand_attack2", dmgtimes = {0.3}}, + {seq = "nz_stand_attack3", dmgtimes = {0.8}}, + {seq = "nz_stand_attack4", dmgtimes = {0.4, 0.8}}, +} +local WalkAttackSequences = { + {seq = "nz_walk_attack1", dmgtimes = {0.3}}, + {seq = "nz_walk_attack2", dmgtimes = {0.4, 0.9}}, + {seq = "nz_walk_attack3", dmgtimes = {0.5}}, + {seq = "nz_walk_attack4", dmgtimes = {0.4, 0.75}}, +} +local RunAttackSequences = { + {seq = "nz_run_attack1", dmgtimes = {0.3}}, + {seq = "nz_run_attack2", dmgtimes = {0.3, 0.65}}, + {seq = "nz_run_attack3", dmgtimes = {0.3, 0.7}}, + {seq = "nz_run_attack4", dmgtimes = {0.3, 0.8}}, +} + +local AttackSounds = { + "nz/zombies/attack/attack_00.wav", + "nz/zombies/attack/attack_01.wav", + "nz/zombies/attack/attack_02.wav", + "nz/zombies/attack/attack_03.wav", + "nz/zombies/attack/attack_04.wav", + "nz/zombies/attack/attack_05.wav", + "nz/zombies/attack/attack_06.wav", + "nz/zombies/attack/attack_07.wav", + "nz/zombies/attack/attack_08.wav", + "nz/zombies/attack/attack_09.wav", + "nz/zombies/attack/attack_10.wav", + "nz/zombies/attack/attack_11.wav", + "nz/zombies/attack/attack_12.wav", + "nz/zombies/attack/attack_13.wav", + "nz/zombies/attack/attack_14.wav", + "nz/zombies/attack/attack_15.wav", + "nz/zombies/attack/attack_16.wav", + "nz/zombies/attack/attack_17.wav", + "nz/zombies/attack/attack_18.wav", + "nz/zombies/attack/attack_19.wav", + "nz/zombies/attack/attack_20.wav", + "nz/zombies/attack/attack_21.wav", + "nz/zombies/attack/attack_22.wav", +} + +local WalkSounds = { + "nz/zombies/ambient/ambient_00.wav", + "nz/zombies/ambient/ambient_01.wav", + "nz/zombies/ambient/ambient_02.wav", + "nz/zombies/ambient/ambient_03.wav", + "nz/zombies/ambient/ambient_04.wav", + "nz/zombies/ambient/ambient_05.wav", + "nz/zombies/ambient/ambient_06.wav", + "nz/zombies/ambient/ambient_07.wav", + "nz/zombies/ambient/ambient_08.wav", + "nz/zombies/ambient/ambient_09.wav", + "nz/zombies/ambient/ambient_10.wav", + "nz/zombies/ambient/ambient_11.wav", + "nz/zombies/ambient/ambient_12.wav", + "nz/zombies/ambient/ambient_13.wav", + "nz/zombies/ambient/ambient_14.wav", + "nz/zombies/ambient/ambient_15.wav", + "nz/zombies/ambient/ambient_16.wav", + "nz/zombies/ambient/ambient_17.wav", + "nz/zombies/ambient/ambient_18.wav", + "nz/zombies/ambient/ambient_19.wav", + "nz/zombies/ambient/ambient_20.wav" +} + +local RunSounds = { + "nz/zombies/sprint2/sprint0.wav", + "nz/zombies/sprint2/sprint1.wav", + "nz/zombies/sprint2/sprint2.wav", + "nz/zombies/sprint2/sprint3.wav", + "nz/zombies/sprint2/sprint4.wav", + "nz/zombies/sprint2/sprint5.wav", + "nz/zombies/sprint2/sprint6.wav", + "nz/zombies/sprint2/sprint7.wav", + "nz/zombies/sprint2/sprint8.wav" +} + +local JumpSequences = { + {seq = "nz_barricade1", speed = 15, time = 2.7}, + {seq = "nz_barricade2", speed = 15, time = 2.4}, + {seq = "nz_barricade_fast1", speed = 15, time = 1.8}, + {seq = "nz_barricade_fast2", speed = 35, time = 4}, +} +local SprintJumpSequences = { + {seq = "nz_barricade_sprint1", speed = 50, time = 1.9}, + {seq = "nz_barricade_sprint2", speed = 35, time = 1.9}, +} + +ENT.ActStages = { + [1] = { + act = ACT_WALK, + minspeed = 5, + attackanims = WalkAttackSequences, + -- no attackhitsounds, just use ENT.AttackHitSounds for all act stages + sounds = WalkSounds, + barricadejumps = JumpSequences, + }, + [2] = { + act = ACT_WALK_ANGRY, + minspeed = 40, + attackanims = WalkAttackSequences, + sounds = WalkSounds, + barricadejumps = JumpSequences, + }, + [3] = { + act = ACT_RUN, + minspeed = 100, + attackanims = RunAttackSequences, + sounds = RunSounds, + barricadejumps = SprintJumpSequences, + }, + [4] = { + act = ACT_SPRINT, + minspeed = 160, + attackanims = RunAttackSequences, + sounds = RunSounds, + barricadejumps = SprintJumpSequences, + }, +} + +ENT.RedEyes = true + +ENT.ElectrocutionSequences = { + "nz_electrocuted1", + "nz_electrocuted2", + "nz_electrocuted3", + "nz_electrocuted4", + "nz_electrocuted5", +} +ENT.EmergeSequences = { + "nz_emerge1", + "nz_emerge2", + "nz_emerge3", + "nz_emerge4", + "nz_emerge5", +} +ENT.AttackHitSounds = { + "npc/zombie/zombie_hit.wav" +} +ENT.PainSounds = { + "physics/flesh/flesh_impact_bullet1.wav", + "physics/flesh/flesh_impact_bullet2.wav", + "physics/flesh/flesh_impact_bullet3.wav", + "physics/flesh/flesh_impact_bullet4.wav", + "physics/flesh/flesh_impact_bullet5.wav" +} +ENT.DeathSounds = { + "nz/zombies/death/death_00.wav", + "nz/zombies/death/death_01.wav", + "nz/zombies/death/death_02.wav", + "nz/zombies/death/death_03.wav", + "nz/zombies/death/death_04.wav", + "nz/zombies/death/death_05.wav", + "nz/zombies/death/death_06.wav", + "nz/zombies/death/death_07.wav", + "nz/zombies/death/death_08.wav", + "nz/zombies/death/death_09.wav", + "nz/zombies/death/death_10.wav" +} + +function ENT:StatsInitialize() + if SERVER then + if nzRound:GetNumber() == -1 then + self:SetRunSpeed( math.random(30, 300) ) + self:SetHealth( math.random(100, 1500) ) + else + local speeds = nzRound:GetZombieSpeeds() + if speeds then + self:SetRunSpeed( nzMisc.WeightedRandom(speeds) ) + else + self:SetRunSpeed( 100 ) + end + self:SetHealth( nzRound:GetZombieHealth() or 75 ) + end + + --Preselect the emerge sequnces for clientside use + self:SetEmergeSequenceIndex(math.random(#self.EmergeSequences)) + end +end + +function ENT:SpecialInit() + + if CLIENT then + --make them invisible for a really short duration to blend the emerge sequences + self:TimedEvent(0.1, function() -- Tiny delay just to make sure they are fully initialized + if string.find(self:GetSequenceName(self:GetSequence()), "nz_emerge") then + self:SetNoDraw(true) + self:TimedEvent( 0.15, function() + self:SetNoDraw(false) + end) + + self:SetRenderClipPlaneEnabled( true ) + self:SetRenderClipPlane(self:GetUp(), self:GetUp():Dot(self:GetPos())) + + --local _, dur = self:LookupSequence(self.EmergeSequences[self:GetEmergeSequenceIndex()]) + local _, dur = self:LookupSequence(self.EmergeSequences[self:GetEmergeSequenceIndex()]) + dur = dur - (dur * self:GetCycle()) -- Subtract the time we are already thruogh the animation + -- The above is important if the zombie only appears in PVS mid-way through the animation + + self:TimedEvent( dur, function() + self:SetRenderClipPlaneEnabled(false) + end) + end + end) + + end +end + +function ENT:OnSpawn() + + local seq = self.EmergeSequences[self:GetEmergeSequenceIndex()] + local _, dur = self:LookupSequence(seq) + + --dust cloud + local effectData = EffectData() + effectData:SetStart( self:GetPos() ) + effectData:SetOrigin( self:GetPos() ) + effectData:SetMagnitude(dur) + util.Effect("zombie_spawn_dust", effectData) + + -- play emerge animation on spawn + -- if we have a coroutine else just spawn the zombie without emerging for now. + if coroutine.running() then + self:PlaySequenceAndWait(seq) + end +end + +function ENT:OnZombieDeath(dmgInfo) + + if dmgInfo:GetDamageType() == DMG_SHOCK then + self:SetRunSpeed(0) + self.loco:SetVelocity(Vector(0,0,0)) + self:Stop() + local seq, dur = self:LookupSequence(self.ElectrocutionSequences[math.random(#self.ElectrocutionSequences)]) + self:ResetSequence(seq) + self:SetCycle(0) + self:SetCollisionGroup(COLLISION_GROUP_DEBRIS) + -- Emit electrocution scream here when added + timer.Simple(dur, function() + if IsValid(self) then + self:BecomeRagdoll(dmgInfo) + end + end) + else + self:EmitSound( self.DeathSounds[ math.random( #self.DeathSounds ) ], 100) + self:BecomeRagdoll(dmgInfo) + end + +end diff --git a/gamemodes/nzombies/entities/entities/nz_zombiebase.lua b/gamemodes/nzombies/entities/entities/nz_zombiebase.lua new file mode 100644 index 00000000..fcc0b24c --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_zombiebase.lua @@ -0,0 +1,1544 @@ +AddCSLuaFile() + +--debug cvars +CreateConVar( "nz_zombie_debug", "0", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_CHEAT } ) + +--[[ +This Base is not really spawnable but it contains a lot of useful functions for it's children +--]] + +--Boring +ENT.Base = "base_nextbot" +ENT.PrintName = "Zombie" +ENT.Category = "Brainz" +ENT.Author = "Lolle & Zet0r" +ENT.Spawnable = true +ENT.AdminOnly = true + +-- Zombie Stuffz +-- fallbacks +ENT.DeathDropHeight = 700 +ENT.StepHeight = 22 --Default is 18 but it makes things easier +ENT.JumpHeight = 70 +ENT.AttackRange = 65 +ENT.RunSpeed = 200 +ENT.WalkSpeed = 100 +ENT.Acceleration = 400 +ENT.DamageLow = 35 +ENT.DamageHigh = 45 + +-- important for ent:IsZombie() +ENT.bIsZombie = true +ENT.bSelfHandlePath = true -- PathFollower will not auto-check for barricades or navlocks + +--The Accessors will be partially shared, but should only be used serverside +AccessorFunc( ENT, "fWalkSpeed", "WalkSpeed", FORCE_NUMBER) +AccessorFunc( ENT, "fRunSpeed", "RunSpeed", FORCE_NUMBER) +AccessorFunc( ENT, "fAttackRange", "AttackRange", FORCE_NUMBER) +AccessorFunc( ENT, "fLastLand", "LastLand", FORCE_NUMBER) +AccessorFunc( ENT, "fLastTargetCheck", "LastTargetCheck", FORCE_NUMBER) +AccessorFunc( ENT, "fLastAtack", "LastAttack", FORCE_NUMBER) +AccessorFunc( ENT, "fLastTargetChange", "LastTargetChange", FORCE_NUMBER) +AccessorFunc( ENT, "fTargetCheckRange", "TargetCheckRange", FORCE_NUMBER) + +--sounds +AccessorFunc( ENT, "fNextMoanSound", "NextMoanSound", FORCE_NUMBER) + +--Stuck prevention +AccessorFunc( ENT, "fLastPostionSave", "LastPostionSave", FORCE_NUMBER) +AccessorFunc( ENT, "fLastPush", "LastPush", FORCE_NUMBER) +AccessorFunc( ENT, "iStuckCounter", "StuckCounter", FORCE_NUMBER) +AccessorFunc( ENT, "vStuckAt", "StuckAt") +AccessorFunc( ENT, "bTimedOut", "TimedOut") + +-- spawner accessor +AccessorFunc(ENT, "hSpawner", "Spawner") + +AccessorFunc( ENT, "bJumping", "Jumping", FORCE_BOOL) +AccessorFunc( ENT, "bAttacking", "Attacking", FORCE_BOOL) +AccessorFunc( ENT, "bClimbing", "Climbing", FORCE_BOOL) +AccessorFunc( ENT, "bStop", "Stop", FORCE_BOOL) +AccessorFunc( ENT, "bSpecialAnim", "SpecialAnimation", FORCE_BOOL) +AccessorFunc( ENT, "bBlockAttack", "BlockAttack", FORCE_BOOL) + +AccessorFunc( ENT, "iActStage", "ActStage", FORCE_NUMBER) + +ENT.ActStages = {} + +function ENT:SetupDataTables() + -- If you want decapitation in you zombie and overwrote ENT:SetupDataTables() make sure to add self:NetworkVar("Bool", 0, "Decapitated") again. + self:NetworkVar("Bool", 0, "Decapitated") + if self.InitDataTables then self:InitDataTables() end +end + +function ENT:Precache() + + for _,v in pairs(self.Models) do + util.PrecacheModel( v ) + end + + if self.AttackSounds then + for _,v in pairs(self.AttackSounds) do + util.PrecacheSound( v ) + end + end + + if self.AttackHitSounds then + for _,v in pairs(self.AttackHitSounds) do + util.PrecacheSound( v ) + end + end + + if self.PainSounds then + for _,v in pairs(self.PainSounds) do + util.PrecacheSound( v ) + end + end + + if self.DeathSounds then + for _,v in pairs(self.DeathSounds) do + util.PrecacheSound( v ) + end + end + + if self.WalkSounds then + for _,v in pairs(self.WalkSounds) do + util.PrecacheSound( v ) + end + end + + if self.RunSounds then + for _,v in pairs(self.RunSounds) do + util.PrecacheSound( v ) + end + end +end +--Init +function ENT:Initialize() + + self:Precache() + + self:SetModel( self.Models[math.random( #self.Models )] ) + + self:SetJumping( false ) + self:SetLastLand( CurTime() + 1 ) --prevent jumping after spawn + self:SetLastTargetCheck( CurTime() ) + self:SetLastTargetChange( CurTime() ) + + --sounds + self:SetNextMoanSound( CurTime() + 1 ) + + --stuck prevetion + self:SetLastPush( CurTime() ) + self:SetLastPostionSave( CurTime() ) + self:SetStuckAt( self:GetPos() ) + self:SetStuckCounter( 0 ) + + self:SetAttacking( false ) + self:SetLastAttack( CurTime() ) + self:SetAttackRange( self.AttackRange ) + self:SetTargetCheckRange(0) -- 0 for no distance restriction (infinite) + + --target ignore + self:ResetIgnores() + + self:SetHealth( 75 ) --fallback + + self:SetRunSpeed( self.RunSpeed ) --fallback + self:SetWalkSpeed( self.WalkSpeed ) --fallback + + self:SetCollisionBounds(Vector(-16,-16, 0), Vector(16, 16, 70)) + + self:SetActStage(0) + self:SetSpecialAnimation(false) + + self:StatsInitialize() + self:SpecialInit() + + if SERVER then + self.loco:SetDeathDropHeight( self.DeathDropHeight ) + self.loco:SetDesiredSpeed( self:GetRunSpeed() ) + self.loco:SetAcceleration( self.Acceleration ) + self.loco:SetJumpHeight( self.JumpHeight ) + if GetConVar("nz_zombie_lagcompensated"):GetBool() then + self:SetLagCompensated(true) + end + self.BarricadeJumpTries = 0 + end + + for i,v in ipairs(self:GetBodyGroups()) do + self:SetBodygroup( i-1, math.random(0, self:GetBodygroupCount(i-1) - 1)) + end + self:SetSkin( math.random(self:SkinCount()) - 1 ) + + self.ZombieAlive = true + +end + +--init for class related attributes hooks etc... +function ENT:SpecialInit() + --print("PLEASE Override the base class!") +end + +function ENT:StatsInit() + --print("PLEASE Override the base class!") +end + +function ENT:Think() + if SERVER then --think is shared since last update but all the stuff in here should be serverside + if !self:IsJumping() and !self:GetSpecialAnimation() and (self:GetSolidMask() == MASK_NPCSOLID_BRUSHONLY or self:GetSolidMask() == MASK_SOLID_BRUSHONLY) then + local occupied = false + local tr = util.TraceHull( { + start = self:GetPos(), + endpos = self:GetPos(), + filter = self, + mins = Vector( -20, -20, -0 ), + maxs = Vector( 20, 20, 70 ), + mask = MASK_NPCSOLID + } ) + if !tr.HitNonWorld then + self:SetSolidMask(MASK_NPCSOLID) + self:SetCollisionGroup(COLLISION_GROUP_PLAYER) + --print("No longer no-colliding") + end + --[[for _,ent in pairs(ents.FindInBox(self:GetPos() + Vector( -16, -16, 0 ), self:GetPos() + Vector( 16, 16, 70 ))) do + if ent:GetClass() == "nz_zombie*" and ent != self then occupied = true end + end + if !occupied then self:SetSolidMask(MASK_NPCSOLID) end]] + end + + if self.loco:IsUsingLadder() then + --self:SetSolidMask(MASK_NPCSOLID_BRUSHONLY) + end + + --this is a very costly operation so we only do it every second + if self:GetLastTargetCheck() + 1 < CurTime() then + self:SetTarget(self:GetPriorityTarget()) + end + + -- We don't want to say we're stuck if it's because we're attacking or timed out + if !self:GetAttacking() and !self:GetTimedOut() and self:GetLastPostionSave() + 4 < CurTime() then + if self:GetPos():Distance( self:GetStuckAt() ) < 10 then + self:SetStuckCounter( self:GetStuckCounter() + 1) + else + self:SetStuckCounter( 0 ) + end + + if self:GetStuckCounter() > 2 then + + local tr = util.TraceHull({ + start = self:GetPos(), + endpos = self:GetPos(), + maxs = self:OBBMaxs(), + mins = self:OBBMins(), + filter = self + }) + if tr.Hit then + --if there bounding box is intersecting with something there is now way we can unstuck them just respawn. + --make a dust cloud to make it look less ugly + local effectData = EffectData() + effectData:SetStart( self:GetPos() + Vector(0,0,32) ) + effectData:SetOrigin( self:GetPos() + Vector(0,0,32) ) + effectData:SetMagnitude(1) + util.Effect("zombie_spawn_dust", effectData) + + self:RespawnZombie() + self:SetStuckCounter( 0 ) + end + + if self:GetStuckCounter() <= 3 then + --try to unstuck via random velocity + self:ApplyRandomPush() + end + + if self:GetStuckCounter() > 3 and self:GetStuckCounter() <= 5 then + --try to unstuck via jump + self:Jump() + end + + if self:GetStuckCounter() > 5 then + --Worst case: + --respawn the zombie after 32 seconds with no postion change + self:RespawnZombie() + self:SetStuckCounter( 0 ) + end + + end + self:SetLastPostionSave( CurTime() ) + self:SetStuckAt( self:GetPos() ) + end + + --sounds + self:SoundThink() + + if self:ZombieWaterLevel() == 3 then + self:RespawnZombie() + end + + self:DebugThink() + + end + self:OnThink() +end + +function ENT:DebugThink() + if GetConVar( "nz_zombie_debug" ):GetBool() then + local spacing = Vector(0,0,64) + local target = self:GetTarget() + if target then + debugoverlay.Text( self:GetPos() + spacing, tostring(target), FrameTime() * 2 ) + else + debugoverlay.Text( self:GetPos() + spacing, "NO_TARGET", FrameTime() * 2 ) + end + spacing = spacing + Vector(0,0,8) + local attacking = self:IsAttacking() + if attacking then + debugoverlay.Text( self:GetPos() + spacing, "IN_ATTACK", FrameTime() * 2 ) + elseif self:IsTimedOut() then + debugoverlay.Text( self:GetPos() + spacing, "TIMED_OUT", FrameTime() * 2 ) + elseif target then + debugoverlay.Text( self:GetPos() + spacing, "MOVING_TO_TARGET", FrameTime() * 2 ) + else + debugoverlay.Text( self:GetPos() + spacing, "ERROR", FrameTime() * 2 ) + end + spacing = spacing + Vector(0,0,8) + debugoverlay.Text( self:GetPos() + spacing, "HitPoints: " .. tostring(self:Health()), FrameTime() * 2 ) + spacing = spacing + Vector(0,0,8) + debugoverlay.Text( self:GetPos() + spacing, tostring(self), FrameTime() * 2 ) + end +end + +function ENT:SoundThink() + if CurTime() > self:GetNextMoanSound() and !self:GetStop() then + local soundtbl = self.ActStages[self:GetActStage()] and self.ActStages[self:GetActStage()].sounds or self.WalkSounds + if soundtbl then + local soundName = soundtbl[math.random(#soundtbl)] + self:EmitSound( soundName, 80 ) + local nextSound = SoundDuration( soundName ) + math.random(0,4) + CurTime() + self:SetNextMoanSound( nextSound ) + end + end +end + +function ENT:RunBehaviour() + + self:SpawnZombie() + + while (true) do + if !self:GetStop() then + self:SetTimedOut(false) + if self:HasTarget() then + local pathResult = self:ChaseTarget( { + maxage = 1, + draw = false, + tolerance = self:GetSpecialAnimation() and 0 or ((self:GetAttackRange() -30) > 0 ) and self:GetAttackRange() - 20 + } ) + if pathResult == "ok" then + if self:TargetInAttackRange() then + self:OnTargetInAttackRange() + else + self:TimeOut(1) + end + elseif pathResult == "timeout" then --asume pathing timedout, maybe we are stuck maybe we are blocked by barricades + local barricade, dir = self:CheckForBarricade() + if barricade then + self:OnBarricadeBlocking( barricade, dir ) + else + self:OnPathTimeOut() + end + else + self:TimeOut(2) + -- path failed what should we do :/? + end + else + self:OnNoTarget() + end + else + self:TimeOut(2) + end + end +end + +function ENT:Stop() + self:SetStop(true) + self:SetTarget(nil) +end + +--Draw sppoky red eyes +local eyeglow = Material( "sprites/redglow1" ) +local white = Color( 255, 255, 255, 255 ) + +function ENT:Draw() + self:DrawModel() + if self.RedEyes then + --local eyes = self:GetAttachment(self:LookupAttachment("eyes")).Pos + --local leftEye = eyes + self:GetRight() * -1.5 + self:GetForward() * 0.5 + --local rightEye = eyes + self:GetRight() * 1.5 + self:GetForward() * 0.5 + + local lefteye = self:GetAttachment(self:LookupAttachment("lefteye")) + local righteye = self:GetAttachment(self:LookupAttachment("righteye")) + + if !lefteye then lefteye = self:GetAttachment(self:LookupAttachment("left_eye")) end + if !righteye then righteye = self:GetAttachment(self:LookupAttachment("right_eye")) end + + local righteyepos + local lefteyepos + + if lefteye and righteye then + lefteyepos = lefteye.Pos + righteyepos = righteye.Pos + else + local eyes = self:GetAttachment(self:LookupAttachment("eyes")) + if eyes then + lefteyepos = eyes.Pos + self:GetRight() * -1.5 + self:GetForward() * 0.5 + righteyepos = eyes.Pos + self:GetRight() * 1.5 + self:GetForward() * 0.5 + end + end + + if lefteyepos and righteyepos then + cam.Start3D(EyePos(),EyeAngles()) + render.SetMaterial( eyeglow ) + render.DrawSprite( lefteye.Pos, 4, 4, white) + render.DrawSprite( righteye.Pos, 4, 4, white) + cam.End3D() + end + end + if GetConVar( "nz_zombie_debug" ):GetBool() then + render.DrawWireframeBox(self:GetPos(), Angle(0,0,0), self:OBBMins(), self:OBBMaxs(), Color(255,0,0), true) + render.DrawWireframeSphere(self:GetPos(), self:GetAttackRange(), 10, 10, Color(255,165,0), true) + end +end + +--[[ + Events + You can easily override them. + Todo: Add Hooks +--]] + +function ENT:SpawnZombie() + --BAIL if no navmesh is near + local nav = navmesh.GetNearestNavArea( self:GetPos() ) + if !self:IsInWorld() or !IsValid(nav) or nav:GetClosestPointOnArea( self:GetPos() ):DistToSqr( self:GetPos() ) >= 10000 then + ErrorNoHalt("Zombie ["..self:GetClass().."]["..self:EntIndex().."] spawned too far away from a navmesh!") + self:RespawnZombie() + end + + self:OnSpawn() +end + +function ENT:OnSpawn() + +end + +function ENT:OnTargetInAttackRange() + if !self:GetBlockAttack() then + self:Attack() + else + self:TimeOut(2) + end +end + +function ENT:OnBarricadeBlocking( barricade, dir ) + if (IsValid(barricade) and barricade:GetClass() == "breakable_entry" ) then + if barricade:GetNumPlanks() > 0 then + timer.Simple(0.3, function() + barricade:EmitSound("physics/wood/wood_plank_break" .. math.random(1, 4) .. ".wav", 100, math.random(90, 130)) + barricade:RemovePlank() + end) + + self:SetAngles(Angle(0,(barricade:GetPos()-self:GetPos()):Angle()[2],0)) + + local seq, dur + + local attacktbl = self.ActStages[1] and self.ActStages[1].attackanims or self.AttackSequences + local target = type(attacktbl) == "table" and attacktbl[math.random(#attacktbl)] or attacktbl + + if type(target) == "table" then + seq, dur = self:LookupSequenceAct(target.seq) + elseif target then -- It is a string or ACT + seq, dur = self:LookupSequenceAct(target) + else + seq, dur = self:LookupSequence("swing") + end + + self:SetAttacking(true) + self:PlaySequenceAndWait(seq, 1) + self:SetLastAttack(CurTime()) + self:SetAttacking(false) + self:UpdateSequence() + if coroutine.running() then + coroutine.wait(2 - dur) + end + + -- this will cause zombies to attack the barricade until it's destroyed + local stillBlocked, dir = self:CheckForBarricade() + if stillBlocked then + self:OnBarricadeBlocking(stillBlocked, dir) + return + end + + -- Attacking a new barricade resets the counter + self.BarricadeJumpTries = 0 + elseif barricade:GetTriggerJumps() and self.TriggerBarricadeJump then + local dist = barricade:GetPos():DistToSqr(self:GetPos()) + if dist <= 3500 + (1000 * self.BarricadeJumpTries) then + self:TriggerBarricadeJump(barricade, dir) + self.BarricadeJumpTries = 0 + else + -- If we continuously fail, we need to increase the check range (if it is a bigger prop) + self.BarricadeJumpTries = self.BarricadeJumpTries + 1 + -- Otherwise they'd get continuously stuck on slightly bigger props :( + end + else + self:SetAttacking(false) + end + end +end + +function ENT:TimeOut(time) + self:SetTimedOut(true) + if coroutine.running() then + coroutine.wait(time) + end +end + +function ENT:OnPathTimeOut() + +end + +function ENT:OnNoTarget() + -- Game over! Walk around randomly + if nzRound:InState( ROUND_GO ) then + self:StartActivity(ACT_WALK) + self.loco:SetDesiredSpeed(40) + self:MoveToPos(self:GetPos() + Vector(math.random(-512, 512), math.random(-512, 512), 0), { + repath = 3, + maxage = 5 + }) + else + self:TimeOut(0.5) + -- Start off by checking for a new target + local newtarget = self:GetPriorityTarget() + if self:IsValidTarget(newtarget) then + self:SetTarget(newtarget) + else + -- If not visible to players respawn immediately + if !self:IsInSight() then + self:RespawnZombie() + else + self:UpdateSequence() -- Updates the sequence to be idle animation + self:StartActivity(self.CalcIdeal) -- Starts the newly updated sequence + self:TimeOut(3) -- Time out even longer if seen + end + end + end +end + +function ENT:OnContactWithTarget() + +end + +function ENT:OnLandOnGroundZombie() + +end + +function ENT:OnThink() + +end + +--Default NEXTBOT Events +function ENT:OnLandOnGround() + self:EmitSound("physics/flesh/flesh_impact_hard" .. math.random(1, 6) .. ".wav") + self:SetJumping( false ) + if self:HasTarget() then + self.loco:SetDesiredSpeed(self:GetRunSpeed()) + else + self.loco:SetDesiredSpeed(self:GetWalkSpeed()) + end + self.loco:SetAcceleration( self.Acceleration ) + self.loco:SetStepHeight( 22 ) + self:SetLastLand(CurTime()) + self:OnLandOnGroundZombie() +end + +function ENT:OnLeaveGround( ent ) + self:SetJumping( true ) +end + +function ENT:OnNavAreaChanged(old, new) + if bit.band(new:GetAttributes(), NAV_MESH_JUMP) != 0 then + --dont make jumps in the wrong direction + if old:ComputeGroundHeightChange( new ) < 0 then + return + end + self:Jump() + end +end + +function ENT:OnContact( ent ) + if nzConfig.ValidEnemies[ent:GetClass()] and nzConfig.ValidEnemies[self:GetClass()] then + --this is a poor approach to unstuck them when walking into each other + self.loco:Approach( self:GetPos() + Vector( math.Rand( -1, 1 ), math.Rand( -1, 1 ), 0 ) * 2000,1000) + --important if the get stuck on top of each other! + --if math.abs(self:GetPos().z - ent:GetPos().z) > 30 then self:SetSolidMask( MASK_NPCSOLID_BRUSHONLY ) end + end + --buggy prop push away thing comment if you dont want this :) + if ( ent:GetClass() == "prop_physics_multiplayer" or ent:GetClass() == "prop_physics" ) then + --self.loco:Approach( self:GetPos() + Vector( math.Rand( -1, 1 ), math.Rand( -1, 1 ), 0 ) * 2000,1000) + local phys = ent:GetPhysicsObject() + if IsValid(phys) then + local force = -physenv.GetGravity().z * phys:GetMass() / 12 * ent:GetFriction() + local dir = ent:GetPos() - self:GetPos() + dir:Normalize() + phys:ApplyForceCenter( dir * force ) + end + end + + if self:IsTarget( ent ) then + self:OnContactWithTarget() + end +end + +function ENT:OnInjured( dmgInfo ) + local attacker = dmgInfo:GetAttacker() + if self:IsValidTarget( attacker ) then + self:SetTarget( attacker ) + end + local soundName = self.PainSounds[ math.random( #self.PainSounds ) ] + self:EmitSound( soundName, 90 ) +end + +function ENT:OnZombieDeath() + self:BecomeRagdoll(dmgInfo) +end + +function ENT:Alive() + return self.ZombieAlive +end + +function ENT:OnKilled(dmgInfo) + if dmgInfo and self:Alive() then -- Only call once! + self:OnZombieDeath(dmgInfo) + end + + local headbone = self:LookupBone("ValveBiped.Bip01_Head1") + if !headbone then headbone = self:LookupBone("j_head") end + if headbone then + local headPos = self:GetBonePosition(headbone) + local dmgPos = dmgInfo:GetDamagePosition() + + -- it will not always trigger since the offset can be larger than 12 + -- but I think it's fine not to decapitate every headshotted zombie + if headPos and dmgPos and headPos:Distance(dmgPos) < 12 then + self:SetDecapitated(true) + end + end + + self.ZombieAlive = false + + hook.Call("OnZombieKilled", GAMEMODE, self, dmgInfo) + +end + +function ENT:OnRemove() + +end + +function ENT:OnStuck() + -- + --self.loco:Approach( self:GetPos() + Vector( math.Rand( -1, 1 ), math.Rand( -1, 1 ), 0 ) * 2000, 1000 ) + --print("Now I'm stuck", self) +end + +--Target and pathfidning +function ENT:GetPriorityTarget() + + self:SetLastTargetCheck( CurTime() ) + + --if you really would want something that atracts the zombies from everywhere you would need something like this + local allEnts = ents.GetAll() + --[[for _, ent in pairs(allEnts) do + if ent:GetTargetPriority() == TARGET_PRIORITY_ALWAYS and self:IsValidTarget(ent) then + return ent + end + end]] + + -- Disabled the above for for now since it just might be better to use that same loop for everything + + local bestTarget = nil + local highestPriority = TARGET_PRIORITY_NONE + local maxdistsqr = self:GetTargetCheckRange()^2 + local targetDist = maxdistsqr + 10 + + --local possibleTargets = ents.FindInSphere( self:GetPos(), self:GetTargetCheckRange()) + + for _, target in pairs(allEnts) do + if self:IsValidTarget(target) and !self:IsIgnoredTarget(target) then + + if target:GetTargetPriority() == TARGET_PRIORITY_ALWAYS then return target end + + local dist = self:GetRangeSquaredTo( target:GetPos() ) + if maxdistsqr <= 0 or dist <= maxdistsqr then -- 0 distance is no distance restrictions + local priority = target:GetTargetPriority() + if target:GetTargetPriority() > highestPriority then + highestPriority = priority + bestTarget = target + targetDist = dist + elseif target:GetTargetPriority() == highestPriority then + if targetDist > dist then + highestPriority = priority + bestTarget = target + targetDist = dist + end + end + --print(highestPriority, bestTarget, targetDist, maxdistsqr) + end + end + end + + return bestTarget +end + +function ENT:ChaseTarget( options ) + + options = options or {} + + if !options.target then + options.target = self:GetTarget() + end + + local path = self:ChaseTargetPath( options ) + + if ( !IsValid(path) ) then return "failed" end + while ( path:IsValid() and self:HasTarget() and !self:TargetInAttackRange() ) do + + path:Update( self ) + + --Timeout the pathing so it will rerun the entire behaviour (break barricades etc) + if ( path:GetAge() > options.maxage ) then + local segment = path:FirstSegment() + self.BarricadeCheckDir = segment and segment.forward or Vector(0,0,0) + return "timeout" + end + + path:Update( self ) -- This function moves the bot along the path + if options.draw or GetConVar( "nz_zombie_debug" ):GetBool() then + path:Draw() + end + + --the jumping part simple and buggy + --local scanDist = (self.loco:GetVelocity():Length()^2)/(2*900) + 15 + local scanDist + --this will probaly need asjustments to fit the zombies speed + if self:GetVelocity():Length2D() > 150 then scanDist = 30 else scanDist = 20 end + --debug section + if GetConVar( "nz_zombie_debug" ):GetBool() then + debugoverlay.Line( self:GetPos(), path:GetClosestPosition(self:EyePos() + self.loco:GetGroundMotionVector() * scanDist), 0.05, Color(0,0,255,0) ) + local losColor = Color(255,0,0) + if self:IsLineOfSightClear( self:GetTarget():GetPos() + Vector(0,0,35) ) then + losColor = Color(0,255,0) + end + debugoverlay.Line( self:EyePos(), self:GetTarget():GetPos() + Vector(0,0,35), 0.03, losColor ) + --[[local nav = navmesh.GetNearestNavArea( self:GetPos() ) + if IsValid(nav) and nav:GetClosestPointOnArea( self:GetPos() ):DistToSqr( self:GetPos() ) < 2500 then + debugoverlay.Line( nav:GetCorner( 0 ), nav:GetCorner( 1 ), 0.05, Color(255,0,0), true ) + debugoverlay.Line( nav:GetCorner( 0 ), nav:GetCorner( 3 ), 0.05, Color(255,0,0), true ) + debugoverlay.Line( nav:GetCorner( 1 ), nav:GetCorner( 2 ), 0.05, Color(255,0,0), true ) + debugoverlay.Line( nav:GetCorner( 2 ), nav:GetCorner( 3 ), 0.05, Color(255,0,0), true ) + for _,v in pairs(nav:GetAdjacentAreas()) do + debugoverlay.Line( v:GetCorner( 0 ), v:GetCorner( 1 ), 0.05, Color(150,80,0,80), true ) + debugoverlay.Line( v:GetCorner( 0 ), v:GetCorner( 3 ), 0.05, Color(150,80,0,80), true ) + debugoverlay.Line( v:GetCorner( 1 ), v:GetCorner( 2 ), 0.05, Color(150,80,0,80), true ) + debugoverlay.Line( v:GetCorner( 2 ), v:GetCorner( 3 ), 0.05, Color(150,80,0,80), true ) + end + end ]]-- + end + --print(self.loco:GetGroundMotionVector(), self:GetForward()) + local goal = path:GetCurrentGoal() + + --height triggered jumping + if path:IsValid() and math.abs(self:GetPos().z - path:GetClosestPosition(self:EyePos() + self.loco:GetGroundMotionVector() * scanDist).z) > 22 and (goal and goal.type != 1) then + self:Jump() + end + --[[if path:IsValid() and goal.type == 4 then + --self.loco:SetVelocity( Vector( 0, 0, 1000 ) ) + self:SetPos( path:GetClosestPosition( goal.ladder:GetTopForwardArea():GetCenter() ) ) + self:SetClimbing( true ) + coroutine.wait( 0.5 ) + self:SetSolidMask( MASK_NPCSOLID_BRUSHONLY ) + return "timeout" + if self.loco:IsUsingLadder() then + self.loco:SetVelocity( self.loco:GetVelocity() + Vector( 0, 0, 50 ) ) + end + end --]] + + -- If we're stuck, then call the HandleStuck function and abandon + if ( self.loco:IsStuck() ) then + self:HandleStuck() + return "stuck" + end + + if self.loco:GetVelocity():Length() < 10 then + self:ApplyRandomPush() + end + + coroutine.yield() + + end + + return "ok" + +end + +function ENT:ChaseTargetPath( options ) + + options = options or {} + + local path = Path( "Follow" ) + path:SetMinLookAheadDistance( options.lookahead or 300 ) + path:SetGoalTolerance( options.tolerance or 30 ) + + --[[local targetPos = options.target:GetPos() + --set the goal to the closet navmesh + local goal = navmesh.GetNearestNavArea(targetPos, false, 100) + goal = goal and goal:GetClosestPointOnArea(targetPos) or targetPos--]] + + -- Custom path computer, the same as default but not pathing through locked nav areas. + path:Compute( self, options.target:GetPos(), function( area, fromArea, ladder, elevator, length ) + if ( !IsValid( fromArea ) ) then + -- First area in path, no cost + return 0 + else + if ( !self.loco:IsAreaTraversable( area ) ) then + -- Our locomotor says we can't move here + return -1 + end + -- Prevent movement through either locked navareas or areas with closed doors + if (nzNav.Locks[area:GetID()]) then + if nzNav.Locks[area:GetID()].link then + if !nzDoors:IsLinkOpened( nzNav.Locks[area:GetID()].link ) then + return -1 + end + elseif nzNav.Locks[area:GetID()].locked then + return -1 end + end + -- Compute distance traveled along path so far + local dist = 0 + --[[if ( IsValid( ladder ) ) then + dist = ladder:GetLength() + elseif ( length > 0 ) then + --optimization to avoid recomputing length + dist = length + else + dist = ( area:GetCenter() - fromArea:GetCenter() ):GetLength() + end]]-- + local cost = dist + fromArea:GetCostSoFar() + --check height change + local deltaZ = fromArea:ComputeAdjacentConnectionHeightChange( area ) + if ( deltaZ >= self.loco:GetStepHeight() ) then + -- use player default max jump height even thouh teh zombie will jump a bit higher + if ( deltaZ >= 64 ) then + --Include ladders in pathing: + --currently disableddue to the lack of a loco:Climb function + --[[if IsValid( ladder ) then + if ladder:GetTopForwardArea():GetID() == area:GetID() then + return cost + end + end --]] + --too high to reach + return -1 + end + --jumping is slower than flat ground + local jumpPenalty = 1.1 + cost = cost + jumpPenalty * dist + elseif ( deltaZ < -self.loco:GetDeathDropHeight() ) then + --too far to drop + return -1 + end + return cost + end + end) + + -- this will replace nav groups + -- we do this after pathing to know when this happens + local lastSeg = path:LastSegment() + + -- a little more complicated that i thought but it should do the trick + if lastSeg then + if self:GetTargetNavArea() and lastSeg.area:GetID() != self:GetTargetNavArea():GetID() then + if !nzNav.Locks[self:GetTargetNavArea():GetID()] or nzNav.Locks[self:GetTargetNavArea():GetID()].locked then + self:IgnoreTarget(self:GetTarget()) + -- trigger a retarget + self:SetLastTargetCheck(CurTime() - 1) + self:TimeOut(0.5) + return nil + end + else + self:ResetIgnores() + return path + end + end + + return path + +end + +function ENT:GetLadderTop( ladder ) + return ladder:GetTopForwardArea() or ladder:GetTopBehindArea() or ladder:GetTopRightArea() or ladder:GetTopLeftArea() +end + +function ENT:TargetInAttackRange() + return self:TargetInRange( self:GetAttackRange() ) +end + +function ENT:TargetInRange( range ) + local target = self:GetTarget() + if !IsValid(target) then return false end + return self:GetRangeTo( target:GetPos() ) < range +end + +function ENT:CheckForBarricade() + --we try a line trace first since its more efficient + local dataL = {} + dataL.start = self:GetPos() + Vector( 0, 0, self:OBBCenter().z ) + dataL.endpos = self:GetPos() + Vector( 0, 0, self:OBBCenter().z ) + self.BarricadeCheckDir * 48 + dataL.filter = function( ent ) if ( ent:GetClass() == "breakable_entry" ) then return true end end + dataL.ignoreworld = true + local trL = util.TraceLine( dataL ) + + --debugoverlay.Line(self:GetPos() + Vector( 0, 0, self:OBBCenter().z ), self:GetPos() + Vector( 0, 0, self:OBBCenter().z ) + self.BarricadeCheckDir * 32) + --debugoverlay.Cross(self:GetPos() + Vector( 0, 0, self:OBBCenter().z ), 1) + + if IsValid( trL.Entity ) and trL.Entity:GetClass() == "breakable_entry" then + return trL.Entity, trL.HitNormal + end + + -- Perform a hull trace if line didnt hit just to make sure + local dataH = {} + dataH.start = self:GetPos() + dataH.endpos = self:GetPos() + self.BarricadeCheckDir * 48 + dataH.filter = function( ent ) if ( ent:GetClass() == "breakable_entry" ) then return true end end + dataH.mins = self:OBBMins() * 0.65 + dataH.maxs = self:OBBMaxs() * 0.65 + local trH = util.TraceHull(dataH ) + + if IsValid( trH.Entity ) and trH.Entity:GetClass() == "breakable_entry" then + return trH.Entity, trH.HitNormal + end + + return nil + +end + +-- A standard attack you can use it or create something fancy yourself +function ENT:Attack( data ) + + self:SetLastAttack(CurTime()) + + --if self:Health() <= 0 then coroutine.yield() return end + + data = data or {} + + data.attackseq = data.attackseq + if !data.attackseq then + local curstage = self:GetActStage() + local actstage = self.ActStages[curstage] + if !actstage and curstage <= 0 then actstage = self.ActStages[1] end + + local attacktbl = actstage and actstage.attackanims or self.AttackSequences + local target = type(attacktbl) == "table" and attacktbl[math.random(#attacktbl)] or attacktbl + + if type(target) == "table" then + local id, dur = self:LookupSequenceAct(target.seq) + data.attackseq = {seq = id, dmgtimes = target.dmgtimes or {0.5}} + data.attackdur = dur + elseif target then -- It is a string or ACT + local id, dur = self:LookupSequenceAct(attacktbl) + data.attackseq = {seq = id, dmgtimes = {dur/2}} + data.attackdur = dur + else + local id, dur = self:LookupSequence("swing") + data.attackseq = {seq = id, dmgtimes = {1}} + data.attackdur = dur + end + end + + data.attacksound = data.attacksound + if !data.attacksound then + local actstage = self.ActStages[self:GetActStage()] + local soundtbl = actstage and actstage.attacksounds or self.AttackSounds + data.attacksound = soundtbl and soundtbl[math.random(#soundtbl)] or Sound( "npc/vort/claw_swing1.wav" ) + end + + data.hitsound = data.hitsound + if !data.hitsound then + local actstage = self.ActStages[self:GetActStage()] + local soundtbl = actstage and actstage.attackhitsounds or self.AttackHitSounds + data.hitsound = soundtbl and soundtbl[math.random(#soundtbl)] or Sound( "npc/zombie/zombie_hit.wav" ) + end + + data.viewpunch = data.viewpunch or VectorRand():Angle() * 0.05 + data.dmglow = data.dmglow or self.DamageLow or 25 + data.dmghigh = data.dmghigh or self.DamageHigh or 45 + data.dmgtype = data.dmgtype or DMG_CLUB + data.dmgforce = data.dmgforce or (self:GetTarget():GetPos() - self:GetPos()) * 7 + Vector( 0, 0, 16 ) + data.dmgforce.z = math.Clamp(data.dmgforce.z, 1, 16) + + + self:EmitSound("npc/zombie_poison/pz_throw2.wav", 50, math.random(75, 125)) + + self:SetAttacking( true ) + + self:TimedEvent(0.1, function() + self:EmitSound( data.attacksound ) + end) + + if self:GetTarget():IsPlayer() then + for k,v in pairs(data.attackseq.dmgtimes) do + self:TimedEvent( v, function() + if !self:GetStop() and self:IsValidTarget( self:GetTarget() ) and self:TargetInRange( self:GetAttackRange() + 10 ) then + local dmgAmount = math.random( data.dmglow, data.dmghigh ) + local dmgInfo = DamageInfo() + dmgInfo:SetAttacker( self ) + dmgInfo:SetDamage( dmgAmount ) + dmgInfo:SetDamageType( data.dmgtype ) + dmgInfo:SetDamageForce( data.dmgforce ) + self:GetTarget():TakeDamageInfo(dmgInfo) + if !IsValid(self:GetTarget()) then return end + self:GetTarget():EmitSound( data.hitsound, 50, math.random( 80, 160 ) ) + self:GetTarget():ViewPunch( data.viewpunch ) + self:GetTarget():SetVelocity( data.dmgforce ) + + local blood = ents.Create("env_blood") + blood:SetKeyValue("targetname", "carlbloodfx") + blood:SetKeyValue("parentname", "prop_ragdoll") + blood:SetKeyValue("spawnflags", 8) + blood:SetKeyValue("spraydir", math.random(500) .. " " .. math.random(500) .. " " .. math.random(500)) + blood:SetKeyValue("amount", dmgAmount * 5) + blood:SetCollisionGroup( COLLISION_GROUP_WORLD ) + blood:SetPos( self:GetTarget():GetPos() + self:GetTarget():OBBCenter() + Vector( 0, 0, 10 ) ) + blood:Spawn() + blood:Fire("EmitBlood") + SafeRemoveEntityDelayed( blood, 2) -- Just to make sure everything gets cleaned + end + end) + end + end + + self:TimedEvent(data.attackdur, function() + self:SetAttacking(false) + self:SetLastAttack(CurTime()) + end) + + self:PlayAttackAndWait(data.attackseq.seq, 1) +end + +function ENT:PlayAttackAndWait( name, speed ) + + local len = self:SetSequence( name ) + speed = speed or 1 + + self:ResetSequenceInfo() + self:SetCycle( 0 ) + self:SetPlaybackRate( speed ) + + local endtime = CurTime() + len / speed + + while ( true ) do + + if ( endtime < CurTime() ) then + if !self:GetStop() then + self:StartActivity( ACT_WALK ) + self.loco:SetDesiredSpeed( self:GetRunSpeed() ) + end + return + end + if self:IsValidTarget( self:GetTarget() ) and self:TargetInRange( self:GetAttackRange() * 2 ) then + self.loco:SetDesiredSpeed( self:GetRunSpeed() / 3 ) + self.loco:Approach( self:GetTarget():GetPos(), 10 ) + self.loco:FaceTowards( self:GetTarget():GetPos() ) + end + + coroutine.yield() + + end + +end + +--we do our own jump since the loco one is a bit weird. +function ENT:Jump() + if CurTime() < self:GetLastLand() + 0.5 or navmesh.GetNavArea(self:GetPos(), 50):HasAttributes( NAV_MESH_NO_JUMP ) then return end + if !self:IsOnGround() then return end + self.loco:SetDesiredSpeed( 450 ) + self.loco:SetAcceleration( 5000 ) + self:SetJumping( true ) + --self:SetSolidMask( MASK_NPCSOLID_BRUSHONLY ) + self.loco:Jump() + --Boost them + self:TimedEvent( 0.5, function() self.loco:SetVelocity( self:GetForward() * 5 ) end) +end + +function ENT:Flames( state ) + if state then + self.FlamesEnt = ents.Create("env_fire") + if IsValid( self.FlamesEnt ) then + self.FlamesEnt:SetParent(self) + self.FlamesEnt:SetOwner(self) + self.FlamesEnt:SetPos(self:GetPos() - Vector(0, 0, -50)) + --no glow + delete when out + start on + last forever + self.FlamesEnt:SetKeyValue("spawnflags", tostring(128 + 32 + 4 + 2 + 1)) + self.FlamesEnt:SetKeyValue("firesize", (1 * math.Rand(0.7, 1.1))) + self.FlamesEnt:SetKeyValue("fireattack", 0) + self.FlamesEnt:SetKeyValue("health", 0) + self.FlamesEnt:SetKeyValue("damagescale", "-10") -- only neg. value prevents dmg + + self.FlamesEnt:Spawn() + self.FlamesEnt:Activate() + end + elseif IsValid( self.FlamesEnt ) then + self.FlamesEnt:Remove() + self.FlamesEnt = nil + end +end + +function ENT:Explode(dmg, suicide) + + suicide = suicide or true + + local ex = ents.Create("env_explosion") + if !IsValid(ex) then return end + ex:SetPos(self:GetPos()) + ex:SetKeyValue( "iMagnitude", tostring( dmg ) ) + ex:SetOwner(self) + ex:Spawn() + ex:Fire("Explode",0,0) + ex:EmitSound( "weapons/explode" .. math.random( 3, 5 ) .. ".wav" ) + ex:Fire("Kill",0,0) + + if suicide then self:TimedEvent( 0, function() self:Kill() end ) end + +end + +function ENT:Kill(dmginfo, noprogress, noragdoll) + local dmg = dmginfo or DamageInfo() + if noragdoll then + self:Fire("Kill",0,0) + else + self:BecomeRagdoll(dmg) + end + if !noprogress then + nzEnemies:OnEnemyKilled(self, dmg:GetAttacker(), dmg, 0) + end + self:OnKilled(dmg) + --self:TakeDamage( 10000, self, self ) +end + +function ENT:RespawnZombie() + if SERVER then + if self:GetSpawner() then + self:GetSpawner():IncrementZombiesToSpawn() + end + + self:Remove() + end +end + +function ENT:Freeze(time) + --self:TimeOut(time) + self:SetStop(true) + self.FrozenTime = CurTime() + time +end + +function ENT:IsInSight() + for _, ply in pairs( player.GetAll() ) do + --can player see us or the teleport location + if ply:Alive() and ply:IsLineOfSightClear( self ) then + if ply:GetAimVector():Dot((self:GetPos() - ply:GetPos()):GetNormalized()) > 0 then + return true + end + end + end +end + +function ENT:TeleportToTarget( silent ) + + if !self:HasTarget() then return false end + + --that's probably not smart, just like me. SORRY D: + local locations = { + Vector( 256, 0, 0), + Vector( -256, 0, 0), + Vector( 0, 256, 0), + Vector( 0, -256, 0), + Vector( 256, 256, 0), + Vector( -256, -256, 0), + Vector( 512, 0, 0), + Vector( -512, 0, 0), + Vector( 0, 512, 0), + Vector( 0, -512, 0), + Vector( 512, 512, 0), + Vector( -512, -512, 0), + Vector( 1024, 0, 0), + Vector( -1024, 0, 0), + Vector( 0, 1024, 0), + Vector( 0, -1024, 0), + Vector( 1024, 1024, 0), + Vector( -1024, -1024, 0) + } + + --resource friendly shuffle + local rand = math.random + local n = #locations + + while n > 2 do + + local k = rand(n) -- 1 <= k <= n + + locations[n], locations[k] = locations[k], locations[n] + n = n - 1 + + end + + for _, v in pairs( locations ) do + + local area = navmesh.GetNearestNavArea( self:GetTarget():GetPos() + v ) + + if area then + + local location = area:GetRandomPoint() + Vector( 0, 0, 2 ) + + local tr = util.TraceHull( { + start = location, + endpos = location, + maxs = Vector( 16, 16, 40 ), --DOGE is small + mins = Vector( -16, -16, 0 ), + } ) + + --debugoverlay.Box( location, Vector( -16, -16, 0 ), Vector( 16, 16, 40 ), 5, Color( 255, 0, 0 ) ) + + if silent then + if !tr.Hit then + local inFOV = false + for _, ply in pairs( player.GetAllPlayingAndAlive() ) do + --can player see us or the teleport location + if ply:Alive() and ply:IsLineOfSightClear( location ) or ply:IsLineOfSightClear( self ) then + inFOV = true + end + end + if !inFOV then + self:SetPos( location ) + return true + end + end + else + self:SetPos( location ) + end + end + end + + return false + +end + +--broken +function ENT:InFieldOfView( pos ) + + local fov = math.rad( math.cos( 110 ) ) + local v = ( Vector( pos.x, pos.y, 0 ) - Vector( self:GetPos().x, self:GetPos().y, 0 ) ):GetNormalized() + + if self:GetAimVector():Dot( v ) > fov then + local tr = util.TraceLine( { + start = self:GetShootPos(), + endpos = pos + Vector( 0, 0, 64), + filter = self + } ) + + if !tr.Hit then return true end + + end + + return true + +end + +function ENT:BodyUpdate() + + self.CalcIdeal = ACT_IDLE + + local velocity = self:GetVelocity() + + local len2d = velocity:Length2D() + + local range = 10 + + local curstage = self.ActStages[self:GetActStage()] + local nextstage = self.ActStages[self:GetActStage() + 1] + + if self:GetActStage() <= 0 then -- We are currently idling, no range to start walking + if nextstage and len2d >= nextstage.minspeed then -- We DO NOT apply the range here, he needs to walk at 5 speed! + self:SetActStage( self:GetActStage() + 1 ) + end + -- If there is no minspeed for the next stage, someone did something wrong and we just idle :/ + elseif (curstage and len2d <= curstage.minspeed - range) then + self:SetActStage( self:GetActStage() - 1 ) + elseif (nextstage and len2d >= nextstage.minspeed + range) then + self:SetActStage( self:GetActStage() + 1 ) + elseif !self.ActStages[self:GetActStage() - 1] and len2d < curstage.minspeed - 4 then -- Much smaller range to go back to idling + self:SetActStage(0) + end + + curstage = self.ActStages[self:GetActStage()] + + if curstage and curstage.act then + local act = curstage.act + if type(act) == "table" then -- A table of sequences + local new = act[math.random(#act)] + self.CalcIdeal = new + elseif act then + self.CalcIdeal = act + end + end + + if self:IsJumping() and self:WaterLevel() <= 0 then + self.CalcIdeal = ACT_JUMP + end + + if !self:GetSpecialAnimation() and !self:IsAttacking() then + if self:GetActivity() != self.CalcIdeal and !self:GetStop() then self:StartActivitySeq(self.CalcIdeal) end + + if self.ActStages[self:GetActStage()] and !self.FrozenTime then + self:BodyMoveXY() + end + end + + if self.FrozenTime then + if self.FrozenTime < CurTime() then + self.FrozenTime = nil + self:SetStop(false) + end + self:BodyMoveXY() + --self:FrameAdvance() + else + self:FrameAdvance() + end + +end + +function ENT:UpdateSequence() + self:SetActStage(0) + self:BodyUpdate() + local actstage = self.ActStages[self:GetActStage()] + local act = actstage and actstage.act + if type(act) == "table" then -- A table of sequences + local new = act[math.random(#act)] + self:StartActivitySeq(new) + elseif act then + self:StartActivitySeq(act) + else + self:StartActivitySeq(self.CalcIdeal) + end +end + +function ENT:TriggerBarricadeJump( barricade, dir ) + if !self:GetSpecialAnimation() and (!self.NextBarricade or CurTime() > self.NextBarricade) then + self:SetSpecialAnimation(true) + self:SetBlockAttack(true) + + local id, dur, speed + local actstage = self.ActStages[self:GetActStage()] + local animtbl = actstage and actstage.barricadejumps or (self.ActStages[1] and self.ActStages[1].barricadejumps) + + if type(animtbl) == "number" then -- ACT_ is a number, this is set if it's an ACT + id = self:SelectWeightedSequence(animtbl) + dur = self:SequenceDuration(id) + speed = self:GetSequenceGroundSpeed(id) + if speed < 10 then + speed = 20 + end + else + local targettbl = animtbl and animtbl[math.random(#animtbl)] or self.JumpSequences + if targettbl then -- It is a table of sequences + id, dur = self:LookupSequenceAct(targettbl.seq) -- Whether it's an ACT or a sequence string + speed = targettbl.speed + --dur = targettbl.time or dur + else + id = self:SelectWeightedSequence(ACT_JUMP) + dur = self:SequenceDuration(id) + speed = 30 + end + end + + self:SetSolidMask(MASK_SOLID_BRUSHONLY) + self:SetCollisionGroup(COLLISION_GROUP_DEBRIS_TRIGGER) + --self.loco:SetAcceleration( 5000 ) + self.loco:SetDesiredSpeed(speed) + self:SetVelocity(self:GetForward() * speed) + self:SetSequence(id) + self:SetCycle(0) + self:SetPlaybackRate(1) + --self:BodyMoveXY() + --PrintTable(self:GetSequenceInfo(id)) + self:TimedEvent(dur, function() + self.NextBarricade = CurTime() + 2 + self:SetSpecialAnimation(false) + self:SetBlockAttack(false) + self.loco:SetAcceleration( self.Acceleration ) + self.loco:SetDesiredSpeed(self:GetRunSpeed()) + self:UpdateSequence() + end) + + local pos = barricade:GetPos() - dir * 40 + + --debugoverlay.Cross(pos, 5, 5) + -- This forces us to move straight through the barricade + -- in the opposite direction of where we hit the trace from + self:MoveToPos(pos, { + lookahead = 40, + tolerance = 1, + draw = false, + maxage = 3, + repath = 3, + }) + end +end + +function ENT:GetAimVector() + + return self:GetForward() + +end + +function ENT:GetShootPos() + + return self:EyePos() + +end + +function ENT:LookupSequenceAct(id) + if type(id) == "number" then + local id = self:SelectWeightedSequence(id) + local dur = self:SequenceDuration(id) + return id, dur + else + return self:LookupSequence(id) + end +end + +function ENT:StartActivitySeq(act) + if type(act) == "number" then + self:StartActivity(act) + else + local id, dur = self:LookupSequence(act) + --self:ResetSequenceInfo() + --self:ResetSequence(id) + self:SetSequence(id) + end +end + +--Helper function +function ENT:TimedEvent(time, callback) + timer.Simple(time, function() + if (IsValid(self) and self:Health() > 0) then + callback() + end + end) +end + +function ENT:ApplyRandomPush( power ) + if CurTime() < self:GetLastPush() + 0.2 or !self:IsOnGround() then return end + power = power or 100 + local vec = self.loco:GetVelocity() + VectorRand() * power + vec.z = math.random( 100 ) + self.loco:SetVelocity( vec ) + self:SetLastPush( CurTime() ) +end + +function ENT:ZombieWaterLevel() + local pos1 = self:GetPos() + local halfSize = self:OBBCenter() + local pos2 = pos1 + halfSize + local pos3 = pos2 + halfSize + if bit.band( util.PointContents( pos3 ), CONTENTS_WATER ) == CONTENTS_WATER or bit.band( util.PointContents( pos3 ), CONTENTS_SLIME ) == CONTENTS_SLIME then + return 3 + elseif bit.band( util.PointContents( pos2 ), CONTENTS_WATER ) == CONTENTS_WATER or bit.band( util.PointContents( pos2 ), CONTENTS_SLIME ) == CONTENTS_SLIME then + return 2 + elseif bit.band( util.PointContents( pos1 ), CONTENTS_WATER ) == CONTENTS_WATER or bit.band( util.PointContents( pos1 ), CONTENTS_SLIME ) == CONTENTS_SLIME then + return 1 + end + + return 0 +end + +--Targets +function ENT:HasTarget() + return self:IsValidTarget( self:GetTarget() ) +end + +function ENT:GetTarget() + return self.Target +end + +function ENT:GetTargetNavArea() + return self:HasTarget() and navmesh.GetNearestNavArea( self:GetTarget():GetPos(), false, 100) +end + +function ENT:SetTarget( target ) + self.Target = target + if self.Target != target then + self:SetLastTargetChange(CurTime()) + end +end + +function ENT:IsTarget( ent ) + return self.Target == ent +end + +function ENT:RemoveTarget() + self:SetTarget( nil ) +end + +function ENT:IsValidTarget( ent ) + if !ent then return false end + return IsValid( ent ) and ent:GetTargetPriority() != TARGET_PRIORITY_NONE +end + +function ENT:GetIgnoredTargets() + return self.tIgnoreList +end + +function ENT:IgnoreTarget( target ) + table.insert(self.tIgnoreList, target) +end + +function ENT:IsIgnoredTarget( ent ) + table.HasValue(self.tIgnoreList, ent) +end + +function ENT:ResetIgnores() + self.tIgnoreList = {} +end + +--AccessorFuncs +function ENT:IsJumping() + return self:GetJumping() +end + +function ENT:IsClimbing() + return self:GetClimbing() +end + +function ENT:IsAttacking() + return self:GetAttacking() +end + +function ENT:IsTimedOut() + return self:GetTimedOut() +end + +function ENT:SetInvulnerable(bool) + self.Invulnerable = bool +end + +function ENT:IsInvulnerable() + return self.Invulnerable +end diff --git a/gamemodes/nzombies/entities/entities/nz_zombieshield_back.lua b/gamemodes/nzombies/entities/entities/nz_zombieshield_back.lua new file mode 100644 index 00000000..fdc953db --- /dev/null +++ b/gamemodes/nzombies/entities/entities/nz_zombieshield_back.lua @@ -0,0 +1,80 @@ + +AddCSLuaFile() + +DEFINE_BASECLASS( "base_anim" ) + +ENT.PrintName = "Zombie Shield (Back)" +ENT.Author = "Zet0r" +ENT.Information = "When the shield is holstered, it goes on the back" + +ENT.Spawnable = false +ENT.AdminOnly = false +ENT.RenderGroup = RENDERGROUP_BOTH + +function ENT:Initialize() + + self:SetModel("models/weapons/w_zombieshield.mdl") + if SERVER then + self:SetHealth(450) -- 15 hits (30 damage per hit) + self:SetMaxHealth(450) + end + self:SetParent(self.Owner) + self:AddEffects(EF_BONEMERGE) + + self.Weapon = self:GetParent():GetWeapon("nz_zombieshield") + +end + +function ENT:Draw() + self:DrawModel() + if IsValid(self.Weapon) and self.Weapon:GetElectrified() then + local pos, ang = self:GetBonePosition(1) + nzEffects:DrawElectricArcs( self, pos, ang, 1, 1, 0.3 ) + end +end + +local function DrawShields() + +end +--hook.Add( "PostPlayerDraw", "nzZombieShieldDrawing", DrawShields ) + +function ENT:OnTakeDamage(dmginfo) + local dmg = dmginfo:GetDamage() + self:SetHealth(self:Health() - dmg) + local att = dmginfo:GetAttacker() + if att:IsValidZombie() and IsValid(self.Weapon) and self.Weapon:GetElectrified() then + local d = DamageInfo() + d:SetDamage( 250 ) + d:SetAttacker( self:GetParent() ) + d:SetDamageType( DMG_SHOCK ) + + att:TakeDamageInfo( d ) + end + if self:Health() <= 0 then + self.Owner:EmitSound("physics/metal/metal_box_break"..math.random(1,2)..".wav") + self.Owner:StripWeapon("nz_zombieshield") + self.Owner:EquipPreviousWeapon() + else + local pct = self:Health()/self:GetMaxHealth() + if pct < 0.2 then + self:SetBodygroup(0,2) + self.Weapon:SetDamage(2) + elseif pct < 0.6 then + self:SetBodygroup(0,1) + self.Weapon:SetDamage(1) + else + self:SetBodygroup(0,0) + self.Weapon:SetDamage(0) + end + self:EmitSound("physics/metal/metal_box_impact_hard"..math.random(1,3)..".wav") + end +end + +hook.Add("PostMapCleanup", "nzRestoreShields", function() + for k,v in pairs(player.GetAll()) do + local wep = v:GetWeapon("nz_zombieshield") + if IsValid(wep) then + wep:CreateBackShield(v) + end + end +end) \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/pap_weapon_fly/shared.lua b/gamemodes/nzombies/entities/entities/pap_weapon_fly/shared.lua new file mode 100644 index 00000000..894b1d64 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/pap_weapon_fly/shared.lua @@ -0,0 +1,67 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "pap_weapon_fly" +ENT.Author = "Zet0r" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + self:NetworkVar( "String", 0, "WeaponClass") +end + +function ENT:Initialize() + + self:SetMoveType( MOVETYPE_FLY ) + self:SetSolid( SOLID_OBB ) + --self:SetCollisionBounds(Vector(-5, -10, -3), Vector(5, 10, 3)) + --self:UseTriggerBounds(true, 1) + self:SetMoveType(MOVETYPE_FLY) + self:PhysicsInitBox(Vector(-5, -10, -3), Vector(5, 10, 3)) + self:GetPhysicsObject():EnableCollisions(false) + self:SetNotSolid(true) + self:DrawShadow( false ) + self.TriggerPos = self:GetPos() + + if SERVER then + self:SetUseType( SIMPLE_USE ) + self:SetWeaponClass(self.WepClass) + else + local wep = weapons.Get(self:GetWeaponClass()) + if wep and wep.DrawWorldModel then self.WorldModelFunc = wep.DrawWorldModel end + end +end + +function ENT:SetWepClass(class) + if IsValid(self.button) then + self.button:SetWepClass(class) + end + self:SetWeaponClass(class) +end + +function ENT:CreateTriggerZone(reroll) + if SERVER then + self.button = ents.Create("pap_weapon_trigger") + self.button:SetPos(self.TriggerPos) + self.button:SetAngles(self:GetAngles() - Angle(90,90,0)) + self.button:Spawn() + self.button:SetCollisionGroup(COLLISION_GROUP_DEBRIS_TRIGGER) + self.button.RerollingAtts = reroll + self.button:SetPaPOwner(self.Owner) + self.button.wep = self + self.button:SetWepClass(self.WepClass) + end +end + +function ENT:OnRemove() + if IsValid(self.button) then self.button:Remove() end +end + +if CLIENT then + function ENT:Draw() + -- We can use the stored world model draw function from the original weapon, but if it doesn't exist or errors, then just draw model + if !self.WorldModelFunc or !pcall(self.WorldModelFunc, self) then self:DrawModel() end + end +end diff --git a/gamemodes/nzombies/entities/entities/pap_weapon_trigger/shared.lua b/gamemodes/nzombies/entities/entities/pap_weapon_trigger/shared.lua new file mode 100644 index 00000000..e25e1bb6 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/pap_weapon_trigger/shared.lua @@ -0,0 +1,70 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "pap_weapon_trigger" +ENT.Author = "Zet0r" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + + self:NetworkVar( "String", 0, "WepClass" ) + self:NetworkVar( "Entity", 0, "PaPOwner" ) + +end + +function ENT:Initialize() + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_OBB ) + self:SetModel("models/hunter/blocks/cube05x1x025.mdl") + self:DrawShadow(false) + + if SERVER then + self:SetUseType( SIMPLE_USE ) + end +end + +function ENT:Use( activator, caller ) + if activator == self:GetPaPOwner() then + local class = self:GetWepClass() + local weapon + if self.RerollingAtts then + weapon = activator:GiveNoAmmo(class) + else + weapon = activator:Give(class) + end + timer.Simple(0, function() + if IsValid(weapon) and IsValid(activator) then + if activator:HasPerk("speed") and weapon:IsFAS2() then + weapon:ApplyNZModifier("speed") + end + if (activator:HasPerk("dtap") or activator:HasPerk("dtap2")) and weapon:IsFAS2() then + weapon:ApplyNZModifier("dtap") + end + weapon:ApplyNZModifier("pap") + weapon:SetClip1(weapon.Primary.ClipSize) + if IsValid(self.wep) then + self.wep.machine:SetBeingUsed(false) + self.wep:Remove() + end + end + --[[if !self.RerollingAtts then -- A 2000 point reroll should not give max ammo + print("Giving ammo") + nzWeps:GiveMaxAmmoWep(activator, class, true) -- We give pap ammo count + end]] + self:Remove() + end) + else + if IsValid(self:GetPaPOwner()) then + activator:PrintMessage( HUD_PRINTTALK, "This is " .. self:GetPaPOwner():Nick() .. "'s gun. You cannot take it." ) + end + end +end + +if CLIENT then + function ENT:Draw() + return + end +end diff --git a/gamemodes/nzombies/entities/entities/perk_machine/shared.lua b/gamemodes/nzombies/entities/entities/perk_machine/shared.lua new file mode 100644 index 00000000..2f6cc560 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/perk_machine/shared.lua @@ -0,0 +1,156 @@ +AddCSLuaFile() + +ENT.Type = "anim" + +ENT.PrintName = "perk_machine" +ENT.Author = "Alig96" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +ENT.DynLightColors = { + ["jugg"] = Color(255, 100, 100), + ["speed"] = Color(100, 255, 100), + ["dtap"] = Color(255, 255, 100), + ["revive"] = Color(100, 100, 255), + ["dtap2"] = Color(255, 255, 100), + ["staminup"] = Color(200, 255, 100), + ["phd"] = Color(255, 50, 255), + ["deadshot"] = Color(150, 200, 150), + ["mulekick"] = Color(100, 200, 100), + ["cherry"] = Color(50, 50, 200), + ["tombstone"] = Color(100, 100, 100), + ["whoswho"] = Color(100, 100, 255), + ["vulture"] = Color(255, 100, 100), + ["pap"] = Color(200, 220, 220), +} + +function ENT:SetupDataTables() + self:NetworkVar("String", 0, "PerkID") + self:NetworkVar("Bool", 0, "Active") + self:NetworkVar("Bool", 1, "BeingUsed") + self:NetworkVar("Int", 0, "Price") +end + +function ENT:Initialize() + if SERVER then + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + self:DrawShadow( false ) + self:SetUseType( SIMPLE_USE ) + self:SetBeingUsed(false) + local PerkData = nzPerks:Get(self:GetPerkID()) + self:SetPrice(PerkData.price) + end +end + +function ENT:TurnOn() + self:SetActive(true) + self:Update() +end + +function ENT:TurnOff() + self:SetActive(false) + self:Update() +end + +function ENT:Update() + local PerkData = nzPerks:Get(self:GetPerkID()) + local skinmodel = PerkData.model + if skinmodel then + self:SetModel(skinmodel) + if self:IsOn() then + self:SetSkin(PerkData.on_skin or 0) + else + self:SetSkin(PerkData.off_skin or 1) + end + else + self:SetModel(PerkData and (self:IsOn() and PerkData.on_model or PerkData.off_model) or "") + end +end + +function ENT:IsOn() + return self:GetActive() +end + +local MachinesNoDrink = { + ["pap"] = true, +} + +function ENT:Use(activator, caller) + local PerkData = nzPerks:Get(self:GetPerkID()) + + if self:IsOn() then + local price = self:GetPrice() + -- As long as they have less than the max perks, unless it's pap + if #activator:GetPerks() < GetConVar("nz_difficulty_perks_max"):GetInt() or self:GetPerkID() == "pap" then + -- If they have enough money + local func = function() + local id = self:GetPerkID() + if !activator:HasPerk(id) then + local given = true + + if PerkData.condition then + given = PerkData.condition(id, activator, self) + end + + -- Call a hook for it + local hookblock = hook.Call("OnPlayerBuyPerkMachine", nil, activator, self) + if hookblock != nil then -- Only if the hook returned true/false + given = hookblock + end + + if given then + if !PerkData.specialmachine then + local wep = activator:Give("nz_perk_bottle") + if IsValid(wep) then wep:SetPerk(id) end + timer.Simple(3, function() + if IsValid(activator) and activator:GetNotDowned() then + activator:GivePerk(id, self) + end + end) + else + activator:GivePerk(id, self) + end + self:EmitSound("nz/machines/jingle/"..id.."_get.wav", 75) + return true + end + else + print("Already have perk") + return false + end + end + + -- If a perk has NoBuy true, then it won't run a Buy on it but just run the func directly + -- (Allows stuff like dynamic pricing and conditional checks, similar to PaP) + if PerkData.nobuy then func() else activator:Buy(price, self, func) end + else + print(activator:Nick().." already has max perks") + end + end +end + +if CLIENT then + local usedcolor = Color(255,255,255) + + function ENT:Draw() + self:DrawModel() + if self:GetActive() then + if !self.NextLight or CurTime() > self.NextLight then + local dlight = DynamicLight( self:EntIndex() ) + if ( dlight ) then + local col = nzPerks:Get(self:GetPerkID()).color or usedcolor + dlight.pos = self:GetPos() + self:OBBCenter() + dlight.r = col.r + dlight.g = col.g + dlight.b = col.b + dlight.brightness = 2 + dlight.Decay = 1000 + dlight.Size = 256 + dlight.DieTime = CurTime() + 1 + end + if math.random(300) == 1 then self.NextLight = CurTime() + 0.05 end + end + end + end +end \ No newline at end of file diff --git a/nzombies3/entities/entities/player_spawns/shared.lua b/gamemodes/nzombies/entities/entities/player_spawns/shared.lua similarity index 80% rename from nzombies3/entities/entities/player_spawns/shared.lua rename to gamemodes/nzombies/entities/entities/player_spawns/shared.lua index 208782f9..d59950de 100644 --- a/nzombies3/entities/entities/player_spawns/shared.lua +++ b/gamemodes/nzombies/entities/entities/player_spawns/shared.lua @@ -1,26 +1,27 @@ AddCSLuaFile( ) ENT.Type = "anim" - + ENT.PrintName = "player_spawns" ENT.Author = "Alig96" ENT.Contact = "Don't" ENT.Purpose = "" ENT.Instructions = "" +ENT.NZOnlyVisibleInCreative = true function ENT:Initialize() self:SetModel( "models/player/odessa.mdl" ) self:SetMoveType( MOVETYPE_NONE ) self:SetSolid( SOLID_VPHYSICS ) self:SetCollisionGroup( COLLISION_GROUP_WEAPON ) - self:SetColor(0, 255, 0, 255) + self:SetColor(Color(0,0,255)) self:DrawShadow( false ) end if CLIENT then function ENT:Draw() - if nz.Rounds.Data.CurrentState == ROUND_CREATE then + if nzRound:InState( ROUND_CREATE ) then self:DrawModel() end end diff --git a/gamemodes/nzombies/entities/entities/point_worldhint/cl_init.lua b/gamemodes/nzombies/entities/entities/point_worldhint/cl_init.lua new file mode 100644 index 00000000..2de9786c --- /dev/null +++ b/gamemodes/nzombies/entities/entities/point_worldhint/cl_init.lua @@ -0,0 +1,39 @@ +include("shared.lua") + +function ENT:Initialize() + self:DrawShadow(false) + self:SetMoveType(MOVETYPE_NONE) + self:SetSolid(SOLID_NONE) + self:SetCollisionGroup(COLLISION_GROUP_WORLD) +end + +local GripMaterial = Material( "sprites/grip" ) +function ENT:Draw() + if !nzRound:InState( ROUND_CREATE ) then return end + render.SetMaterial( GripMaterial ) + render.DrawSprite( self:GetPos(), 16, 16, color_white ) + --self:DrawHint() +end + +function ENT:DrawHint() + -- Only if set to ALL or HUMANS + if self:GetViewable() == 0 or self:GetViewable() == 4 then + local pos = self:GetPos() + local eyepos = EyePos() + local range = self:GetRange() + + if range <= 0 then + DrawWorldHint(self:GetHint(), pos) + else + local dist = pos:Distance(eyepos) + if dist <= range then + --[[local fadeoff = range * 0.75 + if dist >= fadeoff then + DrawWorldHint(self:GetHint(), pos, 1 - (dist - fadeoff) / range) + else]] + DrawWorldHint(self:GetHint(), pos) + --end + end + end + end +end diff --git a/gamemodes/nzombies/entities/entities/point_worldhint/init.lua b/gamemodes/nzombies/entities/entities/point_worldhint/init.lua new file mode 100644 index 00000000..658c6ddc --- /dev/null +++ b/gamemodes/nzombies/entities/entities/point_worldhint/init.lua @@ -0,0 +1,44 @@ +AddCSLuaFile("cl_init.lua") +AddCSLuaFile("shared.lua") + +include("shared.lua") + +function ENT:Initialize() + -- Remove it as soon as it spawns, if the gamemode hasn't been enabled in Map Settings + if !nzMapping.Settings.gamemodeentities then + self:Remove() + end + + self:DrawShadow(false) + self:SetMoveType(MOVETYPE_NONE) + self:SetSolid(SOLID_NONE) + self:SetCollisionGroup(COLLISION_GROUP_WORLD) +end + +function ENT:AcceptInput(name, activator, caller, args) + if name == "setviewer" then + self:SetKeyValue("viewer", args) + return true + elseif name == "sethint" then + self:SetKeyValue("hint", args) + return true + elseif name == "setrange" then + self:SetKeyValue("range", args) + return true + end +end + +function ENT:KeyValue(key, value) + key = string.lower(key) + if key == "viewer" then + self:SetViewable(tonumber(value) or 0) + elseif key == "hint" then + self:SetHint(value) + elseif key == "range" then + self:SetRange(tonumber(value) or 0) + end +end + +function ENT:UpdateTransmitState() + return TRANSMIT_ALWAYS +end diff --git a/gamemodes/nzombies/entities/entities/point_worldhint/shared.lua b/gamemodes/nzombies/entities/entities/point_worldhint/shared.lua new file mode 100644 index 00000000..e7ea0ed5 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/point_worldhint/shared.lua @@ -0,0 +1,14 @@ +ENT.Type = "anim" + +AccessorFuncDT(ENT, "Viewable", "Int", 0) +AccessorFuncDT(ENT, "Hint", "String", 0) +AccessorFuncDT(ENT, "Range", "Float", 0) +AccessorFuncDT(ENT, "Translated", "Bool", 0) + +function ENT:GetHint() + local hint = self:GetDTString(0) + + --if self:GetTranslated() then return translate.Get(hint) end + + return hint +end diff --git a/gamemodes/nzombies/entities/entities/point_zsmessage/init.lua b/gamemodes/nzombies/entities/entities/point_zsmessage/init.lua new file mode 100644 index 00000000..2a7de540 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/point_zsmessage/init.lua @@ -0,0 +1,65 @@ +ENT.Type = "point" + +function ENT:Initialize() + -- Remove it as soon as it spawns, if the gamemode hasn't been enabled in Map Settings + if !nzMapping.Settings.gamemodeentities then + self:Remove() + end + self.SendTo = self.SendTo or -1 +end + +function ENT:Think() +end + +function ENT:AcceptInput(name, caller, activator, args) + name = string.lower(name) + if name == "message" then + args = args or "" + + args = string.gsub(args, "<.-=.->", "") + args = string.gsub(args, "", "") + + if self.SendTo == 0 then + nz_zsCenterNotifyAll(args) + elseif self.SendTo == -1 then + for _, pl in pairs(player.GetAll()) do + if pl == activator or pl == caller then + nz_zsCenterNotifyPlayer(pl, args) + break + end + end + else + for _, pl in pairs(player.GetAll()) do + if self.SendTo == TEAM_HUMAN then -- Only humans + nz_zsCenterNotifyPlayer(pl, args) + end + end + end + + return true + elseif name == "setundeadhudmessage" or name == "setzombiehudmessage" then + SetGlobalString("hudoverride"..TEAM_UNDEAD, args) + elseif name == "sethumanhudmessage" or name == "setsurvivorhudmessage" then + --SetGlobalString("hudoverride"..TEAM_HUMAN, args) + elseif name == "clearundeadhudmessage" or name == "clearzombiehudmessage" then + --SetGlobalString("hudoverride"..TEAM_UNDEAD, "") + elseif name == "clearhumanhudmessage" or name == "clearsurvivorhudmessage" then + SetGlobalString("hudoverride"..TEAM_HUMAN, "") + end +end + +function ENT:KeyValue(key, value) + key = string.lower(key) + if key == "team" then + value = string.lower(value or "") + if value == "zombie" or value == "undead" or value == "zombies" then + self.SendTo = TEAM_UNDEAD + elseif value == "human" or value == "humans" then + self.SendTo = TEAM_HUMAN + elseif value == "activator" or value == "caller" or value == "private" then + self.SendTo = -1 + else + self.SendTo = 0 + end + end +end diff --git a/gamemodes/nzombies/entities/entities/power_box/shared.lua b/gamemodes/nzombies/entities/entities/power_box/shared.lua new file mode 100644 index 00000000..0632540a --- /dev/null +++ b/gamemodes/nzombies/entities/entities/power_box/shared.lua @@ -0,0 +1,77 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "Zombies Power" +ENT.Author = "Zet0r" +ENT.Contact = "" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + + self:NetworkVar( "Bool", 0, "Switch" ) + self:NetworkVar( "Entity", 0, "PowerHandle") + +end + +function ENT:Initialize() + if SERVER then + self:SetModel( "models/nzprops/zombies_power_lever.mdl" ) + self:SetSolid( SOLID_VPHYSICS ) + self:SetMoveType( MOVETYPE_NONE ) + self:SetUseType( ONOFF_USE ) + self:SetSwitch(false) + + self.Handle = ents.Create("nz_prop_effect_attachment") + self.Handle:SetModel("models/nzprops/zombies_power_lever_handle.mdl") + self.Handle:SetAngles( self:GetAngles() ) + self.Handle:SetPos(self:GetPos() + self:GetAngles():Up()*46 + self:GetAngles():Forward()*7) + self.Handle:Spawn() + self.Handle:SetParent(self) + self:SetPowerHandle(self.Handle) + + self:DeleteOnRemove( self.Handle ) + else + self.Switched = false + end +end + +function ENT:Use( activator ) + + if ( !activator:IsPlayer() ) then return end + if !IsElec() and nzRound:InProgress() then + self:SetSwitch(true) + self.Switched = 0 + nzElec:Activate() + end + +end + +if CLIENT then + + local offang = Angle(0,0,0) + local onang = Angle(-90,0,0) + + function ENT:Think() + local handle = self:GetPowerHandle() + if self:GetSwitch() != self.Switched then + self.Switching = math.Approach( self.Switching or 0, 1, FrameTime() * 2 ) + local ang = self:GetAngles() + if self:GetSwitch() then + handle:SetRenderAngles(LerpAngle(self.Switching, self:LocalToWorldAngles(offang), self:LocalToWorldAngles(onang))) + else + handle:SetRenderAngles(LerpAngle(self.Switching, self:LocalToWorldAngles(onang), self:LocalToWorldAngles(offang))) + end + + if self.Switching >= 1 then + self.Switched = self:GetSwitch() + self.Switching = nil + end + end + end + + function ENT:Draw() + self:DrawModel() + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/prop_buys/shared.lua b/gamemodes/nzombies/entities/entities/prop_buys/shared.lua new file mode 100644 index 00000000..a6691ce2 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/prop_buys/shared.lua @@ -0,0 +1,114 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "wall_block_buy" +ENT.Author = "Alig96" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + + self:NetworkVar( "Bool", 0, "NWLocked" ) + +end + +function ENT:Initialize() + if SERVER then + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + self:DrawShadow( false ) + self:SetUseType( SIMPLE_USE ) + self.Boundone,self.Boundtwo = self:GetCollisionBounds() + self:BlockLock(true) + end +end + +function ENT:BlockUnlock(spawn) + --self.Locked = false + --self:SetNoDraw( true ) + if SERVER then + --self:SetCollisionBounds( Vector(-4, -4, 0), Vector(4, 4, 64) ) + self:SetSolid( SOLID_NONE ) + self:SetNWLocked(false) + self:EmitSound("nz/effects/gone.wav") + if !spawn then -- Spawning a prop shouldn't register it to the doors list + self:SetLocked(false) + end + local pos = self:GetPos() + + timer.Simple(0.5, function() + if IsValid(self) then + if !self:GetNWLocked() then + self:SetNoDraw(true) + end + end + end) + + local e = EffectData() + e:SetRadius(1) + e:SetMagnitude(0.5) + e:SetScale(1) + e:SetEntity(self) + util.Effect("lightning_field", e) + end +end + +function ENT:BlockLock(spawn) + --self.Locked = true + --self:SetNoDraw( false ) + if SERVER then + --self:SetCollisionBounds( self.Boundone, self.Boundtwo ) + self:SetSolid( SOLID_VPHYSICS ) + self:SetNoDraw(false) + self:SetNWLocked(true) + if !spawn then + self:SetLocked(true) + end + end +end + +function ENT:OnRemove() + if SERVER then + nzDoors:RemoveLink( self, true ) + self:SetLocked(false) + else + --self:SetLocked(false) + end +end + +if CLIENT then + + function ENT:Think() + if !self.ShakeEffectTime then + if !self:GetNoDraw() and !self:GetNWLocked() then + self.ShakeEffectTime = CurTime() + 0.3 + self.ShakePos = self:GetNetworkOrigin() + end + else + if CurTime() > self.ShakeEffectTime then + self.ShakePos = self.ShakePos + Vector(0,0,1000)*FrameTime() + if CurTime() - self.ShakeEffectTime >= 0.5 then + self.ShakePos = nil + self.ShakeEffectTime = nil + self:SetRenderOrigin(nil) + end + end + end + end + + function ENT:Draw() + if self.ShakePos then + --print("Yo shakey") + self:SetRenderOrigin(self.ShakePos + Vector(math.Rand(-1,1), math.Rand(-1,1), math.Rand(-1,1))) + end + self:DrawModel() + + if nzRound:InState( ROUND_CREATE ) then + if nzDoors.DisplayLinks[self] then + nzDisplay.DrawLinks(self, nzDoors.PropDoors[self:EntIndex()].link) + end + end + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/random_box/shared.lua b/gamemodes/nzombies/entities/entities/random_box/shared.lua new file mode 100644 index 00000000..90abcaad --- /dev/null +++ b/gamemodes/nzombies/entities/entities/random_box/shared.lua @@ -0,0 +1,239 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "random_box" +ENT.Author = "Alig96" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + + self:NetworkVar( "Bool", 0, "Open" ) + +end + +function ENT:Initialize() + + self:SetModel( "models/hoff/props/mysterybox/box.mdl" ) + self:PhysicsInit( SOLID_VPHYSICS ) + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + + --[[local phys = self:GetPhysicsObject() + if (phys:IsValid()) then + phys:Wake() + end]] + + self:DrawShadow( false ) + self:AddEffects( EF_ITEM_BLINK ) + self:SetOpen(false) + self.Moving = false + self:Activate() + if SERVER then + self:SetUseType( SIMPLE_USE ) + end + + if CLIENT then + self.Light = ClientsideModel("models/effects/vol_light128x512.mdl") + local ang = self:GetAngles() + self.Light:SetAngles(Angle(0, ang[2], 180)) + self.Light:SetPos(self:GetPos() - Vector(0,0,50)) + --self.Light:SetParent(self) + self.Light:SetColor(Color(150,200,255)) + self.Light:DrawShadow(false) + local min, max = self.Light:GetRenderBounds() + self.Light:SetRenderBounds(Vector(min.x, min.y, min.z), Vector(max.x, max.y, max.z*10)) + + local scale = Vector( 1, 1, 5 ) + local mat = Matrix() + mat:Scale( scale ) + self.Light:EnableMatrix( "RenderMultiply", mat ) + + self.Light:Spawn() + end +end + +function ENT:Use( activator, caller ) + if self:GetOpen() == true or self.Moving then return end + self:BuyWeapon(activator) + -- timer.Simple(5,function() self:MoveAway() end) +end + +function ENT:BuyWeapon(ply) + ply:Buy(nzPowerUps:IsPowerupActive("firesale") and 10 or 950, self, function() + local class = nzRandomBox.DecideWep(ply) + if class != nil then + --ply:TakePoints(nzPowerUps:IsPowerupActive("firesale") and 10 or 950) + self:Open() + local wep = self:SpawnWeapon( ply, class ) + wep.Buyer = ply + return true + else + ply:PrintMessage( HUD_PRINTTALK, "No available weapons left!") + return false + end + end) +end + + +function ENT:Open() + local sequence = self:LookupSequence("Close") + self:ResetSequence(sequence) + self:RemoveEffects( EF_ITEM_BLINK ) + + self:SetOpen(true) +end + +function ENT:Close() + local sequence = self:LookupSequence("Open") + self:ResetSequence(sequence) + self:AddEffects( EF_ITEM_BLINK ) + + self:SetOpen(false) +end + +function ENT:SpawnWeapon(activator, class) + local wep = ents.Create("random_box_windup") + local ang = self:GetAngles() + wep:SetAngles( ang ) + wep:SetPos( self:GetPos() + ang:Up()*10 ) + wep:SetWepClass(class) + wep:Spawn() + wep.Buyer = activator + --wep:SetParent( self ) + wep.Box = self + --wep:SetAngles( self:GetAngles() ) + self:EmitSound("nz/randombox/random_box_jingle.wav") + + return wep +end + +function ENT:Think() + self:NextThink(CurTime()) + + if self.MarkedForRemoval and !self:GetOpen() then + self:Remove() + end + + return true +end + +function ENT:MoveAway() + nzNotifications:PlaySound("nz/randombox/Announcer_Teddy_Zombies.wav", 0) + self.Moving = true + self:SetSolid(SOLID_NONE) + local s = 0 + local ang = self:GetAngles() + -- Shake Effect + timer.Create( "shake", 0.1, 300, function() + if s < 23 then + if s % 2 == 0 then + if self:IsValid() then + self:SetAngles(ang + Angle(10, 0, 0)) + end + else + if self:IsValid() then + self:SetAngles(ang + Angle(-10, 0, 0)) + end + end + else + self:SetAngles(ang) + timer.Destroy("shake") + end + s = s + 1 + end) + + -- Move Up + timer.Simple( 1, function() + timer.Create( "moveAway", 5, 1, function() + self.Moving = false + timer.Destroy("moveAway") + timer.Destroy("shake") + + self.SpawnPoint.Box = nil + --self.SpawnPoint:SetBodygroup(1,0) + self:MoveToNewSpot(self.SpawnPoint) + self:EmitSound("nz/randombox/poof.wav") + self:Remove() + end) + --print(self:GetMoveType()) + self:SetMoveType(MOVETYPE_FLY) + self:SetGravity(0.1) + self:SetNotSolid(true) + self:SetCollisionBounds(Vector(0,0,0), Vector(0,0,0)) + self:GetPhysicsObject():SetDamping(100, 0) + self:CollisionRulesChanged() + self:SetLocalVelocity(ang:Up()*100) + timer.Simple(1.5, function() + self:SetLocalVelocity( Vector(0,0,0) ) + self:SetVelocity( Vector(0,0,0) ) + self:SetMoveType(MOVETYPE_FLY) + self:Open() + self:SetLocalAngularVelocity( Angle(0, 0, 250) ) + timer.Simple(0.5, function() + self:SetLocalAngularVelocity( Angle(0, 0, 500) ) + timer.Simple(0.5, function() + self:SetLocalAngularVelocity( Angle(0, 0, 750) ) + timer.Simple(0.2, function() + self:SetLocalAngularVelocity( Angle(0, 0, 1000) ) + timer.Simple(0.2, function() + self:SetLocalAngularVelocity( Angle(0, 0, 2000) ) + end) + end) + end) + end) + end) + end) +end + +function ENT:MoveToNewSpot(oldspot) + -- Calls mapping function excluding the current spot + nzRandomBox.Spawn(oldspot) +end + +function ENT:MarkForRemoval() + self.MarkedForRemoval = true + --[[if !self:GetOpen() then + self:Remove() + else + hook.Add("Think", "RemoveBox"..self:EntIndex(), function() + if !IsValid(self) or !self:GetOpen() then + hook.Remove("Think", "RemoveBox"..self:EntIndex()) + self:Remove() + end + end) + end]] +end + +if CLIENT then + function ENT:Draw() + self:DrawModel() + end + + --[[hook.Add( "PostDrawOpaqueRenderables", "random_box_beam", function() + for k,v in pairs(ents.FindByClass("random_box")) do + if ( LocalPlayer():GetPos():Distance( v:GetPos() ) ) > 750 then + local Vector1 = v:GetPos() + Vector( 0, 0, -200 ) + local Vector2 = v:GetPos() + Vector( 0, 0, 5000 ) + render.SetMaterial( Material( "cable/redlaser" ) ) + render.DrawBeam( Vector1, Vector2, 300, 1, 1, Color( 255, 255, 255, 255 ) ) + end + end + end )]] + +end + +function ENT:OnRemove() + if CLIENT then + if IsValid(self.Light) then + self.Light:Remove() + end + else + if IsValid(self.SpawnPoint) then + --self.SpawnPoint.Box = nil + self.SpawnPoint:SetBodygroup(1,0) + end + end +end diff --git a/gamemodes/nzombies/entities/entities/random_box_spawns/shared.lua b/gamemodes/nzombies/entities/entities/random_box_spawns/shared.lua new file mode 100644 index 00000000..7252fd4e --- /dev/null +++ b/gamemodes/nzombies/entities/entities/random_box_spawns/shared.lua @@ -0,0 +1,23 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "random_box_spawns" +ENT.Author = "Zet0r" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:Initialize() + self:SetModel( "models/nzprops/mysterybox_pile.mdl" ) + self:SetColor( Color(255, 255, 255) ) + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + --self:SetNotSolid(true) + --self:SetCollisionGroup( COLLISION_GROUP_DEBRIS_TRIGGER ) + --self:DrawShadow( false ) +end + +if CLIENT then + +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/random_box_windup/shared.lua b/gamemodes/nzombies/entities/entities/random_box_windup/shared.lua new file mode 100644 index 00000000..4d342b4d --- /dev/null +++ b/gamemodes/nzombies/entities/entities/random_box_windup/shared.lua @@ -0,0 +1,154 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "random_box_windup" +ENT.Author = "Alig96" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + + self:NetworkVar( "Bool", 0, "Winding" ) + self:NetworkVar( "String", 0, "WepClass") + self:NetworkVar( "Bool", 1, "IsTeddy" ) + +end + +function ENT:Initialize() + + self:SetMoveType(MOVETYPE_NOCLIP) + self:SetLocalVelocity(self:GetAngles():Up() * 4) + + self:SetSolid( SOLID_OBB ) + self:DrawShadow( false ) + + self:SetWinding(true) + self:SetIsTeddy(false) + self.c = 0 + self.s = -20 + self.t = 0 + self:SetModel("models/weapons/w_rif_ak47.mdl") + --self:SetAngles(self.Box:GetAngles()) + local box = self.Box -- self.Box + + if SERVER then + -- Stop winding up + if nzMapping.Settings.rboxweps then + self.ScrollWepList = table.GetKeys(nzMapping.Settings.rboxweps) + end + timer.Simple(5, function() + self:SetWinding(false) + if self:GetWepClass() == "nz_box_teddy" then + self:SetModel("models/hoff/props/teddy_bear/teddy_bear.mdl") + self:SetAngles( self.Box:GetAngles() + Angle(-90,90,0) ) + self:SetLocalVelocity(self.Box:GetAngles():Up()*30) + nzNotifications:PlaySound("nz/randombox/teddy_bear_laugh.wav", 0) + self:SetIsTeddy(true) + if IsValid(self.Buyer) then self.Buyer:GivePoints(950) end -- Refund please + else + local wep = weapons.Get(self:GetWepClass()) + self:SetModel(wep.WM or wep.WorldModel) + self:SetLocalVelocity(Vector(0,0,0)) -- Stop + end + --print(self:GetModel()) + end) + -- If we time out, remove the object + timer.Simple(15, function() if IsValid(self) then self:SetLocalVelocity(self:GetAngles():Up()*-2) end end) + -- If we time out, remove the object + timer.Simple(25, function() if IsValid(self) then self.Box:Close() self:Remove() end end) + else + local wep = weapons.Get(self:GetWepClass()) + if !wep then + timer.Simple(1, function() + if IsValid(self) then + wep = weapons.Get(self:GetWepClass()) + if wep and wep.DrawWorldModel then self.WorldModelFunc = wep.DrawWorldModel end + end + end) + elseif wep.DrawWorldModel then + self.WorldModelFunc = wep.DrawWorldModel + end + end +end + +function ENT:Use( activator, caller ) + if !self:GetWinding() and self:GetWepClass() != "nz_box_teddy" then + if activator == self.Buyer then + local class = self:GetWepClass() + activator:Give(class) + nzWeps:GiveMaxAmmoWep(activator, class) + self.Box:Close() + self:Remove() + else + if IsValid(self.Buyer) then + activator:PrintMessage( HUD_PRINTTALK, "This is " .. self.Buyer:Nick() .. "'s gun. You cannot take it." ) + end + end + end +end + +function ENT:WindUp( ) + local gun + if self.ScrollWepList then + gun = weapons.Get(self.ScrollWepList[math.random(#self.ScrollWepList)]) + else + gun = table.Random(weapons.GetList()) + end + + if gun and gun.WorldModel != nil then + self:SetModel(gun.WM or gun.WorldModel) + end + --[[self.c = self.c + 1.3 + if self.c > 7 then + self.c = 7 + end + self:SetPos(Vector(self:GetPos().X, self:GetPos().Y, self:GetPos().Z + 0.1*self.c))]] +end + +function ENT:TeddyFlyUp( ) + self.t = self.t + 1 + if self.t > 25 then + self.Box:Close() + self.Box:MoveAway() + self:Remove() + self.t = 25 + end + --self:SetPos(Vector(self:GetPos().X, self:GetPos().Y, self:GetPos().Z + 1*self.t)) +end + +function ENT:WindDown( ) + --[[self.s = self.s + 1 + + if self.s > 7 then + self.s = 7 + end + if self.s >= 0 then + self:SetPos(Vector(self:GetPos().X, self:GetPos().Y, self:GetPos().Z - 0.1*self.s)) + end]] +end + +function ENT:Think() + if SERVER then + if self:GetIsTeddy() then + self:TeddyFlyUp() + elseif self:GetWinding() then + self:WindUp() + else + self:WindDown() + end + end +end + +if CLIENT then + function ENT:Draw() + -- If we've stopped winding + if !self:GetWinding() then + -- We can use the stored world model draw function from the original weapon, but if it doesn't exist or causes errors, then just draw model + if !self.WorldModelFunc or !pcall(self.WorldModelFunc, self) then self:DrawModel() end + else + self:DrawModel() + end + end +end diff --git a/gamemodes/nzombies/entities/entities/sent_grenade_frag/init.lua b/gamemodes/nzombies/entities/entities/sent_grenade_frag/init.lua new file mode 100644 index 00000000..284ee1af --- /dev/null +++ b/gamemodes/nzombies/entities/entities/sent_grenade_frag/init.lua @@ -0,0 +1,302 @@ + +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) +include( 'outputs.lua' ) + + +FRAG_GRENADE_BLIP_FREQUENCY = 1.0 +FRAG_GRENADE_BLIP_FAST_FREQUENCY = 0.3 + +FRAG_GRENADE_GRACE_TIME_AFTER_PICKUP = 1.5 +FRAG_GRENADE_WARN_TIME = 1.5 + +GRENADE_COEFFICIENT_OF_RESTITUTION = 0.2; + +local sk_plr_dmg_fraggrenade = 100 +local sk_npc_dmg_fraggrenade = 200 +local sk_fraggrenade_radius = 100 + +GRENADE_MODEL = "models/Weapons/w_grenade.mdl" + + +function ENT:GetShakeAmplitude() return 25.0; end +function ENT:GetShakeRadius() return 750.0; end + +// Damage accessors. +function ENT:GetDamage() + return self.m_flDamage; +end +function ENT:GetDamageRadius() + return self.m_DmgRadius; +end + +function ENT:SetDamage(flDamage) + self.m_flDamage = flDamage; +end + +function ENT:SetDamageRadius(flDamageRadius) + self.m_DmgRadius = flDamageRadius; +end + +// Bounce sound accessors. +function ENT:SetBounceSound( pszBounceSound ) + self.m_iszBounceSound = tostring( pszBounceSound ); +end + +function ENT:BlipSound() self.Entity:EmitSound( self.Sound.Blip ); end + +// UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution. +function ENT:Explode( pTrace, bitsDamageType ) + +if !( CLIENT ) then + + self.Entity:SetModel( "" );//invisible + self.Entity:SetColor( color_transparent ); + self.Entity:SetSolid( SOLID_NONE ); + + self.m_takedamage = DAMAGE_NO; + + local vecAbsOrigin = self.Entity:GetPos(); + local contents = util.PointContents ( vecAbsOrigin ); + + if ( pTrace.Fraction != 1.0 ) then + local vecNormal = pTrace.HitNormal; + local pdata = pTrace.MatType; + + util.BlastDamage( self.Entity, // don't apply cl_interp delay + self:GetOwner(), + self.Entity:GetPos(), + self.m_DmgRadius, + self.m_flDamage ); + else + util.BlastDamage( self.Entity, // don't apply cl_interp delay + self:GetOwner(), + self.Entity:GetPos(), + self.m_DmgRadius, + self.m_flDamage ); + end + + self:DoExplodeEffect(); + + self:OnExplode( pTrace ); + + self.Entity:EmitSound( self.Sound.Explode ); + + self.Touch = function( ... ) return end; + self.Entity:SetSolid( SOLID_NONE ); + + self.Entity:SetVelocity( vec3_origin ); + + // Because the grenade is zipped out of the world instantly, the EXPLOSION sound that it makes for + // the AI is also immediately destroyed. For this reason, we now make the grenade entity inert and + // throw it away in 1/10th of a second instead of right away. Removing the grenade instantly causes + // intermittent bugs with env_microphones who are listening for explosions. They will 'randomly' not + // hear explosion sounds when the grenade is removed and the SoundEnt thinks (and removes the sound) + // before the env_microphone thinks and hears the sound. + SafeRemoveEntityDelayed( self.Entity, 0.1 ); + +end + +end + +function ENT:Detonate() + + local tr; + local vecSpot;// trace starts here! + + self.Think = function( ... ) return end; + + vecSpot = self.Entity:GetPos() + Vector ( 0 , 0 , 8 ); + tr = {}; + tr.start = vecSpot; + tr.endpos = vecSpot + Vector ( 0, 0, -32 ); + tr.mask = MASK_SHOT_HULL; + tr.filter = self.Entity; + tr.collision = COLLISION_GROUP_NONE; + tr = util.TraceLine ( tr); + + if( tr.StartSolid ) then + // Since we blindly moved the explosion origin vertically, we may have inadvertently moved the explosion into a solid, + // in which case nothing is going to be harmed by the grenade's explosion because all subsequent traces will startsolid. + // If this is the case, we do the downward trace again from the actual origin of the grenade. (sjb) 3/8/2007 (for ep2_outland_09) + tr = {}; + tr.start = self.Entity:GetPos(); + tr.endpos = self.Entity:GetPos() + Vector( 0, 0, -32); + tr.mask = MASK_SHOT_HULL; + tr.filter = self.Entity; + tr.collision = COLLISION_GROUP_NONE; + tr = util.TraceLine( tr ); + end + + tr = self:Explode( tr, DMG_BLAST ); + + if ( self:GetShakeAmplitude() ) then + util.ScreenShake( self.Entity:GetPos(), self:GetShakeAmplitude(), 150.0, 1.0, self:GetShakeRadius() ); + end + +end + +/*--------------------------------------------------------- + Name: Initialize +---------------------------------------------------------*/ +function ENT:Initialize() + + self.m_hThrower = NULL; + self.m_hOriginalThrower = NULL; + self.m_bIsLive = false; + self.m_DmgRadius = 100; + self.m_flDetonateTime = CurTime() + GRENADE_TIMER; + self.m_flWarnAITime = CurTime() + GRENADE_TIMER - FRAG_GRENADE_WARN_TIME; + self.m_bHasWarnedAI = false; + + self:Precache( ); + + self.Entity:SetModel( GRENADE_MODEL ); + + if( self:GetOwner() && self:GetOwner():IsPlayer() ) then + self.m_flDamage = sk_plr_dmg_fraggrenade; + self.m_DmgRadius = sk_fraggrenade_radius; + else + self.m_flDamage = sk_npc_dmg_fraggrenade; + self.m_DmgRadius = sk_fraggrenade_radius; + end + + self.m_takedamage = DAMAGE_YES; + self.m_iHealth = 1; + + self.Entity:SetCollisionBounds( -Vector(4,4,4), Vector(4,4,4) ); + self:CreateVPhysics(); + + self:BlipSound(); + self.m_flNextBlipTime = CurTime() + FRAG_GRENADE_BLIP_FREQUENCY; + + self.m_combineSpawned = false; + self.m_punted = false; + + self:CreateEffects(); + + self:OnInitialize(); + self.BaseClass:Initialize(); + +end + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +function ENT:OnRestore() + + // If we were primed and ready to detonate, put FX on us. + if (self.m_flDetonateTime > 0) then + self:CreateEffects(); + end + + self.BaseClass:OnRestore(); + +end + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +function ENT:CreateEffects() + + local nAttachment = self.Entity:LookupAttachment( "fuse" ); + + // Start up the eye trail + self.m_pGlowTrail = util.SpriteTrail( self.Entity, nAttachment, self.Trail.Color, true, self.Trail.StartWidth, self.Trail.EndWidth, self.Trail.LifeTime, 1 / ( self.Trail.StartWidth + self.Trail.EndWidth ) * 0.5, self.Trail.Material ); + +end + +function ENT:CreateVPhysics() + + // Create the object in the physics system + self.Entity:PhysicsInit( SOLID_VPHYSICS, 0, false ); + + local Phys = self:GetPhysicsObject() + if ( Phys ) then + + Phys:SetMaterial( "grenade" ) + + end + return true; + +end + +function ENT:Precache() + + util.PrecacheModel( GRENADE_MODEL ); + + util.PrecacheSound( self.Sound.Blip ); + + util.PrecacheModel( "sprites/redglow1.vmt" ); + util.PrecacheModel( self.Trail.Material ); + + util.PrecacheSound( self.Sound.Explode ); + +end + +function ENT:SetTimer( detonateDelay, warnDelay ) + + self.m_flDetonateTime = CurTime() + detonateDelay; + self.m_flWarnAITime = CurTime() + warnDelay; + self.Entity:NextThink( CurTime() ); + + self:CreateEffects(); + +end + +function ENT:Think() + + self:OnThink() + + if( CurTime() > self.m_flDetonateTime ) then + self:Detonate(); + return; + end + + if( !self.m_bHasWarnedAI && CurTime() >= self.m_flWarnAITime ) then + self.m_bHasWarnedAI = true; + end + + if( CurTime() > self.m_flNextBlipTime ) then + self:BlipSound(); + + if( self.m_bHasWarnedAI ) then + self.m_flNextBlipTime = CurTime() + FRAG_GRENADE_BLIP_FAST_FREQUENCY; + else + self.m_flNextBlipTime = CurTime() + FRAG_GRENADE_BLIP_FREQUENCY; + end + end + + self.Entity:NextThink( CurTime() + 0.1 ); + +end + +function ENT:SetVelocity( velocity, angVelocity ) + + local pPhysicsObject = self:GetPhysicsObject(); + if ( pPhysicsObject ) then + pPhysicsObject:AddVelocity( velocity ); + pPhysicsObject:AddAngleVelocity( angVelocity ); + end + +end + +/*--------------------------------------------------------- + Name: OnTakeDamage +---------------------------------------------------------*/ +function ENT:OnTakeDamage( dmginfo ) + + // Manually apply vphysics because BaseCombatCharacter takedamage doesn't call back to CBaseEntity OnTakeDamage + self.Entity:TakePhysicsDamage( dmginfo ); + + // Grenades only suffer blast damage and burn damage. + if( !(dmginfo:GetDamageType() == (DMG_BLAST) ) ) then + return 0; + end + + return self.BaseClass:OnTakeDamage( dmginfo ); + +end + + + diff --git a/gamemodes/nzombies/entities/entities/sent_grenade_frag/outputs.lua b/gamemodes/nzombies/entities/entities/sent_grenade_frag/outputs.lua new file mode 100644 index 00000000..7c5de5d0 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/sent_grenade_frag/outputs.lua @@ -0,0 +1,69 @@ + +ENT.Sound = {} +ENT.Sound.Blip = "Grenade.Blip" +ENT.Sound.Explode = "BaseGrenade.Explode" + +ENT.Trail = {} +ENT.Trail.Color = Color( 255, 0, 0, 255 ) +ENT.Trail.Material = "sprites/bluelaser1.vmt" +ENT.Trail.StartWidth = 8.0 +ENT.Trail.EndWidth = 1.0 +ENT.Trail.LifeTime = 0.5 + +// Nice helper function, this does all the work. + +/*--------------------------------------------------------- + Name: DoExplodeEffect +---------------------------------------------------------*/ +function ENT:DoExplodeEffect() + + local info = EffectData(); + info:SetEntity( self.Entity ); + info:SetOrigin( self.Entity:GetPos() ); + + util.Effect( "Explosion", info ); + +end + +/*--------------------------------------------------------- + Name: OnExplode + Desc: The grenade has just exploded. +---------------------------------------------------------*/ +function ENT:OnExplode( pTrace ) + + local Pos1 = pTrace.HitPos + pTrace.HitNormal + local Pos2 = pTrace.HitPos - pTrace.HitNormal + + util.Decal( "Scorch", Pos1, Pos2 ); + +end + +/*--------------------------------------------------------- + Name: OnInitialize +---------------------------------------------------------*/ +function ENT:OnInitialize() +end + +/*--------------------------------------------------------- + Name: StartTouch +---------------------------------------------------------*/ +function ENT:StartTouch( entity ) +end + +/*--------------------------------------------------------- + Name: EndTouch +---------------------------------------------------------*/ +function ENT:EndTouch( entity ) +end + +/*--------------------------------------------------------- + Name: Touch +---------------------------------------------------------*/ +function ENT:Touch( entity ) +end + +/*--------------------------------------------------------- + Name: OnThink +---------------------------------------------------------*/ +function ENT:OnThink() +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/sent_grenade_frag/shared.lua b/gamemodes/nzombies/entities/entities/sent_grenade_frag/shared.lua new file mode 100644 index 00000000..c0725fcc --- /dev/null +++ b/gamemodes/nzombies/entities/entities/sent_grenade_frag/shared.lua @@ -0,0 +1,9 @@ + + +ENT.Type = "anim" +ENT.Base = "base_anim" +ENT.PrintName = "" +ENT.Author = "" + +ENT.Spawnable = false +ENT.AdminSpawnable = false diff --git a/gamemodes/nzombies/entities/entities/ttt_traitor_button/init.lua b/gamemodes/nzombies/entities/entities/ttt_traitor_button/init.lua new file mode 100644 index 00000000..a0375f4b --- /dev/null +++ b/gamemodes/nzombies/entities/entities/ttt_traitor_button/init.lua @@ -0,0 +1,116 @@ +AddCSLuaFile("shared.lua") +include("shared.lua") + +-- serverside only +ENT.RemoveOnPress = false + +ENT.Model = Model("models/weapons/w_bugbait.mdl") + +function ENT:Initialize() + self:SetModel(self.Model) + + --self:SetNoDraw(true) + self:DrawShadow(false) + self:SetSolid(SOLID_NONE) + self:SetMoveType(MOVETYPE_NONE) + + self:SetDelay(self.RawDelay or 1) + + if self:GetDelay() < 0 then + -- func_button can be made single use by setting delay to be negative, so + -- mimic that here + self.RemoveOnPress = true + end + + if self.RemoveOnPress then + self:SetDelay(-1) -- tells client we're single use + end + + if self:GetUsableRange() < 1 then + self:SetUsableRange(1024) + end + + self:SetNextUseTime(0) + self:SetTTTLocked(self:HasSpawnFlags(2048)) + + self:SetDescription(self.RawDescription or "?") + + self.RawDelay = nil + self.RawDescription = nil +end + +function ENT:KeyValue(key, value) + if key == "OnPressed" then + self:StoreOutput(key, value) + elseif key == "wait" then -- as Delay Before Reset in func_button + self.RawDelay = tonumber(value) + elseif key == "description" then + self.RawDescription = tostring(value) + + if self.RawDescription and string.len(self.RawDescription) < 1 then + self.RawDescription = nil + end + elseif key == "RemoveOnPress" then + self[key] = tobool(value) + else + self:SetNetworkKeyValue(key, value) + end +end + + +function ENT:AcceptInput(name, activator) + if name == "Toggle" then + self:SetTTTLocked(not self:GetTTTLocked()) + return true + elseif name == "Hide" or name == "Lock" then + self:SetTTTLocked(true) + return true + elseif name == "Unhide" or name == "Unlock" then + self:SetTTTLocked(false) + return true + end +end + +function ENT:TraitorUse(ply) + if not (IsValid(ply) and ply:IsPlaying() and ply:GetNotDowned()) then return false end + if not self:IsUsable() then return false end + + --if self:GetPos():Distance(ply:GetPos()) > self:GetUsableRange() then return false end + + -- send output to all entities linked to us + self:TriggerOutput("OnPressed", ply) + + if self.RemoveOnPress then + self:SetTTTLocked(true) + self:Remove() + else + -- lock ourselves until we should be usable again + self:SetNextUseTime(CurTime() + self:GetDelay()) + end + + return true +end + +--[[function ENT:Use(activator) + if self:IsUsable() then + local data = self:GetDoorData() + if data then + if data.price <= 0 or activator:CanAfford(data.price) then + self:TraitorUse(activator) + activator:TakePoints(data.price) + end + end + end +end]] + +function ENT:UseViaButtonBox(user) + if self:IsUsable() then + local data = self:GetDoorData() + if data then + if data.price <= 0 or activator:CanAfford(data.price) then + self:TraitorUse(activator) + activator:TakePoints(data.price) + end + end + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/ttt_traitor_button/shared.lua b/gamemodes/nzombies/entities/entities/ttt_traitor_button/shared.lua new file mode 100644 index 00000000..a9533a72 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/ttt_traitor_button/shared.lua @@ -0,0 +1,31 @@ +-- We remake the Traitor Button so it can be given a price and triggered in nZombies +-- If it has no price, it will not be usable - A price of 0 will make it usable for free + +ENT.Type = "anim" +ENT.Base = "base_anim" + +function ENT:SetupDataTables() + self:NetworkVar("Float", 0, "Delay") + self:NetworkVar("Float", 1, "NextUseTime") + self:NetworkVar("Bool", 0, "TTTLocked") + self:NetworkVar("String", 0, "Description") + self:NetworkVar("Int", 0, "UsableRange", {KeyName = "UsableRange"}) +end + +function ENT:IsUsable() + return (not self:GetTTTLocked()) and self:GetNextUseTime() < CurTime() and self:GetDoorData() +end + +if CLIENT then + local mat = Material( "icon16/exclamation.png" ) + function ENT:Draw() + if !nzRound:InState( ROUND_CREATE ) then return end + + render.SetMaterial( mat ) + render.DrawSprite( self:GetPos(), 4, 4, color_white ) + end + + -- Handling of buttons (copied from TTT Code) + + +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/wall_block/shared.lua b/gamemodes/nzombies/entities/entities/wall_block/shared.lua new file mode 100644 index 00000000..f909a09f --- /dev/null +++ b/gamemodes/nzombies/entities/entities/wall_block/shared.lua @@ -0,0 +1,56 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "wall_block" +ENT.Author = "Alig96 & Zet0r" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +ENT.NZOnlyVisibleInCreative = true + +--[[function ENT:SetupDataTables() + self:NetworkVar("Bool", 0, "BlockPlayers") + self:NetworkVar("Bool", 1, "BlockZombies") +end + +function ENT:SetFilter(players, zombies) + if players and zombies then + self:SetBlockPlayers(true) + self:SetBlockZombies(true) + self:SetCustomCollisionCheck(false) + self:SetColor(Color(255,255,255)) + elseif players and !zombies then + self:SetBlockPlayers(true) + self:SetBlockZombies(false) + self:SetCustomCollisionCheck(true) + self:SetColor(Color(100,100,255)) + elseif !players and zombies then + self:SetBlockPlayers(false) + self:SetBlockZombies(true) + self:SetCustomCollisionCheck(true) + self:SetColor(Color(255,100,100)) + end +end]] + +function ENT:Initialize() + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + self:DrawShadow( false ) + self:SetRenderMode( RENDERMODE_TRANSCOLOR ) + self:SetCustomCollisionCheck(true) + + -- YES! Finally found a way to make bullets pass through without disabling solidity! + --self:AddSolidFlags(FSOLID_CUSTOMRAYTEST) + --self:AddSolidFlags(FSOLID_CUSTOMBOXTEST) + +end + +if CLIENT then + function ENT:Draw() + if ConVarExists("nz_creative_preview") and !GetConVar("nz_creative_preview"):GetBool() and nzRound:InState( ROUND_CREATE ) then + self:DrawModel() + end + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/wall_buys/shared.lua b/gamemodes/nzombies/entities/entities/wall_buys/shared.lua new file mode 100644 index 00000000..f6214746 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/wall_buys/shared.lua @@ -0,0 +1,381 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "buy_gun_area" +ENT.Author = "Alig96 & Zet0r" +ENT.Contact = "Don't" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + self:NetworkVar( "String", 0, "WepClass" ) + self:NetworkVar( "String", 1, "Price" ) + self:NetworkVar( "Bool", 0, "Bought" ) + self:NetworkVar( "Bool", 1, "Flipped" ) +end + +local flipscale = Vector(1.5, 0.01, 1.5) -- Decides on which axis it flattens the outline +local normalscale = Vector(0.01, 1.5, 1.5) -- based on the bool self:GetFlipped() + +CreateClientConVar("nz_outlinedetail", "4", true) -- Controls the outline creation + +chalkmaterial = "chalk.png" --= Material("chalk.png", "unlitgeneric smooth") + +function ENT:Initialize() + if SERVER then + self:SetMoveType( MOVETYPE_NONE ) + --self:SetSolid( SOLID_VPHYSICS ) + self:SetCollisionGroup(COLLISION_GROUP_DEBRIS_TRIGGER) + self:SetUseType(SIMPLE_USE) + self:SetFlipped(true) -- Apparently makes it work with default orientation? + self:SetSolid( SOLID_OBB ) + self:PhysicsInit( SOLID_OBB ) + else + self.Flipped = self:GetFlipped() + local wep = weapons.Get(self:GetWepClass()) + if wep then + if wep.DrawWorldModel then self.WorldModelFunc = wep.DrawWorldModel end + + -- Forced precaching! + local model = ClientsideModel("models/hoff/props/teddy_bear/teddy_bear.mdl") + util.PrecacheModel(wep.VM or wep.ViewModel) + model:SetModel(wep.ViewModel) + if wep.VM then model:SetModel(wep.VM) end + model:Remove() + + self:RecalculateModelOutlines() + end + end + self:SetRenderMode(RENDERMODE_TRANSALPHA) + self:DrawShadow(false) + --self:SetColor(Color(0,0,0,0)) +end + +function ENT:OnRemove() + if CLIENT then + self:RemoveOutline() + end +end + +function ENT:RecalculateModelOutlines() + self:RemoveOutline() + local num = GetConVar("nz_outlinedetail"):GetInt() + local ang = self:GetAngles() + local curang = self:GetAngles() -- Modifies offset if flipped + local curpos = self:GetPos() + local wep = weapons.Get(self:GetWepClass()) + if !wep then self:RemoveOutline() return end + local model = wep.WM or wep.WorldModel + + -- Precache the model whenever it changes, including on spawn + util.PrecacheModel(wep.WM or wep.WorldModel) + + self.modelclass = self:GetWepClass() + + if !self.Flipped then + curang:RotateAroundAxis(curang:Up(), 90) + end + --print(curang, "HUDIASHUD", self.Flipped) + if num >= 1 then + self.Chalk1 = ClientsideModel(model) + local offset = curang:Up()*0.5 + curang:Forward()*-0.5 --Vector(0,-0.5,0.5) + self.Chalk1:SetPos(curpos + offset) + self.Chalk1:SetAngles(ang) + self.Chalk1:SetMaterial(chalkmaterial) + --self.Chalk:SetModelScale(1.7) + + local mat = Matrix() + mat:Scale( self.Flipped and flipscale or normalscale ) + + self.Chalk1:EnableMatrix( "RenderMultiply", mat ) + self.Chalk1:SetNoDraw(true) + self.Chalk1:SetParent(self) + end + + if num >= 2 then + self.Chalk2 = ClientsideModel(model) + offset = curang:Up()*-0.5 + curang:Forward()*0.5 + self.Chalk2:SetPos(curpos + offset) + self.Chalk2:SetAngles(ang) + self.Chalk2:SetMaterial(chalkmaterial) + --self.Chalk:SetModelScale(1.7) + + mat = Matrix() + mat:Scale( self.Flipped and flipscale or normalscale ) + + self.Chalk2:EnableMatrix( "RenderMultiply", mat ) + self.Chalk2:SetNoDraw(true) + self.Chalk2:SetParent(self) + end + + if num >= 3 then + self.Chalk3 = ClientsideModel(model) + offset = curang:Up()*0.5 + curang:Forward()*0.5 + self.Chalk3:SetPos(curpos + offset) + self.Chalk3:SetAngles(ang) + self.Chalk3:SetMaterial(chalkmaterial) + --self.Chalk:SetModelScale(1.7) + + mat = Matrix() + mat:Scale( self.Flipped and flipscale or normalscale ) + + self.Chalk3:EnableMatrix( "RenderMultiply", mat ) + self.Chalk3:SetNoDraw(true) + self.Chalk3:SetParent(self) + end + + if num >= 4 then + self.Chalk4 = ClientsideModel(model) + offset = curang:Up()*-0.5 + curang:Forward()*-0.5 + self.Chalk4:SetPos(curpos + offset) + self.Chalk4:SetAngles(ang) + self.Chalk4:SetMaterial(chalkmaterial) + --self.Chalk:SetModelScale(1.7) + + mat = Matrix() + mat:Scale( self.Flipped and flipscale or normalscale ) + + self.Chalk4:EnableMatrix( "RenderMultiply", mat ) + self.Chalk4:SetNoDraw(true) + self.Chalk4:SetParent(self) + end + + if num >= 1 then + self.ChalkCenter = ClientsideModel(model) + self.ChalkCenter:SetPos(curpos) + self.ChalkCenter:SetAngles(ang) + self.ChalkCenter:SetMaterial(chalkmaterial) + + mat = Matrix() + mat:Scale( self.Flipped and flipscale or normalscale ) + + self.ChalkCenter:EnableMatrix( "RenderMultiply", mat ) + self.ChalkCenter:SetNoDraw(true) + self.ChalkCenter:SetParent(self) + end +end + +function ENT:RemoveOutline() + if IsValid(self.Chalk1) then + self.Chalk1:Remove() + end + if IsValid(self.Chalk2) then + self.Chalk2:Remove() + end + if IsValid(self.Chalk3) then + self.Chalk3:Remove() + end + if IsValid(self.Chalk4) then + self.Chalk4:Remove() + end + if IsValid(self.ChalkCenter) then + self.ChalkCenter:Remove() + end +end + +if SERVER then + + function ENT:SetWeapon(weapon, price) + -- Add a special check for FAS weps + local price = price or self:GetPrice() + local wep = weapons.Get(weapon) + local model + if !wep then + model = "models/weapons/w_crowbar.mdl" + else + model = wep.WM or wep.WorldModel + --self:SetFlipped(false) + end + self:SetModel(model) + self:SetModelScale( 1.5, 0 ) + self.WeaponGive = weapon + self.Price = price + self:SetWepClass(weapon) + self:SetPrice(price) + end + + function ENT:ToggleRotate() + local ang = self:GetAngles() + self:SetFlipped(!self:GetFlipped()) + --self:SetAngles(self:GetAngles() + Angle(0,90,0)) + ang:RotateAroundAxis(ang:Up(), 90) + self:SetAngles(ang) + --print(self:GetFlipped()) + end + + function ENT:Use( activator, caller ) + local price = self.Price + + local wep + for k,v in pairs(activator:GetWeapons()) do + if v:GetClass() == self.WeaponGive then wep = v break end + end + if !wep then wep = weapons.Get(self.WeaponGive) end + if !wep then return end + local ammo_type = IsValid(wep) and wep:GetPrimaryAmmoType() or wep.Primary.Ammo + + local ammo_price = math.ceil((price - (price % 10))/2) + local ammo_price_pap = 4500 + local curr_ammo = activator:GetAmmoCount( ammo_type ) + local give_ammo = nzWeps:CalculateMaxAmmo(self.WeaponGive) - curr_ammo + + --print(ammo_type, curr_ammo, give_ammo) + + if !activator:HasWeapon( self.WeaponGive ) then + activator:Buy(price, self, function() + local wep = activator:Give(self.WeaponGive) + timer.Simple(0, function() if IsValid(wep) then wep:GiveMaxAmmo() end end) + self:SetBought(true) + return true + end) + elseif string.lower(ammo_type) != "none" and ammo_type != -1 then + local wep = activator:GetWeapon(self.WeaponGive) + if wep:HasNZModifier("pap") then + activator:Buy(ammo_price_pap, self, function() + if give_ammo != 0 then + wep:GiveMaxAmmo() + return true + else + print("Max Clip!") + return false -- Didn't work, don't take points! + end + end) + else -- Refill ammo + activator:Buy(ammo_price, self, function() + if give_ammo != 0 then + wep:GiveMaxAmmo() + return true + else + print("Max Clip!") + return false + end + end) + end + end + return + end +end + + +if CLIENT then + + function ENT:Update() + local wep = weapons.Get(self:GetWepClass()) + if wep then + if wep.DrawWorldModel then self.WorldModelFunc = wep.DrawWorldModel end + util.PrecacheModel(wep.WM or wep.WorldModel) + self:RecalculateModelOutlines() + end + self.OutlineGiveUp = 0 + end + + function ENT:Think() + if self.Flipped != self:GetFlipped() then + self.Flipped = self:GetFlipped() + self:RecalculateModelOutlines() + --print(self.Flipped) + end + if self.modelclass != self:GetWepClass() then + self.modelclass = self:GetWepClass() + self:Update() + --print(self.Flipped) + end + end + + local glow = Material( "sprites/light_ignorez" ) + local white = Color(0,200,255,50) + + function ENT:Draw() + --self:DrawModel() + local num = math.Clamp(GetConVar("nz_outlinedetail"):GetInt(), 0, 4) + if num < 1 or (self.OutlineGiveUp and self.OutlineGiveUp > 5) then + -- If we don't have a function or it errors, call default DrawModel + if !self.WorldModelFunc or !pcall(self.WorldModelFunc, self) then self:DrawModel() end + --self:DrawModel() + else + local pos = LocalPlayer():EyePos()+LocalPlayer():EyeAngles():Forward()*10 + local ang = LocalPlayer():EyeAngles() + ang = Angle(ang.p+90,ang.y,0) + if halo.RenderedEntity() != self then + render.ClearStencil() + render.SetStencilEnable(true) + render.SetStencilWriteMask(255) + render.SetStencilTestMask(255) + render.SetStencilReferenceValue(15) + render.SetStencilFailOperation(STENCILOPERATION_KEEP) + render.SetStencilZFailOperation(STENCILOPERATION_KEEP) + render.SetStencilPassOperation(STENCILOPERATION_REPLACE) + render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_ALWAYS) + render.SetBlend(0) + + for i = 1, num do + -- If it isn't valid (NULL ENTITY), attempt to recreate + if !IsValid(self["Chalk"..i]) then + self:RecalculateModelOutlines() + -- Log how many tries we did, we'll give up after 5 and just draw the model :( + self.OutlineGiveUp = self.OutlineGiveUp and self.OutlineGiveUp + 1 or 1 + break + end + self["Chalk"..i]:DrawModel() + end + + render.SetStencilPassOperation(STENCILOPERATION_ZERO) -- Make it deselect the center model + if !IsValid(self["ChalkCenter"]) then + self:RecalculateModelOutlines() + self.OutlineGiveUp = self.OutlineGiveUp and self.OutlineGiveUp + 1 or 1 + else + self.ChalkCenter:DrawModel() + end + + render.SetBlend(1) + render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_EQUAL) + cam.Start3D2D(pos,ang,1) + --surface.SetDrawColor(0,0,0) + surface.SetDrawColor(255,255,255) + surface.DrawRect(-ScrW(),-ScrH(),ScrW()*2,ScrH()*2) + --surface.SetMaterial(chalkmaterial) + --surface.DrawTexturedRect(-ScrW(),-ScrH(),ScrW()*2,ScrH()*2) + cam.End3D2D() + render.SetStencilEnable(false) + end + + local wsc = self:WorldSpaceCenter() + local wsp = self:GetPos() + + local spritepos = self:GetFlipped() and Vector(wsp.x, wsc.y, wsc.z) or Vector(wsc.x, wsp.y, wsc.z) + local spriteang = self:GetFlipped() and self:GetAngles() + Angle(180,10,-90) or self:GetAngles() + Angle(0,90,90) + --[[cam.Start3D() + render.SetMaterial( glow ) + render.DrawSprite( spritepos + (pos-spritepos):GetNormalized()*5, 200, 100, white) + cam.End3D()]] + + cam.Start3D2D(spritepos, spriteang, 1) + surface.SetMaterial(glow) + surface.SetDrawColor(white) + --surface.DrawTexturedRect(-50,-25,100,50) + surface.DrawTexturedRectUV(-50,-25,50,50,0,0,0.5,1) + cam.End3D2D() + + debugoverlay.Line(spritepos, spritepos + spriteang:Forward()*15, 1, Color(0,255,0)) + debugoverlay.Line(spritepos, spritepos + spriteang:Right()*5, 1, Color(0,255,0)) + + spriteang:RotateAroundAxis(spriteang:Right(),20) + + debugoverlay.Line(spritepos, spritepos + spriteang:Forward()*15, 1, Color(255,0,0)) + debugoverlay.Line(spritepos, spritepos + spriteang:Right()*5, 1, Color(255,0,0)) + + cam.Start3D2D(spritepos, spriteang, 1) + surface.SetMaterial(glow) + surface.SetDrawColor(white) + --surface.DrawTexturedRect(-50,-25,100,50) + surface.DrawTexturedRectUV(0,-25,50,50,0.5,0,1,1) + cam.End3D2D() + + if self:GetBought() then + if !self.WorldModelFunc or !pcall(self.WorldModelFunc, self) then self:DrawModel() end + end + end + end + +end diff --git a/gamemodes/nzombies/entities/entities/whoswho_downed_clone.lua b/gamemodes/nzombies/entities/entities/whoswho_downed_clone.lua new file mode 100644 index 00000000..68f7e0c2 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/whoswho_downed_clone.lua @@ -0,0 +1,180 @@ +AddCSLuaFile() + +ENT.Base = "base_nextbot" +ENT.PrintName = "Faked downed player" +ENT.Category = "Brainz" +ENT.Author = "Lolle & Zet0r" + +function ENT:Initialize() + --change those after creation + self:SetModel( "models/player/kleiner.mdl" ) + self.OwnerData = {} + if SERVER then self:GiveWeapon( "weapon_pistol" ) end +end + +function ENT:SetupDataTables() + self:NetworkVar("Entity", 0, "PerkOwner") +end + +function ENT:BodyUpdate() + if self:GetActivity() != ACT_HL2MP_SIT_PISTOL then self:StartActivity( ACT_HL2MP_SIT_PISTOL ) end +end + +function ENT:Use( act, call, type, value ) + --revive here? +end + +function ENT:RunBehaviour() + while (true) do + coroutine.wait(60) + end +end + +function ENT:GiveWeapon( wepclass ) + if !wepclass then return end + + if IsValid(self.Weapon) then + self.Weapon:Remove() + end + + self.Weapon = ents.Create( wepclass ) + if !IsValid(self.Weapon) then + return + end + self.Weapon:SetOwner(self) + self.Weapon:SetParent(self) + self.Weapon:SetPos( self:GetAttachment(self:LookupAttachment("anim_attachment_RH")).Pos ) + self.Weapon:Spawn() + self.Weapon:SetSolid(SOLID_NONE) + self.Weapon:AddEffects(EF_BONEMERGE) + self.Weapon:Fire( "SetParentAttachment", "anim_attachment_LH" ) + +end + + +local mat = Material("Models/effects/comball_tape") +function ENT:Draw() + + self:DrawModel() + render.MaterialOverride(mat) + self:DrawModel() + render.MaterialOverride(nil) + +end + +-- FAS2 weapons seem to want this function +function ENT:InVehicle() + return false +end + +function ENT:RevivePlayer() + local ply = self:GetPerkOwner() + print(self:GetPerkOwner()) + PrintTable(self.OwnerData) + + if (IsValid(ply) and ply:IsPlayer()) then + if ply:Alive() then + if !ply:GetNotDowned() then + ply:RevivePlayer() + end + else + ply:Spawn() + end + + ply:SetPos(self:GetPos()) + ply:SetEyeAngles(self:GetAngles()) + + -- Yeah no, Who's Who doesn't actually let you keep your clone's perks or weapons + ply:RemovePerks() + ply:StripWeapons() + + for k,v in pairs(self.OwnerData.weps) do + local wep = ply:Give(v.class) + if v.pap then + timer.Simple(0, function() + if IsValid(wep) then + wep:ApplyNZModifier("pap") + end + end) + end + end + for k,v in pairs(self.OwnerData.perks) do + if v != "whoswho" then + ply:GivePerk(v) + end + end + ply:GiveMaxAmmo() + end + + -- Everything bought as the clone will be refunded, even doors + ply:GivePoints(ply.WhosWhoMoney) + + local revivor = nzRevive.Players[id] and nzRevive.Players[id].RevivePlayer or nil + if IsValid(revivor) and revivor:IsPlayer() then + if self.DownPoints then + revivor:GivePoints(self.DownPoints) + end + revivor:StripWeapon("nz_revive_morphine") -- Remove the viewmodel again + end + + self:Remove() +end + +function ENT:StartRevive(revivor, nosync) + local id = self:EntIndex() + if !nzRevive.Players[id] then return end -- Not even downed + if nzRevive.Players[id].ReviveTime then return end -- Already being revived + + nzRevive.Players[id].ReviveTime = CurTime() + nzRevive.Players[id].RevivePlayer = revivor + revivor.Reviving = self + + revivor:Give("nz_revive_morphine") -- Give them the viewmodel + + if !nosync then hook.Call("PlayerBeingRevived", nzRevive, self, revivor) end +end + +function ENT:StopRevive(nosync) + local id = self:EntIndex() + if !nzRevive.Players[id] then return end -- Not even downed + + local revivor = nzRevive.Players[id].RevivePlayer + if IsValid(revivor) then + revivor:StripWeapon("nz_revive_morphine") -- Remove the revivors viewmodel + end + + nzRevive.Players[id].ReviveTime = nil + nzRevive.Players[id].RevivePlayer = nil + + if !nosync then hook.Call("PlayerNoLongerBeingRevived", nzRevive, self) end +end + +function ENT:KillDownedPlayer() + self:Remove() +end + +function ENT:OnRemove() + local ply = self:GetPerkOwner() + if (IsValid(ply) and ply:IsPlayer()) then + -- No more refunds for you once you become your clone mate! + ply.WhosWhoMoney = nil + end + + local revivor = nzRevive.Players[id] and nzRevive.Players[id].RevivePlayer or nil + if IsValid(revivor) then -- This shouldn't happen as players can't die if they are currently being revived + revivor:StripWeapon("nz_revive_morphine") -- Remove the revivors if someone was reviving viewmodel + end + + nzRevive.Players[self:EntIndex()] = nil + + if SERVER then + net.Start("nz_WhosWhoActive") + net.WriteBool(false) + net.Send(ply) + hook.Call("PlayerRevived", nzRevive, self) + end +end + +function ENT:UpdateTransmitState() + return TRANSMIT_ALWAYS +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/wunderfizz_machine/shared.lua b/gamemodes/nzombies/entities/entities/wunderfizz_machine/shared.lua new file mode 100644 index 00000000..c381e039 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/wunderfizz_machine/shared.lua @@ -0,0 +1,197 @@ +AddCSLuaFile() + +ENT.Type = "anim" + +ENT.PrintName = "wundefizz_machine" +ENT.Author = "Zet0r" +ENT.Contact = "youtube.com/Zet0r" +ENT.Purpose = "" +ENT.Instructions = "" + +function ENT:SetupDataTables() + self:NetworkVar("Int", 0, "Price") + self:NetworkVar("Bool", 0, "Active") + self:NetworkVar("Bool", 1, "BeingUsed") + self:NetworkVar("Entity", 0, "User") + + self:NetworkVar( "String", 0, "PerkID") + self:NetworkVar( "Bool", 2, "IsTeddy" ) +end + +function ENT:DecideOutcomePerk(ply, specific) + if specific then self:SetPerkID(specific) return end + + if self.TimesUsed > 2 and math.random(100) <= 55 and #ents.FindByClass("wundefizz_machine") > 1 then + return hook.Call("OnPlayerBuyWunderfizz", nil, ply, "teddy") or "teddy" + else + local blockedperks = { + ["wunderfizz"] = true, -- lol, this would happen + ["pap"] = true, + } + local available = nzMapping.Settings.wunderfizzperks or nzPerks:GetList() + local tbl = {} + for k,v in pairs(available) do + if !self:GetUser():HasPerk(k) and !blockedperks[k] then + table.insert(tbl, k) + end + end + if #tbl <= 0 then return hook.Call("OnPlayerBuyWunderfizz", nil, ply, "teddy") or "teddy" end -- Teddy bear for no more perks D: + local outcome = tbl[math.random(#tbl)] + return hook.Call("OnPlayerBuyWunderfizz", nil, ply, outcome) or outcome + end +end + +function ENT:Initialize() + if SERVER then + self:SetModel("models/alig96/perks/wunderfizz/nz_wunderfizz.mdl") + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_VPHYSICS ) + --self:DrawShadow( false ) + self:SetUseType( SIMPLE_USE ) + self:SetBeingUsed(false) + self:SetIsTeddy(false) + self:SetPrice(1500) + + self.NextLightning = CurTime() + math.random(10) + self:SetAutomaticFrameAdvance(true) + self:TurnOff(true) + self.TimesUsed = 0 + end +end + +function ENT:TurnOn() + local turnon, dur = self:LookupSequence("turn_on") + self:SetCycle(0) + self:ResetSequence(turnon) + self.GoIdle = CurTime() + dur -- Delay when to go idle (after turn on animation) +end + +function ENT:TurnOff(spawn) + self:SetActive(false) + local turnoff, dur = self:LookupSequence("turn_off") + self:ResetSequence(turnoff) + if spawn then self:SetCycle(1) else self:SetCycle(0) end + --self:SetCycle(0) + --self:SetPlaybackRate(10) + --print(turnoff) +end + +function ENT:IsOn() + return self:GetActive() +end + +function ENT:Think() + if SERVER then + if self.GoIdle and self.GoIdle < CurTime() then + local idle = self:LookupSequence("idle") + self:SetCycle(0) + self:ResetSequence(idle) + self:SetActive(true) -- Turn on here + self.GoIdle = nil + --print("idling") + end + if self:IsOn() and CurTime() > self.NextLightning then + local e = EffectData() + e:SetStart(self:GetPos() + Vector(0,0,3000)) + e:SetOrigin(self:GetPos() + Vector(0,0,100)) + e:SetMagnitude(0.5) + util.Effect("lightning_strike_wunderfizz", e) + self.NextLightning = CurTime() + math.random(30) + end + self:NextThink(CurTime()) + return true + end +end + +function ENT:Use(activator, caller) + if self:IsOn() and !self.GoIdle then -- Only after fully arriving + if !IsValid(self.Bottle) and !self:GetBeingUsed() then + local price = self:GetPrice() + -- Can only be bought if you have free perk slots + if #activator:GetPerks() < GetConVar("nz_difficulty_perks_max"):GetInt() then + -- If they have enough money + activator:Buy(price, self, function() + self:SetBeingUsed(true) + self:SetUser(activator) + + self.OutcomePerk = self:DecideOutcomePerk(activator) + self.Bottle = ents.Create("wunderfizz_windup") + self.Bottle:SetPos(self:GetPos() + Vector(0,0,45)) + self.Bottle:SetAngles(self:GetAngles() + Angle(0,-90,0)) + self.Bottle.WMachine = self + self.Bottle.Perk = self.OutcomePerk + self.Bottle:Spawn() + + timer.Simple(0, function() + if IsValid(self.Bottle) then + local e = EffectData() + e:SetEntity(self.Bottle) + e:SetMagnitude(1.1) + e:SetScale(5) + util.Effect("lightning_aura", e) + end + end) + + self.TimesUsed = self.TimesUsed + 1 + return true + end) + else + print(activator:Nick().." already has max perks") + end + elseif self:GetUser() == activator and !self.Bottle:GetWinding() and !self:GetIsTeddy() then + local perk = self:GetPerkID() + local wep = activator:Give("nz_perk_bottle") + wep:SetPerk(perk) + activator:GivePerk(perk) + self:SetBeingUsed(false) + self:SetPerkID("") + self:SetUser(nil) + self.Bottle:Remove() + end + end +end + +function ENT:OnRemove() + if IsValid(self.Bottle) then self.Bottle:Remove() end +end + +function ENT:MoveLocation() + self:TurnOff() + self:SetPerkID("") + self:SetUser(nil) + self:SetIsTeddy(false) + + local tbl = {} + for k,v in pairs(ents.FindByClass("wunderfizz_machine")) do + if !v:IsOn() and v != self then + table.insert(tbl, v) + end + end + local target = tbl[math.random(#tbl)] + if IsValid(target) then + target:TurnOn() + end +end + +local offlight = Material( "sprites/redglow1" ) +local offpos = Vector(10, 23.6, 61.4) +local red = Color(255,255,255) -- The sprite itself is red +local onlight = Material( "sprites/physg_glow1" ) +local onpos = Vector(10, 23.6, 58) +local green = Color(0,255,0) -- That one's white though +if CLIENT then + function ENT:Draw() + self:DrawModel() + if self:IsOn() then + cam.Start3D(EyePos(),EyeAngles()) + render.SetMaterial( onlight ) + render.DrawSprite( self:LocalToWorld(onpos), 10, 10, green) + cam.End3D() + else + cam.Start3D(EyePos(),EyeAngles()) + render.SetMaterial( offlight ) + render.DrawSprite( self:LocalToWorld(offpos), 10, 10, red) + cam.End3D() + end + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/entities/wunderfizz_windup/shared.lua b/gamemodes/nzombies/entities/entities/wunderfizz_windup/shared.lua new file mode 100644 index 00000000..74fb35d5 --- /dev/null +++ b/gamemodes/nzombies/entities/entities/wunderfizz_windup/shared.lua @@ -0,0 +1,119 @@ +AddCSLuaFile( ) + +ENT.Type = "anim" + +ENT.PrintName = "wunderfizz_windup" +ENT.Author = "Zet0r" +ENT.Contact = "youtube.com/Zet0r" +ENT.Purpose = "" +ENT.Instructions = "" + +--[[local perk_materials = { + ["jugg"] = "models/perk_bottle/c_perk_bottle_jugg", + ["speed"] = "models/perk_bottle/c_perk_bottle_speed", + ["dtap"] = "models/perk_bottle/c_perk_bottle_dtap", + ["revive"] = "models/perk_bottle/c_perk_bottle_revive", + ["dtap2"] = "models/perk_bottle/c_perk_bottle_dtap2", + ["staminup"] = "models/perk_bottle/c_perk_bottle_stamin", + ["phd"] = "models/perk_bottle/c_perk_bottle_phd", + ["deadshot"] = "models/perk_bottle/c_perk_bottle_deadshot", + ["mulekick"] = "models/perk_bottle/c_perk_bottle_mulekick", + ["cherry"] = "models/perk_bottle/c_perk_bottle_cherry", + ["tombstone"] = "models/perk_bottle/c_perk_bottle_tombstone", + ["whoswho"] = "models/perk_bottle/c_perk_bottle_whoswho", + ["vulture"] = "models/perk_bottle/c_perk_bottle_vulture", + ["teddy"] = "models/perk_bottle/c_perk_bottle_teddy", +}]] + +local teddymat = "models/perk_bottle/c_perk_bottle_teddy" + +function ENT:SetupDataTables() + self:NetworkVar( "Bool", 0, "Winding" ) +end + +function ENT:RandomizeSkin() + local skin + if nzMapping.Settings.wunderfizzperks then + skin = nzPerks:Get(table.Random(table.GetKeys(nzMapping.Settings.wunderfizzperks))).material + else + skin = nzPerks:Get(table.Random(table.GetKeys(nzPerks:GetList()))).material + end + + if skin then + self:SetMaterial(skin) + end +end + +function ENT:Initialize() + + self:SetMoveType(MOVETYPE_NONE) + + self:SetSolid( SOLID_OBB ) + self:DrawShadow( false ) + + self:SetModel("models/alig96/perks/perkacola/perkacola.mdl") + self:RandomizeSkin() + local machine = self.WMachine + + if SERVER then + self:SetWinding(true) + //Stop winding up + timer.Simple(5, function() + self:SetWinding(false) + + if self.Perk == "teddy" then + self:SetMaterial(teddymat) + machine:SetIsTeddy(true) + machine:GetUser():GivePoints(machine:GetPrice()) + timer.Simple(5, function() + if IsValid(self) and IsValid(machine) then + self:Remove() + machine:MoveLocation() + end + end) + else + self:SetMaterial(nzPerks:Get(self.Perk).material) + end + machine:SetPerkID(self.Perk) + end) + -- If we time out, remove the object + timer.Simple(25, function() if IsValid(self) then self:Remove() end end) + end +end + +function ENT:WindUp( ) + self:RandomizeSkin() +end + +function ENT:TeddyFlyUp( ) + +end + +function ENT:Think() + if SERVER then + if self:GetWinding() then + self:WindUp() + end + end +end + +function ENT:OnRemove() + if IsValid(self.WMachine) then + self.WMachine:SetBeingUsed(false) + self.WMachine.Bottle = nil + end +end + +if CLIENT then + function ENT:Draw() + self:DrawModel() + if self:GetWinding() then + if !self:GetRenderAngles() then self:SetRenderAngles(self:GetAngles() + Angle(20,0,0)) end + self:SetRenderAngles(self:GetRenderAngles()+(Angle(0,50,0)*FrameTime())) + elseif !self.Stopped then + self:SetRenderAngles(self:GetNetworkAngles()) + self.LightningAura = nil -- Kill the aura effect + self.Stopped = true + end + end +end diff --git a/gamemodes/nzombies/entities/entitiestemporary/info_player_undead/init.lua b/gamemodes/nzombies/entities/entitiestemporary/info_player_undead/init.lua new file mode 100644 index 00000000..6027084b --- /dev/null +++ b/gamemodes/nzombies/entities/entitiestemporary/info_player_undead/init.lua @@ -0,0 +1,27 @@ +ENT.Type = "point" + +function ENT:Initialize() +end + +function ENT:KeyValue(key, value) + key = string.lower(key) + if key == "disabled" then + self.Disabled = tonumber(value) == 1 + elseif key == "active" then + self.Disabled = tonumber(value) == 0 + end +end + +function ENT:AcceptInput(name, activator, caller, arg) + name = string.lower(name) + if name == "enable" then + self.Disabled = false + return true + elseif name == "disable" then + self.Disabled = true + return true + elseif name == "toggle" then + self.Disabled = not self.Disabled + return true + end +end diff --git a/gamemodes/nzombies/entities/entitiestemporary/info_player_zombie/init.lua b/gamemodes/nzombies/entities/entitiestemporary/info_player_zombie/init.lua new file mode 100644 index 00000000..88302e35 --- /dev/null +++ b/gamemodes/nzombies/entities/entitiestemporary/info_player_zombie/init.lua @@ -0,0 +1,30 @@ +ENT.Type = "point" + +function ENT:Initialize() +end + +function ENT:Think() +end + +function ENT:KeyValue(key, value) + key = string.lower(key) + if key == "disabled" then + self.Disabled = tonumber(value) == 1 + elseif key == "active" then + self.Disabled = tonumber(value) == 0 + end +end + +function ENT:AcceptInput(name, activator, caller, arg) + name = string.lower(name) + if name == "enable" then + self.Disabled = false + return true + elseif name == "disable" then + self.Disabled = true + return true + elseif name == "toggle" then + self.Disabled = not self.Disabled + return true + end +end diff --git a/gamemodes/nzombies/entities/weapons/nz_bowie_knife.lua b/gamemodes/nzombies/entities/weapons/nz_bowie_knife.lua new file mode 100644 index 00000000..4c03471c --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_bowie_knife.lua @@ -0,0 +1,164 @@ +if SERVER then + AddCSLuaFile("nz_bowie_knife.lua") + SWEP.Weight = 5 + SWEP.AutoSwitchTo = false + SWEP.AutoSwitchFrom = true +end + +if CLIENT then + + SWEP.PrintName = "Bowie Knife" + SWEP.Slot = 1 + SWEP.SlotPos = 1 + SWEP.DrawAmmo = false + SWEP.DrawCrosshair = true + + SWEP.Category = "nZombies" + +end + + +SWEP.Author = "Zet0r" +SWEP.Contact = "youtube.com/Zet0r" +SWEP.Purpose = "Stab Stab Stab!" +SWEP.Instructions = "Let the gamemode give you it" + +SWEP.Spawnable = false +SWEP.AdminSpawnable = false + +SWEP.HoldType = "knife" + +SWEP.ViewModel = "models/weapons/c_bowie_knife.mdl" +SWEP.WorldModel = "models/weapons/w_bowie_knife.mdl" +SWEP.UseHands = true +SWEP.vModel = true + +SWEP.Primary.ClipSize = -1 +SWEP.Primary.DefaultClip = -1 +SWEP.Primary.Automatic = false +SWEP.Primary.Ammo = "none" +SWEP.Primary.DamageType = DMG_CLUB +SWEP.Primary.Force = 0 + +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "none" + +SWEP.NextReload = 1 + +SWEP.Primary.Damage = 200 +SWEP.Range = 100 + + +function SWEP:Initialize() + + self:SetHoldType( self.HoldType ) + +end + +function SWEP:Deploy() + self:SendWeaponAnim(ACT_VM_DRAW) + self.HolsterTime = CurTime() + 2.5 + self:EmitSound("nz/bowie/draw/bowie_start.wav") + + timer.Simple(0.7, function() + if IsValid(self) then + self:EmitSound("nz/bowie/draw/bowie_turn.wav") + end + end) + timer.Simple(1.4, function() + if IsValid(self) then + self:EmitSound("nz/bowie/draw/bowie_toss.wav") + end + end) + + timer.Simple(1.9, function() + if IsValid(self) then + self:EmitSound("nz/bowie/draw/bowie_catch.wav") + end + end) +end + +function SWEP:PrimaryAttack() + -- Only the player fires this way so we can cast + + local ply = self.Owner; + + if ( !ply ) then + return + end + + local vecSrc = ply:GetShootPos() + local vecDirection = ply:GetAimVector() + + local trace = {} + trace.start = vecSrc + trace.endpos = vecSrc + ( vecDirection * self.Range) + trace.filter = ply + + local traceHit = util.TraceLine( trace ) + + if ( traceHit.Hit ) then + + if math.random(0,1) == 0 then + self:SendWeaponAnim( ACT_VM_HITCENTER ) + ply:SetAnimation( PLAYER_ATTACK1 ) + self.nzHolsterTime = CurTime() + 1 + self:EmitSound("nz/bowie/stab/bowie_stab_0"..math.random(0,2)..".wav") + else + self:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + ply:SetAnimation( PLAYER_ATTACK1 ) + self.nzHolsterTime = CurTime() + 0.5 + self:EmitSound("nz/bowie/swing/bowie_swing_0"..math.random(0,2)..".wav") + end + + local vecSrc = ply:GetShootPos() + + if ( SERVER ) then + ply:TraceHullAttack( vecSrc, traceHit.HitPos, Vector( -5, -5, -5 ), Vector( 5, 5, 36 ), self.Primary.Damage, self.Primary.DamageType, self.Primary.Force ) + end + + return + + end + + + self:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + ply:SetAnimation( PLAYER_ATTACK1 ) + self:EmitSound("nz/bowie/swing/bowie_swing_0"..math.random(0,2)..".wav") + + return +end + +function SWEP:DrawAnim() + +end + +function SWEP:PostDrawViewModel() + +end + +function SWEP:DrawWorldModel() + +end + +function SWEP:OnRemove() + +end + +function SWEP:Think() + +end + +function SWEP:GetViewModelPosition( pos, ang ) + + local newpos = LocalPlayer():EyePos() + local newang = LocalPlayer():EyeAngles() + local up = newang:Up() + + newpos = newpos + LocalPlayer():GetAimVector()*6 - up*65 + + return newpos, newang + +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/weapons/nz_death_machine.lua b/gamemodes/nzombies/entities/weapons/nz_death_machine.lua new file mode 100644 index 00000000..3d68dcf6 --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_death_machine.lua @@ -0,0 +1,123 @@ +if SERVER then + AddCSLuaFile("nz_death_machine.lua") + SWEP.Weight = 5 + SWEP.AutoSwitchTo = true + SWEP.AutoSwitchFrom = false +end + +if CLIENT then + + SWEP.PrintName = "Death Machine" + SWEP.Slot = 1 + SWEP.SlotPos = 1 + SWEP.DrawAmmo = false + SWEP.DrawCrosshair = true + + SWEP.Category = "nZombies" + +end + + +SWEP.Author = "Zet0r" +SWEP.Contact = "youtube.com/Zet0r" +SWEP.Purpose = "Bringing Death to Zombies since 1999" +SWEP.Instructions = "Find a powerup to get it" + +SWEP.Spawnable = false +SWEP.AdminSpawnable = false + +SWEP.HoldType = "shotgun" + +SWEP.ViewModel = "models/weapons/c_zombies_deathmachine.mdl" +SWEP.WorldModel = "models/weapons/w_zombies_deathmachine.mdl" +SWEP.UseHands = true +SWEP.vModel = true + +SWEP.Primary.ClipSize = -1 +SWEP.Primary.DefaultClip = -1 +SWEP.Primary.Automatic = true +SWEP.Primary.Ammo = "none" + +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "none" + +SWEP.NZPreventBox = true +SWEP.NZTotalBlacklist = true +SWEP.NZSpecialCategory = "display" -- This makes it count as special, as well as what category it replaces +-- (display is generic stuff that should only be carried temporarily and never holstered and kept) + +function SWEP:Initialize() + + self:SetHoldType( self.HoldType ) + +end + +function SWEP:Deploy() + self:SendWeaponAnim(ACT_VM_DRAW) + self.WepOwner = self.Owner +end + +function SWEP:Equip( owner ) + owner:SetActiveWeapon("nz_death_machine") +end + +local shootsound = Sound("nz/deathmachine/loop_l_.wav") +function SWEP:PrimaryAttack() + + self:SetNextPrimaryFire(CurTime() + 0.05) + self:EmitSound( shootsound ) + + local shootpos = self.Owner:GetShootPos() + local shootang = self.Owner:GetAimVector() + + local bullet = {} + bullet.Damage = 9000 + bullet.Force = 10 + bullet.Tracer = 1 + bullet.TracerName = "AirboatGunHeavyTracer" + bullet.Src = shootpos + bullet.Dir = shootang + Vector(0,0,0) + bullet.Spread = Vector(0.02, 0.02, 0) + + --local fx = EffectData() + --fx:SetEntity(self) + --fx:SetOrigin(shootpos) + --fx:SetNormal(shootang) + --fx:SetAttachment(self.MuzzleAttachment) + self.Owner:MuzzleFlash() + self.Owner:FireBullets( bullet ) + self:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + self.Owner:ViewPunch( Angle( math.Rand(-0.5,-0.3), math.Rand(-0.3,0.3), 0 ) ) + +end + +function SWEP:PostDrawViewModel() + +end + +function SWEP:NZSpecialHolster(wep) + if IsValid(self.Owner) then + self.Owner:RemovePowerUp("deathmachine") + end + return true +end + +function SWEP:OnRemove() + if SERVER then + if !IsValid(self.WepOwner:GetActiveWeapon()) or !self.WepOwner:GetActiveWeapon():IsSpecial() then + self.WepOwner:SetUsingSpecialWeapon(false) + end + self.WepOwner:SetActiveWeapon(nil) + self.WepOwner:EquipPreviousWeapon() + end +end + +function SWEP:GetViewModelPosition( pos, ang ) + + + return pos, ang + +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/weapons/nz_grenade.lua b/gamemodes/nzombies/entities/weapons/nz_grenade.lua new file mode 100644 index 00000000..0769b8b6 --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_grenade.lua @@ -0,0 +1,100 @@ +if SERVER then + AddCSLuaFile("nz_grenade.lua") + SWEP.Weight = 1 + SWEP.AutoSwitchTo = false + SWEP.AutoSwitchFrom = true +end + +if CLIENT then + + SWEP.PrintName = "M67 Grenade" + SWEP.Slot = 1 + SWEP.SlotPos = 1 + SWEP.DrawAmmo = false + SWEP.DrawCrosshair = true + +end + + +SWEP.Author = "Zet0r" +SWEP.Contact = "youtube.com/Zet0r" +SWEP.Purpose = "Throws a grenade if you have any" +SWEP.Instructions = "Let the gamemode give you it" + +SWEP.Spawnable = false +SWEP.AdminSpawnable = false + +SWEP.HoldType = "grenade" + +SWEP.ViewModel = "models/weapons/c_grenade.mdl" +SWEP.WorldModel = "models/weapons/w_grenade.mdl" +SWEP.UseHands = true +SWEP.vModel = true + +SWEP.Primary.ClipSize = -1 +SWEP.Primary.DefaultClip = -1 +SWEP.Primary.Automatic = false +SWEP.Primary.Ammo = "none" + +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "none" + +SWEP.NextReload = 1 + +function SWEP:Initialize() + + self:SetHoldType( self.HoldType ) + +end + +function SWEP:Deploy() + self:SendWeaponAnim(ACT_VM_DRAW) + --if !self.Owner:GetUsingSpecialWeapon() then + --self.Owner:EquipPreviousWeapon() + --end +end + +function SWEP:PrimaryAttack() + self:ThrowGrenade(6000) +end + +function SWEP:ThrowGrenade(force) + self.Owner:SetAnimation(PLAYER_ATTACK1) + self:SendWeaponAnim(ACT_VM_THROW) + + if SERVER then + local nade = ents.Create("nz_fraggrenade") + nade:SetPos(self.Owner:EyePos() + (self.Owner:GetAimVector() * 20)) + nade:SetAngles( Angle(30,0,0) ) + nade:Spawn() + nade:Activate() + nade:SetOwner(self.Owner) + if self.Owner:HasPerk("widowswine") then + nade.WidowsWine = true + end + + local nadePhys = nade:GetPhysicsObject() + if !IsValid(nadePhys) then return end + nadePhys:ApplyForceCenter(self.Owner:GetAimVector():GetNormalized() * force + self.Owner:GetVelocity()) + nadePhys:AddAngleVelocity(Vector(1000,0,0)) + nade:SetExplosionTimer(3) + end +end + +function SWEP:PostDrawViewModel() + +end + +function SWEP:DrawWorldModel() +end + +function SWEP:OnRemove() + +end + +function SWEP:Holster( wep ) + --if not IsFirstTimePredicted() then return end + return true +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/weapons/nz_monkey_bomb.lua b/gamemodes/nzombies/entities/weapons/nz_monkey_bomb.lua new file mode 100644 index 00000000..dda48afa --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_monkey_bomb.lua @@ -0,0 +1,140 @@ +if SERVER then + AddCSLuaFile("nz_monkey_bomb.lua") + SWEP.Weight = 5 + SWEP.AutoSwitchTo = false + SWEP.AutoSwitchFrom = true +end + +if CLIENT then + + SWEP.PrintName = "Monkey Bomb" + SWEP.Slot = 1 + SWEP.SlotPos = 1 + SWEP.DrawAmmo = false + SWEP.DrawCrosshair = true + + SWEP.Category = "nZombies" + +end + + +SWEP.Author = "Zet0r" +SWEP.Contact = "youtube.com/Zet0r" +SWEP.Purpose = "Throws a monkey bomb if you have any" +SWEP.Instructions = "Let the gamemode give you it" + +SWEP.Spawnable = false +SWEP.AdminSpawnable = false + +SWEP.HoldType = "slam" + +SWEP.ViewModel = "models/weapons/c_monkey_bomb.mdl" +SWEP.WorldModel = "models/nzprops/monkey_bomb.mdl" +SWEP.UseHands = true +SWEP.vModel = true + +SWEP.Primary.ClipSize = -1 +SWEP.Primary.DefaultClip = -1 +SWEP.Primary.Automatic = false +SWEP.Primary.Ammo = "none" + +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "none" + +SWEP.NextReload = 1 + +SWEP.PrimeSounds = { + "nz/monkey/voice_prime/raise_vox_00.wav", + "nz/monkey/voice_prime/raise_vox_01.wav", + "nz/monkey/voice_prime/raise_vox_02.wav", + "nz/monkey/voice_prime/raise_vox_03.wav", + "nz/monkey/voice_prime/raise_vox_04.wav", + "nz/monkey/voice_prime/raise_vox_05.wav", + "nz/monkey/voice_prime/raise_vox_06.wav", + "nz/monkey/voice_prime/raise_vox_07.wav", + "nz/monkey/voice_prime/raise_vox_08.wav", + "nz/monkey/voice_prime/raise_vox_09.wav", + "nz/monkey/voice_prime/raise_vox_10.wav", + "nz/monkey/voice_prime/raise_vox_11.wav", +} + +function SWEP:Initialize() + + self:SetHoldType( "slam" ) + +end + +function SWEP:Deploy() + self:SendWeaponAnim(ACT_VM_DRAW) + self:SetHoldType( "slam" ) + timer.Simple(2, function() if IsValid(self) then self:SetHoldType("grenade") end end) + if CLIENT then + local sound = self.PrimeSounds[math.random(1,#self.PrimeSounds)] + surface.PlaySound(sound) + timer.Simple(1.2, function() + if IsValid(self) then + surface.PlaySound("nz/monkey/hat1.wav") + local i = 0 + timer.Create("MonkeyCymbalViewmodel", 0.23, 7, function() + surface.PlaySound("nz/monkey/cymbals/monk_cymb_0"..math.Round(i/2)..".wav") + i = i < 8 and i + 1 or 8 + end) + end + end) + + else + self:CallOnClient("Deploy") + end +end + +function SWEP:PrimaryAttack() + if SERVER then + self:ThrowBomb(500) + end +end + +function SWEP:ThrowBomb(force) + self.Owner:SetAnimation(PLAYER_ATTACK1) + self:SendWeaponAnim(ACT_VM_THROW) + + local nade = ents.Create("nz_monkeybomb") + local pos = self.Owner:EyePos() + (self.Owner:GetAimVector() * 20) + local ang = Angle(0,(self.Owner:GetPos() - pos):Angle()[2]-90,0) + nade:SetPos(pos) + nade:SetAngles(ang) + nade:Spawn() + nade:Activate() + nade:SetOwner(self.Owner) + + local nadePhys = nade:GetPhysicsObject() + if !IsValid(nadePhys) then return end + nadePhys:ApplyForceCenter(self.Owner:GetAimVector():GetNormalized() * force + self.Owner:GetVelocity()) + nade:EmitSound("nz/monkey/voice_throw/throw_0"..math.random(0,3)..".wav") + +end + +function SWEP:PostDrawViewModel() + +end + +function SWEP:DrawWorldModel() + +end + +function SWEP:OnRemove() + +end + +function SWEP:GetViewModelPosition( pos, ang ) + + local newpos = LocalPlayer():EyePos() + local newang = LocalPlayer():EyeAngles() + local up = newang:Up() + + newpos = newpos + LocalPlayer():GetAimVector()*6 - up*65 + + return newpos, newang + +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/weapons/nz_multi_tool.lua b/gamemodes/nzombies/entities/weapons/nz_multi_tool.lua new file mode 100644 index 00000000..abd1c2e6 --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_multi_tool.lua @@ -0,0 +1,296 @@ +SWEP.PrintName = "Create Mode Toolgun" +SWEP.Author = "Zet0r" +SWEP.Contact = "" +SWEP.Purpose = "" +SWEP.Instructions = "" + +SWEP.ViewModel = "models/weapons/c_toolgun.mdl" +SWEP.WorldModel = "models/weapons/w_toolgun.mdl" +SWEP.AnimPrefix = "python" + +SWEP.Slot = 5 +SWEP.SlotPos = 1 + +SWEP.UseHands = true + +util.PrecacheModel( SWEP.ViewModel ) +util.PrecacheModel( SWEP.WorldModel ) + +SWEP.ShootSound = Sound( "Airboat.FireGunRevDown" ) + +SWEP.Tool = {} + +SWEP.Primary = +{ + ClipSize = -1, + DefaultClip = -1, + Automatic = false, + Ammo = "none" +} + +SWEP.Secondary = +{ + ClipSize = -1, + DefaultClip = -1, + Automatic = false, + Ammo = "none" +} + +SWEP.CanHolster = true +SWEP.CanDeploy = true + +SWEP.NZPreventBox = true + +--[[--------------------------------------------------------- + Initialize +-----------------------------------------------------------]] +function SWEP:Initialize() + self.Primary = + { + ClipSize = -1, + DefaultClip = -1, + Automatic = false, + Ammo = "none" + } + + self.Secondary = + { + ClipSize = -1, + DefaultClip = -1, + Automatic = false, + Ammo = "none" + } + + self.ToolMode = "default" +end + +--[[--------------------------------------------------------- + Precache Stuff +-----------------------------------------------------------]] +function SWEP:Precache() + + util.PrecacheSound( self.ShootSound ) + +end + +--[[--------------------------------------------------------- + The shoot effect +-----------------------------------------------------------]] +function SWEP:DoShootEffect( hitpos, hitnormal, entity, physbone, bFirstTimePredicted ) + + self.Weapon:EmitSound( self.ShootSound ) + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + + + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + if ( !bFirstTimePredicted ) then return end + + local effectdata = EffectData() + effectdata:SetOrigin( hitpos ) + effectdata:SetNormal( hitnormal ) + effectdata:SetEntity( entity ) + effectdata:SetAttachment( physbone ) + util.Effect( "selection_indicator", effectdata ) + + local effectdata = EffectData() + effectdata:SetOrigin( hitpos ) + effectdata:SetStart( self.Owner:GetShootPos() ) + effectdata:SetAttachment( 1 ) + effectdata:SetEntity( self.Weapon ) + util.Effect( "ToolTracer", effectdata ) + +end + +--[[--------------------------------------------------------- + Switch to another toolmode +-----------------------------------------------------------]] +function SWEP:SwitchTool(id) + + -- Only allow if the condition has been met + if nzTools.ToolData[id].condition(self, self.Owner) then + self.ToolMode = id + + -- Update the server with the newly equipped tool, switches data server-side + nzTools:SendData( nzTools.SavedData[id], id ) + end + +end + + +--[[--------------------------------------------------------- + Trace a line then send the result to a mode function +-----------------------------------------------------------]] +function SWEP:PrimaryAttack() + + local tr = util.GetPlayerTrace( self.Owner ) + tr.mask = bit.bor( CONTENTS_SOLID, CONTENTS_MOVEABLE, CONTENTS_MONSTER, CONTENTS_WINDOW, CONTENTS_DEBRIS, CONTENTS_GRATE, CONTENTS_AUX ) + local trace = util.TraceLine( tr ) + if (!trace.Hit) then return end + + self:DoShootEffect( trace.HitPos, trace.HitNormal, trace.Entity, trace.PhysicsBone, IsFirstTimePredicted() ) + + if CLIENT and !game.SinglePlayer() and !IsFirstTimePredicted() then return end + if nzTools.ToolData[self.ToolMode] and nzTools.ToolData[self.ToolMode].PrimaryAttack then + nzTools.ToolData[self.ToolMode].PrimaryAttack(self, self.Owner, trace, self.Owner.NZToolData) + end + if ( game.SinglePlayer() ) then self:CallOnClient( "PrimaryAttack" ) end +end + + +--[[--------------------------------------------------------- + SecondaryAttack - Reset everything to how it was +-----------------------------------------------------------]] +function SWEP:SecondaryAttack() + + local tr = util.GetPlayerTrace( self.Owner ) + tr.mask = bit.bor( CONTENTS_SOLID, CONTENTS_MOVEABLE, CONTENTS_MONSTER, CONTENTS_WINDOW, CONTENTS_DEBRIS, CONTENTS_GRATE, CONTENTS_AUX ) + local trace = util.TraceLine( tr ) + if (!trace.Hit) then return end + + self:DoShootEffect( trace.HitPos, trace.HitNormal, trace.Entity, trace.PhysicsBone, IsFirstTimePredicted() ) + + if CLIENT and !game.SinglePlayer() and !IsFirstTimePredicted() then return end + if nzTools.ToolData[self.ToolMode] and nzTools.ToolData[self.ToolMode].SecondaryAttack then + nzTools.ToolData[self.ToolMode].SecondaryAttack(self, self.Owner, trace, self.Owner.NZToolData) + end + if ( game.SinglePlayer() ) then self:CallOnClient( "SecondaryAttack" ) end +end + +local reload_cd = CurTime() + +function SWEP:Reload() + if reload_cd < CurTime() then + local tr = util.GetPlayerTrace( self.Owner ) + tr.mask = bit.bor( CONTENTS_SOLID, CONTENTS_MOVEABLE, CONTENTS_MONSTER, CONTENTS_WINDOW, CONTENTS_DEBRIS, CONTENTS_GRATE, CONTENTS_AUX ) + local trace = util.TraceLine( tr ) + if (!trace.Hit) then return end + + self:DoShootEffect( trace.HitPos, trace.HitNormal, trace.Entity, trace.PhysicsBone, IsFirstTimePredicted() ) + + reload_cd = CurTime() + 0.3 + + if CLIENT and !game.SinglePlayer() and !IsFirstTimePredicted() then return end + if nzTools.ToolData[self.ToolMode] and nzTools.ToolData[self.ToolMode].Reload then + nzTools.ToolData[self.ToolMode].Reload(self, self.Owner, trace, self.Owner.NZToolData) + end + + end + if ( game.SinglePlayer() ) then self:CallOnClient( "Reload" ) end +end + +function SWEP:Deploy() + if CLIENT and !game.SinglePlayer() and !IsFirstTimePredicted() then return end + if nzTools.ToolData[self.ToolMode] and nzTools.ToolData[self.ToolMode].OnEquip then + nzTools.ToolData[self.ToolMode].OnEquip(self, self.Owner, self.Owner.NZToolData) + end + if ( game.SinglePlayer() ) then self:CallOnClient( "Deploy" ) end +end + +function SWEP:Holster(wep) + if nzTools.ToolData[self.ToolMode] and nzTools.ToolData[self.ToolMode].OnHolster then + nzTools.ToolData[self.ToolMode].OnHolster(self, self.Owner, self.Owner.NZToolData) + end + if ( game.SinglePlayer() ) then self:CallOnClient( "Holster" ) end + return true +end + +function SWEP:Think() + if nzTools.ToolData[self.ToolMode] and nzTools.ToolData[self.ToolMode].Think then + nzTools.ToolData[self.ToolMode].Think() + end +end + +--[[ +RENDER The scroll text Liek in sandbox +--]] + +if CLIENT then + local matScreen = Material( "models/weapons/v_toolgun/screen" ) + local txBackground = surface.GetTextureID( "models/weapons/v_toolgun/screen_bg" ) + + -- GetRenderTarget returns the texture if it exists, or creates it if it doesn't + local RTTexture = GetRenderTarget( "GModToolgunScreen", 256, 256 ) + + surface.CreateFont( "GModToolScreen", { + font = "Helvetica", + size = 60, + weight = 900 + } ) + + + local function DrawScrollingText( text, y, texwide ) + + local w, h = surface.GetTextSize( text ) + w = w + 64 + + y = y - h / 2 -- Center text to y position + + local x = RealTime() * 250 % w * -1 + + while ( x < texwide ) do + + surface.SetTextColor( 0, 0, 0, 255 ) + surface.SetTextPos( x + 3, y + 3 ) + surface.DrawText( text ) + + surface.SetTextColor( 255, 255, 255, 255 ) + surface.SetTextPos( x, y ) + surface.DrawText( text ) + + x = x + w + + end + + end + + --[[--------------------------------------------------------- + We use this opportunity to draw to the toolmode + screen's rendertarget texture. + -----------------------------------------------------------]] + function SWEP:RenderScreen() + + local TEX_SIZE = 256 + local mode = GetConVarString( "gmod_toolmode" ) + local oldW = ScrW() + local oldH = ScrH() + + -- Set the material of the screen to our render target + matScreen:SetTexture( "$basetexture", RTTexture ) + + local OldRT = render.GetRenderTarget() + local text = "Toolgun" + if nzTools.ToolData[self.ToolMode] then + text = nzTools.ToolData[self.ToolMode].displayname + if nzTools.SavedData[self.ToolMode] then + for k,v in pairs(nzTools.SavedData[self.ToolMode]) do + text = text .." - "..k..": ".. tostring(v) + end + text = text .. " - " + end + end + + -- Set up our view for drawing to the texture + render.SetRenderTarget( RTTexture ) + render.SetViewPort( 0, 0, TEX_SIZE, TEX_SIZE ) + cam.Start2D() + + -- Background + surface.SetDrawColor( 255, 255, 255, 255 ) + surface.SetTexture( txBackground ) + surface.DrawTexturedRect( 0, 0, TEX_SIZE, TEX_SIZE ) + + surface.SetFont( "GModToolScreen" ) + DrawScrollingText( text, 104, TEX_SIZE ) + + cam.End2D() + render.SetRenderTarget( OldRT ) + render.SetViewPort( 0, 0, oldW, oldH ) + end + + function SWEP:DrawHUD() + if nzTools.ToolData[self.ToolMode] and nzTools.ToolData[self.ToolMode].drawhud then + nzTools.ToolData[self.ToolMode].drawhud() + end + end +end diff --git a/gamemodes/nzombies/entities/weapons/nz_one_inch_punch.lua b/gamemodes/nzombies/entities/weapons/nz_one_inch_punch.lua new file mode 100644 index 00000000..96e3cd53 --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_one_inch_punch.lua @@ -0,0 +1,187 @@ +SWEP.Base = "weapon_fists" + +if SERVER then + AddCSLuaFile("nz_one_inch_punch.lua") + SWEP.Weight = 5 + SWEP.AutoSwitchTo = false + SWEP.AutoSwitchFrom = true +end + +if CLIENT then + + SWEP.PrintName = "One Inch Punch" + SWEP.Slot = 1 + SWEP.SlotPos = 1 + SWEP.DrawAmmo = false + SWEP.DrawCrosshair = true + + SWEP.Category = "nZombies" + +end + + +SWEP.Author = "Zet0r" +SWEP.Contact = "youtube.com/Zet0r" +SWEP.Purpose = "FORCE SLAM!" +SWEP.Instructions = "Let the gamemode give you it" + +SWEP.Spawnable = false +SWEP.AdminSpawnable = false +SWEP.WorldModel = Model( "models/effects/combineball.mdl" ) + +SWEP.NZPreventBox = true + +function SWEP:PostDrawViewModel() + +end + +local SwingSound = Sound( "WeaponFrag.Throw" ) +local HitSound = Sound( "Flesh.ImpactHard" ) + +function SWEP:PrimaryAttack( right ) + + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + local anim = "fists_left" + local bone = 8 + if ( self:GetCombo() >= 1 ) then anim = "fists_right" bone = 27 end + if ( self:GetCombo() >= 2 ) then + anim = "fists_uppercut" + bone = 27 + end + + local vm = self.Owner:GetViewModel() + vm:SendViewModelMatchingSequence( vm:LookupSequence( anim ) ) + + self:EmitSound( SwingSound ) + + self:UpdateNextIdle() + self:SetNextMeleeAttack( CurTime() + 0.2 ) + + self:SetNextPrimaryFire( CurTime() + 0.9 ) + self:SetNextSecondaryFire( CurTime() + 0.9 ) + + if CLIENT then + local e = EffectData() + e:SetMagnitude(bone) + util.Effect("one_inch_punch_blow",e) + end + +end + +function SWEP:SecondaryAttack() + + self:PrimaryAttack( true ) + +end + +function SWEP:DealDamage() + + local anim = self:GetSequenceName(self.Owner:GetViewModel():GetSequence()) + + self.Owner:LagCompensation( true ) + + local tr = util.TraceLine( { + start = self.Owner:GetShootPos(), + endpos = self.Owner:GetShootPos() + self.Owner:GetAimVector() * self.HitDistance, + filter = self.Owner, + mask = MASK_SHOT_HULL + } ) + + if ( !IsValid( tr.Entity ) ) then + tr = util.TraceHull( { + start = self.Owner:GetShootPos(), + endpos = self.Owner:GetShootPos() + self.Owner:GetAimVector() * self.HitDistance, + filter = self.Owner, + mins = Vector( -10, -10, -8 ), + maxs = Vector( 10, 10, 8 ), + mask = MASK_SHOT_HULL + } ) + end + + -- We need the second part for single player because SWEP:Think is ran shared in SP + if ( tr.Hit && !( game.SinglePlayer() && CLIENT ) ) then + self:EmitSound( HitSound ) + end + + local hit = false + + if ( SERVER && IsValid( tr.Entity ) && ( tr.Entity:IsNPC() || tr.Entity:IsPlayer() || tr.Entity:Health() > 0 ) ) then + local dmginfo = DamageInfo() + + local attacker = self.Owner + if ( !IsValid( attacker ) ) then attacker = self end + dmginfo:SetAttacker( attacker ) + + dmginfo:SetInflictor( self ) + dmginfo:SetDamage( math.random( 419, 450 ) ) + + if ( anim == "fists_left" ) then + dmginfo:SetDamageForce( self.Owner:GetRight() * 4912 + self.Owner:GetForward() * 9998 + self.Owner:GetUp() * 5000 ) -- Yes we need those specific numbers + elseif ( anim == "fists_right" ) then + dmginfo:SetDamageForce( self.Owner:GetRight() * -4912 + self.Owner:GetForward() * 9989 + self.Owner:GetUp() * 5000 ) + elseif ( anim == "fists_uppercut" ) then + dmginfo:SetDamageForce( self.Owner:GetUp() * 15158 + self.Owner:GetForward() * 10012 ) + end + + tr.Entity:TakeDamageInfo( dmginfo ) + hit = true + else + if ( SERVER ) then + self:SetCombo( 0 ) + end + end + + if ( SERVER && IsValid( tr.Entity ) ) then + local phys = tr.Entity:GetPhysicsObject() + if ( IsValid( phys ) ) then + phys:ApplyForceOffset( self.Owner:GetAimVector() * 80 * phys:GetMass(), tr.HitPos ) + end + end + + if ( SERVER ) then + if ( hit && anim != "fists_uppercut" ) then + self:SetCombo( self:GetCombo() + 1 ) + else + self:SetCombo( 0 ) + end + end + + self.Owner:LagCompensation( false ) + +end + +function SWEP:Think() + + local vm = self.Owner:GetViewModel() + local curtime = CurTime() + local idletime = self:GetNextIdle() + + if ( idletime > 0 && CurTime() > idletime ) then + + vm:SendViewModelMatchingSequence( vm:LookupSequence( "fists_idle_0" .. math.random( 1, 2 ) ) ) + + self:UpdateNextIdle() + + end + + local meleetime = self:GetNextMeleeAttack() + + if ( meleetime > 0 && CurTime() > meleetime ) then + + self:DealDamage() + + self:SetNextMeleeAttack( 0 ) + + end + +end + +function SWEP:Deploy() + + local vm = self.Owner:GetViewModel() + vm:SendViewModelMatchingSequence( vm:LookupSequence( "fists_draw" ) ) + + self:UpdateNextIdle() + +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/weapons/nz_packapunch_arms.lua b/gamemodes/nzombies/entities/weapons/nz_packapunch_arms.lua new file mode 100644 index 00000000..f0db8156 --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_packapunch_arms.lua @@ -0,0 +1,108 @@ +if SERVER then + AddCSLuaFile("nz_packapunch_arms.lua") + SWEP.Weight = 5 + SWEP.AutoSwitchTo = false + SWEP.AutoSwitchFrom = true +end + +if CLIENT then + + SWEP.PrintName = "Hands" + SWEP.Slot = 1 + SWEP.SlotPos = 1 + SWEP.DrawAmmo = false + SWEP.DrawCrosshair = true + + SWEP.Category = "nZombies" + +end + + +SWEP.Author = "Zet0r" +SWEP.Contact = "youtube.com/Zet0r" +SWEP.Purpose = "Fancy Viewmodel Animations" +SWEP.Instructions = "Let the gamemode give you it" + +SWEP.Spawnable = false +SWEP.AdminSpawnable = false + +SWEP.HoldType = "slam" + +SWEP.ViewModel = "models/weapons/c_packapunch_arms.mdl" +SWEP.WorldModel = "" +SWEP.UseHands = true +SWEP.vModel = true + +SWEP.Primary.ClipSize = -1 +SWEP.Primary.DefaultClip = -1 +SWEP.Primary.Automatic = false +SWEP.Primary.Ammo = "none" + +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "none" + +SWEP.NZPreventBox = true +SWEP.NZTotalBlacklist = true + +function SWEP:Initialize() + + self:SetHoldType( "slam" ) + +end + +function SWEP:Deploy() + self:SendWeaponAnim(ACT_VM_DRAW) + + timer.Simple(0.5,function() + if IsValid(self) and IsValid(self.Owner) then + if self.Owner:Alive() then + self:EmitSound("nz/perks/knuckle_00.wav") + end + end + end) + + timer.Simple(1.3,function() + if IsValid(self) and IsValid(self.Owner) then + if self.Owner:Alive() then + self:EmitSound("nz/perks/knuckle_01.wav") + end + end + end) +end + +function SWEP:Equip( owner ) + + --timer.Simple(3.2,function() self:Remove() end) + --owner:SetActiveWeapon("nz_packapunch_arms") + +end + +function SWEP:PrimaryAttack() + +end + +function SWEP:PostDrawViewModel() + +end + +function SWEP:DrawWorldModel() + +end + +function SWEP:OnRemove() + +end + +function SWEP:GetViewModelPosition( pos, ang ) + + local newpos = LocalPlayer():EyePos() + local newang = LocalPlayer():EyeAngles() + local up = newang:Up() + + newpos = newpos + LocalPlayer():GetAimVector()*6 - up*63 + + return newpos, newang + +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/weapons/nz_perk_bottle/shared.lua b/gamemodes/nzombies/entities/weapons/nz_perk_bottle/shared.lua new file mode 100644 index 00000000..9959830e --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_perk_bottle/shared.lua @@ -0,0 +1,182 @@ + +AddCSLuaFile( "shared.lua" ) + +SWEP.Author = "Zet0r" +SWEP.Instructions = "Fancy Viewmodel Animations" +SWEP.Spawnable = false +SWEP.AdminSpawnable = false + +SWEP.ViewModel = "models/weapons/c_perk_bottle.mdl" +SWEP.WorldModel = "" + +SWEP.UseHands = true + +SWEP.Primary.ClipSize = -1 +SWEP.Primary.DefaultClip = -1 +SWEP.Primary.Delay = 1 +SWEP.Primary.Ammo = -1 +SWEP.ViewModelFOV = 75 +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Ammo = -1 + +SWEP.Weight = 5 +SWEP.AutoSwitchTo = true +SWEP.AutoSwitchFrom = false + +SWEP.PrintName = "Perk Bottle" +SWEP.Slot = 3 +SWEP.SlotPos = 1 +SWEP.DrawAmmo = false +SWEP.DrawCrosshair = false + +SWEP.SwayScale = 0 +SWEP.BobScale = 0 + +SWEP.NZPreventBox = true -- Prevents from being in the box by default + +local oldmat +--[[local perk_materials = { + ["jugg"] = "models/perk_bottle/c_perk_bottle_jugg", + ["speed"] = "models/perk_bottle/c_perk_bottle_speed", + ["dtap"] = "models/perk_bottle/c_perk_bottle_dtap", + ["revive"] = "models/perk_bottle/c_perk_bottle_revive", + ["dtap2"] = "models/perk_bottle/c_perk_bottle_dtap2", + ["staminup"] = "models/perk_bottle/c_perk_bottle_stamin", + ["phd"] = "models/perk_bottle/c_perk_bottle_phd", + ["deadshot"] = "models/perk_bottle/c_perk_bottle_deadshot", + ["mulekick"] = "models/perk_bottle/c_perk_bottle_mulekick", + ["cherry"] = "models/perk_bottle/c_perk_bottle_cherry", + ["tombstone"] = "models/perk_bottle/c_perk_bottle_tombstone", + ["whoswho"] = "models/perk_bottle/c_perk_bottle_whoswho", + ["vulture"] = "models/perk_bottle/c_perk_bottle_vulture", +}]] + +if SERVER then + util.AddNetworkString("perk_blur_screen") +end + +function SWEP:SetupDataTables() + + self:NetworkVar( "String", 0, "Perk" ) + +end + +function SWEP:Initialize() + if CLIENT then + if self.Owner == LocalPlayer() then + local vm = LocalPlayer():GetViewModel() + print(self:GetPerk()) + local mat = nzPerks:Get(self:GetPerk()).material --perk_materials[self:GetPerk()] + oldmat = vm:GetMaterial() or "" + vm:SetMaterial(mat) + end + end +end + +function SWEP:Equip( owner ) + + timer.Simple(3.2,function() + owner:SetUsingSpecialWeapon(false) + owner:EquipPreviousWeapon() + end) + owner:SetActiveWeapon("nz_perk_bottle") + +end + +function SWEP:Deploy() + + timer.Simple(0.5,function() + if IsValid(self) and IsValid(self.Owner) then + if self.Owner:Alive() then + self:EmitSound("nz/perks/open.wav") + self.Owner:ViewPunch( Angle( -1, -1, 0 ) ) + end + end + end) + + timer.Simple(1.3,function() + if IsValid(self) and IsValid(self.Owner) then + if self.Owner:Alive() then + self:EmitSound("nz/perks/drink.wav") + self.Owner:ViewPunch( Angle( -3, 0, 0 ) ) + end + end + end) + + timer.Simple(2.3,function() + if IsValid(self) and IsValid(self.Owner) then + if self.Owner:Alive() then + self:EmitSound("nz/perks/smash.wav") + net.Start("perk_blur_screen") + net.Send(self.Owner) + end + end + end) + + timer.Simple(3,function() + if IsValid(self) and IsValid(self.Owner) then + if self.Owner:Alive() then + self:EmitSound("nz/perks/burp.wav") + end + end + end) + + +end + +function PerkBlurScreen() + local mat = Material( "pp/blurscreen" ) + local function blurhook() + DrawMotionBlur(0.4, 0.8, 0.01) + end + hook.Add( "RenderScreenspaceEffects", "PaintPerkBlur", blurhook ) + timer.Simple(0.7,function() hook.Remove( "RenderScreenspaceEffects", "PaintPerkBlur" ) end) +end +net.Receive("perk_blur_screen", PerkBlurScreen) + +function SWEP:Holster() + return false +end + +function SWEP:PrimaryAttack() +end + +function SWEP:OnRemove() + + if CLIENT then + local ply = LocalPlayer() + if IsValid(ply) and self.Owner == ply then + local vm = ply:GetViewModel() + vm:SetMaterial(oldmat) + end + end + + hook.Remove( "RenderScreenspaceEffects", "PaintPerkBlur" ) + +end + +function SWEP:GetViewModelPosition( pos, ang ) + + local ply = LocalPlayer() + local newpos = ply:EyePos() + local newang = ply:EyeAngles() + local up = newang:Up() + + newpos = newpos + ply:GetAimVector()*3 - up*65 + + return newpos, newang + +end + +function SWEP:SecondaryAttack() +end + +function SWEP:ShouldDropOnDie() + return false +end + +-- So it counts as special weapon in the gamemode +function SWEP:IsSpecial() + return true +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/ai_translations.lua b/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/ai_translations.lua new file mode 100644 index 00000000..748d50db --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/ai_translations.lua @@ -0,0 +1,20 @@ + +/*--------------------------------------------------------- + Name: SetupWeaponHoldTypeForAI + Desc: Mainly a Todo.. In a seperate file to clean up the init.lua +---------------------------------------------------------*/ +function SWEP:SetupWeaponHoldTypeForAI( t ) + + self.ActivityTranslateAI = {} + self.ActivityTranslateAI [ ACT_STAND ] = ACT_IDLE_MELEE + self.ActivityTranslateAI [ ACT_IDLE_ANGRY ] = ACT_IDLE_ANGRY_MELEE + + self.ActivityTranslateAI [ ACT_MP_RUN ] = ACT_HL2MP_RUN_MELEE + self.ActivityTranslateAI [ ACT_MP_CROUCHWALK ] = ACT_HL2MP_WALK_CROUCH_MELEE + + self.ActivityTranslateAI [ ACT_MELEE_ATTACK1 ] = ACT_MELEE_ATTACK1 + + self.ActivityTranslateAI [ ACT_RELOAD ] = ACT_RELOAD + +end + diff --git a/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/cl_init.lua b/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/cl_init.lua new file mode 100644 index 00000000..95638668 --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/cl_init.lua @@ -0,0 +1,37 @@ + +include('shared.lua') + + +SWEP.PrintName = "Crowbar" +SWEP.ClassName = "nz_quickknife_crowbar" +SWEP.Slot = 0 +SWEP.SlotPos = 0 +SWEP.DrawAmmo = false +SWEP.DrawCrosshair = true +SWEP.DrawWeaponInfoBox = false +SWEP.BounceWeaponIcon = false + +SWEP.WepSelectFont = "HL2MPTypeDeath" +SWEP.WepSelectLetter = "6" +SWEP.IconFont = "HL2MPTypeDeath" +SWEP.IconLetter = "6" + +/*--------------------------------------------------------- + Checks the objects before any action is taken + This is to make sure that the entities haven't been removed +---------------------------------------------------------*/ +function SWEP:DrawWeaponSelection( x, y, wide, tall, alpha ) + + // Set us up the texture + surface.SetDrawColor( color_transparent ) + surface.SetTextColor( 255, 220, 0, alpha ) + surface.SetFont( self.WepSelectFont ) + local w, h = surface.GetTextSize( self.WepSelectLetter ) + + // Draw that mother + surface.SetTextPos( x + ( wide / 2 ) - ( w / 2 ), + y + ( tall / 2 ) - ( h / 2 ) ) + surface.DrawText( self.WepSelectLetter ) + +end + diff --git a/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/init.lua b/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/init.lua new file mode 100644 index 00000000..bd42ca76 --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/init.lua @@ -0,0 +1,23 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) + +include( "shared.lua" ) +include( "ai_translations.lua" ) + +SWEP.Weight = 0 +SWEP.AutoSwitchTo = false +SWEP.AutoSwitchFrom = false + +/*--------------------------------------------------------- + Name: OnDrop + Desc: Weapon was dropped +---------------------------------------------------------*/ +function SWEP:OnDrop() + + if ( IsValid( self.Weapon ) ) then + // self.Weapon:Remove() + end + +end + diff --git a/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/shared.lua b/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/shared.lua new file mode 100644 index 00000000..4c358712 --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_quickknife_crowbar/shared.lua @@ -0,0 +1,252 @@ + + -- Weapon base courtesy of CptFuzzies SWEP Bases project + -- Recoded to do more balanced damage + +SWEP.Author = "" +SWEP.Contact = "" +SWEP.Purpose = "" +SWEP.Instructions = "" + +SWEP.ViewModelFOV = 54 +SWEP.ViewModelFlip = false +SWEP.ViewModel = "models/weapons/c_crowbar.mdl" +SWEP.WorldModel = "models/weapons/w_crowbar.mdl" +SWEP.AnimPrefix = "crowbar" +SWEP.HoldType = "melee" + +SWEP.UseHands = true + +SWEP.Spawnable = false +SWEP.AdminSpawnable = false + +CROWBAR_RANGE = 75.0 +CROWBAR_REFIRE = 0.4 + +SWEP.Primary.Sound = Sound( "Weapon_Crowbar.Single" ) +SWEP.Primary.Hit = Sound( "Weapon_Crowbar.Melee_Hit" ) +SWEP.Primary.Range = CROWBAR_RANGE +SWEP.Primary.Damage = 75 +SWEP.Primary.DamageType = DMG_CLUB +SWEP.Primary.Force = 0.75 +SWEP.Primary.ClipSize = -1 +SWEP.Primary.Delay = CROWBAR_REFIRE +SWEP.Primary.DefaultClip = -1 +SWEP.Primary.Automatic = true +SWEP.Primary.Ammo = "None" + +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "None" + +SWEP.NZPreventBox = true + + + +/*--------------------------------------------------------- + Name: SWEP:Initialize( ) + Desc: Called when the weapon is first loaded +---------------------------------------------------------*/ +function SWEP:Initialize() + self:SetWeaponHoldType( self.HoldType ) +end + + +/*--------------------------------------------------------- + Name: SWEP:PrimaryAttack( ) + Desc: +attack1 has been pressed +---------------------------------------------------------*/ +function SWEP:PrimaryAttack() + + // Only the player fires this way so we can cast + local pPlayer = self.Owner; + + if ( !pPlayer ) then + return; + end + + // Make sure we can swing first + if ( !self:CanPrimaryAttack() ) then return end + + local vecSrc = pPlayer:GetShootPos(); + local vecDirection = pPlayer:GetAimVector(); + + local trace = {} + trace.start = vecSrc + trace.endpos = vecSrc + ( vecDirection * self:GetRange() ) + trace.filter = pPlayer + + local traceHit = util.TraceLine( trace ) + + if ( traceHit.Hit ) then + + self.Weapon:EmitSound( self.Primary.Hit ); + + self.Weapon:SendWeaponAnim( ACT_VM_HITCENTER ); + pPlayer:SetAnimation( PLAYER_ATTACK1 ); + + self.Weapon:SetNextPrimaryFire( CurTime() + self:GetFireRate() ); + self.Weapon:SetNextSecondaryFire( CurTime() + self.Weapon:SequenceDuration() ); + + self:Hit( traceHit, pPlayer ); + + return + + end + + self.Weapon:EmitSound( self.Primary.Sound ); + + self.Weapon:SendWeaponAnim( ACT_VM_MISSCENTER ); + pPlayer:SetAnimation( PLAYER_ATTACK1 ); + + self.Weapon:SetNextPrimaryFire( CurTime() + self:GetFireRate() ); + self.Weapon:SetNextSecondaryFire( CurTime() + self.Weapon:SequenceDuration() ); + + self:Swing( traceHit, pPlayer ); + + return + +end + + +/*--------------------------------------------------------- + Name: SWEP:SecondaryAttack( ) + Desc: +attack2 has been pressed +---------------------------------------------------------*/ +function SWEP:SecondaryAttack() + return false +end + +/*--------------------------------------------------------- + Name: SWEP:Reload( ) + Desc: Reload is being pressed +---------------------------------------------------------*/ +function SWEP:Reload() + return false +end + +//----------------------------------------------------------------------------- +// Purpose: Get the damage amount for the animation we're doing +// Input : hitActivity - currently played activity +// Output : Damage amount +//----------------------------------------------------------------------------- +function SWEP:GetDamageForActivity( hitActivity ) + return nzRound:InProgress() and 30 + (45/nzRound:GetNumber()) or 75 +end + +//----------------------------------------------------------------------------- +// Purpose: Add in a view kick for this weapon +//----------------------------------------------------------------------------- +function SWEP:AddViewKick() + + local pPlayer = self:GetOwner(); + + if ( pPlayer == NULL ) then + return; + end + + if ( pPlayer:IsNPC() ) then + return; + end + + local punchAng = Angle( 0, 0 ,0 ); + + punchAng.pitch = math.Rand( 1.0, 2.0 ); + punchAng.yaw = math.Rand( -2.0, -1.0 ); + punchAng.roll = 0.0; + + pPlayer:ViewPunch( punchAng ); + +end + + +/*--------------------------------------------------------- + Name: SWEP:Deploy( ) + Desc: Whip it out +---------------------------------------------------------*/ +function SWEP:Deploy() + + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + self:SetDeploySpeed( self.Weapon:SequenceDuration() ) + + return true + +end + + +/*--------------------------------------------------------- + Name: SWEP:Hit( ) + Desc: A convenience function to trace impacts +---------------------------------------------------------*/ +function SWEP:Hit( traceHit, pPlayer ) + + local vecSrc = pPlayer:GetShootPos(); + + if ( SERVER ) then + pPlayer:TraceHullAttack( vecSrc, traceHit.HitPos, Vector( -5, -5, -5 ), Vector( 5, 5, 36 ), self:GetDamageForActivity(), self.Primary.DamageType, self.Primary.Force ); + end + + // self:AddViewKick(); + +end + + +/*--------------------------------------------------------- + Name: SWEP:Swing( ) + Desc: A convenience function to trace impacts +---------------------------------------------------------*/ +function SWEP:Swing( traceHit, pPlayer ) +end + + +/*--------------------------------------------------------- + Name: SWEP:CanPrimaryAttack( ) + Desc: Helper function for checking for no ammo +---------------------------------------------------------*/ +function SWEP:CanPrimaryAttack() + return true +end + + +/*--------------------------------------------------------- + Name: SWEP:CanSecondaryAttack( ) + Desc: Helper function for checking for no ammo +---------------------------------------------------------*/ +function SWEP:CanSecondaryAttack() + return false +end + + +/*--------------------------------------------------------- + Name: SetDeploySpeed + Desc: Sets the weapon deploy speed. + This value needs to match on client and server. +---------------------------------------------------------*/ +function SWEP:SetDeploySpeed( speed ) + + self.m_WeaponDeploySpeed = tonumber( speed / GetConVarNumber( "phys_timescale" ) ) + + self.Weapon:SetNextPrimaryFire( CurTime() + speed ) + self.Weapon:SetNextSecondaryFire( CurTime() + speed ) + +end + + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +function SWEP:Drop( vecVelocity ) +if ( !CLIENT ) then + self:Remove(); +end +end + +function SWEP:GetRange() + return self.Primary.Range; +end + +function SWEP:GetFireRate() + return self.Primary.Delay; +end + diff --git a/gamemodes/nzombies/entities/weapons/nz_revive_morphine.lua b/gamemodes/nzombies/entities/weapons/nz_revive_morphine.lua new file mode 100644 index 00000000..54fa5a2c --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_revive_morphine.lua @@ -0,0 +1,96 @@ +if SERVER then + AddCSLuaFile("nz_revive_morphine.lua") + SWEP.Weight = 5 + SWEP.AutoSwitchTo = false + SWEP.AutoSwitchFrom = true +end + +if CLIENT then + + SWEP.PrintName = "Morphine" + SWEP.Slot = 1 + SWEP.SlotPos = 1 + SWEP.DrawAmmo = false + SWEP.DrawCrosshair = true + + SWEP.Category = "nZombies" + +end + + +SWEP.Author = "Zet0r" +SWEP.Contact = "youtube.com/Zet0r" +SWEP.Purpose = "Fancy Viewmodel Animations" +SWEP.Instructions = "Let the gamemode give you it" + +SWEP.Spawnable = false +SWEP.AdminSpawnable = false + +SWEP.HoldType = "slam" + +SWEP.ViewModel = "models/weapons/c_revive_morphine.mdl" +SWEP.WorldModel = "" +SWEP.UseHands = true +SWEP.vModel = true + +SWEP.Primary.ClipSize = -1 +SWEP.Primary.DefaultClip = -1 +SWEP.Primary.Automatic = false +SWEP.Primary.Ammo = "none" + +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "none" + +SWEP.NZPreventBox = true +SWEP.NZTotalBlacklist = true + +function SWEP:Initialize() + + self:SetHoldType( "slam" ) + +end + +function SWEP:Deploy() + self:SendWeaponAnim(ACT_VM_DRAW) + self.WepOwner = self.Owner +end + +function SWEP:Equip( owner ) + owner:SetActiveWeapon("nz_revive_morphine") +end + +function SWEP:PrimaryAttack() + +end + +function SWEP:PostDrawViewModel() + +end + +function SWEP:DrawWorldModel() + +end + +function SWEP:OnRemove() + if SERVER then + if !IsValid(self.WepOwner:GetActiveWeapon()) or !self.WepOwner:GetActiveWeapon():IsSpecial() then + self.WepOwner:SetUsingSpecialWeapon(false) + end + self.WepOwner:SetActiveWeapon(nil) + self.WepOwner:EquipPreviousWeapon() + end +end + +function SWEP:GetViewModelPosition( pos, ang ) + + local newpos = LocalPlayer():EyePos() + local newang = LocalPlayer():EyeAngles() + local up = newang:Up() + + newpos = newpos + LocalPlayer():GetAimVector()*6 - up*63 + + return newpos, newang + +end \ No newline at end of file diff --git a/nzombies3/entities/weapons/nz_tool_base/cl_init.lua b/gamemodes/nzombies/entities/weapons/nz_tool_base/cl_init.lua similarity index 100% rename from nzombies3/entities/weapons/nz_tool_base/cl_init.lua rename to gamemodes/nzombies/entities/weapons/nz_tool_base/cl_init.lua diff --git a/nzombies3/entities/weapons/nz_tool_base/init.lua b/gamemodes/nzombies/entities/weapons/nz_tool_base/init.lua similarity index 100% rename from nzombies3/entities/weapons/nz_tool_base/init.lua rename to gamemodes/nzombies/entities/weapons/nz_tool_base/init.lua diff --git a/nzombies3/entities/weapons/nz_tool_base/shared.lua b/gamemodes/nzombies/entities/weapons/nz_tool_base/shared.lua similarity index 99% rename from nzombies3/entities/weapons/nz_tool_base/shared.lua rename to gamemodes/nzombies/entities/weapons/nz_tool_base/shared.lua index 17f572a2..979252da 100644 --- a/nzombies3/entities/weapons/nz_tool_base/shared.lua +++ b/gamemodes/nzombies/entities/weapons/nz_tool_base/shared.lua @@ -39,6 +39,8 @@ SWEP.Secondary = SWEP.CanHolster = true SWEP.CanDeploy = true +SWEP.NZPreventBox = true + --[[--------------------------------------------------------- Initialize -----------------------------------------------------------]] diff --git a/gamemodes/nzombies/entities/weapons/nz_touchedlast.lua b/gamemodes/nzombies/entities/weapons/nz_touchedlast.lua new file mode 100644 index 00000000..1f1b7f63 --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_touchedlast.lua @@ -0,0 +1,304 @@ +if SERVER then + AddCSLuaFile() + SWEP.Weight = 5 + SWEP.AutoSwitchTo = true + SWEP.AutoSwitchFrom = false + + util.AddNetworkString("ThrowBall") + util.AddNetworkString("ThrowBallCancel") +end + +if CLIENT then + + SWEP.PrintName = "Weaponized YTi-L4" + SWEP.Slot = 1 + SWEP.SlotPos = 1 + SWEP.DrawAmmo = false + SWEP.DrawCrosshair = true + +end + +local ballmat = Material( "sprites/sent_ball" ) +local charger = 2 + +SWEP.NZPreventBox = true +SWEP.NZPaPName = "Fragmentized YTi-L4 XP" +SWEP.NZTotalBlacklist = true +SWEP.NZRePaPText = "Reroll Color" -- It automatically adds "Press E to" and "for 2000 points" + +SWEP.Author = "Zet0r" +SWEP.Contact = "youtube.com/Zet0r" +SWEP.Purpose = "You Touched it Last weapon ;)" +SWEP.Instructions = "Throw balls at zombies" + +SWEP.Spawnable = false +SWEP.AdminSpawnable = false + +SWEP.HoldType = "normal" + +SWEP.ViewModel = "models/weapons/c_grenade.mdl" +SWEP.WorldModel = "models/Combine_Helicopter/helicopter_bomb01.mdl" +SWEP.UseHands = true + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.DefaultClip = 1 +SWEP.Primary.Automatic = false +SWEP.Primary.Ammo = "XBowBolt" + +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "none" + +SWEP.BallKillRecoverTime = 5 -- Time in seconds for each "kill" to be added to the ball + +--[[if SERVER then + util.AddNetworkString("HasBall") + util.AddNetworkString("ThrowBall") + util.AddNetworkString("ActiveBall") +end]] + +function SWEP:SetupDataTables() + + self:NetworkVar( "Int", 0, "CurKills" ) + self:NetworkVar( "Int", 1, "BallColor" ) + +end + +function SWEP:NZMaxAmmo() + self:ReplenishBall(0) +end + +function SWEP:Initialize() + + self:SetHoldType( self.HoldType ) + self:SetCurKills(0) + self.Charge = 0 + self:SetBallColor(math.random(0,360)) + +end + +function SWEP:Deploy() + + if self:Clip1() >= 1 then + if IsValid(self.Owner:GetViewModel()) then self.Owner:GetViewModel():SetNoDraw(false) end + self:SendWeaponAnim(ACT_VM_DRAW) + else + if IsValid(self.Owner:GetViewModel()) then self.Owner:GetViewModel():SetNoDraw(true) end + self:SendWeaponAnim(ACT_VM_THROW) + end + +end + +function SWEP:PrimaryAttack() + + if game.SinglePlayer() then self:CallOnClient("PrimaryAttack") end + + if self:Clip1() >= 1 then + self:SetHoldType( "grenade" ) + + if CLIENT then + hook.Add("Tick", "ChargeUp"..self.Owner:EntIndex(), function() self:ChargeUp() end) + hook.Add("HUDPaint", "debugDrawCharge", function() + draw.SimpleText(self.Charge, "DebugFixed", ScrW() / 2, ScrH() / 4 * 3, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + end) + end + end + + --[[if self:Clip1() >= 1 then + self:ThrowBall(1000) + self:SetClip1(0) + end]] + +end + +function SWEP:ChargeUp() + + self.Charge = self.Charge + charger + if self.Charge >= 100 then + charger = -2 + elseif self.Charge <= 0 then + charger = 2 + end + + if input.IsMouseDown(MOUSE_RIGHT) then + hook.Remove("Tick", "ChargeUp"..self.Owner:EntIndex()) + hook.Remove("HUDPaint", "debugDrawCharge") + self.Charge = 0 + charger = 2 + net.Start("ThrowBallCancel") + net.SendToServer() + return false + end + + if !input.IsMouseDown(MOUSE_LEFT) then + hook.Remove("Tick", "ChargeUp"..self.Owner:EntIndex()) + hook.Remove("HUDPaint", "debugDrawCharge") + net.Start("ThrowBall") + net.WriteInt(self.Charge, 8) + net.SendToServer() + self.Charge = 0 + charger = 2 + self.Owner.HasBall = false + return true + end + +end + +function SWEP:ThrowBall(force) + + if self:Clip1() < 1 then return end + self:SetClip1(0) + + self.Owner:SetAnimation(PLAYER_ATTACK1) + self:SendWeaponAnim(ACT_VM_THROW) + + timer.Simple(0.7, function() + if IsValid(self) then self:SetHoldType( self.HoldType ) end + end) + timer.Simple(0.3, function() + if IsValid(self) then self.Owner:GetViewModel():SetNoDraw(true) end + end) + + local ball = ents.Create("nz_ytil_ball") + ball:SetBallColor(self:GetBallColor()) + ball:SetBallOwner(self.Owner) + ball:SetFragment(false) + ball:SetMaxKills(self.pap and 20 or 10) + ball:SetCurKills(self:GetCurKills()) + + ball:SetPos(self.Owner:EyePos() + (self.Owner:GetAimVector() * 40)) + ball:Spawn() + ball:Activate() + ball.pap = self.pap + + local ballPhys = ball:GetPhysicsObject() + if IsValid(ballPhys) then + ballPhys:ApplyForceCenter(self.Owner:GetAimVector():GetNormalized() * force * 10) + end + + self:SetCurKills(-1) + self:SetHoldType( "normal" ) + +end + +function SWEP:ReplenishBall(charge) + self:SetCurKills(charge) + self:SetClip1(1) + if IsValid(self.Owner:GetActiveWeapon()) and self.Owner:GetActiveWeapon():GetClass() == "nz_touchedlast" then + if IsValid(self.Owner:GetViewModel()) then self.Owner:GetViewModel():SetNoDraw(false) end + self:SendWeaponAnim(ACT_VM_DRAW) + end + if self.pap then + self.NextRecover = CurTime() + (self.BallKillRecoverTime/2) + else + self.NextRecover = CurTime() + self.BallKillRecoverTime + end +end + +net.Receive("ThrowBall", function(len, ply) + if ply:Alive() and IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():Clip1() >= 1 then + ply:GetActiveWeapon():ThrowBall(net.ReadInt(8)) + end +end) + +net.Receive("ThrowBallCancel", function(len, ply) + if ply:Alive() and IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():GetClass() == "nz_touchedlast" then + ply:GetActiveWeapon():SetHoldType("normal") + end +end) + +function SWEP:SecondaryAttack() + +end + +function SWEP:Think() + if SERVER then + if self.pap then + if self:GetCurKills() > 0 and CurTime() >= self.NextRecover then + self:SetCurKills(self:GetCurKills() - 1) + self.NextRecover = CurTime() + (self.BallKillRecoverTime/2) + end + else + if self:GetCurKills() > 0 and CurTime() >= self.NextRecover then + self:SetCurKills(self:GetCurKills() - 1) + self.NextRecover = CurTime() + (self.BallKillRecoverTime) + end + end + end +end + +function SWEP:DrawHUD() + + + +end + +local defcolor = Color(255,0,0) +function SWEP:DrawWorldModel() + if self:GetClass() != "nz_touchedlast" then + -- For wall buys and other entities + local pos = self:GetPos() + local size = 20 + + render.SetMaterial( ballmat ) + local color = defcolor + render.DrawSprite( pos, size, size, color ) + else + if self:GetCurKills() == -1 then return end + local pos = IsValid(self.Owner) and self.Owner:GetBonePosition(self.Owner:LookupBone("ValveBiped.Bip01_R_Hand")) or self:GetPos() + local size = 20 + + render.SetMaterial( ballmat ) + local color = HSVToColor(self:GetBallColor(), 1, 1) + render.DrawSprite( pos, size, size, color ) + end +end + +function SWEP:OnRemove() + if CLIENT then + hook.Remove("Tick", "ChargeUp"..self.Owner:EntIndex()) + LocalPlayer().charge = 0 + charger = 2 + end +end + +function SWEP:PreDrawViewModel(vm, ply, wep) +end + +function SWEP:PostDrawViewModel(vm, wep, ply) + + local hands = LocalPlayer():GetHands() + if ( IsValid( hands ) ) then hands:DrawModel() end + + -- Draw the ball over the grenade + if self:Clip1() >= 1 then + local maxkills = self.pap and 20 or 10 + local ballColor = HSVToColor(self:GetBallColor(), 1 - (self:GetCurKills()/maxkills), 1) + render.SetMaterial( ballmat ) + render.DrawSprite( + LocalPlayer():GetViewModel():GetBonePosition( LocalPlayer():GetViewModel():LookupBone( "ValveBiped.Grenade_body" ) ) + + LocalPlayer():EyeAngles():Forward()*-1 + LocalPlayer():EyeAngles():Right()*-4 + + LocalPlayer():EyeAngles():Up()*1, + 10, 10, + ballColor + ) + end + + -- Hide the grenade bone + LocalPlayer():GetViewModel():ManipulateBoneScale( LocalPlayer():GetViewModel():LookupBone( "ValveBiped.Grenade_body" ), Vector(0,0,0) ) + LocalPlayer():GetViewModel():ManipulateBoneScale( LocalPlayer():GetViewModel():LookupBone( "ValveBiped.Pin" ), Vector(0,0,0) ) + +end + +function SWEP:OnPaP() + self.pap = true + return true +end + +function SWEP:OnRePaP() + -- We return true to not modify attachments or anything + -- However re-pap'ing rerolls the color and having this function allows re-pap'ing + -- so that's what that is for (expensive for 2000 huh ;) ) + return true +end \ No newline at end of file diff --git a/gamemodes/nzombies/entities/weapons/nz_zombieshield.lua b/gamemodes/nzombies/entities/weapons/nz_zombieshield.lua new file mode 100644 index 00000000..c708d11a --- /dev/null +++ b/gamemodes/nzombies/entities/weapons/nz_zombieshield.lua @@ -0,0 +1,211 @@ +if SERVER then + AddCSLuaFile("nz_zombieshield.lua") + SWEP.Weight = 5 + SWEP.AutoSwitchTo = true + SWEP.AutoSwitchFrom = false +end + +if CLIENT then + + SWEP.PrintName = "Zombie Shield" + SWEP.Slot = 1 + SWEP.SlotPos = 1 + SWEP.DrawAmmo = false + SWEP.DrawCrosshair = true + + SWEP.Category = "nZombies" + +end + + +SWEP.Author = "Zet0r" +SWEP.Contact = "youtube.com/Zet0r" +SWEP.Purpose = "Your back is now protected!" +SWEP.Instructions = "Build it by finding all its parts!" + +SWEP.Spawnable = false +SWEP.AdminSpawnable = false + +SWEP.HoldType = "fist" + +SWEP.ViewModel = "models/weapons/c_zombieshield.mdl" +SWEP.WorldModel = "models/weapons/w_zombieshield_equipped.mdl" +SWEP.UseHands = true +SWEP.vModel = true + +SWEP.Primary.ClipSize = -1 +SWEP.Primary.DefaultClip = -1 +SWEP.Primary.Automatic = false +SWEP.Primary.Ammo = "none" + +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "none" + +SWEP.NZPreventBox = true +--SWEP.NZTotalBlacklist = true +SWEP.NZSpecialCategory = "shield" -- This makes it count as special, as well as what category it replaces +-- Since this is a unique ID, it won't replace any other special weapon and it won't be selectable, so we call this function: + +nzSpecialWeapons:RegisterSpecialWeaponCategory("shield", KEY_N) -- This also adds a convar to rebind (with that default) + +function SWEP:NZSpecialHolster(wep) + return true -- This lets us always holster it even though it is a special weapon +end + +function SWEP:SetupDataTables() + self:NetworkVar("Bool", 0, "Electrified") +end + +function SWEP:Initialize() + + self:SetHoldType( self.HoldType ) + print(self.NZSpecialHolster) + +end + +function SWEP:Deploy() + if SERVER then + if IsValid(self.Owner) and IsValid(self.Shield) then + self.Owner.Shield:SetNoDraw(true) + else + self:Remove() + end + end + self:SendWeaponAnim(ACT_VM_DRAW) + self.WepOwner = self.Owner + self:CallOnClient("Deploy") + + local viewmodel = self.Owner:GetViewModel() + if IsValid(viewmodel) then + viewmodel:SetBodygroup(0,self:GetBodygroup(0)) + viewmodel:SetBodygroup(1,self:GetBodygroup(1)) + viewmodel:SetBodygroup(2,self:GetBodygroup(2)) + end +end + +function SWEP:Holster() + if SERVER then + if IsValid(self.Owner) and IsValid(self.Shield) then + self.Owner.Shield:SetNoDraw(false) + else + self:Remove() + end + end + local viewmodel = self.Owner:GetViewModel() + if IsValid(viewmodel) then + viewmodel:SetBodygroup(0,0) + viewmodel:SetBodygroup(1,0) + viewmodel:SetBodygroup(2,0) + end + return true +end + +function SWEP:CreateBackShield(owner) + owner.Shield = ents.Create("nz_zombieshield_back") + owner.Shield:SetOwner(owner) + owner.Shield:Spawn() + self.Shield = owner.Shield +end + +function SWEP:Equip( owner ) + self:CreateBackShield(owner) +end + +function SWEP:PrimaryAttack() + + self:SetNextPrimaryFire(CurTime() + 1) + + local vecSrc = self.Owner:GetShootPos() + local vecDirection = self.Owner:GetAimVector() + + local trace = {} + trace.start = vecSrc + trace.endpos = vecSrc + ( vecDirection * 100) + trace.filter = self.Owner + + local tracehit = util.TraceLine( trace ) + self:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + if ( tracehit.Hit ) then + if ( SERVER ) then + self:EmitSound("physics/metal/metal_box_impact_hard"..math.random(1,3)..".wav") + if self:GetElectrified() then + local ent = self.Owner:TraceHullAttack( vecSrc, tracehit.HitPos, Vector( -5, -5, -5 ), Vector( 5, 5, 36 ), 450, DMG_SHOCK, 100 ) + if IsValid(ent) then timer.Simple(0, function() self:EmitSound("ambient/energy/zap"..math.random(1,9)..".wav") end) end + else + self.Owner:TraceHullAttack( vecSrc, tracehit.HitPos, Vector( -5, -5, -5 ), Vector( 5, 5, 36 ), 250, DMG_CLUB, 100 ) + end + end + end + +end + +function SWEP:OnRemove() + if SERVER then + if IsValid(self.Shield) then + self.Shield:Remove() + end + end +end + +function SWEP:GetViewModelPosition( pos, ang ) + + return pos, ang + +end + +function SWEP:SetDamage(value) + if self.DamagedVariant == value then return end + + self.DamagedVariant = value + self:SetBodygroup(0,value) + self:SetBodygroup(1,value) + self:SetBodygroup(2,value) + + if self.Owner:GetActiveWeapon() == self then + local viewmodel = self.Owner:GetViewModel() + if IsValid(viewmodel) then + viewmodel:SetBodygroup(0,value) + viewmodel:SetBodygroup(1,value) + viewmodel:SetBodygroup(2,value) + end + end + + self:EmitSound("physics/metal/metal_sheet_impact_hard"..math.random(6,8)..".wav") +end + + +if CLIENT then + function SWEP:DrawWorldModel() + self:DrawModel() + if self:GetElectrified() then + local pos, ang = self:GetBonePosition(1) + nzEffects:DrawElectricArcs( self, pos, ang, 1, 1, 0.3 ) + end + end + + function SWEP:PostDrawViewModel(vm) + if self:GetElectrified() then + local pos, ang = vm:GetBonePosition(23) + nzEffects:DrawElectricArcs( self, pos, ang, 1, 1, 0.3 ) + end + end + +end + +hook.Add("PlayerShouldTakeDamage", "nzShieldDamageHandler", function(ply, ent) + + if ent:IsValidZombie() and IsValid(ply.Shield) then + local dot = (ent:GetPos() - ply:GetPos()):Dot(ply:GetAimVector()) + local wep = ply:GetActiveWeapon() + local shield = IsValid(wep) and wep:GetClass() == "nz_zombieshield" + if (dot < 0 and !shield) or (dot >= 0 and shield) then + ply.Shield:TakeDamage(30, ent, ent) + return false + end + end + +end) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/chatcommand/sh_chatcommands.lua b/gamemodes/nzombies/gamemode/chatcommand/sh_chatcommands.lua new file mode 100644 index 00000000..00b055ef --- /dev/null +++ b/gamemodes/nzombies/gamemode/chatcommand/sh_chatcommands.lua @@ -0,0 +1,270 @@ +nzChatCommand.Add("/cheats", CLIENT, function(ply, text) + if CLIENT then + if !IsValid(g_nz_cheats) then + g_nz_cheats = vgui.Create("NZCheatFrame") + else + g_nz_cheats:Remove() + end + else + return true -- Doesn't block the command (client does this instead) + end +end, false, "Opens the cheat panel.") + +-- Chat Commands + +nzChatCommand.Add("/help", SERVER, function(ply, text) + ply:PrintMessage( HUD_PRINTTALK, "-----" ) + ply:PrintMessage( HUD_PRINTTALK, "[nZ] Available commands:" ) + ply:PrintMessage( HUD_PRINTTALK, "Arguments in [] are optional." ) + for _, cmd in pairs(nzChatCommand.commands) do + local cmdText = cmd[1] + if cmd[4] then + cmdText = cmdText .. " " .. cmd[4] + end + if cmd[3] or (!cmd[3] and ply:IsSuperAdmin()) then + ply:PrintMessage( HUD_PRINTTALK, cmdText ) + end + end + ply:PrintMessage( HUD_PRINTTALK, "-----" ) + ply:PrintMessage( HUD_PRINTTALK, "" ) +end, true, " Print this list.") + +nzChatCommand.Add("/ready", SERVER, function(ply, text) + ply:ReadyUp() +end, true, " Mark yourself as ready.") + +nzChatCommand.Add("/unready", SERVER, function(ply, text) + ply:UnReady() +end, true, " Mark yourself as unready.") + +nzChatCommand.Add("/dropin", SERVER, function(ply, text) + ply:DropIn() +end, true, " Drop into the next round.") + +nzChatCommand.Add("/dropout", SERVER, function(ply, text) + ply:DropOut() +end, true, " Drop out of the current round.") + +nzChatCommand.Add("/create", SERVER, function(ply, text) + local plyToCreate + if text[1] then plyToCreate = player.GetByName(text[1]) else plyToCreate = ply end + + if IsValid(plyToCreate) then + plyToCreate:ToggleCreativeMode() + else + ply:ChatPrint("[nZ] Could not find player '"..text[1].."', are you sure he exists?") + end +end, false, " Respawn in creative mode.") + +nzChatCommand.Add("/generate", SERVER, function(ply, text) + if navmesh.IsLoaded() then + ply:PrintMessage( HUD_PRINTTALK, "[nZ] Navmesh already exists, couldn't generate." ) + else + ply:PrintMessage( HUD_PRINTTALK, "[nZ] Starting Navmesh Generation, this may take a while." ) + navmesh.BeginGeneration() + --force generate + if !navmesh.IsGenerating() then + ply:PrintMessage( HUD_PRINTTALK, "[nZ] No walkable seeds found, forcing generation..." ) + local sPoint = GAMEMODE.SpawnPoints[ math.random( #GAMEMODE.SpawnPoints ) ] + local tr = util.TraceLine( { + start = sPoint:GetPos(), + endpos = sPoint:GetPos() - Vector( 0, 0, 100), + filter = sPoint + } ) + + local ent = ents.Create("info_player_start") + ent:SetPos( tr.HitPos ) + ent:Spawn() + navmesh.BeginGeneration() + end + + if !navmesh.IsGenerating() then + --Will not happen but just in case + ply:PrintMessage( HUD_PRINTTALK, "[nZ] Navmesh Generation failed! Please try this command again or generate the navmesh manually." ) + end + end +end, false, " Generate a new naviagtion mesh.") + +nzChatCommand.Add("/save", SERVER, function(ply, text) + if nzRound:InState( ROUND_CREATE ) then + net.Start("nz_SaveConfig") + net.WriteString(nzMapping.CurrentConfig or "") + net.Send(ply) + else + ply:PrintMessage( HUD_PRINTTALK, "[nZ] You can't save a config outside of creative mode." ) + end +end, false, " Save your changes to a config.") + +nzChatCommand.Add("/load", SERVER, function(ply, text) + if nzRound:InState( ROUND_CREATE) or nzRound:InState( ROUND_WAITING ) then + nzInterfaces.SendInterface(ply, "ConfigLoader", nzMapping:GetConfigs()) + else + ply:PrintMessage( HUD_PRINTTALK, "[nZ] You can't load while playing!" ) + end +end, false, " Open the map config load dialog.") + +nzChatCommand.Add("/clean", SERVER, function(ply, text) + if nzRound:InState( ROUND_CREATE) or nzRound:InState( ROUND_WAITING ) then + nzMapping:ClearConfig() + else + ply:PrintMessage( HUD_PRINTTALK, "[nZ] You can't clean while playing!" ) + end +end) + +-- Tests + +nzChatCommand.Add("/spectate", SERVER, function(ply, text) + if !nzRound:InProgress() or nzRound:InState( ROUND_INIT ) then + ply:PrintMessage( HUD_PRINTTALK, "[nZ] No round in progress, couldnt set you to spectator!" ) + elseif ply:IsReady() then + ply:UnReady() + ply:SetSpectator() + else + ply:SetSpectator() + end +end, true) + +nzChatCommand.Add("/soundcheck", SERVER, function(ply, text) + if ply:IsSuperAdmin() then + nzNotifications:PlaySound("nz/powerups/double_points.mp3", 1) + nzNotifications:PlaySound("nz/powerups/insta_kill.mp3", 2) + nzNotifications:PlaySound("nz/powerups/max_ammo.mp3", 2) + nzNotifications:PlaySound("nz/powerups/nuke.mp3", 2) + + nzNotifications:PlaySound("nz/round/round_start.mp3", 14) + nzNotifications:PlaySound("nz/round/round_end.mp3", 9) + nzNotifications:PlaySound("nz/round/game_over_4.mp3", 21) + end +end, true) + +--cheats +nzChatCommand.Add("/revive", SERVER, function(ply, text) + local plyToRev = text[1] and player.GetByName(text[1]) or ply + if IsValid(plyToRev) and !plyToRev:GetNotDowned() then + plyToRev:RevivePlayer() + else + ply:ChatPrint("[nZ] Player could not have been revived, are you sure he is downed?") + end +end, false, "[playerName] Revive yourself or another player.") + +nzChatCommand.Add("/givepoints", SERVER, function(ply, text) + local plyToGiv = player.GetByName(text[1]) + local points + + if !plyToGiv then + points = tonumber(text[1]) + plyToGiv = ply + else + points = tonumber(text[2]) + end + + if IsValid(plyToGiv) and plyToGiv:Alive() and (plyToGiv:IsPlaying() or nzRound:InState(ROUND_CREATE)) then + if points then + plyToGiv:GivePoints(points) + else + ply:ChatPrint("[nZ] No valid number provided.") + end + else + ply:ChatPrint("[nZ] The player you have selected is either not valid or not alive.") + end +end, false, "[playerName] pointAmount Give points to yourself or another player.") + +nzChatCommand.Add("/giveweapon", SERVER, function(ply, text) + local plyToGiv = player.GetByName(text[1]) + + local wep + + if !plyToGiv then + wep = weapons.Get(text[1]) + plyToGiv = ply + else + wep = weapons.Get(text[2]) + end + if IsValid(plyToGiv) and plyToGiv:Alive() and (plyToGiv:IsPlaying() or nzRound:InState(ROUND_CREATE)) then + if wep then + plyToGiv:Give(wep.ClassName) + else + ply:ChatPrint("[nZ] No valid weapon provided.") + end + else + ply:ChatPrint("[nZ] The player you have selected is either not valid or not alive.") + end +end, false, "[playerName] weaponName Give a weapon to yourself or another player.") + +nzChatCommand.Add("/giveperk", SERVER, function(ply, text) + local plyToGiv = player.GetByName(text[1]) + + local perk + + if !plyToGiv then + perk = text[1] + plyToGiv = ply + else + perk = text[2] + end + if IsValid(plyToGiv) and plyToGiv:Alive() and (plyToGiv:IsPlaying() or nzRound:InState(ROUND_CREATE)) then + if nzPerks:Get(perk) then + plyToGiv:GivePerk(perk) + else + ply:ChatPrint("[nZ] No valid perk provided.") + end + else + ply:ChatPrint("[nZ] They player you have selected is either not valid or not alive.") + end +end, false, "[playerName] perkID Give a perk to yourself or another player.") + +nzChatCommand.Add("/targetpriority", SERVER, function(ply, text) + local plyToGiv + local strstart, strend = string.find(text[1], "entity(", 1, true) + if strstart then + local _, strstop = string.find(text[1], ")", strend, true) + local ent = string.sub(text[1], strend + 1, strstop - 1) + if ent and IsValid(Entity(ent)) then + plyToGiv = Entity(ent) + end + else + plyToGiv = player.GetByName(text[1]) + end + + local priority + + if !plyToGiv then + priority = tonumber(text[1]) + plyToGiv = ply + else + priority = tonumber(text[2]) + end + if IsValid(plyToGiv) and (!plyToGiv:IsPlayer() or (plyToGiv:Alive() and (plyToGiv:IsPlaying() or nzRound:InState(ROUND_CREATE)))) then + if priority then + plyToGiv:SetTargetPriority(priority) + else + ply:ChatPrint("[nZ] No valid priority provided.") + end + else + ply:ChatPrint("[nZ] The player you have selected is either not valid or not alive.") + end +end) + +nzChatCommand.Add("/activateelec", SERVER, function(ply, text) + nzElec:Activate() +end) + +nzChatCommand.Add("/navflush", SERVER, function(ply, text) + nzNav.FlushAllNavModifications() + PrintMessage(HUD_PRINTTALK, "[nZ] Navlocks successfully flushed. Remember to redo them for best playing experience.") +end) + +nzChatCommand.Add("/tools", SERVER, function(ply, text) + if ply:IsInCreative() then + ply:Give("weapon_physgun") + ply:Give("nz_multi_tool") + end +end, true, "Give creative mode tools to yourself if in Creative.") + +nzChatCommand.Add("/maxammo", SERVER, function(ply, text) + nzNotifications:PlaySound("nz/powerups/max_ammo.mp3", 2) + -- Give everyone ammo + for k,v in pairs(player.GetAll()) do + v:GiveMaxAmmo() + end +end, false, "Gives all players max ammo.") diff --git a/gamemodes/nzombies/gamemode/chatcommand/sh_constructor.lua b/gamemodes/nzombies/gamemode/chatcommand/sh_constructor.lua new file mode 100644 index 00000000..289ae843 --- /dev/null +++ b/gamemodes/nzombies/gamemode/chatcommand/sh_constructor.lua @@ -0,0 +1,169 @@ +-- Chat Commands module +nzChatCommand = nzChatCommand or AddNZModule("chatcommand") + +nzChatCommand.commands = nzChatCommand.commands or {} + +if CLIENT then + nzChatCommand.servercommands = nzChatCommand.servercommands or {} -- For autocomplete +end + +-- Functions +--[[ nzChatCommand.Add + text [string]: The text you put in chat to trigger this command + realm [realm]: The realm this command will work in (SERVER/CLIENT) + func [function]: The function to run when the command is issued. It runs the function with the player as the first argument, then all arguments in the chat seperated by space + allowAll [boolean]: If set to true, will allow even non-admins to run this command + --]] + +--TODO add more descriptive table indices. +function nzChatCommand.Add(text, realm, func, allowAll, usageHelp) + if realm or SERVER then -- Always server + if usageHelp then + table.insert(nzChatCommand.commands, {text, func, allowAll and true or false, usageHelp}) + else + table.insert(nzChatCommand.commands, {text, func, allowAll and true or false}) + end + elseif CLIENT then + table.insert(nzChatCommand.servercommands, {text, allowAll and true or false, usageHelp}) + end +end + +-- Hooks +if SERVER then + local function commandListenerSV( ply, text, public ) + --print("Here", text, ply) + if text[1] == "/" then + text = string.lower(text) + for k,v in pairs(nzChatCommand.commands) do + if (string.sub(text, 1, string.len(v[1])) == v[1]) then + if !v[3] and !ply:IsSuperAdmin() then + ply:ChatPrint("NZ This command can only be used by administrators.") + return false + end + + local args = nzChatCommand.splitCommand(text) + -- Check if quotionmark usage was valid + if args then + -- Remove first arguement (command name) and then call function with the reamianing args + table.remove(args, 1) + local block = v[2](ply, args) or false + print("NZ " .. tostring(ply) .. " used command " .. v[1] .. " with arguments:\n" .. table.ToString(args)) + return block + else + ply:ChatPrint("NZ Invalid command usage (check for missing quotes).") + return false + end + end + end + ply:ChatPrint("NZ No valid command exists with this name, try '/help' for a list of commands.") + end + end + hook.Add("PlayerSay", "nzChatCommand", commandListenerSV) + + -- Receiving net messages from console command nz_chatcommand instead (in case another addon blocks the hook) + util.AddNetworkString("nzChatCommand") + net.Receive("nzChatCommand", function(len, ply) + if !IsValid(ply) then return end + local command = net.ReadString() + print("Got command", command) + commandListenerSV(ply, command) + end) +end + +if CLIENT then + local function commandListenerCL( ply, text, public, dead ) + if text[1] == "/" then + text = string.lower(text) + for k,v in pairs(nzChatCommand.commands) do + if (string.sub(text, 1, string.len(v[1])) == v[1]) then + if v[3] and !ply:IsSuperAdmin() then + return true + end + if ply == LocalPlayer() then + local args = nzChatCommand.splitCommand(text) + -- Check if quotionmark usage was valid + if args then + -- Remove first arguement (command name) and then call function with the reamianing args + table.remove(args, 1) + local block = v[2](ply, args) or false + return block + else + ply:ChatPrint("NZ Invalid command usage (check for missing quotes).") + return false + end + end + return true + end + end + end + end + hook.Add("OnPlayerChat", "nzChatCommandClient", commandListenerCL) + + -- Console command nz_chatcommand in case another addon blocks the hooks (works just like chat, "nz_chatcommand [chat commands]") + local function nz_chatcommand(ply, cmd, args, argstr) + if !argstr then return end + argstr = string.Trim(argstr, " ") -- Trim spaces + if string.sub(argstr, 1, 1) == "\"" and string.sub(argstr, #argstr, #argstr) == "\"" then + argstr = string.sub(argstr, 2, #argstr-1) -- Trim quotation marks but only if they are around the WHOLE string + -- As to avoid trimming in commmands like /revive "Some Name with Spaces" + end + net.Start("nzChatCommand") + net.WriteString(argstr) + net.SendToServer() + commandListenerCL(LocalPlayer(), argstr) + end + -- Even comes with autocomplete :D + local function nz_chatcommand_autocomplete(cmd, argstr) + argstr = string.Trim( argstr ) + argstr = string.lower( argstr ) + + local tbl = {} + + for _, cmd in pairs(nzChatCommand.servercommands) do + local cmdText = cmd[1] + if string.find(cmdText, argstr) then + if cmd[2] or (!cmd[2] and LocalPlayer():IsSuperAdmin()) then + local text = "nz_chatcommand ".. cmdText + if !table.HasValue(tbl, text) then + table.insert(tbl, text) + end + end + end + end + + for _, cmd in pairs(nzChatCommand.commands) do + local cmdText = cmd[1] + if string.find(cmdText, argstr) then + if cmd[3] or (!cmd[3] and LocalPlayer():IsSuperAdmin()) then + local text = "nz_chatcommand ".. cmdText + if !table.HasValue(tbl, text) then + table.insert(tbl, text) + end + end + end + end + + return tbl + end + concommand.Add("nz_chatcommand", nz_chatcommand, nz_chatcommand_autocomplete, "Executes a chatcommand without the use of chat, in case chatcommands don't work.") +end + +function nzChatCommand.splitCommand(command) + local spat, epat, buf, quoted = [=[^(['"])]=], [=[(['"])$]=] + local result = {} + for str in string.gmatch(command, "%S+") do + local squoted = str:match(spat) + local equoted = str:match(epat) + local escaped = str:match([=[(\*)['"]$]=]) + if squoted and not quoted and not equoted then + buf, quoted = str, squoted + elseif buf and equoted == quoted and #escaped % 2 == 0 then + str, buf, quoted = buf .. ' ' .. str, nil, nil + elseif buf then + buf = buf .. ' ' .. str + end + if not buf then table.insert(result, (str:gsub(spat,""):gsub(epat,""))) end + end + if buf then return nil end + return result +end diff --git a/gamemodes/nzombies/gamemode/chatcommand/sh_player.lua b/gamemodes/nzombies/gamemode/chatcommand/sh_player.lua new file mode 100644 index 00000000..3ab16095 --- /dev/null +++ b/gamemodes/nzombies/gamemode/chatcommand/sh_player.lua @@ -0,0 +1,10 @@ +function player.GetByName(name) + name = string.lower(name) + for _,v in ipairs(player.GetHumans()) do + if string.find(string.lower(v:Nick()), name, 1, true) != nil then + return v + end + end + + return nil +end diff --git a/nzombies3/gamemode/cl_init.lua b/gamemodes/nzombies/gamemode/cl_init.lua similarity index 100% rename from nzombies3/gamemode/cl_init.lua rename to gamemodes/nzombies/gamemode/cl_init.lua diff --git a/gamemodes/nzombies/gamemode/class/sh_constructor.lua b/gamemodes/nzombies/gamemode/class/sh_constructor.lua new file mode 100644 index 00000000..65d80e54 --- /dev/null +++ b/gamemodes/nzombies/gamemode/class/sh_constructor.lua @@ -0,0 +1,262 @@ +-- class.lua +-- Compatible with Lua 5.1 (not 5.0). +-- +--[[ + Usage: + -- Define a class A + A = class( + -- First parameter to class function is a table with properties and + -- constructor method. Error if not specified or not a table + -- + { + -- Define our properties. These are the values each new instance will start out with. + -- + a = 0; + b = 0; + c = 0; + -- Implement a constructor that will get called once for each instance and create/set + -- property values. You are responsible for ensuring the first parameter is the self + -- parameter as it will be invoked with the instanceObj when a new instance is created. + -- Defining functions here is kind of ugly as you have to use table name = value syntax + -- See __tostring example below for a better looking way to do it. + -- + constructor = function (self, a, b, c) + -- For each parameter specified, overwrite default value, otherwise keep default value + -- + self.a = a or self.a + self.b = b or self.b + self.c = c or self.c + end + -- Define any further class methods here. Again, you are responsible + -- for making sure the first parameter is the self parameter and calling + -- the method with the : syntax (e.g. instanceObj:method) so that Lua will + -- pass instanceObj as the first parameter to the method. + }, + -- Second parameter is an optional (non-nil) table that defines + -- static member variables. Error if specified and not a table. + -- + { + __class__name = "A" + }, + -- Third parameter is an optional (non-nil) table that defines + -- the base class. If present, this class will inherit, via copy, + -- the base classes properties and methods. Error if specified + -- and not a table created by the the class function + -- + nil + ) + -- Add a new property d to the class definition before we create any instances + -- + A.d = 0 + -- Implement a tostring method to return string representation of instance + -- Using classname: syntax allows a more natural definition and eliminates the + -- need to explicitly specify the self parameter + -- + function A:__tostring() + return "A: " .. self.a .. " B: " .. self.b .. " C: " .. self.c .. " D: " .. self.d + end + -- Implement a method to do a random calculation on the instance property values. + -- + function A:Step(amount) + self.a = self.b + (self.c * amount); + end + -- Create an instance of class A + test = A(1,2,3); + -- Display its value + print("test.tostring: " .. test.tostring(); + -- Call Step method to do a random calculation + test.Step(10); + -- Display its value to see what changed. + print("test.tostring: " .. test.tostring(); +]]-- + +function nzClass(def, statics, base) + -- Error if def argument missing or is not a table + if not def or type(def) ~= 'table' then error("class definition missing or not a table") end + + -- Error if statics argument is not nil and not a table + if statics and type(statics) ~= 'table' then error("statics parameter specified but not a table") end + + -- Error if base argument not nil and not a table created by this function. + if base and (type(base) ~= 'table' or not isclass(base)) then error("base parameter specified but not a table created by class function") end + + -- Start with a table for this class. This will be the metatable for + -- all instances of this class and where all class methods and static properties + -- will be kept. Initially it has two slots, __class__ == true to indicate this + -- table represents a class created by this function and __base__, which if not + -- nil is a reference to a base class created by this function + -- + local c = {__base__ = base} + c.__class__ = c + + -- Local function that will be used to create an instance of the class + -- when the class is called + -- + local function create(class_tbl, ...) + -- Create an instance initialized with per instance properties + -- + local instanceObj = {} + + -- Shallow copy of any class instance property initializers into our copy + -- + for i,v in pairs(c.__initprops__) do + instanceObj[i] = v + end + + -- __index for each instance is the class object + -- + setmetatable(instanceObj, { __index = c }) + + -- If constructor key is not nil then it is this class's constructor + -- so call it with our arguments + -- + if instanceObj.constructor then + instanceObj:constructor(...) + end + + -- Return new instance of the class + -- + return instanceObj + end + + + -- Create a metatable for the class whose __index field is just the class + -- This will be the metatable for each new instance of this class created. + -- + local c_mt = { __call = create} + if base then + -- Redirect class metatable __index slot to base class if specified + -- + c_mt.__index = base + end + + -- If statics is specified, shallow copy of non-function slots to our class + -- + if statics then + for i,v in pairs(statics) do + if type(v) ~= 'function' then + -- Ignore functions in statics table as we only support + -- static properties. + -- + c[i] = v + else + -- Error if this happens? + error("function definitions not supported in statics table") + end + end + end + + -- Table for instance property initial values + -- + c.__initprops__ = {} + + -- Copy base class slots first if any so they will get overlayed + -- by class slots of the same key + -- + if base then + -- Copy instance property initializers from base class + -- + for i,v in pairs(base.__initprops__) do + c.__initprops__[i] = v + end + end + + -- Now copy slots from the definition passed in. For functions, + -- store shallow copy to our class table. For anything not a + -- function slot, shallow copy to c.__initprops__ table for use + -- when a new object of this class is instantiated. + -- + for i,v in pairs(def) do + if type(v) ~= 'function' then + c.__initprops__[i] = v + else + c[i] = v + end + end + + -- Define an__instanceof__ method to determine if an instance. + -- was derived from the passed class. Used to emulate Squirrel + -- instanceof binary operator + -- + c.__instanceof__ = function(instanceObj, classObj) + local c = getclass(instanceObj) + while c do + if c == classObj then return true end + c = c.__base__ + end + return false + end + + -- Define an __getclass__ method to emulate Squirrel 3 object.getclass() + -- + c.__getclass__ =function(instanceObj) + -- class object is __class__ slot of instance object's metatable + -- + local classObj = getmetatable(instanceObj).__index + + -- Sanity check the metatable is really a class object + -- we created. If so return it otherwise nil + -- + if isclass(classObj) then + return classObj + else + return nil + end + end + + -- Define a __getbase__ method to emulate Squirrel 3 object.getbase() + -- method. + -- + c.__getbase__ = function(classObj) + -- Sanity check the metatable is really a class object + -- we created. If so return it's __base__ property + -- otherwise nil + -- + if isclass(classObj) then + -- base class, if any, is stored in class __base__ slot + -- + return classObj.__base__ + else + return nil + end + end + + setmetatable(c, c_mt) + return c +end + +--[[ Disabled as it wasn't being used. Will be uncommented when and if they find a use + +-- Implement Squirrel instanceof binary operator +-- +function instanceof(instanceObj, classObj) + c = rawget(getmetatable(instanceObj) or {}, "__index") + h = rawget(c or {}, "__instanceof__") + return h and h(instanceObj, classObj) or nil +end + + +-- Implement Squirrel getclass function +-- +function getclass(instanceObj) + c = rawget(getmetatable(instanceObj) or {}, "__index") + h = rawget(c or {}, "__getclass__") + return h and h(instanceObj) or nil +end + + +-- Implement Squirrel getbase function +-- +function getbase(instanceObj) + c = isclass(instanceObj) and instanceObj or rawget(getmetatable(instanceObj) or {}, "__index") + h = rawget(c or {}, "__getbase__") + return h and h(c) or nil +end + + +-- Implement isclass function +-- +function isclass(classObj) + return classObj and classObj.__class__ == classObj +end +]] \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/config/sh_constructor.lua b/gamemodes/nzombies/gamemode/config/sh_constructor.lua new file mode 100644 index 00000000..a830c902 --- /dev/null +++ b/gamemodes/nzombies/gamemode/config/sh_constructor.lua @@ -0,0 +1,228 @@ +-- Main Tables +nzConfig = nzConfig or AddNZModule("Config") + +-- Defaults + +if not ConVarExists("nz_randombox_whitelist") then CreateConVar("nz_randombox_whitelist", 1, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE}) end +if not ConVarExists("nz_downtime") then CreateConVar("nz_downtime", 45, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_nav_grouptargeting") then CreateConVar("nz_nav_grouptargeting", 1, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_round_special_interval") then CreateConVar("nz_round_special_interval", 6, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_round_prep_time") then CreateConVar("nz_round_prep_time", 10, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_randombox_maplist") then CreateConVar("nz_randombox_maplist", 1, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_round_dropins_allow") then CreateConVar("nz_round_dropins_allow", 1, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_difficulty_zombie_amount_base") then CreateConVar("nz_difficulty_zombie_amount_base", 6, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_difficulty_zombie_amount_scale") then CreateConVar("nz_difficulty_zombie_amount_scale", 0.35, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_difficulty_zombie_health_base") then CreateConVar("nz_difficulty_zombie_health_base", 75, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_difficulty_zombie_health_scale") then CreateConVar("nz_difficulty_zombie_health_scale", 1.1, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_difficulty_max_zombies_alive") then CreateConVar("nz_difficulty_max_zombies_alive", 35, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_difficulty_barricade_planks_max") then CreateConVar("nz_difficulty_barricade_planks_max", 6, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_difficulty_powerup_chance") then CreateConVar("nz_difficulty_powerup_chance", 2, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_difficulty_perks_max") then CreateConVar("nz_difficulty_perks_max", 4, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_point_notification_clientside") then CreateConVar("nz_point_notification_clientside", 0, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_REPLICATED}) end +if not ConVarExists("nz_zombie_lagcompensated") then CreateConVar("nz_zombie_lagcompensated", 1, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE}) end +if not ConVarExists("nz_spawnpoint_update_rate") then CreateConVar("nz_spawnpoint_update_rate", 4, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE}) end +if not ConVarExists("nz_rtv_time") then CreateConVar("nz_rtv_time", 45, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE}) end +if not ConVarExists("nz_rtv_enabled") then CreateConVar("nz_rtv_enabled", 0, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE}) end + +-- Zombie table - Moved to shared area for client collision prediction (barricades) +nzConfig.ValidEnemies = { + ["nz_zombie_walker"] = { + -- Set to false to disable the spawning of this zombie + Valid = true, + -- Allow you to scale damage on a per-hitgroup basis + ScaleDMG = function(zombie, hitgroup, dmginfo) + -- Headshots for double damage + if hitgroup == HITGROUP_HEAD then dmginfo:ScaleDamage(2) end + end, + -- Function runs whenever the zombie is damaged (NOT when killed) + OnHit = function(zombie, dmginfo, hitgroup) + local attacker = dmginfo:GetAttacker() + -- If player is playing and is not downed, give points + if attacker:IsPlayer() and attacker:GetNotDowned() then + attacker:GivePoints(10) + end + end, + -- Function is run whenever the zombie is killed + OnKilled = function(zombie, dmginfo, hitgroup) + local attacker = dmginfo:GetAttacker() + if attacker:IsPlayer() and attacker:GetNotDowned() then + if dmginfo:GetDamageType() == DMG_CLUB then + attacker:GivePoints(130) + elseif hitgroup == HITGROUP_HEAD then + attacker:GivePoints(100) + else + attacker:GivePoints(50) + end + end + end + }, + ["nz_zombie_special_burning"] = { + Valid = true, + ScaleDMG = function(zombie, hitgroup, dmginfo) + if hitgroup == HITGROUP_HEAD then dmginfo:ScaleDamage(2) end + end, + OnHit = function(zombie, dmginfo, hitgroup) + local attacker = dmginfo:GetAttacker() + if attacker:IsPlayer() and attacker:GetNotDowned() then + attacker:GivePoints(10) + end + end, + OnKilled = function(zombie, dmginfo, hitgroup) + local attacker = dmginfo:GetAttacker() + if attacker:IsPlayer() and attacker:GetNotDowned() then + if dmginfo:GetDamageType() == DMG_CLUB then + attacker:GivePoints(130) + elseif hitgroup == HITGROUP_HEAD then + attacker:GivePoints(100) + else + attacker:GivePoints(50) + end + end + end + }, + ["nz_zombie_special_dog"] = { + Valid = true, + SpecialSpawn = true, + ScaleDMG = function(zombie, hitgroup, dmginfo) + if hitgroup == HITGROUP_HEAD then dmginfo:ScaleDamage(2) end + end, + OnHit = function(zombie, dmginfo, hitgroup) + local attacker = dmginfo:GetAttacker() + if attacker:IsPlayer() and attacker:GetNotDowned() then + attacker:GivePoints(10) + end + end, + OnKilled = function(zombie, dmginfo, hitgroup) + local attacker = dmginfo:GetAttacker() + if attacker:IsPlayer() and attacker:GetNotDowned() then + if dmginfo:GetDamageType() == DMG_CLUB then + attacker:GivePoints(130) + elseif hitgroup == HITGROUP_HEAD then + attacker:GivePoints(100) + else + attacker:GivePoints(50) + end + end + end + }, +} + +-- Random Box + +nzConfig.WeaponBlackList = {} +function nzConfig.AddWeaponToBlacklist( class, remove ) + nzConfig.WeaponBlackList[class] = remove and nil or true +end + +nzConfig.AddWeaponToBlacklist( "weapon_base" ) +nzConfig.AddWeaponToBlacklist( "weapon_fists" ) +nzConfig.AddWeaponToBlacklist( "weapon_flechettegun" ) +nzConfig.AddWeaponToBlacklist( "weapon_medkit" ) +nzConfig.AddWeaponToBlacklist( "weapon_dod_sim_base" ) +nzConfig.AddWeaponToBlacklist( "weapon_dod_sim_base_shot" ) +nzConfig.AddWeaponToBlacklist( "weapon_dod_sim_base_snip" ) +nzConfig.AddWeaponToBlacklist( "weapon_sim_admin" ) +nzConfig.AddWeaponToBlacklist( "weapon_sim_spade" ) +nzConfig.AddWeaponToBlacklist( "fas2_base" ) +nzConfig.AddWeaponToBlacklist( "fas2_ammobox" ) +nzConfig.AddWeaponToBlacklist( "fas2_ifak" ) +nzConfig.AddWeaponToBlacklist( "nz_multi_tool" ) +nzConfig.AddWeaponToBlacklist( "nz_grenade" ) +nzConfig.AddWeaponToBlacklist( "nz_perk_bottle" ) +nzConfig.AddWeaponToBlacklist( "nz_quickknife_crowbar" ) +nzConfig.AddWeaponToBlacklist( "nz_tool_base" ) +nzConfig.AddWeaponToBlacklist( "nz_one_inch_punch" ) -- Nope! You gotta give this with special map scripts + +nzConfig.AddWeaponToBlacklist( "cw_base" ) + +nzConfig.WeaponWhiteList = { + "fas2_", "m9k_", "cw_", +} + +if SERVER then + + nzConfig.RoundData = {} + --nzConfig.RoundData[1] = {["nz_zombie_walker"] = 100} + + --[[ + -- EXAMPLE of a round zombie config: + nzConfig.RoundData[ROUNDNUMBER] = { + -- define normal zombies and theri spawn chances + normalTypes = { + ["nz_zombie_walker"] = { + chance = 100, + }, + }, + -- (optional) how many normal zombies will spawn this wil overwrite the default curves + normalCount = 50, + + -- (optional) modify teh count witha function ratehr than a fixed amount + -- if both normalCount and normalCountMod are set the gamemode will ignore normalCount + normalCountMod = function(original) return orignal / 2 end, + + -- (optional) spawn delay + -- this will spawn the zombies in a 3 second intervall + normalDelay = 3, + + -- special zombies (different spawnpoint usually in front of barricades) + -- this will spawn 10 hellhounds in additon to the normal zombies + specialTypes = { + ["nz_zombie_special_dog"] = { + chance = 100, + }, + + }, + -- (optional) not required but recommended if this is not set teh zombie amount will be doubled + specialCount = 10 + -- (optional) flag this round as special (this will trigger fog etc.) + special = true + } + ]]-- + + nzConfig.RoundData[1] = { + normalTypes = { + ["nz_zombie_walker"] = { + chance = 100, + }, + }, + } + nzConfig.RoundData[2] = { + normalTypes = { + ["nz_zombie_walker"] = { + chance = 100, + }, + }, + } + nzConfig.RoundData[13] = { + normalTypes = { + ["nz_zombie_walker"] = { + chance = 75, + }, + ["nz_zombie_special_burning"] = { + chance = 25, + }, + }, + } + nzConfig.RoundData[14] = { + normalTypes = { + ["nz_zombie_walker"] = { + chance = 100, + }, + }, + } + nzConfig.RoundData[23] = { + normalTypes = { + ["nz_zombie_walker"] = { + chance = 90, + }, + ["nz_zombie_special_burning"] = { + chance = 10, + }, + }, + } + + -- Player Class + nzConfig.BaseStartingWeapons = {"fas2_glock20"} -- "fas2_p226", "fas2_ots33", "fas2_glock20" "weapon_pistol" + -- nzConfig.CustomConfigStartingWeps = true -- If this is set to false, the gamemode will avoid using custom weapons in configs + +end diff --git a/gamemodes/nzombies/gamemode/curves/sh_constructor.lua b/gamemodes/nzombies/gamemode/curves/sh_constructor.lua new file mode 100644 index 00000000..5e687f43 --- /dev/null +++ b/gamemodes/nzombies/gamemode/curves/sh_constructor.lua @@ -0,0 +1,42 @@ +if SERVER then + -- Main Tables + nzCurves = nzCurves or AddNZModule("Curves") + + function nzCurves.GenerateHealthCurve(round) + local base = GetConVar("nz_difficulty_zombie_health_base"):GetFloat() + local scale = GetConVar("nz_difficulty_zombie_health_scale"):GetFloat() + + return math.Round(base*math.pow(scale,round - 1)) + end + + function nzCurves.GenerateMaxZombies(round) + local base = GetConVar("nz_difficulty_zombie_amount_base"):GetInt() + local scale = GetConVar("nz_difficulty_zombie_amount_scale"):GetFloat() + + return math.Round((base + (scale * (#player.GetAllPlaying() - 1))) * round) + end + + function nzCurves.GenerateSpeedTable(round) + if !round then return {[50] = 100} end -- Default speed for any invalid round (Say, creative mode test zombies) + local tbl = {} + local range = 3 -- The range on either side of the tip (current round) of speeds in steps of "steps" + local min = 30 -- Minimum speed (Round 1) + local max = 300 -- Maximum speed + local maxround = 27 -- The round at which the 300 speed has its tip + local steps = ((max-min)/maxround) -- The different speed steps speed can exist in + + print("Generating round speeds with steps of "..steps.."...") + for i = -range, range do + local speed = (min - steps + steps*round) + (steps*i) + if speed >= min and speed <= max then + local chance = 100 - 10*math.abs(i)^2 + --print("Speed is "..speed..", with a chance of "..chance) + tbl[speed] = chance + elseif speed >= max then + tbl[max] = 100 + end + end + return tbl + end + +end diff --git a/gamemodes/nzombies/gamemode/debugging/sh_constructor.lua b/gamemodes/nzombies/gamemode/debugging/sh_constructor.lua new file mode 100644 index 00000000..b78ac46d --- /dev/null +++ b/gamemodes/nzombies/gamemode/debugging/sh_constructor.lua @@ -0,0 +1,23 @@ +NZ_DEBUG_LOGLEVEL_MAX = 3 +NZ_DEBUG_LOGLEVEL_INFO = 2 +NZ_DEBUG_LOGLEVEL_ERROR = 1 + +CreateConVar("nz_log_level", "0", FCVAR_ARCHIVE, "The nz log level.") + +-- Usage: Provide a loglevel and a comma seperated list of values +function DebugPrint(logLevel, ...) + local requiredLvl = GetConVar("nz_log_level"):GetInt() or 0 + if requiredLvl >= logLevel then + local arg = {...} + local result = "" + for i=1, #arg do + if istable(arg[i]) then + PrintTable(arg[i]) + else + result = result .. tostring(arg[i]) .. "\t" + end + end + print(result) + end + +end diff --git a/gamemodes/nzombies/gamemode/display/cl_contextmenu.lua b/gamemodes/nzombies/gamemode/display/cl_contextmenu.lua new file mode 100644 index 00000000..183e29cc --- /dev/null +++ b/gamemodes/nzombies/gamemode/display/cl_contextmenu.lua @@ -0,0 +1,234 @@ + +local PANEL = {} + +AccessorFunc( PANEL, "m_bHangOpen", "HangOpen" ) + +function PANEL:Init() + + -- + -- This makes it so that when you're hovering over this panel + -- you can `click` on the world. Your viewmodel will aim etc. + -- + self:SetWorldClicker( true ) + + self.Canvas = vgui.Create( "DCategoryList", self ) + self.m_bHangOpen = false + + --self.Canvas:EnableVerticalScrollbar( true ) + --self.Canvas:SetSpacing( 0 ) + --self.Canvas:SetPadding( 5 ) + --self.Canvas:SetDrawBackground( false ) + +end + + +function PANEL:Open() + + self:SetHangOpen( false ) + + if ( self:IsVisible() ) then return end + + CloseDermaMenus() + + self:MakePopup() + self:SetVisible( true ) + self:SetKeyboardInputEnabled( false ) + self:SetMouseInputEnabled( true ) + + RestoreCursorPosition() + + local bShouldShow = true; + + -- TODO: Any situation in which we shouldn't show the tool menu on the context menu? + + -- Set up the active panel.. + + self.Canvas:SetVisible( false ) + + self:InvalidateLayout( true ) + +end + + +function PANEL:Close( bSkipAnim ) + + if ( self:GetHangOpen() ) then + self:SetHangOpen( false ) + return + end + + RememberCursorPosition() + + CloseDermaMenus() + + self:SetKeyboardInputEnabled( false ) + self:SetMouseInputEnabled( false ) + + self:SetAlpha( 255 ) + self:SetVisible( false ) + self:RestoreControlPanel() + +end + + +function PANEL:PerformLayout() + + self:SetPos( 0, 0 ) + self:SetSize( ScrW(), ScrH() ) + + self.Canvas:SetWide( 311 ) + self.Canvas:SetPos( ScrW() - self.Canvas:GetWide() - 50, self.y ) + + self.Canvas:InvalidateLayout( true ) + +end + + +function PANEL:StartKeyFocus( pPanel ) + + self:SetKeyboardInputEnabled( true ) + self:SetHangOpen( true ) + +end + + +function PANEL:EndKeyFocus( pPanel ) + + self:SetKeyboardInputEnabled( false ) + +end + + +function PANEL:RestoreControlPanel() + +end + +-- +-- Note here: EditablePanel is important! Child panels won't be able to get +-- keyboard input if it's a DPanel or a Panel. You need to either have an EditablePanel +-- or a DFrame (which is derived from EditablePanel) as your first panel attached to the system. +-- +vgui.Register( "ContextMenu", PANEL, "EditablePanel" ) + + +function CreateContextMenu() + + if ( IsValid( g_ContextMenu ) ) then + g_ContextMenu:Remove() + g_ContextMenu = nil + end + + g_ContextMenu = vgui.Create( "ContextMenu" ) + g_ContextMenu:SetVisible( false ) + + menubar.Init() + -- + -- We're blocking clicks to the world - but we don't want to + -- so feed clicks to the proper functions.. + -- + g_ContextMenu.OnMousePressed = function( p, code ) + hook.Run( "GUIMousePressed", code, gui.ScreenToVector( gui.MousePos() ) ) + end + g_ContextMenu.OnMouseReleased = function( p, code ) + hook.Run( "GUIMouseReleased", code, gui.ScreenToVector( gui.MousePos() ) ) + end + + hook.Run( "ContextMenuCreated", g_ContextMenu ) + + + local IconLayout = g_ContextMenu:Add( "DIconLayout" ) + IconLayout:Dock( LEFT ) + IconLayout:SetWorldClicker( true ) + IconLayout:SetBorder( 8 ) + IconLayout:SetSpaceX( 8 ) + IconLayout:SetSpaceY( 8 ) + IconLayout:SetWide( 200 ) + IconLayout:SetLayoutDir( LEFT ) + + for k, v in pairs( list.Get( "DesktopWindows" ) ) do + + local icon = IconLayout:Add( "DButton" ) + icon:SetText( "" ) + icon:SetSize( 80, 82 ) + icon.Paint = function()end + + local label = icon:Add( "DLabel" ) + label:Dock( BOTTOM ) + label:SetText( v.title ) + label:SetContentAlignment( 5 ) + label:SetTextColor( Color( 255, 255, 255, 255 ) ) + label:SetExpensiveShadow( 1, Color( 0, 0, 0, 200 ) ) + + local image = icon:Add( "DImage" ) + image:SetImage( v.icon ) + image:SetSize( 64, 64 ) + image:Dock( TOP ) + image:DockMargin( 8, 0, 8, 0 ) + + icon.DoClick = function() + + -- + -- v might have changed using autorefresh so grab it again + -- + local newv = list.Get( "DesktopWindows" )[ k ] + + if ( v.onewindow ) then + if ( IsValid( icon.Window ) ) then icon.Window:Center() return end + end + + -- Make the window + icon.Window = g_ContextMenu:Add( "DFrame" ) + icon.Window:SetSize( newv.width, newv.height ) + icon.Window:SetTitle( newv.title ) + icon.Window:Center() + + newv.init( icon, icon.Window ) + + end + + end + +end + + +function GM:OnContextMenuOpen() + -- Let the gamemode decide whether we should open or not.. + --if ( !hook.Call( "ContextMenuOpen", GAMEMODE ) ) then return end + + if ( IsValid( g_ContextMenu ) && !g_ContextMenu:IsVisible() ) then + g_ContextMenu:Open() + menubar.ParentTo( g_ContextMenu ) + else + CreateContextMenu() + g_ContextMenu:Open() + menubar.ParentTo( g_ContextMenu ) + end + +end + + +function GM:OnContextMenuClose() + + if ( IsValid( g_ContextMenu ) ) then + g_ContextMenu:Close() + end + +end + +local function SpawnMenuKeyboardFocusOn( pnl ) + + if ( IsValid( g_ContextMenu ) && IsValid( pnl ) && pnl:HasParent( g_ContextMenu ) ) then + g_ContextMenu:StartKeyFocus( pnl ) + end + +end +hook.Add( "OnTextEntryGetFocus", "SpawnMenuKeyboardFocusOn", SpawnMenuKeyboardFocusOn ) + +local function SpawnMenuKeyboardFocusOff( pnl ) + + if ( IsValid( g_ContextMenu ) && IsValid( pnl ) && pnl:HasParent( g_ContextMenu ) ) then + g_ContextMenu:EndKeyFocus( pnl ) + end + +end +hook.Add( "OnTextEntryLoseFocus", "SpawnMenuKeyboardFocusOff", SpawnMenuKeyboardFocusOff ) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/display/cl_fonts.lua b/gamemodes/nzombies/gamemode/display/cl_fonts.lua new file mode 100644 index 00000000..f2016e3b --- /dev/null +++ b/gamemodes/nzombies/gamemode/display/cl_fonts.lua @@ -0,0 +1,95 @@ +//Main Text +surface.CreateFont( "nz.display.hud.main", { + font = "DK Umbilical Noose", //Avenir Next + size = 48, + weight = 300, + antialias = true, +} ) + +surface.CreateFont( "nz.display.hud.small", { + font = "DK Umbilical Noose", //Avenir Next + size = 28, + weight = 300, + antialias = true, +} ) + +surface.CreateFont( "nz.display.hud.medium", { + font = "DK Umbilical Noose", //Avenir Next + size = 36, + weight = 300, + antialias = true, +} ) + +surface.CreateFont( "nz.display.hud.points", { + font = "Default", + size = 20, + weight = 5000, + antialias = true, +} ) + +surface.CreateFont( "nz.display.hud.ammo", { + font = "Calibri", + size = 60, + weight = 50, + antialias = true, +} ) + +surface.CreateFont( "nz.display.hud.ammo2", { + font = "Calibri", + size = 40, + weight = 50, + antialias = true, +} ) + +surface.CreateFont( "nz.display.hud.ammo3", { + font = "Calibri", + size = 20, + weight = 50, + antialias = true, +} ) + +surface.CreateFont( "nz.display.hud.ammo4", { + font = "Calibri", + size = 15, + weight = 50, + antialias = true, +} ) + +surface.CreateFont( "nz.display.hud.smaller", { + font = "DK Umbilical Noose", //Avenir Next + size = 18, + weight = 300, + antialias = true, +} ) + +surface.CreateFont( "nz.display.hud.rounds", { + font = "DK Umbilical Noose", //Avenir Next + size = 400, + weight = 30, + antialias = true, +} ) + +-- Rotated text function, as taken from the gmod wiki +local matscale = Vector(1,1,1) +function draw.TextRotatedScaled( text, x, y, color, font, ang, scaleX, scaleY ) + render.PushFilterMag( TEXFILTER.ANISOTROPIC ) + render.PushFilterMin( TEXFILTER.ANISOTROPIC ) + surface.SetFont( font ) + surface.SetTextColor( color ) + surface.SetTextPos( 0, 0 ) + local textWidth, textHeight = surface.GetTextSize( text ) + local rad = -math.rad( ang ) + x = x - ( math.cos( rad ) * textWidth / 2 + math.sin( rad ) * textHeight / 2 ) + y = y + ( math.sin( rad ) * textWidth / 2 + math.cos( rad ) * textHeight / 2 ) + local m = Matrix() + m:SetAngles( Angle( 0, ang, 0 ) ) + m:SetTranslation( Vector( x, y, 0 ) ) + matscale.x = scaleX + matscale.y = scaleY + m:Scale(matscale) + cam.PushModelMatrix( m ) + surface.DrawText( text ) + cam.PopModelMatrix() + render.PopFilterMag() + render.PopFilterMin() +end diff --git a/gamemodes/nzombies/gamemode/display/cl_gamemodehooks.lua b/gamemodes/nzombies/gamemode/display/cl_gamemodehooks.lua new file mode 100644 index 00000000..b2485fe4 --- /dev/null +++ b/gamemodes/nzombies/gamemode/display/cl_gamemodehooks.lua @@ -0,0 +1,17 @@ +function GM:ContextMenuOpen() + return nzRound:InState( ROUND_CREATE ) and LocalPlayer():IsAdmin() +end + +function GM:PopulateMenuBar(panel) + panel:Remove() + return false +end + +function GM:OnUndo( name, strCustomString ) + if ( !strCustomString ) then + notification.AddLegacy( "Undone "..name, NOTIFY_UNDO, 2 ) + else + notification.AddLegacy( strCustomString, NOTIFY_UNDO, 2 ) + end + surface.PlaySound( "buttons/button15.wav" ) +end diff --git a/gamemodes/nzombies/gamemode/display/cl_hud.lua b/gamemodes/nzombies/gamemode/display/cl_hud.lua new file mode 100644 index 00000000..57b0c592 --- /dev/null +++ b/gamemodes/nzombies/gamemode/display/cl_hud.lua @@ -0,0 +1,577 @@ +-- +nzDisplay = nzDisplay or AddNZModule("Display") + +local bloodline_points = Material("bloodline_score2.png", "unlitgeneric smooth") +local bloodline_gun = Material("cod_hud.png", "unlitgeneric smooth") + +--[[local bloodDecals = { + Material("decals/blood1"), + Material("decals/blood2"), + Material("decals/blood3"), + Material("decals/blood4"), + Material("decals/blood5"), + Material("decals/blood6"), + Material("decals/blood7"), + Material("decals/blood8"), + nil +}]] + +CreateClientConVar( "nz_hud_points_show_names", "1", true, false ) + +local function StatesHud() + if GetConVar("cl_drawhud"):GetBool() then + local text = "" + local font = "nz.display.hud.main" + local w = ScrW() / 2 + if nzRound:InState( ROUND_WAITING ) then + text = "Waiting for players. Type /ready to ready up." + font = "nz.display.hud.small" + elseif nzRound:InState( ROUND_CREATE ) then + text = "Creative Mode" + elseif nzRound:InState( ROUND_GO ) then + text = "Game Over" + end + draw.SimpleText(text, font, w, ScrH() * 0.85, Color(200, 0, 0,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + end +end + +local tbl = {Entity(3), Entity(1), Entity(3), Entity(4), Entity(5),} + +local function ScoreHud() + if GetConVar("cl_drawhud"):GetBool() then + if nzRound:InProgress() then + + local scale = (ScrW() / 1920 + 1) / 2 + local offset = 0 + + for k,v in pairs(player.GetAll()) do + local hp = v:Health() + if hp == 0 then hp = "Dead" elseif nzRevive.Players[v:EntIndex()] then hp = "Downed" else hp = hp .. " HP" end + if v:GetPoints() >= 0 then + + local text = "" + local nameoffset = 0 + if GetConVar("nz_hud_points_show_names"):GetBool() then + local nick + if #v:Nick() >= 20 then + nick = string.sub(v:Nick(), 1, 20) -- limit name to 20 chars + else + nick = v:Nick() + end + text = nick + nameoffset = 10 + end + + local font = "nz.display.hud.small" + + surface.SetFont(font) + + local textW, textH = surface.GetTextSize(text) + + if LocalPlayer() == v then + offset = offset + textH + 5 -- change this if you change the size of nz.display.hud.medium + else + offset = offset + textH + end + + surface.SetDrawColor(200,200,200) + local index = v:EntIndex() + local color = player.GetColorByIndex(v:EntIndex()) + local blood = player.GetBloodByIndex(v:EntIndex()) + --for i = 0, 8 do + --surface.SetMaterial(bloodDecals[((index + i - 1) % #bloodDecals) + 1 ]) + surface.SetMaterial(blood) + surface.DrawTexturedRect(ScrW() - textW - 180, ScrH() - 275 * scale - offset, textW + 150, 45) + --end + --surface.DrawTexturedRect(ScrW() - 325*scale - numname * 10, ScrH() - 285*scale - (30*k), 250 + numname*10, 35) + if text then draw.SimpleText(text, font, ScrW() - textW - 60, ScrH() - 255 * scale - offset, color, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER) end + if LocalPlayer() == v then + font = "nz.display.hud.medium" + end + draw.SimpleText(v:GetPoints(), font, ScrW() - textW - 60 - nameoffset, ScrH() - 255 * scale - offset, color, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER) + v.PointsSpawnPosition = {x = ScrW() - textW - 170, y = ScrH() - 255 * scale - offset} + end + end + end + end +end + +local function GunHud() + if GetConVar("cl_drawhud"):GetBool() then + if !LocalPlayer():IsNZMenuOpen() then + local wep = LocalPlayer():GetActiveWeapon() + local w,h = ScrW(), ScrH() + local scale = ((w/1920)+1)/2 + + surface.SetMaterial(bloodline_gun) + surface.SetDrawColor(200,200,200) + surface.DrawTexturedRect(w - 630*scale, h - 225*scale, 600*scale, 225*scale) + if IsValid(wep) then + if wep:GetClass() == "nz_multi_tool" then + draw.SimpleTextOutlined(nzTools.ToolData[wep.ToolMode].displayname or wep.ToolMode, "nz.display.hud.small", w - 240*scale, h - 125*scale, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_BOTTOM, 2, color_black) + draw.SimpleTextOutlined(nzTools.ToolData[wep.ToolMode].desc or "", "nz.display.hud.smaller", w - 240*scale, h - 90*scale, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP, 2, color_black) + else + local name = wep:GetPrintName() + local x = 250 + local y = 165 + if wep:GetPrimaryAmmoType() != -1 then + local clip + if wep.Primary.ClipSize and wep.Primary.ClipSize != -1 then + draw.SimpleTextOutlined("/"..wep:Ammo1(), "nz.display.hud.ammo2", ScrW() - 310*scale, ScrH() - 120*scale, color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_BOTTOM, 2, color_black) + clip = wep:Clip1() + x = 315 + y = 155 + else + clip = wep:Ammo1() + end + draw.SimpleTextOutlined(clip, "nz.display.hud.ammo", ScrW() - x*scale, ScrH() - 115*scale, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_BOTTOM, 2, color_black) + x = x + 80 + end + + draw.SimpleTextOutlined(name, "nz.display.hud.small", ScrW() - x*scale, ScrH() - 120*scale, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_BOTTOM, 2, color_black) + + x = 270 + if wep:GetSecondaryAmmoType() != -1 then + local clip + if wep.Secondary.ClipSize and wep.Secondary.ClipSize != -1 then + draw.SimpleTextOutlined("/"..wep:Ammo2(), "nz.display.hud.ammo4", ScrW() - x*scale, ScrH() - y*scale, color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_BOTTOM, 2, color_black) + clip = wep:Clip2() + x = x + 3 + else + clip = wep:Ammo2() + end + draw.SimpleTextOutlined(clip, "nz.display.hud.ammo3", ScrW() - x*scale, ScrH() - y*scale, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_BOTTOM, 2, color_black) + x = x + 80 + end + + --[[if clip >= 0 then + draw.SimpleTextOutlined(name, "nz.display.hud.small", ScrW() - 390*scale, ScrH() - 120*scale, Color(255,255,255,255), TEXT_ALIGN_RIGHT, TEXT_ALIGN_BOTTOM, 2, Color(0,0,0)) + draw.SimpleTextOutlined(clip, "nz.display.hud.ammo", ScrW() - 315*scale, ScrH() - 115*scale, Color(255,255,255,255), TEXT_ALIGN_RIGHT, TEXT_ALIGN_BOTTOM, 2, Color(0,0,0)) + draw.SimpleTextOutlined("/"..wep:Ammo1(), "nz.display.hud.ammo2", ScrW() - 310*scale, ScrH() - 120*scale, Color(255,255,255,255), TEXT_ALIGN_LEFT, TEXT_ALIGN_BOTTOM, 2, Color(0,0,0)) + else + draw.SimpleTextOutlined(name, "nz.display.hud.small", ScrW() - 250*scale, ScrH() - 120*scale, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_BOTTOM, 2, color_black) + end]] + end + end + end + end +end + +local function PowerUpsHud() + if nzRound:InProgress() or nzRound:InState(ROUND_CREATE) then + local font = "nz.display.hud.main" + local w = ScrW() / 2 + local offset = 40 + local c = 0 + for k,v in pairs(nzPowerUps.ActivePowerUps) do + if nzPowerUps:IsPowerupActive(k) then + local powerupData = nzPowerUps:Get(k) + draw.SimpleText(powerupData.name .. " - " .. math.Round(v - CurTime()), font, w, ScrH() * 0.85 + offset * c, Color(255, 255, 255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + c = c + 1 + end + end + if !nzPowerUps.ActivePlayerPowerUps[LocalPlayer()] then nzPowerUps.ActivePlayerPowerUps[LocalPlayer()] = {} end + for k,v in pairs(nzPowerUps.ActivePlayerPowerUps[LocalPlayer()]) do + if nzPowerUps:IsPlayerPowerupActive(LocalPlayer(), k) then + local powerupData = nzPowerUps:Get(k) + draw.SimpleText(powerupData.name .. " - " .. math.Round(v - CurTime()), font, w, ScrH() * 0.85 + offset * c, Color(255, 255, 255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + c = c + 1 + end + end + end +end + +local Laser = Material( "cable/redlaser" ) +function nzDisplay.DrawLinks( ent, link ) + + local tbl = {} + -- Check for zombie spawns + for k, v in pairs(ents.GetAll()) do + if v:IsBuyableProp() then + if nzDoors.PropDoors[k] != nil then + if v.link == link then + table.insert(tbl, Entity(k)) + end + end + elseif v:IsDoor() then + if nzDoors.MapDoors[v:doorIndex()] != nil then + if nzDoors.MapDoors[v:doorIndex()].link == link then + table.insert(tbl, v) + end + end + elseif v:GetClass() == "nz_spawn_zombie_normal" then + if v:GetLink() == link then + table.insert(tbl, v) + end + end + end + + + -- Draw + if tbl[1] != nil then + for k,v in pairs(tbl) do + render.SetMaterial( Laser ) + render.DrawBeam( ent:GetPos(), v:GetPos(), 20, 1, 1, Color( 255, 255, 255, 255 ) ) + end + end +end + +local PointsNotifications = {} +local function PointsNotification(ply, amount) + if !IsValid(ply) then return end + local data = {ply = ply, amount = amount, diry = math.random(-20, 20), time = CurTime()} + table.insert(PointsNotifications, data) + --PrintTable(data) +end + +net.Receive("nz_points_notification", function() + local amount = net.ReadInt(20) + local ply = net.ReadEntity() + + PointsNotification(ply, amount) +end) + +local function DrawPointsNotification() + + if GetConVar("nz_point_notification_clientside"):GetBool() then + for k,v in pairs(player.GetAll()) do + if v:GetPoints() >= 0 then + if !v.LastPoints then v.LastPoints = 0 end + if v:GetPoints() != v.LastPoints then + PointsNotification(v, v:GetPoints() - v.LastPoints) + v.LastPoints = v:GetPoints() + end + end + end + end + + local font = "nz.display.hud.points" + + for k,v in pairs(PointsNotifications) do + local fade = math.Clamp((CurTime()-v.time), 0, 1) + if !v.ply.PointsSpawnPosition then return end + if v.amount >= 0 then + draw.SimpleText(v.amount, font, v.ply.PointsSpawnPosition.x - 50*fade, v.ply.PointsSpawnPosition.y + v.diry*fade, Color(255,255,0,255-255*fade), TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER) + else + draw.SimpleText(v.amount, font, v.ply.PointsSpawnPosition.x - 50*fade, v.ply.PointsSpawnPosition.y + v.diry*fade, Color(255,0,0,255-255*fade), TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER) + end + if fade >= 1 then + table.remove(PointsNotifications, k) + end + end +end + +-- Now handled via perks individual icon table entries +--[[local perk_icons = { + ["jugg"] = Material("perk_icons/jugg.png", "smooth unlitgeneric"), + ["speed"] = Material("perk_icons/speed.png", "smooth unlitgeneric"), + ["dtap"] = Material("perk_icons/dtap.png", "smooth unlitgeneric"), + ["revive"] = Material("perk_icons/revive.png", "smooth unlitgeneric"), + ["dtap2"] = Material("perk_icons/dtap2.png", "smooth unlitgeneric"), + ["staminup"] = Material("perk_icons/staminup.png", "smooth unlitgeneric"), + ["phd"] = Material("perk_icons/phd.png", "smooth unlitgeneric"), + ["deadshot"] = Material("perk_icons/deadshot.png", "smooth unlitgeneric"), + ["mulekick"] = Material("perk_icons/mulekick.png", "smooth unlitgeneric"), + ["cherry"] = Material("perk_icons/cherry.png", "smooth unlitgeneric"), + ["tombstone"] = Material("perk_icons/tombstone.png", "smooth unlitgeneric"), + ["whoswho"] = Material("perk_icons/whoswho.png", "smooth unlitgeneric"), + ["vulture"] = Material("perk_icons/vulture.png", "smooth unlitgeneric"), + + -- Only used to see PaP through walls with Vulture Aid + ["pap"] = Material("vulture_icons/pap.png", "smooth unlitgeneric"), +}]] + +local function PerksHud() + local scale = (ScrW()/1920 + 1)/2 + local w = -20 + local size = 50 + for k,v in pairs(LocalPlayer():GetPerks()) do + surface.SetMaterial(nzPerks:Get(v).icon) + surface.SetDrawColor(255,255,255) + surface.DrawTexturedRect(w + k*(size*scale + 10), ScrH() - 200, size*scale, size*scale) + end +end + +local vulture_textures = { + ["wall_buys"] = Material("vulture_icons/wall_buys.png", "smooth unlitgeneric"), + ["random_box"] = Material("vulture_icons/random_box.png", "smooth unlitgeneric"), + ["wunderfizz_machine"] = Material("vulture_icons/wunderfizz.png", "smooth unlitgeneric"), +} + +local function VultureVision() + if !LocalPlayer():HasPerk("vulture") then return end + local scale = (ScrW()/1920 + 1)/2 + + for k,v in pairs(ents.FindInSphere(LocalPlayer():GetPos(), 700)) do + local target = v:GetClass() + if vulture_textures[target] then + local data = v:WorldSpaceCenter():ToScreen() + if data.visible then + surface.SetMaterial(vulture_textures[target]) + surface.SetDrawColor(255,255,255,150) + surface.DrawTexturedRect(data.x - 15*scale, data.y - 15*scale, 30*scale, 30*scale) + end + elseif target == "perk_machine" then + local data = v:WorldSpaceCenter():ToScreen() + if data.visible then + local icon = nzPerks:Get(v:GetPerkID()).icon + if icon then + surface.SetMaterial(icon) + surface.SetDrawColor(255,255,255,150) + surface.DrawTexturedRect(data.x - 15*scale, data.y - 15*scale, 30*scale, 30*scale) + end + end + end + end +end + +local round_white = 0 +local round_alpha = 255 +local round_num = 0 +local infmat = Material("materials/round_-1.png", "smooth") +local function RoundHud() + + local text = "" + local font = "nz.display.hud.rounds" + local w = 70 + local h = ScrH() - 30 + local round = round_num + local col = Color(200 + round_white*55, round_white, round_white,round_alpha) + if round == -1 then + --text = "∞" + surface.SetMaterial(infmat) + surface.SetDrawColor(col.r,round_white,round_white,round_alpha) + surface.DrawTexturedRect(w - 25, h - 100, 200, 100) + return + elseif round < 11 then + for i = 1, round do + if i == 5 or i == 10 then + text = text.." " + else + text = text.."i" + end + end + if round >= 5 then + draw.TextRotatedScaled( "i", w + 100, h - 150, col, font, 60, 1, 1.7 ) + end + if round >= 10 then + draw.TextRotatedScaled( "i", w + 220, h - 150, col, font, 60, 1, 1.7 ) + end + else + text = round + end + draw.SimpleText(text, font, w, h, col, TEXT_ALIGN_LEFT, TEXT_ALIGN_BOTTOM) + +end + +local roundchangeending = false +local prevroundspecial = false +local function StartChangeRound() + + print(nzRound:GetNumber(), nzRound:IsSpecial()) + + local lastround = nzRound:GetNumber() + + if lastround >= 1 then + if prevroundspecial then + surface.PlaySound("nz/round/special_round_end.wav") + else + surface.PlaySound("nz/round/round_end.mp3") + end + elseif lastround == -2 then + surface.PlaySound("nz/round/round_-1_prepare.mp3") + else + round_num = 0 + end + + roundchangeending = false + round_white = 0 + local round_charger = 0.25 + local alphafading = false + local haschanged = false + hook.Add("HUDPaint", "nz_roundnumWhiteFade", function() + if !alphafading then + round_white = math.Approach(round_white, round_charger > 0 and 255 or 0, round_charger*350*FrameTime()) + if round_white >= 255 and !roundchangeending then + alphafading = true + round_charger = -1 + elseif round_white <= 0 and roundchangeending then + hook.Remove("HUDPaint", "nz_roundnumWhiteFade") + end + else + round_alpha = math.Approach(round_alpha, round_charger > 0 and 255 or 0, round_charger*350*FrameTime()) + if round_alpha >= 255 then + if haschanged then + round_charger = -0.25 + alphafading = false + else + round_charger = -1 + end + elseif round_alpha <= 0 then + if roundchangeending then + round_num = nzRound:GetNumber() + round_charger = 0.5 + if round_num == -1 then + --surface.PlaySound("nz/easteregg/motd_round-03.wav") + elseif nzRound:IsSpecial() then + surface.PlaySound("nz/round/special_round_start.wav") + prevroundspecial = true + else + surface.PlaySound("nz/round/round_start.mp3") + prevroundspecial = false + end + haschanged = true + else + round_charger = 1 + end + end + end + end) + +end + +local function EndChangeRound() + roundchangeending = true +end + +local grenade_icon = Material("grenade-256.png", "unlitgeneric smooth") +local function DrawGrenadeHud() + local num = LocalPlayer():GetAmmoCount(GetNZAmmoID("grenade") or -1) + local numspecial = LocalPlayer():GetAmmoCount(GetNZAmmoID("specialgrenade") or -1) + local scale = (ScrW()/1920 + 1)/2 + + --print(num) + if num > 0 then + surface.SetMaterial(grenade_icon) + surface.SetDrawColor(255,255,255) + for i = num, 1, -1 do + --print(i) + surface.DrawTexturedRect(ScrW() - 250*scale - i*10*scale, ScrH() - 90*scale, 30*scale, 30*scale) + end + end + if numspecial > 0 then + surface.SetMaterial(grenade_icon) + surface.SetDrawColor(255,100,100) + for i = numspecial, 1, -1 do + --print(i) + surface.DrawTexturedRect(ScrW() - 300*scale - i*10*scale, ScrH() - 90*scale, 30*scale, 30*scale) + end + end + --surface.DrawTexturedRect(ScrW()/2, ScrH()/2, 100, 100) +end + +-- Hooks +hook.Add("HUDPaint", "pointsNotifcationHUD", DrawPointsNotification ) +hook.Add("HUDPaint", "roundHUD", StatesHud ) +hook.Add("HUDPaint", "scoreHUD", ScoreHud ) +hook.Add("HUDPaint", "gunHUD", GunHud ) +hook.Add("HUDPaint", "powerupHUD", PowerUpsHud ) +hook.Add("HUDPaint", "perksHUD", PerksHud ) +hook.Add("HUDPaint", "vultureVision", VultureVision ) +hook.Add("HUDPaint", "roundnumHUD", RoundHud ) +hook.Add("HUDPaint", "grenadeHUD", DrawGrenadeHud ) + +hook.Add("OnRoundPreparation", "BeginRoundHUDChange", StartChangeRound) +hook.Add("OnRoundStart", "EndRoundHUDChange", EndChangeRound) + +local blockedweps = { + ["nz_revive_morphine"] = true, + ["nz_packapunch_arms"] = true, + ["nz_perk_bottle"] = true, +} + +function GM:HUDWeaponPickedUp( wep ) + + if ( !IsValid( LocalPlayer() ) || !LocalPlayer():Alive() ) then return end + if ( !IsValid( wep ) ) then return end + if ( !isfunction( wep.GetPrintName ) ) then return end + if blockedweps[wep:GetClass()] then return end + + local pickup = {} + pickup.time = CurTime() + pickup.name = wep:GetPrintName() + pickup.holdtime = 5 + pickup.font = "DermaDefaultBold" + pickup.fadein = 0.04 + pickup.fadeout = 0.3 + pickup.color = Color( 255, 200, 50, 255 ) + + surface.SetFont( pickup.font ) + local w, h = surface.GetTextSize( pickup.name ) + pickup.height = h + pickup.width = w + + if ( self.PickupHistoryLast >= pickup.time ) then + pickup.time = self.PickupHistoryLast + 0.05 + end + + table.insert( self.PickupHistory, pickup ) + self.PickupHistoryLast = pickup.time + + if wep.NearWallEnabled then wep.NearWallEnabled = false end + if wep:IsFAS2() then wep.NoNearWall = true end + +end + +local function ParseAmmoName(str) + local pattern = "nz_weapon_ammo_(%d)" + local slot = tonumber(string.match(str, pattern)) + if slot then + for k,v in pairs(LocalPlayer():GetWeapons()) do + if v:GetNWInt("SwitchSlot", -1) == slot then + if v.Primary and v.Primary.OldAmmo then + return "#"..v.Primary.OldAmmo.."_ammo" + end + local wep = weapons.Get(v:GetClass()) + if wep and wep.Primary and wep.Primary.Ammo then + return "#"..wep.Primary.Ammo.."_ammo" + end + return v:GetPrintName() .. " Ammo" + end + end + end + return str +end + +function GM:HUDAmmoPickedUp( itemname, amount ) + if ( !IsValid( LocalPlayer() ) || !LocalPlayer():Alive() ) then return end + + itemname = ParseAmmoName(itemname) + + -- Try to tack it onto an exisiting ammo pickup + if ( self.PickupHistory ) then + for k, v in pairs( self.PickupHistory ) do + if ( v.name == itemname ) then + v.amount = tostring( tonumber( v.amount ) + amount ) + v.time = CurTime() - v.fadein + return + end + end + end + + local pickup = {} + pickup.time = CurTime() + pickup.name = itemname + pickup.holdtime = 5 + pickup.font = "DermaDefaultBold" + pickup.fadein = 0.04 + pickup.fadeout = 0.3 + pickup.color = Color( 180, 200, 255, 255 ) + pickup.amount = tostring( amount ) + + surface.SetFont( pickup.font ) + local w, h = surface.GetTextSize( pickup.name ) + pickup.height = h + pickup.width = w + + local w, h = surface.GetTextSize( pickup.amount ) + pickup.xwidth = w + pickup.width = pickup.width + w + 16 + + if ( self.PickupHistoryLast >= pickup.time ) then + pickup.time = self.PickupHistoryLast + 0.05 + end + + table.insert( self.PickupHistory, pickup ) + self.PickupHistoryLast = pickup.time +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/display/cl_hudblock.lua b/gamemodes/nzombies/gamemode/display/cl_hudblock.lua new file mode 100644 index 00000000..0f695824 --- /dev/null +++ b/gamemodes/nzombies/gamemode/display/cl_hudblock.lua @@ -0,0 +1,11 @@ +local blockedhuds = { + ["CHudAmmo"] = true, + ["CHudSecondaryAmmo"] = true, + ["CHudBattery"] = true, +} + +hook.Add( "HUDShouldDraw", "HideHUD", function( name ) + if blockedhuds[name] then return false end + if name == "CHudWeaponSelection" then return !nzRound:InProgress() and !nzRound:InState(ROUND_GO) end -- Has it's own value + if name == "CHudHealth" then return !GetConVar("nz_bloodoverlay"):GetBool() end -- Same +end ) diff --git a/gamemodes/nzombies/gamemode/display/cl_player.lua b/gamemodes/nzombies/gamemode/display/cl_player.lua new file mode 100644 index 00000000..fa7a91dc --- /dev/null +++ b/gamemodes/nzombies/gamemode/display/cl_player.lua @@ -0,0 +1,54 @@ +local playerColors = { + Color(239,154,154), + Color(244,143,177), + Color(159,168,218), + Color(129,212,250), + Color(128,203,196), + Color(165,214,167), + Color(230,238,156), + Color(255,241,118), + Color(255,224,130), + Color(255,171,145), + Color(161,136,127), + Color(224,224,224), + Color(144,164,174), + nil +} + +local blooddecals = { + Material("bloodline_score1.png", "unlitgeneric smooth"), + Material("bloodline_score2.png", "unlitgeneric smooth"), + Material("bloodline_score3.png", "unlitgeneric smooth"), + Material("bloodline_score4.png", "unlitgeneric smooth"), + nil +} + +--shuffle the colors on map start +local rand = math.random +local n = #playerColors + +while n > 2 do + + local k = rand(n) -- 1 <= k <= n + + playerColors[n], playerColors[k] = playerColors[k], playerColors[n] + n = n - 1 +end + +n = #blooddecals + +while n > 2 do + + local k = rand(n) -- 1 <= k <= n + + blooddecals[n], blooddecals[k] = blooddecals[k], blooddecals[n] + n = n - 1 +end + +function player.GetColorByIndex(index) + return playerColors[((index - 1) % #playerColors) + 1] +end + +function player.GetBloodByIndex(index) + return blooddecals[((index - 1) % #blooddecals) + 1] +end diff --git a/gamemodes/nzombies/gamemode/display/cl_scoreboard.lua b/gamemodes/nzombies/gamemode/display/cl_scoreboard.lua new file mode 100644 index 00000000..6bace268 --- /dev/null +++ b/gamemodes/nzombies/gamemode/display/cl_scoreboard.lua @@ -0,0 +1,393 @@ + +surface.CreateFont( "ScoreboardDefault", { + font = "Helvetica", + size = 22, + weight = 800 +} ) + +surface.CreateFont( "ScoreboardDefaultTitle", { + font = "Helvetica", + size = 32, + weight = 800 +} ) + +local bloodline_scoreboard = Material("bloodline_scoreboard.png", "unlitgeneric smooth") + +-- +-- This defines a new panel type for the player row. The player row is given a player +-- and then from that point on it pretty much looks after itself. It updates player info +-- in the think function, and removes itself when the player leaves the server. +-- +local PLAYER_LINE = { + Init = function( self ) + + self.AvatarButton = self:Add( "DButton" ) + self.AvatarButton:Dock( LEFT ) + self.AvatarButton:SetSize( 32, 32 ) + self.AvatarButton.DoClick = function() self.Player:ShowProfile() end + + self.Avatar = vgui.Create( "AvatarImage", self.AvatarButton ) + self.Avatar:SetSize( 32, 32 ) + self.Avatar:SetMouseInputEnabled( false ) + + self.Name = self:Add( "DLabel" ) + self.Name:Dock( FILL ) + self.Name:SetFont( "ScoreboardDefault" ) + self.Name:SetTextColor( self.TextColor or Color(255, 255, 255) ) + + self.Mute = self:Add( "DImageButton" ) + self.Mute:SetSize( 32, 32 ) + self.Mute:Dock( RIGHT ) + + self.Ping = self:Add( "DLabel" ) + self.Ping:Dock( RIGHT ) + self.Ping:SetWidth( 50 ) + self.Ping:SetFont( "ScoreboardDefault" ) + self.Ping:SetTextColor( Color( 255, 255, 255 ) ) + self.Ping:SetContentAlignment( 5 ) + + self.Revives = self:Add( "DLabel" ) + self.Revives:Dock( RIGHT ) + self.Revives:SetWidth( 100 ) + self.Revives:SetFont( "ScoreboardDefault" ) + self.Revives:SetTextColor( self.TextColor or Color(255, 255, 255) ) + self.Revives:SetContentAlignment( 5 ) + + self.Downs = self:Add( "DLabel" ) + self.Downs:Dock( RIGHT ) + self.Downs:SetWidth( 100 ) + self.Downs:SetFont( "ScoreboardDefault" ) + self.Downs:SetTextColor( self.TextColor or Color(255, 255, 255) ) + self.Downs:SetContentAlignment( 5 ) + + self.Kills = self:Add( "DLabel" ) + self.Kills:Dock( RIGHT ) + self.Kills:SetWidth( 100 ) + self.Kills:SetFont( "ScoreboardDefault" ) + self.Kills:SetTextColor( self.TextColor or Color(255, 255, 255) ) + self.Kills:SetContentAlignment( 5 ) + + self.Points = self:Add( "DLabel" ) + self.Points:Dock( RIGHT ) + self.Points:SetWidth( 100 ) + self.Points:SetFont( "ScoreboardDefault" ) + self.Points:SetTextColor( self.TextColor or Color(255, 255, 255) ) + self.Points:SetContentAlignment( 5 ) + + self.Items = self:Add( "DPanel" ) + self.Items:Dock( RIGHT ) + self.Items:SetWidth( 175 ) + self.Items.Paint = function(pnl) + surface.SetDrawColor(255, 255, 255) + local num = 0 + for k,v in pairs(self.Player:GetCarryItems()) do + local item = nzItemCarry.Items[v] + if item and (item.icon or item.model) then + local x, y = pnl:GetPos() + + if item.model then + surface.SetMaterial(item.model) + surface.DrawTexturedRect(x - num*26, y + 6, 24, 24) + if item.icon then + surface.SetMaterial(item.icon) + surface.DrawTexturedRect(x - num*26 + 18, y, 12, 12) + end + else + surface.SetMaterial(item.icon) + surface.DrawTexturedRect(x - num*26, y + 6, 24, 24) + end + + num = num + 1 + end + end + end + + self:Dock( TOP ) + self:SetSize( 32, 32) + self:DockMargin(5,0,5,0) + + end, + + Setup = function( self, pl ) + + self.Player = pl + + self.Avatar:SetPlayer( pl ) + + self:Think( self ) + + --local friend = self.Player:GetFriendStatus() + --MsgN( pl, " Friend: ", friend ) + + end, + + Think = function( self ) + + if ( !IsValid( self.Player ) ) then + self:SetZPos( 9999 ) -- Causes a rebuild + self:Remove() + return + end + + if ( self.TextColor == nil || self.TextColor != player.GetColorByIndex( self.Player:EntIndex() ) ) then + self.TextColor = player.GetColorByIndex( self.Player:EntIndex() ) + self.Name:SetTextColor( self.TextColor ) + self.Points:SetTextColor( self.TextColor ) + self.Revives:SetTextColor( self.TextColor ) + self.Ping:SetTextColor( self.TextColor ) + self.Downs:SetTextColor( self.TextColor ) + self.Kills:SetTextColor( self.TextColor ) + end + + if ( self.ZombieKills == nil || self.ZombieKills != self.Player:GetTotalKills() ) then + self.ZombieKills = self.Player:GetTotalKills() + self.Kills:SetText( self.ZombieKills ) + end + + if ( self.NumDowns == nil || self.Downs != self.Player:GetTotalDowns() ) then + self.NumDowns = self.Player:GetTotalDowns() + self.Downs:SetText( self.NumDowns ) + end + + if ( self.NumRevives == nil || self.NumRevives != self.Player:GetTotalRevives() ) then + self.NumRevives = self.Player:GetTotalRevives() + self.Revives:SetText( self.NumRevives ) + end + + if ( self.PName == nil || self.PName != self.Player:Nick() ) then + self.PName = self.Player:Nick() + self.Name:SetText( self.PName ) + end + + if ( self.NumPoints == nil || self.NumPoints != self.Player:GetPoints() ) then + self.NumPoints = self.Player:GetPoints() + self.Points:SetText( self.NumPoints ) + end + + if ( self.NumPing == nil || self.NumPing != self.Player:Ping() ) then + self.NumPing = self.Player:Ping() + self.Ping:SetText( self.NumPing ) + end + + -- + -- Change the icon of the mute button based on state + -- + if ( self.Muted == nil || self.Muted != self.Player:IsMuted() ) then + + self.Muted = self.Player:IsMuted() + if ( self.Muted ) then + self.Mute:SetImage( "icon32/muted.png" ) + else + self.Mute:SetImage( "icon32/unmuted.png" ) + end + + self.Mute.DoClick = function() self.Player:SetMuted( !self.Muted ) end + + end + + -- + -- Connecting players go at the very bottom + -- + if ( self.Player:Team() == TEAM_CONNECTING ) then + self:SetZPos( 2000 + self.Player:EntIndex() ) + return + end + + -- + -- This is what sorts the list. The panels are docked in the z order, + -- so if we set the z order according to kills they'll be ordered that way! + -- Careful though, it's a signed short internally, so needs to range between -32,768k and +32,767 + -- + self:SetZPos( ( self.NumPoints * -50 ) + self.NumPoints + self.Player:EntIndex() ) + + end, + + Paint = function( self, w, h ) + + if ( !IsValid( self.Player ) ) then + return + end + + -- + -- We draw our background a different colour based on the status of the player + -- + + --if ( !self.Player:Alive() ) then + --draw.RoundedBox( 4, 0, 0, w, h, Color( pColor[1] * 150, pColor[2] * 150, pColor[3] * 150, 255 ) ) + --return + --end + + --draw.RoundedBox( 4, 0, 0, w, h, Color( pColor[1] * 100 + 155, pColor[2] * 100 + 155, pColor[3] * 100 + 155, 255 ) ) + + surface.SetMaterial(player.GetBloodByIndex(self.Player:EntIndex())) + surface.SetDrawColor(200,200,200) + surface.DrawTexturedRect(0, 0, w, h) + + end +} + +-- +-- Convert it from a normal table into a Panel Table based on DPanel +-- +PLAYER_LINE = vgui.RegisterTable( PLAYER_LINE, "DPanel" ) + +-- +-- Here we define a new panel table for the scoreboard. It basically consists +-- of a header and a scrollpanel - into which the player lines are placed. +-- + +local SCORE_BOARD = { + Init = function( self ) + + self.Header = self:Add( "Panel" ) + self.Header:Dock( TOP ) + self.Header:SetHeight( 100 ) + + self.Name = self.Header:Add( "DLabel" ) + self.Name:SetFont( "nz.display.hud.main" ) + self.Name:SetTextColor( Color( 255, 255, 255, 255 ) ) + self.Name:Dock( TOP ) + self.Name:SetHeight( 40 ) + self.Name:SetContentAlignment( 5 ) + + self.Key = self:Add( "DPanel" ) + self.Key:Dock( TOP ) + self.Key:SetContentAlignment( 6 ) + self.Key:SetHeight( 20 ) + self.Key.Paint = function() end + + self.Mute = self.Key:Add( "DLabel" ) + self.Mute:Dock( RIGHT ) + self.Mute:SetWidth( 32 ) + self.Mute:SetFont( "ScoreboardDefault" ) + self.Mute:SetTextColor( Color( 255, 255, 255 ) ) + self.Mute:SetContentAlignment( 5 ) + self.Mute:SetText("") + + self.Ping = self.Key:Add( "DLabel" ) + self.Ping:Dock( RIGHT ) + self.Ping:SetWidth( 50 ) + self.Ping:SetFont( "ScoreboardDefault" ) + self.Ping:SetTextColor( Color( 255, 255, 255 ) ) + self.Ping:SetContentAlignment( 5 ) + self.Ping:SetText("Ping") + + self.Revives = self.Key:Add( "DLabel" ) + self.Revives:Dock( RIGHT ) + self.Revives:SetWidth( 100 ) + self.Revives:SetFont( "ScoreboardDefault" ) + self.Revives:SetTextColor( Color(255, 255, 255) ) + self.Revives:SetContentAlignment( 5 ) + self.Revives:SetText("Revives") + + self.Downs = self.Key:Add( "DLabel" ) + self.Downs:Dock( RIGHT ) + self.Downs:SetWidth( 100 ) + self.Downs:SetFont( "ScoreboardDefault" ) + self.Downs:SetTextColor( Color(255, 255, 255) ) + self.Downs:SetContentAlignment( 5 ) + self.Downs:SetText("Downs") + + self.Kills = self.Key:Add( "DLabel" ) + self.Kills:Dock( RIGHT ) + self.Kills:SetWidth( 100 ) + self.Kills:SetFont( "ScoreboardDefault" ) + self.Kills:SetTextColor( Color( 255, 255, 255, 255 ) ) + self.Kills:SetContentAlignment( 5 ) + self.Kills:SetText("Kills") + + self.Points = self.Key:Add( "DLabel" ) + self.Points:Dock( RIGHT ) + self.Points:SetWidth( 100 ) + self.Points:SetFont( "ScoreboardDefault" ) + self.Points:SetTextColor( Color( 255, 255, 255, 255 ) ) + self.Points:SetContentAlignment( 5 ) + self.Points:SetText("Points") + + + + --self.NumPlayers = self.Header:Add( "DLabel" ) + --self.NumPlayers:SetFont( "ScoreboardDefault" ) + --self.NumPlayers:SetTextColor( Color( 255, 255, 255, 255 ) ) + --self.NumPlayers:SetPos( 0, 100 - 30 ) + --self.NumPlayers:SetSize( 300, 30 ) + --self.NumPlayers:SetContentAlignment( 4 ) + + self.Scores = self:Add( "DScrollPanel" ) + self.Scores:Dock( FILL ) + + end, + + PerformLayout = function( self ) + + self:SetSize( 800, ScrH() - 200 ) + self:SetPos( ScrW() / 2 - 400, 100 ) + + end, + + Paint = function( self, w, h ) + + --DrawBlurRect( 0, 0, w, h ) + + end, + + Think = function( self, w, h ) + + self.Name:SetText( GetHostName() ) + + -- + -- Loop through each player, and if one doesn't have a score entry - create it. + -- + local plyrs = player.GetAll() + for id, pl in pairs( plyrs ) do + + if ( IsValid( pl.ScoreEntry ) ) then continue end + + pl.ScoreEntry = vgui.CreateFromTable( PLAYER_LINE, pl.ScoreEntry ) + pl.ScoreEntry:Setup( pl ) + + self.Scores:AddItem( pl.ScoreEntry ) + + end + + end +} + +SCORE_BOARD = vgui.RegisterTable( SCORE_BOARD, "EditablePanel" ) + +--[[--------------------------------------------------------- + Name: gamemode:ScoreboardShow( ) + Desc: Sets the scoreboard to visible +-----------------------------------------------------------]] +function GM:ScoreboardShow() + + if ( !IsValid( g_Scoreboard ) ) then + g_Scoreboard = vgui.CreateFromTable( SCORE_BOARD ) + end + + if ( IsValid( g_Scoreboard ) ) then + g_Scoreboard:Show() + g_Scoreboard:MakePopup() + g_Scoreboard:SetKeyboardInputEnabled( false ) + end + +end + +--[[--------------------------------------------------------- + Name: gamemode:ScoreboardHide( ) + Desc: Hides the scoreboard +-----------------------------------------------------------]] +function GM:ScoreboardHide() + + if ( IsValid( g_Scoreboard ) ) then + g_Scoreboard:Hide() + end + +end + +--[[--------------------------------------------------------- + Name: gamemode:HUDDrawScoreBoard( ) + Desc: If you prefer to draw your scoreboard the stupid way (without vgui) +-----------------------------------------------------------]] +function GM:HUDDrawScoreBoard() +end diff --git a/gamemodes/nzombies/gamemode/display/cl_target.lua b/gamemodes/nzombies/gamemode/display/cl_target.lua new file mode 100644 index 00000000..86248dc6 --- /dev/null +++ b/gamemodes/nzombies/gamemode/display/cl_target.lua @@ -0,0 +1,264 @@ +-- + +local traceents = { + ["wall_buys"] = function(ent) + local wepclass = ent:GetWepClass() + local price = ent:GetPrice() + local wep = weapons.Get(wepclass) + if !wep then return "INVALID WEAPON" end + local name = wep.PrintName + local ammo_price = math.Round((price - (price % 10))/2) + local text = "" + + if !LocalPlayer():HasWeapon( wepclass ) then + text = "Press E to buy " .. name .." for " .. price .. " points." + elseif string.lower(wep.Primary.Ammo) != "none" then + if LocalPlayer():GetWeapon( wepclass ):HasNZModifier("pap") then + text = "Press E to buy " .. wep.Primary.Ammo .." Ammo refill for " .. 4500 .. " points." + else + text = "Press E to buy " .. wep.Primary.Ammo .." Ammo refill for " .. ammo_price .. " points." + end + else + text = "You already have this weapon." + end + + return text + end, + ["breakable_entry"] = function(ent) + if ent:GetHasPlanks() and ent:GetNumPlanks() < GetConVar("nz_difficulty_barricade_planks_max"):GetInt() then + local text = "Hold E to rebuild the barricade." + return text + end + end, + ["random_box"] = function(ent) + if !ent:GetOpen() then + local text = nzPowerUps:IsPowerupActive("firesale") and "Press E to buy a random weapon for 10 points." or "Press E to buy a random weapon for 950 points." + return text + end + end, + ["random_box_windup"] = function(ent) + if !ent:GetWinding() and ent:GetWepClass() != "nz_box_teddy" then + local wepclass = ent:GetWepClass() + local wep = weapons.Get(wepclass) + local name = "UNKNOWN" + if wep != nil then + name = wep.PrintName + end + if name == nil then name = wepclass end + name = "Press E to take " .. name .. " from the box." + + return name + end + end, + ["perk_machine"] = function(ent) + local text = "" + if !ent:IsOn() then + text = "No Power." + elseif ent:GetBeingUsed() then + text = "Currently in use." + else + if ent:GetPerkID() == "pap" then + local wep = LocalPlayer():GetActiveWeapon() + if wep:HasNZModifier("pap") then + if wep.NZRePaPText then + text = "Press E to "..wep.NZRePaPText.." for 2000 points." + elseif wep:CanRerollPaP() then + text = "Press E to reroll attachments for 2000 points." + else + text = "This weapon is already upgraded." + end + else + text = "Press E to buy Pack-a-Punch for 5000 points." + end + else + local perkData = nzPerks:Get(ent:GetPerkID()) + -- Its on + text = "Press E to buy " .. perkData.name .. " for " .. ent:GetPrice() .. " points." + -- Check if they already own it + if LocalPlayer():HasPerk(ent:GetPerkID()) then + text = "You already own this perk." + end + end + end + + return text + end, + ["player_spawns"] = function() if nzRound:InState( ROUND_CREATE ) then return "Player Spawn" end end, + ["nz_spawn_zombie_normal"] = function() if nzRound:InState( ROUND_CREATE ) then return "Zombie Spawn" end end, + ["nz_spawn_zombie_special"] = function() if nzRound:InState( ROUND_CREATE ) then return "Zombie Special Spawn" end end, + ["pap_weapon_trigger"] = function(ent) + local wepclass = ent:GetWepClass() + local wep = weapons.Get(wepclass) + local name = "UNKNOWN" + if wep != nil then + name = nz.Display_PaPNames[wepclass] or nz.Display_PaPNames[wep.PrintName] or "Upgraded "..wep.PrintName + end + name = "Press E to take " .. name .. " from the machine." + + return name + end, + ["wunderfizz_machine"] = function(ent) + local text = "" + if !ent:IsOn() then + text = "The Wunderfizz Orb is currently at another location." + elseif ent:GetBeingUsed() then + if ent:GetUser() == LocalPlayer() and ent:GetPerkID() != "" and !ent:GetIsTeddy() then + text = "Press E to take "..nzPerks:Get(ent:GetPerkID()).name.." from Der Wunderfizz." + else + text = "Currently in use." + end + else + if #LocalPlayer():GetPerks() >= GetConVar("nz_difficulty_perks_max"):GetInt() then + text = "You cannot have more perks." + else + text = "Press E to buy Der Wunderfizz for " .. ent:GetPrice() .. " points." + end + end + + return text + end, +} + +local function GetTarget() + local tr = { + start = EyePos(), + endpos = EyePos() + LocalPlayer():GetAimVector()*150, + filter = LocalPlayer(), + } + local trace = util.TraceLine( tr ) + if (!trace.Hit) then return end + if (!trace.HitNonWorld) then return end + + --print(trace.Entity:GetClass()) + return trace.Entity +end + +local function GetDoorText( ent ) + local door_data = ent:GetDoorData() + local text = "" + + if door_data and tonumber(door_data.price) == 0 and nzRound:InState(ROUND_CREATE) then + if tobool(door_data.elec) then + text = "This door will open when electricity is turned on." + else + text = "This door will open on game start." + end + elseif door_data and tonumber(door_data.buyable) == 1 then + local price = tonumber(door_data.price) + local req_elec = tobool(door_data.elec) + local link = door_data.link + + if ent:IsLocked() then + if req_elec and !IsElec() then + text = "You must turn on the electricity first!" + elseif door_data.text then + text = door_data.text + elseif price != 0 then + --print("Still here", nz.nzDoors.Data.OpenedLinks[tonumber(link)]) + text = "Press E to open for " .. price .. " points." + end + end + elseif door_data and tonumber(door_data.buyable) != 1 and nzRound:InState( ROUND_CREATE ) then + text = "This door is locked and cannot be bought in-game." + --PrintTable(door_data) + end + + return text +end + +local function GetText( ent ) + + if !IsValid(ent) then return "" end + + if ent.GetNZTargetText then return ent:GetNZTargetText() end + + local class = ent:GetClass() + local text = "" + + local neededcategory, neededcategory2, deftext, hastext, has2text = ent:GetNWString("NZRequiredItem"), ent:GetNWString("NZRequiredItem2"), ent:GetNWString("NZText"), ent:GetNWString("NZHasText"), ent:GetNWString("NZHas2Text") + local itemcategory = ent:GetNWString("NZItemCategory") + + if neededcategory != "" then + local hasitem = LocalPlayer():HasCarryItem(neededcategory) + text = hasitem and hastext != "" and hastext or deftext + elseif neededcategory2 != "" then + local hasitem = LocalPlayer():HasCarryItem(neededcategory) + text = hasitem and has2text != "" and has2text or deftext + elseif deftext != "" then + text = deftext + elseif itemcategory != "" then + local item = nzItemCarry.Items[itemcategory] + local hasitem = LocalPlayer():HasCarryItem(itemcategory) + if hasitem then + text = item and item.hastext or "You already have this." + else + text = item and item.text or "Press E to pick up." + end + elseif ent:IsPlayer() then + if ent:GetNotDowned() then + text = ent:Nick() .. " - " .. ent:Health() .. " HP" + else + text = "Hold E to revive "..ent:Nick() + end + elseif ent:IsDoor() or ent:IsButton() or ent:GetClass() == "class C_BaseEntity" or ent:IsBuyableProp() then + text = GetDoorText(ent) + else + text = traceents[class] and traceents[class](ent) + end + + return text +end + +local function GetMapScriptEntityText() + local text = "" + + for k,v in pairs(ents.FindByClass("nz_script_triggerzone")) do + local dist = v:NearestPoint(EyePos()):Distance(EyePos()) + if dist <= 1 then + text = GetDoorText(v) + break + end + end + + return text +end + +local function DrawTargetID( text ) + + if !text then return end + + local font = "nz.display.hud.small" + surface.SetFont( font ) + local w, h = surface.GetTextSize( text ) + + local MouseX, MouseY = gui.MousePos() + + if ( MouseX == 0 && MouseY == 0 ) then + + MouseX = ScrW() / 2 + MouseY = ScrH() / 2 + + end + + local x = MouseX + local y = MouseY + + x = x - w / 2 + y = y + 30 + + -- The fonts internal drop shadow looks lousy with AA on + draw.SimpleText( text, font, x+1, y+1, Color(255,255,255,255) ) +end + + +function GM:HUDDrawTargetID() + + local ent = GetTarget() + + if ent != nil then + DrawTargetID(GetText(ent)) + else + DrawTargetID(GetMapScriptEntityText()) + end + +end diff --git a/gamemodes/nzombies/gamemode/display/sh_papnames.lua b/gamemodes/nzombies/gamemode/display/sh_papnames.lua new file mode 100644 index 00000000..c2471498 --- /dev/null +++ b/gamemodes/nzombies/gamemode/display/sh_papnames.lua @@ -0,0 +1,63 @@ +nz.Display_PaPNames = { + -- You can use both class names and display names, class names take priority but display names can apply to multiple weapons + ["fas2_glock20"] = "Glock-115c", + ["Ray Gun"] = "Porter's X2 Ray Gun", + ["Raygun"] = "Porter's X2 Ray Gun", + ["fas2_ak12"] = "AK-12EAPER", + ["fas2_ak47"] = "AK-4TW", + ["fas2_ak74"] = "AK74FU2", + ["fas2_an94"] = "Actuated Neutralizer 94000", + ["fas2_famas"] = "F4M3-A55", + ["fas2_g36c"] = "GL-HF36", + ["fas2_g3"] = "G3T-GUD", + ["fas2_deagle"] = "Desert Hawk", + ["fas2_galil"] = "Gabig", + ["fas2_uzi"] = "Uncle Gal", + ["fas2_ks23"] = "K1LL-ST34L", + ["fas2_mac11"] = "Big Mac", + ["fas2_m14"] = "M8-YUDODIZ", + ["fas2_m1911"] = "M9-K11L", + ["fas2_m21"] = "M21GHT", + ["fas2_m24"] = "M2ATH", + ["fas2_m3s90"] = "M30 Ultra 9000", + ["fas2_m4a1"] = "M4A115", + ["fas2_m82"] = "M8-U2", + ["fas2_mp5a5"] = "M115 A55", + ["fas2_mp5k"] = "M115 Kollider", + ["fas2_mp5sd6"] = "M115 S4D", + ["fas2_ots33"] = "Ostrich-33", + ["fas2_p226"] = "P-4U2", + ["fas2_pp19"] = "PP20 Buffalo", + ["fas2_ragingbull"] = "Furious Bull", + ["fas2_rem870"] = "REM-3MB3R M3", + ["fas2_rpk"] = "RPK-4TW", + ["fas2_rk95"] = "Sa-KO 9500", + ["fas2_sg550"] = "SG 11500", + ["fas2_sg552"] = "SG 11502", + ["fas2_sks"] = "Seeking Kill Steals", + ["fas2_sr25"] = "SR3KT", + + -- CW 2 weapons + ["cw_ak74"] = "AK-4TW", + ["cw_ar15"] = "All-Right15", + ["cw_auggsm"] = "AUG-SOM3", + ["cw_g3a3"] = "G3T-B3TTER", + ["cw_mp5"] = "MP115", + ["cw_deagle"] = "Desert Hawk", + ["cw_l115"] = "L-Emnt 115", + ["cw_lr300"] = "Liberator 115x2", + ["cw_mr96"] = "Mr.Rekker 96", + ["UMP45"] = "Unified Material Penetrator 4D5", + ["cw_c7a1"] = "C7-KILL7", + ["cw_kimber_kw"] = "Kimber Knight Warlord", + ["cw_mk11"] = "Mr.Kill 115", + ["cw_ppsh-41"] = "The Reaper", + ["cw_xm1014"] = "XTREME1015", + ["cw_dz_ru556"] = "Codename Rul3R-5000", + + +} + +function AddPackAPunchName(class, papname) -- The function also works with display names just like above + nz.Display_PaPNames[class] = papname +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/display/sh_properties.lua b/gamemodes/nzombies/gamemode/display/sh_properties.lua new file mode 100644 index 00000000..57e69779 --- /dev/null +++ b/gamemodes/nzombies/gamemode/display/sh_properties.lua @@ -0,0 +1,334 @@ +--[[ + Properties added in here are added manually because they share tools and/or use specialized means of updating and fetching data + If you want to add a quick Properties for your tool, look at nzTools:EnableProperties() function. + (gamemode/tools/sh_tools.lua) +]] + +properties.Add( "nz_remove", { + MenuLabel = "Remove", + Order = 1000, + MenuIcon = "icon16/delete.png", + + Filter = function( self, ent, ply ) -- A function that determines whether an entity is valid for this property + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( ent:IsPlayer() ) then return false end + if ( !ply:IsAdmin() ) then return false end + + return true + end, + Action = function( self, ent ) + + self:MsgStart() + net.WriteEntity( ent ) + self:MsgEnd() + + end, + + Receive = function( self, length, player ) + local ent = net.ReadEntity() + + if ( !IsValid( ent ) ) then return false end + if ( !IsValid( player ) ) then return false end + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( !player:IsAdmin() ) then return false end + if ( ent:IsPlayer() ) then return false end + if ( !self:Filter( ent, player ) ) then return false end + + -- Remove all constraints (this stops ropes from hanging around) + constraint.RemoveAll( ent ) + + -- Remove it properly in 1 second + timer.Simple( 1, function() if ( IsValid( ent ) ) then ent:Remove() print("Removed", ent) end end ) + + -- Make it non solid + ent:SetNotSolid( true ) + ent:SetMoveType( MOVETYPE_NONE ) + ent:SetNoDraw( true ) + + -- Send Effect + local ed = EffectData() + ed:SetEntity( ent ) + util.Effect( "entity_remove", ed, true, true ) + end +} ) + +properties.Add( "nz_editentity", { + MenuLabel = "Edit Properties...", + Order = 90010, + PrependSpacer = true, + MenuIcon = "icon16/pencil.png", + + Filter = function( self, ent, ply ) + + if ( !IsValid( ent ) ) then return false end + if ( !ent.Editable ) then return false end + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( ent:IsPlayer() ) then return false end + if ( !ply:IsAdmin() ) then return false end + + return true + + end, + + Action = function( self, ent ) + + local window = g_ContextMenu:Add( "DFrame" ) + window:SetSize( 320, 400 ) + window:SetTitle( tostring( ent ) ) + window:Center() + window:SetSizable( true ) + + local control = window:Add( "DEntityProperties" ) + control:SetEntity( ent ) + control:Dock( FILL ) + + control.OnEntityLost = function() + + window:Remove() + + end + end +} ) + +properties.Add( "nz_lock", { + MenuLabel = "Edit Lock...", + Order = 9001, + PrependSpacer = true, + MenuIcon = "icon16/lock_edit.png", + + Filter = function( self, ent, ply ) + + if ( !IsValid( ent ) or !IsValid(ply) ) then return false end + if !( ent:IsDoor() or ent:IsButton() or ent:IsBuyableProp() ) then return false end + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( !ply:IsInCreative() ) then return false end + + return true + + end, + + Action = function( self, ent ) + local frame = vgui.Create("DFrame") + frame:SetPos( 100, 100 ) + frame:SetSize( 300, 280 ) + frame:SetTitle( "Edit Lock..." ) + frame:SetVisible( true ) + frame:SetDraggable( true ) + frame:ShowCloseButton( true ) + frame:MakePopup() + frame:Center() + + local door = ent:GetDoorData() + if !door then door = {} end + + door.flag = door.flag or 0 + door.link = door.link or 1 + door.price = door.price or 1000 + door.elec = door.elec or 0 + door.buyable = door.buyable or 1 + door.rebuyable = door.rebuyable or 0 + + + + local panel = nzTools.ToolData["door"].interface(frame, door, true) + panel:SetPos(10, 40) + + local data2 = panel.CompileData() + panel.UpdateData = function(data) + data2 = data + end + + local submit = vgui.Create("DButton", frame) + submit:SetText("Submit") + submit:SetPos(50, 245) + submit:SetSize(200, 25) + submit.DoClick = function(self2) + self:MsgStart() + net.WriteEntity( ent ) + net.WriteTable( data2 ) + self:MsgEnd() + end + end, + + Receive = function( self, length, ply ) + local ent = net.ReadEntity() + local data = net.ReadTable() + if ( !self:Filter( ent, ply ) ) then return false end + + nzTools.ToolData["door"].PrimaryAttack(nil, ply, {Entity = ent}, data) + end +} ) + +properties.Add( "nz_unlock", { + MenuLabel = "Unlock", + Order = 9002, + PrependSpacer = false, + MenuIcon = "icon16/lock_delete.png", + + Filter = function( self, ent, ply ) + + if ( !IsValid( ent ) or !IsValid(ply) ) then return false end + if !( ent:IsDoor() or ent:IsButton() or ent:IsBuyableProp() ) then return false end + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( !ply:IsInCreative() ) then return false end + if ent:IsBuyableProp() then + if ( !nzDoors.PropDoors[ent:EntIndex()] ) then return false end + else + if ( !nzDoors.MapDoors[ent:DoorIndex()] ) then return false end + end + + return true + + end, + + Action = function( self, ent ) + + self:MsgStart() + net.WriteEntity( ent ) + self:MsgEnd() + + end, + + Receive = function( self, length, player ) + local ent = net.ReadEntity() + if ( !self:Filter( ent, player ) ) then return false end + + nzDoors:RemoveLink( ent ) + + end +} ) + +properties.Add( "nz_editzspawn", { + MenuLabel = "Edit Spawnpoint...", + Order = 9003, + PrependSpacer = true, + MenuIcon = "icon16/link_edit.png", + + Filter = function( self, ent, ply ) + + if ( !IsValid( ent ) or !IsValid(ply) ) then return false end + if ( ent:GetClass() != "nz_spawn_zombie_normal" and ent:GetClass() != "nz_spawn_zombie_special" ) then return false end + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( !ply:IsInCreative() ) then return false end + + return true + + end, + + Action = function( self, ent ) + local frame = vgui.Create("DFrame") + frame:SetPos( 100, 100 ) + frame:SetSize( 300, 280 ) + frame:SetTitle( "Edit Spawnpoint..." ) + frame:SetVisible( true ) + frame:SetDraggable( true ) + frame:ShowCloseButton( true ) + frame:MakePopup() + frame:Center() + + local ztype = ent:GetClass() == "nz_spawn_zombie_normal" and "zspawn" or "zspecialspawn" + + local spawndata = {} + if ent:GetLink() then + spawndata.flag = 1 + spawndata.link = ent:GetLink() + else + spawndata.flag = 0 + spawndata.link = "" + end + + local panel = nzTools.ToolData[ztype].interface(frame, spawndata, true) + panel:SetPos(10, 40) + + local data2 = panel.CompileData() + panel.UpdateData = function(data) + data2 = data + end + + local submit = vgui.Create("DButton", frame) + submit:SetText("Submit") + submit:SetPos(50, 245) + submit:SetSize(200, 25) + submit.DoClick = function(self2) + self:MsgStart() + net.WriteEntity( ent ) + net.WriteTable( data2 ) + self:MsgEnd() + end + end, + + Receive = function( self, length, player ) + local ent = net.ReadEntity() + local data = net.ReadTable() + if ( !self:Filter( ent, player ) ) then return false end + + local ztype = ent:GetClass() == "nz_spawn_zombie_normal" and "zspawn" or "zspecialspawn" + + nzTools.ToolData[ztype].PrimaryAttack(nil, ply, {Entity = ent}, data) + end +} ) + +properties.Add( "nz_nocollide_on", { + MenuLabel = "Disable Collisions", + Order = 9006, + PrependSpacer = true, + MenuIcon = "icon16/collision_off.png", + + Filter = function( self, ent, ply ) + + if ( !IsValid( ent ) ) then return false end + if ( ent:GetClass() != "prop_buys" ) then return false end + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( !ply:IsAdmin() ) then return false end + if ( ent:GetCollisionGroup() == COLLISION_GROUP_WORLD ) then return false end + + return true + + end, + + Action = function( self, ent ) + self:MsgStart() + net.WriteEntity( ent ) + self:MsgEnd() + end, + + Receive = function( self, length, player ) + local ent = net.ReadEntity() + if ( !self:Filter( ent, player ) ) then return false end + + ent:SetCollisionGroup(COLLISION_GROUP_WORLD) + + end +} ) + +properties.Add( "nz_nocollide_off", { + MenuLabel = "Enable Collisions", + Order = 9007, + PrependSpacer = true, + MenuIcon = "icon16/collision_on.png", + + Filter = function( self, ent, ply ) + + if ( !IsValid( ent ) ) then return false end + if ( ent:GetClass() != "prop_buys" ) then return false end + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( !ply:IsAdmin() ) then return false end + + return ( ent:GetCollisionGroup() == COLLISION_GROUP_WORLD ) + + end, + + Action = function( self, ent ) + self:MsgStart() + net.WriteEntity( ent ) + self:MsgEnd() + end, + + Receive = function( self, length, player ) + local ent = net.ReadEntity() + if ( !self:Filter( ent, player ) ) then return false end + + ent:SetCollisionGroup(COLLISION_GROUP_NONE) + + end +} ) diff --git a/gamemodes/nzombies/gamemode/doors/sh_constructor.lua b/gamemodes/nzombies/gamemode/doors/sh_constructor.lua new file mode 100644 index 00000000..38c4cfc1 --- /dev/null +++ b/gamemodes/nzombies/gamemode/doors/sh_constructor.lua @@ -0,0 +1,2 @@ +-- Setup Doors module +nzDoors = nzDoors or AddNZModule("Doors") diff --git a/gamemodes/nzombies/gamemode/doors/sh_door_meta_accessors.lua b/gamemodes/nzombies/gamemode/doors/sh_door_meta_accessors.lua new file mode 100644 index 00000000..f9b1f974 --- /dev/null +++ b/gamemodes/nzombies/gamemode/doors/sh_door_meta_accessors.lua @@ -0,0 +1,144 @@ +local meta = FindMetaTable("Entity") + +nzDoors.MapDoors = nzDoors.MapDoors or {} +nzDoors.PropDoors = nzDoors.PropDoors or {} +nzDoors.OpenedLinks = nzDoors.OpenedLinks or {} + +function meta:IsLocked() + if self:IsBuyableProp() or self:IsScriptBuyable() then + return nzDoors.PropDoors[self:EntIndex()] and nzDoors.PropDoors[self:EntIndex()].locked or false + else + return nzDoors.MapDoors[self:DoorIndex()] and nzDoors.MapDoors[self:DoorIndex()].locked or false + end +end + +function meta:SetLocked( bool ) + if self:IsBuyableProp() or self:IsScriptBuyable() then + if !nzDoors.PropDoors[self:EntIndex()] then nzDoors.PropDoors[self:EntIndex()] = {} end + nzDoors.PropDoors[self:EntIndex()].locked = bool + else + if !nzDoors.MapDoors[self:DoorIndex()] then nzDoors.MapDoors[self:DoorIndex()] = {} end + nzDoors.MapDoors[self:DoorIndex()].locked = bool + end +end + +local validdoors = { + ["func_door"] = true, + ["func_door_rotating"] = true, + ["prop_door_rotating"] = true, + ["prop_dynamic"] = true, +} + +local scriptbuyables = { + ["nz_script_triggerzone"] = true, + ["nz_triggerbutton"] = true, +} + +function meta:IsDoor() + if not IsValid(self) then return false end + local class = self:GetClass() + + return validdoors[class] or false +end + +function meta:IsScriptBuyable() + if not IsValid(self) then return false end + local class = self:GetClass() + + return scriptbuyables[class] or false +end + +function meta:IsBuyableEntity() + return self:IsDoor() or self:IsBuyableProp() or self:IsButton() or self:IsScriptBuyable() or false +end + +function meta:IsButton() + if not IsValid(self) then return false end + local class = self:GetClass() + + if class == "func_button" or (CLIENT and class == "class C_BaseEntity") then + return true + end + return false +end + +function meta:IsBuyableProp() + if not IsValid(self) then return false end + return self:GetClass() == "prop_buys" +end + +function meta:IsPropDoorType() + return self:IsScriptBuyable() or self:IsBuyableProp() +end + +function meta:IsBuyableMapEntity() + return self:IsDoor() or self:IsButton() or self:IsBuyableProp() or self:IsScriptBuyable() or false +end + +function meta:DoorIndex() + if !IsValid(self) then return end + if SERVER then + return self:CreatedByMap() and self:MapCreationID() or nil + else + -- Check the ED table + return nzDoors.MapCreationIndexTable[self:EntIndex()] or 0 + end +end + +function meta:GetDoorData() + if !IsValid(self) then return end + if self:IsBuyableProp() or self:IsScriptBuyable() then + if !nzDoors.PropDoors[self:EntIndex()] then return end + return nzDoors.PropDoors[self:EntIndex()].flags + else + if !nzDoors.MapDoors[self:DoorIndex()] then return end + return nzDoors.MapDoors[self:DoorIndex()].flags + end +end + +function meta:SetDoorData( tbl ) + if !IsValid(self) then return end + if self:IsBuyableProp() or self:IsScriptBuyable() then + if !nzDoors.PropDoors[self:EntIndex()] then nzDoors.PropDoors[self:EntIndex()] = {} end + nzDoors.PropDoors[self:EntIndex()].flags = tbl + else + if !nzDoors.MapDoors[self:DoorIndex()] then nzDoors.MapDoors[self:DoorIndex()] = {} end + nzDoors.MapDoors[self:DoorIndex()].flags = tbl + end +end + +function nzDoors:DoorIndexByID( id ) + if SERVER then + local ent = Entity(id) + return ent:CreatedByMap() and ent:MapCreationID() or nil + else + -- Check the ED table + return nzDoors.MapCreationIndexTable[id] or 0 + end +end + +function nzDoors:SetDoorDataByID( id, prop, tbl ) + --if !tbl then return end + if prop then + if !self.PropDoors[id] then self.PropDoors[id] = {} end + self.PropDoors[id].flags = tbl + else + if !self.MapDoors[id] then self.MapDoors[id] = {} end + self.MapDoors[id].flags = tbl + end +end + +function nzDoors:SetLockedByID( id, prop, bool ) + if prop then + if !nzDoors.PropDoors[id] then nzDoors.PropDoors[id] = {} end + self.PropDoors[id].locked = bool + else + local index = nzDoors:DoorIndexByID( id ) + if !nzDoors.MapDoors[index] then nzDoors.MapDoors[index] = {} end + self.MapDoors[index].locked = bool + end +end + +function nzDoors:IsLinkOpened( link ) + return self.OpenedLinks[link] +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/doors/sh_sync.lua b/gamemodes/nzombies/gamemode/doors/sh_sync.lua new file mode 100644 index 00000000..224395f6 --- /dev/null +++ b/gamemodes/nzombies/gamemode/doors/sh_sync.lua @@ -0,0 +1,201 @@ +if SERVER then + util.AddNetworkString( "nzMapDoorCreation" ) + util.AddNetworkString( "nzPropDoorCreation" ) + util.AddNetworkString( "nzAllDoorsLocked" ) + util.AddNetworkString( "nzDoorOpened" ) + util.AddNetworkString( "nzClearDoorData" ) + + function CleanFlagTable(flags) + local newFlags = {} + newFlags["link"] = flags["link"] + newFlags["buyable"] = tobool(flags["buyable"]) + newFlags["price"] = flags["price"] + newFlags["elec"] = tobool(flags["elec"]) + newFlags["rebuyable"] = tobool(flags["rebuyable"]) + + return newFlags + end + + function nzDoors:SendMapDoorCreation( door, flags, id, ply ) + if IsValid(door) then + + flags = CleanFlagTable(flags) + net.Start("nzMapDoorCreation") + net.WriteBool(true) + net.WriteInt(door:EntIndex(), 13) + net.WriteString(flags["link"] or "") + net.WriteString(flags["price"] or "0") + net.WriteBool(flags["buyable"] or false) + net.WriteBool(flags["elec"] or false) + net.WriteBool(flags["rebuyable"] or false) + net.WriteInt(id or 0, 13) + return ply and net.Send(ply) or net.Broadcast() + end + end + + function nzDoors:SendPropDoorCreation( ent, flags, ply ) + if IsValid(ent) then + flags = CleanFlagTable(flags) + net.Start("nzPropDoorCreation") + net.WriteBool(true) + net.WriteInt(ent:EntIndex(), 13) + net.WriteString(flags["link"] or "") + net.WriteString(flags["price"] or "0") + net.WriteBool(flags["buyable"] or false) + net.WriteBool(flags["elec"] or false) + net.WriteBool(flags["rebuyable"] or false) + return ply and net.Send(ply) or net.Broadcast() + end + end + + function nzDoors:SendMapDoorRemoval( door, ply ) + if IsValid(door) then + net.Start("nzMapDoorCreation") + net.WriteBool(false) + net.WriteInt(door:EntIndex(), 13) + return ply and net.Send(ply) or net.Broadcast() + end + end + + function nzDoors:SendPropDoorRemoval( ent, ply ) + if IsValid(ent) then + net.Start("nzPropDoorCreation") + net.WriteBool(false) + net.WriteInt(ent:EntIndex(), 13) + return ply and net.Send(ply) or net.Broadcast() + end + end + + function nzDoors:SendAllDoorsLocked( ply ) + net.Start("nzAllDoorsLocked") + return ply and net.Send(ply) or net.Broadcast() + end + + function nzDoors:SendDoorOpened( door, rebuyable, ply ) + net.Start("nzDoorOpened") + net.WriteBool(IsValid(door) and door:IsPropDoorType()) + net.WriteInt(door:EntIndex(), 13) + net.WriteBool(rebuyable and tobool(rebuyable) or false) + return ply and net.Send(ply) or net.Broadcast() + end + + function nzDoors.SendSync( ply ) + -- Clear all data first + if ply then + net.Start("nzClearDoorData") + net.Send(ply) + else + net.Start("nzClearDoorData") + net.Broadcast() + end + + -- Remove old doors + for k,v in pairs(nzDoors.MapDoors) do + nzDoors:SendMapDoorCreation( nzDoors:DoorIndexToEnt(k), v.flags, k, ply ) + if !v.locked then + nzDoors:SendDoorOpened( nzDoors:DoorIndexToEnt(k), ply ) + end + end + for k,v in pairs(nzDoors.PropDoors) do + nzDoors:SendPropDoorCreation( Entity(k), v.flags, ply ) + if !v.locked then + nzDoors:SendDoorOpened( Entity(k), ply ) + end + end + end + + FullSyncModules["Doors"] = nzDoors.SendSync + +end + +if CLIENT then + nzDoors.MapCreationIndexTable = nzDoors.MapCreationIndexTable or {} + nzDoors.DisplayLinks = nzDoors.DisplayLinks or {} + + function BoolToIntString(bool) + if bool and isbool(bool) then + return "1" + else + return "0" + end + end + + local function ReceiveMapDoorCreation() + local bool = net.ReadBool() + local index = net.ReadInt(13) + -- True if door is created, false if removed + if bool then + local tbl = {} --net.ReadTable() + tbl["link"] = net.ReadString() + tbl["price"] = net.ReadString() + tbl["buyable"] = BoolToIntString(net.ReadBool()) + tbl["elec"] = BoolToIntString(net.ReadBool()) + tbl["rebuyable"] = BoolToIntString(net.ReadBool()) + nzDoors.MapCreationIndexTable[index] = net.ReadInt(13) + nzDoors:SetDoorDataByID( nzDoors.MapCreationIndexTable[index], false, tbl ) + nzDoors:SetLockedByID( index, false, true ) + --ent:SetDoorData(tbl) + -- We store the map creation ID in a table so we can access it universally + --ent:SetLocked(true) + else + --ent:SetDoorData(nil) + --nzDoors.MapCreationIndexTable[index] = nil + --ent:SetLocked(false) + nzDoors:SetDoorDataByID( nzDoors.MapCreationIndexTable[index], false, nil ) + nzDoors:SetLockedByID( index, false, false ) + end + end + net.Receive("nzMapDoorCreation", ReceiveMapDoorCreation) + + local function ReceivePropDoorCreation() + local bool = net.ReadBool() + local index = net.ReadInt(13) + --local ent = Entity(index) + -- True if door is created, false if removed + if bool then + local tbl = {}--net.ReadTable() + tbl["link"] = net.ReadString() + tbl["price"] = net.ReadString() + tbl["buyable"] = BoolToIntString(net.ReadBool()) + tbl["elec"] = BoolToIntString(net.ReadBool()) + tbl["rebuyable"] = BoolToIntString(net.ReadBool()) + nzDoors:SetDoorDataByID( index, true, tbl ) + nzDoors:SetLockedByID( index, true, true ) + --ent:SetDoorData(tbl) + --ent:SetLocked(true) + else + nzDoors:SetDoorDataByID( index, true, nil ) + nzDoors:SetLockedByID( index, true, false ) + --ent:SetDoorData(nil) + --ent:SetLocked(false) + end + end + net.Receive("nzPropDoorCreation", ReceivePropDoorCreation) + + local function ReceiveAllDoorsLocked() + for k,v in pairs(nzDoors.MapDoors) do + v.locked = true + end + for k,v in pairs(nzDoors.PropDoors) do + v.locked = true + end + end + net.Receive("nzAllDoorsLocked", ReceiveAllDoorsLocked) + + local function ReceiveDoorOpened() + local prop = net.ReadBool() + local index = net.ReadInt(13) + local rebuyable = net.ReadBool() + nzDoors:SetLockedByID( index, prop, rebuyable ) + --local door = Entity(index) + --door:SetLocked(false) + end + net.Receive("nzDoorOpened", ReceiveDoorOpened) + + local function ClearAllDoorData() + nzDoors.MapDoors = {} + nzDoors.PropDoors = {} + nzDoors.MapCreationIndexTable = {} + end + net.Receive("nzClearDoorData", ClearAllDoorData) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/doors/sv_door_meta_functions.lua b/gamemodes/nzombies/gamemode/doors/sv_door_meta_functions.lua new file mode 100644 index 00000000..cf00b747 --- /dev/null +++ b/gamemodes/nzombies/gamemode/doors/sv_door_meta_functions.lua @@ -0,0 +1,84 @@ +local meta = FindMetaTable("Entity") + +function meta:UnlockDoor() + if self:IsDoor() then + local data = self:GetDoorData() + if data.NextBuy and data.NextBuy > CurTime() then return end + print("Unlocking door ", self) + + self:Fire("unlock", "", 0) + self:Fire("Unlock", "", 0) + self:Fire("open", "", 0) -- Seems like some doors wanted it capitalized + self:Fire("Open", "", 0) + + -- Doors that can be rebought should not be locked - only use this on doors with buttons that should close again! + if tobool(data.rebuyable) then return end + + self:SetLocked(false) + self:SetCollisionGroup(COLLISION_GROUP_DEBRIS_TRIGGER) + + self:Fire("lock", "", 0) + self:Fire("Lock", "", 0) + self:SetKeyValue("wait",-1) + self:SetKeyValue("Wait",-1) + + -- Dem sneaky doors keep closing themselves with their modern triggers - we gotta reopen! + self:Fire("addoutput", "onclose !self:open::0:-1,0,-1") + self:Fire("addoutput", "onclose !self:unlock::0:-1,0,-1") + + elseif self:IsBuyableProp() then + self:SetLocked(false) + self:BlockUnlock() + end +end + +function meta:UnlockButton(rebuyable) + if self:IsButton() then + print("Unlocked button", self) + --print(self) + --self:Fire("unlock") + self:Fire("Unlock") + --self:Fire("press") + self:Fire("Press") + --self:Fire("pressin") + self:Fire("PressIn") + --self:Fire("pressout") + self:Fire("PressOut") + + -- Repurchasable buttons don't lock + if rebuyable then return end + + --self:Fire("lock") + self:Fire("Lock") + --self:SetKeyValue("wait",-1) + self:SetKeyValue("Wait",-1) + + self:SetLocked(false) + end +end + +function meta:LockButton() + if self:IsButton() then + self:SetLocked(true) + --self:Fire("lock", "", 0) + --self:Fire("Lock", "", 0) + end +end + +function meta:LockDoor() + if self:IsDoor() then + local data = self:GetDoorData() + print("Locked ", self) + self:SetLocked(true) + --self:SetCollisionGroup(COLLISION_GROUP_NONE) + + if data.buyable and !tobool(data.buyable) then return end + + self:Fire("close", "", 0) + self:Fire("Close", "", 0) + self:Fire("lock", "", 0) + self:Fire("Lock", "", 0) + elseif self:IsBuyableProp() then + self:BlockLock() + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/doors/sv_doors.lua b/gamemodes/nzombies/gamemode/doors/sv_doors.lua new file mode 100644 index 00000000..2f5f1de4 --- /dev/null +++ b/gamemodes/nzombies/gamemode/doors/sv_doors.lua @@ -0,0 +1,127 @@ +function nzDoors:DoorToEntIndex(num) + local ent = ents.GetMapCreatedEntity(num) + + return IsValid(ent) and ent:EntIndex() or nil +end + +function nzDoors:DoorIndexToEnt(num) + if !num then return nil end + return ents.GetMapCreatedEntity(num) or NULL +end + +function nzDoors:ParseFlagString( flagsStr ) + + local tbl = {} + + flagsStr = string.lower(flagsStr) + + -- Translate the flags string into a table + local ex = string.Explode( ",", flagsStr ) + + for k,v in pairs(ex) do + local ex2 = string.Explode( "=", v ) + tbl[ex2[1]] = ex2[2] + -- If buyable is not set on a door, we default to on + if !tbl["buyable"] and k == #ex then + tbl["buyable"] = "1" + end + end + + --PrintTable(tbl) + return tbl + +end + +function nzDoors:CreateLink( ent, flagsStr ) + -- First remove all links + --self:RemoveLink( ent ) + if ent:IsDoor() or ent:IsButton() then + self:CreateMapDoorLink( ent:DoorIndex(), flagsStr ) + elseif ent:IsBuyableProp() or ent:IsScriptBuyable() then + self:CreatePropDoorLink( ent, flagsStr ) + end +end + +function nzDoors:RemoveLink( ent, nohook ) + if ent:IsDoor() or ent:IsButton() then + self:RemoveMapDoorLink( ent:DoorIndex() ) + elseif ent:IsBuyableProp() then + self:RemovePropDoorLink( ent ) + end + if !nohook then + hook.Call("OnDoorUnlocked", self, ent) + end +end + +function nzDoors:CreateMapDoorLink( doorID, flagsStr ) + + local door = self:DoorIndexToEnt(doorID) + if !flagsStr then ErrorNoHalt("Door "..doorID.." doesn't have a flagsStr saved!") return end + local flagsTbl = self:ParseFlagString( flagsStr ) + + if IsValid(door) and (door:IsDoor() or door:IsButton()) then + -- Assign the flags to the door and the table + door:SetDoorData(flagsTbl) + door:SetLocked(true) + --self.MapDoors[doorID] = flagsTbl + + hook.Call("OnMapDoorLinkCreated", self, door, flagsTbl, doorID) + else + print("Error: " .. doorID .. " is not a door.") + end + +end + +function nzDoors:RemoveMapDoorLink( doorID ) + + local door = self:DoorIndexToEnt(doorID) + if door:GetDoorData() then + if IsValid(door) and (door:IsDoor() or door:IsButton()) then + self.MapDoors[doorID] = nil + + hook.Call("OnMapDoorLinkRemoved", self, door, doorID) + else + print("Error: " .. doorID .. " is not a door. ") + end + end + +end + +function nzDoors:CreatePropDoorLink( ent, flagsStr ) + + local flagsTbl = self:ParseFlagString( flagsStr ) + + if IsValid(ent) and ent:IsBuyableProp() then + ent:SetDoorData(flagsTbl) + ent:SetLocked(true) + --self.PropDoors[ent:EntIndex()] = flagsTbl + + hook.Call("OnPropDoorLinkCreated", self, ent, flagsTbl) + else + --print("Error: " .. doorID .. " is not a door. ") + end + +end + +function nzDoors:RemovePropDoorLink( ent ) + + if IsValid(ent) and ent:IsBuyableProp() then + -- Total clear of the table + self.PropDoors[ent:EntIndex()] = nil + + hook.Call("OnPropDoorLinkRemoved", self, ent) + else + --print("Error: " .. doorID .. " is not a door. ") + end +end + +function nzDoors:DisplayDoorLinks( ent ) + if ent.link == nil then self.DisplayLinks[ent] = nil return end + + if self.DisplayLinks[ent] == nil then + self.DisplayLinks[ent] = ent.link + else + self.DisplayLinks[ent] = nil + end + self:SendSync() +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/doors/sv_gameplay.lua b/gamemodes/nzombies/gamemode/doors/sv_gameplay.lua new file mode 100644 index 00000000..b00ef33a --- /dev/null +++ b/gamemodes/nzombies/gamemode/doors/sv_gameplay.lua @@ -0,0 +1,180 @@ +function nzDoors:OpenDoor( ent, ply ) + if !IsValid(ent) then return end + + local data = ent:GetDoorData() + local link = data.link + local rebuyable = data.rebuyable + + -- Open the door and any other door with the same link + if ent:IsScriptBuyable() then + ent.BuyFunction(ply) + if !tobool(rebuyable) then + ent:SetLocked(false) + end + elseif ent:IsButton() then + ent:UnlockButton(tobool(ent.rebuyable)) + else + ent:UnlockDoor() + end + + -- Sync + if link != nil then + self.OpenedLinks[link] = true + end + hook.Call("OnDoorUnlocked", self, ent, link, rebuyable, ply) +end + +function nzDoors:OpenLinkedDoors( link, ply ) + -- Go through all the doors + for k,v in pairs(self.MapDoors) do + if v.flags then + local doorlink = v.flags.link + if doorlink and doorlink == link then + self:OpenDoor( self:DoorIndexToEnt(k), ply ) + end + end + end + + for k,v in pairs(self.PropDoors) do + if v.flags then + local doorlink = v.flags.link + if doorlink and doorlink == link then + self:OpenDoor( Entity(k), ply ) + end + end + end + + self.OpenedLinks[link] = true +end + +function nzDoors:CloseLinkedDoors( link, ply ) + -- Go through all the doors + for k,v in pairs(self.MapDoors) do + if v.flags then + local doorlink = v.flags.link + if doorlink and doorlink == link then + if v:IsButton() then + v:ButtonLock() + v:SetUseType( SIMPLE_USE ) + else + v:SetUseType( SIMPLE_USE ) + v:LockDoor() + v:SetKeyValue("wait",-1) + --print("Locked door ", v) + end + end + end + end + + for k,v in pairs(self.PropDoors) do + if v.flags then + local doorlink = v.flags.link + if doorlink and doorlink == link then + v:SetUseType( SIMPLE_USE ) + v:LockDoor() + end + end + end + + self.OpenedLinks[link] = nil +end + +function nzDoors:LockAllDoors() + -- Force all doors to lock and stay open when opened + for k,v in pairs(ents.GetAll()) do + if (v:IsDoor() or v:IsBuyableProp()) then + -- Only lock doors that have been assigned a price - Prop Dynamics may be tied to invisible func_doors + if self.MapDoors[v:DoorIndex()] or self.PropDoors[v:EntIndex()] then + v:SetUseType( SIMPLE_USE ) + v:LockDoor() + v:SetKeyValue("wait",-1) + print("Locked door ", v) + else + -- Unlocked doors get an output which forces it to stay open once you open it + v:Fire("addoutput", "onclose !self:open::0:-1,0,-1") + v:Fire("addoutput", "onclose !self:unlock::0:-1,0,-1") + print("Added lock output to", v) + -- They now get that output through OpenDoor too, but for safety + end + -- Allow locking buttons + elseif v:IsButton() and self.MapDoors[v:DoorIndex()] then + v:ButtonLock() + v:SetUseType( SIMPLE_USE ) + end + end + self.OpenedLinks = {} + hook.Call("OnAllDoorsLocked", self) +end + +function nzDoors:BuyDoor( ply, ent ) + if ent.lasttime and ent.lasttime + 2 > CurTime() then return end + + local flags = ent:GetDoorData() + if !flags then return end + local price = tonumber(flags.price) + local req_elec = tonumber(flags.elec) or 0 + local link = flags.link + local buyable = flags.buyable or 1 + --print("Entity info buying ", ent, link, req_elec, price, buyable, ent:IsLocked()) + -- If it has a price and it can be bought + if price != nil and tonumber(buyable) == 1 then + ply:Buy(price, ent, function() + if ent:IsLocked() then + -- If this door doesn't require electricity or if it does, then if the electricity is on at the same time + if (req_elec == 0 or (req_elec == 1 and IsElec())) then + --ply:TakePoints(price) + if link == nil then + self:OpenDoor( ent, ply ) + else + self:OpenLinkedDoors( link, ply ) + end + return true + end + end + end) + elseif price == nil and buyable == nil and !ent:IsBuyableProp() then + -- Doors that can be opened because the gamemode doesn't lock them, still need to try and lock upon opening. + -- Additionally, they get the OnClose output added, in case they can still close + ent:UnlockDoor() + end + + ent.lasttime = CurTime() +end + + +-- Hooks + +function nzDoors.OnUseDoor( ply, ent ) + -- Downed players can't use anything! + if !ply:GetNotDowned() then return false end + + -- Players can't use stuff while using special weapons! (Perk bottles, knives, etc) + if IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():IsSpecial() then return false end + + if ent:IsBuyableEntity() then + if ent.buyable == nil or tobool(ent.buyable) then + nzDoors:BuyDoor( ply, ent ) + end + end +end +hook.Add( "PlayerUse", "nzPlayerBuyDoor", nzDoors.OnUseDoor ) + +function nzDoors.CheckUseDoor(ply, ent) + --print(ply, ent) + + local tr = util.QuickTrace(ply:EyePos(), ply:GetAimVector()*100, ply) + local door = tr.Entity + --print(door) + + if IsValid(door) and door:IsDoor() then + return door + else + for k,v in pairs(ents.FindInSphere(ply:EyePos(), 1)) do + if v:GetClass() == "nz_triggerzone" then + return v + end + end + end + +end +hook.Add("FindUseEntity", "nzCheckDoor", nzDoors.CheckUseDoor) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/doors/sv_hooks.lua b/gamemodes/nzombies/gamemode/doors/sv_hooks.lua new file mode 100644 index 00000000..5e65f30d --- /dev/null +++ b/gamemodes/nzombies/gamemode/doors/sv_hooks.lua @@ -0,0 +1,27 @@ +function nzDoors:OnPlayerBuyDoor( ply, door ) + +end + +function nzDoors:OnAllDoorsLocked( ) + self:SendAllDoorsLocked() +end + +function nzDoors:OnDoorUnlocked( door, link, rebuyable, ply ) + self:SendDoorOpened( door, rebuyable ) +end + +function nzDoors:OnMapDoorLinkCreated( door, flags, id ) + self:SendMapDoorCreation(door, flags, id) +end + +function nzDoors:OnMapDoorLinkRemoved( door, id ) + self:SendMapDoorRemoval(door) +end + +function nzDoors:OnPropDoorLinkCreated( ent, flags ) + self:SendPropDoorCreation( ent, flags ) +end + +function nzDoors:OnPropDoorLinkRemoved( ent ) + self:SendPropDoorRemoval( ent ) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/easter_eggs/cl_ee.lua b/gamemodes/nzombies/gamemode/easter_eggs/cl_ee.lua new file mode 100644 index 00000000..58916ea5 --- /dev/null +++ b/gamemodes/nzombies/gamemode/easter_eggs/cl_ee.lua @@ -0,0 +1,93 @@ +if not ConVarExists("nz_eastereggsongs") then CreateClientConVar("nz_eastereggsongs", "1") end + +cvars.AddChangeCallback("nz_eastereggsongs", function( convar_name, value_old, value_new ) + local old, new = tobool(value_old), tobool(value_new) + if old != new then + if new then + EasterEggData.ParseSong(play) + else + EasterEggData.StopSong() + EasterEggData.AudioChannel = nil + end + end +end) + +EasterEggData = EasterEggData or {} +EasterEggData.AudioChannel = EasterEggData.AudioChannel or nil + +net.Receive("EasterEggSong", function() + EasterEggData.PlaySong() +end) + +net.Receive("EasterEggSongPreload", function() + timer.Simple(1, function() + EasterEggData.ParseSong() + end) +end) + +net.Receive("EasterEggSongStop", function() + EasterEggData.StopSong() +end) + +function EasterEggData.ParseSong(play) + if !GetConVar("nz_eastereggsongs"):GetBool() then + print("Prevented loading the Easter Egg song because you have nz_eastereggsongs to 0") + return + end + + if !nzMapping.Settings.eeurl then return end + local url = string.lower(nzMapping.Settings.eeurl) + if url == nil or url == "" then return end + + local soundcloud = string.find(url, "soundcloud.com/") + if !soundcloud then print("Easter Egg Song currently only supports Soundcloud. Make sure you use the full URL to the song.") return end + + http.Fetch( "http://api.soundcloud.com/resolve?url="..url.."&client_id=d8e0407577f7fc8475978904ef89b1f7", + function( body, len, headers, code ) + if body then + local _, streamstart = string.find(body, '"stream_url":"') + if !streamstart then print("This Soundcloud song does not have allow streaming.") return end + local streamend = string.find(body, '","', streamstart + 1) + local stream = string.sub(body, streamstart + 1, streamend - 1) + if stream then + if play then + EasterEggData.PlaySong(stream.."?client_id=d8e0407577f7fc8475978904ef89b1f7") + else + EasterEggData.PreloadSong(stream.."?client_id=d8e0407577f7fc8475978904ef89b1f7") + end + else + print("This Soundcloud song does not have allow streaming.") + end + return end + end, + function( error ) + Error( "Failed to fetch song! Error: " .. error ) + end ) +end + +function EasterEggData.PlaySong(url) + -- We have a preloaded channel + if IsValid(EasterEggData.AudioChannel) then + EasterEggData.AudioChannel:Play() + print("Playing easter egg song!") + -- We need to instantly play the given link + elseif url then + --print("Playing!") + sound.PlayURL( url, "", function(channel) EasterEggData.AudioChannel = channel end) + print("Easter egg song was not preloaded, will play through streaming.") + -- No link and no preload, parse the link and loopback to above + else + EasterEggData.ParseSong(true) + end +end + +function EasterEggData.StopSong() + if IsValid(EasterEggData.AudioChannel) then + EasterEggData.AudioChannel:Stop() + end +end + +function EasterEggData.PreloadSong(song) + sound.PlayURL( song, "noplay noblock", function(channel) EasterEggData.AudioChannel = channel end) + print("Successfully preloaded easter egg song") +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/easter_eggs/sh_constructor.lua b/gamemodes/nzombies/gamemode/easter_eggs/sh_constructor.lua new file mode 100644 index 00000000..cbe8e09f --- /dev/null +++ b/gamemodes/nzombies/gamemode/easter_eggs/sh_constructor.lua @@ -0,0 +1,7 @@ +-- Main Tables +nzEE = nzEE or AddNZModule("EE") +nzEE.Data = nzEE.Data or {} +nzEE.Major = nzEE.Major or {} + +nzEE.Data.EggCount = 0 +nzEE.Data.MaxEggCount = 0 diff --git a/gamemodes/nzombies/gamemode/easter_eggs/sh_ee_camera.lua b/gamemodes/nzombies/gamemode/easter_eggs/sh_ee_camera.lua new file mode 100644 index 00000000..8b9f8716 --- /dev/null +++ b/gamemodes/nzombies/gamemode/easter_eggs/sh_ee_camera.lua @@ -0,0 +1,361 @@ + +if SERVER then + + -- Scroll down to the functions you can use + -- This here is so that the server can follow (for PVS etc) + + nzEE.Cam = nzEE.Cam or {} + util.AddNetworkString("nzEECamera") + + local queue = queue or {} + local nextqueuetime + local curqueueinsert = 0 + + local function NextCamQueue() + local q = queue[1] + if !q then + hook.Remove("Think", "nzEECameraThink") + return + end + + nextqueuetime = RealTime() + q.time + local time = nextqueuetime + local camtime = q.time + + local startpos = q.startpos + local endpos = q.endpos + if startpos and endpos then + local dir = endpos - startpos + hook.Add("SetupPlayerVisibility", "nzEndCameraPVS", function( ply ) + local delta = math.Clamp((time-RealTime())/camtime, 0, 1) + local pos = startpos + dir*delta + AddOriginToPVS(pos) + + if time < RealTime() then + hook.Remove("SetupPlayerVisibility", "nzEndCameraPVS") + end + end) + end + + if q.func then q.func() end + end + + local function StartCamQueue() + PrintTable(queue) + local start = queue[1] + if !start then return end + + nextqueuetime = RealTime() + start.time + NextCamQueue() + + hook.Add("Think", "nzEECameraThink", function() + if RealTime() > nextqueuetime then + table.remove(queue, 1) + curqueueinsert = curqueueinsert - 1 + NextCamQueue() + end + end) + end + + --[[ Functions in here can be queued clientside by running them along QueueView + E.g. doing this: + nzEE.Cam:QueueView(10) + nzEE.Cam:Text("Hey") + nzEE.Cam:QueueView(10) + nzEE.Cam:Text("Hello") + would display "Hey" for 10 seconds and then "Hello" for 10 seconds after a 10 second queue + + If QueueView is called with positional arguements, it will render a moving camera between these positions for this duration + Each view is transitioned by a fade-to-black. If called without positions, just renders from eyes (can be used to queue) + + All other functions run along the previously called QueueView and will be drawn under the fade-to-black + + ply is optional and will run the cameras only on that player - Leave it empty for all players (default) + + ]] + + function nzEE.Cam:QueueView(time, pos1, pos2, angle, fade, scoreboard, ply) + net.Start("nzEECamera") + net.WriteUInt(0, 2) -- Indicates which function is called + net.WriteUInt(time, 8) -- Max 255 seconds (waaay too long anyway) + if pos1 then + net.WriteBool(true) + net.WriteVector(pos1) + if pos2 then + net.WriteBool(true) + net.WriteVector(pos2) + else + net.WriteBool(false) + end + + if angle then + net.WriteBool(true) + net.WriteAngle(angle) + else + net.WriteBool(false) + end + else + net.WriteBool(false) + end + + if fade then net.WriteBool(true) else net.WriteBool(false) end + if scoreboard then net.WriteBool(true) else net.WriteBool(false) end + + curqueueinsert = curqueueinsert + 1 + queue[curqueueinsert] = {time = time} + local q = queue[curqueueinsert] + if pos1 then + q.startpos = pos1 + q.endpos = pos2 or pos1 + end + + return ply and net.Send(ply) or net.Broadcast() + end + + function nzEE.Cam:Text(msg, ply) + if !msg then return end + net.Start("nzEECamera") + net.WriteUInt(1, 2) -- Text + net.WriteString(msg) + return ply and net.Send(ply) or net.Broadcast() + end + + function nzEE.Cam:Music(path, ply) + if !path then return end + net.Start("nzEECamera") + net.WriteUInt(2, 2) -- Music + net.WriteString(path) + return ply and net.Send(ply) or net.Broadcast() + end + + function nzEE.Cam:Begin(ply) + net.Start("nzEECamera") + net.WriteUInt(3, 2) -- Start + StartCamQueue() -- Server needs to follow to add PVS' and run functions + return ply and net.Send(ply) or net.Broadcast() + end + + -- You can use this to set a function to run with this queue + function nzEE.Cam:Function(func) + local q = queue[curqueueinsert] + q.func = func + end + +end + +if CLIENT then + + local queue = queue or {} + local nextqueuetime + local curqueueinsert = 0 + + local function FadeCam() + print("Fading") + local fade = 0 + local fadeup = true + hook.Add("HUDPaint", "nzEECameraFade", function() + fade = fadeup and fade + 255*RealFrameTime() or fade - 255*RealFrameTime() + if fade > 300 then fadeup = false end + surface.SetDrawColor(0,0,0,fade) + surface.DrawRect(0,0,ScrW(),ScrH()) + if fade <= 0 and !fadeup then + hook.Remove("HUDPaint", "nzEECameraFade") + end + end) + end + + local function NextCamQueue() + local q = queue[1] + if !q then + hook.Remove("Think", "nzEECameraThink") + return + end + + nextqueuetime = RealTime() + q.time + local time = nextqueuetime + local camtime = q.time + + local startpos = q.startpos + local endpos = q.endpos + if startpos and endpos then + local dir = endpos - startpos + local ang = q.ang or dir:Angle() + hook.Add("CalcView", "nzEECamera", function(ply, origin, angles, fov, znear, zfar) + if time < RealTime() then + hook.Remove("CalcView", "nzEECamera") + end + + local delta = math.Clamp((time-RealTime())/camtime, 0, 1) + local pos = endpos - dir*delta + + return {origin = pos, angles = ang, drawviewer = true} + end) + hook.Add("CalcViewModelView", "nzEECamera", function(wep, vm, oldpos, oldang, pos, ang) + if time < RealTime() then + hook.Remove("CalcViewModelView", "nzEECamera") + end + + return oldpos - ang:Forward()*50, ang + end) + end + + if q.fade then + local fadestart = nextqueuetime - 1 + hook.Add("Think", "nzEECamera", function() + if fadestart < RealTime() then + FadeCam() + hook.Remove("Think", "nzEECamera") + end + end) + end + + local text = q.text + if text then + local w = ScrW() / 2 + local h = ScrH() / 2 + local font = "DermaLarge" + + hook.Add("HUDPaint", "nzEECamera", function() + draw.SimpleText(text, font, w, h, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + if time < RealTime() then + hook.Remove("HUDPaint", "nzEECamera") + end + end) + end + + local music = q.music + if music then + surface.PlaySound(music) + end + end + + local function StartCamQueue() + PrintTable(queue) + local start = queue[1] + if !start then return end + + nextqueuetime = RealTime() + start.time + NextCamQueue() + + hook.Add("Think", "nzEECameraThink", function() + if RealTime() > nextqueuetime then + table.remove(queue, 1) + curqueueinsert = curqueueinsert - 1 + NextCamQueue() + end + end) + end + + local queuefunctions = { + [0] = function() -- QueueView + local time = net.ReadUInt(8) + + curqueueinsert = curqueueinsert + 1 + queue[curqueueinsert] = {time = time} + local q = queue[curqueueinsert] + + if net.ReadBool() then + local pos1 = net.ReadVector() + local pos2 = nil + + if net.ReadBool() then + pos2 = net.ReadVector() + end + pos2 = pos2 or pos1 + + if net.ReadBool() then + ang = net.ReadAngle() + else + ang = (pos2 - pos1):Angle() + end + + q.startpos = pos1 + q.endpos = pos2 + q.ang = ang + end + + if net.ReadBool() then q.fade = true end + if net.ReadBool() then q.scoreboard = true end + end, + [1] = function() -- Text + local msg = net.ReadString() + + local q = queue[curqueueinsert] + q.text = msg + end, + [2] = function() -- Music + local path = net.ReadString() + + local q = queue[curqueueinsert] + q.music = path + end, + [3] = function() -- Start queue + StartCamQueue() + end + } + + local function ReceiveQueuedCam() + local func = net.ReadUInt(2) + queuefunctions[func]() + end + net.Receive("nzEECamera", ReceiveQueuedCam) + + local function ShowWinScreen() + local easteregg = net.ReadBool() + local win = net.ReadBool() + local msg = net.ReadString() + local camtime = net.ReadFloat() + local time = CurTime() + camtime + local endcam = net.ReadBool() + + local startpos, endpos + if endcam then + startpos = net.ReadVector() + endpos = net.ReadVector() + end + + local w = ScrW() / 2 + local h = ScrH() / 2 + local font = "DermaLarge" + + if endcam and startpos and endpos and time then + local dir = endpos - startpos + local ang = dir:Angle() + hook.Add("CalcView", "nzCalcEndCameraView", function(ply, origin, angles, fov, znear, zfar) + if time < CurTime() then + hook.Remove("CalcView", "nzCalcEndCameraView") + end + + local delta = math.Clamp((time-CurTime())/camtime, 0, 1) + local pos = endpos - dir*delta + + return {origin = pos, angles = ang, drawviewer = true} + end) + hook.Add("CalcViewModelView", "nzCalcEndCameraView", function(wep, vm, oldpos, oldang, pos, ang) + if time < CurTime() then + hook.Remove("CalcViewModelView", "nzCalcEndCameraView") + end + + return oldpos - ang:Forward()*50, ang + end) + end + + hook.Add("HUDPaint", "nzDrawEEEndScreen", function() + draw.SimpleText(msg, font, w, h, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + if time < CurTime() then + hook.Remove("HUDPaint", "nzDrawEEEndScreen") + end + end) + + if easteregg then + if win then + surface.PlaySound(GetGlobalString("winmusic", "nz/easteregg/motd_standard.wav")) + else + surface.PlaySound(GetGlobalString("losemusic", "nz/round/game_over_4.mp3")) + end + end + end + net.Receive("nzMajorEEEndScreen", ShowWinScreen) + + +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/easter_eggs/sv_ee.lua b/gamemodes/nzombies/gamemode/easter_eggs/sv_ee.lua new file mode 100644 index 00000000..31bbd330 --- /dev/null +++ b/gamemodes/nzombies/gamemode/easter_eggs/sv_ee.lua @@ -0,0 +1,53 @@ +// + +function nzEE:Reset() + -- Reset the counter of eggs + self.Data.EggCount = 0 + self.Data.MaxEggCount = 0 + + -- Reset all easter eggs + for k,v in pairs(ents.FindByClass("easter_egg")) do + v.Used = false + end + hook.Call("OnEasterEggsReset") +end + +function nzEE:ActivateEgg( ent, ply ) + + ent.Used = true + ent:EmitSound("WeaponDissolve.Dissolve", 100, 100) + + self.Data.EggCount = self.Data.EggCount + 1 + hook.Call( "OnEasterEggFound", ply, ent ) + + if self.Data.MaxEggCount == 0 then + self.Data.MaxEggCount = #ents.FindByClass("easter_egg") + end + + -- What we should do when we have all the eggs + if self.Data.EggCount == self.Data.MaxEggCount then + print("All easter eggs found yay!") + hook.Call( "OnAllEasterEggsFound", ply, ent ) + end +end + +util.AddNetworkString("EasterEggSong") +util.AddNetworkString("EasterEggSongPreload") +util.AddNetworkString("EasterEggSongStop") + +hook.Add("OnAllEasterEggsFound", "PlayEESong", function() + net.Start("EasterEggSong") + net.Broadcast() +end) + +hook.Add("OnEasterEggsReset", "StopEESong", function() + net.Start("EasterEggSongStop") + net.Broadcast() +end) + +hook.Add("PlayerFullyInitialized", "PreloadEESongSpawn", function(ply) + -- Send players the map settings - this will trigger the preload client-side + net.Start("nzMapping.SyncSettings") + net.WriteTable(nzMapping.Settings) + net.Send(ply) +end) diff --git a/gamemodes/nzombies/gamemode/easter_eggs/sv_major_ee.lua b/gamemodes/nzombies/gamemode/easter_eggs/sv_major_ee.lua new file mode 100644 index 00000000..e1d7244b --- /dev/null +++ b/gamemodes/nzombies/gamemode/easter_eggs/sv_major_ee.lua @@ -0,0 +1,36 @@ +nzEE.Major.Steps = nzEE.Major.Steps or {} +nzEE.Major.CurrentStep = nzEE.Major.CurrentStep or 1 + +function nzEE.Major:AddStep(func, step) + if step and tonumber(step) then + nzEE.Major.Steps[step] = func + else + table.insert(nzEE.Major.Steps, func) + end +end + +function nzEE.Major:SetCurrentStep(step) + nzEE.Major.CurrentStep = step +end + +function nzEE.Major:CompleteStep(step, ...) + if nzEE.Major.CurrentStep == step then + if nzEE.Major.Steps[step] then + print("Completed step "..step) + local args = {...} + nzEE.Major.Steps[step](args) -- Varargs passable if you call Complete Step with more stuff + end + nzEE.Major.CurrentStep = nzEE.Major.CurrentStep + 1 + end +end + +util.AddNetworkString("nzMajorEEEndScreen") + +function nzEE.Major:Reset() + nzEE.Major.CurrentStep = 1 +end + +function nzEE.Major:Cleanup() + nzEE.Major.CurrentStep = 1 + nzEE.Major.Steps = {} +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/effects/cl_electricarcs.lua b/gamemodes/nzombies/gamemode/effects/cl_electricarcs.lua new file mode 100644 index 00000000..f7d894af --- /dev/null +++ b/gamemodes/nzombies/gamemode/effects/cl_electricarcs.lua @@ -0,0 +1,100 @@ + +local mat = Material( "effects/tool_tracer" ) + +local function GenerateArc(startPos, endPos, branchChance, detail, size) + local points = {} + local maxPoints = 2^detail + + if maxPoints % 2 != 0 then + maxPoints = maxPoints + 1 + end + + points[0] = startPos + + local randVec = VectorRand() * 10 + + randVec.z = math.Clamp(randVec.z, 0, 10) + + points[maxPoints] = endPos + randVec + + local i = 1 + + while i < maxPoints do + local j = (maxPoints / i) / 2 + while j < maxPoints do + points[j] = ((points[j - (maxPoints / i) / 2] + points[j + (maxPoints / i) / 2]) / 2); + points[j] = points[j] + VectorRand() * 10 + if math.Rand(0,1) < branchChance then + points[#points + 1] = GenerateArc(points[j], points[j] + Vector(math.random(-50 * branchChance, 50 * branchChance), math.random(-50 * branchChance, 50 * branchChance), math.random(-50 * branchChance, 10 * branchChance)), branchChance/1.3, detail, size) + end + j = j + maxPoints / i + end + i = i * 2 + end + + points.size = math.random(1,3)*size + points.color = Color(200, 240, math.random(230, 255), math.random(200, 255)) + points.dietime = CurTime() + 0.07 + + return points +end + +local function RenderArc(arc) + render.SetMaterial( mat ) + for j = 1, #arc - 1 do + + if istable(arc[j]) then + RenderArc(arc[j]) + elseif !istable(arc[j+1]) then + + local texcoord = math.Rand( 0, 1 ) + + local startPos = arc[j] + local endPos = arc[j + 1] + + render.DrawBeam( + startPos, + endPos, + arc.size, + texcoord, + texcoord + ((startPos - endPos):Length() / 128), + arc.color + ) + end + end +end + +function nzEffects:DrawElectricArcs( entity, epos, normal, effectsize, maxarcs, freq ) + + if !IsValid(entity) then return end + + if !entity.NextElecArc or entity.NextElecArc <= CurTime() then + if !entity.ElecArcs then entity.ElecArcs = {} end + + local size = #entity.ElecArcs + --add a arc to the array + while entity.ElecArcs[size] do + size = size + 1 + end + local norm = VectorRand() + entity.ElecArcs[size] = GenerateArc(epos - norm*effectsize, epos + norm*effectsize, 0.01, 4, effectsize) + entity.NextElecArc = CurTime() + freq + + if size >= maxarcs then + local i = 1 + while not entity.ElecArcs[i] and i <= size do + i = i + 1 + end + entity.ElecArcs[i] = nil + end + end + + for _, arc in pairs(entity.ElecArcs) do + if arc.dietime <= CurTime() then + entity.ElecArcs[_] = nil + else + RenderArc(arc) + end + end + +end diff --git a/gamemodes/nzombies/gamemode/effects/sh_constructor.lua b/gamemodes/nzombies/gamemode/effects/sh_constructor.lua new file mode 100644 index 00000000..5fe35ffd --- /dev/null +++ b/gamemodes/nzombies/gamemode/effects/sh_constructor.lua @@ -0,0 +1 @@ +nzEffects = nzEffects or AddNZModule("Effects") diff --git a/gamemodes/nzombies/gamemode/effects/sv_tesla.lua b/gamemodes/nzombies/gamemode/effects/sv_tesla.lua new file mode 100644 index 00000000..88e3f1ad --- /dev/null +++ b/gamemodes/nzombies/gamemode/effects/sv_tesla.lua @@ -0,0 +1,83 @@ +--Name: Tesla Effect using point_tesla +--Author: Lolle +-- +-- +--Arguments: +-- +--Data Table: +-- +--pos: vector required +-- +--ent: entity required +-- +--radius: float or string def: 50 +-- +--beamcountMin : integer or string def:20 +--beamcountMax : integer or string def:35 +-- +--color: string "r g b" def: 255 255 255 +-- +--texture: string (path to .vmt relative to materials) def: effects/tool_tracer.vmt +-- +--turnOn: boolean def: false (true will periodically emit lightnigs) +-- +--Interval, how often arcs will be emitted (only makes sense with higher dieTime and turnOn = true) +--intervalMin: float (seconds) or string def: 0.5 +--intervalMax: float (seconds) or string def: 0.5 +-- +--dieTime: float (seconds) def: 3 (use nil or false to prevent removal) +-- +--thickMin: float or string def:5 (lighnting thickness) +--thickMax: float or string def 15 +-- +--MakeSure to adjust the dieTime atleast to lifetimeMax*2 +--lifetimeMin: float or string def: 0.3 (lighnting lifetime) +--lifetimeMax: float or string def: 0.55 +-- +--sound: string def: weapons/physcannon/superphys_small_zap1.wav (sound to play on emit) +--Return: +-- +--Returns wether the effect could be created or not +--returns: boolean +-- + +function nzEffects:Tesla( data ) + + local tesla = ents.Create("point_tesla") + + if not IsValid( tesla ) then return false end + tesla:SetPos( data.pos ) + tesla:SetParent( data.ent ) + tesla:SetOwner( data.ent ) + + tesla:SetKeyValue("texture", data.texture and tostring(data.texture) or "trails/electric.vmt") + tesla:SetKeyValue("m_iszSpriteName", "sprites/physbeam.vmt") + tesla:SetKeyValue("m_Color", data.color and tostring(data.color) or "255 255 255") + tesla:SetKeyValue("m_flRadius", data.radius and tostring(data.radius) or "50") + tesla:SetKeyValue("interval_min", data.intevalMin and tostring(data.intervalMin) or "0.5") + tesla:SetKeyValue("interval_max", data.intervalMax and tostring(data.intervalMax) or "0.5") + tesla:SetKeyValue("beamcount_min", data.beamcountMin and tostring(data.beamcountMin) or "20") + tesla:SetKeyValue("beamcount_max", data.beamcountMax and tostring(data.beamcountMax) or "35") + tesla:SetKeyValue("thick_min", data.thickMin and tostring(data.thickMin) or "5") + tesla:SetKeyValue("thick_max", data.thickMax and tostring(data.thickMax) or "15") + tesla:SetKeyValue("lifetime_min", data.lifetimeMin and tostring(data.lifetimeMin) or "0.3") + tesla:SetKeyValue("lifetime_max", data.lifetimeMax and tostring(data.lifetimeMax) or "0.55") + tesla:SetKeyValue("m_SoundName", data.sound and tostring(data.sound) or tostring("weapons/physcannon/superphys_small_zap" .. math.random(1,4) .. ".wav")) + + tesla:Spawn() + tesla:Activate() + + if data.turnOn then + tesla:Fire("TurnOn", "", 0) + else + --emit one spark + tesla:Fire("DoSpark", "", 0) + end + + if data.dieTime then + SafeRemoveEntityDelayed( tesla, data.dieTime or 3 ) + end + + return true + +end diff --git a/gamemodes/nzombies/gamemode/electricity/sh_constructor.lua b/gamemodes/nzombies/gamemode/electricity/sh_constructor.lua new file mode 100644 index 00000000..086fa77e --- /dev/null +++ b/gamemodes/nzombies/gamemode/electricity/sh_constructor.lua @@ -0,0 +1,11 @@ +-- Main Tables +nzElec = nzElec or AddNZModule("Elec") + +-- Variables +nzElec.Active = false + +function nzElec.IsOn() + return nzElec.Active +end + +IsElec = nzElec.IsOn diff --git a/gamemodes/nzombies/gamemode/electricity/sh_sync.lua b/gamemodes/nzombies/gamemode/electricity/sh_sync.lua new file mode 100644 index 00000000..d587c9cd --- /dev/null +++ b/gamemodes/nzombies/gamemode/electricity/sh_sync.lua @@ -0,0 +1,44 @@ +-- Client Server Syncing + +if SERVER then + + -- Server to client (Server) + util.AddNetworkString( "nz.nzElec.Sync" ) + util.AddNetworkString( "nz.nzElec.Sound" ) + + function nzElec:SendSync(ply) + net.Start( "nz.nzElec.Sync" ) + net.WriteBool(self.Active) + return IsValid(ply) and net.Send(ply) or net.Broadcast() + end + + FullSyncModules["Elec"] = function(ply) + nzElec:SendSync(ply) + end + +end + +if CLIENT then + + -- Server to client (Client) + local function ReceiveSync( length ) + local active = net.ReadBool() + nzElec.Active = active + end + + local function RecievePowerSound() + local on = net.ReadBool() + print(on) + if on then + surface.PlaySound("nz/machines/power_up.wav") + else + surface.PlaySound("nz/machines/power_down.wav") + end + end + + -- Receivers + net.Receive( "nz.nzElec.Sync", ReceiveSync ) + net.Receive( "nz.nzElec.Sound", RecievePowerSound ) + + +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/electricity/sv_elec.lua b/gamemodes/nzombies/gamemode/electricity/sv_elec.lua new file mode 100644 index 00000000..16d3c274 --- /dev/null +++ b/gamemodes/nzombies/gamemode/electricity/sv_elec.lua @@ -0,0 +1,86 @@ +-- + +function nzElec:Activate(nochat) + + --if self.Active then return end -- We don't wanna turn it on twice + + self.Active = true + self:SendSync() + + -- Open all doors with no price and electricity requirement + for k,v in pairs(ents.GetAll()) do + if v:IsBuyableEntity() then + local data = v:GetDoorData() + if data then + if tonumber(data.price) == 0 and tobool(data.elec) == true then + nzDoors:OpenDoor( v ) + end + end + end + end + + -- Turn on all perk machines + for k,v in pairs(ents.FindByClass("perk_machine")) do + v:TurnOn() + end + + for k,v in pairs(ents.FindByClass("wunderfizz_machine")) do + v:TurnOff() -- Reset all Wunderfizz's + end + + local wund = ents.FindByClass("wunderfizz_machine") + local machine = wund[math.random(#wund)] + if IsValid(machine) then machine:TurnOn() end + + -- Inform players + if !nochat then + PrintMessage(HUD_PRINTTALK, "[NZ] Electricity is on!") + net.Start("nz.nzElec.Sound") + net.WriteBool(true) + net.Broadcast() + end + + for k,v in pairs(ents.FindByClass("nz_electricity")) do + v:Fire("OnElectricityOn") + end + + hook.Call("ElectricityOn") + +end + +function nzElec:Reset(nochat) + + if !self.Active then return end -- No need to turn it off again + + self.Active = false + -- Reset the button aswell + local prevs = ents.FindByClass("power_box") + for k,v in pairs(prevs) do + v:SetSwitch(false) + end + + -- Turn off all perk machines + for k,v in pairs(ents.FindByClass("perk_machine")) do + v:TurnOff() + end + + -- And Wunderfizz Machines + for k,v in pairs(ents.FindByClass("wunderfizz_machine")) do + v:TurnOff() + end + + self:SendSync() + + if !nochat then + net.Start("nz.nzElec.Sound") + net.WriteBool(false) + net.Broadcast() + end + + for k,v in pairs(ents.FindByClass("nz_electricity")) do + v:Fire("OnElectricityOff") + end + + hook.Call("ElectricityOff") + +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/enemies/sh_constructor.lua b/gamemodes/nzombies/gamemode/enemies/sh_constructor.lua new file mode 100644 index 00000000..d89f51d0 --- /dev/null +++ b/gamemodes/nzombies/gamemode/enemies/sh_constructor.lua @@ -0,0 +1,2 @@ + +nzEnemies = nzEnemies or AddNZModule("Enemies") diff --git a/gamemodes/nzombies/gamemode/enemies/sh_ent_ext.lua b/gamemodes/nzombies/gamemode/enemies/sh_ent_ext.lua new file mode 100644 index 00000000..d888c5e3 --- /dev/null +++ b/gamemodes/nzombies/gamemode/enemies/sh_ent_ext.lua @@ -0,0 +1,170 @@ +TARGET_PRIORITY_NONE = 0 +TARGET_PRIORITY_PLAYER = 1 +TARGET_PRIORITY_SPECIAL = 2 +TARGET_PRIORITY_MAX = 2 +-- Someone could add a new priority level by doing this: +-- TARGET_PRIORITY_CUSTOM = TARGET_PRIORITY_MAX + 1 +-- TARGET_PRIORITY_MAX = TARGET_PRIORITY_MAX + 1 +-- would be limited to 7 custom levels before overwritting TARGET_PRIORITY_ALWAYS, which shoiuld be enough. +TARGET_PRIORITY_ALWAYS = 10 --make this entity a global target (not recommended) + +--WARNING HTIS IS ONLY PARTIALLY SHARED its not recommended to use it clientside. + +local meta = FindMetaTable("Entity") + +function meta:SetIsZombie(value) + self.bIsZombie = value +end + +function meta:SetIsActivatable(value) + self.bIsActivatable = value +end + +function meta:IsActivatable() + return self.bIsActivatable or false +end + +function meta:GetTargetPriority() + return self.iTargetPriority or TARGET_PRIORITY_NONE +end + +function meta:SetTargetPriority(value) + self.iTargetPriority = value +end + +function meta:SetDefaultTargetPriority() + if self:IsPlayer() then + if self:GetNotDowned() and self:IsPlaying() then + self:SetTargetPriority(TARGET_PRIORITY_PLAYER) + else + self:SetTargetPriority(TARGET_PRIORITY_NONE) + end + else + self:SetTargetPriority(TARGET_PRIORITY_NONE) -- By default all entities are non-targetable + end +end + +if SERVER then + function UpdateAllZombieTargets(target) + if IsValid(target) then + for k,v in pairs(ents.GetAll()) do + if nzConfig.ValidEnemies[v:GetClass()] then + v:SetTarget(target) + end + end + end + end + + function meta:ApplyWebFreeze(time) + local block = false + if self.Freeze then + block = self:Freeze(time) -- Return true to not apply effect + else + self.loco:SetDesiredSpeed(0) + timer.Simple(time, function() + if IsValid(self) then + self.WebAura = nil + local speeds = nzRound:GetZombieSpeeds() + if speeds then + self.loco:SetDesiredSpeed( nzMisc.WeightedRandom(speeds) ) + else + self.loco:SetDesiredSpeed( 100 ) + end + end + end) + end + + if block then return end + + local e = EffectData() + e:SetMagnitude(1.5) + e:SetScale(time) -- The time the effect lasts + e:SetEntity(self) + util.Effect("web_aura", e) + --self.WebAura = CurTime() + time + end +end + +local validenemies = {} +function nzEnemies:AddValidZombieType(class) + validenemies[class] = true +end + +function meta:IsValidZombie() + return self.bIsZombie or validenemies[self:GetClass()] != nil +end + +nzEnemies:AddValidZombieType("nz_zombie_walker") +nzEnemies:AddValidZombieType("nz_zombie_special_burning") +nzEnemies:AddValidZombieType("nz_zombie_special_dog") + +function meta:ShouldPhysgunNoCollide() + return self.bPhysgunNoCollide +end + +local base = "nz_zombiebase" +--[[function nzEnemies:NZModNextbot(class, ignore) + local bclass = scripted_ents.get(base) + local tclass = scripted_ents.get(class) + if not tclass or not bclass then return end + + local old = tclass.RunBehaviour + tclass.RunBehaviour = function(self) + + end + + scripted_ents.Register(tclass, class) +end]] + +if SERVER then + local Path = FindMetaTable("PathFollower") + + -- Overwrite Update which moves the bot so that if it hits a barricade, it will attack it + --local update = Path.Update + --function Path:Update(bot) + -- update(self, bot) + + --end + + -- Overwrite Compute so that it computes with nZombies pathfinding if a custom func is not given + local compute = Path.Compute + function Path:Compute(bot, to, func) + compute(self, bot, to, func or function( area, fromArea, ladder, elevator, length ) + if ( !IsValid( fromArea ) ) then + return 0 + else + if ( !bot.loco:IsAreaTraversable( area ) ) then + return -1 + end + -- Prevent movement through either locked navareas or areas with closed doors + if (nzNav.Locks[area:GetID()]) then + if nzNav.Locks[area:GetID()].link then + if !nzDoors:IsLinkOpened( nzNav.Locks[area:GetID()].link ) then + return -1 + end + elseif nzNav.Locks[area:GetID()].locked then + return -1 end + end + -- Compute distance traveled along path so far + local dist = 0 + local cost = dist + fromArea:GetCostSoFar() + --check height change + local deltaZ = fromArea:ComputeAdjacentConnectionHeightChange( area ) + if ( deltaZ >= bot.loco:GetStepHeight() ) then + -- use player default max jump height even thouh teh zombie will jump a bit higher + if ( deltaZ >= 64 ) then + --too high to reach + return -1 + end + --jumping is slower than flat ground + local jumpPenalty = 1.1 + cost = cost + jumpPenalty * dist + elseif ( deltaZ < -bot.loco:GetDeathDropHeight() ) then + --too far to drop + return -1 + end + return cost + end + end) + end +end diff --git a/gamemodes/nzombies/gamemode/enemies/sv_enemies.lua b/gamemodes/nzombies/gamemode/enemies/sv_enemies.lua new file mode 100644 index 00000000..f3355cae --- /dev/null +++ b/gamemodes/nzombies/gamemode/enemies/sv_enemies.lua @@ -0,0 +1,14 @@ +function nzEnemies:TotalAlive() + local c = 0 + + -- Count + for k,v in pairs(nzConfig.ValidEnemies) do + c = c + #ents.FindByClass(k) + end + + return c +end + +function nzEnemies:OnZombieSpawned(zombie, spawnpoint) + +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/enemies/sv_hooks.lua b/gamemodes/nzombies/gamemode/enemies/sv_hooks.lua new file mode 100644 index 00000000..a6dbddfc --- /dev/null +++ b/gamemodes/nzombies/gamemode/enemies/sv_hooks.lua @@ -0,0 +1,125 @@ +local meleetypes = { + [DMG_CLUB] = true, + [DMG_SLASH] = true, + [DMG_CRUSH] = true, +} + +function nzEnemies:OnEnemyKilled(enemy, attacker, dmginfo, hitgroup) + -- Prevent multiple "dyings" by making sure the zombie has not already been "killed" + if enemy.MarkedForDeath then return end + + if attacker:IsPlayer() then + --attacker:GivePoints(90) + attacker:AddFrags(1) + if attacker:HasPerk("vulture") then + if math.random(10) == 1 then + local drop = ents.Create("drop_vulture") + drop:SetPos(enemy:GetPos() + Vector(0,0,50)) + drop:Spawn() + end + end + end + + -- Run on-killed function to give points if the hook isn't blocking it + if !hook.Call("OnZombieKilled", nil, enemy, attacker, dmginfo, hitgroup) then + if enemy:IsValidZombie() then + if attacker:IsPlayer() and attacker:GetNotDowned() then + if meleetypes[dmginfo:GetDamageType()] then + attacker:GivePoints(130) + elseif hitgroup == HITGROUP_HEAD then + attacker:GivePoints(100) + else + attacker:GivePoints(50) + end + end + end + end + + if nzRound:InProgress() then + nzRound:SetZombiesKilled( nzRound:GetZombiesKilled() + 1 ) + + -- Chance a powerup spawning + if !nzPowerUps:IsPowerupActive("insta") and IsValid(enemy) then -- Don't spawn powerups during instakill + if !nzPowerUps:GetPowerUpChance() then nzPowerUps:ResetPowerUpChance() end + if math.Rand(0, 100) < nzPowerUps:GetPowerUpChance() then + nzPowerUps:SpawnPowerUp(enemy:GetPos()) + nzPowerUps:ResetPowerUpChance() + else + nzPowerUps:IncreasePowerUpChance() + end + end + + print("Killed Enemy: " .. nzRound:GetZombiesKilled() .. "/" .. nzRound:GetZombiesMax() ) + if nzRound:IsSpecial() and nzRound:GetZombiesKilled() >= nzRound:GetZombiesMax() then + nzPowerUps:SpawnPowerUp(enemy:GetPos(), "maxammo") + --reset chance here? + end + end + -- Prevent this function from running on this zombie again + enemy.MarkedForDeath = true +end + +function GM:EntityTakeDamage(zombie, dmginfo) + + -- Who's Who clones can't take damage! + if zombie:GetClass() == "whoswho_downed_clone" then return true end + + if zombie.Alive and zombie:Alive() and zombie:Health() < 0 then zombie:Kill(dmginfo) end + + local attacker = dmginfo:GetAttacker() + + if !attacker:IsPlayer() then return end + if IsValid(zombie) then + if zombie.NZBossType then + if zombie.IsInvulnerable and zombie:IsInvulnerable() then return true end -- Bosses can still be invulnerable + + local data = nzRound:GetBossData(zombie.NZBossType) -- Just in case it was switched mid-game, use the id stored on zombie + if data then -- If we got the boss data + local hitgroup = util.QuickTrace( dmginfo:GetDamagePosition(), dmginfo:GetDamagePosition() ).HitGroup + if zombie:Health() > dmginfo:GetDamage() then + if data.onhit then data.onhit(zombie, attacker, dmginfo, hitgroup) end + elseif !zombie.MarkedForDeath then + if data.deathfunc then data.deathfunc(zombie, attacker, dmginfo, hitgroup) end + hook.Call("OnBossKilled", nil, zombie) + zombie.MarkedForDeath = true + end + end + elseif zombie:IsValidZombie() then + if zombie.IsInvulnerable and zombie:IsInvulnerable() then return true end + local hitgroup = util.QuickTrace( dmginfo:GetDamagePosition( ), dmginfo:GetDamagePosition( ) ).HitGroup + + if nzPowerUps:IsPowerupActive("insta") then + zombie:Kill(dmginfo) + nzEnemies:OnEnemyKilled(zombie, attacker, dmginfo, hitgroup) + return end + + + if hitgroup == HITGROUP_HEAD then dmginfo:ScaleDamage(2) end + + -- Pack-a-Punch doubles damage + if dmginfo:GetAttacker():GetActiveWeapon():HasNZModifier("pap") then dmginfo:ScaleDamage(2) end + + if zombie:Health() > dmginfo:GetDamage() then + if zombie.HasTakenDamageThisTick then return end + if attacker:IsPlayer() and attacker:GetNotDowned() and !hook.Call("OnZombieShot", nil, zombie, attacker, dmginfo, hitgroup) then + if dmginfo:GetDamageType() == DMG_CLUB and attacker:HasPerk("widowswine") then + zombie:ApplyWebFreeze(5) + end + attacker:GivePoints(10) + end + zombie.HasTakenDamageThisTick = true + -- Prevent multiple damages in one tick (FA:S 2 Bullet penetration makes them hit 1 zombie 2-3 times per bullet) + timer.Simple(0, function() if IsValid(zombie) then zombie.HasTakenDamageThisTick = false end end) + else + nzEnemies:OnEnemyKilled(zombie, attacker, dmginfo, hitgroup) + end + end + end +end + +local function OnRagdollCreated( ent ) + if ( ent:GetClass() == "prop_ragdoll" ) then + ent:SetCollisionGroup(COLLISION_GROUP_DEBRIS) + end +end +hook.Add("OnEntityCreated", "nzEnemies_OnEntityCreated", OnRagdollCreated) diff --git a/gamemodes/nzombies/gamemode/enemies/sv_spawner.lua b/gamemodes/nzombies/gamemode/enemies/sv_spawner.lua new file mode 100644 index 00000000..7970e628 --- /dev/null +++ b/gamemodes/nzombies/gamemode/enemies/sv_spawner.lua @@ -0,0 +1,173 @@ +-- Class for spawning zombies. This can be used t create different Spawners for different spawnpoints. +-- Warning! Creating multiple instances of this class for the same spawnpoint entity will overwrite prior instances. +-- Author: Lolle + +if Spawner == nil then + Spawner = nzClass({ + -- CONSTRUCTOR + -- sPointClass: The class of spawnpoints this spawner will create entities from. + -- A spawnpoint class should only be used by one spawner at a time. + -- data: information about the entities that are spawned, required are a entity class and chance. + -- zombiesToSpawn: the amount of zombies this type of spawner will spawn in total. + -- spawnDelay: delays the next spawn by the amount set in this value + -- roundNum: the round this spawner was created (after this round teh spawn will be removed) + constructor = function(self, spointClass, data, zombiesToSpawn, spawnDelay, roundNum) + self.sSpointClass = spointClass or "nz_spawn_zombie_normal" + self.tData = data or {["nz_zombie_walker"] = {chance = 100}} + self.iZombiesToSpawn = zombiesToSpawn or 5 + self.tSpawns = ents.FindByClass(self.sSpointClass) + self.tValidSpawns = {} + self:SetDelay(spawnDelay or 0.25) + self:SetNextSpawn(CurTime()) + self:SetZombieData(self.tData) + -- not really sure if this is 100% unique but for our purpose it will be enough + self.sUniqueName = self.sSpointClass .. "." .. CurTime() + self.iRoundNumber = roundNum or nzRound:GetNumber() + self:Activate() + end + }) +end + +AccessorFunc(Spawner, "dDelay", "Delay", FORCE_NUMBER) +AccessorFunc(Spawner, "dNextSpawn", "NextSpawn", FORCE_NUMBER) + +function Spawner:Activate() + for _, spawn in pairs(self.tSpawns) do + spawn:SetSpawner(self) + end + -- curently does the costly zombie distribution 4 seconds can be lowered (without any problems) + timer.Create("nzZombieSpawnThink" .. self.sUniqueName, GetConVar("nz_spawnpoint_update_rate"):GetInt(), 0, function() self:Update() end) +end + +function Spawner:DecrementZombiesToSpawn() + self.iZombiesToSpawn = self.iZombiesToSpawn - 1 +end + +function Spawner:IncrementZombiesToSpawn() + self.iZombiesToSpawn = self.iZombiesToSpawn + 1 +end + +function Spawner:GetZombiesToSpawn() + return nzRound:GetNumber() == -1 and 50 or self.iZombiesToSpawn -- Round Infinity always has 50 zombies to spawn (even after they spawn ;) ) +end + +function Spawner:SetZombiesToSpawn(value) + self.iZombiesToSpawn = value +end + +function Spawner:GetSpawns() + return self.tSpawns +end + +function Spawner:GetData() + return self.tData +end + +function Spawner:Update() + -- garbage collect the spawner object if a round is over + if (self.iRoundNumber != nzRound:GetNumber() or nzRound:InState(ROUND_GO)) and timer.Exists("nzZombieSpawnThink" .. self.sUniqueName) then + self:Remove() + end + + self:UpdateWeights() + self:UpdateValidSpawns() +end + +function Spawner:UpdateWeights() + local plys = player.GetAllTargetable() + for _, spawn in pairs(self.tSpawns) do + -- reset + spawn:SetSpawnWeight(0) + local weight = math.huge + for _, ply in pairs(plys) do + local dist = spawn:GetPos():Distance(ply:GetPos()) + if dist < weight then + weight = dist + end + end + spawn:SetSpawnWeight(10000/weight) -- The spawnweight is inversely related to the distance + -- E.g. Distance = 10, 20, weights = 10000/10, 10000/20 = 1000, 500 + -- We could do 1/weight, but 10000 makes then number easier to read (often around 10-50 depending on the amount of spawns) + end +end + +function Spawner:UpdateValidSpawns() + + if self:GetZombiesToSpawn() <= 0 then return end + + -- reset + self.tValidSpawns = {} + + local average = self:GetAverageWeight() + local total = 0 + for _, spawn in pairs(self.tSpawns) do + -- reset the zombiesToSpawn value on every Spawnpoint + spawn:SetZombiesToSpawn(0) + if spawn:GetSpawnWeight() <= average then + if spawn.link == nil or nzDoors:IsLinkOpened( spawn.link ) then + table.insert(self.tValidSpawns, spawn) + total = total + spawn:GetSpawnWeight() + end + end + end + table.sort(self.tValidSpawns, function(a, b) return a:GetSpawnWeight() < b:GetSpawnWeight() end ) + + local zombiesToSpawn = self:GetZombiesToSpawn() + local numspawns = table.Count(self.tValidSpawns) + + -- distribute zombies to spawn on to the valid spawnpoints + + if numspawns == 1 then -- 1 spawnpoint, give it all the zomblez + local vspawn = self.tValidSpawns[1] + vspawn:SetZombiesToSpawn(zombiesToSpawn) + debugoverlay.Text(vspawn:GetPos() + Vector(0,0,75), "%: 100, #: "..tostring(toSpawn)..", B: "..tostring(vspawn:IsSuitable())..", T: "..math.Round(vspawn:GetNextSpawn()-CurTime(), 2)..", ST: "..(vspawn:GetSpawner() and math.Round(vspawn:GetSpawner():GetNextSpawn() - CurTime(), 2) or "nil"), 4) + else + local totalDistributed = 0 + + for k, vspawn in pairs(self.tValidSpawns) do + local w = vspawn:GetSpawnWeight() -- The weight + if w > 0 then -- 0 weight is disabled (or it'd take all the zombies) + local toSpawn = math.Round((w/total) * zombiesToSpawn) + + if zombiesToSpawn - totalDistributed - toSpawn <= 0 or k == numspawns then -- If we're using more than our total or it's the last one + toSpawn = zombiesToSpawn - totalDistributed -- Then just give the rest + vspawn:SetZombiesToSpawn(toSpawn) + debugoverlay.Text(vspawn:GetPos() + Vector(0,0,75), "W: "..math.Round(w, 2)..", %: "..math.Round((w/total), 2)..", #: "..tostring(toSpawn)..", B: "..tostring(vspawn:IsSuitable())..", T: "..math.Round(vspawn:GetNextSpawn()-CurTime(), 2)..", ST: "..(vspawn:GetSpawner() and math.Round(vspawn:GetSpawner():GetNextSpawn() - CurTime(), 2) or "nil"), 4) + break -- Just stop here, we got no more zombies to distribute + end + + vspawn:SetZombiesToSpawn(toSpawn) + totalDistributed = totalDistributed + toSpawn + debugoverlay.Text(vspawn:GetPos() + Vector(0,0,75), "W: "..math.Round(w, 2)..", %: "..math.Round((w/total), 2)..", #: "..tostring(toSpawn)..", B: "..tostring(vspawn:IsSuitable())..", T: "..math.Round(vspawn:GetNextSpawn()-CurTime(), 2)..", ST: "..(vspawn:GetSpawner() and math.Round(vspawn:GetSpawner():GetNextSpawn() - CurTime(), 2) or "nil"), 4) + end + end + end +end + +function Spawner:GetAverageWeight() + local sum = 0 + for _, spawn in pairs(self.tSpawns) do + sum = sum + spawn:GetSpawnWeight() + end + return ((sum / #self.tSpawns) * 0.5) + 1500 +end + +function Spawner:GetValidSpawns() + return self.tValidSpawns +end + +function Spawner:SetZombieData(data) + for _, spawn in pairs(self.tSpawns) do + spawn:SetZombieData(data) + end +end + +function Spawner:Remove() + timer.Remove("nzZombieSpawnThink" .. self.sUniqueName) + for _, spawn in pairs(self.tSpawns) do + if IsValid(spawn) then + spawn:SetSpawner(nil) + end + end + self = nil +end diff --git a/gamemodes/nzombies/gamemode/function_override/sh_hookorder.lua b/gamemodes/nzombies/gamemode/function_override/sh_hookorder.lua new file mode 100644 index 00000000..a012b055 --- /dev/null +++ b/gamemodes/nzombies/gamemode/function_override/sh_hookorder.lua @@ -0,0 +1,35 @@ +-- Add to this table as more conflicting hook names are found +local hooks = { + "PlayerUse", +} + +-- This rehooks all hooks marked in the above table, making nZ-hooks run first to avoid conflicts +hook.Add("InitPostEntity", "nzReorderHooks", function() + timer.Simple(3, function() + local tbl = hook.GetTable() + for k,v in pairs(hooks) do + local funcs = tbl[v] + if funcs then + local nzfuncs = {} + local nonfuncs = {} + + for k2,v2 in pairs(funcs) do -- Loop through all hooks + if string.sub(k2, 1, 2) == "nz" then -- Store which ones are nZ and which are not + nzfuncs[k2] = v2 + else + nonfuncs[k2] = v2 + end + hook.Remove(v, k2) -- Unhook + end + + -- Now rehook all hooks so the pairs iterator loops through nZ first + for k2,v2 in pairs(nzfuncs) do + hook.Add(v, "_"..k2, v2) -- Prepend _ to make it alphabetically first + end + for k2,v2 in pairs(nonfuncs) do + hook.Add(v, "addon_"..k2, v2) -- Prepend "addon_" to make sure, doesn't actually change anything + end + end + end + end) +end) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/function_override/sh_meta.lua b/gamemodes/nzombies/gamemode/function_override/sh_meta.lua new file mode 100644 index 00000000..9f88b566 --- /dev/null +++ b/gamemodes/nzombies/gamemode/function_override/sh_meta.lua @@ -0,0 +1,268 @@ +local playerMeta = FindMetaTable("Player") +local wepMeta = FindMetaTable("Weapon") + +if SERVER then + + -- Now handled in default weapon modifiers + + --[[function ReplaceReloadFunction(wep) + -- Either not a weapon, doesn't have a reload function, or is FAS2 + if wep:NZPerkSpecialTreatment() then return end + local oldreload = wep.Reload + if !oldreload then return end + + --print("Weapon reload modified") + + wep.Reload = function( self, ... ) + if self.ReloadFinish and self.ReloadFinish > CurTime() then return end + local ply = self.Owner + if ply:HasPerk("speed") then + --print("Hasd perk") + local cur = self:Clip1() + if cur >= self:GetMaxClip1() then return end + local give = self:GetMaxClip1() - cur + if give > ply:GetAmmoCount(self:GetPrimaryAmmoType()) then + give = ply:GetAmmoCount(self:GetPrimaryAmmoType()) + end + if give <= 0 then return end + --print(give) + + self:SendWeaponAnim(ACT_VM_RELOAD) + oldreload(self, ...) + local rtime = self:SequenceDuration(self:SelectWeightedSequence(ACT_VM_RELOAD))/2 + self:SetPlaybackRate(2) + ply:GetViewModel():SetPlaybackRate(2) + + local nexttime = CurTime() + rtime + + self:SetNextPrimaryFire(nexttime) + self:SetNextSecondaryFire(nexttime) + self.ReloadFinish = nexttime + + timer.Simple(rtime, function() + if IsValid(self) and ply:GetActiveWeapon() == self then + self:SetPlaybackRate(1) + ply:GetViewModel():SetPlaybackRate(1) + self:SendWeaponAnim(ACT_VM_IDLE) + self:SetClip1(give + cur) + ply:RemoveAmmo(give, self:GetPrimaryAmmoType()) + self:SetNextPrimaryFire(0) + self:SetNextSecondaryFire(0) + end + end) + else + oldreload(self, ...) + end + end + end + hook.Add("WeaponEquip", "nzModifyWeaponReloads", ReplaceReloadFunction) + + function ReplacePrimaryFireCooldown(wep) + local oldfire = wep.PrimaryAttack + if !oldfire then return end + + --print("Weapon fire modified") + + wep.PrimaryAttack = function(...) + oldfire(wep, ...) + + -- FAS2 weapons have built-in DTap functionality + if wep:IsFAS2() then return end + -- With double tap, reduce the delay for next primary fire to 2/3 + if wep.Owner:HasPerk("dtap") or wep.Owner:HasPerk("dtap2") then + local delay = (wep:GetNextPrimaryFire() - CurTime())*0.80 + wep:SetNextPrimaryFire(CurTime() + delay) + end + end + end + hook.Add("WeaponEquip", "nzModifyWeaponNextFires", ReplacePrimaryFireCooldown)]] + + function ReplaceAimDownSight(wep) + local oldfire = wep.SecondaryAttack + if !oldfire then return end + + --print("Weapon fire modified") + + wep.SecondaryAttack = function(...) + oldfire(wep, ...) + -- With deadshot, aim at the head of the entity aimed at + if wep.Owner:HasPerk("deadshot") then + local tr = wep.Owner:GetEyeTrace() + local ent = tr.Entity + if IsValid(ent) and nzConfig.ValidEnemies[ent:GetClass()] then + local head = ent:LookupBone("ValveBiped.Bip01_Neck1") + if head then + local headpos,headang = ent:GetBonePosition(head) + wep.Owner:SetEyeAngles((headpos - wep.Owner:GetShootPos()):Angle()) + end + end + end + end + end + hook.Add("WeaponEquip", "nzModifyAimDownSights", ReplaceAimDownSight) + + hook.Add("DoAnimationEvent", "nzReloadCherry", function(ply, event, data) + --print(ply, event, data) + if event == PLAYERANIMEVENT_RELOAD then + if ply:HasPerk("cherry") then + local wep = ply:GetActiveWeapon() + if IsValid(wep) and wep:Clip1() < wep:GetMaxClip1() then + local pct = 1 - (wep:Clip1()/wep:GetMaxClip1()) + local pos, ang = ply:GetPos() + ply:GetAimVector()*10 + Vector(0,0,50), ply:GetAimVector() + nzEffects:Tesla( { + pos = ply:GetPos() + Vector(0,0,50), + ent = ply, + turnOn = true, + dieTime = 1, + lifetimeMin = 0.05*pct, + lifetimeMax = 0.1*pct, + intervalMin = 0.01, + intervalMax = 0.02, + }) + --print(pct) + local zombies = ents.FindInSphere(ply:GetPos(), 250*pct) + local d = DamageInfo() + d:SetDamage( 100*pct ) + d:SetDamageType( DMG_SHOCK ) + d:SetAttacker(ply) + d:SetInflictor(ply) + + for k,v in pairs(zombies) do + if nzConfig.ValidEnemies[v:GetClass()] then + v:TakeDamageInfo(d) + end + end + end + end + end + end) + + function GM:GetFallDamage( ply, speed ) + local dmg = speed / 10 + if ply:HasPerk("phd") and dmg >= 50 then + if ply:Crouching() then + local zombies = ents.FindInSphere(ply:GetPos(), 250) + for k,v in pairs(zombies) do + if nzConfig.ValidEnemies[v:GetClass()] then + v:TakeDamage(150, ply, ply) + end + end + local pos = ply:GetPos() + local effectdata = EffectData() + effectdata:SetOrigin( pos ) + util.Effect( "HelicopterMegaBomb", effectdata ) + ply:EmitSound("phx/explode0"..math.random(0, 6)..".wav") + end + return 0 + end + return ( dmg ) + end + + local oldsetwep = playerMeta.SetActiveWeapon + function playerMeta:SetActiveWeapon(wep) + local oldwep = self:GetActiveWeapon() + if IsValid(oldwep) and !oldwep:IsSpecial() then + self.NZPrevWep = oldwep + end + oldsetwep(self, wep) + end + +else + + --[[ Manual speedup of the reload function on FAS2 weapons - seemed like the original solution broke along the way + function ReplaceReloadFunction(wep) + print(wep, "HUKDAHD1") + if wep:IsFAS2() then + print(wep, "HUKDAHD2") + local oldreload = wep.Reload + if !oldreload then return end + print(wep, "HUKDAHD3") + wep.Reload = function() + print(wep, "HUKDAHD4") + oldreload(wep) + if LocalPlayer():HasPerk("speed") then + wep.Wep:SetPlaybackRate(2) + end + end + print(wep, "HUKDAHD5") + end + end + hook.Add("HUDWeaponPickedUp", "ModifyFAS2WeaponReloads", ReplaceReloadFunction)]] + +end + +local olddefreload = wepMeta.DefaultReload +function wepMeta:DefaultReload(act) + if IsValid(self.Owner) and self.Owner:HasPerk("speed") then return end + olddefreload(self, act) +end + +local ghosttraceentities = { + ["wall_block"] = true, + ["invis_wall"] = true, + ["invis_damage_wall"] = true, + ["player"] = true, +} + +function GM:EntityFireBullets(ent, data) + + -- Fire the PaP shooting sound if the weapon is PaP'd + --print(wep, wep:HasNZModifier("pap")) + if ent:IsPlayer() then + local wep = ent:GetActiveWeapon() + if IsValid(wep) and wep:HasNZModifier("pap") and !wep.IsMelee and !wep.IsKnife then + ent:EmitSound("nz/effects/pap_shoot_glock20.wav", 60, 100, 0.7) + end + end + + -- Perform a trace that filters out entities from the table above + --[[local tr = util.TraceLine({ + start = data.Src, + endpos = data.Src + (data.Dir*data.Distance), + filter = function(ent2) + if ghosttraceentities[ent2:GetClass()] then + return false + else + return true + end + end + }) + + --PrintTable(tr) + + -- If we hit anything, move the source of the bullets up to that point + if IsValid(tr.Entity) and tr.Fraction < 1 then + data.Src = tr.HitPos - data.Dir * 5 + return true + end]] + + if ent:IsPlayer() and ent:HasPerk("dtap2") then return true end +end + +-- Ghost invisible walls so nothing but players or NPCs collide with them +local inviswalls = { + ["invis_damage_wall"] = true, + ["invis_wall"] = true, + ["wall_block"] = true, +} +hook.Add("ShouldCollide", "nz_InvisibleBlockFilter", function(ent1, ent2) + if inviswalls[ent1:GetClass()] then + return ent2:IsPlayer() or ent2:IsNPC() + elseif inviswalls[ent2:GetClass()] then + return ent1:IsPlayer() or ent1:IsNPC() + end +end) + +-- This is so awkward ._. +-- game.AddAmmoType doesn't take duplicates into account and has a hardcoded limit of 128 +-- which means our ammo types won't exist if we pass that limit with the countless duplicates :( +local oldaddammo = game.AddAmmoType +local alreadyexist = alreadyexist or {} +function game.AddAmmoType( tbl ) -- Let's prevent that! + if tbl.name and !alreadyexist[tbl.name] then -- Only if the ammo doesn't already exist! + oldaddammo(tbl) -- THEN we can proceed with normal procedure! + alreadyexist[tbl.name] = true + end +end +-- This doesn't work for lua scripts run before the gamemode, but should help for weapons adding ammo types on-the-fly! +-- This will also prevent some ammo types from being added - that's fine. Our gamemode doesn't need them. \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/gamemode_compatibility/sh_zombiesurvival.lua b/gamemodes/nzombies/gamemode/gamemode_compatibility/sh_zombiesurvival.lua new file mode 100644 index 00000000..51619e9d --- /dev/null +++ b/gamemodes/nzombies/gamemode/gamemode_compatibility/sh_zombiesurvival.lua @@ -0,0 +1,197 @@ +function AccessorFuncDT(tab, membername, type, id) + local emeta = FindMetaTable("Entity") + local setter = emeta["SetDT"..type] + local getter = emeta["GetDT"..type] + + tab["Set"..membername] = function(me, val) + setter(me, id, val) + end + + tab["Get"..membername] = function(me) + return getter(me, id) + end +end + +if SERVER then + + util.AddNetworkString("zs_worldhint") + util.AddNetworkString("zs_centernotify") + + local function WorldHint(hint, pos, ent, lifetime, filter) + net.Start("zs_worldhint") + net.WriteString(hint) + net.WriteVector(pos or ent and ent:IsValid() and ent:GetPos() or vector_origin) + net.WriteEntity(ent or NULL) + net.WriteFloat(lifetime or 8) + if filter then + net.Send(filter) + else + net.Broadcast() + end + end + + function nz_zsCenterNotifyAll(...) + local args = {...} + local msg = "" + for k,v in pairs(args) do + local vtype = type(v) + if vtype == "Player" then + msg = msg .. v:Nick() .. " " + elseif vtype == "Entity" then + msg = msg .. "[".. IsValid(v) and v:GetClass() or "?" .."] " + elseif vtype == "table" then + -- nothing + else + msg = msg .. tostring(v) .. " " + end + end + net.Start("zs_centernotify") + net.WriteString(msg) + net.Broadcast() + end + + function nz_zsCenterNotifyPlayer(ply, ...) + local args = {...} + local msg = "" + for k,v in pairs(args) do + local vtype = type(v) + if vtype == "Player" then + msg = msg .. v:Nick() .. " " + elseif vtype == "Entity" then + msg = msg .. "[".. IsValid(v) and v:GetClass() or "?" .."] " + elseif vtype == "table" then + -- nothing + else + msg = msg .. tostring(v) .. " " + end + end + net.Start("zs_centernotify") + net.WriteString(msg) + net.Send(ply) + end + + local meta = FindMetaTable("Entity") + if meta then + function meta:AddOnOutput(key, value) + self[key] = self[key] or {} + local tab = string.Explode(",", value) + table.insert(self[key], {entityname=tab[1], input=tab[2], args=tab[3], delay=tab[4], reps=tab[5]}) + end + + function meta:FireOutput(outpt, activator, caller, args) + local intab = self[outpt] + if intab then + for key, tab in pairs(intab) do + for __, subent in pairs(self:FindByNameHammer(tab.entityname, activator, caller)) do + local delay = tonumber(tab.delay) + if delay == nil or delay <= 0 then + subent:Input(tab.input, activator, caller, tab.args) + else + local inp = tab.input + local args = tab.args + timer.Simple(delay, function() if subent:IsValid() then subent:Input(inp, activator, caller, args) end end) + end + end + end + end + end + + function meta:FindByNameHammer(name, activator, caller) + if name == "!self" then return {self} end + if name == "!activator" then return {activator} end + if name == "!caller" then return {caller} end + return ents.FindByName(name) + end + end + +else + local Hints = {} + + local function DrawPointWorldHints() + for _, ent in pairs(ents.FindByClass("point_worldhint")) do ent:DrawHint() end + end + + local function WorldHint(hint, pos, ent, lifetime) + lifetime = lifetime or 8 + + if ent and ent:IsValid() then + if pos then + pos = ent:WorldToLocal(pos) + else + pos = ent:OBBCenter() + end + end + + local hint = {Hint = hint, Pos = pos, Entity = ent, StartTime = CurTime(), EndTime = CurTime() + lifetime} + table.insert(Hints, hint) + + return hint + end + + net.Receive("zs_worldhint", function(length) + WorldHint(net.ReadString(), net.ReadVector(), net.ReadEntity(), net.ReadFloat()) + end) + + local matRing = Material("effects/select_ring") + local colFG = Color(220, 220, 220, 255) + function DrawWorldHint(hint, pos, delta, scale) + local eyepos = EyePos() + + delta = delta or 1 + + colFG.a = math.min(220, delta * 220) + + local ang = (eyepos - pos):Angle() + ang:RotateAroundAxis(ang:Right(), 270) + ang:RotateAroundAxis(ang:Up(), 90) + + cam.IgnoreZ(true) + cam.Start3D2D(pos, ang, (scale or 1) * math.max(250, eyepos:Distance(pos)) * delta * 0.0005) + + draw.SimpleText("!", "DermaLarge", 0, 0, colFG, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + draw.SimpleText(hint, "DermaLarge", 0, 64, colFG, TEXT_ALIGN_CENTER) + + surface.SetMaterial(matRing) + for i=1, 4 do + colFG.a = colFG.a * (1 / i) + surface.SetDrawColor(colFG) + local pulse = math.max(0.25, math.abs(math.sin(RealTime() * 6))) * 30 * i + surface.DrawTexturedRectRotated(0, 0, 128 + pulse, 128 + pulse, 0) + end + + cam.End3D2D() + cam.IgnoreZ(false) + end + local DrawWorldHint = DrawWorldHint + + local function DrawWorldHints() + if #Hints > 0 then + local curtime = CurTime() + + local done = true + + for _, hint in pairs(Hints) do + local ent = hint.Entity + if curtime < hint.EndTime and not (ent and not ent:IsValid()) then + done = false + + DrawWorldHint(hint.Hint, ent and ent:LocalToWorld(hint.Pos) or hint.Pos, math.Clamp(hint.EndTime - curtime, 0, 1)) + end + end + + if done then + Hints = {} + end + end + end + + hook.Add("PostDrawTranslucentRenderables", "nzDrawZSWorldHints", function() + DrawPointWorldHints() + DrawWorldHints() + end) + + net.Receive("zs_centernotify", function(length) + -- We use the same HUD as the revive notifications + Revive:CustomNotify(net.ReadString(), 10) + end) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/init.lua b/gamemodes/nzombies/gamemode/init.lua new file mode 100644 index 00000000..d25c9ce9 --- /dev/null +++ b/gamemodes/nzombies/gamemode/init.lua @@ -0,0 +1,15 @@ +local plyMeta = FindMetaTable("Player") +FullSyncModules = {} + +function plyMeta:SendFullSync() + -- Modules add their own fullsync functions into this table + for k,v in pairs(FullSyncModules) do + v(self) + end +end + +include( "shared.lua" ) +AddCSLuaFile( "shared.lua" ) + +include( "loader.lua" ) +AddCSLuaFile( "loader.lua" ) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/interfaces/sh_constructor.lua b/gamemodes/nzombies/gamemode/interfaces/sh_constructor.lua new file mode 100644 index 00000000..f7c0b4cc --- /dev/null +++ b/gamemodes/nzombies/gamemode/interfaces/sh_constructor.lua @@ -0,0 +1,5 @@ +-- Main Tables +nzInterfaces = nzInterfaces or AddNZModule("Interfaces") +nzInterfaces.Data = nzInterfaces.Data or {} + +-- Variables \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/interfaces/sh_int_configloader.lua b/gamemodes/nzombies/gamemode/interfaces/sh_int_configloader.lua new file mode 100644 index 00000000..06fc11a4 --- /dev/null +++ b/gamemodes/nzombies/gamemode/interfaces/sh_int_configloader.lua @@ -0,0 +1,765 @@ +if SERVER then + util.AddNetworkString("nzReceiveVotes") + util.AddNetworkString("nzStartVote") + + function nzInterfaces.ConfigLoaderHandler( ply, data ) + if ply:IsSuperAdmin() then + nzMapping:LoadConfig( data.config, ply ) + end + end + + local votetime = votetime or 0 + local votes = votes or {} + local voting = false + local convartime = GetConVar("nz_rtv_time"):GetInt() + local nextvote + if convartime > 0 then + nextvote = nextvote or CurTime() + convartime*60 + end + + function nzInterfaces.StartVote( time, caller ) + local tbl = nzMapping:GetConfigs() + + votes = {} + + for k,v in pairs(tbl.configs) do + votes[v] = 0 + end + for k,v in pairs(tbl.workshopconfigs) do + votes[v] = 0 + end + for k,v in pairs(tbl.officialconfigs) do + votes[v] = 0 + end + + net.Start("nzStartVote") + net.WriteUInt(time, 6) + net.WriteTable(tbl) + net.Broadcast() + + for k,v in pairs(player.GetAll()) do + v.nzConfigVote = nil -- Reset what config they voted on + end + + votetime = CurTime() + time + hook.Add("Think", "nzVoteHandler", function() + if CurTime() > votetime then + local winner = {} + local winvotes = 0 + + for k,v in pairs(votes) do + if v > winvotes then + winner = {k} + winvotes = v + elseif v == winvotes then + table.insert(winner, k) + end + end + + winner = table.Random(winner) + + net.Start("nzReceiveVotes") + net.WriteBool(true) -- We're done voting + net.WriteString(winner) + net.WriteBool(false) -- No one added a vote + net.WriteBool(false) -- No one removed a vote + net.Broadcast() + + hook.Remove("Think", "nzVoteHandler") + timer.Simple(5, function() + voting = false + --PrintMessage(HUD_PRINTTALK, "[nZ] The winner is "..winner) + if nzRound:InProgress() then + PrintMessage(HUD_PRINTTALK, "[nZ] The config will be loaded after the current game.") + nzMapping:QueueConfig( winner, caller ) -- Caller of the vote is responsible for mismatch if done via nz_rtv command + else + nzMapping:LoadConfig( winner, caller ) + end + end) + end + end) + + voting = true + local convartime = GetConVar("nz_rtv_time"):GetInt() + if convartime > 0 then + nextvote = CurTime() + convartime*60 + else + nextvote = nil + end + end + concommand.Add("nz_rtv", function(ply,cmd,args,argstr) + local time = args[1] and tonumber(args[1]) or 30 + nzInterfaces.StartVote(time, ply) + end, nil, "Starts a config vote. Accepts 1 argument: The amount of time to have the vote running. Defaults to 30 seconds.", + FCVAR_SERVER_CAN_EXECUTE) + + local function votechange(newvote, oldvote, ply) + if !voting then return end -- We're not even voting, wut?! + + --print(new, old, ply) + + net.Start("nzReceiveVotes") + net.WriteBool(false) -- We haven't finished yet + if newvote then + if votes[newvote] then + votes[newvote] = votes[newvote] + 1 + end + net.WriteBool(true) -- Vote was added + net.WriteString(newvote) -- This was the vote + else + net.WriteBool(false) + end + if oldvote then + if votes[oldvote] then + votes[oldvote] = votes[oldvote] - 1 + end + net.WriteBool(true) + net.WriteString(oldvote) + else + net.WriteBool(false) + end + net.Broadcast() + + ply.nzConfigVote = newvote + end + + net.Receive("nzReceiveVotes", function(len, ply) + if !voting then return end -- We're not even voting, wut?! + + local newvote = net.ReadString() + local oldvote = ply.nzConfigVote + + votechange(newvote, oldvote, ply) + end) + + local rtvs = rtvs or {} + local rtvcount = rtvcount or 0 + + hook.Add("EntityRemoved", "nzVotePlayerLeft", function(ent) + if ent:IsPlayer() then + votechange(nil, ent.nzConfigVote, ent) + if rtvs[ent] then + rtvcount = rtvcount - 1 + rtvs[ent] = nil + end + end + end) + + hook.Add("OnRoundWaiting", "nzVoteOnRoundEnd", function() + if nextvote and CurTime() >= nextvote and GetConVar("nz_rtv_enabled"):GetBool() then + nzInterfaces.StartVote( 30 ) + end + end) + + + nzChatCommand.Add("/rtv", function(ply, text) + if !GetConVar("nz_rtv_enabled"):GetBool() then return end + if IsValid(ply) then + if voting then + ply:ChatPrint("A vote is already going. Press F1 to open the window.") + else + if !rtvs[ply] then + rtvcount = rtvcount + 1 + rtvs[ply] = true + + local req = math.ceil(#player.GetAll()/2) + PrintMessage(HUD_PRINTTALK, ply:Nick().." has voted to change map. "..rtvcount.."/"..req.." votes.") + if rtvcount >= req then + if nzRound:InState( ROUND_WAITING ) or nzRound:InState( ROUND_CREATE ) then + PrintMessage(HUD_PRINTTALK, "Vote succeeded!") + nzInterfaces.StartVote(30) + else + PrintMessage(HUD_PRINTTALK, "Vote succeeded! Vote will take place at the end of the current game.") + nextvote = CurTime() + end + end + else + ply:ChatPrint("You have already voted to change map.") + end + end + end + end, true, " Vote to change map.") +end + +if CLIENT then + + if not ConVarExists("nz_configloader_fetchworkshop") then CreateConVar("nz_configloader_fetchworkshop", 1, {FCVAR_ARCHIVE}) end + + local maxvote -- Used to calculate the green bars filling them up + + function nzInterfaces.ConfigLoader( data, vote, votetime ) + if vote and IsValid(nzInterfaces.ConfigVoter) then + nzInterfaces.ConfigVoter:Show() -- If players closed the config voter, recalling this func will just reopen it + return + end + + local time = CurTime() + local configs = {} + local selectedconfig + local hoveredpanel + + if data.officialconfigs then + for k,v in pairs(data.officialconfigs) do + local name = string.Explode(";", string.StripExtension(v)) + local map, configname, workshopid = name[1], name[2], name[3] + if name[2] then + local config = {} + config.map = string.sub(map, 4) + config.name = configname + config.config = v + config.official = true + if workshopid then config.workshopid = workshopid end + table.insert(configs, config) + end + end + end + if data.configs then + for k,v in pairs(data.configs) do + local name = string.Explode(";", string.StripExtension(v)) + local map, configname, workshopid = name[1], name[2], name[3] + if name[2] then + local config = {} + config.map = string.sub(map, 4) + config.name = configname + config.config = v + if workshopid then config.workshopid = workshopid end + table.insert(configs, config) + end + end + end + if data.workshopconfigs then + for k,v in pairs(data.workshopconfigs) do + local name = string.Explode(";", string.StripExtension(v)) + local map, configname, workshopid = name[1], name[2], name[3] + if name[2] then + local config = {} + config.map = string.sub(map, 4) + config.name = configname + config.config = v + config.workshop = true + if workshopid then config.workshopid = workshopid end + table.insert(configs, config) + end + end + end + + local DermaPanel = vgui.Create( "DFrame" ) + DermaPanel:SetPos( 100, 100 ) + DermaPanel:SetSize( 400, 500 ) + DermaPanel:SetTitle( vote and "Vote on a config (Press F1 to reopen)" or "Load a config" ) + DermaPanel:SetVisible( true ) + DermaPanel:SetDraggable( true ) + DermaPanel:ShowCloseButton( true ) + DermaPanel:MakePopup() + DermaPanel:Center() + + if vote then + DermaPanel:SetDeleteOnClose(false) + nzInterfaces.ConfigVoter = DermaPanel + end + + local SubmitButton = vgui.Create( "DButton", DermaPanel ) + SubmitButton:SetText( vote and "Click a config to vote" or "Click a config to load" ) + SubmitButton:SetPos( 10, 460 ) + SubmitButton:SetSize( 380, 30 ) + SubmitButton.DoClick = function(self) + if vote then + if selectedconfig != nil and selectedconfig != "" then + net.Start("nzReceiveVotes") + net.WriteString(selectedconfig) + net.SendToServer() + end + else + if selectedconfig != nil and selectedconfig != "" then + if string.find(self:GetText(), "This map is not installed") then + chat.AddText("This map cannot be loaded as it is not installed") + elseif selectedconfig and selectedconfig != "" then + nzInterfaces.SendRequests( "ConfigLoader", {config = selectedconfig} ) + DermaPanel:Close() + end + end + end + end + if vote and time then + SubmitButton.PaintOver = function(self, w, h) + local pct = (CurTime() - time)/votetime + surface.SetDrawColor(100, 100, 255, 150) + surface.DrawRect(0, 0, w*pct, h) + end + end + + local sheet = vgui.Create("DPropertySheet", DermaPanel) + sheet:SetPos(5, 30) + sheet:SetSize(390, 420) + + local ConfigsScroll = vgui.Create("DScrollPanel", sheet) + ConfigsScroll:SetPos(5, 5) + ConfigsScroll:SetSize(380, 420) + sheet:AddSheet("Configs", ConfigsScroll, "icon16/brick.png") + + if !vote then + local OldConfigs = vgui.Create("DListView", sheet) + OldConfigs:SetPos(175, 350) + OldConfigs:SetSize(250, 100) + OldConfigs:SetMultiSelect(false) + OldConfigs:AddColumn("Name") + if data.configs then + for k,v in pairs(data.configs) do + OldConfigs:AddLine(v) + end + end + if data.workshopconfigs then + for k,v in pairs(data.workshopconfigs) do + OldConfigs:AddLine(v) + end + end + if data.officialconfigs then + for k,v in pairs(data.officialconfigs) do + OldConfigs:AddLine(v) + end + end + OldConfigs.OnRowSelected = function(self, index, row) + selectedconfig = row:GetValue(1) + SubmitButton:SetText( " Load config\nWarning: May not work properly without changing map" ) + end + sheet:AddSheet("All config files", OldConfigs, "icon16/database_table.png") + end + + local ConfigList = vgui.Create("DListLayout", ConfigsScroll) + ConfigList:SetPos(0,150) + ConfigList:SetSize(370, 420) + ConfigList:SetPaintBackground(true) + ConfigList:SetBackgroundColor(Color(255,255,255)) + + local CurMapConfigList = vgui.Create("DListLayout", ConfigsScroll) + CurMapConfigList:SetPos(0,0) + CurMapConfigList:SetSize(370, 120) + CurMapConfigList:SetPaintBackground(true) + CurMapConfigList:SetBackgroundColor(Color(255,255,255)) + + for k,v in pairs(configs) do + local config = vgui.Create("DPanel", v.map == game.GetMap() and CurMapConfigList or ConfigList) + config:SetPos(0,0) + config:SetSize(380, 50) + config:SetPaintBackground(true) + config.Paint = function(self, w, h) + + surface.SetDrawColor(255,255,255) + self:DrawFilledRect() + + if vote and maxvote and maxvote > 0 then + local votes = nzInterfaces.ConfigVotes[v.config] + if votes then + if votes > maxvote then maxvote = votes end + surface.SetDrawColor(100,255,100) + surface.DrawRect(0,0, w * votes/maxvote, h) + end + end + + if selectedconfig == v.config then + surface.SetDrawColor(100,100,255,100) + self:DrawFilledRect() + elseif hoveredpanel == k then + surface.SetDrawColor(180,180,255,100) + self:DrawFilledRect() + end + end + --config:SetBackgroundColor(ColorRand()) + + local mapicon = "nzmapicons/nz_"..v.map..";"..v.name..".png" + if ( Material(mapicon):IsError() ) then mapicon = "maps/thumb/" .. v.map .. ".png" end + if ( Material(mapicon):IsError() ) then mapicon = "maps/" .. v.map .. ".png" end + if ( Material(mapicon):IsError() ) then mapicon = "noicon.png" end + + local map = vgui.Create("DImage", config) + map:SetPos(5, 5) + map:SetSize(40, 40) + map:SetImage(mapicon) + + local configname = vgui.Create("DLabel", config) + configname:SetText(v.name) + configname:SetTextColor(Color(20, 20, 20)) + configname:SizeToContents() + configname:SetPos(70, 18) + + local mapname = vgui.Create("DLabel", config) + mapname:SetText(v.map) + mapname:SetTextColor(Color(20, 20, 20)) + mapname:SizeToContents() + mapname:SetPos(180, vote and 11 or 18) + + if vote then + local votecount = vgui.Create("DLabel", config) + votecount:SetText("Votes: 0") + votecount:SetTextColor(Color(200, 20, 20)) + votecount:SizeToContents() + votecount:SetPos(190, 25) + votecount.Think = function(self) + --PrintTable(nzInterfaces.ConfigVotes) + self:SetText("Votes: "..nzInterfaces.ConfigVotes[v.config]) + end + end + + local mapstatus = vgui.Create("DLabel", config) + local status = file.Find("maps/"..v.map..".bsp", "GAME")[1] and true or false + mapstatus:SetText(status and "Map installed" or "Map not installed" ) + mapstatus:SetTextColor(status and Color(20, 200, 20) or Color(200, 20, 20)) + mapstatus:SizeToContents() + mapstatus:SetPos(360 - mapstatus:GetWide(), 12) + + local click = vgui.Create("DButton", config) + click:SetText("") + click:SetPos(0,0) + click:SetSize(380, 50) + click.Paint = function(self) + if self:IsHovered() then hoveredpanel = k end + end + click.DoClick = function(self) + selectedconfig = v.config + if game.GetMap() != v.map and !vote then + SubmitButton:SetText(status and "Change map to "..v.map.." and load" or "This map is not installed") + else + SubmitButton:SetText( vote and "Cast vote" or "Load config" ) + end + -- Doesn't work? :/ + --OldConfigs:SelectItem(nil) + end + + local configlocation = vgui.Create(v.workshopid and "DLabelURL" or "DLabel", config) + if v.workshopid then + configlocation:SetURL("http://steamcommunity.com/sharedfiles/filedetails/?id="..v.workshopid) + -- It isn't underlined? :( + end + configlocation:SetText(v.workshop and "Workshop" or v.official and "Official" or "Local") + configlocation:SetTextColor(v.workshop and Color(150, 20, 100) or v.official and Color(255,0,0) or Color(20, 20, 200)) + configlocation:SizeToContents() + configlocation:SetPos(360 - configlocation:GetWide(), 26) + + local function IsLocalCopy(name) + if configs then + for k2,v2 in pairs(configs) do + if v2.official or v2.workshop then + if v2.name == name then return true end + end + end + end + return false + end + + local maphover = vgui.Create("DButton", config) + maphover:SetText("") + maphover:SetPos(0,0) + maphover:SetSize(50, 50) + maphover.Paint = function(self) + if self:IsHovered() then + hoveredpanel = k + if !IsValid(self.ExtendedInfo) then + self.ExtendedInfo = vgui.Create("DPanel") + self.ExtendedInfo:SetSize(400, 150) + local x, y = self:LocalToScreen(0, 25) + self.ExtendedInfo:SetPos(x - 400, y - 75) + + self.ExtendedInfo.MapIcon = vgui.Create("DImage", self.ExtendedInfo) + self.ExtendedInfo.MapIcon:SetPos(5, 5) + self.ExtendedInfo.MapIcon:SetSize(140, 140) + self.ExtendedInfo.MapIcon:SetImage(mapicon) + + self.ExtendedInfo.Title = vgui.Create("DLabel", self.ExtendedInfo) + self.ExtendedInfo.Title:SetText(v.name) + self.ExtendedInfo.Title:SetTextColor(Color(50,50,50)) + self.ExtendedInfo.Title:SetFont("Trebuchet18") + self.ExtendedInfo.Title:SizeToContents() + self.ExtendedInfo.Title:SetPos(265 - self:GetWide()/2, 10) + + self.ExtendedInfo.CreateLayout = function(self2) + if !IsValid(self2.Msg) then + self2.Msg = vgui.Create("DLabel", self2) + self2.Msg:SetPos(155, 35) + self2.Msg:SetSize(235, 45) + self2.Msg:SetWrap(true) + self2.Msg:SetTextColor(Color(100,100,100)) + end + if !GetConVar("nz_configloader_fetchworkshop"):GetBool() then + self2.Msg:SetText("Set 'nz_configloader_fetchworkshop' to 1 to be able to load metadata from the config's workshop page.") + self2.NoLoad = true + elseif !v.workshop and !v.official then + if IsLocalCopy(v.name) then + self2.Msg:SetText("Local copy of "..v.name..".") + else + self2.Msg:SetText("Local config.") + end + self2.NoLoad = true + elseif !v.workshopid then + self2.Msg:SetText("This config does not have any set Workshop ID to get data from.") + self2.NoLoad = true + else + self2.Msg:SetText("Loading ...") + end + end + + self.ExtendedInfo.UpdateData = function(self2) + if !self2.DataTable then + if !IsValid(self2.Msg) then + self2.Msg = vgui.Create("DLabel", self2) + self2.Msg:SetPos(155, 25) + self2.Msg:SetSize(235, 45) + self2.Msg:SetWrap(true) + self2.Msg:SetTextColor(Color(100,100,100)) + end + self2.Msg:SetText("Failed loading information!") + return end + + if IsValid(self2.Msg) then + self2.Msg:Remove() + end + + if !IsValid(self2.Desc) then + self2.Desc = vgui.Create("DLabel", self2) + self2.Desc:SetPos(155, 25) + self2.Desc:SetSize(235, 45) + self2.Desc:SetWrap(true) + self2.Desc:SetTextColor(Color(100,100,100)) + end + self2.Desc:SetText(self2.DataTable.Description or "No Description found.") + + if !IsValid(self2.MidLine) then + self2.MidLine = vgui.Create("DPanel", self2) + self2.MidLine:SetPos(155, 74) + self2.MidLine:SetSize(235, 2) + self2.MidLine:SetBackgroundColor(Color(225,225,225)) + end + + if !IsValid(self2.SplitLine) then + self2.SplitLine = vgui.Create("DPanel", self2) + self2.SplitLine:SetPos(299, 80) + self2.SplitLine:SetSize(2, 60) + self2.SplitLine:SetBackgroundColor(Color(225,225,225)) + end + + if !IsValid(self2.Creator) then + self2.Creator = vgui.Create("DLabel", self2) + self2.Creator:SetPos(155, 80) + self2.Creator:SetSize(140, 10) + self2.Creator:SetTextColor(Color(100,100,100)) + end + self2.Creator:SetText(self2.DataTable.Creator and "Creator: "..self2.DataTable.Creator or "Creator: N/A") + self2.Creator:SetTooltip(self2.DataTable.Creator or "N/A") + + if !IsValid(self2.Map) then + self2.Map = vgui.Create("DLabel", self2) + self2.Map:SetPos(155, 92) + self2.Map:SetSize(30, 15) + self2.Map:SetTextColor(Color(100,100,100)) + self2.Map:SetText("Map:") + end + + if !IsValid(self2.MapLink) then + self2.MapLink = vgui.Create(self2.DataTable["Map ID"] and "DLabelURL" or "DLabel", self2) + self2.MapLink:SetPos(185, 92) + self2.MapLink:SetSize(110, 15) + self2.MapLink:SetTextColor(self2.DataTable["Map ID"] and Color(50,50,200) or Color(100,100,100)) + self2.MapLink:SetText(v.map) + self2.MapLink:SetTooltip(v.map) + if self2.DataTable["Map ID"] then self2.MapLink:SetURL("http://steamcommunity.com/sharedfiles/filedetails/?id="..self2.DataTable["Map ID"]) end + end + + if !IsValid(self2.ConfigPack) then + self2.ConfigPack = vgui.Create("DLabel", self2) + self2.ConfigPack:SetPos(155, 104) + self2.ConfigPack:SetSize(30, 15) + self2.ConfigPack:SetTextColor(Color(100,100,100)) + self2.ConfigPack:SetText("Pack:") + end + + if !IsValid(self2.ConfigLink) then + self2.ConfigLink = vgui.Create(self2.DataTable["Pack Name"] and "DLabelURL" or "DLabel", self2) + self2.ConfigLink:SetPos(185, 104) + self2.ConfigLink:SetSize(110, 15) + self2.ConfigLink:SetTextColor(self2.DataTable["Pack Name"] and Color(50,50,200) or Color(100,100,100)) + self2.ConfigLink:SetText(self2.DataTable["Pack Name"] or "N/A") + self2.ConfigLink:SetTooltip(self2.DataTable["Pack Name"] or "N/A") + if self2.DataTable["Pack Name"] then self2.ConfigLink:SetURL("http://steamcommunity.com/sharedfiles/filedetails/?id="..v.workshopid) end + end + + if !IsValid(self2.Note) and self2.DataTable["Note"] then + self2.Note = vgui.Create("DLabel", self2) + self2.Note:SetPos(155, 118) + self2.Note:SetSize(140, 30) + self2.Note:SetWrap(true) + self2.Note:SetTextColor(Color(120,120,120)) + self2.Note:SetText(self2.DataTable["Note"]) + self2.Note:SetTooltip(self2.DataTable["Note"]) + end + + if !IsValid(self2.Packs) then + self2.Packs = vgui.Create("DLabel", self2) + self2.Packs:SetPos(320, 80) + self2.Packs:SetSize(60, 15) + self2.Packs:SetTextColor(Color(50,50,50)) + self2.Packs:SetText("Used Packs") + end + + if !IsValid(self2.PackScroll) then + self2.PackScroll = vgui.Create("DScrollPanel", self2) + self2.PackScroll:SetPos(310, 95) + self2.PackScroll:SetSize(80, 50) + self2.PackScroll.Paint = function() end + --print(self2.PackScroll:GetChildren().DVScrollBar) + --PrintTable(self2.PackScroll:GetChildren()) + local scroll = self2.PackScroll:GetChildren()[2] + scroll.Paint = function() end + for k,v in pairs(scroll:GetChildren()) do + v.Paint = function() end + end + end + + if self2.DataTable["Used Packs"] then + local count = 0 + for k,v in pairs(self2.DataTable["Used Packs"]) do + local pack = vgui.Create("DLabelURL", self2.PackScroll) + pack:SetText(k) + pack:SetTooltip(k) + pack:SetURL("http://steamcommunity.com/sharedfiles/filedetails/?id="..v) + pack:SetSize(80, 15) + pack:SetPos(0, count*15) + count = count + 1 + --self2.PackScroll:AddItem(pack) + end + end + + end + + self.ExtendedInfo.Think = function(self2) + if !self2.DataTable and !self2.NoLoad then + self2:CreateLayout() + + if !self2.NoLoad then + if !self2.TimeMark then self2.TimeMark = CurTime() + 0.2 end + if CurTime() > self2.TimeMark then + self2.NoLoad = true + http.Fetch( "http://steamcommunity.com/sharedfiles/filedetails/?id="..v.workshopid, + function( body, len, headers, code ) + --print(body) + local strstart1, strend1 = string.find(body, '{'..v.name..'} = {') + if !strend1 then self2:UpdateData() return end + --print(v.name, strstart1 and string.sub(body, strstart1, strend1 + 50) or "Not found", #body, strstart1, strend1) + local strstart2, strend2 = string.find(body, '{end}', strend1) + if !strend2 then self2:UpdateData() return end + local data = string.sub(body, strend1, strstart2 - 1) + if !data then self2:UpdateData() return end + data = string.Replace(data, """, '"') + data = string.Replace(data, "
", '') + --print(data) + --PrintTable(util.JSONToTable(data)) + self2.DataTable = util.JSONToTable(data) + self2:UpdateData() + + end, + function( error ) + print("Couldn't get information from the workshop! Error: ".. error) + end + ) + end + end + end + end + + self.ExtendedInfo:MakePopup() + elseif !self.ExtendedInfo:IsVisible() then + self.ExtendedInfo:Show() + local x, y = self:LocalToScreen(0, 25) + self.ExtendedInfo:SetPos(x - 400, y - 75) + self.ExtendedInfo:MakePopup() + end + else + if IsValid(self.ExtendedInfo) and !self.ExtendedInfo:IsHovered() and !self.ExtendedInfo:IsChildHovered() and self.ExtendedInfo:IsVisible() then self.ExtendedInfo:Hide() end + end + end + maphover.OnRemove = function(self) + if IsValid(self.ExtendedInfo) then self.ExtendedInfo:Remove() end + end + --[[maphover.DoClick = function(self) + selectedconfig = v.config + if game.GetMap() != v.map then + SubmitButton:SetText(status and "Change map to "..v.map or "This map is not installed") + else + SubmitButton:SetText( "Load config" ) + end + -- Doesn't work? :/ + OldConfigs:SelectItem(nil) + end]] + + end + + local curmapcount = table.Count(CurMapConfigList:GetChildren()) + if curmapcount <= 0 then + local txtpnl = vgui.Create("DPanel", CurMapConfigList) + txtpnl:SetSize(380,50) + + local txt = vgui.Create("DLabel", txtpnl) + txt:SetText("No configs found for the current map.") + txt:SizeToContents() + txt:Center() + txt:SetTextColor(Color(0,0,0)) + curmapcount = 1 + end + ConfigList:SetPos(0,curmapcount*50 + 20) + end + + net.Receive("nzReceiveVotes", function() + maxvote = 0 + + local finished = net.ReadBool() -- Reused later + if finished then -- Vote finished + local config = net.ReadString() + + if IsValid(nzInterfaces.ConfigVoter) then nzInterfaces.ConfigVoter:Remove() end + nzInterfaces.ConfigVotes = nil + config = config and string.Explode(";", string.StripExtension(config))[2] or config or "[INVALID]" + chat.AddText("[nZ] Vote finished! The winning map is ", Color(255,150,150), config..".") + end + + if net.ReadBool() then -- Vote added. This will never be true if the above is true + local config = net.ReadString() + if !nzInterfaces.ConfigVotes then nzInterfaces.ConfigVotes = {} end + if !nzInterfaces.ConfigVotes[config] then nzInterfaces.ConfigVotes[config] = 0 end + + nzInterfaces.ConfigVotes[config] = nzInterfaces.ConfigVotes[config] + 1 + end + + if net.ReadBool() then -- Vote removed. Either from changing vote or disconnecting + local config = net.ReadString() + if nzInterfaces.ConfigVotes[config] then + nzInterfaces.ConfigVotes[config] = nzInterfaces.ConfigVotes[config] - 1 + else + nzInterfaces.ConfigVotes[config] = 0 + end + end + + if !finished then + -- Recalculate every time it's not finished, after votes have changed + for k,v in pairs(nzInterfaces.ConfigVotes) do + if v > maxvote then maxvote = v end + end + end + end) + + net.Receive("nzStartVote", function() + local time = net.ReadUInt(6) + local data = net.ReadTable() + + if IsValid(nzInterfaces.ConfigVoter) then nzInterfaces.ConfigVoter:Remove() end -- Reset it + nzInterfaces.ConfigVotes = {} + for k,v in pairs(data.configs) do + nzInterfaces.ConfigVotes[v] = 0 + end + for k,v in pairs(data.workshopconfigs) do + nzInterfaces.ConfigVotes[v] = 0 + end + for k,v in pairs(data.officialconfigs) do + nzInterfaces.ConfigVotes[v] = 0 + end + maxvote = 0 + nzInterfaces.ConfigLoader(data, true, time) + end) +end diff --git a/gamemodes/nzombies/gamemode/interfaces/sh_int_configsaver.lua b/gamemodes/nzombies/gamemode/interfaces/sh_int_configsaver.lua new file mode 100644 index 00000000..2058321e --- /dev/null +++ b/gamemodes/nzombies/gamemode/interfaces/sh_int_configsaver.lua @@ -0,0 +1,58 @@ +-- + +if SERVER then + util.AddNetworkString("nz_SaveConfig") + + function nzInterfaces.ConfigSaverHandler( ply, data ) + if ply:IsSuperAdmin() then + nzMapping:SaveConfig( data.name ) + end + end +end + +if CLIENT then + function nzInterfaces.ConfigSaver(name) + local DermaPanel = vgui.Create( "DFrame" ) + DermaPanel:SetPos( 100, 100 ) + DermaPanel:SetSize( 300, 120 ) + DermaPanel:SetTitle( "Save config" ) + DermaPanel:SetVisible( true ) + DermaPanel:SetDraggable( true ) + DermaPanel:ShowCloseButton( true ) + DermaPanel:MakePopup() + DermaPanel:Center() + + local WarnText = vgui.Create("DLabel", DermaPanel) + WarnText:SetSize(280, 20) + WarnText:SetPos(10, 50) + WarnText:SetText("") + WarnText:SetTextColor( Color(150,0,0) ) + + local TextEntry = vgui.Create("DTextEntry", DermaPanel) + TextEntry:SetPos(10, 30) + TextEntry:SetSize(280, 20) + TextEntry:SetText(name) + TextEntry.OnChange = function(self) + if string.find(self:GetValue(), ";") then + WarnText:SetText("The name cannot contain ';'!") + else + WarnText:SetText("") + end + end + + local DermaButton = vgui.Create( "DButton", DermaPanel ) + DermaButton:SetText( "Save" ) + DermaButton:SetPos( 10, 80 ) + DermaButton:SetSize( 280, 30 ) + DermaButton.DoClick = function() + local name = TextEntry:GetValue() + nzInterfaces.SendRequests( "ConfigSaver", {name = name} ) + end + end + + net.Receive("nz_SaveConfig", function() + local name = net.ReadString() + nzInterfaces.ConfigSaver(name) + end) + +end diff --git a/nzombies3/gamemode/interfaces/sh_sync.lua b/gamemodes/nzombies/gamemode/interfaces/sh_sync.lua similarity index 57% rename from nzombies3/gamemode/interfaces/sh_sync.lua rename to gamemodes/nzombies/gamemode/interfaces/sh_sync.lua index 6ff4d736..04cc0d93 100644 --- a/nzombies3/gamemode/interfaces/sh_sync.lua +++ b/gamemodes/nzombies/gamemode/interfaces/sh_sync.lua @@ -5,7 +5,7 @@ if SERVER then //Server to client (Server) util.AddNetworkString( "nz.Interfaces.Send" ) - function nz.Interfaces.Functions.SendInterface(ply, interface, data) + function nzInterfaces.SendInterface(ply, interface, data) net.Start( "nz.Interfaces.Send" ) net.WriteString( interface ) net.WriteTable( data ) @@ -15,33 +15,33 @@ if SERVER then //Client to Server (Server) util.AddNetworkString( "nz.Interfaces.Requests" ) - function nz.Interfaces.Functions.ReceiveRequests( len, ply ) + function nzInterfaces.ReceiveRequests( len, ply ) local interface = net.ReadString() local data = net.ReadTable() - nz.Interfaces.Functions[interface.."Handler"](ply, data) + nzInterfaces[interface.."Handler"](ply, data) end //Receivers - net.Receive( "nz.Interfaces.Requests", nz.Interfaces.Functions.ReceiveRequests ) + net.Receive( "nz.Interfaces.Requests", nzInterfaces.ReceiveRequests ) end if CLIENT then //Server to client (Client) - function nz.Interfaces.Functions.ReceiveSync( length ) + function nzInterfaces.ReceiveSync( length ) local interface = net.ReadString() local data = net.ReadTable() - nz.Interfaces.Functions[interface](data) + nzInterfaces[interface](data) end //Receivers - net.Receive( "nz.Interfaces.Send", nz.Interfaces.Functions.ReceiveSync ) + net.Receive( "nz.Interfaces.Send", nzInterfaces.ReceiveSync ) //Client to Server (Client) - function nz.Interfaces.Functions.SendRequests( interface, data ) + function nzInterfaces.SendRequests( interface, data ) net.Start( "nz.Interfaces.Requests" ) net.WriteString( interface ) net.WriteTable( data ) diff --git a/gamemodes/nzombies/gamemode/itemcarrying/cl_hud.lua b/gamemodes/nzombies/gamemode/itemcarrying/cl_hud.lua new file mode 100644 index 00000000..99fd16ff --- /dev/null +++ b/gamemodes/nzombies/gamemode/itemcarrying/cl_hud.lua @@ -0,0 +1,113 @@ +local function DrawItemCarryHud() + + local scale = (ScrW()/1920 + 1)/2 + local ply = LocalPlayer() + surface.SetDrawColor(255,255,255) + local num = 0 + for k,v in pairs(ply:GetCarryItems()) do + local item = nzItemCarry.Items[v] + if item then + if item.model then + surface.SetMaterial(item.model) + surface.DrawTexturedRect(ScrW() - 400*scale - num*40*scale, ScrH() - 90*scale, 30*scale, 30*scale) + if item.icon then + surface.SetMaterial(item.icon) + surface.DrawTexturedRect(ScrW() - 384*scale - num*40*scale, ScrH() - 90*scale, 16*scale, 16*scale) + end + elseif item.icon then + surface.SetMaterial(item.icon) + surface.DrawTexturedRect(ScrW() - 400*scale - num*40*scale, ScrH() - 90*scale, 30*scale, 30*scale) + end + num = num + 1 + end + end + +end + +local itemnotif = itemnotif or {} + +net.Receive( "nzItemCarryPlayersNotif", function() + local ply = net.ReadEntity() + local id = net.ReadString() + + if itemnotif[id] then + itemnotif[id].time = CurTime() + 5 + if IsValid(itemnotif[id].avatar) then + if IsValid(ply) then + itemnotif[id].avatar:SetPlayer(ply) + else + itemnotif[id].avatar:Remove() + itemnotif[id].avatar = nil + end + else + if IsValid(ply) then + itemnotif[id].avatar = vgui.Create("AvatarImage") + itemnotif[id].avatar:SetSize( 32, 32 ) + itemnotif[id].avatar:SetPos( 0, 0 ) + itemnotif[id].avatar:SetPlayer( ply, 32 ) + end + end + else + local item = nzItemCarry.Items[id] + local avatar + if IsValid(ply) then + avatar = vgui.Create("AvatarImage") + avatar:SetSize( 32, 32 ) + avatar:SetPos( 0, 0 ) + avatar:SetPlayer( ply, 32 ) + end + if item then --and item.notif then + itemnotif[id] = { + avatar = avatar, + time = CurTime() + 5, + } + end + end + + surface.PlaySound("nz/easteregg/ee_item_grab1.wav") +end) + +local function DrawItemCarryNotifications() + --local scale = (ScrW()/1920 + 1)/2 + surface.SetDrawColor(255,255,255) + local num = 0 + for k,v in pairs(itemnotif) do + local item = nzItemCarry.Items[k] + if item and (item.icon or item.model) then + local avatar = v.avatar + local time = v.time + if time < CurTime() then + local fade = (1-(CurTime()-time))*255 + surface.SetDrawColor(255,255,255, fade) + if fade <= 0 then + itemnotif[k] = nil + if IsValid(avatar) then + avatar:Remove() + end + end + end + + local x = ScrW() - 96 - num*66 + + if item.model then + surface.SetMaterial(item.model) + surface.DrawTexturedRect(x, 32, 64, 64) + if item.icon then + surface.SetMaterial(item.icon) + surface.DrawTexturedRect(x+48, 26, 16, 16) + end + else + surface.SetMaterial(item.icon) + surface.DrawTexturedRect(x, 32, 64, 64) + end + + if IsValid(avatar) then + avatar:SetPos(x + 32, 75) + end + num = num + 1 + end + end +end + +hook.Add("HUDPaint", "nzItemCarryHUD", DrawItemCarryHud ) +hook.Add("HUDPaint", "nzItemCarryNotifications", DrawItemCarryNotifications ) diff --git a/gamemodes/nzombies/gamemode/itemcarrying/sh_constructor.lua b/gamemodes/nzombies/gamemode/itemcarrying/sh_constructor.lua new file mode 100644 index 00000000..4737b844 --- /dev/null +++ b/gamemodes/nzombies/gamemode/itemcarrying/sh_constructor.lua @@ -0,0 +1,117 @@ +-- Main Tables +nzItemCarry = nzItemCarry or AddNZModule("ItemCarry") +nzItemCarry.Items = nzItemCarry.Items or {} +nzItemCarry.Players = nzItemCarry.Players or {} + +if SERVER then + local baseitem = { + id = nil, + items = {}, + text = nil, -- Nil makes default texts + hastext = nil, + icon = "", -- Icon, if model is set this is drawn on top in the corner, otherwise just this + model = nil, -- Model of the spawnicon, if not set the icon takes its place + shared = false, + dropondowned = true, + dropfunction = function(self, ply) + --if ply:IsCarryingItem( + end, + resetfunction = function() end, + condition = function(self, ply) + return !ply:HasCarryItem(self.id) + end, + pickupfunction = function(self, ply, ent) + ply:GiveCarryItem(self.id) + ent:Remove() + end, + notif = true, + } + + -- Functions to call during runtime + local nzItemMeta = { + -- Adds an entity so it can be picked up + RegisterEntity = function(self, ent) + if !table.HasValue(self.items, ent) then + -- First check if it already belongs somewhere + local id = ent:GetNWString("NZItemCategory") + if id != "" then + local item = nzItemCarry.Items[id] + -- If so, remove it from there + if item and item.items and table.HasValue(item.items, ent) then + table.RemoveByValue(item.items, ent) + end + end + -- Now add it to the new category + ent:SetNWString("NZItemCategory", self.id) + table.insert(self.items, ent) + end + end, + -- Sets the text displayed when looking at an entity with this + SetText = function(self, text) + self.text = text + end, + -- Sets the text to be displayed when looking at it while you already have it + SetHasText = function(self, text) + self.hastext = text + end, + -- Sets the icon displayed in the corner of the spawnicon, or fully if no model was provided + SetIcon = function(self, iconpath) + self.icon = iconpath + end, + -- Sets the model displayed the spawnicon for on HUD and scoreboard + SetModel = function(self, model) + self.model = model and string.StripExtension(model) or nil + end, + -- Sets whether all players "has" the item when it is picked up + SetShared = function(self, bool) + self.shared = bool + end, + -- Sets whether to run the Drop Function when a player is downed with the item + SetDropOnDowned = function(self, bool) + self.dropondowned = bool + end, + -- Sets the function to run when downed; has 1 argument: The player getting downed + SetDropFunction = function(self, func) + self.dropfunction = func + end, + -- Sets the function to run to reset; happens when a player disconnects without Drop On Downed on or when self:Reset() is called + SetResetFunction = function(self, func) + self.resetfunction = func + end, + -- Sets the function to determine if a player can pick it up; return true to allow + -- It will always be blocked if the player is already carrying this category + SetCondition = function(self, func) + self.condition = func + end, + -- Sets the function to be run when picked up; has 2 arguments: The player picking it up, the entity being used + SetPickupFunction = function(self, func) + self.pickupfunction = func + end, + -- Sets whether this item will display a notification to all players when picked up + SetShowNotification = function(self, bool) + self.notif = bool + end, + -- Sets the function to reset the item(s). Typically used to respawn them back at the original spot + Reset = function(self) + self:resetfunction() + end, + -- Returns a table of all entities registered in this category + GetEntities = function(self) + return self.items + end, + -- Call this to send the info to clients; do this after all changes + Update = function(self) + nzItemCarry:SendObjectCreated(self.id) + end, + } + nzItemMeta.__index = nzItemMeta + + function nzItemCarry:CreateCategory(id) + local tbl = table.Copy(baseitem) + tbl.id = id + setmetatable(tbl, nzItemMeta) + self.Items[id] = tbl + + return self.Items[id] + end +end diff --git a/gamemodes/nzombies/gamemode/itemcarrying/sh_itemusetime.lua b/gamemodes/nzombies/gamemode/itemcarrying/sh_itemusetime.lua new file mode 100644 index 00000000..e1e50d20 --- /dev/null +++ b/gamemodes/nzombies/gamemode/itemcarrying/sh_itemusetime.lua @@ -0,0 +1,105 @@ + +if CLIENT then + local timeusetime = nil + local completetime = nil + + local function DrawUseProgress() + local time = timeusetime + local ctime = completetime + if !time or !ctime then return end + + surface.SetDrawColor(0,0,0) + surface.DrawRect(ScrW()/2 - 150, ScrH() - 300, 300, 20) + surface.SetDrawColor(255,255,255) + + if time < CurTime() then + surface.DrawRect(ScrW()/2 - 145, ScrH() - 295, 290 * (1-(completetime - CurTime())/time), 10) + else + surface.DrawRect(ScrW()/2 - 145, ScrH() - 295, 290, 10) + end + end + hook.Add("HUDPaint", "nzItemUseTimeDrawProgress", DrawUseProgress) + + net.Receive("nzTimedUse", function() + local start = net.ReadBool() + if start then + local time = net.ReadFloat() + print(time) + timeusetime = time + completetime = CurTime() + time + else + timeusetime = nil + completetime = nil + end + end) +end + +if SERVER then + local function DetermineItemUseTime(ply, ent) + if ent.RelayUse then ent = ent.RelayUse end -- If we relay uses, we refer to the relay entity + + if ply.TimedUseEntity then + if ply.TimedUseEntity == ent and !ply:KeyReleased(IN_USE) then + if ply.TimedUseComplete < CurTime() then + ply:FinishTimedUse() + end + else + ply:StopTimedUse() + end + end + + if IsValid(ent) and ent.StartTimedUse then + if ply:KeyPressed(IN_USE) then + ply:StartTimedUse(ent) + end + return false + end + end + hook.Add( "FindUseEntity", "nzItemUseTime", DetermineItemUseTime ) + + local meta = FindMetaTable("Player") + util.AddNetworkString("nzTimedUse") + + function meta:StartTimedUse(ent) + if IsValid(self.TimedUseEntity) then self:StopTimedUse() end + + local time = ent:StartTimedUse(self, self, USE_OFF, 0) + if time then + self.TimedUseEntity = ent + self.TimedUseComplete = CurTime() + time + + net.Start("nzTimedUse") + net.WriteBool(true) + net.WriteFloat(time) + net.Send(self) + end + end + + function meta:StopTimedUse() + local ent = self.TimedUseEntity + if !IsValid(ent) then return end + + ent:StopTimedUse(self, self, USE_OFF, 0) + self.TimedUseEntity = nil + self.TimedUseEntity = nil + + net.Start("nzTimedUse") + net.WriteBool(false) + net.Send(self) + end + + function meta:FinishTimedUse() + local ent = self.TimedUseEntity + if !IsValid(ent) then return end + + ent:FinishTimedUse(self, self, USE_ON, 0) -- Imitate ENTITY:Use arguments + self.TimedUseEntity = nil + self.TimedUseComplete = nil + + net.Start("nzTimedUse") + net.WriteBool(false) + net.Send(self) + end + +end + diff --git a/gamemodes/nzombies/gamemode/itemcarrying/sh_meta.lua b/gamemodes/nzombies/gamemode/itemcarrying/sh_meta.lua new file mode 100644 index 00000000..412372e9 --- /dev/null +++ b/gamemodes/nzombies/gamemode/itemcarrying/sh_meta.lua @@ -0,0 +1,81 @@ +local playerMeta = FindMetaTable("Player") +if SERVER then + + function playerMeta:GiveCarryItem(id, alloverride) + if !nzItemCarry.Players[self] then nzItemCarry.Players[self] = {} end + if nzItemCarry.Items[id].shared and !alloverride then -- If shared, give to all players + for k,v in pairs(player.GetAllPlaying()) do + if !table.HasValue(nzItemCarry.Players[v], id) then + table.insert(nzItemCarry.Players[v], id) + end + end + nzItemCarry:SendPlayerItem() + if nzItemCarry.Items[id].notif then + nzItemCarry:SendPlayerItemNotification(nil, id) + end + else + if !table.HasValue(nzItemCarry.Players[self], id) then + table.insert(nzItemCarry.Players[self], id) + nzItemCarry:SendPlayerItem(self) + if nzItemCarry.Items[id].notif then + nzItemCarry:SendPlayerItemNotification(self, id) + end + end + end + end + + function playerMeta:RemoveCarryItem(id, alloverride) + if !nzItemCarry.Players[self] then nzItemCarry.Players[self] = {} end + if nzItemCarry.Items[id].shared and !alloverride then -- If shared, remove from all players + for k,v in pairs(player.GetAllPlaying()) do + if table.HasValue(nzItemCarry.Players[v], id) then + table.RemoveByValue(nzItemCarry.Players[v], id) + end + end + nzItemCarry:SendPlayerItem() + else + if table.HasValue(nzItemCarry.Players[self], id) then + table.RemoveByValue(nzItemCarry.Players[self], id) + nzItemCarry:SendPlayerItem(self) + end + end + end + +end + +function playerMeta:HasCarryItem(id) + if !nzItemCarry.Players[self] then nzItemCarry.Players[self] = {} end + return table.HasValue(nzItemCarry.Players[self], id) +end + +function playerMeta:GetCarryItems() + if !nzItemCarry.Players[self] then nzItemCarry.Players[self] = {} end + return nzItemCarry.Players[self] +end + +-- On player downed +hook.Add("PlayerDowned", "nzDropCarryItems", function(ply) + if ply.GetCarryItems then + for k,v in pairs(ply:GetCarryItems()) do + local item = nzItemCarry.Items[v] + if item.dropondowned and item.dropfunction then + item:dropfunction(ply) + ply:RemoveCarryItem(v) + end + end + end +end) + +-- Players disconnecting/dropping out need to reset the item so it isn't lost forever +hook.Add("OnPlayerDropOut", "nzResetCarryItems", function(ply) + for k,v in pairs(ply:GetCarryItems()) do + local item = nzItemCarry.Items[v] + if item.dropondowned and item.dropfunction then + item:dropfunction(ply) + else + item:resetfunction() + end + end + nzItemCarry.Players[ply] = nil + nzItemCarry:SendPlayerItem() -- No arguments for full sync, cleans the table of this disconnected player +end) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/itemcarrying/sh_sync.lua b/gamemodes/nzombies/gamemode/itemcarrying/sh_sync.lua new file mode 100644 index 00000000..8b45271c --- /dev/null +++ b/gamemodes/nzombies/gamemode/itemcarrying/sh_sync.lua @@ -0,0 +1,145 @@ +-- Client Server Syncing + +if SERVER then + + -- Server to client (Server) + util.AddNetworkString( "nzItemCarryUpdate" ) + util.AddNetworkString( "nzItemCarryPlayers" ) + util.AddNetworkString( "nzItemCarryPlayersFull" ) + util.AddNetworkString( "nzItemCarryPlayersNotif" ) + util.AddNetworkString( "nzItemCarryClean" ) + + function nzItemCarry:SendObjectCreated(id, receiver) + if !id then return end + local data = nzItemCarry.Items[id] + local tbl = { + id = data.id, + text = data.text, + hastext = data.hastext, + icon = data.icon, + model = data.model, + } + + net.Start( "nzItemCarryUpdate" ) + net.WriteString(id) + net.WriteTable(tbl) + return receiver and net.Send(receiver) or net.Broadcast() + end + + function nzItemCarry:SendPlayerItem(ply, receiver) + if IsValid(ply) then + local data = nzItemCarry.Players[ply] + net.Start( "nzItemCarryPlayers" ) + net.WriteEntity(ply) + net.WriteTable( data ) + return receiver and net.Send(receiver) or net.Broadcast() + else + local data = nzItemCarry.Players + net.Start( "nzItemCarryPlayersFull" ) + net.WriteTable( data ) + return receiver and net.Send(receiver) or net.Broadcast() + end + end + + -- This one is received in cl_hud.lua + function nzItemCarry:SendPlayerItemNotification(ply, id, receiver) + local item = nzItemCarry.Items[id] + if item then --and item.notif then + if item.shared then + net.Start( "nzItemCarryPlayersNotif" ) + net.WriteEntity(NULL) + net.WriteString( id ) + return receiver and net.Send(receiver) or net.Broadcast() + else + net.Start( "nzItemCarryPlayersNotif" ) + net.WriteEntity(ply) + net.WriteString( id ) + return receiver and net.Send(receiver) or net.Broadcast() + end + end + end + + function nzItemCarry:CleanUp() + nzItemCarry.Items = {} + nzItemCarry.Players = {} + + net.Start( "nzItemCarryClean" ) + net.Broadcast() + end + + FullSyncModules["ItemCarry"] = function(ply) + for k,v in pairs(nzItemCarry.Items) do + nzItemCarry:SendObjectCreated(k, ply) + end + nzItemCarry:SendPlayerItem(nil, ply) -- No specific target, all players + end + +end + +if CLIENT then + + -- Server to client (Client) + local generatingicons = {} + hook.Add("SpawniconGenerated", "nzItemCarryIconGeneration", function(model, path, left) + if generatingicons[model] then + if IsValid(generatingicons[model].vgui) then + generatingicons[model].vgui:Remove() + end + if generatingicons[model].item then + generatingicons[model].item.model = Material(path) + end + generatingicons[model] = nil + print("Generated icon for "..model, path) + end + end) + + local function ReceiveItemObject( length ) + local id = net.ReadString() + local data = net.ReadTable() + + -- Precache the material here + --print(data.icon) + if data.icon and data.icon != "" then data.icon = Material(data.icon) else data.icon = nil end + + if data.model and data.model != "" then + local model = data.model..".mdl" + data.model = Material("spawnicons/"..data.model..".png") + if data.model:IsError() and (!generatingicons[model] or !IsValid(generatingicons[model].vgui)) then + local s = vgui.Create("SpawnIcon") + s:SetModel(model) + generatingicons[model] = {vgui = s, item = data} + end + else + data.model = nil + end + + nzItemCarry.Items[id] = data + --PrintTable(nzItemCarry.Items[id]) + end + + local function ReceiveItemPlayer( length ) + local ply = net.ReadEntity() + local data = net.ReadTable() + + nzItemCarry.Players[ply] = data + --PrintTable(nzItemCarry.Players[ply]) + end + + local function ReceiveItemPlayerFull( length ) + local data = net.ReadTable() + + nzItemCarry.Players = data + --PrintTable(nzItemCarry.Players) + end + + local function ReceiveItemCleanup( length ) + nzItemCarry.Players = {} + nzItemCarry.Items = {} + end + + -- Receivers + net.Receive( "nzItemCarryUpdate", ReceiveItemObject ) + net.Receive( "nzItemCarryPlayers", ReceiveItemPlayer ) + net.Receive( "nzItemCarryPlayersFull", ReceiveItemPlayerFull ) + net.Receive( "nzItemCarryClean", ReceiveItemCleanup ) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/itemcarrying/sv_gameplay.lua b/gamemodes/nzombies/gamemode/itemcarrying/sv_gameplay.lua new file mode 100644 index 00000000..299418bf --- /dev/null +++ b/gamemodes/nzombies/gamemode/itemcarrying/sv_gameplay.lua @@ -0,0 +1,53 @@ + +function nzItemCarry.OnPlayerPickItemUp( ply, ent ) + -- Downed players can't pick up anything! + if !ply:GetNotDowned() then return false end + + -- Players can't pick stuff up while using special weapons! (Perk bottles, knives, etc) + if IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():IsSpecial() then return false end + + -- Used in map scripting + if ent.OnUsed and type(ent.OnUsed) == "function" then + if ply:KeyPressed(IN_USE) then + ent:OnUsed(ply) + end + end + + local category = ent:GetNWString("NZItemCategory") + if category != "" then + local item = nzItemCarry.Items[category] + if item.pickupfunction and item:condition(ply) then -- If it has a pickup function and it is allowed in this case + --print("allowed") + item:pickupfunction(ply, ent) + end + end +end +hook.Add( "PlayerUse", "nzPlayerPickupItems", nzItemCarry.OnPlayerPickItemUp ) + +function nzItemCarry.RemoveItemsOnRemoved( ent ) + local item = nzItemCarry.Items[ent:GetNWString("NZItemCategory")] + if item and item.items and table.HasValue(item.items, ent) then + table.RemoveByValue(item.items, ent) + end +end +hook.Add( "EntityRemoved", "nzItemCarryRemoveItems", nzItemCarry.RemoveItemsOnRemoved ) + +-- These correctly obey Use types (SIMPLE_USE etc.) by directly injecting into ENTITY:Use() + +local meta = FindMetaTable("Entity") +function meta:AddUseFunction( func ) + local olduse = self.Use + if olduse then + self.Use = function(self2,a,b,c,d) + olduse(self2,a,b,c,d) + func(self2,a,b,c,d) + end + else + self:ReplaceUseFunction(func) + end +end +function meta:ReplaceUseFunction( func ) + self.Use = function(self2,a,b,c,d) + func(self2,a,b,c,d) + end +end \ No newline at end of file diff --git a/nzombies3/gamemode/loader.lua b/gamemodes/nzombies/gamemode/loader.lua similarity index 67% rename from nzombies3/gamemode/loader.lua rename to gamemodes/nzombies/gamemode/loader.lua index ab2ad076..bcd1338a 100644 --- a/nzombies3/gamemode/loader.lua +++ b/gamemodes/nzombies/gamemode/loader.lua @@ -1,26 +1,31 @@ -//Load all our files in to the respective realms +-- Load all our files in to the respective realms -//Main Tables -nz = {} +-- Main Tables +nz = nz or {} +function AddNZModule(id) + local tbl = {} + --nz[id] = tbl -- Enabling this line will make all tables parented to nz again + return tbl +end -local gmfolder = "nzombies3" +local gmfolder = "nzombies" local _,dirs = file.Find( gmfolder.."/gamemode/*", "LUA" ) -print("nZombies 3.0 Loading...") +print("nZombies Loading...") function AutoInclude(name, dir) local sep = string.Explode("_", name) name = dir..name - + if sep[1] == "cl" and SERVER then print("Sending: "..name) else print("Including: "..name) end - - // Determine where to load the files + + -- Determine where to load the files if sep[1] == "sv" then if SERVER then include(name) @@ -39,29 +44,26 @@ function AutoInclude(name, dir) include(name) end end - + end -//Run this on both client and server +-- Run this on both client and server if SERVER then print(" ** Server List **") else print(" ** Client List **") end for k,v in pairs(dirs) do local f2,d2 = file.Find( gmfolder.."/gamemode/"..v.."/*", "LUA" ) - - //Load construction file before everything else + + -- Load construction file before everything else if table.HasValue(f2, "sh_constructor.lua") then print("Constructing: " .. v) AutoInclude("sh_constructor.lua", v.."/") end - + for k2,v2 in pairs(f2) do - //we already loaded the construction file once, so dont load again + -- we already loaded the construction file once, so dont load again if v2 != "sh_constructor.lua" then AutoInclude(v2, v.."/") end end - + end print(" ** End List **") - - - diff --git a/gamemodes/nzombies/gamemode/mainmenu/cl_cheats.lua b/gamemodes/nzombies/gamemode/mainmenu/cl_cheats.lua new file mode 100644 index 00000000..aeea924e --- /dev/null +++ b/gamemodes/nzombies/gamemode/mainmenu/cl_cheats.lua @@ -0,0 +1,231 @@ +local CheatFrame = {} + +function CheatFrame:Init() + self:SetTitle("Cheats") + self:MakePopup(true) + self:SetSize( 524, 256 ) + self:SetPos( ScrW() / 2 - 256, ScrH() / 2 - 128 ) + self:SetVisible( true ) + + local list = vgui.Create("NZCheatList", self) + list:Dock(FILL) + list:SetSize(200,200) + list:AddCheat("Give Points", "/givepoints", "Player", "Number") + list:AddCheat("Give Weapon", "/giveweapon", "Player", "Weapon") + list:AddCheat("Give Perk", "/giveperk", "Player", "Perk") + list:AddCheat("Activate electricity", "/activateelec") + list:AddCheat("Revive", "/revive", "Player") + list:AddCheat("Target Priority", "/targetpriority", "PlayerEntity", "Priority") +end + +vgui.Register( "NZCheatFrame", CheatFrame, "DFrame") + + + +local CheatList = {} + +function CheatList:AddCheat(label, command, input1, input2, input3) + local panel = vgui.Create("DPanel", self) + panel.Paint = function() return end + local cheatLabel = vgui.Create("DLabel", panel) + cheatLabel:SetWide(128) + cheatLabel:SetText(label) + + if input1 then + + input1 = vgui.Create("NZCheatInput" .. input1, panel) + input1:SetPos(128,0) + + if input2 then + + input2 = vgui.Create("NZCheatInput" .. input2, panel) + input2:SetPos(256,0) + + end + + end + + local cheatSubmit = vgui.Create("DButton", panel) + cheatSubmit:SetSize(128, 24) + cheatSubmit:SetPos(384,0) + cheatSubmit:SetText("Submit") + --[[function cheatSubmit:Think() + if input1 and input1:GetCheatData() and input1:GetCheatData() != "" then + if input2 and input2:GetCheatData() and input2:GetCheatData() != "" then + cheatSubmit:SetConsoleCommand("say", command .. " " .. input1:GetCheatData() .. " " .. input2:GetCheatData()) + else + cheatSubmit:SetConsoleCommand( "say", command .. " " .. input1:GetCheatData() ) + end + else + cheatSubmit:SetConsoleCommand("say", command) + end + end]] + cheatSubmit.DoClick = function() + if input1 and input1:GetCheatData() and input1:GetCheatData() != "" then + if input2 and input2:GetCheatData() and input2:GetCheatData() != "" then + RunConsoleCommand("say", command .. " " .. input1:GetCheatData() .. " " .. input2:GetCheatData()) + else + RunConsoleCommand( "say", command .. " " .. input1:GetCheatData() ) + end + else + RunConsoleCommand("say", command) + end + end + + self:Add(panel) +end + +function CheatList:Paint() + return +end + +vgui.Register( "NZCheatList", CheatList, "DListLayout") + + + +local CheatInputPlayer = {} + +AccessorFunc(CheatInputPlayer, "sCheatData", "CheatData", FORCE_STRING) + +function CheatInputPlayer:Init() + self:SetValue("Player") + self:SetWide(128) + self:SetTall(24) + for _,ply in pairs(player.GetAll()) do + self:AddChoice(ply:Nick()) + end +end + +function CheatInputPlayer:OnSelect(index, value, data) + self:SetCheatData(value) +end + +vgui.Register("NZCheatInputPlayer", CheatInputPlayer, "DComboBox") + + + +local CheatInputNumber = {} + +AccessorFunc(CheatInputNumber, "fCheatData", "CheatData", FORCE_STRING) + +function CheatInputNumber:Init() + self:SetText("Number") + self:SetEditable(true) + self:SetWide(128) + self:SetTall(24) +end + +function CheatInputNumber:Think() + self:SetCheatData(self:GetText()) +end + +vgui.Register("NZCheatInputNumber", CheatInputNumber, "DTextEntry") + + + +local CheatInputText = {} + +AccessorFunc(CheatInputText, "sCheatData", "CheatData", FORCE_STRING) + +function CheatInputText:Init() + self:SetText("Text") + self:SetEditable(true) + self:SetWide(128) + self:SetTall(24) +end + +function CheatInputText:Think() + self:SetCheatData(self:GetText()) +end + +vgui.Register("NZCheatInputText", CheatInputText, "DTextEntry") + + + +local CheatInputWeapon = {} + +AccessorFunc(CheatInputWeapon, "sCheatData", "CheatData", FORCE_STRING) + +function CheatInputWeapon:Init() + self:SetValue("Weapon") + self:SetWide(128) + self:SetTall(24) + for _,wep in pairs(weapons.GetList()) do + self:AddChoice(wep.ClassName) + end +end + +function CheatInputWeapon:OnSelect(index, value, data) + self:SetCheatData(value) +end + +vgui.Register("NZCheatInputWeapon", CheatInputWeapon, "DComboBox") + + + +local CheatInputPerk = {} + +AccessorFunc(CheatInputPerk, "iCheatData", "CheatData", FORCE_STRING) + +function CheatInputPerk:Init() + self:SetValue("Perk") + self:SetWide(128) + self:SetTall(24) + for id, perk in pairs(nzPerks.Data) do + self:AddChoice(perk.name, id) + end +end + +function CheatInputPerk:OnSelect(index, value, data) + self:SetCheatData(data) +end + +vgui.Register("NZCheatInputPerk", CheatInputPerk, "DComboBox") + +local CheatInputPriority = {} + +AccessorFunc(CheatInputPriority, "iCheatData", "CheatData", FORCE_STRING) + +function CheatInputPriority:Init() + self:SetValue("Target") + self:SetWide(128) + self:SetTall(24) + + self:AddChoice("None (0)", "0") + self:AddChoice("Player (1)", "1") + self:AddChoice("Special (2)", "2") + self:AddChoice("Max (3)", "3") + self:AddChoice("Always (10)", "10") +end + +function CheatInputPriority:OnSelect(index, value, data) + self:SetCheatData(data) +end + +vgui.Register("NZCheatInputPriority", CheatInputPriority, "DComboBox") + + +local CheatInputPlayerEntity = {} + +AccessorFunc(CheatInputPlayerEntity, "sCheatData", "CheatData", FORCE_STRING) + +function CheatInputPlayerEntity:Init() + self:SetValue("Entity") + self:SetWide(128) + self:SetTall(24) + for _,ply in pairs(player.GetAll()) do + self:AddChoice(ply:Nick()) + end + local ent = LocalPlayer():GetEyeTrace().Entity + if IsValid(ent) then + self:AddChoice("Entity ["..ent:EntIndex().."] ["..ent:GetClass().."]", "entity("..ent:EntIndex()..")") + else + self:AddChoice("Look at an entity to target that.", "") + end +end + +function CheatInputPlayerEntity:OnSelect(index, value, data) + self:SetCheatData(data or value) +end + +vgui.Register("NZCheatInputPlayerEntity", CheatInputPlayerEntity, "DComboBox") diff --git a/gamemodes/nzombies/gamemode/mainmenu/cl_player.lua b/gamemodes/nzombies/gamemode/mainmenu/cl_player.lua new file mode 100644 index 00000000..9b86d892 --- /dev/null +++ b/gamemodes/nzombies/gamemode/mainmenu/cl_player.lua @@ -0,0 +1,5 @@ +local plyMeta = FindMetaTable("Player") + +function plyMeta:IsNZMenuOpen() + return IsValid(g_Settings) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/mainmenu/cl_vgui.lua b/gamemodes/nzombies/gamemode/mainmenu/cl_vgui.lua new file mode 100644 index 00000000..697f5a16 --- /dev/null +++ b/gamemodes/nzombies/gamemode/mainmenu/cl_vgui.lua @@ -0,0 +1,451 @@ +surface.CreateFont( "pier_large", { + font = "PierSans-Regular", + size = 48, + antialias = true, +} ) + +surface.CreateFont( "pier_medium", { + font = "PierSans-Regular", + size = 24, + antialias = true, +} ) + +surface.CreateFont( "pier_small", { + font = "PierSans-Regular", + size = 16, + antialias = true, +} ) + +local MenuFrame = {} + +AccessorFunc( MenuFrame, "fLastSpawnSwitch", "LastSpawnSwitch", FORCE_NUMBER ) + +function MenuFrame:Init() + self:SetSize(ScrW(), ScrH()) + self:SetPos( 0, 0 ) + gui.EnableScreenClicker( true ) + + self.ToolBar = vgui.Create( "NZMainMenuToolBar", self ) + self.Content = vgui.Create( "NZMainMenuContent", self ) + self.PlayerList = vgui.Create( "NZMainMenuPlayerList", self ) + + self.CameraPos = LocalPlayer():GetPos() + Vector( 30, 30, 30 ) + self:SetLastSpawnSwitch( CurTime() ) + +end + +function MenuFrame:Think() + local ply = LocalPlayer() + if ply:Alive() then return end + if self:GetLastSpawnSwitch() + 15 < CurTime() then + local sPoints = ents.FindByClass( "player_spawns" ) + if sPoints then + local sPoint = sPoints[ math.random( #sPoints ) ] + if IsValid( sPoint ) then + ply:SetPos( sPoint:GetPos() ) + self.CameraPos = LocalPlayer():GetPos() + Vector( 20, 20, 40 ) + self:SetLastSpawnSwitch( CurTime() ) + end + end + end + local vec1 = self.CameraPos + local vec2 = ply:GetPos() + Vector( 0, 0, 20 ) + local ang = ( vec2 - vec1 ):Angle() + ang:RotateAroundAxis( Vector( 0, 0, 1), math.sin( CurTime()/20 ) * 360 ) + ply:SetEyeAngles( ang ) +end + +function MenuFrame:Paint() + --Derma_DrawBackgroundBlur( self, self.startTime ) + return +end + +--It's not actually a frame but whatever +vgui.Register( "NZMainMenuFrame", MenuFrame, "DPanel") + + +local MenuToolBar = {} + +function MenuToolBar:Init() + self:SetSize( ScrW(), 80 ) + self:SetPos( 0, 0 ) + + self.Logo = vgui.Create( "DLabel", self ) + self.Logo:SetPos( 14, 14 ) + self.Logo:SetFont( "nz.display.hud.main" ) + self.Logo:SetColor( Color( 255, 255, 255 ) ) + self.Logo:SetText( "nZombies" ) + self.Logo:SizeToContents() + + self.Entries = {} + + local ready = self:AddEntry( "READY", "large", "nz_chatcommand", "/ready" ) + function ready:Think() + if nzRound:InProgress() then + if LocalPlayer():Alive() then + self:SetText( "DROPOUT" ) + self:SetConsoleCommand( "nz_chatcommand", "/dropout" ) + else + self:SetText( "DROPIN" ) + self:SetConsoleCommand( "nz_chatcommand", "/dropin" ) + end + else + if LocalPlayer():IsReady() then + self:SetText( "UNREADY" ) + else + self:SetText( "READY" ) + end + self.DoClick = function() + if LocalPlayer():IsReady() then + RunConsoleCommand( "nz_chatcommand", "/unready" ) + else + RunConsoleCommand( "nz_chatcommand", "/ready" ) + RunConsoleCommand( "nz_settings" ) + end + end + end + end + + local spectate = self:AddEntry( "SPECTATE", "medium", "nz_chatcommand", "/spectate" ) + + local creative = self:AddEntry( "CREATIVE MODE", "medium", "nz_chatcommand", "/create" ) + function creative:Think() + if LocalPlayer():IsInCreative() then + self:SetText("SURVIVAL MODE") + else + self:SetText("CREATIVE MODE") + end + end + + self:AddEntry( "WORKSHOP PAGE", "medium", function() gui.OpenURL( "http://steamcommunity.com/sharedfiles/filedetails/?id=675138912" ) end ) + + self:AddEntry( "Press F1 to toggle this menu", "small", function() RunConsoleCommand("nz_settings") end ) + + --Settings Button / Close button + if LocalPlayer():IsSuperAdmin() then + self.SettingsButton = vgui.Create( "DImageButton", self ) + self.SettingsButton:SetImage( "icon_settings.png" ) + self.SettingsButton:SetPos( ScrW() - 60, 20 ) + self.SettingsButton:SetSize( 40, 40 ) + self.SettingsButton:SetContentAlignment( 5 ) + function self.SettingsButton:Paint( w, h ) + + end + + AccessorFunc( self.SettingsButton, "bSettingsMenuOpen", "SettingsMenuOpen", FORCE_BOOL ) + + function self.SettingsButton:DoClick() + if !self:GetSettingsMenuOpen() then + self.SettingsMenu = vgui.Create( "NZMainMenuSettingsPanel", self:GetParent():GetParent() ) --Parent to mainframe + self:SetSettingsMenuOpen( true ) + self:SetColor( Color( 85, 85, 85, 255 ) ) + else + self.SettingsMenu:Remove() + self:SetSettingsMenuOpen( false ) + self:SetColor( Color( 255, 255, 255, 255 ) ) + end + end + + else + --Show close icon if user not superadmin + self.CloseButton = vgui.Create( "DImageButton", self ) + self.CloseButton:SetImage( "icon_close.png" ) + self.CloseButton:SetPos( ScrW() - 60, 20 ) + self.CloseButton:SetSize( 40, 40 ) + self.CloseButton:SetContentAlignment( 5 ) + self.CloseButton:SetConsoleCommand( "nz_settings" ) + function self.CloseButton:Paint( w, h ) + + end + end + +end + +local col = Color( 130, 45, 45, 255 ) +function MenuToolBar:Paint( w, h ) + draw.RoundedBox( 0, 0, 0, w, h, col ) + --draw.RoundedBox( 0, 0, h-5, w, 5, Color( 255, 255, 255, 255 ) ) +end + +--[[function MenuToolBar:Think() + local nextPos = 320 + local temp = self.Entries + for i = #self.Entries, 1, -1 do + self.Entries[i]:SizeToContentsX() + for j = #self.Entries, i, -1 do + if i == j then break end + nextPos = nextPos + self.Entries[j]:GetWide() + 30 + end + self.Entries[i]:SetPos( nextPos, 20 ) + nextPos = 320 + end +end]] + +function MenuToolBar:AddEntry( lbl, fontSize, cmd, args ) + local entry = vgui.Create( "NZMainMenuToolBarEntry", self ) + if fontSize == "large" then + entry:SetFont( "pier_large" ) + elseif fontSize == "medium" then + entry:SetFont( "pier_medium" ) + else + entry:SetFont( "pier_small" ) + end + local nextPos = 300 + for _, v in pairs( self.Entries ) do + nextPos = nextPos + v:GetWide() + 30 + end + entry:SetPos( nextPos, 0 ) + entry:SetTall( self:GetTall() ) + if isfunction( cmd ) then + entry.DoClick = cmd + elseif isstring( cmd ) then + entry:SetConsoleCommand( cmd, args ) + end + entry:SetText( lbl ) + entry:SetContentAlignment( 5 ) + --entry:SizeToContentsX() + + table.insert( self.Entries, 1, entry ) + + return self.Entries[ 1 ] +end + +vgui.Register( "NZMainMenuToolBar", MenuToolBar, "DPanel") + + +local MenuToolBarEntry = {} + +function MenuToolBarEntry:Init() + self:SetSize( 260, 60 ) + self:SetFont( "pier_large" ) + self:SetContentAlignment( 5 ) + self:SetTextColor( Color( 255, 255, 255 ) ) +end + +function MenuToolBarEntry:Paint() + +end + +vgui.Register( "NZMainMenuToolBarEntry", MenuToolBarEntry, "DButton") + + +local MenuSettingsPanel = {} + +local white = Color(255,255,255,255) +local green = Color(230,255,230,255) + +local function MenuSettingsListInit(self) + self:SetWide( 256 ) + local btnMode = self:AddButton( "< Toggle Creative Mode ...", "nz_chatcommand", "/create" ) + function btnMode:Think() + if self:IsHovered() or IsValid(self.ExtendedList) and (self.ExtendedList:IsHovered() or self.ExtendedList:IsChildHovered()) then + if !IsValid(self.ExtendedList) then + self.ExtendedList = vgui.Create("DScrollPanel", self:GetParent():GetParent():GetParent():GetParent()) + function self.ExtendedList:Paint( w, h ) + draw.RoundedBox( 0, 0, 0, w, h, white ) + end + + self.ExtendedList:SetPos( ScrW() - 512, 80 ) + self.ExtendedList:SetSize( 256, math.Clamp(#player.GetAll() * 42, 0, 1024) ) + self.ExtendedList.PlayerList = vgui.Create("NZMainMenuSettingsList", self.ExtendedList) + self.ExtendedList.PlayerList:SetWide( 256 ) + + for k,v in pairs(player.GetAll()) do + local plybtn = self.ExtendedList.PlayerList:AddButton( v:Nick(), "nz_chatcommand", "/create "..v:Nick()) + function plybtn:Paint( w, h ) + draw.RoundedBox( 0, 0, 1, w, h-1, v:IsInCreative() and green or white ) + end + end + end + else + if IsValid(self.ExtendedList) then + self.ExtendedList:Remove() + end + end + end + + self:AddButton( "Load Map config", "nz_chatcommand", "/load" ) + self:AddButton( "Save Map config", "nz_chatcommand", "/save" ) + self:AddButton( "Player Model Editor", function() nzPlayers:PlayerModelEditor() end) + self:AddButton( "Generate Navmesh", "nz_chatcommand", "/generate" ) + self:AddButton( "Cheats (Beta)", "nz_chatcommand", "/cheats" ) +end + +function MenuSettingsPanel:Init() + self:SetPos( ScrW() - 256, 80 ) + self:SetSize( 256, 256) + self.List = vgui.Create( "NZMainMenuSettingsList", self ) + MenuSettingsListInit(self.List) +end + +function MenuSettingsPanel:Paint( w, h ) + draw.RoundedBox( 0, 0, 0, w, h, white ) +end + +vgui.Register( "NZMainMenuSettingsPanel", MenuSettingsPanel, "DScrollPanel" ) + +local MenuSettingsList = {} + +function MenuSettingsList:AddButton( lbl, cmd, args ) + local button = vgui.Create( "DButton", self ) + if isfunction( cmd ) then + button.DoClick = cmd + elseif isstring( cmd ) then + button:SetConsoleCommand( cmd, args ) + end + button:SetText( lbl ) + button:SetFont( "pier_small" ) + button:SetTall( 42 ) + + function button:Paint( w, h ) + + end + + if !self.ButtonContent then self.ButtonContent = {} end + local btn = self:Add( button ) + table.insert(self.ButtonContent, btn) + return btn +end + +function MenuSettingsList:Paint( w, h ) + for k,v in ipairs(self.ButtonContent) do + local nextbtn = self.ButtonContent[k + 1] + if IsValid(nextbtn) then + local x, y = nextbtn:GetPos() + local mid = y - 0 + surface.SetDrawColor(230, 230, 230) + surface.DrawLine(20, mid, self:GetWide() - 20, mid) + end + end +end + +vgui.Register( "NZMainMenuSettingsList", MenuSettingsList, "DListLayout" ) + + +local MenuContent = {} + +function MenuContent:Init() + self.Layouts = {} + self.ActiveLayout = "main" + self:SetSize(ScrW(), ScrH() - 80 ) + self:SetPos( 0, 80 ) + + --Main Page of the menu + local mainLayout = vgui.Create( "NZMainMenuContentLayout" ) + + self:AddLayout( "main", mainLayout ) + + --Set Active page to main on Init + self:SetActiveLayout( "main" ) + +end + +function MenuContent:SetActiveLayout( name ) + self:GetActiveLayout():SetVisible( false ) + self.ActiveLayout = name + self:GetActiveLayout():SetVisible( true ) +end + +function MenuContent:GetActiveLayout() + return self.Layouts[ self.ActiveLayout ] +end + +function MenuContent:Paint() + return +end + +function MenuContent:AddLayout( name, layout ) + layout:SetParent( self ) + self.Layouts[name] = layout +end + +vgui.Register( "NZMainMenuContent", MenuContent, "DPanel") + + +local MenuContentLayout = {} + +function MenuContentLayout:Init() + self.Panels = {} + self:SetSize( 768, 512 ) + self:SetPos( ScrW() / 2 - 384, ScrH() / 2 - 320 ) + self:SetVisible( false ) +end + +function MenuContentLayout:GetPanels() + return self.Panels +end + +function MenuContentLayout:Paint() + return +end + +function MenuContentLayout:AddPanel( pnl, startGridX, startGridY, gridSizeX, gridSizeY ) + local gridSize = 128 + pnl:SetParent( self ) + pnl:SetPos( gridSize * ( startGridX - 1 ), gridSize * (startGridY - 1) ) + pnl:SetSize( gridSize * gridSizeX, gridSize * gridSizeY ) + table.insert( self.Panels, pnl ) +end + +vgui.Register( "NZMainMenuContentLayout", MenuContentLayout, "DPanel") + +local PlayerList = {} + +function PlayerList:Init() + self:SetPos(100, 200) + self:SetSize(500, 800) +end + +local bloodline_points = Material("bloodline_score.png", "unlitgeneric smooth") +function PlayerList:Paint(w, h) + local c = 0 + local n = #player.GetAllReady() + for _,ply in pairs( player.GetAll() ) do + if IsValid(ply) then + local text = "" + surface.SetMaterial(bloodline_points) + surface.SetDrawColor(200,0,0) + surface.DrawTexturedRect(0, h / 2 - n * 17.5 + 35 * c, 300, 40) + if ply:IsReady() then text = "Ready" else + if nzRound:InState(ROUND_CREATE) and ply:Alive() then + text = "In Creative" + else + text = "Not ready" + end + end + draw.SimpleText(ply:Nick() .. " - " .. text, "nz.display.hud.small", 25, h / 2 - n * 17.5 + 35 * c + 15, Color(255,255,255,255), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER) + c = c + 1 + end + end + return +end + +vgui.Register( "NZMainMenuPlayerList", PlayerList, "DPanel") + + +local function showSettings(ply, cmd, args) + if ( !IsValid( g_Settings ) ) then + g_Settings = vgui.Create("NZMainMenuFrame") + g_Settings:SetVisible(false) -- use the visible bool as toggle indicator TODO: this is bullshit since we are removing the menu anyways + end + + if ( IsValid( g_Settings ) ) then + if g_Settings:IsVisible() then + g_Settings:Hide() + gui.EnableScreenClicker( false ) + g_Settings:SetVisible(false) + g_Settings:Remove() + else + g_Settings:Show() + gui.EnableScreenClicker( true ) + g_Settings:SetVisible(true) + + if IsValid(nzInterfaces.ConfigVoter) then nzInterfaces.ConfigVoter:Show() end -- Reopen config voter as well if a vote is going on + end + end +end +concommand.Add("nz_settings", showSettings) + +hook.Add("InitPostEntity", "AutoOpenMenu", function() + LocalPlayer():ConCommand("nz_settings") +end) diff --git a/gamemodes/nzombies/gamemode/mainmenu/sv_controls.lua b/gamemodes/nzombies/gamemode/mainmenu/sv_controls.lua new file mode 100644 index 00000000..3c4157f9 --- /dev/null +++ b/gamemodes/nzombies/gamemode/mainmenu/sv_controls.lua @@ -0,0 +1,5 @@ +function GM:ShowHelp( ply ) + if IsValid( ply ) then + ply:ConCommand("nz_settings") + end +end diff --git a/gamemodes/nzombies/gamemode/mapping/sh_constructor.lua b/gamemodes/nzombies/gamemode/mapping/sh_constructor.lua new file mode 100644 index 00000000..094702ce --- /dev/null +++ b/gamemodes/nzombies/gamemode/mapping/sh_constructor.lua @@ -0,0 +1,24 @@ +-- Setup round module +nzMapping = nzMapping or AddNZModule("Mapping") + +-- Variables +nzMapping.Settings = nzMapping.Settings or {} +nzMapping.MarkedProps = nzMapping.MarkedProps or {} +nzMapping.ScriptHooks = nzMapping.ScriptHooks or {} + +-- Once more gamemode entities are added, add the gamemodes to this list +nzMapping.GamemodeExtensions = nzMapping.GamemodeExtensions or { + ["Zombie Survival"] = false, +} + +-- Prevent undo without being in creative +-- This can be circumvented with "alias", but it's more for accidental undos than exploit fixing +if CLIENT then + hook.Add("PlayerBindPress", "nzUndoHandling", function(ply, bind, pressed) + if string.find(bind, "undo") then + if !ply:IsInCreative() then + return true + end + end + end) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/mapping/sh_mapscripthandler.lua b/gamemodes/nzombies/gamemode/mapping/sh_mapscripthandler.lua new file mode 100644 index 00000000..adb94070 --- /dev/null +++ b/gamemodes/nzombies/gamemode/mapping/sh_mapscripthandler.lua @@ -0,0 +1,156 @@ +if SERVER then + util.AddNetworkString("NZMapScript") + util.AddNetworkString("NZMapScriptUnload") + function nzMapping:LoadScript( name ) + + self:UnloadScript() -- For safety + + local filePath = "nzmapscripts/" .. string.StripExtension(name) .. ".lua" + + if !file.Exists( filePath, "LUA") then + local alternative = string.Explode(";", string.StripExtension(name)) + if alternative[1] and alternative[2] then + filePath = "nzmapscripts/"..alternative[1]..";"..alternative[2]..".lua" + end + + if !file.Exists( filePath, "LUA") then + PrintMessage(HUD_PRINTTALK, "Attempted to load non-existant map script: "..filePath) + return false + end + end + + -- To keep track of stuff created in this script + local create = ents.Create + ents.Create = function(class) + local ent = create(class) + ent.NZMapScriptCreated = true + return ent + end + + self.ScriptHooks = include( filePath ) + self.ScriptPath = filePath + + + for k,v in pairs(self.ScriptHooks) do + if type(v) == "function" then + hook.Add(k, "nzmapscript"..k, v) + end + end + + if self.ScriptHooks.ClientSideSend then + AddCSLuaFile( filePath ) + timer.Simple(1, function() + net.Start("NZMapScript") + net.WriteString(filePath) + net.Broadcast() + end) + end + + --[[hook.Add("OnRoundInit", "nzmapscriptinit", hooks.RoundInit) + hook.Add("OnRoundStart", "nzmapscriptstart", hooks.RoundStart) + hook.Add("OnRoundThink", "nzmapscriptthink", hooks.RoundThink) + hook.Add("OnRoundEnd", "nzmapscriptend", hooks.RoundEnd)]] + + if self.ScriptHooks.ScriptLoad then + self.ScriptHooks.ScriptLoad() + end + + -- Restore + ents.Create = create + + PrintMessage(HUD_PRINTTALK, "Successfully loaded map script: "..filePath) + return true + + end + + function nzMapping:UnloadScript() + if !self.ScriptHooks then return end + + for k,v in pairs(self.ScriptHooks) do + if type(v) == "function" then + hook.Remove(k, "nzmapscript"..k) + end + end + + if self.ScriptHooks.ClientSideSend then + net.Start("NZMapScriptUnload") + net.Broadcast() + end + + --[[hook.Remove("OnRoundInit", "nzmapscriptinit") + hook.Remove("OnRoundStart", "nzmapscriptstart") + hook.Remove("OnRoundThink", "nzmapscriptthink") + hook.Remove("OnRoundEnd", "nzmapscriptend")]] + + if self.ScriptHooks.ScriptUnload then + self.ScriptHooks.ScriptUnload() + end + + self.ScriptHooks = nil + + -- Remove all created entities that weren't already + for k,v in pairs(ents.GetAll()) do + if v.NZMapScriptCreated then v:Remove() end + end + + -- Clean up all items + nzItemCarry:CleanUp() + + end + + hook.Add("PlayerInitialSpawn", "SendMapScriptSpawn", function(ply) + if nzMapping.ScriptHooks and nzMapping.ScriptHooks.ClientSideSend then + timer.Simple(1, function() + net.Start("NZMapScript") + net.WriteString(nzMapping.ScriptPath) + net.Broadcast() + end) + end + end) +end + +if CLIENT then + + net.Receive("NZMapScript", function() + local path = net.ReadString() + print(path) + + if !file.Exists( path, "LUA") then return end + + nzMapping.ScriptHooks = include( path ) + + PrintTable(nzMapping.ScriptHooks) + + for k,v in pairs(nzMapping.ScriptHooks) do + if isfunction(v) then + hook.Add(k, "nzmapscript"..k, v) + end + end + + if nzMapping.ScriptHooks.ScriptLoad then + nzMapping.ScriptHooks.ScriptLoad() + end + end) + + net.Receive("NZMapScriptUnload", function() + if !nzMapping.ScriptHooks then return end + + for k,v in pairs(nzMapping.ScriptHooks) do + if isfunction(v) then + hook.Remove(k, "nzmapscript"..k) + end + end + + if nzMapping.ScriptHooks.ScriptUnload then + nzMapping.ScriptHooks.ScriptUnload() + end + + nzMapping.ScriptHooks = nil + nzMapping.ScriptPath = nil + end) + +end + +function nzMapping:GetMapScript() + return self.ScriptHooks +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/mapping/sh_mismatch.lua b/gamemodes/nzombies/gamemode/mapping/sh_mismatch.lua new file mode 100644 index 00000000..00d763f5 --- /dev/null +++ b/gamemodes/nzombies/gamemode/mapping/sh_mismatch.lua @@ -0,0 +1,563 @@ +nzMapping.Mismatch = nzMapping.Mismatch or {} +nzMapping.MismatchData = nzMapping.MismatchData or {} + +if SERVER then + util.AddNetworkString("nzMappingMismatchData") + util.AddNetworkString("nzMappingMismatchEnd") + + net.Receive("nzMappingMismatchData", function(len, ply) + if !ply:IsSuperAdmin() then + print(ply:Nick() .. " tried to correct map data. You need to be a super admin to do this.") + return + end + local id = net.ReadString() + local data = net.ReadTable() + nzMapping.Mismatch[id].Correct(data) + end) + +else + net.Receive("nzMappingMismatchData", function() + local id = net.ReadString() + local data = net.ReadTable() + nzMapping.MismatchData[id] = data + end) + + local function OpenMismatchInterface() + local frame = vgui.Create("DFrame") + frame:SetSize(400, 500) + frame:Center() + frame:SetTitle("Config Loading Mismatch!") + frame:MakePopup() + + local sheet = vgui.Create("DPropertySheet", frame) + sheet:SetPos(5, 25) + sheet:SetSize(390, 435) + sheet.sheets = {} + + frame.OnClose = function() + local corrected = nil + for k,v in pairs(sheet.sheets) do + v.ReturnCorrectedData() + corrected = true + end + if corrected then + chat.AddText("Applied default actions on the rest of the mismatches, some entities may have disappeared.") + end + end + + for k,v in pairs(nzMapping.MismatchData) do + if table.Count(v) > 0 then + local panel = nzMapping.Mismatch[k].Interface(sheet) + local info = sheet:AddSheet(k, panel) + --table.insert(sheet.sheets, {tab = info.Tab, panel = info.Panel, name = tab.Name}) + sheet.sheets[info.Tab] = info.Panel + end + end + + sheet.CloseTabAndOpenNew = function(update) + local tab = sheet:GetActiveTab() + local panel = sheet.sheets[tab] + if update then + panel.ReturnCorrectedData() + end + + local newtab = table.GetKeys(sheet.sheets)[1] + if newtab == tab then newtab = table.GetKeys(sheet.sheets)[2] end + if !IsValid(newtab) then + sheet.sheets[tab] = nil + frame:Close() + chat.AddText("Remember to re-save the cleaned config if you don't want to go through this every time.") + return + end + sheet:SetActiveTab(newtab) + + timer.Simple(0.1, function() + if IsValid(tab) then + sheet.sheets[tab] = nil + sheet:CloseTab(tab) + end + end) + end + + local submit = vgui.Create("DButton", frame) + submit:SetText("Submit Changes") + submit:SetSize(200, 30) + submit:SetPos(90, 465) + submit:CenterHorizontal() + submit.DoClick = function() + sheet.CloseTabAndOpenNew(true) + end + end + net.Receive("nzMappingMismatchEnd", OpenMismatchInterface) +end + +function CreateMismatchCheck(id, sv_check, cl_interface, sv_correct) + -- Create tables for storing it + nzMapping.Mismatch[id] = nzMapping.Mismatch[id] or {} + nzMapping.MismatchData[id] = nzMapping.MismatchData[id] or {} + + if SERVER then + nzMapping.Mismatch[id].Check = sv_check + nzMapping.Mismatch[id].Correct = sv_correct + else + nzMapping.Mismatch[id].Interface = cl_interface + end +end + +function nzMapping:CheckMismatch( loader ) + if !IsValid(loader) then return end + local faults = nil + + for k,v in pairs(self.Mismatch) do + local data = self.Mismatch[k].Check() -- Run the check function and save the data + if data and table.Count(data) > 0 then -- Empty tables don't get sent, no errors + net.Start("nzMappingMismatchData") + net.WriteString(k) + net.WriteTable(data) + net.Send(loader) + faults = true + end + end + + if faults then -- No need to send if there's nothing wrong + net.Start("nzMappingMismatchEnd") -- Mark the end of all data so the client can compile it all + net.Send(loader) + end +end + +CreateMismatchCheck("Wall Buys", function() + local tbl = {} + for k,v in pairs(ents.FindByClass("wall_buys")) do + if !weapons.Get(v:GetWepClass()) then + print("Wall Buy has non-existant weapon class: " .. v:GetWepClass() .. "!") + tbl[v:GetWepClass()] = true + end + end + + return tbl -- Return the data you want to send to the client + +end, function(frame) + + local pnl = vgui.Create("DPanel", frame) + pnl:SetPos(5, 5) + pnl:SetSize(380, 425) + + local properties = vgui.Create("DProperties", pnl) + properties:SetPos(0, 0) + properties:SetSize(380, 420) + + for k,v in pairs(nzMapping.MismatchData["Wall Buys"]) do + local choice = properties:CreateRow( "Missing Weapons", k ) + choice:Setup( "Combo", {} ) + choice:AddChoice( " Remove ...", "nz_removeweapon", true ) + nzMapping.MismatchData["Wall Buys"][k] = "nz_removeweapon" + for _, v2 in pairs(weapons.GetList()) do + if v2.Category and v2.Category != "" then + choice:AddChoice(v2.PrintName and v2.PrintName != "" and v2.Category.. " - "..v2.PrintName or v2.ClassName, v2.ClassName, false) + else + choice:AddChoice(v2.PrintName and v2.PrintName != "" and v2.PrintName or v2.ClassName, v2.ClassName, false) + end + end + choice.DataChanged = function(self, val) + nzMapping.MismatchData["Wall Buys"][k] = val + end + end + + pnl.ReturnCorrectedData = function() -- Add the function to the returned panel so we can access it outside + net.Start("nzMappingMismatchData") + net.WriteString("Wall Buys") + net.WriteTable(nzMapping.MismatchData["Wall Buys"]) + net.SendToServer() + nzMapping.MismatchData["Wall Buys"] = nil -- Clear the data + end + + return pnl -- Return it to add it the the sheets + +end, function( data ) + for k,v in pairs(ents.FindByClass("wall_buys")) do + local new = data[v:GetWepClass()] + if new then + if new == "nz_removeweapon" then + v:Remove() + else + v:SetWeapon(new) + end + end + end + + nzMapping.MismatchData["Wall Buys"] = nil -- Clear the data +end) + +CreateMismatchCheck("Perks", function() + local tbl = {} + for k,v in pairs(ents.FindByClass("perk_machine")) do + if !nzPerks:Get(v:GetPerkID()) then + print("Perk with non-existant perk: " .. v:GetPerkID() .. "!") + tbl[v:GetPerkID()] = true + end + end + + return tbl -- Return the data you want to send to the client + +end, function(frame) + + local pnl = vgui.Create("DPanel", frame) + pnl:SetPos(5, 5) + pnl:SetSize(380, 425) + + local properties = vgui.Create("DProperties", pnl) + properties:SetPos(0, 0) + properties:SetSize(380, 420) + + for k,v in pairs(nzMapping.MismatchData["Perks"]) do + local choice = properties:CreateRow( "Invalid Perks", k ) + choice:Setup( "Combo", {} ) + choice:AddChoice( " Remove ...", "nz_removeperk", true ) + nzMapping.MismatchData["Perks"][k] = "nz_removeperk" + for k2, v2 in pairs(weapons.GetList()) do + choice:AddChoice(v2.name or k2, k2, false) + end + choice.DataChanged = function(self, val) + nzMapping.MismatchData["Petks"][k] = val + end + end + + pnl.ReturnCorrectedData = function() + net.Start("nzMappingMismatchData") + net.WriteString("Perks") + net.WriteTable(nzMapping.MismatchData["Perks"]) + net.SendToServer() + nzMapping.MismatchData["Perks"] = nil -- Clear the data + end + + return pnl + +end, function( data ) + for k,v in pairs(ents.FindByClass("perk_machine")) do + local new = data[v:GetPerkID()] + if new then + if new == "nz_removeperk" then + v:Remove() + else + v:SetPerkID(new) + v:Update() -- Update model and perk values + end + end + end + + nzMapping.MismatchData["Perks"] = nil -- Clear the data +end) + +CreateMismatchCheck("Map Settings", function() + local tbl = {} + local settings = nzMapping.Settings + + local startwep = settings.startwep or nzConfig.BaseStartingWeapons[1] or "Invalid" + if !weapons.Get(startwep) then tbl["startwep"] = startwep end + + local specialround = settings.specialroundtype + if !nzRound.SpecialData[specialround] and specialround != "None" and specialround != nil then tbl["specialroundtype"] = specialround end + + local boss = settings.bosstype + if !nzRound.BossData[boss] and boss != "None" and boss != nil then tbl["bosstype"] = boss end + + return tbl + + end, function(frame) + + local pnl = vgui.Create("DPanel", frame) + pnl:SetPos(5, 5) + pnl:SetSize(380, 425) + + local properties = vgui.Create("DProperties", pnl) + properties:SetPos(0, 0) + properties:SetSize(380, 420) + + local tbl = nzMapping.MismatchData["Map Settings"] + + if tbl.startwep then + local choice = properties:CreateRow( "Start Weapon", tbl.startwep ) + choice:Setup( "Combo", {} ) + for k,v2 in pairs(weapons.GetList()) do + choice:AddChoice(v2.PrintName and v2.PrintName != "" and v2.PrintName or v2.ClassName, v2.ClassName, false) + end + choice.DataChanged = function(self, val) + nzMapping.MismatchData["Map Settings"]["startwep"] = val + end + end + if tbl.specialroundtype then + local choice = properties:CreateRow( "Special Round", tbl.specialroundtype ) + choice:Setup( "Combo", {} ) + for k,v in pairs(nzRound.SpecialData) do + choice:AddChoice(k, k, false) + end + choice:AddChoice(" None", "None", true) + nzMapping.MismatchData["Map Settings"]["specialroundtype"] = "None" -- Default + choice.DataChanged = function(self, val) + nzMapping.MismatchData["Map Settings"]["specialroundtype"] = val + end + end + if tbl.bosstype then + local choice = properties:CreateRow( "Boss", tbl.bosstype ) + choice:Setup( "Combo", {} ) + for k,v in pairs(nzRound.BossData) do + choice:AddChoice(k, k, false) + end + choice:AddChoice(" None", "None", true) + nzMapping.MismatchData["Map Settings"]["bosstype"] = "None" -- Default + choice.DataChanged = function(self, val) + nzMapping.MismatchData["Map Settings"]["bosstype"] = val + end + end + + pnl.ReturnCorrectedData = function() + net.Start("nzMappingMismatchData") + net.WriteString("Map Settings") + net.WriteTable(nzMapping.MismatchData["Map Settings"]) + net.SendToServer() + nzMapping.MismatchData["Map Settings"] = nil + end + + return pnl + + end, function( data ) + + if data.startwep then + nzMapping.Settings.startwep = data.startwep + end + if data.specialroundtype then + nzMapping.Settings.specialroundtype = data.specialroundtype + end + if data.bosstype then + nzMapping.Settings.bosstype = data.bosstype + end + + for k,v in pairs(player.GetAll()) do + nzMapping:SendMapData(ply) -- Update the data to players + end + + nzMapping.MismatchData["Map Settings"] = nil +end) + +CreateMismatchCheck("Map Script", function() + local tbl = {} + if tobool(nzMapping.Settings.script) then tbl["script"] = true end + --if true then tbl["script"] = true end + + return tbl + + end, function(frame) + + local pnl = vgui.Create("DPanel", frame) + pnl:SetPos(5, 5) + pnl:SetSize(380, 425) + + local txt = vgui.Create("DLabel", pnl) + txt:SetText("Map Script Load") + txt:SetFont("DermaLarge") + txt:SetTextColor(Color(75,75,75)) + txt:SizeToContents() + txt:SetPos(0, 30) + txt:CenterHorizontal() + + local txt2 = vgui.Create("DLabel", pnl) + txt2:SetText("This config is attempting to load a lua script along with it.") + txt2:SetTextColor(Color(75,75,75)) + txt2:SetFont("Trebuchet18") + txt2:SizeToContents() + txt2:SetPos(0, 70) + txt2:CenterHorizontal() + + local txt3 = vgui.Create("DLabel", pnl) + txt3:SetText("Lua scripts can be potentially dangerous as they can do") + txt3:SetTextColor(Color(75,75,75)) + txt3:SetFont("Trebuchet18") + txt3:SizeToContents() + txt3:SetPos(0, 90) + txt3:CenterHorizontal() + + local txt4 = vgui.Create("DLabel", pnl) + txt4:SetText("anything any other addon or gamemode could potentially do.") + txt4:SetTextColor(Color(75,75,75)) + txt4:SetFont("Trebuchet18") + txt4:SizeToContents() + txt4:SetPos(0, 100) + txt4:CenterHorizontal() + + local txt5 = vgui.Create("DLabel", pnl) + txt5:SetText("including kicking, banning, saving data, and more.") + txt5:SetTextColor(Color(175,75,75)) + txt5:SetFont("Trebuchet18") + txt5:SizeToContents() + txt5:SetPos(0, 110) + txt5:CenterHorizontal() + + local txt6 = vgui.Create("DLabel", pnl) + txt6:SetText("However map scripts is what allows special events,") + txt6:SetTextColor(Color(75,75,75)) + txt6:SetFont("Trebuchet18") + txt6:SizeToContents() + txt6:SetPos(0, 130) + txt6:CenterHorizontal() + + local txt7 = vgui.Create("DLabel", pnl) + txt7:SetText("objectives, or whole easter eggs to be coded directly.") + txt7:SetTextColor(Color(75,75,75)) + txt7:SetFont("Trebuchet18") + txt7:SizeToContents() + txt7:SetPos(0, 140) + txt7:CenterHorizontal() + + local txt8 = vgui.Create("DLabel", pnl) + txt8:SetText("Load scripts from configs you trust or have verified yourself.") + txt8:SetTextColor(Color(75,75,75)) + txt8:SetFont("Trebuchet18") + txt8:SizeToContents() + txt8:SetPos(0, 160) + txt8:CenterHorizontal() + + local txt9 = vgui.Create("DLabel", pnl) + txt9:SetText("This config claims to do the following:") + txt9:SetTextColor(Color(75,75,75)) + txt9:SetFont("Trebuchet18") + txt9:SizeToContents() + txt9:SetPos(0, 190) + txt9:CenterHorizontal() + + local txt10 = vgui.Create("DLabel", pnl) + txt10:SetSize(350, 100) + txt10:SetWrap(true) + txt10:SetText(nzMapping.Settings.scriptinfo or "- no description -") + txt10:SetTextColor(Color(75,175,75)) + txt10:SetFont("Trebuchet18") + txt10:SetPos(0, 210) + txt10:CenterHorizontal() + + local txt11 = vgui.Create("DLabel", pnl) + txt11:SetText("Load Script?") + txt11:SetTextColor(Color(75,75,75)) + txt11:SetFont("Trebuchet18") + txt11:SizeToContents() + txt11:SetPos(0, 320) + txt11:CenterHorizontal() + + local yes = vgui.Create("DButton", pnl) + yes:SetText("Yes") + yes:SetSize(75, 20) + yes:SetPos(100, 340) + yes.DoClick = function() + net.Start("nzMappingMismatchData") + net.WriteString("Map Script") + net.WriteTable({load = true}) + net.SendToServer() + nzMapping.MismatchData["Map Script"] = nil + frame:CloseTabAndOpenNew() + end + + local no = vgui.Create("DButton", pnl) + no:SetText("No") + no:SetSize(75, 20) + no:SetPos(200, 340) + no.DoClick = function() + net.Start("nzMappingMismatchData") + net.WriteString("Map Script") + net.WriteTable({load = false}) + net.SendToServer() + nzMapping.MismatchData["Map Script"] = nil + frame:CloseTabAndOpenNew() + end + + local txt12 = vgui.Create("DLabel", pnl) + txt12:SetText("Clicking submit or closing will make it not load.") + txt12:SetTextColor(Color(75,75,75)) + txt12:SetFont("Trebuchet18") + txt12:SizeToContents() + txt12:SetPos(0, 380) + txt12:CenterHorizontal() + + pnl.ReturnCorrectedData = function() -- In this case, just a default action + net.Start("nzMappingMismatchData") + net.WriteString("Map Script") + net.WriteTable({load = false}) + net.SendToServer() + nzMapping.MismatchData["Map Script"] = nil + end + + return pnl + + end, function( data ) + + if data.load then + nzMapping:LoadScript(nzMapping.ConfigFile) + end + + nzMapping.MismatchData["Map Script"] = nil +end) + +CreateMismatchCheck("Random Box Weapons", function() + local tbl = {} + if nzMapping.Settings.rboxweps and table.Count(nzMapping.Settings.rboxweps) > 0 then + for k,v in pairs(nzMapping.Settings.rboxweps) do + if !weapons.Get(k) then + print("Random Box has non-existant weapon class: " .. k .. "!") + tbl[k] = true + end + end + end + + return tbl -- Return the data you want to send to the client + +end, function(frame) + + local pnl = vgui.Create("DPanel", frame) + pnl:SetPos(5, 5) + pnl:SetSize(380, 425) + + local properties = vgui.Create("DProperties", pnl) + properties:SetPos(0, 0) + properties:SetSize(380, 420) + + for k,v in pairs(nzMapping.MismatchData["Random Box Weapons"]) do + local choice = properties:CreateRow( "Missing Box Weapons", k ) + choice:Setup( "Combo", {} ) + choice:AddChoice( " Remove ...", "nz_removeweapon", true ) + nzMapping.MismatchData["Random Box Weapons"][k] = "nz_removeweapon" + for _, v2 in pairs(weapons.GetList()) do + if !v2.NZPreventBox and !v2.NZTotalBlacklist then + if v2.Category and v2.Category != "" then + choice:AddChoice(v2.PrintName and v2.PrintName != "" and v2.Category.. " - "..v2.PrintName or v2.ClassName, v2.ClassName, false) + else + choice:AddChoice(v2.PrintName and v2.PrintName != "" and v2.PrintName or v2.ClassName, v2.ClassName, false) + end + end + end + choice.DataChanged = function(self, val) + nzMapping.MismatchData["Random Box Weapons"][k] = val + end + end + + pnl.ReturnCorrectedData = function() -- Add the function to the returned panel so we can access it outside + net.Start("nzMappingMismatchData") + net.WriteString("Random Box Weapons") + net.WriteTable(nzMapping.MismatchData["Random Box Weapons"]) + net.SendToServer() + nzMapping.MismatchData["Random Box Weapons"] = nil -- Clear the data + end + + return pnl -- Return it to add it the the sheets + +end, function( data ) + if nzMapping.Settings.rboxweps and table.Count(nzMapping.Settings.rboxweps) > 0 then + for k,v in pairs(nzMapping.Settings.rboxweps) do + local new = data[k] + if new then + if new != "nz_removeweapon" then + nzMapping.Settings.rboxweps[new] = v -- Insert new weapon with same weight + end + nzMapping.Settings.rboxweps[k] = nil -- Remove old one regardless + end + end + end + + nzMapping.MismatchData["Wall Buys"] = nil -- Clear the data +end) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/mapping/sh_sync.lua b/gamemodes/nzombies/gamemode/mapping/sh_sync.lua new file mode 100644 index 00000000..b9d5983d --- /dev/null +++ b/gamemodes/nzombies/gamemode/mapping/sh_sync.lua @@ -0,0 +1,57 @@ +if SERVER then + util.AddNetworkString( "nzMapping.SyncSettings" ) + + local function receiveMapData(len, ply) + local tbl = net.ReadTable() + PrintTable(tbl) + nzMapping:LoadMapSettings(tbl) + -- nzMapping.Settings = tbl + end + net.Receive( "nzMapping.SyncSettings", receiveMapData ) + + function nzMapping:SendMapData(ply) + if !self.GamemodeExtensions then self.GamemodeExtensions = {} end + net.Start("nzMapping.SyncSettings") + net.WriteTable(self.Settings) + return IsValid(ply) and net.Send(ply) or net.Broadcast() + end +end + +if CLIENT then + local function cleanUpMap() + game.CleanUpMap() + end + + net.Receive("nzCleanUp", cleanUpMap ) + + local function receiveMapData() + local oldeeurl = nzMapping.Settings.eeurl or "" + nzMapping.Settings = net.ReadTable() + + if !EEAudioChannel or (oldeeurl != nzMapping.Settings.eeurl and nzMapping.Settings.eeurl) then + EasterEggData.ParseSong() + end + + -- Precache all random box weapons in the list + if nzMapping.Settings.rboxweps then + local model = ClientsideModel("models/hoff/props/teddy_bear/teddy_bear.mdl") + for k,v in pairs(nzMapping.Settings.rboxweps) do + local wep = weapons.Get(k) + if wep and (wep.WM or wep.WorldModel) then + util.PrecacheModel(wep.WM or wep.WorldModel) + model:SetModel(wep.WM or wep.WorldModel) + end + end + model:Remove() + end + end + net.Receive( "nzMapping.SyncSettings", receiveMapData ) + + function nzMapping:SendMapData( data ) + if data then + net.Start("nzMapping.SyncSettings") + net.WriteTable(data) + net.SendToServer() + end + end +end diff --git a/gamemodes/nzombies/gamemode/mapping/sv_mapping.lua b/gamemodes/nzombies/gamemode/mapping/sv_mapping.lua new file mode 100644 index 00000000..7f3da16b --- /dev/null +++ b/gamemodes/nzombies/gamemode/mapping/sv_mapping.lua @@ -0,0 +1,420 @@ +-- + +function nzMapping:ZedSpawn(pos, link, ply) + + local ent = ents.Create("nz_spawn_zombie_normal") + pos.z = pos.z - ent:OBBMaxs().z + ent:SetPos( pos ) + ent:Spawn() + -- For the link displayer + if link != nil then + ent:SetLink(tostring(link)) + ent.link = tostring(link) + end + + if ply then + undo.Create( "Zombie Spawnpoint" ) + undo.SetPlayer( ply ) + undo.AddEntity( ent ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return ent +end + +function nzMapping:ZedSpecialSpawn(pos, link, ply) + + local ent = ents.Create("nz_spawn_zombie_special") + pos.z = pos.z - ent:OBBMaxs().z + ent:SetPos( pos ) + ent:Spawn() + -- For the link displayer + if link != nil then + ent:SetLink(tostring(link)) + ent.link = tostring(link) + end + + if ply then + undo.Create( "Special Zombie Spawnpoint" ) + undo.SetPlayer( ply ) + undo.AddEntity( ent ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return ent +end + +function nzMapping:PlayerSpawn(pos, ply) + + local ent = ents.Create("player_spawns") + pos.z = pos.z - ent:OBBMaxs().z + ent:SetPos( pos ) + ent:Spawn() + + if ply then + undo.Create( "Player Spawnpoint" ) + undo.SetPlayer( ply ) + undo.AddEntity( ent ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return ent + +end + +function nzMapping:EasterEgg(pos, ang, model, ply) + local egg = ents.Create( "easter_egg" ) + egg:SetModel( model ) + egg:SetPos( pos ) + egg:SetAngles( ang ) + egg:Spawn() + + local phys = egg:GetPhysicsObject() + if phys:IsValid() then + phys:EnableMotion(false) + end + + if ply then + undo.Create( "Easter Egg" ) + undo.SetPlayer( ply ) + undo.AddEntity( egg ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return egg +end + +function nzMapping:WallBuy(pos, gun, price, angle, oldent, ply, flipped) + + if IsValid(oldent) then oldent:Remove() end + + local ent = ents.Create("wall_buys") + ent:SetAngles(angle) + pos.z = pos.z - ent:OBBMaxs().z + ent:SetPos( pos ) + ent:SetWeapon(gun, price) + ent:Spawn() + --ent:PhysicsInit( SOLID_VPHYSICS ) + + local phys = ent:GetPhysicsObject() + if phys:IsValid() then + phys:EnableMotion(false) + end + + if flipped != nil then + ent:SetFlipped(flipped) + end + + if ply then + undo.Create( "Wall Gun" ) + undo.SetPlayer( ply ) + undo.AddEntity( ent ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return ent + +end + +function nzMapping:PropBuy(pos, ang, model, flags, ply) + local prop = ents.Create( "prop_buys" ) + prop:SetModel( model ) + prop:SetPos( pos ) + prop:SetAngles( ang ) + prop:Spawn() + prop:PhysicsInit( SOLID_VPHYSICS ) + + -- REMINDER APPY FLAGS + if flags != nil then + nzDoors:CreateLink( prop, flags ) + end + + local phys = prop:GetPhysicsObject() + if phys:IsValid() then + phys:EnableMotion(false) + end + + if ply then + undo.Create( "Prop" ) + undo.SetPlayer( ply ) + undo.AddEntity( prop ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return prop +end + +function nzMapping:Electric(pos, ang, model, ply) + --THERE CAN ONLY BE ONE TRUE HERO + local prevs = ents.FindByClass("power_box") + if prevs[1] != nil then + prevs[1]:Remove() + end + + local ent = ents.Create( "power_box" ) + ent:SetPos( pos ) + ent:SetAngles( ang ) + ent:Spawn() + ent:PhysicsInit( SOLID_VPHYSICS ) + + local phys = ent:GetPhysicsObject() + if phys:IsValid() then + phys:EnableMotion(false) + end + + if ply then + undo.Create( "Power Switch" ) + undo.SetPlayer( ply ) + undo.AddEntity( ent ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return ent +end + +function nzMapping:BlockSpawn(pos, ang, model, ply) + local block = ents.Create( "wall_block" ) + + -- Replace with nZombies versions of the same model (if exist) which are grate-based (bullets go through) + local model2 = string.Replace(model, "/hunter/plates/", "/nzombies_plates/") + if !util.IsValidModel(model2) then + model2 = model + end + print(model2) + + block:SetModel( model2 ) + block:SetPos( pos ) + block:SetAngles( ang ) + block:Spawn() + block:PhysicsInit( SOLID_VPHYSICS ) + print(block:GetModel()) + + local phys = block:GetPhysicsObject() + if IsValid(phys) then + phys:EnableMotion(false) + end + + if ply then + undo.Create( "Invisible Block" ) + undo.SetPlayer( ply ) + undo.AddEntity( block ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return block +end + +function nzMapping:BoxSpawn(pos, ang, spawn, ply) + local box = ents.Create( "random_box_spawns" ) + box:SetPos( pos ) + box:SetAngles( ang ) + box:Spawn() + box:PhysicsInit( SOLID_VPHYSICS ) + box:SetCollisionGroup( COLLISION_GROUP_DEBRIS_TRIGGER ) + box.PossibleSpawn = spawn + + if ply then + undo.Create( "Random Box Spawnpoint" ) + undo.SetPlayer( ply ) + undo.AddEntity( box ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return box +end + +function nzMapping:PerkMachine(pos, ang, id, ply) + if id == "wunderfizz" then + local perk = ents.Create("wunderfizz_machine") + perk:SetPos(pos) + perk:SetAngles(ang) + perk:Spawn() + perk:Activate() + perk:PhysicsInit( SOLID_VPHYSICS ) + perk:TurnOff() + + local phys = perk:GetPhysicsObject() + if phys:IsValid() then + phys:EnableMotion(false) + end + + if ply then + undo.Create( "Der Wunderfizz" ) + undo.SetPlayer( ply ) + undo.AddEntity( perk ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return perk + else + local perkData = nzPerks:Get(id) + + local perk = ents.Create("perk_machine") + perk:SetPerkID(id) + perk:TurnOff() + perk:SetPos(pos) + perk:SetAngles(ang) + perk:Spawn() + perk:Activate() + perk:PhysicsInit( SOLID_VPHYSICS ) + + local phys = perk:GetPhysicsObject() + if phys:IsValid() then + phys:EnableMotion(false) + end + + if ply then + undo.Create( "Perk Machine" ) + undo.SetPlayer( ply ) + undo.AddEntity( perk ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return perk + end +end + +function nzMapping:BreakEntry(pos, ang, planks, jump, ply) + local planks = planks + if planks == nil then planks = true else planks = tobool(planks) end + local jump = jump + if jump == nil then jump = false else jump = tobool(jump) end + + local entry = ents.Create( "breakable_entry" ) + entry:SetPos( pos ) + entry:SetAngles( ang ) + entry:SetHasPlanks(planks) + entry:SetTriggerJumps(jump) + entry:Spawn() + entry:PhysicsInit( SOLID_VPHYSICS ) + + local phys = entry:GetPhysicsObject() + if phys:IsValid() then + phys:EnableMotion(false) + end + + if ply then + undo.Create( "Barricade" ) + undo.SetPlayer( ply ) + undo.AddEntity( entry ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return entry +end + +function nzMapping:SpawnEffect( pos, ang, model, ply ) + + local e = ents.Create("nz_prop_effect") + e:SetModel(model) + e:SetPos(pos) + e:SetAngles( ang ) + e:Spawn() + e:Activate() + if ( !IsValid( e ) ) then return end + + if ply then + undo.Create( "Effect" ) + undo.SetPlayer( ply ) + undo.AddEntity( e ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return e + +end + +function nzMapping:SpawnEntity(pos, ang, ent, ply) + local entity = ents.Create( ent ) + entity:SetPos( pos ) + entity:SetAngles( ang ) + entity:Spawn() + entity:PhysicsInit( SOLID_VPHYSICS ) + + table.insert(nzQMenu.Data.SpawnedEntities, entity) + + entity:CallOnRemove("nzSpawnedEntityClean", function(ent) + table.RemoveByValue(nzQMenu.Data.SpawnedEntities, ent) + end) + + if ply then + undo.Create( "Entity" ) + undo.SetPlayer( ply ) + undo.AddEntity( entity ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return entity +end + +function nzMapping:CreateInvisibleWall(vec1, vec2, ply) + local wall = ents.Create( "invis_wall" ) + wall:SetPos( vec1 ) -- Later we might make the position the center + --wall:SetAngles( ang ) + --wall:SetMinBound(vec1) -- Just the position for now + wall:SetMaxBound(vec2) + wall:Spawn() + wall:PhysicsInitBox( Vector(0,0,0), vec2 ) + + local phys = wall:GetPhysicsObject() + if IsValid(phys) then + phys:EnableMotion(false) + end + + if ply then + undo.Create( "Invis Wall" ) + undo.SetPlayer( ply ) + undo.AddEntity( wall ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return wall +end + +function nzMapping:CreateInvisibleDamageWall(vec1, vec2, ply, dmg, delay, radiation, poison, tesla) + local wall = ents.Create( "invis_damage_wall" ) + wall:SetPos( vec1 ) + wall:SetMaxBound(vec2) + wall:Spawn() + wall:PhysicsInitBox( Vector(0,0,0), vec2 ) + wall:SetNotSolid(true) + wall:SetTrigger(true) + wall:SetDamage(dmg) + wall:SetDelay(delay) + + wall:SetRadiation(radiation) + wall:SetPoison(poison) + wall:SetTesla(tesla) + + local phys = wall:GetPhysicsObject() + if IsValid(phys) then + phys:EnableMotion(false) + end + + if ply then + undo.Create( "Damage Wall" ) + undo.SetPlayer( ply ) + undo.AddEntity( wall ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end + return wall +end + +-- Physgun Hooks +local ghostentities = { + ["prop_buys"] = true, + ["wall_block"] = true, + ["breakable_entry"] = true, + ["invis_wall"] = true, + --["wall_buys"] = true, +} +local function onPhysgunPickup( ply, ent ) + local class = ent:GetClass() + if ghostentities[class] or ent:ShouldPhysgunNoCollide() then + -- Ghost the entity so we can put them in walls. + local phys = ent:GetPhysicsObject() + phys:EnableCollisions(false) + phys:Wake() + end + +end + +local function onPhysgunDrop( ply, ent ) + local class = ent:GetClass() + if ghostentities[class] or ent:ShouldPhysgunNoCollide() then + -- Unghost the entity so we can put them in walls. + local phys = ent:GetPhysicsObject() + phys:EnableCollisions(true) + phys:EnableMotion(false) + phys:Sleep() + end + +end + +hook.Add( "PhysgunPickup", "nz.OnPhysPick", onPhysgunPickup ) +hook.Add( "PhysgunDrop", "nz.OnDrop", onPhysgunDrop ) diff --git a/gamemodes/nzombies/gamemode/mapping/sv_mapsettings.lua b/gamemodes/nzombies/gamemode/mapping/sv_mapsettings.lua new file mode 100644 index 00000000..78957b0f --- /dev/null +++ b/gamemodes/nzombies/gamemode/mapping/sv_mapsettings.lua @@ -0,0 +1,61 @@ + +function nzMapping:LoadMapSettings(data) + if !data then return end + + if data.startwep then + nzMapping.Settings.startwep = weapons.Get(data.startwep) and data.startwep or nzConfig.BaseStartingWeapons[1] + end + if data.startpoints then + nzMapping.Settings.startpoints = tonumber(data.startpoints) or 500 + end + if data.eeurl then + nzMapping.Settings.eeurl = data.eeurl or nil + end + if data.script then + nzMapping.Settings.script = data.script or nil + end + if data.scriptinfo then + nzMapping.Settings.scriptinfo = data.scriptinfo or nil + end + if data.rboxweps then + if table.Count(data.rboxweps) > 0 then + local tbl = {} + for k,v in pairs(data.rboxweps) do + local wep = weapons.Get(k) + if wep and !wep.NZTotalBlacklist and !wep.NZPreventBox then -- Weapons are keys + tbl[k] = tonumber(v) or 10 -- Set weight to value or 10 + else + wep = weapons.Get(v) -- Weapons are values (old format) + if wep and !wep.NZTotalBlacklist and !wep.NZPreventBox then + tbl[v] = 10 -- Set weight to 10 + else + -- No valid weapon on either key or value + if tonumber(k) == nil then -- For every key that isn't a number (new format keys are classes) + tbl[k] = 10 + end + if tonumber(v) == nil then -- Or for every value that isn't a number (old format values are classes) + tbl[v] = 10 -- Insert them anyway to make use of mismatch + end + end + end + end + nzMapping.Settings.rboxweps = tbl + else + nzMapping.Settings.rboxweps = nil + end + end + if data.wunderfizzperks then + nzMapping.Settings.wunderfizzperks = table.Count(data.wunderfizzperks) > 0 and data.wunderfizzperks or nil + end + if data.gamemodeentities then + nzMapping.Settings.gamemodeentities = data.gamemodeentities or nil + end + if data.specialroundtype then + nzMapping.Settings.specialroundtype = data.specialroundtype or "Hellhounds" + end + if data.bosstype then + nzMapping.Settings.bosstype = data.bosstype or "Panzer" + end + + nzMapping:SendMapData() +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/mapping/sv_saveload.lua b/gamemodes/nzombies/gamemode/mapping/sv_saveload.lua new file mode 100644 index 00000000..e72c1d2c --- /dev/null +++ b/gamemodes/nzombies/gamemode/mapping/sv_saveload.lua @@ -0,0 +1,409 @@ +nzMapping.Version = 400 --Note to Ali; Any time you make an update to the way this is saved, increment this. + +local savemodules = savemodules or {} + +function nzMapping:AddSaveModule(id, tbl) + savemodules[id] = tbl +end + +function nzMapping:SaveConfig(name) + + local main = {} + + --Check if the nz folder exists + if !file.Exists( "nz/", "DATA" ) then + file.CreateDir( "nz" ) + end + + main.version = self.Version + + -- Loop through our savemodules + for id, funcs in pairs(savemodules) do + print("[nZ] Saving module ["..id.."]...") + local succ, err = pcall(funcs.savefunc) -- Run their save function and get the returned table + if succ then -- If it didn't error + local tbl = err -- Second argument becomes the table + main[id] = tbl -- Saves the table under the ID + else + print("[ERROR] in nZ Save Module ["..id.."]:") + ErrorNoHalt(err) -- We make sure these errors don't halt the save process! + print("\n") + print(debug.traceback()) + print("Skipped save module ["..id.."]...") + end + end + + -- These are hardcoded and run after any modules, meaning they can't be overwritten + main["NavTable"] = nzNav.Locks + main["MapSettings"] = self.Settings + main["RemoveProps"] = self.MarkedProps + + local configname + if name and name != "" then + configname = "nz/nz_" .. game.GetMap() .. ";" .. name .. ".txt" + else + configname = "nz/nz_" .. game.GetMap() .. ";" .. os.date("%H_%M_%j") .. ".txt" + end + + file.Write( configname, util.TableToJSON( main ) ) -- Save it all in a JSON format + PrintMessage( HUD_PRINTTALK, "[nZ] Saved to garrysmod/data/" .. configname) -- And write it to our file! >:D + + nzMapping.CurrentConfig = name + +end + +function nzMapping:ClearConfig(noclean) + print("[nZ] Clearing current map") + + -- ALWAYS do this first! + nzMapping:UnloadScript() + + -- Some default entities to clear: + local entClasses = { + ["edit_fog"] = true, + ["edit_fog_special"] = true, + ["edit_sky"] = true, + ["edit_color"] = true, + ["edit_sun"] = true, + ["edit_dynlight"] = true, + ["nz_triggerzone"] = true, + ["nz_script_triggerzone"] = true, + ["nz_script_prop"] = true, + } + + -- Now loop through our savemodules + for id, funcs in pairs(savemodules) do + print("[nZ] Clearing config for module ["..id.."]...") + if funcs.cleanents then -- If the module has a table of entities + for k,v in pairs(funcs.cleanents) do + entClasses[v] = true -- Then mark these to also be cleared + end + end + if funcs.cleanfunc then -- If we have a clean func + local succ, err = pcall(funcs.cleanfunc) -- Then run it! + if !succ then + print("[ERROR] in nZ Save Module ["..id.."]:") + ErrorNoHalt(err) -- Print the error, but don't stop the rest of the modules! + print("\n") + print(debug.traceback()) + print("\nSkipped clean for module ["..id.."]...") -- It doesn't actually quite skip it, rather it stops mid-func + end + end + end + + -- Now loop over all marked entities and remove them all in one single loop + for k,v in pairs(ents.GetAll()) do + if entClasses[v:GetClass()] then + v:Remove() + end + end + + --Reset Navigation table, Settings and MarkedProps (Hardcoded modules) + nzNav.Locks = {} + nzMapping.Settings = {} + nzMapping.MarkedProps = {} + + for k,v in pairs(player.GetAll()) do + nzMapping:SendMapData(v) + end + + -- Sync + FullSyncModules["Round"]() + + -- Clear out the item objects creating with this config (if any) + nzItemCarry:CleanUp() + + nzMapping.CurrentConfig = nil + nzMapping.ConfigFile = nil + + if !noclean then + game.CleanUpMap() -- No need for restorative measures (nzMapping:CleanUpMap()) + end +end + +function nzMapping:LoadConfig( name, loader ) + + hook.Call("PreConfigLoad") + + local filepath = "nz/" .. name + local location = "DATA" + local official = false + + if string.GetExtensionFromFilename(name) == "lua" then + if file.Exists("gamemodes/nzombies/officialconfigs/"..name, "GAME") then + location, filepath = "GAME", "gamemodes/nzombies/officialconfigs/"..name + official = true + else + location = "LUA" + end + end + + if file.Exists( filepath, location )then + print("[nZ] MAP CONFIG FOUND!") + + local cfg = string.Explode(";", string.StripExtension(name)) + local map, configname, workshopid = string.sub(cfg[1], 4), cfg[2], cfg[3] + + -- BUT WAIT! Is it another map? :O + if map and map != game.GetMap() then + file.Write("nz/autoload.txt", loader and name.."@"..loader:SteamID() or name.."@INVALIDPLAYER") + RunConsoleCommand("changelevel", map) + return + end + + -- Load a lua file for a specific map + -- Make sure all hooks are removed before adding the new ones + nzMapping:UnloadScript() + + local data = util.JSONToTable( file.Read( filepath, location ) ) + + if !data then + print("Critical Warning: Could not read data from file! Is the save corrupted? It might be possible to recover with manual text editing.") + return + end + + local version = data.version + + -- Check the version of the config. + if version == nil then + print("This map config is too out of date to be used. Sorry about that!") + return + end + + if version < nzMapping.Version then + print("Warning: This map config was made with an older version of nZombies. After this has loaded, use the save command to save a newer version.") + end + + if version < 300 then + print("Warning: Inital Version: No changes have been made.") + end + + if version < 350 then + print("Warning: This map config does not contain any set barricades.") + end + + self:ClearConfig(true) -- We pass true to not clean up the map + + -- Then we can load if entity extensions are to be used + if data.MapSettings then + nzMapping:LoadMapSettings(data.MapSettings) + -- That way, the gamemode entities will spawn without getting removed during the map clean up + end + -- That we then manually call here + nzMapping:CleanUpMap() + + + print("[nZ] Loading " .. filepath .. "...") + + + -- Start sorting the data + for id, funcs in pairs(savemodules) do + if data[id] then -- If data was saved by this module's ID + print("[nZ] Loading module ["..id.."]...") -- Load for it + local succ, err = pcall(funcs.loadfunc, data[id]) -- Call the load function with the data as argument + if !succ then + print("[ERROR] in nZ Load Module ["..id.."]:") + ErrorNoHalt(err) -- Let's not let it stop us! + print("\n") + print(debug.traceback()) + print("Skipped load module ["..id.."]...") + end + end + end + + -- NavTable, Map Settings, Removed Props (Hardcoded modules) + if data.NavTable then + nzNav.Locks = data.NavTable + end + + for k,v in pairs(player.GetAll()) do + nzMapping:SendMapData(v) + end + + if data.RemoveProps then + nzMapping.MarkedProps = data.RemoveProps + if !nzRound:InState( ROUND_CREATE ) then + for k,v in pairs(nzMapping.MarkedProps) do + local ent = ents.GetMapCreatedEntity(k) + if IsValid(ent) then ent:Remove() end + end + else + for k,v in pairs(nzMapping.MarkedProps) do + local ent = ents.GetMapCreatedEntity(k) + if IsValid(ent) then ent:SetColor(Color(200,0,0)) end + end + end + end + + nzMapping:CheckMismatch( loader ) + + -- Set the current config name, we will use this to load scripts via mismatch window + nzMapping.CurrentConfig = configname + nzMapping.OfficialConfig = official + nzMapping.ConfigFile = name + + if !nzRound:InState(ROUND_CREATE) then + for k,v in pairs(ents.GetAll()) do + if v.NZOnlyVisibleInCreative then -- This is set in each entity's file + v:SetNoDraw(true) -- Yes this improves FPS by ~50% over a client-side convar and round state check + end + end + end + + print("[nZ] Finished loading map config.") + hook.Call("PostConfigLoad", nil, true) + else + print(filepath) + print("[nZ] Warning: NO MAP CONFIG FOUND! Make a config in game using the /create command, then use /save to save it all!") + hook.Call("PostConfigLoad", nil, false) + end + +end + +-- The function to clean up the map but not the config! +function nzMapping:CleanUpMap() + + hook.Call("PreConfigMapCleanup") + + -- Some default entities to spare: + local entClasses = { + --["edit_fog"] = true, + ["edit_fog_special"] = true, + ["edit_sky"] = true, + ["edit_color"] = true, + ["edit_sun"] = true, + ["edit_dynlight"] = true, + ["nz_triggerzone"] = true, + ["nz_script_triggerzone"] = true, + ["nz_script_prop"] = true, + } + + -- Prepare to save module data + local module_savetable = {} + + -- Loop through modules + for id, funcs in pairs(savemodules) do + if funcs.cleanents then + for k,v in pairs(funcs.cleanents) do + entClasses[v] = true -- All entities marked will this time be SPARED from the map cleanup + end + end + if funcs.prerestorefunc then -- If we have a pre-restore function (before map cleanup) + print("[nZ] Preparing map cleanup restore data for module ["..id.."]...") + local succ, err = pcall(funcs.prerestorefunc) -- Then call it and get the data (if any) + if succ then + local tbl = err + if tbl then + module_savetable[id] = tbl -- Save it in our temporary table + end + else + print("[ERROR] in nZ Save Module ["..id.."]:") + ErrorNoHalt(err) + print("\n") + print(debug.traceback()) + print("Skipped pre-restore for module ["..id.."]...") + end + end + end + + -- Now we clean up the map, sparing the marked entities! + game.CleanUpMap(false, table.GetKeys(entClasses)) + + -- And we come back to our save modules + for id, funcs in pairs(savemodules) do + if funcs.postrestorefunc then -- Because if they have a restoration function + print("[nZ] Executing post-map cleanup restoration for module ["..id.."]...") + local succ, err = pcall(funcs.postrestorefunc, module_savetable[id]) -- Then we need to run it with the data + if !succ then + print("[ERROR] in nZ Save Module ["..id.."]:") + ErrorNoHalt(err) + print("Skipped pre-restore for module ["..id.."]...") + end + end + end + + -- These are from the the hardcoded modules + if self.MarkedProps then + if !nzRound:InState( ROUND_CREATE ) then + for k,v in pairs(self.MarkedProps) do + local ent = ents.GetMapCreatedEntity(k) + if IsValid(ent) then ent:Remove() end + end + else + for k,v in pairs(self.MarkedProps) do + local ent = ents.GetMapCreatedEntity(k) + if IsValid(ent) then ent:SetColor(Color(200,0,0)) end + end + end + end + + hook.Call("PostConfigMapCleanup") +end + +hook.Add("Initialize", "nz_Loadmaps", function() + timer.Simple(5, function() + local autoload + local isautomated = false + if file.Exists("nz/autoload.txt", "DATA") then + local data = string.Explode("@", file.Read("nz/autoload.txt", "DATA")) + if data and data != "" then + autoload, loader = data[1], data[2] + if loader then + loader = game.SinglePlayer() and Entity(1) or player.GetBySteamID(loader) + end + end + end + if !autoload or #autoload <= 0 then + if file.Exists("nz/server_autoload.txt", "DATA") then + local data = util.JSONToTable(file.Read("nz/server_autoload.txt", "DATA")) + if data then + if data[game.GetMap()] then + autoload = data[game.GetMap()] + isautomated = true + end + end + else + if !file.Exists( "nz/", "DATA" ) then + file.CreateDir( "nz" ) + end + file.Write("nz/server_autoload.txt", util.TableToJSON({ + ["some_map1"] = "config_to_autoload1", + ["some_map2"] = "config_to_autoload2", + ["some_map3"] = "config_to_autoload3" + })) + end + end + if !autoload then + autoload = "nz_"..game.GetMap()..".txt" + isautomated = true + end + + local map = string.sub(string.Explode(";", string.StripExtension(autoload))[1], 4) + if map and map != game.GetMap() then + file.Write("nz/autoload.txt", "") + if !isautomated then + -- Automatic map loads (such as from server_autoload.txt or just game map) does not stop here + return + end + end + + nzMapping:LoadConfig( autoload, IsValid(loader) and loader or nil ) + end) +end) + +function nzMapping:QueueConfig( name, loader ) + if name then + self.QueuedConfig = {config = name, loader = loader} + else + self.QueueConfig = nil + end +end + +function nzMapping:GetConfigs() + local tbl = {} + tbl.configs = file.Find( "nz/nz_*", "DATA" ) + tbl.workshopconfigs = file.Find( "nz/nz_*", "LUA" ) + tbl.officialconfigs = file.Find("gamemodes/nzombies/officialconfigs/*", "GAME") + + return tbl +end diff --git a/gamemodes/nzombies/gamemode/mapping/sv_savemodules.lua b/gamemodes/nzombies/gamemode/mapping/sv_savemodules.lua new file mode 100644 index 00000000..f7737efd --- /dev/null +++ b/gamemodes/nzombies/gamemode/mapping/sv_savemodules.lua @@ -0,0 +1,454 @@ +-- In here we have all default savemodules. You can add your own with the function used here: +-- nzMapping:AddSaveModule(id, {savefunc, loadfunc, cleanents, cleanfunc, prerestorefunc, postrestorefunc}) + +-- Savefunc should return the table to be written into the save file + +-- Loadfunc takes 1 argument, data, which is the saved table + +-- Cleanents is a table containing all entity types that should get cleaned when the config is cleared +-- and that should be spared when the map is cleanup for a simple game reset + +-- Cleanfunc is run when the config is wiped, like when switching config or /clean (not after each game) +-- It should remove all entities related to your module that aren't in the cleanents table + +-- Prerestorefunc is only used for modules that need to "reinitialize" post-map cleanup (NOT config cleanup, MAP cleanup) +-- This is run before the map cleanup, making you able to temporarily save data to use after the map cleanup again +-- This function should only be used for stuff that needs to mark how it is before map cleanup, to reset to that post-cleanup +-- such as SpecialEntities that need to be temporarily duplicate-saved so they can be spawned afterwards +-- It should return a table that will be used in the postrestorefunc + +-- Postrestorefunc is only used for stuff that needs to "reintialize" after the map has been cleaned up, like Prerestorefunc +-- It gets an argument, data, which is the table stored from Prerestorefunc, if any +-- This function should be used for stuff such as doors, that otherwise would be cleaned up by map cleanup +-- and thus needs to get their data re-applied. + +-- Put simply: +-- savefunc: Run when saved +-- loadfunc: Run when load +-- cleanents: A table containing entities related to module +-- cleanfunc: Run when CONFIG is cleaned (optional) +-- prerestorefunc: Run before MAP is cleaned and NOT config (optional) +-- postrestorefunc: Run after MAP is cleaned and NOT config (optional) + +-- Note: MAP is cleaned after EVERY game (restore funcs)! +-- MAP cleanup ignores all entity types in CLEANENTS! +-- Always add entity types that relate to your module that should NOT be removed on reset, but SHOULD on clean! + +nzMapping:AddSaveModule("ZedSpawns", { + savefunc = function() + local zed_spawns = {} + for _, v in pairs(ents.FindByClass("nz_spawn_zombie_normal")) do + table.insert(zed_spawns, { + pos = v:GetPos(), + link = v.link + }) + end + return zed_spawns + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:ZedSpawn(v.pos, v.link) + end + end, + cleanents = {"nz_spawn_zombie_normal"}, -- Simply clean entities of this type +}) + +nzMapping:AddSaveModule("ZedSpecialSpawns", { + savefunc = function() + local zed_special_spawns = {} + for _, v in pairs(ents.FindByClass("nz_spawn_zombie_special")) do + table.insert(zed_special_spawns, { + pos = v:GetPos(), + link = v.link + }) + end + return zed_special_spawns + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:ZedSpecialSpawn(v.pos, v.link) + end + end, + cleanents = {"nz_spawn_zombie_special"}, +}) + +nzMapping:AddSaveModule("PlayerSpawns", { + savefunc = function() + local player_spawns = {} + for _, v in pairs(ents.FindByClass("player_spawns")) do + table.insert(player_spawns, { + pos = v:GetPos(), + }) + end + return player_spawns + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:PlayerSpawn(v.pos) + end + end, + cleanents = {"player_spawns"}, +}) + +nzMapping:AddSaveModule("WallBuys", { + savefunc = function() + local wall_buys = {} + for _, v in pairs(ents.FindByClass("wall_buys")) do + table.insert(wall_buys, { + pos = v:GetPos(), + wep = v.WeaponGive, + price = v.Price, + angle = v:GetAngles(), + flipped = v:GetFlipped(), + }) + end + return wall_buys + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:WallBuy(v.pos,v.wep, v.price, v.angle, nil, nil, v.flipped) + end + end, + cleanents = {"wall_buys"}, + postrestorefunc = function(data) -- Post-map cleanup restoration (game reset) + -- Reset bought status on wall buys + for k,v in pairs(ents.FindByClass("wall_buys")) do + v:SetBought(false) + end + end, +}) + +nzMapping:AddSaveModule("BuyablePropSpawns", { + savefunc = function() + local buyableprop_spawns = {} + for _, v in pairs(ents.FindByClass("prop_buys")) do + + -- Convert the table to a flag string - if it even has any + local data = v:GetDoorData() + local flagstr + if data then + flagstr = "" + for k2, v2 in pairs(data) do + flagstr = flagstr .. k2 .."=" .. v2 .. "," + end + flagstr = string.Trim(flagstr, ",") + end + + table.insert(buyableprop_spawns, { + pos = v:GetPos(), + angle = v:GetAngles(), + model = v:GetModel(), + flags = flagstr, + collision = v:GetCollisionGroup(), + }) + end + return buyableprop_spawns + end, + loadfunc = function(data) + for k,v in pairs(data) do + local prop = nzMapping:PropBuy(v.pos, v.angle, v.model, v.flags) + prop:SetCollisionGroup(v.collision or COLLISION_GROUP_NONE) + end + end, + cleanents = {"prop_buys"}, +}) + +nzMapping:AddSaveModule("PropEffects", { + savefunc = function() + local prop_effects = {} + for _, v in pairs(ents.FindByClass("nz_prop_effect")) do + table.insert(prop_effects, { + pos = v:GetPos(), + angle = v:GetAngles(), + model = v.AttachedEntity:GetModel(), + }) + end + return prop_effects + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:SpawnEffect(v.pos, v.angle, v.model) + end + end, + cleanents = {"nz_prop_effect", "nz_prop_effect_attachment"}, +}) + +nzMapping:AddSaveModule("EasterEggs", { + savefunc = function() + local easter_eggs = {} + for _, v in pairs(ents.FindByClass("easter_egg")) do + table.insert(easter_eggs, { + pos = v:GetPos(), + angle = v:GetAngles(), + model = v:GetModel(), + }) + end + return easter_eggs + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:EasterEgg(v.pos, v.angle, v.model) + end + end, + cleanents = {"easter_egg"}, +}) + +nzMapping:AddSaveModule("ElecSpawns", { + savefunc = function() + local elec_spawn = {} + for _, v in pairs(ents.FindByClass("power_box")) do + table.insert(elec_spawn, { + pos = v:GetPos(), + angle = v:GetAngles( ), + }) + end + return elec_spawn + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:Electric(v.pos, v.angle) + end + end, + cleanents = {"power_box", "button_elec"}, -- Cleans two entity types +}) + +nzMapping:AddSaveModule("BlockSpawns", { + savefunc = function() + local block_spawns = {} + for _, v in pairs(ents.FindByClass("wall_block")) do + table.insert(block_spawns, { + pos = v:GetPos(), + angle = v:GetAngles(), + model = v:GetModel(), + }) + end + return block_spawns + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:BlockSpawn(v.pos, v.angle, v.model) + end + end, + cleanents = {"wall_block"}, +}) + +nzMapping:AddSaveModule("RandomBoxSpawns", { + savefunc = function() + local randombox_spawn = {} + for _, v in pairs(ents.FindByClass("random_box_spawns")) do + table.insert(randombox_spawn, { + pos = v:GetPos(), + angle = v:GetAngles(), + spawn = v.PossibleSpawn, + }) + end + return randombox_spawn + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:BoxSpawn(v.pos, v.angle, v.spawn) + end + end, + cleanents = {"random_box_spawns"}, +}) + +nzMapping:AddSaveModule("PerkMachineSpawns", { + savefunc = function() + local perk_machinespawns = {} + for _, v in pairs(ents.FindByClass("perk_machine")) do + table.insert(perk_machinespawns, { + pos = v:GetPos(), + angle = v:GetAngles(), + id = v:GetPerkID(), + }) + end + for _, v in pairs(ents.FindByClass("wunderfizz_machine")) do + table.insert(perk_machinespawns, { + pos = v:GetPos(), + angle = v:GetAngles(), + id = "wunderfizz", + }) + end + return perk_machinespawns + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:PerkMachine(v.pos, v.angle, v.id) + end + end, + cleanents = {"perk_machine", "wunderfizz_machine", "wunderfizz_windup"}, +}) + +nzMapping:AddSaveModule("DoorSetup", { + savefunc = function() + local door_setup = {} + for k,v in pairs(nzDoors.MapDoors) do + local flags = "" + for k2, v2 in pairs(v.flags) do + flags = flags .. k2 .. "=" .. v2 .. "," + end + flags = string.Trim(flags, ",") + door = nzDoors:DoorIndexToEnt(k) + if door:IsDoor() then + door_setup[k] = { + flags = flags, + } + --print(door.Data) + end + end + return door_setup + end, + loadfunc = function(data) + for k,v in pairs(data) do + --print(v.flags) + nzDoors:CreateMapDoorLink(k, v.flags) + end + end, + cleanfunc = function() + -- Cleans up differently, does not return any entity types + for k,v in pairs(nzDoors.MapDoors) do + nzDoors:RemoveMapDoorLink( k ) + end + + -- This module is responsible for both prop doors and map doors + nzDoors.MapDoors = {} + nzDoors.PropDoors = {} + -- Clear all door data on clients + net.Start("nzClearDoorData") + net.Broadcast() + end, + postrestorefunc = function(data) + -- Doors are reset by map cleanup, we loop through the data and reapply them! + for k,v in pairs(nzDoors.MapDoors) do + local door = nzDoors:DoorIndexToEnt(k) + door:SetLocked(true) + if door:IsDoor() then + door:LockDoor() + elseif door:IsButton() then + door:LockButton() + end + nzDoors.SendSync( ply ) + end + end, +}) + +nzMapping:AddSaveModule("BreakEntry", { + savefunc = function() + local break_entry = {} + for _, v in pairs(ents.FindByClass("breakable_entry")) do + table.insert(break_entry, { + pos = v:GetPos(), + angle = v:GetAngles(), + planks = v:GetHasPlanks(), + jump = v:GetTriggerJumps(), + }) + end + return break_entry + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:BreakEntry(v.pos, v.angle, v.planks, v.jump) + end + end, + cleanents = {"breakable_entry", "breakable_entry_plank"}, + postrestorefunc = function(data) + -- Now we respawn them! :D + for k,v in pairs(ents.FindByClass("breakable_entry")) do + if IsValid(v) then + v:ResetPlanks() + end + end + end, +}) + +nzMapping:AddSaveModule("SpecialEntities", { + savefunc = function() + local special_entities = {} + for k, v in pairs(nzQMenu.Data.SpawnedEntities) do + if IsValid(v) then + table.insert(special_entities, duplicator.CopyEntTable(v)) + else + nzQMenu.Data.SpawnedEntities[k] = nil + end + end + return special_entities + end, + loadfunc = function(data) + for k,v in pairs(data) do + --PrintTable(v) + local ent = duplicator.CreateEntityFromTable(Entity(1), v) + table.insert(nzQMenu.Data.SpawnedEntities, ent) + end + end, + cleanfunc = function() + --Specially spawned entities are directly removed, not by type + for k,v in pairs(nzQMenu.Data.SpawnedEntities) do + if IsValid(v) then + v:Remove() + end + end + nzQMenu.Data.SpawnedEntities = {} -- Also cleanup the table from it + end, + prerestorefunc = function() -- PRE-map cleanup! Save all special entities before they are wiped! + local special_entities = {} + for k,v in pairs(nzQMenu.Data.SpawnedEntities) do + if IsValid(v) then + special_entities[v] = duplicator.CopyEntTable(v) + end + end + return special_entities -- Return the data to be used in the next function after the cleanup + end, + postrestorefunc = function(data) + -- Now we respawn them! :D + for k,v in pairs(data) do + if !IsValid(k) then -- Only if they aren't still around + local ent = duplicator.CreateEntityFromTable(Entity(1), v) + table.insert(nzQMenu.Data.SpawnedEntities, ent) + end + end + end, +}) + +nzMapping:AddSaveModule("InvisWalls", { + savefunc = function() + -- Store all invisible walls with their boundaries and angles + local invis_walls = {} + for _, v in pairs(ents.FindByClass("invis_wall")) do + table.insert(invis_walls, { + pos = v:GetPos(), + maxbound = v:GetMaxBound(), + }) + end + return invis_walls + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:CreateInvisibleWall(v.pos, v.maxbound) + end + end, + cleanents = {"invis_wall"}, +}) + +nzMapping:AddSaveModule("DamageWalls", { + savefunc = function() + local invis_damage_walls = {} + for _, v in pairs(ents.FindByClass("invis_damage_wall")) do + table.insert(invis_damage_walls, { + pos = v:GetPos(), + maxbound = v:GetMaxBound(), + damage = v:GetDamage(), + delay = v:GetDelay(), + radiation = v:GetRadiation(), + poison = v:GetPoison(), + tesla = v:GetTesla(), + }) + end + return invis_damage_walls + end, + loadfunc = function(data) + for k,v in pairs(data) do + nzMapping:CreateInvisibleDamageWall(v.pos, v.maxbound, nil, v.damage, v.delay, v.radiation, v.poison, v.tesla) + end + end, + cleanents = {"invis_damage_wall"}, +}) diff --git a/gamemodes/nzombies/gamemode/mapping/sv_validation.lua b/gamemodes/nzombies/gamemode/mapping/sv_validation.lua new file mode 100644 index 00000000..276cc3af --- /dev/null +++ b/gamemodes/nzombies/gamemode/mapping/sv_validation.lua @@ -0,0 +1,24 @@ +function nzMapping:CheckSpawns() + + --Check Player spawns + if #ents.FindByClass("player_spawns") == 0 then + return false + end + + --Check Zombie Spawns + if #ents.FindByClass("nz_spawn_zombie_*") == 0 then + return false + end + + return true +end + +function nzMapping:CheckEnoughPlayerSpawns() + + //Check Player spawns + if #ents.FindByClass("player_spawns") < #player.GetAll() then + return false + end + + return true +end diff --git a/gamemodes/nzombies/gamemode/misc/cl_precache.lua b/gamemodes/nzombies/gamemode/misc/cl_precache.lua new file mode 100644 index 00000000..42b20653 --- /dev/null +++ b/gamemodes/nzombies/gamemode/misc/cl_precache.lua @@ -0,0 +1,47 @@ + +-- Zombies +util.PrecacheModel("models/nz_zombie/zombie_rerig_animated.mdl") +util.PrecacheModel("models/nz_zombie/zombie_hellhound.mdl") + +-- Perk machines +util.PrecacheModel("models/alig96/perks/cherry/cherry.mdl") +util.PrecacheModel("models/alig96/perks/deadshot/deadshot.mdl") +util.PrecacheModel("models/alig96/perks/doubletap/doubletap_off.mdl") +util.PrecacheModel("models/alig96/perks/doubletap/doubletap_on.mdl") +util.PrecacheModel("models/alig96/perks/doubletap2/doubletap2.mdl") +util.PrecacheModel("models/alig96/perks/jugg/jugg_off.mdl") +util.PrecacheModel("models/alig96/perks/jugg/jugg_on.mdl") +util.PrecacheModel("models/alig96/perks/mulekick/mulekick.mdl") +util.PrecacheModel("models/alig96/perks/packapunch/packapunch.mdl") +util.PrecacheModel("models/alig96/perks/phd/phdflopper.mdl") +util.PrecacheModel("models/alig96/perks/revive/revive_off.mdl") +util.PrecacheModel("models/alig96/perks/revive/revive_on.mdl") +util.PrecacheModel("models/alig96/perks/speed/speed_off.mdl") +util.PrecacheModel("models/alig96/perks/speed/speed_on.mdl") +util.PrecacheModel("models/alig96/perks/staminup/staminup.mdl") +util.PrecacheModel("models/alig96/perks/tombstone/tombstone.mdl") +util.PrecacheModel("models/alig96/perks/vulture/vultureaid.mdl") +util.PrecacheModel("models/alig96/perks/whoswho/whoswho.mdl") + +-- Mysery box, teddy and other props +util.PrecacheModel("models/hoff/props/mysterybox/box.mdl") +util.PrecacheModel("models/hoff/props/mysterybox/box1.mdl") +util.PrecacheModel("models/hoff/props/mysterybox/box2.mdl") +util.PrecacheModel("models/hoff/props/teddy_bear/teddy_bear.mdl") +util.PrecacheModel("models/nzprops/monkey_bomb.mdl") +util.PrecacheModel("models/nzprops/power_lever.mdl") +util.PrecacheModel("models/nzprops/power_lever_handle.mdl") +util.PrecacheModel("models/nzprops/power_lever_short.mdl") + +-- Powerups +util.PrecacheModel("models/nzpowerups/carpenter.mdl") +util.PrecacheModel("models/nzpowerups/nuke.mdl") +util.PrecacheModel("models/nzpowerups/x2.mdl") +util.PrecacheModel("models/nzpowerups/insta.mdl") + +-- Viewmodels +util.PrecacheModel("models/weapons/c_perk_bottle.mdl") +util.PrecacheModel("models/weapons/c_monkey_bomb.mdl") +util.PrecacheModel("models/weapons/c_bowie_knife.mdl") +util.PrecacheModel("models/weapons/c_revive_morphine.mdl") +util.PrecacheModel("models/weapons/c_packapunch_arms.mdl") \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/misc/sh_constructor.lua b/gamemodes/nzombies/gamemode/misc/sh_constructor.lua new file mode 100644 index 00000000..1d6d6a64 --- /dev/null +++ b/gamemodes/nzombies/gamemode/misc/sh_constructor.lua @@ -0,0 +1,2 @@ +-- Main Tables +nzMisc = nzMisc or AddNZModule("Misc") diff --git a/gamemodes/nzombies/gamemode/misc/sh_playerinit.lua b/gamemodes/nzombies/gamemode/misc/sh_playerinit.lua new file mode 100644 index 00000000..516f383f --- /dev/null +++ b/gamemodes/nzombies/gamemode/misc/sh_playerinit.lua @@ -0,0 +1,33 @@ +if SERVER then + util.AddNetworkString("nz_PlayerInit") + net.Receive("nz_PlayerInit", function(len, ply) + hook.Call("PlayerFullyInitialized", nil, ply) + end) + + hook.Add("PlayerInitialSpawn", "nzCheckIfInSteamGroup", function(ply) + -- I ask of you that you do not remove the below part. This part was made as a reward for being part of my Steam Group. + -- Since this reward is to be used universally on all servers, I ask of you that you do not remove it. Thank you :) + http.Fetch( "http://steamcommunity.com/groups/the_banter_brigade/memberslistxml/?xml=1", + function(body) -- On Success + local playerIDStartIndex = ply:SteamID64() and string.find( tostring(body), ""..ply:SteamID64().."" ) or print("Can't get SteamID64 in single player. Weaponized YTi-L4 is unavailable.") + if playerIDStartIndex == nil then return else + ply.nz_InSteamGroup = true + ply:PrintMessage(HUD_PRINTCONSOLE, "Thank you for being part of the Banter Brigade Steam Group. YTi-L4 is accessible to you in the box.") + end + end, + function() -- On fail + print("Couldn't get it the data from the Banter Brigade Steam Group. Weaponized YTi-L4 is unavailable") + end + ) + end) + + hook.Add("PlayerFullyInitialized", "SetPlayerClassInit", function(ply) + player_manager.SetPlayerClass( ply, "player_ingame" ) + end) +else + hook.Add("InitPostEntity", "PlayerFullyInitialized", function() + net.Start("nz_PlayerInit") + net.SendToServer() + end) + +end diff --git a/gamemodes/nzombies/gamemode/misc/sh_weightedrandom.lua b/gamemodes/nzombies/gamemode/misc/sh_weightedrandom.lua new file mode 100644 index 00000000..9f5a7c6f --- /dev/null +++ b/gamemodes/nzombies/gamemode/misc/sh_weightedrandom.lua @@ -0,0 +1,40 @@ +-- http://snippets.luacode.org/snippets/Weighted_random_choice_104 + +-- Modified to allow special weight keys + +local function weighted_total( choices, weightkey ) + local total = 0 + if weightkey then + for choice, weight in pairs(choices) do + total = total + weight[weightkey] + end + else + for choice, weight in pairs(choices) do + total = total + weight + end + end + return total +end + +local function weighted_random_choice( choices, weightkey ) + local threshold = math.random(0, weighted_total( choices, weightkey )) + local last_choice + if weightkey then + for choice, weight in pairs(choices) do + threshold = threshold - weight[weightkey] + if threshold <= 0 then return choice end + last_choice = choice + end + else + for choice, weight in pairs(choices) do + threshold = threshold - weight + if threshold <= 0 then return choice end + last_choice = choice + end + end + return last_choice +end + +function nzMisc.WeightedRandom( choices, weightkey ) + return weighted_random_choice( choices, weightkey ) +end diff --git a/nzombies3/gamemode/misc/sv_autoreload.lua b/gamemodes/nzombies/gamemode/misc/sv_autoreload.lua similarity index 77% rename from nzombies3/gamemode/misc/sv_autoreload.lua rename to gamemodes/nzombies/gamemode/misc/sv_autoreload.lua index 3a76d986..95b0fa48 100644 --- a/nzombies3/gamemode/misc/sv_autoreload.lua +++ b/gamemodes/nzombies/gamemode/misc/sv_autoreload.lua @@ -6,12 +6,12 @@ function GM:OnReloaded( ) if v:IsDoor() or v:IsBuyableProp() then local data = v.Data if data != nil then - nz.Doors.Functions.CreateLink(v, data) + nzDoors:CreateLink(v, data) end end end - nz.Players.Functions.FullSync( ply ) + nzPlayers:FullSync( ply ) end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/misc/sv_consolecommands.lua b/gamemodes/nzombies/gamemode/misc/sv_consolecommands.lua new file mode 100644 index 00000000..356d25e3 --- /dev/null +++ b/gamemodes/nzombies/gamemode/misc/sv_consolecommands.lua @@ -0,0 +1,86 @@ +-- Actual Commands + +-- Quick reload for dedicated severs +concommand.Add("nz_qr", function(ply) +if !IsValid(ply) or ply:IsSuperAdmin() then + RunConsoleCommand("changelevel", game.GetMap()) + end +end) + +concommand.Add( "nz_print_weps", function() + for k,v in pairs( weapons.GetList() ) do + print( v.ClassName ) + end +end) + +concommand.Add("nz_door_id", function() + local tr = util.TraceLine( util.GetPlayerTrace( player.GetByID(1) ) ) + if IsValid( tr.Entity ) then print( tr.Entity:doorIndex() ) end +end) + +concommand.Add("nz_test1", function() + nz.nzDoors.Functions.CreateMapDoorLink( 1236, "price=500,elec=0,link=1" ) + + timer.Simple(5, function() nz.nzDoors.Functions.RemoveMapDoorLink( 1236 ) end) +end) + +concommand.Add("nz_forceround", function(ply, cmd, args, argStr) + if !IsValid(ply) or ply:IsSuperAdmin() then + local round = args[1] and tonumber(args[1]) or nil + local nokill = args[2] and tobool(args[2]) or false + + if !nokill then + nzPowerUps:Nuke(nil, true) -- Nuke kills them all, no points, no position delay + end + + if round then + nzRound:SetNumber( round - 1 ) + local specint = GetConVar("nz_round_special_interval"):GetInt() or 6 + nzRound:SetNextSpecialRound( math.ceil(round/specint)*specint) + end + nzRound:Prepare() + end +end) + +-- Isn't used anywhere, marked for removal +function lmne(name, find, listall) + if !IsValid(ply) or ply:IsSuperAdmin() then + if name then + local tbl = {} + if find then + for k,v in pairs(ents.GetAll()) do + if v:GetName() != "" and string.find(string.lower(v:GetName()), string.lower(name)) then + table.insert(tbl, v) + print(v:GetName(),"\t\t\t",v) + end + end + else + tbl = ents.FindByName(name) + end + if !listall then + return tbl[1] + else + return tbl + end + else + local tbl = {} + for k,v in pairs(ents.GetAll()) do + if v:GetName() != "" then + table.insert(tbl, v) + print(v:GetName(),"\t\t\t",v) + end + end + return tbl + end + end +end + +concommand.Add("printeyeentityinfo", function(ply, cmd, args, argstr) + if !ply:IsSuperAdmin() then return end + local ent = ply:GetEyeTrace().Entity + if IsValid(ent) then + local pos = ent:GetPos() + local ang = ent:GetAngles() + print("{pos = Vector("..math.Round(pos.x)..", "..math.Round(pos.y)..", "..math.Round(pos.z).."), ang = Angle("..math.Round(ang[1])..", "..math.Round(ang[2])..", "..math.Round(ang[3])..")}") + end +end) diff --git a/nzombies3/gamemode/misc/sv_resources.lua b/gamemodes/nzombies/gamemode/misc/sv_resources.lua similarity index 65% rename from nzombies3/gamemode/misc/sv_resources.lua rename to gamemodes/nzombies/gamemode/misc/sv_resources.lua index 8e74d81c..72cd5473 100644 --- a/nzombies3/gamemode/misc/sv_resources.lua +++ b/gamemodes/nzombies/gamemode/misc/sv_resources.lua @@ -2,7 +2,7 @@ resource.AddFile( "resource/fonts/DK Umbilical Noose.ttf" ) //Content Pack -resource.AddWorkshop( "485777655" ) +--resource.AddWorkshop( "485777655" ) //FAS2 Base Weapons -resource.AddWorkshop( "180507408" ) +--resource.AddWorkshop( "180507408" ) diff --git a/gamemodes/nzombies/gamemode/navigation/sh_constructor.lua b/gamemodes/nzombies/gamemode/navigation/sh_constructor.lua new file mode 100644 index 00000000..beb1b37c --- /dev/null +++ b/gamemodes/nzombies/gamemode/navigation/sh_constructor.lua @@ -0,0 +1,17 @@ +-- Main Tables +nzNav = nzNav or AddNZModule("Nav") +nzNav.Locks = nzNav.Locks or {} + +function IsNavApplicable(ent) + -- All classes that can be linked with navigation + if !IsValid(ent) then return false end + if (ent:IsDoor() or ent:IsBuyableProp() or ent:IsButton()) and ent:GetDoorData().link then + return true + else + return false + end +end + +function nzNav.FlushAllNavModifications() + nzNav.Locks = {} +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/notifications/sh_constructor.lua b/gamemodes/nzombies/gamemode/notifications/sh_constructor.lua new file mode 100644 index 00000000..c250233a --- /dev/null +++ b/gamemodes/nzombies/gamemode/notifications/sh_constructor.lua @@ -0,0 +1,9 @@ +-- Main Tables +nzNotifications = nzNotifications or AddNZModule("Notifications") +nzNotifications.Data = {} + +-- Variables +if CLIENT then + nzNotifications.Data.SoundQueue = {} + nzNotifications.Data.NextSound = CurTime() +end diff --git a/gamemodes/nzombies/gamemode/notifications/sh_sounds.lua b/gamemodes/nzombies/gamemode/notifications/sh_sounds.lua new file mode 100644 index 00000000..2c06377e --- /dev/null +++ b/gamemodes/nzombies/gamemode/notifications/sh_sounds.lua @@ -0,0 +1,34 @@ +-- + +if SERVER then + + function nzNotifications:PlaySound(path, delay) + self:SendRequest("sound", {path = path, delay = delay}) + end + +end + +if CLIENT then + + function nzNotifications:AddSoundToQueue(data) + table.insert(self.Data.SoundQueue, data) + end + + function nzNotifications.SoundHandler() + -- Check we're allowed to play the next sound + if CurTime() > nzNotifications.Data.NextSound then + -- Check the queue + if nzNotifications.Data.SoundQueue[1] != nil then + local data = nzNotifications.Data.SoundQueue[1] + table.remove(nzNotifications.Data.SoundQueue, 1) + surface.PlaySound( data.path ) + nzNotifications.Data.NextSound = CurTime() + data.delay + end + end + end + + timer.Create("nz.Sound.Handler", 1, 0, nzNotifications.SoundHandler) +end + + + diff --git a/gamemodes/nzombies/gamemode/notifications/sh_sync.lua b/gamemodes/nzombies/gamemode/notifications/sh_sync.lua new file mode 100644 index 00000000..97c41648 --- /dev/null +++ b/gamemodes/nzombies/gamemode/notifications/sh_sync.lua @@ -0,0 +1,32 @@ +-- Client Server Syncing + +if SERVER then + + -- Server to client (Server) + util.AddNetworkString( "nz.Notifications.Request" ) + + function nzNotifications:SendRequest(header, data) + net.Start( "nz.Notifications.Request" ) + net.WriteString( header ) + net.WriteTable( data ) + net.Broadcast() + end + +end + +if CLIENT then + + -- Server to client (Client) + local function ReceiveRequest( length ) + --print("Received Notifications Request") + local header = net.ReadString() + local data = net.ReadTable() + + if header == "sound" then + nzNotifications:AddSoundToQueue(data) + end + end + + -- Receivers + net.Receive( "nz.Notifications.Request", ReceiveRequest ) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/nzombies.fgd b/gamemodes/nzombies/gamemode/nzombies.fgd new file mode 100644 index 00000000..b4280dff --- /dev/null +++ b/gamemodes/nzombies/gamemode/nzombies.fgd @@ -0,0 +1,98 @@ +@include "base.fgd" + +@PointClass base(Targetname, Origin, Angles) = nz_electricity : "Fires outputs when electricity is turned on or off, and can also turn it on or off itself. Will be removed if Map Extensions is not ticked in the loaded config." +[ + input TurnElectricityOn(void) : "Turns on electricity. Pass 1 to make it silent." + input TurnElectricityOff(void) : "Turns off electricity. Pass 1 to make it silent." + + output OnInitialized(void) : "Fires when the entity is created in nZombies." + output OnElectricityOn(void) : "Fires when the electricity is turned on." + output OnElectricityOff(void) : "Fires when the electricity is turned off." +] + +@PointClass base(Origin) iconsprite("editor/game_text.vmt") = nz_autoload_config : + "Lets you set a Map Official config. Remember to tick Map Extensions in Map Settings tool for Hammer entities to not get removed." +[ + config(string) : "Config Name" : "" : "The name of the config to autoload. Should only be the savename, not map name or Workshop ID." +] + +@PointClass base(Targetname, PlayerClass, Angles) studio("models/editor/playerstart.mdl") = nz_zombie_spawn : + "Allows you to set where Zombies spawn to be controlled via map logic. These work regardless of links. Will be removed if Map Extensions is not ticked in the loaded config." +[ + input EnableSpawn(void) : "Enables spawnpoint." + input DisableSpawn(void) : "Disables spawnpoint." +] + +@PointClass base(Targetname) iconsprite("editor/obsolete.vmt") = nz_door_listener : + "Listens for a specific Door Link and outputs when this link is opened/closed. Links are set in Creative Mode in-game. Can also open/close door links. Will be removed if Map Extensions is not ticked in the loaded config." +[ + link(string) : "Door Link" : "" : "The name of the link the door(s) to listen for has set. Make sure it matches your config's links." + + input OpenLinkedDoors(void) : "Opens all doors with the selected link." + input CloseLinkedDoors(void) : "Closes all doors with the selected link." + + output OnDoorOpened(string) : "Fires when the door with the selected link is opened. If no link is selected, fires on all door openings. Passes string [door link]." + output OnDoorClosed(string) : "Fires when the door with the selected link is closed, including on map reset. If no link is selected, fires on all door closings. Passes string [door link]." +] + +@SolidClass base(Trigger, Targetname) = nz_trigger_buyable : + "Triggers when the player buys this entity by looking at it and pressing E if he has enough points. Will be removed if Map Extensions is not ticked in the loaded config." +[ + points(integer) : "Cost" : 1000 : "The cost to use this entity. Set to 0 to make it free. Set negative to give points." + text(string) : "Display Text" : "Press E to buy for 1000" : "Text to display for players when looking at this entity." + delay(float) : "Cooldown" : 1 : "Use Lock/Unlock for more advanced control." + + requireditem(string) : "(Optional) Required Item ID" : : "If set, requires the Inventory item with this ID to be used." + nothastext(string) : "Display Text when missing item" : "You don't have the required items!" : "The text to display when the player doesn't have this item." + + input Lock(void) : "Prevent this from being bought." + input Unlock(void) : "Allow this to be bought again." + + output OnBought(integer) : "Fires when a player successfully bought this trigger." +] + +@PointClass base(Targetname, Origin, Angles) = nz_game_listener : "Fires outputs Fires outputs with game events such as Player Downed or Round Progressed. Will be removed if Map Extensions is not ticked in the loaded config." +[ + output OnGameStart(void) : "Fires when all players have readied and the game has started. Fires after the initial map cleanup." + output OnRoundPrepare(integer) : "Fires when a round has been completed and the next round prepares. Passes the preparing round number." + output OnRoundStart(integer) : "Fires when the round starts. Passes the started round number." + output OnPlayerDowned(void) : "Fires when a player has been downed. The player will be the !activator." + output OnPlayerRevived(void) : "Fires when a player has been revived. The player will be the !activator." + output OnGameOver(integer) : "Fires when all players have been downed and the game has ended. Passes the current round number." + output OnGameReset(void) : "Fires when the config initially loads and after every Game Over when players can ready again." +] + +@PointClass base(Targetname, Origin) = nz_carryitem_creator : "Lets you set up an item using nZombie's CarryItem/Inventory system. Will be removed if Map Extensions is not ticked in the loaded config." +[ + id(string) : "ID" : : "ID to associate with this item and to spawn it." + text(string) : "Pickup Text" : "Press E to pick up" : "Text to display when players are looking at the item." + icon(string) : "Icon path" : "spawnicons/models/props_junk/gascan001a.png" : "Filepath to the icon it should be represented by." + model(string) : "Model path" : "models/props_junk/gascan001a.mdl" : "Filepath to the model the item will be spawned with." + shared(integer) : "Shared" : 0 : "(0/1) Will be carried by all players when picked up by any player if set to 1." + notification(integer) : "Notify players" : 1 : "(0/1) Will notify all players when anyone has picked the item up." + dropondown(integer) : "Drop on downed" : 1 : "(0/1) Will drop the item when the carrying player gets downed." + + input Update(void) : "Create the item and/or edit its properties on-the-fly." + input RemoveAllInstances(void) : "Removes any dropped item of this ID and clears any player's inventory of it." + input SpawnRandomly(void) : "Randomly spawn the item on any set nz_carryitem_spawner with this ID." + + output OnPickedUp(void) : "Fires when a player has picked up this item. The player will be the !activator." + output OnDropped(void) : "Fires when the item is dropped. The player dropping the item will be the !activator." + output OnSpawned(void) : "Fires when this item has spawned." +] + +@PointClass base(Targetname, Origin, Angles) studioprop() = nz_carryitem_spawner : "Lets you spawn an item created by a nz_carryitem_creator. Will be removed if Map Extensions is not ticked in the loaded config." +[ + id(string) : "ID" : : "ID of the item to spawn." + input SpawnItem(void) : "Spawn the item with this ID on this spawnpoint." +] + +@PointClass base(Targetname, Origin) = nz_carryitem_checker : "Lets you check if players are carrying this item. Will be removed if Map Extensions is not ticked in the loaded config." +[ + id(string) : "ID" : : "ID of the item to check for." + + input Check(void) : "Checks whether !activator is carrying the item of the set ID. Calls OnCheckSuccess when true, OnCheckFail otherwise." + + output OnCheckSuccess(void) : "Fires when the check has successfully passed and !activator was carrying the item." + output OnCheckFail(void) : "Fires when the check failed to pass and !activator was not carrying the item." +] \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/perks/sh_constructor.lua b/gamemodes/nzombies/gamemode/perks/sh_constructor.lua new file mode 100644 index 00000000..9c3bcb96 --- /dev/null +++ b/gamemodes/nzombies/gamemode/perks/sh_constructor.lua @@ -0,0 +1,7 @@ +-- Main Tables +nzPerks = nzPerks or AddNZModule("Perks") +nzPerks.Data = nzPerks.Data or {} + +-- Variables + +nzPerks.Players = nzPerks.Players or {} \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/perks/sh_meta.lua b/gamemodes/nzombies/gamemode/perks/sh_meta.lua new file mode 100644 index 00000000..b4d7c916 --- /dev/null +++ b/gamemodes/nzombies/gamemode/perks/sh_meta.lua @@ -0,0 +1,113 @@ +local playerMeta = FindMetaTable("Player") +if SERVER then + + function playerMeta:GivePerk(id, machine) + local block = hook.Call("OnPlayerBuyPerk", nil, self, id, machine) + + if block or self:HasPerk(id) then return end + local perkData = nzPerks:Get(id) + if !perkData or !perkData.func then return false end + + perkData.func(id, self, machine) + + -- Specialmachine blocks the networking and storing of the perk + if !perkData.specialmachine then + if nzPerks.Players[self] == nil then nzPerks.Players[self] = {} end + + table.insert(nzPerks.Players[self], id) + nzPerks:SendSync(self) + hook.Call("OnPlayerGetPerk", nil, self, id, machine) + end + end + + local exceptionperks = { + ["whoswho"] = true, + } + + function playerMeta:RemovePerk(id, forced) + local block = hook.Call("OnPlayerRemovePerk", nil, self, id, forced) + + if (self.PreventPerkLoss and !exceptionperks[id] or block) and !forced then return end + local perkData = nzPerks:Get(id) + if perkData == nil then return end + + if nzPerks.Players[self] == nil then nzPerks.Players[self] = {} end + if self:HasPerk(id) then + perkData.lostfunc(id, self) + table.RemoveByValue( nzPerks.Players[self], id ) + hook.Call("OnPlayerLostPerk", nil, self, id, forced) + end + nzPerks:SendSync(self) + end + + function playerMeta:RemovePerks() + if self.PreventPerkLoss then + if nzPerks.Players[self] then + for k,v in pairs(nzPerks.Players[self]) do + if exceptionperks[v] then + self:RemovePerk(v) + end + end + end + else + if nzPerks.Players[self] then + for k,v in pairs(nzPerks.Players[self]) do + local perkData = nzPerks:Get(v) + if perkData then perkData.lostfunc(v, self) end + end + end + nzPerks.Players[self] = {} + end + nzPerks:SendSync(self) + end + + function playerMeta:GiveRandomPerk(maponly) + local tbl = {} + for k,v in pairs(nzPerks.Data) do + if !self:HasPerk(k) and !v.specialmachine then + if maponly then + for k2,v2 in pairs(ents.FindByClass("perk_machine")) do + if v2:GetPerkID() == k then + table.insert(tbl, k) + break + end + end + else + table.insert(tbl, k) + end + end + end + --PrintTable(tbl) + if tbl[1] then + self:GivePerk(table.Random(tbl)) + end + end + + function playerMeta:SetPreventPerkLoss(bool) + self.PreventPerkLoss = bool + end + + function playerMeta:GivePermaPerks() + self:SetPreventPerkLoss(true) + for k,v in pairs(nzPerks:GetList()) do + if !nzPerks:Get(k).specialmachine then + self:GivePerk(k) + end + end + end +end + +function playerMeta:HasPerk(id) + if nzPerks.Players[self] == nil then nzPerks.Players[self] = {} end + if table.HasValue(nzPerks.Players[self], id) then + return true + end + return false +end + +function playerMeta:GetPerks() + if nzPerks.Players[self] == nil then nzPerks.Players[self] = {} end + local tbl = table.Copy(nzPerks.Players[self]) + if table.HasValue(tbl, "pap") then table.RemoveByValue(tbl, "pap") end + return tbl +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/perks/sh_perks.lua b/gamemodes/nzombies/gamemode/perks/sh_perks.lua new file mode 100644 index 00000000..24b12f71 --- /dev/null +++ b/gamemodes/nzombies/gamemode/perks/sh_perks.lua @@ -0,0 +1,498 @@ + +function nzPerks:NewPerk(id, data) + if SERVER then + //Sanitise any client data. + else + data.Func = nil + end + nzPerks.Data[id] = data +end + +function nzPerks:Get(id) + return nzPerks.Data[id] +end + +function nzPerks:GetByName(name) + for _, perk in pairs(nzPerks.Data) do + if perk.name == name then + return perk + end + end + + return nil +end + +function nzPerks:GetList() + local tbl = {} + + for k,v in pairs(nzPerks.Data) do + tbl[k] = v.name + end + + return tbl +end + +function nzPerks:GetIcons() + local tbl = {} + + for k,v in pairs(nzPerks.Data) do + tbl[k] = v.icon + end + + return tbl +end + +function nzPerks:GetBottleMaterials() + local tbl = {} + + for k,v in pairs(nzPerks.Data) do + tbl[k] = v.material + end + + return tbl +end + +nzPerks:NewPerk("jugg", { + name = "Juggernog", + off_model = "models/alig96/perks/jugg/jugg_off.mdl", + on_model = "models/alig96/perks/jugg/jugg_on.mdl", + price = 2500, + material = "models/perk_bottle/c_perk_bottle_jugg", + icon = Material("perk_icons/jugg.png", "smooth unlitgeneric"), + color = Color(255, 100, 100), + func = function(self, ply, machine) + ply:SetMaxHealth(250) + ply:SetHealth(250) + end, + lostfunc = function(self, ply) + ply:SetMaxHealth(100) + if ply:Health() > 100 then ply:SetHealth(100) end + end, +}) + +nzPerks:NewPerk("dtap", { + name = "Double Tap", + off_model = "models/alig96/perks/doubletap/doubletap_off.mdl", + on_model = "models/alig96/perks/doubletap/doubletap_on.mdl", + price = 2000, + material = "models/perk_bottle/c_perk_bottle_dtap", + icon = Material("perk_icons/dtap.png", "smooth unlitgeneric"), + color = Color(255, 255, 100), + func = function(self, ply, machine) + local tbl = {} + for k,v in pairs(ply:GetWeapons()) do + if v:IsFAS2() then + table.insert(tbl, v) + end + end + if tbl[1] != nil then + for k,v in pairs(tbl) do + v:ApplyNZModifier("dtap") + end + end + end, + lostfunc = function(self, ply) + if !ply:HasPerk("dtap2") then + local tbl = {} + for k,v in pairs(ply:GetWeapons()) do + if v:IsFAS2() then + table.insert(tbl, v) + end + end + if tbl[1] != nil then + for k,v in pairs(tbl) do + v:RevertNZModifier("dtap") + end + end + end + end, +}) + +nzPerks:NewPerk("revive", { + name = "Quick Revive", + off_model = "models/alig96/perks/revive/revive_off.mdl", + on_model = "models/alig96/perks/revive/revive_on.mdl", + price = 1500, + material = "models/perk_bottle/c_perk_bottle_revive", + icon = Material("perk_icons/revive.png", "smooth unlitgeneric"), + color = Color(100, 100, 255), + func = function(self, ply, machine) + if #player.GetAllPlaying() <= 1 then + if !ply.SoloRevive or ply.SoloRevive < 3 or !IsValid(machine) then + ply:ChatPrint("You got Quick Revive (Solo)!") + else + ply:ChatPrint("You can only get Quick Revive Solo 3 times.") + return false + end + end + end, + lostfunc = function(self, ply) + + end, +}) + +nzPerks:NewPerk("speed", { + name = "Speed Cola", + off_model = "models/alig96/perks/speed/speed_off.mdl", + on_model = "models/alig96/perks/speed/speed_on.mdl", + price = 3000, + material = "models/perk_bottle/c_perk_bottle_speed", + icon = Material("perk_icons/speed.png", "smooth unlitgeneric"), + color = Color(100, 255, 100), + func = function(self, ply, machine) + local tbl = {} + for k,v in pairs(ply:GetWeapons()) do + if v:NZPerkSpecialTreatment() then + table.insert(tbl, v) + end + end + if tbl[1] != nil then + --local str = "" + for k,v in pairs(tbl) do + v:ApplyNZModifier("speed") + --str = str .. v.ClassName .. ", " + end + end + end, + lostfunc = function(self, ply) + local tbl = {} + for k,v in pairs(ply:GetWeapons()) do + if v:NZPerkSpecialTreatment() then + table.insert(tbl, v) + end + end + if tbl[1] != nil then + for k,v in pairs(tbl) do + v:RevertNZModifier("speed") + end + end + end, +}) + +nzPerks:NewPerk("pap", { + name = "Pack-a-Punch", + off_model = "models/alig96/perks/packapunch/packapunch.mdl", //Find a new model. + on_model = "models/alig96/perks/packapunch/packapunch.mdl", + price = 0, + specialmachine = true, -- Prevents players from getting the perk when they buy it + nobuy = true, -- A "Buy" event won't run when this is used (we do that ourselves in its function) + -- We don't use materials + icon = Material("vulture_icons/pap.png", "smooth unlitgeneric"), + color = Color(200, 220, 220), + condition = function(self, ply, machine) + local wep = ply:GetActiveWeapon() + if (!wep:HasNZModifier("pap") or wep:CanRerollPaP()) and !machine:GetBeingUsed() then + local reroll = false + if wep:HasNZModifier("pap") and wep:CanRerollPaP() then + reroll = true + end + local cost = reroll and 2000 or 5000 + return ply:GetPoints() >= cost + else + ply:PrintMessage( HUD_PRINTTALK, "This weapon is already Pack-a-Punched") + return false + end + end, + func = function(self, ply, machine) + local wep = ply:GetActiveWeapon() + + local reroll = false + if wep:HasNZModifier("pap") and wep:CanRerollPaP() then + reroll = true + end + local cost = reroll and 2000 or 5000 + + ply:Buy(cost, machine, function() + hook.Call("OnPlayerBuyPackAPunch", nil, ply, wep, machine) + + ply:Give("nz_packapunch_arms") + + machine:SetBeingUsed(true) + machine:EmitSound("nz/machines/pap_up.wav") + local class = wep:GetClass() + + local e = EffectData() + e:SetEntity(machine) + local ang = machine:GetAngles() + e:SetOrigin(machine:GetPos() + ang:Up()*35 + ang:Forward()*20 - ang:Right()*2) + e:SetMagnitude(3) + util.Effect("pap_glow", e, true, true) + + wep:Remove() + local wep = ents.Create("pap_weapon_fly") + local startpos = machine:GetPos() + ang:Forward()*30 + ang:Up()*25 + ang:Right()*-3 + wep:SetPos(startpos) + wep:SetAngles(ang + Angle(0,90,0)) + wep.WepClass = class + wep:Spawn() + local weapon = weapons.Get(class) + local model = (weapon and weapon.WM or weapon.WorldModel) or "models/weapons/w_rif_ak47.mdl" + if !util.IsValidModel(model) then model = "models/weapons/w_rif_ak47.mdl" end + wep:SetModel(model) + wep.machine = machine + wep.Owner = ply + wep:SetMoveType( MOVETYPE_FLY ) + + --wep:SetNotSolid(true) + --wep:SetGravity(0.000001) + --wep:SetCollisionBounds(Vector(0,0,0), Vector(0,0,0)) + timer.Simple(0.5, function() + if IsValid(wep) then + wep:SetLocalVelocity(ang:Forward()*-30) + end + end) + timer.Simple(1.8, function() + if IsValid(wep) then + wep:SetMoveType(MOVETYPE_NONE) + wep:SetLocalVelocity(Vector(0,0,0)) + end + end) + timer.Simple(3, function() + if IsValid(wep) and IsValid(machine) then + local weapon = weapons.Get(class) + if weapon and weapon.NZPaPReplacement and weapons.Get(weapon.NZPaPReplacement) then + local pos, ang = wep:GetPos(), wep:GetAngles() + wep:Remove() + wep = ents.Create("pap_weapon_fly") -- Recreate a new entity with the replacement class instead + wep:SetPos(pos) + wep:SetAngles(ang) + wep.WepClass = weapon.NZPaPReplacement + wep:Spawn() + wep.TriggerPos = startpos + + local replacewep = weapons.Get(weapon.NZPaPReplacement) + local model = (replacewep and replacewep.WM or replacewep.WorldModel) or "models/weapons/w_rif_ak47.mdl" + if !util.IsValidModel(model) then model = "models/weapons/w_rif_ak47.mdl" end + wep:SetModel(model) -- Changing the model and name + wep.machine = machine + wep.Owner = ply + wep:SetMoveType( MOVETYPE_FLY ) + end + + --print(wep, wep.WepClass, wep:GetModel()) + + machine:EmitSound("nz/machines/pap_ready.wav") + wep:SetCollisionBounds(Vector(0,0,0), Vector(0,0,0)) + wep:SetMoveType(MOVETYPE_FLY) + wep:SetGravity(0.000001) + wep:SetLocalVelocity(ang:Forward()*30) + --print(ang:Forward()*30, wep:GetVelocity()) + wep:CreateTriggerZone(reroll) + --print(reroll) + end + end) + timer.Simple(4.2, function() + if IsValid(wep) then + --print("YDA") + --print(wep:GetMoveType()) + --print(ang:Forward()*30, wep:GetVelocity()) + wep:SetMoveType(MOVETYPE_NONE) + wep:SetLocalVelocity(Vector(0,0,0)) + end + end) + timer.Simple(10, function() + if IsValid(wep) then + wep:SetMoveType(MOVETYPE_FLY) + wep:SetLocalVelocity(ang:Forward()*-2) + end + end) + timer.Simple(25, function() + if IsValid(wep) then + wep:Remove() + if IsValid(machine) then + machine:SetBeingUsed(false) + end + end + end) + + timer.Simple(2, function() ply:RemovePerk("pap") end) + return true + end) + end, + lostfunc = function(self, ply) + + end, +}) + +nzPerks:NewPerk("dtap2", { + name = "Double Tap II", + off_model = "models/alig96/perks/doubletap2/doubletap2_off.mdl", + on_model = "models/alig96/perks/doubletap2/doubletap2.mdl", + price = 2000, + material = "models/perk_bottle/c_perk_bottle_dtap2", + icon = Material("perk_icons/dtap2.png", "smooth unlitgeneric"), + color = Color(255, 255, 100), + func = function(self, ply, machine) + local tbl = {} + for k,v in pairs(ply:GetWeapons()) do + if v:IsFAS2() then + table.insert(tbl, v) + end + end + if tbl[1] != nil then + for k,v in pairs(tbl) do + v:ApplyNZModifier("dtap") + end + end + end, + lostfunc = function(self, ply) + if !ply:HasPerk("dtap") then + local tbl = {} + for k,v in pairs(ply:GetWeapons()) do + if v:IsFAS2() then + table.insert(tbl, v) + end + end + if tbl[1] != nil then + for k,v in pairs(tbl) do + v:RevertNZModifier("dtap") + end + end + end + end, +}) + +nzPerks:NewPerk("staminup", { + name = "Stamin-Up", + off_model = "models/alig96/perks/staminup/staminup_off.mdl", + on_model = "models/alig96/perks/staminup/staminup.mdl", + price = 2000, + material = "models/perk_bottle/c_perk_bottle_stamin", + icon = Material("perk_icons/staminup.png", "smooth unlitgeneric"), + color = Color(200, 255, 100), + func = function(self, ply, machine) + ply:SetRunSpeed(350) + ply:SetMaxRunSpeed( 350 ) + ply:SetStamina( 200 ) + ply:SetMaxStamina( 200 ) + end, + lostfunc = function(self, ply) + ply:SetRunSpeed(300) + ply:SetMaxRunSpeed( 300 ) + ply:SetStamina( 100 ) + ply:SetMaxStamina( 100 ) + end, +}) + +nzPerks:NewPerk("phd", { + name = "PhD Flopper", + off_model = "models/alig96/perks/phd/phdflopper_off.mdl", + on_model = "models/alig96/perks/phd/phdflopper.mdl", + price = 2000, + material = "models/perk_bottle/c_perk_bottle_phd", + icon = Material("perk_icons/phd.png", "smooth unlitgeneric"), + color = Color(255, 50, 255), + func = function(self, ply, machine) + end, + lostfunc = function(self, ply) + end, +}) + +nzPerks:NewPerk("deadshot", { + name = "Deadshot Daiquiri", + off_model = "models/alig96/perks/deadshot/deadshot_off.mdl", + on_model = "models/alig96/perks/deadshot/deadshot.mdl", + price = 2000, + material = "models/perk_bottle/c_perk_bottle_deadshot", + icon = Material("perk_icons/deadshot.png", "smooth unlitgeneric"), + color = Color(150, 200, 150), + func = function(self, ply, machine) + end, + lostfunc = function(self, ply) + end, +}) + +nzPerks:NewPerk("mulekick", { + name = "Mule Kick", + off_model = "models/alig96/perks/mulekick/mulekick_off.mdl", + on_model = "models/alig96/perks/mulekick/mulekick.mdl", + price = 4000, + material = "models/perk_bottle/c_perk_bottle_mulekick", + icon = Material("perk_icons/mulekick.png", "smooth unlitgeneric"), + color = Color(100, 200, 100), + func = function(self, ply, machine) + end, + lostfunc = function(self, ply) + for k,v in pairs(ply:GetWeapons()) do + if v:GetNWInt("SwitchSlot") == 3 then + ply:StripWeapon(v:GetClass()) + end + end + end, +}) + +nzPerks:NewPerk("tombstone", { + name = "Tombstone Soda", + off_model = "models/alig96/perks/tombstone/tombstone_off.mdl", + on_model = "models/alig96/perks/tombstone/tombstone.mdl", + price = 2000, + material = "models/perk_bottle/c_perk_bottle_tombstone", + icon = Material("perk_icons/tombstone.png", "smooth unlitgeneric"), + color = Color(100, 100, 100), + func = function(self, ply, machine) + end, + lostfunc = function(self, ply) + end, +}) + +nzPerks:NewPerk("whoswho", { + name = "Who's Who", + off_model = "models/alig96/perks/whoswho/whoswho_off.mdl", + on_model = "models/alig96/perks/whoswho/whoswho.mdl", + price = 2000, + material = "models/perk_bottle/c_perk_bottle_whoswho", + icon = Material("perk_icons/whoswho.png", "smooth unlitgeneric"), + color = Color(100, 100, 255), + func = function(self, ply, machine) + end, + lostfunc = function(self, ply) + end, +}) + +nzPerks:NewPerk("cherry", { + name = "Electric Cherry", + off_model = "models/alig96/perks/cherry/cherry_off.mdl", + on_model = "models/alig96/perks/cherry/cherry.mdl", + price = 2000, + material = "models/perk_bottle/c_perk_bottle_cherry", + icon = Material("perk_icons/cherry.png", "smooth unlitgeneric"), + color = Color(50, 50, 200), + func = function(self, ply, machine) + end, + lostfunc = function(self, ply) + end, +}) + +nzPerks:NewPerk("vulture", { + name = "Vulture Aid Elixir", + off_model = "models/alig96/perks/vulture/vultureaid_off.mdl", + on_model = "models/alig96/perks/vulture/vultureaid.mdl", + price = 3000, + material = "models/perk_bottle/c_perk_bottle_vulture", + icon = Material("perk_icons/vulture.png", "smooth unlitgeneric"), + color = Color(255, 100, 100), + func = function(self, ply, machine) + end, + lostfunc = function(self, ply) + end, +}) + +nzPerks:NewPerk("wunderfizz", { + name = "Der Wunderfizz", -- Nothing more is needed, it is specially handled + specialmachine = true, +}) + +nzPerks:NewPerk("widowswine", { + name = "Widow's Wine", + model = "models/yolojoenshit/bo3perks/widows_wine/mc_mtl_p7_zm_vending_widows_wine.mdl", + off_skin = 1, + on_skin = 0, + price = 4000, + material = "models/perk_bottle/c_perk_bottle_widowswine", + icon = Material("perk_icons/widows_wine.png", "smooth unlitgeneric"), + color = Color(255, 50, 200), + func = function(self, ply, machine) + end, + lostfunc = function(self, ply) + end, +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/perks/sh_sync.lua b/gamemodes/nzombies/gamemode/perks/sh_sync.lua new file mode 100644 index 00000000..f29f22b7 --- /dev/null +++ b/gamemodes/nzombies/gamemode/perks/sh_sync.lua @@ -0,0 +1,54 @@ +-- Client Server Syncing + +if SERVER then + + -- Server to client (Server) + util.AddNetworkString( "nz.Perks.Sync" ) + util.AddNetworkString( "nz.Perks.FullSync" ) + + function nzPerks:SendSync(ply, receiver) + if !ply then nzPerks:SendFullSync(receiver) return end -- No valid player set, just do a full sync + if !nzPerks.Players[ply] then nzPerks.Players[ply] = {} end -- Create table should it not exist (for some reason) + + local data = table.Copy(nzPerks.Players[ply]) + + net.Start( "nz.Perks.Sync" ) + net.WriteEntity( ply ) + net.WriteTable( data ) + return receiver and net.Send(receiver) or net.Broadcast() + end + + function nzPerks:SendFullSync(receiver) + local data = table.Copy(nzPerks.Players) + + net.Start( "nz.Perks.FullSync" ) + net.WriteTable( data ) + return receiver and net.Send(receiver) or net.Broadcast() + end + + FullSyncModules["Perks"] = function(ply) + nzPerks:SendFullSync(ply) + end + +end + +if CLIENT then + + -- Server to client (Client) + local function ReceiveSync( length ) + print("Received Player Perks Sync") + local ply = net.ReadEntity() + nzPerks.Players[ply] = net.ReadTable() + --PrintTable(nzPerks.Players) + end + + local function ReceiveFullSync( length ) + print("Received Full Perks Sync") + nzPerks.Players = net.ReadTable() + PrintTable(nzPerks.Players) + end + + -- Receivers + net.Receive( "nz.Perks.Sync", ReceiveSync ) + net.Receive( "nz.Perks.FullSync", ReceiveFullSync ) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/perks/sv_solorevive.lua b/gamemodes/nzombies/gamemode/perks/sv_solorevive.lua new file mode 100644 index 00000000..72d39c66 --- /dev/null +++ b/gamemodes/nzombies/gamemode/perks/sv_solorevive.lua @@ -0,0 +1,29 @@ +function nzPerks:UpdateQuickRevive() + if #player.GetAllPlaying() <= 1 then + for k,v in pairs(ents.FindByClass("perk_machine")) do + if v:GetPerkID() == "revive" then + v:SetPrice(500) -- Price is 500 for Solo variant and always on + v:TurnOn() + end + end + else + for k,v in pairs(ents.FindByClass("perk_machine")) do + if v:GetPerkID() == "revive" then + v:SetPrice(1500) -- Reset to default 1500 and turn off if power is not on + if !IsElec() then + v:TurnOff() + else + v:TurnOn() + end + end + end + end +end + +hook.Add("OnPlayerDropIn", "UpdateRevive", function() + nzPerks:UpdateQuickRevive() +end) + +hook.Add("OnPlayerDropOut", "UpdateRevive", function() + nzPerks:UpdateQuickRevive() +end) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/player_class/cl_editor_player.lua b/gamemodes/nzombies/gamemode/player_class/cl_editor_player.lua new file mode 100644 index 00000000..33161913 --- /dev/null +++ b/gamemodes/nzombies/gamemode/player_class/cl_editor_player.lua @@ -0,0 +1,284 @@ +--AddCSLuaFile() + +local default_animations = { "idle_all_01", "menu_walk" } + +CreateConVar( "cl_playercolor", "0.24 0.34 0.41", { FCVAR_ARCHIVE, FCVAR_USERINFO, FCVAR_DONTRECORD }, "The value is a Vector - so between 0-1 - not between 0-255" ) +CreateConVar( "cl_weaponcolor", "0.30 1.80 2.10", { FCVAR_ARCHIVE, FCVAR_USERINFO, FCVAR_DONTRECORD }, "The value is a Vector - so between 0-1 - not between 0-255" ) +CreateConVar( "cl_playerskin", "0", { FCVAR_ARCHIVE, FCVAR_USERINFO, FCVAR_DONTRECORD }, "The skin to use, if the model has any" ) +CreateConVar( "cl_playerbodygroups", "0", { FCVAR_ARCHIVE, FCVAR_USERINFO, FCVAR_DONTRECORD }, "The bodygroups to use, if the model has any" ) + + +function nzPlayers:PlayerModelEditor() + local window = vgui.Create("DFrame") + window:SetWidth(960) + window:SetHeight(700) + window:SetTitle("Player Model") + + local mdl = window:Add( "DModelPanel" ) + mdl:Dock( FILL ) + mdl:SetFOV( 36 ) + mdl:SetCamPos( Vector( 0, 0, 0 ) ) + mdl:SetDirectionalLight( BOX_RIGHT, Color( 255, 160, 80, 255 ) ) + mdl:SetDirectionalLight( BOX_LEFT, Color( 80, 160, 255, 255 ) ) + mdl:SetAmbientLight( Vector( -64, -64, -64 ) ) + mdl:SetAnimated( true ) + mdl.Angles = Angle( 0, 0, 0 ) + mdl:SetLookAt( Vector( -100, 0, -22 ) ) + + local sheet = window:Add( "DPropertySheet" ) + sheet:Dock( RIGHT ) + sheet:SetSize( 430, 0 ) + + local PanelSelect = sheet:Add( "DPanelSelect" ) + + for name, model in SortedPairs( player_manager.AllValidModels() ) do + + local icon = vgui.Create( "SpawnIcon" ) + icon:SetModel( model ) + icon:SetSize( 64, 64 ) + icon:SetTooltip( name ) + icon.playermodel = name + + PanelSelect:AddPanel( icon, { cl_playermodel = name } ) + + end + + sheet:AddSheet( "Model", PanelSelect, "icon16/user.png" ) + + local controls = window:Add( "DPanel" ) + controls:DockPadding( 8, 8, 8, 8 ) + + local lbl = controls:Add( "DLabel" ) + lbl:SetText( "Player color" ) + lbl:SetTextColor( Color( 0, 0, 0, 255 ) ) + lbl:Dock( TOP ) + + local plycol = controls:Add( "DColorMixer" ) + plycol:SetAlphaBar( false ) + plycol:SetPalette( false ) + plycol:Dock( TOP ) + plycol:SetSize( 200, 260 ) + + local lbl = controls:Add( "DLabel" ) + lbl:SetText( "Physgun color" ) + lbl:SetTextColor( Color( 0, 0, 0, 255 ) ) + lbl:DockMargin( 0, 32, 0, 0 ) + lbl:Dock( TOP ) + + local wepcol = controls:Add( "DColorMixer" ) + wepcol:SetAlphaBar( false ) + wepcol:SetPalette( false ) + wepcol:Dock( TOP ) + wepcol:SetSize( 200, 260 ) + wepcol:SetVector( Vector( GetConVarString( "cl_weaponcolor" ) ) ); + + sheet:AddSheet( "Colors", controls, "icon16/color_wheel.png" ) + + local bdcontrols = window:Add( "DPanel" ) + bdcontrols:DockPadding( 8, 8, 8, 8 ) + + local bdcontrolspanel = bdcontrols:Add( "DPanelList" ) + bdcontrolspanel:EnableVerticalScrollbar( true ) + bdcontrolspanel:Dock( FILL ) + + local bgtab = sheet:AddSheet( "Bodygroups", bdcontrols, "icon16/cog.png" ) + + -- Helper functions + + local function MakeNiceName( str ) + local newname = {} + + for _, s in pairs( string.Explode( "_", str ) ) do + if ( string.len( s ) == 1 ) then table.insert( newname, string.upper( s ) ) continue end + table.insert( newname, string.upper( string.Left( s, 1 ) ) .. string.Right( s, string.len( s ) - 1 ) ) -- Ugly way to capitalize first letters. + end + + return string.Implode( " ", newname ) + end + + local function PlayPreviewAnimation( panel, playermodel ) + + if ( !panel or !IsValid( panel.Entity ) ) then return end + + local anims = list.Get( "PlayerOptionsAnimations" ) + + local anim = default_animations[ math.random( 1, #default_animations ) ] + if ( anims[ playermodel ] ) then + anims = anims[ playermodel ] + anim = anims[ math.random( 1, #anims ) ] + end + + local iSeq = panel.Entity:LookupSequence( anim ) + if ( iSeq > 0 ) then panel.Entity:ResetSequence( iSeq ) end + + end + + -- Updating + + local function UpdateBodyGroups( pnl, val ) + if ( pnl.type == "bgroup" ) then + + mdl.Entity:SetBodygroup( pnl.typenum, math.Round( val ) ) + + local str = string.Explode( " ", GetConVarString( "cl_playerbodygroups" ) ) + if ( #str < pnl.typenum + 1 ) then for i = 1, pnl.typenum + 1 do str[ i ] = str[ i ] or 0 end end + str[ pnl.typenum + 1 ] = math.Round( val ) + RunConsoleCommand( "cl_playerbodygroups", table.concat( str, " " ) ) + + elseif ( pnl.type == "skin" ) then + + mdl.Entity:SetSkin( math.Round( val ) ) + RunConsoleCommand( "cl_playerskin", math.Round( val ) ) + + end + end + + local function RebuildBodygroupTab() + bdcontrolspanel:Clear() + + bgtab.Tab:SetVisible( false ) + + local nskins = mdl.Entity:SkinCount() - 1 + if ( nskins > 0 ) then + local skins = vgui.Create( "DNumSlider" ) + skins:Dock( TOP ) + skins:SetText( "Skin" ) + skins:SetDark( true ) + skins:SetTall( 50 ) + skins:SetDecimals( 0 ) + skins:SetMax( nskins ) + skins:SetValue( GetConVarNumber( "cl_playerskin" ) ) + skins.type = "skin" + skins.OnValueChanged = UpdateBodyGroups + + bdcontrolspanel:AddItem( skins ) + + mdl.Entity:SetSkin( GetConVarNumber( "cl_playerskin" ) ) + + bgtab.Tab:SetVisible( true ) + end + + local groups = string.Explode( " ", GetConVarString( "cl_playerbodygroups" ) ) + for k = 0, mdl.Entity:GetNumBodyGroups() - 1 do + if ( mdl.Entity:GetBodygroupCount( k ) <= 1 ) then continue end + + local bgroup = vgui.Create( "DNumSlider" ) + bgroup:Dock( TOP ) + bgroup:SetText( MakeNiceName( mdl.Entity:GetBodygroupName( k ) ) ) + bgroup:SetDark( true ) + bgroup:SetTall( 50 ) + bgroup:SetDecimals( 0 ) + bgroup.type = "bgroup" + bgroup.typenum = k + bgroup:SetMax( mdl.Entity:GetBodygroupCount( k ) - 1 ) + bgroup:SetValue( groups[ k + 1 ] or 0 ) + bgroup.OnValueChanged = UpdateBodyGroups + + bdcontrolspanel:AddItem( bgroup ) + + mdl.Entity:SetBodygroup( k, groups[ k + 1 ] or 0 ) + + bgtab.Tab:SetVisible( true ) + end + end + + local function UpdateFromConvars() + + local model = LocalPlayer():GetInfo( "cl_playermodel" ) + local modelname = player_manager.TranslatePlayerModel( model ) + util.PrecacheModel( modelname ) + mdl:SetModel( modelname ) + mdl.Entity.GetPlayerColor = function() return Vector( GetConVarString( "cl_playercolor" ) ) end + mdl.Entity:SetPos( Vector( -100, 0, -61 ) ) + + plycol:SetVector( Vector( GetConVarString( "cl_playercolor" ) ) ) + wepcol:SetVector( Vector( GetConVarString( "cl_weaponcolor" ) ) ) + + PlayPreviewAnimation( mdl, model ) + RebuildBodygroupTab() + + end + + local function UpdateFromControls() + + RunConsoleCommand( "cl_playercolor", tostring( plycol:GetVector() ) ) + RunConsoleCommand( "cl_weaponcolor", tostring( wepcol:GetVector() ) ) + + end + + plycol.ValueChanged = UpdateFromControls + wepcol.ValueChanged = UpdateFromControls + + UpdateFromConvars() + + function PanelSelect:OnActivePanelChanged( old, new ) + + if ( old != new ) then -- Only reset if we changed the model + RunConsoleCommand( "cl_playerbodygroups", "0" ) + RunConsoleCommand( "cl_playerskin", "0" ) + end + + timer.Simple( 0.1, function() UpdateFromConvars() end ) + + end + + -- Hold to rotate + + function mdl:DragMousePress() + self.PressX, self.PressY = gui.MousePos() + self.Pressed = true + end + + function mdl:DragMouseRelease() self.Pressed = false end + + function mdl:LayoutEntity( Entity ) + if ( self.bAnimated ) then self:RunAnimation() end + + if ( self.Pressed ) then + local mx, my = gui.MousePos() + self.Angles = self.Angles - Angle( 0, ( self.PressX or mx ) - mx, 0 ) + + self.PressX, self.PressY = gui.MousePos() + end + + Entity:SetAngles( self.Angles ) + end + + gui.EnableScreenClicker(true) + + window:MakePopup() + window:Center() + + function window:OnClose() + --gui.EnableScreenClicker(false) + end + +end + +list.Set( "PlayerOptionsAnimations", "gman", { "menu_gman" } ) + +list.Set( "PlayerOptionsAnimations", "hostage01", { "idle_all_scared" } ) +list.Set( "PlayerOptionsAnimations", "hostage02", { "idle_all_scared" } ) +list.Set( "PlayerOptionsAnimations", "hostage03", { "idle_all_scared" } ) +list.Set( "PlayerOptionsAnimations", "hostage04", { "idle_all_scared" } ) + +list.Set( "PlayerOptionsAnimations", "zombine", { "menu_zombie_01" } ) +list.Set( "PlayerOptionsAnimations", "corpse", { "menu_zombie_01" } ) +list.Set( "PlayerOptionsAnimations", "zombiefast", { "menu_zombie_01" } ) +list.Set( "PlayerOptionsAnimations", "zombie", { "menu_zombie_01" } ) +list.Set( "PlayerOptionsAnimations", "skeleton", { "menu_zombie_01" } ) + +list.Set( "PlayerOptionsAnimations", "combine", { "menu_combine" } ) +list.Set( "PlayerOptionsAnimations", "combineprison", { "menu_combine" } ) +list.Set( "PlayerOptionsAnimations", "combineelite", { "menu_combine" } ) +list.Set( "PlayerOptionsAnimations", "police", { "menu_combine" } ) +list.Set( "PlayerOptionsAnimations", "policefem", { "menu_combine" } ) + +list.Set( "PlayerOptionsAnimations", "css_arctic", { "pose_standing_02", "idle_fist" } ) +list.Set( "PlayerOptionsAnimations", "css_gasmask", { "pose_standing_02", "idle_fist" } ) +list.Set( "PlayerOptionsAnimations", "css_guerilla", { "pose_standing_02", "idle_fist" } ) +list.Set( "PlayerOptionsAnimations", "css_leet", { "pose_standing_02", "idle_fist" } ) +list.Set( "PlayerOptionsAnimations", "css_phoenix", { "pose_standing_02", "idle_fist" } ) +list.Set( "PlayerOptionsAnimations", "css_riot", { "pose_standing_02", "idle_fist" } ) +list.Set( "PlayerOptionsAnimations", "css_swat", { "pose_standing_02", "idle_fist" } ) +list.Set( "PlayerOptionsAnimations", "css_urban", { "pose_standing_02", "idle_fist" } ) diff --git a/gamemodes/nzombies/gamemode/player_class/sh_constructor.lua b/gamemodes/nzombies/gamemode/player_class/sh_constructor.lua new file mode 100644 index 00000000..d2700e53 --- /dev/null +++ b/gamemodes/nzombies/gamemode/player_class/sh_constructor.lua @@ -0,0 +1,56 @@ +-- Main Tables +nzPlayers = nzPlayers or AddNZModule("Players") +nzPlayers.Data = nzPlayers.Data or {} + +-- Variables +local downedspeed = 30 + +-- Copy-pasted from the wiki, a nice little function +local CMoveData = FindMetaTable( "CMoveData" ) +function CMoveData:RemoveKeys( keys ) + -- Using bitwise operations to clear the key bits. + local newbuttons = bit.band( self:GetButtons(), bit.bnot( keys ) ) + self:SetButtons( newbuttons ) +end + +-- Stops players from moving if downed +hook.Add( "SetupMove", "nzFreezePlayersDowned", function( ply, mv, cmd ) + if !ply:GetNotDowned() then + mv:SetMaxClientSpeed( downedspeed ) + mv:RemoveKeys(IN_JUMP + IN_DUCK) + + --[[if mv:GetVelocity():Length2D() > 10 then -- Can't shoot while crawling! + mv:RemoveKeys(IN_ATTACK + IN_ATTACK2) -- Doesn't work for some reason? :( + end]] + end +end ) + +hook.Add("PlayerSpawn", "SetupHands", function(ply) + + local mdl = ply:GetInfo( "cl_playermodel" ) + ply:SetModel(mdl) + + local col = ply:GetInfo( "cl_playercolor" ) + ply:SetPlayerColor( Vector( col ) ) + + local col = Vector( ply:GetInfo( "cl_weaponcolor" ) ) + if col:Length() == 0 then + col = Vector( 0.001, 0.001, 0.001 ) + end + ply:SetWeaponColor( col ) + + local skin = ply:GetInfoNum( "cl_playerskin", 0 ) + ply:SetSkin( skin ) + + local groups = ply:GetInfo( "cl_playerbodygroups" ) + if ( groups == nil ) then groups = "" end + local groups = string.Explode( " ", groups ) + for k = 0, ply:GetNumBodyGroups() - 1 do + ply:SetBodygroup( k, tonumber( groups[ k + 1 ] ) or 0 ) + end + + timer.Simple(0, function() + if IsValid(ply) then ply:SetupHands() end + end) + +end) diff --git a/gamemodes/nzombies/gamemode/player_class/sh_player_create.lua b/gamemodes/nzombies/gamemode/player_class/sh_player_create.lua new file mode 100644 index 00000000..8e2e0bf3 --- /dev/null +++ b/gamemodes/nzombies/gamemode/player_class/sh_player_create.lua @@ -0,0 +1,49 @@ +DEFINE_BASECLASS( "player_default" ) + +local PLAYER = {} + +-- +-- See gamemodes/base/player_class/player_default.lua for all overridable variables +-- +PLAYER.WalkSpeed = 300 +PLAYER.RunSpeed = 600 +PLAYER.CanUseFlashlight = true + +function PLAYER:SetupDataTables() + self.Player:NetworkVar("Bool", 0, "UsingSpecialWeapon") +end + +function PLAYER:Init() + -- Don't forget Colours + -- This runs when the player is first brought into the game + -- print("create") +end + +function PLAYER:Loadout() + + -- Creation Tools + self.Player:Give( "weapon_physgun" ) + self.Player:Give( "nz_multi_tool" ) + + timer.Simple(0.1, function() + if IsValid(self.Player) then + if !self.Player:HasWeapon( "weapon_physgun" ) then + self.Player:Give( "weapon_physgun" ) + end + if !self.Player:HasWeapon( "nz_multi_tool" ) then + self.Player:Give( "nz_multi_tool" ) + end + end + end) + +end + +function PLAYER:Spawn() + -- if we are in create or debuging make zombies target us + if nzRound:InState(ROUND_CREATE) or GetConVar( "nz_zombie_debug" ):GetBool() then --TODO this is bullshit? + self.Player:SetTargetPriority(TARGET_PRIORITY_PLAYER) + end + self.Player:SetUsingSpecialWeapon(false) +end + +player_manager.RegisterClass( "player_create", PLAYER, "player_default" ) diff --git a/gamemodes/nzombies/gamemode/player_class/sh_player_ingame.lua b/gamemodes/nzombies/gamemode/player_class/sh_player_ingame.lua new file mode 100644 index 00000000..416792bb --- /dev/null +++ b/gamemodes/nzombies/gamemode/player_class/sh_player_ingame.lua @@ -0,0 +1,84 @@ +DEFINE_BASECLASS( "player_default" ) + +local PLAYER = {} + +-- +-- See gamemodes/base/player_class/player_default.lua for all overridable variables +-- +PLAYER.WalkSpeed = 200 +PLAYER.RunSpeed = 300 +PLAYER.CanUseFlashlight = true + +function PLAYER:SetupDataTables() + self.Player:NetworkVar("Bool", 0, "UsingSpecialWeapon") +end + +function PLAYER:Init() + -- Don't forget Colours + -- This runs when the player is first brought into the game and when they die during a round and are brought back + +end + +if not ConVarExists("nz_failsafe_preventgrenades") then CreateConVar("nz_failsafe_preventgrenades", 0, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_ARCHIVE, FCVAR_NOTIFY}) end + +function PLAYER:Loadout() + -- Give ammo and guns + + if nzMapping.Settings.startwep then + self.Player:Give( nzMapping.Settings.startwep ) + else + -- A setting does not exist, give default starting weapons + for k,v in pairs(nzConfig.BaseStartingWeapons) do + self.Player:Give( v ) + end + end + self.Player:GiveMaxAmmo() + + if !GetConVar("nz_papattachments"):GetBool() and FAS2_Attachments != nil then + for k,v in pairs(FAS2_Attachments) do + self.Player:FAS2_PickUpAttachment(v.key) + end + end + self.Player:Give("nz_quickknife_crowbar") + + -- We need this to disable the grenades for those that it causes problems with until they've been remade :( + if !GetConVar("nz_failsafe_preventgrenades"):GetBool() then + self.Player:Give("nz_grenade") + end + +end +function PLAYER:Spawn() + + if nzMapping.Settings.startpoints then + if !self.Player:CanAfford(nzMapping.Settings.startpoints) then + self.Player:SetPoints(nzMapping.Settings.startpoints) + end + else + if !self.Player:CanAfford(500) then -- Has less than 500 points + -- Poor guy has no money, lets start him off + self.Player:SetPoints(500) + end + end + + -- Reset their perks + self.Player:RemovePerks() + + -- activate zombie targeting + self.Player:SetTargetPriority(TARGET_PRIORITY_PLAYER) + + local spawns = ents.FindByClass("player_spawns") + -- Get player number + for k,v in pairs(player.GetAll()) do + if v == self.Player then + if IsValid(spawns[k]) then + v:SetPos(spawns[k]:GetPos()) + else + print("No spawn set for player: " .. v:Nick()) + end + end + end + + self.Player:SetUsingSpecialWeapon(false) +end + +player_manager.RegisterClass( "player_ingame", PLAYER, "player_default" ) diff --git a/gamemodes/nzombies/gamemode/player_class/sv_healthregen.lua b/gamemodes/nzombies/gamemode/player_class/sv_healthregen.lua new file mode 100644 index 00000000..46fd1b47 --- /dev/null +++ b/gamemodes/nzombies/gamemode/player_class/sv_healthregen.lua @@ -0,0 +1,21 @@ +local HealthRegen = { + Amount = 10, + Delay = 3, + Rate = 0.05 +} + +hook.Add( "Think", "RegenHealth", function() + for k,v in pairs( player.GetAll() ) do + + if v:Alive() and v:GetNotDowned() and v:Health() < v:GetMaxHealth() and (!v.lastregen or CurTime() > v.lastregen + HealthRegen.Rate) and (!v.lasthit or CurTime() > v.lasthit + HealthRegen.Delay) then + v.lastregen = CurTime() + v:SetHealth( math.Clamp(v:Health() + HealthRegen.Amount, 0, v:GetMaxHealth() ) ) + end + end +end ) + +hook.Add( "EntityTakeDamage", "PreventHealthRegen", function(ent, dmginfo) + if ent:IsPlayer() and ent:GetNotDowned() then + ent.lasthit = CurTime() + end +end) diff --git a/gamemodes/nzombies/gamemode/player_class/sv_players.lua b/gamemodes/nzombies/gamemode/player_class/sv_players.lua new file mode 100644 index 00000000..9ef961b9 --- /dev/null +++ b/gamemodes/nzombies/gamemode/player_class/sv_players.lua @@ -0,0 +1,82 @@ +-- + +function nzPlayers.PlayerNoClip( ply, desiredState ) + if ply:Alive() and nzRound:InState( ROUND_CREATE ) then + return ply:IsInCreative() + --else + --return GetConVar("nz_allow_noclip"):GetBool() + end +end + +function nzPlayers:FullSync( ply ) + -- A full sync module using the new rewrites + if IsValid(ply) then + ply:SendFullSync() + end +end + +local function initialSpawn( ply ) + timer.Simple(1, function() + -- Fully Sync + nzPlayers:FullSync( ply ) + end) +end + +local function playerLeft( ply ) + -- this was previously hooked to PlayerDisconnected + -- it will now detect leaving players via entity removed, to take kicking banning etc into account. + if ply:IsPlayer() then + ply:DropOut() + if IsValid(ply.TimedUseEntity) then + ply:StopTimedUse() + end + end +end + +local function friendlyFire( ply, ent ) + if !ply:GetNotDowned() then return false end + if ent:IsPlayer() then + if ent == ply then + -- You can damage yourself as long as you don't have PhD + return !ply:HasPerk("phd") and !ply.SELFIMMUNE + else + --Friendly fire is disabled for all other players TODO make hardcore setting? + return false + end + elseif ent:IsValidZombie() then + if ply:HasPerk("widowswine") and ply:GetAmmoCount(GetNZAmmoID("grenade")) > 0 then -- WIDOWS WINE TAKE DAMAGE EFFECT + local pos = ply:GetPos() + + ply.SELFIMMUNE = true + util.BlastDamage(ply, ply, pos, 350, 50) + ply.SELFIMMUNE = nil + + local zombls = ents.FindInSphere(pos, 350) + + local e = EffectData() + e:SetMagnitude(1.5) + e:SetScale(20) -- The time the effect lasts + + local fx = EffectData() + fx:SetOrigin(pos) + fx:SetMagnitude(1) + util.Effect("web_explosion", fx) + + for k,v in pairs(zombls) do + if IsValid(v) and v:IsValidZombie() then + v:ApplyWebFreeze(20) + end + end + + ply:SetAmmo(ply:GetAmmoCount(GetNZAmmoID("grenade")) - 1, GetNZAmmoID("grenade")) + end + end +end + +function GM:PlayerNoClip( ply, desiredState ) + return nzPlayers.PlayerNoClip(ply, desiredState) +end + +hook.Add( "PlayerInitialSpawn", "nzPlayerInitialSpawn", initialSpawn ) +hook.Add( "PlayerShouldTakeDamage", "nzFriendlyFire", friendlyFire ) +hook.Add( "EntityRemoved", "nzPlayerLeft", playerLeft ) diff --git a/gamemodes/nzombies/gamemode/player_class/sv_sprint.lua b/gamemodes/nzombies/gamemode/player_class/sv_sprint.lua new file mode 100644 index 00000000..746591a8 --- /dev/null +++ b/gamemodes/nzombies/gamemode/player_class/sv_sprint.lua @@ -0,0 +1,82 @@ +local plymeta = FindMetaTable( "Player" ) + +AccessorFunc( plymeta, "fStamina", "Stamina", FORCE_NUMBER ) +AccessorFunc( plymeta, "fMaxStamina", "MaxStamina", FORCE_NUMBER ) +AccessorFunc( plymeta, "fLastStaminaRecover", "LastStaminaRecover", FORCE_NUMBER ) +AccessorFunc( plymeta, "fLastStaminaLoss", "LastStaminaLoss", FORCE_NUMBER ) +AccessorFunc( plymeta, "fStaminaLossAmount", "StaminaLossAmount", FORCE_NUMBER ) +AccessorFunc( plymeta, "fStaminaRecoverAmount", "StaminaRecoverAmount", FORCE_NUMBER ) +AccessorFunc( plymeta, "fMaxRunSpeed", "MaxRunSpeed", FORCE_NUMBER ) +AccessorFunc( plymeta, "bSprinting", "Sprinting", FORCE_BOOL ) +AccessorFunc( plymeta, "bSpawned", "Spawned", FORCE_BOOL ) + +function plymeta:IsSprinting() + return self:GetSprinting() +end + +function plymeta:IsSpawned() + return self:GetSpawned() +end + +hook.Add( "PlayerSpawn", "PlayerSprintSpawn", function( ply ) + + ply:SetSprinting( false ) + ply:SetStamina( 100 ) + ply:SetMaxStamina( 100 ) + + --The rate is fixed on 0.05 seconds + ply:SetStaminaLossAmount( 2 ) + ply:SetStaminaRecoverAmount( 4 ) + + ply:SetLastStaminaLoss( 0 ) + ply:SetLastStaminaRecover( 0 ) + + -- Delay this a bit - it seems like it takes the old sprint speed from last round state (Creative speed) + timer.Simple(0.1, function() + if IsValid(ply) then + ply:SetMaxRunSpeed( ply:GetRunSpeed() ) + -- player variables (especially spritn vars) have been initialized + ply:SetSpawned(true) + end + end) + --print(player_manager.GetPlayerClass(ply)) + +end ) + + +hook.Add( "Think", "PlayerSprint", function() + if !nzRound:InState( ROUND_CREATE ) then + for _, ply in pairs( player.GetAll() ) do + if ply:Alive() and ply:GetNotDowned() and ply:IsSprinting() and ply:GetStamina() >= 0 and ply:GetLastStaminaLoss() + 0.05 <= CurTime() then + ply:SetStamina( math.Clamp( ply:GetStamina() - ply:GetStaminaLossAmount(), 0, ply:GetMaxStamina() ) ) + ply:SetLastStaminaLoss( CurTime() ) + + -- Delay the recovery a bit, you can't sprint instantly after + ply:SetLastStaminaRecover( CurTime() + 0.75 ) + + if ply:GetStamina() == 0 then + ply:SetRunSpeed( ply:GetWalkSpeed() ) + ply:SetSprinting( false ) + end + elseif ply:Alive() and ply:GetNotDowned() and !ply:IsSprinting() and ply:GetStamina() < ply:GetMaxStamina() and ply:GetLastStaminaRecover() + 0.05 <= CurTime() then + ply:SetStamina( math.Clamp( ply:GetStamina() + ply:GetStaminaRecoverAmount(), 0, ply:GetMaxStamina() ) ) + ply:SetLastStaminaRecover( CurTime() ) + end + end + end +end ) + +hook.Add( "KeyPress", "OnSprintKeyPressed", function( ply, key ) + if !nzRound:InState( ROUND_CREATE ) and ( key == IN_SPEED ) and IsValid(ply) and ply:Alive() then + ply:SetSprinting( true ) + end +end ) + +hook.Add( "KeyRelease", "OnSprintKeyReleased", function( ply, key ) + -- Always reset sprint state even if player is dead. + -- Reason: player can die while holding shift. + if !nzRound:InState( ROUND_CREATE ) and ( key == IN_SPEED ) and ply:IsSpawned() then + ply:SetSprinting( false ) + ply:SetRunSpeed( ply:GetMaxRunSpeed() ) + end +end ) diff --git a/gamemodes/nzombies/gamemode/points/sh_points.lua b/gamemodes/nzombies/gamemode/points/sh_points.lua new file mode 100644 index 00000000..a798391d --- /dev/null +++ b/gamemodes/nzombies/gamemode/points/sh_points.lua @@ -0,0 +1,75 @@ +local _PLAYER = FindMetaTable("Player") + +function _PLAYER:GetPoints() + return self:GetNWInt("points") or 0 +end + +function _PLAYER:HasPoints(amount) + return self:GetPoints() >= amount +end + +function _PLAYER:CanAfford(amount) + return (self:GetPoints() - amount) >= 0 +end + + +if (SERVER) then + util.AddNetworkString("nz_points_notification") + -- Sets the character's amount of currency to a specific value. + function _PLAYER:SetPoints(amount) + amount = math.Round(amount, 2) + if !GetConVar("nz_point_notification_clientside"):GetBool() then + local num = amount - self:GetPoints() + if num != 0 then -- 0 points doesn't get sent + net.Start("nz_points_notification") + net.WriteInt(num, 20) + net.WriteEntity(self) + net.Broadcast() + end + end + self:SetNWInt("points", amount) + end + + -- Quick function to set the money to the current amount plus an amount specified. + function _PLAYER:GivePoints(amount, ignoredp) + -- If double points is on. + if nzPowerUps:IsPowerupActive("dp") and !ignoredp then + amount = amount * 2 + end + amount = hook.Call("OnPlayerGetPoints", nil, self, amount) or amount + self:SetPoints(self:GetPoints() + amount) + end + + -- Takes away a certain amount by inverting the amount specified. + function _PLAYER:TakePoints(amount, nosound) + -- Changed to prevent double points from removing double the points. - Don't even think of changing this back Ali, Love Ali. + amount = hook.Call("OnPlayerLosePoints", nil, self, amount) or amount + self:SetPoints(self:GetPoints() - amount) + + if !nosound then + self:EmitSound("nz/effects/buy.wav") + end + + -- If you have a clone like this, it tracks money spent which will be refunded on revival + if self.WhosWhoMoney then self.WhosWhoMoney = self.WhosWhoMoney + amount end + end + + function _PLAYER:Buy(amount, ent, func) + local new = hook.Call("OnPlayerBuy", nil, self, amount, ent, func) or amount + if type(new) == "number" then + if self:CanAfford(new) then + local success = func() + if success then + self:TakePoints(new) + hook.Call("OnPlayerBought", nil, self, new, ent) + return true -- If the buy was successfull, this function also returns true + end + else + return false -- Return false if we can't afford + end + else + return false -- And return false if the hook blocked the event by returning true + end + end + +end diff --git a/gamemodes/nzombies/gamemode/powerups/sh_constructor.lua b/gamemodes/nzombies/gamemode/powerups/sh_constructor.lua new file mode 100644 index 00000000..66589229 --- /dev/null +++ b/gamemodes/nzombies/gamemode/powerups/sh_constructor.lua @@ -0,0 +1,33 @@ +-- Main Tables +nzPowerUps = nzPowerUps or AddNZModule("PowerUps") +nzPowerUps.Data = nzPowerUps.Data or {} + +-- Tables storing the active powerups and their expiration time +nzPowerUps.ActivePowerUps = nzPowerUps.ActivePowerUps or {} +nzPowerUps.ActivePlayerPowerUps = nzPowerUps.ActivePlayerPowerUps or {} + +AccessorFunc(nzPowerUps, "fPowerUpChance", "PowerUpChance", FORCE_NUMBER) + + +function nzPowerUps:ResetPowerUpChance() + -- pseudo random so we start a bit lower than the actual chance + self:SetPowerUpChance(GetConVar("nz_difficulty_powerup_chance"):GetFloat() / 10) +end + +function nzPowerUps:IncreasePowerUpChance() + -- function: + -- f(0) = initialchance, f(n) = f(n-1) + initialchance + + -- % = chance of powerup spawning per zombie. + -- for default 2% this would be 0.2% on reset + -- after one kill it would be 0.04% + -- after 10 kills 2.2% + -- ... + -- after 50 kills 10.2% + -- .. + -- after 100 kills 20.2% + -- ... + -- after 499 kills a powerup drop is guaranteed + -- for default 2%: f(n) = n+1/5 + self:SetPowerUpChance(self:GetPowerUpChance() + (GetConVar("nz_difficulty_powerup_chance"):GetFloat() / 10)) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/powerups/sh_powerups.lua b/gamemodes/nzombies/gamemode/powerups/sh_powerups.lua new file mode 100644 index 00000000..89fb5d17 --- /dev/null +++ b/gamemodes/nzombies/gamemode/powerups/sh_powerups.lua @@ -0,0 +1,309 @@ +-- + +if SERVER then + + local plyMeta = FindMetaTable("Player") + + function plyMeta:GivePowerUp(id, duration) + if duration > 0 then + if !nzPowerUps.ActivePlayerPowerUps[self] then nzPowerUps.ActivePlayerPowerUps[self] = {} end + + nzPowerUps.ActivePlayerPowerUps[self][id] = CurTime() + duration + nzPowerUps:SendPlayerSync(self) -- Sync this player's powerups + end + end + + function plyMeta:RemovePowerUp(id, nosync) + local PowerupData = nzPowerUps:Get(id) + if PowerupData and PowerupData.expirefunc then + PowerupData.expirefunc(id, self) -- Call expirefunc when manually removed + end + + if !nzPowerUps.ActivePlayerPowerUps[self] then nzPowerUps.ActivePlayerPowerUps[self] = {} end + nzPowerUps.ActivePlayerPowerUps[self][id] = nil + if !nosync then nzPowerUps:SendPlayerSync(self) end -- Sync this player's powerups + end + + function plyMeta:RemoveAllPowerUps() + if !nzPowerUps.ActivePlayerPowerUps[self] then nzPowerUps.ActivePlayerPowerUps[self] = {} return end + + for k,v in pairs(nzPowerUps.ActivePlayerPowerUps[self]) do + self:RemovePowerUp(k, true) + end + nzPowerUps:SendPlayerSync(self) + end + + function nzPowerUps:Activate(id, ply, ent) + if hook.Call("OnPlayerPickupPowerUp", nil, ply, id, ent) then return end + + local PowerupData = self:Get(id) + + if !PowerupData.global then + if IsValid(ply) then + if not nzPowerUps.ActivePlayerPowerUps[ply] or not nzPowerUps.ActivePlayerPowerUps[ply][id] then -- If you don't have the powerup + PowerupData.func(id, ply) + end + ply:GivePowerUp(id, PowerupData.duration) + end + else + if PowerupData.duration != 0 then + -- Activate for a certain time + if not self.ActivePowerUps[id] then + PowerupData.func(id, ply) + end + self.ActivePowerUps[id] = CurTime() + PowerupData.duration + else + -- Activate Once + PowerupData.func(id, ply) + end + -- Sync to everyone + self:SendSync() + + end + + -- Notify + if IsValid(ply) then ply:EmitSound("nz/powerups/power_up_grab.wav") end + if PowerupData.announcement then + nzNotifications:PlaySound(PowerupData.announcement, 1) + end + end + + function nzPowerUps:SpawnPowerUp(pos, specific) + local choices = {} + local total = 0 + + -- Chance it + if !specific then + for k,v in pairs(self.Data) do + if k != "ActivePowerUps" then + choices[k] = v.chance + total = total + v.chance + end + end + end + + local id = specific and specific or nzMisc.WeightedRandom(choices) + if !id or id == "null" then return end -- Back out + + local ent = ents.Create("drop_powerup") + id = hook.Call("OnPowerUpSpawned", nil, id, ent) or id + if !IsValid(ent) then return end -- If a hook removed the powerup + + -- Spawn it + local PowerupData = self:Get(id) + + local pos = pos+Vector(0,0,50) + + ent:SetPowerUp(id) + pos.z = pos.z - ent:OBBMaxs().z + ent:SetModel(PowerupData.model) + ent:SetPos(pos) + ent:SetAngles(PowerupData.angle) + ent:Spawn() + ent:EmitSound("nz/powerups/power_up_spawn.wav") + end + +end + +function nzPowerUps:IsPowerupActive(id) + + local time = self.ActivePowerUps[id] + + if time != nil then + -- Check if it is still within the time. + if CurTime() > time then + -- Expired + self.ActivePowerUps[id] = nil + else + return true + end + end + + return false + +end + +function nzPowerUps:IsPlayerPowerupActive(ply, id) + + local time = self.ActivePlayerPowerUps[ply][id] + + if time then + -- Check if it is still within the time. + if CurTime() > time then + -- Expired + self.ActivePlayerPowerUps[ply][id] = nil + else + return true + end + end + + return false + +end + +function nzPowerUps:AllActivePowerUps() + + return self.ActivePowerUps + +end + +function nzPowerUps:NewPowerUp(id, data) + if SERVER then + -- Sanitise any client data. + else + data.Func = nil + end + self.Data[id] = data +end + +function nzPowerUps:Get(id) + return self.Data[id] +end + +-- Double Points +nzPowerUps:NewPowerUp("dp", { + name = "Double Points", + model = "models/nzpowerups/x2.mdl", + global = true, -- Global means it will appear for any player and will refresh its own time if more + angle = Angle(25,0,0), + scale = 1, + chance = 5, + duration = 30, + announcement = "nz/powerups/double_points.mp3", + func = function(self, ply) + end, +}) + +-- Max Ammo +nzPowerUps:NewPowerUp("maxammo", { + name = "Max Ammo", + model = "models/Items/BoxSRounds.mdl", + global = true, + angle = Angle(0,0,25), + scale = 1.5, + chance = 5, + duration = 0, + func = (function(self, ply) + nzNotifications:PlaySound("nz/powerups/max_ammo.mp3", 2) + -- Give everyone ammo + for k,v in pairs(player.GetAll()) do + v:GiveMaxAmmo() + end + end), +}) + +-- Insta Kill +nzPowerUps:NewPowerUp("insta", { + name = "Insta Kill", + model = "models/nzpowerups/insta.mdl", + global = true, + angle = Angle(0,0,0), + scale = 1, + chance = 5, + duration = 30, + announcement = "nz/powerups/insta_kill.mp3", + func = function(self, ply) + print("Called") + end, +}) + +-- Nuke +nzPowerUps:NewPowerUp("nuke", { + name = "Nuke", + model = "models/nzpowerups/nuke.mdl", + global = true, + angle = Angle(10,0,0), + scale = 1, + chance = 5, + duration = 0, + announcement = "nz/powerups/nuke.wav", + func = (function(self, ply) + nzPowerUps:Nuke(ply:GetPos()) + end), +}) + +-- Fire Sale +nzPowerUps:NewPowerUp("firesale", { + name = "Fire Sale", + model = "models/nzpowerups/firesale.mdl", + global = true, + angle = Angle(45,0,0), + scale = 0.75, + chance = 1, + duration = 30, + announcement = "nz/powerups/fire_sale_announcer.wav", + func = (function(self, ply) + nzPowerUps:FireSale() + end), + expirefunc = function() + local tbl = ents.FindByClass("random_box_spawns") + for k,v in pairs(tbl) do + local box = v.FireSaleBox + if IsValid(box) then + box:StopSound("nz_firesale_jingle") + if box.MarkForRemoval then + box:MarkForRemoval() + box.FireSaling = false + else + box:Remove() + end + end + end + end, +}) + +-- Carpenter +nzPowerUps:NewPowerUp("carpenter", { + name = "Carpenter", + model = "models/nzpowerups/carpenter.mdl", + global = true, + angle = Angle(45,0,0), + scale = 1, + chance = 5, + duration = 0, + func = (function(self, ply) + nzNotifications:PlaySound("nz/powerups/carpenter.wav", 0) + nzNotifications:PlaySound("nz/powerups/carp_loop.wav", 1) + nzPowerUps:Carpenter() + end), +}) + +-- Zombie Blood +nzPowerUps:NewPowerUp("zombieblood", { + name = "Zombie Blood", + model = "models/nzpowerups/zombieblood.mdl", + global = false, -- Only applies to the player picking it up and time is handled individually per player + angle = Angle(0,0,0), + scale = 1, + chance = 2, + duration = 30, + announcement = "nz/powerups/zombie_blood.wav", + func = (function(self, ply) + ply:SetTargetPriority(TARGET_PRIORITY_NONE) + end), + expirefunc = function(self, ply) -- ply is only passed if the powerup is non-global + ply:SetTargetPriority(TARGET_PRIORITY_PLAYER) + end, +}) + +-- Death Machine +nzPowerUps:NewPowerUp("deathmachine", { + name = "Death Machine", + model = "models/nzpowerups/deathmachine.mdl", + global = false, -- Only applies to the player picking it up and time is handled individually per player + angle = Angle(0,0,0), + scale = 1, + chance = 2, + duration = 30, + announcement = "nz/powerups/deathmachine.mp3", + func = (function(self, ply) + ply:SetUsingSpecialWeapon(true) + ply:Give("nz_death_machine") + ply:SelectWeapon("nz_death_machine") + end), + expirefunc = function(self, ply) -- ply is only passed if the powerup is non-global + ply:SetUsingSpecialWeapon(false) + ply:StripWeapon("nz_death_machine") + ply:EquipPreviousWeapon() + end, +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/powerups/sh_sync.lua b/gamemodes/nzombies/gamemode/powerups/sh_sync.lua new file mode 100644 index 00000000..452a741b --- /dev/null +++ b/gamemodes/nzombies/gamemode/powerups/sh_sync.lua @@ -0,0 +1,92 @@ +-- Client Server Syncing + +if SERVER then + + -- Server to client (Server) + util.AddNetworkString( "nzPowerUps.Sync" ) + util.AddNetworkString( "nzPowerUps.SyncPlayer" ) + util.AddNetworkString( "nzPowerUps.SyncPlayerFull" ) + util.AddNetworkString( "nzPowerUps.Nuke" ) -- See the nuke function in sv_powerups + + function nzPowerUps:SendSync(receiver) + local data = table.Copy(self.ActivePowerUps) + + net.Start( "nzPowerUps.Sync" ) + net.WriteTable( data ) + return IsValid(receiver) and net.Send(receiver) or net.Broadcast() + end + + function nzPowerUps:SendPlayerSync(ply, receiver) + if !self.ActivePlayerPowerUps[ply] then self.ActivePlayerPowerUps[ply] = {} end + local data = table.Copy(self.ActivePlayerPowerUps[ply]) + + net.Start( "nzPowerUps.SyncPlayer" ) + net.WriteEntity(ply) + net.WriteTable( data ) + return IsValid(receiver) and net.Send(receiver) or net.Broadcast() + end + + function nzPowerUps:SendPlayerSyncFull(receiver) + local data = table.Copy(self.ActivePlayerPowerUps) + + net.Start( "nzPowerUps.SyncPlayerFull" ) + net.WriteTable( data ) + return IsValid(receiver) and net.Send(receiver) or net.Broadcast() + end + + FullSyncModules["PowerUps"] = function(ply) + nzPowerUps:SendSync(ply) + nzPowerUps:SendPlayerSyncFull(ply) + end + +end + +if CLIENT then + + -- Server to client (Client) + local function ReceivePowerupSync( length ) + --print("Received PowerUps Sync") + nzPowerUps.ActivePowerUps = net.ReadTable() + --PrintTable(nzPowerUps.ActivePowerUps) + end + + local function ReceivePowerupPlayerSync( length ) + --print("Received PowerUps Player Sync") + local ply = net.ReadEntity() + nzPowerUps.ActivePlayerPowerUps[ply] = net.ReadTable() + --PrintTable(nzPowerUps.ActivePlayerPowerUps) + end + + local function ReceivePowerupPlayerSyncFull( length ) + --print("Received PowerUps Full Player Sync") + nzPowerUps.ActivePlayerPowerUps = net.ReadTable() + --PrintTable(nzPowerUps.ActivePlayerPowerUps) + end + + local function ReceiveNukeEffect() + local fade = 0 + local rising = true + hook.Add("RenderScreenspaceEffects", "DrawNukeEffect", function() + if rising then + fade = fade + 2000*FrameTime() + if fade >= 1000 then + fade = 255 + rising = false + end + else + fade = fade - 100*FrameTime() + if fade <= 0 then + hook.Remove("RenderScreenspaceEffects", "DrawNukeEffect") + end + end + surface.SetDrawColor(255,255,255,fade) + surface.DrawRect(-ScrW(),-ScrH(),ScrW()*2,ScrH()*2) + end) + end + + -- Receivers + net.Receive( "nzPowerUps.Sync", ReceivePowerupSync ) + net.Receive( "nzPowerUps.SyncPlayer", ReceivePowerupPlayerSync ) + net.Receive( "nzPowerUps.SyncPlayerFull", ReceivePowerupPlayerSyncFull ) + net.Receive( "nzPowerUps.Nuke", ReceiveNukeEffect ) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/powerups/sv_powerups.lua b/gamemodes/nzombies/gamemode/powerups/sv_powerups.lua new file mode 100644 index 00000000..26849adb --- /dev/null +++ b/gamemodes/nzombies/gamemode/powerups/sv_powerups.lua @@ -0,0 +1,171 @@ +-- + +hook.Add("Think", "CheckActivePowerups", function() + for k,v in pairs(nzPowerUps.ActivePowerUps) do + if CurTime() >= v then + local func = nzPowerUps:Get(k).expirefunc + if func then func(id) end + nzPowerUps.ActivePowerUps[k] = nil + nzPowerUps:SendSync() + end + end + for k,v in pairs(nzPowerUps.ActivePlayerPowerUps) do + if !IsValid(k) then + nzPowerUps.ActivePlayerPowerUps[k] = nil + nzPowerUps:SendPlayerSyncFull() + else + for id, time in pairs(v) do + if CurTime() >= time then + local func = nzPowerUps:Get(id).expirefunc + if func then func(id, k) end + nzPowerUps.ActivePlayerPowerUps[k][id] = nil + nzPowerUps:SendPlayerSync(k) + end + end + end + end +end) + +function nzPowerUps:Nuke(pos, nopoints, noeffect) + -- Kill them all + local highesttime = 0 + if pos and type(pos) == "Vector" then + for k,v in pairs(ents.GetAll()) do + if v:IsValidZombie() then + if IsValid(v) then + v:SetBlockAttack(true) -- They cannot attack now! + local insta = DamageInfo() + insta:SetAttacker(Entity(0)) + insta:SetDamageType(DMG_BLAST_SURFACE) + -- Delay the death by the distance from the position in milliseconds + local time = v:GetPos():Distance(pos)/1000 + if time > highesttime then highesttime = time end + timer.Simple(time, function() + if IsValid(v) then + insta:SetDamage(v:Health()) + v:TakeDamageInfo( insta ) + end + end) + end + end + end + else + for k,v in pairs(ents.GetAll()) do + if v:IsValidZombie() then + print(v, IsValid(v)) + if IsValid(v) then + local insta = DamageInfo() + insta:SetAttacker(Entity(0)) + insta:SetInflictor(Entity(0)) + insta:SetDamageType(DMG_BLAST_SURFACE) + timer.Simple(0.1, function() + if IsValid(v) then + insta:SetDamage(v:Health()) + v:TakeDamageInfo( insta ) + end + end) + end + end + end + end + + -- Give the players a set amount of points + if !nopoints then + timer.Simple(highesttime, function() + if nzRound:InProgress() then -- Only if the game is still going! + for k,v in pairs(player.GetAll()) do + if v:IsPlayer() then + v:GivePoints(400) + end + end + end + end) + end + + if !noeffect then + net.Start("nzPowerUps.Nuke") + net.Broadcast() + end +end + +-- Add the sound so we can stop it again +sound.Add( { + name = "nz_firesale_jingle", + channel = CHAN_STATIC, + volume = 1.0, + level = 75, + pitch = { 100, 100 }, + sound = "nz/randombox/fire_sale.wav" +} ) + +function nzPowerUps:FireSale() + --print("Running") + -- Get all spawns + local all = ents.FindByClass("random_box_spawns") + + for k,v in pairs(all) do + if !IsValid(v.Box) then + local box = ents.Create( "random_box" ) + local pos = v:GetPos() + local ang = v:GetAngles() + + box:SetPos( pos + ang:Up()*10 + ang:Right()*7 ) + box:SetAngles( ang ) + box:Spawn() + --box:PhysicsInit( SOLID_VPHYSICS ) + box.SpawnPoint = v + v.FireSaleBox = box + + v:SetBodygroup(1,1) + + local phys = box:GetPhysicsObject() + if phys:IsValid() then + phys:EnableMotion(false) + end + + box:EmitSound("nz_firesale_jingle") + else + local sound = ents.Create("nz_prop_effect_attachment") + sound:SetNoDraw(true) + sound:SetPos(v:GetPos()) + sound:SetCollisionGroup(COLLISION_GROUP_DEBRIS) + sound:Spawn() + sound:EmitSound("nz_firesale_jingle") + v.FireSaleBox = sound + end + end +end + +function nzPowerUps:CleanUp() + -- Clear all powerups + for k,v in pairs(ents.FindByClass("drop_powerup")) do + v:Remove() + end + + -- Turn off all modifiers + table.Empty(self.ActivePowerUps) + -- Sync + self:SendSync() +end + +function nzPowerUps:Carpenter(nopoints) + -- Repair them all + for k,v in pairs(ents.FindByClass("breakable_entry")) do + if v:IsValid() then + for i=1, GetConVar("nz_difficulty_barricade_planks_max"):GetInt() do + if i > #v.Planks then + v:AddPlank() + end + end + end + end + + -- Give the players a set amount of points + if !nopoints then + for k,v in pairs(player.GetAll()) do + if v:IsPlayer() then + v:GivePoints(200) + end + end + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/q_menu/cl_menu.lua b/gamemodes/nzombies/gamemode/q_menu/cl_menu.lua new file mode 100644 index 00000000..76a1ba7d --- /dev/null +++ b/gamemodes/nzombies/gamemode/q_menu/cl_menu.lua @@ -0,0 +1,758 @@ +function nzQMenu:CreatePropsMenu( ) + + -- Data we will need later + local data -- Table with spawnlist data + local SpawnSheet -- Spawnlist sheet + local UtilitySheet -- Utility sheet + local CategoryEditor -- Function for creating Category Editor + local ReloadSpawnlist -- Function for creating/reloading spawnlist sheet + + -- Create a Frame to contain everything. + local frame = vgui.Create( "DFrame" ) + frame:SetTitle( "Props Menu" ) + frame:SetSize( 475, 340 ) + frame:Center() + frame:SetPopupStayAtBack(true) + frame:MakePopup() + frame:ShowCloseButton( true ) + frame:SetVisible( false ) + frame.SpawnlistActive = true + + local oncolor = Color(255,255,255) + local offcolor = Color(200,200,200) + + local utilitiestab -- Store it here so Spawntab can refer back to it + + local spawntab = vgui.Create("DPanel", frame) + spawntab:SetPos(5,5) + spawntab:SetSize(75,15) + spawntab:SetBackgroundColor( oncolor ) + + local spawntext = vgui.Create("DLabel", spawntab) + spawntext:SetText("Spawnlist") + spawntext:SetPos(14,-2) + spawntext:SetTextColor( Color(10,10,10) ) + + local spawnbut = vgui.Create("DButton", spawntab) + spawnbut:SetSize(spawntab:GetSize()) + spawnbut.Paint = function() end + spawnbut:SetText("") + spawnbut.DoClick = function(self) + UtilitySheet:SetVisible(false) + SpawnSheet:SetVisible(true) + spawntab:SetBackgroundColor( oncolor ) + utilitiestab:SetBackgroundColor( offcolor ) + frame.SpawnlistActive = true + end + + utilitiestab = vgui.Create("DPanel", frame) + utilitiestab:SetPos(85,5) + utilitiestab:SetSize(75,15) + utilitiestab:SetBackgroundColor( offcolor ) + + local utilitiestext = vgui.Create("DLabel", utilitiestab) + utilitiestext:SetText("Utilities") + utilitiestext:SetPos(20,-2) + utilitiestext:SetTextColor( Color(10,10,10) ) + + local utilitiesbut = vgui.Create("DButton", utilitiestab) + utilitiesbut:SetSize(utilitiestab:GetSize()) + utilitiesbut.Paint = function() end + utilitiesbut:SetText("") + utilitiesbut.DoClick = function(self) + UtilitySheet:SetVisible(true) + SpawnSheet:SetVisible(false) + spawntab:SetBackgroundColor( offcolor ) + utilitiestab:SetBackgroundColor( oncolor ) + frame.SpawnlistActive = false + end + + + nzQMenu.Data.MainFrame = frame + + -- Loop to make all the tabs + local tabs = {} + tabs.Scrolls = {} + tabs.Lists = {} + tabs.Categories = {} + + CategoryEditor = function(oldcat, model) + local frame = vgui.Create("DFrame") + frame:SetTitle(oldcat and "Edit Category ..." or "Add Category ...") + frame:SetSize(400, 250) + frame:SetPos(ScrW()/2 - 200, ScrH()/2 - 125) + + local highlightcolor = Color(150,150,150) + + local name = vgui.Create( "DTextEntry", frame ) + name:SetSize( 380, 20 ) + name:SetPos( 10, 30 ) + if oldcat then + name:SetValue(oldcat) + end + name.PaintOver = function(self, w, h) + if self.HighlightRed then + surface.SetDrawColor(255,0,0,self.HighlightRed) + local x2,y2 = self:GetSize() + surface.DrawRect(-50, -50, x2+50, y2+50) + self.HighlightRed = self.HighlightRed - FrameTime() * 100 + if self.HighlightRed <= 0 then + self.HighlightRed = nil + end + end + if self:GetValue() == "" then + draw.SimpleText("Name", "DermaDefault", 4, 3, highlightcolor) + end + end + + local tooltip = vgui.Create( "DTextEntry", frame ) + tooltip:SetSize( 380, 20 ) + tooltip:SetPos( 10, 55 ) + if oldcat then + tooltip:SetValue(data[tabs.Categories[oldcat]].tooltip) + end + tooltip.PaintOver = function(self, w, h) + if self:GetValue() == "" then + draw.SimpleText("Tooltip (Optional)", "DermaDefault", 4, 3, highlightcolor) + end + end + + local icons = vgui.Create( "DIconBrowser", frame ) + icons:SetSize( 380, 130 ) + icons:SetPos( 10, 80 ) + if oldcat then + icons:SetSelectedIcon(data[tabs.Categories[oldcat]].icon) + else + icons:SetSelectedIcon("icon16/accept.png") + end + + local save = vgui.Create("DButton", frame) + save:SetSize( 350, 25 ) + save:SetPos( 25, 215 ) + save:SetText(oldcat and "Save" or "Add") + save.DoClick = function(self) + local chosenname = name:GetValue() + if chosenname == "" then + name.HighlightRed = 255 + else + local good = true + if oldcat != chosenname then + for k,v in pairs(data) do + if v.name == chosenname then + name.HighlightRed = 255 + good = false + break + end + end + end + + if good then + if oldcat then + local tbl = data[tabs.Categories[oldcat]] + tbl.name = chosenname + tbl.icon = icons:GetSelectedIcon() + if tooltip:GetValue() != "" then + tbl.tooltip = tooltip:GetValue() + else + tbl.tooltip = nil + end + else + local tbl = {} + if tooltip:GetValue() != "" then + tbl.tooltip = tooltip:GetValue() + end + tbl.icon = icons:GetSelectedIcon() + tbl.name = chosenname + tbl.models = {} + if model then table.insert(tbl.models, model) end + table.insert(data, tbl) + end + ReloadSpawnlist() + frame:Close() + end + end + end + + frame:MakePopup() + end + + ReloadSpawnlist = function() + + if IsValid(SpawnSheet) then SpawnSheet:Remove() end + SpawnSheet = vgui.Create( "DPropertySheet", nzQMenu.Data.MainFrame ) + SpawnSheet:SetPos( 10, 30 ) + SpawnSheet:SetSize( 455, 300 ) + + tabs.Scrolls = {} + tabs.Lists = {} + tabs.Categories = {} + + -- Then re-add from the data table + for k,v in pairs(data) do + local cat = v.name + tabs.Scrolls[cat] = vgui.Create( "DScrollPanel", nzQMenu.Data.MainFrame ) + tabs.Scrolls[cat]:SetSize( 455, 300 ) + tabs.Scrolls[cat]:SetPos( 10, 30 ) + + tabs.Lists[cat] = vgui.Create( "DIconLayout", tabs.Scrolls[cat] ) + tabs.Lists[cat]:SetSize( 440, 300 ) + tabs.Lists[cat]:SetPos( 0, 0 ) + tabs.Lists[cat]:SetSpaceY( 5 ) + tabs.Lists[cat]:SetSpaceX( 5 ) + local tab = SpawnSheet:AddSheet( cat, tabs.Scrolls[cat], v.icon, false, false, v.tooltip ).Tab + tab.DoRightClick = function(self) + local menu = DermaMenu() + menu:AddOption("Edit Category ...", function() + CategoryEditor(cat) + end) + local submenu = menu:AddSubMenu( "Set Order" ) + for i = 1, #data do + submenu:AddOption(i, function() + local temp = v + table.remove(data, k) + table.insert(data, i, v) + ReloadSpawnlist() + end) + end + + menu:AddSpacer() + + menu:AddOption("Remove Category", function() + table.remove(data, k) + ReloadSpawnlist() + end) + menu:Open() + end + + for k2,v2 in pairs(v.models) do + local ListItem = tabs.Lists[cat]:Add( "SpawnIcon" ) + ListItem:SetSize( 48, 48 ) + ListItem:SetModel(v2) + ListItem.Model = v2 + ListItem.DoClick = function( item ) + nzQMenu:Request(item.Model) + surface.PlaySound( "ui/buttonclickrelease.wav" ) + end + ListItem.DoRightClick = function( item ) + local menu = DermaMenu() + local submenu = menu:AddSubMenu( "Add to category" ) + + for k3,v3 in pairs(data) do + submenu:AddOption(v3.name, function() + table.insert(v3.models, v2) + ReloadSpawnlist() + end) + end + + menu:AddOption("Add to new category ...", function() + CategoryEditor(nil, v2) + end) + + menu:AddSpacer() + + menu:AddOption("Remove from category", function() + table.remove(v.models, k2) + ReloadSpawnlist() + end) + menu:Open() + end + end + tabs.Categories[cat] = k + end + + if !frame.SpawnlistActive then + SpawnSheet:SetVisible(false) + end + end + + tabs.Utilities = {} + local function CreateUtilities() + if IsValid(UtilitySheet) then UtilitySheet:Remove() end + UtilitySheet = vgui.Create( "DPropertySheet", nzQMenu.Data.MainFrame ) + UtilitySheet:SetPos( 10, 30 ) + UtilitySheet:SetSize( 455, 300 ) + + tabs.Utilities["Entities"] = vgui.Create( "DScrollPanel", nzQMenu.Data.MainFrame ) + tabs.Utilities["Entities"]:SetSize( 455, 300 ) + tabs.Utilities["Entities"]:SetPos( 10, 30 ) + + local lists = vgui.Create( "DIconLayout", tabs.Utilities["Entities"] ) + lists:SetSize( 440, 300 ) + lists:SetPos( 0, 0 ) + lists:SetSpaceY( 5 ) + lists:SetSpaceX( 5 ) + tabs.Utilities["Entities"].List = lists + UtilitySheet:AddSheet( "Entities", tabs.Utilities["Entities"], nil, false, false, v ) + + tabs.Utilities["Search"] = vgui.Create( "DPanel", nzQMenu.Data.MainFrame ) + tabs.Utilities["Search"]:SetSize( 455, 300 ) + tabs.Utilities["Search"]:SetPos( 10, 30 ) + + tabs.Utilities["Search"].Warn = vgui.Create( "DLabel", tabs.Utilities["Search"] ) + tabs.Utilities["Search"].Warn:SetSize( 420, 20 ) + tabs.Utilities["Search"].Warn:SetPos( 60, 5 ) + tabs.Utilities["Search"].Warn:SetTextColor( Color(0,0,0) ) + tabs.Utilities["Search"].Warn:SetText("Warning: May cause severe lag and/or crash. Be sure to save first.") + + tabs.Utilities["Search"].Search = vgui.Create( "DTextEntry", tabs.Utilities["Search"] ) + tabs.Utilities["Search"].Search:SetSize( 420, 20 ) + tabs.Utilities["Search"].Search:SetPos( 10, 25 ) + tabs.Utilities["Search"].Search.OnEnter = function() tabs.Utilities["Search"]:RefreshResults() end + tabs.Utilities["Search"].Search:SetTooltip("Press Enter to search/update results") + + tabs.Utilities["Search"].Content = vgui.Create( "DScrollPanel", tabs.Utilities["Search"] ) + tabs.Utilities["Search"].Content:SetSize( 430, 210 ) + tabs.Utilities["Search"].Content:SetPos( 0, 50 ) + + lists = vgui.Create( "DIconLayout", tabs.Utilities["Search"].Content ) + lists:SetSize( 440, 210 ) + lists:SetPos( 10, 00 ) + lists:SetSpaceY( 5 ) + lists:SetSpaceX( 5 ) + tabs.Utilities["Search"].List = lists + + tabs.Utilities["MapProps"] = vgui.Create( "DPanel", nzQMenu.Data.MainFrame ) + tabs.Utilities["MapProps"]:SetSize( 455, 300 ) + tabs.Utilities["MapProps"]:SetPos( 10, 30 ) + + tabs.Utilities["MapProps"].Search = vgui.Create( "DButton", tabs.Utilities["MapProps"] ) + tabs.Utilities["MapProps"].Search:SetSize( 420, 20 ) + tabs.Utilities["MapProps"].Search:SetPos( 10, 10 ) + tabs.Utilities["MapProps"].Search.DoClick = function() tabs.Utilities["MapProps"]:RefreshResults() end + tabs.Utilities["MapProps"].Search:SetText("Update") + + tabs.Utilities["MapProps"].Content = vgui.Create( "DScrollPanel", tabs.Utilities["MapProps"] ) + tabs.Utilities["MapProps"].Content:SetSize( 430, 220 ) + tabs.Utilities["MapProps"].Content:SetPos( 0, 40 ) + + lists = vgui.Create( "DIconLayout", tabs.Utilities["MapProps"].Content ) + lists:SetSize( 440, 210 ) + lists:SetPos( 10, 00 ) + lists:SetSpaceY( 5 ) + lists:SetSpaceX( 5 ) + tabs.Utilities["MapProps"].List = lists + + function tabs.Utilities.Search:RefreshResults() + if ( self.Search:GetText() == "" ) then return end + local pnl = tabs.Utilities["Search"].List + pnl:Clear() + local results = search.GetResults( self.Search:GetText() ) + for k,v in pairs(results) do + local ListItem = pnl:Add( "SpawnIcon" ) + ListItem:SetSize( 45, 45 ) + ListItem:SetModel(v) + ListItem.Model = v + ListItem.DoClick = function( item ) + nzQMenu:Request(item.Model) + surface.PlaySound( "ui/buttonclickrelease.wav" ) + end + ListItem.DoRightClick = function( item ) + local menu = DermaMenu() + local submenu = menu:AddSubMenu( "Add to category" ) + for k2,v2 in pairs(data) do + submenu:AddOption(v2.name, function() + table.insert(v2.models, v) + ReloadSpawnlist() + end) + end + + menu:AddSpacer() + + menu:AddOption("Add to new category ...", function() + CategoryEditor(nil, v) + end) + menu:Open() + end + end + end + + function tabs.Utilities.MapProps:RefreshResults() + local pnl = tabs.Utilities["MapProps"].List + pnl:Clear() + local used = {} + for k,v in pairs(ents.GetAll()) do + if string.find(v:GetClass(), "prop") then + local model = v:GetModel() + if !used[model] then + local ListItem = pnl:Add( "SpawnIcon" ) + ListItem:SetSize( 45, 45 ) + ListItem:SetModel(model) + ListItem.Model = model + ListItem.DoClick = function( item ) + nzQMenu:Request(item.Model) + surface.PlaySound( "ui/buttonclickrelease.wav" ) + end + ListItem.DoRightClick = function( item ) + local menu = DermaMenu() + local submenu = menu:AddSubMenu( "Add to category" ) + for k,v in pairs(data) do + submenu:AddOption(v.name, function() + table.insert(v.models, model) + ReloadSpawnlist() + end) + end + + menu:AddSpacer() + + menu:AddOption("Add to new category ...", function() + CategoryEditor(nil, v) + end) + menu:Open() + end + used[model] = true + end + end + end + end + + UtilitySheet:AddSheet( "Map Props", tabs.Utilities["MapProps"], "icon16/map.png", false, false, v ) + UtilitySheet:AddSheet( "Search", tabs.Utilities["Search"], "icon16/magnifier.png", false, false, v ) + + for k,v in pairs(nzQMenu.Data.Entities) do + local ListItem = tabs.Utilities["Entities"].List:Add( "DImageButton" ) + ListItem:SetSize( 48, 48 ) + ListItem:SetImage(v[2]) + ListItem.Entity = v[1] + ListItem.DoClick = function( item ) + nzQMenu:Request(item.Entity, true) + surface.PlaySound( "ui/buttonclickrelease.wav" ) + end + ListItem:SetTooltip(v[3] or v[1]) + -- You don't need to set the position, that is done automatically + + end + + tabs.Utilities["Addons"] = vgui.Create( "DPanel", nzQMenu.Data.MainFrame ) + tabs.Utilities["Addons"]:SetSize( 455, 300 ) + tabs.Utilities["Addons"]:SetPos( 0, 30 ) + + tabs.Utilities["Addons"].AddonList = vgui.Create( "DTree", tabs.Utilities["Addons"] ) + tabs.Utilities["Addons"].AddonList:SetSize(200, 280) + tabs.Utilities["Addons"].AddonList:SetPos(-20, 0) + tabs.Utilities["Addons"].AddonList:SetPadding(0) + + tabs.Utilities["Addons"].Content = vgui.Create( "DScrollPanel", tabs.Utilities["Addons"] ) + tabs.Utilities["Addons"].Content:SetSize( 330, 220 ) + tabs.Utilities["Addons"].Content:SetPos( 180, 10 ) + + lists = vgui.Create( "DIconLayout", tabs.Utilities["Addons"].Content ) + lists:SetSize( 340, 210 ) + lists:SetPos( 10, 0 ) + lists:SetSpaceY( 5 ) + lists:SetSpaceX( 5 ) + tabs.Utilities["Addons"].List = lists + + -- From Sandbox + local function AddRecursive( pnl, folder, path, wildcard ) + local files, folders = file.Find( folder .. "*", path ) + for k, v in pairs( files ) do + if ( !string.EndsWith( v, ".mdl" ) ) then continue end + + local model = folder..v + + local ListItem = pnl:Add( "SpawnIcon" ) + ListItem:SetSize( 45, 45 ) + ListItem:SetModel(model) + ListItem.Model = model + ListItem.DoClick = function( item ) + nzQMenu:Request(item.Model) + surface.PlaySound( "ui/buttonclickrelease.wav" ) + end + ListItem.DoRightClick = function( item ) + local menu = DermaMenu() + local submenu = menu:AddSubMenu( "Add to category" ) + for k2,v2 in pairs(data) do + submenu:AddOption(v2.name, function() + table.insert(v2.models, model) + ReloadSpawnlist() + end) + end + + menu:AddSpacer() + + menu:AddOption("Add to new category ...", function() + CategoryEditor(nil, model) + end) + menu:Open() + end + + end + for k, v in pairs( folders ) do + AddRecursive( pnl, folder .. v .. "/", path, wildcard ) + end + end + + for _, addon in SortedPairsByMemberValue( engine.GetAddons(), "title" ) do + if ( !addon.downloaded || !addon.mounted ) then continue end + if ( addon.models <= 0 ) then continue end + + local models = tabs.Utilities["Addons"].AddonList:AddNode( addon.title .. " (" .. addon.models .. ")", "icon16/bricks.png" ) + models.DoClick = function() + + local pnl = tabs.Utilities["Addons"].List + pnl:Clear() + + AddRecursive(pnl, "models/", addon.title, "*.mdl") + + end + end + + UtilitySheet:AddSheet( "Addons", tabs.Utilities["Addons"], "icon16/bricks.png", false, false, v ) + + if !frame.SpawnlistActive then + UtilitySheet:SetVisible(false) + end + end + + if !file.Exists( "nz/spawnlist.txt", "DATA" ) then + if !file.Exists( "nz/", "DATA" ) then + file.CreateDir( "nz" ) + end + local content = file.Read("nzmapscripts/defaultspawnlist.lua", "LUA") + file.Write("nz/spawnlist.txt", content) + end + + local content = file.Read( "nz/spawnlist.txt", "DATA" ) + if content then + data = util.KeyValuesToTable(content) + ReloadSpawnlist() + CreateUtilities() + UtilitySheet:SetVisible(false) -- This starts off + end + + hook.Add( "SearchUpdate", "SearchUpdate", function() + if ( !tabs.Utilities["Search"]:IsVisible() ) then return end + tabs.Utilities["Search"]:RefreshResults() + end) + + local save = vgui.Create("DButton", frame) + save:SetPos(325, 4) + save:SetSize(50, 16) + save:SetText("Save") + save.DoClick = function() + local tbl = {} + for k,v in pairs(data) do + table.insert(tbl, v) + end + local keyvalues = util.TableToKeyValues(tbl) + file.Write("nz/spawnlist.txt", keyvalues) + end + +end + +function nzQMenu:CreateToolsMenu( ) + + -- Create a Frame to contain everything. + nzQMenu.Data.MainFrame = vgui.Create( "DFrame" ) + --nzQMenu.Data.MainFrame:SetTitle( "Tools Menu" ) + nzQMenu.Data.MainFrame:SetSize( 465, 300 ) + nzQMenu.Data.MainFrame:Center() + nzQMenu.Data.MainFrame:MakePopup() + nzQMenu.Data.MainFrame:ShowCloseButton( true ) + nzQMenu.Data.MainFrame:SetTitle("") + nzQMenu.Data.MainFrame.Paint = function(self, w, h) end + nzQMenu.Data.MainFrame.ToolMode = true + nzQMenu.Data.MainFrame:MakePopup() + + local ToolPanel = vgui.Create("DFrame", nzQMenu.Data.MainFrame ) + ToolPanel:SetPos( 305, 25 ) + ToolPanel:SetSize( 155, 260 ) + ToolPanel:SetZPos(-30) + ToolPanel:ShowCloseButton(false) + ToolPanel:SetDraggable(false) + ToolPanel:SetTitle("Tool List") + + local ToolInterface = vgui.Create("DFrame", nzQMenu.Data.MainFrame ) + ToolInterface:SetPos( 0, 0 ) + ToolInterface:SetSize( 310, 300 ) + ToolInterface:ShowCloseButton(false) + ToolInterface:SetDraggable(true) + ToolInterface:SetTitle(nzTools.ToolData[LocalPlayer():GetActiveWeapon().ToolMode or "default"].displayname) + + local FrameMerge = vgui.Create("DPanel", nzQMenu.Data.MainFrame ) + FrameMerge:SetPos( 308, 49 ) + FrameMerge:SetSize( 4, 235 ) + FrameMerge.Paint = function(self, w, h) + surface.SetDrawColor(96, 100, 103) + surface.DrawRect(0, 0, w, h) + end + + local ToolList = vgui.Create( "DScrollPanel", nzQMenu.Data.MainFrame ) + ToolList:SetPos( 305, 58 ) + ToolList:SetSize( 150, 220 ) + + local ToolData = vgui.Create("DPanel", ToolInterface ) + ToolData:SetPos( 5, 30 ) + ToolData:SetSize( 300, 265 ) + + -- Loop to make all the tabs + local tabs = {} + tabs.Tools = {} + local curtool = nil + local numtools = 0 + + local function RebuildToolInterface(id) + --print(ToolData.interface) + if nzTools.ToolData[id] then + if ToolData.interface then ToolData.interface:Remove() end + ToolData.interface = nzTools.ToolData[id].interface(ToolData, nzTools.SavedData[id]) + + if tabs.Tools[curtool] then tabs.Tools[curtool]:SetBackgroundColor( Color(150, 150, 150) ) end + if tabs.Tools[id] then tabs.Tools[id]:SetBackgroundColor( Color(255, 255, 255) ) end + ToolInterface:SetTitle(nzTools.ToolData[id or "default"].displayname) + curtool = id + + if !IsValid(ToolData.interface) then + ToolData.interface = vgui.Create("DLabel", ToolData) + ToolData.interface:SetText("This tool does not have any properties.") + ToolData.interface:SetFont("Trebuchet18") + ToolData.interface:SetTextColor( Color(50, 50, 50) ) + ToolData.interface:SizeToContents() + ToolData.interface:Center() + return end + end + end + + local function RebuildToolList() + for k,v in pairs(tabs.Tools) do + v:Remove() + numtools = 0 + end + local tbl = {} + + -- Create a new cloned table that we can sort by weight + for k,v in pairs(nzTools.ToolData) do + if !nzTools.SavedData[k] then + nzTools.SavedData[k] = v.defaultdata + end + local num = table.insert(tbl, v) + tbl[num].id = k + end + table.SortByMember(tbl, "weight", true) + + for k,v in pairs(tbl) do + if v.condition(LocalPlayer():GetActiveWeapon(), LocalPlayer()) then + tabs.Tools[v.id] = vgui.Create("DPanel", ToolList) + tabs.Tools[v.id]:SetSize(145, 20) + tabs.Tools[v.id]:SetPos(0, 0 + numtools*22) + tabs.Tools[v.id]:SetZPos(30000) + if LocalPlayer():GetActiveWeapon().ToolMode and LocalPlayer():GetActiveWeapon().ToolMode == k then + tabs.Tools[v.id]:SetBackgroundColor( Color(255, 255, 255) ) + RebuildToolInterface(v.id) + else + tabs.Tools[v.id]:SetBackgroundColor( Color(150, 150, 150) ) + end + + local icon = vgui.Create("DImage", tabs.Tools[v.id]) + icon:SetImage(v.icon) + icon:SetPos(3,3) + icon:SizeToContents() + + local tooltext = vgui.Create("DLabel", tabs.Tools[v.id]) + tooltext:SetText(v.displayname) + tooltext:SetTextColor( Color(10, 10, 10) ) + tooltext:SetPos(24,3) + tooltext:SizeToContents() + + local toolbutton = vgui.Create("DButton", tabs.Tools[v.id]) + toolbutton:SetPos(0,0) + toolbutton:SetSize(145, 20) + toolbutton:SetText("") + toolbutton.Paint = function() end + toolbutton.DoClick = function() + local wep = LocalPlayer():GetActiveWeapon() + if wep and wep:GetClass() == "nz_multi_tool" then + LocalPlayer():GetActiveWeapon():SwitchTool(v.id) + RebuildToolInterface(v.id) + end + end + + numtools = numtools + 1 + end + end + end + RebuildToolList() + RebuildToolInterface(LocalPlayer():GetActiveWeapon().ToolMode or "default") + + ToolInterface.OnFocusChanged = function(self, bool) + if bool then + -- Keep the design here, the buttons are supposed to leak into the main frame + self:SetZPos(-10) + end + end + + local advanced = vgui.Create("DCheckBoxLabel", ToolInterface) + advanced:SetPos(200, 6) + advanced:SetText("Advanced Mode") + advanced:SetValue(nzTools.Advanced) + advanced:SizeToContents() + advanced.OnChange = function(self) + nzTools.Advanced = self:GetChecked() + RebuildToolList() + RebuildToolInterface(LocalPlayer():GetActiveWeapon().ToolMode or "default") + end + +end + +function nzQMenu:Open() + -- Check if we're in create mode + if nzRound:InState( ROUND_CREATE ) and LocalPlayer():IsInCreative() then + if !IsValid(nzQMenu.Data.MainFrame) then + if IsValid(LocalPlayer():GetActiveWeapon()) and LocalPlayer():GetActiveWeapon():GetClass() == "nz_multi_tool" then + nzQMenu:CreateToolsMenu() + else + nzQMenu:CreatePropsMenu() + end + end + + -- If the toolgun is equipped and the menu isn't the toolmenu or vice versa, recreate + if IsValid(LocalPlayer():GetActiveWeapon()) and LocalPlayer():GetActiveWeapon():GetClass() == "nz_multi_tool" and !nzQMenu.Data.MainFrame.ToolMode then + nzQMenu.Data.MainFrame:Remove() + nzQMenu:CreateToolsMenu() + elseif IsValid(LocalPlayer():GetActiveWeapon()) and LocalPlayer():GetActiveWeapon():GetClass() != "nz_multi_tool" and nzQMenu.Data.MainFrame.ToolMode then + nzQMenu.Data.MainFrame:Remove() + nzQMenu:CreatePropsMenu() + end + + nzQMenu.Data.MainFrame:SetVisible( true ) + end +end + +local textentryfocus = false + +function nzQMenu:Close() + + -- We don't want to close if we're currently typing + if textentryfocus then return end + + if !IsValid(nzQMenu.Data.MainFrame) then + if IsValid(LocalPlayer():GetActiveWeapon()) and LocalPlayer():GetActiveWeapon():GetClass() == "nz_multi_tool" then + nzQMenu:CreateToolsMenu() + else + nzQMenu:CreatePropsMenu() + end + end + + nzQMenu.Data.MainFrame:SetVisible( false ) + nzQMenu.Data.MainFrame:KillFocus() + nzQMenu.Data.MainFrame:SetKeyboardInputEnabled(false) + textentryfocus = false +end + +hook.Add( "OnSpawnMenuOpen", "OpenSpawnMenu", nzQMenu.Open ) +hook.Add( "OnSpawnMenuClose", "CloseSpawnMenu", nzQMenu.Close ) + +hook.Add( "OnTextEntryGetFocus", "StartTextFocus", function(panel) + textentryfocus = true + if IsValid(nzQMenu.Data.MainFrame) then + nzQMenu.Data.MainFrame:SetKeyboardInputEnabled(true) + end +end ) +hook.Add( "OnTextEntryLoseFocus", "EndTextFocus", function(panel) + textentryfocus = false + TextEntryLoseFocus() + if IsValid(nzQMenu.Data.MainFrame) then + nzQMenu.Data.MainFrame:KillFocus() + nzQMenu.Data.MainFrame:SetKeyboardInputEnabled(false) + end +end ) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/q_menu/cl_search_models.lua b/gamemodes/nzombies/gamemode/q_menu/cl_search_models.lua new file mode 100644 index 00000000..153fc883 --- /dev/null +++ b/gamemodes/nzombies/gamemode/q_menu/cl_search_models.lua @@ -0,0 +1,67 @@ + +-- A copy paste of the sandbox one, but only for models + +local HasCreated = HasCreated or false + +local function GetAllFiles( tab, folder, extension, path ) + + local files, folders = file.Find( folder .. "/*", path ) + + for k, v in pairs( files ) do + + if ( v:EndsWith( extension ) ) then + table.insert( tab, (folder .. v):lower() ) + end + + end + + for k, v in pairs( folders ) do + timer.Simple( k * 0.1, function() + GetAllFiles( tab, folder .. v .. "/", extension, path ) + end ) + end + + if ( folder == "models/" ) then + hook.Run( "SearchUpdate" ) + end + +end + + +local model_list = nil +-- +-- Model Search +-- +if !HasCreated then + search.AddProvider( function( str ) + + str = str:PatternSafe() + + if ( model_list == nil ) then + + model_list = {} + GetAllFiles( model_list, "models/", ".mdl", "GAME" ) + timer.Simple( 1, function() hook.Run( "SearchUpdate" ) end ) + + end + + local list = {} + + for k, v in pairs( model_list ) do + + if ( v:find( str ) ) then + + if ( IsUselessModel( v ) ) then continue end + + table.insert( list, v ) + + end + + if ( #list >= 128 ) then break end + + end + + return list + + end ) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/q_menu/sh_constructor.lua b/gamemodes/nzombies/gamemode/q_menu/sh_constructor.lua new file mode 100644 index 00000000..8fa688a3 --- /dev/null +++ b/gamemodes/nzombies/gamemode/q_menu/sh_constructor.lua @@ -0,0 +1,8 @@ +-- Main Tables +nzQMenu = nzQMenu or AddNZModule("QMenu") +nzQMenu.Data = nzQMenu.Data or {} + +nzQMenu.Data.SpawnedEntities = {} + +-- sh_populate +nzQMenu.Data.Entities = {} \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/q_menu/sh_net.lua b/gamemodes/nzombies/gamemode/q_menu/sh_net.lua new file mode 100644 index 00000000..32269573 --- /dev/null +++ b/gamemodes/nzombies/gamemode/q_menu/sh_net.lua @@ -0,0 +1,50 @@ +-- Client Server Syncing + +if CLIENT then + + -- Client to Server (Client) + function nzQMenu:Request( model, entity ) + local entity = entity or false + net.Start( "nzQMenu.Request" ) + net.WriteString( model ) + net.WriteBool( entity ) + net.SendToServer() + end + +end + +if SERVER then + + -- Client to Server (Server) + util.AddNetworkString( "nzQMenu.Request" ) + + local function HandleRequest( len, ply ) + local model = net.ReadString() + local entity = net.ReadBool() + if nzRound:InState( ROUND_CREATE ) then + print(ply:Nick() .. " requested prop " .. model) + if ply:IsInCreative() then + local tr = util.GetPlayerTrace( ply ) + tr.mask = bit.bor( CONTENTS_SOLID, CONTENTS_MOVEABLE, CONTENTS_MONSTER, CONTENTS_WINDOW, CONTENTS_DEBRIS, CONTENTS_GRATE, CONTENTS_AUX ) + local trace = util.TraceLine( tr ) + if entity then + nzMapping:SpawnEntity(trace.HitPos, Angle(0,0,0), model, ply) + else + if util.IsValidProp(model) then + nzMapping:PropBuy(trace.HitPos, Angle(0,0,0), model, nil, ply) + else + nzMapping:SpawnEffect(trace.HitPos, Angle(0,0,0), model, ply) + end + end + -- Since we're adding a prop, lets switch to the phys gun for convenience + ply:SelectWeapon( "weapon_physgun" ) + else + print("Denied request from " .. ply:Nick()) + end + end + end + + -- Receivers + net.Receive( "nzQMenu.Request", HandleRequest ) + +end diff --git a/gamemodes/nzombies/gamemode/q_menu/sh_populate.lua b/gamemodes/nzombies/gamemode/q_menu/sh_populate.lua new file mode 100644 index 00000000..64c5cfd1 --- /dev/null +++ b/gamemodes/nzombies/gamemode/q_menu/sh_populate.lua @@ -0,0 +1,16 @@ + +function nzQMenu.AddNewEntity( ent, icon, name ) + table.insert(nzQMenu.Data.Entities, {ent, icon, name}) +end + +-- QuickFunctions +PropMenuAddEntity = nzQMenu.AddNewEntity + +PropMenuAddEntity("edit_fog", "entities/edit_fog.png", "Base Fog Editor") +PropMenuAddEntity("edit_fog_special", "entities/edit_fog.png", "Special Round Fog Editor") +PropMenuAddEntity("edit_sky", "entities/edit_sky.png", "Sky Editor") +PropMenuAddEntity("edit_sun", "entities/edit_sun.png", "Sun Editor") +PropMenuAddEntity("edit_color", "gmod/demo.png", "Color Correction Editor") +PropMenuAddEntity("nz_fire_effect", "icon16/fire.png", "Fire Effect") +PropMenuAddEntity("edit_dynlight", "icon16/lightbulb.png", "Dynamic Light") +--PropMenuAddEntity("edit_damage", "icon16/lightbulb.png", "Damage") \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/ragdoll/sh_zombierags.lua b/gamemodes/nzombies/gamemode/ragdoll/sh_zombierags.lua new file mode 100644 index 00000000..9002727b --- /dev/null +++ b/gamemodes/nzombies/gamemode/ragdoll/sh_zombierags.lua @@ -0,0 +1,61 @@ + +local function cleanrag(ent, ragdoll, time) + local dTime = math.random( time*0.75, time*1.25 ) + + if ent.GetDecapitated and ent:GetDecapitated() then + local bone = ragdoll:LookupBone("ValveBiped.Bip01_Head1") + if !bone then bone = ragdoll:LookupBone("j_head") end + + if bone then + ragdoll:ManipulateBoneScale(bone, Vector(0.00001,0.00001,0.00001)) + --- Y GMOD YYYYYYYY I DONT UNDERSTAND + ragdoll:ManipulateBoneScale(bone, Vector(0.00001,0.00001,0.00001)) + end + end + + --[[ + timer.Simple( dTime, function() + if IsValid(ragdoll) then + ragdoll:PhysWake() + ragdoll:SetMoveType(MOVETYPE_NOCLIP) + ragdoll:SetCollisionGroup(COLLISION_GROUP_IN_VEHICLE) + -- ragdoll:Fire("EnableMotion") + PrintTable(debug.getmetatable(ragdoll)) + for i = 0, ragdoll:GetPhysicsObjectCount() - 1 do + + local phys = ragdoll:GetPhysicsObjectNum( i ) + phys:Wake() + phys:EnableCollisions(false) + phys:EnableGravity(false) + phys:SetVelocityInstantaneous( Vector( 0, 0, -15) ) + + -- apply another push after dealy + timer.Simple(2, function() if IsValid(phys) then phys:SetVelocityInstantaneous(Vector( 0, 0, -20)) end end) + end + ragdoll:SetVelocity(Vector( 0, 0, -15)) + end + end) + ]]-- + --SafeRemoveEntityDelayed( ragdoll, dTime + 2.5 ) + timer.Simple( dTime + 2.5, function() + if ragdoll ~= NULL then + SafeRemoveEntity( ragdoll ) + end + end) +end + +if CLIENT then + if not ConVarExists("nz_client_ragdolltime") then CreateConVar("nz_client_ragdolltime", 30, {FCVAR_ARCHIVE}, "How long clientside Zombie ragdolls will stay in the map.") end + + function GM:CreateClientsideRagdoll( ent, ragdoll ) + local convar = GetConVar("nz_client_ragdolltime"):GetInt() + cleanrag(ent, ragdoll, convar) + end +else -- Server ragdolls + if not ConVarExists("nz_server_ragdolltime") then CreateConVar("nz_server_ragdolltime", 30, {FCVAR_ARCHIVE}, "How long serverside Zombie ragdolls will stay in the map.") end + + function GM:CreateEntityRagdoll( ent, ragdoll ) + local convar = GetConVar("nz_server_ragdolltime"):GetInt() + cleanrag(ent, ragdoll, convar) + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/random_box/sh_constructor.lua b/gamemodes/nzombies/gamemode/random_box/sh_constructor.lua new file mode 100644 index 00000000..bb35be36 --- /dev/null +++ b/gamemodes/nzombies/gamemode/random_box/sh_constructor.lua @@ -0,0 +1 @@ +nzRandomBox = nzRandomBox or AddNZModule("RandomBox") diff --git a/gamemodes/nzombies/gamemode/random_box/sv_random_box.lua b/gamemodes/nzombies/gamemode/random_box/sv_random_box.lua new file mode 100644 index 00000000..fa653ec0 --- /dev/null +++ b/gamemodes/nzombies/gamemode/random_box/sv_random_box.lua @@ -0,0 +1,112 @@ +-- + +function nzRandomBox.Spawn(exclude, first) + --Get all spawns + local all = ents.FindByClass("random_box_spawns") + local possible = {} + for k,v in pairs(all) do + if (!IsValid(exclude) or exclude != v) and (!first or tobool(v.PossibleSpawn)) then + table.insert(possible, v) + end + end + -- No points with possible spawn set, we'll just use all then + if #possible <= 0 then possible = all end + + local rand = possible[ math.random( #possible ) ] + + if rand != nil and !IsValid(rand.Box) then + local box = ents.Create( "random_box" ) + local pos = rand:GetPos() + local ang = rand:GetAngles() + + box:SetPos( pos + ang:Up()*10 + ang:Right()*7 ) + box:SetAngles( ang ) + box:Spawn() + --box:PhysicsInit( SOLID_VPHYSICS ) + box.SpawnPoint = rand + rand.Box = box + + rand:SetBodygroup(1,1) + + local phys = box:GetPhysicsObject() + if phys:IsValid() then + phys:EnableMotion(false) + end + else + print("No random box spawns have been set.") + end +end + +function nzRandomBox.Remove() + --Get all spawns + local all = ents.FindByClass("random_box") + --Loop just incase + for k,v in pairs(all) do + v.SpawnPoint.Box = nil + v:Remove() + end +end + +function nzRandomBox.DecideWep(ply) + + local teddychance = math.random(1, 15) + if teddychance <= 1 and !nzPowerUps:IsPowerupActive("firesale") and table.Count(ents.FindByClass("random_box_spawns")) > 1 then + return hook.Call("OnPlayerBuyBox", nil, ply, "nz_box_teddy") or "nz_box_teddy" + end + + local guns = {} + local blacklist = table.Copy(nzConfig.WeaponBlackList) + + --Add all our current guns to the black list + if IsValid(ply) and ply:IsPlayer() then + local found + for k,v in pairs( ply:GetWeapons() ) do + if v.ClassName then + blacklist[v.ClassName] = true + if v.ClassName == "nz_touchedlast" then found = true end + end + end + if !found and ply.nz_InSteamGroup then guns["nz_touchedlast"] = 20 end + end + + --Add all guns with no model or wonder weapons that are out to the blacklist + for k,v in pairs( weapons.GetList() ) do + if !blacklist[v.ClassName] and !v.NZPreventBox then + if v.WorldModel == nil or nzWeps:IsWonderWeaponOut(v.ClassName) then + blacklist[v.ClassName] = true + end + end + end + + if GetConVar("nz_randombox_maplist"):GetBool() and nzMapping.Settings.rboxweps then + for k,v in pairs(nzMapping.Settings.rboxweps) do + if !blacklist[k] then + guns[k] = v + end + end + elseif GetConVar("nz_randombox_whitelist"):GetBool() then + -- Load only weapons that have a prefix from the whitelist + for k,v in pairs( weapons.GetList() ) do + if !blacklist[v.ClassName] and !v.NZPreventBox and !v.NZTotalBlacklist then + for k2,v2 in pairs(nzConfig.WeaponWhiteList) do + if string.sub(v.ClassName, 1, #v2) == v2 then + guns[v.ClassName] = 10 + break + end + end + end + end + else + -- No weapon list and not using whitelist only, add all guns + for k,v in pairs( weapons.GetList() ) do + if !blacklist[v.ClassName] and !v.NZPreventBox and !v.NZTotalBlacklist then + guns[v.ClassName] = 10 + end + end + end + + local gun = nzMisc.WeightedRandom( guns ) -- Randomly decide by weight + gun = hook.Call("OnPlayerBuyBox", nil, ply, gun) or gun + + return gun +end diff --git a/gamemodes/nzombies/gamemode/revive_system/cl_view.lua b/gamemodes/nzombies/gamemode/revive_system/cl_view.lua new file mode 100644 index 00000000..dad6f092 --- /dev/null +++ b/gamemodes/nzombies/gamemode/revive_system/cl_view.lua @@ -0,0 +1,291 @@ +-- Useful ToScreen replacement for better directional +function XYCompassToScreen(pos, boundary) + local boundary = boundary or 0 + local eyedir = EyeVector() + local w = ScrW() - boundary + local h = ScrH() - boundary + local dir = (pos - EyePos()):GetNormalized() + dir = Vector(dir.x, dir.y, 0) + eyedir = Vector(eyedir.x, eyedir.y, 0) + + eyedir:Rotate(Angle(0,-90,0)) + local newdirx = eyedir:Dot(dir) + --draw.SimpleText(newdirx, "nz.display.hud.small", ScrW()/2, ScrH() - 50, Color(255, 255, 255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + + return ScrW()/2 + (newdirx*w/2), math.Clamp(pos:ToScreen().y, boundary, h) +end + +local tab = { + [ "$pp_colour_addr" ] = 0, + [ "$pp_colour_addg" ] = 0, + [ "$pp_colour_addb" ] = 0, + [ "$pp_colour_brightness" ] = 0, + [ "$pp_colour_contrast" ] = 1, + [ "$pp_colour_colour" ] = 0, + [ "$pp_colour_mulr" ] = 0, + [ "$pp_colour_mulg" ] = 0, + [ "$pp_colour_mulb" ] = 0 +} +local fade = 1 + +local mat_revive = Material("materials/Revive.png", "unlitgeneric smooth") + +function nzRevive:ResetColorFade() + tab = { + [ "$pp_colour_addr" ] = 0, + [ "$pp_colour_addg" ] = 0, + [ "$pp_colour_addb" ] = 0, + [ "$pp_colour_brightness" ] = 0, + [ "$pp_colour_contrast" ] = 1, + [ "$pp_colour_colour" ] = 0, + [ "$pp_colour_mulr" ] = 0, + [ "$pp_colour_mulg" ] = 0, + [ "$pp_colour_mulb" ] = 0 + } + fade = 1 + + --print("Color reset!") +end + +local function CalcDownView(ply, pos, ang, fov, znear, zfar) + if nzRevive.Players[LocalPlayer():EntIndex()] then + local pos = pos + Vector(0,0,-15) + local ang = ang + Angle(0,0,20) + + return {origin = pos, angles = ang, fov = fov, znear = znear, zfar = zfar, drawviewer = false } + end +end + +local function CalcDownViewmodelView(wep, vm, oldpos, oldang, pos, ang) + if nzRevive.Players[LocalPlayer():EntIndex()] then + local oldpos = oldpos + Vector(0,0,-15) + local oldang = oldang + Angle(0,0,20) + if wep:IsCW2() or wep:IsFAS2() then oldpos = oldpos + oldang:Up() * -100 end + + return oldpos, oldang + end +end + +local function DrawColorModulation() + if nzRevive.Players[LocalPlayer():EntIndex()] then + local fadeadd = ((1/GetConVar("nz_downtime"):GetFloat()) * FrameTime()) * -1 -- Change 45 to the revival time + tab[ "$pp_colour_colour" ] = math.Approach(tab[ "$pp_colour_colour" ], 0, fadeadd) + tab[ "$pp_colour_addr" ] = math.Approach(tab[ "$pp_colour_addr" ], 0.5, fadeadd *-0.5) + tab[ "$pp_colour_mulr" ] = math.Approach(tab[ "$pp_colour_mulr" ], 1, -fadeadd) + tab[ "$pp_colour_mulg" ] = math.Approach(tab[ "$pp_colour_mulg" ], 0, fadeadd) + tab[ "$pp_colour_mulb" ] = math.Approach(tab[ "$pp_colour_mulb" ], 0, fadeadd) + + --print(fadeadd, tab[ "$pp_colour_colour" ], tab[ "$pp_colour_brightness" ]) + DrawColorModify(tab) + end +end + +function surface.DrawTexturedRectRotatedPoint( x, y, w, h, rot, x0, y0 ) + + local c = math.cos( math.rad( rot ) ) + local s = math.sin( math.rad( rot ) ) + + local newx = y0 * s - x0 * c + local newy = y0 * c + x0 * s + + surface.DrawTexturedRectRotated( x + newx, y + newy, w, h, rot ) + +end + +local function DrawDownedPlayers() + + for k,v in pairs(nzRevive.Players) do + local ply = Entity(k) + if IsValid(ply) then -- If they're outside PVS, don't draw the icon at all + if ply == LocalPlayer() then return end + local posxy = (ply:GetPos() + Vector(0,0,35)):ToScreen() + local dir = ((ply:GetPos() + Vector(0,0,35)) - EyeVector()*2):GetNormal():ToScreen() + --print(posxy["x"], posxy["y"], posxy["visible"]) + + if posxy.x - 35 < 60 or posxy.x - 35 > ScrW()-130 or posxy.y - 50 < 60 or posxy.y - 50 > ScrH()-110 then + posxy.x, posxy.y = XYCompassToScreen((ply:GetPos() + Vector(0,0,35)), 60) + end + + surface.SetMaterial(mat_revive) + if v.ReviveTime then + surface.SetDrawColor(255, 255, 255) + else + surface.SetDrawColor(255, 150 - (CurTime() - v.DownTime)*(150/GetConVar("nz_downtime"):GetFloat()), 0) + end + + --draw.SimpleText(v.ReviveTime and "REVIVING" or "DOWNED", font, posxy["x"], posxy["y"] + 10, v.ReviveTime and Color(255,255,255) or Color(200, 0, 0,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP) + --draw.SimpleText(k:Nick(), font2, posxy["x"], posxy["y"] - 20, v.ReviveTime and Color(255,255,255) or Color(200, 0, 0,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP) + + surface.DrawTexturedRect(posxy.x - 35, posxy.y - 50, 70, 50) + end + end +end + +local function DrawRevivalProgress() + local tr = util.QuickTrace(LocalPlayer():EyePos(), LocalPlayer():GetAimVector()*100, LocalPlayer()) + local dply = tr.Entity + local id = dply:EntIndex() + + local revtime = LocalPlayer():HasPerk("revive") and 2 or 4 + + if IsValid(dply) and nzRevive.Players[id] and nzRevive.Players[id].RevivePlayer == LocalPlayer() then + surface.SetDrawColor(0,0,0) + surface.DrawRect(ScrW()/2 - 150, ScrH() - 300, 300, 20) + + surface.SetDrawColor(255,255,255) + surface.DrawRect(ScrW()/2 - 145, ScrH() - 295, 290 * (CurTime()-nzRevive.Players[id].ReviveTime)/revtime, 10) + end +end + +local function DrawDownedNotify() + + if !LocalPlayer():GetNotDowned() then + local text = "YOU NEED HELP!" + local font = "nz.display.hud.main" + local rply = nzRevive.Players[LocalPlayer():EntIndex()].RevivePlayer + + if IsValid(rply) and rply:IsPlayer() then + text = rply:Nick().." is reviving you!" + end + draw.SimpleText(text, font, ScrW() / 2, ScrH() * 0.9, Color(200, 0, 0,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + end + +end + +function nzRevive:DownedHeadsUp(ply, text) + nzRevive.Notify[ply] = {time = CurTime(), text = text} + --PrintTable(nzRevive.Notify[ply]) +end + +function nzRevive:CustomNotify(text, time) + if !text or !isstring(text) then return end + if time then + table.insert(nzRevive.Notify, {time = CurTime() + time, text = text}) + else + table.insert(nzRevive.Notify, {time = CurTime() + 5, text = text}) + end + --PrintTable(nzRevive.Notify[ply]) +end + +local function DrawDownedHeadsUp() + local font = "nz.display.hud.small" + local h = 40 + local offset = 20 + local max = 2 + local c = 0 + --table.SortByMember(nz.nzRevive.Data.Notify, "time") + + for k,v in pairs(nzRevive.Notify) do + if type(k) == "Player" and IsValid(k) then + local fade = math.Clamp(CurTime() - v.time - 5, 0, 1) + local status = v.text or "needs to be revived!" + draw.SimpleText(k:Nick().." "..status, font, ScrW()/2, ScrH() - h - offset * c, Color(255, 255, 255,255-(255*fade)), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + if fade >= 1 then nzRevive.Notify[k] = nil end + c = c + 1 + else + local fade = math.Clamp(CurTime() - v.time, 0, 1) + local status = v.text + draw.SimpleText(status, font, ScrW()/2, ScrH() - h - offset * c, Color(255, 255, 255,255-(255*fade)), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + if fade >= 1 then nzRevive.Notify[k] = nil end + c = c + 1 + end + end +end + +CreateClientConVar("nz_bloodoverlay", 1, true, false) + +local blood_overlay = Material("materials/overlay_low_health.png", "unlitgeneric smooth") +local bloodpulse = true --if true, going up +local pulse = 0 +local function DrawDamagedOverlay() + if GetConVar("nz_bloodoverlay"):GetBool() and LocalPlayer():Alive() then + local fade = (math.Clamp(LocalPlayer():Health()/LocalPlayer():GetMaxHealth(), 0.3, 0.7)-0.3)/0.4 + local fade2 = 1 - math.Clamp(LocalPlayer():Health()/LocalPlayer():GetMaxHealth(), 0, 0.7)/0.7 + + surface.SetMaterial(blood_overlay) + surface.SetDrawColor(255,255,255,255-fade*255) + surface.DrawTexturedRect( -10, -10, ScrW()+20, ScrH()+20) + + if fade2 > 0 then + if bloodpulse then + pulse = math.Approach(pulse, 255, math.Clamp(pulse, 1, 50)*FrameTime()*100) + if pulse >= 255 then bloodpulse = false end + else + if pulse <= 0 then bloodpulse = true end + pulse = math.Approach(pulse, 0, -255*FrameTime()) + end + surface.SetDrawColor(255,255,255,pulse*fade2) + surface.DrawTexturedRect( -10, -10, ScrW()+20, ScrH()+20) + end + end +end + +local function DrawTombstoneNotify() + local font = "nz.display.hud.small" + + if LocalPlayer():GetDownedWithTombstone() then + local text = "Hold E to feed the zombies" + draw.SimpleText(text, font, ScrW()/2, ScrH() - 320, Color(255, 255, 255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + end +end + +local tombstonetime = nil +local senttombstonerequest = false + +local function DrawTombstoneProgress() + if LocalPlayer():GetDownedWithTombstone() then + + local killtime = 1 + + if LocalPlayer():KeyDown(IN_USE) then + if !tombstonetime then + tombstonetime = CurTime() + end + + local pct = math.Clamp((CurTime()-tombstonetime)/killtime, 0, 1) + + surface.SetDrawColor(0,0,0) + surface.DrawRect(ScrW()/2 - 150, ScrH() - 300, 300, 20) + + surface.SetDrawColor(255,255,255) + surface.DrawRect(ScrW()/2 - 145, ScrH() - 295, 290 * pct, 10) + if pct >= 1 and !senttombstonerequest then + net.Start("nz_TombstoneSuicide") + net.SendToServer() + senttombstonerequest = true + end + else + tombstonetime = nil + senttombstonerequest = false + end + end +end + +local whoswhoactive = false +net.Receive("nz_WhosWhoActive", function() + whoswhoactive = net.ReadBool() +end) +local whoswhomat = "models/shadertest/shader4" +local firemat = "models/onfire" + +local function DrawWhosWhoOverlay() + if whoswhoactive then + DrawMaterialOverlay(whoswhomat, 0.03) + end + --[[if LocalPlayer():IsOnFire() then + DrawMaterialOverlay("firemat", 1) + end]] +end + +-- Hooks +hook.Add("CalcView", "CalcDownedView", CalcDownView ) +hook.Add("CalcViewModelView", "CalcDownedViewmodelView", CalcDownViewmodelView ) +hook.Add("RenderScreenspaceEffects", "DrawColorModulation", DrawColorModulation) +hook.Add("HUDPaint", "DrawDamageOverlay", DrawDamagedOverlay) +hook.Add("HUDPaint", "DrawDownedPlayers", DrawDownedPlayers ) +hook.Add("HUDPaint", "DrawDownedNotify", DrawDownedNotify ) +hook.Add("HUDPaint", "DrawRevivalProgress", DrawRevivalProgress ) +hook.Add("HUDPaint", "DrawDownedPlayersNotify", DrawDownedHeadsUp ) +hook.Add("HUDPaint", "DrawTombstoneNotify", DrawTombstoneNotify ) +hook.Add("HUDPaint", "DrawTombstoneProgress", DrawTombstoneProgress ) +hook.Add("RenderScreenspaceEffects", "DrawWhosWhoOverlay", DrawWhosWhoOverlay ) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/revive_system/sh_animation.lua b/gamemodes/nzombies/gamemode/revive_system/sh_animation.lua new file mode 100644 index 00000000..413dba65 --- /dev/null +++ b/gamemodes/nzombies/gamemode/revive_system/sh_animation.lua @@ -0,0 +1,62 @@ + +local function HandlePlayerDowned(ply, vel) + if !ply:GetNotDowned() then + + ply.CalcIdeal = ACT_HL2MP_SWIM_REVOLVER + + local len = vel:Length2D() + if ( len <= 1 ) then + ply.CalcIdeal = ACT_HL2MP_SWIM_PISTOL + end + + return ply.CalcIdeal, ply.CalcSeqOverride + end +end +hook.Add("CalcMainActivity", "nzPlayerDownedAnims", HandlePlayerDowned) + +local function PlayerDownedParameters(ply, vel, seqspeed) + if !ply:GetNotDowned() then + local len = vel:Length2D() + local movement = 0 + + if ( len > 1 ) then + movement = ( len / seqspeed ) + elseif math.Round(ply:GetCycle(), 1) != 0.7 then + movement = 5 + end + + local rate = math.min( movement, 1 ) + + ply:SetPoseParameter("move_x", -1) + ply:SetPlaybackRate( movement ) + + if !ply.NZDownedAnim then + ply:SetHull(Vector(-16,-16,25), Vector(16,16,97)) + ply.NZDownedAnim = true + end + + --ply:SetNetworkOrigin(ply:GetPos() - Vector(0,0,20)) + -- + return true + elseif ply.NZDownedAnim then + --ply:SetPos(ply:GetPos() + Vector(0,0,25)) + ply:ResetHull() + ply.NZDownedAnim = false + end +end +hook.Add("UpdateAnimation", "nzPlayerDownedAnims", PlayerDownedParameters) + +if CLIENT then + local function RenderDownedPlayers(ply) + if !ply:GetNotDowned() then + ply:SetRenderOrigin(ply:GetPos() - Vector(0,0,50)) + local ang = ply:GetAngles() + ply:SetRenderAngles(Angle(-30,ang[2],ang[3])) + ply:InvalidateBoneCache() + + local wep = ply:GetActiveWeapon() + if IsValid(wep) then wep:InvalidateBoneCache() end + end + end + hook.Add("PrePlayerDraw", "nzPlayerDownedAnims", RenderDownedPlayers) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/revive_system/sh_constructor.lua b/gamemodes/nzombies/gamemode/revive_system/sh_constructor.lua new file mode 100644 index 00000000..70787b1e --- /dev/null +++ b/gamemodes/nzombies/gamemode/revive_system/sh_constructor.lua @@ -0,0 +1,9 @@ +-- Main Tables +nzRevive = nzRevive or AddNZModule("Revive") + +-- Variables +nzRevive.Players = {} + +if CLIENT then + nzRevive.Notify = {} +end diff --git a/gamemodes/nzombies/gamemode/revive_system/sh_meta.lua b/gamemodes/nzombies/gamemode/revive_system/sh_meta.lua new file mode 100644 index 00000000..ab1aada7 --- /dev/null +++ b/gamemodes/nzombies/gamemode/revive_system/sh_meta.lua @@ -0,0 +1,186 @@ +local playerMeta = FindMetaTable("Player") +if SERVER then + + function playerMeta:DownPlayer() + local id = self:EntIndex() + --self:AnimRestartGesture(GESTURE_SLOT_CUSTOM, ACT_HL2MP_SIT_PISTOL) + + nzRevive.Players[id] = {} + nzRevive.Players[id].DownTime = CurTime() + + -- downed players are not targeted + self:SetTargetPriority(TARGET_PRIORITY_NONE) + self:SetHealth(100) + + if self:HasPerk("whoswho") then + self.HasWhosWho = true + timer.Simple(5, function() + -- If you choose to use Tombstone within these seconds, you won't make a clone and will get Who's Who back from Tombstone + if IsValid(self) and !self:GetNotDowned() then + --print("Should've respawned by now") + nzRevive:CreateWhosWhoClone(self) + nzRevive:RespawnWithWhosWho(self) + end + end) + end + if self:HasPerk("tombstone") then + nzRevive.Players[id].tombstone = true + end + if #player.GetAllPlaying() <= 1 and self:HasPerk("revive") and (!self.SoloRevive or self.SoloRevive < 3) then + self.SoloRevive = self.SoloRevive and self.SoloRevive + 1 or 1 + self.DownedWithSoloRevive = true + self:StartRevive(self) + timer.Simple(8, function() + if IsValid(self) and !self:GetNotDowned() then + self:RevivePlayer(self) + end + end) + --print(self, "Downed with solo revive") + end + + self.OldPerks = self:GetPerks() + + self:RemovePerks() + + self.DownPoints = math.Round(self:GetPoints()*0.05, -1) + if self.DownPoints >= self:GetPoints() then + self:SetPoints(0) + else + self:TakePoints(self.DownPoints, true) + end + + hook.Call("PlayerDowned", nzRevive, self) + + -- Equip the first pistol found in inventory - unless a pistol is already equipped + local wep = self:GetActiveWeapon() + if IsValid(wep) and wep.GetHoldType and wep:GetHoldType() == "pistol" or wep:GetHoldType() == "duel" or wep.HoldType == "pistol" or wep.HoldType == "duel" then + return + end + for k,v in pairs(self:GetWeapons()) do + if v.GetHoldType and v:GetHoldType() == "pistol" or v:GetHoldType() == "duel" or v.HoldType == "pistol" or v.HoldType == "duel" then + self:SelectWeapon(v:GetClass()) + return + end + end + end + + function playerMeta:RevivePlayer(revivor, nosync) + local id = self:EntIndex() + if !nzRevive.Players[id] then return end + --self:AnimResetGestureSlot(GESTURE_SLOT_CUSTOM) + nzRevive.Players[id] = nil + if !nosync then + hook.Call("PlayerRevived", nzRevive, self, revivor) + end + self:SetTargetPriority(TARGET_PRIORITY_PLAYER) + self.HasWhosWho = nil + if IsValid(revivor) and revivor:IsPlayer() then + if self.DownPoints then + revivor:GivePoints(self.DownPoints) + end + revivor:StripWeapon("nz_revive_morphine") -- Remove the viewmodel again + end + self.DownPoints = nil + self.HasWhosWho = nil + self.DownedWithSoloRevive = nil + + self:SetPos(self:GetPos() + Vector(0,0,25)) + self:ResetHull() + end + + function playerMeta:StartRevive(revivor, nosync) + local id = self:EntIndex() + if !nzRevive.Players[id] then return end -- Not even downed + if nzRevive.Players[id].ReviveTime then return end -- Already being revived + + nzRevive.Players[id].ReviveTime = CurTime() + nzRevive.Players[id].RevivePlayer = revivor + revivor.Reviving = self + + print("Started revive", self, revivor) + + if revivor:GetNotDowned() then -- You can revive yourself while downed with Solo Quick Revive + revivor:Give("nz_revive_morphine") -- Give them the viewmodel + end + + if !nosync then hook.Call("PlayerBeingRevived", nzRevive, self, revivor) end + end + + function playerMeta:StopRevive(nosync) + local id = self:EntIndex() + if !nzRevive.Players[id] then return end -- Not even downed + + local revivor = nzRevive.Players[id].RevivePlayer + if IsValid(revivor) then + revivor:StripWeapon("nz_revive_morphine") -- Remove the revivors viewmodel + end + + nzRevive.Players[id].ReviveTime = nil + nzRevive.Players[id].RevivePlayer = nil + + print("Stopped revive", self) + + if !nosync then hook.Call("PlayerNoLongerBeingRevived", nzRevive, self) end + end + + function playerMeta:KillDownedPlayer(silent, nosync, nokill) + local id = self:EntIndex() + if !nzRevive.Players[id] then return end + + local revivor = nzRevive.Players[id].RevivePlayer + if IsValid(revivor) then -- This shouldn't happen as players can't die if they are currently being revived + revivor:StripWeapon("nz_revive_morphine") -- Remove the revivors if someone was reviving viewmodel + end + + nzRevive.Players[id] = nil + if !nokill then + if silent then + self:KillSilent() + else + self:Kill() + end + end + if !nosync then hook.Call("PlayerKilled", nzRevive, self) end + self.HasWhosWho = nil + self.DownPoints = nil + self.DownedWithSoloRevive = nil + for k,v in pairs(player.GetAllPlayingAndAlive()) do + v:TakePoints(math.Round(v:GetPoints()*0.1, -1), true) + end + + self:RemoveAllPowerUps() + + --self:SetPos(self:GetPos() + Vector(0,0,25)) + self:ResetHull() + end + +end + +function playerMeta:GetNotDowned() + local id = self:EntIndex() + if nzRevive.Players[id] then + return false + else + return true + end +end + +function playerMeta:GetDownedWithTombstone() + local id = self:EntIndex() + if nzRevive.Players[id] then + return nzRevive.Players[id].tombstone or false + else + return false + end +end + +function playerMeta:GetPlayerReviving() + return self.Reviving +end + +-- We overwrite the shoot pos function here so we can set it to the lower angle when downed +local oldshootpos = playerMeta.GetShootPos +function playerMeta:GetShootPos() + if self:GetNotDowned() then return oldshootpos(self) end + return oldshootpos(self) + Vector(0,0,-15) +end diff --git a/gamemodes/nzombies/gamemode/revive_system/sh_playerdeath.lua b/gamemodes/nzombies/gamemode/revive_system/sh_playerdeath.lua new file mode 100644 index 00000000..5e68853c --- /dev/null +++ b/gamemodes/nzombies/gamemode/revive_system/sh_playerdeath.lua @@ -0,0 +1,44 @@ + +function nzRevive.DoPlayerDeath(ply, dmg) + + if IsValid(ply) and ply:IsPlayer() then + if ply:Health() - dmg:GetDamage() <= 0 then + local allow = hook.Call("PlayerShouldTakeDamage", nil, ply, dmg:GetAttacker()) + --print(allow, "Allowed or not") + if allow != false then -- Only false should prevent it (not nil) + if ply:GetNotDowned() then + print(ply:Nick() .. " got downed!") + ply:DownPlayer() + --ply:SetMaxHealth(100) -- failsafe for Jugg not resetting + return true + else + ply:KillDownedPlayer() -- Kill them if they are already downed + end + end + elseif !ply:GetNotDowned() then + return true -- Downed players cannot take non-fatal damage + end + end + +end + +function nzRevive.PostPlayerDeath(ply) + -- Performs all the resetting functions without actually killing the player + if !ply:GetNotDowned() then ply:KillDownedPlayer(nil, false, true) end +end + +local function HandleKillCommand(ply) + if (ply:IsPlaying() and !ply:IsSpectating()) or ply:IsInCreative() then + if ply:GetNotDowned() then + ply:DownPlayer() + else + ply:KillDownedPlayer() + end + end + return false +end + +-- Hooks +hook.Add("EntityTakeDamage", "nzDownKilledPlayers", nzRevive.DoPlayerDeath) +hook.Add("PostPlayerDeath", "nzPlayerDeathRevivalReset", nzRevive.PostPlayerDeath) +hook.Add("CanPlayerSuicide", "nzSuicideDowning", HandleKillCommand) diff --git a/gamemodes/nzombies/gamemode/revive_system/sh_revival.lua b/gamemodes/nzombies/gamemode/revive_system/sh_revival.lua new file mode 100644 index 00000000..0131deaa --- /dev/null +++ b/gamemodes/nzombies/gamemode/revive_system/sh_revival.lua @@ -0,0 +1,205 @@ +-- +local revivefailtime = 0.2 + +if SERVER then + hook.Add("Think", "CheckDownedPlayersTime", function() + for k,v in pairs(nzRevive.Players) do + -- The time it takes for a downed player to die - Prevent dying if being revived + if CurTime() - v.DownTime >= GetConVar("nz_downtime"):GetFloat() and !v.ReviveTime then + local ent = Entity(k) + if ent.KillDownedPlayer then + ent:KillDownedPlayer() + else + -- If it's a non-player entity, do the same thing just to clean up the table + local revivor = v.RevivePlayer + if IsValid(revivor) then + revivor:StripWeapon("nz_revive_morphine") + end + nzRevive.Players[k] = nil + end + end + end + end) +end + +function nzRevive.HandleRevive(ply, ent) + --print(ply, ent) + + -- Make sure other downed players can't revive other downed players next to them + if !nzRevive.Players[ply:EntIndex()] then + + local tr = util.QuickTrace(ply:EyePos(), ply:GetAimVector()*100, ply) + local dply = tr.Entity + local ct = CurTime() + --print(dply) + + if IsValid(dply) and (dply:IsPlayer() or dply:GetClass() == "whoswho_downed_clone") then + local id = dply:EntIndex() + if nzRevive.Players[id] then + if !nzRevive.Players[id].RevivePlayer then + dply:StartRevive(ply) + end + + -- print(CurTime() - nzRevive.Players[id].ReviveTime) + + if ply:HasPerk("revive") and ct - nzRevive.Players[id].ReviveTime >= 2 -- With quick-revive + or ct - nzRevive.Players[id].ReviveTime >= 4 then -- 4 is the time it takes to revive + dply:RevivePlayer(ply) + ply.Reviving = nil + end + end + elseif ply.LastReviveTime ~= nil and IsValid(ply.Reviving) and ply.Reviving != dply -- Holding E on another player or no player + and ct > ply.LastReviveTime + revivefailtime then -- and for longer than fail time window + local id = ply.Reviving:EntIndex() + if nzRevive.Players[id] then + if nzRevive.Players[id].ReviveTime then + --ply:SetMoveType(MOVETYPE_WALK) + ply.Reviving:StopRevive() + ply.Reviving = nil + end + end + end + + -- When a player stops reviving + if !ply:KeyDown(IN_USE) then -- If you have an old revival target + if IsValid(ply.Reviving) and (ply.Reviving:IsPlayer() or ply.Reviving:GetClass() == "whoswho_downed_clone") then + local id = ply.Reviving:EntIndex() + if nzRevive.Players[id] then + if nzRevive.Players[id].ReviveTime then + --ply:SetMoveType(MOVETYPE_WALK) + ply.Reviving:StopRevive() + ply.Reviving = nil + --nz.nzRevive.Functions.SendSync() + end + end + end + end + + end +end + +-- Hooks +hook.Add("FindUseEntity", "CheckRevive", nzRevive.HandleRevive) + +if SERVER then + util.AddNetworkString("nz_TombstoneSuicide") + + net.Receive("nz_TombstoneSuicide", function(len, ply) + if ply:GetDownedWithTombstone() then + local tombstone = ents.Create("drop_tombstone") + tombstone:SetPos(ply:GetPos() + Vector(0,0,50)) + tombstone:Spawn() + local weps = {} + for k,v in pairs(ply:GetWeapons()) do + table.insert(weps, {class = v:GetClass(), pap = v:HasNZModifier("pap")}) + end + local perks = ply.OldPerks + + tombstone.OwnerData.weps = weps + tombstone.OwnerData.perks = perks + + ply:KillDownedPlayer() + tombstone:SetPerkOwner(ply) + end + end) +end + +if SERVER then + util.AddNetworkString("nz_WhosWhoActive") +end + +function nzRevive:CreateWhosWhoClone(ply, pos) + local pos = pos or ply:GetPos() + + local wep = IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():GetClass() != "nz_perk_bottle" and ply:GetActiveWeapon():GetClass() or ply.oldwep or nil + + local who = ents.Create("whoswho_downed_clone") + who:SetPos(pos + Vector(0,0,10)) + who:SetAngles(ply:GetAngles()) + who:Spawn() + who:GiveWeapon(wep) + who:SetPerkOwner(ply) + who:SetModel(ply:GetModel()) + who.OwnerData.perks = ply.OldPerks or ply:GetPerks() + local weps = {} + for k,v in pairs(ply:GetWeapons()) do + table.insert(weps, {class = v:GetClass(), pap = v:HasNZModifier("pap"), speed = v:HasNZModifier("speed"), dtap = v:HasNZModifier("dtap")}) + end + who.OwnerData.weps = weps + + timer.Simple(0.1, function() + if IsValid(who) then + local id = who:EntIndex() + self.Players[id] = {} + self.Players[id].DownTime = CurTime() + + hook.Call("PlayerDowned", nzRevive, who) + end + end) + + ply.WhosWhoClone = who + ply.WhosWhoMoney = 0 + + net.Start("nz_WhosWhoActive") + net.WriteBool(true) + net.Send(ply) +end + +function nzRevive:RespawnWithWhosWho(ply, pos) + local pos = pos or nil + + if !pos then + local spawns = {} + local plypos = ply:GetPos() + local maxdist = 1500^2 + local mindist = 500^2 + + local available = ents.FindByClass("nz_spawn_zombie_special") + if IsValid(available[1]) then + for k,v in pairs(available) do + local dist = plypos:DistToSqr(v:GetPos()) + if v.link == nil or nzDoors:IsLinkOpened( v.link ) then -- Only for rooms that are opened (using links) + if dist < maxdist and dist > mindist then -- Within the range we set above + if v:IsSuitable() then -- And nothing is blocking it + table.insert(spawns, v) + end + end + end + end + if !IsValid(spawns[1]) then + for k,v in pairs(available) do -- Retry, but without the range check (just use all of them) + local dist = plypos:DistToSqr(v:GetPos()) + if v.link == nil or nzDoors:IsLinkOpened( v.link ) then + if v:IsSuitable() then + table.insert(spawns, v) + end + end + end + end + if !IsValid(spawns[1]) then -- Still no open linked ones?! Spawn at a random player spawnpoint + local pspawns = ents.FindByClass("player_spawns") + if !IsValid(pspawns[1]) then + ply:Spawn() + else + pos = pspawns[math.random(#pspawns)]:GetPos() + end + else + pos = spawns[math.random(#spawns)]:GetPos() + end + else + -- There exists no special spawnpoints - Use regular player spawns + local pspawns = ents.FindByClass("player_spawns") + if !IsValid(pspawns[1]) then + ply:Spawn() + else + pos = pspawns[math.random(#pspawns)]:GetPos() + end + end + end + ply:RevivePlayer() + ply:StripWeapons() + player_manager.RunClass(ply, "Loadout") -- Rearm them + + if pos then ply:SetPos(pos) end + +end diff --git a/gamemodes/nzombies/gamemode/revive_system/sh_sync.lua b/gamemodes/nzombies/gamemode/revive_system/sh_sync.lua new file mode 100644 index 00000000..3c1f3082 --- /dev/null +++ b/gamemodes/nzombies/gamemode/revive_system/sh_sync.lua @@ -0,0 +1,153 @@ +-- Client Server Syncing + +if SERVER then + + util.AddNetworkString( "nzRevivePlayerFull" ) + util.AddNetworkString( "nzRevivePlayerDowned" ) + util.AddNetworkString( "nzRevivePlayerRevived" ) + util.AddNetworkString( "nzRevivePlayerBeingRevived" ) + util.AddNetworkString( "nzRevivePlayerKilled" ) + + + function nzRevive:SendPlayerFullData(ply, receiver) + local data = table.Copy(self.Players[ply:EntIndex()]) + + net.Start( "nzRevivePlayerFull" ) + net.WriteInt(ply:EntIndex(), 13) + net.WriteTable( data ) + return receiver and net.Send(receiver) or net.Broadcast() + end + + function nzRevive:SendPlayerDowned(ply, receiver, attdata) + print("Sent") + attdata = attdata or {} + net.Start( "nzRevivePlayerDowned" ) + net.WriteInt(ply:EntIndex(), 13) + net.WriteTable(attdata) + return receiver and net.Send(receiver) or net.Broadcast() + end + + function nzRevive:SendPlayerRevived(ply, receiver) + net.Start( "nzRevivePlayerRevived" ) + net.WriteInt(ply:EntIndex(), 13) + return receiver and net.Send(receiver) or net.Broadcast() + end + + function nzRevive:SendPlayerBeingRevived(ply, revivor, receiver) + net.Start( "nzRevivePlayerBeingRevived" ) + net.WriteInt(ply:EntIndex(), 13) + if IsValid(revivor) then + net.WriteBool(true) + net.WriteInt(revivor:EntIndex(), 13) + else -- No valid revivor means the player stopped being revived + net.WriteBool(false) + end + return receiver and net.Send(receiver) or net.Broadcast() + end + + function nzRevive:SendPlayerKilled(ply, receiver) + net.Start( "nzRevivePlayerKilled" ) + net.WriteInt(ply:EntIndex(), 13) + return receiver and net.Send(receiver) or net.Broadcast() + end + + FullSyncModules["Revive"] = function(ply) + for k,v in pairs(player.GetAll()) do + if !v:GetNotDowned() then -- Player needs to be downed + nzRevive:SendPlayerFullData(v, ply) + end + end + end +end + +if CLIENT then + + local function ReceivePlayerDowned() + print("Gotten") + local id = net.ReadInt(13) + local attached = net.ReadTable() + + nzRevive.Players[id] = nzRevive.Players[id] or {} + nzRevive.Players[id].DownTime = CurTime() + + for k,v in pairs(attached) do + print(k,v) + nzRevive.Players[id][k] = v + end + + local ply = Entity(id) + if IsValid(ply) and ply:IsPlayer() then + --ply:AnimRestartGesture(GESTURE_SLOT_CUSTOM, ACT_HL2MP_SWIM_PISTOL) + nzRevive:DownedHeadsUp(ply, "needs to be revived!") + end + end + + local function ReceivePlayerRevived() + local id = net.ReadInt(13) + nzRevive.Players[id] = nil + local ply = Entity(id) + if IsValid(ply) and ply:IsPlayer() then + --ply:AnimResetGestureSlot(GESTURE_SLOT_CUSTOM) + if ply == LocalPlayer() then nzRevive:ResetColorFade() end + nzRevive:DownedHeadsUp(ply, "has been revived!") + end + end + + local function ReceivePlayerBeingRevived() + local id = net.ReadInt(13) + local bool = net.ReadBool() + if bool then + local revivor = Entity(net.ReadInt(13)) + nzRevive.Players[id] = nzRevive.Players[id] or {} + if !nzRevive.Players[id].ReviveTime then + nzRevive.Players[id].ReviveTime = CurTime() + nzRevive.Players[id].RevivePlayer = revivor + revivor.Reviving = Entity(id) + end + else + local revivor = nzRevive.Players[id].RevivePlayer + if IsValid(revivor) then revivor.Reviving = nil end + + nzRevive.Players[id] = nzRevive.Players[id] or {} + nzRevive.Players[id].ReviveTime = nil + nzRevive.Players[id].RevivePlayer = nil + end + end + + local function ReceivePlayerKilled() + local id = net.ReadInt(13) + + local revivor = nzRevive.Players[id].RevivePlayer + if IsValid(revivor) then revivor.Reviving = nil end + + nzRevive.Players[id] = nil + local ply = Entity(id) + if IsValid(ply) and ply:IsPlayer() then + --ply:AnimResetGestureSlot(GESTURE_SLOT_CUSTOM) + if ply == LocalPlayer() then nzRevive:ResetColorFade() end + nzRevive:DownedHeadsUp(ply, "has died!") + end + end + + local function ReceiveFullPlayerSync() + local id = net.ReadInt(13) + local data = net.ReadTable() + nzRevive.Players[id] = data + + local ply = Entity(id) + local revivor = data.RevivePlayer + if IsValid(revivor) then revivor.Reviving = ply end + + if IsValid(ply) and ply:IsPlayer() then + --ply:AnimRestartGesture(GESTURE_SLOT_CUSTOM, ACT_HL2MP_SWIM_PISTOL) + nzRevive:DownedHeadsUp(ply, "has been downed!") + end + end + + -- Receivers + net.Receive( "nzRevivePlayerDowned", ReceivePlayerDowned ) + net.Receive( "nzRevivePlayerRevived", ReceivePlayerRevived ) + net.Receive( "nzRevivePlayerBeingRevived", ReceivePlayerBeingRevived ) + net.Receive( "nzRevivePlayerKilled", ReceivePlayerKilled ) + net.Receive( "nzRevivePlayerFull", ReceiveFullPlayerSync ) +end diff --git a/gamemodes/nzombies/gamemode/revive_system/sv_hooks.lua b/gamemodes/nzombies/gamemode/revive_system/sv_hooks.lua new file mode 100644 index 00000000..f57bc046 --- /dev/null +++ b/gamemodes/nzombies/gamemode/revive_system/sv_hooks.lua @@ -0,0 +1,31 @@ +local defaultdata = { + DownTime = true, + ReviveTime = true, + RevivePlayer = true, +} + +function nzRevive:PlayerDowned( ply ) + local attdata = {} + -- Attach whatever other data was attached to the table, other than the default ones + for k,v in pairs(nzRevive.Players[ply:EntIndex()]) do + if !defaultdata[k] then attdata[k] = v end + end + self:SendPlayerDowned( ply, nil, attdata ) +end + +function nzRevive:PlayerRevived( ply ) + self:SendPlayerRevived( ply ) +end + +function nzRevive:PlayerBeingRevived( ply, revivor ) + self:SendPlayerBeingRevived( ply, revivor ) +end + +function nzRevive:PlayerNoLongerBeingRevived( ply ) + self:SendPlayerBeingRevived( ply ) -- No second argument means no revivor +end + + +function nzRevive:PlayerKilled( ply ) + self:SendPlayerKilled( ply ) +end diff --git a/gamemodes/nzombies/gamemode/round/cl_fog.lua b/gamemodes/nzombies/gamemode/round/cl_fog.lua new file mode 100644 index 00000000..b9c2f450 --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/cl_fog.lua @@ -0,0 +1,126 @@ +local fade +local fadetime = 5 + +local fogstart = fogstart or 50 +local fogend = fogend or 1000 +local fogdensity = fogdensity or 0 +local fogcolor = fogcolor or Vector(0.4,0.7,0.8) + +local tfogstart = tfogstart or 50 +local tfogend = tfogend or 1000 +local tfogdensity = tfogdensity or 0 +local tfogcolor = tfogcolor or Vector(0.4,0.7,0.8) + +local ofogstart = fogstart +local ofogend = fogend +local ofogdensity = fogdensity +local ofogcolor = fogcolor + +local specialfog = false +local foginit = false + +function nzRound:EnableSpecialFog( bool ) + local ent = ents.FindByClass("edit_fog")[1] + local ent_special = ents.FindByClass("edit_fog_special")[1] + + hook.Remove("Think", "nzFogThink") + + if bool and (!specialfog or !foginit) then + if IsValid(ent_special) then + tfogstart = ent_special:GetFogStart() + tfogend = ent_special:GetFogEnd() + tfogdensity = ent_special:GetDensity() + tfogcolor = ent_special:GetFogColor() + else + tfogstart = 50 + tfogend = 1000 + tfogdensity = 0.9 + tfogcolor = Vector(0.4,0.7,0.8) + end + specialfog = true + elseif specialfog or !foginit then + if IsValid(ent) then + tfogstart = ent:GetFogStart() + tfogend = ent:GetFogEnd() + tfogdensity = ent:GetDensity() + tfogcolor = ent:GetFogColor() + else + tfogstart = 50 + tfogend = 1000 + tfogdensity = 0 + tfogcolor = Vector(0.4,0.7,0.8) + end + specialfog = false + end + -- Changed to always true because we now have defaults that apply if the entities don't exist + if true then --IsValid(ent) or IsValid(ent_special) then + fade = 0 + ofogstart = fogstart + ofogend = fogend + ofogdensity = fogdensity + ofogcolor = fogcolor + hook.Add("Think", "nzFogFade", nzFogFade) + hook.Add("SetupWorldFog", "nzWorldFog", nzSetupWorldFog) + hook.Add("SetupSkyboxFog", "nzSkyboxFog", nzSetupSkyFog) + foginit = true + else + hook.Remove("SetupWorldFog", "nzWorldFog") + hook.Remove("SetupSkyboxFog", "nzSkyboxFog") + foginit = false + end +end + +function nzFogFade() + fade = math.Approach(fade, 1, FrameTime()/fadetime) + fogstart = Lerp(fade, ofogstart, tfogstart) + fogend = Lerp(fade, ofogend, tfogend) + fogdensity = Lerp(fade, ofogdensity, tfogdensity) + fogcolor = LerpVector(fade, ofogcolor, tfogcolor) + + if fade >= 1 then + hook.Remove("Think", "nzFogFade") + hook.Add("Think", "nzFogThink", nzFogThink) + end +end + +function nzFogThink() + local ent + if specialfog then + ent = ents.FindByClass("edit_fog_special")[1] + else + ent = ents.FindByClass("edit_fog")[1] + end + --print(ent) + if IsValid(ent) then + fogstart = ent:GetFogStart() + fogend = ent:GetFogEnd() + fogdensity = ent:GetDensity() + fogcolor = ent:GetFogColor() + end +end + +function nzSetupWorldFog() + + render.FogMode( 1 ) + render.FogStart( fogstart ) + render.FogEnd( fogend ) + render.FogMaxDensity( fogdensity ) + + render.FogColor( fogcolor.x * 255, fogcolor.y * 255, fogcolor.z * 255 ) + + return true + +end + +function nzSetupSkyFog( skyboxscale ) + + render.FogMode( 1 ) + render.FogStart( fogstart * skyboxscale ) + render.FogEnd( fogend * skyboxscale ) + render.FogMaxDensity( fogdensity ) + + render.FogColor( fogcolor.x * 255, fogcolor.y * 255, fogcolor.z * 255 ) + + return true + +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/round/cl_round.lua b/gamemodes/nzombies/gamemode/round/cl_round.lua new file mode 100644 index 00000000..11571397 --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/cl_round.lua @@ -0,0 +1,42 @@ +function nzRound:GetEndTime() + return GetGlobalFloat( "gwEndTime", 0 ) +end + +local states = { + [ROUND_INIT] = "OnRoundInit", + [ROUND_PREP] = "OnRoundPreparation", + [ROUND_PROG] = "OnRoundStart", + [ROUND_GO] = "OnRoundEnd", + [ROUND_CREATE] = "OnRoundCreative", +} + +function nzRound:StateChange( old, new ) + if new == ROUND_WAITING then + nzRound:EnableSpecialFog( false ) + hook.Call( "OnRoundWating", nzRound ) + else + hook.Call( states[new], nzRound ) + end + hook.Call( "OnRoundChangeState", nzRound, new, old ) +end + +function nzRound:OnRoundPreperation() + if !self:IsSpecial() then + self:EnableSpecialFog(false) + end +end + +function nzRound:OnRoundStart() + if self:IsSpecial() then + self:EnableSpecialFog(true) + else + self:EnableSpecialFog(false) + end +end + +net.Receive("nz_hellhoundround", function() + if net.ReadBool() then + hook.Call( "OnSpecialRoundStart" ) + surface.PlaySound("nz/round/dog_start.wav") + end +end) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/round/cl_round_meta.lua b/gamemodes/nzombies/gamemode/round/cl_round_meta.lua new file mode 100644 index 00000000..8651c34e --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/cl_round_meta.lua @@ -0,0 +1,16 @@ +function nzRound:GetState() return self.State end +function nzRound:SetState( state ) self.State = state end + +function nzRound:GetNumber() return self.Number or 0 end +function nzRound:SetNumber( num ) self.Number = num end + +function nzRound:IsSpecial() return self.SpecialRound or false end +function nzRound:SetSpecial( bool ) self.SpecialRound = bool end + +function nzRound:InState( state ) + return nzRound:GetState() == state +end + +function nzRound:InProgress() + return nzRound:GetState() == ROUND_PREP or nzRound:GetState() == ROUND_PROG +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/round/sh_boss_round.lua b/gamemodes/nzombies/gamemode/round/sh_boss_round.lua new file mode 100644 index 00000000..40d13f75 --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/sh_boss_round.lua @@ -0,0 +1,174 @@ +if SERVER then + function nzRound:SetNextBossRound( num ) + local round = self:GetNumber() + if round == -1 then + local diff = num - round + if diff > 0 then -- If we're on infinity + self:SetNextBossRound(round) -- Mark this round again + self:PrepareBoss(diff * 10) -- Spawn the boss 10 zombies later for each round it was delayed with + end + else + self.NextBossRound = num + end + end + + function nzRound:GetNextBossRound() + return self.NextBossRound + end + + function nzRound:MarkedForBoss( num ) + return self.NextBossRound == num and self.BossType and self.BossData[self.BossType] and true -- Valid boss + end + + function nzRound:SetBossType(id) + if id == "None" then + self.BossType = nil -- "None" makes a nil key + else + self.BossType = id or "Panzer" -- A nil id defaults to "Panzer", otherwise id + end + end + + function nzRound:GetBossType(id) + return self.BossType + end + + function nzRound:GetBossData(id) + local bosstype = id or self.BossType + return bosstype and self.BossData[bosstype] or nil + end + + function nzRound:SpawnBoss(id) + local bosstype = id or self.BossType + if bosstype then + local data = nzRound:GetBossData(bosstype) + local spawnpoint = data.specialspawn and "nz_spawn_zombie_special" or "nz_spawn_zombie_normal" -- Check what spawnpoint type we're using + local spawnpoints = {} + for k,v in pairs(ents.FindByClass(spawnpoint)) do -- Find and add all valid spawnpoints that are opened and not blocked + if (v.link == nil or nzDoors:IsLinkOpened( v.link )) and v:IsSuitable() then + table.insert(spawnpoints, v) + end + end + + local spawn = spawnpoints[math.random(#spawnpoints)] -- Pick a random one + if IsValid(spawn) then -- If we this exists, spawn here + local boss = ents.Create(data.class) + boss:SetPos(spawn:GetPos()) + boss:Spawn() + boss.NZBossType = bosstype + data.spawnfunc(boss) -- Call this after in case it runs PrepareBoss to enable another boss this round + return boss + end + end + end + + -- This runs at the start of every round + hook.Add("OnRoundStart", "nzBossRoundHandler", function(round) + if !nzRound:GetNextBossRound() then return end + if round == -1 then -- Round infinity always spawn bosses + local diff = nzRound:GetNextBossRound() - round + if diff > 0 then + nzRound:SetNextBossRound(round) -- Mark this round again + nzRound:PrepareBoss(diff * 10) -- Spawn the boss 10 zombies later for each round it was delayed with + end + return + end + if nzRound:MarkedForBoss(round) then -- If this round is a boss round + if nzRound:IsSpecial() then nzRound:SetNextBossRound(round + 1) return end -- If special round, delay 1 more round and back out + + local spawntime = math.random(1, nzRound:GetZombiesMax() - 2) -- Set a random time to spawn + nzRound:PrepareBoss( spawntime ) + end + end) + + -- This function spawns a boss in after this many zombies has spawned + -- If called multiple times, the latter will overwrite the prior (because of hook names) + function nzRound:PrepareBoss( spawntime ) + local spawncount = 0 + hook.Add("OnZombieSpawned", "nzBossSpawnHandler", function() -- Add a hook for each zombie spawned + if !nzRound:MarkedForBoss(nzRound:GetNumber()) then + hook.Remove("OnZombieSpawned", "nzBossSpawnHandler") -- Cancel if we're no longer on a boss round! + return end + + spawncount = spawncount + 1 -- Add 1 more zombie spawned since we started tracking + + --print("BOSS: "..spawncount.."/"..spawntime) + + if spawncount >= spawntime then -- If we've spawned the amount of zombies that we randomly set + local data = nzRound:GetBossData() -- Check if we got boss data + if !data then hook.Remove("OnZombieSpawned", "nzBossSpawnHandler") return end -- If not, remove and cancel + + local boss = nzRound:SpawnBoss() + if IsValid(boss) then + hook.Remove("OnZombieSpawned", "nzBossSpawnHandler") -- Only remove the hook when we spawned the boss + end + -- If there is no valid spawnpoint to spawn at, it will try again next zombie that spawns + -- until we get out of the boss round, then it gives up + end + end) + end + + hook.Add( "OnGameBegin", "nzBossInit", function() + nzRound:SetBossType(nzMapping.Settings.bosstype) + local data = nzRound:GetBossData() + if data then + data.initfunc() + end + end) + + hook.Add( "OnBossKilled", "nzInfinityBossReengange", function() + local round = nzRound:GetNumber() + if round == -1 then + local diff = nzRound:GetNextBossRound() - round + print("Diff here is", diff, diff > 0) + if diff > 0 then -- If a new round for the boss has been set after the first one died + nzRound:SetNextBossRound(round) -- Mark this round again + nzRound:PrepareBoss(diff * 10) -- Spawn the boss 10 zombies later for each round it was delayed with + end + end + end) + +end + +nzRound.BossData = nzRound.BossData or {} +function nzRound:AddBossType(id, class, funcs) + if SERVER then + if class then + local data = {} + -- Which entity to spawn + data.class = class + -- Whether to spawn at special spawnpoints + data.specialspawn = funcs.specialspawn + -- Runs on game begin with this boss set, use to set first boss round + data.initfunc = funcs.initfunc + -- Run when the boss spawns, arguments are (boss) + data.spawnfunc = funcs.spawnfunc + -- Run when the boss dies, arguments are (boss, attacker, dmginfo, hitgroup) + data.deathfunc = funcs.deathfunc + -- Whenever the boss is damaged, arguments are (boss, attacker, dmginfo, hitgroup) Called before damage applied (can scale dmginfo) + data.onhit = funcs.onhit + -- All functions are optional, but death/spawn func is needed to set next boss round! (Unless you got another way) + nzRound.BossData[id] = data + else + nzRound.BossData[id] = nil -- Remove it if no valid class was added + end + else + -- Clients only need it for the dropdown, no need to actually know the data and such + nzRound.BossData[id] = class + end +end + +nzRound:AddBossType("Panzer", "nz_zombie_boss_panzer", { + specialspawn = true, + initfunc = function() + nzRound:SetNextBossRound(math.random(6,8)) -- Randomly spawn in rounds 6-8 + end, + spawnfunc = function(panzer) + panzer:SetHealth(nzRound:GetNumber() * 75 + 500) + end, + deathfunc = function(panzer, killer, dmginfo, hitgroup) + nzRound:SetNextBossRound(nzRound:GetNumber() + math.random(3,5)) -- Delay further boss spawning by 3-5 rounds after its death + if IsValid(attacker) and attacker:IsPlayer() and attacker:GetNotDowned() then + attacker:GivePoints(500) -- Give killer 500 points if not downed + end + end, +}) -- No onhit function, we don't give points on hit for this guy \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/round/sh_constructor.lua b/gamemodes/nzombies/gamemode/round/sh_constructor.lua new file mode 100644 index 00000000..e90c96b9 --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/sh_constructor.lua @@ -0,0 +1,2 @@ +-- Setup round module +nzRound = nzRound or AddNZModule("Round") diff --git a/gamemodes/nzombies/gamemode/round/sh_player.lua b/gamemodes/nzombies/gamemode/round/sh_player.lua new file mode 100644 index 00000000..b2cef09f --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/sh_player.lua @@ -0,0 +1,69 @@ +local plyMeta = FindMetaTable( "Player" ) + +AccessorFunc( plyMeta, "bReady", "Ready", FORCE_BOOL ) +function plyMeta:IsReady() return self:GetReady() end + +AccessorFunc( plyMeta, "bPlaying", "Playing", FORCE_BOOL ) +function plyMeta:IsPlaying() return self:GetPlaying() end + +function plyMeta:IsSpectating() return self:Team() == TEAM_SPECTATOR end + +function plyMeta:IsInCreative() return player_manager.GetPlayerClass( self ) == "player_create" end + +local player = player + +--player.utils +function player.GetAllReady() + local result = {} + for _, ply in pairs( player.GetAll() ) do + if ply:IsReady() then + table.insert( result, ply ) + end + end + + return result +end + +function player.GetAllPlaying() + local result = {} + for _, ply in pairs( player.GetAll() ) do + if ply:IsPlaying() then + table.insert( result, ply ) + end + end + + return result +end + +function player.GetAllPlayingAndAlive() + local result = {} + for _, ply in pairs( player.GetAllPlaying() ) do + if ply:Alive() and (ply:GetNotDowned() or ply.HasWhosWho or ply.DownedWithSoloRevive) then -- Who's Who will respawn the player, don't end yet + table.insert( result, ply ) + end + end + + return result +end + +function player.GetAllNonSpecs() + local result = {} + for _, ply in pairs( player.GetAll() ) do + if ply:Team() != TEAM_SPECTATOR then + table.insert( result, ply ) + end + end + + return result +end + +function player.GetAllTargetable() + local result = {} + for _, ply in pairs(player.GetAll()) do + if ply:GetTargetPriority() > 0 then + table.insert( result, ply ) + end + end + + return result +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/round/sh_special_round.lua b/gamemodes/nzombies/gamemode/round/sh_special_round.lua new file mode 100644 index 00000000..7cb4fa42 --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/sh_special_round.lua @@ -0,0 +1,78 @@ +if SERVER then + function nzRound:SetNextSpecialRound( num ) + self.NextSpecialRound = num + end + + function nzRound:GetNextSpecialRound() + return self.NextSpecialRound + end + + function nzRound:MarkedForSpecial( num ) + return ((self.NextSpecialRound == num and self.SpecialRoundType and self.SpecialData[self.SpecialRoundType] and true) or (nzConfig.RoundData[ num ] and nzConfig.RoundData[ num ].special)) or false + end + + function nzRound:SetSpecialRoundType(id) + if id == "None" then + self.SpecialRoundType = nil -- "None" makes a nil key + else + self.SpecialRoundType = id or "Hellhounds" -- A nil id defaults to "Hellhounds", otherwise id + end + end + + function nzRound:GetSpecialRoundType(id) + return self.SpecialRoundType + end + + function nzRound:GetSpecialRoundData() + if !self.SpecialRoundType then return nil end + return self.SpecialData[self.SpecialRoundType] + end + + util.AddNetworkString("nz_hellhoundround") + function nzRound:CallHellhoundRound() + net.Start("nz_hellhoundround") + net.WriteBool(true) + net.Broadcast() + end +end + +nzRound.SpecialData = nzRound.SpecialData or {} +function nzRound:AddSpecialRoundType(id, data, spawnfunc, roundfunc, endfunc) + if SERVER then + nzRound.SpecialData[id] = {} + -- Zombie data, like those in the configuration files + nzRound.SpecialData[id].data = data + -- Optional spawn function, runs when a zombie spawns (can be used to set health, speed, etc) + if spawnfunc then nzRound.SpecialData[id].spawnfunc = spawnfunc end + -- Optional round function, runs when the round starts (can be used to set amount, sounds, fog, etc) + if roundfunc then nzRound.SpecialData[id].roundfunc = roundfunc end + -- Optional end function, runs when the special round ends (can be used to clean up changes) + if endfunc then nzRound.SpecialData[id].endfunc = endfunc end + else + -- Clients only need it for the dropdown, no need to actually know the data and such + nzRound.SpecialData[id] = (data and true or nil) + end +end + +nzRound:AddSpecialRoundType("Hellhounds", { + specialTypes = { + ["nz_zombie_special_dog"] = {chance = 100} + }, + specialDelayMod = function() return math.Clamp(2 - #player.GetAllPlaying()*0.5, 0.5, 2) end, -- Dynamically change spawn speed depending on player count + specialCountMod = function() return nzRound:GetNumber() * #player.GetAllPlaying() end, -- Modify the count +}, function(dog) -- We want to modify health + local round = nzRound:GetNumber() + if round == -1 then + dog:SetHealth(math.random(120, 1200)) + else + dog:SetHealth(math.Clamp(round * 20, 120, 1200)) + end +end) -- No round func or end func + +nzRound:AddSpecialRoundType("Burning Zombies", { + normalTypes = { + ["nz_zombie_special_burning"] = {chance = 100} + }, + normalDelay = 0.75, + normalCountMod = function(original) return original * 0.5 end, -- Half the normal count here +}) -- No special functions or anything really \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/round/sh_sync.lua b/gamemodes/nzombies/gamemode/round/sh_sync.lua new file mode 100644 index 00000000..49d54962 --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/sh_sync.lua @@ -0,0 +1,106 @@ +if SERVER then + util.AddNetworkString( "nzRoundNumber" ) + util.AddNetworkString( "nzRoundState" ) + util.AddNetworkString( "nzRoundSpecial" ) + util.AddNetworkString( "nzPlayerReadyState" ) + util.AddNetworkString( "nzPlayerPlayingState" ) + + function nzRound:SendNumber( number, ply ) + net.Start( "nzRoundNumber" ) + net.WriteInt( number or 0, 16 ) + return ply and net.Send( ply ) or net.Broadcast() + + end + + function nzRound:SendState( state, ply ) + net.Start( "nzRoundState" ) + net.WriteUInt( state or ROUND_WAITING, 3 ) + return ply and net.Send( ply ) or net.Broadcast() + + end + + function nzRound:SendSpecialRound( bool, ply ) + net.Start( "nzRoundSpecial" ) + net.WriteBool( bool or false ) + return ply and net.Send( ply ) or net.Broadcast() + + end + + function nzRound:SendReadyState( ply, state, recieverPly ) + net.Start( "nzPlayerReadyState" ) + net.WriteUInt(ply:EntIndex(), 511) + net.WriteBool( state ) + return recieverPly and net.Send( recieverPly ) or net.Broadcast() + + end + + function nzRound:SendPlayingState( ply, state, recieverPly ) + net.Start( "nzPlayerPlayingState" ) + net.WriteUInt(ply:EntIndex(), 511) + net.WriteBool( state ) + return recieverPly and net.Send( recieverPly ) or net.Broadcast() + + end + + function nzRound:SendSync(ply) + self:SendNumber( self:GetNumber(), ply ) + self:SendSpecialRound( self:IsSpecial(), ply) + self:SendState(self:GetState(), ply) + + for _, v in pairs(player.GetAll()) do + self:SendReadyState(v, v:GetReady(), ply) + self:SendPlayingState(v, v:GetPlaying(), ply) + end + + self:SetEndTime( self:GetEndTime() ) + + end + + FullSyncModules["Round"] = function(ply) + nzRound:SendSync(ply) + end +end + +if CLIENT then + local function receiveRoundState() + local old = nzRound:GetState() + new = net.ReadUInt( 3 ) + + nzRound:SetState( new ) + + if old != new then + nzRound:StateChange( old, new ) + end + end + net.Receive( "nzRoundState", receiveRoundState ) + + + local function receiveRoundNumber() + nzRound:SetNumber( net.ReadInt( 16 ) ) + end + net.Receive( "nzRoundNumber", receiveRoundNumber) + + local function receiveSpecialRound() + nzRound:SetSpecial( net.ReadBool() ) + end + net.Receive( "nzRoundSpecial", receiveSpecialRound ) + + + local function receivePlayerReadyState() + local ply = ents.GetByIndex(net.ReadUInt(511)) + local state = net.ReadBool() + if IsValid(ply) then + ply:SetReady( state ) + end + end + net.Receive( "nzPlayerReadyState", receivePlayerReadyState ) + + local function receivePlayerPlayingState() + local ply = ents.GetByIndex(net.ReadUInt(511)) + local state = net.ReadBool() + if IsValid(ply) then + ply:SetPlaying( state ) + end + end + net.Receive( "nzPlayerPlayingState", receivePlayerPlayingState ) +end diff --git a/gamemodes/nzombies/gamemode/round/sv_hooks.lua b/gamemodes/nzombies/gamemode/round/sv_hooks.lua new file mode 100644 index 00000000..70b7e6a3 --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/sv_hooks.lua @@ -0,0 +1,30 @@ +function nzRound:OnPlayerReady( ply ) + + self:SendReadyState( ply, true ) + + --Start Round if we have enough players + if self:InState( ROUND_WAITING ) and #player.GetAllReady() > #player.GetAllNonSpecs() / 3 then + self:Init() + end + +end + +function nzRound:OnPlayerUnReady( ply ) + + self:SendReadyState( ply, false ) + +end + +function nzRound:OnPlayerDropIn( ply ) + + self:SendPlayingState( ply, true ) + self:SendReadyState( ply, true ) + +end + +function nzRound:OnPlayerDropOut( ply ) + + self:SendPlayingState( ply, false ) + self:SendReadyState( ply, false ) + +end diff --git a/gamemodes/nzombies/gamemode/round/sv_player.lua b/gamemodes/nzombies/gamemode/round/sv_player.lua new file mode 100644 index 00000000..3f7be39b --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/sv_player.lua @@ -0,0 +1,141 @@ +local plyMeta = FindMetaTable( "Player" ) + +function plyMeta:ReadyUp() + + if !navmesh.IsLoaded() then + PrintMessage( HUD_PRINTTALK, "Can't ready you up, because the map has not Navmesh loaded. Use the settings menu to generate a rough Navmesh or use tools in sandbox to make a proper one.") + return false + end + + if nzMapping:CheckSpawns() == false then + PrintMessage( HUD_PRINTTALK, "Can't ready you up, because no Zombie/Player spawns have been set.") + return false + end + + --Check if we have enough player spawns + if nzMapping:CheckEnoughPlayerSpawns() == false then + PrintMessage( HUD_PRINTTALK, "Can't ready you up, because not enough player spawns have been set. We need " .. #player.GetAll() .. " but only have " .. #ents.FindByClass("player_spawns") .. "." ) + return false + end + + if nzRound:InState( ROUND_WAITING ) or nzRound:InState( ROUND_INIT ) then + if !self:IsReady() then + PrintMessage( HUD_PRINTTALK, self:Nick() .. " is ready!" ) + self:SetReady( true ) + self:SetTeam(TEAM_PLAYERS) + hook.Call( "OnPlayerReady", nzRound, self ) + else + self:PrintMessage( HUD_PRINTTALK, "You are already ready!" ) + end + elseif nzRound:InProgress() then + if self:IsPlaying() then + self:PrintMessage( HUD_PRINTTALK, "You are already playing!" ) + else + self:PrintMessage( HUD_PRINTTALK, "Round in progress you will be dropped into next round if possible." ) + self:DropIn() + end + end + + return true + +end + +function plyMeta:UnReady() + if nzRound:InState( ROUND_WAITING ) then + if self:IsReady() then + PrintMessage( HUD_PRINTTALK, self:Nick() .. " is no longer ready!" ) + self:SetReady( false ) + hook.Call( "OnPlayerUnReady", nzRound, self ) + end + end + if nzRound:InProgress() then + self:DropOut() + end +end + +function plyMeta:DropIn() + if GetConVar("nz_round_dropins_allow"):GetBool() and !self:IsPlaying() then + self:SetReady( true ) + self:SetPlaying( true ) + self:SetTeam( TEAM_PLAYERS ) + self:RevivePlayer() + hook.Call( "OnPlayerDropIn", nzRound, self ) + if nzRound:GetNumber() == 1 and nzRound:InState(ROUND_PREP) then + PrintMessage( HUD_PRINTTALK, self:Nick() .. " is dropping in!" ) + self:ReSpawn() + else + PrintMessage( HUD_PRINTTALK, self:Nick() .. " will be dropping in next round!" ) + end + else + self:PrintMessage( HUD_PRINTTALK, "You are already in queue or dropins are not allowed on this Server." ) + end +end + +function plyMeta:DropOut() + if self:IsPlaying() then + PrintMessage( HUD_PRINTTALK, self:Nick().." has dropped out of the game!" ) + self:SetReady( false ) + self:SetPlaying( false ) + self:RevivePlayer() + self:KillSilent() + self:SetTargetPriority(TARGET_PRIORITY_NONE) + hook.Call( "OnPlayerDropOut", nzRound, self ) + end +end + +function plyMeta:ReSpawn() + + --Setup a player + player_manager.SetPlayerClass( self, "player_ingame" ) + if !self:Alive() then + self:Spawn() + self:SetTeam( TEAM_PLAYERS ) + end + +end + +function plyMeta:GiveCreativeMode() + + player_manager.SetPlayerClass( self, "player_create" ) + if !self:Alive() then + self:Spawn() + end + +end + +function plyMeta:RemoveCreativeMode() + + player_manager.SetPlayerClass( self, "player_ingame" ) -- Defaults to ingame + self:SetSpectator() + +end + +function plyMeta:ToggleCreativeMode() + if self:IsInCreative() then + self:RemoveCreativeMode() + + if nzRound:InState(ROUND_CREATE) then + local creative = false + for k,v in pairs(player.GetAll()) do + if v:IsInCreative() then + creative = true + break + end + end + + -- If there are no other players left in creative, return to survival + if !creative then + nzRound:Create(false) + end + end + else + if !nzRound:InState(ROUND_CREATE) then + nzRound:Create(true) + end + if nzRound:InState(ROUND_CREATE) then -- Only if we already are or we successfully switched to it + self:GiveCreativeMode() + else + self:ChatPrint("Can't go in Creative right now.") + end + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/round/sv_round.lua b/gamemodes/nzombies/gamemode/round/sv_round.lua new file mode 100644 index 00000000..6a2d026d --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/sv_round.lua @@ -0,0 +1,624 @@ +function GM:InitPostEntity() + + nzRound:Waiting() + +end + +function nzRound:Waiting() + + self:SetState( ROUND_WAITING ) + hook.Call( "OnRoundWaiting", nzRound ) + +end + +function nzRound:Init() + + timer.Simple( 5, function() self:SetupGame() self:Prepare() end ) + self:SetState( ROUND_INIT ) + self:SetEndTime( CurTime() + 5 ) + PrintMessage( HUD_PRINTTALK, "5 seconds till start time." ) + hook.Call( "OnRoundInit", nzRound ) + +end + +function nzRound:Prepare( time ) + + if self:IsSpecial() then -- From previous round + local data = self:GetSpecialRoundData() + if data and data.endfunc then data.endfunc() end + end + + -- Update special round type every round, before special state is set + local roundtype = nzMapping.Settings.specialroundtype + self:SetSpecialRoundType(roundtype) + + -- Set special for the upcoming round during prep, that way clients have time to fade the fog in + self:SetSpecial( self:MarkedForSpecial( self:GetNumber() + 1 ) ) + self:SetState( ROUND_PREP ) + self:IncrementNumber() + + self:SetZombieHealth( nzCurves.GenerateHealthCurve(self:GetNumber()) ) + self:SetZombiesMax( nzCurves.GenerateMaxZombies(self:GetNumber()) ) + + self:SetZombieSpeeds( nzCurves.GenerateSpeedTable(self:GetNumber()) ) + + self:SetZombiesKilled( 0 ) + + --Notify + --PrintMessage( HUD_PRINTTALK, "ROUND: " .. self:GetNumber() .. " preparing" ) + hook.Call( "OnRoundPreparation", nzRound, self:GetNumber() ) + --Play the sound + + --Spawn all players + --Check config for dropins + --For now, only allow the players who started the game to spawn + for _, ply in pairs( player.GetAllPlaying() ) do + ply:ReSpawn() + end + + -- Setup the spawners after all players have been spawned + + -- Reset and remove the old spawners + if self:GetSpecialSpawner() then + self:GetSpecialSpawner():Remove() + self:SetSpecialSpawner(nil) + end + + if self:GetNormalSpawner() then + self:GetNormalSpawner():Remove() + self:SetNormalSpawner(nil) + end + + -- Prioritize any configs (useful for mapscripts) + if nzConfig.RoundData[ self:GetNumber() ] or (self:IsSpecial() and self:GetSpecialRoundData()) then + local roundData = self:IsSpecial() and self:GetSpecialRoundData().data or nzConfig.RoundData[ self:GetNumber() ] + + --normal spawner + local normalCount = 0 + + -- only setup a spawner if we have zombie data + if roundData.normalTypes then + if roundData.normalCountMod then + local mod = roundData.normalCountMod + normalCount = mod(self:GetZombiesMax()) + elseif roundData.normalCount then + normalCount = roundData.normalCount + else + normalCount = self:GetZombiesMax() + end + + local normalDelay + if roundData.normalDelayMod then + local mod = roundData.normalDelayMod + normalDelay = mod(self:GetZombiesMax()) + elseif roundData.normalDelay then + normalDelay = roundData.normalDelay + else + normalDelay = 0.25 + end + + local normalData = roundData.normalTypes + local normalSpawner = Spawner("nz_spawn_zombie_normal", normalData, normalCount, normalDelay or 0.25) + + -- save the spawner to access data + self:SetNormalSpawner(normalSpawner) + end + + -- special spawner + local specialCount = 0 + + -- only setup a spawner if we have zombie data + if roundData.specialTypes then + if roundData.specialCountMod then + local mod = roundData.specialCountMod + specialCount = mod(self:GetZombiesMax()) + elseif roundData.specialCount then + specialCount = roundData.specialCount + else + specialCount = self:GetZombiesMax() + end + + local specialDelay + if roundData.specialDelayMod then + local mod = roundData.specialDelayMod + specialDelay = mod(self:GetZombiesMax()) + elseif roundData.specialDelay then + specialDelay = roundData.specialDelay + else + specialDelay = 0.5 + end + + local specialData = roundData.specialTypes + local specialSpawner = Spawner("nz_spawn_zombie_special", specialData, specialCount, specialDelay or 0.25) + + -- save the spawner to access data + self:SetSpecialSpawner(specialSpawner) + end + + -- update the zombiesmax (for win detection) + self:SetZombiesMax(normalCount + specialCount) + + -- Woah ... spooky round O_o + elseif self:GetNumber() == -1 then + + local normalrounddata = {["nz_zombie_walker"] = {chance = 100}} + local specialrounddata = {} + + for k,v in pairs(nzRound.SpecialData) do + if v.data then + if v.data.normalTypes then + for k3,v3 in pairs(v.data.normalTypes) do + local chance = v3.chance + normalrounddata[k3] = {["chance"] = chance/10} + end + end + if v.data.specialTypes then + for k3,v3 in pairs(v.data.specialTypes) do + local chance = v3.chance + specialrounddata[k3] = {["chance"] = chance/10} + end + end + end + end + + local normalSpawner = Spawner("nz_spawn_zombie_normal", normalrounddata, 1) + self:SetNormalSpawner(normalSpawner) + + if table.Count(specialrounddata) > 0 then + local specialSpawner = Spawner("nz_spawn_zombie_special", specialrounddata, 1, 4) + self:SetSpecialSpawner(specialSpawner) + end + + + -- else if no data was set continue with the gamemodes default spawning + -- if the round is special use the gamemodes default special round (Hellhounds) + elseif self:IsSpecial() then + -- only setup a special spawner + self:SetZombiesMax(math.floor(self:GetZombiesMax() / 2)) -- Half the amount of special zombies + local specialSpawner = Spawner("nz_spawn_zombie_special", {["nz_zombie_special_dog"] = {chance = 100}}, self:GetZombiesMax(), 2) + + -- save the spawner to access data + self:SetSpecialSpawner(specialSpawner) + + -- else just do regular walker spawning + else + local normalSpawner = Spawner("nz_spawn_zombie_normal", {["nz_zombie_walker"] = {chance = 100}}, self:GetZombiesMax()) + + -- after round 20 spawn some hellhounds aswell (half of the round number 21: 10, 22: 11, 23: 11, 24: 12 ...) + if self:GetNumber() > 20 then + local amount = math.floor(self:GetNumber() / 2) + local specialSpawner = Spawner("nz_spawn_zombie_special", {["nz_zombie_special_dog"] = {chance = 100}}, amount, 2) + + self:SetSpecialSpawner(specialSpawner) + self:SetZombiesMax(self:GetZombiesMax() + amount) + end + + -- save the spawner to access data + self:SetNormalSpawner(normalSpawner) + end + + --Heal + --[[for _, ply in pairs( player.GetAllPlaying() ) do + ply:SetHealth( ply:GetMaxHealth() ) + end]] + + --Set this to reset the overspawn debug message status + CurRoundOverSpawned = false + + --Start the next round + local time = time or GetConVar("nz_round_prep_time"):GetFloat() + if self:GetNumber() == -1 then time = 20 end + --timer.Simple(time, function() if self:InProgress() then self:Start() end end ) + + local starttime = CurTime() + time + hook.Add("Think", "nzRoundPreparing", function() + if CurTime() > starttime then + if self:InProgress() then self:Start() end + hook.Remove("Think", "nzRoundPreparing") + end + end) + + if self:IsSpecial() then + self:SetNextSpecialRound( self:GetNumber() + GetConVar("nz_round_special_interval"):GetInt() ) + end + +end + +local CurRoundOverSpawned = false + +function nzRound:Start() + + self:SetState( ROUND_PROG ) + local spawner = self:GetNormalSpawner() + if spawner then + spawner:SetNextSpawn( CurTime() + 3 ) -- Delay zombie spawning by 3 seconds + end + + local specialspawner = self:GetSpecialSpawner() + if self:IsSpecial() then + if specialspawner and specialspawner:GetData()["nz_zombie_special_dog"] then -- If we got a dog special round + specialspawner:SetNextSpawn( CurTime() + 6 ) -- Delay spawning even furhter + timer.Simple(3, function() + nzRound:CallHellhoundRound() -- Play the sound + end) + end + + local data = self:GetSpecialRoundData() + if data and data.roundfunc then data.roundfunc() end + end + + --Notify + --PrintMessage( HUD_PRINTTALK, "ROUND: " .. self:GetNumber() .. " started" ) + hook.Call("OnRoundStart", nzRound, self:GetNumber() ) + --nzNotifications:PlaySound("nz/round/round_start.mp3", 1) + + timer.Create( "NZRoundThink", 0.1, 0, function() self:Think() end ) + + nzWeps:DoRoundResupply() + + if self:GetNumber() == -1 then + self.InfinityStart = CurTime() + end +end + +function nzRound:Think() + if self.Frozen then return end + hook.Call( "OnRoundThink", self ) + --If all players are dead, then end the game. + if #player.GetAllPlayingAndAlive() < 1 then + self:End() + timer.Remove( "NZRoundThink" ) + return -- bail + end + + --If we've killed all the spawned zombies, then progress to the next level. + local numzombies = nzEnemies:TotalAlive() + + -- failsafe temporary until i can identify the issue (why are not all zombies spawned and registered) + local zombiesToSpawn + if self:GetNormalSpawner() then + zombiesToSpawn = self:GetNormalSpawner():GetZombiesToSpawn() + end + + if self:GetSpecialSpawner() then + if zombiesToSpawn then + zombiesToSpawn = zombiesToSpawn + self:GetSpecialSpawner():GetZombiesToSpawn() + else + zombiesToSpawn = self:GetSpecialSpawner():GetZombiesToSpawn() + end + end + + -- this will trigger if no more zombies will spawn, but more are required to end a round + if zombiesToSpawn == 0 and self:GetZombiesKilled() + numzombies < self:GetZombiesMax() then + if self:GetNormalSpawner() then + self:GetNormalSpawner():SetZombiesToSpawn(self:GetZombiesMax() - (self:GetZombiesKilled() + numzombies)) + DebugPrint(2, "Spawned additional normal zombies because the wave was underspawning.") + elseif self:GetSpecialSpawner() then + self:GetSpecialSpawner():SetZombiesToSpawn(self:GetZombiesMax() - (self:GetZombiesKilled() + numzombies)) + DebugPrint(2, "Spawned additional special zombies because the wave was underspawning.") + end + end + + self:SetZombiesToSpawn(zombiesToSpawn) + + if ( self:GetZombiesKilled() >= self:GetZombiesMax() and self:GetNumber() != -1 ) then + if numzombies <= 0 then + self:Prepare() + timer.Remove( "NZRoundThink" ) + end + end +end + +function nzRound:ResetGame() + --Main Behaviour + nzDoors:LockAllDoors() + self:Waiting() + --Notify + PrintMessage( HUD_PRINTTALK, "GAME READY!" ) + --Reset variables + self:SetNumber( 0 ) + + self:SetZombiesKilled( 0 ) + self:SetZombiesMax( 0 ) + + --Reset all player ready states + for _, ply in pairs( player.GetAllReady() ) do + ply:UnReady() + end + + --Reset all downed players' downed status + for k,v in pairs( player.GetAll() ) do + v:KillDownedPlayer( true ) + v.SoloRevive = nil -- Reset Solo Revive counter + v:SetPreventPerkLoss(false) + v:RemovePerks() + end + + --Remove all enemies + for k,v in pairs( nzConfig.ValidEnemies ) do + for k2, v2 in pairs( ents.FindByClass( k ) ) do + v2:Remove() + end + end + + --Resets all active palyers playing state + for _, ply in pairs( player.GetAllPlaying() ) do + ply:SetPlaying( false ) + end + + --Reset the electricity + nzElec:Reset(true) + + --Remove the random box + nzRandomBox.Remove() + + --Reset all perk machines + for k,v in pairs(ents.FindByClass("perk_machine")) do + v:TurnOff() + end + + for _, ply in pairs(player.GetAll()) do + ply:SetPoints(0) --Reset all player points + ply:RemovePerks() --Remove all players perks + ply:SetTotalRevives(0) --Reset all player total revive + ply:SetTotalDowns(0) --Reset all player total down + ply:SetTotalKills(0) --Reset all player total kill + end + + --Clean up powerups + nzPowerUps:CleanUp() + + --Reset easter eggs + nzEE:Reset() + nzEE.Major:Reset() + + -- Load queued config if any + if nzMapping.QueuedConfig then + nzMapping:LoadConfig(nzMapping.QueuedConfig.config, nzMapping.QueuedConfig.loader) + end + +end + +function nzRound:End() + --Main Behaviour + self:SetState( ROUND_GO ) + --Notify + PrintMessage( HUD_PRINTTALK, "GAME OVER!" ) + PrintMessage( HUD_PRINTTALK, "Restarting in 10 seconds!" ) + if self:GetNumber() == -1 then + if self.InfinityStart then + local time = string.FormattedTime(CurTime() - self.InfinityStart) + local timestr = string.format("%02i:%02i:%02i", time.h, time.m, time.s) + net.Start("nzMajorEEEndScreen") + net.WriteBool(false) + net.WriteBool(false) + net.WriteString("You survived for "..timestr.." in Round Infinity") + net.WriteFloat(10) + net.WriteBool(false) + net.Broadcast() + end + nzNotifications:PlaySound("nz/round/game_over_-1.mp3", 21) + elseif nzMapping.OfficialConfig then + nzNotifications:PlaySound("nz/round/game_over_5.mp3", 21) + else + nzNotifications:PlaySound("nz/round/game_over_4.mp3", 21) + end + + timer.Simple(10, function() + self:ResetGame() + end) + + hook.Call( "OnRoundEnd", nzRound ) +end + +function nzRound:Win(message, keepplaying, time, noautocam, camstart, camend) + if !message then message = "You survived after " .. self:GetNumber() .. " rounds!" end + local time = time or 10 + + if not noautocam then + net.Start("nzMajorEEEndScreen") + net.WriteBool(false) + net.WriteBool(true) + net.WriteString(message) + net.WriteFloat(time) + if camstart and camend then + net.WriteBool(true) + net.WriteVector(camstart) + net.WriteVector(camend) + else + net.WriteBool(false) + end + net.Broadcast() + end + + -- Set round state to Game Over + if !keepplaying then + nzRound:SetState( ROUND_GO ) + --Notify with chat message + PrintMessage( HUD_PRINTTALK, "GAME OVER!" ) + PrintMessage( HUD_PRINTTALK, "Restarting in 10 seconds!" ) + + if self.OverrideEndSlomo then + game.SetTimeScale(0.25) + timer.Simple(2, function() game.SetTimeScale(1) end) + end + + timer.Simple(time, function() + nzRound:ResetGame() + end) + + hook.Call( "OnRoundEnd", nzRound ) + else + for k,v in pairs(player.GetAllPlaying()) do + v:SetTargetPriority(TARGET_PRIORITY_NONE) + end + if self.OverrideEndSlomo then + game.SetTimeScale(0.25) + timer.Simple(2, function() game.SetTimeScale(1) end) + end + timer.Simple(time, function() + for k,v in pairs(player.GetAllPlaying()) do + v:SetTargetPriority(TARGET_PRIORITY_PLAYER) + --v:GivePermaPerks() + end + end) + end + +end + +function nzRound:Lose(message, time, noautocam, camstart, camend) + if !message then message = "You got overwhelmed after " .. self:GetNumber() .. " rounds!" end + local time = time or 10 + + if not noautocam then + net.Start("nzMajorEEEndScreen") + net.WriteBool(false) + net.WriteBool(true) + net.WriteString(message) + net.WriteFloat(time) + if camstart and camend then + net.WriteBool(true) + net.WriteVector(camstart) + net.WriteVector(camend) + else + net.WriteBool(false) + end + net.Broadcast() + end + + -- Set round state to Game Over + nzRound:SetState( ROUND_GO ) + --Notify with chat message + PrintMessage( HUD_PRINTTALK, "GAME OVER!" ) + PrintMessage( HUD_PRINTTALK, "Restarting in 10 seconds!" ) + + if self.OverrideEndSlomo then + game.SetTimeScale(0.25) + timer.Simple(2, function() game.SetTimeScale(1) end) + end + + timer.Simple(time, function() + nzRound:ResetGame() + end) + + hook.Call( "OnRoundEnd", nzRound ) +end + +function nzRound:Create(on) + if on then + if self:InState( ROUND_WAITING ) then + PrintMessage( HUD_PRINTTALK, "The mode has been set to creative mode!" ) + self:SetState( ROUND_CREATE ) + hook.Call("OnRoundCreative", nzRound) + --We are in create + for _, ply in pairs( player.GetAll() ) do + if ply:IsSuperAdmin() then + ply:GiveCreativeMode() + end + if ply:IsReady() then + ply:SetReady( false ) + end + end + + nzMapping:CleanUpMap() + nzDoors:LockAllDoors() + + for k,v in pairs(ents.GetAll()) do + if v.NZOnlyVisibleInCreative then + v:SetNoDraw(false) + end + end + + self:SetZombieHealth(100) + else + PrintMessage( HUD_PRINTTALK, "Can only go in Creative Mode from Waiting state." ) + end + elseif self:InState( ROUND_CREATE ) then + PrintMessage( HUD_PRINTTALK, "The mode has been set to play mode!" ) + self:SetState( ROUND_WAITING ) + --We are in play mode + for k,v in pairs(player.GetAll()) do + v:SetSpectator() + end + + for k,v in pairs(ents.GetAll()) do + if v.NZOnlyVisibleInCreative then -- This is set in each entity's file + v:SetNoDraw(true) -- Yes this improves FPS by ~50% over a client-side convar and round state check + end + end + else + PrintMessage( HUD_PRINTTALK, "Not in Creative Mode." ) + end +end + +function nzRound:SetupGame() + + self:SetNumber( 0 ) + + -- Store a session of all our players + for _, ply in pairs(player.GetAll()) do + if ply:IsValid() and ply:IsReady() then + ply:SetPlaying( true ) + end + ply:SetFrags( 0 ) --Reset all player kills + end + + nzMapping:CleanUpMap() + nzDoors:LockAllDoors() + + -- Open all doors with no price and electricity requirement + for k,v in pairs(ents.GetAll()) do + if v:IsBuyableEntity() then + local data = v:GetDoorData() + if data then + if tonumber(data.price) == 0 and tobool(data.elec) == false then + nzDoors:OpenDoor( v ) + end + end + end + -- Setup barricades + if v:GetClass() == "breakable_entry" then + v:ResetPlanks() + end + end + + -- Empty the link table + table.Empty(nzDoors.OpenedLinks) + + -- All doors with Link 0 (No Link) + nzDoors.OpenedLinks[0] = true + --nz.nzDoors.Functions.SendSync() + + -- Spawn a random box at a possible starting position + nzRandomBox.Spawn(nil, true) + + local power = ents.FindByClass("power_box") + if !IsValid(power[1]) then -- No power switch D: + nzElec:Activate(true) -- Silently turn on the power + else + nzElec:Reset() -- Reset with no value to play the power down sound + end + + nzPerks:UpdateQuickRevive() + + nzRound:SetNextSpecialRound( GetConVar("nz_round_special_interval"):GetInt() ) + + nzEE.Major:Reset() + + hook.Call( "OnGameBegin", nzRound ) + +end + +function nzRound:Freeze(bool) + self.Frozen = bool +end + +function nzRound:RoundInfinity(nokill) + if !nokill then + nzPowerUps:Nuke(nil, true) -- Nuke kills them all, no points, no position delay + end + + nzRound:SetNumber( -2 ) + nzRound:SetState(ROUND_PROG) + nzRound:Prepare() +end diff --git a/gamemodes/nzombies/gamemode/round/sv_round_meta.lua b/gamemodes/nzombies/gamemode/round/sv_round_meta.lua new file mode 100644 index 00000000..4115f440 --- /dev/null +++ b/gamemodes/nzombies/gamemode/round/sv_round_meta.lua @@ -0,0 +1,140 @@ +--pool network strings +util.AddNetworkString( ", nzRoundNumber" ) +util.AddNetworkString( ", nzRoundState" ) +util.AddNetworkString( ", nzRoundSpecial" ) +util.AddNetworkString( "nzPlayerReadyState" ) +util.AddNetworkString( "nzPlayerPlayingState" ) + +nzRound.Number = nzRound.Number or 0 -- Default for reloaded scenarios + +function nzRound:GetZombiesKilled() + return self.ZombiesKilled +end +function nzRound:SetZombiesKilled( num ) + self.ZombiesKilled = num +end + +function nzRound:GetZombiesMax() + return self.ZombiesMax +end +function nzRound:SetZombiesMax( num ) + self.ZombiesMax = num +end + +function nzRound:GetZombiesToSpawn() + return self.ZombiesToSpawn +end +function nzRound:SetZombiesToSpawn( num ) + self.ZombiesToSpawn = num +end +function nzRound:GetZombiesSpawned() + return self.ZombiesMax - self.ZombiesToSpawn +end + +function nzRound:GetZombieHealth() + return self.ZombieHealth +end +function nzRound:SetZombieHealth( num ) + self.ZombieHealth = num +end + +function nzRound:GetNormalSpawner() + return self.hNormalSpawner +end + +function nzRound:SetNormalSpawner(spawner) + self.hNormalSpawner = spawner +end + +function nzRound:GetSpecialSpawner() + return self.hSpecialSpawner +end + +function nzRound:SetSpecialSpawner(spawner) + self.hSpecialSpawner = spawner +end + +function nzRound:GetZombieSpeeds() + return self.ZombieSpeeds +end +function nzRound:SetZombieSpeeds( tbl ) + self.ZombieSpeeds = tbl +end + +function nzRound:SetGlobalZombieData( tbl ) + self:SetZombiesMax(tbl.maxzombies or 5) + self:SetZombieHealth(tbl.health or 75) + self:SetSpecial(tbl.special or false) +end + +function nzRound:InState( state ) + return self:GetState() == state +end + +function nzRound:IsSpecial() + return self.SpecialRound or false +end + +function nzRound:SetSpecial( bool ) + self.SpecialRound = bool or false + self:SendSpecialRound( self.SpecialRound ) +end + +function nzRound:InProgress() + return self:GetState() == ROUND_PREP or self:GetState() == ROUND_PROG +end + +function nzRound:SetState( state ) + + local oldstate = self.RoundState + self.RoundState = state + + self:SendState( state ) + + hook.Call("OnRoundChangeState", nzRound, state, oldstate) + +end + +function nzRound:GetState() + + return self.RoundState + +end + +function nzRound:SetNumber( number ) + self.Number = number + + self:SendNumber( number ) + +end + +function nzRound:IncrementNumber() + + self:SetNumber( self:GetNumber() + 1 ) + +end + +function nzRound:GetNumber() + + return self.Number + +end + +function nzRound:SetEndTime( time ) + + SetGlobalFloat( "nzEndTime", time ) + +end + +function nzRound:GetEndTime( time ) + + GetGlobalFloat( "nzEndTime" ) + +end + +function nzRound:GetNextSpawnTime() + return self.NextSpawnTime or 0 +end +function nzRound:SetNextSpawnTime( time ) + self.NextSpawnTime = time +end diff --git a/gamemodes/nzombies/gamemode/scoring/sh_player.lua b/gamemodes/nzombies/gamemode/scoring/sh_player.lua new file mode 100644 index 00000000..25a0cdf3 --- /dev/null +++ b/gamemodes/nzombies/gamemode/scoring/sh_player.lua @@ -0,0 +1,37 @@ +local meta = FindMetaTable("Player") + +function meta:GetTotalKills() + return self:GetNWInt("iZombiesKilled", 0) +end + +function meta:SetTotalKills(value) + self:SetNWInt("iZombiesKilled", value) +end + +function meta:IncrementTotalKills() + self:SetTotalKills(self:GetTotalKills() + 1) +end + +function meta:GetTotalDowns() + return self:GetNWInt("iTotalDowns", 0) +end + +function meta:SetTotalDowns(value) + self:SetNWInt("iTotalDowns", value) +end + +function meta:IncrementTotalDowns() + self:SetTotalDowns(self:GetTotalDowns() + 1) +end + +function meta:GetTotalRevives() + return self:GetNWInt("iTotalRevieves", 0) +end + +function meta:SetTotalRevives(value) + self:SetNWInt("iTotalRevieves", value) +end + +function meta:IncrementTotalRevives() + self:SetTotalRevives(self:GetTotalRevives() + 1) +end diff --git a/gamemodes/nzombies/gamemode/scoring/sv_update.lua b/gamemodes/nzombies/gamemode/scoring/sv_update.lua new file mode 100644 index 00000000..0509eaae --- /dev/null +++ b/gamemodes/nzombies/gamemode/scoring/sv_update.lua @@ -0,0 +1,18 @@ +function GM:OnZombieKilled(zombie, dmgInfo) + local attacker = dmgInfo:GetAttacker() + if IsValid(attacker) and attacker:IsPlayer() then + attacker:IncrementTotalKills() + end +end + +hook.Add("PlayerRevived", "nzupdateReviveScore", function(ply, revivor) + if IsValid(revivor) and revivor:IsPlayer() then + revivor:IncrementTotalRevives() + end +end ) + +hook.Add("PlayerDowned", "nzupdateDownedScore", function(ply) + if IsValid(ply) and ply:IsPlayer() then + ply:IncrementTotalDowns() + end +end ) diff --git a/gamemodes/nzombies/gamemode/shared.lua b/gamemodes/nzombies/gamemode/shared.lua new file mode 100644 index 00000000..90f132e2 --- /dev/null +++ b/gamemodes/nzombies/gamemode/shared.lua @@ -0,0 +1,26 @@ +GM.Name = "nZombies" +GM.Author = "Alig96, Zet0r, Lolle" +GM.Email = "N/A" +GM.Website = "N/A" + +-- Constants -- + +--Round Constants + +ROUND_WAITING = 0 +ROUND_INIT = 1 +ROUND_PREP = 2 +ROUND_PROG = 3 +ROUND_CREATE = 4 +ROUND_GO = 5 + +--Team Constants + +TEAM_SPECS = 1 +TEAM_PLAYERS = 2 +TEAM_ZOMBIES = 3 + +--Setup Teams +team.SetUp( TEAM_SPECS, "Spectators", Color( 255, 255, 255 ) ) +team.SetUp( TEAM_PLAYERS, "Players", Color( 255, 0, 0 ) ) +team.SetUp( TEAM_ZOMBIES, "Zombies", Color( 0, 255, 0 ) ) diff --git a/gamemodes/nzombies/gamemode/special_weapons/sh_constructor.lua b/gamemodes/nzombies/gamemode/special_weapons/sh_constructor.lua new file mode 100644 index 00000000..0d522b40 --- /dev/null +++ b/gamemodes/nzombies/gamemode/special_weapons/sh_constructor.lua @@ -0,0 +1,17 @@ +-- Setup Doors module +nzSpecialWeapons = nzSpecialWeapons or AddNZModule("SpecialWeapons") + +--nzSpecialWeapons.Categories = nzSpecialWeapons.Categories or {} + +nzSpecialWeapons.Keys = nzSpecialWeapons.Keys or { + ["knife"] = KEY_V, + ["grenade"] = KEY_G, + ["specialgrenade"] = KEY_B, +} + +function nzSpecialWeapons:RegisterSpecialWeaponCategory(id, defaultkey) + if !self.Keys[id] then + if defaultkey and CLIENT then CreateClientConVar("nz_key_"..string.lower(id), defaultkey, true, true, "Sets the key that equips "..id..". Uses numbers from gmod's KEY_ enums: http://wiki.garrysmod.com/page/Enums/KEY") end + self.Keys[id] = defaultkey -- To use as default + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/special_weapons/sh_functions.lua b/gamemodes/nzombies/gamemode/special_weapons/sh_functions.lua new file mode 100644 index 00000000..f9d402ce --- /dev/null +++ b/gamemodes/nzombies/gamemode/special_weapons/sh_functions.lua @@ -0,0 +1,520 @@ +nzSpecialWeapons.Modifiers = nzSpecialWeapons.Modifiers or {} + +function nzSpecialWeapons:RegisterModifier(id, func, defaultdata) + nzSpecialWeapons.Modifiers[id] = {func, defaultdata} +end + +function nzSpecialWeapons:ModifyWeapon(wep, id, data) + local tbl = nzSpecialWeapons.Modifiers[id] + if !tbl then return end + + local pass = {} + local default = tbl[2] + + if !data then pass = default else + for k,v in pairs(default) do + if data[k] != nil then -- ONLY if nil (not passed) + pass[k] = data[k] + else + pass[k] = v + end + end + end + + local bool = tbl[1](wep, pass) -- Run the function with the data, return whether it worked or not + if bool then + wep.NZSpecialWeaponData = pass + wep.NZSpecialCategory = id -- Mark as special from now on + + if isentity(wep) then -- Reregister it on the player if it is currently being carried + wep:SetNWInt( "SwitchSlot", nil ) -- Reset weapon slot + local ply = wep:GetOwner() + if IsValid(ply) then + hook.Run("WeaponEquip", wep) -- Rerun weapon equip logic (resets slots etc) + ply:EquipPreviousWeapon() -- Equip previous weapon + end + end + end + + return bool +end + +nzSpecialWeapons:RegisterModifier("knife", function(wep, data) + if wep then + local attackholstertime = data.AttackHolsterTime + local drawholstertime = data.DrawHolsterTime + + local oldattack = wep.PrimaryAttack + function wep:PrimaryAttack() + if self.nzCanAttack then + oldattack(self) + self.nzCanAttack = false + end + end + + --local olddeploy = wep.Deploy + wep.EquipDraw = wep.Deploy + + function wep:Deploy() + local ct = CurTime() + if !self.nzIsDrawing then + self.nzCanAttack = true + self.nzHolsterTime = ct + attackholstertime + self:SendWeaponAnim(ACT_VM_IDLE) + self:SetNextPrimaryFire(0) + + if self.SetStatus then + self:SetStatus(TFA.Enum.STATUS_IDLE) + end + + self:PrimaryAttack() + else + self.nzHolsterTime = ct + drawholstertime + end + self.nzIsDrawing = nil + end + + local oldthink = wep.Think + function wep:Think() + local ct = CurTime() + + --[[if self.nzAttackTime and ct > self.nzAttackTime then + self:PrimaryAttack() + self.nzAttackTime = nil + end]] + + if self.nzHolsterTime and ct > self.nzHolsterTime and !self.Owner.nzSpecialButtonDown then + self:Holster() + self.Owner:SetUsingSpecialWeapon(false) + self.Owner:EquipPreviousWeapon() + self.nzHolsterTime = nil + end + + oldthink(self) + end + + local oldholster = wep.Holster + function wep:Holster( wep2 ) + if SERVER then self.Owner:SetUsingSpecialWeapon(false) end + return oldholster(self, wep2) + end + return true + end +end, { -- Every field that isn't supplied from the data arg is taken from here instead + AttackHolsterTime = 0.65, + DrawHolsterTime = 1.5, + DrawOnEquip = true, +}) + +nzSpecialWeapons:RegisterModifier("grenade", function(wep, data) + if wep then + local drawact = data.DrawAct + local throwtime = data.ThrowTime + local throwfunc = data.ThrowFunction + local holstertime = data.HolsterTime + + wep.EquipDraw = wep.Deploy + + function wep:Deploy() + local ct = CurTime() + self.nzThrowTime = ct + throwtime + + if !drawact then + self:EquipDraw() -- Use normal draw animation/function for not specifying throw act + else + self:SendWeaponAnim(drawact) -- Otherwise play the act (preferably pull pin act) + end + + end + + local oldthink = wep.Think + + if !throwfunc then + local primary = wep.PrimaryAttack + throwfunc = function(self) + primary(self) + self.Owner:SetAmmo(self.Owner:GetAmmoCount(GetNZAmmoID("grenade")) - 1, GetNZAmmoID("grenade")) + end + end + + function wep:Think() + local ct = CurTime() + + if self.nzThrowTime and ct > self.nzThrowTime and (!self.Owner.nzSpecialButtonDown or !self.Owner:GetNotDowned()) then + self.nzThrowTime = nil + self.nzHolsterTime = ct + holstertime + throwfunc(self) -- If a function was specified (e.g. to run a certain func on the weapon), then do that + -- The above function needs to subtract the grenade ammo (unless they're going for something special) + end + + if self.nzHolsterTime and ct > self.nzHolsterTime then + self.nzHolsterTime = nil + self.Owner:SetUsingSpecialWeapon(false) + self:Holster() + self.Owner:EquipPreviousWeapon() + end + + oldthink(self) + end + + function wep:PrimaryAttack() end + return true + end +end, { + MaxAmmo = 4, + AmmoType = "nz_grenade", + DrawAct = false, -- False/nil makes default + ThrowTime = 0.85, + ThrowFunction = false, -- False/nil uses default PrimaryAttack function + HolsterTime = 0.4, +}) + +nzSpecialWeapons:RegisterModifier("specialgrenade", function(wep, data) + if wep then + local drawact = data.DrawAct + local throwtime = data.ThrowTime + local throwfunc = data.ThrowFunction + local holstertime = data.HolsterTime + + wep.EquipDraw = wep.Deploy + + function wep:Deploy() + local ct = CurTime() + + if !drawact then + self:EquipDraw() -- Use normal draw animation/function for not specifying throw act + else + self:SendWeaponAnim(drawact) -- Otherwise play the act (preferably pull pin act) + end + self.nzThrowTime = ct + throwtime + end + + local oldthink = wep.Think + + if !throwfunc then + local primary = wep.PrimaryAttack + throwfunc = function(self) + primary(self) + self.Owner:SetAmmo(self.Owner:GetAmmoCount(GetNZAmmoID("specialgrenade")) - 1, GetNZAmmoID("specialgrenade")) + end + end + + function wep:Think() + local ct = CurTime() + + if self.nzThrowTime and ct > self.nzThrowTime and (!self.Owner.nzSpecialButtonDown or !self.Owner:GetNotDowned()) then + self.nzThrowTime = nil + self.nzHolsterTime = ct + holstertime + throwfunc(self) + end + + if self.nzHolsterTime and ct > self.nzHolsterTime then + self.nzHolsterTime = nil + self.Owner:SetUsingSpecialWeapon(false) + self:Holster() + self.Owner:EquipPreviousWeapon() + end + + oldthink(self) + end + + function wep:PrimaryAttack() end + return true + end +end, { + MaxAmmo = 3, + AmmoType = "nz_specialgrenade", + DrawAct = false, -- False/nil makes default + ThrowTime = 1.2, + ThrowFunction = false, -- False/nil uses default PrimaryAttack function + HolsterTime = 0.4, +}) + +nzSpecialWeapons:RegisterModifier("display", function(wep, data) + if wep then + local drawfunc = data.DrawFunction + local returnfunc = data.ToHolsterFunction + + wep.EquipDraw = wep.Deploy + + if drawfunc then + function wep:Deploy() + local ct = CurTime() + drawfunc(self) -- Drawfunc specified, overwrite deploy with this function + self.nzDeployTime = ct -- Time when it was equipped, can be used for time comparisons + end + else + function wep:Deploy() + local ct = CurTime() + self:EquipDraw() -- Not specified, use deploy function + self.nzDeployTime = ct -- Time when it was equipped, can be used for time comparisons + end + end + + local oldthink = wep.Think + + function wep:Think() + if returnfunc(self) then + if SERVER then + self.Owner:SetUsingSpecialWeapon(false) + end + self:Holster() + self.Owner:EquipPreviousWeapon() + if SERVER then + self.Owner:StripWeapon(self:GetClass()) -- Always stripped when done with use + end + end + + oldthink(self) + end + return true + end +end, { + DrawFunction = false, + ToHolsterFunction = function(wep) + return SERVER and CurTime() > wep.nzDeployTime + 2.5 -- Default delay 2.5 seconds + end, +}) + +-- Hardcodes the weapon by re-registering the weapon table after it's passed through normal modifications +function nzSpecialWeapons:AddKnife( class, drawonequip, attackholstertime, drawholstertime ) + local wep = weapons.Get(class) + if wep then + if nzSpecialWeapons:ModifyWeapon(wep, "knife", {AttackHolsterTime = attackholstertime, DrawHolsterTime = drawholstertime, DrawOnEquip = drawonequip}) then + weapons.Register(wep, class) + end + end +end + +function nzSpecialWeapons:AddGrenade( class, ammo, drawact, throwtime, throwfunc, holstertime ) + local wep = weapons.Get(class) + if wep then + if nzSpecialWeapons:ModifyWeapon(wep, "grenade", {MaxAmmo = ammo, DrawAct = drawact, ThrowTime = throwtime, ThrowFunction = throwfunc, HolsterTime = holstertime}) then + weapons.Register(wep, class) + end + end +end + +function nzSpecialWeapons:AddSpecialGrenade( class, ammo, drawact, throwtime, throwfunc, holstertime ) + local wep = weapons.Get(class) + if wep then + if nzSpecialWeapons:ModifyWeapon(wep, "specialgrenade", {MaxAmmo = ammo, DrawAct = drawact, ThrowTime = throwtime, ThrowFunction = throwfunc, HolsterTime = holstertime}) then + weapons.Register(wep, class) + end + end +end + +function nzSpecialWeapons:AddDisplay( class, drawfunc, returnfunc ) + local wep = weapons.Get(class) + if wep then + if nzSpecialWeapons:ModifyWeapon(wep, "display", {DrawFunction = drawfunc, ToHolsterFunction = returnfunc}) then + weapons.Register(wep, class) + end + end +end + +if CLIENT then + CreateClientConVar("nz_key_knife", KEY_V, true, true, "Sets the key that triggers Knife. Uses numbers from gmod's KEY_ enums: http://wiki.garrysmod.com/page/Enums/KEY") + CreateClientConVar("nz_key_grenade", KEY_G, true, true, "Sets the key that throws Grenades. Uses numbers from gmod's KEY_ enums: http://wiki.garrysmod.com/page/Enums/KEY") + CreateClientConVar("nz_key_specialgrenade", KEY_B, true, true, "Sets the key that throws Special Grenades. Uses numbers from gmod's KEY_ enums: http://wiki.garrysmod.com/page/Enums/KEY") + + local defaultkeys = nzSpecialWeapons.Keys + + function GetSpecialWeaponIDFromInput() + local ply = LocalPlayer() + if !ply.NZSpecialWeapons then return end + + local id + local wep + + for k,v in pairs(ply.NZSpecialWeapons) do + local key = input.IsKeyDown(ply:GetInfoNum("nz_key_"..k, defaultkeys[k] or -1)) + if key then + id = k + wep = v + break + end + end + + return id, wep + end + + hook.Add("CreateMove", "nzSpecialWeaponSelect", function( cmd ) + if vgui.CursorVisible() then return end + local ply = LocalPlayer() + local id, wep = GetSpecialWeaponIDFromInput() + if id and (ply:GetNotDowned() or id == "knife") and !ply:GetUsingSpecialWeapon() then + local ammo = GetNZAmmoID(id) + if !ammo or ply:GetAmmoCount(ammo) >= 1 then + --local wep = ply:GetSpecialWeaponFromCategory( id ) + if IsValid(wep) then + ply:SelectWeapon(wep:GetClass()) + end + end + end + end) + + hook.Add("HUDWeaponPickedUp", "nzSpecialWeaponAddClient", function(wep) + local ply = LocalPlayer() + local id = IsValid(wep) and wep:IsSpecial() and wep:GetSpecialCategory() + if !ply.NZSpecialWeapons then ply.NZSpecialWeapons = {} end + if id and !IsValid(ply.NZSpecialWeapons[id]) then + ply.NZSpecialWeapons[id] = wep + end + end) +end + +hook.Add("PlayerButtonDown", "nzSpecialWeaponsHandler", function(ply, but) + if but == ply:GetInfoNum("nz_key_knife", KEY_V) or + but == ply:GetInfoNum("nz_key_grenade", KEY_G) or + but == ply:GetInfoNum("nz_key_specialgrenade", KEY_B) then + ply.nzSpecialButtonDown = true + end + + if id and (ply:GetNotDowned() or id == "knife") and !ply:GetUsingSpecialWeapon() then + + end +end) + +hook.Add("PlayerButtonUp", "nzSpecialWeaponsThrow", function(ply, but) + --local id = buttonids[but] + local id = but == ply:GetInfoNum("nz_key_knife", KEY_V) or but == ply:GetInfoNum("nz_key_grenade", KEY_G) or but == ply:GetInfoNum("nz_key_specialgrenade", KEY_B) + if id and ply.nzSpecialButtonDown then + ply.nzSpecialButtonDown = false + end +end) + +local wep = FindMetaTable("Weapon") +local ply = FindMetaTable("Player") + +function wep:IsSpecial() + return self.NZSpecialCategory and true or false +end + +function wep:GetSpecialCategory() + return self.NZSpecialCategory +end + +function ply:GetSpecialWeaponFromCategory( id ) + if !self.NZSpecialWeapons then self.NZSpecialWeapons = {} end + return self.NZSpecialWeapons[id] or nil +end + +function ply:EquipPreviousWeapon() + if IsValid(self.NZPrevWep) then -- If the previously used weapon is valid, use that + if SERVER then + self:SetActiveWeapon(nil) + end + self:SelectWeapon(self.NZPrevWep:GetClass()) + else + for k,v in pairs(self:GetWeapons()) do -- And pick the first one that isn't special + if !v:IsSpecial() then + if SERVER then + self:SetActiveWeapon(nil) + end + self:SelectWeapon(v:GetClass()) + return + end + end + if SERVER then + self:SetActiveWeapon(nil) + end + end +end + +if SERVER then + function ply:AddSpecialWeapon(wep) + if !self.NZSpecialWeapons then self.NZSpecialWeapons = {} end + local id = wep:GetSpecialCategory() + self.NZSpecialWeapons[id] = wep + nzSpecialWeapons:SendSpecialWeaponAdded(self, wep, id) + + local data = wep.NZSpecialWeaponData + + if !data then return end -- No nothing more if it doesn't have data supplied (e.g. specially added thingies) + + local ammo = GetNZAmmoID(id) + local maxammo = data.maxammo + if ammo and maxammo then + self:SetAmmo(maxammo, ammo) + end + + if id == "display" then + self:SetUsingSpecialWeapon(true) + self:SetActiveWeapon(nil) + self:SelectWeapon(wep:GetClass()) + elseif data.DrawOnEquip then + wep.nzIsDrawing = true + self:SetUsingSpecialWeapon(true) + self:SetActiveWeapon(nil) + self:SelectWeapon(wep:GetClass()) + wep:EquipDraw() + end + end + + -- This hook only works server-side + hook.Add("WeaponEquip", "nzSetSpecialWeapons", function(wep) + if wep:IsSpecial() then + -- 0 second timer for the next tick where wep's owner is valid + timer.Simple(0, function() + local ply = wep:GetOwner() + if IsValid(ply) then + local oldwep = ply:GetSpecialWeaponFromCategory( wep:GetSpecialCategory() ) + --print(wep, oldwep) + if IsValid(oldwep) then + ply:StripWeapon(oldwep:GetClass()) + end + ply:AddSpecialWeapon(wep) + end + end) + end + end) +end + +-- Players switching to special weapons can then no longer switch away until its action has been completed +function GM:PlayerSwitchWeapon(ply, oldwep, newwep) + print(ply, oldwep, newwep) + if IsValid(oldwep) and IsValid(newwep) then + + if !oldwep:IsSpecial() then + if oldwep != newwep then + ply.NZPrevWep = oldwep -- Store previous weapon if it's not special and not the same + end + ply:SetUsingSpecialWeapon(false) + end + + if ply:GetUsingSpecialWeapon() then + if oldwep:IsSpecial() then + if oldwep.NZSpecialHolster then + local allow = oldwep:NZSpecialHolster(newwep) + if allow then + ply:SetUsingSpecialWeapon(false) + end + return !allow -- With this function, it determines if we can holster + else + return true -- Otherwise we CAN'T get away from this weapon until SetUsingSpecialWeapon is false! + end + else -- Switching away from a non-sepcial when we have special set; reset it! + ply:SetUsingSpecialWeapon(false) + return false -- Allow + end + else -- Not using special weapons + if newwep:IsSpecial() then -- Switching to a special one, turn Using Special on! + local ammo = GetNZAmmoID(newwep:GetSpecialCategory()) + if !ammo or ply:GetAmmoCount(ammo) >= 1 then + + local holster = oldwep.Holster + oldwep.Holster = function() return true end -- Allow instant holstering + timer.Simple(0, function() oldwep.Holster = holster end) + + ply:SetUsingSpecialWeapon(true) + return false -- We allow it when it's either not using ammo or we have enough + else + return true -- With ammo and less than 1 left, we don't switch :( + end + + end + end + + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/special_weapons/sh_specialweapons.lua b/gamemodes/nzombies/gamemode/special_weapons/sh_specialweapons.lua new file mode 100644 index 00000000..db547a38 --- /dev/null +++ b/gamemodes/nzombies/gamemode/special_weapons/sh_specialweapons.lua @@ -0,0 +1,24 @@ + +local function RegisterDefaultSpecialWeps() + nzSpecialWeapons:AddKnife( "nz_quickknife_crowbar", false, 0.65 ) + nzSpecialWeapons:AddKnife( "nz_bowie_knife", true, 0.65, 2.5 ) + nzSpecialWeapons:AddKnife( "nz_one_inch_punch", true, 0.75, 1.5 ) + + nzSpecialWeapons:AddGrenade( "nz_grenade", 4, false, 0.85, false, 0.4 ) -- ALWAYS pass false instead of nil or it'll assume default value + nzSpecialWeapons:AddSpecialGrenade( "nz_monkey_bomb", 3, false, 3, false, 0.4 ) + + nzSpecialWeapons:AddDisplay( "nz_revive_morphine", false, function(wep) + return !IsValid(wep.Owner:GetPlayerReviving()) + end) + + nzSpecialWeapons:AddDisplay( "nz_perk_bottle", false, function(wep) + return SERVER and CurTime() > wep.nzDeployTime + 3.1 + end) + + nzSpecialWeapons:AddDisplay( "nz_packapunch_arms", false, function(wep) + return SERVER and CurTime() > wep.nzDeployTime + 2.5 + end) +end + +hook.Add("InitPostEntity", "nzRegisterSpecialWeps", RegisterDefaultSpecialWeps) +--hook.Add("OnReloaded", "nzRegisterSpecialWeps", RegisterDefaultSpecialWeps) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/special_weapons/sh_sync.lua b/gamemodes/nzombies/gamemode/special_weapons/sh_sync.lua new file mode 100644 index 00000000..1751e50b --- /dev/null +++ b/gamemodes/nzombies/gamemode/special_weapons/sh_sync.lua @@ -0,0 +1,42 @@ +if SERVER then + util.AddNetworkString("nzSendSpecialWeapon") + + function nzSpecialWeapons:SendSpecialWeaponAdded(ply, wep, id) + timer.Simple(0.5, function() + if IsValid(ply) then + net.Start("nzSendSpecialWeapon") + net.WriteString(id) + net.WriteBool(true) + net.WriteEntity(wep) + net.Send(ply) + end + end) + end + + function nzSpecialWeapons:SendSpecialWeaponRemoved(ply, id) + timer.Simple(0.1, function() + if IsValid(ply) then + net.Start("nzSendSpecialWeapon") + net.WriteString(id) + net.WriteBool(false) + net.Send(ply) + end + end) + end +end + +if CLIENT then + local function ReceiveSpecialWeaponAdded() + if !LocalPlayer().NZSpecialWeapons then LocalPlayer().NZSpecialWeapons = {} end + local id = net.ReadString() + local bool = net.ReadBool() + + if bool then + local ent = net.ReadEntity() + LocalPlayer().NZSpecialWeapons[id] = ent + else + LocalPlayer().NZSpecialWeapons[id] = nil + end + end + net.Receive("nzSendSpecialWeapon", ReceiveSpecialWeaponAdded) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/spectator/sv_override.lua b/gamemodes/nzombies/gamemode/spectator/sv_override.lua new file mode 100644 index 00000000..d7cb00f4 --- /dev/null +++ b/gamemodes/nzombies/gamemode/spectator/sv_override.lua @@ -0,0 +1,70 @@ +--Gamemode Overrides + +function GM:PlayerInitialSpawn( ply ) + timer.Simple( 0, function() ply:SetSpectator() end ) +end + +function GM:PlayerDeath( ply, wep, killer ) + ply:SetSpectator() + ply:SetTargetPriority(TARGET_PRIORITY_NONE) +end + +function GM:PlayerDeathThink( ply ) + + -- Allow players in creative mode to respawn + if ply:IsInCreative() and nzRound:InState( ROUND_CREATE ) then + if ply:KeyDown(IN_JUMP) or ply:KeyDown(IN_ATTACK) then + ply:Spawn() + return true + end + end + + local players = player.GetAllPlayingAndAlive() + + if ply:KeyPressed( IN_RELOAD ) then + ply:SetSpectatingType( ply:GetSpectatingType() + 1 ) + if ply:GetSpectatingType() > 5 then + ply:SetSpectatingType( 4 ) + ply:SetupHands(players[ ply:GetSpectatingID() ]) + end + ply:Spectate( ply:GetSpectatingType() ) + elseif ply:KeyPressed( IN_ATTACK ) then + ply:SetSpectatingID( ply:GetSpectatingID() + 1 ) + if ply:GetSpectatingID() > #players then ply:SetSpectatingID( 1 ) end + ply:SpectateEntity( players[ ply:GetSpectatingID() ] ) + elseif ply:KeyPressed( IN_ATTACK2 ) then + ply:SetSpectatingID( ply:GetSpectatingID() - 1 ) + if ply:GetSpectatingID() <= 0 then ply:SetSpectatingID( #players ) end + ply:SpectateEntity( players[ ply:GetSpectatingID() ] ) + end +end + +local function disableDeadUse( ply, ent ) + if !ply:Alive() then return false end +end + +hook.Add( "PlayerUse", "nzDisableDeadUse", disableDeadUse) + +local hooks = hook.GetTable().AllowPlayerPickup +if hooks then + for k,v in pairs(hooks) do + hook.Remove("AllowPlayerPickup", k) + end +end + +local function disableDeadPickups( ply, ent ) + if !ply:Alive() then + return false + else + -- This will allow pickups even if the weapon can't holster + local wep = ply:GetActiveWeapon() + if IsValid(wep) and !wep:IsSpecial() then + local holster = wep.Holster + wep.Holster = function() return true end + timer.Simple(0, function() wep.Holster = holster end) + end + return true + end +end + +hook.Add( "AllowPlayerPickup", "_nzDisableDeadPickups", disableDeadPickups) diff --git a/gamemodes/nzombies/gamemode/spectator/sv_player.lua b/gamemodes/nzombies/gamemode/spectator/sv_player.lua new file mode 100644 index 00000000..c2e2db0d --- /dev/null +++ b/gamemodes/nzombies/gamemode/spectator/sv_player.lua @@ -0,0 +1,15 @@ +--Get the meta Table +local plyMeta = FindMetaTable( "Player" ) +--accessors +AccessorFunc( plyMeta, "iSpectatingID", "SpectatingID", FORCE_NUMBER ) +AccessorFunc( plyMeta, "iSpectatingType", "SpectatingType", FORCE_NUMBER ) + +function plyMeta:SetSpectator() + if self:Alive() then + self:KillSilent() + end + self:SetTeam( TEAM_SPECTATOR ) + self:SetSpectatingType( OBS_MODE_CHASE ) + self:Spectate( self:GetSpectatingType() ) + self:SetSpectatingID( 1 ) +end diff --git a/gamemodes/nzombies/gamemode/tools/sh_constructor.lua b/gamemodes/nzombies/gamemode/tools/sh_constructor.lua new file mode 100644 index 00000000..e3346151 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_constructor.lua @@ -0,0 +1,9 @@ +//Main Tables +nzTools = nzTools or AddNZModule("Tools") +nzTools.ToolData = nzTools.ToolData or {} + +//Variables +if CLIENT then + nzTools.Advanced = nzTools.Advanced or false + nzTools.SavedData = nzTools.SavedData or {} +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_meta.lua b/gamemodes/nzombies/gamemode/tools/sh_meta.lua new file mode 100644 index 00000000..e431516a --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_meta.lua @@ -0,0 +1,15 @@ +local playerMeta = FindMetaTable("Player") + +function playerMeta:SetNZToolData( data ) + self.NZToolData = nil + if data then + self.NZToolData = data + end +end + +function playerMeta:SetActiveNZTool( tool ) + local wep = self:GetActiveWeapon() + if IsValid(wep) and wep:GetClass() == "nz_multi_tool" then + wep.ToolMode = tool + end +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_sync.lua b/gamemodes/nzombies/gamemode/tools/sh_sync.lua new file mode 100644 index 00000000..8fb3af45 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_sync.lua @@ -0,0 +1,65 @@ +-- Client Server Syncing + +if SERVER then + + -- Server to client (Server) + --util.AddNetworkString( "nzToolsSync" ) + util.AddNetworkString( "nzToolsUpdate" ) + + local function ReceiveData(len, ply) + if !IsValid(ply) then return end + local id = net.ReadString() + local wep = ply:GetActiveWeapon() + + -- Call holster on the old tool + if nzTools.ToolData[wep.ToolMode] then + nzTools.ToolData[wep.ToolMode].OnHolster(wep, ply, ply.NZToolData) + end + + ply:SetActiveNZTool( id ) + -- Only read the data if the tool has any - as shown by the bool + if net.ReadBool() then + ply:SetNZToolData( net.ReadTable() ) + end + + -- Then call equip on the new one + if nzTools.ToolData[id] then + nzTools.ToolData[id].OnEquip(wep, ply, ply.NZToolData) + end + end + net.Receive( "nzToolsUpdate", ReceiveData ) +end + +if CLIENT then + + -- Client to server + function nzTools:SendData( data, tool, savedata ) + if data then + net.Start("nzToolsUpdate") + net.WriteString(tool) + -- Let the server know we're also sending a table of data + net.WriteBool(true) + net.WriteTable(data) + net.SendToServer() + else + -- This tool doesn't have any data + net.Start("nzToolsUpdate") + net.WriteString(tool) + net.WriteBool(false) + net.SendToServer() + end + + -- Always save on submit - if a special table of savedata is provided, use that + if savedata then + nzTools:SaveData( savedata, tool ) + else + nzTools:SaveData( data, tool ) + end + end + + function nzTools:SaveData( data, tool ) + self.SavedData[tool] = nil + self.SavedData[tool] = data + end + +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools.lua b/gamemodes/nzombies/gamemode/tools/sh_tools.lua new file mode 100644 index 00000000..c1a7a67a --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools.lua @@ -0,0 +1,123 @@ +-- + +function nzTools:CreateTool(id, serverdata, clientdata) + if SERVER then + self.ToolData[id] = serverdata + else + self.ToolData[id] = clientdata + end +end + +function nzTools:EnableProperties(id, label, icon, order, spacer, filterfunc, datafunc) + properties.Add( "nztool_"..id, { + MenuLabel = label, + Order = order, + PrependSpacer = spacer, + MenuIcon = icon, + + Filter = filterfunc, + + Action = function( self, ent ) + local frame = vgui.Create("DFrame") + frame:SetPos( 100, 100 ) + frame:SetSize( 300, 280 ) + frame:SetTitle( label ) + frame:SetVisible( true ) + frame:SetDraggable( true ) + frame:ShowCloseButton( true ) + frame:MakePopup() + frame:Center() + + local entdata = datafunc(ent) + if !entdata then entdata = {} end + + local panel = nzTools.ToolData[id].interface(frame, entdata, true) + panel:SetPos(10, 40) + + local data2 = panel.CompileData() + panel.UpdateData = function(data) + data2 = data + end + + local submit = vgui.Create("DButton", frame) + submit:SetText("Submit") + submit:SetPos(50, 245) + submit:SetSize(200, 25) + submit.DoClick = function(self2) + self:MsgStart() + net.WriteEntity( ent ) + net.WriteTable( data2 ) + self:MsgEnd() + end + end, + + Receive = function( self, length, ply ) + local ent = net.ReadEntity() + local data = net.ReadTable() + + if ( !IsValid( ent ) or !IsValid(ply) ) then return false end + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( !ply:IsInCreative() ) then return false end + if ( ent:IsPlayer() ) then return false end + if ( !self:Filter( ent, ply ) ) then return false end + + local trace = ply:GetEyeTrace() + trace.Entity = ent + nzTools.ToolData[id].PrimaryAttack(nil, ply, trace, data) + end + } ) +end + +function nzTools:Get(id) + return self.ToolData[id] +end + +function nzTools:GetList() + local tbl = {} + + for k,v in pairs(self.ToolData) do + tbl[k] = v.displayname + end + + return tbl +end + +nzTools:CreateTool("default", { + displayname = "Multitool", + desc = "Hold Q to pick a tool to use", + condition = function(wep, ply) + return false + end, + + PrimaryAttack = function(wep, ply, tr, data) + end, + + SecondaryAttack = function(wep, ply, tr, data) + end, + Reload = function(wep, ply, tr, data) + -- Nothing + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Multitool", + desc = "Hold Q to pick a tool to use", + condition = function(wep, ply) + return false + end, + interface = function(frame, data) + local text = vgui.Create("DLabel", frame) + text:SetText("Select a tool in the list to the left.") + text:SetFont("Trebuchet18") + text:SetTextColor( Color(50, 50, 50) ) + text:SizeToContents() + text:Center() + + return text + end, + -- defaultdata = {} +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_barricade.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_barricade.lua new file mode 100644 index 00000000..1118aaa8 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_barricade.lua @@ -0,0 +1,75 @@ +nzTools:CreateTool("barricade", { + displayname = "Barricade Creator", + desc = "LMB: Place Barricade, RMB: Remove Barricade", + condition = function(wep, ply) + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + local ent = tr.Entity + if IsValid(ent) and ent:GetClass() == "breakable_entry" then + nzMapping:BreakEntry(ent:GetPos(), ent:GetAngles(), data.planks, data.jump, ply) + ent:Remove() + else + nzMapping:BreakEntry(tr.HitPos + Vector(0,0,45), Angle(0,(tr.HitPos - ply:GetPos()):Angle()[2],0), data.planks, data.jump, ply) + end + end, + SecondaryAttack = function(wep, ply, tr, data) + if IsValid(tr.Entity) and tr.Entity:GetClass() == "breakable_entry" then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + //Nothing + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Barricade Creator", + desc = "LMB: Place Barricade, RMB: Remove Barricade", + icon = "icon16/door.png", + weight = 7, + condition = function(wep, ply) + return true + end, + interface = function(frame, data) + local valz = {} + valz["Row1"] = data.planks + valz["Row2"] = data.jump + + local DProperties = vgui.Create( "DProperties", frame ) + DProperties:SetSize( 280, 180 ) + DProperties:SetPos( 10, 10 ) + + function DProperties.CompileData() + data.planks = valz["Row1"] + data.jump = valz["Row2"] + + --PrintTable(data) + + return data + end + + function DProperties.UpdateData(data) -- This function will be overwritten if opened via context menu + nzTools:SendData(data, "barricade") + end + + local Row1 = DProperties:CreateRow( "Barricade", "Has Planks?" ) + Row1:Setup( "Boolean" ) + Row1:SetValue( valz["Row1"] ) + Row1.DataChanged = function( _, val ) valz["Row1"] = val DProperties.UpdateData(DProperties.CompileData()) end + local Row2 = DProperties:CreateRow( "Barricade", "Jump Animations?" ) + Row2:Setup( "Boolean" ) + Row2:SetValue( valz["Row2"] ) + Row2.DataChanged = function( _, val ) valz["Row2"] = val DProperties.UpdateData(DProperties.CompileData()) end + + return DProperties + end, + defaultdata = { + planks = 1, + jump = 0, + } +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_block.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_block.lua new file mode 100644 index 00000000..4e2657c9 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_block.lua @@ -0,0 +1,188 @@ + +local models = { + "models/nzombies_plates/plate.mdl", + "models/nzombies_plates/plate1.mdl", + "models/nzombies_plates/plate1x1.mdl", + "models/nzombies_plates/plate1x2.mdl", + "models/nzombies_plates/plate1x3.mdl", + "models/nzombies_plates/plate1x4.mdl", + "models/nzombies_plates/plate1x5.mdl", + "models/nzombies_plates/plate1x6.mdl", + "models/nzombies_plates/plate1x7.mdl", + "models/nzombies_plates/plate1x8.mdl", + "models/nzombies_plates/plate1x16.mdl", + "models/nzombies_plates/plate1x24.mdl", + "models/nzombies_plates/plate1x32.mdl", + "models/nzombies_plates/plate2.mdl", + "models/nzombies_plates/plate2x2.mdl", + "models/nzombies_plates/plate2x3.mdl", + "models/nzombies_plates/plate2x4.mdl", + "models/nzombies_plates/plate2x5.mdl", + "models/nzombies_plates/plate2x6.mdl", + "models/nzombies_plates/plate2x7.mdl", + "models/nzombies_plates/plate2x8.mdl", + "models/nzombies_plates/plate2x16.mdl", + "models/nzombies_plates/plate2x24.mdl", + "models/nzombies_plates/plate2x32.mdl", + "models/nzombies_plates/plate3.mdl", + "models/nzombies_plates/plate3x3.mdl", + "models/nzombies_plates/plate3x4.mdl", + "models/nzombies_plates/plate3x5.mdl", + "models/nzombies_plates/plate3x6.mdl", + "models/nzombies_plates/plate3x7.mdl", + "models/nzombies_plates/plate3x8.mdl", + "models/nzombies_plates/plate3x16.mdl", + "models/nzombies_plates/plate3x24.mdl", + "models/nzombies_plates/plate3x32.mdl", + "models/nzombies_plates/plate4.mdl", + "models/nzombies_plates/plate4x4.mdl", + "models/nzombies_plates/plate4x5.mdl", + "models/nzombies_plates/plate4x6.mdl", + "models/nzombies_plates/plate4x7.mdl", + "models/nzombies_plates/plate4x8.mdl", + "models/nzombies_plates/plate4x16.mdl", + "models/nzombies_plates/plate4x24.mdl", + "models/nzombies_plates/plate4x32.mdl", + "models/nzombies_plates/plate5.mdl", + "models/nzombies_plates/plate5x5.mdl", + "models/nzombies_plates/plate5x6.mdl", + "models/nzombies_plates/plate5x7.mdl", + "models/nzombies_plates/plate5x8.mdl", + "models/nzombies_plates/plate5x16.mdl", + "models/nzombies_plates/plate5x24.mdl", + "models/nzombies_plates/plate5x32.mdl", + "models/nzombies_plates/plate6.mdl", + "models/nzombies_plates/plate6x6.mdl", + "models/nzombies_plates/plate6x7.mdl", + "models/nzombies_plates/plate6x8.mdl", + "models/nzombies_plates/plate6x16.mdl", + "models/nzombies_plates/plate6x24.mdl", + "models/nzombies_plates/plate6x32.mdl", + "models/nzombies_plates/plate7.mdl", + "models/nzombies_plates/plate7x7.mdl", + "models/nzombies_plates/plate7x8.mdl", + "models/nzombies_plates/plate7x16.mdl", + "models/nzombies_plates/plate7x24.mdl", + "models/nzombies_plates/plate7x32.mdl", + "models/nzombies_plates/plate8.mdl", + "models/nzombies_plates/plate8x8.mdl", + "models/nzombies_plates/plate8x16.mdl", + "models/nzombies_plates/plate8x24.mdl", + "models/nzombies_plates/plate8x32.mdl", + "models/nzombies_plates/plate16.mdl", + "models/nzombies_plates/plate16x16.mdl", + "models/nzombies_plates/plate16x24.mdl", + "models/nzombies_plates/plate16x32.mdl", + "models/nzombies_plates/plate24x24.mdl", + "models/nzombies_plates/plate24x32.mdl", + "models/nzombies_plates/plate32x32.mdl", + + "models/nzombies_plates/platehole1x1.mdl", + "models/nzombies_plates/platehole1x2.mdl", + "models/nzombies_plates/platehole2x2.mdl", + "models/nzombies_plates/platehole3.mdl", + "models/nzombies_plates/tri1x1.mdl", + "models/nzombies_plates/tri2x1.mdl", + "models/nzombies_plates/tri3x1.mdl", + + "models/nzombies_plates/plate1x3x1trap.mdl", + "models/nzombies_plates/plate1x4x2trap.mdl", + "models/nzombies_plates/plate1x4x2trap1.mdl", +} + +nzTools:CreateTool("block", { + displayname = "Invisible Block Spawner", + desc = "LMB: Create Invisible Block, RMB: Remove Invisible Block, R: Change Model", + condition = function(wep, ply) + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + local ent = tr.Entity + if IsValid(ent) and ent:GetClass() == "wall_block" then + nzMapping:BlockSpawn(ent:GetPos(),ent:GetAngles(), data.model, ply) + ent:Remove() + else + nzMapping:BlockSpawn(tr.HitPos,Angle(90,(tr.HitPos - ply:GetPos()):Angle()[2] + 90,90), data.model, ply) + end + end, + SecondaryAttack = function(wep, ply, tr, data) + if IsValid(tr.Entity) and tr.Entity:GetClass() == "wall_block" then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + if IsValid(tr.Entity) and tr.Entity:GetClass() == "wall_block" then + tr.Entity:SetModel(data.model) + end + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Invisible Block Spawner", + desc = "LMB: Create Invisible Block, RMB: Remove Invisible Block, R: Change Model", + icon = "icon16/shading.png", + weight = 15, + condition = function(wep, ply) + return true + end, + interface = function(frame, data, context) + local Scroll = vgui.Create( "DScrollPanel", frame ) + Scroll:SetSize( 280, 300 ) + Scroll:SetPos( 10, 10 ) + + function Scroll.CompileData() + return {model = data.model} + end + + function Scroll.UpdateData(data) + nzTools:SendData(data, "block", data) -- Save the same data here + end + + local List = vgui.Create( "DIconLayout", Scroll ) + List:SetSize( 340, 200 ) + List:SetPos( 0, 0 ) + List:SetSpaceY( 5 ) + List:SetSpaceX( 5 ) + + local models = models + + for k,v in pairs(models) do + local Blockmodel = List:Add( "SpawnIcon" ) + Blockmodel:SetSize( 40, 40 ) + Blockmodel:SetModel(v) + Blockmodel.DoClick = function() + data.model = v + Scroll.UpdateData(Scroll.CompileData()) + end + Blockmodel.Paint = function(self) + self.OverlayFade = math.Clamp( ( self.OverlayFade or 0 ) - RealFrameTime() * 640 * 2, 0, 255 ) + + if data.model == v or self:IsHovered() then + self.OverlayFade = math.Clamp( self.OverlayFade + RealFrameTime() * 640 * 8, 0, 255 ) + end + end + end + + return Scroll + end, + defaultdata = { + model = "models/nzombies_platess/plate2x2.mdl" + }, +}) + +nzTools:EnableProperties("block", "Edit Model...", "icon16/brick_edit.png", 9009, true, function( self, ent, ply ) + if ( !IsValid( ent ) or !IsValid(ply) ) then return false end + if ( ent:GetClass() != "wall_block" ) then return false end + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( ent:IsPlayer() ) then return false end + if ( !ply:IsInCreative() ) then return false end + + return true + +end, function(ent) + return {model = ent:GetModel()} +end) diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_door.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_door.lua new file mode 100644 index 00000000..62def375 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_door.lua @@ -0,0 +1,139 @@ +nzTools:CreateTool("door", { + displayname = "Door Locker", + desc = "LMB: Apply Door Data, RMB: Remove Door Data, C: Change Properties", + condition = function(wep, ply) + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + PrintTable(data) + local ent = tr.Entity + if !IsValid(ent) then return end + if ent:IsDoor() or ent:IsBuyableProp() or ent:IsButton() then + nzDoors:CreateLink(ent, data.flags) + else + ply:ChatPrint("That is not a valid door.") + end + end, + SecondaryAttack = function(wep, ply, tr, data) + local ent = tr.Entity + if !IsValid(ent) then return end + if ent:IsDoor() or ent:IsBuyableProp() or ent:IsButton() then + nzDoors:RemoveLink(ent) + end + end, + Reload = function(wep, ply, tr, data) + local ent = tr.Entity + if !IsValid(ent) then return end + if ent:IsDoor() or ent:IsBuyableProp() or ent:IsButton() then + nzDoors:DisplayDoorLinks(ent) + end + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Door Locker", + desc = "LMB: Apply Door Data, RMB: Remove Door Data, C: Change Properties", + icon = "icon16/lock.png", + weight = 3, + condition = function(wep, ply) + return true + end, + interface = function(frame, data, context) + local valz = {} + valz["Row1"] = data.flag + valz["Row2"] = data.link + valz["Row3"] = data.price + valz["Row4"] = data.elec + valz["Row5"] = data.buyable + valz["Row6"] = data.rebuyable + + local DProperties = vgui.Create( "DProperties", frame ) + DProperties:SetSize( 280, 260 ) + DProperties:SetPos( 10, 10 ) + + function DProperties.CompileData() + local function compileString(price, elec, flag, buyable, rebuyable) + local str = "price="..price..",elec="..elec + if flag then + str = str..",link="..flag + end + str = str..",buyable="..buyable + str = str..",rebuyable="..rebuyable + return str + end + local flag = false + if valz["Row1"] == 1 then + flag = valz["Row2"] + end + local flagString = compileString(valz["Row3"], valz["Row4"], flag, valz["Row5"], valz["Row6"]) + print(flagString) + + return {flags = flagString} + end + + function DProperties.UpdateData(data) + nzTools:SendData( data, "door", { -- Hardcoded save function, not just the data + flag = valz["Row1"], + link = valz["Row2"], + price = valz["Row3"], + elec = valz["Row4"], + buyable = valz["Row5"], + rebuyable = valz["Row6"], + }) + end + + -- We call it immediately as it would otherwise auto-send our table to the server, not the compiled string + -- Although only if not opened via context menu! Context menu should NOT sync tools, causing tool mismatches! + if !context then DProperties.UpdateData(DProperties.CompileData()) end + + local Row1 = DProperties:CreateRow( "Door Settings", "Enable Flag?" ) + Row1:Setup( "Boolean" ) + Row1:SetValue( valz["Row1"] ) + Row1.DataChanged = function( _, val ) valz["Row1"] = val DProperties.UpdateData(DProperties.CompileData()) end + local Row2 = DProperties:CreateRow( "Door Settings", "Flag" ) + Row2:Setup( "Integer" ) + Row2:SetValue( valz["Row2"] ) + Row2.DataChanged = function( _, val ) valz["Row2"] = val DProperties.UpdateData(DProperties.CompileData()) end + local Row3 = DProperties:CreateRow( "Door Settings", "Price" ) + Row3:Setup( "Integer" ) + Row3:SetValue( valz["Row3"] ) + Row3.DataChanged = function( _, val ) valz["Row3"] = val DProperties.UpdateData(DProperties.CompileData()) end + local Row4 = DProperties:CreateRow( "Door Settings", "Requires Electricity?" ) + Row4:Setup( "Boolean" ) + Row4:SetValue( valz["Row4"] ) + Row4.DataChanged = function( _, val ) valz["Row4"] = val DProperties.UpdateData(DProperties.CompileData()) end + + if nzTools.Advanced then + local Row5 = DProperties:CreateRow( "Advanced Door Settings", "Purchaseable?" ) + Row5:Setup( "Boolean" ) + Row5:SetValue( valz["Row5"] ) + Row5.DataChanged = function( _, val ) valz["Row5"] = val DProperties.UpdateData(DProperties.CompileData()) end + local Row6 = DProperties:CreateRow( "Advanced Door Settings", "Rebuyable?" ) + Row6:Setup( "Boolean" ) + Row6:SetValue( valz["Row6"] ) + Row6.DataChanged = function( _, val ) valz["Row6"] = val DProperties.UpdateData(DProperties.CompileData()) end + else + local text = vgui.Create("DLabel", DProperties) + text:SetText("Enable Advanced Mode for more options.") + text:SetFont("Trebuchet18") + text:SetTextColor( Color(50, 50, 50) ) + text:SizeToContents() + text:Center() + end + + return DProperties + end, + defaultdata = { + flags = "flag=0,price=1000,elec=0,buyable=1,rebuyable=0", + flag = 0, + link = 1, + price = 1000, + elec = 0, + buyable = 1, + rebuyable = 0, + } +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_ee.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_ee.lua new file mode 100644 index 00000000..859c9f9e --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_ee.lua @@ -0,0 +1,36 @@ +nzTools:CreateTool("ee", { + displayname = "Easter Egg Placer", + desc = "LMB: Easter Egg, RMB: Remove Easter Egg, Use Player Handler to select song", + condition = function(wep, ply) + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + nzMapping:EasterEgg(tr.HitPos, Angle(0,0,0), "models/props_lab/huladoll.mdl", ply) + end, + SecondaryAttack = function(wep, ply, tr, data) + if IsValid(tr.Entity) and tr.Entity:GetClass() == "easter_egg" then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + -- Nothing + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Easter Egg Placer", + desc = "LMB: Easter Egg, RMB: Remove Easter Egg, Use Player Handler to select song", + icon = "icon16/music.png", + weight = 20, + condition = function(wep, ply) + return true + end, + interface = function(frame, data) + + end, + --defaultdata = {} +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_elec.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_elec.lua new file mode 100644 index 00000000..7a87e529 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_elec.lua @@ -0,0 +1,38 @@ +nzTools:CreateTool("elec", { + displayname = "Electricity Switch Placer", + desc = "LMB: Place Electricity Switch, RMB: Remove Switch", + condition = function(wep, ply) + return true + end, + + PrimaryAttack = function(wep, ply, tr, data) + nzMapping:Electric(tr.HitPos + tr.HitNormal*5, tr.HitNormal:Angle(), nil, ply) + end, + + SecondaryAttack = function(wep, ply, tr, data) + if IsValid(tr.Entity) and tr.Entity:GetClass() == "power_box" then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + -- Nothing + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Electricity Switch Placer", + desc = "LMB: Place Electricity Switch, RMB: Remove Switch", + icon = "icon16/lightning.png", + weight = 8, + condition = function(wep, ply) + return true + end, + interface = function(frame, data) + + end, + --defaultdata = {} +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_invisdamagewall.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_invisdamagewall.lua new file mode 100644 index 00000000..e5f04d8f --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_invisdamagewall.lua @@ -0,0 +1,150 @@ +local mat = Material("color") +local white = Color(255,0,0,50) +local point1, point2, height + +-- Networking is in the invis wall tool, the bool makes it a normal invis wall + +nzTools:CreateTool("damagewall", { + displayname = "Damage Wall Creator", + desc = "LMB: Set Corners, RMB: Remove Damage Wall at spot, R: Reset corners", + condition = function(wep, ply) + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + + end, + SecondaryAttack = function(wep, ply, tr, data) + local walls = ents.FindInSphere(tr.HitPos, 5) + for k,v in pairs(walls) do + if v:GetClass() == "invis_damage_wall" then v:Remove() end + end + end, + Reload = function(wep, ply, tr, data) + + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Damage Wall Creator", + desc = "LMB: Set Corners, RMB: Remove Damage Wall at spot, R: Reset corners", + icon = "icon16/shape_square_error.png", + weight = 17, + condition = function(wep, ply) + return nzTools.Advanced + end, + interface = function(frame, data) + end, + PrimaryAttack = function(wep, ply, tr, data) + local pos = tr.HitPos + if !pos then return end + + if !point1 then + point1 = pos + elseif !point2 then + point2 = Vector(pos.x - point1.x, pos.y - point1.y, point1.z) + elseif !height then + height = pos.z - point1.z + net.Start("nz_InvisWallCreation") + net.WriteVector(point1) + net.WriteVector(Vector(point2.x, point2.y, height)) + net.WriteBool(false) + net.SendToServer() + point1 = nil + point2 = nil + height = nil + end + end, + Reload = function() + point1 = nil + point2 = nil + height = nil + end, + interface = function(frame, data) + local pnl = vgui.Create("DPanel", frame) + pnl:Dock(FILL) + + + + local data = data or {} + + local valz = {} + if data then + valz["Dmg"] = data.dmg or 10 + valz["Delay"] = data.delay or 0.5 + valz["DmgType"] = data.dmgtype or 1 + end + + function pnl.CompileData() + data.dmg = valz["Dmg"] + data.delay = valz["Delay"] + data.dmgtype = valz["DmgType"] + + return data + end + + function pnl.UpdateData(data) + nzTools:SendData(data, "damagewall", data) -- Save the same data here + end + + local chk = vgui.Create("DCheckBoxLabel", pnl) + chk:SetPos( 100, 20 ) + chk:SetText( "Preview Config" ) + chk:SetTextColor( Color(50,50,50) ) + chk:SetConVar( "nz_creative_preview" ) + chk:SetValue( GetConVar("nz_creative_preview"):GetBool() ) + chk:SizeToContents() + + local properties = vgui.Create("DProperties", pnl) + properties:SetPos(5, 50) + properties:SetSize(290, 100) + + local dmg = properties:CreateRow( "Damage Properties", "Damage" ) + dmg:Setup( "Int", {min = 1, max = 250} ) + dmg:SetValue( data.dmg ) + dmg.DataChanged = function( _, val ) valz["Dmg"] = val pnl.UpdateData(pnl.CompileData()) end + + local delay = properties:CreateRow( "Damage Properties", "Delay" ) + delay:Setup( "Float", {min = 0, max = 10} ) + delay:SetValue( data.delay ) + delay.DataChanged = function( _, val ) valz["Delay"] = val pnl.UpdateData(pnl.CompileData()) end + + local dmgtype = properties:CreateRow( "Damage Properties", "Type" ) + dmgtype:Setup( "Combo", {text = "Select type ..."} ) + dmgtype:AddChoice( "Radiation", 1 ) + dmgtype:AddChoice( "Poison", 2 ) + dmgtype:AddChoice( "Tesla", 3 ) + dmgtype.DataChanged = function( _, val ) valz["DmgType"] = val pnl.UpdateData(pnl.CompileData()) end + + return pnl + end, + drawhud = function() + cam.Start3D() + render.SetMaterial(mat) + local x = point1 or nil + local y + if x then + if point2 then + if height then + y = Vector(point2.x, point2.y, height) + else + y = Vector(point2.x, point2.y, LocalPlayer():GetEyeTrace().HitPos.z - point1.z) + end + else + y = Vector(LocalPlayer():GetEyeTrace().HitPos.x - point1.x, LocalPlayer():GetEyeTrace().HitPos.y - point1.y, 0) + end + end + if x and y then + render.DrawBox(x, Angle(0,0,0), Vector(0,0,0), y, white, true) + end + cam.End3D() + end, + defaultdata = { + dmg = 10, + delay = 0.5, + dmgtype = 1, + } +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_inviswall.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_inviswall.lua new file mode 100644 index 00000000..93b787fd --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_inviswall.lua @@ -0,0 +1,133 @@ +local mat = Material("color") +local white = Color(255,150,0,50) +local point1, point2, height + +if SERVER then + util.AddNetworkString("nz_InvisWallCreation") + + net.Receive("nz_InvisWallCreation", function(len, ply) + if !ply:IsInCreative() then return end + local vec1 = net.ReadVector() + local vec2 = net.ReadVector() + + if net.ReadBool() then + nzMapping:CreateInvisibleWall(vec1, vec2, ply) + else + local data = ply.NZToolData + local radiation = data.dmgtype == 1 + local poison = data.dmgtype == 2 + local tesla = data.dmgtype == 3 + nzMapping:CreateInvisibleDamageWall(vec1, vec2, ply, data.dmg or 1, data.delay or 0.5, radiation, poison, tesla) + end + end) +end + +nzTools:CreateTool("inviswall", { + displayname = "Invisible Wall Creator", + desc = "LMB: Set Corners, RMB: Remove Invisible Wall at spot, R: Reset corners", + condition = function(wep, ply) + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + + end, + SecondaryAttack = function(wep, ply, tr, data) + local walls = ents.FindInSphere(tr.HitPos, 5) + for k,v in pairs(walls) do + if v:GetClass() == "invis_wall" then v:Remove() end + end + end, + Reload = function(wep, ply, tr, data) + + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Invisible Wall Creator", + desc = "LMB: Set Corners, RMB: Remove Invisible Wall at spot, R: Reset corners", + icon = "icon16/shape_handles.png", + weight = 16, + condition = function(wep, ply) + return true + end, + interface = function(frame, data) + end, + PrimaryAttack = function(wep, ply, tr, data) + local pos = tr.HitPos + if !pos then return end + + if !point1 then + point1 = pos + elseif !point2 then + point2 = Vector(pos.x - point1.x, pos.y - point1.y, point1.z) + elseif !height then + height = pos.z - point1.z + net.Start("nz_InvisWallCreation") + net.WriteVector(point1) + net.WriteVector(Vector(point2.x, point2.y, height)) + net.WriteBool(true) + net.SendToServer() + point1 = nil + point2 = nil + height = nil + end + end, + Reload = function() + point1 = nil + point2 = nil + height = nil + end, + interface = function(frame, data) + local pnl = vgui.Create("DPanel", frame) + pnl:Dock(FILL) + + local chk = vgui.Create("DCheckBoxLabel", pnl) + chk:SetPos( 100, 50 ) + chk:SetText( "Preview Config" ) + chk:SetTextColor( Color(50,50,50) ) + chk:SetConVar( "nz_creative_preview" ) + chk:SetValue( GetConVar("nz_creative_preview"):GetBool() ) + chk:SizeToContents() + + local textw = vgui.Create("DLabel", pnl) + textw:SetText("Warning: Rotating Invis Walls does not work") + textw:SetFont("Trebuchet18") + textw:SetTextColor( Color(150, 50, 50) ) + textw:SizeToContents() + textw:SetPos(30, 70) + + local textw2 = vgui.Create("DLabel", pnl) + textw2:SetText("correctly at the moment and will not save!") + textw2:SetFont("Trebuchet18") + textw2:SetTextColor( Color(150, 50, 50) ) + textw2:SizeToContents() + textw2:SetPos(32, 80) + + return pnl + end, + drawhud = function() + cam.Start3D() + render.SetMaterial(mat) + local x = point1 or nil + local y + if x then + if point2 then + if height then + y = Vector(point2.x, point2.y, height) + else + y = Vector(point2.x, point2.y, LocalPlayer():GetEyeTrace().HitPos.z - point1.z) + end + else + y = Vector(LocalPlayer():GetEyeTrace().HitPos.x - point1.x, LocalPlayer():GetEyeTrace().HitPos.y - point1.y, 0) + end + end + if x and y then + render.DrawBox(x, Angle(0,0,0), Vector(0,0,0), y, white, true) + end + cam.End3D() + end, +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_nav.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_nav.lua new file mode 100644 index 00000000..716422c9 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_nav.lua @@ -0,0 +1,358 @@ +nzTools:CreateTool("navedit", { + displayname = "Navmesh Editor", + desc = "Q: Select edit mode", + condition = function(wep, ply) + return true + end, + + PrimaryAttack = function(wep, ply, tr, data) + if data.Primary then + RunConsoleCommand(data.Primary) + end + end, + + SecondaryAttack = function(wep, ply, tr, data) + if data.Secondary then + RunConsoleCommand(data.Secondary) + end + end, + Reload = function(wep, ply, tr, data) + if data.Reload then + RunConsoleCommand(data.Reload) + else + RunConsoleCommand("nav_mark") + end + end, + OnEquip = function(wep, ply, data) + if wep.Owner:IsListenServerHost() then + RunConsoleCommand("nav_edit", 1) + end + end, + OnHolster = function(wep, ply, data) + if SERVER and wep.Owner:IsListenServerHost() then + RunConsoleCommand("nav_edit", 0) + end + end +}, { + displayname = "Navmesh Editor", + desc = "Q: Select edit mode", + icon = "icon16/map.png", + weight = 39, + condition = function(wep, ply) + return nzTools.Advanced + end, + interface = function(frame, data) + + local cont = vgui.Create("DScrollPanel", frame) + cont:Dock(FILL) + + function cont.CompileData() + return data + end + + function cont.UpdateData(data) + nzTools:SendData(data, "navedit") -- Save the same data here + end + + --command and mode declaration + + local modes = { + ["Change Attributes"] = { + Primary = "nav_jump", + PrimaryDesc = "Toggle jumping", + Secondary = "nav_no_jump", + SecondaryDesc = "Toggle no jumping" + }, + ["Delete Area"] = { + Primary = "nav_delete", + PrimaryDesc = "Delete Area" + }, + ["Corners"] = { + Primary = "nav_corner_place_on_ground", + PrimaryDesc = "Lower corner to ground" + }, + ["Edit Area"] = { + Primary = "nav_split", + PrimaryDesc = "Split an area at the white line", + Secondary = "nav_merge", + SecondaryDesc = "Merge 2 areas" + }, + ["Create Areas"] = { + Primary = "nav_begin_area", + PrimaryDesc = "Begin area creation", + Secondary = "nav_end_area", + SecondaryDesc = "End area creation" + }, + ["Connect Areas"] = { + Primary = "nav_connect", + PrimaryDesc = "Add a 1-way connection", + Secondary = "nav_disconnect", + SecondaryDesc = "Remove a connection" + }, + ["Ladder"] = { + Primary = "nav_build_ladder", + PrimaryDesc = "Build a navmesh for a ladder" + }, + ["Splice"] = { + Primary = "nav_splice", + PrimaryDesc = "Splice 2 areas together", + Secondary = "nav_split", + SecondaryDesc = "Split an area at the white line", + } + } + + local commands = { + ["Build Ladder"] = "nav_build_ladder", + ["Toggle jump area"] = "nav_jump", + ["Toggle no jump area"] = "nav_no_jump", + ["Begin Area Creation"] = "nav_begin_area", + ["End Area Creation"] = "nav_end_area", + ["Merge Areas"] = "nav_merge", + ["Place Corner on Ground"] = "nav_corner_place_on_ground", + ["Connect Areas"] = "nav_connect", + ["Disconnect Areas"] = "nav_disconnect", + ["Delete Area"] = "nav_delete", + ["Split Area"] = "nav_split", + ["Mark Area"] = "nav_mark", + ["Generate Incremental"] = "nav_generate_incremental", + ["Clear Selected Set"] = "nav_clear_selected_set", + ["Mark Walkable"] = "nav_mark_walkable", + } + + --update helper + + local function UpdateDesc() + local result = "" + if data.PrimaryDesc then + result = "LMB: " .. data.PrimaryDesc + end + if data.SecondaryDesc then + if result != "" then + result = result .. ", " + end + result = result .. "RMB: " .. data.SecondaryDesc + end + if data.ReloadDesc then + if result != "" then + result = result .. ", " + end + result = result .. "R: " .. data.ReloadDesc + else + if result != "" then + result = result .. ", " + end + result = result .. "R: Mark area" + end + nzTools.ToolData["navedit"].desc = result + end + + --"basic" stuff + + local basicCat = vgui.Create( "DCollapsibleCategory", cont ) + basicCat:SetExpanded( 1 ) + basicCat:SetLabel( "Basics" ) + basicCat:Dock(TOP) + + local basic = vgui.Create("DListLayout", cont) + basic:Dock(TOP) + basic:DockMargin(5,5,5,5) + + local modePnl = basic:Add( "DPanel" ) + modePnl:Dock(TOP) + + local modeLbl = modePnl:Add( "DLabel" ) + modeLbl:SetText("Select edit mode:") + modeLbl:SetDark(true) + modeLbl.Paint = function() end + modeLbl:Dock(LEFT) + modeLbl:SizeToContents() + + local mode = modePnl:Add( "DComboBox" ) + mode:Dock(TOP) + for k,v in pairs(modes) do + mode:AddChoice(k,v) + end + mode:AddChoice("Custom") + + -- custom mode + + local custom = basic:Add( "DPanel" ) + custom:Dock(TOP) + custom:SetVisible(false) + + local primCust = custom:Add( "DComboBox" ) + primCust:Dock(LEFT) + for k,v in pairs(commands) do + primCust:AddChoice(v, k) + end + primCust:SetValue("Primary") + + local secCust = custom:Add( "DComboBox" ) + secCust:Dock(LEFT) + for k,v in pairs(commands) do + secCust:AddChoice(v, k) + end + secCust:SetValue("Secondary") + + local reCust = custom:Add( "DComboBox" ) + reCust:Dock(LEFT) + for k,v in pairs(commands) do + reCust:AddChoice(v, k) + end + reCust:SetValue("Reload") + + local subCust = custom:Add( "DButton" ) + subCust:Dock(LEFT) + subCust:SetText("Submit") + function subCust:DoClick() + if primCust:GetValue() != "Primary" then + data.Primary, data.PrimaryDesc = primCust:GetSelected() + end + if secCust:GetValue() != "Secondary" then + data.Secondary, data.SecondaryDesc = secCust:GetSelected() + end + if reCust:GetValue() != "Reload" then + data.Reload, data.ReloadDesc = reCust:GetSelected() + end + UpdateDesc() + cont.UpdateData(cont.CompileData()) + end + + -- end custom mode + + -- basic settings + local settingsPnl = basic:Add( "DListLayout" ) + settingsPnl:Dock(TOP) + settingsPnl:DockMargin(0,10,0,0) + + local settingsLbl = settingsPnl:Add( "DLabel" ) + settingsLbl:SetText("Settings:") + settingsLbl:SetDark(true) + settingsLbl.Paint = function() end + settingsLbl:Dock(TOP) + settingsLbl:SetContentAlignment(5) + + local snapGrid = settingsPnl:Add("DNumSlider") + snapGrid:Dock(TOP) + snapGrid:SetText("Snap to Grid") + snapGrid:SetMin(0) + snapGrid:SetMax(2) + snapGrid:SetDecimals(0) + snapGrid:SetDark(true) + snapGrid:SetConVar("nav_snap_to_grid") + + local showInfo = settingsPnl:Add("DNumSlider") + showInfo:Dock(TOP) + showInfo:SetText("Display area info (sec)") + showInfo:SetMin(0) + showInfo:SetMax(60) + showInfo:SetDecimals(1) + showInfo:SetDark(true) + showInfo:SetConVar("nav_show_area_info") + + local cvars = { + ["Place created areas on ground"] = "nav_create_place_on_ground", + ["Place splitted areas on ground"] = "nav_split_place_on_ground", + ["Show Compass"] = "nav_show_compass" + } + + for k,v in pairs(cvars) do + local cvar = settingsPnl:Add( "DCheckBoxLabel" ) + cvar:SetConVar(v) + cvar:SetText(k) + cvar:SizeToContents() + cvar:SetDark(true) + cvar:Dock(TOP) + end + + -- end settings + + function mode:OnSelect(index, name, val) + if name == "Custom" then + custom:SetVisible(true) + else + custom:SetVisible(false) + data.Primary = val.Primary + data.Secondary = val.Secondary + data.PrimaryDesc = val.PrimaryDesc + data.SecondaryDesc = val.SecondaryDesc + UpdateDesc() + cont.UpdateData(cont.CompileData()) + end + end + + basicCat:SetContents(basic) + + --danger zone + + local dangerCat = vgui.Create( "DCollapsibleCategory", cont ) + dangerCat:SetExpanded( 1 ) + dangerCat:SetLabel( "Danger Zone" ) + dangerCat:Dock(TOP) + + local danger = vgui.Create("DListLayout", cont) + danger:Dock(TOP) + danger:DockMargin(5,5,5,5) + + local innerPnl = danger:Add("DPanel") + innerPnl:Dock(TOP) + + local save = innerPnl:Add("DButton") + save:Dock(FILL) + save:SetText("Save") + save:SetConsoleCommand("nav_save") + save:SizeToContents() + + local gen = innerPnl:Add("DButton") + gen:Dock(LEFT) + gen:SetText("Generate") + gen:SizeToContents() + gen:DockPadding(5,0,5,0) + gen:SetConsoleCommand("say", "/generate") + + local analyze = innerPnl:Add("DButton") + analyze:Dock(RIGHT) + analyze:SetText("Analyze") + analyze:SizeToContents() + analyze:DockPadding(5,0,5,0) + analyze:SetConsoleCommand("nav_analyze") + + local quick = danger:Add("DCheckBoxLabel") + quick:SetConVar("nav_quicksave") + quick:SetText("Enable quicksave") + quick:SizeToContents() + quick:SetDark(true) + quick:Dock(TOP) + quick:DockMargin(0,10,0,0) + + dangerCat:SetContents(danger) + + + -- end danger zone + + --"advanced" stuff + + local advCat = vgui.Create( "DCollapsibleCategory", cont ) + advCat:SetExpanded( 0 ) + advCat:SetLabel( "Quick Commands" ) + advCat:Dock(TOP) + + local adv = vgui.Create("DListLayout", cont) + adv:Dock(TOP) + + for k,v in pairs(commands) do + local btn = vgui.Create("DButton") + btn:SetText(k) + btn:Dock(TOP) + btn:DockMargin(5,5,5,0) + btn:SetConsoleCommand(v) + adv:Add(btn) + end + + advCat:SetContents(adv) + + return cont + end, + defaultdata = { + } +}) diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_navlock.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_navlock.lua new file mode 100644 index 00000000..41077496 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_navlock.lua @@ -0,0 +1,191 @@ +nzTools:CreateTool("navlock", { + displayname = "Nav Locker Tool", + desc = "LMB: Connect doors and navmeshes, RMB: Lock/Unlock navmeshes", + condition = function(wep, ply) + -- Serverside doesn't need to block + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + local pos = tr.HitPos + if tr.HitWorld or wep.Owner:KeyDown(IN_SPEED) then + if !IsValid(wep.Ent1) then wep.Owner:ChatPrint("You need to mark a door first to link an area.") return end + local navarea = navmesh.GetNearestNavArea(pos) + local id = navarea:GetID() + + nzNav.Locks[id] = { + locked = true, + link = wep.Ent1:GetDoorData().link + } + + wep.Owner:ChatPrint("Navmesh ["..id.."] locked to door "..wep.Ent1:GetClass().."["..wep.Ent1:EntIndex().."] with link ["..wep.Ent1:GetDoorData().link.."]!") + wep.Ent1:SetMaterial( "" ) + wep.Ent1 = nil + return end + + local ent = tr.Entity + if !IsNavApplicable(ent) then + wep.Owner:ChatPrint("Only buyable props, doors, and buyable buttons with LINKS can be linked to navareas.") + return end + + if IsValid(wep.Ent1) and wep.Ent1 != ent then + wep.Ent1:SetMaterial( "" ) + end + + wep.Ent1 = ent + ent:SetMaterial( "hunter/myplastic.vtf" ) + end, + SecondaryAttack = function(wep, ply, tr, data) + if(!tr.HitPos)then return false end + local pos = tr.HitPos + local navarea = navmesh.GetNearestNavArea(pos) + local navid = navarea:GetID() + + if nzNav.Locks[navid] then + wep.Owner:ChatPrint("Navmesh ["..navid.."] unlocked!") + nzNav.Locks[navid] = nil + return end + + nzNav.Locks[navid] = { + locked = true, + link = nil + } + + wep.Owner:ChatPrint("Navmesh ["..navid.."] locked!") + end, + Reload = function(wep, ply, tr, data) + -- Nothing + end, + OnEquip = function(wep, ply, data) + if wep.Owner:IsListenServerHost() then + RunConsoleCommand("nav_edit", 1) + end + end, + OnHolster = function(wep, ply, data) + if SERVER and wep.Owner:IsListenServerHost() then + RunConsoleCommand("nav_edit", 0) + end + return true + end, + Think = function() + if GetConVar("nav_edit"):GetBool() and GetConVar("developer"):GetBool() then + local pos = navmesh.GetEditCursorPosition() + local area = navmesh.GetNearestNavArea(pos) + local id = area:GetID() + + local tbl = nzNav.Locks[id] + if tbl then + if tbl.locked then + if tbl.link then + debugoverlay.Sphere(area:GetCenter(), 10, 0.1, Color(0,255,0,50)) + else + debugoverlay.Sphere(area:GetCenter(), 10, 0.1, Color(255,0,0,50)) + end + end + end + end + end +}, { + displayname = "Nav Locker Tool", + desc = "LMB: Connect doors and navmeshes, RMB: Lock/Unlock navmeshes", + icon = "icon16/arrow_switch.png", + weight = 40, + condition = function(wep, ply) + -- Client needs advanced editing on to see the tool + return nzTools.Advanced + end, + interface = function(frame, data) + local panel = vgui.Create("DPanel", frame) + panel:SetSize(frame:GetSize()) + + local textw = vgui.Create("DLabel", panel) + textw:SetText("You need to be in a listen/local server to be") + textw:SetFont("Trebuchet18") + textw:SetTextColor( Color(150, 50, 50) ) + textw:SizeToContents() + textw:SetPos(0, 20) + textw:CenterHorizontal() + + local textw2 = vgui.Create("DLabel", panel) + textw2:SetText("able to see the Navmeshes!") + textw2:SetFont("Trebuchet18") + textw2:SetTextColor( Color(150, 50, 50) ) + textw2:SizeToContents() + textw2:SetPos(0, 30) + textw2:CenterHorizontal() + + local textw3 = vgui.Create("DLabel", panel) + textw3:SetText("sv_cheats is needed in multiplayer.") + textw3:SetFont("Trebuchet18") + textw3:SetTextColor( Color(150, 50, 50) ) + textw3:SizeToContents() + textw3:SetPos(0, 50) + textw3:CenterHorizontal() + + local textw4 = vgui.Create("DLabel", panel) + textw4:SetText("The tool can still be used blindly") + textw4:SetFont("Trebuchet18") + textw4:SetTextColor( Color(50, 50, 50) ) + textw4:SizeToContents() + textw4:SetPos(0, 60) + textw4:CenterHorizontal() + + local textw5 = vgui.Create("DLabel", panel) + textw5:SetText("Console 'developer 1' is needed to see navlocks.") + textw5:SetFont("Trebuchet18") + textw5:SetTextColor( Color(150, 50, 50) ) + textw5:SizeToContents() + textw5:SetPos(0, 80) + textw5:CenterHorizontal() + + local text = vgui.Create("DLabel", panel) + text:SetText("Right click on the ground to lock a Navmesh") + text:SetFont("Trebuchet18") + text:SetTextColor( Color(50, 50, 50) ) + text:SizeToContents() + text:SetPos(0, 120) + text:CenterHorizontal() + + local text2 = vgui.Create("DLabel", panel) + text2:SetText("Left click a door to mark the door") + text2:SetFont("Trebuchet18") + text2:SetTextColor( Color(50, 50, 50) ) + text2:SizeToContents() + text2:SetPos(0, 160) + text2:CenterHorizontal() + + local text3 = vgui.Create("DLabel", panel) + text3:SetText("then left click the ground to link") + text3:SetFont("Trebuchet18") + text3:SetTextColor( Color(50, 50, 50) ) + text3:SizeToContents() + text3:SetPos(0, 170) + text3:CenterHorizontal() + + local text4 = vgui.Create("DLabel", panel) + text4:SetText("the Navmesh with the door") + text4:SetFont("Trebuchet18") + text4:SetTextColor( Color(50, 50, 50) ) + text4:SizeToContents() + text4:SetPos(0, 180) + text4:CenterHorizontal() + + local text5 = vgui.Create("DLabel", panel) + text5:SetText("Zombies can't pathfind through locked Navmeshes") + text5:SetFont("Trebuchet18") + text5:SetTextColor( Color(50, 50, 50) ) + text5:SizeToContents() + text5:SetPos(0, 210) + text5:CenterHorizontal() + + local text6 = vgui.Create("DLabel", panel) + text6:SetText("unless their door link is opened") + text6:SetFont("Trebuchet18") + text6:SetTextColor( Color(50, 50, 50) ) + text6:SizeToContents() + text6:SetPos(0, 220) + text6:CenterHorizontal() + + return panel + end, + //defaultdata = {} +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_perk.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_perk.lua new file mode 100644 index 00000000..a358cd74 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_perk.lua @@ -0,0 +1,80 @@ +nzTools:CreateTool("perk", { + displayname = "Perk Machine Placer", + desc = "LMB: Place Perk Machine, RMB: Remove Perk Machine, C: Change Perk", + condition = function(wep, ply) + return true + end, + + PrimaryAttack = function(wep, ply, tr, data) + local ent = tr.Entity + if IsValid(ent) and ent:GetClass() == "perk_machine" or ent:GetClass() == "wunderfizz_machine" then + nzMapping:PerkMachine(ent:GetPos(), ent:GetAngles(), data.perk, ply) -- Hitting a perk, replace it + ent:Remove() + else + nzMapping:PerkMachine(tr.HitPos, Angle(0,(ply:GetPos() - tr.HitPos):Angle()[2],0), data.perk, ply) + end + end, + + SecondaryAttack = function(wep, ply, tr, data) + local ent = tr.Entity + if IsValid(ent) and ent:GetClass() == "perk_machine" or ent:GetClass() == "wunderfizz_machine" then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + -- Nothing + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Perk Machine Placer", + desc = "LMB: Place Perk Machine, RMB: Remove Perk Machine, C: Change Perk", + icon = "icon16/drink.png", + weight = 6, + condition = function(wep, ply) + return true + end, + interface = function(frame, data, context) + + local choices = vgui.Create( "DComboBox", frame ) + choices:SetPos( 10, 10 ) + choices:SetSize( 280, 30 ) + choices:SetValue( nzPerks:Get(data.perk).name ) + for k,v in pairs(nzPerks:GetList()) do + choices:AddChoice( v, k ) + end + + function choices.CompileData() + return data + end + + function choices.UpdateData(data) + nzTools:SendData(data, "perk") + end + + choices.OnSelect = function( panel, index, value, id ) + data.perk = id + choices.UpdateData(choices.CompileData()) + end + + return choices + end, + defaultdata = {perk = "jugg"}, +}) + +nzTools:EnableProperties("perk", "Edit Perk...", "icon16/tag_blue_edit.png", 9005, true, function( self, ent, ply ) + if ( !IsValid( ent ) or !IsValid(ply) ) then return false end + if ( ent:GetClass() != "perk_machine" ) then return false end + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( ent:IsPlayer() ) then return false end + if ( !ply:IsInCreative() ) then return false end + + return true + +end, function(ent) + return {perk = ent:GetPerkID()} +end) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_propremover.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_propremover.lua new file mode 100644 index 00000000..ec2d12cb --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_propremover.lua @@ -0,0 +1,166 @@ + +if SERVER then + util.AddNetworkString("nzPropRemoverSearch") + + net.Receive("nzPropRemoverSearch", function(len, ply) + if ply:IsInCreative() then + local tbl = net.ReadTable() + PrintTable(tbl) + for k,v in pairs(tbl) do + local id = k:MapCreationID() + if IsValid(k) and k != Entity(0) and id != -1 then + if v and !nzMapping.MarkedProps[id] then + ply:ChatPrint("Marked "..k:GetClass().." ["..k:EntIndex().."] for removal (ID: "..id..").") + k:SetColor(Color(200,0,0)) + nzMapping.MarkedProps[id] = true + elseif !v and nzMapping.MarkedProps[id] then + ply:ChatPrint("Unmarked "..k:GetClass().." ["..k:EntIndex().."] for removal (ID: "..id..").") + k:SetColor(Color(255,255,255)) + nzMapping.MarkedProps[id] = nil + end + end + end + end + end) + +else + + local function CreateWindowEntityList() + local tbl = net.ReadTable() + + local frame = vgui.Create("DFrame") + frame:SetSize(300, 300) + frame:SetTitle("Mark props for removal ...") + frame:Center() + frame:MakePopup() + + local entlist = vgui.Create("DScrollPanel", frame) + entlist:SetPos(10, 30) + entlist:SetSize(280, 230) + entlist:SetPaintBackground(true) + entlist:SetBackgroundColor( Color(200, 200, 200) ) + + local entchecklist = vgui.Create( "DIconLayout", entlist ) + entchecklist:SetSize( 265, 250 ) + entchecklist:SetPos( 5, 5 ) + entchecklist:SetSpaceY( 5 ) + entchecklist:SetSpaceX( 5 ) + + for k,v in pairs(tbl) do + if IsValid(k) and string.sub(k:GetClass(), 1, 5) != "class" then + local entity = entchecklist:Add( "DPanel" ) + entity:SetSize( 130, 20 ) + + local check = entity:Add("DCheckBox") + check:SetPos(2,2) + check:SetValue(v) + check.OnChange = function(self, val) + tbl[k] = val + end + check:SetTooltip(tostring(k)) + + local name = entity:Add("DLabel") + name:SetTextColor(Color(50,50,50)) + name:SetSize(105, 20) + name:SetPos(20,1) + name:SetText(k:GetClass()) + name:SetTooltip(tostring(k)) + end + end + + local submit = vgui.Create("DButton", frame) + submit:SetSize(200, 25) + submit:SetText("Submit") + submit:SetPos(50, 265) + submit.DoClick = function(self) + net.Start("nzPropRemoverSearch") + net.WriteTable(tbl) + net.SendToServer() + end + end + net.Receive("nzPropRemoverSearch", CreateWindowEntityList) + +end + + +nzTools:CreateTool("propremover", { + displayname = "Prop Remover Tool", + desc = "LMB: Mark Prop for Removal, RMB: Unmark Prop, R: Search Entities in 100 unit radius", + condition = function(wep, ply) + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + local ent = tr.Entity + local id = ent:MapCreationID() + if IsValid(ent) and ent != Entity(0) and id != -1 then + ply:ChatPrint("Marked "..ent:GetClass().." ["..ent:EntIndex().."] for removal (ID: "..id..").") + ent:SetColor(Color(200,0,0)) + nzMapping.MarkedProps[id] = true + end + end, + SecondaryAttack = function(wep, ply, tr, data) + local ent = tr.Entity + local id = ent:MapCreationID() + if IsValid(ent) and ent != Entity(0) and id != -1 then + ply:ChatPrint("Unmarked "..ent:GetClass().." ["..ent:EntIndex().."] for removal (ID: "..id..").") + ent:SetColor(Color(255,255,255)) + nzMapping.MarkedProps[id] = nil + end + end, + Reload = function(wep, ply, tr, data) + local tbl = ents.FindInSphere(tr.HitPos, 100) + local send = {} + for k,v in pairs(tbl) do + local id = v:MapCreationID() + if IsValid(v) and v != Entity(0) and id != -1 and string.sub(v:GetClass(), 1, 5) != "class" then + send[v] = nzMapping.MarkedProps[id] or false + end + end + net.Start("nzPropRemoverSearch") + net.WriteTable(send) + net.Send(ply) + end, + OnEquip = function(wep, ply, data) + end, + OnHolster = function(wep, ply, data) + end +}, { + displayname = "Prop Remover Tool", + desc = "LMB: Mark Prop for Removal, RMB: Unmark Prop, R: Search Entities in 100 unit radius", + icon = "icon16/cancel.png", + weight = 35, + condition = function(wep, ply) + return true + end, + interface = function(frame, data) + local panel = vgui.Create("DPanel", frame) + panel:SetSize(frame:GetSize()) + + local textw = vgui.Create("DLabel", panel) + textw:SetText("This tool marks props to be removed in-game.") + textw:SetFont("Trebuchet18") + textw:SetTextColor( Color(50, 50, 50) ) + textw:SizeToContents() + textw:SetPos(0, 80) + textw:CenterHorizontal() + + local textw2 = vgui.Create("DLabel", panel) + textw2:SetText("It will only apply once a game begins") + textw2:SetFont("Trebuchet18") + textw2:SetTextColor( Color(50, 50, 50) ) + textw2:SizeToContents() + textw2:SetPos(0, 100) + textw2:CenterHorizontal() + + local textw3 = vgui.Create("DLabel", panel) + textw3:SetText("and will reset when entering Creative Mode.") + textw3:SetFont("Trebuchet18") + textw3:SetTextColor( Color(50, 50, 50) ) + textw3:SizeToContents() + textw3:SetPos(0, 110) + textw3:CenterHorizontal() + + return panel + end, + -- defaultdata = {} +}) diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_pspawn.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_pspawn.lua new file mode 100644 index 00000000..3793722b --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_pspawn.lua @@ -0,0 +1,34 @@ +nzTools:CreateTool("pspawn", { + displayname = "Player Spawn Creator", + desc = "LMB: Place Spawnpoint, RMB: Remove Spawnpoint", + condition = function(wep, ply) + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + nzMapping:PlayerSpawn(tr.HitPos, ply) + end, + SecondaryAttack = function(wep, ply, tr, data) + if IsValid(tr.Entity) and tr.Entity:GetClass() == "player_spawns" then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + -- Nothing + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Player Spawn Creator", + desc = "LMB: Place Spawnpoint, RMB: Remove Spawnpoint", + icon = "icon16/user.png", + weight = 2, + condition = function(wep, ply) + return true + end, + interface = function(frame, data) end, + -- defaultdata = {} +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_rbox.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_rbox.lua new file mode 100644 index 00000000..3bf4ed22 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_rbox.lua @@ -0,0 +1,61 @@ +nzTools:CreateTool("rbox", { + displayname = "Random Box Spawnpoint", + desc = "LMB: Place Random Box Spawnpoint, RMB: Remove Random Box Spawnpoint", + condition = function(wep, ply) + return true + end, + + PrimaryAttack = function(wep, ply, tr, data) + nzMapping:BoxSpawn(tr.HitPos, Angle(0,(tr.HitPos - ply:GetPos()):Angle()[2] - 90,0), data.PossibleSpawn, ply) + end, + + SecondaryAttack = function(wep, ply, tr, data) + if IsValid(tr.Entity) and tr.Entity:GetClass() == "random_box_spawns" then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + -- Nothing + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Random Box Spawnpoint", + desc = "LMB: Place Random Box Spawnpoint, RMB: Remove Random Box Spawnpoint", + icon = "icon16/briefcase.png", + weight = 4, + condition = function(wep, ply) + return true + end, + interface = function(frame, data) + local valz = {} + valz["Row1"] = data.PossibleSpawn + + local DProperties = vgui.Create( "DProperties", frame ) + DProperties:SetSize( 280, 180 ) + DProperties:SetPos( 10, 10 ) + + function DProperties.CompileData() + data.PossibleSpawn = valz["Row1"] + return data + end + + function DProperties.UpdateData(data) + nzTools:SendData(data, "rbox") + end + + local Row1 = DProperties:CreateRow( "Random Box", "Possible Spawn?" ) + Row1:Setup( "Boolean" ) + Row1:SetValue( valz["Row1"] ) + Row1.DataChanged = function( _, val ) valz["Row1"] = val DProperties.UpdateData(DProperties.CompileData()) end + + return DProperties + end, + defaultdata = { + PossibleSpawn = 0, + } +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_settings.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_settings.lua new file mode 100644 index 00000000..295308aa --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_settings.lua @@ -0,0 +1,526 @@ +nzTools:CreateTool("settings", { + displayname = "Map Settings", + desc = "Use the Tool Interface and press Submit to save changes", + condition = function(wep, ply) + return true + end, + + PrimaryAttack = function(wep, ply, tr, data) + end, + SecondaryAttack = function(wep, ply, tr, data) + end, + Reload = function(wep, ply, tr, data) + end, + OnEquip = function(wep, ply, data) + end, + OnHolster = function(wep, ply, data) + end +}, { + displayname = "Map Settings", + desc = "Use the Tool Interface and press Submit to save changes", + icon = "icon16/cog.png", + weight = 25, + condition = function(wep, ply) + return true + end, + interface = function(frame, data) + local data = table.Copy(nzMapping.Settings) + local valz = {} + valz["Row1"] = data.startwep or "Select ..." + valz["Row2"] = data.startpoints or 500 + valz["Row3"] = data.eeurl or "" + valz["Row4"] = data.script or false + valz["Row5"] = data.scriptinfo or "" + valz["Row6"] = data.gamemodeentities or false + valz["Row7"] = data.specialroundtype or "Hellhounds" + valz["Row8"] = data.bosstype or "Panzer" + valz["RBoxWeps"] = data.RBoxWeps or {} + + local sheet = vgui.Create( "DPropertySheet", frame ) + sheet:SetSize( 280, 250 ) + sheet:SetPos( 10, 10 ) + + local DProperties = vgui.Create( "DProperties", DProperySheet ) + DProperties:SetSize( 280, 250 ) + DProperties:SetPos( 0, 0 ) + sheet:AddSheet( "Map Properties", DProperties, "icon16/cog.png", false, false, "Allows you to set a list of general settings. The Easter Egg Song URL needs to be from Soundcloud.") + + local Row1 = DProperties:CreateRow( "Map Settings", "Starting Weapon" ) + Row1:Setup( "Combo" ) + for k,v in pairs(weapons.GetList()) do + if !v.NZTotalBlacklist then + if v.Category and v.Category != "" then + Row1:AddChoice(v.PrintName and v.PrintName != "" and v.Category.. " - "..v.PrintName or v.ClassName, v.ClassName, false) + else + Row1:AddChoice(v.PrintName and v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, false) + end + end + end + if data.startwep then + local wep = weapons.Get(data.startwep) + if !wep then wep = weapons.Get(nzConfig.BaseStartingWeapons[1]) end + if wep.Category and wep.Category != "" then + Row1:AddChoice(wep.PrintName and wep.PrintName != "" and wep.Category.. " - "..wep.PrintName or wep.ClassName, wep.ClassName, false) + else + Row1:AddChoice(wep.PrintName and wep.PrintName != "" and wep.PrintName or wep.ClassName, wep.ClassName, false) + end + end + + Row1.DataChanged = function( _, val ) valz["Row1"] = val end + + local Row2 = DProperties:CreateRow( "Map Settings", "Starting Points" ) + Row2:Setup( "Integer" ) + Row2:SetValue( valz["Row2"] ) + Row2.DataChanged = function( _, val ) valz["Row2"] = val end + + local Row3 = DProperties:CreateRow( "Map Settings", "Easter Egg Song URL" ) + Row3:Setup( "Generic" ) + Row3:SetValue( valz["Row3"] ) + Row3.DataChanged = function( _, val ) valz["Row3"] = val end + Row3:SetTooltip("Add a link to a SoundCloud track to play this when all easter eggs have been found") + + if nzTools.Advanced then + local Row4 = DProperties:CreateRow( "Map Settings", "Includes Map Script?" ) + Row4:Setup( "Boolean" ) + Row4:SetValue( valz["Row4"] ) + Row4.DataChanged = function( _, val ) valz["Row4"] = val end + Row4:SetTooltip("Loads a .lua file with the same name as the config .txt from /lua/nzmapscripts - for advanced developers.") + + local Row5 = DProperties:CreateRow( "Map Settings", "Script Description" ) + Row5:Setup( "Generic" ) + Row5:SetValue( valz["Row5"] ) + Row5.DataChanged = function( _, val ) valz["Row5"] = val end + Row5:SetTooltip("Sets the description displayed when attempting to load the script.") + + local Row6 = DProperties:CreateRow( "Map Settings", "Gamemode Extensions" ) + Row6:Setup( "Boolean" ) + Row6:SetValue( valz["Row6"] ) + Row6.DataChanged = function( _, val ) valz["Row6"] = val end + Row6:SetTooltip("Sets whether the gamemode should spawn in map entities from other gamemodes, such as ZS.") + + local Row7 = DProperties:CreateRow( "Map Settings", "Special Round" ) + Row7:Setup( "Combo" ) + local found = false + for k,v in pairs(nzRound.SpecialData) do + if k == valz["Row7"] then + Row7:AddChoice(k, k, true) + found = true + else + Row7:AddChoice(k, k, false) + end + end + Row7:AddChoice(" None", "None", !found) + Row7.DataChanged = function( _, val ) valz["Row7"] = val end + Row7:SetTooltip("Sets what type of special round will appear.") + + local Row8 = DProperties:CreateRow( "Map Settings", "Boss" ) + Row8:Setup( "Combo" ) + local found = false + for k,v in pairs(nzRound.BossData) do + if k == valz["Row8"] then + Row8:AddChoice(k, k, true) + found = true + else + Row8:AddChoice(k, k, false) + end + end + Row8:AddChoice(" None", "None", !found) + Row8.DataChanged = function( _, val ) valz["Row8"] = val end + Row8:SetTooltip("Sets what type of boss will appear.") + + end + + local function UpdateData() -- Will remain a local function here. There is no need for the context menu to intercept + if !weapons.Get( valz["Row1"] ) then data.startwep = nil else data.startwep = valz["Row1"] end + if !tonumber(valz["Row2"]) then data.startpoints = 500 else data.startpoints = tonumber(valz["Row2"]) end + if !valz["Row3"] or valz["Row3"] == "" then data.eeurl = nil else data.eeurl = valz["Row3"] end + if !valz["Row4"] then data.script = nil else data.script = valz["Row4"] end + if !valz["Row5"] or valz["Row5"] == "" then data.scriptinfo = nil else data.scriptinfo = valz["Row5"] end + if !valz["Row6"] or valz["Row6"] == "0" then data.gamemodeentities = nil else data.gamemodeentities = tobool(valz["Row6"]) end + if !valz["Row7"] then data.specialroundtype = "Hellhounds" else data.specialroundtype = valz["Row7"] end + if !valz["Row8"] then data.bosstype = "Panzer" else data.bosstype = valz["Row8"] end + if !valz["RBoxWeps"] or table.Count(valz["RBoxWeps"]) < 1 then data.rboxweps = nil else data.rboxweps = valz["RBoxWeps"] end + if !valz["WMPerks"] or !valz["WMPerks"][1] then data.wunderfizzperks = nil else data.wunderfizzperks = valz["WMPerks"] end + PrintTable(data) + + nzMapping:SendMapData( data ) + end + + local DermaButton = vgui.Create( "DButton", DProperties ) + DermaButton:SetText( "Submit" ) + DermaButton:SetPos( 0, 185 ) + DermaButton:SetSize( 260, 30 ) + DermaButton.DoClick = UpdateData + + if nzTools.Advanced then + local weplist = {} + local numweplist = 0 + + local rboxpanel = vgui.Create("DPanel", sheet) + sheet:AddSheet( "Random Box Weapons", rboxpanel, "icon16/box.png", false, false, "Allows you to set which weapons appear in the Random Box.") + rboxpanel.Paint = function() return end + + local rbweplist = vgui.Create("DScrollPanel", rboxpanel) + rbweplist:SetPos(0, 0) + rbweplist:SetSize(265, 150) + rbweplist:SetPaintBackground(true) + rbweplist:SetBackgroundColor( Color(200, 200, 200) ) + + local function InsertWeaponToList(name, class, weight, tooltip) + weight = weight or 10 + if IsValid(weplist[class]) then return end + weplist[class] = vgui.Create("DPanel", rbweplist) + weplist[class]:SetSize(265, 16) + weplist[class]:SetPos(0, numweplist*16) + valz["RBoxWeps"][class] = weight + + local dname = vgui.Create("DLabel", weplist[class]) + dname:SetText(name) + dname:SetTextColor(Color(50, 50, 50)) + dname:SetPos(5, 0) + dname:SetSize(250, 16) + + local dhover = vgui.Create("DPanel", weplist[class]) + dhover.Paint = function() end + dhover:SetText("") + dhover:SetSize(265, 16) + dhover:SetPos(0,0) + if tooltip then + dhover:SetTooltip(tooltip) + end + + local dweight = vgui.Create("DNumberWang", weplist[class]) + dweight:SetPos(195, 1) + dweight:SetSize(40, 14) + dweight:SetTooltip("The chance of this weapon appearing in the box") + dweight:SetMinMax( 1, 100 ) + dweight:SetValue(valz["RBoxWeps"][class]) + function dweight:OnValueChanged(val) + valz["RBoxWeps"][class] = val + end + + local ddelete = vgui.Create("DImageButton", weplist[class]) + ddelete:SetImage("icon16/delete.png") + ddelete:SetPos(235, 0) + ddelete:SetSize(16, 16) + ddelete.DoClick = function() + valz["RBoxWeps"][class] = nil + weplist[class]:Remove() + weplist[class] = nil + local num = 0 + for k,v in pairs(weplist) do + v:SetPos(0, num*16) + num = num + 1 + end + numweplist = numweplist - 1 + end + + numweplist = numweplist + 1 + end + + if nzMapping.Settings.rboxweps then + for k,v in pairs(nzMapping.Settings.rboxweps) do + local wep = weapons.Get(k) + if wep then + if wep.Category and wep.Category != "" then + InsertWeaponToList(wep.PrintName != "" and wep.PrintName or k, k, v or 10, k.." ["..wep.Category.."]") + else + InsertWeaponToList(wep.PrintName != "" and wep.PrintName or k, k, v or 10, k.." [No Category]") + end + end + end + else + for k,v in pairs(weapons.GetList()) do + -- By default, add all weapons that have print names unless they are blacklisted + if v.PrintName and v.PrintName != "" and !nzConfig.WeaponBlackList[v.ClassName] and v.PrintName != "Scripted Weapon" and !v.NZPreventBox and !v.NZTotalBlacklist then + if v.Category and v.Category != "" then + InsertWeaponToList(v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, 10, v.ClassName.." ["..v.Category.."]") + else + InsertWeaponToList(v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, 10, v.ClassName.." [No Category]") + end + end + -- The rest are still available in the dropdown + end + end + + local wepentry = vgui.Create( "DComboBox", rboxpanel ) + wepentry:SetPos( 0, 155 ) + wepentry:SetSize( 146, 20 ) + wepentry:SetValue( "Weapon ..." ) + for k,v in pairs(weapons.GetList()) do + if !v.NZTotalBlacklist and !v.NZPreventBox then + if v.Category and v.Category != "" then + wepentry:AddChoice(v.PrintName and v.PrintName != "" and v.Category.. " - "..v.PrintName or v.ClassName, v.ClassName, false) + else + wepentry:AddChoice(v.PrintName and v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, false) + end + end + end + wepentry.OnSelect = function( panel, index, value ) + end + + local wepadd = vgui.Create( "DButton", rboxpanel ) + wepadd:SetText( "Add" ) + wepadd:SetPos( 150, 155 ) + wepadd:SetSize( 53, 20 ) + wepadd.DoClick = function() + local v = weapons.Get(wepentry:GetOptionData(wepentry:GetSelectedID())) + if v then + if v.Category and v.Category != "" then + InsertWeaponToList(v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, 10, v.ClassName.." ["..v.Category.."]") + else + InsertWeaponToList(v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, 10, v.ClassName.." [No Category]") + end + end + wepentry:SetValue( "Weapon..." ) + end + + local wepmore = vgui.Create( "DButton", rboxpanel ) + wepmore:SetText( "More ..." ) + wepmore:SetPos( 207, 155 ) + wepmore:SetSize( 53, 20 ) + wepmore.DoClick = function() + local morepnl = vgui.Create("DFrame") + morepnl:SetSize(300, 170) + morepnl:SetTitle("More weapon options ...") + morepnl:Center() + morepnl:SetDraggable(true) + morepnl:ShowCloseButton(true) + morepnl:MakePopup() + + local morecat = vgui.Create("DComboBox", morepnl) + morecat:SetSize(150, 20) + morecat:SetPos(10, 30) + local cattbl = {} + for k,v in pairs(weapons.GetList()) do + if v.Category and v.Category != "" then + if !cattbl[v.Category] then + morecat:AddChoice(v.Category, v.Category, false) + cattbl[v.Category] = true + end + end + end + morecat:AddChoice(" Category ...", nil, true) + + local morecatadd = vgui.Create("DButton", morepnl) + morecatadd:SetText( "Add all" ) + morecatadd:SetPos( 165, 30 ) + morecatadd:SetSize( 60, 20 ) + morecatadd.DoClick = function() + local cat = morecat:GetOptionData(morecat:GetSelectedID()) + if cat and cat != "" then + for k,v in pairs(weapons.GetList()) do + if v.Category and v.Category == cat and !nzConfig.WeaponBlackList[v.ClassName] and !v.NZPreventBox and !v.NZTotalBlacklist then + InsertWeaponToList(v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, 10, v.ClassName.." ["..v.Category.."]") + end + end + end + end + + local morecatdel = vgui.Create("DButton", morepnl) + morecatdel:SetText( "Remove all" ) + morecatdel:SetPos( 230, 30 ) + morecatdel:SetSize( 60, 20 ) + morecatdel.DoClick = function() + local cat = morecat:GetOptionData(morecat:GetSelectedID()) + if cat and cat != "" then + for k,v in pairs(weplist) do + local wep = weapons.Get(k) + if wep then + if wep.Category and wep.Category == cat then + valz["RBoxWeps"][k] = nil + weplist[k]:Remove() + weplist[k] = nil + local num = 0 + for k,v in pairs(weplist) do + v:SetPos(0, num*16) + num = num + 1 + end + numweplist = numweplist - 1 + end + end + end + end + end + + local moreprefix = vgui.Create("DComboBox", morepnl) + moreprefix:SetSize(150, 20) + moreprefix:SetPos(10, 60) + local prefixtbl = {} + for k,v in pairs(weapons.GetList()) do + local prefix = string.sub(v.ClassName, 0, string.find(v.ClassName, "_")) + if prefix and !prefixtbl[prefix] then + moreprefix:AddChoice(prefix, prefix, false) + prefixtbl[prefix] = true + end + end + moreprefix:AddChoice(" Prefix ...", nil, true) + + local moreprefixadd = vgui.Create("DButton", morepnl) + moreprefixadd:SetText( "Add all" ) + moreprefixadd:SetPos( 165, 60 ) + moreprefixadd:SetSize( 60, 20 ) + moreprefixadd.DoClick = function() + local prefix = moreprefix:GetOptionData(moreprefix:GetSelectedID()) + if prefix and prefix != "" then + for k,v in pairs(weapons.GetList()) do + local wepprefix = string.sub(v.ClassName, 0, string.find(v.ClassName, "_")) + if wepprefix and wepprefix == prefix and !nzConfig.WeaponBlackList[v.ClassName] and !v.NZPreventBox and !v.NZTotalBlacklist then + if v.Category and v.Category != "" then + InsertWeaponToList(v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, 10, v.ClassName.." ["..v.Category.."]") + else + InsertWeaponToList(v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, 10, v.ClassName.." [No Category]") + end + end + end + end + end + + local moreprefixdel = vgui.Create("DButton", morepnl) + moreprefixdel:SetText( "Remove all" ) + moreprefixdel:SetPos( 230, 60 ) + moreprefixdel:SetSize( 60, 20 ) + moreprefixdel.DoClick = function() + local prefix = moreprefix:GetOptionData(moreprefix:GetSelectedID()) + if prefix and prefix != "" then + for k,v in pairs(weplist) do + local wepprefix = string.sub(k, 0, string.find(k, "_")) + if wepprefix and wepprefix == prefix then + valz["RBoxWeps"][k] = nil + weplist[k]:Remove() + weplist[k] = nil + local num = 0 + for k,v in pairs(weplist) do + v:SetPos(0, num*16) + num = num + 1 + end + numweplist = numweplist - 1 + end + end + end + end + + local removeall = vgui.Create("DButton", morepnl) + removeall:SetText( "Remove all" ) + removeall:SetPos( 10, 100 ) + removeall:SetSize( 140, 25 ) + removeall.DoClick = function() + for k,v in pairs(weplist) do + valz["RBoxWeps"][k] = nil + weplist[k]:Remove() + weplist[k] = nil + numweplist = 0 + end + end + + local addall = vgui.Create("DButton", morepnl) + addall:SetText( "Add all" ) + addall:SetPos( 150, 100 ) + addall:SetSize( 140, 25 ) + addall.DoClick = function() + for k,v in pairs(weplist) do + valz["RBoxWeps"][k] = nil + weplist[k]:Remove() + weplist[k] = nil + numweplist = 0 + end + for k,v in pairs(weapons.GetList()) do + -- By default, add all weapons that have print names unless they are blacklisted + if v.PrintName and v.PrintName != "" and !nzConfig.WeaponBlackList[v.ClassName] and v.PrintName != "Scripted Weapon" and !v.NZPreventBox and !v.NZTotalBlacklist then + if v.Category and v.Category != "" then + InsertWeaponToList(v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, 10, v.ClassName.." ["..v.Category.."]") + else + InsertWeaponToList(v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, 10, v.ClassName.." [No Category]") + end + end + -- The same reset as when no random box list exists on server + end + end + + local reload = vgui.Create("DButton", morepnl) + reload:SetText( "Reload from server" ) + reload:SetPos( 10, 130 ) + reload:SetSize( 280, 25 ) + reload.DoClick = function() + -- Remove all and insert from random box list + for k,v in pairs(weplist) do + valz["RBoxWeps"][k] = nil + weplist[k]:Remove() + weplist[k] = nil + numweplist = 0 + end + if nzMapping.Settings.rboxweps then + for k,v in pairs(nzMapping.Settings.rboxweps) do + local wep = weapons.Get(v) + if wep then + if wep.Category and wep.Category != "" then + InsertWeaponToList(wep.PrintName != "" and wep.PrintName or v, v, 10, v.." ["..v.Category.."]") + else + InsertWeaponToList(wep.PrintName != "" and wep.PrintName or v, v, 10, v.." [No Category]") + end + end + end + end + end + end + + local DermaButton2 = vgui.Create( "DButton", rboxpanel ) + DermaButton2:SetText( "Submit" ) + DermaButton2:SetPos( 0, 185 ) + DermaButton2:SetSize( 260, 30 ) + DermaButton2.DoClick = UpdateData + + local perklist = {} + + local perkpanel = vgui.Create("DPanel", sheet) + sheet:AddSheet( "Wunderfizz Perks", perkpanel, "icon16/drink.png", false, false, "Allows you to set which perks appears in Der Wunderfizz.") + perkpanel.Paint = function() return end + + local perklistpnl = vgui.Create("DScrollPanel", perkpanel) + perklistpnl:SetPos(0, 0) + perklistpnl:SetSize(265, 250) + perklistpnl:SetPaintBackground(true) + perklistpnl:SetBackgroundColor( Color(200, 200, 200) ) + + local perkchecklist = vgui.Create( "DIconLayout", perklistpnl ) + perkchecklist:SetSize( 265, 250 ) + perkchecklist:SetPos( 0, 0 ) + perkchecklist:SetSpaceY( 5 ) + perkchecklist:SetSpaceX( 5 ) + + for k,v in pairs(nzPerks:GetList()) do + if k != "wunderfizz" and k != "pap" then + local perkitem = perkchecklist:Add( "DPanel" ) + perkitem:SetSize( 130, 20 ) + + local check = perkitem:Add("DCheckBox") + check:SetPos(2,2) + local has = nzMapping.Settings.wunderfizzperks and table.HasValue(nzMapping.Settings.wunderfizzperks, k) or 1 + check:SetValue(has) + if has then perklist[k] = true else perklist[k] = nil end + check.OnChange = function(self, val) + if val then perklist[k] = true else perklist[k] = nil end + nzMapping:SendMapData( {wunderfizzperks = perklist} ) + end + + local name = perkitem:Add("DLabel") + name:SetTextColor(Color(50,50,50)) + name:SetSize(105, 20) + name:SetPos(20,1) + name:SetText(v) + end + end + else + local text = vgui.Create("DLabel", DProperties) + text:SetText("Enable Advanced Mode for more options.") + text:SetFont("Trebuchet18") + text:SetTextColor( Color(50, 50, 50) ) + text:SizeToContents() + text:SetPos(0, 140) + text:CenterHorizontal() + end + + return sheet + end, + -- defaultdata = {} +}) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_testzombie.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_testzombie.lua new file mode 100644 index 00000000..0ca1a276 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_testzombie.lua @@ -0,0 +1,116 @@ +nzTools:CreateTool("testzombie", { + displayname = "Spawn Test Zombie", + desc = "LMB: Create a test zombie, RMB: Remove test zombie", + condition = function(wep, ply) + return true + end, + + PrimaryAttack = function(wep, ply, tr, data) + data = data or {speed = 51, type = "nz_zombie_walker"} + PrintTable(data) + local z = ents.Create(data.type) + z:SetPos(tr.HitPos) + z:SetHealth(100) + local oldinit = z.StatsInitialize + z.StatsInitialize = function(self) + oldinit(z) + self:SetRunSpeed(data.speed) + end + z:Spawn() + z:SetRunSpeed(data.speed) + + undo.Create( "Test Zombie" ) + undo.SetPlayer( ply ) + undo.AddEntity( z ) + undo.Finish( "Effect (" .. tostring( model ) .. ")" ) + end, + + SecondaryAttack = function(wep, ply, tr, data) + if IsValid(tr.Entity) and string.find(tr.Entity:GetClass(), "nz_zombie") then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + if IsValid(tr.Entity) and string.find(tr.Entity:GetClass(), "nz_zombie") then + if tr.Entity:GetStop() then tr.Entity:SetStop(false) else tr.Entity:Stop() end + end + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Spawn Test Zombie", + desc = "LMB: Create a test zombie, RMB: Remove test zombie", + icon = "icon16/user_green.png", + weight = 400, + condition = function(wep, ply) + return nzTools.Advanced + end, + interface = function(frame, data) + + local pnl = vgui.Create("DPanel", frame) + pnl:Dock(FILL) + + local txt = vgui.Create("DLabel", pnl) + txt:SetText("Zombie Speed") + txt:SizeToContents() + txt:SetTextColor(Color(0,0,0)) + txt:SetPos(120, 30) + + local slider = vgui.Create("DNumberScratch", pnl) + slider:SetSize(100, 20) + slider:SetPos(130, 50) + slider:SetMin(0) + slider:SetMax(300) + slider:SetValue(data.speed) + + local num = vgui.Create("DNumberWang", pnl) + num:SetValue(data.speed) + num:SetMinMax(0, 300) + num:SetPos(90, 50) + + local txt2 = vgui.Create("DLabel", pnl) + txt2:SetText("Zombie Type") + txt2:SizeToContents() + txt2:SetTextColor(Color(0,0,0)) + txt2:SetPos(120, 90) + + local drop = vgui.Create("DComboBox", pnl) + drop:SetPos(50, 110) + drop:SetSize(200, 20) + for k,v in pairs(nzConfig.ValidEnemies) do + drop:AddChoice(k, k, data.type == k and true or false) + end + for k,v in pairs(nzRound.BossData) do + drop:AddChoice(v, v, data.type == v and true or false) + end + + local function UpdateData() -- No need for context menu to intercept, can remain local + nzTools:SendData( data, "testzombie" ) + end + + slider.OnValueChanged = function(self, val) + data.speed = val + num:SetValue(val) + UpdateData() + end + num.OnValueChanged = function(self, val) + data.speed = val + slider:SetValue(val) + UpdateData() + end + drop.OnSelect = function(self, index, val, id) + data.type = id + UpdateData() + end + + return pnl + end, + defaultdata = { + speed = 51, + type = "nz_zombie_walker", + } +}) diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_wallbuy.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_wallbuy.lua new file mode 100644 index 00000000..489d7974 --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_wallbuy.lua @@ -0,0 +1,104 @@ +nzTools:CreateTool("wallbuy", { + displayname = "Weapon Buy Placer", + desc = "LMB: Place Weapon Buy, RMB: Remove Weapon Buy, R: Rotate, C: Change Properties", + condition = function(wep, ply) + return true + end, + + PrimaryAttack = function(wep, ply, tr, data) + local ent = tr.Entity + if IsValid(ent) and ent:GetClass() == "wall_buys" then + nzMapping:WallBuy(ent:GetPos(), data.class, tonumber(data.price), ent:GetAngles(), nil, ply) + ent:Remove() + else + local ang = tr.HitNormal:Angle() + ang:RotateAroundAxis(tr.HitNormal:Angle():Up()*-1, 90) + nzMapping:WallBuy(tr.HitPos + tr.HitNormal*0.5, data.class, tonumber(data.price), ang, nil, ply) + end + end, + + SecondaryAttack = function(wep, ply, tr, data) + if IsValid(tr.Entity) and tr.Entity:GetClass() == "wall_buys" then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + if IsValid(tr.Entity) and tr.Entity:GetClass() == "wall_buys" then + tr.Entity:ToggleRotate() + end + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Weapon Buy Placer", + desc = "LMB: Place Weapon Buy, RMB: Remove Weapon Buy, R: Rotate, C: Change Properties", + icon = "icon16/cart.png", + weight = 5, + condition = function(wep, ply) + return true + end, + interface = function(frame, data) + local valz = {} + valz["Row1"] = data.class + valz["Row2"] = data.price + + local DProperties = vgui.Create( "DProperties", frame ) + DProperties:SetSize( 280, 180 ) + DProperties:SetPos( 10, 10 ) + + function DProperties.CompileData() + if weapons.Get( valz["Row1"] ) then + data.class = valz["Row1"] + data.price = tostring(valz["Row2"]) + else + ErrorNoHalt("NZ: This weapon class is not valid!") + end + return data + end + + function DProperties.UpdateData(data) + nzTools:SendData(data, "wallbuy") + end + + local Row1 = DProperties:CreateRow( "Weapon Settings", "Weapon Class" ) + Row1:Setup( "Combo" ) + for k,v in pairs(weapons.GetList()) do + if !v.NZTotalBlacklist then + if v.Category and v.Category != "" then + Row1:AddChoice(v.PrintName and v.PrintName != "" and v.Category.. " - "..v.PrintName or v.ClassName, v.ClassName, false) + else + Row1:AddChoice(v.PrintName and v.PrintName != "" and v.PrintName or v.ClassName, v.ClassName, false) + end + end + end + Row1.DataChanged = function( _, val ) valz["Row1"] = val DProperties.UpdateData(DProperties.CompileData()) end + + local Row2 = DProperties:CreateRow( "Weapon Settings", "Price" ) + Row2:Setup( "Integer" ) + Row2:SetValue( valz["Row2"] ) + Row2.DataChanged = function( _, val ) valz["Row2"] = val DProperties.UpdateData(DProperties.CompileData()) end + + return DProperties + end, + defaultdata = { + class = "weapon_class", + price = 500, + } +}) + +nzTools:EnableProperties("wallbuy", "Edit Wallbuy...", "icon16/cart_edit.png", 9004, true, function( self, ent, ply ) + if ( !IsValid( ent ) or !IsValid(ply) ) then return false end + if ( ent:GetClass() != "wall_buys" ) then return false end + if !nzRound:InState( ROUND_CREATE ) then return false end + if ( ent:IsPlayer() ) then return false end + if ( !ply:IsInCreative() ) then return false end + + return true + +end, function(ent) + return {class = ent:GetWepClass(), price = ent:GetPrice()} +end) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_zspawn.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_zspawn.lua new file mode 100644 index 00000000..2981596f --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_zspawn.lua @@ -0,0 +1,93 @@ +nzTools:CreateTool("zspawn", { + displayname = "Zombie Spawn Creator", + desc = "LMB: Place Spawnpoint, RMB: Remove Spawnpoint", + condition = function(wep, ply) + -- Function to check whether a player can access this tool - always accessible + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + -- Create a new spawnpoint and set its data to the guns properties + local ent + if IsValid(tr.Entity) and tr.Entity:GetClass() == "nz_spawn_zombie_normal" then + ent = tr.Entity -- No need to recreate if we shot an already existing one + else + ent = nzMapping:ZedSpawn(tr.HitPos, tobool(data.flag) and data.link or nil, ply) + end + + ent.flag = data.flag + if tobool(data.flag) and ent.link != "" then + ent.link = data.link + end + + -- For the link displayer + if data.link then + ent:SetLink(data.link) + end + end, + SecondaryAttack = function(wep, ply, tr, data) + -- Remove entity if it is a zombie spawnpoint + if IsValid(tr.Entity) and tr.Entity:GetClass() == "nz_spawn_zombie_normal" then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + -- Nothing + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { -- Switch on to the client table (interfaces, defaults, HUD elements) + displayname = "Zombie Spawn Creator", + desc = "LMB: Place Spawnpoint, RMB: Remove Spawnpoint", + icon = "icon16/user_green.png", + weight = 1, + condition = function(wep, ply) + -- Function to check whether a player can access this tool - always accessible + return true + end, + interface = function(frame, data) + local valz = {} + valz["Row1"] = data.flag + valz["Row2"] = data.link + + local DProperties = vgui.Create( "DProperties", frame ) + DProperties:SetSize( 280, 180 ) + DProperties:SetPos( 10, 10 ) + + function DProperties.CompileData() + local str="nil" + if valz["Row1"] == 0 then + str=nil + data.flag = 0 + else + str=valz["Row2"] + data.flag = 1 + end + data.link = str + + return data + end + + function DProperties.UpdateData(data) + nzTools:SendData(data, "zspawn") + end + + local Row1 = DProperties:CreateRow( "Zombie Spawn", "Enable Flag?" ) + Row1:Setup( "Boolean" ) + Row1:SetValue( valz["Row1"] ) + Row1.DataChanged = function( _, val ) valz["Row1"] = val DProperties.UpdateData(DProperties.CompileData()) end + local Row2 = DProperties:CreateRow( "Zombie Spawn", "Flag" ) + Row2:Setup( "Integer" ) + Row2:SetValue( valz["Row2"] ) + Row2.DataChanged = function( _, val ) valz["Row2"] = val DProperties.UpdateData(DProperties.CompileData()) end + + return DProperties + end, + defaultdata = { + flag = 0, + link = 1, + } +}) diff --git a/gamemodes/nzombies/gamemode/tools/sh_tools_zspecialspawn.lua b/gamemodes/nzombies/gamemode/tools/sh_tools_zspecialspawn.lua new file mode 100644 index 00000000..6db5232c --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_tools_zspecialspawn.lua @@ -0,0 +1,109 @@ +nzTools:CreateTool("zspecialspawn", { + displayname = "Special Spawn Creator", + desc = "LMB: Place Spawnpoint, RMB: Remove Spawnpoint", + condition = function(wep, ply) + -- Function to check whether a player can access this tool - always accessible + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + -- Create a new spawnpoint and set its data to the guns properties + local ent + if IsValid(tr.Entity) and tr.Entity:GetClass() == "nz_spawn_zombie_special" then + ent = tr.Entity -- No need to recreate if we shot an already existing one + else + ent = nzMapping:ZedSpecialSpawn(tr.HitPos, nil, ply) + end + + ent.flag = data.flag + if tobool(data.flag) and ent.link != "" then + ent.link = data.link + end + + -- For the link displayer + if data.link then + ent:SetLink(data.link) + end + end, + SecondaryAttack = function(wep, ply, tr, data) + -- Remove entity if it is a zombie spawnpoint + if IsValid(tr.Entity) and tr.Entity:GetClass() == "nz_spawn_zombie_special" then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + -- Nothing + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Special Spawn Creator", + desc = "LMB: Place Spawnpoint, RMB: Remove Spawnpoint", + icon = "icon16/user_red.png", + weight = 2, + condition = function(wep, ply) + return true + end, + interface = function(frame, data) + local valz = {} + valz["Row1"] = data.flag + valz["Row2"] = data.link + + local DProperties = vgui.Create( "DProperties", frame ) + DProperties:SetSize( 280, 180 ) + DProperties:SetPos( 10, 10 ) + + function DProperties.CompileData() + local str="nil" + if valz["Row1"] == 0 then + str=nil + data.flag = 0 + else + str=valz["Row2"] + data.flag = 1 + end + data.link = str + + return data + end + + function DProperties.UpdateData(data) + nzTools:SendData(data, "zspecialspawn") + end + + local Row1 = DProperties:CreateRow( "Zombie Spawn", "Enable Flag?" ) + Row1:Setup( "Boolean" ) + Row1:SetValue( valz["Row1"] ) + Row1.DataChanged = function( _, val ) valz["Row1"] = val DProperties.UpdateData(DProperties.CompileData()) end + local Row2 = DProperties:CreateRow( "Zombie Spawn", "Flag" ) + Row2:Setup( "Integer" ) + Row2:SetValue( valz["Row2"] ) + Row2.DataChanged = function( _, val ) valz["Row2"] = val DProperties.UpdateData(DProperties.CompileData()) end + + local text = vgui.Create("DLabel", DProperties) + text:SetText("Special Spawnpoints apply to Hellhounds") + text:SetFont("Trebuchet18") + text:SetTextColor( Color(50, 50, 50) ) + text:SizeToContents() + text:Center() + + local text2 = vgui.Create("DLabel", DProperties) + text2:SetText("and for respawning with Who's Who") + text2:SetFont("Trebuchet18") + text2:SetPos(0, 95) + text2:SetTextColor( Color(50, 50, 50) ) + text2:SizeToContents() + text2:CenterHorizontal() + + return DProperties + end, + defaultdata = { + flag = 0, + link = 1, + spawnable = 1, + respawnable = 1, + } +}) diff --git a/gamemodes/nzombies/gamemode/tools/sh_traps_logic.lua b/gamemodes/nzombies/gamemode/tools/sh_traps_logic.lua new file mode 100644 index 00000000..8b83309a --- /dev/null +++ b/gamemodes/nzombies/gamemode/tools/sh_traps_logic.lua @@ -0,0 +1,129 @@ +nzTools:CreateTool("traps_logic", { + displayname = "Traps, Buttons, Logic", + desc = "LMB: Create Entity, RMB: Remove Entity, R: Duplicate Entity, C: Edit Properties", + condition = function(wep, ply) + return true + end, + PrimaryAttack = function(wep, ply, tr, data) + local ent + if data.clone then + ent = duplicator.CreateEntityFromTable(ply, data.dupe) + if !IsValid(ent) then return end + else + ent = ents.Create(data.classname) + end + ent:SetPos(tr.HitPos) + --ent:SetAngles(tr.HitNormal:Angle() + Angle(90,0,0)) + ent:Spawn() + ent:Activate() + + if IsValid(ply) then + undo.Create( "Logic/Trap" ) + undo.SetPlayer( ply ) + undo.AddEntity( ent ) + undo.Finish() + end + + if data.clone then + for k, v in pairs(data.dupe.DT) do + if ent["Set" .. k] then + timer.Simple( 0.1, function() ent["Set" .. k](ent, v) end) + end + end + end + end, + SecondaryAttack = function(wep, ply, tr, data) + if IsValid(tr.Entity) then + tr.Entity:Remove() + end + end, + Reload = function(wep, ply, tr, data) + ply:SetNZToolData({dupe = duplicator.CopyEntTable( tr.Entity ), clone = true}) + end, + OnEquip = function(wep, ply, data) + + end, + OnHolster = function(wep, ply, data) + + end +}, { + displayname = "Traps, Buttons, Logic", + desc = "LMB: Create Entity, RMB: Remove Entity, R: Duplicate Entity, C: Edit Properties", + icon = "icon16/controller.png", + weight = 40, + condition = function(wep, ply) + return nzTools.Advanced + end, + interface = function(frame, data, context) + + local cont = vgui.Create("DScrollPanel", frame) + cont:Dock(FILL) + + function cont.CompileData() + return data + end + + function cont.UpdateData(data) + nzTools:SendData(data, "traps_logic") -- Save the same data here + end + + local function genSpawnList(tbl, parent) + for _, classname in pairs(tbl) do + local info = baseclass.Get(classname) + local model = info.SpawnIcon + local name = info.PrintName + local desc = info.Description + if model then + local panel = vgui.Create("DPanel", parent) + panel:Dock(TOP) + panel:DockMargin(2, 0, 2, 2) + panel:DockPadding(2, 2, 2, 2) + panel:SetHeight(64) + + local entityIcon = vgui.Create( "SpawnIcon", panel ) + entityIcon:Dock(LEFT) + entityIcon:SetModel(model) + entityIcon:SetTooltip(name) + entityIcon:SetWidth(64) + entityIcon.DoClick = function() + cont.UpdateData({classname = classname, clone = false}) + end + + local richText = vgui.Create( "RichText" , panel) + richText:SetFontInternal("DermaDefault") + richText:InsertColorChange(9, 9, 9, 255) + richText:AppendText(name .. "\n\n") + richText:InsertColorChange(40, 40, 40, 255) + richText:AppendText(desc) + richText:Dock(FILL) + + panel:InvalidateLayout( true ) + panel:SizeToChildren( false, true ) + end + end + + return list + end + + local traps = vgui.Create( "DCollapsibleCategory", cont ) + traps:SetExpanded( 1 ) + traps:SetLabel( "Traps" ) + traps:Dock(TOP) + + genSpawnList(nzTraps:GetAll(), traps) + + + local logic = vgui.Create( "DCollapsibleCategory", cont ) + logic:SetExpanded( 1 ) + logic:SetLabel( "Logic" ) + logic:Dock(TOP) + + PrintTable(nzLogic:GetAll()) + genSpawnList(nzLogic:GetAll(), logic) + + return cont + end, + defaultdata = { + model = "models/hunter/plates/plate2x2.mdl" + }, +}) diff --git a/gamemodes/nzombies/gamemode/traps_logic/sh_constructor.lua b/gamemodes/nzombies/gamemode/traps_logic/sh_constructor.lua new file mode 100644 index 00000000..a952beb3 --- /dev/null +++ b/gamemodes/nzombies/gamemode/traps_logic/sh_constructor.lua @@ -0,0 +1,60 @@ +-- Setup round module +nzTraps = nzTraps or AddNZModule("Traps") +nzLogic = nzLogic or AddNZModule("Logic") + +nzTraps.Registry = nzTraps.Registry or {} +nzLogic.Registry = nzLogic.Registry or {} + +local function register (tbl, classname) + table.insert(tbl, classname) +end + +function nzTraps:Register(classname) + if !table.HasValue(self.Registry, classname) then + register(self.Registry, classname) + end +end + +function nzLogic:Register(classname) + if !table.HasValue(self.Registry, classname) then + register(self.Registry, classname) + end +end + +function nzTraps:GetAll() + return self.Registry +end + +function nzLogic:GetAll() + return self.Registry +end + +if SERVER then + nzMapping:AddSaveModule("TrapsLogic", { + savefunc = function() + local traps_logic = {} + local classes = nzTraps:GetAll() + table.Add(classes, nzLogic:GetAll()) + for k, class in pairs(classes) do + for _, ent in pairs(ents.FindByClass(class)) do + table.insert(traps_logic, duplicator.CopyEntTable(ent)) + end + end + return traps_logic + end, + loadfunc = function(data) + for _, entTable in pairs(data) do + local ent = duplicator.CreateEntityFromTable(ply, entTable) + ent:Activate() + ent:Spawn() + + for k, v in pairs(entTable.DT) do + if ent["Set" .. k] then + timer.Simple( 0.1, function() ent["Set" .. k](ent, v) end) + end + end + end + end, + cleanents = {"nz_button", "nz_button_and", "nz_trap_turret", "nz_trap_zapper"}, + }) +end diff --git a/gamemodes/nzombies/gamemode/weapons/cl_wepswitch.lua b/gamemodes/nzombies/gamemode/weapons/cl_wepswitch.lua new file mode 100644 index 00000000..7b8aea77 --- /dev/null +++ b/gamemodes/nzombies/gamemode/weapons/cl_wepswitch.lua @@ -0,0 +1,70 @@ +local plyMeta = FindMetaTable( "Player" ) +AccessorFunc( plyMeta, "iLastWeaponSlot", "LastWeaponSlot", FORCE_NUMBER) +AccessorFunc( plyMeta, "iCurrentWeaponSlot", "CurrentWeaponSlot", FORCE_NUMBER) +function plyMeta:SelectWeapon( class ) + if ( !self:HasWeapon( class ) ) then return end + self.DoWeaponSwitch = self:GetWeapon( class ) + --print(self.DoWeaponSwitch) +end + +function GM:CreateMove( cmd ) + local ply = LocalPlayer() + if ( IsValid( ply.DoWeaponSwitch ) ) then + cmd:SelectWeapon( ply.DoWeaponSwitch ) + + if ( LocalPlayer():GetActiveWeapon() == ply.DoWeaponSwitch ) then + ply:SetCurrentWeaponSlot(ply:GetActiveWeapon():GetNWInt("SwitchSlot", 1)) + ply.DoWeaponSwitch = nil + end + end +end + +function GM:PlayerBindPress( ply, bind, pressed ) + if nzRound:InProgress() or nzRound:InState(ROUND_GO) then + if !ply:GetCurrentWeaponSlot() then ply:SetCurrentWeaponSlot(ply:GetActiveWeapon():GetNWInt("SwitchSlot", 1)) end + local slot + local curslot = ply:GetCurrentWeaponSlot() or 1 + if ( string.find( bind, "slot1" ) ) then slot = 1 end + if ( string.find( bind, "slot2" ) ) then slot = 2 end + if ( string.find( bind, "slot3" ) ) then slot = 3 end + if ( string.find( bind, "invnext" ) ) then + slot = curslot + 1 + if (ply:HasPerk("mulekick") and slot > 3) or (!ply:HasPerk("mulekick") and slot > 2) then + slot = 1 + end + end + if ( string.find( bind, "invprev" ) ) then + slot = curslot - 1 + if slot < 1 then + slot = ply:HasPerk("mulekick") and 3 or 2 + end + end + if !nzRound:InState(ROUND_CREATE) and (bind == "+menu" and pressed ) then slot = ply:GetLastWeaponSlot() or 1 end + if slot then + ply:SetLastWeaponSlot( ply:GetActiveWeapon():GetNWInt( "SwitchSlot", 1) ) + if slot == 3 then + for k,v in pairs( ply:GetWeapons() ) do + if v:GetNWInt( "SwitchSlot" ) == slot then + ply:SelectWeapon( v:GetClass() ) + return true + end + end + slot = 1 + for k,v in pairs( ply:GetWeapons() ) do + if v:GetNWInt( "SwitchSlot" ) == slot then + ply:SelectWeapon( v:GetClass() ) + return true + end + end + else + for k,v in pairs( ply:GetWeapons() ) do + if v:GetNWInt( "SwitchSlot" ) == slot then + ply:SelectWeapon( v:GetClass() ) + return true + end + end + end + end + if ( string.find( bind, "slot" ) ) then return true end + end +end diff --git a/gamemodes/nzombies/gamemode/weapons/sh_ammo.lua b/gamemodes/nzombies/gamemode/weapons/sh_ammo.lua new file mode 100644 index 00000000..5294c9ae --- /dev/null +++ b/gamemodes/nzombies/gamemode/weapons/sh_ammo.lua @@ -0,0 +1,107 @@ +-- Create new ammo types for each weapon slot; that way all 3 weapons have seperate ammo even if they share type +game.AddAmmoType( { + name = "nz_weapon_ammo_1", + dmgtype = DMG_BULLET, + tracer = TRACER_LINE, + plydmg = 0, + npcdmg = 0, + force = 2000, + minsplash = 10, + maxsplash = 5 +} ) + +game.AddAmmoType( { + name = "nz_weapon_ammo_2", + dmgtype = DMG_BULLET, + tracer = TRACER_LINE, + plydmg = 0, + npcdmg = 0, + force = 2000, + minsplash = 10, + maxsplash = 5 +} ) + +-- Third one is pretty much only used with Mule Kick +game.AddAmmoType( { + name = "nz_weapon_ammo_3", + dmgtype = DMG_BULLET, + tracer = TRACER_LINE, + plydmg = 0, + npcdmg = 0, + force = 2000, + minsplash = 10, + maxsplash = 5 +} ) + +game.AddAmmoType( { + name = "nz_grenade", +} ) + +game.AddAmmoType( { + name = "nz_specialgrenade", +} ) + +NZAmmoIDs = NZAmmoIDs or {} -- It needs to be global to pass through lua refresh +local ammoids = NZAmmoIDs -- Localize it for optimization + +function GetNZAmmoID( id ) + return ammoids[id] +end + +hook.Add("InitPostEntity", "nzRegisterAmmoIDs", function() + local id + for i = 1, 3 do + id = game.GetAmmoID("nz_weapon_ammo_"..i) + if id and id != -1 then + ammoids[i] = id + end + end + + id = game.GetAmmoID("nz_grenade") + if id and id != -1 then + ammoids["grenade"] = id + else + ammoids["grenade"] = 1 -- Default to AR2 ammo + end + + id = game.GetAmmoID("nz_specialgrenade") + if id and id != -1 then + ammoids["specialgrenade"] = id + else + ammoids["specialgrenade"] = 2 -- Default to AR2 alt ammo (combine balls) + end +end) + +if CLIENT then + net.Receive("nzAmmoTypeSync", function() + ammoids = net.ReadTable() + PrintTable(ammoids) + end) +else + util.AddNetworkString("nzAmmoTypeSync") + + FullSyncModules["AmmoTypes"] = function(ply) + net.Start("nzAmmoTypeSync") + net.WriteTable(ammoids) + net.Broadcast() + end +end + +local wepMeta = FindMetaTable("Weapon") + +local oldammotype = wepMeta.GetPrimaryAmmoType +function wepMeta:GetPrimaryAmmoType() + local id = self:GetNWInt("SwitchSlot", -1) + if ammoids[id] then return ammoids[id] end -- We have our own special ammo, return that! + + local oldammo = oldammotype(self) -- Otherwise get this weapons old ammo + if SERVER and oldammo and oldammo != -1 and id != -1 then -- Oldammo is a valid ID and the slot isn't -1 + ammoids[id] = oldammo -- This of course only runs if !ammoids[id] + + net.Start("nzAmmoTypeSync") + net.WriteTable(ammoids) -- Resync new ammo types + net.Broadcast() + end -- If it exists, store it as our new "ammo for weapons in slot X" + + return oldammo -- Return it as well +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/weapons/sh_constructor.lua b/gamemodes/nzombies/gamemode/weapons/sh_constructor.lua new file mode 100644 index 00000000..5247ae1f --- /dev/null +++ b/gamemodes/nzombies/gamemode/weapons/sh_constructor.lua @@ -0,0 +1,4 @@ +-- Main Tables +nzWeps = nzWeps or AddNZModule("Weps") + +-- Variables diff --git a/gamemodes/nzombies/gamemode/weapons/sh_fas2.lua b/gamemodes/nzombies/gamemode/weapons/sh_fas2.lua new file mode 100644 index 00000000..56cd9987 --- /dev/null +++ b/gamemodes/nzombies/gamemode/weapons/sh_fas2.lua @@ -0,0 +1,412 @@ +function FAS2_PlayAnim(wep, anim, speed, cyc, time) + speed = speed and speed or 1 + cyc = cyc and cyc or 0 + time = time or 0 + + if type(anim) == "table" then + anim = table.Random(anim) + end + + anim = string.lower(anim) + + if wep.Owner:HasPerk("speed") then + if string.find(anim, "reload") != nil or string.find(anim, "insert") != nil then + speed = speed * 1.33 -- For some reason this fits perfectly to a double reload speed? + end + end + if wep.Owner:HasPerk("dtap") or wep.Owner:HasPerk("dtap2") then + if string.find(anim, "fire") != nil or string.find(anim, "cock") != nil or string.find(anim, "pump") != nil then + speed = speed * 1.33 + end + end + + if game.SinglePlayer() then + if SERVER then + if wep.Sounds[anim] then + wep.CurSoundTable = wep.Sounds[anim] + wep.CurSoundEntry = 1 + wep.SoundSpeed = speed + wep.SoundTime = CurTime() + time + end + end + /*if wep.Sounds[anim] then + for k, v in pairs(wep.Sounds[anim]) do + timer.Simple(v.time, function() + if IsValid(ply) and ply:Alive() and IsValid(wep) and wep == ply:GetActiveWeapon() then + wep:EmitSound(v.sound, 70, 100) + end + end) + end + end + end*/ + else + if wep.Sounds[anim] then + wep.CurSoundTable = wep.Sounds[anim] + wep.CurSoundEntry = 1 + wep.SoundSpeed = speed + wep.SoundTime = CurTime() + time + end + + /*if wep.Sounds[anim] then + for k, v in pairs(wep.Sounds[anim]) do + timer.Simple(v.time, function() + wep:EmitSound(v.sound, 70, 100) + end) + end + end*/ + end + + if SERVER and game.SinglePlayer() then + ply = Entity(1) + + umsg.Start("FAS2ANIM", ply) + umsg.String(anim) + umsg.Float(speed) + umsg.Float(cyc) + umsg.End() + end + + if CLIENT then + vm = wep.Wep + + wep.CurAnim = string.lower(anim) + + if vm then + vm:SetCycle(cyc) + vm:SetSequence(anim) + --print(vm:SequenceDuration(vm:LookupSequence(anim))/speed) + --print(LocalPlayer():GetActiveWeapon():GetNextPrimaryFire() - CurTime()) + vm:SetPlaybackRate(speed) + end + end +end + +if CLIENT then + -- A copy using a slightly different usermessage. This one generates the missing tables (which would otherwise require the C-menu) + local function FAS2_Attach(um) + local group = um:ReadShort() + local att = um:ReadString() + local wep = um:ReadEntity() + + ply = LocalPlayer() + + if IsValid(wep) and wep.IsFAS2Weapon then + t = wep.Attachments[group] + + t.active = att + if !t.last then t.last = {} end + t.last[att] = true + t2 = FAS2_Attachments[att] + + if t2.aimpos then + wep.AimPos = wep[t2.aimpos] + wep.AimAng = wep[t2.aimang] + wep.AimPosName = t2.aimpos + wep.AimAngName = t2.aimang + end + + if t.lastdeattfunc then + t.lastdeattfunc(ply, wep) + end + + if t2.clattfunc then + t2.clattfunc(ply, wep) + end + + t.lastdeattfunc = t2.cldeattfunc + + wep:AttachBodygroup(att) + surface.PlaySound("cstm/attach.wav") + end + end + usermessage.Hook("FAS2_ATTACHPAP", FAS2_Attach) +end + +hook.Add("InitPostEntity", "ReplaceCW2BaseFunctions", function() + local cw2 = weapons.Get("cw_base") + if cw2 then + cw2.beginReload = function(self) + mag = self:Clip1() + local CT = CurTime() + + local hasspeed = self.Owner:HasPerk("speed") + + if self.ShotgunReload then + local time = CT + self.ReloadStartTime / self.ReloadSpeed + if hasspeed then time = time / 2 end + + self.WasEmpty = mag == 0 + self.ReloadDelay = time + self:SetNextPrimaryFire(time) + self:SetNextSecondaryFire(time) + self.GlobalDelay = time + self.ShotgunReloadState = 1 + + self:sendWeaponAnim("reload_start", hasspeed and self.ReloadSpeed * 2 or self.ReloadSpeed) + else + local reloadTime = nil + local reloadHalt = nil + + if mag == 0 then + if self.Chamberable then + self.Primary.ClipSize = self.Primary.ClipSize_Orig + end + + reloadTime = self.ReloadTime_Empty + reloadHalt = self.ReloadHalt_Empty + else + reloadTime = self.ReloadTime + reloadHalt = self.ReloadHalt + + if self.Chamberable then + self.Primary.ClipSize = self.Primary.ClipSize_Orig + 1 + end + end + + reloadTime = reloadTime / self.ReloadSpeed + reloadHalt = reloadHalt / self.ReloadSpeed + + if hasspeed then + reloadTime = reloadTime / 2 + reloadHalt = reloadHalt / 2 + end + + self.ReloadDelay = CT + reloadTime + self:SetNextPrimaryFire(CT + reloadHalt) + self:SetNextSecondaryFire(CT + reloadHalt) + self.GlobalDelay = CT + reloadHalt + + if self.reloadAnimFunc then + self:reloadAnimFunc(mag) + else + if self.Animations.reload_empty and mag == 0 then + self:sendWeaponAnim("reload_empty", hasspeed and self.ReloadSpeed * 2 or self.ReloadSpeed) + else + self:sendWeaponAnim("reload", hasspeed and self.ReloadSpeed * 2 or self.ReloadSpeed) + end + end + end + + CustomizableWeaponry.callbacks.processCategory(self, "beginReload", mag == 0) + + self.Owner:SetAnimation(PLAYER_RELOAD) + end + + cw2.playFireAnim = function(self) + if (self.dt.State == CW_AIMING and not self.ADSFireAnim) or (self.dt.BipodDeployed and not self.BipodFireAnim) then + return + end + + if self.dt.State ~= CW_AIMING and (not self.LuaViewmodelRecoilOverride and self.LuaViewmodelRecoil) then + return + end + + if self:Clip1() - self.AmmoPerShot <= 0 and self.Animations.fire_dry then + if self.Owner:HasPerk("dtap") or self.Owner:HasPerk("dtap2") then + self:sendWeaponAnim("fire_dry", 1.66) + else + self:sendWeaponAnim("fire_dry") + end + else + if self.Owner:HasPerk("dtap") or self.Owner:HasPerk("dtap2") then + self:sendWeaponAnim("fire", 1.66) + else + self:sendWeaponAnim("fire") + end + end + end + weapons.Register(cw2, "cw_base") + + -- We overwrite this slowdown function from CW2 here to take our sprinting system into account + -- But only if the cw2 weapon is even existant + local MaxRunSpeed = debug.getregistry().Player.GetMaxRunSpeed + function CW_Move(ply, m) + local maxspeed + if MaxRunSpeed then -- If the GetMaxRunSpeed function exists (server side) + maxspeed = MaxRunSpeed(ply) + else + local class = player_manager.GetPlayerClass(ply) -- Else, get the player class + if class then -- If it exists, get the class table's RunSpeed value + maxspeed = baseclass.Get(class).RunSpeed + else + maxspeed = ply:GetRunSpeed() -- Otherwise, just set to normal run speed + end + end + if !maxspeed then maxspeed = 300 end -- Fallback + if ply:Crouching() then + m:SetMaxSpeed(ply:GetWalkSpeed() * ply:GetCrouchedWalkSpeed()) + else + wep = ply:GetActiveWeapon() + + if IsValid(wep) and wep.CW20Weapon then + if wep.dt and wep.dt.State == CW_AIMING then + m:SetMaxSpeed((ply:GetWalkSpeed() - wep.SpeedDec) * 0.75) + else + m:SetMaxSpeed(maxspeed - wep.SpeedDec) + end + else + m:SetMaxSpeed(maxspeed) + end + --print(m:GetMaxSpeed()) + end + end + hook.Add("Move", "CW_Move", CW_Move) + + end + + local fas2 = weapons.Get("fas2_base") + if fas2 then + fas2.PrimaryAttack = function(self) -- Overwrite to prevent up-against-wall-stuff + if self.FireMode == "safe" then + if IsFirstTimePredicted() then + self:CycleFiremodes() + end + + return + end + + if IsFirstTimePredicted() then + if self.BurstAmount > 0 and self.dt.Shots >= self.BurstAmount then + return + end + + if self.ReloadState != 0 then + self.ReloadState = 3 + return + end + + if self.dt.Status == FAS_STAT_CUSTOMIZE then + return + end + + if self.Cooking or self.FuseTime then + return + end + + if self.Owner:KeyDown(IN_USE) then + if self:CanThrowGrenade() then + self:InitialiseGrenadeThrow() + return + end + end + + if self.dt.Status == FAS_STAT_SPRINT or self.dt.Status == FAS_STAT_QUICKGRENADE then + return + end + + mag = self:Clip1() + CT = CurTime() + + if mag <= 0 or self.Owner:WaterLevel() >= 3 then + self:EmitSound(self.EmptySound, 60, 100) + self:SetNextPrimaryFire(CT + 0.2) + //self:EmitSound("FAS2_DRYFIRE", 70, 100) + return + end + + if self.CockAfterShot and not self.Cocked then + if SERVER then + if SP then + SendUserMessage("FAS2_COCKREMIND", self.Owner) -- wow okay + end + else + self.CockRemindTime = CurTime() + 1 + end + + return + end + + self:FireBullet() + + if CLIENT then + self:CreateMuzzle() + + if self.Shell and self.CreateShell then + self:CreateShell() + end + end + + ef = EffectData() + ef:SetEntity(self) + util.Effect("fas2_ef_muzzleflash", ef) + + mod = self.Owner:Crouching() and 0.75 or 1 + + self:PlayFireAnim(mag) + + if self.dt.Status == FAS_STAT_ADS then + if self.BurstAmount > 0 then + if self.DelayedBurstRecoil then + if self.dt.Shots == self.ShotToDelayUntil then + self:AimRecoil(self.BurstRecoilMod) + end + else + self:AimRecoil(self.BurstRecoilMod) + end + else + self:AimRecoil() + end + else + if self.BurstAmount > 0 then + if self.DelayedBurstRecoil then + if self.dt.Shots == self.ShotToDelayUntil then + self:HipRecoil(self.BurstRecoilMod) + end + else + self:HipRecoil(self.BurstRecoilMod) + end + else + self:HipRecoil() + end + end + + self.SpreadWait = CT + self.SpreadCooldown + + if self.BurstAmount > 0 then + self.AddSpread = math.Clamp(self.AddSpread + self.SpreadPerShot * mod * 0.5, 0, self.MaxSpreadInc) + self.AddSpreadSpeed = math.Clamp(self.AddSpreadSpeed - 0.2 * mod * 0.5, 0, 1) + else + self.AddSpread = math.Clamp(self.AddSpread + self.SpreadPerShot * mod, 0, self.MaxSpreadInc) + self.AddSpreadSpeed = math.Clamp(self.AddSpreadSpeed - 0.2 * mod, 0, 1) + end + + if self.CockAfterShot then + self.Cocked = false + end + + if SERVER and SP then + SendUserMessage("FAS2SPREAD", self.Owner) + end + + if CLIENT then + self.CheckTime = 0 + end + + if self.dt.Suppressed then + self:EmitSound(self.FireSound_Suppressed, 75, 100) + else + self:EmitSound(self.FireSound, 105, 100) + end + + self.Owner:SetAnimation(PLAYER_ATTACK1) + + self.ReloadWait = CT + 0.3 + end + + if self.BurstAmount > 0 then + self.dt.Shots = self.dt.Shots + 1 + self:SetNextPrimaryFire(CT + self.FireDelay * self.BurstFireDelayMod) + else + self:SetNextPrimaryFire(CT + self.FireDelay) + end + + self:TakePrimaryAmmo(1) + + //self:SetNextSecondaryFire(CT + 0.1) + + return + end + weapons.Register(fas2, "fas2_base") + end + +end) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/weapons/sh_wep_modifiers.lua b/gamemodes/nzombies/gamemode/weapons/sh_wep_modifiers.lua new file mode 100644 index 00000000..29a2ff26 --- /dev/null +++ b/gamemodes/nzombies/gamemode/weapons/sh_wep_modifiers.lua @@ -0,0 +1,625 @@ +local WeaponModificationFunctions = {} + +-- Defaults are run if no other modifiers were added (or they all allowed the next one to be added) +local WeaponModificationFunctionsDefaults = { + speed = function(wep) + local oldreload = wep.Reload + if !oldreload then return end + + --print("Weapon reload modified") + + wep.Reload = function( self, ... ) + if self.ReloadFinish and self.ReloadFinish > CurTime() then return end + local ply = self.Owner + local cur = self:Clip1() + if cur >= self:GetMaxClip1() then return end + local give = self:GetMaxClip1() - cur + if give > ply:GetAmmoCount(self:GetPrimaryAmmoType()) then + give = ply:GetAmmoCount(self:GetPrimaryAmmoType()) + end + if give <= 0 then return end + + self:SendWeaponAnim(ACT_VM_RELOAD) + oldreload(self, ...) + local rtime = self:SequenceDuration(self:SelectWeightedSequence(ACT_VM_RELOAD))/2 + self:SetPlaybackRate(2) + ply:GetViewModel():SetPlaybackRate(2) + + local nexttime = CurTime() + rtime + + self:SetNextPrimaryFire(nexttime) + self:SetNextSecondaryFire(nexttime) + self.ReloadFinish = nexttime + + timer.Simple(rtime, function() + if IsValid(self) and ply:GetActiveWeapon() == self then + self:SetPlaybackRate(1) + ply:GetViewModel():SetPlaybackRate(1) + self:SendWeaponAnim(ACT_VM_IDLE) + self:SetClip1(give + cur) + ply:RemoveAmmo(give, self:GetPrimaryAmmoType()) + self:SetNextPrimaryFire(0) + self:SetNextSecondaryFire(0) + end + end) + end + end, + dtap = function(wep) + local oldpfire = wep.PrimaryAttack + if oldpfire then + wep.PrimaryAttack = function(...) + oldpfire(wep, ...) + local delay = (wep:GetNextPrimaryFire() - CurTime())*0.8 + wep:SetNextPrimaryFire(CurTime() + delay) + end + end + + local oldsfire = wep.SecondaryAttack + if oldsfire then + wep.SecondaryAttack = function(...) + oldsfire(wep, ...) + local delay = (wep:GetNextSecondaryFire() - CurTime())*0.8 + wep:SetNextSecondaryFire(CurTime() + delay) + end + end + end, + pap = function(wep) + if wep.Primary and wep.Primary.ClipSize > 0 then + local newammo = wep.Primary.ClipSize + (wep.Primary.ClipSize*0.5) + newammo = math.Round(newammo/5)*5 + if newammo <= 0 then newammo = 2 end + wep.Primary.ClipSize = newammo + if SERVER then wep:SetClip1(newammo) end + end + + if CLIENT then + local bannedmatnames = {"hand", "arm", "accessor", "scope", "sight"} + local function IsGoodMaterial(str) + for k,v in pairs(bannedmatnames) do + if string.find(str, v) then + return false + end + end + return true + end + + if !wep.PaPMats2 then -- Only if the weapon doesn't already have + if wep.PaPMats then wep.PaPMats2 = wep.PaPMats else + wep.PaPMats2 = {} -- Generate PaP mats for this weapon + local modelstr = wep.VM or wep.ViewModel or (wep.GetViewModel and wep:GetViewModel() or wep.ViewModel) + if modelstr then + local model = ClientsideModel(modelstr) + local mats = model:GetMaterials() + PrintTable(mats) + if table.Count(mats) >= 1 then + local num = 2 + for k,v in pairs(mats) do + if IsGoodMaterial(v) then + if num%3 > 0 then + print("Modified", v) + wep.PaPMats2[k - 1] = true + end + num = num + 1 + end + end + end + model:Remove() + end + end + end + end + end, +} + +local WeaponModificationRevertDefaults = { + pap = function(wep) + if CLIENT then wep.PaPMats2 = nil end + end +} + +-- These work by modifying weapons in a special way - they are called via ApplyWeaponModifier with the event being the type of modification +-- "speed" = Applied to all weapons when Speed Cola is owned +-- "dtap" = Applied to all weapons when Double Tap 1 or 2 is owned +-- "pap" = Applied on Pack-a-Punch +-- "repap" = Applied on Pack-a-Punching again; this is not saved as a modifier, so it can run again and again +-- "equip" = Applied when weapon is equipped; doesn't have any restoration + +-- Any other custom event can be used with weapon:ApplyNZModifier(event) + +function nzWeps:AddWeaponModification(id, event, condition, apply, revert) + if !WeaponModificationFunctions[event] then WeaponModificationFunctions[event] = {} end + + WeaponModificationFunctions[event][id] = { + condition = condition, -- Condition is checked on both revert and apply + apply = apply, -- Applies changes, all changes are restored when reverted automatically + revert = revert -- If you need some special revert function, this is optional + } +end + +function nzWeps:RemoveWeaponModification(id, event) + if !WeaponModificationFunctions[event] then return end + WeaponModificationFunctions[event][id] = nil +end + + +local wepmeta = FindMetaTable("Weapon") +if !wepmeta then return end + +local function RecursiveDifferenceCheck(tbl1, tbl2) + local diffs = {} + + for k,v in pairs(tbl1) do + if v != tbl2[k] then + if type(v) == "table" then + local t = RecursiveDifferenceCheck(v, tbl2[k]) + if table.Count(t) > 0 then + diffs[k] = t + end + else + diffs[k] = v + end + end + end + + return diffs +end + +function wepmeta:ApplyDefaultNZModifier(modifier) + if WeaponModificationFunctionsDefaults[modifier] then + WeaponModificationFunctionsDefaults[modifier](self) + end +end + +function wepmeta:ApplyNZModifier(modifier, blocknetwork) + if self:HasNZModifier(modifier) then return end + + if WeaponModificationFunctions and WeaponModificationFunctions[modifier] then + + local oldversion = table.Copy(self:GetTable()) -- We'll compare to allow for auto-reversion of any changes + local modded = false + + if self.NZModifierAdd and !self:NZModifierAdd(modifier) then + modded = true + end + + if !modded then + if (modifier == "pap" and self.OnPaP and self:OnPaP()) or (modifier == "repap" and self.OnRePaP and self.OnRePaP()) then + modded = true + end + end + + if !modded then + for k,v in pairs(WeaponModificationFunctions[modifier]) do + if v.condition(self) then -- Apply all modifications that pass the condition + if !v.apply(self) then -- Return true to allow other modifiers + modded = true + break + end + end + end + end + + if !modded then -- If all modifiers passed on, default comes last + self:ApplyDefaultNZModifier(modifier) + end + + if SERVER and !blocknetwork then + nzWeps:SendSync(self.Owner, self, modifier, false) -- Sync to let the client do the same + end + + if !self.NZModifiers then self.NZModifiers = {} end + if modifier != "repap" and modifier != "equip" then self.NZModifiers[modifier] = RecursiveDifferenceCheck(oldversion, self:GetTable()) end -- Store all differences so we can restore them! + else + print("Tried to apply invalid modifier "..modifier.." to weapon "..tostring(self)) + end +end + +function wepmeta:RevertNZModifier(modifier, blocknetwork) + if WeaponModificationFunctions and WeaponModificationFunctions[modifier] then + local olds = self.NZModifiers[modifier] + + if olds then + for k,v in pairs(olds) do -- Restore all old data! + self[k] = v + end + end + + for k,v in pairs(WeaponModificationFunctions[modifier]) do + if v.revert and v.condition(self) then + v.revert(self) -- Call revert functions if they were added + end + end + if WeaponModificationRevertDefaults[modifier] then WeaponModificationRevertDefaults[modifier](self) end + + if SERVER and !blocknetwork then + nzWeps:SendSync(self.Owner, self, modifier, true) -- Sync to let the client do the same + end + + if !self.NZModifiers then self.NZModifiers = {} end + self.NZModifiers[modifier] = nil + else + print("Tried to revert invalid modifier "..modifier.." to weapon "..tostring(self)) + end +end + +function wepmeta:HasNZModifier(id) + if !self.NZModifiers then return false end + return self.NZModifiers[id] and true or false +end + +nzWeps:AddWeaponModification("speed_fascw2", "speed", function(wep) + return wep:IsFAS2() or wep:IsCW2() +end, function(wep) + local data = {} + -- Normal + data["ReloadTime"] = 2 + data["ReloadTime_Nomen"] = 2 + data["ReloadTime_Empty"] = 2 + data["ReloadTime_Empty_Nomen"] = 2 + -- BiPod + data["ReloadTime_Bipod"] = 2 + data["ReloadTime_Bipod_Nomen"] = 2 + data["ReloadTime_Bipod_Empty"] = 2 + data["ReloadTime_Bipod_Empty_Nomen"] = 2 + -- Shotguns + data["ReloadStartTime"] = 2 + data["ReloadStartTime_Nomen"] = 2 + data["ReloadEndTime"] = 2 + data["ReloadEndTime_Nomen"] = 2 + data["ReloadAbortTime"] = 2 + data["ReloadAdvanceTimeEmpty"] = 2 + data["ReloadAdvanceTimeEmpty_Nomen"] = 2 + data["ReloadAdvanceTimeLast"] = 2 + data["ReloadAdvanceTimeLast_Nomen"] = 2 + data["InsertTime"] = 2 + data["InsertTime_Nomen"] = 2 + data["InsertEmpty"] = 2 + data["InsertEmpty_Nomen"] = 2 + + for k,v in pairs(data) do + if wep[k] != nil then + local val = wep[k] / v + local old = wep[k] + -- Save the old so we can remove it later + --wep["old_"..k] = old + wep[k] = val + end + end + + if wep.ReloadTimes then + --wep.old_ReloadTimes = table.Copy(wep.ReloadTimes) + for k,v in pairs(wep.ReloadTimes) do + if type(v) == "table" then + for k2,v2 in pairs(v) do + v[k2] = v2/2 + end + elseif type(v) == "number" then + v = v/2 + end + end + end +end) + +nzWeps:AddWeaponModification("dtap_fascw2", "dtap", function(wep) + return wep:IsFAS2() or wep:IsCW2() +end, function(wep) + print("Applying Dtap to: " .. wep.ClassName) + local data = {} + -- Normal + data["FireDelay"] = 1.2 + -- Shotgun Cocking and Sniper Bolting + data["CockTime"] = 1.5 + data["CockTime_Nomen"] = 1.5 + data["CockTime_Bipod"] = 1.5 + data["CockTime_Bipod_Nomen"] = 1.5 + + for k,v in pairs(data) do + if wep[k] != nil then + local val = wep[k] / v + wep[k] = val + end + end +end) + + +-- A copy of the FAS2 function, slightly modified to not require the costumization menu +-- This is used in the PaP modifier below +local function AttachFAS2Attachment(ply, wep, group, att) + if not (IsValid(ply) and ply:Alive()) then + return + end + + if not IsValid(wep) or not wep.IsFAS2Weapon then + return + end + + ply:FAS2_PickUpAttachment(att, false) -- Silently add the attachment + + if not group or not att or not wep.Attachments or wep.NoAttachmentMenu or not table.HasValue(ply.FAS2Attachments, att) then + return + end + + t = wep.Attachments[group] + + if t then + found = false + + for k, v in pairs(t.atts) do + if v == att then + found = true + end + end + + if t.lastdeattfunc then + t.lastdeattfunc(ply, wep) + t.lastdeattfunc = nil + end + + if found then + t.last = att + + t2 = FAS2_Attachments[att] + + if t2.attfunc then + t2.attfunc(ply, wep) + end + + if t2.deattfunc then + t.lastdeattfunc = t2.deattfunc + end + + umsg.Start("FAS2_ATTACHPAP", ply) + umsg.Short(group) + umsg.String(att) + umsg.Entity(wep) + umsg.End() + end + end +end + +local cond = function(wep) return SERVER and wep:IsFAS2() and GetConVar("nz_papattachments"):GetBool() end +local atts = function(wep) + local ply = wep.Owner + if wep.Attachments then + for k,v in pairs(wep.Attachments) do + if string.lower(v.header) != "magazine" and string.lower(v.header) != "mag" then -- Mag can't be edited + local atts = {} + for k2,v2 in pairs(v.atts) do -- List all missing attachments + if !table.HasValue(ply.FAS2Attachments, v2) then + table.insert(atts, v2) + end + end + if table.Count(atts) > 0 then + local newatt = atts[math.random(#atts)] + AttachFAS2Attachment(ply, wep, k, newatt) + if newatt then + print(wep.Owner:Nick().." has Pack-a-Punched and gotten attachment "..newatt) + end + end + end + end + end + return true +end +nzWeps:AddWeaponModification("pap_fas_attachments", "pap", cond, atts) -- Add the same to both PaP and Re-PaP +nzWeps:AddWeaponModification("pap_fas_attachments", "repap", cond, atts) + +local cond = function(wep) return SERVER and wep:IsCW2() and GetConVar("nz_papattachments"):GetBool() end +local atts = function(wep) + if wep.Attachments then + for k,v in pairs(wep.Attachments) do + if string.lower(v.header) != "magazine" and string.lower(v.header) != "mag" then -- Mag can't be edited + local atts = {} + for k2,v2 in pairs(v.atts) do -- List all missing attachments + if !CustomizableWeaponry:hasAttachment(wep.Owner, v2) then + table.insert(atts, v2) + end + end + if #atts > 0 then + local newatt = math.random(#atts) + CustomizableWeaponry:giveAttachment(wep.Owner, atts[newatt]) + wep:attach(k, newatt - 1) + if atts[newatt] then + print(wep.Owner:Nick().." has Pack-a-Punched and gotten attachment "..atts[newatt]) + end + end + end + end + end + return true +end +nzWeps:AddWeaponModification("pap_cw2_attachments", "pap", function(wep) return wep:IsCW2() end, function(wep) + if wep.Primary and wep.Primary.ClipSize_Orig and wep.Primary.ClipSize_Orig > 0 then + local newammo = wep.Primary.ClipSize_Orig + (wep.Primary.ClipSize_Orig*0.5) + newammo = math.Round(newammo/5)*5 + if newammo <= 0 then newammo = 2 end + wep.Primary.ClipSize_Orig = newammo -- CW2 needs special ammo thingies + wep.Primary.ClipSize_ORIG_REAL = newammo + if SERVER then wep:SetClip1(newammo) end + end + + if SERVER then + atts(wep) + end + return true +end) +nzWeps:AddWeaponModification("pap_cw2_attachments", "repap", cond, atts) -- Add the same to both PaP and Re-PaP + +nzWeps:AddWeaponModification("speed_tfa", "speed", function(wep) + return wep:IsTFA() +end, function(wep) + wep.ReloadOld = wep.ReloadOld or wep.Reload + wep.Reload = function(self, ...) + local ct = CurTime() + wep.ReloadOld(self, ...) + local diff = self:GetNextPrimaryFire() - ct + diff = diff/2 + ct + + print(diff) + + if self.SetReloadingEnd then self:SetReloadingEnd(diff) end -- This function handles the ammo refill + self.ReloadingTime = diff + self:SetNextPrimaryFire(diff) + self:SetNextSecondaryFire(diff) + self:SetNextIdleAnim(diff) + self:SetPlaybackRate(2) + self.Owner:GetViewModel():SetPlaybackRate(2) + end +end) + +nzWeps:AddWeaponModification("dtap_tfa", "dtap", function(wep) + return wep:IsTFA() +end, function(wep) + wep.PrimaryAttackOld = wep.PrimaryAttackOld or wep.PrimaryAttack + wep.PrimaryAttack = function(self, ...) + local npfold = wep:GetNextPrimaryFire() + wep.PrimaryAttackOld(wep, ...) + if wep:GetNextPrimaryFire() <= npfold then return end + + local dtap1,dtap2 = wep.Owner:HasPerk("dtap"), wep.Owner:HasPerk("dtap2") + if dtap1 or dtap2 then + local delay = wep:GetNextPrimaryFire() - CurTime() + if dtap2 then + delay = delay * 0.8 + end + if dtap1 then + delay = delay * 0.8 + end + wep:SetNextPrimaryFire(CurTime() + delay) + if ( wep:GetStatus() == TFA.GetStatus("shooting") or wep:GetStatus() == TFA.GetStatus("bashing") ) then + delay = wep:GetStatusEnd() - CurTime() + if dtap2 then + delay = delay * 0.8 + end + if dtap1 then + delay = delay * 0.8 + end + wep:SetStatusEnd( CurTime() + delay ) + end + end + end + wep.SecondaryAttackOld = wep.SecondaryAttackOld or wep.SecondaryAttack + wep.SecondaryAttack = function(self, ...) + local npfold = wep:GetNextPrimaryFire() + wep.SecondaryAttackOld(wep, ...) + if wep:GetNextPrimaryFire() <= npfold then return end + + local dtap1,dtap2 = wep.Owner:HasPerk("dtap"), wep.Owner:HasPerk("dtap2") + if dtap1 or dtap2 then + local delay = wep:GetNextPrimaryFire() - CurTime() + if dtap2 then + delay = delay * 0.8 + end + if dtap1 then + delay = delay * 0.8 + end + wep:SetNextPrimaryFire(CurTime() + delay) + if ( wep:GetStatus() == TFA.GetStatus("shooting") or wep:GetStatus() == TFA.GetStatus("bashing") ) then + delay = wep:GetStatusEnd() - CurTime() + if dtap2 then + delay = delay * 0.8 + end + if dtap1 then + delay = delay * 0.8 + end + wep:SetStatusEnd( CurTime() + delay ) + end + end + end +end) + +nzWeps:AddWeaponModification("tfa_attachmentmod", "equip", function(wep) + return wep:IsTFA() +end, function(wep) + if wep.Attachments then + wep.CanAttach = function() + return false + end + wep.SetTFAAttachment = function(self, cat, id, nw) + if ( not self.Attachments[cat] ) then return false end + if id ~= self.Attachments[cat].sel then + local att_old = TFA.Attachments[ self.Attachments[cat].atts[ self.Attachments[cat].sel ] or -1 ] + if att_old then + att_old:Detach( self ) + end + + local att_neue = TFA.Attachments[ self.Attachments[cat].atts[ id ] or -1 ] + if att_neue then + att_neue:Attach( self ) + end + end + self:ClearStatCache() + if id > 0 then + self.Attachments[cat].sel = id + else + self.Attachments[cat].sel = nil + end + self:BuildAttachmentCache() + if nw then + net.Start("TFA_Attachment_Set") + net.WriteEntity(self) + net.WriteInt(cat,8) + net.WriteInt( id or -1 ,5) + if SERVER then + net.Broadcast() + elseif CLIENT then + net.SendToServer() + end + end + return true + end + end +end) + +local cond = function(wep) return SERVER and wep:IsTFA() and GetConVar("nz_papattachments"):GetBool() end +local atts = function(wep) + if wep.Attachments then + for k,v in pairs(wep.Attachments) do + if v.header and string.lower(v.header) != "magazine" and string.lower(v.header) != "mag" then -- Mag can't be edited + wep:SetTFAAttachment(k, math.random(table.Count(v.atts)), true) + end + end + end + return true +end +nzWeps:AddWeaponModification("pap_tfa_attachments", "pap", cond, atts) -- Add the same to both PaP and Re-PaP +nzWeps:AddWeaponModification("pap_tfa_attachments", "repap", cond, atts) + + +if SERVER then + util.AddNetworkString("nzPaPCamo") + hook.Add("OnViewModelChanged", "nzPaPCamoUpdate", function(vm, old, new) + if IsValid(vm) and IsValid(vm:GetOwner()) then + --print(vm:GetOwner()) + net.Start("nzPaPCamo") + net.Send(vm:GetOwner()) + end + end) +end + +if CLIENT then + CreateClientConVar("nz_papcamo", 1, true, false, "Sets whether Pack-a-Punch applies a camo to your viewmodel") + + local function PaPCamoUpdate(vm, old, new) + if !IsValid(LocalPlayer()) then return end + local wep = LocalPlayer():GetActiveWeapon() + --vm:SetSubMaterial() + if !IsValid(wep) then return end + local view = wep.CW_VM or wep.Wep or vm or LocalPlayer():GetViewModel() + if IsValid(view) then + view:SetSubMaterial() + if !GetConVar("nz_papcamo"):GetBool() then return end + if wep.PaPCamo then -- You can also use a function + wep:PaPCamo(view) + elseif wep.PaPMats2 then -- Will be generated if not defined in the weapon file + timer.Simple(0.01, function() + for k,v in pairs(wep.PaPMats2) do + view:SetSubMaterial(k, "models/XQM/LightLinesRed_tool.vtf") + end + end) + end + end + end + hook.Add("OnViewModelChanged", "nzPaPCamoUpdate", PaPCamoUpdate) + net.Receive("nzPaPCamo", function() PaPCamoUpdate() end) +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/weapons/sh_wep_sync.lua b/gamemodes/nzombies/gamemode/weapons/sh_wep_sync.lua new file mode 100644 index 00000000..cbd2886d --- /dev/null +++ b/gamemodes/nzombies/gamemode/weapons/sh_wep_sync.lua @@ -0,0 +1,38 @@ +-- Client Server Syncing + + +if SERVER then + + -- Server to client (Server) + util.AddNetworkString( "nzWeps.Sync" ) + + function nzWeps:SendSync( ply, weapon, modifier, revert ) + net.Start( "nzWeps.Sync" ) + net.WriteEntity( weapon ) + net.WriteString( modifier ) + net.WriteBool( revert ) + return ply and net.Send( ply ) or net.Broadcast() + end + +end + +if CLIENT then + + -- Server to client (Client) + local function ReceiveSync( length ) + local wep = net.ReadEntity() + local modifier = net.ReadString() + local revert = net.ReadBool() + + if !IsValid(wep) or !modifier then return end + + if revert then + wep:RevertNZModifier(modifier) + else + wep:ApplyNZModifier(modifier) + end + end + + -- Receivers + net.Receive( "nzWeps.Sync", ReceiveSync ) +end diff --git a/gamemodes/nzombies/gamemode/weapons/sh_weps.lua b/gamemodes/nzombies/gamemode/weapons/sh_weps.lua new file mode 100644 index 00000000..f5bcabee --- /dev/null +++ b/gamemodes/nzombies/gamemode/weapons/sh_weps.lua @@ -0,0 +1,62 @@ +local wepMeta = FindMetaTable("Weapon") + +function wepMeta:NZPerkSpecialTreatment( ) + if self:IsFAS2() or self:IsCW2() or self:IsTFA() then + return true + end + + return false +end + +function wepMeta:IsFAS2() + if self.Category == "FA:S 2 Weapons" or self.Base == "fas2_base" then + return true + else + local base = weapons.Get(self.Base) + if base and base.Base == "fas2_base" then + return true + end + end + + return false +end + +function wepMeta:IsCW2() + if self.Category == "CW 2.0" or self.Base == "cw_base" then + return true + else + local base = weapons.Get(self.Base) + if base and base.Base == "cw_base" then + return true + end + end + + return false +end + +function wepMeta:IsTFA() + if self.Category == "TFA" or self.Base == "tfa_gun_base" or string.sub(self:GetClass(), 1, 3) == "tfa" then + return true + else + local base = weapons.Get(self.Base) + if base and base.Base == "tfa_gun_base" then + return true + end + end + + return false +end + +function wepMeta:CanRerollPaP() + return (self.OnRePaP or (self.Attachments and ((self:IsCW2() and CustomizableWeaponry) or self:IsTFA()) or self:IsFAS2())) +end + +local old = wepMeta.GetPrintName +function wepMeta:GetPrintName() + local name = old(self) + if !name or name == "" then name = self:GetClass() end + if self:HasNZModifier("pap") then + name = self.NZPaPName or nz.Display_PaPNames[self:GetClass()] or nz.Display_PaPNames[name] or "Upgraded "..name + end + return name +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/weapons/sv_ammo.lua b/gamemodes/nzombies/gamemode/weapons/sv_ammo.lua new file mode 100644 index 00000000..7d9997f4 --- /dev/null +++ b/gamemodes/nzombies/gamemode/weapons/sv_ammo.lua @@ -0,0 +1,100 @@ +-- Functions +function nzWeps:CalculateMaxAmmo(class, pap) + local wep = isentity(class) and class:IsWeapon() and class or weapons.Get(class) + local clip = wep.Primary.ClipSize + + if pap then + clip = math.Round((clip *1.5)/5)* 5 + return clip * 10 <= 500 and clip * 10 or clip * math.ceil(500/clip) -- Cap the ammo to stop at the clip that passes 500 max + else + return clip * 10 <= 300 and clip * 10 or clip * math.ceil(300/clip) -- 300 max for non-pap weapons + end +end + +function nzWeps:GiveMaxAmmoWep(ply, class, papoverwrite) + + for k,v in pairs(ply:GetWeapons()) do + -- If the weapon entity exist, just give ammo on that + if v:GetClass() == class then v:GiveMaxAmmo(papoverwrite) return end + end + + -- Else we'll have to refer to the old system (for now, this should never happen) + local wep = weapons.Get(class) + if !wep then return end + + -- Weapons can have their own Max Ammo functions that are run instead + if wep.NZMaxAmmo then wep:NZMaxAmmo() return end + + if !wep.Primary then return end + + local ammo_type = wep.Primary.Ammo + local max_ammo = nzWeps:CalculateMaxAmmo(class, (IsValid(ply:GetWeapon(class)) and ply:GetWeapon(class):HasNZModifier("pap")) or papoverwrite) + + local curr_ammo = ply:GetAmmoCount( ammo_type ) + local give_ammo = max_ammo - curr_ammo + + --print(give_ammo) + + -- Just for display, since we're setting their ammo anyway + ply:GiveAmmo(give_ammo, ammo_type) + ply:SetAmmo(max_ammo, ammo_type) + +end + +local usesammo = { + ["grenade"] = "nz_grenade", + ["specialgrenade"] = "nz_specialgrenade", +} + +local plymeta = FindMetaTable("Player") +function plymeta:GiveMaxAmmo(papoverwrite) + for k,v in pairs(self:GetWeapons()) do + if !v:IsSpecial() then + v:GiveMaxAmmo() + else + local wepdata = v.NZSpecialWeaponData + if !wepdata then return end + + local ammo = usesammo[v:GetSpecialCategory()] or wepdata.AmmoType + local maxammo = wepdata.MaxAmmo + + if ammo and maxammo then + self:SetAmmo(maxammo, GetNZAmmoID(ammo) or ammo) -- Special weapon ammo or just that ammo + end + + end + end +end + +local meta = FindMetaTable("Weapon") + +function meta:CalculateMaxAmmo(papoverwrite) + if !self.Primary then return 0 end + local clip = self.Primary and self.Primary.ClipSize or self.Primary.ClipSize_Orig + if !clip then return 0 end + -- When calculated directly on a weapon entity, its clipsize will already have changed from PaP + if self:HasNZModifier("pap") or papoverwrite then + return clip * 10 <= 500 and clip * 10 or clip * math.ceil(500/clip) -- Cap the ammo to stop at the clip that passes 500 max + else + return clip * 10 <= 300 and clip * 10 or clip * math.ceil(300/clip) -- 300 max for non-pap weapons + end +end + +function meta:GiveMaxAmmo(papoverwrite) + + if self.NZMaxAmmo then self:NZMaxAmmo(papoverwrite) return end + + local ply = self.Owner + if !IsValid(ply) then return end + + local ammo_type = self:GetPrimaryAmmoType() or self.Primary.Ammo + local max_ammo = self:CalculateMaxAmmo(papoverwrite) + + local curr_ammo = ply:GetAmmoCount( ammo_type ) + local give_ammo = max_ammo - curr_ammo + + -- Just for display, since we're setting their ammo anyway + ply:GiveAmmo(give_ammo, ammo_type) + ply:SetAmmo(max_ammo, ammo_type) + +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/weapons/sv_roundresupply.lua b/gamemodes/nzombies/gamemode/weapons/sv_roundresupply.lua new file mode 100644 index 00000000..dfcb47eb --- /dev/null +++ b/gamemodes/nzombies/gamemode/weapons/sv_roundresupply.lua @@ -0,0 +1,17 @@ +nzWeps.RoundResupply = {} + +function nzWeps:AddAmmoToRoundResupply(ammo, count, max) + nzWeps.RoundResupply[ammo] = {count = count, max = max} +end + +function nzWeps:DoRoundResupply() + for k,v in pairs(player.GetAllPlaying()) do + for k2,v2 in pairs(nzWeps.RoundResupply) do + local give = math.Clamp(v2.max - v:GetAmmoCount(k2), 0, v2.count) + v:GiveAmmo(give, k2, true) + end + end +end + +-- Standard grenades +nzWeps:AddAmmoToRoundResupply(GetNZAmmoID( "grenade" ) or "nz_grenade", 2, 4) \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/weapons/sv_weps.lua b/gamemodes/nzombies/gamemode/weapons/sv_weps.lua new file mode 100644 index 00000000..0404c93f --- /dev/null +++ b/gamemodes/nzombies/gamemode/weapons/sv_weps.lua @@ -0,0 +1,99 @@ +if not ConVarExists("nz_papattachments") then CreateConVar("nz_papattachments", 1, {FCVAR_SERVER_CAN_EXECUTE, FCVAR_NOTIFY}, "Whether Pack-a-Punching a CW2.0 weapon will attach random attachments for each category. Will also strip players of attachments at the beginning of the game.") end + +hook.Add("PlayerSpawn", "RemoveCW2Attachments", function(ply) + if GetConVar("nz_papattachments"):GetBool() and CustomizableWeaponry then + for k,v in pairs(ply.CWAttachments) do + CustomizableWeaponry:removeAttachment(ply, k) + end + end +end) + +function GetPriorityWeaponSlot(ply) + -- Create some variables to use + local maxnum = ply:HasPerk("mulekick") and 3 or 2 + local tbl = {} + local first + + -- Loop through weapons + for k,v in pairs(ply:GetWeapons()) do + local slot = v:GetNWInt("SwitchSlot") + -- Mark this slot as being used + tbl[slot] = true + -- Also save whichever weapon has slot 1 in case the activeweapon doesnt have a slot + if slot == 1 then first = v end + end + -- Now loop through the maxnumber we can have + for i = 1, maxnum do + -- If this slot hasn't been taken, return it + if !tbl[i] then return i end + end + -- If we didn't return before (all slots taken), check the activeweapon + local activewep = ply:GetActiveWeapon() + local id = activewep:GetNWInt("SwitchSlot") + -- Only replace it if it has an ID (default is 0) + if id > 0 then + return id, activewep + end + -- Else we should return the weapon stored in slot 1, if nothing at all just return slot 1 alone + if first then return 1, first else return 1 end +end + +local function OnWeaponAdded( weapon ) + + if !weapon:IsSpecial() then + weapon.Weight = 10000 + -- 0 seconds timer for the next tick, where the weapon's owner will be valid + timer.Simple(0, function() + local ply = weapon:GetOwner() + if !nzRound:InState( ROUND_CREATE ) then + local slot, exists = GetPriorityWeaponSlot(ply) + if IsValid(exists) then ply:StripWeapon( exists:GetClass() ) end + + weapon:SetNWInt( "SwitchSlot", slot ) + local oldammo = weapon.Primary.Ammo + local newammo = weapon:GetPrimaryAmmoType() -- Get the ammo ID used for this weapon slot + weapon.Primary.Ammo = game.GetAmmoName(newammo) -- Set ammo type to the ammo type designated by this slot! + weapon.Primary.OldAmmo = oldammo -- Save the old ammo (just in case) + --weapon:GiveMaxAmmo() We can't do this! PaP should NOT give ammo when rerolling! + + weapon.Weight = 10000 + ply:SelectWeapon(weapon:GetClass()) + timer.Simple(0, function() + if IsValid(ply) then + if ply:HasPerk("speed") then + weapon:ApplyNZModifier("speed") + end + if ply:HasPerk("dtap") or ply:HasPerk("dtap2") then + weapon:ApplyNZModifier("dtap") + end + if !weapon.NoSpawnAmmo then + weapon:GiveMaxAmmo() + end + ply:SelectWeapon(weapon:GetClass()) + end + weapon.Weight = 0 + end) + end + if weapon.NearWallEnabled then weapon.NearWallEnabled = false end + if weapon:IsFAS2() then weapon.NoNearWall = true end + + weapon:ApplyNZModifier("equip") + end) + end + +end + +--Hooks +hook.Add("WeaponEquip", "nzOnWeaponAdded", OnWeaponAdded) + +hook.Add("PlayerCanPickupWeapon", "PreventWhosWhoWeapons", function(ply, wep) + if IsValid(wep:GetOwner()) and wep:GetOwner():GetClass() == "whoswho_downed_clone" then return false end +end) + +-- Meta stuff +local meta = FindMetaTable("Player") +function meta:GiveNoAmmo(class) + local wep = self:Give(class) + if IsValid(wep) then wep.NoSpawnAmmo = true end + return wep +end \ No newline at end of file diff --git a/gamemodes/nzombies/gamemode/weapons/sv_wonderweapons.lua b/gamemodes/nzombies/gamemode/weapons/sv_wonderweapons.lua new file mode 100644 index 00000000..1f22795d --- /dev/null +++ b/gamemodes/nzombies/gamemode/weapons/sv_wonderweapons.lua @@ -0,0 +1,77 @@ +local wonderweapons = {} + +-- Wonder Weapon system does NOT apply to weapons like Monkey Bombs or Ray Gun +-- ONLY to those that you can only have 1 of at a time + +function nzWeps:AddWonderWeapon(class) + wonderweapons[class] = true +end + +function nzWeps:RemoveWonderWeapon(class) + wonderweapons[class] = nil +end + +function nzWeps:IsWonderWeapon(class) + return wonderweapons[class] or false +end + +function nzWeps:GetHeldWonderWeapons(ply) -- No arguments means all players + local tbl = {} + if IsValid(ply) and ply:IsPlayer() then + for k,v in pairs(ply:GetWeapons()) do + if wonderweapons[v:GetClass()] then + table.insert(tbl, v:GetClass()) + end + end + else + for k,v in pairs(player.GetAll()) do + for k2,v2 in pairs(v:GetWeapons()) do + if wonderweapons[v2:GetClass()] then + table.insert(tbl, v2:GetClass()) + end + end + end + end + + return tbl +end + +function nzWeps:IsWonderWeaponOut(class, ignorewonder) + if (wonderweapons[class] or ignorewonder) then + for k,v in pairs(player.GetAll()) do + for k2,v2 in pairs(v:GetWeapons()) do + local vclass = v2:GetClass() + if vclass == class then + return true + end + end + end + + for k,v in pairs(ents.FindByClass("random_box_windup")) do -- We also gotta check active random boxes + if v:GetWepClass() == class then + return true + end + end + end + return false +end + +-- Now let's add some! +nzWeps:AddWonderWeapon("freeze_gun") +nzWeps:AddWonderWeapon("wunderwaffe") +nzWeps:AddWonderWeapon("weapon_hoff_thundergun") +nzWeps:AddWonderWeapon("weapon_teslagun") + +-- We can also add all weapons which have SWEP.NZWonderWeapon = true set in their files +hook.Add("InitPostEntity", "nzRegisterWonderWeaponsByKey", function() + for k,v in pairs(weapons.GetList()) do + -- Add Wonder Weapons to the list + if v.NZWonderWeapon then nzWeps:AddWonderWeapon(v.ClassName) end + -- If it has a PaP replacement, blacklist that weapon so it can't be gotten in the box + if v.NZPaPReplacement then nzConfig.AddWeaponToBlacklist(v.NZPaPReplacement) end + -- Total blacklisted weapons also need to be added to the box blacklist + if v.NZTotalBlacklist then nzConfig.AddWeaponToBlacklist(v.ClassName) end + end +end) + +-- More wonder weapons should be added by map scripts for their map - if you think you have one that should officially apply to all maps, add me \ No newline at end of file diff --git a/gamemodes/nzombies/icon24.png b/gamemodes/nzombies/icon24.png new file mode 100644 index 00000000..7bf2c6df Binary files /dev/null and b/gamemodes/nzombies/icon24.png differ diff --git a/gamemodes/nzombies/logo.png b/gamemodes/nzombies/logo.png new file mode 100644 index 00000000..1addfdd3 Binary files /dev/null and b/gamemodes/nzombies/logo.png differ diff --git a/gamemodes/nzombies/nzombies.txt b/gamemodes/nzombies/nzombies.txt new file mode 100644 index 00000000..9f85c988 --- /dev/null +++ b/gamemodes/nzombies/nzombies.txt @@ -0,0 +1,134 @@ +"nzombies" +{ + "base" "base" + "title" "nZombies" + "version" "4.0" + "menusystem" "1" + "maps" "^nz_" + + "author_name" "Alig96, Zet0r, Lolle" + "author_email" "" + + "icon" "" + "info" "" + "hide" "0" + + "settings" + { + 1 + { + "name" "nz_downtime" + "text" "Bleedout Time" + "help" "How long time in seconds until you die from not being revived while downed." + "type" "Numeric" + "default" "45" + } + 2 + { + "name" "nz_randombox_maplist" + "text" "Use map's Weapon List" + "help" "Whether to replace the white- and blacklist with the config's Map Settings list - turn off to always use the above lists" + "type" "CheckBox" + "default" "1" + } + 3 + { + "name" "nz_round_special_interval" + "text" "Special round interval." + "help" "How often a special round should occur." + "type" "Numeric" + "default" "6" + "singleplayer" "1" + } + 4 + { + "name" "nz_round_prep_time" + "text" "Round preparation duration" + "help" "The duration of a round's preperation phase.." + "type" "Numeric" + "default" "10" + "singleplayer" "1" + } + 5 + { + "name" "nz_round_dropins_allow" + "text" "Allow dropins" + "help" "Allow player droppins after a round." + "type" "CheckBox" + "default" "1" + } + 6 + { + "name" "nz_difficulty_zombie_amount_base" + "text" "Base Zombie amount" + "help" "The base amount of zombies." + "type" "Numeric" + "default" "6" + } + 7 + { + "name" "nz_difficulty_zombie_amount_scale" + "text" "Zombie amount scale" + "help" "How much the Zombie amount increases each round." + "type" "Numeric" + "default" "0.35" + } + 8 + { + "name" "nz_difficulty_zombie_health_base" + "text" "Base Zombie health" + "help" "The base health of the zombies." + "type" "Numeric" + "default" "75" + } + 9 + { + "name" "nz_difficulty_zombie_health_scale" + "text" "Zombie health scale" + "help" "How much the Zombie health increases each round." + "type" "Numeric" + "default" "1.1" + } + 10 + { + "name" "nz_difficulty_max_zombies_alive" + "text" "Maximum zombies" + "help" "The maximum amount of zombies alive at a time." + "type" "Numeric" + "default" "35" + } + 11 + { + "name" "nz_difficulty_barricade_planks_max" + "text" "Barricade plank amount" + "help" "The maximum amount of planks on a barricade." + "type" "Numeric" + "default" "6" + } + 12 + { + "name" "nz_difficulty_powerup_chance" + "text" "Powerup drop chance in %" + "help" "The chance of a powerup beeing dropped after a zobmie's death." + "type" "Numeric" + "default" "2" + } + 13 + { + "name" "nz_difficulty_perks_max" + "text" "Maximum buyable perks" + "help" "The max perks you can BUY (You can get more in other ways)" + "type" "Numeric" + "default" "4" + "singleplayer" "1" + } + 14 + { + "name" "nz_point_notification_clientside" + "text" "Clientside point calculations" + "help" "Might improve server peformance a little, but can cause point stacking." + "type" "CheckBox" + "default" "0" + } + } +} diff --git a/gamemodes/nzombies/officialconfigs/nz_ttt_casino_b2;High Stakes;675138912.lua b/gamemodes/nzombies/officialconfigs/nz_ttt_casino_b2;High Stakes;675138912.lua new file mode 100644 index 00000000..27a7c232 --- /dev/null +++ b/gamemodes/nzombies/officialconfigs/nz_ttt_casino_b2;High Stakes;675138912.lua @@ -0,0 +1 @@ +{"ZedSpecialSpawns":[{"pos":"[389.8831 -685.3874 -397.6085]"},{"pos":"[940.8306 -891.9608 -397.6085]"},{"pos":"[182.4841 -836.1248 -413.6107]"},{"link":1,"pos":"[961.8286 -548.931 -397.6085]"},{"link":1,"pos":"[1325.9843 -538.2993 -373.6107]"},{"link":1,"pos":"[1786.6635 -525.478 -269.6107]"},{"link":1,"pos":"[1800.4139 -188.6616 -269.6107]"},{"link":1,"pos":"[1815.1622 250.6643 -269.6107]"},{"link":1,"pos":"[1657.479 570.0307 -269.6107]"},{"link":1,"pos":"[1817.4645 884.996 -269.6107]"},{"link":3,"pos":"[1625.2415 126.4474 -317.6107]"},{"link":3,"pos":"[1244.004 142.3239 -397.6085]"},{"link":3,"pos":"[1217.4375 493.8469 -477.6107]"},{"link":3,"pos":"[1369.3772 840.7556 -477.6107]"},{"link":3,"pos":"[1155.5034 1235.158 -477.6107]"},{"link":3,"pos":"[997.0636 739.7059 -477.6107]"},{"link":3,"pos":"[794.3025 139.7442 -397.6085]"},{"link":3,"pos":"[284.3532 207.6278 -397.6085]"},{"link":3,"pos":"[49.8564 -151.2013 -397.6085]"},{"link":3,"pos":"[-148.1327 137.8552 -397.6085]"},{"link":2,"pos":"[-28.56 102.0333 -397.6085]"},{"link":2,"pos":"[153.4195 207.4687 -397.6085]"},{"link":2,"pos":"[6.7695 446.6807 -397.6085]"},{"link":3,"pos":"[1671.8269 892.8224 -477.6107]"},{"link":5,"pos":"[2372.9583 782.2715 -557.6108]"},{"link":5,"pos":"[2545.4697 1221.1886 -557.6108]"},{"link":6,"pos":"[1518.1071 1244.9358 -269.6107]"},{"link":6,"pos":"[985.1483 1231.7772 -269.6107]"},{"link":6,"pos":"[741.0702 1518.942 -269.6107]"},{"link":6,"pos":"[1068.2056 1649.1776 -269.6107]"},{"link":4,"pos":"[57.341 1764.8676 -245.6107]"},{"link":4,"pos":"[-339.1318 1466.7074 -245.6107]"},{"link":4,"pos":"[51.8024 1202.1738 -397.6085]"},{"link":4,"pos":"[-31.051 950.9265 -397.6085]"}],"NavTable":{"2851":{"locked":true},"2357":{"locked":true},"3369":{"locked":true,"link":"4"},"3361":{"locked":true},"3300":{"locked":true},"3312":{"locked":true,"link":"2"},"3324":{"locked":true,"link":"6"},"3246":{"locked":true},"3256":{"locked":true},"3214":{"locked":true},"1829":{"locked":true},"2971":{"locked":true},"2698":{"locked":true,"link":"5"},"1759":{"locked":true},"3348":{"locked":true,"link":"3"},"1748":{"locked":true},"3332":{"locked":true,"link":"4"},"1787":{"locked":true},"1788":{"locked":true},"3307":{"locked":true},"3355":{"locked":true,"link":"2"},"1779":{"locked":true},"1690":{"locked":true},"3303":{"locked":true},"3373":{"locked":true},"2850":{"locked":true},"1692":{"locked":true},"3247":{"locked":true},"3358":{"locked":true},"3259":{"locked":true},"3344":{"locked":true,"link":"3"},"3213":{"locked":true},"2162":{"locked":true},"2972":{"locked":true},"3350":{"locked":true,"link":"5"},"3327":{"locked":true,"link":"6"},"1753":{"locked":true},"3341":{"locked":true,"link":"4"},"3320":{"locked":true,"link":"1"},"3329":{"locked":true,"link":"4"},"3365":{"locked":true,"link":"4"},"3337":{"locked":true,"link":"4"},"3353":{"locked":true,"link":"3"},"3322":{"locked":true,"link":"3"}},"version":400,"DoorSetup":{"1482":{"flags":"price=0,elec=0,buyable=1"},"1276":{"flags":"price=1000,elec=0,buyable=0"},"1481":{"flags":"price=0,elec=0,buyable=1"},"1480":{"flags":"price=1000,elec=0,buyable=0"},"1479":{"flags":"price=0,elec=0,buyable=1"}},"InvisWalls":[{"maxbound":"[-45.5 -919.9375 175.375]","pos":"[-191.875 1647.7188 -245.8438]"},{"maxbound":"[42.8438 -919.9375 175.8125]","pos":"[223.9375 1647.7188 -245.625]"},{"maxbound":"[15.7813 227.1875 319.1875]","pos":"[-33.75 1384.625 -389.0313]"},{"maxbound":"[-15.8438 225.8438 318.1875]","pos":"[-156.0313 1385.875 -388.1875]"},{"maxbound":"[-16.2188 259.9688 317.2813]","pos":"[62.0313 1387.75 -387.0938]"},{"maxbound":"[16.9063 259.9375 319.5625]","pos":"[183.4688 1387.7813 -389.4063]"},{"maxbound":"[-35.5938 35.25 327.7813]","pos":"[208.3438 1360.4688 -397.5938]"},{"maxbound":"[34.4688 33.7813 327.7188]","pos":"[36.6875 1359.9688 -397.5938]"},{"maxbound":"[-29.625 31.5313 327.875]","pos":"[-12.1563 1357.3438 -397.5938]"},{"maxbound":"[-30.1875 33.0313 327.5625]","pos":"[-149.75 1359.5625 -397.5938]"},{"maxbound":"[72.125 147 215.9375]","pos":"[354.0938 131 -245.5938]"},{"maxbound":"[89.375 -111.25 154.3438]","pos":"[979.0938 1467.6563 -269.5938]"},{"maxbound":"[31.8438 75.625 155.2188]","pos":"[1140.0938 1462.0313 -269.5938]"},{"maxbound":"[-85.6875 108.1875 159.9375]","pos":"[1560.0313 1357.0625 -269.5938]"},{"maxbound":"[-143.7188 71.1875 463.8125]","pos":"[2220.0313 432.0313 -557.5]"},{"maxbound":"[5.1875 -136.8438 175.9063]","pos":"[2075.0938 571.7188 -269.5938]"},{"maxbound":"[-186.9688 -39.2188 127.9063]","pos":"[1033.5 -958.8125 -397.5938]"},{"maxbound":"[23 42.5313 135.9063]","pos":"[1010.4688 -1039.9375 -397.5938]"},{"maxbound":"[-23 42.4063 135.9063]","pos":"[869.75 -1040.1875 -397.5938]"}],"BuyablePropSpawns":[{"pos":"[183.9562 -928.349 -372.4261]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{0 73.8613 -0}"},{"pos":"[98.6638 -840.1182 -368.7832]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{0 16.4451 -0}"},{"pos":"[213.7869 -971.2014 -368.1082]","model":"models/props_c17/fence02b.mdl","collision":0,"angle":"{0 36.5641 0}"},{"pos":"[41.9739 -796.2161 -365.1776]","model":"models/props_c17/fence02b.mdl","collision":0,"angle":"{0 89.7176 -0}"},{"pos":"[336.442 -1011.7482 -415.0801]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{-0 0.4845 0}"},{"pos":"[-5.2528 -705.5134 -360.0629]","model":"models/props_c17/fence02b.mdl","collision":0,"angle":"{0 -0.3959 0}"},{"pos":"[557.0767 -538.4931 -343.7874]","flags":"link=1,price=500,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{-0 -0.528 0}"},{"pos":"[1049.4407 -780.1319 -343.4713]","flags":"link=1,price=500,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 87.6895 -0}"},{"pos":"[830.5803 -779.2029 -345.2454]","flags":"link=1,price=500,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 90.8575 0}"},{"pos":"[382.8487 -245.2205 -345.6705]","flags":"link=2,price=500,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 89.8599 -0}"},{"pos":"[1716.2283 -87.9184 -217.7245]","flags":"link=3,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{-0 -1.3199 0}"},{"pos":"[1809.9698 -420.0099 -216.436]","flags":"link=1,price=500,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 91.1722 -0}"},{"pos":"[531.8845 135.4289 -345.9071]","flags":"link=3,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 0.5281 -0}"},{"pos":"[117.6386 631.7202 -345.1119]","flags":"link=4,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 90 -0}"},{"pos":"[-103.4701 630.6705 -345.5871]","flags":"link=4,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 90 -0}"},{"pos":"[-265.5003 383.6479 -396.2065]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{0 0.66 0}"},{"pos":"[-350.6588 384.204 -400.0572]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{-0 0.132 0}"},{"pos":"[-312.8401 641.9106 -193.4552]","flags":"link=4,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 90 -0}"},{"pos":"[338.8817 646.2869 -192.8883]","flags":"link=4,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 89.9999 -0}"},{"pos":"[250.8696 553.8961 -200.659]","model":"models/props_wasteland/interior_fence002e.mdl","collision":0,"angle":"{0 -2.5079 0}"},{"pos":"[220.6307 601.274 -194.9941]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{0 54.4365 0}"},{"pos":"[-227.5287 545.6057 -193.7652]","model":"models/props_wasteland/interior_fence002e.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[-194.5828 592.8581 -195.403]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{0 -49.8762 0}"},{"pos":"[-192.0684 499.9228 -196.3513]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{-0 52.4327 0.0001}"},{"pos":"[-30.4544 474.9312 -182.5172]","model":"models/props_wasteland/interior_fence002d.mdl","collision":0,"angle":"{0 88.6284 -0}"},{"pos":"[147.2686 490.5908 -189.5347]","model":"models/props_c17/fence02b.mdl","collision":0,"angle":"{-0.1648 -73.8216 0.0268}"},{"pos":"[2008.2692 786.5069 -423.3795]","flags":"link=5,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 -180 0}"},{"pos":"[218.1751 509.1033 -196.8495]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{0 -57.8867 0}"},{"pos":"[1970.559 513.677 -218.2099]","flags":"link=5,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door01a.mdl","collision":0,"angle":"{-0 -0.264 0}"},{"pos":"[1194.3953 1139.3048 -218.2735]","model":"models/props_c17/fence03a.mdl","collision":0,"angle":"{-0 89.9999 0}"},{"pos":"[1363.6348 1139.1658 -218.2629]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{0 90 -0}"},{"pos":"[1026.1775 1138.8654 -217.4068]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{0 90 -0}"},{"pos":"[1810.1699 1135.955 -217.7215]","flags":"link=6,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 90 -0}"},{"pos":"[408.0234 1780.4292 -193.5242]","flags":"link=4,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 -0.0005 0.0001}"},{"pos":"[812.8981 878.3658 -424.4413]","flags":"link=3,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[404.8159 1154.1699 -345.1608]","flags":"link=4,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[-401.9546 1118.7227 -356.6552]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{0 -59.8282 0}"},{"pos":"[-400.4076 1214.8768 -362.3685]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{-0 59.767 0.0001}"},{"pos":"[360.4815 1442.9998 -348.1653]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{-0 -29.4552 0}"},{"pos":"[-177.613 1361.1777 -397.6085]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[-207.1526 1305.9773 -397.6085]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[656.9556 1779.0653 -193.5436]","flags":"link=6,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 1.0525 -0}"},{"pos":"[1986.4125 788.7255 -425.5891]","flags":"link=3,price=1000,elec=0,buyable=1","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[887.3828 429.1974 -423.2568]","model":"models/props_c17/fence02b.mdl","collision":0,"angle":"{-0 -35.6936 0}"},{"pos":"[881.045 540.2059 -429.1325]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{-0 44.7337 0.0001}"},{"pos":"[2087.2236 -532.2124 -273.8987]","model":"models/props_trainstation/traincar_seats001.mdl","collision":20,"angle":"{0 -0.1319 0}"},{"pos":"[248.3103 1410.4989 -344.3904]","model":"models/props_c17/fence02b.mdl","collision":0,"angle":"{-0 88.6269 0}"},{"pos":"[12.9073 1359.45 -343.4249]","model":"models/props_c17/fence02b.mdl","collision":0,"angle":"{-0 91.187 0}"},{"pos":"[2077.5354 -532.4479 -285.3516]","model":"models/props_trainstation/traincar_seats001.mdl","collision":20,"angle":"{-0 -0.264 0}"},{"pos":"[1811.1448 -720.7073 -307.6138]","model":"models/props_c17/shelfunit01a.mdl","collision":0,"angle":"{-0 0.264 -44.9996}"},{"pos":"[1847.3927 -663.3439 -267.2398]","model":"models/nzprops/zombies_power_lever_short.mdl","collision":0,"angle":"{-0 75.8752 -90}"},{"pos":"[1427.1359 386.2666 -476.9792]","model":"models/nzprops/origins/barbwire_gate.mdl","collision":0,"angle":"{-0 21.3816 0}"},{"pos":"[1431.4291 549.4119 -481.3182]","model":"models/nzprops/origins/barbwire_blockade.mdl","collision":0,"angle":"{-0 -19.866 0}"},{"pos":"[1411.8794 490.2147 -478.9156]","model":"models/nzprops/origins/originscorpse04stick.mdl","collision":0,"angle":"{-1.3177 4.2562 7.4667}"},{"pos":"[1409.2213 437.1034 -481.2137]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 1.848 0}"},{"pos":"[1435.2802 364.7926 -478.5827]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 -0.3961 0}"},{"pos":"[656.3718 137.2621 -345.831]","flags":"link=2,buyable=1,price=500,elec=0,rebuyable=0","model":"models/props_c17/gate_door02a.mdl","collision":0,"angle":"{0 -0 0.0001}"},{"pos":"[2202.7886 465.0724 -519.0276]","model":"models/props_interiors/vendingmachinesoda01a.mdl","collision":0,"angle":"{0 -3.5611 0}"},{"pos":"[2201.7339 525.4135 -510.9504]","model":"models/props_wasteland/controlroom_storagecloset001b.mdl","collision":0,"angle":"{-11.7645 -0.1323 16.0118}"},{"pos":"[2196.4739 552.3364 -520.5676]","model":"models/props_junk/pushcart01a.mdl","collision":0,"angle":"{90 92.2496 180}"},{"pos":"[2074.4968 552.1774 -554.2536]","model":"models/props_junk/garbage256_composite002b.mdl","collision":0,"angle":"{-0 20.2622 0}"},{"pos":"[2159.1775 476.0496 -526.8054]","model":"models/props_interiors/furniture_couch02a.mdl","collision":0,"angle":"{-0 -0.5283 0}"},{"pos":"[2125.2969 446.4371 -553.2319]","model":"models/props/wet_floor01.mdl","collision":0,"angle":"{0 44.7487 0}"},{"pos":"[2101.4431 528.101 -557.488]","model":"models/props/facility_backzone/bucket01a.mdl","collision":0,"angle":"{0 79.6896 -0}"}],"SpecialEntities":[],"RandomBoxSpawns":[{"angle":"{-0.0615 -0.0056 -0.3519}","pos":"[935.889 -1033.9697 -396.9097]"},{"angle":"{-0.022 89.4684 0.564}","pos":"[1438.0627 -534.6191 -269.3495]"},{"angle":"{0.1542 179.9946 1.5106}","pos":"[17.285 -524.924 -325.3976]"},{"angle":"{-0.1346 0.0113 0.1131}","pos":"[22.3458 1880.3114 -245.1855]"},{"angle":"{0.0238 -90.011 -0.2412}","pos":"[1944.521 704.1528 -268.9648]"},{"angle":"{-0.0127 0.0653 -0.0118}","pos":"[1024.683 1851.577 -269.0024]"},{"angle":"{0.0537 179.9698 0.6611}","pos":"[1193.8911 83.1416 -397.2792]"},{"angle":"{0.2371 179.9252 0.1196}","pos":"[2548.75 719.2097 -556.8928]"}],"ElecSpawns":[{"angle":"{-0 270 0}","pos":"[2539.2178 1430.7488 -557.1972]"}],"WallBuys":[{"angle":"{-0 133.6799 0}","pos":"[606.6221 -783.3337 -344.7821]","flipped":true,"price":500,"wep":"fas2_m1911"},{"angle":"{0 88.944 0}","pos":"[392.5947 -904.8212 -378.2962]","flipped":true,"price":500,"wep":"fas2_m21"},{"angle":"{-0 90.1148 0}","pos":"[1408.1886 -533.4385 -325.691]","flipped":true,"price":750,"wep":"fas2_rem870"},{"angle":"{-0 -180 0}","pos":"[14.7189 603.4263 -350.7854]","flipped":true,"price":750,"wep":"fas2_deagle"},{"angle":"{0.1441 177.9223 -5.0846}","pos":"[958.0509 1591.7395 -427.451]","flipped":true,"price":2000,"wep":"fas2_g36c"},{"angle":"{0 270 0}","pos":"[2428.0313 1050.9688 -501.6875]","flipped":true,"price":2500,"wep":"fas2_ak47"},{"angle":"{0 -89.4061 0}","pos":"[1981.2249 462.6947 -403.9531]","flipped":true,"price":2000,"wep":"fas2_galil"},{"angle":"{0 90 0}","pos":"[2644 1064.625 -506.0625]","flipped":true,"price":2000,"wep":"fas2_famas"},{"angle":"{0 270 0}","pos":"[-355.9688 872.3125 -342.8438]","flipped":true,"price":1500,"wep":"fas2_m14"},{"angle":"{0 360 0}","pos":"[12.5 1687.7813 -189.7813]","flipped":true,"price":1000,"wep":"fas2_uzi"},{"angle":"{0 -1.584 0}","pos":"[1256.6617 1600.3226 -214.9208]","flipped":true,"price":1000,"wep":"fas2_mp5k"},{"angle":"{0 88.086 0}","pos":"[1721.1182 600.3619 -250.0489]","flipped":true,"price":1250,"wep":"fas2_mp5sd6"}],"BreakEntry":[{"jump":false,"angle":"{-0 -132.9999 0}","pos":"[132.7617 -890.7272 -369.8478]","planks":true},{"jump":false,"angle":"{0 -89.4266 0}","pos":"[290.3234 -994.8759 -371.8059]","planks":true},{"jump":false,"angle":"{-0 -171.9655 0}","pos":"[1.0067 -768.9325 -364.7113]","planks":true},{"jump":false,"angle":"{-0 89.9704 0}","pos":"[-309.8142 367.1434 -348.7644]","planks":true},{"jump":false,"angle":"{-0 178.03 0}","pos":"[-229.9243 545.7024 -195.7806]","planks":true},{"jump":false,"angle":"{0 -0.8649 0}","pos":"[256.0614 552.0737 -193.9111]","planks":true},{"jump":false,"angle":"{-0 -0.743 0}","pos":"[1030.5059 1518.6576 -432.816]","planks":true},{"jump":false,"angle":"{0 -177.3773 0}","pos":"[1540.5536 1519.3099 -430.1652]","planks":true},{"jump":false,"angle":"{-0 -179.6387 0}","pos":"[2031.3937 1148.7386 -430.1214]","planks":true},{"jump":false,"angle":"{0 -178.3384 0}","pos":"[2032.1746 1092.0953 -433.3213]","planks":true},{"jump":false,"angle":"{-0 -179.868 0}","pos":"[2031.2197 1264.2307 -430.8684]","planks":true},{"jump":false,"angle":"{-0 -179.8137 0}","pos":"[667.0264 1461.7213 -212.2179]","planks":true},{"jump":false,"angle":"{0 0 0}","pos":"[394.9764 973.4839 -197.0145]","planks":true},{"jump":false,"angle":"{-0 179.6818 0}","pos":"[-367.6821 1166.6085 -351.205]","planks":true},{"jump":false,"angle":"{-0 88.2292 0}","pos":"[312.3195 1403.8314 -348.9823]","planks":true},{"jump":false,"angle":"{0 151.2297 0}","pos":"[-188.8947 1330.4242 -349.6082]","planks":true},{"jump":false,"angle":"{-0 -1.532 0}","pos":"[2746.3123 784.6268 -510.4237]","planks":true},{"jump":false,"angle":"{-0 180 -0}","pos":"[1337.9221 1454.0002 -216.9225]","planks":true},{"jump":false,"angle":"{0 -178.8622 0}","pos":"[909.5579 487.337 -427.3129]","planks":true},{"jump":true,"angle":"{-0 0.0001 0.0001}","pos":"[2080.033 -532.7368 -225.0175]","planks":true},{"jump":false,"angle":"{-0 -1.0702 0}","pos":"[1407.2845 464.7324 -433.0344]","planks":true}],"ZedSpawns":[{"pos":"[368.929 -1484.7828 -413.6107]"},{"pos":"[-434.9544 -1353.2133 -421.6107]"},{"pos":"[-524.8842 -633.3569 -413.6107]"},{"link":1,"pos":"[2160.7649 -533.5587 -269.9688]"},{"link":1,"pos":"[1815.2195 -958.0464 -269.6107]"},{"link":2,"pos":"[-310.4518 439.905 -397.6085]"},{"link":2,"pos":"[-18.4381 550.7325 -245.6107]"},{"link":3,"pos":"[1305.1646 1517.1884 -477.6107]"},{"link":3,"pos":"[1369.884 1510.6787 -477.6107]"},{"link":3,"pos":"[1977.1096 1265.6489 -477.6107]"},{"link":3,"pos":"[1975.6116 1091.4337 -477.6107]"},{"link":3,"pos":"[1977.285 1147.3754 -477.6107]"},{"link":4,"pos":"[-522.113 928.3846 -413.6107]"},{"link":4,"pos":"[326.7743 1646.54 -397.6085]"},{"link":4,"pos":"[-300.8208 1453.2 -397.6085]"},{"link":4,"pos":"[515.366 1228.2345 -245.6107]"},{"link":4,"pos":"[-296.0492 455.5423 -397.6085]"},{"link":5,"pos":"[2826.887 908.0094 -557.6108]"},{"link":6,"pos":"[1236.2648 1446.3351 -269.6107]"},{"link":6,"pos":"[501.5851 1172.2017 -245.6107]"},{"link":3,"pos":"[860.4852 487.4164 -477.6107]"},{"link":3,"pos":"[1484.5806 469.9438 -477.6107]"}],"BlockSpawns":[{"angle":"{44.9999 -89.0782 -179.9999}","model":"models/hunter/plates/plate2x2.mdl","pos":"[1810.113 -690.5557 -267.2563]"},{"angle":"{90 158.2733 180}","model":"models/hunter/plates/plate2x2.mdl","pos":"[-262.9628 442.9485 -346.8898]"},{"angle":"{90 25.2411 180}","model":"models/hunter/plates/plate2x2.mdl","pos":"[-357.261 443.0674 -357.7581]"},{"angle":"{0 90 0}","model":"models/hunter/plates/plate1x7.mdl","pos":"[1234.1512 1423.2186 -391.4774]"},{"angle":"{90 2.5489 180}","model":"models/hunter/plates/plate1x2.mdl","pos":"[-170.102 1436.4807 -284.3526]"},{"angle":"{90 178.144 180}","model":"models/hunter/blocks/cube05x2x05.mdl","pos":"[216.5485 1469.4011 -282.8451]"},{"angle":"{0 72.7861 90}","model":"models/hunter/plates/plate2x3.mdl","pos":"[1422.7838 558.0024 -386.3761]"},{"angle":"{0 -71.2082 90.0001}","model":"models/hunter/plates/plate2x3.mdl","pos":"[1421.678 384.0052 -415.3384]"}],"PlayerSpawns":[{"pos":"[96.718 -704.054 -413.6107]"},{"pos":"[145.672 -818.4766 -413.6107]"},{"pos":"[192.1849 -865.6949 -413.6107]"},{"pos":"[267.2835 -906.8066 -413.6107]"},{"pos":"[337.3264 -941.3328 -413.6107]"},{"pos":"[240.9924 -842.2385 -413.6107]"},{"pos":"[193.8088 -785.7595 -413.6107]"},{"pos":"[175.7631 -710.7011 -405.6107]"},{"pos":"[36.9293 -684.7651 -413.6107]"}],"PerkMachineSpawns":[{"angle":"{-0 -89.9998 0}","pos":"[940.8558 -139.4317 -394.5069]","id":"jugg"},{"angle":"{0.0177 -89.9483 0.0221}","pos":"[1225.0902 1374.7982 -477.2928]","id":"pap"},{"angle":"{-0 -90 0}","pos":"[1213.6609 1306.922 -268.3626]","id":"dtap"},{"angle":"{0.3577 -90.0842 0.2903}","pos":"[53.2563 -646.8318 -413.1154]","id":"revive"},{"angle":"{0.4577 -0.0218 0.1213}","pos":"[-392.0292 212.0529 -245.3387]","id":"speed"},{"angle":"{0 90.599 0}","pos":"[336.3177 690.4959 -397.6085]","id":"vulture"},{"angle":"{0.2583 179.8578 -0.0197}","pos":"[2161.0591 1446.4911 -481.9794]","id":"mulekick"}],"EasterEggs":[{"angle":"{0 0 0}","model":"models/props_lab/huladoll.mdl","pos":"[248.3727 -363.2752 -340.6414]"},{"angle":"{0 0 0}","model":"models/props_lab/huladoll.mdl","pos":"[1246.0629 1848.8982 -245.3662]"},{"angle":"{0 135 0}","model":"models/props_lab/huladoll.mdl","pos":"[1517.1909 1162.8834 -420.6414]"}],"RemoveProps":[],"PropEffects":[],"MapSettings":{"startpoints":500,"rboxweps":["cw_m3super90","cw_mr96","cw_g3a3","cw_scarh","cw_ak74","cw_mp5","cw_g36c","cw_ar15","cw_auggsm","cw_l115","cw_deagle","cw_ump45","cw_m14","khr_vector","khr_cz858","khr_hcar","khr_mp40","khr_m1carbine","khr_mosin","khr_mp5a5","khr_sks","khr_ak103","khr_hmg","khr_svt40","khr_cb4","cw_xm1014","cw_mk11","cw_ppsh-41","cw_c7a1","nz_monkey_bomb","gdcw_raygun"],"startwep":"fas2_glock20","numweps":2,"eeurl":"https://soundcloud.com/redrose1985/cod"},"WunderfizzMachines":[{"angle":"{0.1369 0.3372 0.0713}","pos":"[-342.7596 -127.3226 -397.199]"},{"angle":"{0.3995 -89.9737 -0.1234}","pos":"[535.8199 1838.5833 -245.0419]"},{"angle":"{0.1599 90.2091 0}","pos":"[-307.7739 697.0084 -397.2201]"},{"angle":"{0.184 -0.4253 -0.1571}","pos":"[891.2708 1270.7008 -477.2133]"}]} \ No newline at end of file diff --git a/gamemodes/nzombies/officialconfigs/nz_ttt_kosovos;Breakout;675138912.lua b/gamemodes/nzombies/officialconfigs/nz_ttt_kosovos;Breakout;675138912.lua new file mode 100644 index 00000000..2bdaf192 --- /dev/null +++ b/gamemodes/nzombies/officialconfigs/nz_ttt_kosovos;Breakout;675138912.lua @@ -0,0 +1 @@ +{"ZedSpecialSpawns":[{"pos":"[3395.0276 -1032.6082 24.0313]"},{"pos":"[3760.5569 -1301.8813 24.0313]"},{"pos":"[3965.1033 -948.7398 23.0313]"},{"pos":"[4176.3213 -629.6224 152.0313]"},{"pos":"[4170.2998 -1412.3809 152.0313]"},{"link":1,"pos":"[3096.0422 -619.104 0.0313]"},{"link":1,"pos":"[3089.0381 -314.9153 0.0313]"},{"link":1,"pos":"[3125.335 4.944 0.0313]"},{"link":1,"pos":"[3412.3394 -42.5497 0.0313]"},{"link":1,"pos":"[3689.9319 233.4661 160.0313]"},{"link":2,"pos":"[3920.0791 145.2381 160.0313]"},{"link":2,"pos":"[3370.6287 660.0214 160.0313]"},{"link":2,"pos":"[3767.0447 859.4314 160.0313]"},{"link":2,"pos":"[4143.2144 876.6133 160.0313]"},{"link":2,"pos":"[4535.938 337.7188 160.0313]"},{"link":2,"pos":"[4360.981 340.5414 160.0313]"},{"link":2,"pos":"[4126.1719 534.1306 160.0313]"},{"link":2,"pos":"[4792.1836 14.7885 160.0313]"},{"link":3,"pos":"[4901.5493 -413.9255 160.0313]"},{"link":3,"pos":"[4399.1387 -610.7266 160.0313]"},{"link":5,"pos":"[5224.2495 -1907.0853 -95.9688]"},{"link":5,"pos":"[5247.0957 -1187.9369 -95.9687]"},{"link":5,"pos":"[4934.0356 -1609.2739 -31.9688]"},{"link":5,"pos":"[4670.5049 -1501.2646 -31.9688]"},{"link":5,"pos":"[4423.8389 -1307.3948 -31.9688]"},{"link":4,"pos":"[4598.9443 -607.3469 160.0313]"},{"link":4,"pos":"[4898.4678 -425.9684 160.0313]"},{"link":3,"pos":"[4675.0083 -137.8932 160.0313]"},{"link":3,"pos":"[4583.9551 135.117 160.0313]"},{"link":3,"pos":"[4117.2651 358.9526 160.0313]"},{"link":3,"pos":"[4535.9458 718.4626 160.0313]"},{"link":3,"pos":"[4152.167 812.8559 160.0313]"},{"link":3,"pos":"[3680.7686 627.1187 160.0313]"},{"link":3,"pos":"[3918.1521 158.185 160.0313]"},{"link":3,"pos":"[3915.8005 -311.0944 160.0313]"},{"link":2,"pos":"[3435.105 -47.2271 0.0313]"},{"link":2,"pos":"[3430.4646 221.7128 136.0313]"}],"NavTable":{"1544":{"prev":0,"link":"4","locked":true},"618":{"prev":0,"locked":true},"114":{"prev":0,"link":"5","locked":true},"1942":{"prev":0,"link":"1","locked":true},"1662":{"prev":0,"locked":true},"1661":{"prev":0,"locked":true},"1267":{"prev":0,"link":"1","locked":true},"1199":{"prev":0,"link":"2","locked":true},"159":{"prev":0,"link":"3","locked":true},"619":{"prev":0,"locked":true},"617":{"prev":0,"locked":true},"335":{"prev":0,"locked":true},"415":{"prev":0,"link":"1","locked":true},"1937":{"prev":0,"link":"1","locked":true},"1951":{"prev":0,"link":"2","locked":true}},"version":400,"DoorSetup":{"2113":{"flags":"price=500,buyable=1,link=1,elec=0,rebuyable=0"},"1682":{"flags":"buyable=0,price=1000,elec=0,rebuyable=1"},"1836":{"flags":"rebuyable=0,price=10,elec=0,buyable=0"},"1685":{"flags":"buyable=0,price=1000,elec=0,rebuyable=1"},"1676":{"flags":"buyable=0,price=1000,elec=0,rebuyable=1"},"2196":{"flags":"price=500,buyable=1,link=1,elec=0,rebuyable=0"},"1856":{"flags":"price=500,buyable=1,link=1,elec=0,rebuyable=0"},"2195":{"flags":"price=500,buyable=1,link=1,elec=0,rebuyable=0"},"1677":{"flags":"buyable=0,price=1000,elec=0,rebuyable=1"},"1431":{"flags":"price=500,buyable=1,link=4,elec=0,rebuyable=0"},"2197":{"flags":"price=1000,buyable=1,link=2,elec=0,rebuyable=0"},"2095":{"flags":"rebuyable=0,price=0,elec=0,buyable=1"},"1683":{"flags":"buyable=0,price=1000,elec=0,rebuyable=1"},"1684":{"flags":"buyable=0,price=1000,elec=0,rebuyable=1"}},"NavGroups":[],"InvisWalls":[{"maxbound":"[-9.6563 53.5938 175.9375]","pos":"[4036.0938 -1395.3438 152.0313]"},{"maxbound":"[-341.8438 -2.3438 175.9375]","pos":"[4036.0313 -1341.6563 152.0313]"},{"maxbound":"[336.7188 5.5 175.9375]","pos":"[3696.9688 -1266.4375 152.0313]"},{"maxbound":"[5.1875 570.2188 175.9375]","pos":"[4033.7188 -1266.25 152.0313]"},{"maxbound":"[4.5 517.125 175.9375]","pos":"[4109.8125 -1267.8125 152.0313]"},{"maxbound":"[51.875 -3.125 175.9375]","pos":"[4110 -751 152.0313]"},{"maxbound":"[-1.9063 -75.6875 175.9375]","pos":"[4162.0625 -751.5313 152.0313]"},{"maxbound":"[-1 -112.125 220.1563]","pos":"[4161.4375 -830.3125 107.7813]"},{"maxbound":"[0.4063 -190.4688 175.9375]","pos":"[4214.0313 -752.6875 152.0313]"},{"maxbound":"[1.8438 -82.5313 240.625]","pos":"[4213.9688 -860.375 87.3125]"},{"maxbound":"[-2.5 -73.0625 159.9375]","pos":"[4034.875 -1446.875 152.0313]"},{"maxbound":"[-7.1563 222.75 125.8438]","pos":"[3491.6563 -1519.9688 24.0938]"},{"maxbound":"[-128.3125 -7.5 125.9375]","pos":"[3487.9688 -1295.625 24.0313]"},{"maxbound":"[62.1563 -125.8438 292.9375]","pos":"[3353.0313 -1305.5313 -142.9688]"},{"maxbound":"[-88.8125 2.2188 255.2188]","pos":"[3543.2188 -880.1875 72.7188]"},{"maxbound":"[-81.5 -2.1875 255.5625]","pos":"[3542.5313 -823.5625 72.375]"},{"maxbound":"[-91.0938 95.3438 255.9375]","pos":"[3118.125 280.0625 0.0313]"},{"maxbound":"[-56.4375 -43.3438 255.9375]","pos":"[3083.4688 260 0]"},{"maxbound":"[-5.4688 147 84.1875]","pos":"[4473.875 292.9375 195.75]"},{"maxbound":"[207.375 -6.875 87.9375]","pos":"[4248.5625 219.7813 192.0313]"},{"maxbound":"[7.5313 207.6875 87.9375]","pos":"[4612.0625 232.25 192.0313]"},{"maxbound":"[147.4688 -7.5313 95.9375]","pos":"[4248.4688 75.4375 192.0313]"},{"maxbound":"[-132.5 5.7188 87.8438]","pos":"[3743.9688 692.4375 192.0938]"},{"maxbound":"[148.7813 -7.2813 95.9375]","pos":"[3624.5625 555.7813 192.0313]"},{"maxbound":"[-145.4063 7.4063 95.9375]","pos":"[4839.5313 212.0625 192.0313]"},{"maxbound":"[-6.7813 -148.2813 95.9375]","pos":"[4027.625 933.8125 192.0313]"},{"maxbound":"[-133.8438 45.9688 191.9375]","pos":"[4817.875 -2114.75 -31.9688]"},{"maxbound":"[-16.5625 -4.3125 86.2188]","pos":"[4262.625 -749.8125 24.0313]"},{"maxbound":"[69.625 46.75 255.9375]","pos":"[3266.2188 49.1875 0.0313]"},{"maxbound":"[20.3125 -115.5938 119.9375]","pos":"[4287.0313 825.625 160.0313]"},{"maxbound":"[-41.75 74.8125 175.9375]","pos":"[3719.8438 -1340.6563 152.0313]"},{"maxbound":"[18.0938 265.3125 287.9375]","pos":"[3711.0313 -761.3438 24.0313]"},{"maxbound":"[1.8438 -187.0313 159.9375]","pos":"[3597.9063 -627.9375 168.0313]"},{"maxbound":"[-270.625 -11.375 159.9375]","pos":"[3598.4375 -814.0313 168.0313]"},{"maxbound":"[187.3125 -2.7188 159.9375]","pos":"[3264.8125 -877 168.0313]"}],"BuyablePropSpawns":[{"pos":"[3870.9773 -750.3015 78.5465]","angle":"{-0 -85.7752 0}","model":"models/props_c17/fence03a.mdl"},{"pos":"[4115.7378 -728.7572 78.0443]","angle":"{-0 -86.6843 0}","model":"models/props_c17/fence03a.mdl"},{"pos":"[4299.8159 -1131.6956 30.4173]","angle":"{0.0069 0.4548 0.0091}","model":"models/props_wasteland/interior_fence002d.mdl","flags":"link=5,buyable=1,price=1250,elec=1,rebuyable=0"},{"pos":"[2909.6924 -371.4893 -1.1449]","angle":"{-0 -0.7919 0}","model":"models/props_wasteland/medbridge_post01.mdl"},{"pos":"[2915.5754 -280.0517 -2.6775]","angle":"{0 -1.0557 0}","model":"models/props_wasteland/medbridge_post01.mdl"},{"pos":"[3700.0435 -40.1522 196.0614]","angle":"{-0 -0.8031 0}","model":"models/props_c17/fence03a.mdl","flags":"price=1000,buyable=1,link=2,elec=0,rebuyable=0"},{"pos":"[4834.8022 -237.6875 201.5246]","angle":"{0 -43.8379 0}","model":"models/props_wasteland/interior_fence002d.mdl","flags":"link=3,buyable=1,price=1250,elec=0,rebuyable=0"},{"pos":"[4046.6985 225.4895 156.2779]","angle":"{-0 87.4918 0}","model":"models/props_c17/powerbox_damaged.mdl"},{"pos":"[3447.8127 -1248.144 -126.2949]","angle":"{0 -90 -0}","model":"models/props_wasteland/interior_fence001g.mdl","flags":"buyable=1,price=0,elec=1,rebuyable=0"},{"pos":"[2879.5825 -1177.0906 -138.2236]","angle":"{0 -0.462 0}","model":"models/props_wasteland/prison_celldoor001b.mdl"},{"pos":"[3328.2949 -1318.5757 54.6491]","angle":"{-0 0.5986 -45}","model":"models/props_interiors/vendingmachinesoda01a.mdl"},{"pos":"[3268.73 -1272.5822 36.6522]","angle":"{-90 1.1887 180}","model":"models/props_wasteland/kitchen_stove002a.mdl"},{"pos":"[4050.6882 456.2972 166.2059]","angle":"{0 1.0559 0}","model":"models/props_lab/teleplatform.mdl"},{"pos":"[4022.3591 366.1931 159.6718]","angle":"{0 -90.263 0}","model":"models/gantry_crane/crane_controlbox.mdl"},{"pos":"[5404.9434 -1045.6135 -100.0139]","angle":"{-0 89.9996 0}","model":"models/gantry_crane/crane_controlbox.mdl"},{"pos":"[5443.9443 -1161.5774 -95.34]","angle":"{0 -97.6437 0}","model":"models/combine_room/combine_wire002.mdl"},{"pos":"[5430.46 -1261.349 -134.0318]","angle":"{-0 -6.204 0}","model":"models/combine_room/combine_wire001.mdl"},{"pos":"[2817.1299 -1177.4338 -190.5547]","angle":"{-0 179.3319 0}","model":"models/props_lab/teleplatform.mdl"},{"pos":"[5386.4067 -1079.5447 -58.4197]","angle":"{-11.3943 -1.843 0.1151}","model":"models/items/car_battery01.mdl"},{"pos":"[4668.5107 209.4207 167.2689]","angle":"{-0 1.056 0}","model":"models/nzprops/origins/sandbag_blockade.mdl"},{"pos":"[4397.8784 83.3205 152.7466]","angle":"{0 89.3395 0}","model":"models/props_c17/concrete_barrier001a.mdl"},{"pos":"[4296.5967 768.4478 152.1621]","angle":"{-0 0.396 0}","model":"models/props_c17/concrete_barrier001a.mdl"},{"pos":"[4544.6274 454.7295 156.177]","angle":"{-0 90 -0}","model":"models/props_c17/concrete_barrier001a.mdl"},{"pos":"[3368.1948 782.7136 156.2093]","angle":"{-0 -0.396 0}","model":"models/props_phx/construct/concrete_barrier00.mdl"},{"pos":"[3297.0413 783.746 209.9719]","angle":"{0 90 90}","model":"models/props_c17/concrete_barrier001a.mdl"},{"pos":"[3445.0042 784.6735 223.5619]","angle":"{0 89.8694 -89.9995}","model":"models/props_c17/concrete_barrier001a.mdl"},{"pos":"[3789.3047 553.6878 175.9698]","angle":"{0 91.7155 0}","model":"models/props_debris/barricade_short02a.mdl"},{"pos":"[4607.394 -526.714 162.0931]","angle":"{0 0.396 0}","model":"models/props_phx/construct/concrete_barrier01.mdl"},{"pos":"[3699.4009 -1305.2585 179.4413]","angle":"{90 -90.792 180}","model":"models/props_lab/reciever_cart.mdl"},{"pos":"[3703.2834 -1298.9155 160.8528]","angle":"{5.2357 82.8157 1.2005}","model":"models/props_debris/broken_pile001a.mdl"},{"pos":"[3511.2173 -515.3076 188.3954]","angle":"{-0 -89.1955 -89.9995}","model":"models/props_wasteland/kitchen_stove002a.mdl"},{"pos":"[3641.856 -41.0599 1.7108]","angle":"{0 0 0}","model":"models/props_c17/signpole001.mdl"},{"pos":"[3640.0833 -37.1844 0.3013]","angle":"{0 -90.7917 0}","model":"models/props_phx/construct/concrete_barrier01.mdl"}],"SpecialEntities":[],"RandomBoxSpawns":[{"angle":"{0.0058 90.0482 0.1327}","pos":"[4051.3127 572.4468 160.585]"},{"angle":"{-0.0341 -134.4137 0.2524}","pos":"[4986.3809 -489.6053 160.4918]"},{"angle":"{0.021 89.8578 0.9451}","pos":"[2965.1812 -607.348 0.4114]"},{"angle":"{-0.2212 -0.0118 0.5276}","pos":"[3438.7952 76.5239 0.6067]"},{"angle":"{-0.0281 -179.9038 -0.1444}","pos":"[3379.2966 563.4102 158.6511]"},{"angle":"{0.1602 -90.0318 0.3818}","pos":"[5480.6387 -1605.9019 -95.3769]"}],"BreakEntry":[{"jump":false,"angle":"{-0 -179.9262 0}","pos":"[3713.9233 -1419.2626 79.5503]","planks":true},{"jump":false,"angle":"{-0 178.3213 0}","pos":"[2915.3916 -326.207 50.1391]","planks":true},{"jump":true,"angle":"{0 91.1523 0}","pos":"[4663.8096 207.2432 204.9412]","planks":true},{"jump":true,"angle":"{-0 -91.0098 0}","pos":"[4426.5093 76.7309 204.9413]","planks":true},{"jump":true,"angle":"{-0 -0.0022 0}","pos":"[4295.0938 773.5864 206.3896]","planks":false},{"jump":true,"angle":"{-0 90 0.0001}","pos":"[4544.0747 453.7821 205.4871]","planks":false},{"jump":true,"angle":"{-0 90 0}","pos":"[3371.5715 780.2276 204.3317]","planks":true},{"jump":true,"angle":"{0 -88.8404 0}","pos":"[3800.8899 554.11 204.388]","planks":true},{"jump":true,"angle":"{-0 89.1321 0}","pos":"[4632.1196 -545.2101 207.308]","planks":true},{"jump":true,"angle":"{-0 179.192 0}","pos":"[3689.4001 -1304.8629 196.8513]","planks":true},{"jump":true,"angle":"{-0 90.3918 0}","pos":"[3574.7283 -497.748 214.7285]","planks":true},{"jump":true,"angle":"{0 1.6512 0}","pos":"[3644.6221 -72.5211 46.9854]","planks":true},{"jump":true,"angle":"{0 -0.8564 0}","pos":"[3642.6294 -10.25 45.177]","planks":true}],"ElecSpawns":[{"angle":"{-0.0255 89.8586 0.015}","pos":"[4077.1973 229.4271 163.1157]"}],"WallBuys":[{"angle":"{0 540 0}","pos":"[3627.9512 -496.0313 53.137]","flipped":true,"price":500,"wep":"fas2_m1911"},{"angle":"{0 270 0}","pos":"[3264.0313 -1136.0227 75.5429]","flipped":true,"price":500,"wep":"fas2_m21"},{"angle":"{360 360 0}","pos":"[3106.9619 -757.9688 53.3728]","flipped":true,"price":1500,"wep":"fas2_m3s90"},{"angle":"{0 495 0}","pos":"[4975.8389 -327.8833 211.9781]","flipped":true,"price":1500,"wep":"fas2_rem870"},{"angle":"{0 360 0}","pos":"[3879.9221 704.0313 213.5464]","flipped":true,"price":2000,"wep":"fas2_galil"},{"angle":"{0 360 0}","pos":"[3550.2466 -255.9688 48.1052]","flipped":true,"price":1200,"wep":"fas2_uzi"},{"angle":"{0 90 -0}","pos":"[3983.9688 -85.2869 212.6242]","flipped":true,"price":1500,"wep":"fas2_mp5sd6"},{"angle":"{0 450 0}","pos":"[4463.9688 557.1966 208.4649]","flipped":true,"price":2500,"wep":"fas2_ak47"},{"angle":"{0 270 0}","pos":"[4325.0313 -1371.6563 21.8379]","flipped":true,"price":2500,"wep":"fas2_m4a1"},{"angle":"{-0 90 0}","pos":"[4510.4688 -1191.0785 23.6308]","flipped":true,"price":3000,"wep":"nz_bowie_knife"}],"NavGroupIDs":[],"ZedSpawns":[{"pos":"[3378.6511 -1420.2484 152.0313]"},{"link":1,"pos":"[2858.7395 -329.153 0.0313]"},{"link":1,"pos":"[3758.1418 -176.9213 0.0313]"},{"link":2,"pos":"[3659.0007 377.9841 160.0313]"},{"link":2,"pos":"[3326.7317 897.1509 160.0313]"},{"link":2,"pos":"[4258.5825 -28.1977 160.0313]"},{"link":2,"pos":"[4669.6821 523.2048 160.0313]"},{"link":3,"pos":"[4575.0073 -388.5615 160.0313]"},{"link":4,"pos":"[4516.2627 -426.3439 160.0313]"},{"link":3,"pos":"[4760.3521 302.3774 160.0313]"},{"link":3,"pos":"[4314.0835 8.7103 160.0313]"},{"link":3,"pos":"[3777.6355 403.2165 160.0313]"},{"link":3,"pos":"[3275.1726 884.158 160.0313]"},{"link":2,"pos":"[3781.4849 -122.4101 0.0312]"},{"link":1,"pos":"[2826.8967 -323.936 0.0313]"},{"link":5,"pos":"[5058.98 -2051.4473 -95.9688]"},{"link":5,"pos":"[5201.209 -2051.4448 -95.9688]"},{"link":5,"pos":"[5320.3564 -2042.6355 -95.9688]"},{"link":5,"pos":"[5442.6704 -2048.7363 -95.9688]"},{"link":5,"pos":"[5337.1509 -907.6223 -95.9688]"},{"link":5,"pos":"[5243.0708 -917.9886 -95.9688]"},{"link":5,"pos":"[5083.9888 -914.8188 -95.9688]"},{"link":5,"pos":"[5455.228 -1028.1593 -47.9688]"},{"link":"3","pos":"[4426.4468 766.6355 160.0313]","respawnable":1},{"link":"2","pos":"[4540.8506 605.5256 160.0313]","respawnable":1},{"link":"2","pos":"[3566.8691 -425.1638 168.0313]","respawnable":1}],"BlockSpawns":[{"angle":"{90 -90.2505 180}","model":"models/hunter/plates/plate2x2.mdl","pos":"[2870.2966 -295.1663 0.0313]"},{"angle":"{90 87.8536 180}","model":"models/hunter/plates/plate2x2.mdl","pos":"[2864.73 -353.6593 0.0313]"},{"angle":"{-0.5616 30.0792 89.1158}","model":"models/hunter/plates/plate1x2.mdl","pos":"[3231.854 443.4987 180.0088]"},{"angle":"{90 -178.4622 180}","model":"models/hunter/plates/plate2x3.mdl","pos":"[3601.52 -210.4269 65.7153]"},{"angle":"{88.3762 -47.567 3.2533}","model":"models/hunter/plates/plate1x1.mdl","pos":"[3620.1108 -121.4807 63.7302]"},{"angle":"{90 0.9383 180}","model":"models/hunter/plates/plate1x1.mdl","pos":"[3478.0168 -220.8691 41.0492]"},{"angle":"{90 88.5847 180}","model":"models/hunter/plates/plate1x1.mdl","pos":"[3452.502 -198.5208 30.7089]"},{"angle":"{90 89.9994 180}","model":"models/hunter/plates/plate1x1.mdl","pos":"[3687.1843 -1386.4001 88.9011]"},{"angle":"{90 -89.9999 180}","model":"models/hunter/plates/plate1x1.mdl","pos":"[3691.3154 -1453.3566 94.5264]"}],"PlayerSpawns":[{"pos":"[3701.0566 -1146.4681 23.0313]"},{"pos":"[3841.6365 -1153.5814 23.0313]"},{"pos":"[3914.4963 -980.9344 23.0313]"},{"pos":"[3828.9316 -891.1439 23.0313]"},{"pos":"[3721.7539 -876.3463 25.0313]"},{"pos":"[3625.4585 -904.9734 23.0313]"},{"pos":"[3612.9338 -1044.7297 23.0313]"},{"pos":"[3926.7446 -1088.3309 23.0313]"},{"pos":"[3998.7029 -916.5186 24.0313]"}],"PerkMachineSpawns":[{"angle":"{0 -89.9261 0}","pos":"[4166.0044 -520.5506 152.0313]","id":"revive"},{"angle":"{0.0046 179.7652 -0.2692}","pos":"[4273.3418 927.4385 160.5491]","id":"jugg"},{"angle":"{1.0721 -89.6979 -0.0347}","pos":"[4363.3745 668.2178 160.4515]","id":"speed"},{"angle":"{-0.4237 -90.9021 -0.1978}","pos":"[4345.3755 -488.4611 158.5645]","id":"deadshot"},{"angle":"{-0.9461 2.9004 -0.0243}","pos":"[4509.6504 -68.8665 159.8929]","id":"whoswho"},{"angle":"{-0 0 0.0001}","pos":"[2539.3401 799.7473 -1680.3997]","id":"pap"},{"angle":"{0.0555 -179.997 0.0445}","pos":"[5478.9067 -1786.9187 -96.0252]","id":"tombstone"},{"angle":"{0.067 179.8578 0}","pos":"[5477.6548 -1433.6165 -95.4346]","id":"cherry"}],"EasterEggs":[{"angle":"{0 0 0}","model":"models/props_lab/huladoll.mdl","pos":"[4220.1348 -1480.2666 24.0313]"},{"angle":"{0 0 0}","model":"models/props_lab/huladoll.mdl","pos":"[4596.1392 -247.5583 181.3079]"},{"angle":"{0 0 0}","model":"models/props_lab/huladoll.mdl","pos":"[2995.5229 -172.7378 0.0312]"}],"RemoveProps":[],"PropEffects":[],"MapSettings":{"startpoints":500,"rboxweps":["fas2_ks23","gdcw_raygun","cw_c7a1","fas2_an94","fas2_sg552","fas2_famas","fas2_m3s90","fas2_m21","fas2_mac11","fas2_glock20","fas2_mp5sd6","fas2_m79","fas2_m4a1","cw_auggsm","fas2_rpk","cw_xm1014","fas2_rk95","fas2_m67","fas2_m14","fas2_p226","cw_mr96","fas2_g3","fas2_ak12","cw_g3a3","cw_l115","nz_monkey_bomb","fas2_m1911","fas2_m24","cw_ws_mosin","cw_dz_ru556","fas2_ots33","fas2_mp5a5","fas2_ragingbull","fas2_ak74","cw_ppsh-41","fas2_deagle","cw_lr300","fas2_mp5k","cw_ak74","fas2_uzi","fas2_toz34","fas2_sr25","fas2_sks","fas2_galil","fas2_sg550","cw_mp5","cw_ar15","fas2_ak47","cw_mk11","fas2_dv2","fas2_g36c","cw_deagle","fas2_pp19","fas2_rem870","fas2_m82"],"startwep":"fas2_glock20","scriptinfo":"Adds Pack-a-Punch Objective","numweps":2,"script":1,"eeurl":"https://soundcloud.com/darkwebside/115-elena-siegman-call-of-duty"},"WunderfizzMachines":[{"angle":"{0.0824 -0.1705 -0.037}","pos":"[3278.4065 696.0577 160.4635]"},{"angle":"{0.0769 -38.3493 -0.0294}","pos":"[2991.3767 61.6178 0.4652]"},{"angle":"{-0.3158 91.0051 0}","pos":"[4907.521 -2084.4719 -31.5002]"}]} \ No newline at end of file diff --git a/gamemodes/nzombies/officialconfigs/nz_zs_obj_station;Imprisoned;675138912.lua b/gamemodes/nzombies/officialconfigs/nz_zs_obj_station;Imprisoned;675138912.lua new file mode 100644 index 00000000..fb6a4297 --- /dev/null +++ b/gamemodes/nzombies/officialconfigs/nz_zs_obj_station;Imprisoned;675138912.lua @@ -0,0 +1 @@ +{"ZedSpecialSpawns":[{"pos":"[1891.2689 -269.9762 172.0313]"},{"pos":"[2190.9854 490.5532 140.0313]"},{"pos":"[1907.8203 -547.0991 140.0313]"},{"link":"1","pos":"[1267.0814 1196.6229 276.0313]"},{"link":"1","pos":"[1171.5031 718.6177 140.0313]"},{"link":"1","pos":"[1817.7554 607.8384 268.0313]"},{"link":"2","pos":"[1439.4187 786.8567 140.0313]"},{"link":"2","pos":"[1840.3342 824.4903 5.3358]"},{"link":"2","pos":"[1809.3217 885.0364 268.0313]"},{"link":"2","pos":"[1609.722 1182.55 276.0313]"},{"link":"2","pos":"[1472.5485 217.2678 128]"},{"link":"2","pos":"[1545.6396 -269.2833 127.9479]"},{"link":"2","pos":"[856.7911 243.8131 128]"},{"link":"2","pos":"[654.343 1103.1528 128.0313]"},{"link":"3","pos":"[339.9817 1069.6758 128.0313]"},{"link":"3","pos":"[705.3626 638.5278 128.0313]"},{"link":"3","pos":"[1217.7797 219.5884 122.8459]"},{"link":"3","pos":"[1540.1475 -12.7641 123.8994]"},{"link":"3","pos":"[487.546 201.7877 160.0313]"},{"link":"3","pos":"[246.5609 -277.22 160.0313]"},{"link":"3","pos":"[596.287 -739.1407 160.0313]"},{"link":"3","pos":"[729.0219 -316.3921 128.0312]"},{"link":"8","pos":"[-248.0674 -965.2192 128.0312]"},{"link":"8","pos":"[-417.2557 -1121.9602 128.0313]"},{"link":"8","pos":"[285.2797 -726.0324 160.0313]"},{"link":"8","pos":"[-729.8441 -1621.8582 128.0313]"},{"link":"8","pos":"[-168.997 -1603.001 128.0313]"},{"link":"8","pos":"[462.0009 -1245.1969 128.0313]"},{"link":"7","pos":"[206.8771 -1153.0702 128.0313]"},{"link":"7","pos":"[-232.3574 -1393.2817 128.0313]"},{"link":"7","pos":"[200.6292 -1628.7637 128.0313]"},{"link":"7","pos":"[993.6713 -1216.5253 128.0313]"},{"link":"7","pos":"[1015.266 -853.2054 128.0313]"},{"link":"7","pos":"[972.8389 -322.8701 128.0313]"},{"link":"7","pos":"[1289.3423 -1455.3799 128.0313]"},{"link":"7","pos":"[649.6738 -1545.2463 128.0313]"},{"link":"9","pos":"[466.1729 -1578.3042 128.0313]"},{"link":"9","pos":"[1084.1 -1547.3495 128.0313]"},{"link":"6","pos":"[1302.3766 -726.3193 128.0313]"},{"link":"6","pos":"[1586.2712 -609.7045 128.0313]"},{"link":"6","pos":"[1307.7249 -28.0193 192.0313]"},{"link":"6","pos":"[878.8822 -135.0254 128.0313]"},{"link":"5","pos":"[888.558 -764.3162 128.0313]"},{"link":"5","pos":"[1293.838 -888.6021 128.0313]"},{"link":"5","pos":"[1036.902 733.5276 -12.0093]"},{"link":"5","pos":"[398.2974 246.1 8.2029]"},{"link":"4","pos":"[426.5353 650.8875 160.0313]"},{"link":"4","pos":"[102.6184 594.6484 128.0313]"},{"link":"4","pos":"[-106.2687 638.3044 128.0313]"},{"link":"4","pos":"[395.5491 721.7593 288.0313]"},{"link":"9","pos":"[1025.1359 -849.8962 256.0313]"},{"link":"9","pos":"[1065.3536 -436.9025 256.0313]"},{"link":"9","pos":"[1051.5911 -1424.0812 256.0313]"}],"NavTable":{"828":{"locked":true},"6069":{"locked":true,"link":"3"},"5523":{"locked":true,"link":"1"},"5476":{"locked":true},"6006":{"prev":24576,"locked":true},"811":{"locked":true,"link":"9"},"93":{"locked":true},"5325":{"locked":true},"6118":{"locked":true},"5524":{"locked":true,"link":"1"},"3509":{"locked":true,"link":"8"},"1851":{"locked":true},"368":{"locked":true},"371":{"locked":true},"6111":{"locked":true},"5326":{"locked":true},"6079":{"locked":true,"link":"gen1"},"1773":{"locked":true},"1763":{"locked":true},"1785":{"locked":true},"1783":{"locked":true},"5135":{"locked":true},"536":{"locked":true},"139":{"locked":true},"6016":{"prev":24576,"locked":true},"6072":{"locked":true,"link":"gen3"},"6001":{"prev":24576,"locked":true},"565":{"locked":true},"566":{"locked":true},"569":{"locked":true},"6007":{"prev":24576,"locked":true},"6017":{"prev":24576,"locked":true},"5256":{"locked":true},"824":{"locked":true},"5191":{"locked":true},"6114":{"locked":true},"6010":{"prev":24576,"locked":true},"6112":{"locked":true,"link":"ee_door"},"2078":{"locked":true,"link":"2"},"4556":{"locked":true,"link":"2"},"680":{"locked":true},"5129":{"locked":true},"676":{"locked":true},"6082":{"locked":true,"link":"9"},"6106":{"locked":true},"675":{"locked":true},"1808":{"locked":true},"6018":{"prev":24576,"locked":true},"6066":{"locked":true,"link":"3"},"1838":{"locked":true},"5192":{"locked":true},"196":{"locked":true},"6011":{"prev":24576,"locked":true},"1067":{"locked":true},"6005":{"prev":24576,"locked":true},"1850":{"locked":true},"567":{"locked":true},"5130":{"locked":true},"6107":{"locked":true},"6062":{"locked":true,"link":"3"},"4381":{"locked":true,"link":"5"},"6115":{"locked":true,"link":"ee_door"},"6035":{"locked":true,"link":"7"},"6019":{"prev":24576,"locked":true},"6002":{"prev":24576,"locked":true},"6059":{"locked":true,"link":"3"},"6000":{"prev":24576,"locked":true},"229":{"locked":true},"6004":{"prev":24576,"locked":true},"4526":{"locked":true,"link":"6"},"1786":{"locked":true},"5136":{"locked":true},"568":{"locked":true},"454":{"locked":true},"6108":{"locked":true},"6009":{"prev":24576,"locked":true},"678":{"locked":true},"6116":{"locked":true},"6036":{"locked":true,"link":"7"},"2488":{"prev":0,"locked":true},"6076":{"locked":true,"link":"gen2"},"1891":{"locked":true},"5475":{"locked":true},"6054":{"locked":true,"link":"3"},"6013":{"prev":24576,"locked":true},"6003":{"prev":24576,"locked":true},"1822":{"locked":true},"6080":{"locked":true,"link":"5"},"5255":{"locked":true},"1075":{"locked":true},"6109":{"locked":true},"6008":{"prev":24576,"locked":true},"1740":{"locked":true,"link":"4"},"825":{"locked":true},"6014":{"prev":24576,"locked":true}},"version":400,"DoorSetup":{"1485":{"flags":"link=7,buyable=1,price=1000,elec=0,rebuyable=0"},"1628":{"flags":"link=6,buyable=1,price=750,elec=0,rebuyable=0"},"1632":{"flags":"price=1000,buyable=1,link=2,elec=0,rebuyable=0"},"1631":{"flags":"price=1000,buyable=1,link=2,elec=0,rebuyable=0"},"2447":{"flags":"link=4,buyable=1,price=1500,elec=1,rebuyable=0"},"2221":{"flags":"link=5,buyable=1,price=0,elec=1,rebuyable=0"}},"BlockSpawns":[{"angle":"{90 -171.5039 180}","model":"models/hunter/plates/plate2x3.mdl","pos":"[1167.0327 -1173.6759 309.2026]"},{"angle":"{90 -178.811 180}","model":"models/hunter/plates/plate2x4.mdl","pos":"[-127.5831 -1131.684 190.9126]"},{"angle":"{-0 90 90}","model":"models/hunter/plates/plate1x2.mdl","pos":"[1062.907 -1633.2869 186.3024]"},{"angle":"{90 90.6316 180}","model":"models/hunter/plates/plate1x1.mdl","pos":"[289.6432 600.7892 335.4275]"}],"BuyablePropSpawns":[{"pos":"[2154.3596 -679.6368 173.1837]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[2153.9688 -615.6158 173.466]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[2061.5259 -188.8465 192.4386]","model":"models/props_c17/fence02b.mdl","collision":0,"angle":"{0 4.9404 -0}"},{"pos":"[2028.4819 493.7937 199.8724]","flags":"price=750,buyable=1,link=1,elec=0,rebuyable=0","model":"models/props_wasteland/controlroom_storagecloset001a.mdl","collision":0,"angle":"{0.3196 0.2541 20.3735}"},{"pos":"[2062.8613 512.4232 189.4933]","flags":"price=750,buyable=1,link=1,elec=0,rebuyable=0","model":"models/props/de_inferno/furniturecouch001a.mdl","collision":0,"angle":"{0 86.3108 -89.9984}"},{"pos":"[2054.6008 553.5822 225.2668]","flags":"price=750,buyable=1,link=1,elec=0,rebuyable=0","model":"models/props_junk/trashdumpster01a.mdl","collision":0,"angle":"{2.5025 -4.1284 33.5916}"},{"pos":"[2110.1428 711.3741 160.5868]","model":"models/props_c17/fence03a.mdl","collision":0,"angle":"{-0 -89.0749 0}"},{"pos":"[2198.4346 829.1579 161.816]","model":"models/props_c17/fence03a.mdl","collision":0,"angle":"{0 -90 0.0001}"},{"pos":"[2065.147 716.8729 310.9365]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{-0 -0.0002 0}"},{"pos":"[2070.9788 1051.0352 259.6271]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 2.1121 -0}"},{"pos":"[1421.9861 1115.6155 271.1271]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{-0 90 0.0001}"},{"pos":"[1094.8345 916.4473 322.8475]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{-0 0 0.0001}"},{"pos":"[1095.0073 996.4654 322.9078]","model":"models/props_c17/fence01b.mdl","collision":0,"angle":"{0 0 0.0001}"},{"pos":"[1105.5991 1164.785 140.4777]","model":"models/nzprops/origins/sandbag_blockade.mdl","collision":0,"angle":"{0 -92.1773 0}"},{"pos":"[1099.0227 1166.2711 151.0806]","model":"models/nzprops/origins/sandbag_blockade.mdl","collision":0,"angle":"{0 -88.4151 0}"},{"pos":"[733.5317 173.7372 182.3809]","flags":"price=1250,buyable=1,link=3,elec=0,rebuyable=0","model":"models/props_c17/fence03a.mdl","collision":0,"angle":"{0 29.3518 -0}"},{"pos":"[-290.1465 1008.9606 125.9902]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{-0 83.12 0.0001}"},{"pos":"[-398.8959 1016.8687 126.9636]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{-0 90 0.0001}"},{"pos":"[-521.5318 1016.5679 124.7294]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{-0 90 0.0001}"},{"pos":"[-635.4354 1016.2394 124.2315]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{0 89.868 0.0001}"},{"pos":"[-753.0101 1012.3397 123.5497]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{0 89.736 -0}"},{"pos":"[-868.7869 1011.2974 122.4085]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{0 91.0401 0}"},{"pos":"[-270.9962 1349.4659 130.2699]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{0 88.8078 0.0001}"},{"pos":"[-233.7883 1349.8104 137.4728]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 -0.792 0}"},{"pos":"[-301.2319 1350.1263 137.4252]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 1.9798 -0}"},{"pos":"[852.1076 1408.4736 124.0284]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{0 -0.924 0}"},{"pos":"[850.9512 1373.1195 129.9597]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 -2.112 0}"},{"pos":"[852.2439 1437.8826 128.0326]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 2.376 -0}"},{"pos":"[806.8635 -162.1814 181.6332]","model":"models/props_c17/fence03a.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[188.2181 29.0611 212.2501]","model":"models/props_c17/fence03a.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[187.1642 -224.9524 211.9071]","model":"models/props_c17/fence03a.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[187.4072 -479.6877 212.2444]","model":"models/props_c17/fence03a.mdl","collision":0,"angle":"{0 0 0.0001}"},{"pos":"[187.3439 -732.9747 212.1546]","model":"models/props_c17/fence03a.mdl","collision":0,"angle":"{0 0 0.0001}"},{"pos":"[420.9675 -609.9632 180.2399]","model":"models/props_c17/lockers001a.mdl","collision":0,"angle":"{0 -90.0507 -89.9998}"},{"pos":"[61.3936 155.7059 175.3659]","model":"models/props_c17/fence03a.mdl","collision":0,"angle":"{0 90 -0}"},{"pos":"[175.6146 228.5593 142.0885]","flags":"price=1000,buyable=0,link=gen1,elec=0,rebuyable=0","model":"models/props_lab/blastdoor001b.mdl","collision":0,"angle":"{0 -0.0027 0}"},{"pos":"[465.2041 -430.5395 199.7339]","flags":"link=5,buyable=1,price=0,elec=1,rebuyable=0","model":"models/props_lab/blastdoor001c.mdl","collision":0,"angle":"{0 1.1733 -0}"},{"pos":"[716.661 -1775.7804 202.7882]","flags":"link=9,buyable=1,price=1500,elec=1,rebuyable=0","model":"models/props_lab/blastdoor001b.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[1223.7073 -560.3162 255.9413]","flags":"link=9,buyable=1,price=1500,elec=1,rebuyable=0","model":"models/props_lab/blastdoor001b.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[932.7548 -1036.0768 124.8946]","flags":"link=7,buyable=1,price=1000,elec=0,rebuyable=0","model":"models/props_wasteland/kitchen_stove002a.mdl","collision":0,"angle":"{-1.345 92.2453 -13.2808}"},{"pos":"[-831.5718 -1205.7423 174.0767]","flags":"link=8,buyable=1,price=1250,elec=0,rebuyable=0","model":"models/props_wasteland/controlroom_storagecloset001b.mdl","collision":0,"angle":"{0 -90.53 0}"},{"pos":"[807.2859 -612.5779 127.697]","flags":"link=5,buyable=1,price=0,elec=1,rebuyable=0","model":"models/props_lab/blastdoor001c.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[1177.8615 -1176.5314 254.6877]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{-1.4592 9.568 0.3176}"},{"pos":"[1172.0538 -1095.8605 315.2263]","model":"models/props_debris/concrete_section128wall001b.mdl","collision":0,"angle":"{-0 -179.2081 0}"},{"pos":"[1305.0664 -224.2966 128.0925]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 1.188 -0}"},{"pos":"[1262.6719 -270.8233 127.7641]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{-0 -3.4318 0}"},{"pos":"[398.341 -1413.2115 119.3654]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{0.1876 42.2288 -0.0285}"},{"pos":"[-122.8713 -1123.5994 123.0597]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{0 0.792 0}"},{"pos":"[-706.9918 -969.3768 122.9951]","model":"models/props_c17/concrete_barrier001a.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[-707.7751 -936.1946 127.6991]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 0.7919 -0}"},{"pos":"[-708.2661 -1002.5836 128.6468]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 -1.0361 0}"},{"pos":"[173.8924 175.3825 151.9371]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{-0 0.0002 -0}"},{"pos":"[176.1037 287.1385 150.285]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{0 0.0001 0}"},{"pos":"[6.988 232.9636 111.2024]","flags":"price=1000,buyable=0,link=gen2,elec=0,rebuyable=0","model":"models/props_lab/blastdoor001b.mdl","collision":0,"angle":"{0 0.0001 -0}"},{"pos":"[-249.7683 235.2957 56.3228]","flags":"price=1000,buyable=0,link=gen3,elec=0,rebuyable=0","model":"models/props_lab/blastdoor001b.mdl","collision":0,"angle":"{0 -0.0358 0}"},{"pos":"[5.6848 288.5558 121.2387]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{0 0.0001 0}"},{"pos":"[6.7985 176.9387 119.7413]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{-0 -0.0001 0}"},{"pos":"[-251.8091 177.7595 66.4501]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[-249.6438 284.7556 66.2894]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{0 0.0011 0}"},{"pos":"[548.6782 -337.7147 198.1566]","model":"models/props_lab/workspace003.mdl","collision":0,"angle":"{-0 178.1519 0}"},{"pos":"[605.6331 913.1691 35.9413]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{0 -1.32 0}"},{"pos":"[514.0544 909.6918 31.9768]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[76.2247 753.6072 125.7398]","model":"models/props_trainstation/traincar_seats001.mdl","collision":0,"angle":"{-0 -92.3757 0}"},{"pos":"[171.6543 761.3869 143.4965]","model":"models/props_c17/furniturecouch001a.mdl","collision":0,"angle":"{89.9999 -86.4439 180}"},{"pos":"[164.7864 995.4737 122.4779]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{-0 0.0005 0}"},{"pos":"[163.8575 1093.4951 126.7966]","flags":"price=1000,buyable=0,link=ee_door,elec=0,rebuyable=0","model":"models/props_lab/blastdoor001c.mdl","collision":0,"angle":"{0 0 0}"},{"pos":"[163.064 1191.516 126.4216]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{-0 0.0033 0}"},{"pos":"[-415.1311 960.7063 -0.2388]","model":"models/props_combine/combine_interface001.mdl","collision":0,"angle":"{0 -89.9996 0}"},{"pos":"[-466.2995 981.689 0.475]","model":"models/props_lab/servers.mdl","collision":0,"angle":"{-0 -90.2635 0}"},{"pos":"[-172.0199 1061.9712 90.024]","model":"models/combine_room/combine_wire001.mdl","collision":20,"angle":"{0 -75.6777 0}"},{"pos":"[92.6968 1034.6396 129.0721]","model":"models/combine_room/combine_wire002.mdl","collision":20,"angle":"{-0 -87.9124 0}"},{"pos":"[39.1471 1040.1377 90.2676]","model":"models/combine_room/combine_wire001.mdl","collision":20,"angle":"{-0 40.5239 0}"},{"pos":"[-302.7144 972.5764 -5.666]","model":"models/props_lab/servers.mdl","collision":0,"angle":"{-0 -89.6032 0}"},{"pos":"[580.5631 -485.5031 196.8857]","model":"models/props_lab/servers.mdl","collision":0,"angle":"{-0 90 0}"},{"pos":"[2219.2793 -232.9719 170.4057]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 -3.5638 0}"},{"pos":"[2284.999 -233.28 171.6595]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{-0 2.3801 0}"},{"pos":"[1171.0316 -1146.4033 257.1092]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{-0 -18.2158 0}"},{"pos":"[1183.6084 -1213.8546 257.8972]","model":"models/props_c17/signpole001.mdl","collision":0,"angle":"{0 -3.8277 0}"},{"pos":"[1238.655 -329.2078 141.9404]","model":"models/props_wasteland/controlroom_desk001a.mdl","collision":0,"angle":"{-0 -2.9039 0}"},{"pos":"[1240.187 -244.7242 127.2686]","model":"models/props_wasteland/medbridge_post01.mdl","collision":0,"angle":"{0 -2.112 0}"}],"SpecialEntities":[],"RandomBoxSpawns":[{"spawn":0,"angle":"{0.0394 -89.3544 0.9692}","pos":"[1974.6617 1199.6521 276.2745]"},{"spawn":0,"angle":"{-0.0647 179.3764 0.4881}","pos":"[1082.0068 -503.8833 128.3228]"},{"spawn":0,"angle":"{0.0119 -0.006 0.4862}","pos":"[-115.4943 940.5054 128.2781]"},{"spawn":0,"angle":"{-0.0542 -179.9813 0.0266}","pos":"[1068.5287 -1012.5771 256.6587]"},{"spawn":1,"angle":"{-0.4749 179.3512 1.1972}","pos":"[1572.9725 -471.8983 135.4011]"},{"spawn":1,"angle":"{0.0373 178.5294 0.9603}","pos":"[953.9736 -1399.5121 128.2791]"}],"DamageWalls":[],"PropEffects":[],"WallBuys":[{"angle":"{-0 90 0}","pos":"[2075.4688 -30.0754 190.8092]","flipped":true,"price":500,"wep":"khr_mosin"},{"angle":"{-0 -90 0}","pos":"[2008.5313 786.2307 197.2724]","flipped":true,"price":500,"wep":"fas2_m1911"},{"angle":"{-0 -90 0}","pos":"[1144.5313 1230.6029 329.7507]","flipped":true,"price":750,"wep":"fas2_deagle"},{"angle":"{0 0 0}","pos":"[1380.9768 424.5313 190.0343]","flipped":true,"price":1000,"wep":"cw_mac11"},{"angle":"{-0 -180 0}","pos":"[1486.4833 415.4688 177.5318]","flipped":true,"price":1500,"wep":"khr_mp40"},{"angle":"{-0 -90 0}","pos":"[1228.5313 -681.4431 176.6693]","flipped":true,"price":1250,"wep":"cw_m3super90"},{"angle":"{-0 -180 0}","pos":"[488.1161 -1040.5313 172.7601]","flipped":true,"price":1500,"wep":"khr_vector"},{"angle":"{-0 90 0}","pos":"[799.4688 -391.7288 178.6819]","flipped":true,"price":1750,"wep":"khr_aek971"},{"angle":"{-0 90 0}","pos":"[323.4688 -252.6962 208.8006]","flipped":true,"price":1750,"wep":"cw_g36c"},{"angle":"{0 0 0}","pos":"[408.0144 604.5313 339.6191]","flipped":true,"price":2000,"wep":"cw_ak74"},{"angle":"{0 0 0}","pos":"[1116.6531 -631.4688 308.343]","flipped":true,"price":2000,"wep":"fas2_m4a1"},{"angle":"{-0 90 0}","pos":"[-448.5313 230.9272 47.6733]","flipped":true,"price":3000,"wep":"nz_bowie_knife"}],"ZedSpawns":[{"pos":"[2304.0396 -645.3283 140.0313]"},{"pos":"[1797.5403 -1123.9858 172.0313]"},{"pos":"[2372.293 -1127.3151 172.0313]"},{"pos":"[2356.3879 -138.4028 140.0313]"},{"link":"1","pos":"[968.2958 478.4869 140.0313]"},{"link":"1","pos":"[973.4571 1165.0188 140.0313]"},{"link":"1","pos":"[2042.5222 1307.7465 260.0313]"},{"link":"1","pos":"[1419.8412 1080.052 276.0313]"},{"link":"2","pos":"[1425.8374 1113.8308 404.0313]"},{"link":"2","pos":"[1029.1649 1107.9175 404.0313]"},{"link":"2","pos":"[1556.241 1408.0642 128.0313]"},{"link":"2","pos":"[1319.1027 1402.9802 128.0313]"},{"link":"3","pos":"[417.5019 -556.2704 160.0313]"},{"link":"3","pos":"[421.0846 1435.7474 141.7465]"},{"link":"9","pos":"[1276.0851 -1163.0236 256.0313]"},{"link":"9","pos":"[951.1391 -1691.3394 256.0313]"},{"link":"9","pos":"[1163.2102 -688.0709 256.0313]"},{"link":"6","pos":"[1268.3517 -165.6855 128.0313]"},{"link":"6","pos":"[1107.5109 -72.3584 128.0313]"},{"link":"8","pos":"[409.2123 -363.1969 379.7278]"},{"link":"3","pos":"[430.0604 -174.1479 389.5004]"},{"link":"5","pos":"[1049.0518 -66.8307 128.0313]"},{"link":"5","pos":"[1255.8802 -173.0037 128.0313]"},{"link":"7","pos":"[1068.1174 -1729.8687 128.0313]"},{"link":"7","pos":"[239.0293 -1774.7527 128.0313]"},{"link":"8","pos":"[200.1158 -1778.1499 128.0313]"},{"link":"8","pos":"[362.692 -1425.2772 128.0313]"},{"link":"7","pos":"[379.5781 -1433.8177 128.0313]"},{"link":"8","pos":"[-856.3936 -970.6315 128.0313]"},{"link":"3","pos":"[-816.3839 -965.6392 128.0313]"},{"link":"3","pos":"[-35.5664 -1124.238 128.0313]"},{"link":"8","pos":"[-60.2921 -1091.6262 128.0313]"},{"link":"1","pos":"[1825.6821 498.6237 6.284]"},{"link":"5","pos":"[560.7059 933.7563 35.1681]"},{"link":"4","pos":"[560.9091 449.813 160.0313]"},{"link":"4","pos":"[381.4799 411.9981 288.0313]"},{"link":"4","pos":"[97.0678 888.1609 128.0313]"},{"link":"2","pos":"[1462.2256 -576.2327 264.0313]"},{"link":"2","pos":"[1697.8186 -578.4184 264.0313]"},{"link":"2","pos":"[428.4572 1439.4895 136.1283]"},{"link":"3","pos":"[1450.1802 1410.182 128.0313]"},{"link":"3","pos":"[1568.3977 -579.726 264.0313]"},{"link":"8","pos":"[444.2024 -557.1701 160.0313]"},{"link":"10","pos":"[-593.1987 913.7235 -35.9688]"},{"link":"10","pos":"[-595.0453 511.8833 -35.9688]"},{"link":"10","pos":"[-594.6772 145.391 -35.9688]"},{"link":"10","pos":"[-593.9968 -156.1181 -35.9687]"},{"link":"10","pos":"[-589.6758 -546.5635 -35.9687]"},{"link":"10","pos":"[-590.1827 -793.4512 -35.9688]"},{"link":"6","pos":"[1161.9637 -95.2908 128.0313]"},{"link":"7","pos":"[1273.5653 -191.4586 128.0313]"},{"link":"9","pos":"[1020.6857 -1738.6904 128.0313]"},{"link":"2","pos":"[1387.7593 1077.4153 276.0313]"},{"link":"2","pos":"[1009.9799 1170.798 140.0313]"},{"link":"2","pos":"[972.3942 999.1134 140.0313]"},{"link":"2","pos":"[1784.3857 970.5988 13.4581]"},{"link":"10","pos":"[-740.1148 1599.7256 384.0313]"},{"link":"10","pos":"[-799.7659 1302.0839 147.3757]"},{"link":"10","pos":"[-609.3833 1327.0742 285.1809]"},{"link":"ee_door","pos":"[-311.7495 1362.8179 293.2738]"},{"link":"ee_door","pos":"[78.2458 1365.02 293.7724]"},{"link":"ee_door","pos":"[-768.3906 1585.0676 384.0313]"},{"link":"ee_door","pos":"[-260.9864 1408.4055 136.0313]"},{"link":"10","pos":"[-296.1949 1403.386 136.0313]"}],"EasterEggs":[{"angle":"{0 0 0}","model":"models/props_lab/huladoll.mdl","pos":"[2061.9114 842.027 140.0313]"},{"angle":"{0 -193.548 0}","model":"models/props_lab/huladoll.mdl","pos":"[-546.879 -893.1187 -35.6318]"},{"angle":"{0 0 0}","model":"models/props_lab/huladoll.mdl","pos":"[996.7664 -1256.5729 256.0313]"}],"PlayerSpawns":[{"pos":"[1956.8391 -330.4176 172.0313]"},{"pos":"[1837.2448 -223.352 172.0313]"},{"pos":"[1827.5652 -63.239 172.0313]"},{"pos":"[2198.5239 -312.6749 172.0313]"},{"pos":"[2098.6821 -584.5078 172.0313]"},{"pos":"[2110.3787 -785.243 172.0313]"},{"pos":"[2291.3118 -342.3848 172.0313]"},{"pos":"[2060.6548 -322.7522 172.0313]"},{"pos":"[1879.0967 -592.9237 140.0313]"}],"PerkMachineSpawns":[{"angle":"{0 0.5943 0}","pos":"[1049.6965 1312.0221 140.0313]","id":"jugg"},{"angle":"{0 -0.4075 0}","pos":"[-828.699 190.3529 0.0313]","id":"pap"},{"angle":"{0.0342 179.9887 0.0212}","pos":"[2377.6328 -321.402 172.3843]","id":"revive"},{"angle":"{-1.5031 90.9942 -0.6736}","pos":"[1092.5708 640.5778 -11.4131]","id":"widowswine"},{"angle":"{-0.0029 89.9562 0.1489}","pos":"[297.4232 323.4221 160.2413]","id":"speed"},{"angle":"{0.4132 0.18 0.1572}","pos":"[818.3199 -390.7758 128.0702]","id":"dtap2"},{"angle":"{0.0102 -1.0556 0.0378}","pos":"[1083.7269 -1634.1523 128.5125]","id":"cherry"},{"angle":"{-0.4826 -0.493 -0.0479}","pos":"[1002.1964 -1229.1592 255.8556]","id":"staminup"},{"angle":"{0.0183 179.8875 0.0056}","pos":"[322.7298 -552.1022 160.4982]","id":"wunderfizz"},{"angle":"{-0.144 179.7126 0}","pos":"[130.8205 1283.1781 136.4998]","id":"wunderfizz"},{"angle":"{0.1437 0.5172 0.013}","pos":"[-469.2006 -1398.5468 128.4294]","id":"wunderfizz"}],"BreakEntry":[{"jump":false,"angle":"{0 -89.1726 0}","pos":"[2365.825 -871.1404 226.7767]","planks":true},{"jump":false,"angle":"{0 -89.7003 0}","pos":"[1804.3214 -872.1442 218.9454]","planks":true},{"jump":false,"angle":"{-0 -1.7884 0}","pos":"[2156.5078 -648.8586 210.2621]","planks":true},{"jump":false,"angle":"{0 90.0595 -0}","pos":"[2254.0918 -237.6402 221.4616]","planks":true},{"jump":false,"angle":"{-0 -16.9925 0}","pos":"[2063.71 -120.6082 191.8933]","planks":true},{"jump":false,"angle":"{0 90.1761 -0}","pos":"[2040.4115 1047.2555 314.0649]","planks":true},{"jump":false,"angle":"{0 90.2963 -0}","pos":"[1062.8569 1046.9767 327.3407]","planks":true},{"jump":true,"angle":"{0 -180 0}","pos":"[1096.5814 1164.572 188.5675]","planks":true},{"jump":true,"angle":"{0 -89.9952 0}","pos":"[1422.5734 1110.0336 321.9478]","planks":false},{"jump":false,"angle":"{-0 90 0.0001}","pos":"[1308.6316 1081.7614 456.1945]","planks":true},{"jump":true,"angle":"{0 -90 -0}","pos":"[-756.3242 1010.8533 172.4685]","planks":false},{"jump":true,"angle":"{-0 -90.0003 -0}","pos":"[-866.2106 1012.272 173.0219]","planks":false},{"jump":true,"angle":"{0 -90.2293 0}","pos":"[-634.7146 1014.2179 173.0238]","planks":false},{"jump":true,"angle":"{0 270.4334 0}","pos":"[-524.0672 1015.5091 173.0313]","planks":false},{"jump":true,"angle":"{0 -90 0}","pos":"[-399.6403 1017.6938 172.9412]","planks":false},{"jump":true,"angle":"{0 -95.507 0}","pos":"[-299.6798 1007.8362 172.4188]","planks":false},{"jump":true,"angle":"{0 88.8951 -0}","pos":"[-268.271 1347.1943 181.7168]","planks":true},{"jump":true,"angle":"{0 -0.9609 0}","pos":"[847.8576 1406.0829 173.3179]","planks":true},{"jump":true,"angle":"{-0 90 0.0001}","pos":"[422.2456 -620.1277 205.5889]","planks":true},{"jump":true,"angle":"{0 8.8483 -0}","pos":"[1173.4785 -1181.9264 302.5197]","planks":true},{"jump":false,"angle":"{0 -90.479 0}","pos":"[949.6481 -1524.0881 302.0483]","planks":true},{"jump":false,"angle":"{-0 138.8041 0}","pos":"[1286.259 -249.0259 173.873]","planks":true},{"jump":false,"angle":"{0 0.8645 -0}","pos":"[932.6553 -68.9018 179.649]","planks":true},{"jump":false,"angle":"{0 -90.0238 0}","pos":"[1212.5715 -1663.8311 176.8871]","planks":true},{"jump":false,"angle":"{-0 -88.4397 0}","pos":"[239.3566 -1727.9628 181.7408]","planks":true},{"jump":true,"angle":"{0 -138.3354 0}","pos":"[395.4426 -1408.1823 173.2821]","planks":false},{"jump":true,"angle":"{0 1.1891 0}","pos":"[-124.3501 -1122.6427 174.4536]","planks":false},{"jump":true,"angle":"{-0 -179.5551 0}","pos":"[-706.7639 -969.7047 174.603]","planks":true},{"jump":false,"angle":"{0.334 91.8312 -0.0376}","pos":"[559.9528 895.6475 81.0917]","planks":true},{"jump":false,"angle":"{-0 -90.0001 -0}","pos":"[430.7921 511.8405 213.1616]","planks":true},{"jump":false,"angle":"{-0 -90 -0}","pos":"[534.472 604.5763 336.3589]","planks":true},{"jump":true,"angle":"{0 87.8891 0}","pos":"[61.5337 767.0472 171.9669]","planks":false},{"jump":true,"angle":"{-0 89.2091 0}","pos":"[146.3929 769.4409 172.8513]","planks":false}],"RemoveProps":{"1282":true,"1468":true,"1633":true,"2172":true,"1641":true,"1432":true,"2444":true,"1559":true,"1434":true,"1726":true,"2002":true,"1634":true},"InvisWalls":[{"maxbound":"[30.8438 10.5625 128]","pos":"[1879.375 413.375 140.0313]"},{"maxbound":"[-205.8125 -48.0938 383.9375]","pos":"[2277.8438 736.0313 140.0313]"},{"maxbound":"[3.75 279.0938 263.9375]","pos":"[2068.25 767 260.0313]"},{"maxbound":"[2.0625 -272.4688 251.5938]","pos":"[2005.9688 1040.0938 272.3438]"},{"maxbound":"[-2.4375 556.0938 255.9375]","pos":"[1613.1563 491.8438 268.0313]"},{"maxbound":"[166.9063 -3.25 383.9375]","pos":"[1444.875 668.4063 140.0313]"},{"maxbound":"[101.0313 -2.5 383.9375]","pos":"[1444.2813 602.0313 140.0313]"},{"maxbound":"[-2.375 -111.6563 319.9375]","pos":"[1545.875 601.75 204.0313]"},{"maxbound":"[-3.1563 67.9375 255.9375]","pos":"[959.4063 424.0625 268.0313]"},{"maxbound":"[68.4375 -3.7188 256.5625]","pos":"[956.1875 492.0313 267.375]"},{"maxbound":"[-1.7188 515 255.9375]","pos":"[1025.6875 489.625 268.0313]"},{"maxbound":"[2.0938 -554.4375 255.9375]","pos":"[1093.9063 1047.6563 268.0313]"},{"maxbound":"[449.3438 -3 119.9375]","pos":"[1093.9375 493.0938 268.0313]"},{"maxbound":"[3.2813 623.625 127.9375]","pos":"[1342.75 424.3125 396.0313]"},{"maxbound":"[-2.9063 623.4375 127.9375]","pos":"[1272.6875 424.5 396.0313]"},{"maxbound":"[695.0625 -19.9375 129.3125]","pos":"[-927.6875 1020.0938 128.0313]"},{"maxbound":"[-21.5625 -32.1563 129.875]","pos":"[-232.5938 1000.1875 128.0313]"},{"maxbound":"[442.6875 40.9063 283.9375]","pos":"[-256.125 -904.5313 128.0313]"},{"maxbound":"[67.0313 -8 211.9375]","pos":"[560.6563 -492 200.0313]"},{"maxbound":"[-6.0938 465 212.125]","pos":"[628.0313 -499.6875 199.8125]"},{"maxbound":"[439.3125 -8.0625 341.4063]","pos":"[-255.4063 160.2813 70.5313]"},{"maxbound":"[9.7813 -1021.4375 273.625]","pos":"[-257.25 161.6563 138.3125]"},{"maxbound":"[-131.625 8.0313 120]","pos":"[931.7188 55.9688 256.0313]"},{"maxbound":"[7.9375 -1020.1563 120]","pos":"[800.0625 56 256.0313]"},{"maxbound":"[-84.8125 -75.1875 179.9375]","pos":"[402.4063 -1736.75 128.0313]"},{"maxbound":"[13.2188 -30.9688 247.9375]","pos":"[-757.25 -1327.6875 128.0313]"},{"maxbound":"[441.4375 16.7188 469.0313]","pos":"[-233.4688 286.5313 74.9063]"},{"maxbound":"[195.5313 38.9375 156.75]","pos":"[12.375 741.1563 128.0313]"},{"maxbound":"[327.5625 431.9063 257.5]","pos":"[2067.9688 -95.875 270.9688]"},{"maxbound":"[139.2188 109.3125 455.7813]","pos":"[-904.6563 1352.9063 152.25]"},{"maxbound":"[-242 4.0938 381.2188]","pos":"[2395.9688 -812 172.125]"},{"maxbound":"[2.3125 131.7813 391.0313]","pos":"[2153.6875 -811.9688 172.0313]"},{"maxbound":"[2.1563 -193 389.375]","pos":"[2153.8438 -421.875 172.0313]"},{"maxbound":"[-238.6563 -2.2188 386.375]","pos":"[2395.9375 -421.7813 172.0313]"},{"maxbound":"[255.8125 2.4375 389.375]","pos":"[1772.0625 -810.4063 172.0313]"},{"maxbound":"[-2.0625 129.875 399.375]","pos":"[2030.0313 -810 172.0313]"},{"maxbound":"[-2.0625 -194.125 389.7813]","pos":"[2030.0313 -421.8438 172.0313]"},{"maxbound":"[254.7188 -2.5313 390.2188]","pos":"[1772.0313 -421.4688 172.0313]"},{"maxbound":"[116.1563 -55.0313 298.5]","pos":"[1772.0313 -365.8438 235.875]"},{"maxbound":"[-111.8438 2.625 360]","pos":"[2395.9688 -234.5938 172.0625]"},{"maxbound":"[257.8125 2.125 379.7188]","pos":"[1961.9375 -234.0938 172.0313]"},{"maxbound":"[-2.2813 -62.6563 375.75]","pos":"[1964.0313 -168.1875 171.6563]"},{"maxbound":"[-61.9688 -2.0625 365.0313]","pos":"[1960.0313 -167.9688 172.2188]"},{"maxbound":"[2.0938 -320 370.4688]","pos":"[1897.9375 152.0313 172.0313]"},{"maxbound":"[2.0313 56 365.4688]","pos":"[1897.9688 215.9375 172.0313]"},{"maxbound":"[125.9375 -2.0313 363.6875]","pos":"[1772.0313 272 171.875]"},{"maxbound":"[184.6563 -13.2188 91.9375]","pos":"[999.5 -1034.7813 156.0313]"},{"maxbound":"[-3.6563 99.9688 127.8125]","pos":"[1307 -219.0938 128.0313]"}],"MapSettings":{"startpoints":500,"script":1,"bosstype":"Panzer","scriptinfo":"Enables PaP objective, Adds Zombie Shield, Enables Main Easter Egg \"The Core of the Problem\"","specialroundtype":"Hellhounds","rboxweps":{"khr_t5000":10,"khr_simsks":10,"cw_m3super90":10,"cw_l115":5,"khr_delisle":10,"cw_shorty":5,"cw_ws_mosin":15,"gdcw_raygun":10,"cw_c7a1":10,"cw_fiveseven":10,"cw_scarh":11,"khr_fnfal":12,"khr_mosin":15,"khr_l2a3":8,"khr_mp5a5":10,"cw_ump45":12,"cw_ppsh-41":20,"cw_mac11":5,"khr_cz858":7,"cw_ak74":15,"cw_deagle":10,"cw_auggsm":8,"cw_p99":10,"khr_vector":10,"cw_g3a3":8,"khr_m1carbine":10,"khr_ak103":12,"cw_m1911":5,"cw_mp5":15,"khr_sks":12,"khr_svt40":8,"khr_aek971":11,"khr_sr338":7,"khr_fmg9":5,"khr_mp5a4":12,"cw_g36c":12,"nz_monkey_bomb":15,"cw_m14":12,"cw_ar15":10,"khr_mp40":10,"cw_m249_official":5}},"ElecSpawns":[{"angle":"{0 90 -0}","pos":"[497.3221 -490.9688 200.5043]"}]} \ No newline at end of file diff --git a/lua/nzmapscripts/defaultspawnlist.lua b/lua/nzmapscripts/defaultspawnlist.lua new file mode 100644 index 00000000..5fb63fee --- /dev/null +++ b/lua/nzmapscripts/defaultspawnlist.lua @@ -0,0 +1,327 @@ +"TableToKeyValues" +{ + "1" + { + "tooltip" "Bushes & Trees" + "Models" + { + "1" "models/props_foliage/tree_springers_01a-lod.mdl" + "2" "models/props_foliage/tree_springers_01a.mdl" + "3" "models/props_foliage/tree_springers_card_01_skybox.mdl" + "4" "models/props_foliage/bramble001a.mdl" + "5" "models/props_foliage/cattails.mdl" + "6" "models/props_foliage/driftwood_01a.mdl" + "7" "models/props_foliage/driftwood_02a.mdl" + "8" "models/props_foliage/driftwood_03a.mdl" + "9" "models/props_foliage/driftwood_clump_01a.mdl" + "10" "models/props_foliage/driftwood_clump_02a.mdl" + "11" "models/props_foliage/driftwood_clump_03a.mdl" + "12" "models/props_foliage/ivy_01.mdl" + "13" "models/props_foliage/oak_tree01.mdl" + "14" "models/props_foliage/shrub_01a.mdl" + "15" "models/props_foliage/tree_cliff_01a.mdl" + "16" "models/props_foliage/tree_cliff_02a.mdl" + "17" "models/props_foliage/tree_deciduous_01a.mdl" + "18" "models/props_foliage/tree_deciduous_03a.mdl" + "19" "models/props_foliage/tree_deciduous_03b.mdl" + "20" "models/props_foliage/tree_poplar_01.mdl" + } + "icon" "icon16/world.png" + "name" "Foliage" + } + "2" + { + "tooltip" "Fences & Useful Door Props" + "Models" + { + "1" "models/props_c17/fence03a.mdl" + "2" "models/props_c17/fence02b.mdl" + "3" "models/props_c17/fence01b.mdl" + "4" "models/props_c17/gate_door01a.mdl" + "5" "models/props_c17/gate_door02a.mdl" + "6" "models/props_building_details/Storefront_Template001a_Bars.mdl" + "7" "models/props_borealis/borealis_door001a.mdl" + "8" "models/props_wasteland/interior_fence001g.mdl" + "9" "models/props_wasteland/interior_fence002d.mdl" + "10" "models/props_wasteland/wood_fence01a.mdl" + "11" "models/props_lab/blastdoor001a.mdl" + "12" "models/props_lab/blastdoor001b.mdl" + "13" "models/props_lab/blastdoor001c.mdl" + "14" "models/props_wasteland/wood_fence02a.mdl" + "15" "models/props_wasteland/prison_celldoor001b.mdl" + "16" "models/props_interiors/ElevatorShaft_Door01a.mdl" + "17" "models/props_debris/metal_panel01a.mdl" + "18" "models/props_debris/metal_panel02a.mdl" + "19" "models/props_doors/door03_slotted_left.mdl" + "20" "models/props_interiors/VendingMachineSoda01a_door.mdl" + "21" "models/props_wasteland/interior_fence002e.mdl" + "22" "models/props_interiors/refrigeratorDoor01a.mdl" + "23" "models/props_c17/door01_left.mdl" + "24" "models/props_c17/door02_double.mdl" + "25" "models/props_c17/gravestone_coffinpiece001a.mdl" + "26" "models/props_c17/gravestone_coffinpiece002a.mdl" + "27" "models/props_junk/TrashDumpster02b.mdl" + } + "icon" "icon16/link_break.png" + "name" "Gates" + } + "3" + { + "tooltip" "Broken Walls & Debris" + "Models" + { + "1" "models/props_debris/plaster_wall001a.mdl" + "2" "models/props_debris/plaster_wall002a.mdl" + "3" "models/props_debris/walldestroyed06b.mdl" + "4" "models/props_debris/walldestroyed07b.mdl" + "5" "models/props_debris/walldestroyed05a.mdl" + "6" "models/props_debris/tile_wall001a.mdl" + "7" "models/props_debris/tile_wall001a_base.mdl" + "8" "models/lostcoast/props_monastery/destroyed_walls02.mdl" + "9" "models/lostcoast/props_monastery/destroyed_walls03.mdl" + "10" "models/props_buildings/collapsedbuilding01awall.mdl" + "11" "models/props_debris/concrete_section128wall001a.mdl" + "12" "models/props_debris/concrete_section128wall001b.mdl" + "13" "models/props_debris/concrete_section128wall001c.mdl" + "14" "models/props_debris/concrete_section128wall002a.mdl" + "15" "models/props_debris/concrete_wall01a.mdl" + "16" "models/props_debris/concrete_wall02a.mdl" + "17" "models/props_debris/tile_wall001a_core.mdl" + "18" "models/props_debris/wall001a_base.mdl" + "19" "models/props_debris/walldestroyed01a.mdl" + "20" "models/props_debris/walldestroyed02a.mdl" + "21" "models/props_debris/walldestroyed03a.mdl" + "22" "models/props_debris/walldestroyed08a.mdl" + "23" "models/props/cs_militia/bathroomwallhole01_tile.mdl" + "24" "models/props/cs_militia/bathroomwallhole01_wood_broken_01.mdl" + "25" "models/props/cs_militia/bathroomwallhole01_wood_broken.mdl" + "26" "models/props/cs_militia/wallconcretehole.mdl" + "27" "models/props_debris/building_brokenexterior001a.mdl" + "28" "models/props_debris/building_brokenexterior001b.mdl" + "29" "models/props_debris/building_brokenexterior001c.mdl" + "30" "models/props_debris/building_brokenexterior002a.mdl" + "31" "models/props_debris/building_brokenexterior002b.mdl" + "32" "models/props_debris/building_brokenexterior002c.mdl" + "33" "models/props_debris/concrete_spawnhole001a.mdl" + "34" "models/props_debris/concrete_spawnplug001a.mdl" + "35" "models/props_debris/concrete_wall01a.mdl" + "36" "models/props_debris/concrete_wall02a.mdl" + "37" "models/props_debris/destroyedceiling01a.mdl" + "38" "models/props_debris/destroyedceiling01b.mdl" + "39" "models/props_debris/destroyedceiling01c.mdl" + "40" "models/props_debris/destroyedceiling01d.mdl" + "41" "models/props_debris/broken_floor001a.mdl" + "42" "models/props_debris/broken_pile001a.mdl" + "43" "models/props_debris/barricade_short01a.mdl" + "44" "models/props_debris/barricade_short02a.mdl" + "45" "models/props_debris/barricade_short03a.mdl" + "46" "models/props_debris/barricade_short04a.mdl" + "47" "models/props_debris/barricade_tall01a.mdl" + "48" "models/props_debris/barricade_tall02a.mdl" + "49" "models/props_debris/barricade_tall03a.mdl" + "50" "models/props_debris/barricade_tall04a.mdl" + "51" "models/props_debris/building_brokenwindow001a.mdl" + "52" "models/props_debris/building_brokenwindow001b.mdl" + "53" "models/props_unique/zombiebreakwallcoreframe01_dm.mdl" + } + "icon" "icon16/house.png" + "name" "Wall Pieces" + } + "4" + { + "tooltip" "Dead Corpses & Barbed Wire (Origins)" + "Models" + { + "1" "models/nzprops/origins/barbwire_blockade.mdl" + "2" "models/nzprops/origins/barbwire_long.mdl" + "3" "models/nzprops/origins/barbwire_gate.mdl" + "4" "models/nzprops/origins/barbwire_tube.mdl" + "5" "models/nzprops/origins/sandbag_blockade.mdl" + "6" "models/nzprops/origins/originscorpse01.mdl" + "7" "models/nzprops/origins/originscorpse02.mdl" + "8" "models/nzprops/origins/originscorpse03.mdl" + "9" "models/nzprops/origins/originscorpse04.mdl" + "10" "models/nzprops/origins/originscorpse04stick.mdl" + "11" "models/nzprops/origins/originscorpse05.mdl" + "12" "models/nzprops/origins/originscorpse05stick.mdl" + "13" "models/props_unique/wooden_barricade.mdl" + "14" "models/props_wasteland/barricade002a.mdl" + "15" "models/props_wasteland/barricade001a.mdl" + "16" "models/props_c17/concrete_barrier001a.mdl" + "17" "models/props_fortifications/concrete_barrier001_128_reference.mdl" + "18" "models/props_fortifications/concrete_barrier001_96_reference.mdl" + "19" "models/props_phx/construct/concrete_barrier00.mdl" + "20" "models/props_phx/construct/concrete_barrier01.mdl" + "21" "models/props_fortifications/barricade_razorwire001_128_reference.mdl" + "22" "models/props_fortifications/concrete_block001_128_reference.mdl" + "23" "models/props_fortifications/concrete_wall001_140_reference.mdl" + "24" "models/props_fortifications/police_barrier001_128_reference.mdl" + "25" "models/props_fortifications/traffic_barrier001.mdl" + "26" "models/props_fortifications/concrete_barrier001_96_reference.mdl" + "27" "models/props_fortifications/concrete_barrier001_96_reference.mdl" + "28" "models/props_fortifications/concrete_barrier001_96_reference.mdl" + } + "icon" "icon16/bomb.png" + "name" "Apocalyptic" + } + "5" + { + "tooltip" "Foggy Light Effect Props" + "Models" + { + "1" "models/effects/vol_light.mdl" + "2" "models/effects/vol_light01.mdl" + "3" "models/effects/vol_light02.mdl" + "4" "models/effects/vol_light128x128.mdl" + "5" "models/effects/vol_light128x256.mdl" + "6" "models/effects/vol_light128x384.mdl" + "7" "models/effects/vol_light128x512.mdl" + "8" "models/effects/vol_light256x512.mdl" + "9" "models/effects/vol_light64x128.mdl" + "10" "models/effects/vol_light64x256.mdl" + "11" "models/effects/lightshaft/lightshaft_2fortspawnext.mdl" + "12" "models/effects/lightshaft/lightshaft_window01.mdl" + "13" "models/lostcoast/effects/vollight_stainedglass.mdl" + "14" "models/props/cs_militia/bridgelight.mdl" + } + "icon" "icon16/shading.png" + "name" "Light Effects" + } + "6" + { + "tooltip" "Cabinets, Shelves, Urban Props" + "Models" + { + "1" "models/props_borealis/bluebarrel001.mdl" + "2" "models/props_interiors/Furniture_shelf01a.mdl" + "3" "models/props_junk/TrashDumpster02.mdl" + "4" "models/props_interiors/VendingMachineSoda01a.mdl" + "5" "models/props_wasteland/laundry_dryer001.mdl" + "6" "models/props_wasteland/laundry_dryer002.mdl" + "7" "models/props_wasteland/kitchen_stove002a.mdl" + "8" "models/props_wasteland/controlroom_storagecloset001b.mdl" + "9" "models/props_wasteland/medbridge_post01.mdl" + "10" "models/props_c17/signpole001.mdl" + "11" "models/props_trainstation/traincar_seats001.mdl" + "12" "models/props_vehicles/carparts_door01a.mdl" + "13" "models/props_lab/securitybank.mdl" + "14" "models/props_lab/reciever_cart.mdl" + "15" "models/props_lab/crematorcase.mdl" + "16" "models/props_lab/corkboard002.mdl" + "17" "models/props_lab/corkboard001.mdl" + "18" "models/props_lab/Cleaver.mdl" + "19" "models/props_lab/cactus.mdl" + "20" "models/props_trainstation/payphone001a.mdl" + "21" "models/props_lab/workspace003.mdl" + "22" "models/props_lab/workspace004.mdl" + "23" "models/props_lab/workspace002.mdl" + "24" "models/props_lab/workspace001.mdl" + "25" "models/props_lab/tpplugholder.mdl" + "26" "models/props_lab/tpplugholder_single.mdl" + "27" "models/props_lab/tpplug.mdl" + "28" "models/props_lab/servers.mdl" + "29" "models/props_vehicles/carparts_tire01a.mdl" + "30" "models/props_combine/combine_monitorbay.mdl" + "31" "models/props_combine/combine_interface001.mdl" + "32" "models/props_combine/combine_intmonitor001.mdl" + "33" "models/props_combine/CombineThumper002.mdl" + "34" "models/props_combine/CombineThumper001a.mdl" + "35" "models/props_combine/breendesk.mdl" + "36" "models/props_combine/combine_barricade_short02a.mdl" + "37" "models/props_combine/combine_bridge_b.mdl" + "38" "models/props_combine/combine_fence01a.mdl" + "39" "models/props_combine/combine_fence01b.mdl" + "40" "models/props_combine/weaponstripper.mdl" + "41" "models/nzprops/zombies_power_lever.mdl" + "42" "models/nzprops/zombies_power_lever_handle.mdl" + "43" "models/nzprops/zombies_power_lever_short.mdl" + "44" "models/props_c17/canister01a.mdl" + "45" "models/props_c17/canister02a.mdl" + "46" "models/props_c17/canister_propane01a.mdl" + "47" "models/props_c17/bench01a.mdl" + "48" "models/props_c17/chair02a.mdl" + "49" "models/props_c17/concrete_barrier001a.mdl" + "50" "models/props_c17/FurnitureChair001a.mdl" + "51" "models/props_c17/FurnitureCouch001a.mdl" + "52" "models/props_c17/FurnitureCouch002a.mdl" + "53" "models/props_c17/FurnitureCupboard001a.mdl" + "54" "models/props_c17/FurnitureDrawer001a.mdl" + "55" "models/props_c17/FurnitureDrawer002a.mdl" + "56" "models/props_c17/FurnitureDresser001a.mdl" + "57" "models/props_c17/FurnitureFridge001a.mdl" + "58" "models/props_c17/FurnitureRadiator001a.mdl" + "59" "models/props_c17/FurnitureShelf001a.mdl" + "60" "models/props_c17/furnitureStove001a.mdl" + "61" "models/props_c17/FurnitureWashingmachine001a.mdl" + "62" "models/props_c17/gravestone_cross001b.mdl" + "63" "models/props_c17/gravestone_statue001a.mdl" + "64" "models/props_c17/Lockers001a.mdl" + "65" "models/props_c17/oildrum001.mdl" + "66" "models/props_c17/shelfunit01a.mdl" + "67" "models/props_combine/breenchair.mdl" + "68" "models/props_interiors/Furniture_Couch01a.mdl" + "69" "models/props_interiors/Furniture_Couch02a.mdl" + "70" "models/props_junk/MetalBucket02a.mdl" + "71" "models/props_junk/metalgascan.mdl" + "72" "models/props_junk/PushCart01a.mdl" + "73" "models/props_junk/sawblade001a.mdl" + "74" "models/props_junk/TrashBin01a.mdl" + "75" "models/props_junk/TrashDumpster01a.mdl" + "76" "models/props_junk/wood_crate001a.mdl" + "77" "models/props_junk/wood_crate002a.mdl" + "78" "models/props_junk/wood_pallet001a.mdl" + "79" "models/props_lab/filecabinet02.mdl" + "80" "models/props_trainstation/trashcan_indoor001a.mdl" + "81" "models/props_trainstation/trashcan_indoor001b.mdl" + "82" "models/props_vehicles/tire001a_tractor.mdl" + "83" "models/props_vehicles/tire001b_truck.mdl" + "84" "models/props_vehicles/tire001c_car.mdl" + "85" "models/props_vehicles/apc_tire001.mdl" + "86" "models/props_wasteland/barricade001a.mdl" + "87" "models/props_wasteland/barricade002a.mdl" + "88" "models/props_wasteland/cargo_container01.mdl" + "89" "models/props_wasteland/cargo_container01b.mdl" + "90" "models/props_wasteland/laundry_washer003.mdl" + "91" "models/props_junk/garbage128_composite001a.mdl" + "92" "models/props_junk/garbage128_composite001b.mdl" + "93" "models/props_junk/garbage128_composite001c.mdl" + "94" "models/props_junk/garbage128_composite001d.mdl" + "95" "models/props_junk/garbage256_composite001a.mdl" + "96" "models/props_junk/garbage256_composite001b.mdl" + "97" "models/props_junk/garbage256_composite002a.mdl" + "98" "models/props_junk/garbage256_composite002b.mdl" + } + "icon" "icon16/camera.png" + "name" "Scenery" + } + "7" + { + "tooltip" "Broken Vehicles" + "Models" + { + "1" "models/props_canal/boat001a.mdl" + "2" "models/props_canal/boat001b.mdl" + "3" "models/props_canal/boat002b.mdl" + "4" "models/props_vehicles/car002a_physics.mdl" + "5" "models/props_vehicles/car001b_hatchback.mdl" + "6" "models/props_vehicles/car001a_hatchback.mdl" + "7" "models/props_vehicles/apc001.mdl" + "8" "models/props_vehicles/car002b_physics.mdl" + "9" "models/props_vehicles/car003a_physics.mdl" + "10" "models/props_vehicles/car003b_physics.mdl" + "11" "models/props_vehicles/car004a_physics.mdl" + "12" "models/props_vehicles/car004b_physics.mdl" + "13" "models/props_vehicles/car005a_physics.mdl" + "14" "models/props_vehicles/car005b_physics.mdl" + "15" "models/props_vehicles/tanker001a.mdl" + "16" "models/props_vehicles/generatortrailer01.mdl" + "17" "models/props_vehicles/trailer002a.mdl" + "18" "models/props_vehicles/truck001a.mdl" + "19" "models/props_vehicles/truck002a_cab.mdl" + "20" "models/props_vehicles/truck003a.mdl" + "21" "models/props_vehicles/van001a_physics.mdl" + } + "icon" "icon16/car.png" + "name" "Vehicles" + } +} diff --git a/lua/nzmapscripts/mechanics_test.lua b/lua/nzmapscripts/mechanics_test.lua new file mode 100644 index 00000000..c392a988 --- /dev/null +++ b/lua/nzmapscripts/mechanics_test.lua @@ -0,0 +1,168 @@ +local script = {} -- Create the table in which to add functions to + +local shieldparts = { + [1] = { -- Fence + {pos = Vector(850, -35, -140), ang = Angle(0,0,0)} + }, + [2] = { -- Radiator + {pos = Vector(850, -235, -140), ang = Angle(0,0,0)} + }, + [3] = { -- Posts + {pos = Vector(850, -435, -140), ang = Angle(0,0,0)} + } +} + +local shield1 = nzItemCarry:CreateCategory("shield1") +shield1:SetIcon("spawnicons/models/props_c17/fence01b.png") +shield1:SetText("Press E to pick up part.") +shield1:SetDropOnDowned(false) +shield1:SetShared(false) + +shield1:SetResetFunction( function(self) + local poss = shieldparts[1] + local ran = poss[math.random(table.Count(poss))] + if ran and ran.pos and ran.ang then + local part = ents.Create("nz_script_prop") + part:SetModel("models/props_c17/fence01b.mdl") + part:SetPos(ran.pos) + part:SetAngles(ran.ang) + part:Spawn() + self:RegisterEntity( part ) + end +end) +shield1:Update() + +local shield2 = nzItemCarry:CreateCategory("shield2") +shield2:SetModel("models/props_c17/furnitureradiator001a.mdl") +shield2:SetText("Press E to pick up part.") +shield2:SetDropOnDowned(false) +shield2:SetShared(false) + +shield2:SetResetFunction( function(self) + local poss = shieldparts[2] + local ran = poss[math.random(table.Count(poss))] + if ran and ran.pos and ran.ang then + local part = ents.Create("nz_script_prop") + part:SetModel("models/props_c17/furnitureradiator001a.mdl") + part:SetPos(ran.pos) + part:SetAngles(ran.ang) + part:Spawn() + self:RegisterEntity( part ) + end +end) +shield2:Update() + +local shield3 = nzItemCarry:CreateCategory("shield3") +shield3:SetIcon("icon16/key.png") +shield3:SetModel("models/lostcoast/fisherman/fisherman_gestures.mdl") +shield3:SetText("Press E to pick up part.") +shield3:SetDropOnDowned(false) +shield3:SetShared(false) + +shield3:SetResetFunction( function(self) + local poss = shieldparts[3] + local ran = poss[math.random(table.Count(poss))] + if ran and ran.pos and ran.ang then + local part = ents.Create("nz_script_prop") + part:SetModel("models/props_c17/playgroundtick-tack-toe_post01.mdl") + part:SetPos(ran.pos) + part:SetAngles(ran.ang) + part:Spawn() + self:RegisterEntity( part ) + end +end) +shield3:Update() + +local buildabletbl = { + model = "models/weapons/w_zombieshield.mdl", + pos = Vector(0,0,60), -- (Relative to tables own pos) + ang = Angle(0,180,90), -- (Relative too) + parts = { + ["shield1"] = {0,1}, -- Submaterials to "unhide" when this part is added + ["shield2"] = {2}, -- id's are ItemCarry object IDs + ["shield3"] = {3}, + -- You can have as many as you want + }, + usefunc = function(self, ply) -- When it's completed and a player presses E (optional) + if !ply:HasWeapon("nz_zombieshield") then + ply:Give("nz_zombieshield") + end + end, + text = "Press E to pick up Zombie Shield" +} + +local tbl = ents.Create("buildable_table") +tbl:AddValidCraft("Zombie Shield", buildabletbl) +tbl:SetPos(Entity(1):GetEyeTrace().HitPos) +tbl:Spawn() + +shield1:Reset() +shield2:Reset() +shield3:Reset() + +local elecbuttonpos = { + Vector(1023, 189, -88), + Vector(1119, 315, -86), + Vector(1639, 847, -84), + Vector(-5280, -2554, -92), +} +script.elecent = NULL +local elechit +function script.electrify() + local rand = math.random(#elecbuttonpos) + local pos = elecbuttonpos[rand] + + elechit = false + + if !IsValid(script.elecent) then + script.elecent = ents.Create("nz_script_prop") + function script.elecent:UpdateTransmitState() + return TRANSMIT_ALWAYS + end + script.elecent:SetModel("models/hunter/blocks/cube025x025x025.mdl") + script.elecent:SetNoDraw(true) + script.elecent:Spawn() + script.elecent.HitPlayer = NULL + script.elecent.OnTakeDamage = function(self, dmginfo) + if nzEE.Major.CurrentStep == 2 then + local att = dmginfo:GetAttacker() + local wep = att:GetActiveWeapon() + if IsValid(wep) and wep:GetClass() == "nz_zombieshield" then + if IsValid(self.HitPlayer) then + local wep2 = self.HitPlayer:GetWeapon("nz_zombieshield") + if IsValid(wep2) then wep2:SetElectrified(false) end + end + self.HitPlayer = att + wep:SetElectrified(true) + elechit = true + end + end + end + end + script.elecent:SetPos(pos) + timer.Simple(0.5, function() + local e = EffectData() + e:SetScale(-1) -- Infinite time + e:SetEntity(script.elecent) + util.Effect("lightning_aura", e) + end) +end +script.electrify() + +function script.camtest() + nzEE.Cam:QueueView(5, nil, nil, nil, true) + nzEE.Cam:Text("Beat it!") + nzEE.Cam:Function( function() game.SetTimeScale(0.2) end) + nzEE.Cam:Music("nz/easteregg/motd_standard.wav") + nzEE.Cam:QueueView(15, Vector(31, -13, -43), Vector(400, -13, -43), Angle(-20,0,0), true) + nzEE.Cam:Text("Beat it!") + nzEE.Cam:Function( function() game.SetTimeScale(1) end) + nzEE.Cam:Begin() +end + +function script.OnRoundBegin(num) + +end + +-- Return the table - this is critical, never forget +return script diff --git a/lua/nzmapscripts/nz_ttt_kosovos;Breakout.lua b/lua/nzmapscripts/nz_ttt_kosovos;Breakout.lua new file mode 100644 index 00000000..7dfbcf21 --- /dev/null +++ b/lua/nzmapscripts/nz_ttt_kosovos;Breakout.lua @@ -0,0 +1,572 @@ +local mapscript = {} + +local scriptgascanpositions = { + {pos = Vector(4275, -1381, 39), ang = Angle(0, 0, 0)}, + {pos = Vector(3507, -1311, 38), ang = Angle(0, 0, 0)}, + {pos = Vector(4274, -697, 39), ang = Angle(0, -2, 0)}, + {pos = Vector(4041, -515, 167), ang = Angle(0, 2, 0)}, + {pos = Vector(4244, -1278, 165), ang = Angle(0, 2, 0)}, + {pos = Vector(4311, -477, 172), ang = Angle(0, 1, 0)}, + {pos = Vector(4887, -249, 172), ang = Angle(0, -2, 0)}, + {pos = Vector(4955, 87, 171), ang = Angle(0, -1, 0)}, + {pos = Vector(4485, -4, 173), ang = Angle(0, 13, 0)}, + {pos = Vector(4203, 231, 175), ang = Angle(0, -91, 0)}, + {pos = Vector(4024, 669, 173), ang = Angle(0, 3, 0)}, + {pos = Vector(3978, 707, 175), ang = Angle(0, -91, 0)}, + {pos = Vector(3527, 983, 173), ang = Angle(0, 42, 0)}, + {pos = Vector(3278, 635, 245), ang = Angle(90, -150, 180)}, + {pos = Vector(3820, 159, 214), ang = Angle(0, -40, 0)}, + {pos = Vector(3618, 308, 174), ang = Angle(90, -132, 180)}, + {pos = Vector(3413, -199, 15), ang = Angle(0, 3, 0)}, + {pos = Vector(3636, 93, 150), ang = Angle(0, -86, 0)}, +} + +local scriptscriptgenerator +local scriptscriptgascan +local hasscriptgascan = false +local scripthasusedelev = false +local scriptnextexpltime + +local ee_cabinet +local ee_lock +local ee_bat_place +local ee_bat_charging + +local gascanobject = nzItemCarry:CreateCategory("gascan") +gascanobject:SetIcon("spawnicons/models/props_junk/gascan001a.png") +gascanobject:SetText("Press E to pick up the Gas Can.") +gascanobject:SetDropOnDowned(true) + +gascanobject:SetDropFunction( function(self, ply) + if IsValid(scriptgascan) then scriptgascan:Remove() end + scriptgascan = ents.Create("nz_script_prop") + scriptgascan:SetModel("models/props_junk/gascan001a.mdl") + scriptgascan:SetPos(ply:GetPos()) + scriptgascan:SetAngles(Angle(0,0,0)) + scriptgascan:Spawn() + self:RegisterEntity( scriptgascan ) +end) + +gascanobject:SetResetFunction( function(self) + hasscriptgascan = false + if IsValid(scriptgascan) then scriptgascan:Remove() end + local ran = scriptgascanpositions[math.random(table.Count(scriptgascanpositions))] + if ran and ran.pos and ran.ang then + scriptgascan = ents.Create("nz_script_prop") + scriptgascan:SetModel("models/props_junk/gascan001a.mdl") + scriptgascan:SetPos(ran.pos) + scriptgascan:SetAngles(ran.ang) + scriptgascan:Spawn() + self:RegisterEntity( scriptgascan ) + end +end) + +gascanobject:SetPickupFunction( function(self, ply, ent) + hasscriptgascan = true + ply:GiveCarryItem(self.id) + ent:Remove() +end) + +-- Call this to update the info to clients! +gascanobject:Update() + +-- Time to create the Easter Egg! Warning: This may spoil the steps! + +local keyobject = nzItemCarry:CreateCategory("ee_key") +keyobject:SetIcon("icon16/key.png") +keyobject:SetText("Press E to pick up the Key.") +keyobject:SetDropOnDowned(false) +keyobject:SetResetFunction( function(self) + local key = ents.Create("nz_prop_effect") + key:SetModel("models/lostcoast/fisherman/keys.mdl") + key:SetPos(Vector(2330, 1432, -1646)) + key:SetAngles(Angle(0, 52, 90)) + --key:PhysicsInitSphere(5, "metal") + --key:SetSolid(SOLID_OBB) + key:Spawn() + self:RegisterEntity(key) +end) +keyobject:Update() + +local batteryobject = nzItemCarry:CreateCategory("ee_battery") +batteryobject:SetIcon("spawnicons/models/items/car_battery01.png") +batteryobject:SetText("Press E to pick up the Battery.") +batteryobject:SetDropOnDowned(true) +batteryobject:SetResetFunction( function(self) + local bat = ents.Create("nz_script_prop") + bat:SetModel("models/items/car_battery01.mdl") + bat:SetPos(Vector(4162, 674, 167)) + bat:SetAngles(Angle(0, 90, 0)) + bat:Spawn() + self:RegisterEntity(bat) +end) +batteryobject:SetDropFunction( function(self, ply) + local bat = ents.Create("nz_script_prop") + bat:SetModel("models/items/car_battery01.mdl") + bat:SetPos(ply:GetPos() + Vector(0,0,5)) + bat:SetAngles(Angle(0, 90, 0)) + bat:Spawn() + self:RegisterEntity(bat) +end) +batteryobject:SetPickupFunction( function(self, ply, ent) + ply:GiveCarryItem(self.id) + nzEE.Major:CompleteStep(2) + ent:Remove() +end) +batteryobject:SetCondition( function() + return nzEE.Major.CurrentStep >= 1 -- Can only be picked up during at Step 1 or higher +end) +batteryobject:Update() + +local chargedbatteryobject = nzItemCarry:CreateCategory("ee_chargedbattery") +chargedbatteryobject:SetIcon("spawnicons/models/items/car_battery01.png") +chargedbatteryobject:SetText("Press E to pick up the Charged Battery.") +chargedbatteryobject:SetDropOnDowned(true) +chargedbatteryobject:SetResetFunction( function(self) + local bat = ents.Create("nz_script_prop") + bat:SetModel("models/items/car_battery01.mdl") + bat:SetPos(Vector(4162, 674, 167)) + bat:SetAngles(Angle(0, 90, 0)) + bat:Spawn() + batteryobject:RegisterEntity(bat) -- Reset it to non-charged +end) +chargedbatteryobject:SetDropFunction( function(self, ply) + local bat = ents.Create("nz_script_prop") + bat:SetModel("models/items/car_battery01.mdl") + bat:SetPos(ply:GetPos() + Vector(0,0,5)) + bat:SetAngles(Angle(0, 90, 0)) + bat:Spawn() + self:RegisterEntity(bat) -- Dropping it is still charged +end) +chargedbatteryobject:SetCondition( function() + return nzEE.Major.CurrentStep >= 2 -- Can only be picked up during at Step 2 or higher +end) +chargedbatteryobject:Update() + + +nzEE.Major:AddStep( function() + -- Add unlock sound here +end) + +nzEE.Major:AddStep( function() -- Creates ghost charger that can charge the battery and return ee_chargedbattery + ee_bat_place = ents.Create("nz_script_prop") + ee_bat_place:SetModel("models/items/car_battery01.mdl") + ee_bat_place:SetPos(Vector(5386, -1079, -58)) + ee_bat_place:SetAngles(Angle(-10, 0, 0)) + ee_bat_place.OnUsed = function(self, ply) + if ply:HasCarryItem("ee_battery") then + ply:RemoveCarryItem("ee_battery") + ee_bat_charging = ents.Create("nz_script_soulcatcher") + ee_bat_charging:SetModel(self:GetModel()) + ee_bat_charging:SetPos(self:GetPos()) + ee_bat_charging:SetAngles(self:GetAngles()) + ee_bat_charging:Spawn() -- Spawn before setting variables or they'll become the default + ee_bat_charging:SetTargetAmount(10) + ee_bat_charging:SetRange(200) + ee_bat_charging:SetReleaseOverride( function(self2, z) + --print(self2.CurrentAmount) + if self2.CurrentAmount >= self2.TargetAmount then return end + --print("Passing") + local e = EffectData() + e:SetOrigin(self2:GetPos()) + e:SetStart(z:GetPos()) + e:SetMagnitude(0.3) + util.Effect("lightning_strike", e) + self2.CurrentAmount = self2.CurrentAmount + 1 + --print(self2.CurrentAmount) + self2:CollectSoul() -- Updates and triggers when to complete it + -- CollectSoul is normally called in the standard effect when the soul gets to the collector + end) + ee_bat_charging:SetCompleteFunction( function(self3) + local chgbat = ents.Create("nz_script_prop") + chgbat:SetModel(self3:GetModel()) + chgbat:SetPos(self3:GetPos()) + chgbat:SetAngles(self3:GetAngles()) + chgbat:Spawn() + chargedbatteryobject:RegisterEntity(chgbat) + self3:Remove() + --print("Done!") + end) + ee_bat_charging:SetCondition( function(self4, z, dmg) + --print(dmg:GetDamageType(), z, self4, dmg) + return dmg:GetDamageType() == DMG_SHOCK -- Only allow electric kills + end) + self:Remove() + end + end + ee_bat_place:Spawn() + ee_bat_place:SetColor(Color(255,255,255,30)) + ee_bat_place:SetRenderMode(RENDERMODE_TRANSCOLOR) +end) + +local propcolors = { + [1] = "models/props_lab/tpplug.mdl", -- Blue plug + [2] = "models/weapons/w_ammobox_thrown.mdl", -- Green ammo case + [3] = "models/props_mining/freightelevatorbutton02.mdl", -- Yellow button + [4] = "models/props_c17/light_cagelight01_off.mdl", -- Red light +} +local colorprops = { -- Table indexes all possible random locations for props + [1] = { -- Key indicates the color + [1] = { -- This key indicates what row these positions are on + {pos = Vector(2391, -1727, -142), ang = Angle(19, 70, 42)}, + {pos = Vector(2385, -1926, -185), ang = Angle(19, 48, -44)}, + {pos = Vector(2383, -2040, -142), ang = Angle(19, 52, -44)}, + }, + [2] = { + {pos = Vector(2233, -1771, -142), ang = Angle(19, -29, 45)}, + {pos = Vector(2236, -2045, -185), ang = Angle(19, -37, -45)}, + }, + [3] = { + {pos = Vector(2033, -2094, -144), ang = Angle(0, 34, -2)}, + {pos = Vector(2027, -2085, -186), ang = Angle(0, -35, -2)}, + {pos = Vector(2044, -1714, -185), ang = Angle(19, -30, -45)}, + }, + [4] = { + {pos = Vector(1874, -2081, -144), ang = Angle(0, -43, -3)}, + {pos = Vector(1873, -1884, -144), ang = Angle(0, 54, -1)}, + {pos = Vector(1884, -1775, -187), ang = Angle(0, 56, 1)}, + }, + }, + [2] = { + [1] = { + {pos = Vector(2397, -1713, -185), ang = Angle(0, 48, 0)}, + {pos = Vector(2383, -1727, -142), ang = Angle(0, 101, 1)}, + {pos = Vector(2381, -1921, -185), ang = Angle(0, 57, 0)}, + {pos = Vector(2379, -2068, -100), ang = Angle(0, 57, -1)}, + }, + [2] = { + {pos = Vector(2257, -2087, -185), ang = Angle(0, 103, 0)}, + {pos = Vector(2244, -1746, -99), ang = Angle(0, 137, 0)}, + }, + [3] = { + {pos = Vector(2034, -1723, -185), ang = Angle(0, 123, -1)}, + {pos = Vector(2047, -2091, -142), ang = Angle(0, -158, 0)}, + {pos = Vector(2048, -2097, -185), ang = Angle(0, -152, -1)}, + {pos = Vector(2045, -2024, -185), ang = Angle(0, -173, 0)}, + }, + [4] = { + {pos = Vector(1873, -1774, -185), ang = Angle(0, -126, 0)}, + {pos = Vector(1894, -1901, -100), ang = Angle(0, -81, 0)}, + {pos = Vector(1886, -2089, -142), ang = Angle(0, -94, 0)}, + }, + }, + [3] = { + [1] = { + {pos = Vector(2386, -1719, -147), ang = Angle(-89, -47, -80)}, + {pos = Vector(2388, -2036, -148), ang = Angle(-89, 150, 89)}, + }, + [2] = { + {pos = Vector(2245, -2040, -191), ang = Angle(-89, -43, 90)}, + {pos = Vector(2226, -1766, -148), ang = Angle(-90, -58, -1)}, + }, + [3] = { + {pos = Vector(2058, -2088, -147), ang = Angle(-90, -159, 180)}, + {pos = Vector(2050, -1727, -191), ang = Angle(-90, -38, 0)}, + }, + [4] = { + {pos = Vector(1904, -2081, -148), ang = Angle(-89, -18, 68)}, + {pos = Vector(1880, -1892, -147), ang = Angle(-89, 85, -135)}, + {pos = Vector(1892, -1768, -190), ang = Angle(-90, 133, 180)}, + }, + }, + [4] = { + [1] = { + {pos = Vector(2385, -1716, -146), ang = Angle(0, -38, -90)}, + {pos = Vector(2378, -1896, -101), ang = Angle(0, -85, -90)}, + {pos = Vector(2385, -2039, -145), ang = Angle(0, 2, -90)}, + }, + [2] = { + {pos = Vector(2264, -2137, -190), ang = Angle(0, 166, -90)}, + {pos = Vector(2247, -2022, -146), ang = Angle(0, 70, -90)}, + {pos = Vector(2245, -1789, -145), ang = Angle(0, 131, -90)}, + }, + [3] = { + {pos = Vector(2042, -2083, -145), ang = Angle(0, 30, -88)}, + {pos = Vector(2039, -1709, -187), ang = Angle(0, 47, 88)}, + }, + [4] = { + {pos = Vector(1875, -2094, -144), ang = Angle(0, 9, 93)}, + {pos = Vector(1879, -1879, -146), ang = Angle(0, -71, 93)}, + {pos = Vector(1873, -1769, -190), ang = Angle(0, -18, 93)}, + }, + }, +} +local countprops = { + [1] = { -- This shows the row + [1] = { -- This is the number of prop + model = "models/items/boxmrounds.mdl", + pos = Vector(2370, -1315, -196), + ang = Angle(-1, 26, 0), + }, + [2] = { + model = "models/items/boxsrounds.mdl", + pos = Vector(2361, -1324, -196), + ang = Angle(1, 28, 0), + }, + [3] = { + model = "models/items/boxmrounds.mdl", + pos = Vector(2346, -1312, -196), + ang = Angle(0, -14, -1), + }, + [4] = { + model = "models/items/357ammobox.mdl", + pos = Vector(2380, -1329, -196), + ang = Angle(2, -43, 0) + }, + }, + [2] = { + [1] = { + model = "models/items/ammocrate_ar2.mdl", + pos = Vector(2137, -1290, -180), + ang = Angle(0, -84, 0), + }, + [2] = { + model = "models/items/boxmrounds.mdl", + pos = Vector(2122, -1320, -196), + ang = Angle(0, -25, 0), + }, + [3] = { + model = "models/items/boxsrounds.mdl", + pos = Vector(2141, -1310, -196), + ang = Angle(1, 88, 1), + }, + [4] = { + model = "models/items/boxbuckshot.mdl", + pos = Vector(2137, -1322, -196), + ang = Angle(0, -68, 0) + }, + }, + [3] = { + [1] = { + model = "models/items/boxmrounds.mdl", + pos = Vector(1917, -1288, -196), + ang = Angle(0, -69, 0) + }, + [2] = { + model = "models/items/boxmrounds.mdl", + pos = Vector(1897, -1288, -196), + ang = Angle(0, -31, 0) + }, + [3] = { + model = "models/items/boxmrounds.mdl", + pos = Vector(1937, -1282, -196), + ang = Angle(0, 49, 0) + }, + [4] = { + model = "models/items/boxsrounds.mdl", + pos = Vector(1905, -1302, -196), + ang = Angle(0, -87, 0) + }, + }, + [4] = { + [1] = { + model = "models/items/boxmrounds.mdl", + pos = Vector(1930, -1582, -164), + ang = Angle(0, 59, 0) + }, + [2] = { + model = "models/items/boxsrounds.mdl", + pos = Vector(1902, -1580, -164), + ang = Angle(-1, 124, 0) + }, + [3] = { + model = "models/items/357ammobox.mdl", + pos = Vector(1930, -1572, -189), + ang = Angle(0, 114, 0) + }, + [4] = { + model = "models/items/boxbuckshot.mdl", + pos = Vector(1910, -1581, -139), + ang = Angle(0, 68, 0) + }, + } +} + +function mapscript.ScriptLoad() +end + +local ee_buttons = { + {pos = Vector(3776, -1482, 83), ang = Angle(9, 92, 0)}, + {pos = Vector(4913, -2115, 22), ang = Angle(0, 90, 0)}, + {pos = Vector(3102, 216, 62), ang = Angle(0, 90, 0)}, + {pos = Vector(3248, 697, 213), ang = Angle(0, 0, 0)}, + {pos = Vector(4232, 682, 218), ang = Angle(0, -90, 0)}, + {pos = Vector(4448, -720, 215), ang = Angle(0, 90, 0)}, +} +local ee_actualbuttons = {} +local curbuttoncount = 0 + +local function RandomizeButtonOrders() + +end + +-- Remove props and stuff on spawn +local function CleanUpMapScriptStuff() + if IsValid(scriptgenerator) then scriptgenerator:Remove() end + if IsValid(scriptgascan) then scriptgascan:Remove() end + scriptgenerator = nil + scriptgaspositions = nil + scriptgascan = nil + hasscriptgascan = nil + for k,v in pairs(ee_actualbuttons) do + if IsValid(v) then + v:Remove() + end + ee_actualbuttons[k] = nil + end +end + +function mapscript.OnGameBegin() + CleanUpMapScriptStuff() -- Clean up the entities from previous games if they exist + local button = ents.FindByName("ele_call_down")[1] + button:Fire("Press") -- Call the elevator down to begin with + + local button2 = ents.FindByName("ele_button_1")[1] + button2.OnUsed = function(self) + if !scripthasusedelev then + scripthasusedelev = true + scriptgenerator:SetNWString("NZText", "The Elevator is currently on a lower floor.") + local ent = ents.FindByName("alarm_obj")[1] + timer.Simple(50, function() + ent:Fire("PlaySound") + end) + timer.Simple(60, function() + ent:Fire("StopSound") + scripthasusedelev = false + scriptgenerator:SetNWString("NZText", "You need a Gas Can to power the Elevator.") + for k,v in pairs(player.GetAllPlaying()) do + local pos = v:GetPos() + if pos.z < -1000 then + local e = EffectData() + e:SetOrigin(v:GetPos()) + e:SetEntity(v) + e:SetMagnitude(2) + util.Effect("lightning_prespawn", e) + local spawn = ents.FindByClass("player_spawns")[v:EntIndex()] + e = EffectData() + e:SetOrigin(spawn:GetPos()) + e:SetEntity(nil) + util.Effect("lightning_prespawn", e) + end + end + timer.Simple(2, function() + for k,v in pairs(player.GetAllPlaying()) do + local pos = v:GetPos() + if pos.z < -1000 then + local e = EffectData() + e:SetOrigin(pos) + e:SetMagnitude(0.75) + util.Effect("lightning_strike", e) + local spawnpos = ents.FindByClass("player_spawns")[v:EntIndex()]:GetPos() + e = EffectData() + e:SetOrigin(spawnpos) + e:SetMagnitude(0.75) + util.Effect("lightning_strike", e) + v:SetPos(spawnpos) + end + end + end) + end) + end + end + + local button3 = ents.FindByName("ele_button_7")[1] + + scriptgenerator = ents.Create("nz_script_prop") + scriptgenerator:SetPos(Vector(3275, -254, -275)) + scriptgenerator:SetAngles(Angle(0, 90, 0)) + scriptgenerator:SetModel("models/props_vehicles/generatortrailer01.mdl") + scriptgenerator:SetNWString("NZText", "You need a Gas Can to power the Elevator.") + scriptgenerator:SetNWString("NZRequiredItem", "gascan") + scriptgenerator:SetNWString("NZHasText", "Press E to fuel the Generator with a Gas Can.") + scriptgenerator:Spawn() + scriptgenerator:Activate() + -- Function when it is used (E) + scriptgenerator.OnUsed = function( self, ply ) + if ply:HasCarryItem("gascan") then -- Only if we picked up the gascan + hasscriptgascan = false -- Reset gascan status + ply:RemoveCarryItem("gascan") + if button3:GetPos().z < -1000 then + button3:Fire("Unlock") -- Call the elevator up + button3:Fire("Press") + scriptgenerator:SetNWString("NZText", "The Elevator is on its way up.") -- Update text + end + end + end + + local door = ents.GetMapCreatedEntity(1836) + if IsValid(door) then door:SetNWString("NZText", "You need to disable the security system.") end + + for k,v in pairs(ents.FindInSphere(Vector(3315, -1280, 55), 10)) do + if v:GetClass() == "prop_buys" then v:BlockUnlock() end + end + + keyobject:Reset() + + ee_cabinet = ents.Create("nz_script_prop") + ee_cabinet:SetModel("models/props_c17/fence01b.mdl") + ee_cabinet:SetPos(Vector(4163, 661, 135)) + ee_cabinet:SetAngles(Angle(0,90,0)) + ee_cabinet:Spawn() + + ee_lock = ents.Create("nz_script_prop") + ee_lock:SetModel("models/props_wasteland/prison_padlock001a.mdl") + ee_lock:SetPos(Vector(4126, 659, 171)) + ee_lock:SetAngles(Angle(0,-90,0)) + ee_lock:SetNWString("NZText", "You need a Key.") + ee_lock:SetNWString("NZRequiredItem", "ee_key") + ee_lock:SetNWString("NZHasText", "Press E to unlock.") + ee_lock.OnUsed = function(self, ply) + if ply:HasCarryItem("ee_key") then + ply:RemoveCarryItem("ee_key") + ee_cabinet:Remove() + ee_lock:Remove() + nzEE.Major:CompleteStep(1) + end + end + ee_lock:Spawn() + + batteryobject:Reset() + + for k,v in pairs(ee_buttons) do + local button = ents.Create("nz_script_prop") + button:SetModel("models/props_lab/keypad.mdl") + button:SetPos(v.pos) + button:SetAngles(v.ang) + table.insert(ee_actualbuttons, button) + end +end + +function mapscript.PostCleanupMap() + --print("Things") +end + +-- This one will be called at the start of each round +function mapscript.OnRoundStart() + if !IsValid(scriptgascan) and !hasscriptgascan and !scripthasusedelev then + gascanobject:Reset() -- Makes it respawn + end +end + +-- Will be called every second if a round is in progress (zombies are alive) +function mapscript.RoundThink() + +end + +-- Will be called after each round +function mapscript.RoundEnd() + +end + +-- Cleanup +function mapscript.ScriptUnload() + CleanUpMapScriptStuff() + +end + +-- Only functions will be hooked, meaning you can safely store data as well +mapscript.TestPrint = "v0.0" +local testprint2 = "This is cool" -- You can also store the data locally + +-- Always return the mapscript table. This gives it on to the gamemode so it can use it. +return mapscript diff --git a/lua/nzmapscripts/nz_zs_obj_station;Imprisoned.lua b/lua/nzmapscripts/nz_zs_obj_station;Imprisoned.lua new file mode 100644 index 00000000..ee03ee25 --- /dev/null +++ b/lua/nzmapscripts/nz_zs_obj_station;Imprisoned.lua @@ -0,0 +1,846 @@ +local mapscript = {} + +local gens = { + {pos = Vector(475, -845, 213), ang = Angle(0,-105,90)}, + {pos = Vector(1860, -365, 225), ang = Angle(0,-87,90)}, + {pos = Vector(1557, 889, 193), ang = Angle(0,-8,90)} +} +local gen_ents = {} + +local shieldparts = { + [1] = { -- Fence + {pos = Vector(324, 348, 205), ang = Angle(15,-45,0)}, + {pos = Vector(16, 523, 180), ang = Angle(-8, 0, 0)}, + {pos = Vector(602, 741, 332), ang = Angle(5, 0, 0)}, + {pos = Vector(-205, 377, 132), ang = Angle(-90, -90, 180)}, + {pos = Vector(575, 887, 186), ang = Angle(45, 90, 90)}, + }, + [2] = { -- Radiator + {pos = Vector(1200, -669, 274), ang = Angle(0,43,0)}, + {pos = Vector(935, -349, 379), ang = Angle(-90, -133, 180)}, + {pos = Vector(1116, -250, 274), ang = Angle(0,0,0)}, + {pos = Vector(1130, -1058, 269), ang = Angle(45,-90,0)}, + {pos = Vector(803, -1775, 338), ang = Angle(0,0,0)}, + }, + [3] = { -- Posts + {pos = Vector(336, 570, 16), ang = Angle(0,0,0)}, + {pos = Vector(338, 120, 37), ang = Angle(-10, 18, 45)}, + {pos = Vector(560, 960, 134), ang = Angle(-90, -90, 180)}, + {pos = Vector(1059, 906, 0), ang = Angle(0,75,0)}, + {pos = Vector(1615, 953, -4), ang = Angle(0,90,0)}, + } +} + +local shield1 = nzItemCarry:CreateCategory("shield1") +shield1:SetIcon("spawnicons/models/props_c17/fence01b.png") +shield1:SetText("Press E to pick up part.") +shield1:SetDropOnDowned(false) +shield1:SetShared(false) + +shield1:SetResetFunction( function(self) + local poss = shieldparts[1] + local ran = poss[math.random(table.Count(poss))] + if ran and ran.pos and ran.ang then + local part = ents.Create("nz_script_prop") + part:SetModel("models/props_c17/fence01b.mdl") + part:SetPos(ran.pos) + part:SetAngles(ran.ang) + part:Spawn() + self:RegisterEntity( part ) + end +end) +shield1:Update() + +local shield2 = nzItemCarry:CreateCategory("shield2") +shield2:SetIcon("spawnicons/models/props_c17/furnitureradiator001a.png") +shield2:SetText("Press E to pick up part.") +shield2:SetDropOnDowned(false) +shield2:SetShared(false) + +shield2:SetResetFunction( function(self) + local poss = shieldparts[2] + local ran = poss[math.random(table.Count(poss))] + if ran and ran.pos and ran.ang then + local part = ents.Create("nz_script_prop") + part:SetModel("models/props_c17/furnitureradiator001a.mdl") + part:SetPos(ran.pos) + part:SetAngles(ran.ang) + part:Spawn() + self:RegisterEntity( part ) + end +end) +shield2:Update() + +local shield3 = nzItemCarry:CreateCategory("shield3") +shield3:SetIcon("spawnicons/models/props_c17/playgroundtick-tack-toe_post01.png") +shield3:SetText("Press E to pick up part.") +shield3:SetDropOnDowned(false) +shield3:SetShared(false) + +shield3:SetResetFunction( function(self) + local poss = shieldparts[3] + local ran = poss[math.random(table.Count(poss))] + if ran and ran.pos and ran.ang then + local part = ents.Create("nz_script_prop") + part:SetModel("models/props_c17/playgroundtick-tack-toe_post01.mdl") + part:SetPos(ran.pos) + part:SetAngles(ran.ang) + part:Spawn() + self:RegisterEntity( part ) + end +end) +shield3:Update() + +local buildabletbl = { + model = "models/weapons/w_zombieshield.mdl", + pos = Vector(0,0,60), -- (Relative to tables own pos) + ang = Angle(0,180,90), -- (Relative too) + parts = { + ["shield1"] = {0,1}, -- Submaterials to "unhide" when this part is added + ["shield2"] = {2}, -- id's are ItemCarry object IDs + ["shield3"] = {3}, + -- You can have as many as you want + }, + usefunc = function(self, ply) -- When it's completed and a player presses E (optional) + if !ply:HasWeapon("nz_zombieshield") then + ply:Give("nz_zombieshield") + end + end, + text = "Press E to pick up Zombie Shield" +} + +local validfuses = { + [1] = {pos = Vector(587, -467, 236), finishpos = Vector(-370, 948, 40), ent = NULL, done = false}, + [2] = {pos = Vector(587, -467, 230), finishpos = Vector(-370, 948, 34), ent = NULL, done = false}, + [3] = {pos = Vector(587, -467, 224), finishpos = Vector(-370, 948, 28), ent = NULL, done = false} +} + +local fuses = nzItemCarry:CreateCategory("fuses") +fuses:SetIcon("spawnicons/models/healthvial.png") +fuses:SetText("Press E to pick up fuse.") +fuses:SetDropOnDowned(true) + +fuses:SetResetFunction( function(self) + for k,v in pairs(validfuses) do + if !v.done and (!IsValid(v.ent) or (v.ent:IsPlayer() and (!v.ent:IsPlaying() or !v.ent:HasCarryItem("fuses")))) then -- Only spawn those that are not being carried + local ent = ents.Create("nz_script_prop") + ent:SetModel("models/healthvial.mdl") + ent:SetPos(v.pos) + ent:SetAngles(Angle(0,-90,-90)) + ent:Spawn() + v.done = false + v.ent = ent + self:RegisterEntity(ent) + end + end +end) + +fuses:SetDropFunction( function(self, ply) + for k,v in pairs(validfuses) do -- Loop through all fuses + if v.ent == ply then -- If this is the one we're carrying + local ent = ents.Create("nz_script_prop") + ent:SetModel("models/healthvial.mdl") + ent:SetPos(ply:GetPos() + Vector(0,0,10)) + ent:SetAngles(Angle(0,0,0)) + ent:Spawn() + ent:DropToFloor() + v.ent = ent -- Drop the fuse and set the entity to this fuse + self:RegisterEntity( ent ) + break + end + end +end) + +fuses:SetPickupFunction( function(self, ply, ent) + for k,v in pairs(validfuses) do -- Loop through all fuses + if v.ent == ent then -- If this is the one + ply:GiveCarryItem(self.id) + ent:Remove() + v.ent = ply -- Mark the new entity to be that of the player + break + end + end +end) +fuses:SetCondition( function(self, ply) + return !ply:HasCarryItem("fuses") and !ply:HasCarryItem("chargedfuses") +end) + +fuses:Update() + +local chargedfuses = nzItemCarry:CreateCategory("chargedfuses") +chargedfuses:SetIcon("spawnicons/models/healthvial.png") +chargedfuses:SetText("Press E to pick up charged fuse.") +chargedfuses:SetDropOnDowned(true) + +chargedfuses:SetResetFunction( function(self) + for k,v in pairs(validfuses) do -- They share the table + if v.done and (!IsValid(v.ent) or (v.ent:IsPlayer() and (!v.ent:IsPlaying() or !v.ent:HasCarryItem("chargedfuses")))) then -- Reset the finished ones not being carried + local ent = ents.Create("nz_script_prop") + ent:SetModel("models/healthvial.mdl") + ent:SetPos(v.pos) + ent:SetAngles(Angle(0,-90,-90)) + ent:Spawn() + v.done = true -- These are already charged, although they will respawn in the start point (if reset) + v.ent = ent + self:RegisterEntity(ent) + end + end +end) + +chargedfuses:SetDropFunction( function(self, ply) + for k,v in pairs(validfuses) do -- Loop through all fuses + if v.ent == ply then -- If this is the one we're carrying + local ent = ents.Create("nz_script_prop") + ent:SetModel("models/healthvial.mdl") + ent:SetPos(ply:GetPos() + Vector(0,0,10)) + ent:SetAngles(Angle(0,0,0)) + ent:Spawn() + ent:DropToFloor() + v.ent = ent -- Drop the fuse and set the entity to this fuse + self:RegisterEntity( ent ) + break + end + end +end) + +chargedfuses:SetPickupFunction( function(self, ply, ent) + for k,v in pairs(validfuses) do -- Loop through all fuses + if v.ent == ent then -- If this is the one + ply:GiveCarryItem(self.id) + ent:Remove() + v.ent = ply -- Mark the new entity to be that of the player + break + end + end +end) +chargedfuses:SetCondition( function(self, ply) + return !ply:HasCarryItem("fuses") and !ply:HasCarryItem("chargedfuses") +end) + +chargedfuses:Update() + +local elecbuttonpos = { + Vector(1922, -872, 223), + Vector(1342, 1048, 192), + Vector(460, -32, 252), + Vector(975, -1048, 181), + Vector(808, -985, 180), + Vector(935, -150, 180), + Vector(24, -1452, 194), + Vector(-344, -1200, 186), + Vector(133, -1717, 185), + Vector(892, 785, 189) +} +local elecent +local elechit +local function electrify() + local rand = math.random(#elecbuttonpos) + local pos = elecbuttonpos[rand] + + elechit = false + + if !IsValid(elecent) then + elecent = ents.Create("nz_script_prop") + function elecent:UpdateTransmitState() + return TRANSMIT_ALWAYS -- Then our effect will work no matter where it is + end + elecent:SetModel("models/hunter/blocks/cube025x025x025.mdl") + elecent:SetNoDraw(true) + elecent:Spawn() + elecent.HitPlayer = NULL + elecent.OnTakeDamage = function(self, dmginfo) + if nzEE.Major.CurrentStep == 2 then + local att = dmginfo:GetAttacker() + local wep = att:GetActiveWeapon() + if IsValid(wep) and wep:GetClass() == "nz_zombieshield" then + if IsValid(self.HitPlayer) then + local wep2 = self.HitPlayer:GetWeapon("nz_zombieshield") + if IsValid(wep2) then wep2:SetElectrified(false) end + end + self.HitPlayer = att + wep:SetElectrified(true) + elechit = true + end + end + end + end + elecent:SetPos(pos) + timer.Simple(0.5, function() + local e = EffectData() + e:SetScale(-1) + e:SetEntity(elecent) + util.Effect("lightning_aura", e) + end) +end +local elecgatebuttonshit = 0 +local function finalelectric() + if !IsValid(elecent) then + elecent = ents.Create("nz_script_prop") + function elecent:UpdateTransmitState() + return TRANSMIT_ALWAYS + end + elecent:SetModel("models/hunter/blocks/cube025x025x025.mdl") + elecent:SetNoDraw(true) + elecent:Spawn() + + end + elecent.OnTakeDamage = function(self, dmginfo) + local att = dmginfo:GetAttacker() + local wep = att:GetActiveWeapon() + if IsValid(wep) and wep:GetClass() == "nz_zombieshield" then + wep:SetElectrified(true) + end + elecgatebuttonshit = elecgatebuttonshit + 1 + if elecgatebuttonshit == 2 then + nzEE.Major:CompleteStep(2) + end + end + elecent:SetPos(Vector(2217, -862, 232)) + timer.Simple(0.5, function() + local e = EffectData() + e:SetScale(-1) + e:SetEntity(elecent) + util.Effect("lightning_aura", e) + end) + + local ent2 = ents.Create("nz_script_prop") + function ent2:UpdateTransmitState() + return TRANSMIT_ALWAYS -- Then our effect will work no matter where it is + end + ent2:SetModel("models/hunter/blocks/cube025x025x025.mdl") + ent2:SetNoDraw(true) + ent2:SetPos(Vector(1966, -862, 232)) + ent2:Spawn() + ent2.OnTakeDamage = function(self, dmginfo) + local att = dmginfo:GetAttacker() + local wep = att:GetActiveWeapon() + if IsValid(wep) and wep:GetClass() == "nz_zombieshield" then + wep:SetElectrified(true) + end + elecgatebuttonshit = elecgatebuttonshit + 1 + if elecgatebuttonshit == 2 then + nzEE.Major:CompleteStep(2) + end + end + + timer.Simple(0.5, function() + if IsValid(ent2) then + local e = EffectData() + e:SetScale(-1) + e:SetEntity(ent2) + util.Effect("lightning_aura", e) + end + end) +end + +nzEE.Major:AddStep( function() -- Step 1, get to the key (fairly long step) + nzDoors:OpenLinkedDoors("ee_door") + nzNotifications:PlaySound("nz/easteregg/motd_round-01.wav", 0) + local ent + for k,v in pairs(ents.FindByName("door_key_5")) do + if IsValid(v) then + ent = v + break + end + end + if !IsValid(ent) then + for k,v in pairs(ents.FindByName("key_template5")) do + v:Fire("ForceSpawn") -- Spawn the key if it doesn't exist + end + end + +end) + +local forcefieldgens = {} +nzEE.Major:AddStep( function() -- Step 2, Open control room gate (fairly long step too) + nzNotifications:PlaySound("nz/easteregg/motd_round-04.wav", 5) + nzNotifications:PlaySound("ambient/machines/thumper_startup1.wav", 2) + nzNotifications:PlaySound("ambient/machines/thumper_hit.wav", 0) + for k,v in pairs(forcefieldgens) do -- This enables the next step + if IsValid(v) then + v:SetSubMaterial(1, "") + end + end + for k,v in pairs(ents.FindByName("gate")) do + if IsValid(v) then + v:Fire("Open") -- Opens the gate + end + end + local ent = ents.FindByName("gate_opening_sound")[1] + ent:Fire("StopSound") + ent:Fire("PlaySound") + timer.Simple(10, function() + if IsValid(ent) then + ent:Fire("StopSound") + end + end) +end) + +nzEE.Major:AddStep( function() -- Step 3, Shut down forcefield + for k,v in pairs(ents.FindByName("energy_shield_2")) do + if IsValid(v) then + v:Remove() -- Closes the forcefield + end + end + for k,v in pairs(ents.FindByName("panel1")) do + v:SetSubMaterial(1, "color") + end + for k,v in pairs(ents.FindByName("panel2")) do + v:SetSubMaterial(0, "color") + end + local corekillstart = ents.FindByName("shield_button1")[1] + corekillstart:CallOnRemove("nzee_core", function() + nzEE.Major:CompleteStep(4) -- Triggers the final step + end) +end) + +local roundwegotto +nzEE.Major:AddStep( function() -- Step 4, trigger the core's destruction + roundwegotto = nzRound:GetNumber() + nzRound:RoundInfinity() + local corekilled = ents.FindByName("corekill_button2")[1] + corekilled:CallOnRemove("nzee_win", function(self) + nzEE.Major:CompleteStep(5) + end) +end) + +nzEE.Major:AddStep( function() -- Step 5, You win :D + nzEE.Cam:QueueView(5, nil, nil, nil, true) + nzEE.Cam:Text("You blew up the core after "..roundwegotto.." rounds!") + nzEE.Cam:Function( function() + game.SetTimeScale(0.2) + nzRound:Freeze(true) -- Prevents switching and spawning + end) + nzEE.Cam:Music("nz/easteregg/motd_standard.wav") + nzEE.Cam:QueueView(15, Vector(1623, -1257, 187), Vector(1623, -1382, 227), nil, true) + nzEE.Cam:Text("You blew up the core after "..roundwegotto.." rounds!") + nzEE.Cam:Function( function() + nzRound.Number = roundwegotto or 0 + game.SetTimeScale(1) + for k,v in pairs(player.GetAll()) do + v:SetTargetPriority(TARGET_PRIORITY_NONE) + v:Freeze(true) + end + end) + nzEE.Cam:QueueView(1) + nzEE.Cam:Function( function() + nzPowerUps:Nuke(nil, true, false) + nzRound:Freeze(false) + nzRound:Prepare() -- We continue now with perma perks :D + for k,v in pairs(player.GetAll()) do + v:GivePermaPerks() + v:SetTargetPriority(TARGET_PRIORITY_PLAYER) + v:Freeze(false) + end + end) + nzEE.Cam:Begin() +end) + +function mapscript.OnGameBegin() + local completed = 1 + for k,v in pairs(gens) do + local gen + if IsValid(gen_ents[k]) then + gen = gen_ents[k] + else + gen = ents.Create("nz_script_soulcatcher") + end + gen:SetNoDraw(true) + gen:SetPos(v.pos) + gen:SetAngles(v.ang) + gen:SetModel("models/hunter/blocks/cube025x025x025.mdl") + gen:Spawn() -- Spawn before setting variables or they'll become the default + gen:SetTargetAmount(20) + gen:SetRange(500) + gen:SetReleaseOverride( function(self, z) + if self.CurrentAmount >= self.TargetAmount then return end + + local e = EffectData() + e:SetOrigin(self:GetPos()) + e:SetStart(z:GetPos()) + e:SetMagnitude(0.3) + util.Effect("lightning_strike", e) + self.CurrentAmount = self.CurrentAmount + 1 + self:CollectSoul() + end) + gen:SetCompleteFunction( function(self) + if validfuses[self.fuse] and IsValid(validfuses[self.fuse].ent) then + validfuses[self.fuse].done = true + chargedfuses:RegisterEntity(validfuses[self.fuse].ent) -- Can now be picked up charged + end + nzDoors:OpenLinkedDoors("gen"..completed) + if completed == 3 then + nzDoors:OpenLinkedDoors("10") -- Enables the spawnpoints by PaP + end + completed = completed + 1 + self:Remove() -- Disappear! + end) + gen:SetCondition( function(self, z, dmg) + return nzElec.Active + end) + gen_ents[k] = gen + + gen:SetEnabled(false) + gen:SetNWString("NZText", "You need a fuse to charge the generator.") + gen:SetNWString("NZRequiredItem", "fuses") + gen:SetNWString("NZHasText", "Press E to insert fuse.") + gen.OnUsed = function(self, ply) + if ply:HasCarryItem("fuses") then + for k,v in pairs(validfuses) do + if v.ent == ply then + local ent = ents.Create("nz_script_prop") + ent:SetModel("models/healthvial.mdl") + ent:SetPos(self:GetPos()) + ent:SetAngles(self:GetAngles()) + ent:Spawn() + v.ent = ent -- Drop the fuse and set the entity to this fuse + self.fuse = k -- ID of this fuse + self:SetEnabled(true) -- Start charging! + gen:SetNWString("NZText", "") + gen:SetNWString("NZHasText", "") + break + end + end + ply:RemoveCarryItem("fuses") + end + end + end + + local tbl = ents.Create("buildable_table") + tbl:AddValidCraft("Zombie Shield", buildabletbl) + tbl:SetPos(Vector(-771, -880, -2)) + tbl:SetAngles(Angle(0,-90,0)) + tbl:Spawn() + + shield1:Reset() + shield2:Reset() + shield3:Reset() + + local fuseholder = ents.Create("nz_script_prop") + fuseholder:SetPos(Vector(592, -478, 230)) + fuseholder:SetAngles(Angle(0,180,0)) + fuseholder:SetModel("models/props_lab/reciever_cart.mdl") + fuseholder:Spawn() + fuseholder.OnUsed = function(self, ply) -- You can temporarily place fuses back here for storage + if ply:HasCarryItem("fuses") or ply:HasCarryItem("chargedfuses") then + for k,v in pairs(validfuses) do + if v.ent == ply then + local ent = ents.Create("nz_script_prop") + ent:SetModel("models/healthvial.mdl") + ent:SetPos(v.pos) + ent:SetAngles(Angle(0,-90,-90)) + ent:Spawn() + v.ent = ent -- Drop the fuse and set the entity to this fuse + if v.done then + chargedfuses:RegisterEntity(ent) + else + fuses:RegisterEntity(ent) + end + break + end + end + ply:RemoveCarryItem("fuses") + ply:RemoveCarryItem("chargedfuses") + end + end + fuseholder:SetNWString("NZHasText", "Press E to place fuse back.") + fuseholder:SetNWString("NZRequiredItem", "chargedfuses") + fuseholder:SetUseType(SIMPLE_USE) + + local finishedcount = 0 + + local finishfuseholder = ents.Create("nz_script_prop") + finishfuseholder:SetPos(Vector(-365, 959, 37)) + finishfuseholder:SetAngles(Angle(0,0,0)) + finishfuseholder:SetModel("models/props_lab/reciever_cart.mdl") + finishfuseholder:Spawn() + finishfuseholder.OnUsed = function(self, ply) -- You can temporarily place fuses back here for storage + if ply:HasCarryItem("chargedfuses") then + for k,v in pairs(validfuses) do + if v.ent == ply and v.done then + local ent = ents.Create("nz_script_prop") + ent:SetModel("models/healthvial.mdl") + ent:SetPos(v.finishpos) + ent:SetAngles(Angle(0,90,90)) + ent:Spawn() + v.ent = ent -- Mark this as the fuse + -- We don't register it, it can no longer be picked up + finishedcount = finishedcount + 1 + break + end + end + ply:RemoveCarryItem("chargedfuses") + end + end + finishfuseholder:SetNWString("NZHasText", "Press E to place charged fuse.") + finishfuseholder:SetNWString("NZRequiredItem", "chargedfuses") + finishfuseholder:SetUseType(SIMPLE_USE) + + local light1 = ents.Create("nz_script_prop") + light1:SetPos(Vector(-418, 974, 46)) + light1:SetAngles(Angle(0,-90, 180)) + light1:SetModel("models/props_c17/light_cagelight02_off.mdl") + light1:Spawn() + + local light2 = ents.Create("nz_script_prop") + light2:SetPos(Vector(-409, 974, 46)) + light2:SetAngles(Angle(0,-90, 180)) + light2:SetModel("models/props_c17/light_cagelight02_off.mdl") + light2:Spawn() + + local light3 = ents.Create("nz_script_prop") + light3:SetPos(Vector(-400, 974, 46)) + light3:SetAngles(Angle(0,-90, 180)) + light3:SetModel("models/props_c17/light_cagelight02_off.mdl") + light3:Spawn() + + local lights = {light1, light2, light3} + + local running = false + local completed = 0 + local maxtime + local nextflip + + local but = ents.Create("nz_script_prop") + but:SetPos(Vector(-406, 946, 32)) + but:SetAngles(Angle(-45,-90, 0)) + but:SetModel("models/props_combine/combinebutton.mdl") + but:Spawn() + but:SetUseType(SIMPLE_USE) + but.OnUsed = function(self, ply) + local light = lights[completed+1] + + if !running and finishedcount > completed then + running = true + light:SetModel("models/props_c17/light_cagelight01_off.mdl") + but:EmitSound("buttons/button3.wav") + local time = CurTime() + 60 -- When it ends + nextflip = CurTime() + math.random(5,10) + + hook.Add("Think", "nzmapscript_EE_ButtonPuzzle", function() + if time < CurTime() then -- We finished the time! + light:SetModel("models/props_c17/light_cagelight02_on.mdl") + but:EmitSound("buttons/button19.wav") + completed = completed + 1 + running = false + if completed == 3 then + nzEE.Major:CompleteStep(1) + end + hook.Remove("Think", "nzmapscript_EE_ButtonPuzzle") + elseif maxtime and maxtime < CurTime() then -- The flip happened more than 3 seconds ago :( + light:SetModel("models/props_c17/light_cagelight02_off.mdl") + but:EmitSound("buttons/combine_button_locked.wav") + running = false + maxtime = nil + hook.Remove("Think", "nzmapscript_EE_ButtonPuzzle") -- This fails it and you need to retry + elseif nextflip and nextflip < CurTime() then -- It's time for a random flip! + light:SetModel("models/props_c17/light_cagelight01_on.mdl") + nextflip = nil + maxtime = CurTime() + 5 + end + end) + elseif running then + if maxtime then -- We hit the button while it was running and you had to hit it! + maxtime = nil + light:SetModel("models/props_c17/light_cagelight01_off.mdl") + but:EmitSound("buttons/combine_button1.wav") + nextflip = CurTime() + math.random(2,15) -- It'll happen again >:D + else -- We pushed when we didn't have to touch it! :( + light:SetModel("models/props_c17/light_cagelight02_off.mdl") + but:EmitSound("buttons/combine_button_locked.wav") + running = false + maxtime = nil + hook.Remove("Think", "nzmapscript_EE_ButtonPuzzle") -- This fails it and you need to retry + end + end + end + + local elight1 = ents.Create("nz_script_prop") + elight1:SetPos(Vector(2110, 20, 225)) + elight1:SetAngles(Angle(-90,180, 180)) + elight1:SetModel("models/props_c17/light_cagelight02_off.mdl") + elight1:Spawn() + + local elight2 = ents.Create("nz_script_prop") + elight2:SetPos(Vector(2110, -8, 225)) + elight2:SetAngles(Angle(-90,180, 180)) + elight2:SetModel("models/props_c17/light_cagelight02_off.mdl") + elight2:Spawn() + + local elight3 = ents.Create("nz_script_prop") + elight3:SetPos(Vector(2110, -36, 225)) + elight3:SetAngles(Angle(-90,180, 180)) + elight3:SetModel("models/props_c17/light_cagelight02_off.mdl") + elight3:Spawn() + + local elight4 = ents.Create("nz_script_prop") + elight4:SetPos(Vector(2110, -64, 225)) + elight4:SetAngles(Angle(-90,180, 180)) + elight4:SetModel("models/props_c17/light_cagelight02_off.mdl") + elight4:Spawn() + + local elights = {elight1, elight2, elight3, elight4} + local elechits = 0 + local elecrunning = false + + local epanel = ents.Create("nz_script_prop") + epanel:SetPos(Vector(2112, -23, 190)) + epanel:SetAngles(Angle(0,0,0)) + epanel:SetModel("models/props_wasteland/panel_leverbase001a.mdl") + epanel:Spawn() + epanel.OnTakeDamage = function(self, dmginfo) + if nzEE.Major.CurrentStep == 2 then + local wep = dmginfo:GetAttacker():GetActiveWeapon() + if IsValid(wep) and wep:GetClass() == "nz_zombieshield" then + if wep:GetElectrified() and elechit then + elechits = elechits + 1 + self:EmitSound("ambient/energy/zap"..math.random(1,9)..".wav") + local light = elights[elechits] + if IsValid(light) then light:SetModel("models/props_c17/light_cagelight02_on.mdl") end + if elechits == 4 then + finalelectric() + elecrunning = nil + elseif elechits < 4 then + elights[elechits+1]:SetModel("models/props_c17/light_cagelight01_on.mdl") + electrify() + end + wep:SetElectrified(false) + end + end + end + end + epanel.OnUsed = function(self, ply) + if nzEE.Major.CurrentStep == 2 and !elecrunning then + self:EmitSound("ambient/levels/labs/electric_explosion4.wav") + electrify() + elecrunning = true + elights[1]:SetModel("models/props_c17/light_cagelight01_on.mdl") + end + end + + local doneforcefields = 0 + local force1 = ents.Create("nz_script_prop") + force1:SetModel("models/props_combine/combine_fence01a.mdl") + force1:SetPos(Vector(1253, -450, 410)) + force1:SetAngles(Angle(0,90,0)) + force1:Spawn() + force1:SetSubMaterial(1, "color") + force1.HasBeenPaPShot = false + force1.OnTakeDamage = function(self, dmginfo) + if !self.HasBeenPaPShot and nzEE.Major.CurrentStep == 3 then + local wep = dmginfo:GetAttacker():GetActiveWeapon() + if IsValid(wep) and wep:HasNZModifier("pap") then + self:SetSubMaterial(1, "color") + doneforcefields = doneforcefields + 1 + self.HasBeenPaPShot = true + self:EmitSound("ambient/machines/thumper_shutdown1.wav", 100) + if doneforcefields == 3 then + nzEE.Major:CompleteStep(3) + end + end + end + end + local force1gen = ents.Create("nz_script_prop") + force1gen:SetPos(Vector(1240, -453, 380)) + force1gen:SetAngles(Angle(0,0,0)) + force1gen:SetModel("models/props_lab/servers.mdl") + force1gen:Spawn() + + local force2 = ents.Create("nz_script_prop") + force2:SetModel("models/props_combine/combine_fence01a.mdl") + force2:SetPos(Vector(-1220, -629, 160)) + force2:SetAngles(Angle(0,0,0)) + force2:Spawn() + force2:SetSubMaterial(1, "color") + force2.HasBeenPaPShot = false + force2.OnTakeDamage = function(self, dmginfo) + if !self.HasBeenPaPShot and nzEE.Major.CurrentStep == 3 then + local wep = dmginfo:GetAttacker():GetActiveWeapon() + if IsValid(wep) and wep:HasNZModifier("pap") then + self:SetSubMaterial(1, "color") + doneforcefields = doneforcefields + 1 + self.HasBeenPaPShot = true + self:EmitSound("ambient/machines/thumper_shutdown1.wav", 100) + if doneforcefields == 3 then + nzEE.Major:CompleteStep(3) + end + end + end + end + local force2gen = ents.Create("nz_script_prop") + force2gen:SetPos(Vector(-1232, -616, 127)) + force2gen:SetAngles(Angle(0,90,0)) + force2gen:SetModel("models/props_lab/servers.mdl") + force2gen:Spawn() + + local force3 = ents.Create("nz_script_prop") + force3:SetModel("models/props_combine/combine_fence01a.mdl") + force3:SetPos(Vector(1651, 1415, 169)) + force3:SetAngles(Angle(0,0,0)) + force3:Spawn() + force3:SetSubMaterial(1, "color") + force3.HasBeenPaPShot = false + force3.OnTakeDamage = function(self, dmginfo) + if !self.HasBeenPaPShot and nzEE.Major.CurrentStep == 3 then + local wep = dmginfo:GetAttacker():GetActiveWeapon() + if IsValid(wep) and wep:HasNZModifier("pap") then + self:SetSubMaterial(1, "color") + doneforcefields = doneforcefields + 1 + self.HasBeenPaPShot = true + self:EmitSound("ambient/machines/thumper_shutdown1.wav", 100) + if doneforcefields == 3 then + nzEE.Major:CompleteStep(3) + end + end + end + end + local force3gen = ents.Create("nz_script_prop") + force3gen:SetPos(Vector(1656, 1428, 128)) + force3gen:SetAngles(Angle(0,90,0)) + force3gen:SetModel("models/props_lab/servers.mdl") + force3gen:Spawn() + + forcefieldgens = {force1, force2, force3} + + for k,v in pairs(validfuses) do + if IsValid(v.ent) and v.ent:GetClass() == "nz_script_prop" then + v.ent:Remove() -- Remove all valid fuses so we can reset + end + v.ent = nil + v.done = false + end + + for k,v in pairs(ents.FindByName("key_case")) do + v:Remove() -- Prevent the key from auto-spawning + end + + for k,v in pairs(ents.FindByName("gate_button_1")) do + v:Remove() -- We don't want players accidentally opening these doors + end + for k,v in pairs(ents.FindByName("gate_button_2")) do + v:Remove() + end + + fuses:Reset() +end + +function mapscript.ScriptUnload() + for k,v in pairs(gen_ents) do + if IsValid(v) then + v:Remove() + end + end + gen_ents = nil +end + +function mapscript.PostCleanupMap() + for k,v in pairs(validfuses) do + if IsValid(v.ent) and v.ent:GetClass() == "nz_script_prop" then + v.ent:Remove() -- Remove all valid fuses so we can reset + end + v.done = false + end +end + +-- Always return the mapscript table. This gives it on to the gamemode so it can use it. +return mapscript diff --git a/lua/nzmapscripts/template.lua b/lua/nzmapscripts/template.lua new file mode 100644 index 00000000..9df0d5dd --- /dev/null +++ b/lua/nzmapscripts/template.lua @@ -0,0 +1,29 @@ +local mapscript = {} + +-- Any function added to this table will automatically get hooked to the hook with the same name +function mapscript.RoundInit() + -- E.g. this function will run with the RoundInit hook + print(mapscript.TestPrint) +end + +-- This one will be called at the start of each round +function mapscript.RoundStart() + +end + +-- Will be called every second if a round is in progress (zombies are alive) +function mapscript.RoundThink() + +end + +-- Will be called after each round +function mapscript.RoundEnd() + +end + +-- Only functions will be hooked, meaning you can safely store data as well +mapscript.TestPrint = "v0.0" +local testprint2 = "This is cool" -- You can also store the data locally + +-- Always return the mapscript table. This gives it on to the gamemode so it can use it. +return mapscript diff --git a/lua/tfa_vox/modules/tfa_vox_nzombies.lua b/lua/tfa_vox/modules/tfa_vox_nzombies.lua new file mode 100644 index 00000000..be4eb747 --- /dev/null +++ b/lua/tfa_vox/modules/tfa_vox_nzombies.lua @@ -0,0 +1,291 @@ +if !MODULE then TFAVOX_Modules_Initialize() return end + +MODULE.name = "nZombies - Perks, Box, Facilities etc." +MODULE.description = "Plays sounds based on nZombies events" +MODULE.author = "Zet0r" +MODULE.realm = "shared" + +hook.Add("TFAVOX_InitializePlayer","TFAVOX_nZombiesIP",function(ply) + if IsValid(ply) then + local mdtbl = TFAVOX_Models[ply:GetModel()] + if mdtbl then + + ply.TFAVOX_Sounds = ply.TFAVOX_Sounds or {} + + if mdtbl.nzombies then + ply.TFAVOX_Sounds['nzombies'] = ply.TFAVOX_Sounds['nzombies'] or {} + ply.TFAVOX_Sounds['nzombies'].perk = mdtbl.nzombies.perk + ply.TFAVOX_Sounds['nzombies'].power = mdtbl.nzombies.power + ply.TFAVOX_Sounds['nzombies'].round = mdtbl.nzombies.round + ply.TFAVOX_Sounds['nzombies'].revive = mdtbl.nzombies.revive + ply.TFAVOX_Sounds['nzombies'].boss = mdtbl.nzombies.boss -- Not implemented yet + ply.TFAVOX_Sounds['nzombies'].powerup = mdtbl.nzombies.powerup + ply.TFAVOX_Sounds['nzombies'].facility = mdtbl.nzombies.facility + end + + end + end + +end) + +hook.Add( "OnPlayerGetPerk", "TFAVOX_nZombies_Perks", function( ply, id, machine ) + timer.Simple(1, function() + if IsValid(ply) and TFAVOX_IsValid(ply) and ply:HasPerk(id) then + if ply.TFAVOX_Sounds and ply.TFAVOX_Sounds.nzombies then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].perk + if sndtbl then + if (not sndtbl[id]) or math.random(0,3) == 0 then id = "generic" end + + if sndtbl[id] then + timer.Simple(0,function() + if IsValid(ply) and ply:HasPerk(id) then + TFAVOX_PlayVoicePriority( ply, sndtbl[id], 0 ) + end + end) + end + end + end + end + end) +end) + +hook.Add( "OnRoundPreparation", "TFAVOX_nZombies_Round", function( round ) + if round and round > 1 then + timer.Simple(3, function() + if nzRound:InProgress() then + local plys = player.GetAllPlayingAndAlive() + local valid = {} + for k,v in pairs(plys) do + if TFAVOX_IsValid(v) and v.TFAVOX_Sounds and v.TFAVOX_Sounds.nzombies and v:GetNotDowned() then + table.insert(valid, v) + end + end + + local ply = table.Random(valid) + if IsValid(ply) then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].round + if sndtbl and sndtbl["prepare"] then + TFAVOX_PlayVoicePriority( ply, sndtbl["prepare"], 0 ) + + -- Play reply 3 seconds later + timer.Simple(3, function() + if nzRound:InProgress() then + local plys = player.GetAllPlayingAndAlive() + local valid = {} + for k,v in pairs(plys) do + if TFAVOX_IsValid(v) and v.TFAVOX_Sounds and v.TFAVOX_Sounds.nzombies and v:GetNotDowned() and v != ply then + table.insert(valid, v) + end + end + + local ply2 = table.Random(valid) + if IsValid(ply2) then + local sndtbl = ply2.TFAVOX_Sounds['nzombies'].round + if sndtbl and sndtbl["preparereply"] then + TFAVOX_PlayVoicePriority( ply2, sndtbl["preparereply"], 0 ) + end + end + end + end) + end + end + end + end) + end +end) + +hook.Add("OnRoundStart", "TFAVOX_nZombies_Round", function( num ) + if nzRound:IsSpecial() then + local plys = player.GetAllPlayingAndAlive() + local valid = {} + for k,v in pairs(plys) do + if TFAVOX_IsValid(v) and v.TFAVOX_Sounds and v.TFAVOX_Sounds.nzombies and v:GetNotDowned() then + table.insert(valid, v) + end + end + + local ply = table.Random(valid) + if IsValid(ply) then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].round + if sndtbl and sndtbl["special"] then + TFAVOX_PlayVoicePriority( ply, sndtbl["special"], 0 ) + end + end + end +end) + +hook.Add( "OnPlayerPickupPowerUp", "TFAVOX_nZombies_Powerups", function( ply, id, ent ) + timer.Simple(2.5, function() + if nzRound:InProgress() then + if IsValid(ply) and TFAVOX_IsValid(ply) then + if ply.TFAVOX_Sounds and ply.TFAVOX_Sounds.nzombies then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].powerup + if sndtbl then + if (not sndtbl[id]) or math.random(0,3) == 0 then id = "generic" end + + if sndtbl[id] then + TFAVOX_PlayVoicePriority( ply, sndtbl[id], 0 ) + end + end + end + end + end + end) +end) + +hook.Add( "PlayerDowned", "TFAVOX_nZombies_Revive", function( ply ) + if IsValid(ply) and TFAVOX_IsValid(ply) then + if ply.TFAVOX_Sounds and ply.TFAVOX_Sounds.nzombies then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].revive + if sndtbl and sndtbl['downed'] then + TFAVOX_PlayVoicePriority( ply, sndtbl['downed'], 0 ) + end + end + end + + timer.Simple(3, function() + local plys = player.GetAllPlayingAndAlive() + local valid = {} + for k,v in pairs(plys) do + if TFAVOX_IsValid(v) and v.TFAVOX_Sounds and v.TFAVOX_Sounds.nzombies and v:GetNotDowned() then + table.insert(valid, v) + end + end + + local ply = table.Random(valid) + if IsValid(ply) then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].revive + if sndtbl and sndtbl["otherdowned"] then + TFAVOX_PlayVoicePriority( ply, sndtbl["otherdowned"], 0 ) + end + end + end) +end) + +hook.Add( "PlayerKilled", "TFAVOX_nZombies_Revive", function( ply ) + local plys = player.GetAllPlayingAndAlive() + local valid = {} + for k,v in pairs(plys) do + if TFAVOX_IsValid(v) and v.TFAVOX_Sounds and v.TFAVOX_Sounds.nzombies and v:GetNotDowned() then + table.insert(valid, v) + end + end + + local ply = table.Random(valid) + if IsValid(ply) then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].revive + if sndtbl and sndtbl["dead"] then + TFAVOX_PlayVoicePriority( ply, sndtbl["dead"], 0 ) + end + end +end) + +hook.Add( "PlayerBeingRevived", "TFAVOX_nZombies_Revive", function( ply, revivor ) + if IsValid(revivor) and TFAVOX_IsValid(revivor) then + if revivor.TFAVOX_Sounds and revivor.TFAVOX_Sounds.nzombies then + local sndtbl = revivor.TFAVOX_Sounds['nzombies'].revive + if sndtbl and sndtbl['reviving'] then + TFAVOX_PlayVoicePriority( revivor, sndtbl['reviving'], 0 ) + end + end + end +end) + +hook.Add( "PlayerRevived", "TFAVOX_nZombies_Revive", function( ply ) + if IsValid(ply) and TFAVOX_IsValid(ply) then + if ply.TFAVOX_Sounds and ply.TFAVOX_Sounds.nzombies then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].revive + if sndtbl and sndtbl['revived'] then + TFAVOX_PlayVoicePriority( ply, sndtbl['revived'], 0 ) + end + end + end +end) + +hook.Add( "ElectricityOn", "TFAVOX_nZombies_Power", function() + timer.Simple(3, function() + if nzRound:InProgress() then + local plys = player.GetAllPlayingAndAlive() + local valid = {} + for k,v in pairs(plys) do + if TFAVOX_IsValid(v) and v.TFAVOX_Sounds and v.TFAVOX_Sounds.nzombies and v:GetNotDowned() then + table.insert(valid, v) + end + end + + local ply = table.Random(valid) + if IsValid(ply) then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].power + if sndtbl and sndtbl["on"] then + TFAVOX_PlayVoicePriority( ply, sndtbl["on"], 0 ) + end + end + end + end) +end) + +hook.Add( "ElectricityOff", "TFAVOX_nZombies_Power", function() + timer.Simple(3, function() + if nzRound:InProgress() then + local plys = player.GetAllPlayingAndAlive() + local valid = {} + for k,v in pairs(plys) do + if TFAVOX_IsValid(v) and v.TFAVOX_Sounds and v.TFAVOX_Sounds.nzombies and v:GetNotDowned() then + table.insert(valid, v) + end + end + + local ply = table.Random(valid) + if IsValid(ply) then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].power + if sndtbl and sndtbl["off"] then + TFAVOX_PlayVoicePriority( ply, sndtbl["off"], 0 ) + end + end + end + end) +end) + +hook.Add( "OnPlayerBuyBox", "TFAVOX_nZombies_Box", function(ply, gun) + if IsValid(ply) and TFAVOX_IsValid(ply) then + if ply.TFAVOX_Sounds and ply.TFAVOX_Sounds.nzombies then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].facility + if sndtbl and sndtbl['randombox'] then + TFAVOX_PlayVoicePriority( ply, sndtbl['randombox'], 0 ) + end + end + end +end) + +hook.Add( "OnPlayerBuyBox", "TFAVOX_nZombies_Box", function(ply, gun) + if IsValid(ply) and TFAVOX_IsValid(ply) then + if ply.TFAVOX_Sounds and ply.TFAVOX_Sounds.nzombies then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].facility + if sndtbl and sndtbl['randombox'] then + TFAVOX_PlayVoicePriority( ply, sndtbl['randombox'], 0 ) + end + end + end +end) + +hook.Add( "OnPlayerBuyWunderfizz", "TFAVOX_nZombies_Wunderfizz", function(ply, perk) + if IsValid(ply) and TFAVOX_IsValid(ply) then + if ply.TFAVOX_Sounds and ply.TFAVOX_Sounds.nzombies then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].facility + if sndtbl and sndtbl['wunderfizz'] then + TFAVOX_PlayVoicePriority( ply, sndtbl['wunderfizz'], 0 ) + end + end + end +end) + +hook.Add( "OnPlayerBuyPackAPunch", "TFAVOX_nZombies_Packapunch", function(ply, gun) + if IsValid(ply) and TFAVOX_IsValid(ply) then + if ply.TFAVOX_Sounds and ply.TFAVOX_Sounds.nzombies then + local sndtbl = ply.TFAVOX_Sounds['nzombies'].facility + if sndtbl and sndtbl['packapunch'] then + TFAVOX_PlayVoicePriority( ply, sndtbl['packapunch'], 0 ) + end + end + end +end) \ No newline at end of file diff --git a/lua/tfa_vox/packs/tfa_vox_nzombies_citizens.lua b/lua/tfa_vox/packs/tfa_vox_nzombies_citizens.lua new file mode 100644 index 00000000..51f00ad1 --- /dev/null +++ b/lua/tfa_vox/packs/tfa_vox_nzombies_citizens.lua @@ -0,0 +1,805 @@ +TFAVOX_Models = TFAVOX_Models or {} + +--[[CONVENIENCE FUNCTIONS, DO NOT EDIT FROM THIS POINT UNTIL CLEAR ]]-- + +local model = "models/player/group01/female01.mdl" + +local tmptbl = string.Split(model,"/") +local mdlprefix = tmptbl[#tmptbl] or model +mdlprefix = string.Replace(mdlprefix,".mdl","") +if model == "models/player/player.mdl" then return end + +--[[CLEAR]]-- + +--[[ +--To give VOX sound paths, I recommend TFAVOX_GenerateSound. +--TFAVOX_GenerateSound( mdlprefix, "sound_event_here", { "path/to/sound1.wav", "path/to/sound2.wav", "path/to/sound3.wav" } +--You may have as many sounds as you want in the GenerateSound table ^^ +--Please have at least one. + +--If you insist on doing things manually, ['sound'] can be a TABLE | { "sound1.wav", "sound2.wav", "sound3.wav" } | or a STRING | "snd" | +--Manual sounds require soundscripts. + +--TFA VOX will now automatically calculate delays. +--If you need to manually override, feed ['delay'] with a TABLE | {min,max} | or a NUMBER | 999 | +]]-- + + + +-- FEMALES +local femaletbl = { + ['perk'] = { -- When you get a perk + ['generic'] = { -- Generic is run if there isn't any voice for the perk bought + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "generic", { + "vo/npc/female01/fantastic01.wav", + "vo/npc/female01/fantastic02.wav", + "vo/npc/female01/yeah02.wav", + "vo/npc/female01/squad_follow03.wav", + "vo/npc/female01/letsgo01.wav", + "vo/npc/female01/letsgo02.wav" + }) + }, + ['jugg'] = { -- Which perk ID. These include custom perks added. + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "jugg", { + "vo/npc/female01/answer37.wav", + "vo/npc/female01/evenodds.wav", + "vo/npc/female01/answer28.wav" + } ) + }, + ['speed'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "speed", { + "vo/npc/female01/gottareload01.wav", + "vo/npc/female01/coverwhilereload01.wav", + "vo/npc/female01/coverwhilereload02.wav" + } ) + }, + ['dtap'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "dtap", { + "vo/npc/female01/answer33.wav", + "vo/npc/female01/answer32.wav" + } ) + }, + ['dtap2'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "dtap2", { + "vo/npc/female01/answer33.wav", + "vo/npc/female01/answer32.wav", + } ) + }, + ['mulekick'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "mulekick", { "vo/npc/female01/answer05.wav" } ) + }, + ['revive'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "revive", { + "vo/npc/female01/answer08.wav", + "vo/npc/female01/answer21.wav", + "vo/npc/female01/answer27.wav" + } ) + }, + ['cherry'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "cherry", { + "vo/npc/female01/vquestion02.wav" + } ) + }, + ['deadshot'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "deadshot", { + "vo/npc/female01/hacks01.wav", + "vo/npc/female01/hacks02.wav", + "vo/npc/female01/thehacks01.wav", + "vo/npc/female01/thehacks02.wav" + } ) + }, + ['phd'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "phd", { + "vo/npc/female01/vanswer13.wav", + "vo/npc/female01/vanswer10.wav" + } ) + }, + ['tombstone'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "tombstone", { + "vo/npc/female01/answer11.wav", + "vo/npc/female01/squad_affirm06.wav", + "vo/npc/female01/squad_affirm05.wav" + } ) + }, + ['whoswho'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "whoswho", { + "vo/npc/female01/vanswer01.wav", + "vo/npc/female01/vanswer03.wav", + "vo/npc/female01/vanswer09.wav" + } ) + }, + ['widowswine'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "widowswine", { + "vo/npc/female01/vanswer07.wav", + "vo/npc/female01/vanswer06.wav", + "vo/npc/female01/vanswer04.wav" + } ) + }, + }, + ['power'] = { + ['on'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "on", { + "vo/npc/female01/finally.wav", + "vo/npc/female01/likethat.wav", + "vo/npc/female01/nice01.wav", + "vo/npc/female01/nice02.wav" + } ) + }, + ['off'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "off", { + "vo/npc/female01/gordead_ans03.wav", + "vo/npc/female01/gordead_ans15.wav", + "vo/npc/female01/gordead_ques01.wav" + } ) + }, + }, + ['revive'] = { + ['downed'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "downed", { + "vo/npc/female01/help01.wav", + "vo/npc/female01/imhurt01.wav", + "vo/npc/female01/imhurt02.wav", + "vo/npc/female01/mygut02.wav", + "vo/npc/female01/myarm01.wav", + "vo/npc/female01/myarm02.wav", + "vo/npc/female01/myleg01.wav", + "vo/npc/female01/myleg02.wav", + } ) + }, + ['otherdowned'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "otherdowned", { + "vo/npc/female01/gordead_ans01.wav", + "vo/npc/female01/gordead_ans02.wav", + "vo/npc/female01/gordead_ans03.wav", + "vo/npc/female01/gordead_ans09.wav", + "vo/npc/female01/gordead_ans15.wav", + "vo/npc/female01/gordead_ans18.wav" + } ) + }, + ['reviving'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "reviving", { + "vo/npc/female01/health05.wav", + "vo/npc/female01/health04.wav", + "vo/npc/female01/health03.wav", + "vo/npc/female01/health02.wav", + "vo/npc/female01/health01.wav" + } ) + }, + ['revived'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "revived", { + "vo/npc/female01/thislldonicely01.wav", + "vo/npc/female01/squad_follow03.wav", + "vo/npc/female01/squad_affirm04.wav", + "vo/streetwar/tunnel/female01/d3_c17_06_post_det04.wav", + "vo/npc/female01/okimready01.wav", + "vo/npc/female01/okimready02.wav", + "vo/npc/female01/okimready03.wav", + }) + }, + ['dead'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "dead", { + "vo/npc/female01/gordead_ques14.wav", + "vo/npc/female01/gordead_ques10.wav", + "vo/npc/female01/gordead_ques07.wav", + "vo/npc/female01/gordead_ques06.wav", + "vo/npc/female01/gordead_ques02.wav", + "vo/npc/female01/gordead_ans20.wav", + "vo/npc/female01/gordead_ans16.wav", + "vo/npc/female01/gordead_ans08.wav", + "vo/npc/female01/gordead_ans07.wav" + } ) + } + }, + ['round'] = { + ['prepare'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "prepare", { + "vo/npc/female01/question01.wav", + "vo/npc/female01/question02.wav", + "vo/npc/female01/question03.wav", + "vo/npc/female01/question04.wav", + "vo/npc/female01/question05.wav", + "vo/npc/female01/question07.wav", + "vo/npc/female01/question12.wav", + "vo/npc/female01/question13.wav", + "vo/npc/female01/question17.wav", + "vo/npc/female01/question18.wav", + "vo/npc/female01/question19.wav", + "vo/npc/female01/question20.wav", + "vo/npc/female01/question21.wav", + "vo/npc/female01/question23.wav", + "vo/npc/female01/question25.wav", + "vo/npc/female01/question29.wav", + "vo/npc/female01/likethat.wav" + }) + }, + ['preparereply'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "preparereply", { + "vo/npc/female01/answer01.wav", + "vo/npc/female01/answer02.wav", + "vo/npc/female01/answer03.wav", + "vo/npc/female01/answer04.wav", + "vo/npc/female01/answer05.wav", + "vo/npc/female01/answer06.wav", + "vo/npc/female01/answer07.wav", + "vo/npc/female01/answer08.wav", + "vo/npc/female01/answer09.wav", + "vo/npc/female01/answer10.wav", + "vo/npc/female01/answer11.wav", + "vo/npc/female01/answer12.wav", + "vo/npc/female01/answer13.wav", + "vo/npc/female01/answer14.wav", + "vo/npc/female01/answer15.wav", + "vo/npc/female01/answer16.wav", + "vo/npc/female01/answer17.wav", + "vo/npc/female01/answer18.wav", + "vo/npc/female01/answer19.wav", + "vo/npc/female01/answer20.wav", + "vo/npc/female01/answer21.wav", + "vo/npc/female01/answer22.wav", + "vo/npc/female01/answer23.wav", + "vo/npc/female01/answer24.wav", + "vo/npc/female01/answer25.wav", + "vo/npc/female01/answer26.wav", + "vo/npc/female01/answer27.wav", + "vo/npc/female01/answer28.wav", + "vo/npc/female01/answer29.wav", + "vo/npc/female01/answer30.wav", + "vo/npc/female01/answer31.wav", + "vo/npc/female01/answer32.wav", + "vo/npc/female01/answer33.wav", + "vo/npc/female01/answer34.wav", + "vo/npc/female01/answer35.wav", + "vo/npc/female01/answer36.wav", + "vo/npc/female01/answer37.wav", + "vo/npc/female01/answer38.wav", + "vo/npc/female01/answer39.wav", + "vo/npc/female01/answer40.wav", + + }) + }, + ['special'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "special", { + "vo/npc/female01/question11.wav", + "vo/npc/female01/question16.wav", + "vo/npc/female01/uhoh.wav", + "vo/npc/female01/youdbetterreload01.wav", + "vo/npc/female01/okimready01.wav", + "vo/npc/female01/okimready02.wav", + "vo/npc/female01/okimready03.wav", + "vo/npc/female01/ohno.wav", + "vo/npc/female01/incoming02.wav", + "vo/npc/female01/holddownspot01.wav", + "vo/npc/female01/holddownspot02.wav", + "vo/npc/female01/heretheycome01.wav", + "vo/npc/female01/headsup01.wav", + "vo/npc/female01/headsup02.wav" + }) + } + }, + ['powerup'] = { + ['generic'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "generic", { + "vo/coast/odessa/female01/nlo_cheer01.wav", + "vo/coast/odessa/female01/nlo_cheer02.wav", + "vo/coast/odessa/female01/nlo_cheer03.wav" + } ) + }, + ['maxammo'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "maxammo", { + "vo/npc/female01/ammo03.wav", + "vo/npc/female01/ammo04.wav", + "vo/npc/female01/ammo05.wav", + "vo/npc/female01/gottareload01.wav", + "vo/npc/female01/youdbetterreload01.wav" + } ) + }, + ['carpenter'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "carpenter", { + "vo/trainyard/female01/cit_window_use01.wav", + "vo/trainyard/female01/cit_window_use02.wav", + "vo/trainyard/female01/cit_window_use03.wav", + "vo/trainyard/female01/cit_window_use04.wav", + "vo/canals/female01/gunboat_moveon.wav" + }) + } + }, + ['facility'] = { + ['randombox'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "randombox", { + "vo/npc/female01/question06.wav", + "vo/npc/female01/question07.wav", + "vo/npc/female01/question08.wav", + "vo/npc/female01/question09.wav", + "vo/npc/female01/question14.wav", + "vo/npc/female01/question16.wav", + "vo/npc/female01/question17.wav", + "vo/npc/female01/question21.wav", + "vo/npc/female01/question26.wav", + "vo/npc/female01/question28.wav", + "vo/npc/female01/question31.wav", + "vo/npc/female01/squad_affirm05.wav", + "vo/npc/female01/squad_affirm06.wav", + "vo/npc/female01/waitingsomebody.wav", + }) + }, + ['packapunch'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "packapunch", { + "vo/streetwar/tunnel/female01/c17_06_det02.wav", + "vo/npc/female01/answer29.wav", + "vo/npc/female01/answer33.wav", + "vo/npc/female01/busy02.wav", + "vo/npc/female01/doingsomething.wav", + "vo/npc/female01/evenodds.wav", + "vo/npc/female01/holddownspot01.wav", + "vo/npc/female01/holddownspot02.wav", + "vo/npc/female01/illstayhere.wav", + "vo/npc/female01/imstickinghere01.wav", + "vo/npc/female01/letsgo02.wav", + "vo/npc/female01/letsgo01.wav", + "vo/npc/female01/littlecorner01.wav", + "vo/npc/female01/readywhenyouare01.wav", + "vo/npc/female01/readywhenyouare02.wav", + "vo/npc/female01/waitingsomebody.wav", + "vo/npc/female01/zombies02.wav", + }) + }, + ['wunderfizz'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "wunderfizz", { + "vo/npc/female01/question06.wav", + "vo/npc/female01/question07.wav", + "vo/npc/female01/question08.wav", + "vo/npc/female01/question09.wav", + "vo/npc/female01/question14.wav", + "vo/npc/female01/question16.wav", + "vo/npc/female01/question17.wav", + "vo/npc/female01/question21.wav", + "vo/npc/female01/question26.wav", + "vo/npc/female01/question28.wav", + "vo/npc/female01/question31.wav", + "vo/npc/female01/squad_affirm05.wav", + "vo/npc/female01/squad_affirm06.wav", + "vo/npc/female01/waitingsomebody.wav", + }) + }, + } +} + +model = "models/player/group01/male01.mdl" + +tmptbl = string.Split(model,"/") +mdlprefix = tmptbl[#tmptbl] or model +mdlprefix = string.Replace(mdlprefix,".mdl","") + +-- MALES +local maletbl = { + ['perk'] = { -- When you get a perk + ['generic'] = { -- Generic is run if there isn't any voice for the perk bought + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "generic", { + "vo/npc/male01/fantastic01.wav", + "vo/npc/male01/fantastic02.wav", + "vo/npc/male01/oneforme.wav", + "vo/npc/male01/yeah02.wav", + "vo/npc/male01/squad_follow03.wav", + "vo/npc/male01/letsgo01.wav", + "vo/npc/male01/letsgo02.wav" + }) + }, + ['jugg'] = { -- Which perk ID. These include custom perks added. + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "jugg", { + "vo/npc/male01/answer36.wav", + "vo/npc/male01/evenodds.wav", + "vo/npc/male01/answer28.wav" + } ) + }, + ['speed'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "speed", { + "vo/npc/male01/gottareload01.wav", + "vo/npc/male01/coverwhilereload01.wav", + "vo/npc/male01/coverwhilereload02.wav" + } ) + }, + ['dtap'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "dtap", { + "vo/npc/male01/answer33.wav", + "vo/npc/male01/answer32.wav" + } ) + }, + ['dtap2'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "dtap2", { + "vo/npc/male01/answer33.wav", + "vo/npc/male01/answer32.wav", + } ) + }, + ['mulekick'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "mulekick", { "vo/npc/male01/answer05.wav" } ) + }, + ['revive'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "revive", { + "vo/npc/male01/answer08.wav", + "vo/npc/male01/answer21.wav", + "vo/npc/male01/answer27.wav" + } ) + }, + ['cherry'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "cherry", { + "vo/npc/male01/vquestion02.wav" + } ) + }, + ['deadshot'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "deadshot", { + "vo/npc/male01/hacks01.wav", + "vo/npc/male01/hacks02.wav", + "vo/npc/male01/thehacks01.wav", + "vo/npc/male01/thehacks02.wav" + } ) + }, + ['phd'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "phd", { + "vo/npc/male01/vanswer13.wav", + "vo/npc/male01/vanswer10.wav" + } ) + }, + ['tombstone'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "tombstone", { + "vo/npc/male01/answer11.wav", + "vo/npc/male01/squad_affirm06.wav", + "vo/npc/male01/squad_affirm05.wav" + } ) + }, + ['whoswho'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "whoswho", { + "vo/npc/male01/vanswer01.wav", + "vo/npc/male01/vanswer03.wav", + "vo/npc/male01/vanswer09.wav" + } ) + }, + ['widowswine'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "widowswine", { + "vo/npc/male01/vanswer07.wav", + "vo/npc/male01/vanswer06.wav", + "vo/npc/male01/vanswer04.wav" + } ) + }, + }, + ['power'] = { + ['on'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "on", { + "vo/npc/male01/finally.wav", + "vo/npc/male01/likethat.wav", + "vo/npc/male01/nice.wav" + } ) + }, + ['off'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "off", { + "vo/npc/male01/gordead_ans03.wav", + "vo/npc/male01/gordead_ans15.wav", + "vo/npc/male01/gordead_ques16.wav" + } ) + }, + }, + ['revive'] = { + ['downed'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "downed", { + "vo/npc/male01/help01.wav", + "vo/npc/male01/imhurt01.wav", + "vo/npc/male01/mygut02.wav", + "vo/npc/male01/myarm01.wav", + "vo/npc/male01/myleg01.wav", + "vo/npc/male01/myleg02.wav", + "vo/streetwar/sniper/male01/c17_09_help01.wav", + "vo/streetwar/sniper/male01/c17_09_help02.wav", + "vo/streetwar/sniper/male01/c17_09_help03.wav", + } ) + }, + ['otherdowned'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "otherdowned", { + "vo/npc/male01/gordead_ans01.wav", + "vo/npc/male01/gordead_ans02.wav", + "vo/npc/male01/gordead_ans03.wav", + "vo/npc/male01/gordead_ans09.wav", + "vo/npc/male01/gordead_ans15.wav", + "vo/npc/male01/gordead_ans18.wav" + } ) + }, + ['reviving'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "reviving", { + "vo/npc/male01/health05.wav", + "vo/npc/male01/health04.wav", + "vo/npc/male01/health03.wav", + "vo/npc/male01/health02.wav", + "vo/npc/male01/health01.wav" + } ) + }, + ['revived'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "revived", { + "vo/npc/male01/thislldonicely01.wav", + "vo/npc/male01/squad_follow03.wav", + "vo/npc/male01/squad_affirm04.wav", + "vo/coast/barn/male01/youmadeit.wav", + "vo/streetwar/tunnel/male01/d3_c17_06_post_det04.wav", + }) + }, + ['dead'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "dead", { + "vo/npc/male01/gordead_ques14.wav", + "vo/npc/male01/gordead_ques10.wav", + "vo/npc/male01/gordead_ques07.wav", + "vo/npc/male01/gordead_ques06.wav", + "vo/npc/male01/gordead_ques02.wav", + "vo/npc/male01/gordead_ans20.wav", + "vo/npc/male01/gordead_ans16.wav", + "vo/npc/male01/gordead_ans08.wav", + "vo/npc/male01/gordead_ans07.wav" + } ) + } + }, + ['round'] = { + ['prepare'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "prepare", { + "vo/npc/male01/question01.wav", + "vo/npc/male01/question02.wav", + "vo/npc/male01/question03.wav", + "vo/npc/male01/question04.wav", + "vo/npc/male01/question07.wav", + "vo/npc/male01/question12.wav", + "vo/npc/male01/question13.wav", + "vo/npc/male01/question17.wav", + "vo/npc/male01/question18.wav", + "vo/npc/male01/question19.wav", + "vo/npc/male01/question20.wav", + "vo/npc/male01/question21.wav", + "vo/npc/male01/question23.wav", + "vo/npc/male01/question25.wav", + "vo/npc/male01/question29.wav", + "vo/npc/male01/question31.wav", + "vo/npc/male01/likethat.wav" + }) + }, + ['preparereply'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "preparereply", { + "vo/npc/male01/answer01.wav", + "vo/npc/male01/answer02.wav", + "vo/npc/male01/answer03.wav", + "vo/npc/male01/answer04.wav", + "vo/npc/male01/answer05.wav", + "vo/npc/male01/answer06.wav", + "vo/npc/male01/answer07.wav", + "vo/npc/male01/answer08.wav", + "vo/npc/male01/answer09.wav", + "vo/npc/male01/answer10.wav", + "vo/npc/male01/answer11.wav", + "vo/npc/male01/answer12.wav", + "vo/npc/male01/answer13.wav", + "vo/npc/male01/answer14.wav", + "vo/npc/male01/answer15.wav", + "vo/npc/male01/answer16.wav", + "vo/npc/male01/answer17.wav", + "vo/npc/male01/answer18.wav", + "vo/npc/male01/answer19.wav", + "vo/npc/male01/answer20.wav", + "vo/npc/male01/answer21.wav", + "vo/npc/male01/answer22.wav", + "vo/npc/male01/answer23.wav", + "vo/npc/male01/answer24.wav", + "vo/npc/male01/answer25.wav", + "vo/npc/male01/answer26.wav", + "vo/npc/male01/answer27.wav", + "vo/npc/male01/answer28.wav", + "vo/npc/male01/answer29.wav", + "vo/npc/male01/answer30.wav", + "vo/npc/male01/answer31.wav", + "vo/npc/male01/answer32.wav", + "vo/npc/male01/answer33.wav", + "vo/npc/male01/answer34.wav", + "vo/npc/male01/answer35.wav", + "vo/npc/male01/answer36.wav", + "vo/npc/male01/answer37.wav", + "vo/npc/male01/answer38.wav", + "vo/npc/male01/answer39.wav", + "vo/npc/male01/answer40.wav", + }) + }, + ['special'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "special", { + "vo/npc/male01/question11.wav", + "vo/npc/male01/question16.wav", + "vo/npc/male01/uhoh.wav", + "vo/npc/male01/youdbetterreload01.wav", + "vo/npc/male01/okimready01.wav", + "vo/npc/male01/okimready02.wav", + "vo/npc/male01/okimready03.wav", + "vo/npc/male01/ohno.wav", + "vo/npc/male01/incoming02.wav", + "vo/npc/male01/holddownspot01.wav", + "vo/npc/male01/holddownspot02.wav", + "vo/npc/male01/heretheycome01.wav", + "vo/npc/male01/headsup01.wav", + "vo/npc/male01/headsup02.wav" + }) + } + }, + ['powerup'] = { + ['generic'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "generic", { + "vo/coast/odessa/male01/nlo_cheer01.wav", + "vo/coast/odessa/male01/nlo_cheer02.wav", + "vo/coast/odessa/male01/nlo_cheer03.wav", + "vo/coast/odessa/male01/nlo_cheer04.wav" + } ) + }, + ['maxammo'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "maxammo", { + "vo/npc/male01/ammo03.wav", + "vo/npc/male01/ammo04.wav", + "vo/npc/male01/ammo05.wav", + "vo/npc/male01/gottareload01.wav", + "vo/npc/male01/youdbetterreload01.wav" + } ) + }, + ['carpenter'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "carpenter", { + "vo/trainyard/male01/cit_window_use01.wav", + "vo/trainyard/male01/cit_window_use02.wav", + "vo/trainyard/male01/cit_window_use03.wav", + "vo/trainyard/male01/cit_window_use04.wav", + "vo/canals/male01/gunboat_moveon.wav" + }) + } + }, + ['facility'] = { + ['randombox'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "randombox", { + "vo/npc/male01/question06.wav", + "vo/npc/male01/question07.wav", + "vo/npc/male01/question08.wav", + "vo/npc/male01/question09.wav", + "vo/npc/male01/question14.wav", + "vo/npc/male01/question16.wav", + "vo/npc/male01/question17.wav", + "vo/npc/male01/question21.wav", + "vo/npc/male01/question26.wav", + "vo/npc/male01/question28.wav", + "vo/npc/male01/question31.wav", + "vo/npc/male01/squad_affirm05.wav", + "vo/npc/male01/squad_affirm06.wav", + "vo/npc/male01/waitingsomebody.wav", + }) + }, + ['packapunch'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "packapunch", { + "vo/streetwar/tunnel/male01/c17_06_det02.wav", + "vo/npc/male01/answer29.wav", + "vo/npc/male01/answer33.wav", + "vo/npc/male01/busy02.wav", + "vo/npc/male01/doingsomething.wav", + "vo/npc/male01/evenodds.wav", + "vo/npc/male01/holddownspot01.wav", + "vo/npc/male01/holddownspot02.wav", + "vo/npc/male01/illstayhere.wav", + "vo/npc/male01/imstickinghere01.wav", + "vo/npc/male01/letsgo02.wav", + "vo/npc/male01/letsgo01.wav", + "vo/npc/male01/littlecorner01.wav", + "vo/npc/male01/readywhenyouare01.wav", + "vo/npc/male01/readywhenyouare02.wav", + "vo/npc/male01/waitingsomebody.wav", + "vo/npc/male01/zombies02.wav", + }) + }, + ['wunderfizz'] = { + ['delay'] = nil, + ['sound'] = TFAVOX_GenerateSound( mdlprefix, "wunderfizz", { + "vo/npc/male01/question06.wav", + "vo/npc/male01/question07.wav", + "vo/npc/male01/question08.wav", + "vo/npc/male01/question09.wav", + "vo/npc/male01/question14.wav", + "vo/npc/male01/question16.wav", + "vo/npc/male01/question17.wav", + "vo/npc/male01/question21.wav", + "vo/npc/male01/question26.wav", + "vo/npc/male01/question28.wav", + "vo/npc/male01/question31.wav", + "vo/npc/male01/squad_affirm05.wav", + "vo/npc/male01/squad_affirm06.wav", + "vo/npc/male01/waitingsomebody.wav", + }) + }, + } +} + +local function inject(model, tbl) + -- Inject into any already existant model tables + if not TFAVOX_Models[model] then TFAVOX_Models[model] = {} end + TFAVOX_Models[model].nzombies = tbl +end + +-- Inject into all male citizen models +for i = 1, 9 do + local mdl = "models/player/group01/male_0"..i..".mdl" + inject(mdl, maletbl) +end +for i = 10, 18 do + local mdl = "models/player/group01/male_"..i..".mdl" + inject(mdl, maletbl) +end +for i = 1, 9 do + local mdl = "models/player/group01/medic_0"..i..".mdl" + inject(mdl, maletbl) +end +for i = 1, 4 do + local mdl = "models/player/group01/refugee_0"..i..".mdl" + inject(mdl, maletbl) +end + +-- Inject into all female citizen models +for i = 1, 9 do + local mdl = "models/player/group01/female_0"..i..".mdl" + inject(mdl, femaletbl) +end +for i = 10, 12 do + local mdl = "models/player/group01/female_"..i..".mdl" + inject(mdl, femaletbl) +end +for i = 10, 15 do + local mdl = "models/player/group01/medic_"..i..".mdl" + inject(mdl, femaletbl) +end + diff --git a/maps/ttt_casino_b2.nav b/maps/ttt_casino_b2.nav new file mode 100644 index 00000000..979e02e9 Binary files /dev/null and b/maps/ttt_casino_b2.nav differ diff --git a/maps/ttt_kosovos.nav b/maps/ttt_kosovos.nav new file mode 100644 index 00000000..862a80fc Binary files /dev/null and b/maps/ttt_kosovos.nav differ diff --git a/maps/zs_obj_station.nav b/maps/zs_obj_station.nav new file mode 100644 index 00000000..35e1389d Binary files /dev/null and b/maps/zs_obj_station.nav differ diff --git a/materials/nzmapicons/nz_ttt_casino_b2;High Stakes.png b/materials/nzmapicons/nz_ttt_casino_b2;High Stakes.png new file mode 100644 index 00000000..cbb09ba9 Binary files /dev/null and b/materials/nzmapicons/nz_ttt_casino_b2;High Stakes.png differ diff --git a/materials/nzmapicons/nz_ttt_kosovos;Breakout.png b/materials/nzmapicons/nz_ttt_kosovos;Breakout.png new file mode 100644 index 00000000..dd484774 Binary files /dev/null and b/materials/nzmapicons/nz_ttt_kosovos;Breakout.png differ diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap.vmt b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap.vmt deleted file mode 100644 index 46c5d50d..00000000 --- a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/doubletap/Doubletap" - "$surfaceprop" "Metal" - "$nocull" 1 - "$alphatest" "1" -} diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap.vtf b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap.vtf deleted file mode 100644 index 37d0dde3..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_off.vmt b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_off.vmt deleted file mode 100644 index d7b852c4..00000000 --- a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_off.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/doubletap/Doubletap" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_on.vmt b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_on.vmt deleted file mode 100644 index 9d9bf454..00000000 --- a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_on.vmt +++ /dev/null @@ -1,5 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/doubletap/Doubletap" - "$selfillum" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_phong.vtf b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_phong.vtf deleted file mode 100644 index df584bcd..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_phong.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price.vmt b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price.vmt deleted file mode 100644 index 79975557..00000000 --- a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/doubletap/Doubletap_Price" - "$surfaceprop" "Metal" - "$nocull" 1 - "$alphatest" "1" -} diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price.vtf b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price.vtf deleted file mode 100644 index 97c92093..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price_off.vmt b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price_off.vmt deleted file mode 100644 index 1812c8b8..00000000 --- a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price_off.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/doubletap/Doubletap_price" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price_on.vmt b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price_on.vmt deleted file mode 100644 index 018a5c64..00000000 --- a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_price_on.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/doubletap/Doubletap_price" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 - "$selfillummask" "models/alig96/perks/doubletap/white" -} diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn.vmt b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn.vmt deleted file mode 100644 index 689c9bd6..00000000 --- a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/doubletap/Doubletap_SNN" - "$bumpmap" "models/alig96/perks/doubletap/Doubletap_SNN_NRM" - "$surfaceprop" "Metal" - "$alphatest" 1 - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn.vtf b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn.vtf deleted file mode 100644 index b02a6418..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_nrm.vtf b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_nrm.vtf deleted file mode 100644 index 58131b1f..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_nrm.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_off.vmt b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_off.vmt deleted file mode 100644 index 3bfa4043..00000000 --- a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_off.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/doubletap/Doubletap_SNN" - "$bumpmap" "models/alig96/perks/doubletap/Doubletap_SNN_NRM" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_on.vmt b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_on.vmt deleted file mode 100644 index 06dc9265..00000000 --- a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_on.vmt +++ /dev/null @@ -1,9 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/doubletap/Doubletap_SNN" - "$bumpmap" "models/alig96/perks/doubletap/Doubletap_SNN_NRM" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 - "$selfillummask" "models/alig96/perks/doubletap/white" -} diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_phong.vtf b/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_phong.vtf deleted file mode 100644 index b60a6580..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/doubletap/doubletap_snn_phong.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/power_off.vmt b/nzombies3/content/materials/models/alig96/perks/doubletap/power_off.vmt deleted file mode 100644 index 4636402a..00000000 --- a/nzombies3/content/materials/models/alig96/perks/doubletap/power_off.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/doubletap/Power_Off" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/power_off.vtf b/nzombies3/content/materials/models/alig96/perks/doubletap/power_off.vtf deleted file mode 100644 index 928366a9..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/doubletap/power_off.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/power_on.vmt b/nzombies3/content/materials/models/alig96/perks/doubletap/power_on.vmt deleted file mode 100644 index 1f86c92a..00000000 --- a/nzombies3/content/materials/models/alig96/perks/doubletap/power_on.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/doubletap/Power_On" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/power_on.vtf b/nzombies3/content/materials/models/alig96/perks/doubletap/power_on.vtf deleted file mode 100644 index 5e05a60d..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/doubletap/power_on.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/doubletap/white.vtf b/nzombies3/content/materials/models/alig96/perks/doubletap/white.vtf deleted file mode 100644 index b847bc06..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/doubletap/white.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg.vmt b/nzombies3/content/materials/models/alig96/perks/jugg/jugg.vmt deleted file mode 100644 index 05cf4d3d..00000000 --- a/nzombies3/content/materials/models/alig96/perks/jugg/jugg.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/jugg/Jugg" - "$surfaceprop" "Metal" - "$alphatest" 1 - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg.vtf b/nzombies3/content/materials/models/alig96/perks/jugg/jugg.vtf deleted file mode 100644 index 7dd210ee..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/jugg/jugg.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_nrm.vtf b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_nrm.vtf deleted file mode 100644 index 0a214a33..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_nrm.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_off.vmt b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_off.vmt deleted file mode 100644 index e102faa0..00000000 --- a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_off.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/jugg/Jugg" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_on.vmt b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_on.vmt deleted file mode 100644 index 5b4432df..00000000 --- a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_on.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/jugg/Jugg" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 - "$selfillummask" "models/alig96/perks/jugg/white" -} diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_phong.vtf b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_phong.vtf deleted file mode 100644 index 6040ca92..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_phong.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price.vmt b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price.vmt deleted file mode 100644 index 90ba080d..00000000 --- a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/jugg/Jugg_price" - "$surfaceprop" "Metal" - "$alphatest" 1 - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price.vtf b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price.vtf deleted file mode 100644 index d7dccc16..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price_off.vmt b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price_off.vmt deleted file mode 100644 index 3c909a03..00000000 --- a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price_off.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/jugg/Jugg_price" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price_on.vmt b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price_on.vmt deleted file mode 100644 index 459806b0..00000000 --- a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_price_on.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/jugg/Jugg_price" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 - "$selfillummask" "models/alig96/perks/jugg/white" -} diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn.vmt b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn.vmt deleted file mode 100644 index af30fafd..00000000 --- a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/jugg/Jugg_SNN" - "$bumpmap" "models/alig96/perks/jugg/Jugg_SNN_NRM" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn.vtf b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn.vtf deleted file mode 100644 index 590282f7..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_nrm.vtf b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_nrm.vtf deleted file mode 100644 index 9bdc7695..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_nrm.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_off.vmt b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_off.vmt deleted file mode 100644 index af30fafd..00000000 --- a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_off.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/jugg/Jugg_SNN" - "$bumpmap" "models/alig96/perks/jugg/Jugg_SNN_NRM" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_on.vmt b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_on.vmt deleted file mode 100644 index 1bcf587f..00000000 --- a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_on.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/jugg/Jugg_SNN" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 - "$selfillummask" "models/alig96/perks/jugg/white" -} diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_phong.vtf b/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_phong.vtf deleted file mode 100644 index 057c0c3a..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/jugg/jugg_snn_phong.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/power_off.vmt b/nzombies3/content/materials/models/alig96/perks/jugg/power_off.vmt deleted file mode 100644 index fffd7927..00000000 --- a/nzombies3/content/materials/models/alig96/perks/jugg/power_off.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/jugg/Power_Off" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/power_off.vtf b/nzombies3/content/materials/models/alig96/perks/jugg/power_off.vtf deleted file mode 100644 index 928366a9..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/jugg/power_off.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/power_on.vmt b/nzombies3/content/materials/models/alig96/perks/jugg/power_on.vmt deleted file mode 100644 index 14e2cd7d..00000000 --- a/nzombies3/content/materials/models/alig96/perks/jugg/power_on.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/jugg/Power_On" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/power_on.vtf b/nzombies3/content/materials/models/alig96/perks/jugg/power_on.vtf deleted file mode 100644 index 5e05a60d..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/jugg/power_on.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/jugg/white.vtf b/nzombies3/content/materials/models/alig96/perks/jugg/white.vtf deleted file mode 100644 index b847bc06..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/jugg/white.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_c.vmt b/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_c.vmt deleted file mode 100644 index cc02989d..00000000 --- a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_c.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/packapunch/pack_a_punch_c" - "$normalmap" "models/alig96/perks/packapunch/pack_a_punch_c" - "$surfaceprop" "Metal" -} diff --git a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_c.vtf b/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_c.vtf deleted file mode 100644 index 2415806d..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_c.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_moving_c.vmt b/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_moving_c.vmt deleted file mode 100644 index d2598bc8..00000000 --- a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_moving_c.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/packapunch/pack_a_punch_moving_c" - "$normalmap" "models/alig96/perks/packapunch/pack_a_punch_moving_n" - "$surfaceprop" "Metal" -} diff --git a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_moving_c.vtf b/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_moving_c.vtf deleted file mode 100644 index 0cc696d7..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_moving_c.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_moving_n.vtf b/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_moving_n.vtf deleted file mode 100644 index 68d577ba..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_moving_n.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_n.vtf b/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_n.vtf deleted file mode 100644 index cf9ed621..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/packapunch/pack_a_punch_n.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/readme.txt b/nzombies3/content/materials/models/alig96/perks/readme.txt deleted file mode 100644 index c0801c50..00000000 --- a/nzombies3/content/materials/models/alig96/perks/readme.txt +++ /dev/null @@ -1,3 +0,0 @@ -Models by Beat the Zombie - -Recompiled by Alig96 so everything is in a nice folder. \ No newline at end of file diff --git a/nzombies3/content/materials/models/alig96/perks/revive/power_off.vmt b/nzombies3/content/materials/models/alig96/perks/revive/power_off.vmt deleted file mode 100644 index 32580cfe..00000000 --- a/nzombies3/content/materials/models/alig96/perks/revive/power_off.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/revive/Power_Off" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/revive/power_off.vtf b/nzombies3/content/materials/models/alig96/perks/revive/power_off.vtf deleted file mode 100644 index 928366a9..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/power_off.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/power_on.vmt b/nzombies3/content/materials/models/alig96/perks/revive/power_on.vmt deleted file mode 100644 index 237c3d1b..00000000 --- a/nzombies3/content/materials/models/alig96/perks/revive/power_on.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/revive/Power_On" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/revive/power_on.vtf b/nzombies3/content/materials/models/alig96/perks/revive/power_on.vtf deleted file mode 100644 index 5e05a60d..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/power_on.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revive.vmt b/nzombies3/content/materials/models/alig96/perks/revive/revive.vmt deleted file mode 100644 index 45199a7a..00000000 --- a/nzombies3/content/materials/models/alig96/perks/revive/revive.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/revive/Revive" - "$bumpmap" "models/alig96/perks/revive/Revive_NRM" - "$surfaceprop" "Metal" - "$alphatest" 1 - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revive.vtf b/nzombies3/content/materials/models/alig96/perks/revive/revive.vtf deleted file mode 100644 index 00379310..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/revive.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revive_nrm.vtf b/nzombies3/content/materials/models/alig96/perks/revive/revive_nrm.vtf deleted file mode 100644 index e4d89d06..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/revive_nrm.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revive_phong.vtf b/nzombies3/content/materials/models/alig96/perks/revive/revive_phong.vtf deleted file mode 100644 index c3ab70c8..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/revive_phong.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revive_price.vmt b/nzombies3/content/materials/models/alig96/perks/revive/revive_price.vmt deleted file mode 100644 index 772b677b..00000000 --- a/nzombies3/content/materials/models/alig96/perks/revive/revive_price.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/revive/Revive_price" - "$bumpmap" "models/alig96/perks/revive/Revive_NRM" - "$surfaceprop" "Metal" - "$alphatest" 1 - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revive_price.vtf b/nzombies3/content/materials/models/alig96/perks/revive/revive_price.vtf deleted file mode 100644 index f88af4a6..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/revive_price.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revive_snn.vmt b/nzombies3/content/materials/models/alig96/perks/revive/revive_snn.vmt deleted file mode 100644 index 3e16f7be..00000000 --- a/nzombies3/content/materials/models/alig96/perks/revive/revive_snn.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/revive/Revive_SNN" - "$bumpmap" "models/alig96/perks/revive/Revive_SNN_NRM" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revive_snn.vtf b/nzombies3/content/materials/models/alig96/perks/revive/revive_snn.vtf deleted file mode 100644 index 748f1b07..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/revive_snn.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revive_snn_nrm.vtf b/nzombies3/content/materials/models/alig96/perks/revive/revive_snn_nrm.vtf deleted file mode 100644 index e8b8a312..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/revive_snn_nrm.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revive_snn_phong.vtf b/nzombies3/content/materials/models/alig96/perks/revive/revive_snn_phong.vtf deleted file mode 100644 index c992333c..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/revive_snn_phong.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revivesign.vmt b/nzombies3/content/materials/models/alig96/perks/revive/revivesign.vmt deleted file mode 100644 index b4ffa04d..00000000 --- a/nzombies3/content/materials/models/alig96/perks/revive/revivesign.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/revive/Revivesign" - "$bumpmap" "models/alig96/perks/revive/Revivesign_NRM" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revivesign.vtf b/nzombies3/content/materials/models/alig96/perks/revive/revivesign.vtf deleted file mode 100644 index ae1915cb..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/revivesign.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revivesign_nrm.vtf b/nzombies3/content/materials/models/alig96/perks/revive/revivesign_nrm.vtf deleted file mode 100644 index 94fac285..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/revivesign_nrm.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revivesign_off.vmt b/nzombies3/content/materials/models/alig96/perks/revive/revivesign_off.vmt deleted file mode 100644 index b4ffa04d..00000000 --- a/nzombies3/content/materials/models/alig96/perks/revive/revivesign_off.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/revive/Revivesign" - "$bumpmap" "models/alig96/perks/revive/Revivesign_NRM" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revivesign_on.vmt b/nzombies3/content/materials/models/alig96/perks/revive/revivesign_on.vmt deleted file mode 100644 index 86e3c8e2..00000000 --- a/nzombies3/content/materials/models/alig96/perks/revive/revivesign_on.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/revive/Revivesign" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 - "$selfillummask" "models/alig96/perks/revive/white" -} diff --git a/nzombies3/content/materials/models/alig96/perks/revive/revivesign_phong.vtf b/nzombies3/content/materials/models/alig96/perks/revive/revivesign_phong.vtf deleted file mode 100644 index 8d8191ba..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/revivesign_phong.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/revive/white.vtf b/nzombies3/content/materials/models/alig96/perks/revive/white.vtf deleted file mode 100644 index b847bc06..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/revive/white.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_drips.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_drips.vmt deleted file mode 100644 index 24091582..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_drips.vmt +++ /dev/null @@ -1,15 +0,0 @@ -"VertexLitGeneric" -{ - "$baseTexture" "models/alig96/perks/sleight/Perk_bottle_drips" - "$translucent" 1 - "$phong" "0" - "$phongexponent" "8" - "$phongboost" ".1" - "$phongfresnelranges" "[.3 1 8]" - "$halflambert" "1" - - // Rim lighting parameters - "$rimlight" "1" // To enable rim lighting (requires phong) - "$rimlightexponent" "4" // Exponent for phong component of rim lighting - "$rimlightboost" "1" // Boost for amb -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_drips.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_drips.vtf deleted file mode 100644 index 20c4c1da..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_drips.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_nrm.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_nrm.vtf deleted file mode 100644 index c2d5b007..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_nrm.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_sleight.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_sleight.vmt deleted file mode 100644 index 3da10248..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_sleight.vmt +++ /dev/null @@ -1,14 +0,0 @@ -"VertexLitGeneric" -{ - "$baseTexture" "models/alig96/perks/sleight/Perk_bottle_sleight" - "$phong" "1" - "$phongexponent" "8" - "$phongboost" ".1" - "$phongfresnelranges" "[.3 1 8]" - "$halflambert" "1" - - // Rim lighting parameters - "$rimlight" "1" // To enable rim lighting (requires phong) - "$rimlightexponent" "4" // Exponent for phong component of rim lighting - "$rimlightboost" "1" // Boost for amb -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_sleight.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_sleight.vtf deleted file mode 100644 index aa85979c..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/perk_bottle_sleight.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/power_off.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/power_off.vmt deleted file mode 100644 index c4416641..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/power_off.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Power_Off" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/power_off.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/power_off.vtf deleted file mode 100644 index 928366a9..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/power_off.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/power_on.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/power_on.vmt deleted file mode 100644 index 8b4980bd..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/power_on.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Power_On" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/power_on.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/power_on.vtf deleted file mode 100644 index 5e05a60d..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/power_on.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/sleight.vmt deleted file mode 100644 index 63d30a69..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/sleight.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Sleight" - "$bumpmap" "models/alig96/perks/sleight/Sleight_NRM" - "$surfaceprop" "Metal" - "$alphatest" 1 - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/sleight.vtf deleted file mode 100644 index c5e25a27..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/sleight.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_nrm.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_nrm.vtf deleted file mode 100644 index e61f0aa8..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_nrm.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_off.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_off.vmt deleted file mode 100644 index ab4a2482..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_off.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Sleight" - "$bumpmap" "models/alig96/perks/sleight/Sleight_NRM" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_on.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_on.vmt deleted file mode 100644 index 09e6cd23..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_on.vmt +++ /dev/null @@ -1,9 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Sleight" - "$bumpmap" "models/alig96/perks/sleight/Sleight_NRM" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 - "$selfillummask" "models/alig96/perks/sleight/white" -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_phong.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_phong.vtf deleted file mode 100644 index d5c865df..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_phong.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_price.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_price.vmt deleted file mode 100644 index 0d69c1f4..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_price.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Sleight_Price" - "$bumpmap" "models/alig96/perks/sleight/Sleight_NRM" - "$surfaceprop" "Metal" - "$alphatest" 1 - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_price.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_price.vtf deleted file mode 100644 index f0031236..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_price.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn.vmt deleted file mode 100644 index 1e478b2b..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Sleight_SNN" - "$bumpmap" "models/alig96/perks/sleight/Sleight_SNN_NRM" - "$surfaceprop" "Metal" - "$alphatest" 1 - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn.vtf deleted file mode 100644 index d8988dea..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_nrm.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_nrm.vtf deleted file mode 100644 index 374ef888..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_nrm.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_off.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_off.vmt deleted file mode 100644 index a8d6a821..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_off.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Sleight_SNN" - "$bumpmap" "models/alig96/perks/sleight/Sleight_SNN_NRM" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_on.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_on.vmt deleted file mode 100644 index 507e29fa..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_on.vmt +++ /dev/null @@ -1,9 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Sleight_SNN" - "$bumpmap" "models/alig96/perks/sleight/Sleight_SNN_NRM" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 - "$selfillummask" "models/alig96/perks/sleight/white" -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_phong.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_phong.vtf deleted file mode 100644 index fefce5fd..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_snn_phong.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_window.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_window.vmt deleted file mode 100644 index 367aa11d..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_window.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Sleight_window" - "$surfaceprop" "Glass" - "$nocull" 1 - "$translucent" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_window.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/sleight_window.vtf deleted file mode 100644 index c5e25a27..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/sleight_window.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign.vmt deleted file mode 100644 index 9dc3c0e5..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Sleightsign" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign.vtf deleted file mode 100644 index 6b6495f1..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign_off.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign_off.vmt deleted file mode 100644 index 9dc3c0e5..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign_off.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Sleightsign" - "$surfaceprop" "Metal" - "$nocull" 1 -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign_on.vmt b/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign_on.vmt deleted file mode 100644 index 96ddff78..00000000 --- a/nzombies3/content/materials/models/alig96/perks/sleight/sleightsign_on.vmt +++ /dev/null @@ -1,8 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/alig96/perks/sleight/Sleightsign" - "$surfaceprop" "Metal" - "$nocull" 1 - "$selfillum" 1 - "$selfillummask" "models/alig96/perks/sleight/white" -} diff --git a/nzombies3/content/materials/models/alig96/perks/sleight/white.vtf b/nzombies3/content/materials/models/alig96/perks/sleight/white.vtf deleted file mode 100644 index b847bc06..00000000 Binary files a/nzombies3/content/materials/models/alig96/perks/sleight/white.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_box_c.vmt b/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_box_c.vmt deleted file mode 100644 index 0abc0ee1..00000000 --- a/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_box_c.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/hoff/props/mysterybox/zombie_treasure_box_c" - "$alphatest" "1" - "$nocull" "1" -} diff --git a/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_box_c.vtf b/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_box_c.vtf deleted file mode 100644 index 9e22c5d6..00000000 Binary files a/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_box_c.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_fill_c.vmt b/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_fill_c.vmt deleted file mode 100644 index daa02667..00000000 --- a/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_fill_c.vmt +++ /dev/null @@ -1,4 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/hoff/props/mysterybox/zombie_treasure_fill_c" -} diff --git a/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_fill_c.vtf b/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_fill_c.vtf deleted file mode 100644 index 03e1a275..00000000 Binary files a/nzombies3/content/materials/models/hoff/props/mysterybox/zombie_treasure_fill_c.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/hoff/props/teddy_bear/zombie_teddybear_c.vmt b/nzombies3/content/materials/models/hoff/props/teddy_bear/zombie_teddybear_c.vmt deleted file mode 100644 index 4eabdaa7..00000000 --- a/nzombies3/content/materials/models/hoff/props/teddy_bear/zombie_teddybear_c.vmt +++ /dev/null @@ -1,4 +0,0 @@ -"VertexlitGeneric" -{ - "$basetexture" "models/hoff/props/teddy_bear/zombie_teddybear_c" -} diff --git a/nzombies3/content/materials/models/hoff/props/teddy_bear/zombie_teddybear_c.vtf b/nzombies3/content/materials/models/hoff/props/teddy_bear/zombie_teddybear_c.vtf deleted file mode 100644 index b95a2a61..00000000 Binary files a/nzombies3/content/materials/models/hoff/props/teddy_bear/zombie_teddybear_c.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/art_facemap.vmt b/nzombies3/content/materials/models/zed/male/art_facemap.vmt deleted file mode 100644 index 0fc8b872..00000000 --- a/nzombies3/content/materials/models/zed/male/art_facemap.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models\Zombie_Classic/art_facemap" - "$Bumpmap" "models\Zombie_Classic/art_facemap_normal" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/art_facemap.vtf b/nzombies3/content/materials/models/zed/male/art_facemap.vtf deleted file mode 100644 index ad25be31..00000000 Binary files a/nzombies3/content/materials/models/zed/male/art_facemap.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/art_facemap_normal.vtf b/nzombies3/content/materials/models/zed/male/art_facemap_normal.vtf deleted file mode 100644 index 8972f41f..00000000 Binary files a/nzombies3/content/materials/models/zed/male/art_facemap_normal.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/blood_sheet.vmt b/nzombies3/content/materials/models/zed/male/blood_sheet.vmt deleted file mode 100644 index a20c63e5..00000000 --- a/nzombies3/content/materials/models/zed/male/blood_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/blood_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/blood_sheet.vtf b/nzombies3/content/materials/models/zed/male/blood_sheet.vtf deleted file mode 100644 index b88b11c2..00000000 Binary files a/nzombies3/content/materials/models/zed/male/blood_sheet.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/citizen2_sheet.vmt b/nzombies3/content/materials/models/zed/male/citizen2_sheet.vmt deleted file mode 100644 index 97c02864..00000000 --- a/nzombies3/content/materials/models/zed/male/citizen2_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/citizen_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/citizen3_sheet.vmt b/nzombies3/content/materials/models/zed/male/citizen3_sheet.vmt deleted file mode 100644 index 97c02864..00000000 --- a/nzombies3/content/materials/models/zed/male/citizen3_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/citizen_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/citizen_sheet.vmt b/nzombies3/content/materials/models/zed/male/citizen_sheet.vmt deleted file mode 100644 index 97c02864..00000000 --- a/nzombies3/content/materials/models/zed/male/citizen_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/citizen_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/citizen_sheet.vtf b/nzombies3/content/materials/models/zed/male/citizen_sheet.vtf deleted file mode 100644 index f92f0001..00000000 Binary files a/nzombies3/content/materials/models/zed/male/citizen_sheet.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/citizen_sheet2.vmt b/nzombies3/content/materials/models/zed/male/citizen_sheet2.vmt deleted file mode 100644 index 71a9a383..00000000 --- a/nzombies3/content/materials/models/zed/male/citizen_sheet2.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models\Zombie_Classic/citizen_sheet2" - "$halflambert" 1 - -} diff --git a/nzombies3/content/materials/models/zed/male/citizen_sheet2.vtf b/nzombies3/content/materials/models/zed/male/citizen_sheet2.vtf deleted file mode 100644 index d6d32980..00000000 Binary files a/nzombies3/content/materials/models/zed/male/citizen_sheet2.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/citizen_sheet2_normal.vtf b/nzombies3/content/materials/models/zed/male/citizen_sheet2_normal.vtf deleted file mode 100644 index b1eed595..00000000 Binary files a/nzombies3/content/materials/models/zed/male/citizen_sheet2_normal.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/citizen_sheet3.vmt b/nzombies3/content/materials/models/zed/male/citizen_sheet3.vmt deleted file mode 100644 index ff69639d..00000000 --- a/nzombies3/content/materials/models/zed/male/citizen_sheet3.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models\Zombie_Classic/citizen_sheet3" - "$halflambert" 1 - -} diff --git a/nzombies3/content/materials/models/zed/male/citizen_sheet3.vtf b/nzombies3/content/materials/models/zed/male/citizen_sheet3.vtf deleted file mode 100644 index bb9420d8..00000000 Binary files a/nzombies3/content/materials/models/zed/male/citizen_sheet3.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/citizen_sheet_normal.vtf b/nzombies3/content/materials/models/zed/male/citizen_sheet_normal.vtf deleted file mode 100644 index 8706d940..00000000 Binary files a/nzombies3/content/materials/models/zed/male/citizen_sheet_normal.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/corpse1.vmt b/nzombies3/content/materials/models/zed/male/corpse1.vmt deleted file mode 100644 index 120ec700..00000000 --- a/nzombies3/content/materials/models/zed/male/corpse1.vmt +++ /dev/null @@ -1,5 +0,0 @@ -"VertexLitGeneric" -{ - "$baseTexture" "models/Zombie_Classic/corpse1" - "$model" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/corpse1.vtf b/nzombies3/content/materials/models/zed/male/corpse1.vtf deleted file mode 100644 index 58582bb7..00000000 Binary files a/nzombies3/content/materials/models/zed/male/corpse1.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/dark_eyeball_l.vmt b/nzombies3/content/materials/models/zed/male/dark_eyeball_l.vmt deleted file mode 100644 index 16e518a2..00000000 --- a/nzombies3/content/materials/models/zed/male/dark_eyeball_l.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"eyes" -{ - "$basetexture" "models/Zed/Male/dark_eyeball_l" - "$iris" "models/Zed/Male/pupil_l" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/dark_eyeball_l.vtf b/nzombies3/content/materials/models/zed/male/dark_eyeball_l.vtf deleted file mode 100644 index 1764f6ce..00000000 Binary files a/nzombies3/content/materials/models/zed/male/dark_eyeball_l.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/dark_eyeball_r.vmt b/nzombies3/content/materials/models/zed/male/dark_eyeball_r.vmt deleted file mode 100644 index cdeb9165..00000000 --- a/nzombies3/content/materials/models/zed/male/dark_eyeball_r.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"eyes" -{ - "$basetexture" "models/Zed/Male/dark_eyeball_r" - "$iris" "models/Zed/Male/pupil_r" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/dark_eyeball_r.vtf b/nzombies3/content/materials/models/zed/male/dark_eyeball_r.vtf deleted file mode 100644 index 5f158985..00000000 Binary files a/nzombies3/content/materials/models/zed/male/dark_eyeball_r.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/erdim_cylmap.vmt b/nzombies3/content/materials/models/zed/male/erdim_cylmap.vmt deleted file mode 100644 index 90876cc1..00000000 --- a/nzombies3/content/materials/models/zed/male/erdim_cylmap.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models\Zombie_Classic/erdim_cylmap" - "$Bumpmap" "models\Zombie_Classic/erdim_cylmap_normal" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/erdim_cylmap.vtf b/nzombies3/content/materials/models/zed/male/erdim_cylmap.vtf deleted file mode 100644 index a6397de5..00000000 Binary files a/nzombies3/content/materials/models/zed/male/erdim_cylmap.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/erdim_cylmap_normal.vtf b/nzombies3/content/materials/models/zed/male/erdim_cylmap_normal.vtf deleted file mode 100644 index e64cfb44..00000000 Binary files a/nzombies3/content/materials/models/zed/male/erdim_cylmap_normal.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/erdim_facemap.vmt b/nzombies3/content/materials/models/zed/male/erdim_facemap.vmt deleted file mode 100644 index 16fccf51..00000000 --- a/nzombies3/content/materials/models/zed/male/erdim_facemap.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/erdim_cylmap" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/eric_facemap.vmt b/nzombies3/content/materials/models/zed/male/eric_facemap.vmt deleted file mode 100644 index 5a6f0023..00000000 --- a/nzombies3/content/materials/models/zed/male/eric_facemap.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/eric_facemap" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/eric_facemap.vtf b/nzombies3/content/materials/models/zed/male/eric_facemap.vtf deleted file mode 100644 index cbcfc641..00000000 Binary files a/nzombies3/content/materials/models/zed/male/eric_facemap.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/eric_facemap_normal.vtf b/nzombies3/content/materials/models/zed/male/eric_facemap_normal.vtf deleted file mode 100644 index 206c5405..00000000 Binary files a/nzombies3/content/materials/models/zed/male/eric_facemap_normal.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/eyeball_l.vmt b/nzombies3/content/materials/models/zed/male/eyeball_l.vmt deleted file mode 100644 index 25ea99f8..00000000 --- a/nzombies3/content/materials/models/zed/male/eyeball_l.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"eyes" -{ - "$basetexture" "models/Zed/Male/eyeball_l" - "$iris" "models/Zed/Male/pupil_l" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/eyeball_l.vtf b/nzombies3/content/materials/models/zed/male/eyeball_l.vtf deleted file mode 100644 index 8e571024..00000000 Binary files a/nzombies3/content/materials/models/zed/male/eyeball_l.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/eyeball_r.vmt b/nzombies3/content/materials/models/zed/male/eyeball_r.vmt deleted file mode 100644 index bb0eb052..00000000 --- a/nzombies3/content/materials/models/zed/male/eyeball_r.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"eyes" -{ - "$basetexture" "models/Zed/Male/eyeball_r" - "$iris" "models/Zed/Male/pupil_r" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/eyeball_r.vtf b/nzombies3/content/materials/models/zed/male/eyeball_r.vtf deleted file mode 100644 index 570c7d1c..00000000 Binary files a/nzombies3/content/materials/models/zed/male/eyeball_r.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/g1_01_sheet.vmt b/nzombies3/content/materials/models/zed/male/g1_01_sheet.vmt deleted file mode 100644 index 11a521cc..00000000 --- a/nzombies3/content/materials/models/zed/male/g1_01_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/plaid_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g1_02_sheet.vmt b/nzombies3/content/materials/models/zed/male/g1_02_sheet.vmt deleted file mode 100644 index 65c06c9c..00000000 --- a/nzombies3/content/materials/models/zed/male/g1_02_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/grey_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g1_03_sheet.vmt b/nzombies3/content/materials/models/zed/male/g1_03_sheet.vmt deleted file mode 100644 index a20c63e5..00000000 --- a/nzombies3/content/materials/models/zed/male/g1_03_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/blood_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g1_04_sheet.vmt b/nzombies3/content/materials/models/zed/male/g1_04_sheet.vmt deleted file mode 100644 index e5923156..00000000 --- a/nzombies3/content/materials/models/zed/male/g1_04_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/service_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g1_05_sheet.vmt b/nzombies3/content/materials/models/zed/male/g1_05_sheet.vmt deleted file mode 100644 index 83dd7dd5..00000000 --- a/nzombies3/content/materials/models/zed/male/g1_05_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/jackson_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g2_01_sheet.vmt b/nzombies3/content/materials/models/zed/male/g2_01_sheet.vmt deleted file mode 100644 index 11a521cc..00000000 --- a/nzombies3/content/materials/models/zed/male/g2_01_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/plaid_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g2_02_sheet.vmt b/nzombies3/content/materials/models/zed/male/g2_02_sheet.vmt deleted file mode 100644 index 65c06c9c..00000000 --- a/nzombies3/content/materials/models/zed/male/g2_02_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/grey_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g2_03_sheet.vmt b/nzombies3/content/materials/models/zed/male/g2_03_sheet.vmt deleted file mode 100644 index a20c63e5..00000000 --- a/nzombies3/content/materials/models/zed/male/g2_03_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/blood_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g2_04_sheet.vmt b/nzombies3/content/materials/models/zed/male/g2_04_sheet.vmt deleted file mode 100644 index e5923156..00000000 --- a/nzombies3/content/materials/models/zed/male/g2_04_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/service_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g2_05_sheet.vmt b/nzombies3/content/materials/models/zed/male/g2_05_sheet.vmt deleted file mode 100644 index 83dd7dd5..00000000 --- a/nzombies3/content/materials/models/zed/male/g2_05_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/jackson_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g3_01_sheet.vmt b/nzombies3/content/materials/models/zed/male/g3_01_sheet.vmt deleted file mode 100644 index 11a521cc..00000000 --- a/nzombies3/content/materials/models/zed/male/g3_01_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/plaid_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g3_02_sheet.vmt b/nzombies3/content/materials/models/zed/male/g3_02_sheet.vmt deleted file mode 100644 index 65c06c9c..00000000 --- a/nzombies3/content/materials/models/zed/male/g3_02_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/grey_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g3_03_sheet.vmt b/nzombies3/content/materials/models/zed/male/g3_03_sheet.vmt deleted file mode 100644 index a20c63e5..00000000 --- a/nzombies3/content/materials/models/zed/male/g3_03_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/blood_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g3_04_sheet.vmt b/nzombies3/content/materials/models/zed/male/g3_04_sheet.vmt deleted file mode 100644 index e5923156..00000000 --- a/nzombies3/content/materials/models/zed/male/g3_04_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/service_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g3_05_sheet.vmt b/nzombies3/content/materials/models/zed/male/g3_05_sheet.vmt deleted file mode 100644 index 83dd7dd5..00000000 --- a/nzombies3/content/materials/models/zed/male/g3_05_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/jackson_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g4_01_sheet.vmt b/nzombies3/content/materials/models/zed/male/g4_01_sheet.vmt deleted file mode 100644 index 11a521cc..00000000 --- a/nzombies3/content/materials/models/zed/male/g4_01_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/plaid_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g4_02_sheet.vmt b/nzombies3/content/materials/models/zed/male/g4_02_sheet.vmt deleted file mode 100644 index 65c06c9c..00000000 --- a/nzombies3/content/materials/models/zed/male/g4_02_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/grey_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g4_03_sheet.vmt b/nzombies3/content/materials/models/zed/male/g4_03_sheet.vmt deleted file mode 100644 index a20c63e5..00000000 --- a/nzombies3/content/materials/models/zed/male/g4_03_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/blood_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g4_04_sheet.vmt b/nzombies3/content/materials/models/zed/male/g4_04_sheet.vmt deleted file mode 100644 index e5923156..00000000 --- a/nzombies3/content/materials/models/zed/male/g4_04_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/service_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/g4_05_sheet.vmt b/nzombies3/content/materials/models/zed/male/g4_05_sheet.vmt deleted file mode 100644 index 83dd7dd5..00000000 --- a/nzombies3/content/materials/models/zed/male/g4_05_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/jackson_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/glint.vmt b/nzombies3/content/materials/models/zed/male/glint.vmt deleted file mode 100644 index 9dd2d50e..00000000 --- a/nzombies3/content/materials/models/zed/male/glint.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - // Original shader: AddTexture - "$basetexture" "models/Zed/Male/glint" - "$additive" 1 - "$model" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/glint.vtf b/nzombies3/content/materials/models/zed/male/glint.vtf deleted file mode 100644 index 7d4a0ff6..00000000 Binary files a/nzombies3/content/materials/models/zed/male/glint.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/grey_sheet.vmt b/nzombies3/content/materials/models/zed/male/grey_sheet.vmt deleted file mode 100644 index 65c06c9c..00000000 --- a/nzombies3/content/materials/models/zed/male/grey_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/grey_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/grey_sheet.vtf b/nzombies3/content/materials/models/zed/male/grey_sheet.vtf deleted file mode 100644 index 69a621b4..00000000 Binary files a/nzombies3/content/materials/models/zed/male/grey_sheet.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/jackson_sheet.vmt b/nzombies3/content/materials/models/zed/male/jackson_sheet.vmt deleted file mode 100644 index 83dd7dd5..00000000 --- a/nzombies3/content/materials/models/zed/male/jackson_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/jackson_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/jackson_sheet.vtf b/nzombies3/content/materials/models/zed/male/jackson_sheet.vtf deleted file mode 100644 index de27faf7..00000000 Binary files a/nzombies3/content/materials/models/zed/male/jackson_sheet.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/joe_facemap.vmt b/nzombies3/content/materials/models/zed/male/joe_facemap.vmt deleted file mode 100644 index 80e15334..00000000 --- a/nzombies3/content/materials/models/zed/male/joe_facemap.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/joe_facemap" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/joe_facemap.vtf b/nzombies3/content/materials/models/zed/male/joe_facemap.vtf deleted file mode 100644 index 5c31cd96..00000000 Binary files a/nzombies3/content/materials/models/zed/male/joe_facemap.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/joe_facemap_normal.vtf b/nzombies3/content/materials/models/zed/male/joe_facemap_normal.vtf deleted file mode 100644 index 2e1b1839..00000000 Binary files a/nzombies3/content/materials/models/zed/male/joe_facemap_normal.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/mike_facemap.vmt b/nzombies3/content/materials/models/zed/male/mike_facemap.vmt deleted file mode 100644 index b67a27bd..00000000 --- a/nzombies3/content/materials/models/zed/male/mike_facemap.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models\Zombie_Classic/mike_facemap" - "$Bumpmap" "models\Zombie_Classic/mike_facemap_normal" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/mike_facemap.vtf b/nzombies3/content/materials/models/zed/male/mike_facemap.vtf deleted file mode 100644 index f54636aa..00000000 Binary files a/nzombies3/content/materials/models/zed/male/mike_facemap.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/mike_facemap_normal.vtf b/nzombies3/content/materials/models/zed/male/mike_facemap_normal.vtf deleted file mode 100644 index 1a373b7d..00000000 Binary files a/nzombies3/content/materials/models/zed/male/mike_facemap_normal.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/mouth.vmt b/nzombies3/content/materials/models/zed/male/mouth.vmt deleted file mode 100644 index d0789af5..00000000 --- a/nzombies3/content/materials/models/zed/male/mouth.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"Teeth" -{ - "$basetexture" "models/Zed/Male/mouth" - "$model" 1 - "$clientshader" "MouthShader" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/mouth.vtf b/nzombies3/content/materials/models/zed/male/mouth.vtf deleted file mode 100644 index abe1c02b..00000000 Binary files a/nzombies3/content/materials/models/zed/male/mouth.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/plaid_sheet.vmt b/nzombies3/content/materials/models/zed/male/plaid_sheet.vmt deleted file mode 100644 index 11a521cc..00000000 --- a/nzombies3/content/materials/models/zed/male/plaid_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/plaid_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/plaid_sheet.vtf b/nzombies3/content/materials/models/zed/male/plaid_sheet.vtf deleted file mode 100644 index 21789e42..00000000 Binary files a/nzombies3/content/materials/models/zed/male/plaid_sheet.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/pupil_l.vmt b/nzombies3/content/materials/models/zed/male/pupil_l.vmt deleted file mode 100644 index 61dfe74b..00000000 --- a/nzombies3/content/materials/models/zed/male/pupil_l.vmt +++ /dev/null @@ -1,4 +0,0 @@ -"Eyeball" -{ - "$basetexture" "models/Zed/Male/pupil_l" -} diff --git a/nzombies3/content/materials/models/zed/male/pupil_l.vtf b/nzombies3/content/materials/models/zed/male/pupil_l.vtf deleted file mode 100644 index 481beab3..00000000 Binary files a/nzombies3/content/materials/models/zed/male/pupil_l.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/pupil_r.vmt b/nzombies3/content/materials/models/zed/male/pupil_r.vmt deleted file mode 100644 index 23fac5bc..00000000 --- a/nzombies3/content/materials/models/zed/male/pupil_r.vmt +++ /dev/null @@ -1,4 +0,0 @@ -"Eyeball" -{ - "$basetexture" "models/Zed/Male/pupil_r" -} diff --git a/nzombies3/content/materials/models/zed/male/pupil_r.vtf b/nzombies3/content/materials/models/zed/male/pupil_r.vtf deleted file mode 100644 index 3bdc93d5..00000000 Binary files a/nzombies3/content/materials/models/zed/male/pupil_r.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/sandro_facemap.vmt b/nzombies3/content/materials/models/zed/male/sandro_facemap.vmt deleted file mode 100644 index bd3d3756..00000000 --- a/nzombies3/content/materials/models/zed/male/sandro_facemap.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/sandro_facemap" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/sandro_facemap.vtf b/nzombies3/content/materials/models/zed/male/sandro_facemap.vtf deleted file mode 100644 index 4e13337a..00000000 Binary files a/nzombies3/content/materials/models/zed/male/sandro_facemap.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/sandro_facemap_normal.vtf b/nzombies3/content/materials/models/zed/male/sandro_facemap_normal.vtf deleted file mode 100644 index dfa6c600..00000000 Binary files a/nzombies3/content/materials/models/zed/male/sandro_facemap_normal.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/service_sheet.vmt b/nzombies3/content/materials/models/zed/male/service_sheet.vmt deleted file mode 100644 index e5923156..00000000 --- a/nzombies3/content/materials/models/zed/male/service_sheet.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/service_sheet" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/service_sheet.vtf b/nzombies3/content/materials/models/zed/male/service_sheet.vtf deleted file mode 100644 index af96c062..00000000 Binary files a/nzombies3/content/materials/models/zed/male/service_sheet.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/ted_facemap.vmt b/nzombies3/content/materials/models/zed/male/ted_facemap.vmt deleted file mode 100644 index 8a093a84..00000000 --- a/nzombies3/content/materials/models/zed/male/ted_facemap.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models\Zombie_Classic/ted_facemap" - "$Bumpmap" "models\Zombie_Classic/ted_facemap_normal" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/ted_facemap.vtf b/nzombies3/content/materials/models/zed/male/ted_facemap.vtf deleted file mode 100644 index f4c6f419..00000000 Binary files a/nzombies3/content/materials/models/zed/male/ted_facemap.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/ted_facemap_normal.vtf b/nzombies3/content/materials/models/zed/male/ted_facemap_normal.vtf deleted file mode 100644 index c0f6bf2d..00000000 Binary files a/nzombies3/content/materials/models/zed/male/ted_facemap_normal.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/van_facemap.vmt b/nzombies3/content/materials/models/zed/male/van_facemap.vmt deleted file mode 100644 index 5cf09f3b..00000000 --- a/nzombies3/content/materials/models/zed/male/van_facemap.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models\Zombie_Classic/van_facemap" - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/van_facemap.vtf b/nzombies3/content/materials/models/zed/male/van_facemap.vtf deleted file mode 100644 index b1fcde85..00000000 Binary files a/nzombies3/content/materials/models/zed/male/van_facemap.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/van_facemap_normal.vtf b/nzombies3/content/materials/models/zed/male/van_facemap_normal.vtf deleted file mode 100644 index c9584d98..00000000 Binary files a/nzombies3/content/materials/models/zed/male/van_facemap_normal.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/vance_facemap.vmt b/nzombies3/content/materials/models/zed/male/vance_facemap.vmt deleted file mode 100644 index b88a5885..00000000 --- a/nzombies3/content/materials/models/zed/male/vance_facemap.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"VertexLitGeneric" -{ - // Original shader: VertexLitTexture - "$basetexture" "models/Zed/Male/vance_facemap" - "$envmapsphere" 1 - "$halflambert" 1 -} diff --git a/nzombies3/content/materials/models/zed/male/vance_facemap.vtf b/nzombies3/content/materials/models/zed/male/vance_facemap.vtf deleted file mode 100644 index 46913ec7..00000000 Binary files a/nzombies3/content/materials/models/zed/male/vance_facemap.vtf and /dev/null differ diff --git a/nzombies3/content/materials/models/zed/male/vance_facemap_normal.vtf b/nzombies3/content/materials/models/zed/male/vance_facemap_normal.vtf deleted file mode 100644 index 0c64c721..00000000 Binary files a/nzombies3/content/materials/models/zed/male/vance_facemap_normal.vtf and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.dx80.vtx b/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.dx80.vtx deleted file mode 100644 index f3697622..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.dx90.vtx b/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.dx90.vtx deleted file mode 100644 index aacc5cfd..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.mdl b/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.mdl deleted file mode 100644 index a39ba957..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.mdl and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.phy b/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.phy deleted file mode 100644 index 7de8a3f9..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.phy and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.sw.vtx b/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.sw.vtx deleted file mode 100644 index 25e70d79..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.vvd b/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.vvd deleted file mode 100644 index 289234a4..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_off.vvd and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.dx80.vtx b/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.dx80.vtx deleted file mode 100644 index 0e355863..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.dx90.vtx b/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.dx90.vtx deleted file mode 100644 index 1ac2dbe3..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.mdl b/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.mdl deleted file mode 100644 index e422f075..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.mdl and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.phy b/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.phy deleted file mode 100644 index 5f07ca04..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.phy and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.sw.vtx b/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.sw.vtx deleted file mode 100644 index 65795395..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.vvd b/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.vvd deleted file mode 100644 index bf539637..00000000 Binary files a/nzombies3/content/models/alig96/perks/doubletap/doubletap_on.vvd and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_off.dx80.vtx b/nzombies3/content/models/alig96/perks/jugg/jugg_off.dx80.vtx deleted file mode 100644 index f73b8f97..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_off.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_off.dx90.vtx b/nzombies3/content/models/alig96/perks/jugg/jugg_off.dx90.vtx deleted file mode 100644 index f2a532ea..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_off.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_off.mdl b/nzombies3/content/models/alig96/perks/jugg/jugg_off.mdl deleted file mode 100644 index 68a5a83c..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_off.mdl and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_off.phy b/nzombies3/content/models/alig96/perks/jugg/jugg_off.phy deleted file mode 100644 index 4ba6b4de..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_off.phy and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_off.sw.vtx b/nzombies3/content/models/alig96/perks/jugg/jugg_off.sw.vtx deleted file mode 100644 index 4302a580..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_off.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_off.vvd b/nzombies3/content/models/alig96/perks/jugg/jugg_off.vvd deleted file mode 100644 index d0e83a42..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_off.vvd and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_on.dx80.vtx b/nzombies3/content/models/alig96/perks/jugg/jugg_on.dx80.vtx deleted file mode 100644 index aa1fd5c8..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_on.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_on.dx90.vtx b/nzombies3/content/models/alig96/perks/jugg/jugg_on.dx90.vtx deleted file mode 100644 index 8bd2d513..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_on.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_on.mdl b/nzombies3/content/models/alig96/perks/jugg/jugg_on.mdl deleted file mode 100644 index 6c27c2e9..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_on.mdl and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_on.phy b/nzombies3/content/models/alig96/perks/jugg/jugg_on.phy deleted file mode 100644 index a60fac5d..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_on.phy and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_on.sw.vtx b/nzombies3/content/models/alig96/perks/jugg/jugg_on.sw.vtx deleted file mode 100644 index 4f195087..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_on.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/jugg/jugg_on.vvd b/nzombies3/content/models/alig96/perks/jugg/jugg_on.vvd deleted file mode 100644 index 16edc3ab..00000000 Binary files a/nzombies3/content/models/alig96/perks/jugg/jugg_on.vvd and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/packapunch/packapunch.dx80.vtx b/nzombies3/content/models/alig96/perks/packapunch/packapunch.dx80.vtx deleted file mode 100644 index bc55817b..00000000 Binary files a/nzombies3/content/models/alig96/perks/packapunch/packapunch.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/packapunch/packapunch.dx90.vtx b/nzombies3/content/models/alig96/perks/packapunch/packapunch.dx90.vtx deleted file mode 100644 index 561382c3..00000000 Binary files a/nzombies3/content/models/alig96/perks/packapunch/packapunch.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/packapunch/packapunch.mdl b/nzombies3/content/models/alig96/perks/packapunch/packapunch.mdl deleted file mode 100644 index 2237c182..00000000 Binary files a/nzombies3/content/models/alig96/perks/packapunch/packapunch.mdl and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/packapunch/packapunch.phy b/nzombies3/content/models/alig96/perks/packapunch/packapunch.phy deleted file mode 100644 index 01884c68..00000000 Binary files a/nzombies3/content/models/alig96/perks/packapunch/packapunch.phy and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/packapunch/packapunch.sw.vtx b/nzombies3/content/models/alig96/perks/packapunch/packapunch.sw.vtx deleted file mode 100644 index 107705a6..00000000 Binary files a/nzombies3/content/models/alig96/perks/packapunch/packapunch.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/packapunch/packapunch.vvd b/nzombies3/content/models/alig96/perks/packapunch/packapunch.vvd deleted file mode 100644 index f690c8d5..00000000 Binary files a/nzombies3/content/models/alig96/perks/packapunch/packapunch.vvd and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/readme.txt b/nzombies3/content/models/alig96/perks/readme.txt deleted file mode 100644 index c0801c50..00000000 --- a/nzombies3/content/models/alig96/perks/readme.txt +++ /dev/null @@ -1,3 +0,0 @@ -Models by Beat the Zombie - -Recompiled by Alig96 so everything is in a nice folder. \ No newline at end of file diff --git a/nzombies3/content/models/alig96/perks/revive/revive_off.dx80.vtx b/nzombies3/content/models/alig96/perks/revive/revive_off.dx80.vtx deleted file mode 100644 index bcc55895..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_off.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/revive/revive_off.dx90.vtx b/nzombies3/content/models/alig96/perks/revive/revive_off.dx90.vtx deleted file mode 100644 index 30e9e56b..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_off.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/revive/revive_off.mdl b/nzombies3/content/models/alig96/perks/revive/revive_off.mdl deleted file mode 100644 index c973d705..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_off.mdl and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/revive/revive_off.phy b/nzombies3/content/models/alig96/perks/revive/revive_off.phy deleted file mode 100644 index 5d5c2885..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_off.phy and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/revive/revive_off.sw.vtx b/nzombies3/content/models/alig96/perks/revive/revive_off.sw.vtx deleted file mode 100644 index f3fd1b54..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_off.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/revive/revive_off.vvd b/nzombies3/content/models/alig96/perks/revive/revive_off.vvd deleted file mode 100644 index e706a112..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_off.vvd and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/revive/revive_on.dx80.vtx b/nzombies3/content/models/alig96/perks/revive/revive_on.dx80.vtx deleted file mode 100644 index 0c4da67b..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_on.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/revive/revive_on.dx90.vtx b/nzombies3/content/models/alig96/perks/revive/revive_on.dx90.vtx deleted file mode 100644 index 38c425cb..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_on.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/revive/revive_on.mdl b/nzombies3/content/models/alig96/perks/revive/revive_on.mdl deleted file mode 100644 index c6fa28e5..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_on.mdl and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/revive/revive_on.phy b/nzombies3/content/models/alig96/perks/revive/revive_on.phy deleted file mode 100644 index a7bb97e4..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_on.phy and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/revive/revive_on.sw.vtx b/nzombies3/content/models/alig96/perks/revive/revive_on.sw.vtx deleted file mode 100644 index 05a15264..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_on.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/revive/revive_on.vvd b/nzombies3/content/models/alig96/perks/revive/revive_on.vvd deleted file mode 100644 index b7610eba..00000000 Binary files a/nzombies3/content/models/alig96/perks/revive/revive_on.vvd and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_off.dx80.vtx b/nzombies3/content/models/alig96/perks/sleight/sleight_off.dx80.vtx deleted file mode 100644 index d44ba040..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_off.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_off.dx90.vtx b/nzombies3/content/models/alig96/perks/sleight/sleight_off.dx90.vtx deleted file mode 100644 index 715c4576..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_off.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_off.mdl b/nzombies3/content/models/alig96/perks/sleight/sleight_off.mdl deleted file mode 100644 index 893f8aa8..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_off.mdl and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_off.phy b/nzombies3/content/models/alig96/perks/sleight/sleight_off.phy deleted file mode 100644 index b7ad8ce8..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_off.phy and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_off.sw.vtx b/nzombies3/content/models/alig96/perks/sleight/sleight_off.sw.vtx deleted file mode 100644 index ebf421a7..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_off.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_off.vvd b/nzombies3/content/models/alig96/perks/sleight/sleight_off.vvd deleted file mode 100644 index 728ae443..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_off.vvd and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_on.dx80.vtx b/nzombies3/content/models/alig96/perks/sleight/sleight_on.dx80.vtx deleted file mode 100644 index 5cc5d812..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_on.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_on.dx90.vtx b/nzombies3/content/models/alig96/perks/sleight/sleight_on.dx90.vtx deleted file mode 100644 index edf89fdd..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_on.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_on.mdl b/nzombies3/content/models/alig96/perks/sleight/sleight_on.mdl deleted file mode 100644 index 19aede86..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_on.mdl and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_on.phy b/nzombies3/content/models/alig96/perks/sleight/sleight_on.phy deleted file mode 100644 index 4258cdc5..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_on.phy and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_on.sw.vtx b/nzombies3/content/models/alig96/perks/sleight/sleight_on.sw.vtx deleted file mode 100644 index 39c1cf55..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_on.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/alig96/perks/sleight/sleight_on.vvd b/nzombies3/content/models/alig96/perks/sleight/sleight_on.vvd deleted file mode 100644 index c66271e7..00000000 Binary files a/nzombies3/content/models/alig96/perks/sleight/sleight_on.vvd and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box.dx80.vtx b/nzombies3/content/models/hoff/props/mysterybox/box.dx80.vtx deleted file mode 100644 index 4d6add08..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box.dx90.vtx b/nzombies3/content/models/hoff/props/mysterybox/box.dx90.vtx deleted file mode 100644 index 45415e70..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box.mdl b/nzombies3/content/models/hoff/props/mysterybox/box.mdl deleted file mode 100644 index 28167944..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box.mdl and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box.phy b/nzombies3/content/models/hoff/props/mysterybox/box.phy deleted file mode 100644 index e327f6c7..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box.phy and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box.sw.vtx b/nzombies3/content/models/hoff/props/mysterybox/box.sw.vtx deleted file mode 100644 index f71053f2..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box.vvd b/nzombies3/content/models/hoff/props/mysterybox/box.vvd deleted file mode 100644 index 74b00c24..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box.vvd and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box1.dx80.vtx b/nzombies3/content/models/hoff/props/mysterybox/box1.dx80.vtx deleted file mode 100644 index e6b22244..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box1.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box1.dx90.vtx b/nzombies3/content/models/hoff/props/mysterybox/box1.dx90.vtx deleted file mode 100644 index 94430cef..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box1.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box1.mdl b/nzombies3/content/models/hoff/props/mysterybox/box1.mdl deleted file mode 100644 index c9332f0b..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box1.mdl and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box1.phy b/nzombies3/content/models/hoff/props/mysterybox/box1.phy deleted file mode 100644 index 3ee874d5..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box1.phy and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box1.sw.vtx b/nzombies3/content/models/hoff/props/mysterybox/box1.sw.vtx deleted file mode 100644 index 11945f88..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box1.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box1.vvd b/nzombies3/content/models/hoff/props/mysterybox/box1.vvd deleted file mode 100644 index d1734a9e..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box1.vvd and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box2.dx80.vtx b/nzombies3/content/models/hoff/props/mysterybox/box2.dx80.vtx deleted file mode 100644 index f6ea7647..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box2.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box2.dx90.vtx b/nzombies3/content/models/hoff/props/mysterybox/box2.dx90.vtx deleted file mode 100644 index c9a760b6..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box2.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box2.mdl b/nzombies3/content/models/hoff/props/mysterybox/box2.mdl deleted file mode 100644 index c546884a..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box2.mdl and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box2.sw.vtx b/nzombies3/content/models/hoff/props/mysterybox/box2.sw.vtx deleted file mode 100644 index 8e90ef40..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box2.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/mysterybox/box2.vvd b/nzombies3/content/models/hoff/props/mysterybox/box2.vvd deleted file mode 100644 index 82798e2c..00000000 Binary files a/nzombies3/content/models/hoff/props/mysterybox/box2.vvd and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.dx80.vtx b/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.dx80.vtx deleted file mode 100644 index 943068eb..00000000 Binary files a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.dx90.vtx b/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.dx90.vtx deleted file mode 100644 index c7dc96ef..00000000 Binary files a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.mdl b/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.mdl deleted file mode 100644 index f39bc5c2..00000000 Binary files a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.mdl and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.phy b/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.phy deleted file mode 100644 index 1fa32c3b..00000000 Binary files a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.phy and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.sw.vtx b/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.sw.vtx deleted file mode 100644 index 2c66ca62..00000000 Binary files a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.vvd b/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.vvd deleted file mode 100644 index b9e1d684..00000000 Binary files a/nzombies3/content/models/hoff/props/teddy_bear/teddy_bear.vvd and /dev/null differ diff --git a/nzombies3/content/models/zed/male_shared.mdl b/nzombies3/content/models/zed/male_shared.mdl deleted file mode 100644 index 3dacef39..00000000 Binary files a/nzombies3/content/models/zed/male_shared.mdl and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_04.dx80.vtx b/nzombies3/content/models/zed/malezed_04.dx80.vtx deleted file mode 100644 index 4286d81b..00000000 Binary files a/nzombies3/content/models/zed/malezed_04.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_04.dx90.vtx b/nzombies3/content/models/zed/malezed_04.dx90.vtx deleted file mode 100644 index 602b05f8..00000000 Binary files a/nzombies3/content/models/zed/malezed_04.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_04.mdl b/nzombies3/content/models/zed/malezed_04.mdl deleted file mode 100644 index 4cf04b03..00000000 Binary files a/nzombies3/content/models/zed/malezed_04.mdl and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_04.phy b/nzombies3/content/models/zed/malezed_04.phy deleted file mode 100644 index 6837ae84..00000000 Binary files a/nzombies3/content/models/zed/malezed_04.phy and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_04.sw.vtx b/nzombies3/content/models/zed/malezed_04.sw.vtx deleted file mode 100644 index faa6237e..00000000 Binary files a/nzombies3/content/models/zed/malezed_04.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_04.vvd b/nzombies3/content/models/zed/malezed_04.vvd deleted file mode 100644 index 419ad42e..00000000 Binary files a/nzombies3/content/models/zed/malezed_04.vvd and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_06.dx80.vtx b/nzombies3/content/models/zed/malezed_06.dx80.vtx deleted file mode 100644 index 48424622..00000000 Binary files a/nzombies3/content/models/zed/malezed_06.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_06.dx90.vtx b/nzombies3/content/models/zed/malezed_06.dx90.vtx deleted file mode 100644 index 758e6fa7..00000000 Binary files a/nzombies3/content/models/zed/malezed_06.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_06.mdl b/nzombies3/content/models/zed/malezed_06.mdl deleted file mode 100644 index 10196b8c..00000000 Binary files a/nzombies3/content/models/zed/malezed_06.mdl and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_06.phy b/nzombies3/content/models/zed/malezed_06.phy deleted file mode 100644 index e857d4e9..00000000 Binary files a/nzombies3/content/models/zed/malezed_06.phy and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_06.sw.vtx b/nzombies3/content/models/zed/malezed_06.sw.vtx deleted file mode 100644 index b59eb20f..00000000 Binary files a/nzombies3/content/models/zed/malezed_06.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_06.vvd b/nzombies3/content/models/zed/malezed_06.vvd deleted file mode 100644 index 452e5c10..00000000 Binary files a/nzombies3/content/models/zed/malezed_06.vvd and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_08.dx80.vtx b/nzombies3/content/models/zed/malezed_08.dx80.vtx deleted file mode 100644 index 045dc1fe..00000000 Binary files a/nzombies3/content/models/zed/malezed_08.dx80.vtx and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_08.dx90.vtx b/nzombies3/content/models/zed/malezed_08.dx90.vtx deleted file mode 100644 index 06984c79..00000000 Binary files a/nzombies3/content/models/zed/malezed_08.dx90.vtx and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_08.mdl b/nzombies3/content/models/zed/malezed_08.mdl deleted file mode 100644 index a1bca030..00000000 Binary files a/nzombies3/content/models/zed/malezed_08.mdl and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_08.phy b/nzombies3/content/models/zed/malezed_08.phy deleted file mode 100644 index 99f6e054..00000000 Binary files a/nzombies3/content/models/zed/malezed_08.phy and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_08.sw.vtx b/nzombies3/content/models/zed/malezed_08.sw.vtx deleted file mode 100644 index f83c17c0..00000000 Binary files a/nzombies3/content/models/zed/malezed_08.sw.vtx and /dev/null differ diff --git a/nzombies3/content/models/zed/malezed_08.vvd b/nzombies3/content/models/zed/malezed_08.vvd deleted file mode 100644 index 8ba3f68d..00000000 Binary files a/nzombies3/content/models/zed/malezed_08.vvd and /dev/null differ diff --git a/nzombies3/content/sound/nz/powerups/double_points.mp3 b/nzombies3/content/sound/nz/powerups/double_points.mp3 deleted file mode 100644 index 89d58487..00000000 Binary files a/nzombies3/content/sound/nz/powerups/double_points.mp3 and /dev/null differ diff --git a/nzombies3/content/sound/nz/powerups/insta_kill.mp3 b/nzombies3/content/sound/nz/powerups/insta_kill.mp3 deleted file mode 100644 index 1f7ecb20..00000000 Binary files a/nzombies3/content/sound/nz/powerups/insta_kill.mp3 and /dev/null differ diff --git a/nzombies3/content/sound/nz/powerups/max_ammo.mp3 b/nzombies3/content/sound/nz/powerups/max_ammo.mp3 deleted file mode 100644 index 0c375015..00000000 Binary files a/nzombies3/content/sound/nz/powerups/max_ammo.mp3 and /dev/null differ diff --git a/nzombies3/content/sound/nz/powerups/nuke.mp3 b/nzombies3/content/sound/nz/powerups/nuke.mp3 deleted file mode 100644 index 2e184065..00000000 Binary files a/nzombies3/content/sound/nz/powerups/nuke.mp3 and /dev/null differ diff --git a/nzombies3/content/sound/nz/round/game_over_4.mp3 b/nzombies3/content/sound/nz/round/game_over_4.mp3 deleted file mode 100644 index 5299d9be..00000000 Binary files a/nzombies3/content/sound/nz/round/game_over_4.mp3 and /dev/null differ diff --git a/nzombies3/content/sound/nz/round/round_end.mp3 b/nzombies3/content/sound/nz/round/round_end.mp3 deleted file mode 100644 index d92a113f..00000000 Binary files a/nzombies3/content/sound/nz/round/round_end.mp3 and /dev/null differ diff --git a/nzombies3/content/sound/nz/round/round_start.mp3 b/nzombies3/content/sound/nz/round/round_start.mp3 deleted file mode 100644 index 1a71306c..00000000 Binary files a/nzombies3/content/sound/nz/round/round_start.mp3 and /dev/null differ diff --git a/nzombies3/entities/entities/breakable_entry/shared.lua b/nzombies3/entities/entities/breakable_entry/shared.lua deleted file mode 100644 index a8d700be..00000000 --- a/nzombies3/entities/entities/breakable_entry/shared.lua +++ /dev/null @@ -1,110 +0,0 @@ -AddCSLuaFile( ) - -ENT.Type = "anim" - -ENT.PrintName = "breakable_entry" -ENT.Author = "Alig96" -ENT.Contact = "Don't" -ENT.Purpose = "" -ENT.Instructions = "" -//models/props_interiors/elevatorshaft_door01a.mdl -//models/props_debris/wood_board02a.mdl -function ENT:Initialize() - - self:SetModel("models/props_c17/fence01b.mdl") - self:SetMoveType( MOVETYPE_NONE ) - self:SetSolid( SOLID_VPHYSICS ) - - self:SetHealth(0) - self:SetCustomCollisionCheck(true) - self.NextPlank = CurTime() - - self.Planks = {} - - if SERVER then - self:ResetPlanks() - end -end - -function ENT:AddPlank() - self:SpawnPlank() - self:SetHealth(self:Health()+10) - print("Health: " .. self:Health()) -end - -function ENT:RemovePlank() - - local plank = table.Random(self.Planks) - if plank != nil then - table.RemoveByValue(self.Planks, plank) - self:SetHealth(self:Health()-10) - - //Drop off - plank:SetParent(nil) - plank:PhysicsInit(SOLID_VPHYSICS) - local entphys = plank:GetPhysicsObject() - if entphys:IsValid() then - entphys:EnableGravity(true) - entphys:Wake() - end - plank:SetCollisionGroup( COLLISION_GROUP_DEBRIS ) - //Remove - timer.Simple(2, function() plank:Remove() end) - end -end - -function ENT:ResetPlanks() - for i=1, nz.Config.MaxPlanks do - self:RemovePlank() - end - for i=1, nz.Config.MaxPlanks do - self:AddPlank() - end -end - -function ENT:Use( activator, caller ) - if CurTime() > self.NextPlank then - if self:Health() < nz.Config.MaxPlanks * 10 then - self:AddPlank() - activator:GivePoints(10) - self.NextPlank = CurTime() + 1 - end - end -end - -function ENT:SpawnPlank() - //Spawn - local angs = {-60,-70,60,70} - local plank = ents.Create("breakable_entry_plank") - plank:SetPos( self:GetPos()+Vector(0,0, math.random( -45, 45 )) ) - plank:SetAngles( Angle(0,self:GetAngles().y, table.Random(angs)) ) - plank:Spawn() - plank:SetParent(self) - plank:SetCollisionGroup( COLLISION_GROUP_DEBRIS ) - table.insert(self.Planks, plank) -end - -hook.Add("ShouldCollide", "zCollisionHook", function(ent1, ent2) - if ent1:GetClass() == "breakable_entry" and ent2:GetClass() == "nut_zombie" then - if ent1:IsValid() and ent1:Health() == 0 then - ent1:SetSolid(SOLID_NONE) - timer.Simple(0.1, function() if ent1:IsValid() then ent1:SetSolid(SOLID_VPHYSICS) end end) - end - return false - end - if ent2:GetClass() == "breakable_entry" and ent1:GetClass() == "nut_zombie" then - if ent2:IsValid() and ent2:Health() == 0 then - ent2:SetSolid(SOLID_NONE) - timer.Simple(0.1, function() if ent2:IsValid() then ent2:SetSolid(SOLID_VPHYSICS) end end) - end - return false - end -end) - -if CLIENT then - function ENT:Draw() - if nz.Rounds.Data.CurrentState == ROUND_CREATE then - self:DrawModel() - end - end -end diff --git a/nzombies3/entities/entities/drop_powerup/shared.lua b/nzombies3/entities/entities/drop_powerup/shared.lua deleted file mode 100644 index 85146962..00000000 --- a/nzombies3/entities/entities/drop_powerup/shared.lua +++ /dev/null @@ -1,80 +0,0 @@ -AddCSLuaFile() - -ENT.Type = "anim" - -ENT.PrintName = "drop_powerups" -ENT.Author = "Alig96" -ENT.Contact = "Don't" -ENT.Purpose = "" -ENT.Instructions = "" - -function ENT:SetupDataTables() - - self:NetworkVar( "String", 0, "PowerUp" ) - -end - -function ENT:Initialize() - - //self:SetPowerUp("dp") - self:SetModelScale(nz.PowerUps.Functions.Get(self:GetPowerUp()).scale, 0) - - self:PhysicsInit(SOLID_VPHYSICS) - self:SetMoveType(MOVETYPE_NONE) - self:SetSolid(SOLID_VPHYSICS) - self.DeathTimer = 30 - if SERVER then - self:SetUseType(SIMPLE_USE) - local phys = self:GetPhysicsObject() - if (phys:IsValid()) then - phys:Wake() - --phys:EnableCollisions(false) - end - end - timer.Create( self:EntIndex().."_deathtimer", 0.1, 300, function() - if self:IsValid() then - self.DeathTimer = self.DeathTimer - 0.1 - if self.DeathTimer <= 0 then - timer.Destroy(self:EntIndex().."_deathtimer") - if SERVER then - self:Remove() - end - end - end - end) -end - -if SERVER then - function ENT:StartTouch(hitEnt) - if (hitEnt:IsValid() and hitEnt:IsPlayer()) then - nz.PowerUps.Functions.Activate(self:GetPowerUp(), hitEnt) - self:Remove() - end - end -end - -if CLIENT then - function ENT:Draw() - - local modi,modf = math.modf(self.DeathTimer) - if modi > 10 then - self:DrawModel() - elseif modi > 5 and modi <= 10 then - if modi % 2 == 0 then - self:DrawModel() - end - else - if math.Round(modf*10) % 2 == 0 then - self:DrawModel() - end - end - end - local num = 0 - function ENT:Think() - local var = math.sin( CurTime() * 3 ) - self:SetPos(Vector(self:GetPos().X, self:GetPos().Y, self:GetPos().Z +1*var)) - end - hook.Add( "PreDrawHalos", "drop_powerups_halos", function() - halo.Add( ents.FindByClass( "drop_powerup" ), Color( 0, 255, 0 ), 2, 2, 2 ) - end ) -end \ No newline at end of file diff --git a/nzombies3/entities/entities/nut_zombie.lua b/nzombies3/entities/entities/nut_zombie.lua deleted file mode 100644 index 904ffba7..00000000 --- a/nzombies3/entities/entities/nut_zombie.lua +++ /dev/null @@ -1,278 +0,0 @@ -AddCSLuaFile() - -ENT.Base = "base_nextbot" -ENT.PrintName = "Zombie" -ENT.Category = "Dissolution" -ENT.Author = "Chessnut" -ENT.Spawnable = true -ENT.AdminOnly = true - -for i = 2, 4 do - util.PrecacheModel("models/zed/malezed_0"..(i * 2)..".mdl") -end - -function ENT:Initialize() - self:SetModel("models/zed/malezed_0"..(math.random(2, 4) * 2)..".mdl") - self.breathing = CreateSound(self, "npc/zombie_poison/pz_breathe_loop1.wav") - self.breathing:Play() - self.breathing:ChangePitch(60, 0) - self.breathing:ChangeVolume(0.1, 0) - self.loco:SetDeathDropHeight(700) - if SERVER then - self:SetHealth(nz.Curves.Data.Health[nz.Rounds.Data.CurrentRound]) - end - self:SetCollisionBounds(Vector(-12,-12, 0), Vector(12, 12, 64)) - self:SetSkin(math.random(0, self:SkinCount() - 1)) - - hook.Add("EntityRemoved", self, function() - if (self.breathing) then - self.breathing:Stop() - self.breathing = nil - end - end) -end - -function ENT:TimedEvent(time, callback) - timer.Simple(time, function() - if (IsValid(self)) then - callback() - end - end) -end - -function ENT:GetPriorityEnemy() - local pos = self:GetPos() - - local min_dist, closest_target = -1, nil - - for _, target in pairs(player.GetAll()) do - if (IsValid(target)&&target:Alive()&&target:GetMoveType()==MOVETYPE_WALK) then - local dist = target:NearestPoint(pos):Distance(pos) - if ((dist < min_dist||min_dist==-1)) then - closest_target = target - min_dist = dist - end - end - end - - return closest_target -end - -function ENT:RunBehaviour() - while (true) do - local target = self.target - - if (IsValid(target) and target:Alive()) then - local data = {} - data.start = self:GetPos() - data.endpos = self:GetPos() + self:GetForward()*128 - data.filter = self - data.mins = self:OBBMins() * 0.65 - data.maxs = self:OBBMaxs() * 0.65 - local trace = util.TraceHull(data) - local entity = trace.Entity - - //Barricades - if (IsValid(entity) and entity:GetClass() == "breakable_entry" ) then - if entity:Health() != 0 then - timer.Simple(0.3, function() - - entity:EmitSound("physics/wood/wood_plank_break"..math.random(1, 4)..".wav", 100, math.random(90, 130)) - - entity:RemovePlank() - - end) - - self:PlaySequenceAndWait("swing", 1) - end - end - end - - if (IsValid(target) and target:Alive() ) then --and self:GetRangeTo(target) <= 1500 - self.loco:FaceTowards(target:GetPos()) - - if (self:GetRangeTo(target) <= 42) then - self:EmitSound("npc/zombie_poison/pz_throw2.wav", 50, math.random(75, 125)) - - self:TimedEvent(0.3, function() - self:EmitSound("npc/vort/claw_swing"..math.random(1, 2)..".wav") - end) - - self:TimedEvent(0.4, function() - if (IsValid(target) and self:GetRangeTo(target) <= 50) then - local damageInfo = DamageInfo() - damageInfo:SetAttacker(self) - damageInfo:SetDamage(math.random(5, 10)) - damageInfo:SetDamageType(DMG_CLUB) - - local force = target:GetAimVector() * -300 - force.z = 16 - - damageInfo:SetDamageForce(force) - target:TakeDamageInfo(damageInfo) - target:EmitSound("npc/zombie/zombie_hit.wav", 50, math.random(80, 160)) - target:ViewPunch(VectorRand():Angle() * 0.1) - target:SetVelocity(force) - end - end) - - self:TimedEvent(0.45, function() - if (IsValid(target) and !target:Alive()) then - target.target = nil - end - end) - - self:PlaySequenceAndWait("swing", 1) - else - if nz.Curves.Data.Speed[nz.Rounds.Data.CurrentRound] >= 160 then - self:StartActivity(ACT_RUN) - else - self:StartActivity(ACT_WALK) - end - if (self.breathing) then - self.breathing:ChangePitch(80, 1) - self.breathing:ChangeVolume(1.25, 1) - end - - if (math.random(1, 2) == 2 and (self.nextYell or 0) < CurTime()) then - self:EmitSound("npc/zombie_poison/pz_pain"..math.random(1, 3)..".wav", 40, math.random(30, 50)) - self.nextYell = CurTime() + math.random(4, 8) - end - - self.loco:SetDesiredSpeed(nz.Curves.Data.Speed[nz.Rounds.Data.CurrentRound]) - self:MoveToPos(target:GetPos(), { - maxage = 0.67 - }) - end - else - self.target = nil - self:StartActivity(ACT_WALK) - self.loco:SetDesiredSpeed(40) - self:MoveToPos(self:GetPos() + Vector(math.random(-256, 256), math.random(-256, 256), 0), { - repath = 3, - maxage = 2 - }) - - if (math.random(1, 8) == 2) then - self:EmitSound("npc/zombie/zombie_voice_idle"..math.random(2, 7)..".wav", 50, 60) - - if (math.random(1, 2) == 2) then - self:PlaySequenceAndWait("scaredidle") - else - self:PlaySequenceAndWait("photo_react_startle") - end - end - //New AI Stuffz - if (!self.target) then - local v = self:GetPriorityEnemy() - self.target = v - self:AlertNearby(v) - self.target = v - self:PlaySequenceAndWait("wave_smg1", 0.9) - end - end - coroutine.yield() - end -end - -function ENT:Think() - //Retarget closest players. Don't put this in the function above or else mass lag due to constant rethinking of target - self.target = self:GetPriorityEnemy() - self:NextThink(4) -end - -function ENT:AlertNearby(target, range, noNoise) - range = range or 2400 - noNoise = noNoise or (#ents.FindByClass("nut_zombie") < 1) - - if (IsValid(self.target)) then - return - end - - for k, v in pairs(ents.FindByClass("nut_zombie")) do - if (self != v and !IsValid(v.target) and self:GetRangeTo(v) <= range) then - timer.Create("zombieAlert_"..v:EntIndex(), self:GetRangeTo(v) / 800, 1, function() - if (!IsValid(v) or !IsValid(target)) then - return - end - - v.target = target - v:EmitSound("npc/zombie/zombie_alert"..math.random(1, 3)..".wav", 50, math.random(60, 120)) - v:AlertNearby(target, range + 640) - end) - - noNoise = false - end - end - - if (!noNoise) then - self:EmitSound("npc/zombie_poison/pz_call1.wav", 50, 120) - end -end - -function ENT:OnLandOnGround() - self:EmitSound("physics/flesh/flesh_impact_hard"..math.random(1, 6)..".wav") -end - -local deathSounds = { - "npc/zombie_poison/pz_die1.wav", - "npc/zombie_poison/pz_die2.wav", - "npc/zombie/zombie_die1.wav", - "npc/zombie/zombie_die3.wav" -} - -function ENT:OnKilled(damageInfo) - local attacker = damageInfo:GetAttacker() - - if (IsValid(attacker) and self:GetRangeTo(attacker) <= 4800) then - self:AlertNearby(attacker, 1600, true) - else - local entities = ents.FindInSphere(self:GetPos(), 2400) - - for k, v in pairs(entities) do - if (v:IsPlayer()) then - self:AlertNearby(v, 2400, true) - - break - end - end - end - - self:EmitSound(table.Random(deathSounds), 50, math.random(75, 130)) - self:BecomeRagdoll(damageInfo) - - nz.Enemies.Functions.OnEnemyKilled( self, attacker ) - -end - -local painSounds = { - "npc/zombie_poison/pz_pain1.wav", - "npc/zombie_poison/pz_pain2.wav", - "npc/zombie_poison/pz_pain3.wav", - "npc/zombie/zombie_die1.wav", - "npc/zombie/zombie_die2.wav", - "npc/zombie/zombie_die3.wav" -} - -function ENT:OnInjured(damageInfo) - local attacker = damageInfo:GetAttacker() - local hitgroup = util.QuickTrace( damageInfo:GetDamagePosition( ), damageInfo:GetDamagePosition( ) ).HitGroup - local range = self:GetRangeTo(attacker) - //Deal an double damage if headshot - if hitgroup == HITGROUP_HEAD then - if self:IsValid() and damageInfo:GetDamageType() != DMG_BLAST_SURFACE then - local headshot = DamageInfo() - headshot:SetDamage(damageInfo:GetDamage( )) - headshot:SetAttacker(attacker) - headshot:SetDamageType(DMG_BLAST_SURFACE) - print("Headshot! ", headshot:GetDamage( )) - //Delay so it doesn't "die" twice - timer.Simple(0.1, function() if self:IsValid() then self:TakeDamageInfo( headshot ) end end) - end - end - self:EmitSound(table.Random(painSounds), 50, math.random(50, 130)) - self.target = attacker - self:AlertNearby(attacker, 1000) - - nz.Enemies.Functions.OnEnemyHurt( self, attacker, hitgroup ) -end diff --git a/nzombies3/entities/entities/perk_machine/shared.lua b/nzombies3/entities/entities/perk_machine/shared.lua deleted file mode 100644 index 02279c74..00000000 --- a/nzombies3/entities/entities/perk_machine/shared.lua +++ /dev/null @@ -1,62 +0,0 @@ -AddCSLuaFile() - -ENT.Type = "anim" - -ENT.PrintName = "perk_machine" -ENT.Author = "Alig96" -ENT.Contact = "Don't" -ENT.Purpose = "" -ENT.Instructions = "" - -function ENT:SetupDataTables() - self:NetworkVar("String", 0, "PerkID") - self:NetworkVar("Bool", 0, "Active") -end - -function ENT:Initialize() - if SERVER then - self:SetMoveType( MOVETYPE_NONE ) - self:SetSolid( SOLID_VPHYSICS ) - self:DrawShadow( false ) - self:SetUseType( SIMPLE_USE ) - end -end - -function ENT:TurnOn() - local perkData = nz.Perks.Functions.Get(self:GetPerkID()) - self:SetModel(perkData.on_model) - self:SetActive(true) -end - -function ENT:TurnOff() - local perkData = nz.Perks.Functions.Get(self:GetPerkID()) - self:SetModel(perkData.off_model) - self:SetActive(false) -end - -function ENT:IsOn() - return self:GetActive() -end - -function ENT:Use(activator, caller) - local perkData = nz.Perks.Functions.Get(self:GetPerkID()) - - if self:IsOn() then - local price = perkData.price - //If they have enough money - if activator:CanAfford(price) then - if !activator:HasPerk(self:GetPerkID()) then - activator:TakePoints(price) - activator:GivePerk(self:GetPerkID()) - else - print("already have perk") - end - end - end -end - -if CLIENT then - function ENT:Draw() - self:DrawModel() - end -end \ No newline at end of file diff --git a/nzombies3/entities/entities/prop_buys/shared.lua b/nzombies3/entities/entities/prop_buys/shared.lua deleted file mode 100644 index 5f34c3c1..00000000 --- a/nzombies3/entities/entities/prop_buys/shared.lua +++ /dev/null @@ -1,63 +0,0 @@ -AddCSLuaFile( ) - -ENT.Type = "anim" - -ENT.PrintName = "wall_block_buy" -ENT.Author = "Alig96" -ENT.Contact = "Don't" -ENT.Purpose = "" -ENT.Instructions = "" - -function ENT:SetupDataTables() - - self:NetworkVar( "Bool", 0, "Locked" ) - -end - -function ENT:Initialize() - if SERVER then - self:SetMoveType( MOVETYPE_NONE ) - self:SetSolid( SOLID_VPHYSICS ) - self:DrawShadow( false ) - self:SetUseType( SIMPLE_USE ) - self.Boundone,self.Boundtwo = self:GetCollisionBounds() - end - self:BlockLock() -end - -function ENT:BlockUnlock() - self.Locked = false - --self:SetNoDraw( true ) - if SERVER then - self:SetCollisionBounds( Vector(-4, -4, 0), Vector(4, 4, 64) ) - end - self:SetSolid( SOLID_NONE ) - self:SetLocked(false) -end - -function ENT:BlockLock() - self.Locked = true - --self:SetNoDraw( false ) - if SERVER then - self:SetCollisionBounds( self.Boundone, self.Boundtwo ) - end - self:SetSolid( SOLID_VPHYSICS ) - self:SetLocked(true) -end - -if CLIENT then - function ENT:Draw() - if (nz.Rounds.Data.CurrentState == ROUND_PROG or nz.Rounds.Data.CurrentState == ROUND_PREP) then - if self:GetLocked() then - self:DrawModel() - end - else - self:DrawModel() - end - if nz.Rounds.Data.CurrentState == ROUND_CREATE then - if nz.Doors.Data.DisplayLinks[self] != nil then - nz.Display.Functions.DrawLinks(self, nz.Doors.Data.BuyableProps[self:EntIndex()].link) - end - end - end -end \ No newline at end of file diff --git a/nzombies3/entities/entities/random_box/shared.lua b/nzombies3/entities/entities/random_box/shared.lua deleted file mode 100644 index 3725736d..00000000 --- a/nzombies3/entities/entities/random_box/shared.lua +++ /dev/null @@ -1,153 +0,0 @@ -AddCSLuaFile( ) - -ENT.Type = "anim" - -ENT.PrintName = "random_box" -ENT.Author = "Alig96" -ENT.Contact = "Don't" -ENT.Purpose = "" -ENT.Instructions = "" - -function ENT:SetupDataTables() - - self:NetworkVar( "Bool", 0, "Open" ) - -end - -function ENT:Initialize() - - self:SetModel( "models/hoff/props/mysterybox/box.mdl" ) - self:PhysicsInit( SOLID_VPHYSICS ) - self:SetMoveType( MOVETYPE_NONE ) - self:SetSolid( SOLID_VPHYSICS ) - - local phys = self:GetPhysicsObject() - if (phys:IsValid()) then - phys:Wake() - end - - self:DrawShadow( false ) - self:AddEffects( EF_ITEM_BLINK ) - self:SetOpen(false) - self.Moving = false - self:Activate() - if SERVER then - self:SetUseType( SIMPLE_USE ) - end -end - -function ENT:Use( activator, caller ) - if self:GetOpen() == true or self.Moving then return end - self:BuyWeapon(activator) - //timer.Simple(5,function() self:MoveAway() end) -end - -function ENT:BuyWeapon(ply) - if ply:CanAfford(950) then - local class = nz.RandomBox.Functions.DecideWep(ply) - if class != nil then - ply:TakePoints(950) - self:Open() - local wep = self:SpawnWeapon( ply, class ) - else - ply:PrintMessage( HUD_PRINTTALK, "No available weapons left!") - end - else - ply:PrintMessage( HUD_PRINTTALK, "You can't afford this!") - end -end - - -function ENT:Open() - local sequence = self:LookupSequence("Close") - self:ResetSequence(sequence) - self:RemoveEffects( EF_ITEM_BLINK ) - - self:SetOpen(true) -end - -function ENT:Close() - local sequence = self:LookupSequence("Open") - self:ResetSequence(sequence) - self:AddEffects( EF_ITEM_BLINK ) - - self:SetOpen(false) -end - -function ENT:SpawnWeapon(activator, class) - local wep = ents.Create("random_box_windup") - wep:Spawn() - wep:SetPos( self:GetPos( ) - Vector(0,0,-10) ) - wep.Buyer = activator - wep:SetParent( self ) - wep:SetWepClass(class) - - return wep -end - -function ENT:Think() - self:NextThink(CurTime()) - return true -end - -function ENT:MoveAway() - self.Moving = true - local s = 0 - //Shake Effect - timer.Create( "shake", 0.1, 300, function() - if s < 30 then - if s % 2 == 0 then - if self:IsValid() then - self:SetAngles(Angle(10, 0, 0)) - end - else - if self:IsValid() then - self:SetAngles(Angle(-10, 0, 0)) - end - end - else - timer.Destroy("shake") - end - s = s + 1 - end) - - //Move Up - timer.Simple( 1, function() - local c = 0 - timer.Create( "moveAway", 0.1, 300, function() - if c == 65 then - self.Moveing = false - timer.Destroy("moveAway") - timer.Destroy("shake") - - self:Remove() - else - if c < 30 then - c = c + 1 - else - c = c + 5 - end - self:SetPos(Vector(self:GetPos().X, self:GetPos().Y, self:GetPos().Z + c)) - end - end ) - end) - - -end - -if CLIENT then - function ENT:Draw() - self:DrawModel() - end - - hook.Add( "PostDrawOpaqueRenderables", "random_box_beam", function() - for k,v in pairs(ents.FindByClass("random_box")) do - if ( LocalPlayer():GetPos():Distance( v:GetPos() ) ) > 750 then - local Vector1 = v:LocalToWorld( Vector( 0, 0, -200 ) ) - local Vector2 = v:LocalToWorld( Vector( 0, 0, 5000 ) ) - render.SetMaterial( Material( "cable/redlaser" ) ) - render.DrawBeam( Vector1, Vector2, 300, 1, 1, Color( 255, 255, 255, 255 ) ) - end - end - end ) -end diff --git a/nzombies3/entities/entities/random_box_spawns/shared.lua b/nzombies3/entities/entities/random_box_spawns/shared.lua deleted file mode 100644 index a9aa5bc3..00000000 --- a/nzombies3/entities/entities/random_box_spawns/shared.lua +++ /dev/null @@ -1,27 +0,0 @@ -AddCSLuaFile( ) - -ENT.Type = "anim" - -ENT.PrintName = "random_box_spawns" -ENT.Author = "Alig96" -ENT.Contact = "Don't" -ENT.Purpose = "" -ENT.Instructions = "" - - -function ENT:Initialize() - self:SetModel( "models/hoff/props/mysterybox/box.mdl" ) - self:SetColor( 255, 255, 255 ) - self:SetMoveType( MOVETYPE_NONE ) - self:SetSolid( SOLID_VPHYSICS ) - self:SetCollisionGroup( COLLISION_GROUP_WEAPON ) - self:DrawShadow( false ) -end - -if CLIENT then - function ENT:Draw() - if nz.Rounds.Data.CurrentState == ROUND_CREATE then - self:DrawModel() - end - end -end \ No newline at end of file diff --git a/nzombies3/entities/entities/random_box_windup/shared.lua b/nzombies3/entities/entities/random_box_windup/shared.lua deleted file mode 100644 index 73e81545..00000000 --- a/nzombies3/entities/entities/random_box_windup/shared.lua +++ /dev/null @@ -1,89 +0,0 @@ -AddCSLuaFile( ) - -ENT.Type = "anim" - -ENT.PrintName = "random_box_windup" -ENT.Author = "Alig96" -ENT.Contact = "Don't" -ENT.Purpose = "" -ENT.Instructions = "" - -function ENT:SetupDataTables() - - self:NetworkVar( "Bool", 0, "Winding" ) - self:NetworkVar( "String", 0, "WepClass") - -end - -function ENT:Initialize() - - self:SetMoveType( MOVETYPE_NONE ) - self:SetSolid( SOLID_VPHYSICS ) - self:DrawShadow( false ) - - self:SetWinding(true) - self.c = 0 - self.s = -20 - self:SetModel("models/weapons/w_rif_ak47.mdl") - - if SERVER then - //Stop winding up - timer.Simple(7, function() self:SetWinding(false) self:SetModel(weapons.Get(self:GetWepClass()).WorldModel) end) - //If we time out, remove the object - timer.Simple(18, function() if self:IsValid() then self:GetParent():Close() self:Remove() end end) - end -end - -function ENT:Use( activator, caller ) - if !self:GetWinding() then - if activator == self.Buyer then - local class = self:GetWepClass() - activator:Give(class) - nz.Weps.Functions.GiveMaxAmmoWep(activator, class) - self:GetParent():Close() - self:Remove() - else - if self.Buyer:IsValid() then - activator:PrintMessage( HUD_PRINTTALK, "This is " .. self.Buyer:Nick() .. "'s gun. You cannot take it." ) - end - end - end -end - -function ENT:WindUp( ) - local gun = table.Random(weapons.GetList()) - if gun.WorldModel != nil then - self:SetModel(gun.WorldModel) - end - self.c = self.c + 1 - if self.c > 7 then - self.c = 7 - end - self:SetPos(Vector(self:GetPos().X, self:GetPos().Y, self:GetPos().Z + 0.1*self.c)) -end - -function ENT:WindDown( ) - self.s = self.s + 1 - if self.s > 7 then - self.s = 7 - end - if self.s >= 0 then - self:SetPos(Vector(self:GetPos().X, self:GetPos().Y, self:GetPos().Z - 0.1*self.s)) - end -end - -function ENT:Think() - if SERVER then - if self:GetWinding() then - self:WindUp() - else - self:WindDown() - end - end -end - -if CLIENT then - function ENT:Draw() - self:DrawModel() - end -end diff --git a/nzombies3/entities/entities/wall_block/shared.lua b/nzombies3/entities/entities/wall_block/shared.lua deleted file mode 100644 index fdb6607c..00000000 --- a/nzombies3/entities/entities/wall_block/shared.lua +++ /dev/null @@ -1,24 +0,0 @@ -AddCSLuaFile( ) - -ENT.Type = "anim" - -ENT.PrintName = "wall_block" -ENT.Author = "Alig96" -ENT.Contact = "Don't" -ENT.Purpose = "" -ENT.Instructions = "" - -function ENT:Initialize() - self:SetMoveType( MOVETYPE_NONE ) - self:SetSolid( SOLID_VPHYSICS ) - self:DrawShadow( false ) - self:SetRenderMode( RENDERMODE_TRANSCOLOR ) -end - -if CLIENT then - function ENT:Draw() - if nz.Rounds.Data.CurrentState == ROUND_CREATE then - self:DrawModel() - end - end -end \ No newline at end of file diff --git a/nzombies3/entities/entities/wall_buys/shared.lua b/nzombies3/entities/entities/wall_buys/shared.lua deleted file mode 100644 index 861eb438..00000000 --- a/nzombies3/entities/entities/wall_buys/shared.lua +++ /dev/null @@ -1,75 +0,0 @@ -AddCSLuaFile( ) - -ENT.Type = "anim" - -ENT.PrintName = "buy_gun_area" -ENT.Author = "Alig96" -ENT.Contact = "Don't" -ENT.Purpose = "" -ENT.Instructions = "" - -function ENT:SetupDataTables() - - self:NetworkVar( "String", 0, "EntName" ) - self:NetworkVar( "String", 1, "Price" ) -end - -if SERVER then - function ENT:Initialize() - self:SetMoveType( MOVETYPE_NONE ) - self:SetSolid( SOLID_VPHYSICS ) - self:SetUseType(SIMPLE_USE) - end - - function ENT:SetWeapon(weapon, price) - //Add a special check for FAS weps - if weapons.Get(weapon).Category == "FA:S 2 Weapons" then - //self:SetModel( weapons.Get(weapon).WM ) - self:SetModel( weapons.Get(weapon).WorldModel ) - else - self:SetModel( weapons.Get(weapon).WorldModel ) - end - self:SetModelScale( 1.5, 0 ) - self.WeaponGive = weapon - self.Price = price - self:SetEntName(weapon) - self:SetPrice(price) - end - - function ENT:Use( activator, caller ) - local price = self.Price - local ammo_type = weapons.Get(self.WeaponGive).Primary.Ammo - local ammo_price = math.Round((price - (price % 10))/2) - local curr_ammo = activator:GetAmmoCount( ammo_type ) - local give_ammo = nz.Weps.Functions.CalculateMaxAmmo(self.WeaponGive) - curr_ammo - - - if !activator:HasWeapon( self.WeaponGive ) then - if activator:CanAfford(price) then - activator:TakePoints(price) - activator:Give(self.WeaponGive) - nz.Weps.Functions.GiveMaxAmmoWep(activator, self.WeaponGive) - else - print("Can't afford!") - end - else // Refill ammo - if activator:CanAfford(ammo_price) then - if give_ammo != 0 then - activator:TakePoints(ammo_price) - nz.Weps.Functions.GiveMaxAmmoWep(activator, self.WeaponGive) - else - print("Max Clip!") - end - else - print("Can't afford!") - end - end - return - end -end - -if CLIENT then - function ENT:Draw() - self:DrawModel() - end -end diff --git a/nzombies3/entities/entities/zed_spawns/shared.lua b/nzombies3/entities/entities/zed_spawns/shared.lua deleted file mode 100644 index b4938545..00000000 --- a/nzombies3/entities/entities/zed_spawns/shared.lua +++ /dev/null @@ -1,32 +0,0 @@ -AddCSLuaFile( ) - -ENT.Type = "anim" - -ENT.PrintName = "zed_spawns" -ENT.Author = "Alig96" -ENT.Contact = "Don't" -ENT.Purpose = "" -ENT.Instructions = "" - -function ENT:SetupDataTables() - - self:NetworkVar( "String", 0, "Link" ) - -end - -function ENT:Initialize() - self:SetModel( "models/player/odessa.mdl" ) - self:SetMoveType( MOVETYPE_NONE ) - self:SetSolid( SOLID_VPHYSICS ) - self:SetCollisionGroup( COLLISION_GROUP_WEAPON ) - self:SetColor(255, 0, 0, 255) - self:DrawShadow( false ) -end - -if CLIENT then - function ENT:Draw() - if nz.Rounds.Data.CurrentState == ROUND_CREATE then - self:DrawModel() - end - end -end diff --git a/nzombies3/entities/weapons/nz_tool_barricades.lua b/nzombies3/entities/weapons/nz_tool_barricades.lua deleted file mode 100644 index bebd3efe..00000000 --- a/nzombies3/entities/weapons/nz_tool_barricades.lua +++ /dev/null @@ -1,17 +0,0 @@ -SWEP.PrintName = "Barricade Tool" -SWEP.Author = "Alig96" -SWEP.Slot = 1 -SWEP.SlotPos = 9 -SWEP.Base = "nz_tool_base" - -if SERVER then - function SWEP:OnPrimaryAttack( trace ) - nz.Mapping.Functions.BreakEntry(trace.HitPos,Angle(0,0,0)) - end - - function SWEP:OnSecondaryAttack( trace ) - if trace.Entity:GetClass() == "breakable_entry" then - trace.Entity:Remove() - end - end -end \ No newline at end of file diff --git a/nzombies3/entities/weapons/nz_tool_block_spawns.lua b/nzombies3/entities/weapons/nz_tool_block_spawns.lua deleted file mode 100644 index d1c6a3de..00000000 --- a/nzombies3/entities/weapons/nz_tool_block_spawns.lua +++ /dev/null @@ -1,17 +0,0 @@ -SWEP.PrintName = "Invisible Block Spawn Placer Tool" -SWEP.Author = "Alig96" -SWEP.Slot = 4 -SWEP.SlotPos = 10 -SWEP.Base = "nz_tool_base" - -if SERVER then - function SWEP:OnPrimaryAttack( trace ) - nz.Mapping.Functions.BlockSpawn(trace.HitPos,Angle(90,0,0), "models/hunter/plates/plate2x2.mdl") - end - - function SWEP:OnSecondaryAttack( trace ) - if trace.Entity:GetClass() == "wall_block" then - trace.Entity:Remove() - end - end -end \ No newline at end of file diff --git a/nzombies3/entities/weapons/nz_tool_door_locker.lua b/nzombies3/entities/weapons/nz_tool_door_locker.lua deleted file mode 100644 index 5c9bd327..00000000 --- a/nzombies3/entities/weapons/nz_tool_door_locker.lua +++ /dev/null @@ -1,30 +0,0 @@ -SWEP.PrintName = "Door Locker Tool" -SWEP.Author = "Alig96" -SWEP.Slot = 3 -SWEP.SlotPos = 10 -SWEP.Base = "nz_tool_base" - -if SERVER then - function SWEP:OnPrimaryAttack( trace ) - if trace.Entity:IsDoor() or trace.Entity:IsBuyableProp() then - //nz.Doors.Functions.CreateLink( trace.Entity, "price=500,elec=0,link=1" ) - nz.Interfaces.Functions.SendInterface(self.Owner, "DoorProps", {door = trace.Entity}) - else - print("Not a door.") - end - end - - function SWEP:OnSecondaryAttack( trace ) - if trace.Entity:IsDoor() or trace.Entity:IsBuyableProp() then - nz.Doors.Functions.RemoveLink( trace.Entity ) - else - print("Not a door.") - end - end - //Display Links - function SWEP:OnReload( trace ) - if trace.Entity:IsDoor() or trace.Entity:IsBuyableProp() then - nz.Doors.Functions.DisplayDoorLinks( trace.Entity ) - end - end -end diff --git a/nzombies3/entities/weapons/nz_tool_elec.lua b/nzombies3/entities/weapons/nz_tool_elec.lua deleted file mode 100644 index 5dd42419..00000000 --- a/nzombies3/entities/weapons/nz_tool_elec.lua +++ /dev/null @@ -1,15 +0,0 @@ -SWEP.PrintName = "Electric Placer Tool" -SWEP.Author = "Alig96" -SWEP.Slot = 5 -SWEP.SlotPos = 9 -SWEP.Base = "nz_tool_base" - -if SERVER then - function SWEP:OnPrimaryAttack( trace ) - nz.Mapping.Functions.Electric(trace.HitPos, trace.HitNormal:Angle() - Angle( 270, 0, 0 )) - end - - function SWEP:OnSecondaryAttack( trace ) - - end -end \ No newline at end of file diff --git a/nzombies3/entities/weapons/nz_tool_perk_machine.lua b/nzombies3/entities/weapons/nz_tool_perk_machine.lua deleted file mode 100644 index d665fafa..00000000 --- a/nzombies3/entities/weapons/nz_tool_perk_machine.lua +++ /dev/null @@ -1,25 +0,0 @@ -SWEP.PrintName = "Perk Machine Spawn Placer Tool" -SWEP.Author = "Alig96" -SWEP.Slot = 5 -SWEP.SlotPos = 8 -SWEP.Base = "nz_tool_base" - -if SERVER then - - function SWEP:OnPrimaryAttack( trace ) - nz.Mapping.Functions.PerkMachine(trace.HitPos, Angle(0,0,0), "jugg") - end - - function SWEP:OnSecondaryAttack( trace ) - if trace.Entity:GetClass() == "perk_machine" then - trace.Entity:Remove() - end - end - - function SWEP:OnReload( trace ) - if trace.Entity:GetClass() == "perk_machine" then - nz.Interfaces.Functions.SendInterface(self.Owner, "PerkMachine", {ent = trace.Entity}) - end - end - -end diff --git a/nzombies3/entities/weapons/nz_tool_player_spawns.lua b/nzombies3/entities/weapons/nz_tool_player_spawns.lua deleted file mode 100644 index a699c470..00000000 --- a/nzombies3/entities/weapons/nz_tool_player_spawns.lua +++ /dev/null @@ -1,17 +0,0 @@ -SWEP.PrintName = "Player Spawn Placer Tool" -SWEP.Author = "Alig96" -SWEP.Slot = 1 -SWEP.SlotPos = 9 -SWEP.Base = "nz_tool_base" - -if SERVER then - function SWEP:OnPrimaryAttack( trace ) - nz.Mapping.Functions.PlayerSpawn(trace.HitPos) - end - - function SWEP:OnSecondaryAttack( trace ) - if trace.Entity:GetClass() == "player_spawns" then - trace.Entity:Remove() - end - end -end \ No newline at end of file diff --git a/nzombies3/entities/weapons/nz_tool_prop_modifier.lua b/nzombies3/entities/weapons/nz_tool_prop_modifier.lua deleted file mode 100644 index d5965a7c..00000000 --- a/nzombies3/entities/weapons/nz_tool_prop_modifier.lua +++ /dev/null @@ -1,19 +0,0 @@ -SWEP.PrintName = "Prop Modifier Tool" -SWEP.Author = "Alig96" -SWEP.Slot = 2 -SWEP.SlotPos = 10 -SWEP.Base = "nz_tool_base" - -if SERVER then - function SWEP:OnPrimaryAttack( trace ) - if trace.Entity:GetClass() == "prop_buys" then - trace.Entity:SetAngles(Angle(0,0,0)) - end - end - - function SWEP:OnSecondaryAttack( trace ) - if trace.Entity:GetClass() == "prop_buys" then - trace.Entity:Remove() - end - end -end \ No newline at end of file diff --git a/nzombies3/entities/weapons/nz_tool_random_box.lua b/nzombies3/entities/weapons/nz_tool_random_box.lua deleted file mode 100644 index 5e6ab998..00000000 --- a/nzombies3/entities/weapons/nz_tool_random_box.lua +++ /dev/null @@ -1,17 +0,0 @@ -SWEP.PrintName = "Random Box Tool" -SWEP.Author = "Alig96" -SWEP.Slot = 5 -SWEP.SlotPos = 10 -SWEP.Base = "nz_tool_base" - -if SERVER then - function SWEP:OnPrimaryAttack( trace ) - nz.Mapping.Functions.BoxSpawn(trace.HitPos,Angle(0,0,0)) - end - - function SWEP:OnSecondaryAttack( trace ) - if trace.Entity:GetClass() == "random_box_spawns" then - trace.Entity:Remove() - end - end -end \ No newline at end of file diff --git a/nzombies3/entities/weapons/nz_tool_template.lua b/nzombies3/entities/weapons/nz_tool_template.lua deleted file mode 100644 index c58fd7ea..00000000 --- a/nzombies3/entities/weapons/nz_tool_template.lua +++ /dev/null @@ -1,18 +0,0 @@ -SWEP.PrintName = "Tool Name" -SWEP.Author = "UserName" -SWEP.Slot = 0 -SWEP.SlotPos = 10 -SWEP.Base = "nz_tool_base" - -if SERVER then - function SWEP:OnPrimaryAttack( trace ) - PrintTable(trace) - end - - function SWEP:OnSecondaryAttack( trace ) - PrintTable(trace) - end - function SWEP:OnReload( trace ) - print(trace) - end -end \ No newline at end of file diff --git a/nzombies3/entities/weapons/nz_tool_wall_buys.lua b/nzombies3/entities/weapons/nz_tool_wall_buys.lua deleted file mode 100644 index e648a3f2..00000000 --- a/nzombies3/entities/weapons/nz_tool_wall_buys.lua +++ /dev/null @@ -1,23 +0,0 @@ -SWEP.PrintName = "Weapon Placer Tool" -SWEP.Author = "Alig96" -SWEP.Slot = 2 -SWEP.SlotPos = 10 -SWEP.Base = "nz_tool_base" - -if SERVER then - function SWEP:OnPrimaryAttack( trace ) - //nz.Mapping.Functions.WallBuy(trace.HitPos, "fas2_ak47", 100, trace.HitNormal:Angle()+Angle(0,270,0)) - nz.Interfaces.Functions.SendInterface(self.Owner, "WepBuy", {vec = trace.HitPos, ang = trace.HitNormal:Angle()+Angle(0,270,0)}) - end - - function SWEP:OnSecondaryAttack( trace ) - if trace.Entity:GetClass() == "wall_buys" then - trace.Entity:Remove() - end - end - function SWEP:OnReload( trace ) - if trace.Entity:GetClass() == "wall_buys" then - trace.Entity:SetAngles(trace.Entity:GetAngles()+Angle(0,90,0)) - end - end -end diff --git a/nzombies3/entities/weapons/nz_tool_zed_spawns.lua b/nzombies3/entities/weapons/nz_tool_zed_spawns.lua deleted file mode 100644 index 3a321d07..00000000 --- a/nzombies3/entities/weapons/nz_tool_zed_spawns.lua +++ /dev/null @@ -1,23 +0,0 @@ -SWEP.PrintName = "Zombie Spawn Placer Tool" -SWEP.Author = "Alig96" -SWEP.Slot = 1 -SWEP.SlotPos = 10 -SWEP.Base = "nz_tool_base" - -if SERVER then - function SWEP:OnPrimaryAttack( trace ) - nz.Mapping.Functions.ZedSpawn(trace.HitPos) - end - - function SWEP:OnSecondaryAttack( trace ) - if trace.Entity:GetClass() == "zed_spawns" then - trace.Entity:Remove() - end - end - - function SWEP:OnReload( trace ) - if trace.Entity:GetClass() == "zed_spawns" then - nz.Interfaces.Functions.SendInterface(self.Owner, "ZombLink", {ent = trace.Entity, link = trace.Entity.link}) - end - end -end diff --git a/nzombies3/gamemode/config/sh_constructor.lua b/nzombies3/gamemode/config/sh_constructor.lua deleted file mode 100644 index f16cb9ba..00000000 --- a/nzombies3/gamemode/config/sh_constructor.lua +++ /dev/null @@ -1,85 +0,0 @@ -//Main Tables -nz.Config = {} -//nz.Config.Functions = {} -//nz.Config.Data = {} - -// Defaults -if SERVER then - - //Curves - - nz.Config.MaxRounds = 100 // How much round data should we load? - - //Spawn Rate Curve - nz.Config.BaseDifficultySpawnRateCurve = 5 - nz.Config.DifficultySpawnRateCurve = 1.01 - //Health Curve - nz.Config.BaseDifficultyHealthCurve = 75 - nz.Config.DifficultyHealthCurve = 0.4 - //Speed curve - nz.Config.BaseDifficultySpeedCurve = 60 - nz.Config.DifficultySpeedCurve = 0.55 - - //Display - - //Door_System - - //Electricity - - //Enemies - nz.Config.ValidEnemies = {"nut_zombie"} - nz.Config.EnemyTypes = {} - nz.Config.EnemyTypes[1] = {["nut_zombie"] = 100} - //nz.Config.EnemyTypes[4] = {["hellhounds"] = 100} - //nz.Config.EnemyTypes[4] = {["nut_zombie"] = 80, ["hellhounds"] = 20} - - //Max amount of zombies at the same time - nz.Config.MaxZombiesSim = 100 - - //Interfaces - - //Mapping - - //Misc - nz.Config.Halos = false // I seem to be getting a lot of lag because of this, so it is disabled here - - //Perks - - //Player Class - nz.Config.BaseStartingWeapons = {"fas2_glock20"} //"fas2_p226", "fas2_ots33", "fas2_glock20" "weapon_pistol" - //nz.Config.CustomConfigStartingWeps = true -- If this is set to false, the gamemode will avoid using custom weapons in configs - - //Points - nz.Config.BaseStartingPoints = 500 - - //Powerups - - //Props_Menu - - //Random Box - - nz.Config.WeaponBlackList = { - "weapon_base", "weapon_fists", "weapon_flechettegun", "weapon_medkit", - "weapon_dod_sim_base", "weapon_dod_sim_base_shot", "weapon_dod_sim_base_snip", "weapon_sim_admin", "weapon_sim_spade", - "fas2_base", "fas2_ammobox", "fas2_ifak", "fas2_base_shotgun", - "nz_tool_base", "nz_tool_barricades", "nz_tool_block_spawns", "nz_tool_door_locker", "nz_tool_elec", "nz_tool_perk_machine", "nz_tool_player_spawns", "nz_tool_prop_modifier", "nz_tool_random_box", "nz_tool_template", "nz_tool_wall_buys", "nz_tool_zed_spawns" - } - - //Round Handler - - //Time Between rounds - nz.Config.PrepareTime = 10 - - //Spectator - - nz.Config.AllowDropins = true - - - - -end - -//Shared - -//Barricades -nz.Config.MaxPlanks = 6 diff --git a/nzombies3/gamemode/curves/sh_constructor.lua b/nzombies3/gamemode/curves/sh_constructor.lua deleted file mode 100644 index 8164291a..00000000 --- a/nzombies3/gamemode/curves/sh_constructor.lua +++ /dev/null @@ -1,25 +0,0 @@ -//We only need this on the server -if SERVER then - //Main Tables - nz.Curves = {} - nz.Curves.Functions = {} - nz.Curves.Data = {} - - //Difficulty Curves - nz.Curves.Data.SpawnRate = {} - nz.Curves.Data.Health = {} - nz.Curves.Data.Speed = {} - - //Generate Curve - function nz.Curves.Functions.GenerateCurve() - for i=1, nz.Config.MaxRounds do - nz.Curves.Data.SpawnRate[i-1] = math.Round(nz.Config.BaseDifficultySpawnRateCurve*math.pow(i-1,nz.Config.DifficultySpawnRateCurve)) - nz.Curves.Data.Health[i-1] = math.Round(nz.Config.BaseDifficultyHealthCurve*math.pow(i-1,nz.Config.DifficultyHealthCurve)) - nz.Curves.Data.Speed[i-1] = math.Round(nz.Config.BaseDifficultySpeedCurve*math.pow(i-1,nz.Config.DifficultySpeedCurve)) - end - //PrintTable(nz.Curves.Data) - end - - nz.Curves.Functions.GenerateCurve() - -end \ No newline at end of file diff --git a/nzombies3/gamemode/display/cl_fonts.lua b/nzombies3/gamemode/display/cl_fonts.lua deleted file mode 100644 index 41e1ad3b..00000000 --- a/nzombies3/gamemode/display/cl_fonts.lua +++ /dev/null @@ -1,34 +0,0 @@ -//Main Text -surface.CreateFont( "nz.display.hud.main", { - font = "DK Umbilical Noose", //Avenir Next - size = 48, - weight = 300, - blursize = 0, - scanlines = 0, - antialias = true, - underline = false, - italic = false, - strikeout = false, - symbol = false, - rotary = false, - shadow = false, - additive = false, - outline = false, -} ) - -surface.CreateFont( "nz.display.hud.small", { - font = "DK Umbilical Noose", //Avenir Next - size = 28, - weight = 300, - blursize = 0, - scanlines = 0, - antialias = true, - underline = false, - italic = false, - strikeout = false, - symbol = false, - rotary = false, - shadow = false, - additive = false, - outline = false, -} ) \ No newline at end of file diff --git a/nzombies3/gamemode/display/cl_halos.lua b/nzombies3/gamemode/display/cl_halos.lua deleted file mode 100644 index 1dc505d0..00000000 --- a/nzombies3/gamemode/display/cl_halos.lua +++ /dev/null @@ -1,43 +0,0 @@ -//Halos - -//Setup -nz.Display.Data.Halos = {} -nz.Display.Data.Halos.Normal = {} -nz.Display.Data.Halos.Create = {} - -//Functions -function nz.Display.Functions.NewHalo(class, colour, createOnly) - if createOnly == true then - table.insert(nz.Display.Data.Halos.Create, {class, colour}) - else - table.insert(nz.Display.Data.Halos.Normal, {class, colour}) - end - -end - -//Hooks -if nz.Config.Halos == true then - hook.Add( "PreDrawHalos", "nz_halos", function() - //Create - if nz.Rounds.Data.CurrentState == ROUND_CREATE then - for k,v in pairs(nz.Display.Data.Halos.Create) do - halo.Add( ents.FindByClass( v[1] ), v[2], 0, 0, 0.1, 0, 1 ) - end - end - - //Normals - for k,v in pairs(nz.Display.Data.Halos.Normal) do - halo.Add( ents.FindByClass( v[1] ), v[2], 0, 0, 0.1, 0, 1 ) - end - end ) -end - -//Quick Function -NewHalo = nz.Display.Functions.NewHalo - -//Actual Halos - -//Zombie Spawns -NewHalo("zed_spawns", Color(255,0,0), true) -//Player Spawns -NewHalo("player_spawns", Color(0,255,0), true) \ No newline at end of file diff --git a/nzombies3/gamemode/display/cl_hud.lua b/nzombies3/gamemode/display/cl_hud.lua deleted file mode 100644 index 09abbe4b..00000000 --- a/nzombies3/gamemode/display/cl_hud.lua +++ /dev/null @@ -1,101 +0,0 @@ -// - -function nz.Display.Functions.StatesHud() - local text = "" - local font = "nz.display.hud.main" - local w = ScrW() / 2 - if nz.Rounds.Data.CurrentState == ROUND_INIT then - text = "Waiting for players. Type /ready to ready up." - font = "nz.display.hud.small" - elseif nz.Rounds.Data.CurrentState == ROUND_PREP then - if nz.Rounds.Data.CurrentRound != 0 then - text = nz.Rounds.Data.CurrentRound - else - text = "1" - end - w = ScrW() * 0.1 - elseif nz.Rounds.Data.CurrentState == ROUND_PROG then - if nz.Rounds.Data.CurrentRound != 0 then - text = nz.Rounds.Data.CurrentRound - else - text = "1" - end - w = ScrW() * 0.1 - elseif nz.Rounds.Data.CurrentState == ROUND_CREATE then - text = "Creative Mode" - elseif nz.Rounds.Data.CurrentState == ROUND_GO then - text = "Game Over" - end - draw.SimpleText(text, font, w, ScrH() * 0.85, Color(200, 0, 0,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) -end - -function nz.Display.Functions.ScoreHud() - if nz.Rounds.Data.CurrentState == ROUND_PREP or nz.Rounds.Data.CurrentState == ROUND_PROG then - for k,v in pairs(player.GetAll()) do - local hp = v:Health() - if hp == 0 then hp = "Dead" else hp = hp .. " HP" end - if v:GetPoints() >= 0 then - draw.SimpleText(v:Nick().."(" .. hp .. ") - "..v:GetPoints(), "nz.display.hud.small", ScrW() * 0.8, ScrH() / 2 + (20*k), Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) - end - end - end - if LocalPlayer():GetActiveWeapon():IsValid() and nz.Rounds.Data.CurrentState == ROUND_CREATE then - draw.SimpleText(LocalPlayer():GetActiveWeapon():GetClass(), "nz.display.hud.small", ScrW() * 0.8, ScrH() - 70, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) - end -end - -function nz.Display.Functions.PowerUpsHud() - if nz.Rounds.Data.CurrentState == ROUND_PREP or nz.Rounds.Data.CurrentState == ROUND_PROG then - local font = "nz.display.hud.main" - local w = ScrW() / 2 - local offset = 40 - local c = 0 - for k,v in pairs(nz.PowerUps.Data.ActivePowerUps) do - if nz.PowerUps.Functions.IsPowerupActive(k) then - local powerupData = nz.PowerUps.Functions.Get(k) - draw.SimpleText(powerupData.name .. " - " .. math.Round(v - CurTime()), font, w, ScrH() * 0.85 + offset * c, Color(255, 255, 255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) - c = c + 1 - end - end - end -end - -local Laser = Material( "cable/redlaser" ) -function nz.Display.Functions.DrawLinks( ent, link ) - - local tbl = {} - //Check for zombie spawns - for k, v in pairs(ents.GetAll()) do - if v:IsBuyableProp() then - if nz.Doors.Data.BuyableProps[k] != nil then - if v.link == link then - table.insert(tbl, Entity(k)) - end - end - elseif v:IsDoor() then - if nz.Doors.Data.LinkFlags[v:doorIndex()] != nil then - if nz.Doors.Data.LinkFlags[v:doorIndex()].link == link then - table.insert(tbl, v) - end - end - elseif v:GetClass() == "zed_spawns" then - if v:GetLink() == link then - table.insert(tbl, v) - end - end - end - - - // Draw - if tbl[1] != nil then - for k,v in pairs(tbl) do - render.SetMaterial( Laser ) - render.DrawBeam( ent:GetPos(), v:GetPos(), 20, 1, 1, Color( 255, 255, 255, 255 ) ) - end - end -end - -//Hooks -hook.Add("HUDPaint", "roundHUD", nz.Display.Functions.StatesHud ) -hook.Add("HUDPaint", "scoreHUD", nz.Display.Functions.ScoreHud ) -hook.Add("HUDPaint", "powerupHUD", nz.Display.Functions.PowerUpsHud ) \ No newline at end of file diff --git a/nzombies3/gamemode/display/cl_target.lua b/nzombies3/gamemode/display/cl_target.lua deleted file mode 100644 index c439edf7..00000000 --- a/nzombies3/gamemode/display/cl_target.lua +++ /dev/null @@ -1,153 +0,0 @@ -// - -function nz.Display.Functions.GetTarget() - local tr = util.GetPlayerTrace( LocalPlayer() ) - local trace = util.TraceLine( tr ) - if (!trace.Hit) then return end - if (!trace.HitNonWorld) then return end - - return trace.Entity -end - -function nz.Display.Functions.GetText( ent ) - - local class = ent:GetClass() - local text = "" - - if ent:IsPlayer() then - text = ent:Nick() .. " - " .. ent:Health() .. " HP" - end - - if class == "wall_buys" then - local wepclass = ent:GetEntName() - local price = ent:GetPrice() - local wep = weapons.Get(wepclass) - local name = wep.PrintName - local ammo_price = math.Round((price - (price % 10))/2) - if !LocalPlayer():HasWeapon( wepclass ) then - text = "Press E to buy " .. name .." for " .. price .. " points." - else - text = "Press E to buy " .. wep.Primary.Ammo .." Ammo refill for " .. ammo_price .. " points." // In future give more ammo - end - end - - if class == "nut_zombie" then - text = "Health: " .. ent:Health() - end - - if class == "breakable_entry" then - if ent:Health() < nz.Config.MaxPlanks * 10 then - text = "Hold E to rebuild the barricade." - end - end - - if class == "random_box" then - if !ent:GetOpen() then - text = "Press E to buy a random weapon for 950 points." - end - end - - if class == "random_box_windup" then - if !ent:GetWinding() then - local wepclass = ent:GetWepClass() - local wep = weapons.Get(wepclass) - local name = "UNKNOWN" - if wep != nil then - name = wep.PrintName - end - if name == nil then name = wepclass end - text = "Press E to take " .. name .. " from the box." - end - end - - if class == "perk_machine" then - if !ent:IsOn() then - text = "No Power." - else - local perkData = nz.Perks.Functions.Get(ent:GetPerkID()) - //Its on - text = "Press E to buy " .. perkData.name .. " for " .. perkData.price .. " points." - //Check if they already own it - if LocalPlayer():HasPerk(ent:GetPerkID()) then - text = "You already own this perk." - end - end - end - - local door_data = nil - - if ent:IsDoor() then - //Normal Doors - door_data = nz.Doors.Data.LinkFlags[ent:doorIndex()] - end - - if ent:IsBuyableProp() then - //Prop Doors - door_data = nz.Doors.Data.BuyableProps[ent:EntIndex()] - end - - //If we have door data - if door_data != nil then - local price = door_data.price - local req_elec = door_data.elec - local link = door_data.link - if req_elec == "1" and !IsElec() then - text = "You must turn on the electricity first!" - else - if !nz.Doors.Data.OpenedLinks[link] == true then - if price != "0" then - text = "Press E to open for " .. price .. " points." - end - end - end - end - - //Create Only - if nz.Rounds.Data.CurrentState == ROUND_CREATE then - if class == "player_spawns" then - text = "Player Spawn" - end - - if class == "zed_spawns" then - text = "Zombie Spawn" - end - end - - return text -end - -function nz.Display.Functions.DrawTargetID( text ) - - local font = "nz.display.hud.small" - surface.SetFont( font ) - local w, h = surface.GetTextSize( text ) - - local MouseX, MouseY = gui.MousePos() - - if ( MouseX == 0 && MouseY == 0 ) then - - MouseX = ScrW() / 2 - MouseY = ScrH() / 2 - - end - - local x = MouseX - local y = MouseY - - x = x - w / 2 - y = y + 30 - - -- The fonts internal drop shadow looks lousy with AA on - draw.SimpleText( text, font, x+1, y+1, Color(255,255,255,255) ) -end - - -function GM:HUDDrawTargetID() - - local ent = nz.Display.Functions.GetTarget() - - if ent != nil then - nz.Display.Functions.DrawTargetID(nz.Display.Functions.GetText(ent)) - end - -end \ No newline at end of file diff --git a/nzombies3/gamemode/display/sh_constructor.lua b/nzombies3/gamemode/display/sh_constructor.lua deleted file mode 100644 index 7606c2a8..00000000 --- a/nzombies3/gamemode/display/sh_constructor.lua +++ /dev/null @@ -1,6 +0,0 @@ -//Main Tables -nz.Display = {} -nz.Display.Functions = {} -nz.Display.Data = {} - -//_ Variables diff --git a/nzombies3/gamemode/door_system/sh_constructor.lua b/nzombies3/gamemode/door_system/sh_constructor.lua deleted file mode 100644 index d4aa0029..00000000 --- a/nzombies3/gamemode/door_system/sh_constructor.lua +++ /dev/null @@ -1,11 +0,0 @@ -//Main Tables -nz.Doors = {} -nz.Doors.Functions = {} -nz.Doors.Data = {} - -//_ Variables -nz.Doors.Data.EaDI = {} -nz.Doors.Data.LinkFlags = {} -nz.Doors.Data.OpenedLinks = {} -nz.Doors.Data.BuyableProps = {} -nz.Doors.Data.DisplayLinks = {} \ No newline at end of file diff --git a/nzombies3/gamemode/door_system/sh_door_meta.lua b/nzombies3/gamemode/door_system/sh_door_meta.lua deleted file mode 100644 index a02f4948..00000000 --- a/nzombies3/gamemode/door_system/sh_door_meta.lua +++ /dev/null @@ -1,59 +0,0 @@ -local meta = FindMetaTable("Entity") - -function meta:IsDoor() - if not IsValid(self) then return false end - local class = self:GetClass() - - if class == "func_door" or - class == "func_door_rotating" or - class == "prop_door_rotating" or - class == "prop_dynamic" then - return true - end - return false -end - -function meta:IsBuyableProp() - if not IsValid(self) then return false end - local class = self:GetClass() - - if class == "prop_buys" then - return true - end - return false -end - -function meta:doorIndex() - if SERVER then - return self:CreatedByMap() and self:MapCreationID() or nil - else - //Check the ED table - return nz.Doors.Data.EaDI[self:EntIndex()] or 0 - end -end - -function meta:DoorUnlock() - //Delay opening the door by a second to stop the door from accidentally opening then closing forever. - //timer.Simple(1, function() - if self:IsDoor() then - self.Locked = false - self:Fire("unlock", "", 0) - self:Fire("open", "", 0) - self:Fire("lock", "", 0) - self:SetKeyValue("wait",-1) - elseif self:IsBuyableProp() then - self.Locked = false - self:BlockUnlock() - end - //end) -end - -function meta:DoorLock() - if self:IsDoor() then - self.Locked = true - self:Fire("close", "", 0) - self:Fire("lock", "", 0) - elseif self:IsBuyableProp() then - self:BlockLock() - end -end \ No newline at end of file diff --git a/nzombies3/gamemode/door_system/sh_doors.lua b/nzombies3/gamemode/door_system/sh_doors.lua deleted file mode 100644 index 3236b3a3..00000000 --- a/nzombies3/gamemode/door_system/sh_doors.lua +++ /dev/null @@ -1,11 +0,0 @@ -//Functions - -function nz.Doors.Functions.doorToEntIndex(num) - local ent = ents.GetMapCreatedEntity(num) - - return IsValid(ent) and ent:EntIndex() or nil -end - -function nz.Doors.Functions.doorIndexToEnt(num) - return ents.GetMapCreatedEntity(num) or NULL -end \ No newline at end of file diff --git a/nzombies3/gamemode/door_system/sh_sync.lua b/nzombies3/gamemode/door_system/sh_sync.lua deleted file mode 100644 index e8c041d8..00000000 --- a/nzombies3/gamemode/door_system/sh_sync.lua +++ /dev/null @@ -1,29 +0,0 @@ -//Client Server Syncing - -if SERVER then - - //Server to client (Server) - util.AddNetworkString( "nz.Doors.Sync" ) - - function nz.Doors.Functions.SendSync() - local data = table.Copy(nz.Doors.Data) - - net.Start( "nz.Doors.Sync" ) - net.WriteTable( data ) - net.Broadcast() - end - -end - -if CLIENT then - - //Server to client (Client) - function nz.Doors.Functions.ReceiveSync( length ) - print("Received Doors Sync") - nz.Doors.Data = net.ReadTable() - PrintTable(nz.Doors.Data) - end - - //Receivers - net.Receive( "nz.Doors.Sync", nz.Doors.Functions.ReceiveSync ) -end \ No newline at end of file diff --git a/nzombies3/gamemode/door_system/sv_doors.lua b/nzombies3/gamemode/door_system/sv_doors.lua deleted file mode 100644 index 1f77e751..00000000 --- a/nzombies3/gamemode/door_system/sv_doors.lua +++ /dev/null @@ -1,138 +0,0 @@ -// - -//price=500,elec=0,link=1 - -function nz.Doors.Functions.ParseFlagString( flagsStr ) - - local tbl = {} - - flagsStr = string.lower(flagsStr) - - //Translate the flags string into a table - local ex = string.Explode( ",", flagsStr ) - - for k,v in pairs(ex) do - local ex2 = string.Explode( "=", v ) - tbl[ex2[1]] = ex2[2] - end - - return tbl - -end - -function nz.Doors.Functions.CreateLink( ent, flagsStr ) - //First remove all links - nz.Doors.Functions.RemoveLink( ent ) - if ent:IsDoor() then - nz.Doors.Functions.CreateMapDoorLink( ent:doorIndex(), flagsStr ) - elseif ent:IsBuyableProp() then - nz.Doors.Functions.CreatePropDoorLink( ent, flagsStr ) - end -end - -function nz.Doors.Functions.RemoveLink( ent ) - if ent:IsDoor() then - nz.Doors.Functions.RemoveMapDoorLink( ent:doorIndex(), flagsStr ) - elseif ent:IsBuyableProp() then - nz.Doors.Functions.RemovePropDoorLink( ent ) - end -end - -function nz.Doors.Functions.CreateMapDoorLink( doorID, flagsStr ) - - local door = nz.Doors.Functions.doorIndexToEnt(doorID) - local flagsTbl = nz.Doors.Functions.ParseFlagString( flagsStr ) - - if door:IsValid() and door:IsDoor() then - //Assign the flags to the door - for k,v in pairs(flagsTbl) do - door[k] = tonumber(v) - end - //Save the data into a convenient table for lua refresh - door.Data = flagsStr - - //Set the Door Data - nz.Doors.Data.LinkFlags[doorID] = flagsTbl - nz.Doors.Data.EaDI[nz.Doors.Functions.doorToEntIndex(doorID)] = doorID - - nz.Doors.Functions.SendSync() - - else - print("Error: " .. doorID .. " is not a door. ") - end - -end - -function nz.Doors.Functions.RemoveMapDoorLink( doorID ) - - local door = nz.Doors.Functions.doorIndexToEnt(doorID) - - if door.Data != nil then - if door:IsValid() and door:IsDoor() then - local flagsTbl = nz.Doors.Functions.ParseFlagString( door.Data ) - - //Remove the flags to the door - for k,v in pairs(flagsTbl) do - door[k] = nil - end - - //Remove the data that was used for lua refresh - door.Data = nil - - //Set the Door Data - nz.Doors.Data.LinkFlags[doorID] = nil - nz.Doors.Data.EaDI[nz.Doors.Functions.doorToEntIndex(doorID)] = nil - - nz.Doors.Functions.SendSync() - else - print("Error: " .. doorID .. " is not a door. ") - end - end - -end - -function nz.Doors.Functions.CreatePropDoorLink( ent, flagsStr ) - - local flagsTbl = nz.Doors.Functions.ParseFlagString( flagsStr ) - - if ent:IsValid() and ent:IsBuyableProp() then - //Assign the flags to the door - for k,v in pairs(flagsTbl) do - ent[k] = tonumber(v) - end - //Save the data into a convenient table for lua refresh - ent.Data = flagsStr - //Set the Door Data - nz.Doors.Data.BuyableProps[ent:EntIndex()] = flagsTbl - nz.Doors.Functions.SendSync() - else - //print("Error: " .. doorID .. " is not a door. ") - end - -end - -function nz.Doors.Functions.RemovePropDoorLink( ent ) - - if ent:IsValid() and ent:IsBuyableProp() then - - //Save the data into a convenient table for lua refresh - ent.Data = nil - //Set the Door Data - nz.Doors.Data.BuyableProps[ent:EntIndex()] = nil - nz.Doors.Functions.SendSync() - - else - //print("Error: " .. doorID .. " is not a door. ") - end -end - -function nz.Doors.Functions.DisplayDoorLinks( ent ) - if ent.link == nil then nz.Doors.Data.DisplayLinks[ent] = nil return end - - if nz.Doors.Data.DisplayLinks[ent] == nil then - nz.Doors.Data.DisplayLinks[ent] = ent.link - else - nz.Doors.Data.DisplayLinks[ent] = nil - end - nz.Doors.Functions.SendSync() -end \ No newline at end of file diff --git a/nzombies3/gamemode/door_system/sv_gameplay.lua b/nzombies3/gamemode/door_system/sv_gameplay.lua deleted file mode 100644 index db13ec03..00000000 --- a/nzombies3/gamemode/door_system/sv_gameplay.lua +++ /dev/null @@ -1,65 +0,0 @@ -function nz.Doors.Functions.OpenDoor( ent ) - //Open the door and any other door with the same link - ent:DoorUnlock() - - //Sync - if ent.link != nil then - nz.Doors.Data.OpenedLinks[ent.link] = true - nz.Doors.Functions.SendSync() - end -end - -function nz.Doors.Functions.OpenLinkedDoors( link ) - //Go through all the doors - for k,v in pairs(ents.GetAll()) do - if v:IsDoor() or v:IsBuyableProp() then - if v.link != nil then - if link == v.link then - nz.Doors.Functions.OpenDoor( v ) - end - end - end - end -end - -function nz.Doors.Functions.LockAllDoors() - //Force all doors to lock and stay open when opened - for k,v in pairs(ents.GetAll()) do - if v:IsDoor() or v:IsBuyableProp() then - v:SetUseType( SIMPLE_USE ) - v:DoorLock() - v:SetKeyValue("wait",-1) - end - end -end - -function nz.Doors.Functions.BuyDoor( ply, ent ) - local price = ent.price - local req_elec = ent.elec - local link = ent.link - //If it has a price - if price != nil then - if ply:CanAfford(price) and ent.Locked == true then - //If this door doesn't require electricity or if it does, then if the electricity is on at the same time - if (req_elec == 0 or (req_elec == 1 and IsElec())) then - ply:TakePoints(price) - if link == nil then - nz.Doors.Functions.OpenDoor( ent ) - else - nz.Doors.Functions.OpenLinkedDoors( link ) - end - end - end - end -end - - -//Hooks - -function nz.Doors.Functions.OnUseDoor( ply, ent ) - if ent:IsDoor() or ent:IsBuyableProp() then - nz.Doors.Functions.BuyDoor( ply, ent ) - end -end - -hook.Add( "PlayerUse", "player_buydoors", nz.Doors.Functions.OnUseDoor ) \ No newline at end of file diff --git a/nzombies3/gamemode/electricity/sh_constructor.lua b/nzombies3/gamemode/electricity/sh_constructor.lua deleted file mode 100644 index 35db8fe2..00000000 --- a/nzombies3/gamemode/electricity/sh_constructor.lua +++ /dev/null @@ -1,13 +0,0 @@ -//Main Tables -nz.Elec = {} -nz.Elec.Functions = {} -nz.Elec.Data = {} - -//_ Variables -nz.Elec.Data.Active = false - -function nz.Elec.Functions.IsElec() - return nz.Elec.Data.Active -end - -IsElec = nz.Elec.Functions.IsElec \ No newline at end of file diff --git a/nzombies3/gamemode/electricity/sh_sync.lua b/nzombies3/gamemode/electricity/sh_sync.lua deleted file mode 100644 index 08efd2d1..00000000 --- a/nzombies3/gamemode/electricity/sh_sync.lua +++ /dev/null @@ -1,28 +0,0 @@ -//Client Server Syncing - -if SERVER then - - //Server to client (Server) - util.AddNetworkString( "nz.Elec.Sync" ) - - function nz.Elec.Functions.SendSync() - net.Start( "nz.Elec.Sync" ) - net.WriteTable(nz.Elec.Data) - net.Broadcast() - end - -end - -if CLIENT then - - //Server to client (Client) - function nz.Elec.Functions.ReceiveSync( length ) - nz.Elec.Data = net.ReadTable() - end - - - //Receivers - net.Receive( "nz.Elec.Sync", nz.Elec.Functions.ReceiveSync ) - - -end \ No newline at end of file diff --git a/nzombies3/gamemode/electricity/sv_elec.lua b/nzombies3/gamemode/electricity/sv_elec.lua deleted file mode 100644 index 8bd6353a..00000000 --- a/nzombies3/gamemode/electricity/sv_elec.lua +++ /dev/null @@ -1,38 +0,0 @@ -// - -function nz.Elec.Functions.Activate() - - nz.Elec.Data.Active = true - nz.Elec.Functions.SendSync() - - //Open all doors with no price and electricity requirement - for k,v in pairs(ents.GetAll()) do - if v:IsDoor() or v:IsBuyableProp() then - if v.price == 0 and v.elec == 1 then - nz.Doors.Functions.OpenDoor( v ) - end - end - end - - //Turn on all perk machines - for k,v in pairs(ents.FindByClass("perk_machine")) do - v:TurnOn() - end - - //Call the hook - PrintMessage(HUD_PRINTTALK, "[NZ] Electricity is on!") - -end - -function nz.Elec.Functions.Reset() - - nz.Elec.Data.Active = false - //Reset the button aswell - local prevs = ents.FindByClass("button_elec") - if prevs[1] != nil then - prevs[1]:SetSwitch(false) - end - - nz.Elec.Functions.SendSync() - -end \ No newline at end of file diff --git a/nzombies3/gamemode/enemies/sh_constructor.lua b/nzombies3/gamemode/enemies/sh_constructor.lua deleted file mode 100644 index bca4711e..00000000 --- a/nzombies3/gamemode/enemies/sh_constructor.lua +++ /dev/null @@ -1,9 +0,0 @@ -//We only need this on the server -if SERVER then - - //Main Tables - nz.Enemies = {} - nz.Enemies.Functions = {} - nz.Enemies.Data = {} - -end \ No newline at end of file diff --git a/nzombies3/gamemode/enemies/sv_hooks.lua b/nzombies3/gamemode/enemies/sv_hooks.lua deleted file mode 100644 index 2b6f0835..00000000 --- a/nzombies3/gamemode/enemies/sv_hooks.lua +++ /dev/null @@ -1,43 +0,0 @@ -// - - -function nz.Enemies.Functions.OnEnemyKilled(enemy, attacker) - - if attacker:IsPlayer() then - attacker:GivePoints(90) - attacker:AddFrags(1) - end - - nz.Rounds.Data.KilledZombies = nz.Rounds.Data.KilledZombies + 1 - //nz.Rounds.Data.ZombiesSpawned = nz.Rounds.Data.ZombiesSpawned - 1 - - //Chance a powerup spawning - if nz.PowerUps.Functions.IsPowerupActive("insta") == false then //Don't spawn powerups during instakill - nz.PowerUps.Functions.SpawnPowerUp(enemy:GetPos()) - end - - print("Killed Enemy: " .. nz.Rounds.Data.KilledZombies .. "/" .. nz.Rounds.Data.MaxZombies ) -end - -function nz.Enemies.Functions.OnEnemyHurt(enemy, attacker) - if attacker:IsPlayer() and enemy:IsValid() then - attacker:GivePoints(10) - if nz.PowerUps.Functions.IsPowerupActive("insta") then - local insta = DamageInfo() - insta:SetDamage(enemy:Health()) - insta:SetAttacker(attacker) - insta:SetDamageType(DMG_BLAST_SURFACE) - //Delay so it doesn't "die" twice - timer.Simple(0.1, function() if enemy:IsValid() and enemy:Health() > 0 then enemy:TakeDamageInfo( insta ) end end) - end - end -end - - -function nz.Enemies.Functions.OnEntityCreated( ent ) - if ( ent:GetClass() == "prop_ragdoll" ) then - ent:SetCollisionGroup(COLLISION_GROUP_DEBRIS) - end -end - -hook.Add("OnEntityCreated", "nz.Enemies.OnEntityCreated", nz.Enemies.Functions.OnEntityCreated) diff --git a/nzombies3/gamemode/enemies/sv_spawner.lua b/nzombies3/gamemode/enemies/sv_spawner.lua deleted file mode 100644 index 3f594152..00000000 --- a/nzombies3/gamemode/enemies/sv_spawner.lua +++ /dev/null @@ -1,119 +0,0 @@ -// - -function nz.Enemies.Functions.CheckIfSuitable(pos) - - local Ents = ents.FindInBox( pos + Vector( -16, -16, 0 ), pos + Vector( 16, 16, 64 ) ) - local Blockers = 0 - if Ents == nil then return true end - for k, v in pairs( Ents ) do - if ( IsValid( v ) and (v:GetClass() == "player" or table.HasValue(nz.Config.ValidEnemies, v:GetClass()) ) ) then - Blockers = Blockers + 1 - end - end - - if Blockers == 0 then - return true - end - - return false - -end - -function nz.Enemies.Functions.ValidSpawns() - - local valids = {} - local spawns = {} - - //Make a table of spawns - for k,v in pairs(team.GetPlayers(TEAM_PLAYERS)) do - //Get all spawns in the range - for k2,v2 in pairs(ents.FindInSphere(v:GetPos(), 1200)) do - if v2:GetClass() == "zed_spawns" then - table.insert(spawns, v2) - end - end - //Remove all spawns that are too close - for k2,v2 in pairs(ents.FindInSphere(v:GetPos(), 200)) do - if table.HasValue(spawns, v2) then - table.RemoveByValue(spawns, v2) - end - end - end - - //Removed unopened linked doors - for k,v in pairs(spawns) do - if v.link != nil then - if nz.Doors.Data.OpenedLinks[tonumber(v.link)] == nil then //Zombie Links - spawns[k] = nil - end - end - end - - //Get positions - for k,v in pairs(spawns) do - table.insert(valids, v:GetPos()) - end - - return valids -end - -function nz.Enemies.Functions.TotalCurrentEnemies() - local c = 0 - - //Count - for k,v in pairs(nz.Config.ValidEnemies) do - for k2,v2 in pairs(ents.FindByClass(v)) do - c = c + 1 - end - end - - return c -end - -function nz.Enemies.Functions.SpawnZombie(pos) - if nz.Enemies.Functions.TotalCurrentEnemies() < 100 then - local ent = "nut_zombie" - - //Get the latest round number from the table - for i = nz.Rounds.Data.CurrentRound, 0, -1 do - if nz.Config.EnemyTypes[i] != nil then - ent = nz.Misc.Functions.WeightedRandom(nz.Config.EnemyTypes[i]) - break - end - end - - local zombie = ents.Create(ent) - zombie:SetPos(pos) - zombie:Spawn() - zombie:Activate() - nz.Rounds.Data.ZombiesSpawned = nz.Rounds.Data.ZombiesSpawned + 1 - print("Spawning Enemy: " .. nz.Rounds.Data.ZombiesSpawned .. "/" .. nz.Rounds.Data.MaxZombies ) - else - print("Limit of Zombies Reached!") - end -end - - -function nz.Enemies.Functions.ZombieSpawner() - //Not enough Zombies - if nz.Rounds.Data.ZombiesSpawned < nz.Rounds.Data.MaxZombies then - if nz.Rounds.Data.CurrentState == ROUND_PROG then - - local valids = nz.Enemies.Functions.ValidSpawns() - - if valids[1] == nil then - print("No valid spawns were found!") - return - --Since we couldn't find a valid spawn, just back out for now. - end - - local pos = table.Random(valids) - - if nz.Enemies.Functions.CheckIfSuitable(pos) then - nz.Enemies.Functions.SpawnZombie(pos) - end - end - end -end - -timer.Create("nz.Rounds.ZombieSpawner", 1, 0, nz.Enemies.Functions.ZombieSpawner) \ No newline at end of file diff --git a/nzombies3/gamemode/init.lua b/nzombies3/gamemode/init.lua deleted file mode 100644 index 7e12d398..00000000 --- a/nzombies3/gamemode/init.lua +++ /dev/null @@ -1,5 +0,0 @@ -include( "shared.lua" ) -include( "loader.lua" ) - -AddCSLuaFile( "shared.lua" ) -AddCSLuaFile( "loader.lua" ) \ No newline at end of file diff --git a/nzombies3/gamemode/interfaces/sh_constructor.lua b/nzombies3/gamemode/interfaces/sh_constructor.lua deleted file mode 100644 index c115ae50..00000000 --- a/nzombies3/gamemode/interfaces/sh_constructor.lua +++ /dev/null @@ -1,6 +0,0 @@ -//Main Tables -nz.Interfaces = {} -nz.Interfaces.Functions = {} -nz.Interfaces.Data = {} - -//_ Variables \ No newline at end of file diff --git a/nzombies3/gamemode/interfaces/sh_int_configloader.lua b/nzombies3/gamemode/interfaces/sh_int_configloader.lua deleted file mode 100644 index d96e33d4..00000000 --- a/nzombies3/gamemode/interfaces/sh_int_configloader.lua +++ /dev/null @@ -1,51 +0,0 @@ -// - -if SERVER then - function nz.Interfaces.Functions.ConfigLoaderHandler( ply, data ) - if ply:IsSuperAdmin() then - nz.Mapping.Functions.LoadConfig( data.config ) - end - end -end - -if CLIENT then - function nz.Interfaces.Functions.ConfigLoader( data ) - local DermaPanel = vgui.Create( "DFrame" ) - DermaPanel:SetPos( 100, 100 ) - DermaPanel:SetSize( 300, 180 ) - DermaPanel:SetTitle( "Load a config" ) - DermaPanel:SetVisible( true ) - DermaPanel:SetDraggable( true ) - DermaPanel:ShowCloseButton( true ) - DermaPanel:MakePopup() - DermaPanel:Center() - - local DermaListView = vgui.Create("DListView") - DermaListView:SetParent(DermaPanel) - DermaListView:SetPos(10, 30) - DermaListView:SetSize(280, 100) - DermaListView:SetMultiSelect(false) - DermaListView:AddColumn("Name") - //Populate - for k,v in pairs(data.configs) do - DermaListView:AddLine(v) - end - - local DermaButton = vgui.Create( "DButton" ) - DermaButton:SetParent( DermaPanel ) - DermaButton:SetText( "Submit" ) - DermaButton:SetPos( 10, 140 ) - DermaButton:SetSize( 280, 30 ) - DermaButton.DoClick = function() - if DermaListView:GetSelectedLine() != nil then - local str = DermaListView:GetLine(DermaListView:GetSelectedLine()):GetValue(1) - if str != nil then - data.configs = nil - data.config = str - nz.Interfaces.Functions.SendRequests( "ConfigLoader", data ) - DermaPanel:Close() - end - end - end - end -end diff --git a/nzombies3/gamemode/interfaces/sh_int_door.lua b/nzombies3/gamemode/interfaces/sh_int_door.lua deleted file mode 100644 index f080dc9b..00000000 --- a/nzombies3/gamemode/interfaces/sh_int_door.lua +++ /dev/null @@ -1,97 +0,0 @@ -// - -if SERVER then - function nz.Interfaces.Functions.DoorPropsHandler( ply, data ) - if ply:IsSuperAdmin() then - nz.Doors.Functions.CreateLink( data.ent, data.flags ) - end - end -end - -if CLIENT then - function nz.Interfaces.Functions.DoorProps( data ) - local ent = data.door - local name = "Add New Door" - local valz = {} - valz["Row1"] = 0 - valz["Row2"] = 1 - valz["Row3"] = 1000 - valz["Row4"] = 0 - - local door_data = nil - - //Check if the ent has flags already - if ent:IsDoor() then - door_data = nz.Doors.Data.LinkFlags[ent:doorIndex()] - elseif ent:IsBuyableProp() then - door_data = nz.Doors.Data.BuyableProps[ent:EntIndex()] - end - //If we do then; - if door_data != nil then - if door_data.link != nil then - valz["Row1"] = 1 - valz["Row2"] = door_data.link - end - valz["Row3"] = door_data.price - valz["Row4"] = door_data.elec - name = "Modifying Door Flag" - end - local DermaPanel = vgui.Create( "DFrame" ) - DermaPanel:SetPos( 100, 100 ) - DermaPanel:SetSize( 300, 180 ) - DermaPanel:SetTitle( name ) - DermaPanel:SetVisible( true ) - DermaPanel:SetDraggable( true ) - DermaPanel:ShowCloseButton( true ) - DermaPanel:MakePopup() - DermaPanel:Center() - - local DProperties = vgui.Create( "DProperties", DermaPanel ) - DProperties:SetSize( 280, 180 ) - DProperties:SetPos( 10, 30 ) - - local Row1 = DProperties:CreateRow( "Door Settings", "Enable Flag?" ) - Row1:Setup( "Boolean" ) - Row1:SetValue( valz["Row1"] ) - Row1.DataChanged = function( _, val ) valz["Row1"] = val end - local Row2 = DProperties:CreateRow( "Door Settings", "Flag" ) - Row2:Setup( "Integer" ) - Row2:SetValue( valz["Row2"] ) - Row2.DataChanged = function( _, val ) valz["Row2"] = val end - local Row3 = DProperties:CreateRow( "Door Settings", "Price" ) - Row3:Setup( "Integer" ) - Row3:SetValue( valz["Row3"] ) - Row3.DataChanged = function( _, val ) valz["Row3"] = val end - local Row4 = DProperties:CreateRow( "Door Settings", "Requires Electricity?" ) - Row4:Setup( "Boolean" ) - Row4:SetValue( valz["Row4"] ) - Row4.DataChanged = function( _, val ) valz["Row4"] = val end - - local DermaButton = vgui.Create( "DButton" ) - DermaButton:SetParent( DermaPanel ) - DermaButton:SetText( "Submit" ) - DermaButton:SetPos( 10, 140 ) - DermaButton:SetSize( 280, 30 ) - DermaButton.DoClick = function() - local function compileString(price, elec, flag) - local str = "price="..price..",elec="..elec - if flag != false then - str = str..",link="..flag - end - return str - end - local flag = false - if valz["Row1"] == 1 then - flag = valz["Row2"] - end - DermaPanel:SetTitle( "Modifying Door Flag" ) - local flagString = compileString(valz["Row3"], valz["Row4"], flag) - print(flagString) - - //Send the data - nz.Interfaces.Functions.SendRequests( "DoorProps", {flags = flagString, ent = ent} ) - - end - end - -end diff --git a/nzombies3/gamemode/interfaces/sh_int_perkmachine.lua b/nzombies3/gamemode/interfaces/sh_int_perkmachine.lua deleted file mode 100644 index 20837186..00000000 --- a/nzombies3/gamemode/interfaces/sh_int_perkmachine.lua +++ /dev/null @@ -1,36 +0,0 @@ -// - -if SERVER then - function nz.Interfaces.Functions.PerkMachineHandler( ply, data ) - if ply:IsSuperAdmin() then - data.ent:SetPerkID(data.id) - data.ent:TurnOff() //Quickly update the model - end - end -end - -if CLIENT then - function nz.Interfaces.Functions.PerkMachine( data ) - local DermaPanel = vgui.Create( "DFrame" ) - DermaPanel:SetPos( 100, 100 ) - DermaPanel:SetSize( 300, 180 ) - DermaPanel:SetTitle( "Modifying Perk Machines" ) - DermaPanel:SetVisible( true ) - DermaPanel:SetDraggable( true ) - DermaPanel:ShowCloseButton( true ) - DermaPanel:MakePopup() - DermaPanel:Center() - - local choices = vgui.Create( "DComboBox", DermaPanel ) - choices:SetPos( 10, 30 ) - choices:SetSize( 280, 30 ) - choices:SetValue( nz.Perks.Functions.Get(data.ent:GetPerkID()).name ) - for k,v in pairs(nz.Perks.Functions.GetList()) do - choices:AddChoice( v, k ) - end - choices.OnSelect = function( panel, index, value, id ) - data.id = id - nz.Interfaces.Functions.SendRequests( "PerkMachine", data ) - end - end -end diff --git a/nzombies3/gamemode/interfaces/sh_int_weps.lua b/nzombies3/gamemode/interfaces/sh_int_weps.lua deleted file mode 100644 index ac636b3a..00000000 --- a/nzombies3/gamemode/interfaces/sh_int_weps.lua +++ /dev/null @@ -1,60 +0,0 @@ -// - -if SERVER then - function nz.Interfaces.Functions.WepBuyHandler( ply, data ) - if ply:IsSuperAdmin() then - nz.Mapping.Functions.WallBuy(data.vec, data.class, tonumber(data.price), data.ang) - end - end -end - -if CLIENT then - function nz.Interfaces.Functions.WepBuy( data ) - - local valz = {} - valz["Row1"] = "weapon_class" - valz["Row2"] = 500 - - local DermaPanel = vgui.Create( "DFrame" ) - DermaPanel:SetPos( 100, 100 ) - DermaPanel:SetSize( 300, 180 ) - DermaPanel:SetTitle( "Add New Weapon" ) - DermaPanel:SetVisible( true ) - DermaPanel:SetDraggable( true ) - DermaPanel:ShowCloseButton( true ) - DermaPanel:MakePopup() - DermaPanel:Center() - - local DProperties = vgui.Create( "DProperties", DermaPanel ) - DProperties:SetSize( 280, 180 ) - DProperties:SetPos( 10, 30 ) - - local Row1 = DProperties:CreateRow( "Weapon Settings", "Weapon Class" ) - Row1:Setup( "Generic" ) - Row1:SetValue( valz["Row1"] ) - Row1.DataChanged = function( _, val ) valz["Row1"] = val end - local Row2 = DProperties:CreateRow( "Weapon Settings", "Price" ) - Row2:Setup( "Integer" ) - Row2:SetValue( valz["Row2"] ) - Row2.DataChanged = function( _, val ) valz["Row2"] = val end - - local DermaButton = vgui.Create( "DButton" ) - DermaButton:SetParent( DermaPanel ) - DermaButton:SetText( "Submit" ) - DermaButton:SetPos( 10, 140 ) - DermaButton:SetSize( 280, 30 ) - DermaButton.DoClick = function() - - //Check the weapon class is fine first - if weapons.Get( valz["Row1"] ) != nil then - data.class = valz["Row1"] - data.price = tostring(valz["Row2"]) - PrintTable(data) - nz.Interfaces.Functions.SendRequests( "WepBuy", data ) - - DermaPanel:Close() - end - - end - end -end diff --git a/nzombies3/gamemode/interfaces/sh_int_zombielinks.lua b/nzombies3/gamemode/interfaces/sh_int_zombielinks.lua deleted file mode 100644 index d243df02..00000000 --- a/nzombies3/gamemode/interfaces/sh_int_zombielinks.lua +++ /dev/null @@ -1,68 +0,0 @@ -// - -if SERVER then - function nz.Interfaces.Functions.ZombLinkHandler( ply, data ) - if ply:IsSuperAdmin() then - data.ent.link = data.link - //For the link displayer - data.ent:SetLink(data.link) - end - end -end - -if CLIENT then - function nz.Interfaces.Functions.ZombLink( data ) - PrintTable(data) - local name = "Add New Zombie Link" - local valz = {} - valz["Row1"] = 0 - valz["Row2"] = 1 - //Check if the ent has flags already - if data.link != nil then - valz["Row1"] = 1 - valz["Row2"] = data.link - name = "Modifying Zombie Link" - end - - local DermaPanel = vgui.Create( "DFrame" ) - DermaPanel:SetPos( 100, 100 ) - DermaPanel:SetSize( 300, 180 ) - DermaPanel:SetTitle( name ) - DermaPanel:SetVisible( true ) - DermaPanel:SetDraggable( true ) - DermaPanel:ShowCloseButton( true ) - DermaPanel:MakePopup() - DermaPanel:Center() - - local DProperties = vgui.Create( "DProperties", DermaPanel ) - DProperties:SetSize( 280, 180 ) - DProperties:SetPos( 10, 30 ) - - local Row1 = DProperties:CreateRow( "Zombie Spawn", "Enable Flag?" ) - Row1:Setup( "Boolean" ) - Row1:SetValue( valz["Row1"] ) - Row1.DataChanged = function( _, val ) valz["Row1"] = val end - local Row2 = DProperties:CreateRow( "Zombie Spawn", "Flag" ) - Row2:Setup( "Integer" ) - Row2:SetValue( valz["Row2"] ) - Row2.DataChanged = function( _, val ) valz["Row2"] = val end - - local DermaButton = vgui.Create( "DButton" ) - DermaButton:SetParent( DermaPanel ) - DermaButton:SetText( "Submit" ) - DermaButton:SetPos( 10, 140 ) - DermaButton:SetSize( 280, 30 ) - DermaButton.DoClick = function() - local str="nil" - if valz["Row1"] == 0 then - str=nil - else - str=valz["Row2"] - end - data.link = str - nz.Interfaces.Functions.SendRequests( "ZombLink", data ) - - DermaPanel:Close() - end - end -end diff --git a/nzombies3/gamemode/mapping/sh_constructor.lua b/nzombies3/gamemode/mapping/sh_constructor.lua deleted file mode 100644 index 628d2e60..00000000 --- a/nzombies3/gamemode/mapping/sh_constructor.lua +++ /dev/null @@ -1,6 +0,0 @@ -//Main Tables -nz.Mapping = {} -nz.Mapping.Functions = {} -nz.Mapping.Data = {} - -//_ Variables diff --git a/nzombies3/gamemode/mapping/sv_mapping.lua b/nzombies3/gamemode/mapping/sv_mapping.lua deleted file mode 100644 index 5c479ab6..00000000 --- a/nzombies3/gamemode/mapping/sv_mapping.lua +++ /dev/null @@ -1,163 +0,0 @@ -// - -function nz.Mapping.Functions.ZedSpawn(pos, link) - - local ent = ents.Create("zed_spawns") - pos.z = pos.z - ent:OBBMaxs().z - ent:SetPos( pos ) - ent:Spawn() - ent.link = link - //For the link displayer - if link != nil then - ent:SetLink(link) - end -end - -function nz.Mapping.Functions.PlayerSpawn(pos) - - local ent = ents.Create("player_spawns") - pos.z = pos.z - ent:OBBMaxs().z - ent:SetPos( pos ) - ent:Spawn() - -end - -function nz.Mapping.Functions.WallBuy(pos, gun, price, angle) - - if weapons.Get(gun) != nil then - - local ent = ents.Create("wall_buys") - ent:SetAngles(angle) - pos.z = pos.z - ent:OBBMaxs().z - ent:SetWeapon(gun, price) - ent:SetPos( pos ) - ent:Spawn() - ent:PhysicsInit( SOLID_VPHYSICS ) - - local phys = ent:GetPhysicsObject() - if phys:IsValid() then - phys:EnableMotion(false) - end - - else - print("SKIPPED: " .. gun .. ". Are you sure you have it installed?") - end - -end - -function nz.Mapping.Functions.PropBuy(pos,ang,model,flags) - local prop = ents.Create( "prop_buys" ) - prop:SetModel( model ) - prop:SetPos( pos ) - prop:SetAngles( ang ) - prop:Spawn() - prop:PhysicsInit( SOLID_VPHYSICS ) - - //REMINDER APPY FLAGS - if flags != nil then - nz.Doors.Functions.CreateLink( prop, flags ) - end - - local phys = prop:GetPhysicsObject() - if phys:IsValid() then - phys:EnableMotion(false) - end -end - -function nz.Mapping.Functions.Electric(pos,ang,model) - //THERE CAN ONLY BE ONE TRUE HERO - local prevs = ents.FindByClass("button_elec") - if prevs[1] != nil then - prevs[1]:Remove() - end - - local ent = ents.Create( "button_elec" ) - ent:SetPos( pos ) - ent:SetAngles( ang ) - ent:Spawn() - ent:PhysicsInit( SOLID_VPHYSICS ) - - local phys = ent:GetPhysicsObject() - if phys:IsValid() then - phys:EnableMotion(false) - end -end - -function nz.Mapping.Functions.BlockSpawn(pos,ang,model) - local block = ents.Create( "wall_block" ) - block:SetModel( model ) - block:SetPos( pos ) - block:SetAngles( ang ) - block:Spawn() - block:PhysicsInit( SOLID_VPHYSICS ) - - local phys = block:GetPhysicsObject() - if phys:IsValid() then - phys:EnableMotion(false) - end -end - -function nz.Mapping.Functions.BoxSpawn(pos,ang) - local box = ents.Create( "random_box_spawns" ) - box:SetPos( pos ) - box:SetAngles( ang ) - box:Spawn() - box:PhysicsInit( SOLID_VPHYSICS ) -end - -function nz.Mapping.Functions.PerkMachine(pos, ang, id) - local perkData = nz.Perks.Functions.Get(id) - - local perk = ents.Create("perk_machine") - perk:SetPerkID(id) - perk:TurnOff() - perk:SetPos(pos) - perk:SetAngles(ang) - perk:Spawn() - perk:Activate() - perk:PhysicsInit( SOLID_VPHYSICS ) - - local phys = perk:GetPhysicsObject() - if phys:IsValid() then - phys:EnableMotion(false) - end -end - -function nz.Mapping.Functions.BreakEntry(pos,ang) - local entry = ents.Create( "breakable_entry" ) - entry:SetPos( pos ) - entry:SetAngles( ang ) - entry:Spawn() - entry:PhysicsInit( SOLID_VPHYSICS ) - - local phys = entry:GetPhysicsObject() - if phys:IsValid() then - phys:EnableMotion(false) - end -end - - - -//Physgun Hooks -function nz.Mapping.Functions.OnPhysgunPickup( ply, ent ) - local class = ent:GetClass() - if ( class == "prop_buys" or class == "wall_block" or class == "breakable_entry" ) then - //Ghost the entity so we can put them in walls. - local phys = ent:GetPhysicsObject() - phys:EnableCollisions(false) - end - -end - -function nz.Mapping.Functions.OnPhysgunDrop( ply, ent ) - local class = ent:GetClass() - if ( class == "prop_buys" or class == "wall_block" or class == "breakable_entry" ) then - //Unghost the entity so we can put them in walls. - local phys = ent:GetPhysicsObject() - phys:EnableCollisions(true) - end - -end - -hook.Add( "PhysgunPickup", "nz.OnPhysPick", nz.Mapping.Functions.OnPhysgunPickup ) -hook.Add( "PhysgunDrop", "nz.OnDrop", nz.Mapping.Functions.OnPhysgunDrop ) \ No newline at end of file diff --git a/nzombies3/gamemode/mapping/sv_saveload.lua b/nzombies3/gamemode/mapping/sv_saveload.lua deleted file mode 100644 index 0795f094..00000000 --- a/nzombies3/gamemode/mapping/sv_saveload.lua +++ /dev/null @@ -1,265 +0,0 @@ -// - -nz.Mapping.Data.Version = 350 //Note to Ali; Any time you make an update to the way this is saved, increment this. - -function nz.Mapping.Functions.SaveConfig() - - local main = {} - - //Check if the nz folder exists - if !file.Exists( "nz/", "DATA" ) then - file.CreateDir( "nz" ) - end - - main.version = nz.Mapping.Data.Version - - local zed_spawns = {} - for k,v in pairs(ents.FindByClass("zed_spawns")) do - table.insert(zed_spawns, { - pos = v:GetPos(), - link = v.link - }) - end - - local player_spawns = {} - for k,v in pairs(ents.FindByClass("player_spawns")) do - table.insert(player_spawns, { - pos = v:GetPos(), - }) - end - - local wall_buys = {} - for k,v in pairs(ents.FindByClass("wall_buys")) do - table.insert(wall_buys, { - pos = v:GetPos(), - wep = v.WeaponGive, - price = v.Price, - angle = v:GetAngles( ), - }) - end - - local buyableprop_spawns = {} - for k,v in pairs(ents.FindByClass("prop_buys")) do - table.insert(buyableprop_spawns, { - pos = v:GetPos(), - angle = v:GetAngles(), - model = v:GetModel(), - flags = v.Data, - }) - end - - local elec_spawn = {} - for k,v in pairs(ents.FindByClass("button_elec")) do - table.insert(elec_spawn, { - pos = v:GetPos(), - angle = v:GetAngles( ), - model = v:GetModel(), - }) - end - - local block_spawns = {} - for k,v in pairs(ents.FindByClass("wall_block")) do - table.insert(block_spawns, { - pos = v:GetPos(), - angle = v:GetAngles( ), - model = v:GetModel(), - }) - end - - local randombox_spawn = {} - for k,v in pairs(ents.FindByClass("random_box_spawns")) do - table.insert(randombox_spawn, { - pos = v:GetPos(), - angle = v:GetAngles(), - }) - end - - local perk_machinespawns = {} - for k,v in pairs(ents.FindByClass("perk_machine")) do - table.insert(perk_machinespawns, { - pos = v:GetPos(), - angle = v:GetAngles(), - id = v:GetPerkID(), - }) - end - - //Normal Map doors - local door_setup = {} - for k,v in pairs(nz.Doors.Data.LinkFlags) do - v = nz.Doors.Functions.doorIndexToEnt(k) - if v:IsDoor() then - door_setup[k] = { - flags = v.Data, - } - end - end - - //barricades - local break_entry = {} - for k,v in pairs(ents.FindByClass("breakable_entry")) do - table.insert(break_entry, { - pos = v:GetPos(), - angle = v:GetAngles(), - }) - end - - main["ZedSpawns"] = zed_spawns - main["PlayerSpawns"] = player_spawns - main["WallBuys"] = wall_buys - main["BuyablePropSpawns"] = buyableprop_spawns - main["ElecSpawns"] = elec_spawn - main["BlockSpawns"] = block_spawns - main["RandomBoxSpawns"] = randombox_spawn - main["PerkMachineSpawns"] = perk_machinespawns - main["DoorSetup"] = door_setup - main["BreakEntry"] = break_entry - - file.Write( "nz/nz_"..game.GetMap( ).."_"..os.date("%H_%M_%j")..".txt", util.TableToJSON( main ) ) - PrintMessage( HUD_PRINTTALK, "[NZ] Saved to garrysmod/data/nz/".."nz_"..game.GetMap( ).."_"..os.date("%H_%M_%j")..".txt" ) - -end - -function nz.Mapping.Functions.ClearConfig() - print("[NZ] Clearing current map") - - for k,v in pairs(ents.FindByClass("zed_spawns")) do - v:Remove() - end - - for k,v in pairs(ents.FindByClass("player_spawns")) do - v:Remove() - end - - for k,v in pairs(ents.FindByClass("wall_buys")) do - v:Remove() - end - - for k,v in pairs(ents.FindByClass("prop_buys")) do - v:Remove() - end - - for k,v in pairs(ents.FindByClass("button_elec")) do - v:Remove() - end - - for k,v in pairs(ents.FindByClass("wall_block")) do - v:Remove() - end - - for k,v in pairs(ents.FindByClass("random_box_spawns")) do - v:Remove() - end - - for k,v in pairs(ents.FindByClass("perk_machine")) do - v:Remove() - end - - //Normal Map doors - for k,v in pairs(nz.Doors.Data.LinkFlags) do - nz.Doors.Functions.RemoveMapDoorLink( k ) - end - - for k,v in pairs(ents.FindByClass("breakable_entry")) do - v:Remove() - end - - //Sync - nz.Rounds.Functions.SendSync() - nz.Doors.Functions.SendSync() -end - -function nz.Mapping.Functions.LoadConfig( name ) - - local filepath = "nz/"..name - - if file.Exists( filepath, "DATA" ) then - print("[NZ] MAP CONFIG FOUND!") - - - - local data = util.JSONToTable( file.Read( filepath, "DATA" ) ) - - local version = data.version - - //Check the version of the config. - if version == nil then - print("This map config is too out of date to be used. Sorry about that!") - return - end - - if version < nz.Mapping.Data.Version then - print("Warning: This map config was made with an older version of nZombies. After this has loaded, use the save command to save a newer version.") - end - - if version < 300 then - print("Warning: Inital Version: No changes have been made.") - end - - if version < 350 then - print("Warning: This map config does not contain any set barricades.") - end - - nz.Mapping.Functions.ClearConfig() - - print("[NZ] Loading " .. filepath .. "...") - - - //Start sorting the data - - for k,v in pairs(data.ZedSpawns) do - nz.Mapping.Functions.ZedSpawn(v.pos, v.link) - end - - for k,v in pairs(data.PlayerSpawns) do - nz.Mapping.Functions.PlayerSpawn(v.pos) - end - - for k,v in pairs(data.WallBuys) do - nz.Mapping.Functions.WallBuy(v.pos,v.wep, v.price, v.angle) - end - - for k,v in pairs(data.BuyablePropSpawns) do - nz.Mapping.Functions.PropBuy(v.pos, v.angle, v.model, v.flags) - end - - for k,v in pairs(data.ElecSpawns) do - nz.Mapping.Functions.Electric(v.pos, v.angle, v.model) - end - - for k,v in pairs(data.BlockSpawns) do - nz.Mapping.Functions.BlockSpawn(v.pos, v.angle, v.model) - end - - for k,v in pairs(data.RandomBoxSpawns) do - nz.Mapping.Functions.BoxSpawn(v.pos, v.angle) - end - - for k,v in pairs(data.PerkMachineSpawns) do - nz.Mapping.Functions.PerkMachine(v.pos, v.angle, v.id) - end - - //Normal Map doors - for k,v in pairs(data.DoorSetup) do - nz.Doors.Functions.CreateMapDoorLink(k, v.flags) - end - - if version >= 350 then - //Barricades - for k,v in pairs(data.BreakEntry) do - nz.Mapping.Functions.BreakEntry(v.pos, v.angle) - end - end - - print("[NZ] Finished loading map config.") - else - print(filepath) - print("[NZ] Warning: NO MAP CONFIG FOUND! Make a config in game using the /create command, then use /save to save it all!") - end - -end - -hook.Add("Initialize", "nz_Loadmaps", function() - timer.Simple(5, function() - nz.Mapping.Functions.LoadConfig("nz_"..game.GetMap()..".txt") - end) -end) \ No newline at end of file diff --git a/nzombies3/gamemode/mapping/sv_validation.lua b/nzombies3/gamemode/mapping/sv_validation.lua deleted file mode 100644 index db8dc054..00000000 --- a/nzombies3/gamemode/mapping/sv_validation.lua +++ /dev/null @@ -1,35 +0,0 @@ -// - -function nz.Mapping.Functions.CheckSpawns() - - //Check Player spawns - if #ents.FindByClass("player_spawns") == 0 then - for k,v in pairs(player.GetAll()) do - nz.Rounds.Functions.UnReady(v, "You have been set to un-ready since the map does not have enough player spawns placed.") - end - return false - end - - //Check Zombie Spawns - if #ents.FindByClass("zed_spawns") == 0 then - for k,v in pairs(player.GetAll()) do - nz.Rounds.Functions.UnReady(v, "You have been set to un-ready since the map does not have enough zombie spawns placed.") - end - return false - end - - return true -end - -function nz.Mapping.Functions.CheckEnoughPlayerSpawns() - - //Check Player spawns - if #ents.FindByClass("player_spawns") < #player.GetAll() then - for k,v in pairs(player.GetAll()) do - nz.Rounds.Functions.UnReady(v, "You have been set to un-ready since the map does not have enough player spawns placed.") - end - return false - end - - return true -end \ No newline at end of file diff --git a/nzombies3/gamemode/misc/sh_constructor.lua b/nzombies3/gamemode/misc/sh_constructor.lua deleted file mode 100644 index 63407406..00000000 --- a/nzombies3/gamemode/misc/sh_constructor.lua +++ /dev/null @@ -1,6 +0,0 @@ -//Main Tables -nz.Misc = {} -nz.Misc.Functions = {} -nz.Misc.Data = {} - -//_ Variables diff --git a/nzombies3/gamemode/misc/sh_weightedrandom.lua b/nzombies3/gamemode/misc/sh_weightedrandom.lua deleted file mode 100644 index f984f79e..00000000 --- a/nzombies3/gamemode/misc/sh_weightedrandom.lua +++ /dev/null @@ -1,24 +0,0 @@ -//http://snippets.luacode.org/snippets/Weighted_random_choice_104 - -local function weighted_total(choices) - local total = 0 - for choice, weight in pairs(choices) do - total = total + weight - end - return total -end - -local function weighted_random_choice( choices ) - local threshold = math.random(0, weighted_total(choices)) - local last_choice - for choice, weight in pairs(choices) do - threshold = threshold - weight - if threshold <= 0 then return choice end - last_choice = choice - end - return last_choice -end - -function nz.Misc.Functions.WeightedRandom(choices) - return weighted_random_choice(choices) -end \ No newline at end of file diff --git a/nzombies3/gamemode/misc/sv_chatcommands.lua b/nzombies3/gamemode/misc/sv_chatcommands.lua deleted file mode 100644 index c58b889d..00000000 --- a/nzombies3/gamemode/misc/sv_chatcommands.lua +++ /dev/null @@ -1,105 +0,0 @@ -//Chat Commands - -//Setup -nz.Misc.Data.ChatCommands = {} - -//Functions -function nz.Misc.Functions.NewChatCommand(text, func) - table.insert(nz.Misc.Data.ChatCommands, {text, func}) -end - -//Hooks -hook.Add( "PlayerSay", "chatCommand", function( ply, text, public ) - local text = string.lower(text) - for k,v in pairs(nz.Misc.Data.ChatCommands) do - if (string.sub(text, 1, string.len(v[1])) == v[1]) then - v[2](ply, text) - return false - end - end -end ) - -//Quick Function -NewChatCommand = nz.Misc.Functions.NewChatCommand - -// Actual Chat Commands - -NewChatCommand("/ready", function(ply, text) - nz.Rounds.Functions.ReadyUp(ply) -end) - -NewChatCommand("/unready", function(ply, text) - nz.Rounds.Functions.UnReady(ply) -end) - -NewChatCommand("/dropin", function(ply, text) - nz.Rounds.Functions.DropIn(ply) -end) - -NewChatCommand("/dropout", function(ply, text) - nz.Rounds.Functions.DropOut(ply) -end) - -NewChatCommand("/create", function(ply, text) - if ply:IsSuperAdmin() then - nz.Rounds.Functions.CreateMode() - end -end) - -NewChatCommand("/generate", function(ply, text) - if ply:IsSuperAdmin() then - if #ents.FindByClass("info_player_start") > 0 then - navmesh.BeginGeneration( ) - else - ply:PrintMessage( HUD_PRINTTALK, "[NZ] There were no walkable seeds found. Please stand on the ground, and use /forcegenerate." ) - end - end -end) - -NewChatCommand("/save", function(ply, text) - if ply:IsSuperAdmin() then - if nz.Rounds.Data.CurrentState == ROUND_CREATE then - nz.Mapping.Functions.SaveConfig() - else - ply:PrintMessage( HUD_PRINTTALK, "[NZ] You can't save outside of create mode." ) - end - end -end) - -NewChatCommand("/forcegenerate", function(ply, text) - if ply:IsSuperAdmin() then - local ent = ents.Create("info_player_start") - ent:SetPos(ply:GetPos()) - ent:Spawn() - navmesh.BeginGeneration( ) - end -end) - -NewChatCommand("/load", function(ply, text) - if ply:IsSuperAdmin() then - if nz.Rounds.Data.CurrentState == ROUND_CREATE or nz.Rounds.Data.CurrentState == ROUND_INIT then - nz.Interfaces.Functions.SendInterface(ply, "ConfigLoader", {configs = file.Find( "nz/nz_"..game.GetMap( ).."*", "DATA" )}) - else - ply:PrintMessage( HUD_PRINTTALK, "[NZ] You can't load while playing!" ) - end - end -end) - -//Tests - -NewChatCommand("/spec", function(ply, text) - ply:PermSpec() -end) - -NewChatCommand("/soundcheck", function(ply, text) - if ply:IsSuperAdmin() then - nz.Notifications.Functions.PlaySound("nz/powerups/double_points.mp3", 1) - nz.Notifications.Functions.PlaySound("nz/powerups/insta_kill.mp3", 2) - nz.Notifications.Functions.PlaySound("nz/powerups/max_ammo.mp3", 2) - nz.Notifications.Functions.PlaySound("nz/powerups/nuke.mp3", 2) - - nz.Notifications.Functions.PlaySound("nz/round/round_start.mp3", 14) - nz.Notifications.Functions.PlaySound("nz/round/round_end.mp3", 9) - nz.Notifications.Functions.PlaySound("nz/round/game_over_4.mp3", 21) - end -end) diff --git a/nzombies3/gamemode/misc/sv_consolecommands.lua b/nzombies3/gamemode/misc/sv_consolecommands.lua deleted file mode 100644 index 099ddf3b..00000000 --- a/nzombies3/gamemode/misc/sv_consolecommands.lua +++ /dev/null @@ -1,39 +0,0 @@ -//Chat Commands - -//Setup -nz.Misc.Data.ConsoleCommands = {} - -//Functions -function nz.Misc.Functions.NewConsoleCommand(text, func) - //For Future Use - table.insert(nz.Misc.Data.ConsoleCommands, {text, func}) - //Console Command usage - concommand.Add( text, func ) -end - -//Quick Function -NewConsoleCommand = nz.Misc.Functions.NewConsoleCommand - -// Actual Commands - -//Quick reload for dedicated severs -NewConsoleCommand("qr", function() - RunConsoleCommand("changelevel", game.GetMap()) -end) - -NewConsoleCommand("PrintWeps", function() - for k,v in pairs( weapons.GetList() ) do - print( v.ClassName ) - end -end) - -NewConsoleCommand("doorId", function() - local tr = util.TraceLine( util.GetPlayerTrace( player.GetByID(1) ) ) - if IsValid( tr.Entity ) then print( tr.Entity:doorIndex() ) end -end) - -NewConsoleCommand("test1", function() - nz.Doors.Functions.CreateMapDoorLink( 1236, "price=500,elec=0,link=1" ) - - timer.Simple(5, function() nz.Doors.Functions.RemoveMapDoorLink( 1236 ) end) -end) \ No newline at end of file diff --git a/nzombies3/gamemode/notifications/sh_constructor.lua b/nzombies3/gamemode/notifications/sh_constructor.lua deleted file mode 100644 index 3aad6e4a..00000000 --- a/nzombies3/gamemode/notifications/sh_constructor.lua +++ /dev/null @@ -1,10 +0,0 @@ -//Main Tables -nz.Notifications = {} -nz.Notifications.Functions = {} -nz.Notifications.Data = {} - -//_ Variables -if CLIENT then - nz.Notifications.Data.SoundQueue = {} - nz.Notifications.Data.NextSound = CurTime() -end diff --git a/nzombies3/gamemode/notifications/sh_sounds.lua b/nzombies3/gamemode/notifications/sh_sounds.lua deleted file mode 100644 index 3ecbc4d6..00000000 --- a/nzombies3/gamemode/notifications/sh_sounds.lua +++ /dev/null @@ -1,34 +0,0 @@ -// - -if SERVER then - - function nz.Notifications.Functions.PlaySound(path, delay) - nz.Notifications.Functions.SendRequest("sound", {path = path, delay = delay}) - end - -end - -if CLIENT then - - function nz.Notifications.Functions.AddSoundToQueue(data) - table.insert(nz.Notifications.Data.SoundQueue, data) - end - - function nz.Notifications.Functions.SoundHandler() - //Check we're allowed to play the next sound - if CurTime() > nz.Notifications.Data.NextSound then - //Check the queue - if nz.Notifications.Data.SoundQueue[1] != nil then - local data = nz.Notifications.Data.SoundQueue[1] - table.remove(nz.Notifications.Data.SoundQueue, 1) - surface.PlaySound( data.path ) - nz.Notifications.Data.NextSound = CurTime() + data.delay - end - end - end - - timer.Create("nz.Sound.Handler", 1, 0, nz.Notifications.Functions.SoundHandler) -end - - - diff --git a/nzombies3/gamemode/notifications/sh_sync.lua b/nzombies3/gamemode/notifications/sh_sync.lua deleted file mode 100644 index 9fa46119..00000000 --- a/nzombies3/gamemode/notifications/sh_sync.lua +++ /dev/null @@ -1,32 +0,0 @@ -//Client Server Syncing - -if SERVER then - - //Server to client (Server) - util.AddNetworkString( "nz.Notifications.Request" ) - - function nz.Notifications.Functions.SendRequest(header, data) - net.Start( "nz.Notifications.Request" ) - net.WriteString( header ) - net.WriteTable( data ) - net.Broadcast() - end - -end - -if CLIENT then - - //Server to client (Client) - function nz.Notifications.Functions.ReceiveRequest( length ) - print("Received Notifications Request") - local header = net.ReadString() - local data = net.ReadTable() - - if header == "sound" then - nz.Notifications.Functions.AddSoundToQueue(data) - end - end - - //Receivers - net.Receive( "nz.Notifications.Request", nz.Notifications.Functions.ReceiveRequest ) -end \ No newline at end of file diff --git a/nzombies3/gamemode/perks/sh_constructor.lua b/nzombies3/gamemode/perks/sh_constructor.lua deleted file mode 100644 index b5ed3a5d..00000000 --- a/nzombies3/gamemode/perks/sh_constructor.lua +++ /dev/null @@ -1,8 +0,0 @@ -//Main Tables -nz.Perks = {} -nz.Perks.Functions = {} -nz.Perks.Data = {} - -//_ Variables - -nz.Perks.Data.Players = {} \ No newline at end of file diff --git a/nzombies3/gamemode/perks/sh_meta.lua b/nzombies3/gamemode/perks/sh_meta.lua deleted file mode 100644 index 8d7054cb..00000000 --- a/nzombies3/gamemode/perks/sh_meta.lua +++ /dev/null @@ -1,53 +0,0 @@ -local playerMeta = FindMetaTable("Player") -if SERVER then - - function playerMeta:GivePerk(id) - local perkData = nz.Perks.Functions.Get(id) - if perkData == nil then return end - - local given = perkData.func(id, self) - - if given then - if nz.Perks.Data.Players[self] == nil then nz.Perks.Data.Players[self] = {} end - table.insert(nz.Perks.Data.Players[self], id) - - nz.Perks.Functions.SendSync() - else - //We didn't want to give them the perk for some reason, so lets back out and refund them. - self:GivePoints(perkData.price) - end - end - - function playerMeta:RemovePerk(id) - local perkData = nz.Perks.Functions.Get(id) - if perkData == nil then return end - - if nz.Perks.Data.Players[self] == nil then nz.Perks.Data.Players[self] = {} end - if self:HasPerk(id) then - table.RemoveByValue( nz.Perks.Data.Players[self], id ) - end - nz.Perks.Functions.SendSync() - end - - function playerMeta:RemovePerks() - nz.Perks.Data.Players[self] = {} - nz.Perks.Functions.SendSync() - end - -end - -function playerMeta:HasPerk(id) - if nz.Perks.Data.Players[self] == nil then nz.Perks.Data.Players[self] = {} end - if table.HasValue(nz.Perks.Data.Players[self], id) then - return true - end - return false -end - -function playerMeta:GetPerks(id) - if nz.Perks.Data.Players[self] == nil then nz.Perks.Data.Players[self] = {} end - if (self.Perks) then - return self.Perks - end - return false -end \ No newline at end of file diff --git a/nzombies3/gamemode/perks/sh_perks.lua b/nzombies3/gamemode/perks/sh_perks.lua deleted file mode 100644 index ccc8176e..00000000 --- a/nzombies3/gamemode/perks/sh_perks.lua +++ /dev/null @@ -1,121 +0,0 @@ -// - -function nz.Perks.Functions.NewPerk(id, data) - if SERVER then - //Sanitise any client data. - else - data.Func = nil - end - nz.Perks.Data[id] = data -end - -function nz.Perks.Functions.Get(id) - return nz.Perks.Data[id] -end - -function nz.Perks.Functions.GetList() - local tbl = {} - - for k,v in pairs(nz.Perks.Data) do - tbl[k] = v.name - end - - return tbl -end - -nz.Perks.Functions.NewPerk("jugg", { - name = "Juggernog", - off_model = "models/alig96/perks/jugg/jugg_off.mdl", - on_model = "models/alig96/perks/jugg/jugg_on.mdl", - price = 100, - func = function(self, ply) - ply:SetMaxHealth(200) - ply:SetHealth(200) - return true - end, -}) - -nz.Perks.Functions.NewPerk("dtap", { - name = "Double Tap", - off_model = "models/alig96/perks/doubletap/doubletap_off.mdl", - on_model = "models/alig96/perks/doubletap/doubletap_on.mdl", - price = 100, - func = function(self, ply) - local tbl = {} - for k,v in pairs(ply:GetWeapons()) do - if nz.Weps.Functions.IsFAS2( v ) then - table.insert(tbl, v) - end - end - if tbl[1] != nil then - local str = "" - for k,v in pairs(tbl) do - nz.Weps.Functions.ApplyDTap( ply, v ) - str = str .. v.ClassName .. ", " - end - ply:PrintMessage( HUD_PRINTTALK, "Double Tap Applied to: " .. str) - return true - else - ply:PrintMessage( HUD_PRINTTALK, "You don't have a weapon that is compatible with this perk. (Requires a FAS2 weapon)") - return false - end - end, -}) - -nz.Perks.Functions.NewPerk("revive", { - name = "Quick Revive", - off_model = "models/alig96/perks/revive/revive_off.mdl", - on_model = "models/alig96/perks/revive/revive_on.mdl", - price = 100, - func = function(self, ply) - print(self) - ply:PrintMessage( HUD_PRINTTALK, "This perk doesn't have any functionality yet.") - return false - end, -}) - -nz.Perks.Functions.NewPerk("sleight", { - name = "Sleight of Hand", - off_model = "models/alig96/perks/sleight/sleight_off.mdl", - on_model = "models/alig96/perks/sleight/sleight_on.mdl", - price = 100, - func = function(self, ply) - local tbl = {} - for k,v in pairs(ply:GetWeapons()) do - if nz.Weps.Functions.IsFAS2( v ) then - table.insert(tbl, v) - end - end - if tbl[1] != nil then - local str = "" - for k,v in pairs(tbl) do - nz.Weps.Functions.ApplySleight( ply, v ) - str = str .. v.ClassName .. ", " - end - ply:PrintMessage( HUD_PRINTTALK, "Sleight of Hand Applied to: " .. str) - return true - else - ply:PrintMessage( HUD_PRINTTALK, "You don't have a weapon that is compatible with this perk. (Requires a FAS2 weapon)") - return false - end - end, -}) - -nz.Perks.Functions.NewPerk("pap", { - name = "Pack-a-Punch", - off_model = "models/alig96/perks/packapunch/packapunch.mdl", //Find a new model. - on_model = "models/alig96/perks/packapunch/packapunch.mdl", - price = 100, - func = function(self, ply) - local wep = ply:GetActiveWeapon() - if wep.pap != true then - ply:PrintMessage( HUD_PRINTTALK, "Pack-a-Punch applied to: " .. wep.ClassName) - nz.Weps.Functions.ApplyPaP( ply, wep ) - timer.Simple(2, function() ply:RemovePerk("pap") end) - return true - else - ply:PrintMessage( HUD_PRINTTALK, "This weapon is already pap'd") - return false - end - end, -}) diff --git a/nzombies3/gamemode/perks/sh_sync.lua b/nzombies3/gamemode/perks/sh_sync.lua deleted file mode 100644 index 07a76e1c..00000000 --- a/nzombies3/gamemode/perks/sh_sync.lua +++ /dev/null @@ -1,29 +0,0 @@ -//Client Server Syncing - -if SERVER then - - //Server to client (Server) - util.AddNetworkString( "nz.Perks.Sync" ) - - function nz.Perks.Functions.SendSync() - local data = table.Copy(nz.Perks.Data.Players) - - net.Start( "nz.Perks.Sync" ) - net.WriteTable( data ) - net.Broadcast() - end - -end - -if CLIENT then - - //Server to client (Client) - function nz.Perks.Functions.ReceiveSync( length ) - print("Received Player Perks Sync") - nz.Perks.Data.Players = net.ReadTable() - PrintTable(nz.Perks.Data.Players) - end - - //Receivers - net.Receive( "nz.Perks.Sync", nz.Perks.Functions.ReceiveSync ) -end \ No newline at end of file diff --git a/nzombies3/gamemode/player_class/sh_constructor.lua b/nzombies3/gamemode/player_class/sh_constructor.lua deleted file mode 100644 index bfd0206f..00000000 --- a/nzombies3/gamemode/player_class/sh_constructor.lua +++ /dev/null @@ -1,6 +0,0 @@ -//Main Tables -nz.Players = {} -nz.Players.Functions = {} -nz.Players.Data = {} - -//_ Variables diff --git a/nzombies3/gamemode/player_class/sh_player_create.lua b/nzombies3/gamemode/player_class/sh_player_create.lua deleted file mode 100644 index 5deaaeb8..00000000 --- a/nzombies3/gamemode/player_class/sh_player_create.lua +++ /dev/null @@ -1,35 +0,0 @@ -DEFINE_BASECLASS( "player_default" ) - -local PLAYER = {} - --- --- See gamemodes/base/player_class/player_default.lua for all overridable variables --- -PLAYER.WalkSpeed = 300 -PLAYER.RunSpeed = 600 -PLAYER.CanUseFlashlight = true - -function PLAYER:Init() - //Don't forget Colours - //This runs when the player is first brought into the game - //print("create") -end - -function PLAYER:Loadout() - - //Creation Tools - self.Player:Give( "weapon_physgun" ) - self.Player:Give( "nz_tool_zed_spawns" ) - self.Player:Give( "nz_tool_player_spawns" ) - self.Player:Give( "nz_tool_wall_buys" ) - self.Player:Give( "nz_tool_prop_modifier" ) - self.Player:Give( "nz_tool_door_locker" ) - self.Player:Give( "nz_tool_elec" ) - self.Player:Give( "nz_tool_block_spawns" ) - self.Player:Give( "nz_tool_random_box" ) - self.Player:Give( "nz_tool_perk_machine" ) - self.Player:Give( "nz_tool_barricades" ) - -end - -player_manager.RegisterClass( "player_create", PLAYER, "player_default" ) \ No newline at end of file diff --git a/nzombies3/gamemode/player_class/sh_player_ingame.lua b/nzombies3/gamemode/player_class/sh_player_ingame.lua deleted file mode 100644 index 742d5437..00000000 --- a/nzombies3/gamemode/player_class/sh_player_ingame.lua +++ /dev/null @@ -1,55 +0,0 @@ -DEFINE_BASECLASS( "player_default" ) - -local PLAYER = {} - --- --- See gamemodes/base/player_class/player_default.lua for all overridable variables --- -PLAYER.WalkSpeed = 100 -PLAYER.RunSpeed = 200 -PLAYER.CanUseFlashlight = true - -function PLAYER:Init() - //Don't forget Colours - //This runs when the player is first brought into the game and when they die during a round and are brought back - -end - -function PLAYER:Loadout() - //Give ammo and guns - for k,v in pairs(nz.Config.BaseStartingWeapons) do - self.Player:Give( v ) - end - nz.Weps.Functions.GiveMaxAmmo(self.Player) - - if FAS2_Attachments != nil then - for k,v in pairs(FAS2_Attachments) do - self.Player:FAS2_PickUpAttachment(v.key) - end - end - -end -function PLAYER:Spawn() - - if !self.Player:CanAfford(nz.Config.BaseStartingPoints) then //Has less than 500 points - //Poor guy has no money, lets start him off - self.Player:SetPoints(nz.Config.BaseStartingPoints) - end - - //Reset their perks - self.Player:RemovePerks() - - local spawns = ents.FindByClass("player_spawns") - //Get player number - for k,v in pairs(player.GetAll()) do - if v == self.Player then - if spawns[k]:IsValid() then - v:SetPos(spawns[k]:GetPos()) - else - print("No spawn set for player: " .. v:Nick()) - end - end - end -end - -player_manager.RegisterClass( "player_ingame", PLAYER, "player_default" ) diff --git a/nzombies3/gamemode/player_class/sv_players.lua b/nzombies3/gamemode/player_class/sv_players.lua deleted file mode 100644 index 10229428..00000000 --- a/nzombies3/gamemode/player_class/sv_players.lua +++ /dev/null @@ -1,47 +0,0 @@ -// - -function nz.Players.Functions.PlayerNoClip( ply, desiredState ) - if ply:Alive() and nz.Rounds.Data.CurrentState == ROUND_CREATE then - return ply:IsSuperAdmin() - end -end - -function nz.Players.Functions.FullSync( ply ) - //Electric - nz.Elec.Functions.SendSync() - //PowerUps - nz.PowerUps.Functions.SendSync() - //Doors - nz.Doors.Functions.SendSync() - //Perks - nz.Perks.Functions.SendSync() - //Rounds - nz.Rounds.Functions.SendSync() -end - -function nz.Players.Functions.PlayerInitialSpawn( ply ) - timer.Simple(1, function() - //Fully Sync - nz.Players.Functions.FullSync( ply ) - end) -end - -function nz.Players.Functions.PlayerDisconnected( ply ) - nz.Rounds.Functions.DropOut(ply) -end - -function nz.Players.Functions.FriendlyFire( ply, ent ) - if ent:IsPlayer() then - if ply:Team() == ent:Team() then - return false - end - end -end - -function GM:PlayerNoClip( ply, desiredState ) - return nz.Players.Functions.PlayerNoClip(ply, desiredState) -end - -hook.Add( "PlayerInitialSpawn", "nz.PlayerInitialSpawn", nz.Players.Functions.PlayerInitialSpawn ) -hook.Add( "PlayerShouldTakeDamage", "nz.FriendlyFire", nz.Players.Functions.FriendlyFire ) -hook.Add( "PlayerDisconnected", "nz.PlayerDisconnected", nz.Players.Functions.PlayerDisconnected ) diff --git a/nzombies3/gamemode/points/sh_points.lua b/nzombies3/gamemode/points/sh_points.lua deleted file mode 100644 index 93ee446b..00000000 --- a/nzombies3/gamemode/points/sh_points.lua +++ /dev/null @@ -1,36 +0,0 @@ -local _PLAYER = FindMetaTable("Player") - -function _PLAYER:GetPoints() - return self:GetNWInt("points") or 0 -end - -function _PLAYER:HasPoints(amount) - return self:GetPoints() >= amount -end - -function _PLAYER:CanAfford(amount) - return (self:GetPoints() - amount) >= 0 -end - -if (SERVER) then - -- Sets the character's amount of currency to a specific value. - function _PLAYER:SetPoints(amount) - amount = math.Round(amount, 2) - self:SetNWInt("points", amount) - end - - -- Quick function to set the money to the current amount plus an amount specified. - function _PLAYER:GivePoints(amount) - //If double points is on. - if nz.PowerUps.Functions.IsPowerupActive("dp") then - amount = amount * 2 - end - self:SetPoints(self:GetPoints() + amount) - end - - -- Takes away a certain amount by inverting the amount specified. - function _PLAYER:TakePoints(amount) - //Changed to prevent double points from removing double the points. - Don't even think of changing this back Ali, Love Ali. - self:SetPoints(self:GetPoints() - amount) - end -end \ No newline at end of file diff --git a/nzombies3/gamemode/powerups/sh_constructor.lua b/nzombies3/gamemode/powerups/sh_constructor.lua deleted file mode 100644 index fdb2baf7..00000000 --- a/nzombies3/gamemode/powerups/sh_constructor.lua +++ /dev/null @@ -1,8 +0,0 @@ -//Main Tables -nz.PowerUps = {} -nz.PowerUps.Functions = {} -nz.PowerUps.Data = {} - -//_ Variables - -nz.PowerUps.Data.ActivePowerUps = {} \ No newline at end of file diff --git a/nzombies3/gamemode/powerups/sh_powerups.lua b/nzombies3/gamemode/powerups/sh_powerups.lua deleted file mode 100644 index e474de65..00000000 --- a/nzombies3/gamemode/powerups/sh_powerups.lua +++ /dev/null @@ -1,143 +0,0 @@ -// - -if SERVER then - function nz.PowerUps.Functions.Activate(id, ply) - local powerupData = nz.PowerUps.Functions.Get(id) - - if powerupData.duration != 0 then - //Activate for a certain time - nz.PowerUps.Data.ActivePowerUps[id] = CurTime() + powerupData.duration - //else - //Activate Once - - end - - //Notify - - powerupData.func(id, ply) - - //Sync - nz.PowerUps.Functions.SendSync() - end - - function nz.PowerUps.Functions.SpawnPowerUp(pos) - local choices = {} - local total = 0 - - //Chance it - for k,v in pairs(nz.PowerUps.Data) do - if k != "ActivePowerUps" then - choices[k] = v.chance - total = total + v.chance - end - end - - //Insert a blank // Change 100 to increase the blank - choices["null"] = 500 - total - - local id = nz.Misc.Functions.WeightedRandom(choices) - if id == "null" then return end // Back out - - //Spawn it - local powerupData = nz.PowerUps.Functions.Get(id) - - local pos = pos+Vector(0,0,50) - local ent = ents.Create("drop_powerup") - ent:SetPowerUp(id) - pos.z = pos.z - ent:OBBMaxs().z - ent:SetModel(powerupData.model) - ent:SetPos(pos) - ent:Spawn() - end - -end - -function nz.PowerUps.Functions.IsPowerupActive(id) - - local time = nz.PowerUps.Data.ActivePowerUps[id] - - if time != nil then - //Check if it is still within the time. - if CurTime() > time then - //Expired - nz.PowerUps.Data.ActivePowerUps[id] = nil - else - return true - end - end - - return false - -end - -function nz.PowerUps.Functions.AllActivePowerUps() - - return nz.PowerUps.Data.ActivePowerUps - -end - -function nz.PowerUps.Functions.NewPowerUp(id, data) - if SERVER then - //Sanitise any client data. - else - data.Func = nil - end - nz.PowerUps.Data[id] = data -end - -function nz.PowerUps.Functions.Get(id) - return nz.PowerUps.Data[id] -end - -//Double Points -nz.PowerUps.Functions.NewPowerUp("dp", { - name = "Double Points", - model = "models/props_c17/gravestone003a.mdl", - scale = 0.5, - chance = 5, - duration = 30, - func = (function(self, ply) - nz.Notifications.Functions.PlaySound("nz/powerups/double_points.mp3", 1) - end), -}) - -//Max Ammo -nz.PowerUps.Functions.NewPowerUp("maxammo", { - name = "Max Ammo", - model = "models/Items/BoxSRounds.mdl", - scale = 1.5, - chance = 5, - duration = 0, - func = (function(self, ply) - nz.Notifications.Functions.PlaySound("nz/powerups/max_ammo.mp3", 2) - //Give everyone ammo - for k,v in pairs(player.GetAll()) do - nz.Weps.Functions.GiveMaxAmmo(v) - end - end), -}) - -//Insta Kill -nz.PowerUps.Functions.NewPowerUp("insta", { - name = "Insta Kill", - model = "models/Gibs/HGIBS.mdl", - scale = 3, - chance = 5, - duration = 30, - func = (function(self, ply) - nz.Notifications.Functions.PlaySound("nz/powerups/insta_kill.mp3", 1) - end), -}) - -//Nuke -nz.PowerUps.Functions.NewPowerUp("nuke", { - name = "Nuke", - model = "models/props_junk/watermelon01.mdl", - scale = 1.5, - chance = 5, - duration = 0, - func = (function(self, ply) - nz.Notifications.Functions.PlaySound("nz/powerups/nuke.mp3", 1) - nz.PowerUps.Functions.Nuke() - end), -}) diff --git a/nzombies3/gamemode/powerups/sh_sync.lua b/nzombies3/gamemode/powerups/sh_sync.lua deleted file mode 100644 index b2e58b73..00000000 --- a/nzombies3/gamemode/powerups/sh_sync.lua +++ /dev/null @@ -1,29 +0,0 @@ -//Client Server Syncing - -if SERVER then - - //Server to client (Server) - util.AddNetworkString( "nz.PowerUps.Sync" ) - - function nz.PowerUps.Functions.SendSync() - local data = table.Copy(nz.PowerUps.Data.ActivePowerUps) - - net.Start( "nz.PowerUps.Sync" ) - net.WriteTable( data ) - net.Broadcast() - end - -end - -if CLIENT then - - //Server to client (Client) - function nz.PowerUps.Functions.ReceiveSync( length ) - print("Received PowerUps Sync") - nz.PowerUps.Data.ActivePowerUps = net.ReadTable() - PrintTable(nz.PowerUps.Data.ActivePowerUps) - end - - //Receivers - net.Receive( "nz.PowerUps.Sync", nz.PowerUps.Functions.ReceiveSync ) -end \ No newline at end of file diff --git a/nzombies3/gamemode/powerups/sv_powerups.lua b/nzombies3/gamemode/powerups/sv_powerups.lua deleted file mode 100644 index d133f4e6..00000000 --- a/nzombies3/gamemode/powerups/sv_powerups.lua +++ /dev/null @@ -1,36 +0,0 @@ -// - -function nz.PowerUps.Functions.Nuke() - //Kill them all - for k,v in pairs(nz.Config.ValidEnemies) do - for k2,enemy in pairs(ents.FindByClass(v)) do - if enemy:IsValid() then - local insta = DamageInfo() - insta:SetDamage(enemy:Health()) - insta:SetAttacker(Entity(0)) - insta:SetDamageType(DMG_BLAST_SURFACE) - //Delay so it doesn't "die" twice - timer.Simple(0.1, function() if enemy:IsValid() then enemy:TakeDamageInfo( insta ) end end) - end - end - end - - //Give the players a set amount of points - for k,v in pairs(player.GetAll()) do - if v:IsPlayer() then - v:GivePoints(500) - end - end -end - -function nz.PowerUps.Functions.CleanUp() - //Clear all powerups - for k,v in pairs(ents.FindByClass("drop_powerup")) do - v:Remove() - end - - //Turn off all modifiers - table.Empty(nz.PowerUps.Data.ActivePowerUps) - //Sync - nz.PowerUps.Functions.SendSync() -end \ No newline at end of file diff --git a/nzombies3/gamemode/props_menu/cl_menu.lua b/nzombies3/gamemode/props_menu/cl_menu.lua deleted file mode 100644 index bd8a5ca9..00000000 --- a/nzombies3/gamemode/props_menu/cl_menu.lua +++ /dev/null @@ -1,75 +0,0 @@ - -function nz.PropsMenu.Functions.Create( ) - - //Create a Frame to contain everything. - nz.PropsMenu.Data.MainFrame = vgui.Create( "DFrame" ) - nz.PropsMenu.Data.MainFrame:SetTitle( "Props Menu" ) - nz.PropsMenu.Data.MainFrame:SetSize( 375, 240 ) - nz.PropsMenu.Data.MainFrame:Center() - nz.PropsMenu.Data.MainFrame:MakePopup() - nz.PropsMenu.Data.MainFrame:ShowCloseButton( false ) - nz.PropsMenu.Data.MainFrame:SetVisible( false ) - - local PropertySheet = vgui.Create( "DPropertySheet", nz.PropsMenu.Data.MainFrame ) - PropertySheet:SetPos( 10, 30 ) - PropertySheet:SetSize( 355, 200 ) - - //Loop to make all the tabs - local tabs = {} - tabs.Scrolls = {} - tabs.Lists = {} - - for k,v in pairs(nz.PropsMenu.Data.Categorys) do - tabs.Scrolls[k] = vgui.Create( "DScrollPanel", nz.PropsMenu.Data.MainFrame ) - tabs.Scrolls[k]:SetSize( 355, 200 ) - tabs.Scrolls[k]:SetPos( 10, 30 ) - - tabs.Lists[k] = vgui.Create( "DIconLayout", tabs.Scrolls[k] ) - tabs.Lists[k]:SetSize( 340, 200 ) - tabs.Lists[k]:SetPos( 0, 0 ) - tabs.Lists[k]:SetSpaceY( 5 ) //Sets the space in between the panels on the X Axis by 5 - tabs.Lists[k]:SetSpaceX( 5 ) //Sets the space in between the panels on the Y Axis by 5 - if v == true then v = nil end - PropertySheet:AddSheet( k, tabs.Scrolls[k], nil, false, false, v ) - end - - - - for k,v in pairs(nz.PropsMenu.Data.Models) do //Make a loop to create a bunch of panels inside of the DIconLayout - local ListItem = tabs.Lists[v[1]]:Add( "SpawnIcon" ) //Add DPanel to the DIconLayout - ListItem:SetSize( 40, 40 ) //Set the size of it - ListItem:SetModel(v[2]) - ListItem.Model = v[2] - ListItem.DoClick = function( item ) - nz.PropsMenu.Functions.Request(item.Model) - surface.PlaySound( "ui/buttonclickrelease.wav" ) - end - //You don't need to set the position, that is done automatically. - - end - -end - -function nz.PropsMenu.Functions.Open() - //Check if we're in create mode - if nz.Rounds.Data.CurrentState == ROUND_CREATE and LocalPlayer():IsSuperAdmin() then - if nz.PropsMenu.Data.MainFrame == nil then - nz.PropsMenu.Functions.Create() - end - - nz.PropsMenu.Data.MainFrame:SetVisible( true ) - end -end - -function nz.PropsMenu.Functions.Close() - if nz.Rounds.Data.CurrentState == ROUND_CREATE then - if nz.PropsMenu.Data.MainFrame == nil then - nz.PropsMenu.Functions.Create() - end - - nz.PropsMenu.Data.MainFrame:SetVisible( false ) - end -end - -hook.Add( "OnSpawnMenuOpen", "OpenSpawnMenu", nz.PropsMenu.Functions.Open ) -hook.Add( "OnSpawnMenuClose", "CloseSpawnMenu", nz.PropsMenu.Functions.Close ) diff --git a/nzombies3/gamemode/props_menu/sh_constructor.lua b/nzombies3/gamemode/props_menu/sh_constructor.lua deleted file mode 100644 index 11c71a52..00000000 --- a/nzombies3/gamemode/props_menu/sh_constructor.lua +++ /dev/null @@ -1,8 +0,0 @@ -//Main Tables -nz.PropsMenu = {} -nz.PropsMenu.Functions = {} -nz.PropsMenu.Data = {} - -//sh_populate -nz.PropsMenu.Data.Models = {} -nz.PropsMenu.Data.Categorys = {} \ No newline at end of file diff --git a/nzombies3/gamemode/props_menu/sh_net.lua b/nzombies3/gamemode/props_menu/sh_net.lua deleted file mode 100644 index 1800e61a..00000000 --- a/nzombies3/gamemode/props_menu/sh_net.lua +++ /dev/null @@ -1,40 +0,0 @@ -//Client Server Syncing - -if CLIENT then - - //Client to Server (Client) - function nz.PropsMenu.Functions.Request( model ) - net.Start( "nz.PropsMenu.Request" ) - net.WriteString( model ) - net.SendToServer() - end - -end - -if SERVER then - - //Client to Server (Server) - util.AddNetworkString( "nz.PropsMenu.Request" ) - - function nz.PropsMenu.Functions.HandleRequest( len, ply ) - local model = net.ReadString() - if nz.Rounds.Data.CurrentState == ROUND_CREATE then - print(ply:Nick() .. " requested prop " .. model) - if ply:IsSuperAdmin() then - local tr = util.GetPlayerTrace( ply ) - tr.mask = bit.bor( CONTENTS_SOLID, CONTENTS_MOVEABLE, CONTENTS_MONSTER, CONTENTS_WINDOW, CONTENTS_DEBRIS, CONTENTS_GRATE, CONTENTS_AUX ) - local trace = util.TraceLine( tr ) - - nz.Mapping.Functions.PropBuy(trace.HitPos,Angle(0,0,0),model) - //Since we're adding a prop, lets switch to the phys gun for convenience - ply:SelectWeapon( "weapon_physgun" ) - else - print("Denied request from " .. ply:Nick()) - end - end - end - - //Receivers - net.Receive( "nz.PropsMenu.Request", nz.PropsMenu.Functions.HandleRequest ) - -end diff --git a/nzombies3/gamemode/props_menu/sh_populate.lua b/nzombies3/gamemode/props_menu/sh_populate.lua deleted file mode 100644 index 196e73e5..00000000 --- a/nzombies3/gamemode/props_menu/sh_populate.lua +++ /dev/null @@ -1,24 +0,0 @@ -// - -function nz.PropsMenu.Functions.AddNewCategory( text, tooltip ) - if tooltip == nil then - tooltip = true - end - nz.PropsMenu.Data.Categorys[text] = tooltip -end - -function nz.PropsMenu.Functions.AddNewModel( cat, model ) - table.insert(nz.PropsMenu.Data.Models, {cat, model}) -end - -//QuickFunctions - -PropMenuAddCat = nz.PropsMenu.Functions.AddNewCategory -PropMenuAddModel = nz.PropsMenu.Functions.AddNewModel - -//Use -PropMenuAddCat("Gates") -PropMenuAddModel("Gates", "models/props_c17/fence03a.mdl") - -PropMenuAddCat("Scenery") -PropMenuAddModel("Scenery", "models/props_borealis/bluebarrel001.mdl") diff --git a/nzombies3/gamemode/random_box/sh_constructor.lua b/nzombies3/gamemode/random_box/sh_constructor.lua deleted file mode 100644 index 2ebe7ee2..00000000 --- a/nzombies3/gamemode/random_box/sh_constructor.lua +++ /dev/null @@ -1,6 +0,0 @@ -//Main Tables -nz.RandomBox = {} -nz.RandomBox.Functions = {} -nz.RandomBox.Data = {} - -//_ Variables diff --git a/nzombies3/gamemode/random_box/sv_random_box.lua b/nzombies3/gamemode/random_box/sv_random_box.lua deleted file mode 100644 index f858a145..00000000 --- a/nzombies3/gamemode/random_box/sv_random_box.lua +++ /dev/null @@ -1,62 +0,0 @@ -// - -function nz.RandomBox.Functions.SpawnBox() - //Get all spawns - local all = ents.FindByClass("random_box_spawns") - local rand = table.Random(all) - - if rand != nil then - local box = ents.Create( "random_box" ) - box:SetPos( rand:GetPos() ) - box:SetAngles( rand:GetAngles() ) - box:Spawn() - box:PhysicsInit( SOLID_VPHYSICS ) - - local phys = box:GetPhysicsObject() - if phys:IsValid() then - phys:EnableMotion(false) - end - else - print("No random box spawns have been set.") - end -end - -function nz.RandomBox.Functions.RemoveBox() - //Get all spawns - local all = ents.FindByClass("random_box") - //Loop just incase - for k,v in pairs(all) do - v:Remove() - end -end - -function nz.RandomBox.Functions.DecideWep(ply) - - local guns = {} - local blacklist = table.Copy(nz.Config.WeaponBlackList) - - //Add all our current guns to the black list - if ply:IsValid() then - for k,v in pairs( ply:GetWeapons() ) do - table.insert(blacklist, v.ClassName) - end - end - - //Add all guns with no model to the blacklist - for k,v in pairs( weapons.GetList() ) do - if !table.HasValue(blacklist, v.ClassName) then - if v.WorldModel == nil then - table.insert(blacklist, v.ClassName) - end - end - end - - //Add all guns to the guns table - for k,v in pairs( weapons.GetList() ) do - if !table.HasValue(blacklist, v.ClassName) then - table.insert(guns, v.ClassName) - end - end - - return table.Random(guns) -end diff --git a/nzombies3/gamemode/round_handler/sh_constructor.lua b/nzombies3/gamemode/round_handler/sh_constructor.lua deleted file mode 100644 index 3532bb29..00000000 --- a/nzombies3/gamemode/round_handler/sh_constructor.lua +++ /dev/null @@ -1,21 +0,0 @@ -//Main Tables -nz.Rounds = {} -nz.Rounds.Functions = {} -nz.Rounds.Data = {} - -//Round Variables -nz.Rounds.Data.CurrentState = ROUND_INIT -nz.Rounds.Data.CurrentRound = 0 - -//Misc -nz.Rounds.Data.CurrentPlayers = {} //No reason to be shared, but maybe in the future we will show the players clientside for scoreboard or smth -nz.Rounds.Elec = false - -if SERVER then - - //Round Variables - nz.Rounds.Data.KilledZombies = 0 - nz.Rounds.Data.ZombiesSpawned = 0 - nz.Rounds.Data.MaxZombies = 0 - nz.Rounds.Data.StartTime = CurTime() -end \ No newline at end of file diff --git a/nzombies3/gamemode/round_handler/sh_sync.lua b/nzombies3/gamemode/round_handler/sh_sync.lua deleted file mode 100644 index ed0c30c0..00000000 --- a/nzombies3/gamemode/round_handler/sh_sync.lua +++ /dev/null @@ -1,36 +0,0 @@ -//Client Server Syncing - -if SERVER then - - //Server to client (Server) - util.AddNetworkString( "nz.Round.Sync" ) - - function nz.Rounds.Functions.SendSync() - net.Start( "nz.Round.Sync" ) - net.WriteString( nz.Rounds.Data.CurrentState ) - net.WriteString( nz.Rounds.Data.CurrentRound ) - net.Broadcast() - end - -end - -if CLIENT then - - //Server to client (Client) - function nz.Rounds.Functions.ReceiveSync( length ) - print("Received Round Sync") - nz.Rounds.Data.CurrentState = tonumber(net.ReadString()) - nz.Rounds.Data.CurrentRound = tonumber(net.ReadString()) - - //Quickly reset the electric value - if !(nz.Rounds.Data.CurrentState == ROUND_PREP or nz.Rounds.Data.CurrentState == ROUND_PROG) or (nz.Rounds.Data.CurrentRound <= 1) then - nz.Rounds.Data.Elec = false - end - end - - - //Receivers - net.Receive( "nz.Round.Sync", nz.Rounds.Functions.ReceiveSync ) - - -end \ No newline at end of file diff --git a/nzombies3/gamemode/round_handler/sv_handler.lua b/nzombies3/gamemode/round_handler/sv_handler.lua deleted file mode 100644 index 91a0f0be..00000000 --- a/nzombies3/gamemode/round_handler/sv_handler.lua +++ /dev/null @@ -1,261 +0,0 @@ -// - -function nz.Rounds.Functions.CheckPrerequisites() - - //If there is there is less than one player - if #player.GetAll() < 1 then - return //"Not enough players to start a game." - end - - //Check if zed/player spawns have been setup - if nz.Mapping.Functions.CheckSpawns() == false then - return "No Zombie/Player spawns have been set." - end - - //Check if we have enough player spawns - if nz.Mapping.Functions.CheckEnoughPlayerSpawns() == false then - return "Not enough player spawns have been set. We need " .. #player.GetAll() .. " but only have " .. #ents.FindByClass("player_spawns") .. "." - end - - //If enough players are ready - if nz.Rounds.Functions.CheckReady() == false then - return "Not enough players have readied up." - end - - - //All Checks have passed, lets go! - if nz.Rounds.Data.StartTime == nil then - nz.Rounds.Data.StartTime = CurTime() + 5 - print("All checks passed, starting in 5 seconds.") - PrintMessage( HUD_PRINTTALK, "5 seconds till start time." ) - end - - local str = "" - //Get the players that are playing - for k,v in pairs(player.GetAll()) do - if v.Ready == 1 and v:IsValid() then - str = str .. v:Nick() .. ", " - end - end - PrintMessage( HUD_PRINTTALK, "Players that will be playing: " .. str ) - - return true - -end - -function nz.Rounds.Functions.PrepareRound() - - //Main Behaviour - nz.Rounds.Data.CurrentState = ROUND_PREP - nz.Rounds.Functions.SendSync() - nz.Rounds.Data.CurrentRound = nz.Rounds.Data.CurrentRound + 1 - - nz.Rounds.Data.MaxZombies = nz.Curves.Data.SpawnRate[nz.Rounds.Data.CurrentRound] - nz.Rounds.Data.KilledZombies = 0 - nz.Rounds.Data.ZombiesSpawned = 0 - - //Notify - PrintMessage( HUD_PRINTTALK, "ROUND: "..nz.Rounds.Data.CurrentRound.." preparing" ) - hook.Run("nz.Round.Prep", nz.Rounds.Data.CurrentRound) - //Play the sound - if nz.Rounds.Data.CurrentRound == 1 then - nz.Notifications.Functions.PlaySound("nz/round/round_start.mp3", 1) - else - nz.Notifications.Functions.PlaySound("nz/round/round_end.mp3", 1) - end - - //Spawn all players - //Check config for dropins - //For now, only allow the players who started the game to spawn - for k,v in pairs(nz.Rounds.Data.CurrentPlayers) do - nz.Rounds.Functions.ReSpawn(v) - end - - //Heal - for k,v in pairs(nz.Rounds.Data.CurrentPlayers) do - v:SetHealth(v:GetMaxHealth()) - end - - //Start the next round - timer.Simple(nz.Config.PrepareTime, function() nz.Rounds.Functions.StartRound() end) - -end - -function nz.Rounds.Functions.StartRound() - - if nz.Rounds.Data.CurrentState != ROUND_GO then - //Main Behaviour - nz.Rounds.Data.CurrentState = ROUND_PROG - nz.Rounds.Functions.SendSync() - //Notify - PrintMessage( HUD_PRINTTALK, "ROUND: "..nz.Rounds.Data.CurrentRound.." started" ) - hook.Run("nz.Round.Start", nz.Rounds.Data.CurrentRound) - end - -end - -function nz.Rounds.Functions.ResetGame() - //Main Behaviour - nz.Rounds.Data.CurrentState = ROUND_INIT - nz.Rounds.Functions.SendSync() - //Notify - PrintMessage( HUD_PRINTTALK, "GAME READY!" ) - //Reset variables - nz.Rounds.Data.CurrentRound = 0 - - nz.Rounds.Data.KilledZombies = 0 - nz.Rounds.Data.ZombiesSpawned = 0 - nz.Rounds.Data.MaxZombies = 0 - - //Reset all player ready states - for k,v in pairs(player.GetAll()) do - nz.Rounds.Functions.UnReady(v) - end - //Remove all enemies - for k,v in pairs(nz.Config.ValidEnemies) do - for k2,v2 in pairs(ents.FindByClass(v)) do - v2:Remove() - end - end - //Empty the table of stored players - table.Empty(nz.Rounds.Data.CurrentPlayers) - //Reset the electricity - nz.Elec.Functions.Reset() - //Remove the random box - nz.RandomBox.Functions.RemoveBox() - - //Reset all perk machines - for k,v in pairs(ents.FindByClass("perk_machine")) do - v:TurnOff() - end - - for k,v in pairs(player.GetAll()) do - v:SetPoints(0) //Reset all player points - v:RemovePerks() //Remove all players perks - end - - //Clean up powerups - nz.PowerUps.Functions.CleanUp() - -end - -function nz.Rounds.Functions.EndRound() - if nz.Rounds.Data.CurrentState != ROUND_GO then - //Main Behaviour - nz.Rounds.Data.CurrentState = ROUND_GO - nz.Rounds.Functions.SendSync() - //Notify - PrintMessage( HUD_PRINTTALK, "GAME OVER!" ) - PrintMessage( HUD_PRINTTALK, "Restarting in 10 seconds!" ) - nz.Notifications.Functions.PlaySound("nz/round/game_over_4.mp3", 21) - timer.Simple(10, function() - nz.Rounds.Functions.ResetGame() - end) - else - //This if statement is to prevent the game from ending twice if all players die during preparing - end -end - -function nz.Rounds.Functions.CreateMode() - - if nz.Rounds.Data.CurrentState == ROUND_INIT then - PrintMessage( HUD_PRINTTALK, "The mode has been set to creative mode!" ) - nz.Rounds.Data.CurrentState = ROUND_CREATE - //We are in create - for k,v in pairs(player.GetAll()) do - if v:IsSuperAdmin() then - nz.Rounds.Functions.Create(v) - end - end - nz.Doors.Functions.LockAllDoors() - elseif nz.Rounds.Data.CurrentState == ROUND_CREATE then - PrintMessage( HUD_PRINTTALK, "The mode has been set to play mode!" ) - nz.Rounds.Data.CurrentState = ROUND_INIT - //We are in play mode - for k,v in pairs(player.GetAll()) do - v:SetAsSpec() - end - end - nz.Rounds.Functions.SendSync() -end - -function nz.Rounds.Functions.SetupGame() - - //Store a session of all our players - for k,v in pairs(player.GetAll()) do - if v:IsValid() and !v:IsPermSpec() then - nz.Rounds.Functions.AddPlayer(v) - end - v.Ready = 0 - v:SetFrags(0) //Reset all player kills - end - - nz.Doors.Functions.LockAllDoors() - - //Open all doors with no price and electricity requirement - for k,v in pairs(ents.GetAll()) do - if v:IsDoor() or v:IsBuyableProp() then - if v.price == 0 and v.elec == 0 then - nz.Doors.Functions.OpenDoor( v ) - end - end - //Setup barricades - if v:GetClass() == "breakable_entry" then - v:ResetPlanks() - end - end - - //Empty the link table - table.Empty(nz.Doors.Data.OpenedLinks) - - //All doors with Link 0 (No Link) - nz.Doors.Data.OpenedLinks[0] = true - nz.Doors.Functions.SendSync() - - //Spawn a random box - nz.RandomBox.Functions.SpawnBox() - //Clear the start time - nz.Rounds.Data.StartTime = nil - - -end - -function nz.Rounds.Functions.RoundHandler() - - //If the game hasn't been started yet - if nz.Rounds.Data.CurrentState == ROUND_INIT then - local pre = nz.Rounds.Functions.CheckPrerequisites() - if pre == true then - if CurTime() > nz.Rounds.Data.StartTime then - nz.Rounds.Functions.SetupGame() - nz.Rounds.Functions.PrepareRound() - end - else - //Reset the start timer - nz.Rounds.Data.StartTime = nil - // notify why, just print for now - print(pre) - return //Don't process any further than here - end - - elseif nz.Rounds.Data.CurrentState == ROUND_CREATE then - //Un-ready all players - for k,v in pairs(player.GetAll()) do - nz.Rounds.Functions.UnReady(v, "You have been set to un-ready since the game has been set to creative mode") - end - return //Don't process any further than here - end - - //If all players are dead, then end the game. - if !nz.Rounds.Functions.CheckAlive() and (nz.Rounds.Data.CurrentState == ROUND_PROG or nz.Rounds.Data.CurrentState == ROUND_PREP) then - nz.Rounds.Functions.EndRound() - end - - //If we've killed all the zombies, then progress to the next level. - if (nz.Rounds.Data.KilledZombies == nz.Rounds.Data.MaxZombies) and nz.Rounds.Data.CurrentState == ROUND_PROG then - nz.Rounds.Functions.PrepareRound() - end - -end - -timer.Create("nz.Rounds.Handler", 1, 0, nz.Rounds.Functions.RoundHandler) diff --git a/nzombies3/gamemode/round_handler/sv_player.lua b/nzombies3/gamemode/round_handler/sv_player.lua deleted file mode 100644 index 60970b81..00000000 --- a/nzombies3/gamemode/round_handler/sv_player.lua +++ /dev/null @@ -1,91 +0,0 @@ -// - -//Player Functions - -function nz.Rounds.Functions.ReadyUp(ply) - if ply.Ready == nil then ply.Ready = 0 end - - if ply:IsPermSpec() then - ply:PrintMessage( HUD_PRINTTALK, "You can't ready up because you are a perm spectator!" ) - return - end - - if nz.Rounds.Data.CurrentState == ROUND_INIT then - if ply.Ready == 0 then - PrintMessage( HUD_PRINTTALK, ply:Nick().." is ready!" ) - ply.Ready = 1 - else - ply:PrintMessage( HUD_PRINTTALK, "You are already ready!" ) - end - elseif nz.Rounds.Data.CurrentState == ROUND_PROG or nz.Rounds.Data.CurrentState == ROUND_PREP then - ply:PrintMessage( HUD_PRINTTALK, "You can't ready up right now, use /dropin to spawn next round." ) - nz.Rounds.Functions.DropIn(ply) - end -end - -function nz.Rounds.Functions.DropIn(ply) - if nz.Config.AllowDropins == true and !table.HasValue(nz.Rounds.Data.CurrentPlayers, ply) then - PrintMessage( HUD_PRINTTALK, ply:Nick().." will be dropping in next round!" ) - nz.Rounds.Functions.AddPlayer(ply) - end -end - -function nz.Rounds.Functions.DropOut(ply) - if table.HasValue(nz.Rounds.Data.CurrentPlayers, ply) then - PrintMessage( HUD_PRINTTALK, ply:Nick().." has dropped out of the game!" ) - nz.Rounds.Functions.RemovePlayer(ply) - ply:KillSilent() - end -end - -function nz.Rounds.Functions.UnReady(ply, reason) - if ply.Ready == nil then ply.Ready = 0 end - if nz.Rounds.Data.CurrentState == ROUND_INIT then - if ply.Ready == 1 then - PrintMessage( HUD_PRINTTALK, ply:Nick().." is no longer ready!" ) - ply.Ready = 0 - if reason != nil then - ply:PrintMessage( HUD_PRINTTALK, reason ) - end - end - elseif nz.Rounds.Data.CurrentState == ROUND_PROG or nz.Rounds.Data.CurrentState == ROUND_PREP then - nz.Rounds.Functions.DropOut(ply) - end -end - -function nz.Rounds.Functions.ReSpawn(ply) - - if !ply:IsValid() then return end - if ply:IsPermSpec() then return end - - //Setup a player - ply:SetTeam( TEAM_PLAYERS ) - player_manager.SetPlayerClass( ply, "player_ingame" ) - if !ply:Alive() then - ply:Spawn() - end -end - -function nz.Rounds.Functions.AddPlayer(ply) - if ply:IsValid() then - table.insert(nz.Rounds.Data.CurrentPlayers, ply) - end -end - -function nz.Rounds.Functions.RemovePlayer(ply) - if table.HasValue(nz.Rounds.Data.CurrentPlayers, ply) then - table.RemoveByValue(nz.Rounds.Data.CurrentPlayers, ply) - end -end - -function nz.Rounds.Functions.Create(ply) - - //Setup a player - ply:SetTeam( TEAM_PLAYERS ) - player_manager.SetPlayerClass( ply, "player_create" ) - if !ply:Alive() then - ply:Spawn() - end - //SetPos - -end diff --git a/nzombies3/gamemode/round_handler/sv_validation.lua b/nzombies3/gamemode/round_handler/sv_validation.lua deleted file mode 100644 index 8f802467..00000000 --- a/nzombies3/gamemode/round_handler/sv_validation.lua +++ /dev/null @@ -1,41 +0,0 @@ -// - -function nz.Rounds.Functions.CheckReady() - - local count = 0 - local total = 0 - - //Get the total number of players that are willing - for k,v in pairs(player.GetAll()) do - if !v:IsPermSpec() then - total = total + 1 - end - end - //Get the total of ready players - for k,v in pairs(player.GetAll()) do - if v.Ready == 1 and v:IsValid() and !v:IsPermSpec() then - count = count + 1 - else - v.Ready = 0 - end - end - print("Waiting for players: " .. count .. " / " .. total) - if count / total < 0.66 then - return false - end - - return true - -end - -function nz.Rounds.Functions.CheckAlive() - - //Check alive players! - for k,v in pairs(team.GetPlayers(TEAM_PLAYERS)) do - if v:Alive() then - return true - end - end - - return false -end diff --git a/nzombies3/gamemode/shared.lua b/nzombies3/gamemode/shared.lua deleted file mode 100644 index 1dc25317..00000000 --- a/nzombies3/gamemode/shared.lua +++ /dev/null @@ -1,25 +0,0 @@ -GM.Name = "nZombies 3" -GM.Author = "N/A" -GM.Email = "N/A" -GM.Website = "N/A" - -// Constants \\ - -//Round Constants - -ROUND_INIT = 0 -ROUND_PREP = 1 -ROUND_PROG = 2 -ROUND_CREATE = 3 -ROUND_GO = 4 - -//Team Constants - -TEAM_SPECS = 1 -TEAM_PLAYERS = 2 - -//Setup Teams -team.SetUp( TEAM_SPECS, "Spectators", Color( 255, 255, 255 ) ) -team.SetUp( TEAM_PLAYERS, "Players", Color( 255, 0, 0 ) ) - -//DeriveGamemode("sandbox") \ No newline at end of file diff --git a/nzombies3/gamemode/spectator/sh_constructor.lua b/nzombies3/gamemode/spectator/sh_constructor.lua deleted file mode 100644 index 0ab01ca9..00000000 --- a/nzombies3/gamemode/spectator/sh_constructor.lua +++ /dev/null @@ -1,6 +0,0 @@ -//Main Tables -nz.Spectator = {} -nz.Spectator.Functions = {} -nz.Spectator.Data = {} - -//_ Variables diff --git a/nzombies3/gamemode/spectator/sv_gm.lua b/nzombies3/gamemode/spectator/sv_gm.lua deleted file mode 100644 index e3cdedc4..00000000 --- a/nzombies3/gamemode/spectator/sv_gm.lua +++ /dev/null @@ -1,45 +0,0 @@ -// - -//Gamemode Functions - -function nz.Spectator.Functions.InitialSpawn(ply) - - //Spectator Vars - if ply.SpecType == nil then - ply.SpecType = 4 - ply:Spectate( ply.SpecType ) - end - - timer.Simple(1, function() ply:SetAsSpec() end) - -end - -function nz.Spectator.Functions.OnDeath(ply) - if (nz.Rounds.Data.CurrentState == ROUND_CREATE) and (ply:IsSuperAdmin()) then - timer.Simple(1, function() ply:Spawn() end) - else - timer.Simple(1, function() ply:SetAsSpec() end) - end -end - -function nz.Spectator.Functions.DeathThink(ply) - - local livePlayers = team.GetPlayers( TEAM_PLAYERS ) - - if ply:KeyPressed( IN_JUMP ) then - ply.SpecType = ply.SpecType + 1 - if ply.SpecType > 6 then ply.SpecType = 4 end - ply:Spectate( ply.SpecType ) - elseif ply:KeyPressed( IN_ATTACK ) then - if !ply.SpecID then ply.SpecID = 1 end - ply.SpecID = ply.SpecID + 1 - if ply.SpecID > #livePlayers then ply.SpecID = 1 end - ply:SpectateEntity( livePlayers[ ply.SpecID ] ) - elseif ply:KeyPressed( IN_ATTACK2 ) then - if !ply.SpecID then ply.SpecID = 1 end - ply.SpecID = ply.SpecID - 1 - if ply.SpecID <= 0 then ply.SpecID = #livePlayers end - ply:SpectateEntity( livePlayers[ ply.SpecID ] ) - end - -end \ No newline at end of file diff --git a/nzombies3/gamemode/spectator/sv_override.lua b/nzombies3/gamemode/spectator/sv_override.lua deleted file mode 100644 index ef33bb7b..00000000 --- a/nzombies3/gamemode/spectator/sv_override.lua +++ /dev/null @@ -1,39 +0,0 @@ -//Get the meta Table -playerMeta = FindMetaTable( "Player" ) - -//Meta Functions -function playerMeta:IsSpec() - return nz.Spectator.Functions.IsSpec(self) -end - -function playerMeta:SetAsSpec() - nz.Spectator.Functions.SetAsSpec(self) -end - -function playerMeta:IsPermSpec() - return nz.Spectator.Functions.IsPermSpec(self) -end - -function playerMeta:PermSpec() - nz.Spectator.Functions.PermSpec(self) -end - -function playerMeta:SetAsPlayer() - nz.Spectator.Functions.SetAsPlayer(self) -end - -//Gamemode Overrides - -function GM:PlayerInitialSpawn( ply ) - nz.Spectator.Functions.InitialSpawn(ply) -end - -function GM:PlayerDeath( victim, weapon, killer ) - nz.Spectator.Functions.OnDeath(victim) -end - -function GM:PlayerDeathThink( ply ) - nz.Spectator.Functions.DeathThink(ply) -end - - diff --git a/nzombies3/gamemode/spectator/sv_player.lua b/nzombies3/gamemode/spectator/sv_player.lua deleted file mode 100644 index 7f4a9e20..00000000 --- a/nzombies3/gamemode/spectator/sv_player.lua +++ /dev/null @@ -1,45 +0,0 @@ -// - -//Spectator Functions - -function nz.Spectator.Functions.IsSpec(ply) - - if ply:Team() == TEAM_UNASSIGNED or ply:Team() == TEAM_SPECS then - return true - end - - return false - -end - -function nz.Spectator.Functions.SetAsSpec(ply) - - //Set them on to the spectator team - player_manager.SetPlayerClass( ply, "player_default" ) - ply:SetTeam( TEAM_SPECS ) - if ply:Alive() then - ply:KillSilent() - end - -end - -//Perm Spectator Functions -function nz.Spectator.Functions.IsPermSpec(ply) - if ply.specFlag == nil then - ply.specFlag = false - end - return ply.specFlag -end - -function nz.Spectator.Functions.PermSpec(ply) - if !ply:IsPermSpec() then - ply.specFlag = true - nz.Rounds.Functions.RemovePlayer(ply) - //Notify - PrintMessage( HUD_PRINTTALK, ply:Nick() .. " has been set to permanent spectator") - ply:SetAsSpec() - else - PrintMessage( HUD_PRINTTALK, ply:Nick() .. " is no longer a permanent spectator") - ply.specFlag = false - end -end \ No newline at end of file diff --git a/nzombies3/gamemode/weapons/sh_constructor.lua b/nzombies3/gamemode/weapons/sh_constructor.lua deleted file mode 100644 index 6b1a0d0f..00000000 --- a/nzombies3/gamemode/weapons/sh_constructor.lua +++ /dev/null @@ -1,6 +0,0 @@ -//Main Tables -nz.Weps = {} -nz.Weps.Functions = {} -nz.Weps.Data = {} - -//_ Variables diff --git a/nzombies3/gamemode/weapons/sh_fas2.lua b/nzombies3/gamemode/weapons/sh_fas2.lua deleted file mode 100644 index 04b3b6d6..00000000 --- a/nzombies3/gamemode/weapons/sh_fas2.lua +++ /dev/null @@ -1,80 +0,0 @@ -function FAS2_PlayAnim(wep, anim, speed, cyc, time) - speed = speed and speed or 1 - cyc = cyc and cyc or 0 - time = time or 0 - - if type(anim) == "table" then - anim = table.Random(anim) - end - - anim = string.lower(anim) - - if wep.sleight == true then - if string.find(anim, "reload") != nil or string.find(anim, "insert") != nil then - speed = 2 - end - end - if wep.dtap == true then - if string.find(anim, "fire") != nil or string.find(anim, "cock") != nil or string.find(anim, "pump") != nil then - speed = 1.25 - end - end - - if game.SinglePlayer() then - if SERVER then - if wep.Sounds[anim] then - wep.CurSoundTable = wep.Sounds[anim] - wep.CurSoundEntry = 1 - wep.SoundSpeed = speed - wep.SoundTime = CurTime() + time - end - end - /*if wep.Sounds[anim] then - for k, v in pairs(wep.Sounds[anim]) do - timer.Simple(v.time, function() - if IsValid(ply) and ply:Alive() and IsValid(wep) and wep == ply:GetActiveWeapon() then - wep:EmitSound(v.sound, 70, 100) - end - end) - end - end - end*/ - else - if wep.Sounds[anim] then - wep.CurSoundTable = wep.Sounds[anim] - wep.CurSoundEntry = 1 - wep.SoundSpeed = speed - wep.SoundTime = CurTime() + time - end - - /*if wep.Sounds[anim] then - for k, v in pairs(wep.Sounds[anim]) do - timer.Simple(v.time, function() - wep:EmitSound(v.sound, 70, 100) - end) - end - end*/ - end - - if SERVER and game.SinglePlayer() then - ply = Entity(1) - - umsg.Start("FAS2ANIM", ply) - umsg.String(anim) - umsg.Float(speed) - umsg.Float(cyc) - umsg.End() - end - - if CLIENT then - vm = wep.Wep - - wep.CurAnim = string.lower(anim) - - if vm then - vm:SetCycle(cyc) - vm:SetSequence(anim) - vm:SetPlaybackRate(speed) - end - end -end diff --git a/nzombies3/gamemode/weapons/sh_wep_sync.lua b/nzombies3/gamemode/weapons/sh_wep_sync.lua deleted file mode 100644 index 9b4c01f8..00000000 --- a/nzombies3/gamemode/weapons/sh_wep_sync.lua +++ /dev/null @@ -1,36 +0,0 @@ -//Client Server Syncing - -if SERVER then - - //Server to client (Server) - util.AddNetworkString( "nz.Weps.Sync" ) - - function nz.Weps.Functions.SendSync( ply, data ) - net.Start( "nz.Weps.Sync" ) - net.WriteTable( data ) - net.Send( ply ) - end - -end - -if CLIENT then - - //Server to client (Client) - function nz.Weps.Functions.ReceiveSync( length ) - print("Received Weps Sync") - local data = net.ReadTable() - local wep = data.wep - data.wep = nil - if wep != nil then - if wep:IsValid() then - print("Applying data to: " .. wep.ClassName) - for k,v in pairs(data) do - wep[k] = v - end - end - end - end - - //Receivers - net.Receive( "nz.Weps.Sync", nz.Weps.Functions.ReceiveSync ) -end diff --git a/nzombies3/gamemode/weapons/sv_ammo.lua b/nzombies3/gamemode/weapons/sv_ammo.lua deleted file mode 100644 index ebe77105..00000000 --- a/nzombies3/gamemode/weapons/sv_ammo.lua +++ /dev/null @@ -1,43 +0,0 @@ -//Functions -function nz.Weps.Functions.CalculateMaxAmmo(class) - local wep = weapons.Get(class) - local clip = wep.Primary.ClipSize - - return clip * 10 -end - -function nz.Weps.Functions.GiveMaxAmmoWep(ply, class) - - local wep = weapons.Get(class) - if wep == nil then return end - local ammo_type = wep.Primary.Ammo - local max_ammo = nz.Weps.Functions.CalculateMaxAmmo(class) - - local ply_weps = ply:GetWeapons() - local multi = 0 - - for k,v in pairs(ply_weps) do - local in_wep = weapons.Get(v:GetClass()) - if in_wep != nil then - if in_wep.Primary.Ammo == ammo_type then - multi = multi + 1 - end - end - end - - max_ammo = max_ammo * multi - - local curr_ammo = ply:GetAmmoCount( ammo_type ) - local give_ammo = max_ammo - curr_ammo - - //Just for display, since we're setting their ammo anyway - ply:GiveAmmo(give_ammo, ammo_type) - ply:SetAmmo(max_ammo, ammo_type) - -end - -function nz.Weps.Functions.GiveMaxAmmo(ply) - for k,v in pairs(ply:GetWeapons()) do - nz.Weps.Functions.GiveMaxAmmoWep(ply, v:GetClass()) - end -end diff --git a/nzombies3/gamemode/weapons/sv_weps.lua b/nzombies3/gamemode/weapons/sv_weps.lua deleted file mode 100644 index a56a3446..00000000 --- a/nzombies3/gamemode/weapons/sv_weps.lua +++ /dev/null @@ -1,103 +0,0 @@ -// - -function nz.Weps.Functions.IsFAS2( wep ) - if wep.Category == "FA:S 2 Weapons" then - return true - end - - return false -end - -function nz.Weps.Functions.ApplySleight( ply, wep ) - if nz.Weps.Functions.IsFAS2( wep ) and wep.sleight != true then - print("Applying Sleight to: " .. wep.ClassName) - local data = {} - //Normal - data["ReloadTime"] = true - data["ReloadTime_Nomen"] = true - data["ReloadTime_Empty"] = true - data["ReloadTime_Empty_Nomen"] = true - //BiPod - data["ReloadTime_Bipod"] = true - data["ReloadTime_Bipod_Nomen"] = true - data["ReloadTime_Bipod_Empty"] = true - data["ReloadTime_Bipod_Empty_Nomen"] = true - for k,v in pairs(data) do - if wep[k] != nil then - local val = wep[k] / 2 - wep[k] = val - data[k] = val - else - data[k] = nil - end - end - //Attach the weapon to the data - data["wep"] = wep - wep["sleight"] = true - data["sleight"] = true - nz.Weps.Functions.SendSync( ply, data ) - end -end - -function nz.Weps.Functions.ApplyDTap( ply, wep ) - if nz.Weps.Functions.IsFAS2( wep ) and wep.dtap != true then - print("Applying Dtap to: " .. wep.ClassName) - local data = {} - //Normal - data["FireDelay"] = true - for k,v in pairs(data) do - if wep[k] != nil then - local val = wep[k] / 2 - wep[k] = val - data[k] = val - else - data[k] = nil - end - end - //Attach the weapon to the data - data["wep"] = wep - wep["dtap"] = true - data["dtap"] = true - nz.Weps.Functions.SendSync( ply, data ) - end -end - -function nz.Weps.Functions.ApplyPaP( ply, wep ) - if wep.pap != true then - print("Applying PaP to: " .. wep.ClassName) - ply:PrintMessage( HUD_PRINTTALK, "Damage: " .. ply:GetActiveWeapon().Damage .. " > ".. ply:GetActiveWeapon().Damage * 2) - local data = {} - //Normal - data["Damage"] = true - for k,v in pairs(data) do - if wep[k] != nil then - local val = wep[k] * 2 - wep[k] = val - data[k] = val - else - data[k] = nil - end - end - //Attach the weapon to the data - data["wep"] = wep - wep["pap"] = true - data["pap"] = true - nz.Weps.Functions.SendSync( ply, data ) - end -end - -function nz.Weps.Functions.OnWepCreated( ent ) - if ent:IsWeapon() and (nz.Rounds.Data.CurrentState == ROUND_PREP or nz.Rounds.Data.CurrentState == ROUND_PROG) then - timer.Simple(1, function() - local ply = ent.Owner - if ply:HasPerk("sleight") then - nz.Weps.Functions.ApplySleight( ply, ent ) - end - if ply:HasPerk("dtap") then - nz.Weps.Functions.ApplyDTap( ply, ent ) - end - end) - end -end - -hook.Add("OnEntityCreated", "nz.Weps.OnEntityCreated", nz.Weps.Functions.OnWepCreated) diff --git a/nzombies3/nzombies3.txt b/nzombies3/nzombies3.txt deleted file mode 100644 index 2a5005d0..00000000 --- a/nzombies3/nzombies3.txt +++ /dev/null @@ -1,14 +0,0 @@ -"nzombies" -{ - "base" "base" - "title" "nZombies 3" - "version" "3.0" - "menusystem" "1" - - "author_name" "Alig96" - "author_email" "" - - "icon" "" - "info" "" - "hide" "0" -} diff --git a/nzombies3/content/resource/fonts/DK Umbilical Noose.ttf b/resource/fonts/DK Umbilical Noose.ttf similarity index 100% rename from nzombies3/content/resource/fonts/DK Umbilical Noose.ttf rename to resource/fonts/DK Umbilical Noose.ttf diff --git a/resource/fonts/HauntAOE.ttf b/resource/fonts/HauntAOE.ttf new file mode 100644 index 00000000..7df20116 Binary files /dev/null and b/resource/fonts/HauntAOE.ttf differ