diff options
| author | Alexander Pickering <alexandermpickering@gmail.com> | 2016-05-30 14:42:09 -0400 |
|---|---|---|
| committer | Alexander Pickering <alexandermpickering@gmail.com> | 2016-05-30 14:42:09 -0400 |
| commit | 2736f498f30220b858fc6fac23e7ddc4a597df6d (patch) | |
| tree | 374ceadedb654b00e09dac321620a8320830f734 | |
| download | redead-2736f498f30220b858fc6fac23e7ddc4a597df6d.tar.gz redead-2736f498f30220b858fc6fac23e7ddc4a597df6d.tar.bz2 redead-2736f498f30220b858fc6fac23e7ddc4a597df6d.zip | |
Inital commit
207 files changed, 28435 insertions, 0 deletions
diff --git a/backgrounds/bg1.jpg b/backgrounds/bg1.jpg Binary files differnew file mode 100644 index 0000000..be70e6d --- /dev/null +++ b/backgrounds/bg1.jpg diff --git a/backgrounds/bg2.jpg b/backgrounds/bg2.jpg Binary files differnew file mode 100644 index 0000000..33b7f0e --- /dev/null +++ b/backgrounds/bg2.jpg diff --git a/backgrounds/bg3.jpg b/backgrounds/bg3.jpg Binary files differnew file mode 100644 index 0000000..ce4e7a6 --- /dev/null +++ b/backgrounds/bg3.jpg diff --git a/backgrounds/bg4.jpg b/backgrounds/bg4.jpg Binary files differnew file mode 100644 index 0000000..dd3be6b --- /dev/null +++ b/backgrounds/bg4.jpg diff --git a/backgrounds/bg5.jpg b/backgrounds/bg5.jpg Binary files differnew file mode 100644 index 0000000..a8fec38 --- /dev/null +++ b/backgrounds/bg5.jpg diff --git a/backgrounds/bg6.jpg b/backgrounds/bg6.jpg Binary files differnew file mode 100644 index 0000000..4f202bb --- /dev/null +++ b/backgrounds/bg6.jpg diff --git a/entities/effects/barrel_gib/init.lua b/entities/effects/barrel_gib/init.lua new file mode 100644 index 0000000..f635312 --- /dev/null +++ b/entities/effects/barrel_gib/init.lua @@ -0,0 +1,42 @@ + +function EFFECT:Init( data ) + + self.Entity:SetModel( table.Random( GAMEMODE.BarrelGibs ) ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + //self.Entity:SetMaterial( "models/flesh" ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_DEBRIS ) + self.Entity:SetCollisionBounds( Vector( -128 -128, -128 ), Vector( 128, 128, 128 ) ) + self.Entity:SetAngles( Angle( math.Rand(0,360), math.Rand(0,360), math.Rand(0,360) ) ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + local vec = VectorRand() + vec.z = math.Clamp( vec.z, -0.4, 0.8 ) + + phys:Wake() + phys:SetMass( 100 ) + phys:AddAngleVelocity( VectorRand() * 500 ) + phys:SetVelocity( vec * math.Rand( 100, 200 ) ) + + end + + self.LifeTime = CurTime() + 15 + +end + +function EFFECT:Think( ) + + return self.LifeTime > CurTime() + +end + +function EFFECT:Render() + + self.Entity:DrawModel() + +end + diff --git a/entities/effects/biohazard/init.lua b/entities/effects/biohazard/init.lua new file mode 100644 index 0000000..8af6357 --- /dev/null +++ b/entities/effects/biohazard/init.lua @@ -0,0 +1,95 @@ + +EFFECT.Color = Color(100,80,0) + +function EFFECT:Init( data ) + + self.DieTime = CurTime() + 1.5 + self.SoundTime = 0 + + local pos = data:GetOrigin() + Vector(0,0,10) + local emitter = ParticleEmitter( pos ) + + self.Pos = pos + + for i=1, math.random(4,8) do + + local particle = emitter:Add( "effects/blood", pos ) + particle:SetVelocity( VectorRand() * 100 + Vector(0,math.random(-25,25),50) ) + particle:SetDieTime( 1.0 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 20, 40 ) ) + particle:SetEndSize( math.random( 50, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( self.Color.r, self.Color.g, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + for i=1, 10 do + + local vec = VectorRand() + vec.z = math.Rand( -0.2, 1.0 ) + + local particle = emitter:Add( "nuke/gore" .. math.random(1,2), pos ) + particle:SetVelocity( vec * 250 ) + particle:SetDieTime( math.Rand( 0.8, 1.0 ) ) + particle:SetStartAlpha( 200 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 10, 20 ) ) + particle:SetEndSize( math.random( 100, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( self.Color.r, self.Color.g + math.random(0,20), 0 ) + particle:SetGravity( Vector( 0, 0, -400 ) ) + + end + + for i=1, math.random(3,6) do + + local vec = VectorRand() + vec.z = math.Rand( -0.2, 1.0 ) + + local particle = emitter:Add( "nuke/gore" .. math.random( 1, 2 ), pos + Vector( 0, 0, math.random( -10, 10 ) ) ) + particle:SetVelocity( vec * 300 ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( math.Rand( 2.0, 4.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 255 ) + particle:SetStartSize( math.random( 8, 12 ) ) + particle:SetEndSize( 1 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( self.Color.r, self.Color.g, 0 ) + + particle:SetGravity( Vector( 0, 0, -500 ) ) + particle:SetCollide( true ) + particle:SetBounce( 0.5 ) + + particle:SetCollideCallback( function( part, pos, normal ) + + util.Decal( "yellowblood", pos + normal, pos - normal ) + + end ) + + end + + emitter:Finish() + +end + +function EFFECT:Think() + + if self.SoundTime < CurTime() then + + sound.Play( table.Random( GAMEMODE.GoreSplat ), self.Pos, 100, math.random(90,110) ) + + self.SoundTime = CurTime() + 0.5 + + end + + return self.DieTime > CurTime() + +end + +function EFFECT:Render() + +end diff --git a/entities/effects/body_gib/init.lua b/entities/effects/body_gib/init.lua new file mode 100644 index 0000000..d433bce --- /dev/null +++ b/entities/effects/body_gib/init.lua @@ -0,0 +1,142 @@ + + +function EFFECT:Init( data ) + + self.DieTime = CurTime() + 1.5 + self.SoundTime = CurTime() + math.Rand( 0.2, 1.0 ) + + local pos = data:GetOrigin() + Vector(0,0,50) + local emitter = ParticleEmitter( pos ) + + self.Pos = pos + self.Normal = data:GetNormal() + + local particle = emitter:Add( "effects/blood_core", pos ) + particle:SetDieTime( math.Rand( 0.5, 1.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 10 ) + particle:SetEndSize( math.random( 100, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + + local particle = emitter:Add( "effects/blood_core", pos ) + particle:SetDieTime( math.Rand( 6.0, 8.0 ) ) + particle:SetStartAlpha( 50 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 150, 200 ) ) + particle:SetEndSize( 200 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + particle:SetGravity( Vector( 0, 0, -5 ) ) + + for i=1, math.random(4,8) do + + local particle = emitter:Add( "effects/blood", pos ) + particle:SetVelocity( VectorRand() * 100 + Vector(0,math.random(-25,25),50) ) + particle:SetDieTime( 1.0 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 20, 40 ) ) + particle:SetEndSize( math.random( 50, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + for i=1, 12 do + + local vec = VectorRand() + vec.z = math.Rand( -0.2, 1.0 ) + + local particle = emitter:Add( "nuke/gore" .. math.random(1,2), pos ) + particle:SetVelocity( vec * 250 + ( self.Normal * ( i * 10 ) ) ) + particle:SetDieTime( math.Rand( 0.5, 1.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 10, 20 ) ) + particle:SetEndSize( math.random( 50, 100 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + for i=1, math.random(3,6) do + + local vec = VectorRand() + vec.z = math.Rand( -0.2, 1.0 ) + + local particle = emitter:Add( "nuke/gore" .. math.random(1,2), pos + Vector(0,0,math.random(-10,10)) ) + particle:SetVelocity( vec * 300 ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( math.Rand( 2.0, 4.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 255 ) + particle:SetStartSize( math.random( 8, 12 ) ) + particle:SetEndSize( 1 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 40, 0, 0 ) + + particle:SetGravity( Vector( 0, 0, -500 ) ) + particle:SetCollide( true ) + particle:SetBounce( 0.5 ) + + particle:SetCollideCallback( function( part, pos, normal ) + + util.Decal( "Blood", pos + normal, pos - normal ) + + end ) + + end + + emitter:Finish() + + for i=1, 8 do + + local ed = EffectData() + ed:SetOrigin( pos + Vector(0,0,math.random(0,30)) ) + + if i < 4 then + ed:SetScale( 1 ) + else + ed:SetScale( 2 ) + end + + util.Effect( "player_gib", ed, true, true ) + + end + + if LocalPlayer():GetPos():Distance( pos ) <= 300 then + + local frac = 1 - ( LocalPlayer():GetPos():Distance( pos ) / 300 ) + + for i=1, math.Round( frac * 6 ) do + + AddStain() + + end + + end + +end + +function EFFECT:Think( ) + + if self.SoundTime < CurTime() then + + sound.Play( table.Random( GAMEMODE.GoreSplat ), self.Pos, 100, math.random(90,110) ) + + self.SoundTime = CurTime() + math.Rand( 0.2, 0.6 ) + + end + + return self.DieTime > CurTime() + +end + +function EFFECT:Render() + +end + diff --git a/entities/effects/bomb_explosion/init.lua b/entities/effects/bomb_explosion/init.lua new file mode 100644 index 0000000..459c3bd --- /dev/null +++ b/entities/effects/bomb_explosion/init.lua @@ -0,0 +1,138 @@ + +local matRefraction = Material( "refract_ring" ) + +function EFFECT:Init( data ) + + self.Entity:SetRenderBounds( Vector() * -1024, Vector() * 1024 ) + + self.Pos = data:GetOrigin() + self.Norm = data:GetNormal() + self.Emitter = ParticleEmitter( self.Pos ) + self.DieTime = CurTime() + 5 + + for i=1, math.random(3,6) do + + local vec = self.Norm + VectorRand() * 0.7 + vec.x = math.Clamp( vec.x, -1.0, 0 ) + + local particle = self.Emitter:Add( "effects/fire_cloud2", self.Pos ) + + particle:SetVelocity( vec * math.random( 400, 600 ) ) + particle:SetDieTime( 1.0 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 5 ) + particle:SetEndSize( 0 ) + particle:SetColor( math.random( 150, 255 ), math.random( 100, 150 ), 100 ) + + particle:SetGravity( Vector( 0, 0, math.random( -700, -500 ) ) ) + particle:SetAirResistance( math.random( 20, 60 ) ) + particle:SetCollide( true ) + + particle:SetLifeTime( 0 ) + particle:SetThinkFunction( CloudThink ) + particle:SetNextThink( CurTime() + 0.1 ) + + end + + for i=1, 15 do + + local particle = self.Emitter:Add( "effects/muzzleflash"..math.random(1,4), self.Pos ) + + particle:SetVelocity( self.Norm * math.random(50,100) + VectorRand() * math.random(50,100) ) + particle:SetDieTime( 0.7 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.Rand( 20, 40 ) ) + particle:SetEndSize( math.Rand( 100, 200 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetRollDelta( math.Rand( -0.2, 0.2 ) ) + particle:SetColor( math.random( 150, 255 ), math.random( 100, 150 ), 100 ) + + local particle = self.Emitter:Add( "particle/particle_smokegrenade", self.Pos ) + + particle:SetDieTime( math.Rand( 1.5, 2.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.Rand( 20, 40 ) ) + particle:SetEndSize( math.Rand( 100, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetRollDelta( math.Rand( -0.1, 0.1 ) ) + + local vec = VectorRand() + vec.x = math.Rand( -0.1, 0.1 ) + + if i % 2 == 0 then + + particle:SetVelocity( self.Norm * math.random(100,150) + vec * math.random(40,80) ) + + else + + particle:SetVelocity( vec * math.random(100,150) ) + + end + + local dark = math.random( 10, 50 ) + particle:SetColor( dark, dark, dark ) + + particle:SetGravity( Vector(0,0,-50) ) + particle:SetCollide( true ) + + end + + local dlight = DynamicLight( self.Entity:EntIndex() ) + + if dlight then + + dlight.Pos = self.Pos + dlight.r = 250 + dlight.g = 200 + dlight.b = 50 + dlight.Brightness = math.Rand( 4, 8 ) + dlight.Decay = 2048 + dlight.size = 2048 + dlight.DieTime = CurTime() + 5 + + end + + self.Emitter:Finish() + +end + +function EFFECT:Think( ) + + return self.DieTime > CurTime() + +end + +function EFFECT:Render() + +end + +function CloudThink( part ) + + part:SetNextThink( CurTime() + 0.05 ) + + local scale = 1 - part:GetLifeTime() + local pos = part:GetPos() + local emitter = ParticleEmitter( pos ) + local vec = VectorRand() + vec.x = math.Rand( -0.1, 0 ) + + local particle = emitter:Add( "particle/particle_smokegrenade", pos ) + + particle:SetVelocity( vec * 3 + ( WindVector * ( 2 * ( 1 - scale ) ) ) ) + particle:SetDieTime( math.Rand( 2.0, 3.0 ) + scale * 1.0 ) + particle:SetStartAlpha( math.random( 100, 150 ) ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 1, 3 ) + scale * 20 ) + particle:SetEndSize( math.random( 1, 5 ) + scale * 30 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetRollDelta( math.Rand( -0.1, 0.1 ) ) + + local dark = math.random( 10, 50 ) + particle:SetColor( dark, dark, dark ) + + emitter:Finish() + +end diff --git a/entities/effects/c4_explosion/init.lua b/entities/effects/c4_explosion/init.lua new file mode 100644 index 0000000..bb676cc --- /dev/null +++ b/entities/effects/c4_explosion/init.lua @@ -0,0 +1,176 @@ + +function EFFECT:Init( data ) + + local pos = data:GetOrigin() + + local emitter = ParticleEmitter( pos ) + + for i=1,math.random(10,15) do + + local particle = emitter:Add( "particles/smokey", pos ) + + particle:SetVelocity( Vector(math.random(-90, 90),math.random(-90, 90), math.random(-70, 70) ) ) + particle:SetDieTime( math.Rand(3,6) ) + particle:SetStartAlpha( math.Rand( 55, 115 ) ) + particle:SetStartSize( math.Rand( 20, 30 ) ) + particle:SetEndSize( math.Rand( 140, 240 ) ) + particle:SetRoll( math.Rand( -95, 95 ) ) + particle:SetRollDelta( math.Rand( -0.12, 0.12 ) ) + particle:SetColor( 10,10,10 ) + + end + + for i=1, math.random(10,15) do + + local particle = emitter:Add( "effects/muzzleflash"..math.random(1,4), pos + Vector(math.random(-40,40),math.random(-40,40),math.random(-30,50))) + + particle:SetVelocity( Vector(math.random(-150,150),math.random(-150,150),math.random(100,200)) ) + particle:SetDieTime( math.Rand(1,1.5) ) + particle:SetStartAlpha( math.Rand( 200, 240 ) ) + particle:SetStartSize( 5 ) + particle:SetEndSize( math.Rand( 90, 100 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetRollDelta( math.Rand( -1, 1 ) ) + particle:SetColor( math.Rand( 150, 255 ), math.Rand( 100, 150 ), 100 ) + particle:VelocityDecay( false ) + + end + + for i=1, math.random(15,25) do + + local particle = emitter:Add( "effects/muzzleflash"..math.random(1,4), pos + Vector(math.random(-40,40),math.random(-40,40),math.random(10,20))) + + particle:SetVelocity( Vector(math.random(-200,200),math.random(-200,200),math.random(0,60)) ) + particle:SetDieTime( math.Rand( 1, 2 ) ) + particle:SetStartAlpha( math.Rand( 200, 240 ) ) + particle:SetStartSize( 48 ) + particle:SetEndSize( math.Rand( 168, 190 ) ) + particle:SetRoll( math.Rand( 360,480 ) ) + particle:SetRollDelta( math.Rand( -1, 1 ) ) + particle:SetColor( math.Rand( 150, 255 ), math.Rand( 100, 150 ), 100 ) + particle:VelocityDecay( true ) + + end + + for i=0,math.random(5,9) do + + local particle = emitter:Add( "effects/fire_embers"..math.random(1,3), pos ) + particle:SetVelocity( Vector(math.random(-400,400),math.random(-400,400),math.random(300,550)) ) + particle:SetDieTime(math.Rand(2,5)) + particle:SetStartAlpha(math.random(140,220)) + particle:SetEndAlpha(50) + particle:SetStartSize(math.random(3,4)) + particle:SetEndSize(0) + particle:SetRoll(math.random(-200,200)) + particle:SetRollDelta( math.random( -1, 1 ) ) + particle:SetColor(255, 220, 100) + particle:SetGravity(Vector(0,0,-520)) //-600 is normal + particle:SetCollide(true) + particle:SetBounce(0.45) + + end + + for i=1, 5 do + + local particle = emitter:Add( "particle/particle_smokegrenade", pos ) + + particle:SetDieTime( math.Rand( 2.0, 4.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + + if i % 2 == 1 then + particle:SetVelocity( Vector( math.random(-100,100), math.random(-100,100), math.random(0,50) ) ) + particle:SetStartSize( math.Rand( 50, 100 ) ) + particle:SetEndSize( math.Rand( 250, 500 ) ) + else + particle:SetVelocity( Vector( math.random(-200,200), math.random(-200,200), 0 ) ) + particle:SetStartSize( math.Rand( 50, 100 ) ) + particle:SetEndSize( math.Rand( 200, 400 ) ) + end + + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetRollDelta( math.Rand( -0.1, 0.1 ) ) + + local dark = math.random( 10, 50 ) + particle:SetColor( dark, dark, dark ) + + if math.random(1,4) != 1 then + + local vec = Vector( math.Rand(-8,8), math.Rand(-8,8), math.Rand(8,12) ) + local particle = emitter:Add( "effects/fire_cloud2", pos + vec * 10 ) + + particle:SetVelocity( vec * 80 ) + particle:SetDieTime( 1.0 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 100 ) + particle:SetStartSize( 8 ) + particle:SetEndSize( 0 ) + particle:SetColor( math.random( 150, 255 ), math.random( 100, 150 ), 100 ) + + particle:SetGravity( Vector( 0, 0, math.random( -700, -500 ) ) ) + particle:SetAirResistance( math.random( 20, 60 ) ) + particle:SetCollide( true ) + + particle:SetLifeTime( 0 ) + particle:SetThinkFunction( CloudThink ) + particle:SetNextThink( CurTime() + 0.1 ) + + end + + end + + emitter:Finish() + + local dlight = DynamicLight( self.Entity:EntIndex() ) + + if dlight then + + dlight.Pos = pos + dlight.r = 250 + dlight.g = 200 + dlight.b = 50 + dlight.Brightness = math.Rand( 4, 8 ) + dlight.Decay = 1024 + dlight.size = 1024 + dlight.DieTime = CurTime() + 5 + + end + +end + +function EFFECT:Think( ) + + return false + +end + +function EFFECT:Render() + +end + +function CloudThink( part ) + + part:SetNextThink( CurTime() + 0.12 ) + + local scale = 1 - part:GetLifeTime() + local pos = part:GetPos() + local emitter = ParticleEmitter( pos ) + + local particle = emitter:Add( "particle/particle_smokegrenade", pos ) + + particle:SetVelocity( VectorRand() * 3 + ( WindVector * ( 3 * ( 1 - scale ) ) ) ) + particle:SetDieTime( math.Rand( 2.0, 3.0 ) + scale * 1.0 ) + particle:SetStartAlpha( math.random( 100, 150 ) ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 1, 3 ) + scale * math.random( 20, 50 ) ) + particle:SetEndSize( math.random( 1, 5 ) + scale * math.random( 30, 50 ) ) + + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetRollDelta( math.Rand( -0.1, 0.1 ) ) + + local dark = math.random( 10, 50 ) + particle:SetColor( dark, dark, dark ) + + emitter:Finish() + +end diff --git a/entities/effects/energy_explosion/init.lua b/entities/effects/energy_explosion/init.lua new file mode 100644 index 0000000..d959e8a --- /dev/null +++ b/entities/effects/energy_explosion/init.lua @@ -0,0 +1,82 @@ + + +function EFFECT:Init( data ) + + self.DieTime = CurTime() + 1.5 + + local pos = data:GetOrigin() + local normal = data:GetNormal() + local emitter = ParticleEmitter( pos ) + + for i=1, 20 do + + local particle = emitter:Add( "effects/muzzleflash"..math.random(1,4), pos ) + particle:SetVelocity( VectorRand() * 100 ) + particle:SetDieTime( math.Rand( 0.3, 0.6 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.Rand( 5, 10 ) ) + particle:SetEndSize( math.Rand( 40, 80 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 100, 250 ) + + end + + for i=1, math.random(3,6) do + + local vec = normal * math.random( 150, 200 )+ VectorRand() * 50 + local normalized = vec:GetNormal():Angle() + + local particle = emitter:Add( "effects/yellowflare", pos ) + particle:SetVelocity( normal * math.random(150,200) + VectorRand() * 50 ) + particle:SetAngles( normalized ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( math.Rand( 0.8, 1.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 10 ) + particle:SetEndSize( 0 ) + particle:SetEndLength( 20 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 100, 200 ) + + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + for i=1, math.random(3,6) do + + local vec = VectorRand() * 500 + local normalized = vec:GetNormal():Angle() + + local particle = emitter:Add( "effects/yellowflare", pos ) + particle:SetVelocity( vec ) + particle:SetAngles( normalized ) + particle:SetDieTime( math.Rand( 2.0, 4.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 10 ) + particle:SetEndSize( 0 ) + particle:SetEndLength( 20 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 100, 200 ) + + particle:SetGravity( Vector( 0, 0, -500 ) ) + particle:SetCollide( true ) + particle:SetBounce( 1.0 ) + + end + + emitter:Finish() + +end + +function EFFECT:Think( ) + + return self.DieTime > CurTime() + +end + +function EFFECT:Render() + +end diff --git a/entities/effects/fire_explosion/init.lua b/entities/effects/fire_explosion/init.lua new file mode 100644 index 0000000..d51b1c3 --- /dev/null +++ b/entities/effects/fire_explosion/init.lua @@ -0,0 +1,83 @@ + + +function EFFECT:Init( data ) + + self.DieTime = CurTime() + 1.5 + + local pos = data:GetOrigin() + local normal = data:GetNormal() + local emitter = ParticleEmitter( pos ) + + local particle = emitter:Add( "effects/blood_core", pos ) + particle:SetDieTime( math.Rand( 1.0, 1.5 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 10 ) + particle:SetEndSize( math.random( 50, 100 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 50, 50 ) + + for i=1, 10 do + + local particle = emitter:Add( "effects/muzzleflash"..math.random(1,4), pos ) + particle:SetVelocity( VectorRand() * 50 + normal * 50 ) + particle:SetDieTime( math.Rand( 0.3, 0.6 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.Rand( 5, 10 ) ) + particle:SetEndSize( math.Rand( 30, 60 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 200, 150, 100 ) + + end + + for i=1, math.random(5,10) do + + local vec = normal * math.random( 150, 200 ) + VectorRand() * 50 + local normalized = vec:GetNormal():Angle() + + local particle = emitter:Add( "effects/yellowflare", pos ) + particle:SetVelocity( normal * math.random(150,200) + VectorRand() * 50 ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( math.Rand( 1.5, 3.5 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 4, 8 ) ) + particle:SetEndSize( 0 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 200, 100, 50 ) + + particle:SetGravity( Vector( 0, 0, -500 ) ) + particle:SetCollide( true ) + particle:SetBounce( math.Rand( 0, 0.2 ) ) + + end + + emitter:Finish() + + local dlight = DynamicLight( self:EntIndex() ) + + if dlight then + + dlight.Pos = pos + dlight.r = 255 + dlight.g = 150 + dlight.b = 50 + dlight.Brightness = 3 + dlight.Decay = 512 + dlight.size = 256 * math.Rand( 0.5, 1.0 ) + dlight.DieTime = CurTime() + 5 + + end + +end + +function EFFECT:Think( ) + + return self.DieTime > CurTime() + +end + +function EFFECT:Render() + +end diff --git a/entities/effects/fire_tracer/init.lua b/entities/effects/fire_tracer/init.lua new file mode 100644 index 0000000..3f8842b --- /dev/null +++ b/entities/effects/fire_tracer/init.lua @@ -0,0 +1,87 @@ + +EFFECT.Mat = Material( "trails/plasma" ) +EFFECT.Sprite = Material( "effects/yellowflare" ) + +function EFFECT:Init( data ) + + self.Position = data:GetStart() + self.WeaponEnt = data:GetEntity() + self.Attachment = data:GetAttachment() + + self.StartPos = self:GetTracerShootPos( self.Position, self.WeaponEnt, self.Attachment ) + self.EndPos = data:GetOrigin() + + local dir = self.StartPos - self.EndPos + dir:Normalize() + + self.Dir = dir + + self.Entity:SetRenderBoundsWS( self.StartPos, self.EndPos ) + + self.Alpha = 100 + self.Color = Color( 250, 150, 50, self.Alpha ) + + local dlight = DynamicLight( self:EntIndex() ) + + if dlight then + + dlight.Pos = self.StartPos + dlight.r = 255 + dlight.g = 150 + dlight.b = 50 + dlight.Brightness = 3 + dlight.Decay = 256 + dlight.size = 256 * math.Rand( 0.5, 1.0 ) + dlight.DieTime = CurTime() + 5 + + end + +end + +function EFFECT:Think( ) + + self.Entity:SetRenderBoundsWS( self.StartPos, self.EndPos ) + + self.Alpha = self.Alpha - FrameTime() * 200 + self.Color = Color( 250, 150, 50, self.Alpha ) + + return self.Alpha > 0 + +end + +function EFFECT:Render( ) + + if self.Alpha < 1 then return end + + --[[self.Length = ( self.StartPos - self.EndPos ):Length() + + render.SetMaterial( self.Mat ) + render.DrawBeam( self.StartPos, self.EndPos, ( 100 / self.Alpha ) * 0.5 + 0.5, 0, 0, self.Color )]] + + if ( self.Alpha < 1 ) then return end + + self.Length = (self.StartPos - self.EndPos):Length() + + local texcoord = CurTime() * -0.2 + + for i = 1, 10 do + + render.SetMaterial( self.Mat ) + + texcoord = texcoord + i * 0.05 * texcoord + + render.DrawBeam( self.StartPos, + self.EndPos, + i * self.Alpha * 0.03, + texcoord, + texcoord + (self.Length / (128 + self.Alpha)), + self.Color ) + + render.SetMaterial( self.Sprite ) + + render.DrawSprite( self.StartPos + self.Dir * i, i * 5, i * 5, Color( self.Color.r, self.Color.g, self.Color.b, self.Alpha ) ) + render.DrawSprite( self.EndPos, i * 5, i * 5, Color( self.Color.r, self.Color.g, self.Color.b, self.Alpha ) ) + + end + +end diff --git a/entities/effects/gore_explosion/init.lua b/entities/effects/gore_explosion/init.lua new file mode 100644 index 0000000..e4406a1 --- /dev/null +++ b/entities/effects/gore_explosion/init.lua @@ -0,0 +1,129 @@ + + +function EFFECT:Init( data ) + + self.DieTime = CurTime() + 1.5 + + local pos = data:GetOrigin() + Vector(0,0,50) + local emitter = ParticleEmitter( pos ) + + local particle = emitter:Add( "effects/blood_core", pos ) + particle:SetDieTime( math.Rand( 0.5, 1.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 10 ) + particle:SetEndSize( math.random( 150, 200 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + + local particle = emitter:Add( "effects/blood_core", pos ) + particle:SetDieTime( math.Rand( 6.0, 8.0 ) ) + particle:SetStartAlpha( 50 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 100, 250 ) ) + particle:SetEndSize( 200 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + particle:SetGravity( Vector( 0, 0, -5 ) ) + + for i=1, math.random(4,8) do + + local particle = emitter:Add( "effects/blood", pos ) + particle:SetVelocity( VectorRand() * 100 + Vector(0,math.random(-25,25),50) ) + particle:SetDieTime( 1.0 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 20, 40 ) ) + particle:SetEndSize( math.random( 50, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + for i=1, 12 do + + local vec = VectorRand() + vec.z = math.Rand( -0.2, 1.0 ) + + local particle = emitter:Add( "nuke/gore" .. math.random(1,2), pos ) + particle:SetVelocity( vec * 250 + Vector(0,0,50) ) + particle:SetDieTime( math.Rand( 0.8, 1.0 ) ) + particle:SetStartAlpha( 200 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 10, 20 ) ) + particle:SetEndSize( math.random( 50, 100 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + for i=1, math.random(3,6) do + + local vec = VectorRand() + vec.z = math.Rand( -0.2, 1.0 ) + + local particle = emitter:Add( "nuke/gore" .. math.random(1,2), pos + Vector(0,0,math.random(-10,10)) ) + particle:SetVelocity( vec * 300 ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( math.Rand( 2.0, 4.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 255 ) + particle:SetStartSize( math.random( 8, 12 ) ) + particle:SetEndSize( 1 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 40, 0, 0 ) + + particle:SetGravity( Vector( 0, 0, -500 ) ) + particle:SetCollide( true ) + particle:SetBounce( 0.5 ) + + particle:SetCollideCallback( function( part, pos, normal ) + + util.Decal( "Blood", pos + normal, pos - normal ) + + end ) + + end + + emitter:Finish() + + for i=1, 15 do + + local ed = EffectData() + ed:SetOrigin( pos + Vector(0,0,math.random(0,30)) ) + + if i < 5 then + ed:SetScale( 1 ) + else + ed:SetScale( 2 ) + end + + util.Effect( "player_gib", ed, true, true ) + + end + + if LocalPlayer():GetPos():Distance( pos ) <= 300 then + + local frac = 1 - ( LocalPlayer():GetPos():Distance( pos ) / 300 ) + + for i=1, math.Round( frac * 12 ) do + + AddStain() + + end + + end + +end + +function EFFECT:Think( ) + + return self.DieTime > CurTime() + +end + +function EFFECT:Render() + +end diff --git a/entities/effects/head_gib/init.lua b/entities/effects/head_gib/init.lua new file mode 100644 index 0000000..8a36dd9 --- /dev/null +++ b/entities/effects/head_gib/init.lua @@ -0,0 +1,91 @@ + + +function EFFECT:Init( data ) + + local pos = data:GetOrigin() + local emitter = ParticleEmitter( pos ) + + local particle = emitter:Add( "effects/blood_core", pos ) + particle:SetDieTime( 0.5 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 5, 10 ) ) + particle:SetEndSize( math.random( 50, 100 ) ) + particle:SetRoll( math.random( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + + local particle = emitter:Add( "effects/blood_core", pos ) + particle:SetDieTime( math.Rand( 5.0, 7.0 ) ) + particle:SetStartAlpha( 50 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 40, 80 ) ) + particle:SetEndSize( 200 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + particle:SetGravity( Vector( 0, 0, -5 ) ) + + for i=1, math.random(5,10) do + + local particle = emitter:Add( "effects/blood", pos ) + particle:SetVelocity( VectorRand() * 100 + Vector(0,math.random(-25,25),50) ) + particle:SetDieTime( 1.0 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 2, 4 ) ) + particle:SetEndSize( math.random( 10, 20 ) ) + particle:SetRoll( math.random( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + for i=1, 6 do + + local particle = emitter:Add( "nuke/gore" .. math.random(1,2), pos ) + particle:SetVelocity( VectorRand() * 100 + Vector(0,0,75) ) + particle:SetDieTime( 0.5 ) + particle:SetStartAlpha( 200 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 5, 10 ) ) + particle:SetEndSize( math.random( 30, 60 ) ) + particle:SetRoll( math.random( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + emitter:Finish() + + for i=1, 3 do + + local ed = EffectData() + ed:SetOrigin( pos ) + ed:SetScale( 1 ) + util.Effect( "player_gib", ed, true, true ) + + end + + if LocalPlayer():GetPos():Distance( pos ) <= 100 then + + local frac = 1 - ( LocalPlayer():GetPos():Distance( pos ) / 100 ) + + for i=1, math.Round( frac * 6 ) do + + AddStain() + + end + + end + +end + +function EFFECT:Think( ) + + return false + +end + +function EFFECT:Render() + +end + diff --git a/entities/effects/headshot/init.lua b/entities/effects/headshot/init.lua new file mode 100644 index 0000000..7aadb41 --- /dev/null +++ b/entities/effects/headshot/init.lua @@ -0,0 +1,66 @@ + + +function EFFECT:Init( data ) + + local pos = data:GetOrigin() + local emitter = ParticleEmitter( pos ) + + local particle = emitter:Add( "effects/blood_core", pos ) + particle:SetDieTime( 0.3 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 5, 10 ) ) + particle:SetEndSize( math.random( 50, 100 ) ) + particle:SetRoll( math.random( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + + local particle = emitter:Add( "particles/smokey", pos ) + particle:SetDieTime( math.Rand( 10, 20 ) ) + particle:SetStartAlpha( math.random( 20, 40 ) ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 20, 40 ) ) + particle:SetEndSize( 10 ) + particle:SetRoll( math.random( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + + for i=1, math.random(2,4) do + + local particle = emitter:Add( "effects/blood", pos ) + particle:SetVelocity( VectorRand() * 100 + Vector(0,math.random(-25,25),50) ) + particle:SetDieTime( 1.0 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 2, 4 ) ) + particle:SetEndSize( math.random( 10, 20 ) ) + particle:SetRoll( math.random( -360, 360 ) ) + particle:SetColor( 50, 0, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + emitter:Finish() + + if LocalPlayer():GetPos():Distance( pos ) <= 100 then + + local frac = 1 - ( LocalPlayer():GetPos():Distance( pos ) / 100 ) + + for i=1, math.Round( frac * 3 ) do + + AddStain() + + end + + end + +end + +function EFFECT:Think( ) + + return false + +end + +function EFFECT:Render() + +end + diff --git a/entities/effects/immolate/init.lua b/entities/effects/immolate/init.lua new file mode 100644 index 0000000..e6a7cc1 --- /dev/null +++ b/entities/effects/immolate/init.lua @@ -0,0 +1,88 @@ + +function EFFECT:Init( data ) + + self.DieTime = CurTime() + 5 + self.SmokeTime = 0 + self.Ent = data:GetEntity() + + if not IsValid( self.Ent ) then self.DieTime = 0 return end + + self.Emitter = ParticleEmitter( self.Ent:GetPos() ) + + if LocalPlayer() != self.Ent then return end + + LocalPlayer():EmitSound( "ambient/fire/ignite.wav", 100, 80 ) + +end + +function EFFECT:Think() + + if IsValid( self.Ent ) then + + if self.Ent:IsPlayer() and ( !self.Ent:Alive() or self.Ent == LocalPlayer() ) then + + self.DieTime = 0 + + end + + end + + if self.DieTime < CurTime() or not IsValid( self.Ent ) then + + if self.Emitter then + + self.Emitter:Finish() + + end + + return false + + end + + local pos + + for i=1, 3 do + + pos = self.Ent:GetPos() + Vector(0,0,math.random(1,50)) + Vector(math.random(-10,10),math.random(-10,10),0) + + local particle = self.Emitter:Add( "effects/muzzleflash" .. math.random(1,4), pos ) + particle:SetVelocity( Vector(0,0,80) ) + particle:SetDieTime( math.Rand( 0.2, 0.4 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random(5,15) ) + particle:SetEndSize( 0 ) + particle:SetRoll( math.random(-180,180) ) + particle:SetColor( 255, 200, 200 ) + particle:SetGravity( Vector( 0, 0, 500 ) ) + + end + + if self.SmokeTime < CurTime() then + + self.SmokeTime = CurTime() + 0.02 + + local particle = self.Emitter:Add( "particles/smokey", pos ) + particle:SetVelocity( Vector(0,0,30) ) + particle:SetDieTime( math.Rand( 1.0, 2.5 ) ) + particle:SetStartAlpha( 50 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 5, 10 ) ) + particle:SetEndSize( math.random( 25, 50 ) ) + particle:SetRoll( 0 ) + particle:SetColor( 50, 50, 50 ) + particle:SetGravity( Vector( 0, 0, 30 ) ) + + end + + return true + +end + +function EFFECT:Render() + +end + + + + diff --git a/entities/effects/player_gib/init.lua b/entities/effects/player_gib/init.lua new file mode 100644 index 0000000..2afcae0 --- /dev/null +++ b/entities/effects/player_gib/init.lua @@ -0,0 +1,58 @@ + +function EFFECT:Init( data ) + + local scale = data:GetScale() + + if scale < 2 then + self.Entity:SetModel( table.Random( GAMEMODE.SmallGibs ) ) + else + self.Entity:SetModel( table.Random( GAMEMODE.BigGibs ) ) + end + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMaterial( "models/flesh" ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_DEBRIS ) + self.Entity:SetCollisionBounds( Vector( -128 -128, -128 ), Vector( 128, 128, 128 ) ) + self.Entity:SetAngles( Angle( math.Rand(0,360), math.Rand(0,360), math.Rand(0,360) ) ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + local vec = VectorRand() + vec.z = math.Clamp( vec.z, -0.4, 0.8 ) + + phys:Wake() + phys:SetMass( 100 ) + phys:AddAngleVelocity( VectorRand() * 500 ) + phys:SetMaterial( "gmod_silent" ) + + if scale < 2 then + + phys:SetVelocity( vec * math.Rand( 100, 200 ) ) + + else + + phys:SetVelocity( vec * math.Rand( 300, 600 ) ) + + end + + end + + self.LifeTime = CurTime() + 15 + +end + +function EFFECT:Think( ) + + return self.LifeTime > CurTime() + +end + +function EFFECT:Render() + + self.Entity:DrawModel() + +end + diff --git a/entities/effects/puke_explosion/init.lua b/entities/effects/puke_explosion/init.lua new file mode 100644 index 0000000..9a13226 --- /dev/null +++ b/entities/effects/puke_explosion/init.lua @@ -0,0 +1,119 @@ + +EFFECT.Color = Color(100,50,0) + +function EFFECT:Init( data ) + + self.DieTime = CurTime() + 1.5 + self.SoundTime = 0 + + local pos = data:GetOrigin() + Vector(0,0,50) + local emitter = ParticleEmitter( pos ) + + self.Pos = pos + + local particle = emitter:Add( "effects/blood_core", pos ) + particle:SetDieTime( math.Rand( 0.5, 1.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 10 ) + particle:SetEndSize( math.random( 100, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( self.Color.r, self.Color.g, 0 ) + + for i=1, math.random(4,8) do + + local particle = emitter:Add( "effects/blood", pos ) + particle:SetVelocity( VectorRand() * 100 + Vector(0,math.random(-25,25),50) ) + particle:SetDieTime( 1.0 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 20, 40 ) ) + particle:SetEndSize( math.random( 50, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( self.Color.r, self.Color.g, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + for i=1, 10 do + + local vec = VectorRand() + vec.z = math.Rand( -0.2, 1.0 ) + + local particle = emitter:Add( "nuke/gore" .. math.random(1,2), pos ) + particle:SetVelocity( vec * 300 ) + particle:SetDieTime( math.Rand( 0.8, 1.0 ) ) + particle:SetStartAlpha( 200 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 10, 20 ) ) + particle:SetEndSize( math.random( 100, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( self.Color.r, self.Color.g + math.random(0,20), 0 ) + particle:SetGravity( Vector( 0, 0, -400 ) ) + + end + + for i=1, math.random(3,6) do + + local vec = VectorRand() + vec.z = math.Rand( -0.2, 1.0 ) + + local particle = emitter:Add( "nuke/gore" .. math.random( 1, 2 ), pos + Vector( 0, 0, math.random( -10, 10 ) ) ) + particle:SetVelocity( vec * 300 ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( math.Rand( 2.0, 4.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 255 ) + particle:SetStartSize( math.random( 8, 12 ) ) + particle:SetEndSize( 1 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( self.Color.r, self.Color.g, 0 ) + + particle:SetGravity( Vector( 0, 0, -500 ) ) + particle:SetCollide( true ) + particle:SetBounce( 0.5 ) + + particle:SetCollideCallback( function( part, pos, normal ) + + util.Decal( "yellowblood", pos + normal, pos - normal ) + + end ) + + end + + emitter:Finish() + + for i=1, 10 do + + local ed = EffectData() + ed:SetOrigin( pos + Vector( 0, 0, math.random( 0, 30 ) ) ) + + if i < 5 then + ed:SetScale( 1 ) + else + ed:SetScale( 2 ) + end + + util.Effect( "player_gib", ed, true, true ) + + end + +end + +function EFFECT:Think() + + if self.SoundTime < CurTime() then + + sound.Play( table.Random( GAMEMODE.GoreSplat ), self.Pos, 100, math.random(90,110) ) + + self.SoundTime = CurTime() + 0.5 + + end + + return self.DieTime > CurTime() + +end + +function EFFECT:Render() + +end diff --git a/entities/effects/puke_spray/init.lua b/entities/effects/puke_spray/init.lua new file mode 100644 index 0000000..b2d73ac --- /dev/null +++ b/entities/effects/puke_spray/init.lua @@ -0,0 +1,119 @@ + +EFFECT.Color = Color(100,50,0) + +function EFFECT:Init( data ) + + self.DieTime = CurTime() + 1.5 + self.SoundTime = 0 + + local pos = data:GetOrigin() + Vector(0,0,50) + local emitter = ParticleEmitter( pos ) + + self.Pos = pos + + local particle = emitter:Add( "effects/blood_core", pos ) + particle:SetDieTime( math.Rand( 0.5, 1.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 10 ) + particle:SetEndSize( math.random( 100, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( self.Color.r, self.Color.g, 0 ) + + for i=1, math.random(4,8) do + + local particle = emitter:Add( "effects/blood", pos ) + particle:SetVelocity( VectorRand() * 100 + Vector(0,math.random(-25,25),50) ) + particle:SetDieTime( 1.0 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 20, 40 ) ) + particle:SetEndSize( math.random( 50, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( self.Color.r, self.Color.g, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + for i=1, 10 do + + local vec = VectorRand() + vec.z = math.Rand( -0.2, 1.0 ) + + local particle = emitter:Add( "nuke/gore" .. math.random(1,2), pos ) + particle:SetVelocity( vec * 200 ) + particle:SetDieTime( math.Rand( 0.8, 1.0 ) ) + particle:SetStartAlpha( 200 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 10, 20 ) ) + particle:SetEndSize( math.random( 100, 150 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( self.Color.r, self.Color.g + math.random(0,20), 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + for i=1, math.random(3,6) do + + local vec = VectorRand() + vec.z = math.Rand( -0.2, 1.0 ) + + local particle = emitter:Add( "nuke/gore" .. math.random(1,2), pos + Vector(0,0,math.random(-10,10)) ) + particle:SetVelocity( vec * 300 ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( math.Rand( 2.0, 4.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 255 ) + particle:SetStartSize( math.random( 8, 12 ) ) + particle:SetEndSize( 1 ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( self.Color.r, self.Color.g, 0 ) + + particle:SetGravity( Vector( 0, 0, -500 ) ) + particle:SetCollide( true ) + particle:SetBounce( 0.5 ) + + particle:SetCollideCallback( function( part, pos, normal ) + + util.Decal( "yellowblood", pos + normal, pos - normal ) + + end ) + + end + + emitter:Finish() + + for i=1, 5 do + + local ed = EffectData() + ed:SetOrigin( pos + Vector(0,0,math.random(0,30)) ) + + if i < 3 then + ed:SetScale( 1 ) + else + ed:SetScale( 2 ) + end + + util.Effect( "player_gib", ed, true, true ) + + end + +end + +function EFFECT:Think( ) + + if self.SoundTime < CurTime() then + + sound.Play( table.Random( GAMEMODE.GoreSplat ), self.Pos, 100, math.random(90,110) ) + + self.SoundTime = CurTime() + 0.5 + + end + + return self.DieTime > CurTime() + +end + +function EFFECT:Render() + +end diff --git a/entities/effects/rad_explosion/init.lua b/entities/effects/rad_explosion/init.lua new file mode 100644 index 0000000..e888a2e --- /dev/null +++ b/entities/effects/rad_explosion/init.lua @@ -0,0 +1,55 @@ + +function EFFECT:Init( data ) + + local pos = data:GetOrigin() + Vector(0,0,40) + local emitter = ParticleEmitter( pos ) + + for i=1, math.random(4,8) do + + local particle = emitter:Add( "effects/blood", pos ) + particle:SetVelocity( VectorRand() * 100 + Vector(0,math.random(-25,25),50) ) + particle:SetDieTime( 1.0 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 5, 10 ) ) + particle:SetEndSize( math.random( 20, 40 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetColor( 100, 200, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + end + + for i=1, 20 do + + local vec = VectorRand() + vec.z = math.Rand( -0.2, 1.0 ) + + local particle = emitter:Add( "effects/yellowflare", pos ) + particle:SetVelocity( vec * 300 ) + particle:SetDieTime( math.Rand( 2.5, 3.5 ) ) + particle:SetStartAlpha( 200 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 2, 4 ) ) + particle:SetEndSize( 0 ) + particle:SetRoll( math.random( -360, 360 ) ) + particle:SetColor( 100, 200, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) ) + + particle:SetCollide( true ) + particle:SetBounce( math.Rand( 0.1, 0.5 ) ) + + end + + emitter:Finish() + +end + +function EFFECT:Think( ) + + return false + +end + +function EFFECT:Render() + +end diff --git a/entities/effects/radiation/init.lua b/entities/effects/radiation/init.lua new file mode 100644 index 0000000..e9021c9 --- /dev/null +++ b/entities/effects/radiation/init.lua @@ -0,0 +1,70 @@ + +function EFFECT:Init( data ) + + self.DieTime = CurTime() + 5 + self.PartTime = 0 + self.Ent = data:GetEntity() + + if not IsValid( self.Ent ) then self.DieTime = 0 return end + + self.Emitter = ParticleEmitter( self.Ent:GetPos() ) + +end + +function EFFECT:Think() + + if IsValid( self.Ent ) then + + if self.Ent:IsPlayer() and ( !self.Ent:Alive() or self.Ent == LocalPlayer() ) then + + self.DieTime = 0 + + end + + end + + if self.DieTime < CurTime() or not IsValid( self.Ent ) then + + if self.Emitter then + + self.Emitter:Finish() + + end + + return false + + end + + if self.PartTime < CurTime() then + + self.PartTime = CurTime() + math.Rand( 0.2, 0.4 ) + + local pos = self.Ent:GetPos() + Vector(0,0,math.random(1,40)) + Vector(math.random(-10,10),math.random(-10,10),0) + + local particle = self.Emitter:Add( "effects/yellowflare", pos ) + particle:SetVelocity( VectorRand() * 5 ) + particle:SetDieTime( math.Rand( 2.0, 4.0 ) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 1, 3 ) ) + particle:SetEndSize( 0 ) + particle:SetRoll( math.random( -180, 180 ) ) + particle:SetColor( 100, 200, 0 ) + particle:SetGravity( Vector( 0, 0, -500 ) ) + + particle:SetCollide( true ) + particle:SetBounce( math.Rand( 0, 0.2 ) ) + + end + + return true + +end + +function EFFECT:Render() + +end + + + + diff --git a/entities/effects/smoke_crater/init.lua b/entities/effects/smoke_crater/init.lua new file mode 100644 index 0000000..68c713b --- /dev/null +++ b/entities/effects/smoke_crater/init.lua @@ -0,0 +1,52 @@ + + +function EFFECT:Init( data ) + + self.Pos = data:GetOrigin() + self.Magnitude = data:GetMagnitude() or 1 + + self.Emitter = ParticleEmitter( self.Pos ) + self.DieTime = CurTime() + 15 + self.Interval = 0 + +end + + +function EFFECT:Think( ) + + if self.Interval < CurTime() then + + self.Interval = CurTime() + 0.2 + + local particle = self.Emitter:Add( "particles/smokey", self.Pos + VectorRand() * 10 ) + + particle:SetVelocity( Vector( math.Rand(-3,3), math.Rand(-3,3), math.Rand(20,40) ) + WindVector ) + particle:SetDieTime( math.Rand( 10, 15 ) + self.Magnitude ) + particle:SetStartAlpha( math.random( 25, 50 ) ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.Rand( 5, 25 ) * self.Magnitude ) + particle:SetEndSize( math.Rand( 50, 200 ) * self.Magnitude ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetRollDelta( math.Rand( -0.1, 0.1 ) ) + + local rand = math.random(10,50) + particle:SetColor( rand, rand, rand ) + + end + + if self.DieTime > CurTime() then + + return true + + else + + self.Emitter:Finish() + return false + + end + +end + +function EFFECT:Render() + +end diff --git a/entities/entities/info_evac/init.lua b/entities/entities/info_evac/init.lua new file mode 100644 index 0000000..40e6489 --- /dev/null +++ b/entities/entities/info_evac/init.lua @@ -0,0 +1,12 @@ + + +ENT.Type = "point" +ENT.Base = "base_point" + +function ENT:Initialize() + +end + +function ENT:KeyValue( key, value ) + +end diff --git a/entities/entities/info_lootspawn/init.lua b/entities/entities/info_lootspawn/init.lua new file mode 100644 index 0000000..957aeb9 --- /dev/null +++ b/entities/entities/info_lootspawn/init.lua @@ -0,0 +1,12 @@ + + +ENT.Type = "anim" +ENT.Base = "base_point" + +function ENT:Initialize() + +end + +function ENT:KeyValue( key, value ) + +end diff --git a/entities/entities/info_npcspawn/init.lua b/entities/entities/info_npcspawn/init.lua new file mode 100644 index 0000000..c7e915b --- /dev/null +++ b/entities/entities/info_npcspawn/init.lua @@ -0,0 +1,18 @@ + + +ENT.Type = "anim" +ENT.Base = "base_point" + +function ENT:Initialize() + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_NONE ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:DrawShadow( false ) + +end + +function ENT:KeyValue( key, value ) + +end diff --git a/entities/entities/info_player_army/init.lua b/entities/entities/info_player_army/init.lua new file mode 100644 index 0000000..40e6489 --- /dev/null +++ b/entities/entities/info_player_army/init.lua @@ -0,0 +1,12 @@ + + +ENT.Type = "point" +ENT.Base = "base_point" + +function ENT:Initialize() + +end + +function ENT:KeyValue( key, value ) + +end diff --git a/entities/entities/info_player_zombie/init.lua b/entities/entities/info_player_zombie/init.lua new file mode 100644 index 0000000..40e6489 --- /dev/null +++ b/entities/entities/info_player_zombie/init.lua @@ -0,0 +1,12 @@ + + +ENT.Type = "point" +ENT.Base = "base_point" + +function ENT:Initialize() + +end + +function ENT:KeyValue( key, value ) + +end diff --git a/entities/entities/info_trader/init.lua b/entities/entities/info_trader/init.lua new file mode 100644 index 0000000..7f4d109 --- /dev/null +++ b/entities/entities/info_trader/init.lua @@ -0,0 +1,115 @@ +ENT.Type = "point" +ENT.Base = "base_point" + +ENT.BuybackScale = 1.0 + +function ENT:Initialize() + + self.Items = {} + + self.Entity:GenerateInventory() + +end + +function ENT:GenerateInventory() + + for k,v in pairs( item.GetByType( ITEM_SUPPLY ) ) do + + self.Entity:AddItem( v.ID ) + + end + + for k,v in pairs( item.GetByType( ITEM_BUYABLE ) ) do + + self.Entity:AddItem( v.ID ) + + end + + for k,v in pairs( item.GetByType( ITEM_MISC ) ) do + + self.Entity:AddItem( v.ID ) + + end + + for k,v in pairs( item.GetByType( ITEM_AMMO ) ) do + + self.Entity:AddItem( v.ID ) + + end + + if self.Special then + + for k,v in pairs( item.GetByType( ITEM_SPECIAL ) ) do + + self.Entity:AddItem( v.ID ) + + end + + end + + for k,v in pairs( item.GetByType( ITEM_WPN_COMMON ) ) do + + self.Entity:AddItem( v.ID ) + + end + + if self.Special then + + for k,v in pairs( item.GetByType( ITEM_WPN_SPECIAL ) ) do + + self.Entity:AddItem( v.ID ) + + end + + end + +end + +function ENT:SetSpecial( bool ) + + self.Special = bool + +end + +function ENT:GetBuybackScale() + + return self.BuybackScale + +end + +function ENT:GetItems() + + return self.Items + +end + +function ENT:AddItem( id ) + + local tbl = item.GetByID( id ) + + if tbl.SaleOverride then return end + + self.Items = self.Items or {} + + table.insert( self.Items, id ) + +end + +function ENT:Think() + +end + +function ENT:OnUsed( ply ) + + ply.Stash = self.Entity + ply:ToggleStashMenu( self.Entity, true, "StoreMenu", self.Entity:GetBuybackScale() ) + +end + +function ENT:OnExit( ply ) + + ply:ToggleStashMenu( self.Entity, false, "StoreMenu", self.Entity:GetBuybackScale() ) + ply.Stash = nil + +end + diff --git a/entities/entities/npc_nb_base/shared.lua b/entities/entities/npc_nb_base/shared.lua new file mode 100644 index 0000000..c2557bb --- /dev/null +++ b/entities/entities/npc_nb_base/shared.lua @@ -0,0 +1,959 @@ + +AddCSLuaFile() + +ENT.Base = "base_nextbot" + +// Moddable + +ENT.Skins = 0 +ENT.AttackAnims = nil +ENT.AnimSpeed = 0.8 +ENT.AttackTime = 0.5 +ENT.MeleeDistance = 64 +ENT.BreakableDistance = 96 +ENT.Damage = 35 +ENT.BaseHealth = 100 +ENT.MoveSpeed = 225 +ENT.JumpHeight = 80 +ENT.BumpSpeed = 500 +ENT.MoveAnim = ACT_RUN + +ENT.Models = nil +ENT.Legs = Model( "models/zombie/classic_legs.mdl" ) +ENT.Model = Model( "models/zombie/classic.mdl" ) + +ENT.WoodHit = Sound( "Wood_Plank.Break" ) +ENT.WoodBust = Sound( "Wood_Crate.Break" ) + +ENT.ClawHit = { Sound( "npc/zombie/claw_strike1.wav" ), +Sound( "npc/zombie/claw_strike2.wav" ), +Sound( "npc/zombie/claw_strike3.wav" ) } + +ENT.ClawMiss = { Sound( "npc/zombie/claw_miss1.wav" ), +Sound( "npc/zombie/claw_miss2.wav" ) } + +ENT.VoiceSounds = {} + +ENT.NextBot = true +ENT.ShouldDrawPath = false +ENT.Obstructed = false +ENT.FireDamageTime = 0 +ENT.FireTime = 0 + +ENT.DoorHit = Sound( "npc/zombie/zombie_hit.wav" ) + +function ENT:Initialize() + + if self.Models then + + local model = table.Random( self.Models ) + self.Entity:SetModel( model ) + + else + + self.Entity:SetModel( self.Model ) + + end + + self.Entity:SetHealth( self.BaseHealth ) + self.Entity:SetCollisionGroup( COLLISION_GROUP_NPC ) + self.Entity:SetCollisionBounds( Vector(-4,-4,0), Vector(4,4,64) ) // nice fat shaming + self.Entity:SetSkin( math.random( 0, self.Skins ) ) + + if(self.loco != nil) then + self.loco:SetDeathDropHeight( 1000 ) + self.loco:SetAcceleration( 500 ) + self.loco:SetJumpHeight( self.JumpHeight ) + end + + self.DmgTable = {} + self.LastPos = self.Entity:GetPos() + self.Stuck = CurTime() + 10 + +end + +function ENT:Think() + + self.Entity:OnThink() + + if ( self.IdleTalk or 0 ) < CurTime() then + + self.Entity:VoiceSound( self.VoiceSounds.Taunt ) + self.IdleTalk = CurTime() + math.Rand(10,20) + + end + + if ( self.Stuck or 0 ) < CurTime() then + + self.Entity:StuckThink() + + self.Stuck = CurTime() + 10 + self.LastPos = self.Entity:GetPos() + + end + + if self.Entity:OnFire() and self.FireDamageTime < CurTime() then + + self.FireDamageTime = CurTime() + 0.25 + + self.Entity:TakeDamage( 10, self.FireAttacker ) + + elseif self.FireSound and not self.Entity:OnFire() then + + self.Entity:StopFireSounds() + + end + + if self.CurAttack and self.CurAttack < CurTime() then + + self.CurAttack = nil + + if IsValid( self.CurEnemy ) then + + if self.CurEnemy:IsPlayer() then + + local enemy = self.Entity:CanAttackEnemy( self.CurEnemy ) + + if IsValid( enemy ) then + + local snd = table.Random( self.ClawHit ) + self.Entity:EmitSound( snd, 100, math.random(90,110) ) + self.Entity:OnHitEnemy( enemy ) + + else + + local snd = table.Random( self.ClawMiss ) + self.Entity:EmitSound( snd, 100, math.random(90,110) ) + + end + + elseif self.CurEnemy.NextBot then + + local enemy = self.Entity:CanAttackEnemy( self.CurEnemy ) + + if IsValid( enemy ) then + + local snd = table.Random( self.ClawHit ) + self.Entity:EmitSound( snd, 100, math.random(90,110) ) + self.Entity:OnHitBot( enemy ) + + else + + local snd = table.Random( self.ClawMiss ) + self.Entity:EmitSound( snd, 100, math.random(90,110) ) + + end + + elseif ( self.CurEnemy:GetPos():Distance( self.Entity:GetPos() ) <= self.BreakableDistance ) or self.CurEnemy == self.Entity:GetBreakable() then + + self.Entity:EmitSound( self.DoorHit, 100, math.random(90,110) ) + self.Entity:OnHitBreakable( self.CurEnemy ) + + end + + else + + local snd = table.Random( self.ClawMiss ) + self.Entity:EmitSound( snd, 100, math.random(90,110) ) + + end + + end + +end + +function ENT:OnHitBot( enemy ) + + enemy:TakeDamage( self.Damage, self.Entity ) + +end + +function ENT:OnThink() + +end + +function ENT:StuckThink() + self.LastPos = self.LastPos or Vector(0,0,0) + if self.LastPos:Distance( self.Entity:GetPos() ) < 50 then + + self.Entity:StartRespawn() + + end + +end + +function ENT:StartRespawn() + GAMEMODE.NPCSpawns = GAMEMODE.NPCSpawns or {} + for k,v in pairs( GAMEMODE.NPCSpawns ) do + + if IsValid( v ) then + + local box = ents.FindInBox( v:GetPos() + Vector( -32, -32, 0 ), v:GetPos() + Vector( 32, 32, 64 ) ) + + if table.Count( box ) <= 1 then + + self.Entity:SetPos( v:GetPos() ) + + return + + end + + end + + end + +end + +function ENT:OnLimbHit( hitgroup, dmginfo ) + + if not IsValid( self.Entity ) then return end + + if hitgroup == HITGROUP_HEAD then + + local snd = table.Random( GAMEMODE.HeadShot ) + + self.Entity:EmitSound( snd, 90, math.random( 100, 120 ) ) + self.Entity:SetHeadshotter( dmginfo:GetAttacker(), true ) + + local effectdata = EffectData() + effectdata:SetOrigin( dmginfo:GetDamagePosition() ) + util.Effect( "headshot", effectdata, true, true ) + + dmginfo:ScaleDamage( 2.75 ) + dmginfo:GetAttacker():NoticeOnce( "Headshot combos earn you more " .. GAMEMODE.CurrencyName .. "s", GAMEMODE.Colors.Blue, 5 ) + dmginfo:GetAttacker():AddHeadshot() + + elseif hitgroup == HITGROUP_CHEST then + + dmginfo:ScaleDamage( 1.25 ) + + self.Entity:SetHeadshotter( dmginfo:GetAttacker(), false ) + if SERVER then dmginfo:GetAttacker():ResetHeadshots() end + + elseif hitgroup == HITGROUP_STOMACH then + + dmginfo:ScaleDamage( 0.75 ) + + self.Entity:SetHeadshotter( dmginfo:GetAttacker(), false ) + if SERVER then dmginfo:GetAttacker():ResetHeadshots() end + + else + + dmginfo:ScaleDamage( 0.50 ) + + self.Entity:SetHeadshotter( dmginfo:GetAttacker(), false ) + if SERVER then dmginfo:GetAttacker():ResetHeadshots() end + + end + +end + +function ENT:OnInjured( dmginfo ) + + if IsValid( dmginfo:GetAttacker() ) and dmginfo:GetAttacker():GetClass() == "trigger_hurt" then + + self.Entity:SpawnRagdoll( dmginfo ) + + return + + end + + if dmginfo:IsExplosionDamage() then + + dmginfo:ScaleDamage( 1.75 ) + + elseif not self.Entity:OnFire() then + + local snd = table.Random( GAMEMODE.GoreBullet ) + sound.Play( snd, self.Entity:GetPos() + Vector(0,0,50), 75, math.random( 90, 110 ), 1.0 ) + + end + + //self.Entity:SetHealth( math.Clamp( self.Entity:Health() - dmginfo:GetDamage(), 0, 1000 ) ) + self.Entity:AddDamageTaken( dmginfo:GetAttacker(), dmginfo:GetDamage() ) + + if self.Entity:Health() > 0 and math.random(1,2) == 1 then + + self.Entity:VoiceSound( self.VoiceSounds.Pain ) + + end + +end + +function ENT:SpawnRagdoll( damageinfo, model, pos, override ) + + timer.Simple( 0.2, function() if IsValid( self.Entity ) then self.Entity:Remove() end end ) + + if not model then + + --[[umsg.Start( "Ragdoll" ) + umsg.Vector( self.Entity:GetPos() ) + + if self.Entity:OnFire() then + + umsg.Short(2) + + else + + umsg.Short(1) + + end + + umsg.Short( self.Entity:EntIndex() ) + umsg.End() + + //self:Fire( "BecomeRagdoll", "", 0 ) ]] + + self.Entity:BecomeRagdoll( damageinfo ) + + else + + local ang = self.Entity:GetAngles() + + local shooter = ents.Create( "env_shooter" ) + shooter:SetPos( pos or self.Entity:GetPos() ) + shooter:SetKeyValue( "m_iGibs", "1" ) + shooter:SetKeyValue( "shootsounds", "3" ) + shooter:SetKeyValue( "gibangles", ang.p.." "..ang.y.." "..ang.r ) + shooter:SetKeyValue( "angles", ang.p.." "..ang.y.." "..ang.r ) + shooter:SetKeyValue( "shootmodel", model ) + shooter:SetKeyValue( "simulation", "2" ) + shooter:SetKeyValue( "gibanglevelocity", math.random(-50,50).." "..math.random(-150,150).." "..math.random(-150,150) ) + shooter:SetKeyValue( "m_flVelocity", tostring( math.Rand( -20, 20 ) ) ) + shooter:SetKeyValue( "m_flVariance", tostring( math.Rand( -2, 2 ) ) ) + + shooter:Spawn() + + shooter:Fire( "shoot", 0, 0 ) + shooter:Fire( "kill", 0.1, 0.1 ) + + if not override then + + self.Entity:Remove() + + end + + end + +end + +function ENT:OnKilled( dmginfo ) + + if self.Dying then return end + + self.Dying = true + + self.Entity:OnDeath( dmginfo ) + + if dmginfo then + + local ent1 = self.Entity:GetHighestDamager() + local tbl = self.Entity:GetHighestDamagers() + + if tbl then + + for k,v in pairs( tbl ) do + + if IsValid( v ) and v != ent1 then + + v:AddCash( GAMEMODE.AssistValues[ self.Entity:GetClass() ] ) + v:AddStat( "Assist" ) + + end + + end + + end + + if IsValid( ent1 ) then + + if math.random(1,40) == 1 then + + ent1:RadioSound( VO_TAUNT ) + + end + + ent1:AddCash( GAMEMODE.KillValues[ self.Entity:GetClass() ] ) + ent1:AddFrags( 1 ) + + local dist = math.floor( ent1:GetPos():Distance( self.Entity:GetPos() ) / 8 ) + + if dist > ent1:GetStat( "Longshot" ) then + + ent1:SetStat( "Longshot", dist ) + + end + + if dmginfo:IsExplosionDamage() then + + local snd = table.Random( GAMEMODE.GoreSplash ) + self.Entity:EmitSound( snd, 90, math.random( 60, 80 ) ) + + local effectdata = EffectData() + effectdata:SetOrigin( self.Entity:GetPos() + Vector(0,0,20) ) + util.Effect( "body_gib", effectdata, true, true ) + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "gore_explosion", ed, true, true ) + + ent1:AddStat( "Explode" ) + + local corpse = table.Random( GAMEMODE.Corpses ) + self.Entity:SpawnRagdoll( dmginfo, corpse ) + + elseif ent1:HasShotgun() and ent1:GetPos():Distance( self.Entity:GetPos() ) < 100 then + + local snd = table.Random( GAMEMODE.GoreSplash ) + self.Entity:EmitSound( snd, 90, math.random( 60, 80 ) ) + + local vec = ( self.Entity:GetPos() - ent1:GetPos() ) + vec:Normalize() + + local effectdata = EffectData() + effectdata:SetOrigin( self.Entity:GetPos() + Vector(0,0,20) ) + effectdata:SetNormal( vec ) + util.Effect( "body_gib", effectdata, true, true ) + + ent1:AddStat( "Meat" ) + + self.Entity:SpawnRagdoll( dmginfo, self.Legs ) + + elseif ent1:HasMelee() then + + ent1:AddStat( "Knife" ) + + self.Entity:VoiceSound( self.VoiceSounds.Death ) + self.Entity:SpawnRagdoll( dmginfo ) + + if self.Entity:OnFire() then + + umsg.Start( "Burned" ) + umsg.Vector( self.Entity:GetPos() ) + umsg.End() + + end + + if self.Entity:GetHeadshotter( ent1 ) then + + local snd = table.Random( GAMEMODE.GoreSplash ) + self.Entity:EmitSound( snd, 90, math.random( 90, 110 ) ) + + local effectdata = EffectData() + effectdata:SetOrigin( self.Entity:GetPos() + Vector(0,0,40) ) + util.Effect( "head_gib", effectdata, true, true ) + + umsg.Start( "Headless" ) + umsg.Vector( self.Entity:GetPos() ) + umsg.End() + + end + + elseif self.Entity:GetHeadshotter( ent1 ) then //self.HeadshotEffects + + local snd = table.Random( GAMEMODE.GoreSplash ) + self.Entity:EmitSound( snd, 90, math.random( 90, 110 ) ) + + local effectdata = EffectData() + effectdata:SetOrigin( self.Entity:GetPos() + Vector(0,0,40) ) + util.Effect( "head_gib", effectdata, true, true ) + + umsg.Start( "Headless" ) + umsg.Vector( self.Entity:GetPos() ) + umsg.End() + + if self.Entity:OnFire() then + + umsg.Start( "Burned" ) + umsg.Vector( self.Entity:GetPos() ) + umsg.End() + + end + + self.Entity:SpawnRagdoll( dmginfo ) + + else + + self.Entity:VoiceSound( self.VoiceSounds.Death ) + self.Entity:SpawnRagdoll( dmginfo ) + + if self.Entity:OnFire() then + + umsg.Start( "Burned" ) + umsg.Vector( self.Entity:GetPos() ) + umsg.End() + + end + + end + + end + + end + +end + +function ENT:OnDeath( dmginfo ) // override this + +end + +function ENT:OnFire() + + return self.FireTime > CurTime() + +end + +function ENT:DoIgnite( att ) + + if self.Entity:OnFire() then return end + + if IsValid( att ) and att:IsPlayer() and att:Team() == TEAM_ARMY then + + att:AddStat( "Igniter" ) + + end + + self.FireTime = CurTime() + 5 + self.FireAttacker = att + self.FireSound = true + + local ed = EffectData() + ed:SetEntity( self.Entity ) + util.Effect( "immolate", ed, true, true ) + + self.Entity:EmitSound( table.Random( GAMEMODE.Burning ), 100, 80 ) + self.Entity:EmitSound( GAMEMODE.BurnFlesh ) + +end + +function ENT:StopFireSounds() + + self.Entity:StopSound( GAMEMODE.BurnFlesh ) + +end + +function ENT:AddDamageTaken( attacker, dmg ) + + if not attacker:IsPlayer() then return end + + if not self.DmgTable[ attacker ] then + + self.DmgTable[ attacker ] = {} + self.DmgTable[ attacker ].Dmg = dmg + + elseif not self.DmgTable[ attacker ].Dmg then + + self.DmgTable[ attacker ].Dmg = dmg + + else + + self.DmgTable[ attacker ].Dmg = self.DmgTable[ attacker ].Dmg + dmg + + end + +end + +function ENT:GetHeadshotter( attacker ) + + if not self.DmgTable[ attacker ] then return false end + + return self.DmgTable[ attacker ].Headshot + +end + +function ENT:SetHeadshotter( attacker, head ) + + if not self.DmgTable[ attacker ] then + + self.DmgTable[ attacker ] = {} + + end + + self.DmgTable[ attacker ].Headshot = head + +end + +function ENT:GetHighestDamager() + + local ent1 = NULL + local high = 0 + + for k,v in pairs( self.DmgTable ) do + + if IsValid( k ) and v.Dmg and v.Dmg > high then + + high = v.Dmg + ent1 = k + + end + + end + + return ent1 + +end + +function ENT:GetHighestDamagers() + + local high = 0 + local tbl = {} + + for k,v in pairs( self.DmgTable ) do + + if IsValid( k ) and k:IsPlayer() then + + table.insert( tbl, k ) + + end + + end + + return tbl + +end + +function ENT:VoiceSound( tbl ) + + if ( self.VoiceTime or 0 ) > CurTime() then return end + + self.VoiceTime = CurTime() + 1.5 + + local snd = table.Random( tbl ) + sound.Play( snd, self.Entity:GetPos() + Vector(0,0,50), 75, ( self.SoundOverride or math.random( 90, 100 ) ), 0.7 ) + +end + +function ENT:StartAttack( enemy ) + + self.Stuck = CurTime() + 10 + self.CurAttack = CurTime() + self.AttackTime + self.CurEnemy = enemy + + self.Entity:VoiceSound( self.VoiceSounds.Attack ) + +end + +function ENT:OnHitEnemy( enemy ) + + enemy:TakeDamage( self.Damage, self.Entity ) + +end + +function ENT:OnHitBreakable( ent ) + + if not IsValid( ent ) then return end + + if string.find( ent:GetClass(), "func_breakable" ) then + + ent:TakeDamage( 25, self.Entity, self.Entity ) + + if ent:GetClass() == "func_breakable_surf" then + + ent:Fire( "shatter", "1 1 1", 0 ) + + end + + elseif string.find( ent:GetClass(), "func_door" ) then + + ent:Remove() + + else + + if not ent.Hits then + + ent.Hits = 1 + ent.MaxHits = math.random(10,20) + + ent:EmitSound( self.WoodHit ) + + else + + ent.Hits = ent.Hits + 1 + + if ent.Hits > ent.MaxHits then + + if ent:GetModel() != "models/props_debris/wood_board04a.mdl" then + + local prop = ents.Create( "prop_physics" ) + prop:SetModel( ent:GetModel() ) + prop:SetPos( ent:GetPos() ) + prop:SetAngles( ent:GetAngles() + Angle( math.random(-10,10), math.random(-5,5), math.random(-5,5) ) ) + prop:SetSkin( ent:GetSkin() ) + prop:SetCollisionGroup( COLLISION_GROUP_DEBRIS ) + prop:Spawn() + + local dir = ( ent:GetPos() - self.Entity:GetPos() ):Normalize() + local phys = prop:GetPhysicsObject() + + if IsValid( phys ) and dir then + + phys:ApplyForceCenter( dir * phys:GetMass() * 800 ) + phys:AddAngleVelocity( VectorRand() * 200 ) + + end + + ent:EmitSound( self.WoodBust ) + ent:Remove() + + else + + ent:Fire( "break", "", 0 ) + + end + + else + + ent:EmitSound( self.WoodHit ) + + end + + end + + end + +end + +function ENT:BehaveAct() // what does this do? + +end + +function ENT:IsZombie() + + return true + +end + +function ENT:CanTarget( v ) + + return ( ( v:IsPlayer() and v:Alive() and v:GetObserverMode() == OBS_MODE_NONE and v:Team() == TEAM_ARMY ) or ( v.NextBot and not v:IsZombie() ) ) + +end + +function ENT:FindEnemy() + + local tbl = team.GetPlayers( TEAM_ARMY ) + tbl = table.Add( tbl, ents.FindByClass( "npc_scientist" ) ) + + self.EnemyTable = tbl + + if #tbl < 1 then + + return NULL + + else + + local enemy = NULL + local dist = 99999 + + for k,v in pairs( tbl ) do + + local compare = v:GetPos():Distance( self.Entity:GetPos() ) + + if compare < dist and self.Entity:CanTarget( v ) then + + enemy = v + dist = compare + + end + + end + + return enemy + + end + +end + +function ENT:CanAttack( ent ) + + return IsValid( ent ) and self.Entity:CanTarget( ent ) and ent:GetPos():Distance( self.Entity:GetPos() ) <= self.MeleeDistance and self.Entity:MeleeTrace( ent ) + +end + +function ENT:MeleeTrace( ent ) + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,40) + trace.endpos = ent:GetPos() + Vector(0,0,40) + trace.filter = { ent, self.Entity } + + local tr = util.TraceLine( trace ) + + if not tr.Hit then + + return true + + end + + if tr.HitWorld or tr.Entity:GetClass() == "prop_door_rotating" or tr.Entity:GetClass() == "func_breakable" or tr.Entity:GetClass() == "func_breakable_surf" then + + return false + + end + + return true + +end + +function ENT:CanAttackEnemy( ent ) + + if self.Entity:CanAttack( ent ) then + + return ent + + end + + if #self.EnemyTable < 1 then return end + + for k,v in pairs( self.EnemyTable ) do + + if self.Entity:CanAttack( v ) then + + return v + + end + + end + +end + +function ENT:GetBreakable() + + local tbl = ents.FindByModel( "models/props_debris/wood_board04a.mdl" ) + tbl = table.Add( tbl, table.Copy( GAMEMODE.Breakables ) ) + + local remove + + for k,v in pairs( tbl ) do + + if IsValid( v ) and v:GetPos() != Vector(0,0,0) and v:GetPos():Distance( self.Entity:GetPos() ) <= self.BreakableDistance then + + return v + + end + + end + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,50) + trace.endpos = trace.start + self.Entity:GetForward() * self.BreakableDistance + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if table.HasValue( GAMEMODE.Breakables, tr.Entity ) then + + return tr.Entity + + end + + return NULL + +end + +function ENT:OnStuck() + + local ent = self.Entity:GetBreakable() + + if IsValid( ent ) then + + self.Obstructed = true + + else + + self.Obstructed = false + + //self.loco:SetDesiredSpeed( self.BumpSpeed ) + //self.loco:Jump() + //self.loco:SetDesiredSpeed( self.BumpSpeed ) + + end + + self.loco:ClearStuck() + +end + +function ENT:OnUnStuck() + + self.Obstructed = false + +end + +function ENT:BreakableRoutine() + + local ent = self.Entity:GetBreakable() + + while IsValid( ent ) do + + local anim = table.Random( self.AttackAnims ) + + self.Entity:StartAttack( ent ) + self.Entity:PlaySequenceAndWait( anim, self.AnimSpeed ) + + ent = self.Entity:GetBreakable() + + end + +end + +function ENT:EnemyRoutine() + + local closest = self.Entity:CanAttackEnemy( enemy ) + + while IsValid( closest ) do + + local anim = table.Random( self.AttackAnims ) + + self.Entity:StartAttack( closest ) + self.Entity:PlaySequenceAndWait( anim, self.AnimSpeed ) + //self.Entity:StartActivity( ACT_MELEE_ATTACK1 ) + + closest = self.Entity:CanAttackEnemy( closest ) + + end + +end + +function ENT:RunBehaviour() + + while true do + + self.Entity:StartActivity( self.MoveAnim ) + self.loco:SetDesiredSpeed( self.MoveSpeed ) + + local enemy = self.Entity:FindEnemy() + + if not IsValid( enemy ) then + + self.Entity:MoveToPos( self.Entity:GetPos() + Vector( math.Rand( -1, 1 ), math.Rand( -1, 1 ), 0 ) * 500 ) + self.Entity:StartActivity( ACT_IDLE ) + + else + + if self.Obstructed then + + self.Entity:BreakableRoutine() + + coroutine.yield() + + end + + local age = math.Clamp( math.min( enemy:GetPos():Distance( self.Entity:GetPos() ), 1000 ) / 1000, 0.2, 1 ) + local opts = { draw = self.ShouldDrawPath, maxage = 3 * age, tolerance = self.MeleeDistance } + + self.Entity:MoveToPos( enemy:GetPos(), opts ) + + self.Entity:StartActivity( ACT_IDLE ) + + self.Entity:BreakableRoutine() + self.Entity:EnemyRoutine() + + self.Entity:StartActivity( ACT_IDLE ) + + end + + coroutine.yield() + + end + +end diff --git a/entities/entities/npc_nb_common/shared.lua b/entities/entities/npc_nb_common/shared.lua new file mode 100644 index 0000000..8890529 --- /dev/null +++ b/entities/entities/npc_nb_common/shared.lua @@ -0,0 +1,83 @@ + +AddCSLuaFile() + +ENT.Base = "npc_nb_base" + +// Moddable + +ENT.Skins = 22 +ENT.AttackAnims = { "attack01", "attack02", "attack03", "attack04" } +ENT.AnimSpeed = 0.8 +ENT.AttackTime = 0.5 +ENT.MeleeDistance = 64 +ENT.BreakableDistance = 96 +ENT.Damage = 30 +ENT.BaseHealth = 90 +ENT.MoveSpeed = 175 +ENT.MoveAnim = ACT_RUN + +ENT.Models = { Model( "models/zed/malezed_04.mdl" ), +Model( "models/zed/malezed_06.mdl" ), +Model( "models/zed/malezed_08.mdl" ) } + +ENT.VoiceSounds = {} + +ENT.VoiceSounds.Death = { Sound( "nuke/redead/death_1.wav" ), +Sound( "nuke/redead/death_2.wav" ), +Sound( "nuke/redead/death_3.wav" ), +Sound( "nuke/redead/death_4.wav" ), +Sound( "nuke/redead/death_5.wav" ), +Sound( "nuke/redead/death_6.wav" ), +Sound( "nuke/redead/death_7.wav" ), +Sound( "nuke/redead/death_8.wav" ), +Sound( "nuke/redead/death_9.wav" ), +Sound( "nuke/redead/death_10.wav" ) } + +ENT.VoiceSounds.Pain = { Sound( "nuke/redead/pain_1.wav" ), +Sound( "nuke/redead/pain_2.wav" ), +Sound( "nuke/redead/pain_3.wav" ), +Sound( "nuke/redead/pain_4.wav" ), +Sound( "nuke/redead/pain_5.wav" ), +Sound( "nuke/redead/pain_6.wav" ), +Sound( "nuke/redead/pain_7.wav" ), +Sound( "nuke/redead/pain_8.wav" ), +Sound( "nuke/redead/pain_9.wav" ), +Sound( "nuke/redead/pain_10.wav" ) } + +ENT.VoiceSounds.Taunt = { Sound( "nuke/redead/idle_1.wav" ), +Sound( "nuke/redead/idle_2.wav" ), +Sound( "nuke/redead/idle_3.wav" ), +Sound( "nuke/redead/idle_4.wav" ), +Sound( "nuke/redead/idle_5.wav" ), +Sound( "nuke/redead/idle_6.wav" ), +Sound( "nuke/redead/idle_7.wav" ), +Sound( "nuke/redead/idle_8.wav" ), +Sound( "nuke/redead/idle_9.wav" ), +Sound( "nuke/redead/idle_10.wav" ) } + +ENT.VoiceSounds.Attack = { Sound( "nuke/redead/attack_1.wav" ), +Sound( "nuke/redead/attack_2.wav" ), +Sound( "nuke/redead/attack_3.wav" ), +Sound( "nuke/redead/attack_4.wav" ), +Sound( "nuke/redead/attack_5.wav" ), +Sound( "nuke/redead/attack_6.wav" ), +Sound( "nuke/redead/attack_7.wav" ), +Sound( "nuke/redead/attack_8.wav" ), +Sound( "nuke/redead/attack_9.wav" ), +Sound( "nuke/redead/attack_10.wav" ) } + +function ENT:OnDeath( dmginfo ) + +end + +function ENT:OnHitEnemy( enemy ) + + enemy:TakeDamage( self.Damage, self.Entity ) + enemy:SetInfected( true ) + enemy:ViewBounce( 10 ) + + umsg.Start( "Drunk", enemy ) + umsg.Short( 1 ) + umsg.End() + +end
\ No newline at end of file diff --git a/entities/entities/npc_nb_contagion/shared.lua b/entities/entities/npc_nb_contagion/shared.lua new file mode 100644 index 0000000..14d1503 --- /dev/null +++ b/entities/entities/npc_nb_contagion/shared.lua @@ -0,0 +1,100 @@ + +AddCSLuaFile() + +ENT.Base = "npc_nb_base" + +// Moddable + +ENT.AttackAnims = { "attackB", "attackD", "attackE", "attackF", "swatleftmid", "swatrightmid" } +ENT.AnimSpeed = 1.2 +ENT.AttackTime = 0.5 +ENT.MeleeDistance = 64 +ENT.BreakableDistance = 96 +ENT.Damage = 60 +ENT.BaseHealth = 200 +ENT.MoveSpeed = 50 +ENT.MoveAnim = ACT_WALK + +ENT.Models = nil +ENT.Model = Model( "models/zombie/classic.mdl" ) + +ENT.VoiceSounds = {} + +ENT.VoiceSounds.Death = { Sound( "npc/zombie/zombie_die1.wav" ), + Sound( "npc/zombie/zombie_die2.wav" ), + Sound( "npc/zombie/zombie_die3.wav" ), + Sound( "npc/zombie/zombie_voice_idle6.wav" ), + Sound( "npc/zombie/zombie_voice_idle11.wav" ) } + +ENT.VoiceSounds.Pain = { Sound( "npc/zombie/zombie_pain1.wav" ), + Sound( "npc/zombie/zombie_pain2.wav" ), + Sound( "npc/zombie/zombie_pain3.wav" ), + Sound( "npc/zombie/zombie_pain4.wav" ), + Sound( "npc/zombie/zombie_pain5.wav" ), + Sound( "npc/zombie/zombie_pain6.wav" ), + Sound( "npc/zombie/zombie_alert1.wav" ), + Sound( "npc/zombie/zombie_alert2.wav" ), + Sound( "npc/zombie/zombie_alert3.wav" ) } + +ENT.VoiceSounds.Taunt = { Sound( "npc/zombie/zombie_voice_idle1.wav" ), + Sound( "npc/zombie/zombie_voice_idle2.wav" ), + Sound( "npc/zombie/zombie_voice_idle3.wav" ), + Sound( "npc/zombie/zombie_voice_idle4.wav" ), + Sound( "npc/zombie/zombie_voice_idle5.wav" ), + Sound( "npc/zombie/zombie_voice_idle7.wav" ), + Sound( "npc/zombie/zombie_voice_idle8.wav" ), + Sound( "npc/zombie/zombie_voice_idle9.wav" ), + Sound( "npc/zombie/zombie_voice_idle10.wav" ), + Sound( "npc/zombie/zombie_voice_idle12.wav" ), + Sound( "npc/zombie/zombie_voice_idle13.wav" ), + Sound( "npc/zombie/zombie_voice_idle14.wav" ) } + +ENT.VoiceSounds.Attack = { Sound( "npc/zombie/zo_attack1.wav" ), +Sound( "npc/zombie/zo_attack2.wav" ) } + +ENT.Torso = Model( "models/zombie/classic_torso.mdl" ) + +function ENT:OnDeath( dmginfo ) + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + if v:GetPos():Distance( self.Entity:GetPos() ) < 150 then + + v:TakeDamage( 40, self.Entity ) + v:SetInfected( true ) + + umsg.Start( "Drunk", v ) + umsg.Short( 2 ) + umsg.End() + + end + + end + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "puke_spray", ed, true, true ) + + if dmginfo:IsExplosionDamage() then + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "gore_explosion", ed, true, true ) + + end + + self.Entity:SpawnRagdoll( dmginfo, self.Torso, self.Entity:GetPos() + Vector(0,0,50), true ) + self.Entity:SetModel( self.Legs ) + +end + +function ENT:OnHitEnemy( enemy ) + + enemy:TakeDamage( self.Damage, self.Entity ) + enemy:ViewBounce( 30 ) + + umsg.Start( "Drunk", enemy ) + umsg.Short( 3 ) + umsg.End() + +end
\ No newline at end of file diff --git a/entities/entities/npc_nb_leaper/shared.lua b/entities/entities/npc_nb_leaper/shared.lua new file mode 100644 index 0000000..174fa0f --- /dev/null +++ b/entities/entities/npc_nb_leaper/shared.lua @@ -0,0 +1,151 @@ + +AddCSLuaFile() + +ENT.Base = "npc_nb_base" + +// Moddable + +ENT.AttackAnims = { "Melee" } +ENT.AnimSpeed = 1.0 +ENT.AttackTime = 0.3 +ENT.MeleeDistance = 64 +ENT.BreakableDistance = 96 +ENT.Damage = 35 +ENT.BaseHealth = 60 +ENT.MoveSpeed = 250 +ENT.JumpHeight = 300 +ENT.MoveAnim = ACT_RUN + +ENT.Models = nil +ENT.Model = Model( "models/zombie/fast.mdl" ) +ENT.Legs = Model( "models/gibs/fast_zombie_legs.mdl" ) + +ENT.VoiceSounds = {} + +ENT.VoiceSounds.Death = { Sound( "npc/fast_zombie/fz_alert_close1.wav" ), +Sound( "npc/fast_zombie/fz_alert_far1.wav" ) } + +ENT.VoiceSounds.Pain = { Sound( "npc/fast_zombie/idle1.wav" ), +Sound( "npc/fast_zombie/idle2.wav" ), +Sound( "npc/fast_zombie/idle3.wav" ), +Sound( "npc/headcrab_poison/ph_hiss1.wav" ), +Sound( "npc/headcrab_poison/ph_idle1.wav" ) } + +ENT.VoiceSounds.Taunt = { Sound( "npc/fast_zombie/fz_frenzy1.wav" ), +Sound( "npc/fast_zombie/fz_scream1.wav" ), +Sound( "npc/barnacle/barnacle_pull1.wav" ), +Sound( "npc/barnacle/barnacle_pull2.wav" ), +Sound( "npc/barnacle/barnacle_pull3.wav" ), +Sound( "npc/barnacle/barnacle_pull4.wav" ) } + +ENT.VoiceSounds.Attack = { Sound( "npc/fast_zombie/wake1.wav" ), +Sound( "npc/fast_zombie/leap1.wav" ) } + +ENT.Leap = Sound( "npc/fast_zombie/fz_scream1.wav" ) + +function ENT:OnDeath( dmginfo ) + +end + +function ENT:OnHitEnemy( enemy ) + + enemy:TakeDamage( self.Damage, self.Entity ) + enemy:SetBleeding( true ) + enemy:ViewBounce( 15 ) + + umsg.Start( "Drunk", enemy ) + umsg.Short( 1 ) + umsg.End() + +end + +function ENT:OnStuck() + + local ent = self.Entity:GetBreakable() + + if IsValid( ent ) then + + self.Obstructed = true + + else + + self.Obstructed = false + self.Entity:DownTrace() + + end + + self.loco:ClearStuck() + +end + +function ENT:DownTrace() + + local trace = {} + trace.start = self.Entity:GetPos() + trace.endpos = trace.start + Vector(0,0,-1000) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.Hit then + + self.Entity:SetPos( tr.HitPos + tr.HitNormal * 5 ) + + end + +end + +function ENT:RunBehaviour() + + while true do + + self.Entity:StartActivity( self.MoveAnim ) + self.loco:SetDesiredSpeed( self.MoveSpeed ) + + local enemy = self.Entity:FindEnemy() + + if not IsValid( enemy ) then + + self.Entity:MoveToPos( self.Entity:GetPos() + Vector( math.Rand( -1, 1 ), math.Rand( -1, 1 ), 0 ) * 500 ) + self.Entity:StartActivity( ACT_IDLE ) + + else + + if self.Obstructed then + + self.Entity:BreakableRoutine() + + coroutine.yield() + + end + + local age = math.Clamp( math.min( enemy:GetPos():Distance( self.Entity:GetPos() ), 1000 ) / 1000, 0.2, 1 ) + local opts = { draw = self.ShouldDrawPath, maxage = 3 * age, tolerance = self.MeleeDistance } + + if math.random(1,20) == 1 then + + self.loco:SetDesiredSpeed( math.random( 350, 700 ) ) + self.loco:SetJumpHeight( math.random( 150, self.JumpHeight ) ) + self.loco:Jump() + + self.Entity:SetVelocity( self.Entity:GetForward() * math.random( 350, 700 ) + Vector(0,0,200) ) + self.Entity:EmitSound( self.Leap, 100, math.random(90,110) ) + + end + + self.Entity:MoveToPos( enemy:GetPos(), opts ) + + self.Entity:StartActivity( ACT_IDLE ) + + self.Entity:BreakableRoutine() + self.Entity:EnemyRoutine() + + self.Entity:StartActivity( ACT_IDLE ) + + end + + coroutine.yield() + + end + +end
\ No newline at end of file diff --git a/entities/entities/npc_nb_poison/shared.lua b/entities/entities/npc_nb_poison/shared.lua new file mode 100644 index 0000000..c4c67b3 --- /dev/null +++ b/entities/entities/npc_nb_poison/shared.lua @@ -0,0 +1,121 @@ + +AddCSLuaFile() + +ENT.Base = "npc_nb_base" + +// Moddable + +ENT.AttackAnims = { "melee_01" } +ENT.AnimSpeed = 1.2 +ENT.AttackTime = 0.5 +ENT.MeleeDistance = 64 +ENT.BreakableDistance = 96 +ENT.Damage = 65 +ENT.BaseHealth = 700 +ENT.MoveSpeed = 75 +ENT.MoveAnim = ACT_WALK + +ENT.Radius = 175 +ENT.SoundRadius = 500 +ENT.EffectTime = 0 + +ENT.Models = nil +ENT.Model = Model( "models/zombie/poison.mdl" ) + +ENT.VoiceSounds = {} + +ENT.VoiceSounds.Death = { Sound( "npc/zombie_poison/pz_die1.wav" ), +Sound( "npc/zombie_poison/pz_die2.wav" ), +Sound( "npc/zombie_poison/pz_idle2.wav" ), +Sound( "npc/zombie_poison/pz_warn2.wav" ) } + +ENT.VoiceSounds.Pain = { Sound( "npc/zombie_poison/pz_idle3.wav" ), +Sound( "npc/zombie_poison/pz_idle4.wav" ), +Sound( "npc/zombie_poison/pz_pain1.wav" ), +Sound( "npc/zombie_poison/pz_pain2.wav" ), +Sound( "npc/zombie_poison/pz_pain3.wav" ), +Sound( "npc/zombie_poison/pz_warn1.wav" ) } + +ENT.VoiceSounds.Taunt = { Sound( "npc/zombie_poison/pz_alert1.wav" ), +Sound( "npc/zombie_poison/pz_alert2.wav" ), +Sound( "npc/zombie_poison/pz_call1.wav" ), +Sound( "npc/zombie_poison/pz_throw2.wav" ), +Sound( "npc/zombie_poison/pz_throw3.wav" ) } + +ENT.VoiceSounds.Attack = { Sound( "npc/zombie_poison/pz_throw2.wav" ), +Sound( "npc/zombie_poison/pz_throw3.wav" ), +Sound( "npc/zombie_poison/pz_alert2.wav" ) } + +function ENT:OnDeath( dmginfo ) + +end + +function ENT:OnThink() + + if self.EffectTime < CurTime() then + + self.EffectTime = CurTime() + 5 + + local ed = EffectData() + ed:SetEntity( self.Entity ) + util.Effect( "radiation", ed, true, true ) + + end + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + local dist = v:GetPos():Distance( self.Entity:GetPos() ) + + if dist < self.SoundRadius then + + if dist < self.Radius then + + if ( v.RadAddTime or 0 ) < CurTime() then + + v.RadAddTime = CurTime() + 8 + v:AddRadiation( 1 ) + + end + + end + + if ( v.NextRadSound or 0 ) < CurTime() then + + local scale = math.Clamp( ( self.SoundRadius - dist ) / ( self.SoundRadius - self.Radius ), 0.1, 1.0 ) + + v.NextRadSound = CurTime() + 1 - scale + v:EmitSound( table.Random( GAMEMODE.Geiger ), 100, math.random( 80, 90 ) + scale * 20 ) + v:NoticeOnce( "A radioactive zombie is nearby", GAMEMODE.Colors.Blue ) + v:NoticeOnce( "Radioactive zombies will poison nearby people", GAMEMODE.Colors.Blue, 3, 2 ) + + end + + end + + end + +end + +function ENT:OnHitEnemy( enemy ) + + enemy:TakeDamage( self.Damage, self.Entity ) + enemy:AddRadiation( 2 ) + enemy:ViewBounce( 35 ) + + umsg.Start( "Drunk", enemy ) + umsg.Short( 3 ) + umsg.End() + +end + +function ENT:OnDeath( dmginfo ) + + local ent = ents.Create( "sent_radiation" ) + ent:SetPos( self.Entity:GetPos() ) + ent:Spawn() + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "rad_explosion", ed, true, true ) + +end
\ No newline at end of file diff --git a/entities/entities/npc_scientist/shared.lua b/entities/entities/npc_scientist/shared.lua new file mode 100644 index 0000000..a39a533 --- /dev/null +++ b/entities/entities/npc_scientist/shared.lua @@ -0,0 +1,699 @@ + +AddCSLuaFile() + +ENT.Base = "base_nextbot" + +// Moddable + +ENT.AnimSpeed = 0.65 +ENT.HealDistance = 96 +ENT.AttackTime = 1.5 +ENT.BaseHealth = 100 +ENT.MoveSpeed = 175 +ENT.MoveAnim = ACT_RUN + +ENT.Models = { Model( "models/characters/hostage_04.mdl" ), Model( "models/kleiner.mdl" ) } +ENT.Legs = Model( "models/zombie/classic_legs.mdl" ) + +ENT.Pain = { "vo/k_lab/kl_ahhhh.wav", +"vo/k_lab/kl_dearme.wav", +"vo/k_lab/kl_getoutrun02.wav", +"vo/k_lab/kl_interference.wav", +"vo/k_lab/kl_mygoodness01.wav", +"vo/k_lab/kl_ohdear.wav" } + +ENT.Death = { "vo/k_lab/kl_ahhhh.wav", +"vo/k_lab/kl_getoutrun03.wav", +"vo/k_lab/kl_hedyno03.wav", +"vo/k_lab2/kl_greatscott.wav", +"vo/trainyard/kl_morewarn01.wav" } + +ENT.Happy = { "vo/k_lab/kl_excellent.wav", +"vo/k_lab/kl_moduli02.wav", +"vo/k_lab/kl_mygoodness03.wav", +"vo/k_lab/kl_relieved.wav", +"vo/k_lab2/kl_givenuphope.wav", +"vo/k_lab2/kl_howandwhen02.wav", +"vo/k_lab2/kl_notallhopeless_b.wav", +"vo/k_lab2/kl_slowteleport01.wav", +"vo/k_lab2/kl_slowteleport02.wav", +"vo/k_lab/kl_nownow02.wav" } + +ENT.Alert = { "vo/k_lab/kl_getoutrun02.wav", +"vo/k_lab/kl_getoutrun03.wav", +"vo/k_lab2/kl_greatscott.wav", +"vo/trainyard/kl_morewarn01.wav", +"vo/k_lab/kl_ohdear.wav" } + +// Other stuff + +ENT.HeadshotNoise = Sound( "Player.DamageHeadShot" ) + +ENT.NextBot = true +ENT.ShouldDrawPath = false +ENT.FireDamageTime = 0 +ENT.FireTime = 0 +ENT.HealTime = 0 +ENT.DmgTable = {} + +function ENT:Initialize() + + local model = table.Random( self.Models ) + self.Entity:SetModel( model ) + + self.Entity:SetHealth( self.BaseHealth ) + self.Entity:SetCollisionGroup( COLLISION_GROUP_NPC ) + self.Entity:SetCollisionBounds( Vector(-4,-4,0), Vector(4,4,64) ) + + self.loco:SetDeathDropHeight( 1000 ) + self.loco:SetAcceleration( 500 ) + + self.LastPos = self.Entity:GetPos() + self.Stuck = CurTime() + 10 + +end + +function ENT:Heal( ply ) + + self.Entity:VoiceSound( self.Happy ) + + ply:EmitSound( "HealthVial.Touch", 50, 120 ) + ply:AddHealth( 20 ) + ply:Notice( "+20 Health", GAMEMODE.Colors.Green ) + +end + +function ENT:Think() + + if ( self.Stuck or 0 ) < CurTime() then + + self.Entity:StuckThink() + + self.Stuck = CurTime() + 10 + self.LastPos = self.Entity:GetPos() + + end + + if self.Entity:OnFire() and self.FireDamageTime < CurTime() then + + self.FireDamageTime = CurTime() + 0.25 + + self.Entity:TakeDamage( 10, self.FireAttacker ) + + elseif self.FireSound and not self.Entity:OnFire() then + + self.Entity:StopFireSounds() + + end + + if ( self.ZombieTimer or 0 ) < CurTime() then + + self.ZombieTimer = CurTime() + 10 + + if self.Entity:NearZombie() then + + self.Entity:VoiceSound( self.Alert ) + + end + + end + + if self.CurAttack and self.CurAttack < CurTime() then + + self.CurAttack = nil + + if IsValid( self.CurEnemy ) and self.Entity:CanAttack( self.CurEnemy ) then + + self.Entity:Heal( self.CurEnemy ) + + end + + end + +end + +function ENT:NearZombie() + + for k,v in pairs( ents.FindByClass( "npc_nb*" ) ) do + + if v:GetPos():Distance( self.Entity:GetPos() ) < 300 then + + return v + + end + + end + +end + +function ENT:StuckThink() + self.LastPos = self.LastPos or Vector(0,0,0) + if self.LastPos:Distance( self.Entity:GetPos() ) < 50 then + + self.Entity:Respawn() + + end + +end + +function ENT:Respawn() + + for k,v in pairs( GAMEMODE.NPCSpawns ) do + + if IsValid( v ) then + + local box = ents.FindInBox( v:GetPos() + Vector( -32, -32, 0 ), v:GetPos() + Vector( 32, 32, 64 ) ) + local can = true + + for k,v in pairs( box ) do + + if v.NextBot then + + can = false + + end + + end + + if can then + + self.Entity:SetPos( v:GetPos() ) + return + + end + + end + + end + +end + +function ENT:OnLimbHit( hitgroup, dmginfo ) + + if not IsValid( self.Entity ) then return end + + if hitgroup == HITGROUP_HEAD then + + self.Entity:EmitSound( self.HeadshotNoise, 80, math.random( 100, 120 ) ) + self.Entity:SetHeadshotter( dmginfo:GetAttacker(), true ) + + local effectdata = EffectData() + effectdata:SetOrigin( dmginfo:GetDamagePosition() ) + util.Effect( "headshot", effectdata, true, true ) + + dmginfo:ScaleDamage( 2.75 ) + + elseif hitgroup == HITGROUP_CHEST then + + dmginfo:ScaleDamage( 1.25 ) + + self.Entity:SetHeadshotter( dmginfo:GetAttacker(), false ) + dmginfo:GetAttacker():ResetHeadshots() + + elseif hitgroup == HITGROUP_STOMACH then + + dmginfo:ScaleDamage( 0.75 ) + + self.Entity:SetHeadshotter( dmginfo:GetAttacker(), false ) + dmginfo:GetAttacker():ResetHeadshots() + + else + + dmginfo:ScaleDamage( 0.50 ) + + self.Entity:SetHeadshotter( dmginfo:GetAttacker(), false ) + dmginfo:GetAttacker():ResetHeadshots() + + end + +end + +function ENT:OnInjured( dmginfo ) + + if dmginfo:IsExplosionDamage() then + + dmginfo:ScaleDamage( 1.75 ) + + elseif not self.Entity:OnFire() then + + local snd = table.Random( GAMEMODE.GoreBullet ) + sound.Play( snd, self.Entity:GetPos() + Vector(0,0,50), 75, math.random( 90, 110 ), 1.0 ) + + end + + self.Entity:AddDamageTaken( dmginfo:GetAttacker(), dmginfo:GetDamage() ) + + if self.Entity:Health() > 0 and math.random(1,2) == 1 then + + self.Entity:VoiceSound( self.Pain ) + + end + + local att = dmginfo:GetAttacker() + + if IsValid( att ) and att.NextBot then + + //self.Entity:OnKilled( dmginfo ) + + end + +end + +function ENT:SpawnRagdoll( dmginfo, model, pos, override ) + + timer.Simple( 0.2, function() if IsValid( self.Entity ) then self.Entity:Remove() end end ) + + if not model then + + self.Entity:BecomeRagdoll( dmginfo ) + + else + + local ang = self.Entity:GetAngles() + + local shooter = ents.Create( "env_shooter" ) + shooter:SetPos( pos or self.Entity:GetPos() ) + shooter:SetKeyValue( "m_iGibs", "1" ) + shooter:SetKeyValue( "shootsounds", "3" ) + shooter:SetKeyValue( "gibangles", ang.p.." "..ang.y.." "..ang.r ) + shooter:SetKeyValue( "angles", ang.p.." "..ang.y.." "..ang.r ) + shooter:SetKeyValue( "shootmodel", model ) + shooter:SetKeyValue( "simulation", "2" ) + shooter:SetKeyValue( "gibanglevelocity", math.random(-50,50).." "..math.random(-150,150).." "..math.random(-150,150) ) + shooter:SetKeyValue( "m_flVelocity", tostring( math.Rand( -20, 20 ) ) ) + shooter:SetKeyValue( "m_flVariance", tostring( math.Rand( -2, 2 ) ) ) + + shooter:Spawn() + + shooter:Fire( "shoot", 0, 0 ) + shooter:Fire( "kill", 0.1, 0.1 ) + + if not override then + + self.Entity:Remove() + + end + + end + +end + +function ENT:OnKilled( dmginfo ) + + if self.Dying then return end + + self.Dying = true + + self.Entity:OnDeath( dmginfo ) + self.Entity:SetNWBool( "Dead", true ) + + if dmginfo then + + local ent1 = self.Entity:GetHighestDamager() + + if IsValid( ent1 ) then + + if dmginfo:IsExplosionDamage() then + + local snd = table.Random( GAMEMODE.GoreSplash ) + self.Entity:EmitSound( snd, 90, math.random( 60, 80 ) ) + + local effectdata = EffectData() + effectdata:SetOrigin( self.Entity:GetPos() + Vector(0,0,20) ) + util.Effect( "body_gib", effectdata, true, true ) + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "gore_explosion", ed, true, true ) + + local corpse = table.Random( GAMEMODE.Corpses ) + self.Entity:SpawnRagdoll( dmginfo, corpse ) + + elseif ent1:HasShotgun() and ent1:GetPos():Distance( self.Entity:GetPos() ) < 100 then + + local snd = table.Random( GAMEMODE.GoreSplash ) + self.Entity:EmitSound( snd, 90, math.random( 60, 80 ) ) + + local effectdata = EffectData() + effectdata:SetOrigin( self.Entity:GetPos() + Vector(0,0,20) ) + util.Effect( "body_gib", effectdata, true, true ) + + self.Entity:SpawnRagdoll( dmginfo, self.Legs ) + + elseif ent1:HasMelee() then + + self.Entity:VoiceSound( self.Death ) + self.Entity:SpawnRagdoll( dmginfo ) + + if self.Entity:OnFire() then + + umsg.Start( "Burned" ) + umsg.Vector( self.Entity:GetPos() ) + umsg.End() + + end + + elseif self.Entity:GetHeadshotter( ent1 ) then //self.HeadshotEffects + + local snd = table.Random( GAMEMODE.GoreSplash ) + self.Entity:EmitSound( snd, 90, math.random( 90, 110 ) ) + + local effectdata = EffectData() + effectdata:SetOrigin( self.Entity:GetPos() + Vector(0,0,40) ) + util.Effect( "head_gib", effectdata, true, true ) + + umsg.Start( "Headless" ) + umsg.Vector( self.Entity:GetPos() ) + umsg.End() + + if self.Entity:OnFire() then + + umsg.Start( "Burned" ) + umsg.Vector( self.Entity:GetPos() ) + umsg.End() + + end + + self.Entity:SpawnRagdoll( dmginfo ) + + else + + self.Entity:VoiceSound( self.Death ) + self.Entity:SpawnRagdoll( dmginfo ) + + if self.Entity:OnFire() then + + umsg.Start( "Burned" ) + umsg.Vector( self.Entity:GetPos() ) + umsg.End() + + end + + end + + else + + self.Entity:SpawnRagdoll( dmginfo ) + + end + + end + +end + +function ENT:OnDeath( dmginfo ) + + for i=1, math.random(1,3) do + + local tbl = item.RandomItem( ITEM_SUPPLY ) + + local prop = ents.Create( "prop_physics" ) + prop:SetPos( self.Entity:GetPos() + Vector(0,0,30) + VectorRand() * 5 ) + prop:SetModel( tbl.Model ) + prop:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + prop:Spawn() + + end + + if math.random(1,4) != 1 then + + local model = table.Random{ "models/healthvial.mdl", "models/items/healthkit.mdl" } + + local prop = ents.Create( "prop_physics" ) + prop:SetPos( self.Entity:GetPos() + Vector(0,0,30) + VectorRand() * 5 ) + prop:SetModel( model ) + prop:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + prop:Spawn() + + end + +end + +function ENT:OnFire() + + return self.FireTime > CurTime() + +end + +function ENT:DoIgnite( att ) + + if self.Entity:OnFire() then return end + + if IsValid( att ) and att:IsPlayer() and att:Team() == TEAM_ARMY then + + att:AddStat( "Igniter" ) + + end + + self.FireTime = CurTime() + 5 + self.FireAttacker = att + self.FireSound = true + + local ed = EffectData() + ed:SetEntity( self.Entity ) + util.Effect( "immolate", ed, true, true ) + + self.Entity:EmitSound( table.Random( GAMEMODE.Burning ), 100, 80 ) + self.Entity:EmitSound( GAMEMODE.BurnFlesh ) + +end + +function ENT:StopFireSounds() + + self.Entity:StopSound( GAMEMODE.BurnFlesh ) + +end + +function ENT:AddDamageTaken( attacker, dmg ) + + if not attacker:IsPlayer() then return end + + if not self.DmgTable[ attacker ] then + + self.DmgTable[ attacker ] = {} + self.DmgTable[ attacker ].Dmg = dmg + + elseif not self.DmgTable[ attacker ].Dmg then + + self.DmgTable[ attacker ].Dmg = dmg + + else + + self.DmgTable[ attacker ].Dmg = self.DmgTable[ attacker ].Dmg + dmg + + end + +end + +function ENT:GetHeadshotter( attacker ) + + if not self.DmgTable[ attacker ] then return false end + + return self.DmgTable[ attacker ].Headshot + +end + +function ENT:SetHeadshotter( attacker, head ) + + if not self.DmgTable[ attacker ] then + + self.DmgTable[ attacker ] = {} + + end + + self.DmgTable[ attacker ].Headshot = head + +end + +function ENT:GetHighestDamager() + + local ent1 = NULL + local high = 0 + + for k,v in pairs( self.DmgTable ) do + + if IsValid( k ) and v.Dmg and v.Dmg > high then + + high = v.Dmg + ent1 = k + + end + + end + + return ent1 + +end + +function ENT:VoiceSound( tbl ) + + if ( self.VoiceTime or 0 ) > CurTime() then return end + + self.VoiceTime = CurTime() + 1.5 + + local snd = table.Random( tbl ) + sound.Play( snd, self.Entity:GetPos() + Vector(0,0,50), 75, 100, 0.7 ) + +end + +function ENT:StartAttack( enemy ) + + self.CurAttack = CurTime() + self.AttackTime + self.CurEnemy = enemy + +end + +function ENT:OnHitEnemy( enemy ) + + enemy:TakeDamage( self.Damage, self.Entity ) + +end + +function ENT:BehaveAct() // what does this do? + +end + +function ENT:IsZombie() + + return false + +end + +function ENT:CanTarget( v ) + + return ( v:Alive() and v:GetObserverMode() == OBS_MODE_NONE and v:Team() == TEAM_ARMY ) + +end + +function ENT:FindHuman() + + local tbl = team.GetPlayers( TEAM_ARMY ) + + self.EnemyTable = tbl + + if #tbl < 1 then + + return NULL + + else + + local enemy = NULL + local dist = 99999 + + for k,v in pairs( tbl ) do + + local compare = v:GetPos():Distance( self.Entity:GetPos() ) + + if compare < dist and self.Entity:CanTarget( v ) then + + enemy = v + dist = compare + + end + + end + + return enemy + + end + +end + +function ENT:CanAttack( ent ) + + return IsValid( ent ) and self.Entity:CanTarget( ent ) and ent:GetPos():Distance( self.Entity:GetPos() ) <= self.HealDistance + +end + +function ENT:CanAttackEnemy( ent ) + + if self.Entity:CanAttack( ent ) then + + return ent + + end + + if #self.EnemyTable < 1 then return end + + for k,v in pairs( self.EnemyTable ) do + + if self.Entity:CanAttack( v ) then + + return v + + end + + end + +end + +function ENT:OnStuck() + + //self.loco:ClearStuck() + self.Entity:VoiceSound( self.Alert ) + +end + +function ENT:OnUnStuck() + + //self.Obstructed = false + +end + +function ENT:StartAttack( enemy ) + + self.CurAttack = CurTime() + self.AttackTime + self.CurEnemy = enemy + +end + +function ENT:EnemyRoutine() + + local closest = self.Entity:CanAttackEnemy( enemy ) + + while IsValid( closest ) do + + self.Entity:StartAttack( closest ) + self.Entity:PlaySequenceAndWait( "open_door_away", self.AnimSpeed ) + + coroutine.wait( 1.0 ) + + closest = self.Entity:CanAttackEnemy( closest ) + + end + +end + +function ENT:RunBehaviour() + + while true do + + self.Entity:StartActivity( self.MoveAnim ) + self.loco:SetDesiredSpeed( self.MoveSpeed ) + + local enemy = self.Entity:FindHuman() + + if not IsValid( enemy ) then + + self.Entity:MoveToPos( self.Entity:GetPos() + Vector( math.Rand( -1, 1 ), math.Rand( -1, 1 ), 0 ) * 500 ) + self.Entity:StartActivity( ACT_IDLE ) + + else + + local opts = { draw = self.ShouldDrawPath, maxage = 1, tolerance = self.HealDistance } + + self.Entity:MoveToPos( enemy:GetPos(), opts ) + + self.Entity:StartActivity( ACT_IDLE ) + + self.Entity:EnemyRoutine() + + self.Entity:StartActivity( ACT_IDLE ) + + end + + coroutine.yield() + + end + +end diff --git a/entities/entities/point_evac/cl_init.lua b/entities/entities/point_evac/cl_init.lua new file mode 100644 index 0000000..c069cf8 --- /dev/null +++ b/entities/entities/point_evac/cl_init.lua @@ -0,0 +1,19 @@ + +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:Think() + +end + +function ENT:OnRemove() + +end + +function ENT:Draw() + +end + diff --git a/entities/entities/point_evac/init.lua b/entities/entities/point_evac/init.lua new file mode 100644 index 0000000..040bf87 --- /dev/null +++ b/entities/entities/point_evac/init.lua @@ -0,0 +1,117 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.Heli = Sound( "ambient/machines/heli_pass2.wav" ) + +ENT.EvacDist = 400 + +function ENT:Initialize() + + self.Entity:SetMoveType( MOVETYPE_NONE ) + self.Entity:SetSolid( SOLID_NONE ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_DEBRIS_TRIGGER ) + self.Entity:SetTrigger( true ) + self.Entity:SetNotSolid( true ) + self.Entity:DrawShadow( false ) + + self.Entity:SetCollisionBounds( Vector( -150, -150, -150 ), Vector( 150, 150, 150 ) ) + self.Entity:PhysicsInitBox( Vector( -150, -150, -150 ), Vector( 150, 150, 150 ) ) + + self.DieTime = CurTime() + 44 + self.SoundTime = CurTime() + 43 + + self.Players = {} + + local flare = ents.Create( "sent_heliflare" ) + flare:SetPos( self.Entity:GetPos() ) + flare:Spawn() + + self.Entity:EmitSound( self.Heli, 150 ) + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,10) + trace.endpos = trace.start + Vector(0,0,800) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.HitPos:Distance( self.Entity:GetPos() ) < 400 then return end + + local heli = ents.Create( "prop_dynamic" ) + heli:SetModel( "models/combine_helicopter.mdl" ) + heli:SetPos( tr.HitPos + Vector(0,0,-150) ) + heli:Spawn() + heli:Fire( "SetAnimation", "idle", 1 ) + +end + +function ENT:Think() + + if self.SoundTime and self.SoundTime < CurTime() then + + self.Entity:EmitSound( self.Heli, 150 ) + + self.SoundTime = nil + + end + + if self.DieTime < CurTime() then + + self.Entity:Evac() + self.Entity:Remove() + + for k,v in pairs( team.GetPlayers( TEAM_ZOMBIES ) ) do + + v:Notice( "The chopper has left the evac zone", GAMEMODE.Colors.White, 5 ) + + end + + end + +end + +function ENT:Evac() + + for k,v in pairs( self.Players ) do + + if IsValid( v ) and v:Alive() and v:Team() == TEAM_ARMY and v:GetPos():Distance( self.Entity:GetPos() ) < self.EvacDist then + + v:Evac() + + end + + end + +end + +function ENT:Touch( ent ) + + if not ent:IsPlayer() then return end + + if ent:Team() != TEAM_ARMY then return end + + if table.HasValue( self.Players, ent ) then return end + + table.insert( self.Players, ent ) + + if not self.FirstEvac then + + self.FirstEvac = true + + ent:AddStat( "Evac" ) + + end + + ent:Notice( "You made it to the evac zone", GAMEMODE.Colors.Green, 5 ) + ent:Notice( "The helicopter will take off shortly", GAMEMODE.Colors.Blue, 5, 2 ) + +end + +function ENT:UpdateTransmitState() + + return TRANSMIT_ALWAYS + +end diff --git a/entities/entities/point_evac/shared.lua b/entities/entities/point_evac/shared.lua new file mode 100644 index 0000000..8e216e2 --- /dev/null +++ b/entities/entities/point_evac/shared.lua @@ -0,0 +1,3 @@ +ENT.Type = "anim" +ENT.Base = "base_anim" + diff --git a/entities/entities/point_radiation/init.lua b/entities/entities/point_radiation/init.lua new file mode 100644 index 0000000..7821c2d --- /dev/null +++ b/entities/entities/point_radiation/init.lua @@ -0,0 +1,94 @@ + +ENT.Type = "point" +ENT.Base = "base_point" + +function ENT:Initialize() + + self.Active = true + self.Radius = 400 + self.SoundRadius = 800 + self.Pos = self.Entity:GetPos() + +end + +function ENT:SetArtifact( ent ) + + self.Artifact = ent + +end + +function ENT:GetArtifact() + + return self.Artifact or NULL + +end + +function ENT:SetActive( bool ) + + self.Active = bool + +end + +function ENT:IsActive() + + return self.Active + +end + +function ENT:KeyValue( key, value ) + + if key == "radius" then + + self.Radius = math.Clamp( tonumber( value ), 100, 5000 ) + self.SoundRadius = self.Radius * 1.4 + + elseif key == "randomradius" then + + self.Radius = math.random( 100, math.Clamp( tonumber( value ), 500, 5000 ) ) + self.SoundRadius = self.Radius * 1.4 + + end + +end + +function ENT:GetRadiationRadius() + + return self.Radius + +end + +function ENT:Think() + + if not self.Active then return end + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + local dist = v:GetPos():Distance( self.Pos ) + + if dist < self.SoundRadius then + + if dist < self.Radius then + + if ( v.RadAddTime or 0 ) < CurTime() then + + v.RadAddTime = CurTime() + 10 + v:AddRadiation( 1 ) + + end + + end + + if ( v.NextRadSound or 0 ) < CurTime() then + + local scale = math.Clamp( ( self.SoundRadius - dist ) / ( self.SoundRadius - self.Radius ), 0.1, 1.0 ) + + v.NextRadSound = CurTime() + 1 - scale + v:EmitSound( table.Random( GAMEMODE.Geiger ), 100, math.random( 80, 90 ) + scale * 20 ) + + end + + end + + end + +end diff --git a/entities/entities/point_stash/cl_init.lua b/entities/entities/point_stash/cl_init.lua new file mode 100644 index 0000000..e978063 --- /dev/null +++ b/entities/entities/point_stash/cl_init.lua @@ -0,0 +1,11 @@ + +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:Draw() + +end + diff --git a/entities/entities/point_stash/init.lua b/entities/entities/point_stash/init.lua new file mode 100644 index 0000000..94fcc43 --- /dev/null +++ b/entities/entities/point_stash/init.lua @@ -0,0 +1,170 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +function ENT:Initialize() + + self.Entity:SetModel( "models/Roller.mdl" ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_NONE ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + self.Entity:DrawShadow( false ) + + self.Cash = 0 + self.LastUse = 0 + self.LastThink = 0 + self.Items = {} + + self.ItemTbl = { ITEM_FOOD, ITEM_FOOD, ITEM_FOOD, ITEM_FOOD, ITEM_FOOD, ITEM_SUPPLY, ITEM_SUPPLY, ITEM_MISC, ITEM_MISC, ITEM_LOOT, ITEM_LOOT, ITEM_AMMO, ITEM_AMMO, ITEM_EXODUS, ITEM_WPN_COMMON } + + for i=1, math.random(2,5) do + + local rand = item.RandomItem( table.Random( self.ItemTbl ) ) + + self.Entity:AddItem( rand.ID ) + + end + +end + +function ENT:SetCash( amt ) + + self.Cash = math.Clamp( amt, 0, 32000 ) + +end + +function ENT:GetCash() + + return self.Cash + +end + +function ENT:Think() + + if not IsValid( self.Entity:GetUser() ) then return end + + if not self.Entity:GetUser():Alive() then + + self.Entity:SetUser() + + end + + if self.LastThink < CurTime() then + + self.LastThink = CurTime() + ( 10 * 60 ) + + if #self.Entity:GetItems() < 1 then + + for i=1, math.random(2,5) do + + local rand = item.RandomItem( table.Random( self.ItemTbl ) ) + + self.Entity:AddItem( rand.ID ) + + end + + end + + end + +end + +function ENT:GetUser() + + return self.User + +end + +function ENT:SetUser( ply ) + + self.User = ply + +end + +function ENT:OnExit( ply ) + + if ( self.LastUse or 0 ) > CurTime() then return end + + self.LastUse = CurTime() + 1.0 + + if IsValid( self.Entity:GetUser() ) then + + self.Entity:SetUser() + ply:ToggleStashMenu( self.Entity, false, "StashMenu" ) + + end + +end + +function ENT:OnUsed( ply ) + + if ( self.LastUse or 0 ) > CurTime() then return end + + self.LastUse = CurTime() + 1.0 + + if IsValid( self.Entity:GetUser() ) and self.Entity:GetUser() != ply then return end + + if not IsValid( self.Entity:GetUser() ) then + + ply:SynchCash( self.Cash ) + + self.Entity:SetUser( ply ) + ply:ToggleStashMenu( self.Entity, true, "StashMenu" ) + + end + +end + +function ENT:Use( ply, caller ) + +end + +function ENT:GetItems() + + return self.Items + +end + +function ENT:AddItem( id ) + + self.Items = self.Items or {} + + table.insert( self.Items, id ) + + self.Entity:Synch() + +end + +function ENT:RemoveItem( id ) + + for k,v in pairs( self.Items ) do + + if v == id then + + self.Entity:Synch() + + table.remove( self.Items, k ) + + return + + end + + end + +end + +function ENT:Synch() + + if IsValid( self.Entity:GetUser() ) then + + self.Entity:GetUser():SynchStash( self.Entity ) + + end + +end + diff --git a/entities/entities/point_stash/shared.lua b/entities/entities/point_stash/shared.lua new file mode 100644 index 0000000..8e216e2 --- /dev/null +++ b/entities/entities/point_stash/shared.lua @@ -0,0 +1,3 @@ +ENT.Type = "anim" +ENT.Base = "base_anim" + diff --git a/entities/entities/sent_antidote/cl_init.lua b/entities/entities/sent_antidote/cl_init.lua new file mode 100644 index 0000000..88a116a --- /dev/null +++ b/entities/entities/sent_antidote/cl_init.lua @@ -0,0 +1,44 @@ + +include('shared.lua') + +function ENT:Initialize() + + GAMEMODE.ClientAntidote = self.Entity + +end + +function ENT:Think() + +end + +local matLight = Material( "toxsin/allyvision" ) + +function ENT:Draw() + + self.Entity:DrawModel() + +end + +--[[local scale = ( math.Clamp( self.Entity:GetPos():Distance( LocalPlayer():GetPos() ), 500, 3000 ) - 500 ) / 2500 + + local eyenorm = self.Entity:GetPos() - EyePos() + local dist = eyenorm:Length() + eyenorm:Normalize() + + local pos = EyePos() + eyenorm * dist * 0.01 + + cam.Start3D( pos, EyeAngles() ) + + render.SetColorModulation( 0, 1.0, 0.5 ) + render.SetBlend( scale ) + render.MaterialOverride( matLight ) + + self.Entity:DrawModel() + + render.SetColorModulation( 1, 1, 1 ) + render.SetBlend( 1 ) + render.MaterialOverride( 0 ) + + cam.End3D() + +end]]
\ No newline at end of file diff --git a/entities/entities/sent_antidote/init.lua b/entities/entities/sent_antidote/init.lua new file mode 100644 index 0000000..8fc742d --- /dev/null +++ b/entities/entities/sent_antidote/init.lua @@ -0,0 +1,86 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.Cure = Sound( "ItemBattery.Touch" ) +ENT.Model = Model( "models/Items/item_item_crate.mdl" ) + +function ENT:Initialize() + + self.Entity:SetModel( self.Model ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + + self.Entity:SetColor( Color( 150, 255, 200, 255 ) ) + + self.CureCount = math.max( team.NumPlayers( TEAM_ARMY ) / 2, 1 ) + +end + +function ENT:Think() + +end + +function ENT:SetOverride() + + self.Override = true + +end + +function ENT:SetCures( num ) + + self.CureCount = num + +end + +function ENT:CuresLeft() + + return self.CureCount + +end + +function ENT:Use( ply, caller ) + + if self.Removing then return end + + if ply:IsInfected() then + + ply:SetInfected( false ) + ply:AddStamina( 20 ) + ply:EmitSound( self.Cure ) + ply:Notice( "Your infection has been cured", GAMEMODE.Colors.Green ) + + if not self.Override then + + self.CureCount = self.CureCount - 1 + + end + + end + + if self.CureCount < 1 then + + self.Entity:Remove() + + end + +end + +function ENT:UpdateTransmitState() + + return TRANSMIT_ALWAYS + +end diff --git a/entities/entities/sent_antidote/shared.lua b/entities/entities/sent_antidote/shared.lua new file mode 100644 index 0000000..8e216e2 --- /dev/null +++ b/entities/entities/sent_antidote/shared.lua @@ -0,0 +1,3 @@ +ENT.Type = "anim" +ENT.Base = "base_anim" + diff --git a/entities/entities/sent_barrel_biohazard/cl_init.lua b/entities/entities/sent_barrel_biohazard/cl_init.lua new file mode 100644 index 0000000..514bad0 --- /dev/null +++ b/entities/entities/sent_barrel_biohazard/cl_init.lua @@ -0,0 +1,20 @@ +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:OnRemove() + +end + +function ENT:Think() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_barrel_biohazard/init.lua b/entities/entities/sent_barrel_biohazard/init.lua new file mode 100644 index 0000000..b776619 --- /dev/null +++ b/entities/entities/sent_barrel_biohazard/init.lua @@ -0,0 +1,137 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.HitSound = Sound( "Metal_Barrel.ImpactSoft" ) +ENT.DieSound = Sound( "Breakable.Metal" ) +ENT.Model = Model( "models/props/de_train/barrel.mdl" ) +ENT.Damage = 60 +ENT.Radius = 300 +ENT.Skins = {2,4,5,6} + +function ENT:Initialize() + + local skin = table.Random( self.Skins ) + + self.Entity:SetModel( self.Model ) + self.Entity:SetSkin( skin ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + //self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + +end + +function ENT:SetSpeed( num ) + + self.Speed = num + +end + +function ENT:Think() + +end + +function ENT:Explode() + + if self.Exploded then return end + + self.Exploded = true + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "Explosion", ed, true, true ) + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,20) + trace.endpos = trace.start + Vector( 0, 0, -200 ) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.HitWorld then + + local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetMagnitude( 0.8 ) + util.Effect( "smoke_crater", ed, true, true ) + + util.Decal( "Scorch", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal ) + + end + + if IsValid( self.Entity:GetOwner() ) then + + util.BlastDamage( self.Entity, self.Entity:GetOwner(), self.Entity:GetPos(), self.Radius, self.Damage ) + + end + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + if v:GetPos():Distance( self.Entity:GetPos() ) < 200 and not v:IsInfected() and v:Alive() then + + v:SetInfected( true ) + + end + + end + + for i=1, math.random( 2, 4 ) do + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "barrel_gib", ed, true, true ) + + end + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "biohazard", ed, true, true ) + + self.Entity:EmitSound( self.DieSound, 100, math.random(90,110) ) + self.Entity:Remove() + +end + +function ENT:Use( ply, caller ) + + ply:AddToInventory( self.Entity ) + +end + +function ENT:OnRemove() + +end + +function ENT:OnTakeDamage( dmginfo ) + + if dmginfo:IsBulletDamage() and IsValid( dmginfo:GetAttacker() ) and dmginfo:GetAttacker():IsPlayer() then + + self.Entity:SetOwner( dmginfo:GetAttacker() ) + self.Entity:Explode() + + end + +end + +function ENT:PhysicsCollide( data, phys ) + + if data.Speed > 50 and data.DeltaTime > 0.15 then + + self.Entity:EmitSound( self.HitSound ) + + end + +end + diff --git a/entities/entities/sent_barrel_biohazard/shared.lua b/entities/entities/sent_barrel_biohazard/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_barrel_biohazard/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_barrel_radioactive/cl_init.lua b/entities/entities/sent_barrel_radioactive/cl_init.lua new file mode 100644 index 0000000..514bad0 --- /dev/null +++ b/entities/entities/sent_barrel_radioactive/cl_init.lua @@ -0,0 +1,20 @@ +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:OnRemove() + +end + +function ENT:Think() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_barrel_radioactive/init.lua b/entities/entities/sent_barrel_radioactive/init.lua new file mode 100644 index 0000000..ef2fcd0 --- /dev/null +++ b/entities/entities/sent_barrel_radioactive/init.lua @@ -0,0 +1,131 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.HitSound = Sound( "Metal_Barrel.ImpactSoft" ) +ENT.DieSound = Sound( "Breakable.Metal" ) +ENT.Model = Model( "models/props/de_train/barrel.mdl" ) +ENT.Damage = 60 +ENT.Radius = 300 +ENT.Skins = {0,1,7} + +function ENT:Initialize() + + local skin = table.Random( self.Skins ) + + self.Entity:SetModel( self.Model ) + self.Entity:SetSkin( skin ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + //self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + +end + +function ENT:SetSpeed( num ) + + self.Speed = num + +end + +function ENT:Think() + +end + +function ENT:Explode() + + if self.Exploded then return end + + self.Exploded = true + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "Explosion", ed, true, true ) + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,20) + trace.endpos = trace.start + Vector( 0, 0, -200 ) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.HitWorld then + + local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetMagnitude( 0.8 ) + util.Effect( "smoke_crater", ed, true, true ) + + util.Decal( "Scorch", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal ) + + end + + if IsValid( self.Entity:GetOwner() ) then + + util.BlastDamage( self.Entity, self.Entity:GetOwner(), self.Entity:GetPos(), self.Radius, self.Damage ) + + end + + for i=1, math.random( 2, 4 ) do + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "barrel_gib", ed, true, true ) + + end + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "rad_explosion", ed, true, true ) + + local ent = ents.Create( "sent_radiation" ) + ent:SetPos( self.Entity:GetPos() ) + ent:Spawn() + + self.Entity:EmitSound( self.DieSound, 100, math.random(90,110) ) + self.Entity:Remove() + +end + +function ENT:Use( ply, caller ) + + ply:AddToInventory( self.Entity ) + +end + +function ENT:OnRemove() + +end + +function ENT:OnTakeDamage( dmginfo ) + + if dmginfo:IsBulletDamage() and IsValid( dmginfo:GetAttacker() ) and dmginfo:GetAttacker():IsPlayer() then + + self.Entity:SetOwner( dmginfo:GetAttacker() ) + self.Entity:Explode() + + end + +end + +function ENT:PhysicsCollide( data, phys ) + + if data.Speed > 50 and data.DeltaTime > 0.15 then + + self.Entity:EmitSound( self.HitSound ) + + end + +end + diff --git a/entities/entities/sent_barrel_radioactive/shared.lua b/entities/entities/sent_barrel_radioactive/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_barrel_radioactive/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_bonuscrate/cl_init.lua b/entities/entities/sent_bonuscrate/cl_init.lua new file mode 100644 index 0000000..f1cad0f --- /dev/null +++ b/entities/entities/sent_bonuscrate/cl_init.lua @@ -0,0 +1,13 @@ + +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_bonuscrate/init.lua b/entities/entities/sent_bonuscrate/init.lua new file mode 100644 index 0000000..3817a61 --- /dev/null +++ b/entities/entities/sent_bonuscrate/init.lua @@ -0,0 +1,97 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.Bang = Sound( "Wood.ImpactHard" ) +ENT.Open = Sound( "Wood.Strain" ) +ENT.Model = Model( "models/items/ammocrate_smg1.mdl" ) + +function ENT:Initialize() + + self.Entity:SetModel( self.Model ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + phys:SetDamping( 0, 200 ) + + end + + self.Removing = false + self.Contents = { 1 } + self.Users = {} + self.Uses = math.random( 1, 5 ) + +end + +function ENT:Think() + +end + +function ENT:GenerateContents() + + self.Contents = {} + + local tbl = { ITEM_WPN_COMMON, ITEM_AMMO, ITEM_AMMO } + + if math.random( 1, 50 ) == 1 then + + tbl = { ITEM_WPN_SPECIAL, ITEM_AMMO, ITEM_AMMO } + + end + + for k,v in pairs( tbl ) do + + local tbl = item.RandomItem( v ) + local id = tbl.ID + + table.insert( self.Contents, id ) + + end + +end + +function ENT:AddUser( ply ) + + table.insert( self.Users, ply ) + +end + +function ENT:Use( ply, caller ) + + if not IsValid( ply ) or table.HasValue( self.Users, ply ) or ply:Team() != TEAM_ARMY or self.Removing then return end + + self.Entity:EmitSound( self.Open ) + self.Entity:GenerateContents() + + ply:AddMultipleToInventory( self.Contents ) + + table.insert( self.Users, ply ) + + if table.Count( self.Users ) == self.Uses then + + self.Entity:Remove() + + end + +end + +function ENT:PhysicsCollide( data, phys ) + + if data.Speed > 50 and data.DeltaTime > 0.15 then + + self.Entity:EmitSound( self.Bang ) + + end + +end + diff --git a/entities/entities/sent_bonuscrate/shared.lua b/entities/entities/sent_bonuscrate/shared.lua new file mode 100644 index 0000000..8e216e2 --- /dev/null +++ b/entities/entities/sent_bonuscrate/shared.lua @@ -0,0 +1,3 @@ +ENT.Type = "anim" +ENT.Base = "base_anim" + diff --git a/entities/entities/sent_c4/cl_init.lua b/entities/entities/sent_c4/cl_init.lua new file mode 100644 index 0000000..1821218 --- /dev/null +++ b/entities/entities/sent_c4/cl_init.lua @@ -0,0 +1,36 @@ +include('shared.lua') + +function ENT:Initialize() + + self.Light = Material( "sprites/light_glow02_add" ) + self.Beep = CurTime() + 1 + +end + +function ENT:OnRemove() + +end + +function ENT:Think() + + if self.Beep < CurTime() then + + self.Beep = CurTime() + 1 + + end + +end + +function ENT:Draw() + + self.Entity:DrawModel() + + if self.Beep <= ( CurTime() + 0.1 ) then + + render.SetMaterial( self.Light ) + render.DrawSprite( self.Entity:GetPos() + self.Entity:GetRight() * -5, 6, 6, Color( 255, 0, 0 ) ) + + end + +end + diff --git a/entities/entities/sent_c4/init.lua b/entities/entities/sent_c4/init.lua new file mode 100644 index 0000000..3410fca --- /dev/null +++ b/entities/entities/sent_c4/init.lua @@ -0,0 +1,120 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.ExplodeSound = { 1, 2, 4, 5, 6, 8 } +ENT.DebrisSound = Sound( "weapons/c4/c4_exp_deb2.wav" ) +ENT.DebrisSound2 = Sound( "weapons/debris2.wav" ) +ENT.BeepSound = Sound( "weapons/c4/c4_beep1.wav" ) +ENT.Damage = 400 +ENT.Radius = 600 + +function ENT:Initialize() + + self.Entity:SetModel( Model( "models/weapons/w_c4.mdl" ) ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + self.Entity:DrawShadow( false ) + + self.Delay = CurTime() + 10 + self.Beep = CurTime() + 1 + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + +end + +function ENT:SetSpeed( num ) + + self.Speed = num + +end + +function ENT:Think() + + if self.Delay < CurTime() then + + self.Entity:Explode() + + end + + if self.Beep < CurTime() then + + self.Beep = CurTime() + 1 + + self.Entity:EmitSound( self.BeepSound, 100, 120 ) + + end + +end + +function ENT:Explode() + + self.Entity:EmitSound( "explode_" .. table.Random( self.ExplodeSound ), 300, 100 ) + self.Entity:EmitSound( self.DebrisSound, 300, 100 ) + self.Entity:EmitSound( self.DebrisSound2, 300, 100 ) + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "c4_explosion", ed, true, true ) + + local trace = {} + trace.start = self.Entity:GetPos() + trace.endpos = trace.start + Vector( 0, 0, -200 ) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.HitWorld then + + local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetMagnitude( 1.2 ) + util.Effect( "smoke_crater", ed, true, true ) + + util.Decal( "Scorch", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal ) + + end + + if IsValid( self.Entity:GetOwner() ) then + + util.BlastDamage( self.Entity, self.Entity:GetOwner(), self.Entity:GetPos(), self.Radius, self.Damage ) + + end + + for k,v in pairs( player.GetAll() ) do + + if v:Team() != self.Entity:GetOwner():Team() and v:GetPos():Distance( self.Entity:GetPos() ) < self.Radius then + + v:SetBleeding( true ) + + end + + end + + self.Entity:Remove() + +end + +function ENT:OnRemove() + +end + +function ENT:OnTakeDamage( dmginfo ) + +end + +function ENT:PhysicsCollide( data, phys ) + +end + diff --git a/entities/entities/sent_c4/shared.lua b/entities/entities/sent_c4/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_c4/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_cash/cl_init.lua b/entities/entities/sent_cash/cl_init.lua new file mode 100644 index 0000000..d0fb196 --- /dev/null +++ b/entities/entities/sent_cash/cl_init.lua @@ -0,0 +1,18 @@ + +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:Think() + +end + +function ENT:Draw() + + //self.Entity:SetModelScale( Vector(1,1,1) + Vector(1,1,1) * math.sin( CurTime() * 3 ) * 0.1 ) + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_cash/init.lua b/entities/entities/sent_cash/init.lua new file mode 100644 index 0000000..1adb29e --- /dev/null +++ b/entities/entities/sent_cash/init.lua @@ -0,0 +1,84 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +function ENT:Initialize() + + self.Entity:SetModel( Model( "models/props/cs_assault/money.mdl" ) ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + + self.Cash = 0 + self.NPCThink = 0 + self.RemoveTime = CurTime() + 10 * 60 + +end + +function ENT:Think() + + if self.NPCThink < CurTime() then + + self.NPCThink = CurTime() + 10 + + for k,v in pairs( ents.FindByClass( "npc_trader*" ) ) do + + if v:GetPos():Distance( self.Entity:GetPos() ) < 50 then + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:ApplyForceCenter( ( self.Entity:GetPos() - v:GetPos() ):Normalize() * phys:GetMass() * 100 ) + + return + + end + + end + + end + + if self.RemoveTime < CurTime() then + + self.Entity:Remove() + + end + + end + +end + +function ENT:SetCash( amt ) + + self.Cash = amt + + self.Entity:SetNWInt( "Cash", amt ) + +end + +function ENT:GetCash() + + return self.Cash + +end + +function ENT:Use( ply, caller ) + + ply:AddCash( self.Cash ) + + self.Entity:Remove() + +end diff --git a/entities/entities/sent_cash/shared.lua b/entities/entities/sent_cash/shared.lua new file mode 100644 index 0000000..8e216e2 --- /dev/null +++ b/entities/entities/sent_cash/shared.lua @@ -0,0 +1,3 @@ +ENT.Type = "anim" +ENT.Base = "base_anim" + diff --git a/entities/entities/sent_dropflare/cl_init.lua b/entities/entities/sent_dropflare/cl_init.lua new file mode 100644 index 0000000..3ff2828 --- /dev/null +++ b/entities/entities/sent_dropflare/cl_init.lua @@ -0,0 +1,73 @@ +include('shared.lua') + +function ENT:Initialize() + + self.Emitter = ParticleEmitter( self.Entity:GetPos() ) + self.Smoke = 0 + +end + +function ENT:OnRemove() + + if self.Emitter then + + self.Emitter:Finish() + + end + +end + +function ENT:Think() + + if self.Entity:GetNWFloat( "BurnDelay", 9000 ) > CurTime() then return end + + if self.Smoke < CurTime() then + + self.Smoke = CurTime() + 0.2 + + local particle = self.Emitter:Add( "particles/smokey", self.Entity:GetPos() + self.Entity:GetRight() * 5 ) + particle:SetVelocity( VectorRand() * 5 + WindVector + Vector(0,0,10) ) + particle:SetDieTime( math.Rand( 2.5, 5.0 ) ) + particle:SetStartAlpha( 100 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 3, 6 ) ) + particle:SetEndSize( math.random( 25, 50 ) ) + particle:SetGravity( Vector( 0, 0, 10 ) ) + + local col = math.random( 100, 150 ) + particle:SetColor( col, col + 50, col ) + + end + + local dlight = DynamicLight( self.Entity:EntIndex() ) + + if dlight then + + dlight.Pos = self.Entity:GetPos() + dlight.r = 50 + dlight.g = 255 + dlight.b = 50 + dlight.Brightness = 3 + dlight.Decay = 2048 + dlight.size = 256 * math.Rand( 0.5, 1.0 ) + dlight.DieTime = CurTime() + 1 + + end + +end + +local matFlare = Material( "effects/blueflare1" ) + +function ENT:Draw() + + self.Entity:DrawModel() + + if self.Entity:GetNWFloat( "BurnDelay", CurTime() + 1 ) > CurTime() then return end + + local size = math.Rand( 5, 25 ) + + render.SetMaterial( matFlare ) + render.DrawSprite( self.Entity:GetPos() + self.Entity:GetRight() * 5, size, size, Color( 50, 255, 50, 255 ) ) + +end + diff --git a/entities/entities/sent_dropflare/init.lua b/entities/entities/sent_dropflare/init.lua new file mode 100644 index 0000000..b806886 --- /dev/null +++ b/entities/entities/sent_dropflare/init.lua @@ -0,0 +1,84 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.Burn = Sound( "Weapon_FlareGun.Burn" ) +ENT.Explode = Sound( "weapons/flashbang/flashbang_explode1.wav" ) + +function ENT:Initialize() + + self.Entity:SetModel( Model( "models/props_c17/trappropeller_lever.mdl" ) ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + self.Entity:DrawShadow( false ) + + self.Entity:SetNWFloat( "BurnDelay", CurTime() + 3 ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + phys:SetDamping( 0, 10 ) + + end + + self.DieTime = CurTime() + 15 + + self.Entity:EmitSound( "Weapon_SMG1.Special1", 100, 80 ) + +end + +function ENT:SetDieTime( t ) + + self.DieTime = CurTime() + t + +end + +function ENT:Think() + + if self.Entity:GetNWFloat( "BurnDelay", 0 ) < CurTime() then + + if not self.Burning then + + self.Burning = true + self.Entity:EmitSound( self.Burn ) + self.Entity:EmitSound( self.Explode, 100, math.random(90,110) ) + + end + + end + + if self.DieTime < CurTime() then + + self.Entity:Remove() + + end + +end + +function ENT:OnRemove() + + self.Entity:StopSound( self.Burn ) + +end + +function ENT:OnTakeDamage( dmginfo ) + +end + +function ENT:PhysicsCollide( data, phys ) + +end + +function ENT:UpdateTransmitState() + + return TRANSMIT_ALWAYS + +end + diff --git a/entities/entities/sent_dropflare/shared.lua b/entities/entities/sent_dropflare/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_dropflare/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_droppedgun/cl_init.lua b/entities/entities/sent_droppedgun/cl_init.lua new file mode 100644 index 0000000..f1cad0f --- /dev/null +++ b/entities/entities/sent_droppedgun/cl_init.lua @@ -0,0 +1,13 @@ + +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_droppedgun/init.lua b/entities/entities/sent_droppedgun/init.lua new file mode 100644 index 0000000..20d6571 --- /dev/null +++ b/entities/entities/sent_droppedgun/init.lua @@ -0,0 +1,49 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +function ENT:Initialize() + + if string.find( self.Entity:GetModel(), "hammer" ) or string.find( self.Entity:GetModel(), "axe" ) then + + local model = self.Entity:GetModel() + + self.Entity:SetModel( "models/props_canal/mattpipe.mdl" ) + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetModel( model ) + + //self.Entity:PhysicsInitBox( Vector(-5,-5,-5), Vector(5,5,5) ) + + else + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + + end + + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + +end + +function ENT:Think() + +end + +function ENT:Use( ply, caller ) + + if ply:Team() != TEAM_ARMY then return end + + ply:AddToInventory( self.Entity ) + +end diff --git a/entities/entities/sent_droppedgun/shared.lua b/entities/entities/sent_droppedgun/shared.lua new file mode 100644 index 0000000..8e216e2 --- /dev/null +++ b/entities/entities/sent_droppedgun/shared.lua @@ -0,0 +1,3 @@ +ENT.Type = "anim" +ENT.Base = "base_anim" + diff --git a/entities/entities/sent_fire/cl_init.lua b/entities/entities/sent_fire/cl_init.lua new file mode 100644 index 0000000..fb83991 --- /dev/null +++ b/entities/entities/sent_fire/cl_init.lua @@ -0,0 +1,120 @@ + +include('shared.lua') + +function ENT:Initialize() + + self.Emitter = ParticleEmitter( self.Entity:GetPos() ) + + self.SmokeTime = 0 + self.LightTime = 0 + + self.Entity:DoTraces() + +end + +function ENT:DoTraces() + + if self.Entity:GetPos() == Vector(0,0,0) then return end + + self.PosTbl = {} + + for i=-30,30 do + + for j=-30,30 do + + local trace = {} + trace.start = self.Entity:GetPos() + Vector( i * 2, j * 2, 10 ) + trace.endpos = trace.start + Vector(0,0,200) + + local tr = util.TraceLine( trace ) + + trace.start = tr.HitPos + trace.endpos = trace.start + Vector( 0, 0, -2000 ) + + local tr2 = util.TraceLine( trace ) + + table.insert( self.PosTbl, { Pos = tr2.HitPos, Scale = ( ( 30 - math.abs( i ) ) + ( 30 - math.abs( j ) ) ) / 60 } ) + + end + + end + +end + +function ENT:Think() + + if not self.PosTbl then + + self.Entity:DoTraces() + + if not self.PosTbl then return end + + end + + local tbl = table.Random( self.PosTbl ) + + local particle = self.Emitter:Add( "effects/muzzleflash" .. math.random(1,4), tbl.Pos + ( VectorRand() * 2 ) ) + particle:SetVelocity( Vector(0,0,80) ) + particle:SetDieTime( math.Rand( 0.2, 0.4 ) + math.Rand( 0.3, 0.6 ) * tbl.Scale ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random(15,25) + ( math.random(25,50) * tbl.Scale ) ) + particle:SetEndSize( 0 ) + particle:SetRoll( math.random(-180,180) ) + particle:SetColor( 255, 200, 200 ) + particle:SetGravity( Vector( 0, 0, 400 + ( tbl.Scale * 100 ) ) ) + + if self.SmokeTime < CurTime() then + + self.SmokeTime = CurTime() + 0.02 + + local particle = self.Emitter:Add( "particles/smokey", tbl.Pos + ( VectorRand() * 2 ) + Vector(0,0,50) ) + particle:SetVelocity( Vector( 0, 0, 30 + tbl.Scale * 10 ) ) + particle:SetDieTime( math.Rand( 0.5, 1.0 ) + ( tbl.Scale * math.Rand( 2.5, 3.5 ) ) ) + particle:SetStartAlpha( 50 + tbl.Scale * 75 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random(10,20) ) + particle:SetEndSize( math.random(30,60) + ( math.random(40,80) * tbl.Scale ) ) + particle:SetRoll( 0 ) + particle:SetColor( 10, 10, 10 ) + particle:SetGravity( Vector( 0, 0, 30 ) ) + + end + + if self.LightTime < CurTime() then + + self.LightTime = CurTime() + 0.05 + + local dlight = DynamicLight( self.Entity:EntIndex() ) + + if dlight then + + dlight.Pos = self.Entity:GetPos() + dlight.r = 255 + dlight.g = 120 + dlight.b = 50 + dlight.Brightness = 4 + dlight.Decay = 2048 + dlight.size = 256 * math.Rand( 0.8, 1.2 ) + dlight.DieTime = CurTime() + 1 + + end + + end + +end + +function ENT:OnRemove() + + if self.Emitter then + + self.Emitter:Finish() + + end + +end + +function ENT:Draw() + +end + diff --git a/entities/entities/sent_fire/init.lua b/entities/entities/sent_fire/init.lua new file mode 100644 index 0000000..d643ada --- /dev/null +++ b/entities/entities/sent_fire/init.lua @@ -0,0 +1,74 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.BurnSound = Sound( "fire_large" ) +ENT.LifeTime = 10 +ENT.Explosives = { "sent_oxygen", "sent_propane_canister", "sent_propane_tank", "sent_fuel_diesel", "sent_fuel_gas" } + +function ENT:Initialize() + + self.Entity:SetMoveType( MOVETYPE_NONE ) + self.Entity:SetSolid( SOLID_NONE ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_DEBRIS_TRIGGER ) + self.Entity:SetTrigger( true ) + self.Entity:SetNotSolid( true ) + self.Entity:DrawShadow( false ) + + self.Entity:SetCollisionBounds( Vector( -60, -60, -60 ), Vector( 60, 60, 60 ) ) + self.Entity:PhysicsInitBox( Vector( -60, -60, -60 ), Vector( 60, 60, 60 ) ) + + self.DieTime = CurTime() + self.LifeTime + + self.Entity:EmitSound( self.BurnSound ) + +end + +function ENT:SetLifeTime( num ) + + self.LifeTime = num + +end + +function ENT:OnRemove() + + self.Entity:StopSound( self.BurnSound ) + +end + +function ENT:Think() + + if self.DieTime < CurTime() then + + self.Entity:Remove() + + end + +end + +function ENT:Touch( ent ) + + if not IsValid( self.Entity:GetOwner() ) then return end + + //if ent:IsPlayer() and ent:Team() == self.Entity:GetOwner():Team() then return end + + if table.HasValue( self.Explosives, ent:GetClass() ) then + + ent:SetOwner( self.Entity:GetOwner() ) + ent:Explode() + + end + + if not ent.NextBot and not ent:IsPlayer() then return end + + ent:DoIgnite( self.Entity:GetOwner() ) + +end + +function ENT:UpdateTransmitState() + + return TRANSMIT_ALWAYS + +end diff --git a/entities/entities/sent_fire/shared.lua b/entities/entities/sent_fire/shared.lua new file mode 100644 index 0000000..8e216e2 --- /dev/null +++ b/entities/entities/sent_fire/shared.lua @@ -0,0 +1,3 @@ +ENT.Type = "anim" +ENT.Base = "base_anim" + diff --git a/entities/entities/sent_flare/cl_init.lua b/entities/entities/sent_flare/cl_init.lua new file mode 100644 index 0000000..d6bf3a4 --- /dev/null +++ b/entities/entities/sent_flare/cl_init.lua @@ -0,0 +1,86 @@ +include('shared.lua') + +function ENT:Initialize() + + self.Emitter = ParticleEmitter( self.Entity:GetPos() ) + self.Smoke = 0 + +end + +function ENT:OnRemove() + + if self.Emitter then + + self.Emitter:Finish() + + end + +end + +function ENT:Think() + + if self.Entity:GetNWFloat( "BurnDelay", 9000 ) > CurTime() then return end + + if self.Smoke < CurTime() then + + self.Smoke = CurTime() + 0.2 + + local particle = self.Emitter:Add( "particles/smokey", self.Entity:GetPos() + self.Entity:GetRight() * 5 ) + particle:SetVelocity( VectorRand() * 5 + WindVector ) + particle:SetDieTime( math.Rand( 2.5, 4.5 ) ) + particle:SetStartAlpha( 100 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 2, 4 ) ) + particle:SetEndSize( math.random( 15, 30 ) ) + particle:SetGravity( Vector( 0, 0, 10 ) ) + + local col = math.random( 100, 150 ) + particle:SetColor( col + 50, col, col ) + + end + + local dlight = DynamicLight( self.Entity:EntIndex() ) + + if dlight then + + dlight.Pos = self.Entity:GetPos() + dlight.r = 255 + dlight.g = 50 + dlight.b = 50 + dlight.Brightness = 3 + dlight.Decay = 2048 + dlight.size = 512 * math.Rand( 1.50, 1.75 ) + dlight.DieTime = CurTime() + 1 + + end + + if not LocalPlayer():Alive() then return end + + local dist = LocalPlayer():GetPos():Distance( self.Entity:GetPos() ) + + if dist < 300 then + + local scale = math.Clamp( 1 - ( math.Clamp( dist, 1, 300 ) / 300 ), 0, 1 ) + + Sharpen = scale * 5 + ColorModify[ "$pp_colour_contrast" ] = 1 + ( scale * 0.6 ) + + end + +end + +local matFlare = Material( "effects/blueflare1" ) + +function ENT:Draw() + + self.Entity:DrawModel() + + if self.Entity:GetNWFloat( "BurnDelay", 9000 ) > CurTime() then return end + + local size = math.Rand( 5, 25 ) + + render.SetMaterial( matFlare ) + render.DrawSprite( self.Entity:GetPos() + self.Entity:GetRight() * 5, size, size, Color( 255, 50, 50, 255 ) ) + +end + diff --git a/entities/entities/sent_flare/init.lua b/entities/entities/sent_flare/init.lua new file mode 100644 index 0000000..7e36159 --- /dev/null +++ b/entities/entities/sent_flare/init.lua @@ -0,0 +1,78 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.Burn = Sound( "Weapon_FlareGun.Burn" ) +ENT.Explode = Sound( "weapons/flashbang/flashbang_explode1.wav" ) + +function ENT:Initialize() + + self.Entity:SetModel( Model( "models/props_c17/trappropeller_lever.mdl" ) ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + self.Entity:DrawShadow( false ) + + self.Entity:SetNWFloat( "BurnDelay", CurTime() + 3 ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + phys:SetDamping( 0, 10 ) + + end + + self.DieTime = CurTime() + 60 * 5 + + self.Entity:EmitSound( "Weapon_SMG1.Special1", 100, 80 ) + +end + +function ENT:Think() + + if self.Entity:GetNWFloat( "BurnDelay", 0 ) < CurTime() then + + if not self.Burning then + + self.Burning = true + self.Entity:EmitSound( self.Burn ) + self.Entity:EmitSound( self.Explode, 100, math.random(90,110) ) + + end + + end + + if self.DieTime < CurTime() then + + self.Entity:Remove() + + end + +end + +function ENT:OnRemove() + + self.Entity:StopSound( self.Burn ) + +end + +function ENT:OnTakeDamage( dmginfo ) + +end + +function ENT:PhysicsCollide( data, phys ) + +end + +function ENT:UpdateTransmitState() + + return TRANSMIT_ALWAYS + +end + diff --git a/entities/entities/sent_flare/shared.lua b/entities/entities/sent_flare/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_flare/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_fuel_diesel/cl_init.lua b/entities/entities/sent_fuel_diesel/cl_init.lua new file mode 100644 index 0000000..514bad0 --- /dev/null +++ b/entities/entities/sent_fuel_diesel/cl_init.lua @@ -0,0 +1,20 @@ +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:OnRemove() + +end + +function ENT:Think() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_fuel_diesel/init.lua b/entities/entities/sent_fuel_diesel/init.lua new file mode 100644 index 0000000..9340505 --- /dev/null +++ b/entities/entities/sent_fuel_diesel/init.lua @@ -0,0 +1,117 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.HitSound = Sound( "Metal_Box.ImpactHard" ) +ENT.DieSound = Sound( "ambient/fire/ignite.wav" ) +ENT.Model = Model( "models/props_junk/metalgascan.mdl" ) +ENT.Damage = 80 +ENT.Radius = 350 + +function ENT:Initialize() + + self.Entity:SetModel( self.Model ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + //self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + +end + +function ENT:SetSpeed( num ) + + self.Speed = num + +end + +function ENT:Think() + +end + +function ENT:Explode() + + if self.Exploded then return end + + self.Exploded = true + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "Explosion", ed, true, true ) + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,20) + trace.endpos = trace.start + Vector( 0, 0, -200 ) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.HitWorld then + + --[[local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetMagnitude( 0.8 ) + util.Effect( "smoke_crater", ed, true, true )]] + + util.Decal( "Scorch", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal ) + + end + + if IsValid( self.Entity:GetOwner() ) then + + util.BlastDamage( self.Entity, self.Entity:GetOwner(), self.Entity:GetPos(), self.Radius, self.Damage ) + + end + + local fire = ents.Create( "sent_fire" ) + fire:SetPos( self.Entity:GetPos() ) + fire:SetOwner( self.Entity:GetOwner() ) + fire:SetLifeTime( 10 ) + fire:Spawn() + + self.Entity:EmitSound( self.DieSound, 100, math.random(90,110) ) + self.Entity:Remove() + +end + +function ENT:Use( ply, caller ) + + ply:AddToInventory( self.Entity ) + +end + +function ENT:OnRemove() + +end + +function ENT:OnTakeDamage( dmginfo ) + + if dmginfo:IsBulletDamage() and IsValid( dmginfo:GetAttacker() ) and dmginfo:GetAttacker():IsPlayer() then + + self.Entity:SetOwner( dmginfo:GetAttacker() ) + self.Entity:Explode() + + end + +end + +function ENT:PhysicsCollide( data, phys ) + + if data.Speed > 50 and data.DeltaTime > 0.15 then + + self.Entity:EmitSound( self.HitSound ) + + end + +end + diff --git a/entities/entities/sent_fuel_diesel/shared.lua b/entities/entities/sent_fuel_diesel/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_fuel_diesel/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_fuel_gas/cl_init.lua b/entities/entities/sent_fuel_gas/cl_init.lua new file mode 100644 index 0000000..514bad0 --- /dev/null +++ b/entities/entities/sent_fuel_gas/cl_init.lua @@ -0,0 +1,20 @@ +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:OnRemove() + +end + +function ENT:Think() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_fuel_gas/init.lua b/entities/entities/sent_fuel_gas/init.lua new file mode 100644 index 0000000..6672661 --- /dev/null +++ b/entities/entities/sent_fuel_gas/init.lua @@ -0,0 +1,117 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.HitSound = Sound( "Metal_Box.ImpactHard" ) +ENT.DieSound = Sound( "ambient/fire/ignite.wav" ) +ENT.Model = Model( "models/props_junk/gascan001a.mdl" ) +ENT.Damage = 50 +ENT.Radius = 350 + +function ENT:Initialize() + + self.Entity:SetModel( self.Model ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + //self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + +end + +function ENT:SetSpeed( num ) + + self.Speed = num + +end + +function ENT:Think() + +end + +function ENT:Explode() + + if self.Exploded then return end + + self.Exploded = true + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "Explosion", ed, true, true ) + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,20) + trace.endpos = trace.start + Vector( 0, 0, -200 ) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.HitWorld then + + --[[local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetMagnitude( 0.8 ) + util.Effect( "smoke_crater", ed, true, true )]] + + util.Decal( "Scorch", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal ) + + end + + if IsValid( self.Entity:GetOwner() ) then + + util.BlastDamage( self.Entity, self.Entity:GetOwner(), self.Entity:GetPos(), self.Radius, self.Damage ) + + end + + local fire = ents.Create( "sent_fire" ) + fire:SetPos( self.Entity:GetPos() ) + fire:SetOwner( self.Entity:GetOwner() ) + fire:SetLifeTime( 12 ) + fire:Spawn() + + self.Entity:EmitSound( self.DieSound, 100, math.random(90,110) ) + self.Entity:Remove() + +end + +function ENT:Use( ply, caller ) + + ply:AddToInventory( self.Entity ) + +end + +function ENT:OnRemove() + +end + +function ENT:OnTakeDamage( dmginfo ) + + if dmginfo:IsBulletDamage() and IsValid( dmginfo:GetAttacker() ) and dmginfo:GetAttacker():IsPlayer() then + + self.Entity:SetOwner( dmginfo:GetAttacker() ) + self.Entity:Explode() + + end + +end + +function ENT:PhysicsCollide( data, phys ) + + if data.Speed > 50 and data.DeltaTime > 0.15 then + + self.Entity:EmitSound( self.HitSound ) + + end + +end + diff --git a/entities/entities/sent_fuel_gas/shared.lua b/entities/entities/sent_fuel_gas/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_fuel_gas/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_grenade/cl_init.lua b/entities/entities/sent_grenade/cl_init.lua new file mode 100644 index 0000000..514bad0 --- /dev/null +++ b/entities/entities/sent_grenade/cl_init.lua @@ -0,0 +1,20 @@ +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:OnRemove() + +end + +function ENT:Think() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_grenade/init.lua b/entities/entities/sent_grenade/init.lua new file mode 100644 index 0000000..3973d4f --- /dev/null +++ b/entities/entities/sent_grenade/init.lua @@ -0,0 +1,113 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.HitSound = Sound( "physics/metal/metal_grenade_impact_hard2.wav" ) +ENT.Damage = 250 +ENT.Radius = 300 +ENT.Speed = 3500 + +function ENT:Initialize() + + self.Entity:SetModel( Model( "models/weapons/w_eq_fraggrenade_thrown.mdl") ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + self.Entity:DrawShadow( false ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + phys:SetDamping( 0, 5 ) + phys:ApplyForceCenter( self.Entity:GetAngles():Forward() * self.Speed ) + + end + + self.Delay = CurTime() + 3.5 + +end + +function ENT:SetSpeed( num ) + + self.Speed = num + +end + +function ENT:Think() + + if self.Delay < CurTime() then + + self.Entity:Explode() + + end + +end + +function ENT:Explode() + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "Explosion", ed, true, true ) + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,20) + trace.endpos = trace.start + Vector( 0, 0, -200 ) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.HitWorld then + + local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetMagnitude( 0.8 ) + util.Effect( "smoke_crater", ed, true, true ) + + util.Decal( "Scorch", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal ) + + end + + if IsValid( self.Entity:GetOwner() ) and self.Entity:GetOwner():Team() == TEAM_ARMY then + + util.BlastDamage( self.Entity, self.Entity:GetOwner(), self.Entity:GetPos(), self.Radius, self.Damage ) + + end + + --[[for k,v in pairs( player.GetAll() ) do + + if v:Team() != self.Entity:GetOwner():Team() and v:GetPos():Distance( self.Entity:GetPos() ) < self.Radius then + + v:SetBleeding( true ) + + end + + end]] + + self.Entity:Remove() + +end + +function ENT:OnRemove() + +end + +function ENT:OnTakeDamage( dmginfo ) + +end + +function ENT:PhysicsCollide( data, phys ) + + if data.Speed > 50 and data.DeltaTime > 0.15 then + + self.Entity:EmitSound( self.HitSound, 50, math.random(90,110) ) + + end + +end + diff --git a/entities/entities/sent_grenade/shared.lua b/entities/entities/sent_grenade/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_grenade/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_grenade_incendiary/cl_init.lua b/entities/entities/sent_grenade_incendiary/cl_init.lua new file mode 100644 index 0000000..514bad0 --- /dev/null +++ b/entities/entities/sent_grenade_incendiary/cl_init.lua @@ -0,0 +1,20 @@ +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:OnRemove() + +end + +function ENT:Think() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_grenade_incendiary/init.lua b/entities/entities/sent_grenade_incendiary/init.lua new file mode 100644 index 0000000..906fe1f --- /dev/null +++ b/entities/entities/sent_grenade_incendiary/init.lua @@ -0,0 +1,116 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.HitSound = Sound( "physics/metal/metal_grenade_impact_hard2.wav" ) +ENT.DieSound = Sound( "ambient/fire/ignite.wav" ) +ENT.Damage = 30 +ENT.Radius = 200 +ENT.Speed = 3500 + +function ENT:Initialize() + + self.Entity:SetModel( Model( "models/weapons/w_eq_flashbang.mdl" ) ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + self.Entity:DrawShadow( false ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + phys:SetDamping( 0, 5 ) + phys:ApplyForceCenter( self.Entity:GetAngles():Forward() * self.Speed ) + + end + + self.Delay = CurTime() + 3.5 + +end + +function ENT:SetSpeed( num ) + + self.Speed = num + +end + +function ENT:Think() + + if self.Delay < CurTime() then + + self.Entity:Explode() + + end + +end + +function ENT:Explode() + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "Explosion", ed, true, true ) + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,20) + trace.endpos = trace.start + Vector( 0, 0, -200 ) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.HitWorld then + + util.Decal( "Scorch", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal ) + + end + + if IsValid( self.Entity:GetOwner() ) and self.Entity:GetOwner():Team() == TEAM_ARMY then + + util.BlastDamage( self.Entity, self.Entity:GetOwner(), self.Entity:GetPos(), self.Radius, self.Damage ) + + end + + local fire = ents.Create( "sent_fire" ) + fire:SetPos( self.Entity:GetPos() ) + fire:SetOwner( self.Entity:GetOwner() ) + fire:SetLifeTime( 8 ) + fire:Spawn() + + --[[for k,v in pairs( player.GetAll() ) do + + if v:Team() != self.Entity:GetOwner():Team() and v:GetPos():Distance( self.Entity:GetPos() ) < self.Radius then + + v:SetBleeding( true ) + + end + + end]] + + self.Entity:EmitSound( self.DieSound, 100, math.random(90,110) ) + self.Entity:Remove() + +end + +function ENT:OnRemove() + +end + +function ENT:OnTakeDamage( dmginfo ) + +end + +function ENT:PhysicsCollide( data, phys ) + + if data.Speed > 50 and data.DeltaTime > 0.15 then + + self.Entity:EmitSound( self.HitSound, 50, math.random(120,140) ) + + end + +end + diff --git a/entities/entities/sent_grenade_incendiary/shared.lua b/entities/entities/sent_grenade_incendiary/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_grenade_incendiary/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_heliflare/cl_init.lua b/entities/entities/sent_heliflare/cl_init.lua new file mode 100644 index 0000000..30e76c6 --- /dev/null +++ b/entities/entities/sent_heliflare/cl_init.lua @@ -0,0 +1,84 @@ +include('shared.lua') + +function ENT:Initialize() + + self.Emitter = ParticleEmitter( self.Entity:GetPos() ) + self.Smoke = 0 + +end + +function ENT:OnRemove() + + if self.Emitter then + + self.Emitter:Finish() + + end + +end + +function ENT:Think() + + if self.Entity:GetNWFloat( "BurnDelay", 9000 ) > CurTime() then return end + + if self.Smoke < CurTime() then + + self.Smoke = CurTime() + 0.2 + + local particle = self.Emitter:Add( "particles/smokey", self.Entity:GetPos() + self.Entity:GetRight() * 5 ) + particle:SetVelocity( VectorRand() * 8 + WindVector ) + particle:SetDieTime( math.Rand( 4.0, 8.0 ) ) + particle:SetStartAlpha( 100 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 1 ) + particle:SetEndSize( math.random( 50, 150 ) ) + particle:SetGravity( Vector( 0, 0, 25 ) + WindVector * 1.5 ) + + local col = math.random( 50, 100 ) + particle:SetColor( col + 150, col, col ) + + end + + local dlight = DynamicLight( self.Entity:EntIndex() ) + + if dlight then + + dlight.Pos = self.Entity:GetPos() + dlight.r = 255 + dlight.g = 50 + dlight.b = 50 + dlight.Brightness = 3 + dlight.Decay = 0 + dlight.size = 256 + dlight.DieTime = CurTime() + 0.1 + + end + + if not LocalPlayer():Alive() then return end + + local dist = LocalPlayer():GetPos():Distance( self.Entity:GetPos() ) + + if dist < 300 then + + local scale = math.Clamp( 1 - ( math.Clamp( dist, 1, 300 ) / 300 ), 0, 1 ) + + Sharpen = scale * 5 + ColorModify[ "$pp_colour_contrast" ] = 1 + ( scale * 0.6 ) + + end + +end + +local matFlare = Material( "sprites/flareglow" ) + +function ENT:Draw() + + self.Entity:DrawModel() + + if self.Entity:GetNWFloat( "BurnDelay", 9000 ) > CurTime() then return end + + render.SetMaterial( matFlare ) + render.DrawSprite( self.Entity:GetPos(), 170, 170, Color( 255, 50, 50, 255 ) ) + +end + diff --git a/entities/entities/sent_heliflare/init.lua b/entities/entities/sent_heliflare/init.lua new file mode 100644 index 0000000..914b5c1 --- /dev/null +++ b/entities/entities/sent_heliflare/init.lua @@ -0,0 +1,76 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.Rotor = Sound( "NPC_AttackHelicopter.RotorsLoud" ) +ENT.Explode = Sound( "weapons/flashbang/flashbang_explode1.wav" ) + +function ENT:Initialize() + + self.Entity:SetModel( Model( "models/props_c17/trappropeller_lever.mdl" ) ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + self.Entity:DrawShadow( false ) + + self.Entity:SetNWFloat( "BurnDelay", CurTime() + 3 ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + phys:SetDamping( 0, 10 ) + + end + + self.DieTime = CurTime() + 45 + +end + +function ENT:Think() + + if self.Entity:GetNWFloat( "BurnDelay", 0 ) < CurTime() then + + if not self.Burning then + + self.Burning = true + self.Entity:EmitSound( self.Rotor ) + self.Entity:EmitSound( self.Explode, 100, math.random(90,110) ) + + end + + end + + if self.DieTime < CurTime() then + + self.Entity:Remove() + + end + +end + +function ENT:OnRemove() + + self.Entity:StopSound( self.Rotor ) + +end + +function ENT:OnTakeDamage( dmginfo ) + +end + +function ENT:PhysicsCollide( data, phys ) + +end + +function ENT:UpdateTransmitState() + + return TRANSMIT_ALWAYS + +end + diff --git a/entities/entities/sent_heliflare/shared.lua b/entities/entities/sent_heliflare/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_heliflare/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_lootbag/cl_init.lua b/entities/entities/sent_lootbag/cl_init.lua new file mode 100644 index 0000000..5af3dc2 --- /dev/null +++ b/entities/entities/sent_lootbag/cl_init.lua @@ -0,0 +1,15 @@ + +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:Draw() + + if IsValid( self.Entity:GetNWEntity( "QuestOwner", nil ) ) and self.Entity:GetNWEntity( "QuestOwner", nil ) != LocalPlayer() then return end + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_lootbag/init.lua b/entities/entities/sent_lootbag/init.lua new file mode 100644 index 0000000..7a93b0a --- /dev/null +++ b/entities/entities/sent_lootbag/init.lua @@ -0,0 +1,149 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +function ENT:Initialize() + + self.Entity:SetModel( "models/props_junk/garbage_bag001a.mdl" ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + + self.LastUse = CurTime() + 1 + self.Cash = 0 + +end + +function ENT:SetCash( amt ) + + self.Cash = math.Clamp( amt, 0, 32000 ) + +end + +function ENT:GetCash() + + return self.Cash + +end + +function ENT:Think() + + if ( table.Count( self.Entity:GetItems() ) < 1 and self:GetCash() < 1 ) or ( self.DieTime and self.DieTime < CurTime() ) then + + self.Entity:Remove() + + end + +end + +function ENT:SetRemoval( num ) + + self.DieTime = CurTime() + num + +end + +--[[function ENT:OnExit( ply ) + + if ( self.LastUse or 0 ) > CurTime() then return end + if IsValid( self.Entity:GetNWEntity( "QuestOwner", nil ) ) and self.Entity:GetNWEntity( "QuestOwner", nil ) != ply then return end + + self.LastUse = CurTime() + 1.0 + + if IsValid( self.Entity:GetUser() ) then + + self.Entity:SetUser() + ply:ToggleStashMenu( self.Entity, false, "StashMenu" ) + + end + +end + +function ENT:OnUsed( ply ) + + if ( self.LastUse or 0 ) > CurTime() then return end + if IsValid( self.Entity:GetNWEntity( "QuestOwner", nil ) ) and self.Entity:GetNWEntity( "QuestOwner", nil ) != ply then return end + + self.LastUse = CurTime() + 1.0 + + if not IsValid( self.Entity:GetUser() ) then + + ply:SynchCash( self.Cash ) + + self.Entity:SetUser( ply ) + ply:ToggleStashMenu( self.Entity, true, "StashMenu" ) + + end + +end]] + +function ENT:Use( ply, caller ) + + if ply:Team() != TEAM_ARMY then return end + + if self.Removing then return end + + self.Removing = true + + ply:AddMultipleToInventory( self.Items ) + ply:AddCash( self:GetCash() ) + + self.Entity:Remove() + +end + +function ENT:GetItems() + + return self.Items or {} + +end + +function ENT:AddItem( id ) + + self.Items = self.Items or {} + + table.insert( self.Items, id ) + + //self.Entity:Synch() + +end + +function ENT:RemoveItem( id ) + + for k,v in pairs( self.Items ) do + + if v == id then + + //self.Entity:Synch() + + table.remove( self.Items, k ) + + return + + end + + end + +end + +function ENT:Synch() + + --[[if IsValid( self.Entity:GetUser() ) then + + self.Entity:GetUser():SynchStash( self.Entity ) + + end]] + +end + diff --git a/entities/entities/sent_lootbag/shared.lua b/entities/entities/sent_lootbag/shared.lua new file mode 100644 index 0000000..8e216e2 --- /dev/null +++ b/entities/entities/sent_lootbag/shared.lua @@ -0,0 +1,3 @@ +ENT.Type = "anim" +ENT.Base = "base_anim" + diff --git a/entities/entities/sent_oxygen/cl_init.lua b/entities/entities/sent_oxygen/cl_init.lua new file mode 100644 index 0000000..514bad0 --- /dev/null +++ b/entities/entities/sent_oxygen/cl_init.lua @@ -0,0 +1,20 @@ +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:OnRemove() + +end + +function ENT:Think() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_oxygen/init.lua b/entities/entities/sent_oxygen/init.lua new file mode 100644 index 0000000..550be32 --- /dev/null +++ b/entities/entities/sent_oxygen/init.lua @@ -0,0 +1,117 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.HitSound = Sound( "Metal_Box.ImpactHard" ) +ENT.Model = Model( "models/props_phx/misc/potato_launcher_explosive.mdl" ) +ENT.Damage = 150 +ENT.Radius = 350 +ENT.Speed = 3500 + +function ENT:Initialize() + + self.Entity:SetModel( self.Model ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + phys:ApplyForceCenter( self.Entity:GetAngles():Forward() * self.Speed ) + + end + +end + +function ENT:SetSpeed( num ) + + self.Speed = num + +end + +function ENT:Think() + +end + +function ENT:Explode() + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "Explosion", ed, true, true ) + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,20) + trace.endpos = trace.start + Vector( 0, 0, -200 ) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.HitWorld then + + local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetMagnitude( 0.8 ) + util.Effect( "smoke_crater", ed, true, true ) + + util.Decal( "Scorch", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal ) + + end + + if IsValid( self.Entity:GetOwner() ) then + + util.BlastDamage( self.Entity, self.Entity:GetOwner(), self.Entity:GetPos(), self.Radius, self.Damage ) + + end + + for k,v in pairs( player.GetAll() ) do + + if v:Team() != self.Entity:GetOwner():Team() and v:GetPos():Distance( self.Entity:GetPos() ) < self.Radius then + + v:SetBleeding( true ) + + end + + end + + self.Entity:Remove() + +end + +function ENT:Use( ply, caller ) + + ply:AddToInventory( self.Entity ) + +end + +function ENT:OnRemove() + +end + +function ENT:OnTakeDamage( dmginfo ) + + if dmginfo:IsBulletDamage() and IsValid( dmginfo:GetAttacker() ) and dmginfo:GetAttacker():IsPlayer() then + + self.Entity:SetOwner( dmginfo:GetAttacker() ) + self.Entity:Explode() + + end + +end + +function ENT:PhysicsCollide( data, phys ) + + if data.Speed > 50 and data.DeltaTime > 0.15 then + + self.Entity:EmitSound( self.HitSound, 100, 120 ) + + end + +end + diff --git a/entities/entities/sent_oxygen/shared.lua b/entities/entities/sent_oxygen/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_oxygen/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_propane_canister/cl_init.lua b/entities/entities/sent_propane_canister/cl_init.lua new file mode 100644 index 0000000..514bad0 --- /dev/null +++ b/entities/entities/sent_propane_canister/cl_init.lua @@ -0,0 +1,20 @@ +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:OnRemove() + +end + +function ENT:Think() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_propane_canister/init.lua b/entities/entities/sent_propane_canister/init.lua new file mode 100644 index 0000000..b36368f --- /dev/null +++ b/entities/entities/sent_propane_canister/init.lua @@ -0,0 +1,111 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.HitSound = Sound( "Canister.ImpactHard" ) +ENT.DieSound = Sound( "PropaneTank.Burst" ) +ENT.Model = Model( "models/props_junk/propane_tank001a.mdl" ) +ENT.Damage = 180 +ENT.Radius = 350 + +function ENT:Initialize() + + self.Entity:SetModel( self.Model ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + //self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + +end + +function ENT:SetSpeed( num ) + + self.Speed = num + +end + +function ENT:Think() + +end + +function ENT:Explode() + + if self.Exploded then return end + + self.Exploded = true + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "Explosion", ed, true, true ) + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,20) + trace.endpos = trace.start + Vector( 0, 0, -200 ) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.HitWorld then + + local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetMagnitude( 0.8 ) + util.Effect( "smoke_crater", ed, true, true ) + + util.Decal( "Scorch", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal ) + + end + + if IsValid( self.Entity:GetOwner() ) then + + util.BlastDamage( self.Entity, self.Entity:GetOwner(), self.Entity:GetPos(), self.Radius, self.Damage ) + + end + + self.Entity:EmitSound( self.DieSound, 100, math.random(90,110) ) + self.Entity:Remove() + +end + +function ENT:Use( ply, caller ) + + ply:AddToInventory( self.Entity ) + +end + +function ENT:OnRemove() + +end + +function ENT:OnTakeDamage( dmginfo ) + + if dmginfo:IsBulletDamage() and IsValid( dmginfo:GetAttacker() ) and dmginfo:GetAttacker():IsPlayer() then + + self.Entity:SetOwner( dmginfo:GetAttacker() ) + self.Entity:Explode() + + end + +end + +function ENT:PhysicsCollide( data, phys ) + + if data.Speed > 50 and data.DeltaTime > 0.15 then + + self.Entity:EmitSound( self.HitSound ) + + end + +end + diff --git a/entities/entities/sent_propane_canister/shared.lua b/entities/entities/sent_propane_canister/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_propane_canister/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_propane_tank/cl_init.lua b/entities/entities/sent_propane_tank/cl_init.lua new file mode 100644 index 0000000..514bad0 --- /dev/null +++ b/entities/entities/sent_propane_tank/cl_init.lua @@ -0,0 +1,20 @@ +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:OnRemove() + +end + +function ENT:Think() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_propane_tank/init.lua b/entities/entities/sent_propane_tank/init.lua new file mode 100644 index 0000000..caadbf5 --- /dev/null +++ b/entities/entities/sent_propane_tank/init.lua @@ -0,0 +1,111 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.HitSound = Sound( "Canister.ImpactHard" ) +ENT.DieSound = Sound( "PropaneTank.Burst" ) +ENT.Model = Model( "models/props_junk/propanecanister001a.mdl" ) +ENT.Damage = 180 +ENT.Radius = 350 + +function ENT:Initialize() + + self.Entity:SetModel( self.Model ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + //self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + +end + +function ENT:SetSpeed( num ) + + self.Speed = num + +end + +function ENT:Think() + +end + +function ENT:Explode() + + if self.Exploded then return end + + self.Exploded = true + + local ed = EffectData() + ed:SetOrigin( self.Entity:GetPos() ) + util.Effect( "Explosion", ed, true, true ) + + local trace = {} + trace.start = self.Entity:GetPos() + Vector(0,0,20) + trace.endpos = trace.start + Vector( 0, 0, -200 ) + trace.filter = self.Entity + + local tr = util.TraceLine( trace ) + + if tr.HitWorld then + + local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetMagnitude( 0.8 ) + util.Effect( "smoke_crater", ed, true, true ) + + util.Decal( "Scorch", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal ) + + end + + if IsValid( self.Entity:GetOwner() ) then + + util.BlastDamage( self.Entity, self.Entity:GetOwner(), self.Entity:GetPos(), self.Radius, self.Damage ) + + end + + self.Entity:EmitSound( self.DieSound, 100, math.random(90,110) ) + self.Entity:Remove() + +end + +function ENT:Use( ply, caller ) + + ply:AddToInventory( self.Entity ) + +end + +function ENT:OnRemove() + +end + +function ENT:OnTakeDamage( dmginfo ) + + if dmginfo:IsBulletDamage() and IsValid( dmginfo:GetAttacker() ) and dmginfo:GetAttacker():IsPlayer() then + + self.Entity:SetOwner( dmginfo:GetAttacker() ) + self.Entity:Explode() + + end + +end + +function ENT:PhysicsCollide( data, phys ) + + if data.Speed > 50 and data.DeltaTime > 0.15 then + + self.Entity:EmitSound( self.HitSound ) + + end + +end + diff --git a/entities/entities/sent_propane_tank/shared.lua b/entities/entities/sent_propane_tank/shared.lua new file mode 100644 index 0000000..8b0a8a2 --- /dev/null +++ b/entities/entities/sent_propane_tank/shared.lua @@ -0,0 +1,2 @@ +ENT.Type = "anim" +ENT.Base = "base_anim"
\ No newline at end of file diff --git a/entities/entities/sent_radiation/cl_init.lua b/entities/entities/sent_radiation/cl_init.lua new file mode 100644 index 0000000..e07f410 --- /dev/null +++ b/entities/entities/sent_radiation/cl_init.lua @@ -0,0 +1,52 @@ + +include('shared.lua') + +function ENT:Initialize() + + self.Emitter = ParticleEmitter( self.Entity:GetPos() ) + self.DieTime = CurTime() + 30 + self.LightTime = 0 + +end + +function ENT:Think() + + self.Scale = ( self.DieTime - CurTime() ) / 30 + + if self.LightTime < CurTime() then + + self.LightTime = CurTime() + 0.1 + + local dlight = DynamicLight( self.Entity:EntIndex() ) + + if dlight then + + dlight.Pos = self.Entity:GetPos() + dlight.r = 150 + dlight.g = 255 + dlight.b = 50 + dlight.Brightness = 2 + dlight.Decay = 0 + dlight.size = self.Scale * self.Entity:GetNWInt( "Distance", 300 ) + dlight.DieTime = CurTime() + 1 + + end + + end + +end + +function ENT:OnRemove() + + if self.Emitter then + + self.Emitter:Finish() + + end + +end + +function ENT:Draw() + +end + diff --git a/entities/entities/sent_radiation/init.lua b/entities/entities/sent_radiation/init.lua new file mode 100644 index 0000000..52eabb4 --- /dev/null +++ b/entities/entities/sent_radiation/init.lua @@ -0,0 +1,90 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.Scale = 1 +ENT.Distance = 300 + +function ENT:Initialize() + + self.Entity:SetMoveType( MOVETYPE_NONE ) + self.Entity:SetSolid( SOLID_NONE ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_DEBRIS_TRIGGER ) + self.Entity:SetNotSolid( true ) + self.Entity:DrawShadow( false ) + + self.Entity:SetCollisionBounds( Vector( -60, -60, -60 ), Vector( 60, 60, 60 ) ) + self.Entity:PhysicsInitBox( Vector( -60, -60, -60 ), Vector( 60, 60, 60 ) ) + + self.Entity:SetNWInt( "Distance", self.Distance ) + + self.DieTime = CurTime() + 30 + +end + +function ENT:SetDistance( num ) + + self.Distance = num + +end + +function ENT:SetLifeTime( num ) + + self.LifeTime = num + +end + +function ENT:OnRemove() + +end + +function ENT:Think() + + if self.DieTime < CurTime() then + + self.Entity:Remove() + + end + + self.Scale = ( self.DieTime - CurTime() ) / 30 + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + local dist = v:GetPos():Distance( self.Entity:GetPos() ) + + if dist < ( self.Distance * self.Scale ) + 100 then + + if dist < ( self.Distance * self.Scale ) then + + if ( v.RadAddTime or 0 ) < CurTime() then + + v.RadAddTime = CurTime() + 8 + v:AddRadiation( 1 ) + + end + + end + + if ( v.NextRadSound or 0 ) < CurTime() then + + local scale = math.Clamp( ( ( self.Distance * self.Scale ) + 100 - dist ) / ( ( self.Distance * self.Scale ) ), 0.1, 1.0 ) + + v.NextRadSound = CurTime() + 1 - scale + v:EmitSound( table.Random( GAMEMODE.Geiger ), 100, math.random( 80, 90 ) + scale * 20 ) + v:NoticeOnce( "A radioactive deposit is nearby", GAMEMODE.Colors.Blue ) + + end + + end + + end + +end + +function ENT:UpdateTransmitState() + + return TRANSMIT_ALWAYS + +end diff --git a/entities/entities/sent_radiation/shared.lua b/entities/entities/sent_radiation/shared.lua new file mode 100644 index 0000000..8e216e2 --- /dev/null +++ b/entities/entities/sent_radiation/shared.lua @@ -0,0 +1,3 @@ +ENT.Type = "anim" +ENT.Base = "base_anim" + diff --git a/entities/entities/sent_supplycrate/cl_init.lua b/entities/entities/sent_supplycrate/cl_init.lua new file mode 100644 index 0000000..f1cad0f --- /dev/null +++ b/entities/entities/sent_supplycrate/cl_init.lua @@ -0,0 +1,13 @@ + +include('shared.lua') + +function ENT:Initialize() + +end + +function ENT:Draw() + + self.Entity:DrawModel() + +end + diff --git a/entities/entities/sent_supplycrate/init.lua b/entities/entities/sent_supplycrate/init.lua new file mode 100644 index 0000000..932ca4e --- /dev/null +++ b/entities/entities/sent_supplycrate/init.lua @@ -0,0 +1,79 @@ + +AddCSLuaFile( "cl_init.lua" ) +AddCSLuaFile( "shared.lua" ) +include( 'shared.lua' ) + +ENT.Bang = Sound( "Wood.ImpactHard" ) +ENT.Open = Sound( "Wood.Strain" ) +ENT.Model = Model( "models/Items/item_item_crate.mdl" ) + +function ENT:Initialize() + + self.Entity:SetModel( self.Model ) + + self.Entity:PhysicsInit( SOLID_VPHYSICS ) + self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) + self.Entity:SetSolid( SOLID_VPHYSICS ) + + self.Entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + local phys = self.Entity:GetPhysicsObject() + + if IsValid( phys ) then + + phys:Wake() + + end + + self.Entity:SetColor( Color( 255, 200, 150, 255 ) ) + + self.Removing = false + self.Contents = { 1 } + +end + +function ENT:Think() + + if IsValid( self.User ) and self.User:Alive() and self.User:Team() == TEAM_ARMY then return end + + self.Entity:SetColor( Color( 255, 255, 150, 255 ) ) + +end + +function ENT:SetContents( tbl ) + + self.Contents = tbl + +end + +function ENT:SetUser( ply ) + + self.User = ply + +end + +function ENT:Use( ply, caller ) + + if IsValid( self.User ) and self.User:Alive() and self.User:Team() == TEAM_ARMY and ply != self.User then return end + + if ply:Team() != TEAM_ARMY then return end + + if self.Removing then return end + + ply:AddMultipleToInventory( self.Contents ) + + self.Entity:EmitSound( self.Open ) + self.Entity:Remove() + +end + +function ENT:PhysicsCollide( data, phys ) + + if data.Speed > 50 and data.DeltaTime > 0.15 then + + self.Entity:EmitSound( self.Bang ) + + end + +end + diff --git a/entities/entities/sent_supplycrate/shared.lua b/entities/entities/sent_supplycrate/shared.lua new file mode 100644 index 0000000..8e216e2 --- /dev/null +++ b/entities/entities/sent_supplycrate/shared.lua @@ -0,0 +1,3 @@ +ENT.Type = "anim" +ENT.Base = "base_anim" + diff --git a/entities/weapons/rad_ak47/shared.lua b/entities/weapons/rad_ak47/shared.lua new file mode 100644 index 0000000..36d2799 --- /dev/null +++ b/entities/weapons/rad_ak47/shared.lua @@ -0,0 +1,37 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.PrintName = "AK-47" + SWEP.IconLetter = "b" + SWEP.Slot = 4 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "ar2" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_rif_ak47.mdl" +SWEP.WorldModel = "models/weapons/w_rif_ak47.mdl" + +SWEP.SprintPos = Vector (-1.3057, -4.167, 0.3971) +SWEP.SprintAng = Vector (-9.8658, -38.0733, 13.8555) + +SWEP.IsSniper = false +SWEP.AmmoType = "Rifle" + +SWEP.Primary.Sound = Sound( "Weapon_AK47.Single" ) +SWEP.Primary.Recoil = 6.5 +SWEP.Primary.Damage = 55 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.035 +SWEP.Primary.Delay = 0.100 + +SWEP.Primary.ClipSize = 30 +SWEP.Primary.Automatic = true diff --git a/entities/weapons/rad_awp/shared.lua b/entities/weapons/rad_awp/shared.lua new file mode 100644 index 0000000..f20fd07 --- /dev/null +++ b/entities/weapons/rad_awp/shared.lua @@ -0,0 +1,46 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "AWP" + SWEP.IconLetter = "r" + SWEP.Slot = 2 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "ar2" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_snip_awp.mdl" +SWEP.WorldModel = "models/weapons/w_snip_awp.mdl" + +SWEP.SprintPos = Vector(-2.4134, -2.7816, 0.4499) +SWEP.SprintAng = Vector(-4.2748, -48.8937, -0.0962) + +SWEP.ZoomModes = { 0, 35, 5 } +SWEP.ZoomSpeeds = { 0.25, 0.30, 0.30 } + +SWEP.IsSniper = true +SWEP.AmmoType = "Sniper" + +SWEP.Primary.Sound = Sound( "Weapon_AWP.Single" ) +SWEP.Primary.Recoil = 17.5 +SWEP.Primary.Damage = 175 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.001 +SWEP.Primary.SniperCone = 0.015 +SWEP.Primary.Delay = 1.500 + +SWEP.Primary.ClipSize = 10 +SWEP.Primary.Automatic = false + +SWEP.MinShellDelay = 0.8 +SWEP.MaxShellDelay = 1.0 diff --git a/entities/weapons/rad_axe/shared.lua b/entities/weapons/rad_axe/shared.lua new file mode 100644 index 0000000..2411957 --- /dev/null +++ b/entities/weapons/rad_axe/shared.lua @@ -0,0 +1,213 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFOV = 80 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Axe" + SWEP.IconLetter = "j" + SWEP.Slot = 1 + SWEP.Slotpos = 0 + +end + +SWEP.HoldType = "melee2" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_axe/v_axe.mdl" +SWEP.WorldModel = "models/weapons/w_axe.mdl" + +SWEP.HoldPos = Vector (1.1747, -16.6759, -5.7913) +SWEP.HoldAng = Vector (23.7548, -8.0105, -5.154) + +SWEP.IsSniper = false +SWEP.AmmoType = "Knife" + +SWEP.Primary.Hit = Sound( "weapons/crowbar/crowbar_impact2.wav" ) +SWEP.Primary.Sound = Sound( "weapons/iceaxe/iceaxe_swing1.wav" ) +SWEP.Primary.Recoil = 9.5 +SWEP.Primary.Damage = 100 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Delay = 1.300 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = true + +function SWEP:GetViewModelPosition( pos, ang ) + + return self.Weapon:MoveViewModelTo( self.HoldPos, self.HoldAng, pos, ang, 1 ) + +end + +function SWEP:SecondaryAttack() + +end + +function SWEP:PrimaryAttack() + + if SERVER then + + self.Owner:AddStamina( -4 ) + + end + + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:MeleeTrace( self.Primary.Damage ) + +end + +function SWEP:Think() + + if self.Owner:GetVelocity():Length() > 0 then + + if self.Owner:KeyDown( IN_SPEED ) then + + self.LastRunFrame = CurTime() + 0.3 + + end + + if self.Weapon:GetZoomMode() != 1 then + + self.Weapon:UnZoom() + + end + + end + + if self.MoveTime and self.MoveTime < CurTime() and SERVER then + + self.MoveTime = nil + self.Weapon:SetZoomMode( self.Weapon:GetZoomMode() + 1 ) + self.Owner:DrawViewModel( false ) + + end + +end + +function SWEP:MeleeTrace( dmg ) + + self.Weapon:SendWeaponAnim( ACT_VM_MISSCENTER ) + + if CLIENT then return end + + local pos = self.Owner:GetShootPos() + local aim = self.Owner:GetAimVector() * 64 + + local line = {} + line.start = pos + line.endpos = pos + aim + line.filter = self.Owner + + local linetr = util.TraceLine( line ) + + local tr = {} + tr.start = pos + self.Owner:GetAimVector() * -5 + tr.endpos = pos + aim + tr.filter = self.Owner + tr.mask = MASK_SHOT_HULL + tr.mins = Vector(-20,-20,-20) + tr.maxs = Vector(20,20,20) + + local trace = util.TraceHull( tr ) + local ent = trace.Entity + local ent2 = linetr.Entity + + if not IsValid( ent ) and IsValid( ent2 ) then + + ent = ent2 + + end + + if not IsValid( ent ) then + + self.Owner:EmitSound( self.Primary.Sound, 100, math.random(60,80) ) + return + + elseif not ent:IsWorld() then + + self.Weapon:SendWeaponAnim( ACT_VM_HITCENTER ) + + if ent:IsPlayer() then + + local snd = table.Random( GAMEMODE.AxeHit ) + ent:EmitSound( snd, 100, math.random(90,110) ) + + if ent:Team() != self.Owner:Team() then + + ent:TakeDamage( dmg, self.Owner, self.Weapon ) + + self.Owner:DrawBlood() + + local ed = EffectData() + ed:SetOrigin( trace.HitPos ) + util.Effect( "BloodImpact", ed, true, true ) + + end + + elseif string.find( ent:GetClass(), "npc" ) then + + ent:SetHeadshotter( self.Owner, true ) + ent:TakeDamage( dmg, self.Owner, self.Weapon ) + + local snd = table.Random( GAMEMODE.AxeHit ) + ent:EmitSound( snd, 100, math.random(90,110) ) + + self.Owner:DrawBlood() + + local ed = EffectData() + ed:SetOrigin( trace.HitPos ) + util.Effect( "BloodImpact", ed, true, true ) + + elseif !ent:IsPlayer() then + + if string.find( ent:GetClass(), "breakable" ) then + + ent:TakeDamage( 50, self.Owner, self.Weapon ) + + if ent:GetClass() == "func_breakable_surf" then + + ent:Fire( "shatter", "1 1 1", 0 ) + + end + + end + + ent:EmitSound( self.Primary.Hit, 100, math.random(90,110) ) + + local phys = ent:GetPhysicsObject() + + if IsValid( phys ) then + + if ent.IsWooden then + + ent:Fire( "break", 0, 0 ) + + else + + ent:SetPhysicsAttacker( self.Owner ) + ent:TakeDamage( 10, self.Owner, self.Weapon ) + + phys:Wake() + phys:ApplyForceCenter( self.Owner:GetAimVector() * phys:GetMass() * 200 ) + + end + + end + + end + + end + +end + +function SWEP:DrawHUD() + +end diff --git a/entities/weapons/rad_base/shared.lua b/entities/weapons/rad_base/shared.lua new file mode 100644 index 0000000..63ef374 --- /dev/null +++ b/entities/weapons/rad_base/shared.lua @@ -0,0 +1,958 @@ +if SERVER then + + AddCSLuaFile( "shared.lua" ) + + SWEP.Weight = 1 + SWEP.AutoSwitchTo = false + SWEP.AutoSwitchFrom = false + +end + +if CLIENT then + + SWEP.DrawAmmo = true + SWEP.DrawCrosshair = false + SWEP.CSMuzzleFlashes = true + + SWEP.ViewModelFOV = 75 + SWEP.ViewModelFlip = true + + SWEP.PrintName = "BASE WEAPON" + SWEP.IconLetter = "c" + SWEP.Slot = 0 + SWEP.Slotpos = 0 + + SWEP.IconFont = "CSSelectIcons" + + function SWEP:DrawWeaponSelection( x, y, wide, tall, alpha ) + //draw.SimpleText( self.IconLetter, self.IconFont, x + wide/2, y + tall/2.5, Color( 15, 20, 200, 255 ), TEXT_ALIGN_CENTER ) + end + +end + +SWEP.HoldType = "pistol" + +SWEP.ViewModel = "models/weapons/v_pistol.mdl" +SWEP.WorldModel = "models/weapons/w_pistol.mdl" + +SWEP.SprintPos = Vector(0,0,0) +SWEP.SprintAng = Vector(0,0,0) + +SWEP.ZoomModes = { 0, 50, 10 } +SWEP.ZoomSpeeds = { 5, 5, 5 } + +SWEP.IsSniper = false +SWEP.AmmoType = "SMG" + +SWEP.Primary.Empty = Sound( "weapons/clipempty_rifle.wav" ) +SWEP.Primary.Sound = Sound( "Weapon_USP.Single" ) +SWEP.Primary.Recoil = 3.5 +SWEP.Primary.Damage = 10 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.025 +SWEP.Primary.SniperCone = 0.025 +SWEP.Primary.Delay = 0.150 + +SWEP.Primary.Ammo = "Pistol" +SWEP.Primary.ClipSize = 50 +SWEP.Primary.DefaultClip = 200 +SWEP.Primary.Automatic = false + +SWEP.Secondary.Sound = Sound( "weapons/zoom.wav" ) +SWEP.Secondary.Laser = Sound( "weapons/ar2/ar2_empty.wav" ) +SWEP.Secondary.Delay = 0.5 + +SWEP.Secondary.Ammo = "none" +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false + +SWEP.LaserOffset = Vector(0,0,0) +SWEP.HolsterMode = false +SWEP.HolsterTime = 0 +SWEP.LastRunFrame = 0 + +SWEP.MinShellDelay = 0.3 +SWEP.MaxShellDelay = 0.6 + +SWEP.FalloffDistances = {} +SWEP.FalloffDistances[ "Sniper" ] = { Range = 3500, Falloff = 8000 } +SWEP.FalloffDistances[ "Rifle" ] = { Range = 2000, Falloff = 2000 } +SWEP.FalloffDistances[ "SMG" ] = { Range = 1500, Falloff = 1500 } +SWEP.FalloffDistances[ "Pistol" ] = { Range = 1000, Falloff = 500 } +SWEP.FalloffDistances[ "Buckshot" ] = { Range = 300, Falloff = 500 } + +SWEP.UseShellSounds = true +SWEP.ShellSounds = { "player/pl_shell1.wav", "player/pl_shell2.wav", "player/pl_shell3.wav" } +SWEP.BuckshotShellSounds = { "weapons/fx/tink/shotgun_shell1.wav", "weapons/fx/tink/shotgun_shell2.wav", "weapons/fx/tink/shotgun_shell3.wav" } + +SWEP.Pitches = {} +SWEP.Pitches[ "Pistol" ] = 100 +SWEP.Pitches[ "SMG" ] = 90 +SWEP.Pitches[ "Rifle" ] = 80 +SWEP.Pitches[ "Sniper" ] = 70 +SWEP.Pitches[ "Buckshot" ] = 100 + +function SWEP:GetViewModelPosition( pos, ang ) + + local newpos = nil + local newang = nil + local movetime = 0.25 + local duration = 0//self.Weapon:GetNWInt( "ViewTime", 0 ) + + local pang = self.Owner:EyeAngles() + local vel = self.Owner:GetVelocity() + + //if not newpos or not newang then + + // newpos = pos + // newang = ang + + //end + + local mul = 0 + + self.SwayScale = 1.0 + self.BobScale = 1.0 + + if ( self.Owner:KeyDown( IN_SPEED ) and self.Owner:GetVelocity():Length() > 0 ) or GAMEMODE:ElementsVisible() or self.HolsterMode then + + self.SwayScale = 1.25 + self.BobScale = 1.25 + + if not self.SprintStart then + + self.SprintStart = CurTime() + + end + + mul = math.Clamp( ( CurTime() - self.SprintStart ) / movetime, 0, 1 ) + mul = -( mul - 1 ) ^ 2 + 1 + + newang = self.SprintAng + newpos = self.SprintPos + + else + + if self.SprintStart then + + self.SprintEnd = CurTime() + self.SprintStart = nil + + end + + if self.SprintEnd then + + mul = math.Clamp( ( CurTime() - self.SprintEnd ) / movetime, 0, 1 ) + mul = ( mul - 1 ) ^ 2 + + newang = self.SprintAng + newpos = self.SprintPos + + if mul == 0 then + + self.SprintEnd = nil + + end + + else + + mul = self:GetMoveScale( movetime, duration, mul ) + + end + end + + return self:MoveViewModelTo( newpos, newang, pos, ang, mul ) + +end + +function SWEP:GetMoveScale( movetime, duration, mul ) + + mul = 1 + + if CurTime() - movetime < duration then + + mul = math.Clamp( ( CurTime() - duration ) / movetime, 0, 1 ) + + end + + if self.Weapon:GetNWBool( "ReverseAnim", false ) then + + return -( mul - 1 ) ^ 3 + + end + + return ( mul - 1 ) ^ 3 + 1 + +end + +function SWEP:AngApproach( newang, ang, mul ) + + if not newang then return ang end + + ang:RotateAroundAxis( ang:Right(), newang.x * mul ) + ang:RotateAroundAxis( ang:Up(), newang.y * mul ) + ang:RotateAroundAxis( ang:Forward(), newang.z * mul ) + + return ang + +end + +function SWEP:PosApproach( newpos, pos, ang, mul ) + + local right = ang:Right() + local up = ang:Up() + local forward = ang:Forward() + + if not newpos then return pos end + + pos = pos + newpos.x * right * mul + pos = pos + newpos.y * forward * mul + pos = pos + newpos.z * up * mul + + return pos + +end + +function SWEP:MoveViewModelTo( newpos, newang, pos, ang, mul ) + + ang = self:AngApproach( newang, ang, mul ) + pos = self:PosApproach( newpos, pos, ang, mul ) + + return pos, ang + +end + +function SWEP:Initialize() + + self.Weapon:SetWeaponHoldType( self.HoldType ) + +end + +function SWEP:Deploy() + + if SERVER then + + self.Weapon:SetZoomMode( 1 ) + self.Owner:DrawViewModel( true ) + + end + + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + + return true + +end + +function SWEP:Holster() + + return true + +end + +function SWEP:Think() + + self.Weapon:ReloadThink() + + if self.Owner:GetVelocity():Length() > 0 and self.Owner:KeyDown( IN_SPEED ) then + + self.LastRunFrame = CurTime() + 0.3 + + self.Weapon:UnZoom() + + end + +end + +function SWEP:SetZoomMode( num ) + + if num > #self.ZoomModes then + + num = 1 + + self.Weapon:UnZoom() + + end + + self.Weapon:SetNWInt( "Mode", num ) + + if self.Owner:GetFOV() != self.ZoomModes[num] then + + self.Owner:SetFOV( self.ZoomModes[num], self.ZoomSpeeds[num] ) + + end + +end + +function SWEP:GetZoomMode() + + return self.Weapon:GetNWInt( "Mode", 1 ) + +end + +function SWEP:UnZoom() + + if CLIENT then return end + + self.Weapon:SetZoomMode( 1 ) + self.Weapon:SetNWBool( "ReverseAnim", true ) + + self.Owner:DrawViewModel( true ) + +end + +function SWEP:Reload() + + if self.Weapon:Clip1() == self.Primary.ClipSize or self.Weapon:Clip1() > self.Owner:GetNWInt( "Ammo" .. self.AmmoType, 0 ) or self.HolsterMode or self.ReloadTime then return end + + if self.Owner:GetNWInt( "Ammo" .. self.AmmoType, 0 ) < 1 then + + self.Weapon:SetClip1( self.Primary.ClipSize ) + + return + + end + + if self.Weapon:GetZoomMode() != 1 then + + self.Weapon:UnZoom() + + end + + self.Weapon:DoReload() + +end + +function SWEP:StartWeaponAnim( anim ) + + if IsValid( self.Owner ) then + + local vm = self.Owner:GetViewModel() + + local idealSequence = self:SelectWeightedSequence( anim ) + local nextSequence = self:FindTransitionSequence( self.Weapon:GetSequence(), idealSequence ) + + //vm:RemoveEffects( EF_NODRAW ) + //vm:SetPlaybackRate( pbr ) + + if nextSequence > 0 then + + vm:SendViewModelMatchingSequence( nextSequence ) + + else + + vm:SendViewModelMatchingSequence( idealSequence ) + + end + + return vm:SequenceDuration( vm:GetSequence() ) + + end + +end + +function SWEP:DoReload() + + local time = self.Weapon:StartWeaponAnim( ACT_VM_RELOAD ) + + self.Weapon:SetNextPrimaryFire( CurTime() + time + 0.080 ) + + self.ReloadTime = CurTime() + time + +end + +function SWEP:ReloadThink() + + if self.ReloadTime and self.ReloadTime <= CurTime() then + + self.ReloadTime = nil + self.Weapon:SetClip1( self.Primary.ClipSize ) + + end + +end + +function SWEP:CanSecondaryAttack() + + if self.HolsterMode or self.Owner:KeyDown( IN_SPEED ) or self.LastRunFrame > CurTime() then return false end + + if self.Weapon:Clip1() <= 0 and self.IsSniper then + + if self.Weapon:GetZoomMode() != 1 then + + self.Weapon:UnZoom() + + end + + return false + + end + + return true + +end + +function SWEP:CanPrimaryAttack() + + if self.HolsterMode or self.ReloadTime or self.LastRunFrame > CurTime() then return false end + + if self.Owner:GetNWInt( "Ammo" .. self.AmmoType, 0 ) < 1 then + + self.Weapon:EmitSound( self.Primary.Empty ) + + return false + + end + + if self.Weapon:Clip1() <= 0 then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + self.Weapon:DoReload() + + if self.Weapon:GetZoomMode() != 1 then + + self.Weapon:UnZoom() + + end + + return false + + end + + return true + +end + +function SWEP:ShootEffects() + + if IsFirstTimePredicted() then + + self.Owner:ViewPunch( Angle( math.Rand( -0.2, -0.1 ) * self.Primary.Recoil, math.Rand( -0.05, 0.05 ) * self.Primary.Recoil, 0 ) ) + + end + + self.Owner:MuzzleFlash() + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + + if CLIENT then return end + + if self.UseShellSounds then + + local pitch = self.Pitches[ self.AmmoType ] + math.random( -3, 3 ) + local tbl = self.ShellSounds + local pos = self.Owner:GetPos() + + if self.AmmoType == "Buckshot" then + + tbl = self.BuckshotShellSounds + + end + + timer.Simple( math.Rand( self.MinShellDelay, self.MaxShellDelay ), function() sound.Play( table.Random( tbl ), pos, 50, pitch ) end ) + + end + +end + +function SWEP:PrimaryAttack() + + if not self.Weapon:CanPrimaryAttack() then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.25 ) + + return + + end + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) ) + self.Weapon:SetClip1( self.Weapon:Clip1() - self.Primary.NumShots ) + self.Weapon:ShootEffects() + + if self.IsSniper and self.Weapon:GetZoomMode() == 1 then + + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.SniperCone, 1 ) + + else + + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.Cone, self.Weapon:GetZoomMode() ) + + end + + if self.Weapon:GetZoomMode() > 1 then + + self.Weapon:UnZoom() + + end + + if SERVER then + + self.Owner:AddAmmo( self.AmmoType, self.Primary.NumShots * -1 ) + + end + +end + +function SWEP:SecondaryAttack() + + if not self.Weapon:CanSecondaryAttack() then return end + + self.Weapon:SetNextSecondaryFire( CurTime() + 0.25 ) + + if not self.IsSniper then + + self.Weapon:ToggleLaser() + + return + + end + + if SERVER then + + if self.Weapon:GetZoomMode() == 1 then + + self.Owner:DrawViewModel( false ) + + end + + self.Weapon:SetZoomMode( self.Weapon:GetZoomMode() + 1 ) + + end + + self.Weapon:EmitSound( self.Secondary.Sound ) + +end + +function SWEP:ToggleLaser() + + self.Weapon:EmitSound( self.Secondary.Laser ) + self.Weapon:SetNWBool( "Laser", !self.Weapon:GetNWBool( "Laser", false ) ) + +end + +function SWEP:AdjustMouseSensitivity() + + local num = self.Weapon:GetNWInt( "Mode", 1 ) + local scale = ( self.ZoomModes[ num ] or 0 ) / 100 + + if scale == 0 then + + return nil + + end + + return scale + +end + +function SWEP:GetDamageFalloffScale( distance ) + + local scale = 1 + + if distance > self.FalloffDistances[ self.AmmoType ].Range then + + scale = ( 1 - ( ( distance - self.FalloffDistances[ self.AmmoType ].Range ) / self.FalloffDistances[ self.AmmoType ].Falloff ) ) + + end + + return math.Clamp( scale, 0.1, 1.0 ) + +end + +function SWEP:ShootBullets( damage, numbullets, aimcone, zoommode ) + + if SERVER then + + self.Owner:AddStat( "Bullets", numbullets ) + + end + + local scale = aimcone + + if self.Owner:KeyDown( IN_FORWARD ) or self.Owner:KeyDown( IN_BACK ) or self.Owner:KeyDown( IN_MOVELEFT ) or self.Owner:KeyDown( IN_MOVERIGHT ) then + + scale = aimcone * 1.75 + + elseif self.Owner:KeyDown( IN_DUCK ) or self.Owner:KeyDown( IN_WALK ) then + + scale = math.Clamp( aimcone / 1.75, 0, 10 ) + + end + + local bullet = {} + bullet.Num = numbullets + bullet.Src = self.Owner:GetShootPos() + bullet.Dir = self.Owner:GetAimVector() + bullet.Spread = Vector( scale, scale, 0 ) + bullet.Tracer = 0 + bullet.Force = damage * 2 + bullet.Damage = damage + bullet.AmmoType = "Pistol" + + //if self.IsSniper and self.AmmoType == "Sniper" then + + //bullet.TracerName = "sniper_tracer" + + //end + + bullet.Callback = function( attacker, tr, dmginfo ) + + dmginfo:ScaleDamage( self:GetDamageFalloffScale( tr.HitPos:Distance( self.Owner:GetShootPos() ) ) ) + + if tr.Entity.NextBot then + + tr.Entity:OnLimbHit( tr.HitGroup, dmginfo ) + + end + + if ( IsValid( tr.Entity ) and tr.Entity:IsPlayer() ) or math.random(1,5) != 1 then return end + + self.Weapon:BulletPenetration( attacker, tr, dmginfo, 0 ) + + end + + self.Owner:LagCompensation( true ) + + self.Owner:FireBullets( bullet ) + + self.Owner:LagCompensation( false ) + +end + +function SWEP:GetPenetrationDistance( mat_type ) + + if ( mat_type == MAT_PLASTIC || mat_type == MAT_WOOD || mat_type == MAT_ALIENFLESH || mat_type == MAT_FLESH || mat_type == MAT_GLASS ) then + + return 64 + + end + + return 32 + +end + +function SWEP:GetPenetrationDamageLoss( mat_type, distance, damage ) + + if ( mat_type == MAT_GLASS || mat_type == MAT_ALIENFLESH || mat_type == MAT_FLESH ) then + return damage + elseif ( mat_type == MAT_PLASTIC || mat_type == MAT_WOOD ) then + return damage - distance + elseif( mat_type == MAT_TILE || mat_type == MAT_SAND || mat_type == MAT_DIRT ) then + return damage - ( distance * 1.2 ) + end + + return damage - ( distance * 1.8 ) + +end + +--[[function SWEP:BulletPenetration( attacker, tr, dmginfo, bounce ) + + if ( !self or !IsValid( self.Weapon ) ) then return end + + if IsValid( tr.Entity ) and string.find( tr.Entity:GetClass(), "npc" ) then + + local effectdata = EffectData() + effectdata:SetOrigin( tr.HitPos ) + util.Effect( "BloodImpact", effectdata ) + + end + + // Don't go through more than 3 times + if ( bounce > 3 ) then return false end + + // Direction (and length) that we are gonna penetrate + local PeneDir = tr.Normal * self:GetPenetrationDistance( tr.MatType ) + + local PeneTrace = {} + PeneTrace.endpos = tr.HitPos + PeneTrace.start = tr.HitPos + PeneDir + PeneTrace.mask = MASK_SHOT + PeneTrace.filter = { self.Owner } + + local PeneTrace = util.TraceLine( PeneTrace ) + + // Bullet didn't penetrate. + if ( PeneTrace.StartSolid or PeneTrace.Fraction >= 1.0 or tr.Fraction <= 0.0 ) then return false end + + local distance = ( PeneTrace.HitPos - tr.HitPos ):Length() + local new_damage = self:GetPenetrationDamageLoss( tr.MatType, distance, dmginfo:GetDamage() ) + + if new_damage > 0 then + + local bullet = + { + Num = 1, + Src = PeneTrace.HitPos, + Dir = tr.Normal, + Spread = Vector( 0, 0, 0 ), + Tracer = 0, + Force = 5, + Damage = new_damage, + AmmoType = "Pistol", + } + + bullet.Callback = function ( attacker, tr, dmginfo ) + + if IsValid( self ) and IsValid( self.Weapon ) then + + self.Weapon:BulletPenetration( attacker, tr, dmginfo, bounce + 1 ) + + end + + end + + local effectdata = EffectData() + effectdata:SetOrigin( PeneTrace.HitPos ) + effectdata:SetNormal( PeneTrace.Normal ) + util.Effect( "Impact", effectdata ) + + local func = function( attacker, bullet ) + + if IsValid( attacker ) then + + attacker.FireBullets( attacker, bullet, true ) + + end + + end + + timer.Simple( 0.05, function() func( attacker, bullet ) end ) + + if SERVER and tr.MatType != MAT_FLESH then + + sound.Play( table.Random( GAMEMODE.Ricochet ), tr.HitPos, 100, math.random(90,120) ) + + end + + end + +end]] + +function SWEP:BulletPenetration( attacker, tr, dmginfo, bounce ) + + if ( !self or not IsValid( self.Weapon ) ) then return end + + if IsValid( tr.Entity ) and string.find( tr.Entity:GetClass(), "npc" ) then + + local effectdata = EffectData() + effectdata:SetOrigin( tr.HitPos ) + util.Effect( "BloodImpact", effectdata ) + + end + + if ( bounce > 3 ) then return false end + + local PeneDir = tr.Normal * self:GetPenetrationDistance( tr.MatType ) + + local PeneTrace = {} + PeneTrace.endpos = tr.HitPos + PeneTrace.start = tr.HitPos + PeneDir + PeneTrace.mask = MASK_SHOT + PeneTrace.filter = { self.Owner } + + local PeneTrace = util.TraceLine( PeneTrace ) + + if ( PeneTrace.StartSolid || PeneTrace.Fraction >= 1.0 || tr.Fraction <= 0.0 ) then return false end + + local distance = ( PeneTrace.HitPos - tr.HitPos ):Length() + local new_damage = self:GetPenetrationDamageLoss( tr.MatType, distance, dmginfo:GetDamage() ) + + if new_damage > 0 then + + local bullet = + { + Num = 1, + Src = PeneTrace.HitPos, + Dir = tr.Normal, + Spread = Vector( 0, 0, 0 ), + Tracer = 0, + Force = 5, + Damage = new_damage, + AmmoType = "Pistol", + } + + bullet.Callback = function( a, b, c ) + + if IsValid( self ) and IsValid( self.Weapon ) then + + self.Weapon:BulletPenetration( attacker, tr, dmginfo, bounce + 1 ) + + end + + end + + local effectdata = EffectData() + effectdata:SetOrigin( PeneTrace.HitPos ); + effectdata:SetNormal( PeneTrace.Normal ); + util.Effect( "Impact", effectdata ) + + timer.Simple( 0.01, function() attacker:FireBullets( bullet, true ) end ) + + if SERVER and tr.MatType != MAT_FLESH and bounce == 0 then + + sound.Play( table.Random( GAMEMODE.Ricochet ), tr.HitPos, 100, math.random(90,120) ) + + end + + end + +end + +function SWEP:ShouldNotDraw() + + return self.Weapon:GetNWBool( "Laser", false ) + +end + +if CLIENT then + + SWEP.CrossRed = CreateClientConVar( "cl_redead_crosshair_r", 255, true, false ) + SWEP.CrossGreen = CreateClientConVar( "cl_redead_crosshair_g", 255, true, false ) + SWEP.CrossBlue = CreateClientConVar( "cl_redead_crosshair_b", 255, true, false ) + SWEP.CrossAlpha = CreateClientConVar( "cl_redead_crosshair_a", 255, true, false ) + SWEP.CrossLength = CreateClientConVar( "cl_redead_crosshair_length", 10, true, false ) + + SWEP.DotMat = Material( "Sprites/light_glow02_add_noz" ) + SWEP.LasMat = Material( "sprites/bluelaser1" ) + +end + +SWEP.CrosshairScale = 1 + +function SWEP:LaserDraw() + + local vm = self.Owner:GetViewModel() + + if IsValid( vm ) then + + local idx = vm:LookupAttachment( "1" ) + + if idx == 0 then idx = vm:LookupAttachment( "muzzle" ) end + + local trace = util.GetPlayerTrace( ply ) + local tr = util.TraceLine( trace ) + local tbl = vm:GetAttachment( idx ) + + local pos = tr.HitPos + + if vm:GetSequence() != ACT_VM_IDLE then + + self.AngDiff = ( tbl.Ang - self.LastGoodAng ):Forward() + + trace = {} + trace.start = tbl.Pos or Vector(0,0,0) + trace.endpos = trace.start + ( ( EyeAngles() + self.AngDiff ):Forward() * 99999 ) + trace.filter = { self.Owner, self.Weapon } + + local tr2 = util.TraceLine( trace ) + + pos = tr2.HitPos + + else + + self.LastGoodAng = tbl.Ang + + end + + cam.Start3D( EyePos(), EyeAngles() ) + + local dir = ( tbl.Ang ):Forward() + local start = tbl.Pos + + render.SetMaterial( self.LasMat ) + + for i=0,254 do + + render.DrawBeam( start, start + dir * 5, 2, 0, 12, Color( 255, 0, 0, 255 - i ) ) + + start = start + dir * 5 + + end + + local dist = tr.HitPos:Distance( EyePos() ) + local size = math.Rand( 6, 7 ) + local dotsize = dist / size ^ 2 + + render.SetMaterial( self.DotMat ) + render.DrawQuadEasy( pos, ( EyePos() - tr.HitPos ):GetNormal(), dotsize, dotsize, Color( 255, 0, 0, 255 ), 0 ) + + cam.End3D() + + end + +end + +function SWEP:DrawHUD() + + if self.Weapon:ShouldNotDraw() then return end + + if self.Weapon:GetNWBool( "Laser", false ) then return end + + local mode = self.Weapon:GetZoomMode() + + if not self.IsSniper or mode == 1 then + + local cone = self.Primary.Cone + local scale = cone + + if self.IsSniper then + + cone = self.Primary.SniperCone + scale = cone + + end + + local x = ScrW() * 0.5 + local y = ScrH() * 0.5 + local scalebywidth = ( ScrW() / 1024 ) * 10 + + if self.Owner:KeyDown( IN_FORWARD ) or self.Owner:KeyDown( IN_BACK ) or self.Owner:KeyDown( IN_MOVELEFT ) or self.Owner:KeyDown( IN_MOVERIGHT ) then + + scale = cone * 1.75 + + elseif self.Owner:KeyDown( IN_DUCK ) or self.Owner:KeyDown( IN_WALK ) then + + scale = math.Clamp( cone / 1.75, 0, 10 ) + + end + + scale = scale * scalebywidth + + local dist = math.abs( self.CrosshairScale - scale ) + self.CrosshairScale = math.Approach( self.CrosshairScale, scale, FrameTime() * 2 + dist * 0.05 ) + + local gap = 40 * self.CrosshairScale + local length = gap + self.CrossLength:GetInt() //20 * self.CrosshairScale + + surface.SetDrawColor( self.CrossRed:GetInt(), self.CrossGreen:GetInt(), self.CrossBlue:GetInt(), self.CrossAlpha:GetInt() ) + surface.DrawLine( x - length, y, x - gap, y ) + surface.DrawLine( x + length, y, x + gap, y ) + surface.DrawLine( x, y - length, x, y - gap ) + surface.DrawLine( x, y + length, x, y + gap ) + + return + + end + + if mode != 1 then + + local w = ScrW() + local h = ScrH() + local wr = ( h / 3 ) * 4 + + surface.SetTexture( surface.GetTextureID( "gmod/scope" ) ) + surface.SetDrawColor( 0, 0, 0, 255 ) + surface.DrawTexturedRect( ( w / 2 ) - wr / 2, 0, wr, h ) + + surface.SetDrawColor( 0, 0, 0, 255 ) + surface.DrawRect( 0, 0, ( w / 2 ) - wr / 2, h ) + surface.DrawRect( ( w / 2 ) + wr / 2, 0, w - ( ( w / 2 ) + wr / 2 ), h ) + surface.DrawLine( 0, h * 0.50, w, h * 0.50 ) + surface.DrawLine( w * 0.50, 0, w * 0.50, h ) + + end + +end + diff --git a/entities/weapons/rad_berettas/shared.lua b/entities/weapons/rad_berettas/shared.lua new file mode 100644 index 0000000..4ffeebd --- /dev/null +++ b/entities/weapons/rad_berettas/shared.lua @@ -0,0 +1,91 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Dual Berettas" + SWEP.IconLetter = "s" + SWEP.Slot = 2 + SWEP.Slotpos = 0 + +end + +SWEP.HoldType = "duel" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_pist_elite.mdl" +SWEP.WorldModel = "models/weapons/w_pist_elite.mdl" + +SWEP.SprintPos = Vector (-0.626, 0.5615, 3.5852) +SWEP.SprintAng = Vector (-25.2347, -3.1815, 0.3427) + +SWEP.IsSniper = false +SWEP.AmmoType = "Pistol" + +SWEP.AnimPos = 1 + +SWEP.Anims = {} +SWEP.Anims[1] = ACT_VM_SECONDARYATTACK +SWEP.Anims[2] = ACT_VM_PRIMARYATTACK + +SWEP.Primary.Sound = Sound( "Weapon_Elite.Single" ) +SWEP.Primary.Recoil = 9.5 +SWEP.Primary.Damage = 40 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.040 +SWEP.Primary.Delay = 0.180 + +SWEP.Primary.ClipSize = 30 +SWEP.Primary.Automatic = false + +function SWEP:ShootEffects() + + if IsFirstTimePredicted() then + + self.Owner:ViewPunch( Angle( math.Rand( -0.2, -0.1 ) * self.Primary.Recoil, math.Rand( -0.05, 0.05 ) * self.Primary.Recoil, 0 ) ) + + end + + self.Owner:MuzzleFlash() + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SendWeaponAnim( self.Anims[ self.AnimPos ] ) + + self.AnimPos = self.AnimPos + 1 + + if self.AnimPos > 2 then + + self.AnimPos = 1 + + end + +end + +--[[function SWEP:PrimaryAttack() + + if not self.Weapon:CanPrimaryAttack() then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + return + + end + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) ) + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.Cone, self.Weapon:GetZoomMode() ) + self.Weapon:TakePrimaryAmmo( 1 ) + self.Weapon:ShootEffects() + + if SERVER then + + self.Owner:AddAmmo( self.AmmoType, -1 ) + + end + +end]] diff --git a/entities/weapons/rad_cmp/shared.lua b/entities/weapons/rad_cmp/shared.lua new file mode 100644 index 0000000..35a68ef --- /dev/null +++ b/entities/weapons/rad_cmp/shared.lua @@ -0,0 +1,174 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFOV = 55 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "CMP-250" + SWEP.IconLetter = "f" + SWEP.Slot = 3 + SWEP.Slotpos = 1 + +end + +SWEP.HoldType = "smg" + +SWEP.Base = "rad_base" + +SWEP.UseHands = true + +SWEP.ViewModel = "models/weapons/c_smg1.mdl" +SWEP.WorldModel = "models/weapons/w_smg1.mdl" + +SWEP.SprintPos = Vector (3.6907, -0.6364, -0.5846) +SWEP.SprintAng = Vector (-2.2928, 28.9069, 0) + +SWEP.IsSniper = false +SWEP.AmmoType = "SMG" +SWEP.FirstShot = true + +SWEP.Primary.Sound = Sound( "Weapon_smg1.Burst" ) +SWEP.Primary.Sound2 = Sound( "weapons/smg1/smg1_fireburst1.wav" ) +SWEP.Primary.ReloadSound = Sound( "Weapon_smg1.reload" ) +SWEP.Primary.Recoil = 12.5 +SWEP.Primary.Damage = 30 +SWEP.Primary.NumShots = 3 +SWEP.Primary.Cone = 0.045 +SWEP.Primary.Delay = 0.600 + +SWEP.Primary.ClipSize = 18 +SWEP.Primary.Automatic = true + +function SWEP:PrimaryAttack() + + if not self.Weapon:CanPrimaryAttack() then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.25 ) + + return + + end + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) ) + self.Weapon:SetClip1( self.Weapon:Clip1() - self.Primary.NumShots ) + self.Weapon:ShootEffects() + + if self.IsSniper and self.Weapon:GetZoomMode() == 1 then + + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.SniperCone, 1 ) + + else + + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.Cone, self.Weapon:GetZoomMode() ) + + end + + if self.Weapon:GetZoomMode() > 1 then + + self.Weapon:UnZoom() + + end + + if SERVER then + + self.Owner:AddAmmo( self.AmmoType, self.Primary.NumShots * -1 ) + self.Owner:EmitSound( self.Primary.Sound2, 100, math.random( 120, 130 ) ) + + end + +end + +function SWEP:CanPrimaryAttack() + + if self.HolsterMode or self.ReloadTime or self.LastRunFrame > CurTime() then return false end + + if self.Owner:GetNWInt( "Ammo" .. self.AmmoType, 0 ) < self.Primary.NumShots then + + self.Weapon:EmitSound( self.Primary.Empty ) + + return false + + end + + if self.Weapon:Clip1() <= 0 then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + self.Weapon:DoReload() + + if self.Weapon:GetZoomMode() != 1 then + + self.Weapon:UnZoom() + + end + + return false + + end + + return true + +end + +--[[function SWEP:PrimaryAttack() + + if not self.Weapon:CanPrimaryAttack() then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + return + + end + + if self.FirstShot then + + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.ShotDelay ) + self.AutoShoot = CurTime() + self.Primary.ShotDelay + + else + + self.Owner:EmitSound( self.Primary.Sound2, 100, math.random(95,105) ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + + end + + self.FirstShot = !self.FirstShot + + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.Cone, self.Weapon:GetZoomMode() ) + self.Weapon:TakePrimaryAmmo( 1 ) + self.Weapon:ShootEffects() + + if SERVER then + + self.Owner:AddAmmo( self.AmmoType, -1 ) + + end + +end]] + +function SWEP:DoReload() + + local time = self.Weapon:StartWeaponAnim( ACT_VM_RELOAD ) + + self.Weapon:SetNextPrimaryFire( CurTime() + time + 0.100 ) + self.Weapon:EmitSound( self.Primary.ReloadSound ) + + self.ReloadTime = CurTime() + time + +end + +function SWEP:ReloadThink() + + if self.ReloadTime and self.ReloadTime <= CurTime() then + + self.ReloadTime = nil + self.Weapon:SetClip1( self.Primary.ClipSize ) + + end + +end
\ No newline at end of file diff --git a/entities/weapons/rad_crowbar/shared.lua b/entities/weapons/rad_crowbar/shared.lua new file mode 100644 index 0000000..54134ac --- /dev/null +++ b/entities/weapons/rad_crowbar/shared.lua @@ -0,0 +1,220 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFOV = 75 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Crowbar" + SWEP.IconLetter = "j" + SWEP.Slot = 1 + SWEP.Slotpos = 0 + +end + +SWEP.HoldType = "melee2" + +SWEP.Base = "rad_base" + +SWEP.UseHands = true + +SWEP.ViewModel = "models/weapons/c_crowbar.mdl" +SWEP.WorldModel = "models/weapons/w_crowbar.mdl" + +SWEP.HoldPos = Vector(8.72, 0, 3.319) +SWEP.HoldAng = Vector(0, 0, 0) + +SWEP.IsSniper = false +SWEP.AmmoType = "Knife" + +SWEP.Primary.Hit = Sound( "weapons/crowbar/crowbar_impact2.wav" ) +SWEP.Primary.Sound = Sound( "weapons/iceaxe/iceaxe_swing1.wav" ) +SWEP.Primary.Recoil = 9.5 +SWEP.Primary.Damage = 90 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Delay = 0.950 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = true + +function SWEP:GetViewModelPosition( pos, ang ) + + return pos, ang //self.Weapon:MoveViewModelTo( self.HoldPos, self.HoldAng, pos, ang, 1 ) + +end + +function SWEP:SecondaryAttack() + +end + +function SWEP:PrimaryAttack() + + if SERVER then + + self.Owner:AddStamina( -3 ) + + end + + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:MeleeTrace( self.Primary.Damage ) + +end + +function SWEP:Think() + + if self.Owner:GetVelocity():Length() > 0 then + + if self.Owner:KeyDown( IN_SPEED ) then + + self.LastRunFrame = CurTime() + 0.3 + + end + + if self.Weapon:GetZoomMode() != 1 then + + self.Weapon:UnZoom() + + end + + end + + if self.MoveTime and self.MoveTime < CurTime() and SERVER then + + self.MoveTime = nil + self.Weapon:SetZoomMode( self.Weapon:GetZoomMode() + 1 ) + self.Owner:DrawViewModel( false ) + + end + +end + +function SWEP:MeleeTrace( dmg ) + + self.Weapon:SendWeaponAnim( ACT_VM_MISSCENTER ) + + if CLIENT then return end + + local pos = self.Owner:GetShootPos() + local aim = self.Owner:GetAimVector() * 64 + + local line = {} + line.start = pos + line.endpos = pos + aim + line.filter = self.Owner + + local linetr = util.TraceLine( line ) + + local tr = {} + tr.start = pos + self.Owner:GetAimVector() * -5 + tr.endpos = pos + aim + tr.filter = self.Owner + tr.mask = MASK_SHOT_HULL + tr.mins = Vector(-20,-20,-20) + tr.maxs = Vector(20,20,20) + + local trace = util.TraceHull( tr ) + local ent = trace.Entity + local ent2 = linetr.Entity + + if not IsValid( ent ) and IsValid( ent2 ) then + + ent = ent2 + + end + + if not IsValid( ent ) then + + self.Owner:EmitSound( self.Primary.Sound, 100, math.random(60,80) ) + return + + elseif not ent:IsWorld() then + + self.Weapon:SendWeaponAnim( ACT_VM_HITCENTER ) + + if ent:IsPlayer() then + + local snd = table.Random( GAMEMODE.BluntHit ) + ent:EmitSound( snd, 100, math.random(90,110) ) + + if ent:Team() != self.Owner:Team() then + + ent:TakeDamage( dmg, self.Owner, self.Weapon ) + + self.Owner:DrawBlood() + + local ed = EffectData() + ed:SetOrigin( trace.HitPos ) + util.Effect( "BloodImpact", ed, true, true ) + + end + + elseif string.find( ent:GetClass(), "npc" ) then + + if math.random(1,3) == 1 then + + ent:SetHeadshotter( self.Owner, true ) + + end + + ent:TakeDamage( dmg, self.Owner, self.Weapon ) + + local snd = table.Random( GAMEMODE.BluntHit ) + ent:EmitSound( snd, 100, math.random(90,110) ) + + self.Owner:DrawBlood() + + local ed = EffectData() + ed:SetOrigin( trace.HitPos ) + util.Effect( "BloodImpact", ed, true, true ) + + elseif !ent:IsPlayer() then + + if string.find( ent:GetClass(), "breakable" ) then + + ent:TakeDamage( 50, self.Owner, self.Weapon ) + + if ent:GetClass() == "func_breakable_surf" then + + ent:Fire( "shatter", "1 1 1", 0 ) + + end + + end + + ent:EmitSound( self.Primary.Hit, 100, math.random(90,110) ) + + local phys = ent:GetPhysicsObject() + + if IsValid( phys ) then + + if ent.IsWooden then + + ent:Fire( "break", 0, 0 ) + + else + + ent:SetPhysicsAttacker( self.Owner ) + ent:TakeDamage( 10, self.Owner, self.Weapon ) + + phys:Wake() + phys:ApplyForceCenter( self.Owner:GetAimVector() * phys:GetMass() * 200 ) + + end + + end + + end + + end + +end + +function SWEP:DrawHUD() + +end diff --git a/entities/weapons/rad_deagle/shared.lua b/entities/weapons/rad_deagle/shared.lua new file mode 100644 index 0000000..1bc4118 --- /dev/null +++ b/entities/weapons/rad_deagle/shared.lua @@ -0,0 +1,39 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "Desert Eagle" + SWEP.IconLetter = "f" + SWEP.Slot = 2 + SWEP.Slotpos = 1 + +end + +SWEP.HoldType = "revolver" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_pist_deagle.mdl" +SWEP.WorldModel = "models/weapons/w_pist_deagle.mdl" + +SWEP.SprintPos = Vector (-4.2232, -5.1203, -2.0386) +SWEP.SprintAng = Vector (12.7496, -52.6848, -7.5206) + +SWEP.IsSniper = false +SWEP.AmmoType = "Pistol" + +SWEP.Primary.Sound = Sound( "Weapon_Deagle.Single" ) +SWEP.Primary.Recoil = 11.5 +SWEP.Primary.Damage = 40 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.030 +SWEP.Primary.Delay = 0.380 + +SWEP.Primary.ClipSize = 7 +SWEP.Primary.Automatic = false
\ No newline at end of file diff --git a/entities/weapons/rad_experimental/shared.lua b/entities/weapons/rad_experimental/shared.lua new file mode 100644 index 0000000..f8da7b8 --- /dev/null +++ b/entities/weapons/rad_experimental/shared.lua @@ -0,0 +1,154 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = false + + SWEP.ViewModelFOV = 60 + + SWEP.PrintName = "PPW-952" + SWEP.IconLetter = "m" + SWEP.Slot = 4 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "ar2" + +SWEP.Base = "rad_base" + +SWEP.UseHands = true + +SWEP.ViewModel = "models/weapons/c_irifle.mdl" +SWEP.WorldModel = "models/weapons/w_irifle.mdl" + +//SWEP.SprintPos = Vector (4.9288, -2.4157, 2.2032) +//SWEP.SprintAng = Vector (0.8736, 40.1165, 28.0526) + +SWEP.SprintPos = Vector(0.55, -5.119, -1.025) +SWEP.SprintAng = Vector(7.44, 25.079, 16.26) + +SWEP.IsSniper = false +SWEP.AmmoType = "Prototype" +SWEP.LaserOffset = Angle( -90, -0.9, 0 ) +SWEP.LaserScale = 0.25 +//SWEP.IronsightsFOV = 60 + +SWEP.Gore = Sound( "npc/roller/mine/rmine_explode_shock1.wav" ) + +SWEP.Primary.Sound = Sound( "Airboat.FireGunHeavy" ) +SWEP.Primary.Sound2 = Sound( "npc/scanner/scanner_electric2.wav" ) +SWEP.Primary.Recoil = 19.5 +SWEP.Primary.Damage = 350 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.010 +SWEP.Primary.Delay = 1.400 + +SWEP.Primary.ClipSize = 3 +SWEP.Primary.Automatic = true + +function SWEP:ShootEffects() + + if IsFirstTimePredicted() then + + self.Owner:ViewPunch( Angle( math.Rand( -0.2, -0.1 ) * self.Primary.Recoil, math.Rand( -0.05, 0.05 ) * self.Primary.Recoil, 0 ) ) + + end + + self.Owner:MuzzleFlash() + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + +end + +function SWEP:PrimaryAttack() + + if not self.Weapon:CanPrimaryAttack() then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + return + + end + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(90,100) ) + self.Weapon:EmitSound( self.Primary.Sound2, 100, math.random(120,130) ) + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.Cone, self.Weapon:GetZoomMode() ) + self.Weapon:TakePrimaryAmmo( 1 ) + self.Weapon:ShootEffects() + + if SERVER then + + self.Owner:AddAmmo( self.AmmoType, -1 ) + + end + +end + +function SWEP:ShootBullets( damage, numbullets, aimcone, zoommode ) + + if SERVER then + + self.Owner:AddStat( "Bullets", numbullets ) + + end + + local scale = aimcone + + if self.Owner:KeyDown( IN_FORWARD ) or self.Owner:KeyDown( IN_BACK ) or self.Owner:KeyDown( IN_MOVELEFT ) or self.Owner:KeyDown( IN_MOVERIGHT ) then + + scale = aimcone * 1.75 + + elseif self.Owner:KeyDown( IN_DUCK ) or self.Owner:KeyDown( IN_WALK ) then + + scale = math.Clamp( aimcone / 1.75, 0, 10 ) + + end + + local bullet = {} + bullet.Num = numbullets + bullet.Src = self.Owner:GetShootPos() + bullet.Dir = self.Owner:GetAimVector() + bullet.Spread = Vector( scale, scale, 0 ) + bullet.Tracer = 1 + bullet.Force = damage * 2 + bullet.Damage = 1 + bullet.AmmoType = "Pistol" + bullet.TracerName = "AirboatGunHeavyTracer" + + bullet.Callback = function ( attacker, tr, dmginfo ) + + if IsValid( tr.Entity ) and IsValid( self ) and IsValid( self.Owner ) and SERVER then + + if tr.Entity:IsPlayer() and tr.Entity:Team() == TEAM_ZOMBIES then + + tr.Entity:SetModel( table.Random( GAMEMODE.Corpses ) ) + + end + + local dmg = DamageInfo() + dmg:SetDamage( 500 ) + dmg:SetDamageType( DMG_BLAST ) + dmg:SetAttacker( self.Owner ) + dmg:SetInflictor( self.Weapon ) + + tr.Entity:EmitSound( self.Gore, 100, math.random(90,110) ) + tr.Entity:TakeDamageInfo( dmg ) + + end + + local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetNormal( tr.HitNormal ) + util.Effect( "energy_explosion", ed, true, true ) + + end + + self.Owner:FireBullets( bullet ) + +end diff --git a/entities/weapons/rad_famas/shared.lua b/entities/weapons/rad_famas/shared.lua new file mode 100644 index 0000000..b7966f4 --- /dev/null +++ b/entities/weapons/rad_famas/shared.lua @@ -0,0 +1,39 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = false + + SWEP.PrintName = "FAMAS" + SWEP.IconLetter = "v" + SWEP.Slot = 4 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "ar2" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_rif_famas.mdl" +SWEP.WorldModel = "models/weapons/w_rif_famas.mdl" + +SWEP.SprintPos = Vector(4.9288, -2.4157, 2.2032) +SWEP.SprintAng = Vector(0.8736, 40.1165, 28.0526) + +SWEP.IsSniper = false +SWEP.AmmoType = "Rifle" + +SWEP.Primary.Sound = Sound( "Weapon_famas.Single" ) +SWEP.Primary.Recoil = 7.5 +SWEP.Primary.Damage = 45 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.035 +SWEP.Primary.Delay = 0.100 + +SWEP.Primary.ClipSize = 25 +SWEP.Primary.Automatic = true diff --git a/entities/weapons/rad_firegun/shared.lua b/entities/weapons/rad_firegun/shared.lua new file mode 100644 index 0000000..a8e3ae8 --- /dev/null +++ b/entities/weapons/rad_firegun/shared.lua @@ -0,0 +1,190 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = false + + SWEP.ViewModelFOV = 60 + + SWEP.PrintName = "HEAT Cannon" + SWEP.IconLetter = "m" + SWEP.Slot = 4 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "physgun" + +SWEP.Base = "rad_base" + +SWEP.UseHands = true + +SWEP.ViewModel = "models/weapons/c_physcannon.mdl" +SWEP.WorldModel = "models/weapons/w_physics.mdl" + +//SWEP.SprintPos = Vector (4.9288, -2.4157, 2.2032) +//SWEP.SprintAng = Vector (0.8736, 40.1165, 28.0526) + +SWEP.SprintPos = Vector(5.36, -0.401, 2.88) +SWEP.SprintAng = Vector(-3.201, 26.799, 5.4) + +SWEP.IsSniper = false +SWEP.AmmoType = "Prototype" +SWEP.LaserOffset = Angle( -90, -0.9, 0 ) +SWEP.LaserScale = 0.25 +//SWEP.IronsightsFOV = 60 + +SWEP.Burn = Sound( "ambient/fire/ignite.wav" ) +SWEP.Burn2 = Sound( "Weapon_Mortar.Impact" ) + +SWEP.Primary.Sound = Sound( "Weapon_mortar.single" ) +SWEP.Primary.Sound2 = Sound( "weapons/physcannon/physcannon_charge.wav" ) +SWEP.Primary.Recoil = 15.5 +SWEP.Primary.Damage = 80 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.015 +SWEP.Primary.Delay = 1.700 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = true + +function SWEP:ShootEffects() + + if IsFirstTimePredicted() then + + self.Owner:ViewPunch( Angle( math.Rand( -0.2, -0.1 ) * self.Primary.Recoil, math.Rand( -0.05, 0.05 ) * self.Primary.Recoil, 0 ) ) + + end + + self.Owner:MuzzleFlash() + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SendWeaponAnim( ACT_VM_SECONDARYATTACK ) + +end + +function SWEP:PrimaryAttack() + + if not self.Weapon:CanPrimaryAttack() then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + return + + end + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(90,100) ) + //self.Weapon:EmitSound( self.Primary.Sound3, 100, 80 ) + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.Cone, self.Weapon:GetZoomMode() ) + self.Weapon:TakePrimaryAmmo( 1 ) + self.Weapon:ShootEffects() + + if SERVER then + + self.Owner:AddAmmo( self.AmmoType, -1 ) + self.Owner:EmitSound( self.Primary.Sound2 ) + + end + + self.ReloadTime = CurTime() + self.Primary.Delay + +end + +function SWEP:ReloadThink() + + if self.ReloadTime and self.ReloadTime <= CurTime() then + + self.ReloadTime = nil + self.Weapon:SetClip1( self.Primary.ClipSize ) + + end + +end + +function SWEP:Reload() + +end + +SWEP.Decals = { "Scorch", "SmallScorch" } + +function SWEP:ShootBullets( damage, numbullets, aimcone, zoommode ) + + if SERVER then + + self.Owner:AddStat( "Bullets", numbullets ) + + end + + local scale = aimcone + + if self.Owner:KeyDown( IN_FORWARD ) or self.Owner:KeyDown( IN_BACK ) or self.Owner:KeyDown( IN_MOVELEFT ) or self.Owner:KeyDown( IN_MOVERIGHT ) then + + scale = aimcone * 1.75 + + elseif self.Owner:KeyDown( IN_DUCK ) or self.Owner:KeyDown( IN_WALK ) then + + scale = math.Clamp( aimcone / 1.75, 0, 10 ) + + end + + local bullet = {} + bullet.Num = numbullets + bullet.Src = self.Owner:GetShootPos() + bullet.Dir = self.Owner:GetAimVector() + bullet.Spread = Vector( scale, scale, 0 ) + bullet.Tracer = 1 + bullet.Force = damage * 2 + bullet.Damage = 1 + bullet.AmmoType = "Pistol" + bullet.TracerName = "fire_tracer" + + bullet.Callback = function ( attacker, tr, dmginfo ) + + if IsValid( tr.Entity ) and IsValid( self ) and IsValid( self.Owner ) and SERVER then + + if tr.Entity:IsPlayer() then + + tr.Entity:TakeDamage( self.Primary.Damage, self.Owner ) + + else + + tr.Entity:TakeDamage( math.Clamp( math.min( 20, tr.Entity:Health() - 5 ), 1, 20 ), self.Owner ) + + end + + if tr.Entity.NextBot or ( tr.Entity:IsPlayer() and tr.Entity:Team() != TEAM_ARMY ) then + + tr.Entity:DoIgnite( self.Owner ) + tr.Entity:EmitSound( self.Burn, 100, math.random(90,110) ) + + end + + end + + sound.Play( self.Burn2, tr.HitPos ) + + local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetNormal( tr.HitNormal ) + util.Effect( "fire_explosion", ed, true, true ) + + if tr.HitNormal.z > 0.5 and tr.HitWorld then + + local ed = EffectData() + ed:SetOrigin( tr.HitPos ) + ed:SetMagnitude( 0.5 ) + util.Effect( "smoke_crater", ed, true, true ) + + end + + util.Decal( table.Random( self.Decals ), tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal ) + + end + + self.Owner:FireBullets( bullet ) + +end diff --git a/entities/weapons/rad_fiveseven/shared.lua b/entities/weapons/rad_fiveseven/shared.lua new file mode 100644 index 0000000..28ce60e --- /dev/null +++ b/entities/weapons/rad_fiveseven/shared.lua @@ -0,0 +1,39 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "FN Five-Seven" + SWEP.IconLetter = "y" + SWEP.Slot = 2 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "pistol" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_pist_fiveseven.mdl" +SWEP.WorldModel = "models/weapons/w_pist_fiveseven.mdl" + +SWEP.SprintPos = Vector (1.3846, -0.6033, -7.1994) +SWEP.SprintAng = Vector (33.9412, 15.0662, 6.288) + +SWEP.IsSniper = false +SWEP.AmmoType = "Pistol" + +SWEP.Primary.Sound = Sound( "Weapon_fiveseven.Single" ) +SWEP.Primary.Recoil = 6.5 +SWEP.Primary.Damage = 25 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.035 +SWEP.Primary.Delay = 0.100 + +SWEP.Primary.ClipSize = 10 +SWEP.Primary.Automatic = false diff --git a/entities/weapons/rad_g3/shared.lua b/entities/weapons/rad_g3/shared.lua new file mode 100644 index 0000000..8e9d8b7 --- /dev/null +++ b/entities/weapons/rad_g3/shared.lua @@ -0,0 +1,76 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "G3 SG1" + SWEP.IconLetter = "i" + SWEP.Slot = 4 + SWEP.Slotpos = 3 + +end + +SWEP.HoldType = "ar2" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_snip_g3sg1.mdl" +SWEP.WorldModel = "models/weapons/w_snip_g3sg1.mdl" + +SWEP.SprintPos = Vector(-2.8398, -3.656, 0.5519) +SWEP.SprintAng = Vector(0.1447, -34.0929, 0) + +SWEP.ZoomModes = { 0, 35, 10 } +SWEP.ZoomSpeeds = { 0.25, 0.40, 0.40 } + +SWEP.IsSniper = true +SWEP.AmmoType = "Sniper" + +SWEP.Primary.Sound = Sound( "Weapon_G3SG1.Single" ) +SWEP.Primary.Recoil = 5.5 +SWEP.Primary.Damage = 100 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.002 +SWEP.Primary.SniperCone = 0.035 +SWEP.Primary.Delay = 0.380 + +SWEP.Primary.ClipSize = 20 +SWEP.Primary.Automatic = true + +function SWEP:PrimaryAttack() + + if not self.Weapon:CanPrimaryAttack() then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.25 ) + + return + + end + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) ) + self.Weapon:SetClip1( self.Weapon:Clip1() - 1 ) + self.Weapon:ShootEffects() + + if self.IsSniper and self.Weapon:GetZoomMode() == 1 then + + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.SniperCone, 1 ) + + else + + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.Cone, self.Weapon:GetZoomMode() ) + + end + + if SERVER then + + self.Owner:AddAmmo( self.AmmoType, -1 ) + + end + +end
\ No newline at end of file diff --git a/entities/weapons/rad_galil/shared.lua b/entities/weapons/rad_galil/shared.lua new file mode 100644 index 0000000..246ab86 --- /dev/null +++ b/entities/weapons/rad_galil/shared.lua @@ -0,0 +1,39 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = false + + SWEP.PrintName = "IMI Galil" + SWEP.IconLetter = "v" + SWEP.Slot = 4 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "ar2" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_rif_galil.mdl" +SWEP.WorldModel = "models/weapons/w_rif_galil.mdl" + +SWEP.SprintPos = Vector (5.6501, -4.3222, 2.1819) +SWEP.SprintAng = Vector (-10.5144, 47.7303, 2.2908) + +SWEP.IsSniper = false +SWEP.AmmoType = "Rifle" + +SWEP.Primary.Sound = Sound( "Weapon_Galil.Single" ) +SWEP.Primary.Recoil = 7.5 +SWEP.Primary.Damage = 50 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.040 +SWEP.Primary.Delay = 0.110 + +SWEP.Primary.ClipSize = 40 +SWEP.Primary.Automatic = true diff --git a/entities/weapons/rad_glock/shared.lua b/entities/weapons/rad_glock/shared.lua new file mode 100644 index 0000000..fd00c73 --- /dev/null +++ b/entities/weapons/rad_glock/shared.lua @@ -0,0 +1,39 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "Glock 19" + SWEP.IconLetter = "c" + SWEP.Slot = 2 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "pistol" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_pist_glock18.mdl" +SWEP.WorldModel = "models/weapons/w_pist_glock18.mdl" + +SWEP.SprintPos = Vector (0.6553, 0.446, 3.2583) +SWEP.SprintAng = Vector (-15.5938, -2.8864, -1.5457) + +SWEP.IsSniper = false +SWEP.AmmoType = "Pistol" + +SWEP.Primary.Sound = Sound( "Weapon_Glock.Single" ) +SWEP.Primary.Recoil = 6.5 +SWEP.Primary.Damage = 25 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.040 +SWEP.Primary.Delay = 0.100 + +SWEP.Primary.ClipSize = 15 +SWEP.Primary.Automatic = false diff --git a/entities/weapons/rad_grenade/shared.lua b/entities/weapons/rad_grenade/shared.lua new file mode 100644 index 0000000..516f491 --- /dev/null +++ b/entities/weapons/rad_grenade/shared.lua @@ -0,0 +1,151 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "HE Grenade" + SWEP.IconLetter = "h" + SWEP.Slot = 3 + SWEP.Slotpos = 3 + +end + +SWEP.HoldType = "grenade" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_eq_fraggrenade.mdl" +SWEP.WorldModel = "models/weapons/w_eq_fraggrenade.mdl" + +SWEP.SprintPos = Vector (10.9603, -1.1484, -0.4996) +SWEP.SprintAng = Vector (13.9974, 21.7915, 59.3288) + +SWEP.IsSniper = false +SWEP.AmmoType = "Knife" +SWEP.ThrowPower = 350 + +SWEP.Primary.Sound = Sound( "WeaponFrag.Throw" ) +SWEP.Primary.Recoil = 6.5 +SWEP.Primary.Damage = 1 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.100 +SWEP.Primary.Delay = 2.300 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = false + +function SWEP:Think() + + if self.Owner:GetVelocity():Length() > 0 then + + if self.Owner:KeyDown( IN_SPEED ) and self.Owner:GetVelocity():Length() > 0 and self.Owner:GetNWFloat( "Weight", 0 ) < 50 then + + self.LastRunFrame = CurTime() + 0.3 + + end + + end + + if self.ThrowTime then + + if self.ThrowTime - 0.3 < CurTime() and not self.ThrowAnim then + + self.ThrowAnim = true + + if self.ThrowPower > 1000 then + + self.Weapon:SendWeaponAnim( ACT_VM_THROW ) + + end + + end + + if self.ThrowTime < CurTime() then + + self.ThrowTime = nil + self.ReloadTime = CurTime() + 0.75 + + if CLIENT then return end + + local tbl = item.GetByModel( "models/weapons/w_eq_fraggrenade_thrown.mdl" ) + + if self.Owner:HasItem( tbl.ID ) then + + self.Owner:RemoveFromInventory( tbl.ID ) + + end + + local ent = ents.Create( "sent_grenade" ) + ent:SetPos( self.Owner:GetShootPos() + self.Owner:GetRight() * 5 + self.Owner:GetUp() * -5 ) + ent:SetOwner( self.Owner ) + ent:SetAngles( self.Owner:GetAimVector():Angle() ) + ent:SetSpeed( self.ThrowPower ) + ent:Spawn() + + if not self.Owner:HasItem( tbl.ID ) then + + self.Owner:StripWeapon( "rad_grenade" ) + + end + + end + + end + + if self.ReloadTime and self.ReloadTime < CurTime() then + + self.ReloadTime = nil + + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + + end + +end + +function SWEP:SecondaryAttack() + + self.Weapon:SendWeaponAnim( ACT_VM_PULLBACK_LOW ) + self.Weapon:SetNextSecondaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:ShootEffects() + + self.ThrowTime = CurTime() + 1.25 + self.ThrowAnim = false + self.ThrowPower = 800 + +end + +function SWEP:PrimaryAttack() + + self.Weapon:SendWeaponAnim( ACT_VM_PULLBACK_LOW ) + self.Weapon:SetNextSecondaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:ShootEffects() + + self.ThrowTime = CurTime() + 1.25 + self.ThrowAnim = false + self.ThrowPower = 3000 + +end + +function SWEP:ShootEffects() + + if IsFirstTimePredicted() then + + self.Owner:ViewPunch( Angle( math.Rand( -0.2, -0.1 ) * self.Primary.Recoil, math.Rand( -0.05, 0.05 ) * self.Primary.Recoil, 0 ) ) + + end + + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + +end + +function SWEP:DrawHUD() + +end + diff --git a/entities/weapons/rad_hammer/shared.lua b/entities/weapons/rad_hammer/shared.lua new file mode 100644 index 0000000..5bf20ee --- /dev/null +++ b/entities/weapons/rad_hammer/shared.lua @@ -0,0 +1,483 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFOV = 80 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Hammer" + SWEP.IconLetter = "j" + SWEP.Slot = 1 + SWEP.Slotpos = 0 + +end + +SWEP.HoldType = "melee" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_hammer/v_hammer.mdl" +SWEP.WorldModel = "models/weapons/w_hammer.mdl" + +SWEP.Barricade = Model( "models/props_debris/wood_board04a.mdl" ) + +SWEP.HoldPos = Vector (1.1747, -16.6759, -5.7913) +SWEP.HoldAng = Vector (23.7548, -8.0105, -5.154) + +SWEP.IsSniper = false +SWEP.AmmoType = "Knife" + +SWEP.Click = Sound( "Buttons.snd14" ) +SWEP.Deny = Sound( "HL1/fvox/buzz.wav" ) + +SWEP.Primary.Hit = Sound( "weapons/crowbar/crowbar_impact1.wav" ) +SWEP.Primary.Sound = Sound( "weapons/iceaxe/iceaxe_swing1.wav" ) +SWEP.Primary.Recoil = 6.5 +SWEP.Primary.Damage = 50 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Delay = 1.100 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = true + +SWEP.Position = 35 +SWEP.BuildAng = 0 + +function SWEP:GetViewModelPosition( pos, ang ) + + return self.Weapon:MoveViewModelTo( self.HoldPos, self.HoldAng, pos, ang, 1 ) + +end + +function SWEP:ReleaseGhost() + + if IsValid( self.GhostEntity ) then + + self.GhostEntity:Remove() + self.GhostEntity = nil + + end + +end + +function SWEP:MakeGhost( model, pos, angle ) + + self.GhostEntity = ents.CreateClientProp( model ) + //self.GhostEntity:SetModel( model ) + self.GhostEntity:SetPos( pos ) + self.GhostEntity:SetAngles( angle ) + self.GhostEntity:Spawn() + + self.GhostEntity:SetSolid( SOLID_VPHYSICS ) + self.GhostEntity:SetMoveType( MOVETYPE_NONE ) + self.GhostEntity:SetNotSolid( true ) + self.GhostEntity:SetRenderMode( RENDERMODE_TRANSALPHA ) + self.GhostEntity:SetColor( Color( 255, 255, 255, 200 ) ) + +end + +function SWEP:UpdateGhost() + + if not IsValid( self.GhostEntity ) then return end + + local tr = util.GetPlayerTrace( self.Owner ) + local trace = util.TraceLine( tr ) + + if not trace.Hit then return end + + local ang = ( trace.HitNormal * -1 ):Angle() + Angle( 0, 0, math.NormalizeAngle( 90 + self.Weapon:GetNWInt( "BuildAng", 0 ) ) ) + local pos = trace.HitPos + + local trlength = self.Weapon:GetOwner():GetPos() - trace.HitPos + trlength = trlength:Length() + + if trlength < 150 and ( trace.HitWorld or trace.Entity:GetClass() == "prop_door_rotating" ) then + + self.GhostEntity:SetColor( Color( 50, 255, 50, 200 ) ) + + else + + self.GhostEntity:SetColor( Color( 255, 50, 50, 200 ) ) + + end + + if not trace.HitWorld and not trace.Entity:GetClass() == "prop_door_rotating" then + + self.GhostEntity:SetColor( Color( 255, 50, 50, 200 ) ) + self.GhostEntity:SetModel( self.Barricade ) + self.GhostEntity:SetPos( pos + ( self.GhostEntity:GetUp() * self.Position ) ) + self.GhostEntity:SetAngles( ang ) + + elseif string.find( trace.Entity:GetClass(), "prop_door" ) then + + self.GhostEntity:SetModel( "models/props_c17/tools_wrench01a.mdl" ) + self.GhostEntity:SetPos( trace.HitPos + trace.HitNormal * 5 ) + self.GhostEntity:SetAngles( ( trace.HitNormal * -1 ):Angle() + Angle(0,90,90) ) + + else + + self.GhostEntity:SetModel( self.Barricade ) + self.GhostEntity:SetPos( pos + ( self.GhostEntity:GetUp() * self.Position ) ) + self.GhostEntity:SetAngles( ang ) + + end + +end + +function SWEP:SetPlacePosition( ent ) + + local tr = util.GetPlayerTrace( self:GetOwner() ) + local trace = util.TraceLine( tr ) + + if not trace.Hit then return end + + local ang = ( trace.HitNormal * -1 ):Angle() + Angle( 0, 0, math.NormalizeAngle( 90 + self.Weapon:GetNWInt( "BuildAng", 0 ) ) ) + ent:SetAngles( ang ) + + local pos = trace.HitPos + ent:SetPos( pos + ( ent:GetUp() * self.Position ) ) + + local phys = ent:GetPhysicsObject() + + if IsValid( phys ) then + + phys:EnableMotion( false ) + + end + +end + +function SWEP:Deploy() + + if SERVER then + + self.Owner:DrawViewModel( true ) + self.Owner:NoticeOnce( "Toggle build mode with your reload key", GAMEMODE.Colors.Blue, 5, 2 ) + + else + + self.Weapon:ReleaseGhost() + + end + + self.InIron = false + + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + + return true + +end + +function SWEP:Holster() + + if CLIENT then + + self.Weapon:ReleaseGhost() + + end + + return true + +end + +function SWEP:Reload() + + if CLIENT then return end + + if ( self.ReloadTime or 0 ) < CurTime() then + + self.ReloadTime = CurTime() + 0.75 + + self.Weapon:SetNWBool( "BuildMode", !self.Weapon:GetNWBool( "BuildMode", false ) ) + + self.Owner:EmitSound( self.Click, 50, 120 ) + self.Owner:NoticeOnce( "Rotate your barricade by right clicking", GAMEMODE.Colors.Blue, 5, 2 ) + + end + +end + +function SWEP:SecondaryAttack() + + if CLIENT then return end + + if ( self.SecondDelay or 0 ) < CurTime() and self.Weapon:GetNWBool( "BuildMode", false ) then + + self.SecondDelay = CurTime() + 0.25 + self.BuildAng = self.BuildAng + 45 + + if self.BuildAng == 360 then + + self.BuildAng = 0 + + end + + self.Weapon:SetNWInt( "BuildAng", self.BuildAng ) + self.Owner:EmitSound( self.Click ) + + end + +end + +function SWEP:PrimaryAttack() + + if not self.Weapon:GetNWBool( "BuildMode", false ) then + + if SERVER then + + self.Owner:AddStamina( -2 ) + + end + + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:MeleeTrace( self.Primary.Damage ) + + else + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:BarricadeTrace() + + end + +end + +function SWEP:BarricadeTrace() + + if CLIENT then return end + + local trace = util.GetPlayerTrace( self.Owner ) + local tr = util.TraceLine( trace ) + local trlength = self.Weapon:GetOwner():GetPos() - tr.HitPos + trlength = trlength:Length() + + local has, id = self.Owner:GetWood() + + if not has then + + self.Owner:Notice( "You don't have enough wood", GAMEMODE.Colors.Red ) + self.Owner:EmitSound( self.Deny, 50, 100 ) + + return + + end + + if tr.HitWorld and trlength < 150 then + + self.Owner:Notice( "Built a barricade using 1 piece of wood", GAMEMODE.Colors.Green ) + self.Owner:NoticeOnce( "You can also repair doors", GAMEMODE.Colors.Blue, 5, 2 ) + + local prop = ents.Create( "prop_physics" ) + prop:SetModel( self.Barricade ) + prop:Spawn() + prop:SetHealth( 350 ) + prop:SetCustomCollisionCheck() + prop.IsWood = true + + self.Weapon:SetPlacePosition( prop ) + + elseif string.find( tr.Entity:GetClass(), "prop_door" ) and trlength < 150 then + + self.Owner:Notice( "Fortified a door using 1 piece of wood", GAMEMODE.Colors.Green ) + + tr.Entity.MaxHits = 30 + tr.Entity.Hits = 0 + + else + + self.Owner:Notice( "You can't build a barricade here", GAMEMODE.Colors.Red ) + self.Owner:EmitSound( self.Deny, 50, 100 ) + + return + + end + + self.Owner:AddStamina( -15 ) + self.Owner:RemoveFromInventory( id ) + self.Owner:AddStat( "Wood" ) + self.Owner:AddCash( 1 ) + + self.Owner:EmitSound( table.Random( GAMEMODE.Drill ), 100, math.random(90,110) ) + self.Owner:EmitSound( table.Random( GAMEMODE.WoodHammer ), 100, math.random(90,110) ) + +end + +function SWEP:MeleeTrace( dmg ) + + self.Weapon:SendWeaponAnim( ACT_VM_MISSCENTER ) + + if CLIENT then return end + + local pos = self.Owner:GetShootPos() + local aim = self.Owner:GetAimVector() * 64 + + local line = {} + line.start = pos + line.endpos = pos + aim + line.filter = self.Owner + + local linetr = util.TraceLine( line ) + + local tr = {} + tr.start = pos + self.Owner:GetAimVector() * -5 + tr.endpos = pos + aim + tr.filter = self.Owner + tr.mask = MASK_SHOT_HULL + tr.mins = Vector(-20,-20,-20) + tr.maxs = Vector(20,20,20) + + local trace = util.TraceHull( tr ) + local ent = trace.Entity + local ent2 = linetr.Entity + + if not IsValid( ent ) and IsValid( ent2 ) then + + ent = ent2 + + end + + if not IsValid( ent ) then + + self.Owner:EmitSound( self.Primary.Sound, 100, math.random(60,80) ) + return + + elseif not ent:IsWorld() then + + self.Weapon:SendWeaponAnim( ACT_VM_HITCENTER ) + + if ent:IsPlayer() then + + local snd = table.Random( GAMEMODE.BluntHit ) + ent:EmitSound( snd, 100, math.random(90,110) ) + + if ent:Team() != self.Owner:Team() then + + ent:TakeDamage( dmg, self.Owner, self.Weapon ) + + self.Owner:DrawBlood() + + local ed = EffectData() + ed:SetOrigin( trace.HitPos ) + util.Effect( "BloodImpact", ed, true, true ) + + end + + elseif string.find( ent:GetClass(), "npc" ) then + + local snd = table.Random( GAMEMODE.BluntHit ) + ent:EmitSound( snd, 100, math.random(90,110) ) + + if math.random(1,3) == 1 then + + ent:SetHeadshotter( self.Owner, true ) + + end + + ent:TakeDamage( dmg, self.Owner, self.Weapon ) + + self.Owner:DrawBlood() + + local ed = EffectData() + ed:SetOrigin( trace.HitPos ) + util.Effect( "BloodImpact", ed, true, true ) + + elseif !ent:IsPlayer() then + + if string.find( ent:GetClass(), "breakable" ) then + + ent:TakeDamage( 50, self.Owner, self.Weapon ) + + if ent:GetClass() == "func_breakable_surf" then + + ent:Fire( "shatter", "1 1 1", 0 ) + + end + + end + + ent:EmitSound( self.Primary.Hit, 100, math.random(90,110) ) + + local phys = ent:GetPhysicsObject() + + if IsValid( phys ) then + + if ent.IsWooden then + + ent:Fire( "break", 0, 0 ) + + else + + ent:SetPhysicsAttacker( self.Owner ) + ent:TakeDamage( 10, self.Owner, self.Weapon ) + + phys:Wake() + phys:ApplyForceCenter( self.Owner:GetAimVector() * phys:GetMass() * 200 ) + + end + + end + + end + + end + +end + +function SWEP:Think() + + if CLIENT then + + if self.Weapon:GetNWBool( "BuildMode", false ) then + + if not self.GhostEntity then + + self.Weapon:MakeGhost( self.Barricade, self.Owner:GetPos() + Vector(0,0,100), Angle(0,0,0)) + + else + + self.Weapon:UpdateGhost() + + end + + elseif IsValid( self.GhostEntity ) then + + self.Weapon:ReleaseGhost() + + end + + end + + if self.Owner:GetVelocity():Length() > 0 then + + if self.Owner:KeyDown( IN_SPEED ) then + + self.LastRunFrame = CurTime() + 0.3 + + end + + if self.Weapon:GetZoomMode() != 1 then + + self.Weapon:UnZoom() + + end + + end + + if self.MoveTime and self.MoveTime < CurTime() and SERVER then + + self.MoveTime = nil + self.Weapon:SetZoomMode( self.Weapon:GetZoomMode() + 1 ) + self.Owner:DrawViewModel( false ) + + end + +end + +function SWEP:DrawHUD() + +end diff --git a/entities/weapons/rad_incendiarygrenade/shared.lua b/entities/weapons/rad_incendiarygrenade/shared.lua new file mode 100644 index 0000000..3dda5dc --- /dev/null +++ b/entities/weapons/rad_incendiarygrenade/shared.lua @@ -0,0 +1,151 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "Incendiary Grenade" + SWEP.IconLetter = "h" + SWEP.Slot = 3 + SWEP.Slotpos = 3 + +end + +SWEP.HoldType = "grenade" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_eq_flashbang.mdl" +SWEP.WorldModel = "models/weapons/w_eq_flashbang.mdl" + +SWEP.SprintPos = Vector (10.9603, -1.1484, -0.4996) +SWEP.SprintAng = Vector (13.9974, 21.7915, 59.3288) + +SWEP.IsSniper = false +SWEP.AmmoType = "Knife" +SWEP.ThrowPower = 300 + +SWEP.Primary.Sound = Sound( "WeaponFrag.Throw" ) +SWEP.Primary.Recoil = 6.5 +SWEP.Primary.Damage = 1 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.100 +SWEP.Primary.Delay = 2.300 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = false + +function SWEP:Think() + + if self.Owner:GetVelocity():Length() > 0 then + + if self.Owner:KeyDown( IN_SPEED ) and self.Owner:GetVelocity():Length() > 0 and self.Owner:GetNWFloat( "Weight", 0 ) < 50 then + + self.LastRunFrame = CurTime() + 0.3 + + end + + end + + if self.ThrowTime then + + if self.ThrowTime - 0.3 < CurTime() and not self.ThrowAnim then + + self.ThrowAnim = true + + if self.ThrowPower > 1000 then + + self.Weapon:SendWeaponAnim( ACT_VM_THROW ) + + end + + end + + if self.ThrowTime < CurTime() then + + self.ThrowTime = nil + self.ReloadTime = CurTime() + 0.75 + + if CLIENT then return end + + local tbl = item.GetByModel( "models/weapons/w_eq_flashbang.mdl" ) + + if self.Owner:HasItem( tbl.ID ) then + + self.Owner:RemoveFromInventory( tbl.ID ) + + end + + local ent = ents.Create( "sent_grenade_incendiary" ) + ent:SetPos( self.Owner:GetShootPos() + self.Owner:GetRight() * 5 + self.Owner:GetUp() * -5 ) + ent:SetOwner( self.Owner ) + ent:SetAngles( self.Owner:GetAimVector():Angle() ) + ent:SetSpeed( self.ThrowPower ) + ent:Spawn() + + if not self.Owner:HasItem( tbl.ID ) then + + self.Owner:StripWeapon( "rad_incendiarygrenade" ) + + end + + end + + end + + if self.ReloadTime and self.ReloadTime < CurTime() then + + self.ReloadTime = nil + + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + + end + +end + +function SWEP:SecondaryAttack() + + self.Weapon:SendWeaponAnim( ACT_VM_PULLBACK_LOW ) + self.Weapon:SetNextSecondaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:ShootEffects() + + self.ThrowTime = CurTime() + 1.25 + self.ThrowAnim = false + self.ThrowPower = 800 + +end + +function SWEP:PrimaryAttack() + + self.Weapon:SendWeaponAnim( ACT_VM_PULLBACK_LOW ) + self.Weapon:SetNextSecondaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:ShootEffects() + + self.ThrowTime = CurTime() + 1.25 + self.ThrowAnim = false + self.ThrowPower = 3000 + +end + +function SWEP:ShootEffects() + + if SERVER then + + self.Owner:ViewBounce( self.Primary.Recoil ) + + end + + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + +end + +function SWEP:DrawHUD() + +end + diff --git a/entities/weapons/rad_inv/shared.lua b/entities/weapons/rad_inv/shared.lua new file mode 100644 index 0000000..50e7691 --- /dev/null +++ b/entities/weapons/rad_inv/shared.lua @@ -0,0 +1,562 @@ +if SERVER then + + AddCSLuaFile( "shared.lua" ) + +end + +if CLIENT then + + SWEP.ViewModelFOV = 70 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Quick Inventory" + SWEP.IconLetter = "H" + SWEP.Slot = 0 + SWEP.Slotpos = 1 + +end + +SWEP.HoldType = "normal" +SWEP.Base = "rad_base" + +SWEP.ViewModel = "" +SWEP.WorldModel = "" + +SWEP.IsSniper = false +SWEP.AmmoType = "Knife" + +SWEP.Primary.ClipSize = 1 + +SWEP.Scroll = Sound( "ui/buttonrollover.wav" ) +SWEP.Selection = Sound( "ui/buttonclickrelease.wav" ) +SWEP.Cancel = Sound( "common/wpn_denyselect.wav" ) + +SWEP.YPos = 10 +SWEP.XPos = 10 +SWEP.NumPanels = 5 +SWEP.PanelSize = 80 + +function SWEP:Holster() + + if SERVER then return true end + + if self.Deployed then + + self.Deployed = false + + self.Weapon:RemovePanels() + + end + + return true + +end + +function SWEP:Deploy() + + if SERVER then + + self.Weapon:SetNWInt( "InvPos", 1 ) + self.Weapon:SetNWBool( "Synch", false ) + self.Weapon:SetNWBool( "UseMode", false ) + + self.Owner:SynchInventory() + + self.Owner:NoticeOnce( "Right click to scroll through your inventory", GAMEMODE.Colors.Blue, 5, 2 ) + self.Owner:NoticeOnce( "Left click to select an item and use it", GAMEMODE.Colors.Blue, 5, 4 ) + + return true + + end + + if not self.Deployed then + + self.Deployed = true + self.LastInv = Inv_Size() + self.InvPos = 1 + + self.Weapon:GeneratePanels() + + end + + return true + +end + +function SWEP:GeneratePanels() + + self.InvPanels = {} + self.YPosTbl = {} + self.InvItems = Inv_UniqueItems() + + if Inv_Size() == 0 then return end + + for i=1, math.min( self.NumPanels, #self.InvItems ) do + + local id = self.Weapon:GetNWInt( "InvPos", 1 ) + i - 1 + + if id > #self.InvItems then + + id = math.Clamp( id - #self.InvItems, 1, #self.InvItems ) + + end + + local panel = vgui.Create( "ItemPanel" ) + panel:SetItemTable( item.GetByID( self.InvItems[id] ) ) + + if i == 1 then + + panel:SetPos( -self.PanelSize, self.YPos ) + panel:SetSize( self.PanelSize * 1.5, self.PanelSize * 1.5 ) + panel:SetSizeOverride( self.PanelSize * 1.5 ) + panel.YPos = self.YPos + + else + + panel:SetPos( -self.PanelSize, self.YPos + ( self.PanelSize * ( i - 1 ) ) + ( self.PanelSize * 1.5 ) + ( 5 * i ) ) + panel:SetSize( self.PanelSize, self.PanelSize ) + panel:SetSizeOverride( self.PanelSize ) + panel.YPos = self.YPos + ( self.PanelSize * ( i - 2 ) ) + ( self.PanelSize * 1.5 ) + ( 5 * i ) + + end + + self.YPosTbl[i] = panel.YPos + + table.insert( self.InvPanels, panel ) + + end + +end + +function SWEP:AddPanel() // call after removing a panel + + local id = self.Weapon:GetNWInt( "InvPos", 1 ) - 1 + local inv = Inv_UniqueItems() + + if id < 1 then + + id = #inv + + end + + local i = #self.InvPanels + local tbl = item.GetByID( inv[id] ) + + local panel = vgui.Create( "ItemPanel" ) + panel:SetItemTable( tbl ) + panel:SetPos( -self.PanelSize, self.YPosTbl[ i + 1 ] ) + panel:SetSize( self.PanelSize, self.PanelSize ) + panel:SetSizeOverride( self.PanelSize ) + panel.YPos = self.YPosTbl[ i + 1 ] + + table.insert( self.InvPanels, panel ) + +end + +function SWEP:RemovePanels() + + for k,v in pairs( self.InvPanels ) do + + v:Remove() + + end + + self.InvPanels = {} + self.InvItems = {} + self.YPosTbl = {} + +end + +function SWEP:RemovePanel() + + if not self.InvPanels[1] then return end + + self.InvPanels[1].Removal = true + +end + +function SWEP:RemoveAllPanels() + + for k,v in pairs( self.InvPanels ) do + + v.Removal = true + + end + +end + +function SWEP:SecondaryAttack() + + if CLIENT then return end + + self.Weapon:SetNextSecondaryFire( CurTime() + 0.3 ) + + if self.Weapon:GetNWBool( "UseMode", false ) then + + local inv = self.Owner:GetUniqueInventory() + local pos = self.Weapon:GetNWInt( "InvPos", 1 ) + local tbl = item.GetByID( inv[pos] ) + + self.Weapon:SetNWInt( "FuncPos", self.Weapon:GetNWInt( "FuncPos", 1 ) + 1 ) + + if tbl.Weapon then + + if self.Weapon:GetNWInt( "FuncPos", 1 ) > 2 then + + self.Weapon:SetNWInt( "FuncPos", 1 ) + + end + + return + + end + + if self.Weapon:GetNWInt( "FuncPos", 1 ) > ( #self.Functions + 2 ) then + + self.Weapon:SetNWInt( "FuncPos", 1 ) + + end + + else + + local size = #self.Owner:GetUniqueInventory() + local pos = self.Weapon:GetNWInt( "InvPos", 1 ) + 1 + + if pos > size then + + pos = 1 + + end + + self.Weapon:SetNWInt( "InvPos", pos ) + + end + + self.Owner:ClientSound( self.Scroll ) + +end + +function SWEP:PrimaryAttack() + + if CLIENT then return end + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + + local inv = self.Owner:GetUniqueInventory() + local pos = self.Weapon:GetNWInt( "InvPos", 1 ) + local tbl = item.GetByID( inv[pos] ) + + if not tbl then return end + + if self.Weapon:GetNWBool( "UseMode", false ) then + + local fpos = self.Weapon:GetNWInt( "FuncPos", 1 ) + + if tbl.Weapon then + + if fpos == 1 then + + self.Owner:ClientSound( self.Cancel ) + + else + + self.Functions[1]( self.Owner, tbl.ID ) + + end + + self.Weapon:SetNWBool( "UseMode", false ) + self.Weapon:SetNWInt( "FuncPos", 1 ) + self.Weapon:SetNWInt( "InvPos", 1 ) + self.Weapon:Synch() + + return + + end + + if fpos == 1 then + + self.Owner:ClientSound( self.Cancel ) + + elseif fpos == 2 then + + self.Weapon:DropItem( tbl.ID, 1 ) + + else + + self.Functions[ fpos - 2 ]( self.Owner, tbl.ID ) + + end + + self.Weapon:SetNWBool( "UseMode", false ) + self.Weapon:SetNWInt( "FuncPos", 1 ) + self.Weapon:SetNWInt( "InvPos", 1 ) + self.Weapon:Synch() + + else + + self.Weapon:SetNWBool( "UseMode", !self.Weapon:SetNWBool( "UseMode", false ) ) + + self.Functions = tbl.Functions + + self.Owner:ClientSound( self.Selection ) + + end + +end + +function SWEP:DropItem( id, count ) + + if not self.Owner:HasItem( id ) then return end + + local tbl = item.GetByID( id ) + + if count == 1 then + + if self.Owner:HasItem( id ) then + + local makeprop = true + + if tbl.DropFunction then + + makeprop = tbl.DropFunction( self.Owner, id, true ) + + end + + if makeprop then + + local prop = ents.Create( "prop_physics" ) + prop:SetPos( self.Owner:GetItemDropPos() ) + prop:SetAngles( self.Owner:GetAimVector():Angle() ) + prop:SetModel( tbl.Model ) + prop:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + prop:Spawn() + prop.IsItem = true + prop.Removal = CurTime() + 5 * 60 + + end + + self.Owner:RemoveFromInventory( id, true ) + self.Owner:EmitSound( Sound( "items/ammopickup.wav" ) ) + + end + + return + + end + + local items = {} + + for i=1, count do + + if self.Owner:HasItem( id ) then + + table.insert( items, id ) + + end + + end + + local loot = ents.Create( "sent_lootbag" ) + + for k,v in pairs( items ) do + + loot:AddItem( v ) + + end + + loot:SetAngles( self.Owner:GetAimVector():Angle() ) + loot:SetPos( self.Owner:GetItemDropPos() ) + loot:SetRemoval( 60 * 5 ) + loot:Spawn() + + self.Owner:EmitSound( Sound( "items/ammopickup.wav" ) ) + self.Owner:RemoveMultipleFromInventory( items ) + + if tbl.DropFunction then + + tbl.DropFunction( self.Owner, id ) + + end + +end + +function SWEP:Synch() + + umsg.Start( "InvSWEP", self.Owner ) + umsg.End() + +end + +function RecvSynch() + + InvSWEPSynch = true + +end +usermessage.Hook( "InvSWEP", RecvSynch ) + +function SWEP:Think() + + if SERVER then return end + + if not self.Deployed then return end + + local removing = false + + if InvSWEPSynch or self.LastInv != Inv_Size() then + + removing = true + InvSWEPSynch = false + + self.Weapon:RemoveAllPanels() + + end + + self.LastInv = Inv_Size() + + if #self.InvPanels < 1 then + + self.Weapon:GeneratePanels() + + end + + if removing then return end + + if self.Shuffle and #self.InvPanels < 5 then + + for k,v in pairs( self.InvPanels ) do + + v.YPos = self.YPosTbl[k] + + end + + self.Weapon:AddPanel() + + self.Shuffle = false + + end + + if self.InvPos != self.Weapon:GetNWInt( "InvPos", 1 ) then + + self.InvPos = self.Weapon:GetNWInt( "InvPos", 1 ) + + self.Weapon:RemovePanel() + + end + +end + +function SWEP:DrawOption( i, name ) + + surface.SetFont( "InventoryFont" ) + + local w,h = surface.GetTextSize( name ) + local col = Color( 255, 255, 255 ) + + if i == self.Weapon:GetNWInt( "FuncPos", 1 ) then + + col = Color( 50, 255, 50 ) + + end + + draw.RoundedBox( 4, self.PanelSize * 1.5 + 20, 12 + ( i - 1 ) * 25, w + 8, h, Color( 0, 0, 0, 200 ) ) + draw.SimpleText( name, "InventoryFont", self.PanelSize * 1.5 + 24 + ( w * 0.5 ), 12 + ( i - 1 ) * 25 + ( h * 0.5 ), col, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + +end + +function SWEP:DrawHUD() + + if self.Weapon:GetNWBool( "UseMode", false ) then + + local inv = Inv_UniqueItems() + local tbl = item.GetByID( inv[ self.Weapon:GetNWInt( "InvPos", 1 ) ] ) + + if not tbl then return end + + if tbl.Weapon then + + self.Weapon:DrawOption( 1, "cancel" ) + self.Weapon:DrawOption( 2, "drop" ) + + return + + end + + for i=1, #tbl.Functions + 2 do + + if i == 1 then + + self.Weapon:DrawOption( i, "cancel" ) + + elseif i == 2 then + + self.Weapon:DrawOption( i, "drop" ) + + else + + self.Weapon:DrawOption( i, string.lower( tbl.Functions[ i - 2 ]( 0, 0, true ) ) ) + + end + + end + + end + + for k,v in pairs( self.InvPanels or {} ) do + + v.LastX = math.Clamp( math.max( ( v.LastX or self.PanelSize + self.XPos ) - ( FrameTime() * 700 ), 1 ), 0, self.PanelSize + self.XPos ) + v.LastY = math.Clamp( math.max( ( v.LastY or self.YPos ) - ( FrameTime() * 700 ), 1 ), 0, self.PanelSize + self.YPos ) + + if v.LastX != 0 or v.LastY != 0 then // automatically bring the panel into the screen + + v:SetPos( self.XPos - v.LastX, v.YPos - v.LastY ) + + if v.YPos == self.YPosTbl[1] then + + v:SetSize( self.PanelSize * 1.5, self.PanelSize * 1.5 ) + v:SetSizeOverride( self.PanelSize * 1.5 ) + + end + + end + + if v.Removal then + + v.RemoveX = math.Clamp( ( v.RemoveX or self.XPos ) - ( FrameTime() * 700 ), -1 * ( self.PanelSize * 2 ), self.PanelSize + self.XPos ) + + if v.RemoveX != -1 * ( self.PanelSize * 2 ) then + + v:SetPos( v.RemoveX, v.YPos ) + + else + + v:Remove() + + table.remove( self.InvPanels, k ) + + local all = true + + for c,d in pairs( self.InvPanels ) do + + if not d.Removal then + + all = false + + end + + end + + if not all then + + self.Shuffle = true + + end + + break + + end + + end + + end + +end diff --git a/entities/weapons/rad_itemplacer/shared.lua b/entities/weapons/rad_itemplacer/shared.lua new file mode 100644 index 0000000..12dad13 --- /dev/null +++ b/entities/weapons/rad_itemplacer/shared.lua @@ -0,0 +1,295 @@ +if SERVER then + + AddCSLuaFile( "shared.lua" ) + + SWEP.Weight = 1 + SWEP.AutoSwitchTo = false + SWEP.AutoSwitchFrom = false + +end + +if CLIENT then + + ClientItemPlacerTbl = {} + ClientItemPlacerTbl[ "teh" ] = {} + + SWEP.DrawAmmo = true + SWEP.DrawCrosshair = true + SWEP.CSMuzzleFlashes = true + + SWEP.ViewModelFOV = 74 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Item Placement Tool" + SWEP.Slot = 5 + SWEP.Slotpos = 5 + + function SWEP:DrawWeaponSelection( x, y, wide, tall, alpha ) + + end + +end + +SWEP.HoldType = "pistol" + +SWEP.ViewModel = "models/weapons/v_pistol.mdl" +SWEP.WorldModel = "models/weapons/w_pistol.mdl" + +SWEP.Primary.Swap = Sound( "weapons/clipempty_rifle.wav" ) +SWEP.Primary.Sound = Sound( "NPC_CombineCamera.Click" ) +SWEP.Primary.Delete1 = Sound( "Weapon_StunStick.Melee_Hit" ) +SWEP.Primary.Delete = Sound( "Weapon_StunStick.Melee_HitWorld" ) + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.DefaultClip = 99999 +SWEP.Primary.Automatic = false +SWEP.Primary.Ammo = "pistol" + +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "none" + +SWEP.AmmoType = "Knife" + +SWEP.ItemTypes = { "info_player_zombie", +"info_player_army", +"info_lootspawn", +"info_npcspawn", +"info_evac", +"point_radiation" } + +SWEP.ServersideItems = { "info_player_zombie", +"info_player_army", +"info_lootspawn", +"info_npcspawn", +"info_evac", +"point_radiation" } + +SWEP.SharedItems = {} + +function SWEP:Initialize() + + if SERVER then + + self.Weapon:SetWeaponHoldType( self.HoldType ) + + end + +end + +function SWEP:Synch() + + for k,v in pairs( self.ServersideItems ) do + + local ents = ents.FindByClass( v ) + local postbl = {} + + for c,d in pairs( ents ) do + + table.insert( postbl, d:GetPos() ) + + end + + net.Start( "ItemPlacerSynch" ) + net.WriteString( v ) + net.WriteTable( postbl ) + net.Send( self.Owner ) + + //local tbl = { Name = v, Ents = postbl } + + //datastream.StreamToClients( { self.Owner }, "ItemPlacerSynch", tbl ) + + end + +end + +net.Receive( "ItemPlacerSynch", function( len ) + + ClientItemPlacerTbl[ net.ReadString() ] = net.ReadTable() + +end ) + +--[[function PlacerSynch( handler, id, encoded, decoded ) + + ClientItemPlacerTbl[ decoded.Name ] = decoded.Ents + +end +datastream.Hook( "ItemPlacerSynch", PlacerSynch )]] + +function SWEP:Deploy() + + if SERVER then + + self.Weapon:Synch() + + end + + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + + return true + +end + +function SWEP:Think() + + if CLIENT then return end + + if self.Owner:KeyDown( IN_USE ) and ( ( self.NextDel or 0 ) < CurTime() ) then + + self.NextDel = CurTime() + 1 + + local tr = util.TraceLine( util.GetPlayerTrace( self.Owner ) ) + + local closest + local dist = 1000 + + for k,v in pairs( ents.FindByClass( self.ItemTypes[ self.Weapon:GetNWInt( "ItemType", 1 ) ] ) ) do + + if v:GetPos():Distance( tr.HitPos ) < dist then + + dist = v:GetPos():Distance( tr.HitPos ) + closest = v + + end + + end + + if IsValid( closest ) then + + closest:Remove() + + self.Owner:EmitSound( self.Primary.Delete1 ) + + self.Weapon:Synch() + + end + + end + +end + +function SWEP:Reload() + + if CLIENT then return end + + for k,v in pairs( ents.FindByClass( self.ItemTypes[ self.Weapon:GetNWInt( "ItemType", 1 ) ] ) ) do + + v:Remove() + + end + + self.Weapon:Synch() + + self.Owner:EmitSound( self.Primary.Delete ) + +end + +function SWEP:Holster() + + return true + +end + +function SWEP:ShootEffects() + + self.Owner:MuzzleFlash() + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + +end + +function SWEP:PlaceItem() + + local itemtype = self.ItemTypes[ self.Weapon:GetNWInt( "ItemType", 1 ) ] + + local tr = util.TraceLine( util.GetPlayerTrace( self.Owner ) ) + + local ent = ents.Create( itemtype ) + ent:SetPos( tr.HitPos + tr.HitNormal * 5 ) + ent:Spawn() + ent.AdminPlaced = true + +end + +function SWEP:PrimaryAttack() + + self.Weapon:SetNextPrimaryFire( CurTime() + 1 ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) ) + self.Weapon:ShootEffects() + + if SERVER then + + self.Weapon:PlaceItem() + + self.Weapon:Synch() + + end + +end + +function SWEP:SecondaryAttack() + + self.Weapon:SetNextSecondaryFire( CurTime() + 0.5 ) + + self.Weapon:EmitSound( self.Primary.Swap ) + + if SERVER then + + self.Weapon:SetNWInt( "ItemType", self.Weapon:GetNWInt( "ItemType", 1 ) + 1 ) + + if self.Weapon:GetNWInt( "ItemType", 1 ) > #self.ItemTypes then + + self.Weapon:SetNWInt( "ItemType", 1 ) + + end + + end + +end + +function SWEP:DrawHUD() + + draw.SimpleText( "PRIMARY FIRE: Place Item SECONDARY FIRE: Change Item Type +USE: Delete Nearest Item Of Current Type RELOAD: Remove All Of Current Item Type", "AmmoFontSmall", ScrW() * 0.5, ScrH() - 120, Color(255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + draw.SimpleText( "CURRENT ITEM TYPE: "..self.ItemTypes[ self.Weapon:GetNWInt( "ItemType", 1 ) ], "AmmoFontSmall", ScrW() * 0.5, ScrH() - 100, Color(255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + for k,v in pairs( self.SharedItems ) do + + for c,d in pairs( ents.FindByClass( v ) ) do + + local pos = d:GetPos():ToScreen() + + if pos.visible then + + draw.SimpleText( v, "AmmoFontSmall", pos.x, pos.y - 15, Color(80,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + draw.RoundedBox( 0, pos.x - 2, pos.y - 2, 4, 4, Color(255,255,255) ) + + end + + end + + end + + for k,v in pairs( ClientItemPlacerTbl ) do + + for c,d in pairs( v ) do + + local vec = Vector( d[1], d[2], d[3] ) + + local pos = vec:ToScreen() + + if pos.visible then + + draw.SimpleText( k, "AmmoFontSmall", pos.x, pos.y - 15, Color(80,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + draw.RoundedBox( 0, pos.x - 2, pos.y - 2, 4, 4, Color(255,255,255) ) + + end + + end + + end + +end + + diff --git a/entities/weapons/rad_knife/shared.lua b/entities/weapons/rad_knife/shared.lua new file mode 100644 index 0000000..8b06c17 --- /dev/null +++ b/entities/weapons/rad_knife/shared.lua @@ -0,0 +1,199 @@ +if SERVER then + + AddCSLuaFile( "shared.lua" ) + +end + +if CLIENT then + + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Knife" + SWEP.IconLetter = "j" + SWEP.Slot = 1 + SWEP.Slotpos = 0 + +end + +SWEP.HoldType = "knife" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_knife_t.mdl" +SWEP.WorldModel = "models/weapons/w_knife_t.mdl" + +SWEP.IsSniper = false +SWEP.AmmoType = "Knife" + +SWEP.Primary.Hit = Sound( "Weapon_Knife.HitWall" ) +SWEP.Primary.HitFlesh = Sound( "Weapon_Knife.Hit" ) +SWEP.Primary.Sound = Sound( "Weapon_Knife.Slash" ) +SWEP.Primary.Deploy = Sound( "Weapon_Knife.Deploy" ) +SWEP.Primary.Recoil = 3.5 +SWEP.Primary.Damage = 35 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Delay = 0.950 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = true + +function SWEP:GetViewModelPosition( pos, ang ) + + return pos, ang + +end + +function SWEP:SecondaryAttack() + +end + +function SWEP:PrimaryAttack() + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:MeleeTrace( self.Primary.Damage ) + + if SERVER then + + self.Owner:AddStamina( -1 ) + + end + +end + +function SWEP:Think() + +end + +function SWEP:MeleeTrace( dmg ) + + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SendWeaponAnim( ACT_VM_MISSCENTER ) + + if CLIENT then return end + + local pos = self.Owner:GetShootPos() + local aim = self.Owner:GetAimVector() * 64 + + local line = {} + line.start = pos + line.endpos = pos + aim + line.filter = self.Owner + + local linetr = util.TraceLine( line ) + + local tr = {} + tr.start = pos + self.Owner:GetAimVector() * -5 + tr.endpos = pos + aim + tr.filter = self.Owner + tr.mask = MASK_SHOT_HULL + tr.mins = Vector(-20,-20,-20) + tr.maxs = Vector(20,20,20) + + local trace = util.TraceHull( tr ) + local ent = trace.Entity + local ent2 = linetr.Entity + + if not IsValid( ent ) and IsValid( ent2 ) then + + ent = ent2 + + end + + if not IsValid( ent ) then + + self.Owner:EmitSound( self.Primary.Sound, 100, math.random(90,110) ) + return + + elseif not ent:IsWorld() then + + self.Weapon:SendWeaponAnim( ACT_VM_HITCENTER ) + self.Owner:AddStamina( -2 ) + + if ent:IsPlayer() then + + ent:EmitSound( self.Primary.HitFlesh, 100, math.random(90,110) ) + + if ent:Team() != self.Owner:Team() then + + ent:TakeDamage( dmg, self.Owner, self.Weapon ) + + self.Owner:DrawBlood() + + local ed = EffectData() + ed:SetOrigin( trace.HitPos ) + util.Effect( "BloodImpact", ed, true, true ) + + end + + elseif string.find( ent:GetClass(), "npc" ) then + + ent:TakeDamage( dmg, self.Owner, self.Weapon ) + ent:EmitSound( self.Primary.HitFlesh, 100, math.random(90,110) ) + + self.Owner:DrawBlood() + + local ed = EffectData() + ed:SetOrigin( trace.HitPos ) + util.Effect( "BloodImpact", ed, true, true ) + + elseif !ent:IsPlayer() then + + if string.find( ent:GetClass(), "breakable" ) then + + ent:TakeDamage( 50, self.Owner, self.Weapon ) + + if ent:GetClass() == "func_breakable_surf" then + + ent:Fire( "shatter", "1 1 1", 0 ) + + end + + end + + ent:EmitSound( self.Primary.Hit, 100, math.random(90,110) ) + + local phys = ent:GetPhysicsObject() + + if IsValid( phys ) then + + if ent.IsWooden then + + ent:Fire( "break", 0, 0 ) + + else + + ent:SetPhysicsAttacker( self.Owner ) + ent:TakeDamage( 10, self.Owner, self.Weapon ) + + phys:Wake() + phys:ApplyForceCenter( self.Owner:GetAimVector() * phys:GetMass() * 200 ) + + end + + end + + end + + end + +end + +function SWEP:DrawHUD() + +end + +function SWEP:Deploy() + + if SERVER then + + self.Owner:DrawViewModel( true ) + self.Owner:EmitSound( self.Primary.Deploy, 100, math.random(90,110) ) + + end + + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + + return true + +end diff --git a/entities/weapons/rad_m1014/shared.lua b/entities/weapons/rad_m1014/shared.lua new file mode 100644 index 0000000..9d4ca65 --- /dev/null +++ b/entities/weapons/rad_m1014/shared.lua @@ -0,0 +1,299 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "M1014 Shotgun" + SWEP.IconLetter = "B" + SWEP.Slot = 3 + SWEP.Slotpos = 3 + +end + +SWEP.HoldType = "shotgun" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_shot_xm1014.mdl" +SWEP.WorldModel = "models/weapons/w_shot_xm1014.mdl" + +SWEP.SprintPos = Vector(-0.6026, -2.715, 0.0137) +SWEP.SprintAng = Vector(-3.4815, -21.9362, 0.0001) + +SWEP.IsSniper = false +SWEP.AmmoType = "Buckshot" + +SWEP.Primary.Sound = Sound( "weapons/shotgun/shotgun_fire6.wav" ) +SWEP.Primary.Recoil = 9.5 +SWEP.Primary.Damage = 30 +SWEP.Primary.NumShots = 8 +SWEP.Primary.Cone = 0.080 +SWEP.Primary.Delay = 0.320 + +SWEP.Primary.ClipSize = 8 +SWEP.Primary.Automatic = true + +function SWEP:Deploy() + + self.Weapon:SetNWBool( "Reloading", false ) + self.Weapon:SetVar( "PumpTime", 0 ) + self.Weapon:SetNextPrimaryFire( CurTime() + 0.3 ) + + if SERVER then + + self.Weapon:SetZoomMode( 1 ) + + end + + self.InIron = false + + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + + return true + +end + +function SWEP:CanPrimaryAttack() + + if self.HolsterMode or self.LastRunFrame > CurTime() then return false end + + if self.Owner:GetNWInt( "Ammo"..self.AmmoType, 0 ) < 1 then + + self.Weapon:EmitSound( self.Primary.Empty ) + return false + + end + + if self.Weapon:GetNWBool( "Reloading", false ) then + + self.Weapon:SetNWBool( "Reloading", false ) + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + + self.Weapon:SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH ) + + return false + + end + + if self.Weapon:Clip1() <= 0 then + + self.Weapon:SetNWBool( "Reloading", true ) + self.Weapon:SetVar( "ReloadTimer", CurTime() + 0.5 ) + self.Weapon:SendWeaponAnim( ACT_VM_RELOAD ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:SetClip1( self.Weapon:Clip1() + 1 ) + + return false + + end + + return true + +end + +function SWEP:PrimaryAttack() + + if not self.Weapon:CanPrimaryAttack() then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + return + + end + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) ) + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.Cone, self.Weapon:GetZoomMode() ) + self.Weapon:TakePrimaryAmmo( 1 ) + self.Weapon:ShootEffects() + + if self.Weapon:GetZoomMode() > 1 then + + self.Weapon:UnZoom() + + end + + if SERVER then + + self.Owner:AddAmmo( self.AmmoType, -1 ) + + end + +end + +function SWEP:Reload() + + if self.HolsterMode or self.Weapon:Clip1() == self.Primary.ClipSize then return end + + if self.Weapon:Clip1() < self.Primary.ClipSize and not self.Weapon:GetNWBool( "Reloading", false ) then + + self.Weapon:SetNWBool( "Reloading", true ) + self.Weapon:SetVar( "ReloadTimer", CurTime() + 0.5 ) + self.Weapon:SendWeaponAnim( ACT_VM_RELOAD ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:SetClip1( self.Weapon:Clip1() + 1 ) + + end + +end + +function SWEP:Think() + + if self.Owner:KeyDown( IN_WALK ) and self.HolsterTime < CurTime() then + + self.HolsterTime = CurTime() + 2 + --[[self.HolsterMode = !self.HolsterMode + + if self.HolsterMode then + + self.Owner:SetLuaAnimation( self.HoldType ) + + else + + self.Owner:StopAllLuaAnimations( 0.5 ) + + end]] + + end + + if self.Weapon:GetNWBool( "Reloading", false ) then + + if self.Weapon:GetVar( "ReloadTimer", 0 ) < CurTime() then + + // Finsished reload + if self.Weapon:Clip1() >= self.Primary.ClipSize then + + self.Weapon:SetNWBool( "Reloading", false ) + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + + self.Weapon:SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH ) + + return + + end + + // Next cycle + self.Weapon:SetVar( "ReloadTimer", CurTime() + 0.75 ) + self.Weapon:SendWeaponAnim( ACT_VM_RELOAD ) + + // Add ammo + self.Weapon:SetClip1( self.Weapon:Clip1() + 1 ) + + end + + end + + if self.Owner:GetVelocity():Length() > 0 then + + if self.Owner:KeyDown( IN_SPEED ) then + + self.LastRunFrame = CurTime() + 0.3 + + end + + end + +end + +function SWEP:ShootBullets( damage, numbullets, aimcone, zoommode ) + + if SERVER then + + self.Owner:AddStat( "Bullets", 1 ) + + end + + local scale = aimcone + + if self.Owner:KeyDown( IN_FORWARD ) or self.Owner:KeyDown( IN_BACK ) or self.Owner:KeyDown( IN_MOVELEFT ) or self.Owner:KeyDown( IN_MOVERIGHT ) then + + scale = aimcone * 1.75 + + elseif self.Owner:KeyDown( IN_DUCK ) or self.Owner:KeyDown( IN_WALK ) then + + scale = math.Clamp( aimcone / 1.25, 0, 10 ) + + end + + local tracer = 1 + + if ( zoommode or 1 ) > 1 then + + tracer = 0 + + end + + local bullet = {} + bullet.Num = numbullets + bullet.Src = self.Owner:GetShootPos() + bullet.Dir = self.Owner:GetAimVector() + bullet.Spread = Vector( scale, scale, 0 ) + bullet.Tracer = 0 + bullet.Force = damage * 2 + bullet.Damage = damage + bullet.AmmoType = "Pistol" + bullet.TracerName = tracername + bullet.Callback = function ( attacker, tr, dmginfo ) + + dmginfo:ScaleDamage( self:GetDamageFalloffScale( tr.HitPos:Distance( self.Owner:GetShootPos() ) ) ) + + if tr.Entity.NextBot then + + tr.Entity:OnLimbHit( tr.HitGroup, dmginfo ) + + end + + if math.random(1,6) == 1 then + + self.Weapon:BulletPenetration( attacker, tr, dmginfo, 0 ) + + end + + end + + self.Owner:FireBullets( bullet ) + +end + +function SWEP:DrawHUD() + + if self.Weapon:ShouldNotDraw() then return end + + if not self.IsSniper and not self.Owner:GetNWBool( "InIron", false ) then + + local x = ScrW() * 0.5 + local y = ScrH() * 0.5 + local scalebywidth = ( ScrW() / 1024 ) * 10 + local scale = self.Primary.Cone + + if self.Owner:KeyDown( IN_FORWARD ) or self.Owner:KeyDown( IN_BACK ) or self.Owner:KeyDown( IN_MOVELEFT ) or self.Owner:KeyDown( IN_MOVERIGHT ) then + + scale = self.Primary.Cone * 1.75 + + elseif self.Owner:KeyDown( IN_DUCK ) or self.Owner:KeyDown( IN_WALK ) then + + scale = math.Clamp( self.Primary.Cone / 1.25, 0, 10 ) + + end + + scale = scale * scalebywidth + + local dist = math.abs( self.CrosshairScale - scale ) + self.CrosshairScale = math.Approach( self.CrosshairScale, scale, FrameTime() * 2 + dist * 0.05 ) + + local gap = 40 * self.CrosshairScale + local length = gap + self.CrossLength:GetInt() + + surface.SetDrawColor( self.CrossRed:GetInt(), self.CrossGreen:GetInt(), self.CrossBlue:GetInt(), self.CrossAlpha:GetInt() ) + surface.DrawLine( x - length, y, x - gap, y ) + surface.DrawLine( x + length, y, x + gap, y ) + surface.DrawLine( x, y - length, x, y - gap ) + surface.DrawLine( x, y + length, x, y + gap ) + + end + +end diff --git a/entities/weapons/rad_m249/shared.lua b/entities/weapons/rad_m249/shared.lua new file mode 100644 index 0000000..7e72cd2 --- /dev/null +++ b/entities/weapons/rad_m249/shared.lua @@ -0,0 +1,40 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = false + + SWEP.PrintName = "M249 SAW" + SWEP.IconLetter = "z" + SWEP.Slot = 4 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "ar2" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_mach_m249para.mdl" +SWEP.WorldModel = "models/weapons/w_mach_m249para.mdl" + +SWEP.SprintPos = Vector (4.0541, -2.0077, -5.4061) +SWEP.SprintAng = Vector (11.4322, 40.43, -7.9447) + +SWEP.IsSniper = false +SWEP.AmmoType = "Rifle" + +SWEP.Primary.Sound = Sound( "Weapon_M249.Single" ) +SWEP.Primary.Recoil = 9.5 +SWEP.Primary.Damage = 75 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.040 +SWEP.Primary.Delay = 0.090 + +SWEP.Primary.ClipSize = 100 +SWEP.Primary.Automatic = true + diff --git a/entities/weapons/rad_mac10/shared.lua b/entities/weapons/rad_mac10/shared.lua new file mode 100644 index 0000000..3e95b6e --- /dev/null +++ b/entities/weapons/rad_mac10/shared.lua @@ -0,0 +1,39 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "MAC 10" + SWEP.IconLetter = "l" + SWEP.Slot = 3 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "revolver" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_smg_mac10.mdl" +SWEP.WorldModel = "models/weapons/w_smg_mac10.mdl" + +SWEP.SprintPos = Vector(-4.7699, -7.2246, -2.8428) +SWEP.SprintAng = Vector(4.4604, -47.001, 6.8488) + +SWEP.IsSniper = false +SWEP.AmmoType = "SMG" + +SWEP.Primary.Sound = Sound( "Weapon_mac10.Single" ) +SWEP.Primary.Recoil = 6.5 +SWEP.Primary.Damage = 30 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.050 +SWEP.Primary.Delay = 0.080 + +SWEP.Primary.ClipSize = 40 +SWEP.Primary.Automatic = true diff --git a/entities/weapons/rad_mp5/shared.lua b/entities/weapons/rad_mp5/shared.lua new file mode 100644 index 0000000..e41ef49 --- /dev/null +++ b/entities/weapons/rad_mp5/shared.lua @@ -0,0 +1,39 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "HK MP5" + SWEP.IconLetter = "x" + SWEP.Slot = 3 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "smg" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_smg_mp5.mdl" +SWEP.WorldModel = "models/weapons/w_smg_mp5.mdl" + +SWEP.SprintPos = Vector(-0.6026, -2.715, 0.0137) +SWEP.SprintAng = Vector(-3.4815, -21.9362, 0.0001) + +SWEP.IsSniper = false +SWEP.AmmoType = "SMG" + +SWEP.Primary.Sound = Sound( "Weapon_MP5Navy.Single" ) +SWEP.Primary.Recoil = 5.5 +SWEP.Primary.Damage = 40 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.035 +SWEP.Primary.Delay = 0.085 + +SWEP.Primary.ClipSize = 30 +SWEP.Primary.Automatic = true diff --git a/entities/weapons/rad_p228/shared.lua b/entities/weapons/rad_p228/shared.lua new file mode 100644 index 0000000..56c1415 --- /dev/null +++ b/entities/weapons/rad_p228/shared.lua @@ -0,0 +1,39 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "P228 Compact" + SWEP.IconLetter = "y" + SWEP.Slot = 2 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "pistol" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_pist_p228.mdl" +SWEP.WorldModel = "models/weapons/w_pist_p228.mdl" + +SWEP.SprintPos = Vector(-0.8052, 0, 3.0657) +SWEP.SprintAng = Vector(-16.9413, -5.786, 4.0159) + +SWEP.IsSniper = false +SWEP.AmmoType = "Pistol" + +SWEP.Primary.Sound = Sound( "Weapon_P228.Single" ) +SWEP.Primary.Recoil = 5.5 +SWEP.Primary.Damage = 25 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.035 +SWEP.Primary.Delay = 0.150 + +SWEP.Primary.ClipSize = 12 +SWEP.Primary.Automatic = false diff --git a/entities/weapons/rad_p90/shared.lua b/entities/weapons/rad_p90/shared.lua new file mode 100644 index 0000000..2055466 --- /dev/null +++ b/entities/weapons/rad_p90/shared.lua @@ -0,0 +1,42 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "FN P90" + SWEP.IconLetter = "l" + SWEP.Slot = 3 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "rpg" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_smg_p90.mdl" +SWEP.WorldModel = "models/weapons/w_smg_p90.mdl" + +SWEP.SprintPos = Vector(-4.7699, -7.2246, -2.8428) +SWEP.SprintAng = Vector(4.4604, -47.001, 6.8488) + +SWEP.IsSniper = false +SWEP.AmmoType = "SMG" + +SWEP.LaserOffset = Angle( 39.9, -50, -90 ) +SWEP.LaserScale = 0.75 + +SWEP.Primary.Sound = Sound( "Weapon_p90.Single" ) +SWEP.Primary.Recoil = 6.5 +SWEP.Primary.Damage = 40 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.040 +SWEP.Primary.Delay = 0.075 + +SWEP.Primary.ClipSize = 50 +SWEP.Primary.Automatic = true diff --git a/entities/weapons/rad_propplacer/shared.lua b/entities/weapons/rad_propplacer/shared.lua new file mode 100644 index 0000000..77a0e96 --- /dev/null +++ b/entities/weapons/rad_propplacer/shared.lua @@ -0,0 +1,382 @@ +if SERVER then + + AddCSLuaFile( "shared.lua" ) + + SWEP.Weight = 1 + SWEP.AutoSwitchTo = false + SWEP.AutoSwitchFrom = false + +end + +if CLIENT then + + SWEP.DrawAmmo = true + SWEP.DrawCrosshair = true + SWEP.CSMuzzleFlashes = true + + SWEP.ViewModelFOV = 74 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Prop Placement Tool" + SWEP.Slot = 5 + SWEP.Slotpos = 7 + + function SWEP:DrawWeaponSelection( x, y, wide, tall, alpha ) + + end + +end + +SWEP.HoldType = "pistol" + +SWEP.ViewModel = "models/weapons/v_pistol.mdl" +SWEP.WorldModel = "models/weapons/w_pistol.mdl" + +SWEP.Primary.Swap = Sound( "weapons/clipempty_rifle.wav" ) +SWEP.Primary.Sound = Sound( "NPC_CombineCamera.Click" ) +SWEP.Primary.Delete = Sound( "Weapon_StunStick.Melee_HitWorld" ) + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.DefaultClip = 99999 +SWEP.Primary.Automatic = false +SWEP.Primary.Ammo = "pistol" + +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "none" + +SWEP.AmmoType = "Knife" + +SWEP.PropList = { "models/props_c17/oildrum001.mdl", +"models/props_c17/canister02a.mdl", +"models/props_c17/furniturewashingmachine001a.mdl", +"models/props_c17/pulleywheels_large01.mdl", +"models/props_c17/pulleywheels_small01.mdl", +"models/props_c17/chair02a.mdl", +"models/props_c17/concrete_barrier001a.mdl", +"models/props_c17/door01_left.mdl", +"models/props_c17/fence01a.mdl", +"models/props_c17/fence01b.mdl", +"models/props_c17/fence03a.mdl", +"models/props_c17/lockers001a.mdl", +"models/props_c17/traffic_light001a.mdl", +"models/props_c17/trappropeller_engine.mdl", +"models/props_c17/furniturebathtub001a.mdl", +"models/props_c17/furniturefridge001a.mdl", +"models/props_interiors/refrigerator01a.mdl", +"models/props_interiors/refrigeratordoor01a.mdl", +"models/props_interiors/vendingmachinesoda01a.mdl", +"models/props_wasteland/cargo_container01.mdl", +"models/props_wasteland/controlroom_storagecloset001a.mdl", +"models/props_wasteland/laundry_cart001.mdl", +"models/props_wasteland/controlroom_chair001a.mdl", +"models/props_wasteland/controlroom_desk001a.mdl", +"models/props_wasteland/controlroom_desk001b.mdl", +"models/props_wasteland/controlroom_filecabinet002a.mdl", +"models/props_wasteland/controlroom_filecabinet001a.mdl", +"models/props_wasteland/laundry_cart002.mdl", +"models/props_wasteland/dockplank01b.mdl", +"models/props_wasteland/barricade001a.mdl", +"models/props_wasteland/barricade002a.mdl", +"models/props_wasteland/wheel01.mdl", +"models/props_wasteland/buoy01.mdl", +"models/props_wasteland/prison_bedframe001b.mdl", +"models/props_wasteland/kitchen_fridge001a.mdl", +"models/props_vehicles/car001a_hatchback.mdl", +"models/props_vehicles/car001b_hatchback.mdl", +"models/props_vehicles/car002a_physics.mdl", +"models/props_vehicles/car002b_physics.mdl", +"models/props_vehicles/car003a_physics.mdl", +"models/props_vehicles/car003b_physics.mdl", +"models/props_vehicles/car004a_physics.mdl", +"models/props_vehicles/car004b_physics.mdl", +"models/props_vehicles/car005b_physics.mdl", +"models/props_vehicles/van001a_physics.mdl", +"models/props_vehicles/generatortrailer01.mdl", +"models/props_vehicles/trailer002a.mdl", +"models/props_vehicles/truck001a.mdl", +"models/props_vehicles/carparts_door01a.mdl", +"models/props_vehicles/carparts_wheel01a.mdl", +"models/props_vehicles/carparts_tire01a.mdl", +"models/props_vehicles/carparts_axel01a.mdl", +"models/props_vehicles/tire001b_truck.mdl", +"models/props_vehicles/tire001a_tractor.mdl", +"models/props_trainstation/train003.mdl", +"models/props_canal/boat001a.mdl", +"models/props_canal/boat001b.mdl", +"models/props_canal/boat002b.mdl", +"models/props_debris/metal_panel01a.mdl", +"models/props_debris/metal_panel02a.mdl", +"models/props_junk/trashdumpster02b.mdl", +"models/props_junk/ravenholmsign.mdl", +"models/props_junk/ibeam01a.mdl", +"models/props_junk/ibeam01a_cluster01.mdl", +"models/props_junk/wood_pallet001a.mdl", +"models/props_junk/propanecanister001a.mdl", +"models/props_junk/pushcart01a.mdl", +"models/props_junk/cinderblock01a.mdl", +"models/props_junk/wood_crate001a.mdl", +"models/props_junk/wood_crate002a.mdl", +"models/props_junk/trashdumpster01a.mdl", +"models/props_junk/wheebarrow01a.mdl", +"models/props_junk/metalgascan.mdl", +"models/props_junk/trashdumpster02.mdl", +//"models/props/de_train/barrel.mdl", +"models/props/de_train/pallet_barrels.mdl", +"models/props/de_prodigy/tirestack.mdl", +"models/props/de_prodigy/tirestack2.mdl", +"models/props/de_prodigy/tirestack3.mdl", +"models/props/de_prodigy/concretebags.mdl", +"models/props/de_prodigy/concretebags2.mdl", +"models/props/de_prodigy/concretebags3.mdl", +"models/props/de_prodigy/concretebags4.mdl", +"models/props/de_prodigy/pushcart.mdl", +"models/props/de_prodigy/spoolwire.mdl", +"models/props/de_prodigy/spool.mdl", +"models/props/de_prodigy/ammo_can_02.mdl", +"models/props/de_prodigy/ammo_can_01.mdl", +"models/props/de_prodigy/ammo_can_03.mdl", +"models/props/de_nuke/cinderblock_stack.mdl", +"models/props/cs_militia/militiarock05.mdl", +"models/props/cs_militia/sawhorse.mdl", +"models/props/cs_militia/table_kitchen.mdl", +"models/props/cs_militia/footlocker01_open.mdl", +"models/props/cs_militia/footlocker01_closed.mdl", +"models/props_junk/MetalBucket01a.mdl", +"models/props_junk/MetalBucket02a.mdl", +"models/props_junk/plasticbucket001a.mdl", +"models/props_wasteland/kitchen_shelf001a.mdl", +"models/props_c17/chair_stool01a.mdl", +"models/props_c17/chair_office01a.mdl", +"models/props_c17/SuitCase001a.mdl", +"models/props_interiors/Radiator01a.mdl", +"models/props_junk/bicycle01a.mdl", +"models/props_lab/citizenradio.mdl", +"models/props_lab/kennel_physics.mdl", +"models/props_lab/partsbin01.mdl", +"models/props_vehicles/carparts_muffler01a.mdl", +"models/props/cs_office/shelves_metal.mdl", +"models/props_phx/construct/concrete_barrier01.mdl", +"models/props_phx/construct/concrete_barrier00.mdl", +"models/props/cs_assault/handtruck.mdl", +"models/props/de_nuke/nuclearcontainerboxclosed.mdl", +"models/props/de_nuke/crate_small.mdl", +"models/props_vehicles/trailer001a.mdl", +"models/props_lab/lockers.mdl", +"models/props_trainstation/train002.mdl", +"models/props_vehicles/wagon001a.mdl", +"models/props_wasteland/gear01.mdl", +"models/props_wasteland/cafeteria_bench001a.mdl", +"models/props_wasteland/cafeteria_table001a.mdl", +"models/props/CS_militia/crate_extrasmallmill.mdl", +"models/props/CS_militia/microwave01.mdl", +"models/props/CS_militia/paintbucket01.mdl", +"models/props/CS_militia/refrigerator01.mdl", +"models/props/CS_militia/toilet.mdl", +"models/props/CS_militia/wood_table.mdl", +"models/props/cs_italy/it_mkt_table2.mdl", +"models/props/de_inferno/wine_barrel.mdl", +"models/props_c17/streetsign004f.mdl", +"models/props_c17/FurnitureDresser001a.mdl", +"models/props_vehicles/truck003a.mdl", +"models/items/car_battery01.mdl", +"models/props_c17/canister_propane01a.mdl", +"models/props_junk/metal_paintcan001b.mdl"} + +function SWEP:Initialize() + + if SERVER then + + self.Weapon:SetWeaponHoldType( self.HoldType ) + + end + +end + +function SWEP:Deploy() + + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + + return true + +end + +function SWEP:Think() + + if CLIENT then return end + + if self.Owner:KeyDown( IN_USE ) and ( ( self.NextDel or 0 ) < CurTime() ) then + + self.NextDel = CurTime() + 1 + + local tr = util.TraceLine( util.GetPlayerTrace( self.Owner ) ) + + local closest + local dist = 1000 + + for k,v in pairs( ents.FindByClass( "prop_physics" ) ) do + + if v:GetPos():Distance( tr.HitPos ) < dist and v.AdminPlaced then + + dist = v:GetPos():Distance( tr.HitPos ) + closest = v + + end + + end + + if IsValid( closest ) then + + closest:Remove() + + self.Owner:EmitSound( self.Primary.Delete ) + + end + + end + +end + +function SWEP:Reload() + + if CLIENT then return end + + for k,v in pairs( ents.FindByClass( "prop_physics" ) ) do + + if v.AdminPlaced then + + v:Remove() + + end + + end + + self.Owner:EmitSound( self.Primary.Delete ) + +end + +function SWEP:Holster() + + return true + +end + +function SWEP:ShootEffects() + + self.Owner:MuzzleFlash() + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + +end + +function SWEP:PlaceItem() + + if not self.Owner:IsAdmin() or not self.Owner:IsSuperAdmin() then return end + + if not self.Owner.PropPos then self.Owner.PropPos = 1 end + + if self.Owner.PropPos < 1 or self.Owner.PropPos > #self.PropList then return end + + local tr = util.TraceLine( util.GetPlayerTrace( self.Owner ) ) + + local ent = ents.Create( "prop_physics" ) + ent:SetPos( tr.HitPos + tr.HitNormal * 50 ) + ent:SetModel( self.PropList[ self.Owner.PropPos ] ) + ent:SetSkin( math.random( 0, 6 ) ) + ent:Spawn() + ent.AdminPlaced = true + +end + +function SWEP:PrimaryAttack() + + self.Weapon:SetNextPrimaryFire( CurTime() + 1 ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) ) + self.Weapon:ShootEffects() + + if SERVER then + + self.Weapon:PlaceItem() + + end + +end + +function SWEP:SecondaryAttack() + + self.Weapon:SetNextSecondaryFire( CurTime() + 0.5 ) + + self.Weapon:EmitSound( self.Primary.Swap ) + + if CLIENT then + + self.Weapon:Menu() + + end + +end + +function SWEP:DrawHUD() + + draw.SimpleText( "PRIMARY FIRE: Create Prop SECONDARY FIRE: Choose Prop Model +USE: Delete Nearest Prop RELOAD: Remove All Placed Props", "AmmoFontSmall", ScrW() * 0.5, ScrH() - 100, Color(255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + +end + +if CLIENT then + + function SWEP:Menu() + + if ( self.MenuTime or 0 ) > CurTime() then return end + + self.MenuTime = CurTime() + 1 + + gui.EnableScreenClicker( true ) + + local frame = vgui.Create( "PanelBase" ) + frame:SetSize( 300, 370 ) + frame:Center() + //frame:ShowCloseButton( false ) + + local plist = vgui.Create( "DPanelList", frame ) + plist:SetPos( 15, 15 ) + plist:SetSize( 270, 340 ) + plist:SetSpacing( 0 ) + plist:EnableHorizontal( true ) + plist:EnableVerticalScrollbar( true ) + + for k, v in pairs( self.PropList ) do + + local icon = vgui.Create( "SpawnIcon", plist ) + icon:SetModel( v ) + icon:SetToolTip() + icon:SetSize( 64, 64 ) + icon.OnMousePressed = function( mc ) + + RunConsoleCommand( "chooseprop", tostring( k ) ) + + gui.EnableScreenClicker( false ) + surface.PlaySound( Sound( "buttons/button14.wav" ) ) + + frame:Remove() + + end + + plist:AddItem( icon ) + + end + + end + + return + +end + +function ChooseProp( ply, cmd, args ) + + ply.PropPos = tonumber( args[1] ) + +end + +concommand.Add( "chooseprop", ChooseProp ) diff --git a/entities/weapons/rad_revolver/shared.lua b/entities/weapons/rad_revolver/shared.lua new file mode 100644 index 0000000..2b34184 --- /dev/null +++ b/entities/weapons/rad_revolver/shared.lua @@ -0,0 +1,71 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFOV = 70 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Colt Python" + SWEP.IconLetter = "f" + SWEP.Slot = 2 + SWEP.Slotpos = 1 + +end + +SWEP.HoldType = "revolver" + +SWEP.Base = "rad_base" + +SWEP.UseHands = true + +SWEP.ViewModel = "models/weapons/c_357.mdl" +SWEP.WorldModel = "models/weapons/w_357.mdl" + +SWEP.SprintPos = Vector (2.4955, 2.1219, 2.9007) +SWEP.SprintAng = Vector (-10.2034, 15.2433, 0) + +SWEP.IsSniper = false +SWEP.AmmoType = "Pistol" + +SWEP.Primary.Sound = Sound( "Weapon_357.Single" ) +SWEP.Primary.Recoil = 13.5 +SWEP.Primary.Damage = 50 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.030 +SWEP.Primary.Delay = 0.850 + +SWEP.Primary.ClipSize = 6 +SWEP.Primary.Automatic = false + +function SWEP:ShootEffects() + + if SERVER then + + self.Owner:ViewBounce( self.Primary.Recoil ) + + end + + self.Owner:MuzzleFlash() + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + + if CLIENT then return end + + local tbl = self.ShellSounds[ ( self.Primary.ShellType or 1 ) ] + local pos = self.Owner:GetPos() + + //timer.Simple( math.Rand( self.MinShellDelay, self.MaxShellDelay ), function() sound.Play( table.Random( tbl.Wavs ), pos, 75, tbl.Pitch ) end ) + + --[[local ed = EffectData() + ed:SetOrigin( self.Owner:GetShootPos() ) + ed:SetEntity( self.Weapon ) + ed:SetAttachment( self.Weapon:LookupAttachment( "2" ) ) + ed:SetScale( ( self.Primary.ShellType or SHELL_9MM ) ) + util.Effect( "weapon_shell", ed, true, true )]] + +end
\ No newline at end of file diff --git a/entities/weapons/rad_scout/shared.lua b/entities/weapons/rad_scout/shared.lua new file mode 100644 index 0000000..d7fa4d0 --- /dev/null +++ b/entities/weapons/rad_scout/shared.lua @@ -0,0 +1,46 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "Steyr Scout" + SWEP.IconLetter = "n" + SWEP.Slot = 2 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "ar2" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_snip_scout.mdl" +SWEP.WorldModel = "models/weapons/w_snip_scout.mdl" + +SWEP.SprintPos = Vector(-1.7763, -1.9796, 1.677) +SWEP.SprintAng = Vector(-11.9431, -36.4352, 0) + +SWEP.ZoomModes = { 0, 40, 10 } +SWEP.ZoomSpeeds = { 0.25, 0.40, 0.40 } + +SWEP.IsSniper = true +SWEP.AmmoType = "Sniper" + +SWEP.Primary.Sound = Sound( "Weapon_Scout.Single" ) +SWEP.Primary.Recoil = 15.5 +SWEP.Primary.Damage = 110 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.001 +SWEP.Primary.SniperCone = 0.035 +SWEP.Primary.Delay = 1.400 + +SWEP.Primary.ClipSize = 10 +SWEP.Primary.Automatic = false + +SWEP.MinShellDelay = 0.8 +SWEP.MaxShellDelay = 1.0 diff --git a/entities/weapons/rad_sg552/shared.lua b/entities/weapons/rad_sg552/shared.lua new file mode 100644 index 0000000..9d22ef2 --- /dev/null +++ b/entities/weapons/rad_sg552/shared.lua @@ -0,0 +1,159 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "SG 552" + SWEP.IconLetter = "A" + SWEP.Slot = 4 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "ar2" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_rif_sg552.mdl" +SWEP.WorldModel = "models/weapons/w_rif_sg552.mdl" + +SWEP.SprintPos = Vector (-2.629, -4.8963, 1.4033) +SWEP.SprintAng = Vector (-7.3401, -31.7536, 3.9563) + +SWEP.ZoomModes = { 0, 35 } +SWEP.ZoomSpeeds = { 0.25, 0.35 } + +SWEP.IsSniper = true +SWEP.AmmoType = "Rifle" + +SWEP.Primary.Sound = Sound( "Weapon_SG552.Single" ) +SWEP.Primary.Recoil = 6.5 +SWEP.Primary.Damage = 60 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.005 +SWEP.Primary.SniperCone = 0.020 +SWEP.Primary.Delay = 0.210 + +SWEP.Primary.ClipSize = 30 +SWEP.Primary.Automatic = true + +function SWEP:SetZoomMode( num ) + + if num > 2 then + + num = 1 + + self.Weapon:UnZoom() + + end + + self.Weapon:SetNWInt( "Mode", num ) + self.Owner:SetFOV( self.ZoomModes[num], self.ZoomSpeeds[num] ) + +end + +function SWEP:PrimaryAttack() + + if not self.Weapon:CanPrimaryAttack() then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.25 ) + + return + + end + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) ) + self.Weapon:SetClip1( self.Weapon:Clip1() - 1 ) + self.Weapon:ShootEffects() + + if self.IsSniper and self.Weapon:GetZoomMode() == 1 then + + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.SniperCone, 1 ) + + else + + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.Cone, self.Weapon:GetZoomMode() ) + + end + + --[[if self.Weapon:GetZoomMode() > 1 then + + self.Weapon:UnZoom() + + end]] + + if SERVER then + + self.Owner:AddAmmo( self.AmmoType, -1 ) + + end + +end + +function SWEP:DrawHUD() + + if self.Weapon:ShouldNotDraw() then return end + + local mode = self.Weapon:GetZoomMode() + + local cone = self.Primary.Cone + local scale = cone + + if mode == 1 then + + cone = self.Primary.SniperCone + scale = cone + + end + + local x = ScrW() * 0.5 + local y = ScrH() * 0.5 + local scalebywidth = ( ScrW() / 1024 ) * 10 + + if self.Owner:KeyDown( IN_FORWARD ) or self.Owner:KeyDown( IN_BACK ) or self.Owner:KeyDown( IN_MOVELEFT ) or self.Owner:KeyDown( IN_MOVERIGHT ) then + + scale = cone * 1.75 + + elseif self.Owner:KeyDown( IN_DUCK ) or self.Owner:KeyDown( IN_WALK ) then + + scale = math.Clamp( cone / 1.75, 0, 10 ) + + end + + scale = scale * scalebywidth + + local dist = math.abs( self.CrosshairScale - scale ) + self.CrosshairScale = math.Approach( self.CrosshairScale, scale, FrameTime() * 2 + dist * 0.05 ) + + local gap = 40 * self.CrosshairScale + local length = gap + self.CrossLength:GetInt() //20 * self.CrosshairScale + + surface.SetDrawColor( self.CrossRed:GetInt(), self.CrossGreen:GetInt(), self.CrossBlue:GetInt(), self.CrossAlpha:GetInt() ) + surface.DrawLine( x - length, y, x - gap, y ) + surface.DrawLine( x + length, y, x + gap, y ) + surface.DrawLine( x, y - length, x, y - gap ) + surface.DrawLine( x, y + length, x, y + gap ) + + if mode != 1 then + + local w = ScrW() + local h = ScrH() + local wr = ( h / 3 ) * 4 + + surface.SetTexture( surface.GetTextureID( "gmod/scope" ) ) + surface.SetDrawColor( 0, 0, 0, 255 ) + surface.DrawTexturedRect( ( w / 2 ) - wr / 2, 0, wr, h ) + + surface.SetDrawColor( 0, 0, 0, 255 ) + surface.DrawRect( 0, 0, ( w / 2 ) - wr / 2, h ) + surface.DrawRect( ( w / 2 ) + wr / 2, 0, w - ( ( w / 2 ) + wr / 2 ), h ) + + end + +end
\ No newline at end of file diff --git a/entities/weapons/rad_shotgun/shared.lua b/entities/weapons/rad_shotgun/shared.lua new file mode 100644 index 0000000..d754462 --- /dev/null +++ b/entities/weapons/rad_shotgun/shared.lua @@ -0,0 +1,320 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "Winchester 1887" + SWEP.IconLetter = "k" + SWEP.Slot = 3 + SWEP.Slotpos = 3 + +end + +SWEP.HoldType = "shotgun" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_shot_m3super91.mdl" +SWEP.WorldModel = "models/weapons/w_annabelle.mdl" + +SWEP.SprintPos = Vector(-0.6026, -2.715, 0.0137) +SWEP.SprintAng = Vector(-3.4815, -21.9362, 0.0001) + +SWEP.IsSniper = false +SWEP.AmmoType = "Buckshot" + +SWEP.Primary.Sound = Sound( "weapons/shotgun/shotgun_fire6.wav" ) +SWEP.Primary.Pump = Sound( "Weapon_M3.Pump" ) +SWEP.Primary.Recoil = 8.5 +SWEP.Primary.Damage = 30 +SWEP.Primary.NumShots = 8 +SWEP.Primary.Cone = 0.085 +SWEP.Primary.Delay = 0.500 + +SWEP.Primary.ClipSize = 5 +SWEP.Primary.Automatic = false + +SWEP.MinShellDelay = 0.5 +SWEP.MaxShellDelay = 0.7 + +function SWEP:Deploy() + + self.Weapon:SetNWBool( "Reloading", false ) + self.Weapon:SetVar( "PumpTime", 0 ) + self.Weapon:SetNextPrimaryFire( CurTime() + 0.3 ) + + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + + return true + +end + +function SWEP:CanPrimaryAttack() + + if self.HolsterMode or self.LastRunFrame > CurTime() then return false end + + if self.Owner:GetNWInt( "Ammo" .. self.AmmoType, 0 ) < 1 then + + self.Weapon:EmitSound( self.Primary.Empty ) + return false + + end + + if self.Weapon:GetNWBool( "Reloading", false ) then + + self.Weapon:SetNWBool( "Reloading", false ) + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + + self.Weapon:SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH ) + + return false + + end + + if self.Weapon:Clip1() <= 0 then + + self.Weapon:SetNWBool( "Reloading", true ) + self.Weapon:SetVar( "ReloadTimer", CurTime() + 0.5 ) + self.Weapon:SendWeaponAnim( ACT_VM_RELOAD ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + //self.Weapon:SetClip1( self.Weapon:Clip1() + 1 ) + + return false + + end + + return true + +end + +function SWEP:ShootEffects() + + if IsFirstTimePredicted() then + + self.Owner:ViewPunch( Angle( math.Rand( -0.2, -0.1 ) * self.Primary.Recoil, math.Rand( -0.05, 0.05 ) * self.Primary.Recoil, 0 ) ) + + end + + self.Owner:MuzzleFlash() + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + + if self.UseShellSounds then + + local pitch = self.Pitches[ self.AmmoType ] + math.random( -3, 3 ) + local tbl = self.BuckshotShellSounds + local pos = self.Owner:GetPos() + + timer.Simple( math.Rand( self.MinShellDelay, self.MaxShellDelay ), function() sound.Play( table.Random( tbl ), pos, 50, pitch ) end ) + + end + +end + +function SWEP:PrimaryAttack() + + if not self.Weapon:CanPrimaryAttack() then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + return + + end + + self.Weapon:SetVar( "PumpTime", CurTime() + 0.5 ) + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) ) + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.Cone, self.Weapon:GetZoomMode() ) + self.Weapon:TakePrimaryAmmo( 1 ) + self.Weapon:ShootEffects() + + if SERVER then + + self.Owner:AddAmmo( self.AmmoType, -1 ) + + end + +end + +function SWEP:Reload() + + if self.Weapon:Clip1() == self.Primary.ClipSize or self.Weapon:Clip1() > self.Owner:GetNWInt( "Ammo" .. self.AmmoType, 0 ) or self.HolsterMode or self.ReloadTime then return end + + if self.Weapon:Clip1() < self.Primary.ClipSize then + + self.Weapon:SetNWBool( "Reloading", true ) + self.Weapon:SetVar( "ReloadTimer", CurTime() + 0.5 ) + self.Weapon:SendWeaponAnim( ACT_VM_RELOAD ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + //self.Weapon:SetClip1( self.Weapon:Clip1() + 1 ) + + end + +end + +function SWEP:PumpIt() + + self.Weapon:SetNWBool( "Reloading", false ) + self.Weapon:SendWeaponAnim( ACT_SHOTGUN_PUMP ) + self.Weapon:EmitSound( self.Primary.Pump ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + +end + +function SWEP:Think() + + if self.Owner:KeyDown( IN_WALK ) and self.HolsterTime < CurTime() then + + self.HolsterTime = CurTime() + 2 + self.HolsterMode = !self.HolsterMode + + if self.HolsterMode then + + self.Owner:SetLuaAnimation( self.HoldType ) + + else + + self.Owner:StopAllLuaAnimations( 0.5 ) + + end + + end + + if self.Weapon:GetVar( "PumpTime", 0 ) != 0 and self.Weapon:GetVar( "PumpTime", 0 ) < CurTime() then + + self.Weapon:SetVar( "PumpTime", 0 ) + self.Weapon:PumpIt() + + end + + if self.Weapon:GetNWBool( "Reloading", false ) then + + if self.Weapon:GetVar( "ReloadTimer", 0 ) < CurTime() then + + // Finsished reload + if self.Weapon:Clip1() >= self.Primary.ClipSize then + + self.Weapon:SetNWBool( "Reloading", false ) + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + + self.Weapon:SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH ) + + return + + end + + // Next cycle + self.Weapon:SetVar( "ReloadTimer", CurTime() + 0.75 ) + self.Weapon:SendWeaponAnim( ACT_VM_RELOAD ) + + // Add ammo + self.Weapon:SetClip1( self.Weapon:Clip1() + 1 ) + + end + + end + + if self.Owner:GetVelocity():Length() > 0 then + + if self.Owner:KeyDown( IN_SPEED ) then + + self.LastRunFrame = CurTime() + 0.3 + + end + + end + +end + +function SWEP:ShootBullets( damage, numbullets, aimcone, zoommode ) + + if SERVER then + + self.Owner:AddStat( "Bullets", 1 ) + + end + + local scale = aimcone + + if self.Owner:KeyDown( IN_FORWARD ) or self.Owner:KeyDown( IN_BACK ) or self.Owner:KeyDown( IN_MOVELEFT ) or self.Owner:KeyDown( IN_MOVERIGHT ) then + + scale = aimcone * 1.75 + + elseif self.Owner:KeyDown( IN_DUCK ) or self.Owner:KeyDown( IN_WALK ) then + + scale = math.Clamp( aimcone / 1.25, 0, 10 ) + + end + + local bullet = {} + bullet.Num = numbullets + bullet.Src = self.Owner:GetShootPos() + bullet.Dir = self.Owner:GetAimVector() + bullet.Spread = Vector( scale, scale, 0 ) + bullet.Tracer = 0 + bullet.Force = damage * 2 + bullet.Damage = damage + bullet.AmmoType = "Pistol" + bullet.TracerName = tracername + bullet.Callback = function ( attacker, tr, dmginfo ) + + dmginfo:ScaleDamage( self:GetDamageFalloffScale( tr.HitPos:Distance( self.Owner:GetShootPos() ) ) ) + + if tr.Entity.NextBot then + + tr.Entity:OnLimbHit( tr.HitGroup, dmginfo ) + + end + + if math.random(1,6) == 1 then + + self.Weapon:BulletPenetration( attacker, tr, dmginfo, 0 ) + + end + + end + + self.Owner:FireBullets( bullet ) + +end + +function SWEP:DrawHUD() + + if self.Weapon:ShouldNotDraw() then return end + + local x = ScrW() * 0.5 + local y = ScrH() * 0.5 + local scalebywidth = ( ScrW() / 1024 ) * 10 + local scale = self.Primary.Cone + + if self.Owner:KeyDown( IN_FORWARD ) or self.Owner:KeyDown( IN_BACK ) or self.Owner:KeyDown( IN_MOVELEFT ) or self.Owner:KeyDown( IN_MOVERIGHT ) then + + scale = self.Primary.Cone * 1.75 + + elseif self.Owner:KeyDown( IN_DUCK ) or self.Owner:KeyDown( IN_WALK ) then + + scale = math.Clamp( self.Primary.Cone / 1.25, 0, 10 ) + + end + + scale = scale * scalebywidth + + local dist = math.abs( self.CrosshairScale - scale ) + self.CrosshairScale = math.Approach( self.CrosshairScale, scale, FrameTime() * 2 + dist * 0.05 ) + + local gap = 40 * self.CrosshairScale + local length = gap + self.CrossLength:GetInt() + + surface.SetDrawColor( self.CrossRed:GetInt(), self.CrossGreen:GetInt(), self.CrossBlue:GetInt(), self.CrossAlpha:GetInt() ) + surface.DrawLine( x - length, y, x - gap, y ) + surface.DrawLine( x + length, y, x + gap, y ) + surface.DrawLine( x, y - length, x, y - gap ) + surface.DrawLine( x, y + length, x, y + gap ) + +end diff --git a/entities/weapons/rad_spas12/shared.lua b/entities/weapons/rad_spas12/shared.lua new file mode 100644 index 0000000..c3bcfb7 --- /dev/null +++ b/entities/weapons/rad_spas12/shared.lua @@ -0,0 +1,342 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFOV = 55 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "SPAS-12" + SWEP.IconLetter = "k" + SWEP.Slot = 3 + SWEP.Slotpos = 3 + +end + +SWEP.HoldType = "shotgun" + +SWEP.Base = "rad_base" + +SWEP.UseHands = true +SWEP.UseShellSounds = false + +SWEP.ViewModel = "models/weapons/c_shotgun.mdl" +SWEP.WorldModel = "models/weapons/w_shotgun.mdl" + +//SWEP.SprintPos = Vector(-0.6026, -2.715, 0.0137) +//SWEP.SprintAng = Vector(-3.4815, -21.9362, 0.0001) +SWEP.SprintPos = Vector (1.4752, 0.0296, -3.577) +SWEP.SprintAng = Vector (5.8948, 20.2814, 0) + +SWEP.IsSniper = false +SWEP.AmmoType = "Buckshot" + +SWEP.Primary.Sound = Sound( "Weapon_Shotgun.Double" ) +SWEP.Primary.Pump = Sound( "Weapon_Shotgun.Special1" ) +SWEP.Primary.ReloadSound = Sound( "Weapon_Shotgun.Reload" ) +SWEP.Primary.Recoil = 9.5 +SWEP.Primary.Damage = 30 +SWEP.Primary.NumShots = 8 +SWEP.Primary.Cone = 0.080 +SWEP.Primary.Delay = 0.500 + +SWEP.Primary.ClipSize = 8 +SWEP.Primary.Automatic = false + +function SWEP:Deploy() + + self.Weapon:SetNWBool( "Reloading", false ) + self.Weapon:SetVar( "PumpTime", 0 ) + self.Weapon:SetNextPrimaryFire( CurTime() + 0.3 ) + + if SERVER then + + self.Weapon:SetZoomMode( 1 ) + + end + + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + + return true + +end + +function SWEP:CanPrimaryAttack() + + if self.HolsterMode or self.LastRunFrame > CurTime() then return false end + + if self.Owner:GetNWInt( "Ammo"..self.AmmoType, 0 ) < 1 then + + self.Weapon:EmitSound( self.Primary.Empty ) + return false + + end + + if self.Weapon:GetNWBool( "Reloading", false ) then + + self.Weapon:SetNWBool( "Reloading", false ) + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + + self.Weapon:SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH ) + + return false + + end + + if self.Weapon:Clip1() <= 0 and not self.Weapon:GetNWBool( "Reloading", false ) then + + self.Weapon:SetNWBool( "Reloading", true ) + self.Weapon:SetVar( "ReloadTimer", CurTime() + 0.5 ) + self.Weapon:SendWeaponAnim( ACT_VM_RELOAD ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + //self.Weapon:SetClip1( self.Weapon:Clip1() + 1 ) + + return false + + end + + return true + +end + +function SWEP:ShootEffects() + + if IsFirstTimePredicted() then + + self.Owner:ViewPunch( Angle( math.Rand( -0.2, -0.1 ) * self.Primary.Recoil, math.Rand( -0.05, 0.05 ) * self.Primary.Recoil, 0 ) ) + + end + + self.Owner:MuzzleFlash() + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + + if self.UseShellSounds then + + local pitch = self.Pitches[ self.AmmoType ] + math.random( -3, 3 ) + local tbl = self.BuckshotShellSounds + local pos = self.Owner:GetPos() + + timer.Simple( math.Rand( self.MinShellDelay, self.MaxShellDelay ), function() sound.Play( table.Random( tbl ), pos, 50, pitch ) end ) + + end + +end + +function SWEP:PrimaryAttack() + + if not self.Weapon:CanPrimaryAttack() then + + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + return + + end + + self.Weapon:SetVar( "PumpTime", CurTime() + 0.5 ) + + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) ) + self.Weapon:ShootBullets( self.Primary.Damage, self.Primary.NumShots, self.Primary.Cone, self.Weapon:GetZoomMode() ) + self.Weapon:TakePrimaryAmmo( 1 ) + self.Weapon:ShootEffects() + + if SERVER then + + self.Owner:AddAmmo( self.AmmoType, -1 ) + + end + +end + +function SWEP:Reload() + + if self.Weapon:Clip1() == self.Primary.ClipSize or self.Weapon:Clip1() > self.Owner:GetNWInt( "Ammo" .. self.AmmoType, 0 ) or self.HolsterMode or self.ReloadTime then return end + + if self.Weapon:Clip1() < self.Primary.ClipSize then + + self.Weapon:SetNWBool( "Reloading", true ) + self.Weapon:SetVar( "ReloadTimer", CurTime() + 0.5 ) + self.Weapon:SendWeaponAnim( ACT_VM_RELOAD ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + + //self.Weapon:SetClip1( self.Weapon:Clip1() + 1 ) + + end + +end + +function SWEP:PumpIt() + + self.Weapon:SetNWBool( "Reloading", false ) + self.Weapon:SendWeaponAnim( ACT_SHOTGUN_PUMP ) + self.Weapon:EmitSound( self.Primary.Pump ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + +end + +function SWEP:Think() + + if self.Owner:KeyDown( IN_WALK ) and self.HolsterTime < CurTime() then + + self.HolsterTime = CurTime() + 2 + self.HolsterMode = !self.HolsterMode + + --[[if self.HolsterMode then + + self.Owner:SetLuaAnimation( self.HoldType ) + + else + + self.Owner:StopAllLuaAnimations( 0.5 ) + + end]] + + end + + if self.Weapon:GetVar( "PumpTime", 0 ) != 0 and self.Weapon:GetVar( "PumpTime", 0 ) < CurTime() then + + self.Weapon:SetVar( "PumpTime", 0 ) + self.Weapon:PumpIt() + + end + + if self.Weapon:GetNWBool( "Reloading", false ) then + + if self.Weapon:GetVar( "ReloadTimer", 0 ) < CurTime() then + + // Finsished reload + if self.Weapon:Clip1() >= self.Primary.ClipSize then + + self.Weapon:SetNWBool( "Reloading", false ) + self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 ) + + self.Weapon:SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH ) + + return + + end + + // Next cycle + self.Weapon:SetVar( "ReloadTimer", CurTime() + 0.75 ) + self.Weapon:SendWeaponAnim( ACT_VM_RELOAD ) + + // Add ammo + self.Weapon:SetClip1( self.Weapon:Clip1() + 1 ) + + // Sound + self.Weapon:EmitSound( self.Primary.ReloadSound, 100, math.random(90,110) ) + + end + + end + + if self.Owner:GetVelocity():Length() > 0 then + + if self.Owner:KeyDown( IN_SPEED ) and self.Owner:GetNWFloat( "Weight", 0 ) < 50 then + + self.LastRunFrame = CurTime() + 0.3 + + end + + end + +end + +function SWEP:ShootBullets( damage, numbullets, aimcone, zoommode ) + + if SERVER then + + self.Owner:AddStat( "Bullets", 1 ) + + end + + local scale = aimcone + + if self.Owner:KeyDown( IN_FORWARD ) or self.Owner:KeyDown( IN_BACK ) or self.Owner:KeyDown( IN_MOVELEFT ) or self.Owner:KeyDown( IN_MOVERIGHT ) then + + scale = aimcone * 1.75 + + elseif self.Owner:KeyDown( IN_DUCK ) or self.Owner:KeyDown( IN_WALK ) then + + scale = math.Clamp( aimcone / 1.25, 0, 10 ) + + end + + local tracer = 1 + + if ( zoommode or 1 ) > 1 then + + tracer = 0 + + end + + local bullet = {} + bullet.Num = numbullets + bullet.Src = self.Owner:GetShootPos() + bullet.Dir = self.Owner:GetAimVector() + bullet.Spread = Vector( scale, scale, 0 ) + bullet.Tracer = 0 + bullet.Force = damage * 2 + bullet.Damage = damage + bullet.AmmoType = "Pistol" + bullet.TracerName = tracername + bullet.Callback = function ( attacker, tr, dmginfo ) + + dmginfo:ScaleDamage( self:GetDamageFalloffScale( tr.HitPos:Distance( self.Owner:GetShootPos() ) ) ) + + if tr.Entity.NextBot then + + tr.Entity:OnLimbHit( tr.HitGroup, dmginfo ) + + end + + if math.random(1,6) == 1 then + + self.Weapon:BulletPenetration( attacker, tr, dmginfo, 0 ) + + end + + end + + self.Owner:FireBullets( bullet ) + +end + +function SWEP:DrawHUD() + + if self.Weapon:ShouldNotDraw() then return end + + local x = ScrW() * 0.5 + local y = ScrH() * 0.5 + local scalebywidth = ( ScrW() / 1024 ) * 10 + local scale = self.Primary.Cone + + if self.Owner:KeyDown( IN_FORWARD ) or self.Owner:KeyDown( IN_BACK ) or self.Owner:KeyDown( IN_MOVELEFT ) or self.Owner:KeyDown( IN_MOVERIGHT ) then + + scale = self.Primary.Cone * 1.75 + + elseif self.Owner:KeyDown( IN_DUCK ) or self.Owner:KeyDown( IN_WALK ) then + + scale = math.Clamp( self.Primary.Cone / 1.25, 0, 10 ) + + end + + scale = scale * scalebywidth + + local dist = math.abs( self.CrosshairScale - scale ) + self.CrosshairScale = math.Approach( self.CrosshairScale, scale, FrameTime() * 2 + dist * 0.05 ) + + local gap = 40 * self.CrosshairScale + local length = gap + self.CrossLength:GetInt() + + surface.SetDrawColor( self.CrossRed:GetInt(), self.CrossGreen:GetInt(), self.CrossBlue:GetInt(), self.CrossAlpha:GetInt() ) + surface.DrawLine( x - length, y, x - gap, y ) + surface.DrawLine( x + length, y, x + gap, y ) + surface.DrawLine( x, y - length, x, y - gap ) + surface.DrawLine( x, y + length, x, y + gap ) + +end diff --git a/entities/weapons/rad_tmp/shared.lua b/entities/weapons/rad_tmp/shared.lua new file mode 100644 index 0000000..f0a794a --- /dev/null +++ b/entities/weapons/rad_tmp/shared.lua @@ -0,0 +1,39 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "TMP" + SWEP.IconLetter = "x" + SWEP.Slot = 3 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "rpg" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_smg_tmp.mdl" +SWEP.WorldModel = "models/weapons/w_smg_tmp.mdl" + +SWEP.SprintPos = Vector (2.0027, -0.751, 0.1411) +SWEP.SprintAng = Vector (-1.2669, -27.7284, 10.4434) + +SWEP.IsSniper = false +SWEP.AmmoType = "SMG" + +SWEP.Primary.Sound = Sound( "Weapon_USP.SilencedShot" ) +SWEP.Primary.Recoil = 4.5 +SWEP.Primary.Damage = 35 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.035 +SWEP.Primary.Delay = 0.075 + +SWEP.Primary.ClipSize = 30 +SWEP.Primary.Automatic = true diff --git a/entities/weapons/rad_ump45/shared.lua b/entities/weapons/rad_ump45/shared.lua new file mode 100644 index 0000000..b8191ca --- /dev/null +++ b/entities/weapons/rad_ump45/shared.lua @@ -0,0 +1,39 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "HK UMP45" + SWEP.IconLetter = "q" + SWEP.Slot = 3 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "smg" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_smg_ump45.mdl" +SWEP.WorldModel = "models/weapons/w_smg_ump45.mdl" + +SWEP.SprintPos = Vector (-1.0859, -4.2523, -1.1534) +SWEP.SprintAng = Vector (-4.8822, -38.3984, 14.6527) + +SWEP.IsSniper = false +SWEP.AmmoType = "SMG" + +SWEP.Primary.Sound = Sound( "Weapon_UMP45.Single" ) +SWEP.Primary.Recoil = 6.5 +SWEP.Primary.Damage = 35 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.045 +SWEP.Primary.Delay = 0.100 + +SWEP.Primary.ClipSize = 25 +SWEP.Primary.Automatic = true diff --git a/entities/weapons/rad_usp/shared.lua b/entities/weapons/rad_usp/shared.lua new file mode 100644 index 0000000..91db700 --- /dev/null +++ b/entities/weapons/rad_usp/shared.lua @@ -0,0 +1,39 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFlip = true + + SWEP.PrintName = "USP Compact" + SWEP.IconLetter = "a" + SWEP.Slot = 2 + SWEP.Slotpos = 2 + +end + +SWEP.HoldType = "pistol" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/weapons/v_pist_usp.mdl" +SWEP.WorldModel = "models/weapons/w_pistol.mdl" + +SWEP.SprintPos = Vector (0.4776, 0.446, 3.1631) +SWEP.SprintAng = Vector (-15.3501, -1.3761, -1.5457) + +SWEP.IsSniper = false +SWEP.AmmoType = "Pistol" + +SWEP.Primary.Sound = Sound( "Weapon_USP.Single" ) +SWEP.Primary.Recoil = 5.5 +SWEP.Primary.Damage = 30 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Cone = 0.040 +SWEP.Primary.Delay = 0.150 + +SWEP.Primary.ClipSize = 12 +SWEP.Primary.Automatic = false diff --git a/entities/weapons/rad_z_banshee/shared.lua b/entities/weapons/rad_z_banshee/shared.lua new file mode 100644 index 0000000..00e881a --- /dev/null +++ b/entities/weapons/rad_z_banshee/shared.lua @@ -0,0 +1,131 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFOV = 70 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Claws" + SWEP.IconLetter = "C" + SWEP.Slot = 0 + SWEP.Slotpos = 0 + + killicon.AddFont( "rad_z_banshee", "CSKillIcons", SWEP.IconLetter, Color( 255, 80, 0, 255 ) ) + +end + +SWEP.Base = "rad_z_base" + +SWEP.ViewModel = "models/Zed/weapons/v_banshee.mdl" + +SWEP.Taunt = Sound( "npc/stalker/go_alert2a.wav" ) + +SWEP.Die = { "npc/headcrab_poison/ph_scream1.wav", +"npc/headcrab_poison/ph_scream2.wav", +"npc/headcrab_poison/ph_scream3.wav"} + +SWEP.Primary.Hit = Sound( "npc/antlion/shell_impact3.wav" ) +SWEP.Primary.HitFlesh = Sound( "npc/antlion/foot4.wav" ) +SWEP.Primary.Sound = Sound( "npc/zombie/zo_attack1.wav" ) +SWEP.Primary.Recoil = 3.5 +SWEP.Primary.Damage = 25 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Delay = 1.900 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = true + +function SWEP:NoobHelp() + + self.Owner:NoticeOnce( "Right click to use your scream ability", GAMEMODE.Colors.Blue, 5, 10 ) + self.Owner:NoticeOnce( "Your scream will disorient nearby people", GAMEMODE.Colors.Blue, 5, 12 ) + +end + +function SWEP:Holster() + + if SERVER then + + self.Owner:EmitSound( table.Random( self.Die ), 100, math.random(40,60) ) + + end + + return true + +end + +function SWEP:SecondaryAttack() + + self.Weapon:SetNextSecondaryFire( CurTime() + 8 ) + + if SERVER then + + self.Owner:VoiceSound( self.Taunt, 100, math.random( 90, 100 ) ) + + local hit = false + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + local dist = v:GetPos():Distance( self.Owner:GetPos() ) + + if dist <= 350 then + + local scale = 1 - ( dist / 350 ) + local count = math.Round( scale * 4 ) + + umsg.Start( "Drunk", v ) + umsg.Short( count ) + umsg.End() + + umsg.Start( "ScreamHit", v ) + umsg.End() + + v:TakeDamage( scale * 20, self.Owner, self.Weapon ) + v:SetDSP( 34, false ) + + self.Owner:AddZedDamage( 5 ) + + hit = true + + end + + end + + if hit then + + self.Owner:Notice( "You disoriented a human", GAMEMODE.Colors.Green ) + + end + + end + +end + +function SWEP:PrimaryAttack() + + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(130,150) ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + + self.ThinkTime = CurTime() + ( self.Primary.Delay * 0.3 ) + +end + +function SWEP:OnHitHuman( ent, dmg ) + + if ent:GetRadiation() != 5 then + + ent:AddRadiation( 1 ) + + self.Owner:AddZedDamage( 10 ) + + end + + self.Owner:AddZedDamage( dmg ) + self.Owner:DrawBlood( 4 ) + self.Owner:Notice( "You irradiated a human", GAMEMODE.Colors.Green ) + +end
\ No newline at end of file diff --git a/entities/weapons/rad_z_base/shared.lua b/entities/weapons/rad_z_base/shared.lua new file mode 100644 index 0000000..0748b8d --- /dev/null +++ b/entities/weapons/rad_z_base/shared.lua @@ -0,0 +1,289 @@ +if SERVER then + + AddCSLuaFile( "shared.lua" ) + +end + +if CLIENT then + + SWEP.ViewModelFOV = 70 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Claws" + SWEP.IconLetter = "C" + SWEP.Slot = 0 + SWEP.Slotpos = 0 + + killicon.AddFont( "rad_z_common", "CSKillIcons", SWEP.IconLetter, Color( 255, 80, 0, 255 ) ); + +end + +SWEP.HoldType = "slam" + +SWEP.Base = "rad_base" + +SWEP.ViewModel = "models/zed/weapons/v_undead.mdl" + +SWEP.IsSniper = false +SWEP.AmmoType = "Knife" +SWEP.ThinkTime = 0 + +SWEP.Primary.Door = Sound( "Wood_Plank.Break" ) +SWEP.Primary.Hit = Sound( "npc/zombie/claw_strike1.wav" ) +SWEP.Primary.HitFlesh = Sound( "npc/zombie/claw_strike2.wav" ) +SWEP.Primary.Sound = Sound( "npc/fast_zombie/idle1.wav" ) +SWEP.Primary.Miss = Sound( "npc/zombie/claw_miss1.wav" ) +SWEP.Primary.Recoil = 3.5 +SWEP.Primary.Damage = 35 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Delay = 1.500 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = true + +function SWEP:GetViewModelPosition( pos, ang ) + + return pos, ang + +end + +function SWEP:NoobHelp() + + self.Owner:NoticeOnce( "Hit people to infect them", GAMEMODE.Colors.Blue, 5, 10 ) + +end + +function SWEP:Deploy() + + self.Owner:DrawWorldModel( false ) + + if SERVER then + + self.Weapon:NoobHelp() + + end + + return true + +end + +function SWEP:Holster() + + if SERVER then + + self.Owner:EmitSound( table.Random( self.Die ), 100, math.random(90,110) ) + + end + + return true + +end + +function SWEP:SecondaryAttack() + + self.Weapon:SetNextSecondaryFire( CurTime() + 2.5 ) + + if SERVER then + + self.Owner:VoiceSound( table.Random( self.Taunt ), 100, math.random( 90, 100 ) ) + + end + +end + +function SWEP:PrimaryAttack() + + self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(90,110) ) + self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay ) + + self.ThinkTime = CurTime() + ( self.Primary.Delay * 0.3 ) + +end + +function SWEP:Think() + + if self.ThinkTime != 0 and self.ThinkTime < CurTime() then + + self.Weapon:MeleeTrace( self.Primary.Damage ) + + self.ThinkTime = 0 + + end + +end + +function SWEP:OnHitHuman( ent, dmg ) + + if not ent:IsInfected() then + + ent:SetInfected( true ) + + self.Owner:Notice( "You infected a human", GAMEMODE.Colors.Green ) + self.Owner:AddZedDamage( 15 ) + + end + + self.Owner:AddZedDamage( dmg ) + self.Owner:DrawBlood( 3 ) + +end + +function SWEP:MeleeTrace( dmg ) + + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + + self.Weapon:SendWeaponAnim( ACT_VM_MISSCENTER ) + + if CLIENT then return end + + self.Weapon:SetNWString( "CurrentAnim", "zattack" .. math.random(1,3) ) + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + + local pos = self.Owner:GetShootPos() + local aim = self.Owner:GetAimVector() * 80 + + local line = {} + line.start = pos + line.endpos = pos + aim + line.filter = self.Owner + + local linetr = util.TraceLine( line ) + + local tr = {} + tr.start = pos + self.Owner:GetAimVector() * -5 + tr.endpos = pos + aim + tr.filter = self.Owner + tr.mask = MASK_SHOT_HULL + tr.mins = Vector(-20,-20,-20) + tr.maxs = Vector(20,20,20) + + local trace = util.TraceHull( tr ) + local ent = trace.Entity + local ent2 = linetr.Entity + + if not IsValid( ent ) and IsValid( ent2 ) then + + ent = ent2 + + end + + if not IsValid( ent ) then + + self.Owner:EmitSound( self.Primary.Miss, 100, math.random(90,110) ) + + return + + elseif not ent:IsWorld() then + + if ent:IsPlayer() and ent:Team() == TEAM_ARMY then + + ent:TakeDamage( dmg, self.Owner, self.Weapon ) + ent:EmitSound( self.Primary.HitFlesh, 100, math.random(90,110) ) + + self.Weapon:OnHitHuman( ent, dmg ) + + local ed = EffectData() + ed:SetOrigin( trace.HitPos ) + util.Effect( "BloodImpact", ed, true, true ) + + elseif string.find( ent:GetClass(), "npc" ) then + + ent:TakeDamage( 20, self.Owner, self.Weapon ) + ent:EmitSound( self.Primary.HitFlesh, 100, math.random(90,110) ) + + elseif !ent:IsPlayer() then + + if ent:GetClass() == "prop_door_rotating" then + + if not ent.Hits then + + ent.Hits = 1 + ent.MaxHits = math.random(5,10) + + ent:EmitSound( Sound( "Wood_Plank.Break" ) ) + + else + + ent.Hits = ent.Hits + 1 + + if ent.Hits > ent.MaxHits then + + local prop = ents.Create( "prop_physics" ) + prop:SetPos( ent:GetPos() ) + prop:SetAngles( ent:GetAngles() + Angle(10,0,2) ) + prop:SetModel( ent:GetModel() ) + prop:SetSkin( ent:GetSkin() ) + prop:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + prop:Spawn() + + local dir = ent:GetPos() - self.Owner:GetShootPos() + dir:Normalize() + + local phys = prop:GetPhysicsObject() + + if IsValid( phys ) then + + phys:ApplyForceCenter( dir * phys:GetMass() * 800 ) + + end + + ent:EmitSound( Sound( "Wood_Crate.Break" ) ) + ent:Remove() + + return + + else + + ent:EmitSound( Sound( "Wood_Plank.Break" ) ) + + end + + end + + elseif string.find( ent:GetClass(), "breakable" ) then + + ent:TakeDamage( 50, self.Owner, self.Weapon ) + ent:EmitSound( self.Primary.Hit, 100, math.random(90,110) ) + + if ent:GetClass() == "func_breakable_surf" then + + ent:Fire( "shatter", "1 1 1", 0 ) + + return + + end + + end + + local phys = ent:GetPhysicsObject() + + if IsValid( phys ) then + + ent:SetPhysicsAttacker( self.Owner ) + ent:EmitSound( self.Primary.Hit, 100, math.random(90,110) ) + + if ent.IsWood then + + ent:TakeDamage( 75, self.Owner, self.Weapon ) + ent:EmitSound( self.Primary.Door ) + + else + + ent:TakeDamage( 25, self.Owner, self.Weapon ) + + end + + phys:Wake() + phys:ApplyForceCenter( self.Owner:GetAimVector() * phys:GetMass() * 400 ) + + end + + end + + end + +end + +function SWEP:DrawHUD() + +end diff --git a/entities/weapons/rad_z_contagion/shared.lua b/entities/weapons/rad_z_contagion/shared.lua new file mode 100644 index 0000000..0bfb142 --- /dev/null +++ b/entities/weapons/rad_z_contagion/shared.lua @@ -0,0 +1,66 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFOV = 70 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Claws" + SWEP.IconLetter = "C" + SWEP.Slot = 0 + SWEP.Slotpos = 0 + + killicon.AddFont( "rad_z_contagion", "CSKillIcons", SWEP.IconLetter, Color( 255, 80, 0, 255 ) ) + +end + +SWEP.Base = "rad_z_base" + +SWEP.ViewModel = "models/Zed/weapons/v_ghoul.mdl" + +SWEP.Taunt = {"npc/zombie/zombie_voice_idle1.wav", +"npc/zombie/zombie_voice_idle2.wav", +"npc/zombie/zombie_voice_idle3.wav", +"npc/zombie/zombie_voice_idle4.wav", +"npc/zombie/zombie_voice_idle5.wav", +"npc/zombie/zombie_voice_idle7.wav", +"npc/zombie/zombie_voice_idle8.wav", +"npc/zombie/zombie_voice_idle9.wav", +"npc/zombie/zombie_voice_idle10.wav", +"npc/zombie/zombie_voice_idle12.wav", +"npc/zombie/zombie_voice_idle13.wav", +"npc/zombie/zombie_voice_idle14.wav" } + +SWEP.Die = { "npc/zombie/zombie_die1.wav", +"npc/zombie/zombie_die2.wav", +"npc/zombie/zombie_die3.wav", +"npc/zombie/zombie_voice_idle6.wav", +"npc/zombie/zombie_voice_idle11.wav" } + +SWEP.Primary.Sound = Sound( "npc/zombie/zombie_pain1.wav" ) +SWEP.Primary.Recoil = 3.5 +SWEP.Primary.Damage = 45 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Delay = 1.800 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = true + +function SWEP:NoobHelp() + + self.Owner:NoticeOnce( "You will unleash a toxic shower when you die", GAMEMODE.Colors.Blue, 5, 10 ) + +end + +function SWEP:OnHitHuman( ent, dmg ) + + ent:ViewBounce( 20 ) + + self.Owner:AddZedDamage( dmg ) + self.Owner:DrawBlood( 5 ) + +end diff --git a/entities/weapons/rad_z_leaper/shared.lua b/entities/weapons/rad_z_leaper/shared.lua new file mode 100644 index 0000000..e123b48 --- /dev/null +++ b/entities/weapons/rad_z_leaper/shared.lua @@ -0,0 +1,96 @@ +if SERVER then + + AddCSLuaFile( "shared.lua" ) + +end + +if CLIENT then + + SWEP.ViewModelFOV = 70 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Claws" + SWEP.IconLetter = "C" + SWEP.Slot = 0 + SWEP.Slotpos = 0 + + killicon.AddFont( "rad_z_leaper", "CSKillIcons", SWEP.IconLetter, Color( 255, 80, 0, 255 ) ) + +end + +SWEP.Base = "rad_z_base" +SWEP.HoldType = "slam" +SWEP.ViewModel = "models/Zed/weapons/v_wretch.mdl" + +SWEP.Taunt = { "npc/fast_zombie/fz_frenzy1.wav", +"npc/barnacle/barnacle_pull1.wav", +"npc/barnacle/barnacle_pull2.wav", +"npc/barnacle/barnacle_pull3.wav", +"npc/barnacle/barnacle_pull4.wav" } + +SWEP.Die = { "npc/fast_zombie/fz_alert_close1.wav", +"npc/fast_zombie/fz_alert_far1.wav" } + +SWEP.Scream = Sound( "npc/fast_zombie/fz_scream1.wav" ) + +SWEP.Primary.Hit = Sound( "npc/zombie/claw_strike1.wav" ) +SWEP.Primary.HitFlesh = Sound( "npc/zombie/claw_strike2.wav" ) +SWEP.Primary.Sound = Sound( "npc/fast_zombie/wake1.wav" ) +SWEP.Primary.Miss = Sound( "npc/zombie/claw_miss1.wav" ) +SWEP.Primary.Recoil = 3.5 +SWEP.Primary.Damage = 15 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Delay = 1.200 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = true + +SWEP.JumpTime = 0 + +function SWEP:NoobHelp() + + self.Owner:NoticeOnce( "Your attacks cause bleeding", GAMEMODE.Colors.Blue, 5, 10 ) + +end + +function SWEP:Think() + + if self.ThinkTime != 0 and self.ThinkTime < CurTime() then + + self.Weapon:MeleeTrace( self.Primary.Damage ) + + self.ThinkTime = 0 + + end + + if CLIENT then return end + + if self.JumpTime < CurTime() and self.Owner:KeyDown( IN_SPEED ) then + + local vec = self.Owner:GetAimVector() + vec.z = math.Clamp( vec.z, 0.40, 0.75 ) + + self.JumpTime = CurTime() + 8 + + self.Owner:SetVelocity( vec * 800 ) + self.Owner:EmitSound( self.Scream, 100, math.random( 90, 110 ) ) + + end + +end + +function SWEP:OnHitHuman( ent, dmg ) + + if not ent:IsBleeding() then + + ent:SetBleeding( true ) + + self.Owner:Notice( "You made a human bleed", GAMEMODE.Colors.Green ) + self.Owner:AddZedDamage( 10 ) + + end + + self.Owner:AddZedDamage( dmg ) + self.Owner:DrawBlood( 5 ) + +end diff --git a/entities/weapons/rad_z_runner/shared.lua b/entities/weapons/rad_z_runner/shared.lua new file mode 100644 index 0000000..feeae59 --- /dev/null +++ b/entities/weapons/rad_z_runner/shared.lua @@ -0,0 +1,44 @@ +if SERVER then + + AddCSLuaFile("shared.lua") + +end + +if CLIENT then + + SWEP.ViewModelFOV = 70 + SWEP.ViewModelFlip = false + + SWEP.PrintName = "Claws" + SWEP.IconLetter = "C" + SWEP.Slot = 0 + SWEP.Slotpos = 0 + + killicon.AddFont( "rad_z_runner", "CSKillIcons", SWEP.IconLetter, Color( 255, 80, 0, 255 ) ); + +end + +SWEP.HoldType = "slam" + +SWEP.Base = "rad_z_base" + +SWEP.Taunt = { "npc/zombie/zombie_alert1.wav", +"npc/zombie/zombie_alert2.wav", +"npc/zombie/zombie_alert3.wav" } + +SWEP.Die = { "vo/npc/vortigaunt/vortigese02.wav", +"vo/npc/vortigaunt/vortigese03.wav", +"vo/npc/vortigaunt/vortigese05.wav", +"vo/npc/vortigaunt/vortigese07.wav" } + +SWEP.Primary.Hit = Sound( "npc/zombie/claw_strike1.wav" ) +SWEP.Primary.HitFlesh = Sound( "npc/zombie/claw_strike2.wav" ) +SWEP.Primary.Sound = Sound( "npc/fast_zombie/idle1.wav" ) +SWEP.Primary.Miss = Sound( "npc/zombie/claw_miss1.wav" ) +SWEP.Primary.Recoil = 3.5 +SWEP.Primary.Damage = 35 +SWEP.Primary.NumShots = 1 +SWEP.Primary.Delay = 1.500 + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Automatic = true diff --git a/gamemode/animations.lua b/gamemode/animations.lua new file mode 100644 index 0000000..3fac3ce --- /dev/null +++ b/gamemode/animations.lua @@ -0,0 +1,32 @@ + +function GM:UpdateAnimation( ply, velocity, maxseqgroundspeed ) + + if ply:Team() == TEAM_UNASSIGNED then return end + + player_manager.RunClass( ply, "UpdateAnimation", velocity, maxseqgroundspeed ) + +end + +function GM:CalcMainActivity( ply, velocity ) + + if ply:Team() == TEAM_UNASSIGNED then return end + + return player_manager.RunClass( ply, "CalcMainActivity", velocity ) + +end + +function GM:TranslateActivity( ply, act ) + + if ply:Team() == TEAM_UNASSIGNED then return end + + return player_manager.RunClass( ply, "TranslateActivity", act ) + +end + +function GM:DoAnimationEvent( ply, event, data ) + + if ply:Team() == TEAM_UNASSIGNED then return end + + return player_manager.RunClass( ply, "DoAnimationEvent", event, data ) + +end
\ No newline at end of file diff --git a/gamemode/cl_hudstains.lua b/gamemode/cl_hudstains.lua new file mode 100644 index 0000000..9b2b637 --- /dev/null +++ b/gamemode/cl_hudstains.lua @@ -0,0 +1,81 @@ + +local BloodTable = {} + +local function DrawBlood() + + if #BloodTable < 1 then return end + + for i=1, #BloodTable do + + if BloodTable[i] then + + local scale = math.Clamp( ( BloodTable[i].DieTime - CurTime() ) / BloodTable[i].Die, 0, 1 ) + + if scale == 0 then + + BloodTable[i].Remove = true + + else + + local alpha = math.floor( BloodTable[i].Alpha * scale ) + + surface.SetTexture( BloodTable[i].Mat ) + //surface.SetDrawColor( 250, 10, 10, alpha ) + surface.SetDrawColor( 175, 10, 10, alpha ) + surface.DrawTexturedRect( BloodTable[i].X, BloodTable[i].Y, BloodTable[i].Size, BloodTable[i].Size )//, BloodTable[i].Rot ) + + end + + end + + end + + for k,v in pairs( BloodTable ) do + + if v.Remove then + + table.remove( BloodTable, k ) + + break + + end + + end + +end +hook.Add( "HUDPaint", "BloodPaint", DrawBlood ) + +StainMats = { "nuke/blood/Blood1", +"nuke/blood/Blood2", +"nuke/blood/Blood3", +"nuke/blood/Blood4", +"nuke/blood/Blood5", +"nuke/blood/Blood6", +"nuke/blood/Blood7" } + +function AddStain( msg ) + + local num = 1 + + if msg then + + num = msg:ReadShort() + + end + + for i=1, num do + + local count = #BloodTable + 1 + + local size = math.random( 256, 1024 ) + local x = math.random( size * -0.5, ScrW() - ( size * 0.5 ) ) + local y = math.random( size * -0.5, ScrH() - ( size * 0.5 ) ) + local rand = math.Rand( 3.5, 6.5 ) + + BloodTable[count] = { Size = size, X = x, Y = y, Mat = surface.GetTextureID( table.Random( StainMats ) ), Die = rand, DieTime = CurTime() + rand, Alpha = math.random( 150, 250 ) } + + end + +end + +usermessage.Hook( "BloodStain", AddStain ) diff --git a/gamemode/cl_init.lua b/gamemode/cl_init.lua new file mode 100644 index 0000000..e9ba2a8 --- /dev/null +++ b/gamemode/cl_init.lua @@ -0,0 +1,1197 @@ + +include( 'player_class/player_base.lua' ) +include( 'player_class/player_zombie.lua' ) +include( 'animations.lua' ) +include( 'items.lua' ) +include( 'shared.lua' ) +include( 'enums.lua' ) +include( 'moddable.lua' ) +include( 'tables.lua' ) +include( 'weather.lua' ) +include( 'cl_notice.lua' ) +include( 'cl_hudstains.lua' ) +include( 'cl_targetid.lua' ) +include( 'cl_spawnmenu.lua' ) +include( 'cl_scoreboard.lua' ) +include( 'cl_postprocess.lua' ) +include( 'cl_inventory.lua' ) +include( 'ply_extension.lua' ) +include( 'vgui/vgui_panelbase.lua' ) +include( 'vgui/vgui_dialogue.lua' ) +include( 'vgui/vgui_itemdisplay.lua' ) +include( 'vgui/vgui_shopmenu.lua' ) +include( 'vgui/vgui_classpicker.lua' ) +include( 'vgui/vgui_zombieclasses.lua' ) +include( 'vgui/vgui_helpmenu.lua' ) +include( 'vgui/vgui_endgame.lua' ) +include( 'vgui/vgui_playerdisplay.lua' ) +include( 'vgui/vgui_playerpanel.lua' ) +include( 'vgui/vgui_itempanel.lua' ) +include( 'vgui/vgui_panelsheet.lua' ) +include( 'vgui/vgui_goodmodelpanel.lua' ) +include( 'vgui/vgui_categorybutton.lua' ) +include( 'vgui/vgui_sidebutton.lua' ) +include( 'vgui/vgui_scroller.lua' ) + +CV_RagdollVision = CreateClientConVar( "cl_redead_ragdoll_vision", "1", true, false ) +CV_Density = CreateClientConVar( "cl_redead_rain_density", "1.0", true, false ) +CV_NoobHelp = CreateClientConVar( "cl_redead_noob_help", "1", true, false ) + +function GM:Initialize() + + WindVector = Vector( math.random(-10,10), math.random(-10,10), 0 ) + StaticPos = Vector(0,0,0) + ViewWobble = 0 + ShopMenu = false + HeadlessTbl = {} + GibbedTbl = {} + BurnTbl = {} + PlayerStats = {} + Drunkness = 0 + DeathScreenTime = 0 + DeathScreenScale = 0 + HeartBeat = 0 + JumpTimer = 0 + + surface.CreateFont ( "DeathFont", { size = 34, weight = 200, antialias = true, additive = true, font = "Graffiare" } ) + surface.CreateFont ( "AmmoFont", { size = 28, weight = 200, antialias = true, additive = true, font = "Graffiare" } ) + surface.CreateFont ( "CashFont", { size = 22, weight = 200, antialias = true, additive = true, font = "Graffiare" } ) + surface.CreateFont ( "InventoryFont", { size = 20, weight = 150, antialias = true, additive = true, font = "Graffiare" } ) + surface.CreateFont ( "HudMarker", { size = 20, weight = 200,antialias = true, additive = true, font = "Graffiare" } ) + surface.CreateFont ( "ZombieHud", { size = 24, weight = 500, antialias = true, additive = true, font = "Typenoksidi" } ) + surface.CreateFont ( "ShopBig", { size = 22, weight = 500, antialias = true, additive = true, font = "Typenoksidi" } ) + surface.CreateFont ( "ShopSmall", { size = 16, weight = 400, antialias = true, additive = true, font = "Typenoksidi" } ) + surface.CreateFont ( "EndGameBig", { size = 24, weight = 300,antialias = true, additive = true, font = "Typenoksidi" } ) + surface.CreateFont ( "EndGame", { size = 14, weight = 400, antialias = true, additive = true, font = "Tahoma" } ) + surface.CreateFont ( "AmmoFontSmall", { size = 12, weight = 300, antialias = true, additive = true, font = "Verdana" } ) + surface.CreateFont ( "TargetIDFont", { size = 12, weight = 200, antialias = true, additive = true, font = "Verdana" } ) + + //matRadar = Material( "radbox/radar" ) + //matArm = Material( "radbox/radar_arm" ) + //matArrow = Material( "radbox/radar_arrow" ) + //matNoise = Material( "radbox/nvg_noise" ) + + matHealth = Material( "radbox/img_health" ) + matStamina = Material( "radbox/img_stamina" ) + matBlood = Material( "radbox/img_blood" ) + matRadiation = Material( "radbox/img_radiation" ) + matInfection = Material( "radbox/img_infect" ) + + GAMEMODE:WeatherInit() + +end + +function GM:GetHelpHTML() + + local str = "" + + for k,v in pairs( GAMEMODE.HelpText ) do + + str = str .. v + + end + + return str + +end + +// Help menu - comment this out later? +function GM:ShowHelp() + + if IsValid( self.HelpFrame ) then return end + + self.HelpFrame = vgui.Create( "HelpMenu" ) + self.HelpFrame:SetSize( 415, 370 ) + self.HelpFrame:Center() + self.HelpFrame:MakePopup() + self.HelpFrame:SetKeyboardInputEnabled( false ) + +end + +function GM:ShowClasses() + + --[[local classmenu = vgui.Create( "ClassPicker" ) + classmenu:SetSize( 415, 475 ) + classmenu:Center() + classmenu:MakePopup()]] + + GAMEMODE:ShowHelp() + +end + +function GM:ShowZombieClasses() + + if IsValid( self.Classes ) then return end + + self.Classes = vgui.Create( "ZombieClassPicker" ) + self.Classes:SetSize( 415, 475 ) + self.Classes:Center() + self.Classes:MakePopup() + +end + +function GM:HUDShouldDraw( name ) + + if GAMEMODE.ScoreboardVisible then return false end + + for k, v in pairs{ "CHudHealth", "CHudBattery", "CHudAmmo", "CHudSecondaryAmmo", "CHudSuitPower", "CHudPoisonDamageIndicator", "CHudCrosshair" } do + + if name == v then return false end + + end + + if name == "CHudDamageIndicator" and not LocalPlayer():Alive() then + + return false + + end + + return true + +end + +function GM:Think() + + GAMEMODE:ProcessWeather() + GAMEMODE:FadeRagdolls() + GAMEMODE:GoreRagdolls() + GAMEMODE:HUDTraces() + //GAMEMODE:SpawnRagdolls() + + if GetGlobalBool( "GameOver", false ) and not EndScreenShown then + + EndScreenShown = true + + local endscreen = vgui.Create( "EndGame" ) + endscreen:SetPos(0,0) + + end + + if IsValid( LocalPlayer() ) and LocalPlayer():Alive() and not StartMenuShown then + + StartMenuShown = true + GAMEMODE:ShowClasses() + + //player_manager.SetPlayerClass( LocalPlayer(), "player_base" ) + + end + + if not LocalPlayer():Alive() and GAMEMODE:ElementsVisible() then + + GAMEMODE:ClearElements() + + gui.EnableScreenClicker( false ) + + end + + if LocalPlayer():Team() != TEAM_ARMY then return end + + if LocalPlayer():Alive() and HeartBeat < CurTime() and ( LocalPlayer():GetNWBool( "Bleeding", false ) or LocalPlayer():Health() < 50 ) then + + local scale = LocalPlayer():Health() / 100 + HeartBeat = CurTime() + 0.5 + scale * 1.5 + + LocalPlayer():EmitSound( Sound( "nuke/heartbeat.wav" ), 100, 150 - scale * 50 ) + + end + + --[[if Inv_HasItem( "models/gibs/shield_scanner_gib1.mdl" ) then + + MaxDist = 2200 + ArmSpeed = 90 + + else + + MaxDist = 1500 + ArmSpeed = 70 + + end + + if ( NextRadarThink or 0 ) < CurTime() then + + NextRadarThink = CurTime() + 1.5 + + RadarEntTable = team.GetPlayers( TEAM_ZOMBIES ) + RadarEntTable = table.Add( RadarEntTable, team.GetPlayers( TEAM_ARMY ) ) + RadarEntTable = table.Add( RadarEntTable, ents.FindByClass( "npc_*" ) ) + RadarEntTable = table.Add( RadarEntTable, ents.FindByClass( "sent_lootbag" ) ) + RadarEntTable = table.Add( RadarEntTable, ents.FindByClass( "point_stash" ) ) + RadarEntTable = table.Add( RadarEntTable, ents.FindByClass( "sent_supplycrate" ) ) + RadarEntTable = table.Add( RadarEntTable, ents.FindByClass( "sent_antidote" ) ) + + end + + local aimvec = LocalPlayer():GetAimVector() + + for k,v in pairs( RadarEntTable ) do + + if not IsValid( v ) then break end + + local dirp = ( LocalPlayer():GetPos() - v:GetPos() ):GetNormal() + local aimvec = LocalPlayer():GetAimVector() + aimvec.z = dirp.z + + local dir = ( aimvec:Angle() + Angle( 0, ArmAngle + 90, 0 ) ):Forward() + local dot = dir:Dot( dirp ) + local diff = ( v:GetPos() - LocalPlayer():GetPos() ) + + local close = math.sqrt( diff.x * diff.x + diff.y * diff.y ) < MaxDist * FadeDist + + if ( !v:IsPlayer() or ( v:Alive() and ( v != LocalPlayer() and ( v:Team() == LocalPlayer():Team() or close ) ) ) ) and !IsOnRadar( v ) and ( dot > 0.99 or close ) then + + local pos = v:GetPos() + local color = Color( 0, 255, 0 ) + + if not v:IsPlayer() then + + color = Color( 80, 150, 255 ) + + if v:GetClass() == "sent_antidote" or v:GetClass() == "sent_supplycrate" then + + color = Color( 255, 255, 255 ) + + elseif v:IsNPC() then + + if v:GetClass() == "npc_scientist" then + + color = Color( 200, 200, 0 ) + + else + + color = Color( 255, 80, 80 ) + + end + + end + + elseif v:IsPlayer() and v:Team() != LocalPlayer():Team() then + + color = Color( 255, 80, 80 ) + + end + + local dietime = CurTime() + BlipTime + + if close then + + dietime = -1 + + end + + table.insert( PosTable, { Ent = v, Pos = pos, DieTime = dietime, Color = color } ) + + end + + end]] + +end + +function GM:FadeRagdolls() + + for k,v in pairs( ents.FindByClass( "class C_ClientRagdoll" ) ) do + + if v.Time and v.Time < CurTime() then + + //v:SetColor( Color( 255, 255, 255, v.Alpha ) ) + //v.Alpha = math.Approach( v.Alpha, 0, -2 ) + + //if v.Alpha <= 0 then + //v:Remove() + //end + + v:Remove() + + elseif not v.Time then + + v.Time = CurTime() + 12 + //v.Alpha = 255 + + end + + end + +end + +function GM:GetNearestEnt( pos, dist, tbl ) + + local closest + local best = 9000 + + for k,v in pairs( tbl ) do + + local newdist = v:GetPos():Distance( pos ) + + if newdist < dist and newdist < best then + + closest = v + + end + + end + + return closest + +end + +GM.GoreSheets = { "models/charple/charple1_sheet", +"models/charple/charple3_sheet", +"models/charple/charple4_sheet" } + +function GM:GoreRagdolls() + + local tbl = ents.FindByClass( "class C_HL2MPRagdoll" ) + tbl = table.Add( tbl, ents.FindByClass( "class C_ClientRagdoll" ) ) + + for k,v in pairs( tbl ) do + + if not v.Gore and table.HasValue( GAMEMODE.Corpses, string.lower( v:GetModel() ) ) then + + v.Gore = true + v:SetMaterial( "models/flesh" ) + + local phys = v:GetPhysicsObject() + + if IsValid( phys ) then + + phys:ApplyForceCenter( VectorRand() * 5000 ) + + end + + elseif not LocalPlayer():Alive() and IsValid( LocalPlayer():GetRagdollEntity() ) and LocalPlayer():GetRagdollEntity() == v and not v.Slowed and not table.HasValue( GAMEMODE.Corpses, string.lower( v:GetModel() ) ) then + + v.Slowed = true + + local phys = v:GetPhysicsObject() + + if IsValid( phys ) then + + local count = LocalPlayer():GetRagdollEntity():GetPhysicsObjectCount() + + for i=0, count do + + local limb = v:GetPhysicsObjectNum( i ) + + if IsValid( limb ) then + + limb:SetDamping( 5, 0 ) + limb:ApplyForceCenter( VectorRand() * 50 ) + + end + + end + + phys:Wake() + + end + + end + + if not v.Randomized then + + v.Randomized = true + + if math.random(1,2) == 1 then + + local phys = v:GetPhysicsObject() + + if IsValid( phys ) then + + for i=1, math.random(2,6) do + + local count = v:GetPhysicsObjectCount() + local limb = v:GetPhysicsObjectNum( math.random( 0, count ) ) + + if IsValid( limb ) then + + limb:SetDamping( math.Rand( 0, 2 ), math.Rand( 0, 5 ) ) + limb:ApplyForceCenter( VectorRand() * 75 ) + + end + + phys:Wake() + + end + + end + + end + + end + + end + + for c,d in pairs( HeadlessTbl ) do + + local ent = GAMEMODE:GetNearestEnt( d.Pos, 50, tbl ) + + if IsValid( ent ) and not ent.IsHeadless then + + ent:ManipulateBoneScale( 6, Vector( 0.01, 0.01, 0.01 ) ) + ent:ManipulateBoneScale( 6, Vector( 0.001, 0.001, 0.001 ) ) + + ent.IsHeadless = true + + table.remove( HeadlessTbl, c ) + + break + + elseif d.Time < CurTime() then + + table.remove( HeadlessTbl, c ) + + break + + end + + end + + for c,d in pairs( BurnTbl ) do + + local ent = GAMEMODE:GetNearestEnt( d.Pos, 50, tbl ) + + if IsValid( ent ) and not ent.IsBurnt then + + ent:SetMaterial( table.Random( GAMEMODE.GoreSheets ) ) + ent.IsBurnt = true + + table.remove( BurnTbl, c ) + + break + + elseif d.Time < CurTime() then + + table.remove( BurnTbl, c ) + + break + + end + + end + +end + +function GM:SpawnRagdolls() + + local tbl = ents.FindByClass( "npc_*" ) + + for c,d in pairs( RagdollTbl ) do + + local ent = GAMEMODE:GetNearestEnt( d.Pos, 30, tbl ) + + if IsValid( ent ) and not ent.Ragdolled then + + ent:BecomeRagdollOnClient() + ent.Ragdolled = true + + table.remove( RagdollTbl, c ) + + break + + elseif d.Time < CurTime() then + + table.remove( RagdollTbl, c ) + + break + + end + + end + +end + +function DrawBar( x, y, w, h, value, maxvalue, icon, colorlight, colordark, hp ) + + draw.RoundedBox( 4, x - 1, y, h + 1, h, Color( 0, 0, 0, 180 ) ) + + surface.SetDrawColor( colorlight.r, colorlight.g, colorlight.b, 180 ) + surface.SetMaterial( icon ) + surface.DrawTexturedRect( x, y + 1, h - 1, h - 2 ) + + x = x + h + 4 + + local w = 5 + maxvalue * 2 + + draw.RoundedBox( 4, x, y, w, h, Color( 0, 0, 0, 180 ) ) + + for i=1, value do + + local grn = colorlight.g + + if i <= 50 then + + grn = grn + 50 + + end + + draw.RoundedBox( 0, 1 + x + i * 2, y + 3, 1, h - 6, colordark ) + draw.RoundedBox( 0, 1 + x + i * 2, y + 3 + ( h * 0.2 ), 1, h - 6 - ( h * 0.4 ), Color( colorlight.r, grn, colorlight.b ) ) + + --[[if hp then + + if i % 6 == 0 or ( i + 1 ) % 6 == 0 or ( i + 2 ) % 6 == 0 then + + draw.RoundedBox( 0, 1 + x + i * 2, y + 3, 1, ( h * ( math.sin( CurTime() * 3 + i ) * 0.2 + 0.5 ) ) - 3, Color( colorlight.r, grn, colorlight.b ) ) + + end + + draw.RoundedBox( 0, 1 + x + i * 2, y + 3, 1, ( h * 0.4 ) - 3, Color( colorlight.r, grn, colorlight.b ) ) + + else + + draw.RoundedBox( 0, 1 + x + i * 2, y + 3, 1, ( h * ( math.sin( ( CurTime() * 0.1 + i * 0.5 ) ) * ( math.sin( CurTime() * 2 ) * 0.15 ) + 0.5 ) ) - 3, Color( colorlight.r, grn, colorlight.b ) ) + + end]] + + end + +end + +function DrawIcon( x, y, w, h, icon, color ) + + draw.RoundedBox( 4, x - 1, y, h + 1, h, Color( 0, 0, 0, 180 ) ) + + surface.SetDrawColor( color.r, color.g, color.b, 180 ) + surface.SetMaterial( icon ) + surface.DrawTexturedRect( x, y + 1, h - 1, h - 2 ) + +end + +function DrawAmmo( x, y, w, h, text, label ) + + if not IsValid( LocalPlayer():GetActiveWeapon() ) then return end + + draw.RoundedBox( 4, x, y, w, h, Color( 0, 0, 0, 180 ) ) + + draw.SimpleText( text, "AmmoFont", x + 5, y + ( h * 0.5 ) - 5, Color( 255, 255, 255 ), TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + draw.SimpleText( label, "AmmoFontSmall", x + 5, y + 5, Color( 255, 255, 150 ), TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + +end + +function DrawCash( x, y, w, h, text ) + + draw.RoundedBox( 4, x, y, w, h, Color( 0, 0, 0, 180 ) ) + draw.SimpleText( text, "CashFont", x + w * 0.5, y + h * 0.5 + 2, Color( 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + +end + +function GM:GetAfflictions() + + local tbl = {} + local cols = { Color( 40, 200, 40 ), Color( 80, 150, 40 ), Color( 150, 150, 0 ), Color( 200, 100, 40 ), Color( 255, 40, 40 ) } + + if LocalPlayer():GetNWBool( "Infected", false ) then + + table.insert( tbl, { Icon = matInfection, Color = Color( 40, 200, 40 ) } ) + + end + + if LocalPlayer():GetNWBool( "Bleeding", false ) then + + table.insert( tbl, { Icon = matBlood, Color = Color( 225, 40, 40 ) } ) + + end + + if LocalPlayer():GetNWInt( "Radiation", 0 ) > 0 then + + table.insert( tbl, { Icon = matRadiation, Color = cols[ LocalPlayer():GetNWInt( "Radiation", 1 ) ] } ) + + end + + return tbl + +end + +function GM:GetHealthColor() + + local hp = math.Clamp( LocalPlayer():Health(), 0, 500 ) + + if hp > 150 then + + return Color( 0, 255, 255 ) + + end + + local scale = hp / 150 + + return Color( ( 1 - scale ) * 255, scale * 255, scale * 255 ) + +end + +function GM:DrawMarkers() + + local tbl = ents.FindByClass( "sent_heliflare" ) + tbl = table.Add( tbl, ents.FindByClass( "sent_antidote" ) ) + + for k,v in pairs( tbl ) do + + local sc = v:GetPos():ToScreen() + + if sc.visible then + + local text = "antidote" + local offset = ( v:GetPos() + Vector(0,0,80) ):ToScreen() + local dist = v:GetPos():Distance( LocalPlayer():GetPos() ) + local maxdist = 1600 + + if v:GetClass() == "sent_heliflare" then + + text = "evac zone" + offset = ( v:GetPos() + Vector(0,0,40) ):ToScreen() + maxdist = 600 + + end + + local alpha = math.Clamp( dist - maxdist, 0, 200 ) / 200 + + sc.y = sc.y + ( offset.y - sc.y ) + + draw.SimpleText( text, "HudMarker", sc.x, sc.y, Color( 255, 255, 255, alpha * 255 ), TEXT_ALIGN_CENTER ) + + end + + end + +end + +function GM:HUDPaint() + + if GetGlobalBool( "GameOver", false ) then return end + + if LocalPlayer():IsFrozen() then return end + + if LocalPlayer():Team() == TEAM_ZOMBIES then + + GAMEMODE:PaintWeather() + + if not LocalPlayer():Alive() then + + DeathScreenScale = math.Approach( DeathScreenScale, 1, FrameTime() * 0.3 ) + + draw.RoundedBox( 0, 0, 0, ScrW(), ScrH() * ( 0.15 * DeathScreenScale ), Color( 0, 0, 0, 180 ) ) + draw.RoundedBox( 0, 0, ScrH() - ( ScrH() * ( 0.15 * DeathScreenScale ) ), ScrW(), ScrH() * ( 0.15 * DeathScreenScale ), Color( 0, 0, 0, 180 ) ) + + if DeathScreenScale == 1 then + + local dtime = math.Round( DeathScreenTime - CurTime() ) + + if dtime > 0 then + + draw.SimpleText( "YOU WILL RESPAWN IN "..dtime.." SECONDS", "DeathFont", ScrW() * 0.5, ScrH() * 0.1, Color( 255, 0, 0 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + else + + draw.SimpleText( "PRESS ANY KEY TO RESPAWN", "DeathFont", ScrW() * 0.5, ScrH() * 0.1, Color( 255, 0, 0 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + end + + draw.SimpleText( DeathScreenText or "POOP", "DeathFont", ScrW() * 0.5, ScrH() * 0.9, Color( 255, 0, 0 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + end + + else + + local hp = math.Clamp( LocalPlayer():Health(), 0, 500 ) + local x, y = 40, ScrH() - 60 + + surface.SetFont( "ZombieHud" ) + local w, h = surface.GetTextSize( "Health: " .. hp ) + + draw.RoundedBox( 4, 30, ScrH() - 70, w + 20, h + 20, Color( 0, 0, 0, 180 ) ) + + draw.SimpleText( "Health: " .. hp, "ZombieHud", x+1, y+1, Color(40,40,40), TEXT_ALIGN_LEFT ) + draw.SimpleText( "Health: " .. hp, "ZombieHud", x+1, y-1, Color(40,40,40), TEXT_ALIGN_LEFT ) + draw.SimpleText( "Health: " .. hp, "ZombieHud", x-1, y-1, Color(40,40,40), TEXT_ALIGN_LEFT ) + draw.SimpleText( "Health: " .. hp, "ZombieHud", x-1, y+1, Color(40,40,40), TEXT_ALIGN_LEFT ) + draw.SimpleText( "Health: " .. hp, "ZombieHud", x, y, GAMEMODE:GetHealthColor(), TEXT_ALIGN_LEFT ) + + if not LocalPlayer():GetNWBool( "Lord", false ) then return end + + local xpos, ypos = x + w + 20, ScrH() - 70 + local w = 200 + local scale = math.floor( w * math.Clamp( LocalPlayer():GetNWInt( "ZedDamage", 0 ) / GAMEMODE.RedemptionDamage, 0.01, 1.00 ) ) + local pos = 0 + + draw.RoundedBox( 4, xpos, ypos, w + 20, h + 20, Color( 0, 0, 0, 180 ) ) + + if scale == 200 then + + draw.RoundedBox( 0, xpos + 10, ScrH() - 60, scale, h, Color( 200, 0, 0, 200 ) ) + + else + + draw.RoundedBox( 0, xpos + 10, ScrH() - 60, scale, h, Color( 100, 0, 0, 200 ) ) + + end + + while pos < scale do + + local width = math.min( math.random( 10, 50 ), math.max( scale - pos, 1 ) ) + + local tbl = {} + tbl.texture = surface.GetTextureID( "nuke/redead/noise0" .. math.random(1,3) ) + tbl.x = xpos + pos + 10 + tbl.y = ScrH() - 60 + tbl.w = width + tbl.h = h + + if scale == 200 then + + tbl.color = Color( 250, 125 + math.sin( CurTime() * 5 ) * 125, 125 + math.sin( CurTime() * 5 ) * 125, 250 ) + + else + + tbl.color = Color( 250, 0, 0, 200 ) + + end + + draw.TexturedQuad( tbl ) + + pos = pos + width + + end + + end + + return + + end + + GAMEMODE:HUDDrawTargetID() + + if not LocalPlayer():Alive() and LocalPlayer():Team() != TEAM_UNASSIGNED then + + DeathScreenScale = math.Approach( DeathScreenScale, 1, FrameTime() * 0.3 ) + + draw.RoundedBox( 0, 0, 0, ScrW(), ScrH() * ( 0.15 * DeathScreenScale ), Color( 0, 0, 0, 180 ) ) + draw.RoundedBox( 0, 0, ScrH() - ( ScrH() * ( 0.15 * DeathScreenScale ) ), ScrW(), ScrH() * ( 0.15 * DeathScreenScale ), Color( 0, 0, 0, 180 ) ) + + if DeathScreenScale == 1 then + + local dtime = math.Round( DeathScreenTime - CurTime() ) + + if dtime > 0 then + + draw.SimpleText( "YOU WILL RESPAWN IN "..dtime.." SECONDS", "DeathFont", ScrW() * 0.5, ScrH() * 0.1, Color( 255, 0, 0 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + else + + draw.SimpleText( "PRESS ANY KEY TO RESPAWN", "DeathFont", ScrW() * 0.5, ScrH() * 0.1, Color( 255, 0, 0 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + end + + draw.SimpleText( DeathScreenText or "POOP", "DeathFont", ScrW() * 0.5, ScrH() * 0.9, Color( 255, 0, 0 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + end + + end + + if not LocalPlayer():Alive() or LocalPlayer():Team() == TEAM_UNASSIGNED then return end //or GAMEMODE:ElementsVisible() then return end + + GAMEMODE:DrawMarkers() + + local xlen = 200 + local ylen = 25 + local xpos = 5 + local ypos = ScrH() - 5 - ylen + + DrawBar( xpos, ypos, xlen, ylen, LocalPlayer():Health(), 150, matHealth, Color( 225, 50, 50, 255 ), Color( 175, 25, 25, 255 ), true ) + + ypos = ScrH() - 10 - ylen * 2 + + local stam = LocalPlayer():GetNWInt( "Stamina", 0 ) + + DrawBar( xpos, ypos, xlen, ylen, stam, 150, matStamina, Color( 50, 100, 225, 255 ), Color( 25, 50, 175, 255 ), false ) + + local tbl = GAMEMODE:GetAfflictions() + + for k,v in pairs( tbl ) do + + ypos = ScrH() - ( 10 + ( k * 5 ) ) - ylen * ( 2 + k ) + + DrawIcon( xpos, ypos, xlen, ylen, v.Icon, v.Color ) + + end + + local ylen = 55 + local ypos = 35 + + if IsValid( LocalPlayer():GetActiveWeapon() ) and ( LocalPlayer():GetActiveWeapon().AmmoType or "SMG" ) != "Knife" then + + local total = LocalPlayer():GetNWInt( "Ammo" .. ( LocalPlayer():GetActiveWeapon().AmmoType or "SMG" ), 0 ) + local ammo = math.Clamp( LocalPlayer():GetActiveWeapon():Clip1(), 0, total ) + + local xlen = 50 + + DrawAmmo( ScrW() - 5 - xlen, ScrH() - ylen - 5, xlen, ylen, total, "TOTAL" ) + DrawAmmo( ScrW() - 10 - xlen * 2, ScrH() - ylen - 5, xlen, ylen, ammo, "AMMO" ) + + ypos = ypos + ylen + 5 + + end + + DrawCash( ScrW() - 110, ScrH() - ypos, 105, 30, string.upper( LocalPlayer():GetNWInt( "Cash", 0 ) .. " " .. GAMEMODE.CurrencyName .. "s" ) ) + + GAMEMODE:PaintWeather() + --[[local radius = 200 + local centerx = ScrW() - ( radius / 2 ) - 20 + local centery = 20 + ( radius / 2 ) + + ArmAngle = ArmAngle + FrameTime() * ArmSpeed + + if ArmAngle > 360 then + ArmAngle = 0 + ( ArmAngle - 360 ) + end + + surface.SetDrawColor( 255, 255, 255, 220 ) + surface.SetMaterial( matRadar ) + surface.DrawTexturedRect( ScrW() - radius - 20, 20, radius, radius ) + + local aimvec = LocalPlayer():GetAimVector() + + for k,v in pairs( PosTable ) do + + local diff = v.Pos - LocalPlayer():GetPos() + local alpha = 100 + + if IsValid( v.Ent ) and ( v.Ent:IsPlayer() or v.Ent:IsNPC() ) then + + diff = v.Ent:GetPos() - LocalPlayer():GetPos() + + end + + if v.DieTime != -1 then + + alpha = 100 * ( math.Clamp( v.DieTime - CurTime(), 0, BlipTime ) / BlipTime ) + + elseif not IsValid( v.Ent ) then + + PosTable[k].DieTime = CurTime() + 1.5 + + end + + if math.sqrt( diff.x * diff.x + diff.y * diff.y ) > MaxDist * FadeDist and v.DieTime == -1 then + + PosTable[k].DieTime = CurTime() + 1.5 // Remove the dot because they left our inner circle + + end + + if alpha > 0 and math.sqrt( diff.x * diff.x + diff.y * diff.y ) < MaxDist then + + local addx = diff.x / MaxDist + local addy = diff.y / MaxDist + local addz = math.sqrt( addx * addx + addy * addy ) + local phi = math.atan2( addx, addy ) - math.atan2( aimvec.x, aimvec.y ) - ( math.pi / 2 ) + + addx = math.cos( phi ) * addz + addy = math.sin( phi ) * addz + + draw.RoundedBox( 4, centerx + addx * ( ( radius - 15 ) / 2 ) - 4, centery + addy * ( ( radius - 15 ) / 2 ) - 4, 5, 5, Color( v.Color.r, v.Color.g, v.Color.b, alpha ) ) + + end + + end + + for k,v in pairs( PosTable ) do + + if v.DieTime != -1 and v.DieTime < CurTime() then + + table.remove( PosTable, k ) + + end + + end + + surface.SetDrawColor( 255, 255, 255, 220 ) + surface.SetMaterial( matArm ) + surface.DrawTexturedRectRotated( centerx, centery, radius, radius, ArmAngle ) + + local ent = LocalPlayer():GetDTEntity( 0 ) + + if IsValid( ent ) or StaticPos != Vector(0,0,0) then + + local ang = Angle(0,0,0) + + if IsValid( ent ) then + + ang = ( ent:GetPos() - LocalPlayer():GetShootPos()):Angle() - LocalPlayer():GetForward():Angle() + + local diff = ( ent:GetPos() - LocalPlayer():GetPos() ) + + if math.sqrt( diff.x * diff.x + diff.y * diff.y ) < MaxDist * FadeDist then + + return + + end + + end + + if StaticPos != Vector(0,0,0) then + + ang = ( StaticPos - LocalPlayer():GetShootPos()):Angle() - LocalPlayer():GetForward():Angle() + + end + + surface.SetDrawColor( 255, 255, 255, 200 ) + surface.SetMaterial( matArrow ) + surface.DrawTexturedRectRotated( centerx, centery, radius, radius, ang.y ) + + end]] + +end + +--[[function IsOnRadar( ent ) + + for k,v in pairs( PosTable ) do + + if v.Ent == ent then + + return v + + end + + end + +end]] + +function GM:HUDWeaponPickedUp( wep ) + +end + +function GM:HUDItemPickedUp( itemname ) + +end + +function GM:HUDAmmoPickedUp( itemname, amount ) + +end + +function GM:HUDDrawPickupHistory( ) + +end + +function GM:HUDPaintBackground() + +end + +function GM:CreateMove( cmd ) + + if LocalPlayer():Team() == TEAM_ZOMBIES then + + if bit.band( cmd:GetButtons(), IN_DUCK ) > 0 then + + cmd:SetButtons( cmd:GetButtons() - IN_DUCK ) + + end + + local ang = cmd:GetViewAngles() + + if ang.r != 0 then + + ang.r = 0 + cmd:SetViewAngles( ang ) + + end + + else + + local scale = LocalPlayer():GetNWInt( "Radiation", 0 ) / 5 + local wobble = 0 + + if LocalPlayer():GetNWBool( "Infected", false ) then + + scale = math.max( scale, 0.3 ) + + end + + if scale > 0 and LocalPlayer():Alive() then + + wobble = scale * 0.05 + + end + + local drunkscale = Drunkness / 10 + + if Drunkness > 0 then + + if ( DrunkTimer or 0 ) < CurTime() then + + Drunkness = math.Clamp( Drunkness - 1, 0, 20 ) + DrunkTimer = CurTime() + 15 + + end + + wobble = wobble + ( drunkscale * 0.08 ) + + end + + if LocalPlayer():Health() <= 75 and LocalPlayer():Alive() then + + local hscale = math.Clamp( LocalPlayer():Health() / 50, 0, 1 ) + wobble = wobble + ( 0.05 - 0.05 * hscale ) + + end + + ViewWobble = math.Approach( ViewWobble, wobble, FrameTime() * 0.1 ) + + local ang = cmd:GetViewAngles() + + if ViewWobble > 0 or ang.r != 0 then + + ang.p = ang.p + math.sin( CurTime() ) * ViewWobble + ang.y = ang.y + math.cos( CurTime() ) * ViewWobble + ang.r = math.Approach( ang.r + math.sin( CurTime() ) * ( ( ViewWobble * 0.5 ) * math.cos( CurTime() * ViewWobble ) ), 0, FrameTime() * 0.5 ) + + cmd:SetViewAngles( ang ) + + end + + end + +end + +function GrenadeHit( msg ) + + DisorientTime = CurTime() + 8 + +end +usermessage.Hook( "GrenadeHit", GrenadeHit ) + +function ScreamHit( msg ) + + ScreamTime = CurTime() + 8 + +end +usermessage.Hook( "ScreamHit", ScreamHit ) + +function DeathScreen( msg ) + + local dteam = msg:ReadShort() + + DeathScreenScale = 0 + DeathScreenTime = CurTime() + 10 + DeathScreenText = table.Random( GAMEMODE.DeathScreenText[ dteam or TEAM_ARMY ] ) + +end +usermessage.Hook( "DeathScreen", DeathScreen ) + +--[[function Ragdoll( msg ) + + local pos = msg:ReadVector() + local burn = msg:ReadShort() + local ent = Entity( msg:ReadShort() ) + + if IsValid( ent ) and not ent.Ragdolled then + + ent:BecomeRagdollOnClient() + ent.Ragdolled = true + + end + + if burn == 2 then + + table.insert( BurnTbl, { Pos = pos, Time = CurTime() + 0.5 } ) + + end + +end +usermessage.Hook( "Ragdoll", Ragdoll )]] + +function Burned( msg ) + + table.insert( BurnTbl, { Pos = msg:ReadVector(), Time = CurTime() + 0.5 } ) + +end +usermessage.Hook( "Burned", Burned ) + +function Gibbed( msg ) + + table.insert( GibbedTbl, { Pos = msg:ReadVector(), Time = CurTime() + 0.5 } ) + +end +usermessage.Hook( "Gibbed", Gibbed ) + +function Headless( msg ) + + table.insert( HeadlessTbl, { Pos = msg:ReadVector(), Time = CurTime() + 0.5 } ) + +end +usermessage.Hook( "Headless", Headless ) + +function SetRadarTarget( msg ) + + StaticPos = msg:ReadVector() + +end +usermessage.Hook( "StaticTarget", SetRadarTarget ) + +function AddDrunkness( msg ) + + Drunkness = math.Clamp( Drunkness + msg:ReadShort(), 0, 20 ) + DrunkTimer = CurTime() + 30 + +end +usermessage.Hook( "Drunk", AddDrunkness ) + +function CashSynch( msg ) + + Inv_SetStashCash( msg:ReadShort() ) + +end +usermessage.Hook( "CashSynch", CashSynch ) + +function Radio( msg ) + + local num = msg:ReadShort() + local snd = msg:ReadString() + + if num == 100 then + + surface.PlaySound( snd ) + + else + + if not IsValid( LocalPlayer() ) then return end + + sound.Play( snd, LocalPlayer():GetShootPos(), 180, num, 1 ) + + end + +end +usermessage.Hook( "Radio", Radio ) + +net.Receive( "StatsSynch", function( len ) + + local count = net.ReadInt( 8 ) + PlayerStats = {} + + for i=1, count do + + table.insert( PlayerStats, { Player = net.ReadEntity(), Stats = net.ReadTable() } ) + + end + +end ) + +net.Receive( "InventorySynch", function( len ) + + LocalInventory = net.ReadTable() + + if GAMEMODE.ItemSheet and GAMEMODE.ItemSheet:IsVisible() then + + GAMEMODE.ItemSheet:RefreshItems( LocalInventory ) + + end + +end ) + +net.Receive( "StashSynch", function( len ) + + LocalStash = net.ReadTable() + + if StashScreen and StashScreen:IsVisible() then + + StashScreen:RefreshItems( LocalStash ) + + end + +end ) diff --git a/gamemode/cl_inventory.lua b/gamemode/cl_inventory.lua new file mode 100644 index 0000000..f8df461 --- /dev/null +++ b/gamemode/cl_inventory.lua @@ -0,0 +1,82 @@ + +LocalInventory = {} +LocalStash = {} +LocalStashCash = 0 +PreviewStyle = "Stash" +PreviewPriceScale = 1 + +function Inv_HasItem( id ) + + for k,v in pairs( LocalInventory ) do + + local tbl = item.GetByID( v ) + + if ( type( id ) == "number" and tbl.ID == id ) or ( type( id ) == "string" and tbl.Model == id ) then + + return tbl + + end + + end + +end + +function Inv_ItemCount( id ) + + local count = 0 + + for k,v in pairs( LocalInventory ) do + + if v == id then + + count = count + 1 + + end + + end + + return count + +end + +function Inv_Get( pos ) + + return LocalInventory[ pos ] + +end + +function Inv_UniqueItems() + + local ids = {} + + for k,v in pairs( LocalInventory ) do + + if not table.HasValue( ids, v ) then + + table.insert( ids, v ) + + end + + end + + return ids + +end + +function Inv_Size() + + return #LocalInventory + +end + +function Inv_GetStashCash() + + return LocalStashCash + +end + +function Inv_SetStashCash( amt ) + + LocalStashCash = amt + +end
\ No newline at end of file diff --git a/gamemode/cl_notice.lua b/gamemode/cl_notice.lua new file mode 100644 index 0000000..c2a7333 --- /dev/null +++ b/gamemode/cl_notice.lua @@ -0,0 +1,156 @@ + +local HUDNote_c = 0 +local HUDNote_i = 1 +local HUDNotes = {} +local NoteQueue = {} +local NextNotify = 0 + +surface.CreateFont ( "Notice", { size = 18, weight = 500, antialias = true, additive = true, font = "Typenoksidi" } ) + +function DoNotice( msg ) + + local str = msg:ReadString() + local r = msg:ReadShort() + local g = msg:ReadShort() + local b = msg:ReadShort() + local len = msg:ReadShort() + local once = msg:ReadBool() + local col = Color( r, g, b, 255 ) + + if once and not CV_NoobHelp:GetBool() then return end + + MsgN( str ) + + str = string.gsub( str, " ", " " ) + + GAMEMODE:AddNotify( str, col, len ) + +end +usermessage.Hook( "ToxNotice", DoNotice ) + +function GM:AddNotify( msg, col, len ) + + local tab = {} + tab.text = msg + tab.recv = 0 //systime + tab.len = len //how long to display + tab.velx = -5 + tab.vely = 0 + tab.x = ScrW() + 200 + tab.y = ScrH() + tab.a = 255 + tab.col = col + + table.insert( NoteQueue, tab ) + +end + +function NotifyThink() + + if NextNotify < CurTime() then + + NextNotify = CurTime() + 0.3 + + if NoteQueue[1] then + + NoteQueue[1].recv = SysTime() + + table.insert( HUDNotes, NoteQueue[1] ) + + HUDNote_c = HUDNote_c + 1 + HUDNote_i = HUDNote_i + 1 + + table.remove( NoteQueue, 1 ) + + end + + end + +end +hook.Add( "Think", "NotifyThink", NotifyThink ) + +local function DrawNotice( self, k, v, i ) + + local H = ScrH() / 1024 + local x = v.x - 25 * H //74 + local y = v.y - 300 * H //580 * H + + if !v.w then + + surface.SetFont( "Notice" ) + v.w, v.h = surface.GetTextSize( v.text ) + + end + + local w = v.w + local h = v.h + w = w - 16 + h = h + 16 + + draw.RoundedBox( 4, x - w - h + 8, y - 8, w + h, h, Color( 10, 10, 10, v.a * 0.5 ) ) + + draw.SimpleText( v.text, "Notice", x+1, y+1, Color(0,0,0,v.a*0.8), TEXT_ALIGN_RIGHT ) + draw.SimpleText( v.text, "Notice", x-1, y-1, Color(0,0,0,v.a*0.5), TEXT_ALIGN_RIGHT ) + draw.SimpleText( v.text, "Notice", x+1, y-1, Color(0,0,0,v.a*0.6), TEXT_ALIGN_RIGHT ) + draw.SimpleText( v.text, "Notice", x-1, y+1, Color(0,0,0,v.a*0.6), TEXT_ALIGN_RIGHT ) + draw.SimpleText( v.text, "Notice", x, y, v.col, TEXT_ALIGN_RIGHT ) + + local ideal_y = ScrH() - (HUDNote_c - i) * (h + 4) + local ideal_x = ScrW() + + local timeleft = v.len - ( SysTime() - v.recv ) + + //gone from screen + + if ( timeleft < 0.5 ) then + + ideal_x = ScrW() + w * 4 //2 + + end + + local spd = RealFrameTime() * 15 + + v.y = v.y + v.vely * spd + v.x = v.x + v.velx * spd + + local dist = ideal_y - v.y + v.vely = v.vely + dist * spd * 1 + + if (math.abs(dist) < 2 && math.abs(v.vely) < 0.1) then v.vely = 0 end + + local dist = ideal_x - v.x + + v.velx = v.velx + dist * spd * 1 + + if (math.abs(dist) < 2 && math.abs(v.velx) < 0.1) then v.velx = 0 end + + //friction that is FPS independant + + v.velx = v.velx * (0.95 - RealFrameTime() * 8 ) + v.vely = v.vely * (0.95 - RealFrameTime() * 8 ) + +end + +function PaintNotes() + + if ( !HUDNotes ) then return end + + local i = 0 + for k, v in pairs( HUDNotes ) do + if ( v != 0 ) then + i = i + 1 + DrawNotice( self, k, v, i) + end + end + + for k, v in pairs( HUDNotes ) do + if ( v != 0 && v.recv + v.len < SysTime() ) then + HUDNotes[ k ] = 0 + HUDNote_c = HUDNote_c - 1 + if (HUDNote_c == 0) then HUDNotes = {} end + end + end +end + +hook.Add("HUDPaint", "PaintNotes", PaintNotes) + diff --git a/gamemode/cl_postprocess.lua b/gamemode/cl_postprocess.lua new file mode 100644 index 0000000..9afad78 --- /dev/null +++ b/gamemode/cl_postprocess.lua @@ -0,0 +1,516 @@ + +Sharpen = 0 +MotionBlur = 0 +DisorientTime = 0 + +ColorModify = {} +ColorModify[ "$pp_colour_addr" ] = 0 +ColorModify[ "$pp_colour_addg" ] = 0 +ColorModify[ "$pp_colour_addb" ] = 0 +ColorModify[ "$pp_colour_brightness" ] = 0 +ColorModify[ "$pp_colour_contrast" ] = 1 +ColorModify[ "$pp_colour_colour" ] = 1 +ColorModify[ "$pp_colour_mulr" ] = 0 +ColorModify[ "$pp_colour_mulg" ] = 0 +ColorModify[ "$pp_colour_mulb" ] = 0 + +MixedColorMod = {} + +function GM:DOFThink() + +end + +function GM:RenderScreenspaceEffects() + + local approach = FrameTime() * 0.05 + + if ( Sharpen > 0 ) then + + DrawSharpen( Sharpen, 0.5 ) + + Sharpen = math.Approach( Sharpen, 0, FrameTime() * 0.5 ) + + end + + if ( MotionBlur > 0 ) then + + DrawMotionBlur( 1 - MotionBlur, 1.0, 0.0 ) + + MotionBlur = math.Approach( MotionBlur, 0, approach ) + + end + + if LocalPlayer():FlashlightIsOn() then + + ColorModify[ "$pp_colour_brightness" ] = math.Approach( ColorModify[ "$pp_colour_brightness" ], 0.01, FrameTime() * 0.25 ) + ColorModify[ "$pp_colour_contrast" ] = math.Approach( ColorModify[ "$pp_colour_contrast" ], 1.02, FrameTime() * 0.25 ) + + end + + local rads = LocalPlayer():GetNWInt( "Radiation", 0 ) + + if rads > 0 and LocalPlayer():Alive() then + + local scale = rads / 5 + + MotionBlur = math.Approach( MotionBlur, scale * 0.5, FrameTime() ) + Sharpen = math.Approach( Sharpen, scale * 5, FrameTime() * 3 ) + + ColorModify[ "$pp_colour_colour" ] = math.Approach( ColorModify[ "$pp_colour_colour" ], 1.0 - scale * 0.8, FrameTime() * 0.1 ) + + end + + if GetGlobalBool( "Radiation", false ) and not GAMEMODE.PlayerIsIndoors then + + ColorModify[ "$pp_colour_mulg" ] = 0.15 + ColorModify[ "$pp_colour_mulr" ] = 0.10 + ColorModify[ "$pp_colour_addg" ] = 0.05 + ColorModify[ "$pp_colour_addr" ] = 0.03 + + end + + if LocalPlayer():Team() == TEAM_ZOMBIES then + + if LocalPlayer():Alive() then + + ColorModify[ "$pp_colour_brightness" ] = -0.15 + ColorModify[ "$pp_colour_addr" ] = 0.25 + ColorModify[ "$pp_colour_mulr" ] = 0.15 + ColorModify[ "$pp_colour_addg" ] = 0.15 + + else + + ColorModify[ "$pp_colour_addr" ] = 0.25 + ColorModify[ "$pp_colour_mulr" ] = 0.30 + ColorModify[ "$pp_colour_addg" ] = 0.05 + ColorModify[ "$pp_colour_brightness" ] = -0.20 + + MotionBlur = 0.40 + + end + + else + + if not LocalPlayer():Alive() then + + ColorModify[ "$pp_colour_addr" ] = 0.25 + ColorModify[ "$pp_colour_mulr" ] = 0.30 + ColorModify[ "$pp_colour_brightness" ] = -0.20 + + MotionBlur = 0.40 + + elseif LocalPlayer():GetNWBool( "Infected", false ) then + + ColorModify[ "$pp_colour_brightness" ] = -0.02 + ColorModify[ "$pp_colour_mulg" ] = 0.55 + ColorModify[ "$pp_colour_addg" ] = 0.02 // too much? too little? + + //MotionBlur = 0.30 + + end + + end + + for k,v in pairs( ColorModify ) do + + if k == "$pp_colour_colour" or k == "$pp_colour_contrast" then + + ColorModify[k] = math.Approach( ColorModify[k], 1, approach ) + + elseif k == "$pp_colour_brightness" and GetGlobalBool( "GameOver", false ) then + + ColorModify[k] = -1.50 + + else + + ColorModify[k] = math.Approach( ColorModify[k], 0, approach ) + + end + + MixedColorMod[k] = math.Approach( MixedColorMod[k] or 0, ColorModify[k], FrameTime() * 0.10 ) + + end + + DrawColorModify( MixedColorMod ) + DrawPlayerRenderEffects() + DrawLaser() + +end + +function GM:GetMotionBlurValues( y, x, fwd, spin ) + + if LocalPlayer():Team() == TEAM_ZOMBIES then return y, x, fwd, spin end + + if LocalPlayer():Alive() and LocalPlayer():Health() <= 50 then + + local scale = math.Clamp( LocalPlayer():Health() / 50, 0, 1 ) + // local beat = math.Clamp( HeartBeat - CurTime(), 0, 2 ) * ( 1 - scale ) + + fwd = 1 - scale // + beat + + elseif LocalPlayer():GetNWBool( "InIron", false ) then + + fwd = 0.05 + + end + + if DisorientTime and DisorientTime > CurTime() then + + if not LocalPlayer():Alive() then + DisorientTime = nil + end + + local scale = ( ( DisorientTime or 0 ) - CurTime() ) / 10 + local newx, newy = RotateAroundCoord( 0, 0, 1, scale * 0.05 ) + + return newy, newx, fwd, spin + + end + + if ScreamTime and ScreamTime > CurTime() then + + if not LocalPlayer():Alive() then + ScreamTime = nil + end + + local scale = ( ( ScreamTime or 0 ) - CurTime() ) / 10 + local newy = math.sin( CurTime() * 1.5 ) * scale * 0.08 + + return newy, x, fwd, spin + + end + + return y, x, fwd, spin + +end + +function RotateAroundCoord( x, y, speed, dist ) + + local newx = x + math.sin( CurTime() * speed ) * dist + local newy = y + math.cos( CurTime() * speed ) * dist + + return newx, newy + +end + +local MaterialVision = Material( "nuke/redead/allyvision" ) +//local MaterialItem = Material( "toxsin/allyvision" ) + +function DrawPlayerRenderEffects() + + if LocalPlayer():Team() != TEAM_ZOMBIES and LocalPlayer():Team() != TEAM_ARMY then return end + + if GetGlobalBool( "GameOver", false ) then return end + + cam.Start3D( EyePos(), EyeAngles() ) + + --[[if IsValid( TargetedEntity ) and table.HasValue( ValidTargetEnts, TargetedEntity:GetClass() ) then // halos replaced this + + if TargetedEntity:GetPos():Distance( LocalPlayer():GetPos() ) < 500 then + + local scale = 1 - ( TargetedEntity:GetPos():Distance( LocalPlayer():GetPos() ) / 500 ) + + render.SuppressEngineLighting( true ) + render.SetBlend( scale * 0.4 ) + render.SetColorModulation( 0, 0.5, 0 ) + + render.MaterialOverride( MaterialItem ) + + cam.IgnoreZ( false ) + + TargetedEntity:DrawModel() + + render.SuppressEngineLighting( false ) + render.SetColorModulation( 1, 1, 1 ) + render.SetBlend( 1 ) + + render.MaterialOverride( 0 ) + + end + + end]] + + for k,v in pairs( GAMEMODE:GetHighlightedUnits() ) do + + if ( v:IsPlayer() and v:Alive() and v != LocalPlayer() ) or v:IsNPC() then + + local scale = ( math.Clamp( v:GetPos():Distance( LocalPlayer():GetPos() ), 500, 3000 ) - 500 ) / 2500 + + //render.SuppressEngineLighting( true ) + render.SetBlend( scale ) + + render.MaterialOverride( MaterialVision ) + + if LocalPlayer():Team() == TEAM_ARMY then + + render.SetColorModulation( 0, 0.2, 1.0 ) + + else + + render.SetColorModulation( 1.0, 0.2, 0 ) + + end + + cam.IgnoreZ( false ) + + v:SetupBones() + v:DrawModel() + + //render.SuppressEngineLighting( false ) + render.SetColorModulation( 1, 1, 1 ) + render.SetBlend( 1 ) + + render.MaterialOverride( 0 ) + + end + + end + + cam.End3D() + +end + +DotMat = Material( "sprites/light_glow02_add_noz" ) +LasMat = Material( "sprites/bluelaser1" ) + +function DrawLaser() + + if LocalPlayer():Team() != TEAM_ARMY then return end + + //local vm = LocalPlayer():GetViewModel( 0 ) + + //if not IsValid( vm ) then return end + + local wep = LocalPlayer():GetActiveWeapon() + + if not IsValid( wep ) or not wep:GetNWBool( "Laser", false ) then return end + + //local idx = vm:LookupAttachment( "1" ) + + //if idx == 0 then idx = vm:LookupAttachment( "muzzle" ) end + + --[[local trace = util.GetPlayerTrace( LocalPlayer() ) + local tr = util.TraceLine( trace ) + local tbl = vm:GetAttachment( idx ) + + local pos = tr.HitPos]] + + local look = LocalPlayer():EyeAngles() + local dir = look:Forward() + //local tbl = vm:GetAttachment( idx ) + //local ang = tbl.Ang + //local offset = wep.LaserOffset + + //ang:RotateAroundAxis( look:Up(), ( offset.p or 0 ) ) + //ang:RotateAroundAxis( look:Forward(), ( offset.r or 0 ) ) + //ang:RotateAroundAxis( look:Right(), ( offset.y or 0 ) ) + + //local forward = ang:Forward() + //lasforward = tbl.Ang:Forward() + + //forward = forward * wep.LaserScale + + //dir = dir + forward + + local trace = {} + + trace.start = LocalPlayer():GetShootPos() + trace.endpos = trace.start + dir * 9000 + trace.filter = { LocalPlayer(), weap, lp } + trace.mask = MASK_SOLID + + local tr = util.TraceLine( trace ) + local dist = math.Clamp( tr.HitPos:Distance( EyePos() ), 0, 500 ) + local size = math.Rand( 2, 4 ) + ( dist / 500 ) * 6 + local col = Color( 255, 0, 0, 255 ) + + --[[if v == lp and IsValid( GAMEMODE.TargetEnt ) and GAMEMODE.TargetEnt:IsPlayer() and GAMEMODE.TargetEnt:Team() == TEAM_HUMAN then + + size = size + math.Rand( 0.5, 2.0 ) + + elseif v != lp then + + size = math.Rand( 0, 1 ) + ( dist / 500 ) * 6 + + end]] + + if ( wep.LastRunFrame or 0 ) > CurTime() then return end + + cam.Start3D( EyePos(), EyeAngles() ) + + local norm = ( EyePos() - tr.HitPos ):GetNormal() + + render.SetMaterial( DotMat ) + render.DrawQuadEasy( tr.HitPos + norm * size, norm, size, size, col, 0 ) + + cam.End3D() + + --[[if vm:GetSequence() != ACT_VM_IDLE then + + wep.AngDiff = ( tbl.Ang - ( wep.LastGoodAng or Angle(0,0,0) ) )//:Forward() + + trace = {} + trace.start = EyePos() or Vector(0,0,0) + trace.endpos = trace.start + ( ( EyeAngles() + wep.AngDiff ):Forward() * 99999 ) + trace.filter = { wep, LocalPlayer() } + + local tr2 = util.TraceLine( trace ) + + pos = tr2.HitPos + + else + + wep.LastGoodAng = tbl.Ang + + end]] + + --[[cam.Start3D( EyePos(), EyeAngles() ) + + local dir = ( tbl.Ang + Angle(0,90,0) ):Forward() + dir.z = EyeAngles():Forward().z + + local start = tbl.Pos + ( dir * -5 ) + wep.LaserOffset + + render.SetMaterial( LasMat ) + + for i=0,254 do + + render.DrawBeam( start, start + dir * 0.2, 2, 0, 12, Color( 255, 0, 0, 255 - i ) ) + + start = start + dir * 0.2 + + end + + local dist = tr.HitPos:Distance( EyePos() ) + local size = math.Rand( 7, 8 ) + local dotsize = dist / ( size ^ 2 ) + + render.SetMaterial( DotMat ) + render.DrawQuadEasy( pos, ( EyePos() - tr.HitPos ):GetNormal(), dotsize, dotsize, Color( 255, 0, 0, 255 ), 0 ) + + cam.End3D() ]] + +end + +function GM:GetHighlightedUnits() + + local tbl = team.GetPlayers( TEAM_ARMY ) + tbl = table.Add( tbl, ents.FindByClass( "npc_scientist" ) ) + + return tbl + +end + +function GM:PreDrawHalos() + + if GetGlobalBool( "GameOver", false ) then return end + + if LocalPlayer():Team() != TEAM_ZOMBIES and LocalPlayer():Team() != TEAM_ARMY then return end + + --[[for k,v in pairs( GAMEMODE:GetHighlightedUnits() ) do + + if ( ( v:IsPlayer() and v:Alive() and v != LocalPlayer() ) or ( v:IsNPC() and not v.Ragdolled ) ) then + + local dist = math.Clamp( v:GetPos():Distance( LocalPlayer():GetPos() ), 250, 500 ) - 250 + local scale = dist / 250 + + if scale > 0 then + + if LocalPlayer():Team() == TEAM_ARMY then + + //halo.Add( {v}, Color( 0, 200, 200, 200 * scale ), 2, 2, 1, 1, true ) // removed till garry optimizes this + + else + + //halo.Add( {v}, Color( 200, 0, 0, 200 * scale ), 2, 2, 1, 1, false ) + + end + + end + + end + + end]] + + if LocalPlayer():Team() == TEAM_ARMY then + + if IsValid( TargetedEntity ) and not TargetedEntity:IsPlayer() and ( TargetedEntity:GetClass() != "npc_scientist" or TargetedEntity:GetNWBool( "Dead", false ) == false ) then + + local dist = math.Clamp( TargetedEntity:GetPos():Distance( LocalPlayer():GetPos() ), 0, 500 ) + local scale = 1 - ( dist / 500 ) + + halo.Add( {TargetedEntity}, Color( 0, 100, 200, 255 * scale ), 2 * scale, 2 * scale, 1, 1, false ) + + end + + if IsValid( GAMEMODE.ClientAntidote ) then + + local dist = math.Clamp( GAMEMODE.ClientAntidote:GetPos():Distance( LocalPlayer():GetPos() ), 250, 500 ) - 250 + local scale = dist / 250 + + halo.Add( {GAMEMODE.ClientAntidote}, Color( 0, 200, 0, 200 * scale ), 2, 2, 1, 1, true ) + + end + + end + +end + +WalkTimer = 0 +VelSmooth = 0 +DeathAngle = Angle(0,0,0) +DeathOrigin = Vector(0,0,0) + +function GM:CalcView( ply, origin, angle, fov ) + + local vel = ply:GetVelocity() + local ang = ply:EyeAngles() + + VelSmooth = VelSmooth * 0.5 + vel:Length() * 0.1 + WalkTimer = WalkTimer + VelSmooth * FrameTime() * 0.1 + + angle.roll = angle.roll + ang:Right():DotProduct( vel ) * 0.002 + + if ply:Alive() then + + --[[if ViewWobble > 0 then + + angle.roll = angle.roll + math.sin( CurTime() + TimeSeed( 1, -2, 2 ) ) * ( ViewWobble * 15 ) + angle.pitch = angle.pitch + math.sin( CurTime() + TimeSeed( 2, -2, 2 ) ) * ( ViewWobble * 15 ) + angle.yaw = angle.yaw + math.sin( CurTime() + TimeSeed( 3, -2, 2 ) ) * ( ViewWobble * 15 ) + + end]] + + DeathAngle = angle + DeathOrigin = origin + + elseif not ply:Alive() and CV_RagdollVision:GetBool() then + + local rag = ply:GetRagdollEntity() + + if IsValid( rag ) then + + local eyes = rag:LookupAttachment( "eyes" ) + local tbl = rag:GetAttachment( eyes ) + + if tbl then + + angle = tbl.Ang + origin = tbl.Pos + ( tbl.Ang:Up() * 16 ) + ( tbl.Ang:Forward() * -8 ) + + end + + end + + end + + if ply:GetGroundEntity() != NULL then + + angle.roll = angle.roll + math.sin( WalkTimer ) * VelSmooth * 0.001 + angle.pitch = angle.pitch + math.cos( WalkTimer * 1.25 ) * VelSmooth * 0.005 + + end + + return self.BaseClass:CalcView( ply, origin, angle, fov ) + +end diff --git a/gamemode/cl_scoreboard.lua b/gamemode/cl_scoreboard.lua new file mode 100644 index 0000000..08c2ee7 --- /dev/null +++ b/gamemode/cl_scoreboard.lua @@ -0,0 +1,398 @@ + +function GM:CustomizeScoreboard() + + // these fonts are used in the header on the top of the scoreboard + surface.CreateFont ( "MenuTitle", { size = 30, weight = 500, antialias = true, additive = false, font = "Graffiare" } ) + surface.CreateFont ( "MenuDesc", { size = 16, weight = 800, antialias = true, additive = false, font = "Verdana" } ) + + // scoreboard fonts + surface.CreateFont ( "ScoreboardLabel", { size = 14, weight = 1000, antialias = true, additive = false, font = "Tahoma" } ) + surface.CreateFont ( "ScoreboardTeamName", { size = 14, weight = 1000, antialias = true, additive = false, font = "Verdana" } ) + surface.CreateFont ( "ScoreboardPlayerText", { size = 14, weight = 600, antialias = true, additive = false, font = "Arial" } ) + + // colors used on the scoreboard + GAMEMODE.TitleColor = Color( 255, 255, 255, 255 ) // title text color + GAMEMODE.TitleShadow = Color( 0, 0, 0, 100 ) // title shadow color + + GAMEMODE.DescColor = Color( 255, 255, 255, 255 ) // subtext color + GAMEMODE.DescShadow = Color( 50, 50, 50, 100 ) // subtext shadow color + + GAMEMODE.TeamTextColor = Color( 0, 0, 0, 255 ) // text color for team bar + GAMEMODE.TeamShadowColor = Color( 255, 255, 255, 0 ) // text shadow color for team bar + + GAMEMODE.TitleBackground = Color( 100, 100, 100, 150 ) // background color for the title and subtext + GAMEMODE.ScreenBackground = Color( 50, 50, 50, 50 ) //background color for the rest of the screen + + GAMEMODE.ScoreBackground = Color( 200, 200, 200, 100 ) // background for team score panel + GAMEMODE.PlayerBackground = Color( 60, 60, 60, 100 ) // background for player score panel + +end + +function GM:ScoreboardShow() + + if not GAMEMODE.ScoreBoard or GAMEMODE.ScoreBoard == NULL then + + GAMEMODE:CustomizeScoreboard() + GAMEMODE.ScoreBoard = vgui.Create( "ScoreBoard" ) + + end + + GAMEMODE.ScoreBoard:SetVisible( true ) + GAMEMODE.ScoreboardVisible = true + + gui.EnableScreenClicker( true ) + +end + +function GM:ScoreboardHide() + + if not GAMEMODE.ScoreBoard or GAMEMODE.ScoreBoard == NULL then return end + + GAMEMODE.ScoreBoard:SetVisible( false ) + GAMEMODE.ScoreboardVisible = false + + gui.EnableScreenClicker( false ) + +end + +function GM:GetPlayerStats( ply ) + + if not ply then + + return { "Kills", GAMEMODE.CurrencyName .. "s" } + + else + + return { ply:Frags(), ply:GetNWInt( "Cash", 10 ) } + + end + +end + +function GM:GetDefaultPlayerStats(ply) + + return ply:Nick(), ply:Ping() + +end + +local MENUBASE = {} + +function MENUBASE:Init() + + self.TitleText = "" + self.DescText = "" + + self:SetPos( 0, 0 ) + self:SetSize( ScrW(), ScrH() ) + + self:SetTitle("") + self:ShowCloseButton(false) + +end + +function MENUBASE:SetTitleText( text ) + self.TitleText = text +end + +function MENUBASE:SetDescText( text ) + self.DescText = text +end + +function MENUBASE:Paint() + + Derma_DrawBackgroundBlur( self ) + + surface.SetDrawColor( GAMEMODE.ScreenBackground.r, GAMEMODE.ScreenBackground.g, GAMEMODE.ScreenBackground.b, GAMEMODE.ScreenBackground.a ) + surface.DrawRect( 0, 80, ScrW(), ScrH() - 80 ) + + surface.SetDrawColor( GAMEMODE.TitleBackground.r, GAMEMODE.TitleBackground.g, GAMEMODE.TitleBackground.b, GAMEMODE.TitleBackground.a ) + surface.DrawRect( 0, 0, ScrW(), 80 ) + + if self.TitleText == "" then + self.TitleText = GetGlobalString( "ServerName" ) + end + + draw.SimpleText( self.TitleText, "MenuTitle", 22, 22, GAMEMODE.TitleShadow, TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + draw.SimpleText( self.TitleText, "MenuTitle", 20, 20, GAMEMODE.TitleColor, TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + + draw.SimpleText( self.DescText, "MenuDesc", 22, 57, GAMEMODE.DescShadow, TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + draw.SimpleText( self.DescText, "MenuDesc", 20, 55, GAMEMODE.DescColor, TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + +end + +vgui.Register( "MenuBase", MENUBASE, "DFrame" ) + +local PANEL = {} + +function PANEL:Init() + + self.BaseClass.SetTitleText( self, GetGlobalString( "ServerName" ) ) + self.BaseClass.SetDescText( self, GAMEMODE.Name .. " - ".. game.GetMap() ) + + self.PanelList = vgui.Create( "DPanelList", self ) + self.PanelList:SetSize( ScrW() - 40, ScrH() - 130 ) + self.PanelList:SetPos( 20, 105 ) + self.PanelList:SetSpacing( 0 ) + self.PanelList:EnableVerticalScrollbar( true ) + self.PanelList:EnableHorizontal( false ) + self.PanelList.Paint = function() end + + self.Canvas = vgui.Create( "Panel" ) + self.Canvas.OnMousePressed = function( self, code ) self:GetParent():OnMousePressed( code ) end + self.Canvas:SetMouseInputEnabled( true ) + self.Canvas.InvalidateLayout = function() self:InvalidateLayout() end + self.Canvas:SetSize( ScrW() - 40, 200 ) + self.Canvas:SetPos( 0, 0 ) + self.Canvas.Paint = function() end + + self.PanelList:AddItem(self.Canvas) + + self.Teams = {} + + local teams = team.GetAllTeams() + + for k,v in pairs( teams ) do + + if k > 0 and k < 1002 then + + table.insert( self.Teams, k ) + + end + + end + +end + +function PANEL:Paint() + + self.BaseClass.Paint(self) + + self.CanvasSize = 0 + + if not self.TeamPanels then + + self.TeamPanels = {} + local ypos = 0 + + for k,v in pairs( self.Teams ) do + + self.TeamPanels[k] = vgui.Create( "TeamScore", self.Canvas ) + self.TeamPanels[k]:SetPos( 0, ypos ) + self.TeamPanels[k]:SetSize( ScrW() - 56, self.TeamPanels[k]:GetVerticalSize() ) + self.TeamPanels[k]:SetTeam( v ) + ypos = ypos + self.TeamPanels[k]:GetVerticalSize() + self.CanvasSize = self.CanvasSize + self.TeamPanels[k]:GetVerticalSize() + + end + + else + + local ypos = 0 + + for k,v in pairs( self.TeamPanels ) do + + v:SetPos( 0, ypos ) + v:SetSize( ScrW() - 56, v:GetVerticalSize() ) + ypos = ypos + v:GetVerticalSize() + self.CanvasSize = self.CanvasSize + v:GetVerticalSize() + + end + + end + + self.Canvas:SetSize( ScrW() - 40, self.CanvasSize ) + self.PanelList:InvalidateLayout( true ) + +end + +vgui.Register( "ScoreBoard", PANEL, "MenuBase" ) + +local TFRAME = {} + +function TFRAME:Init( ) + + self:SetPaintBackgroundEnabled( true ) + self:SetPaintBackgroundEnabled( false ) + self:SetPaintBorderEnabled( false ) + self.CleanUp = 0 + self.Size = 40 + +end + +function TFRAME:SetTeam( teamid ) + + self.TeamID = teamid + self.Players = {} + self.Rows = {} + +end + +function TFRAME:Paint( ) + + if not self.TeamID then return end + + local col = team.GetColor( self.TeamID ) + surface.SetDrawColor( col.r, col.g, col.b, 255 ) + surface.DrawRect( 0, 0, self:GetWide(), 25 ) + + surface.SetDrawColor( 0, 0, 0, 255 ) + surface.DrawOutlinedRect( 0, 0, self:GetWide(), 25 ) + + surface.SetDrawColor( GAMEMODE.ScoreBackground.r, GAMEMODE.ScoreBackground.g, GAMEMODE.ScoreBackground.b, GAMEMODE.ScoreBackground.a ) + surface.DrawRect( 0, 25, self:GetWide(), self:GetTall() - 25 ) + + local text = " Member )" + + if team.NumPlayers( self.TeamID ) > 1 or team.NumPlayers( self.TeamID ) == 0 then + + text = " Members )" + + end + + local teamcol = GAMEMODE.TeamTextColor + local teamshad = GAMEMODE.TeamShadowColor + + draw.SimpleText( team.GetName( self.TeamID ).." ( "..team.NumPlayers( self.TeamID )..text, "ScoreboardTeamName", 10, 3, Color( teamshad.r, teamshad.g, teamshad.b, teamshad.a ), TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + draw.SimpleText( team.GetName( self.TeamID ).." ( "..team.NumPlayers( self.TeamID )..text, "ScoreboardTeamName", 9, 3, Color( teamcol.r, teamcol.g, teamcol.b, teamcol.a ), TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + + local tbl = GAMEMODE:GetPlayerStats() + local pos = 10 + + draw.SimpleText( "Ping", "ScoreboardLabel", self:GetWide() - pos, 3, Color( teamshad.r, teamshad.g, teamshad.b, teamshad.a ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_LEFT ) + draw.SimpleText( "Ping", "ScoreboardLabel", self:GetWide() - pos - 1, 3, Color( teamcol.r, teamcol.g, teamcol.b, teamcol.a ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_LEFT ) + + for k,v in pairs( tbl ) do + + pos = pos + 70 + draw.SimpleText( v, "ScoreboardLabel", self:GetWide() - pos, 3, Color( teamshad.r, teamshad.g, teamshad.b, teamshad.a ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_LEFT ) + draw.SimpleText( v, "ScoreboardLabel", self:GetWide() - pos - 1, 3, Color( teamcol.r, teamcol.g, teamcol.b, teamcol.a ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_LEFT ) + + end + + local size = 40 + self.Players = team.GetPlayers( self.TeamID ) + + for k, v in pairs( self.Players ) do + + local inserted + + for c, d in pairs( self.Rows ) do + + if d.Ply == v then + + inserted = true + + end + + end + + if not inserted then + + local row = vgui.Create( "PlayerRow", self ) + row:SetPlayer( v ) + row:SetSize( self:GetWide() - 15, 30 ) + row.Ply = v + + table.insert( self.Rows, row ) + + end + + end + + for k, v in pairs( self.Rows ) do + + v:SetPos( 5, ( k * 37 ) ) + size = size + 37 + + end + + if self.CleanUp < CurTime() then + + for k, v in pairs( self.Rows ) do + + if not v.Ply or not v.Ply:IsValid() or v.Ply:Team() != self.TeamID then + + local row = v + table.remove( self.Rows, k ) + row:Remove() + size = size - 37 + + end + + end + + self.CleanUp = CurTime() + 0.3 + + end + + self.Size = size + +end + +function TFRAME:GetVerticalSize() + + return self.Size + +end + +vgui.Register( "TeamScore", TFRAME, "DPanel" ) + +local PFRAME = {} + +function PFRAME:Init() + + self.Avatar = vgui.Create( "AvatarImage", self ) + self.Avatar:SetPos( 5, 0 ) + self.Avatar:SetSize( 32, 32 ) + self.Invalid = 0 + +end + +function PFRAME:SetPlayer( ply ) + + if not ply or not ply:IsValid() then + + return false + + end + + self.Player = ply + self.Avatar:SetPlayer( ply ) + +end + +function PFRAME:Paint( ) + + if not self.Player or not self.Player:IsValid() then + + return + + end + + local ply = self.Player + + local name, ping = GAMEMODE:GetDefaultPlayerStats(ply) + local stats = GAMEMODE:GetPlayerStats(ply) + local tbl = GAMEMODE:GetPlayerStats() + + local pos = 0 + + surface.SetDrawColor( GAMEMODE.PlayerBackground.r,GAMEMODE.PlayerBackground.g, GAMEMODE.PlayerBackground.b, GAMEMODE.PlayerBackground.a ) + surface.DrawRect( 5, 0, self:GetWide(), self:GetTall() ) + + draw.SimpleText( name, "ScoreboardPlayerText", 45, 8, Color( 0, 0, 0, 255 ), TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + draw.SimpleText( name, "ScoreboardPlayerText", 44, 8, Color( 255, 255, 255, 255 ), TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + draw.SimpleText( tostring( ping ), "ScoreboardPlayerText", self:GetWide(), 8, Color( 0, 0, 0, 255 ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_LEFT ) + draw.SimpleText( tostring( ping ), "ScoreboardPlayerText", self:GetWide() - 1, 8, Color( 255, 255, 255, 255 ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_LEFT ) + + for k,v in pairs( stats ) do + + pos = pos + 70 + draw.SimpleText( tostring( v ), "ScoreboardPlayerText", self:GetWide() - pos, 8, Color( 0, 0, 0, 255 ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_LEFT ) + draw.SimpleText( tostring( v ), "ScoreboardPlayerText", self:GetWide() - pos - 1, 8, Color( 255, 255, 255, 255 ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_LEFT ) + + end + +end + +vgui.Register( "PlayerRow", PFRAME, "DPanel" ) diff --git a/gamemode/cl_spawnmenu.lua b/gamemode/cl_spawnmenu.lua new file mode 100644 index 0000000..1515e53 --- /dev/null +++ b/gamemode/cl_spawnmenu.lua @@ -0,0 +1,545 @@ + +GM.Elements = {} +GM.Cart = {} +GM.CartItems = {} +GM.OptionPanels = {} + +GM.Categories = { +{ Name = "Weapons", Icon = "icon16/gun.png", Categories = { ITEM_WPN_COMMON, ITEM_WPN_SPECIAL } }, +{ Name = "Ammunition", Icon = "icon16/package.png", Categories = { ITEM_AMMO } }, +{ Name = "Supplies", Icon = "icon16/pill.png", Categories = { ITEM_SUPPLY, ITEM_SPECIAL } }, +{ Name = "Miscellaneous", Icon = "icon16/bin.png", Categories = { ITEM_MISC, ITEM_BUYABLE } } +} + +function GM:CreateElement( name ) + + local element = vgui.Create( name ) + + table.insert( GAMEMODE.Elements, element ) + + return element + +end + +function GM:ClearElements() + + for k,v in pairs( GAMEMODE.Elements ) do + + v:Remove() + + end + + GAMEMODE.Elements = {} + +end + +function GM:AddToCart( tbl, amt ) + + for i=1,amt do + + table.insert( GAMEMODE.Cart, tbl.ID ) + + local btn = GAMEMODE:CreateElement( "SideButton" ) + btn:SetPos( 765, 5 + 35 * ( table.Count( GAMEMODE.Cart ) - 1 ) ) + btn:SetSize( 250, 30 ) + btn:SetImage( "icon16/cross.png" ) + btn:SetText( tbl.Name ) + btn:SetFunction( function() RunConsoleCommand( "inv_refund", tbl.ID ) btn:Remove() GAMEMODE:ClearCartItem( tbl.ID ) end ) + + table.insert( GAMEMODE.CartItems, btn ) + + end + + GAMEMODE:CheckCartButton() + +end + +function GM:RefreshCart() + + local cart = GAMEMODE.CartItems + + GAMEMODE.CartItems = {} + + for k,v in pairs( cart ) do + + if IsValid( v ) then + + table.insert( GAMEMODE.CartItems, v ) + + v:SetPos( 765, 5 + 35 * ( table.Count( GAMEMODE.CartItems ) - 1 ) ) + + end + + end + +end + +function GM:CheckCartButton() + + if GAMEMODE.CartButton then + + GAMEMODE.CartButton:Remove() + + end + + if table.Count( GAMEMODE.Cart ) < 1 then return end + + local btn = GAMEMODE:CreateElement( "SideButton" ) + btn:SetPos( 765, 5 + 35 * ( table.Count( GAMEMODE.Cart ) ) ) + btn:SetSize( 250, 30 ) + btn:SetImage( "icon16/cart.png" ) + btn:SetText( "Airdrop Items" ) + btn:SetFunction( function() RunConsoleCommand( "ordershipment" ) GAMEMODE:ClearCart() btn:Remove() end ) + + GAMEMODE.CartButton = btn + +end + +function GM:ClearCartItem( id ) + + for k,v in pairs( GAMEMODE.Cart ) do + + if v == id then + + table.remove( GAMEMODE.Cart, k ) + + GAMEMODE:RefreshCart() + GAMEMODE:CheckCartButton() + + return + + end + + end + +end + +function GM:ClearCart() + + GAMEMODE.Cart = {} + + for k,v in pairs( GAMEMODE.CartItems ) do + + if IsValid( v ) then + + v:Remove() + + end + + end + +end + +function GM:ElementsVisible() + + if GAMEMODE.Elements[1] then return true end + + return false + +end + +function GM:SetItemToPreview( id, style, scale, count ) + + //print( debug.traceback() ) + + PreviewTable = item.GetByID( id ) //table.Copy( item.GetByID( id ) ) + + if scale and style then + + PreviewStyle = style + PreviewPriceScale = scale + + end + + GAMEMODE:RebuildOptions( PreviewTable or {}, style, count or 1 ) + +end + +function GM:GetItemToPreview() + + return PreviewTable, PreviewStyle, PreviewPriceScale + +end + +function GM:RebuildOptions( tbl, style, count ) + + for k,v in pairs( GAMEMODE.OptionPanels ) do + + v:Remove() + + end + + local ypos = 400 + + if style == "Buy" then + + for k,v in pairs{ 1, 3, 5, 10 } do + + if v == 1 or not tbl.Weapon then + + local btn = GAMEMODE:CreateElement( "SideButton" ) + btn:SetPos( 510, ypos ) + btn:SetSize( 250, 30 ) + btn:SetImage( "icon16/money.png" ) + + if v == 1 then + btn:SetText( "Buy" ) + else + btn:SetText( "Buy " .. v ) + end + + btn:SetFunction( function() if LocalPlayer():GetNWInt( "Cash", 0 ) >= tbl.Price * v then RunConsoleCommand( "inv_buy", tbl.ID, v ) GAMEMODE:AddToCart( tbl, v ) end end ) + + table.insert( GAMEMODE.OptionPanels, btn ) + + ypos = ypos + 5 + 30 + + end + + end + + else + + for k,v in pairs{ 1, 3, 5, 10 } do + + if not tbl.Weapon and count >= v then + + local btn = GAMEMODE:CreateElement( "SideButton" ) + btn:SetPos( 510, ypos ) + btn:SetSize( 250, 30 ) + btn:SetImage( "icon16/arrow_down.png" ) + + if v == 1 then + btn:SetText( "Drop" ) + else + btn:SetText( "Drop " .. v ) + end + + btn:SetFunction( function() RunConsoleCommand( "inv_drop", tbl.ID, v ) end ) + + table.insert( GAMEMODE.OptionPanels, btn ) + + ypos = ypos + 5 + 30 + + end + + end + + if count > 1 then + + local btn = GAMEMODE:CreateElement( "SideButton" ) + btn:SetPos( 510, ypos ) + btn:SetSize( 250, 30 ) + btn:SetImage( "icon16/box.png" ) + btn:SetText( "Drop All" ) + btn:SetFunction( function() RunConsoleCommand( "inv_drop", tbl.ID, count ) end ) + + table.insert( GAMEMODE.OptionPanels, btn ) + + ypos = ypos + 5 + 30 + + end + + for k,v in pairs( tbl.Functions ) do + + local btn = GAMEMODE:CreateElement( "SideButton" ) + btn:SetPos( 510, ypos ) + btn:SetSize( 250, 30 ) + btn:SetImage( v( 0, 0, 0, true ) ) + btn:SetText( v( 0, 0, true ) ) + btn:SetFunction( function() RunConsoleCommand( "inv_action", tbl.ID, k ) end ) + + table.insert( GAMEMODE.OptionPanels, btn ) + + ypos = ypos + 5 + 30 + + end + + end + +end + +function GM:OnSpawnMenuClose() + + if not LocalPlayer():Alive() or LocalPlayer():Team() != TEAM_ARMY then return end + + if GAMEMODE:ElementsVisible() then + + gui.EnableScreenClicker( false ) + + GAMEMODE:ClearElements() + + else + + gui.EnableScreenClicker( true ) + + local ypos = 5 + + for k,v in pairs( GAMEMODE.Categories ) do + + local toggle = GAMEMODE:CreateElement( "CategoryButton" ) + toggle:SetPos( 510, ypos ) + toggle:SetText( v.Name ) + toggle:SetImage( v.Icon ) + toggle:SetSize( 250, 30 ) + toggle:SetSelectedState( true, true ) + toggle.OnToggle = function( pnl, bool ) + + if GAMEMODE.ItemSheet then + + GAMEMODE.ItemSheet:ToggleVisible( v.Categories, bool ) + GAMEMODE.ItemSheet:RefreshItems( LocalInventory ) + + end + + end + + ypos = ypos + 5 + 30 + + end + + local inv = GAMEMODE:CreateElement( "ItemSheet" ) + inv:SetSize( 500, ScrH() - 125 ) + inv:SetPos( 5, 5 ) + inv:SetSpacing( 0 ) + inv:SetPadding( 0 ) + inv:EnableHorizontal( true ) + inv:SetStashable( false, "Stash", true ) + inv:RefreshItems( LocalInventory ) + //inv:EnableVerticalScrollbar() + + GAMEMODE.ItemSheet = inv + + local disp = GAMEMODE:CreateElement( "ItemDisplay" ) + disp:SetSize( 250, 250 ) + disp:SetPos( 510, 145 ) + + local scrollup = GAMEMODE:CreateElement( "Scroller" ) + scrollup:SetSize( 30, 30 ) + scrollup:SetPos( 475, ScrH() - 115 ) + scrollup:SetTarget( inv ) + scrollup:SetImage( "icon16/arrow_up.png" ) + + local scrolldown = GAMEMODE:CreateElement( "Scroller" ) + scrolldown:SetSize( 30, 30 ) + scrolldown:SetPos( 440, ScrH() - 115 ) + scrolldown:SetTarget( inv ) + scrolldown:SetScrollUp( false ) + scrolldown:SetImage( "icon16/arrow_down.png" ) + + end + + --[[if not InventoryScreen:IsVisible() then + + InventoryScreen:SetSize( ScrW() - 10, ScrH() * 0.5 - 10 ) + InventoryScreen:SetStashable( false, "Stash", true ) + InventoryScreen:RefreshItems( LocalInventory ) + InventoryScreen:SetVisible( true ) + InfoScreen:SetVisible( true ) + PlayerScreen:SetVisible( true ) + + gui.EnableScreenClicker( true ) + + else + + InventoryScreen:SetVisible( false ) + InfoScreen:SetVisible( false ) + PlayerScreen:SetVisible( false ) + + gui.EnableScreenClicker( false ) + + end]] + +end + +function StoreMenu( msg ) + + local open = msg:ReadBool() + local scale = msg:ReadFloat() + + if GAMEMODE:ElementsVisible() then + + GAMEMODE:ClearElements() + + end + + if open then + + gui.EnableScreenClicker( true ) + + local ypos = 5 + + for k,v in pairs( GAMEMODE.Categories ) do + + local toggle = GAMEMODE:CreateElement( "CategoryButton" ) + toggle:SetPos( 510, ypos ) + toggle:SetText( v.Name ) + toggle:SetImage( v.Icon ) + toggle:SetSize( 250, 30 ) + toggle:SetSelectedState( true, true ) + toggle.OnToggle = function( pnl, bool ) + + if GAMEMODE.ItemSheet then + + GAMEMODE.ItemSheet:ToggleVisible( v.Categories, bool ) + GAMEMODE.ItemSheet:RefreshItems( LocalStash ) + + end + + end + + ypos = ypos + 5 + 30 + + end + + local inv = GAMEMODE:CreateElement( "ItemSheet" ) + inv:SetSize( 500, ScrH() - 125 ) + inv:SetPos( 5, 5 ) + inv:SetSpacing( 0 ) + inv:SetPadding( 0 ) + inv:EnableHorizontal( true ) + inv:SetStashable( open, "Buy" ) + inv:RefreshItems( LocalStash ) + //inv:EnableVerticalScrollbar() + + GAMEMODE.ItemSheet = inv + + local disp = GAMEMODE:CreateElement( "ItemDisplay" ) + disp:SetSize( 250, 250 ) + disp:SetPos( 510, 145 ) + + local scrollup = GAMEMODE:CreateElement( "Scroller" ) + scrollup:SetSize( 30, 30 ) + scrollup:SetPos( 475, ScrH() - 115 ) + scrollup:SetTarget( inv ) + scrollup:SetImage( "icon16/arrow_up.png" ) + + local scrolldown = GAMEMODE:CreateElement( "Scroller" ) + scrolldown:SetSize( 30, 30 ) + scrolldown:SetPos( 440, ScrH() - 115 ) + scrolldown:SetTarget( inv ) + scrolldown:SetScrollUp( false ) + scrolldown:SetImage( "icon16/arrow_down.png" ) + + surface.PlaySound( table.Random( GAMEMODE.RadioBeep ) ) + + local cart = GAMEMODE.Cart + GAMEMODE.Cart = {} + + for k,v in pairs( cart ) do + + local tbl = item.GetByID( v ) + + GAMEMODE:AddToCart( tbl, 1 ) + + end + + else + + gui.EnableScreenClicker( false ) + + end + + --[[ShopMenu = open + + StashScreen:SetPos( 5, ScrH() * 0.5 + 5 ) + StashScreen:SetStashable( open, "Buy" ) + StashScreen:SetVisible( open ) + + SaleScreen:SetVisible( open ) + InfoScreen:SetVisible( open ) + PlayerScreen:SetVisible( open ) + + gui.EnableScreenClicker( open ) + + if open then + + StashScreen:RefreshItems( LocalStash ) + + surface.PlaySound( table.Random( GAMEMODE.RadioBeep ) ) + + end]] + +end +usermessage.Hook( "StoreMenu", StoreMenu ) + +function GM:InitVGUI() //obsolete + + InventoryScreen = vgui.Create( "ItemSheet" ) + InventoryScreen:SetSize( ScrW() * 0.5 - 10, ScrH() * 0.5 - 10 ) + InventoryScreen:SetPos( 5, ScrH() * 0.5 + 5 ) + InventoryScreen:SetSpacing( 2 ) + InventoryScreen:SetPadding( 3 ) + InventoryScreen:EnableHorizontal( true ) + InventoryScreen:SetVisible( false ) + + InfoScreen = vgui.Create( "ItemDisplay" ) + InfoScreen:SetSize( ScrW() * 0.3 - 10, ScrH() * 0.5 - 5 ) + InfoScreen:SetPos( 5, 5 ) + InfoScreen:SetVisible( false ) + + PlayerScreen = vgui.Create( "PlayerDisplay" ) + PlayerScreen:SetSize( ScrW() * 0.3 - 10, ScrH() * 0.5 - 5 ) + PlayerScreen:SetPos( ScrW() * 0.7 + 5, 5 ) + PlayerScreen:SetVisible( false ) + PlayerScreen:SetupCam( Vector(0,96,36), Vector(0,0,36) ) + + StashScreen = vgui.Create( "ItemSheet" ) + StashScreen:SetSize( ScrW() * 0.5 - 10, ScrH() * 0.5 - 10 ) + StashScreen:SetPos( ScrW() * 0.5 + 5, ScrH() * 0.5 + 5 ) + StashScreen:SetSpacing( 2 ) + StashScreen:SetPadding( 3 ) + StashScreen:EnableHorizontal( true ) + StashScreen:SetVisible( false ) + StashScreen:SetStashable( true, "Take" ) + StashScreen.GetCash = function() return Inv_GetStashCash() end + + SaleScreen = vgui.Create( "ShopMenu" ) + SaleScreen:SetSize( ScrW() * 0.5 - 10, ScrH() * 0.5 - 10 ) + SaleScreen:SetPos( ScrW() * 0.5 + 5, ScrH() * 0.5 + 5 ) + SaleScreen:SetVisible( false ) + + local ypos = 5 + + for k,v in pairs( GAMEMODE.Categories ) do + + local toggle = vgui.Create( "CategoryButton" ) + toggle:SetPos( 5, ypos ) + toggle:SetText( v.Name ) + toggle:SetImage( v.Icon ) + toggle:SetSize( 500, 30 ) + + ypos = ypos + 5 + 30 + + end + +end + +function StashMenu( msg ) + + local open = msg:ReadBool() + + if InventoryScreen:IsVisible() and open then return end + + StashScreen:SetPos( ScrW() * 0.5 + 5, ScrH() * 0.5 + 5 ) + StashScreen:SetStashable( open, "Take" ) + StashScreen:SetVisible( open ) + + InventoryScreen:SetSize( ScrW() * 0.5 - 10, ScrH() * 0.5 - 10 ) + InventoryScreen:SetStashable( open, "Stash", true ) + InventoryScreen:RefreshItems( LocalInventory ) + InventoryScreen:SetVisible( open ) + InfoScreen:SetVisible( open ) + PlayerScreen:SetVisible( open ) + + gui.EnableScreenClicker( open ) + + if open then + + StashScreen:RefreshItems( LocalStash ) + + end + +end +usermessage.Hook( "StashMenu", StashMenu ) + diff --git a/gamemode/cl_targetid.lua b/gamemode/cl_targetid.lua new file mode 100644 index 0000000..0a69c81 --- /dev/null +++ b/gamemode/cl_targetid.lua @@ -0,0 +1,135 @@ + +TargetedEntity = nil + +local TargetedName = nil +local TargetedTime = 0 +local TargetedDist = Vector(0,0,0) + +ValidTargetEnts = { "prop_physics", "sent_oxygen", "sent_fuel_diesel", "sent_fuel_gas", "sent_propane_tank", "sent_propane_canister", "sent_barrel_radioactive", "sent_barrel_biohazard" } + +function GM:GetEntityID( ent ) + + if table.HasValue( ValidTargetEnts, ent:GetClass() ) then + + local tbl = item.GetByClass( ent:GetClass() ) + + if tbl then + + TargetedName = tbl.Name + TargetedEntity = ent + TargetedDist = Vector( 0, 0, TargetedEntity:OBBCenter():Distance( TargetedEntity:OBBMaxs() ) ) + + else + + tbl = item.GetByModel( ent:GetModel() ) + + if tbl then + + TargetedName = tbl.Name + TargetedEntity = ent + TargetedDist = Vector( 0, 0, TargetedEntity:OBBCenter():Distance( TargetedEntity:OBBMaxs() ) ) + + end + + end + + elseif ent:GetClass() == "sent_droppedgun" then + + local tbl = item.GetByModel( ent:GetModel() ) + + if tbl then + + TargetedName = tbl.Name + TargetedEntity = ent + TargetedDist = Vector( 0, 0, 10 ) + + end + + elseif ent:GetClass() == "sent_lootbag" then + + TargetedName = "Loot" + TargetedEntity = ent + TargetedDist = Vector( 0, 0, 10 ) + + elseif ent:GetClass() == "sent_cash" then + + TargetedName = ent:GetNWInt( "Cash", 10 ) .. " " .. GAMEMODE.CurrencyName .. "s" + TargetedEntity = ent + TargetedDist = Vector( 0, 0, 5 ) + + elseif ent:GetClass() == "sent_antidote" then + + TargetedName = "Antidote Crate" + TargetedEntity = ent + TargetedDist = Vector( 0, 0, 15 ) + + elseif ent:GetClass() == "sent_supplycrate" then + + TargetedName = "Supply Crate" + TargetedEntity = ent + TargetedDist = Vector( 0, 0, 15 ) + + elseif ent:GetClass() == "sent_bonuscrate" then + + TargetedName = "Weapon Cache" + TargetedEntity = ent + TargetedDist = Vector( 0, 0, 25 ) + + elseif ent:GetClass() == "npc_scientist" then + + TargetedName = "Field Researcher" + TargetedEntity = ent + TargetedDist = Vector( 0, 0, 40 ) + + elseif ent:IsPlayer() and ent:Team() == TEAM_ARMY then + + TargetedName = ent:Name() + TargetedEntity = ent + TargetedDist = Vector( 0, 0, 35 ) + + end + + if IsValid( TargetedEntity ) then + + TargetedTime = CurTime() + 5 + + end + +end + +function GM:HUDTraces() + + local tr = util.TraceLine( util.GetPlayerTrace( LocalPlayer() ) ) + + GAMEMODE.LastTraceEnt = tr.Entity + + if IsValid( GAMEMODE.LastTraceEnt ) and GAMEMODE.LastTraceEnt:GetPos():Distance( LocalPlayer():GetPos() ) < 800 then + + GAMEMODE:GetEntityID( GAMEMODE.LastTraceEnt ) + + end + +end + +function GM:HUDDrawTargetID() + + if not IsValid( LocalPlayer() ) then return end + + if not LocalPlayer():Alive() or LocalPlayer():Team() == TEAM_ZOMBIES then return end + + if IsValid( TargetedEntity ) and TargetedTime > CurTime() then + + local worldpos = TargetedEntity:LocalToWorld( TargetedEntity:OBBCenter() ) + TargetedDist + local pos = ( worldpos ):ToScreen() + + //print( TargetedName .. " " .. tostring(TargetedDist) .. tostring(pos.visible) .. " - " .. pos.x .. " n " .. pos.y ) + + if pos.visible then + + draw.SimpleText( TargetedName or "Error", "AmmoFontSmall", pos.x, pos.y, Color( 80, 150, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + end + + end + +end diff --git a/gamemode/default_player.lua b/gamemode/default_player.lua new file mode 100644 index 0000000..a84c8ab --- /dev/null +++ b/gamemode/default_player.lua @@ -0,0 +1,15 @@ +DEFINE_BASECLASS( "player_default" ) + +local PLAYER = {} + +function PLAYER:GetHandsModel() + + return { model = "models/weapons/c_arms_cstrike.mdl", skin = 1, body = "0100000" } + +end + +function PLAYER:Spawn() + +end + +player_manager.RegisterClass( "player_army", PLAYER, "player_default" )
\ No newline at end of file diff --git a/gamemode/enums.lua b/gamemode/enums.lua new file mode 100644 index 0000000..9b9a2e6 --- /dev/null +++ b/gamemode/enums.lua @@ -0,0 +1,29 @@ + +// Voice types + +VO_DEATH = 1 +VO_PAIN = 2 +VO_TAUNT = 3 +VO_ALERT = 4 +VO_IDLE = 5 +VO_EVAC = 6 + +// Class types for humans + +CLASS_SCOUT = 1 +CLASS_COMMANDO = 2 +CLASS_SPECIALIST = 3 +CLASS_ENGINEER = 4 + +// Zed types + +CLASS_RUNNER = 1 +CLASS_BANSHEE = 2 +CLASS_CONTAGION = 3 +CLASS_LEAPER = 4 + +// Event types + +EVENT_BONUS = 1 +EVENT_WEATHER = 2 +EVENT_BAD = 3
\ No newline at end of file diff --git a/gamemode/events.lua b/gamemode/events.lua new file mode 100644 index 0000000..c4f9757 --- /dev/null +++ b/gamemode/events.lua @@ -0,0 +1,17 @@ + +module( "event", package.seeall ) + +local Events = {} + +function Register( tbl ) + + table.insert( Events, tbl ) + +end + +function GetRandom() + + return table.Random( Events ) + +end + diff --git a/gamemode/events/antidote_shortage.lua b/gamemode/events/antidote_shortage.lua new file mode 100644 index 0000000..829709b --- /dev/null +++ b/gamemode/events/antidote_shortage.lua @@ -0,0 +1,51 @@ + +local EVENT = {} + +EVENT.Chance = 0.75 +EVENT.Type = EVENT_BAD +EVENT.TimeText = { "1 minute", "2 minutes", "3 minutes" } +EVENT.Times = { 60, 120, 180 } + +function EVENT:Start() + + local num = math.random(1,3) + + EVENT.EndTime = CurTime() + EVENT.Times[ num ] + EVENT.ThinkTime = 0 + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + v:Notice( "Antidote supplies will be low for " .. EVENT.TimeText[ num ], GAMEMODE.Colors.Red, 5 ) + v:Notice( "The antidote shortage has ended", GAMEMODE.Colors.White, 5, EVENT.Times[ num ] ) + + end + +end + +function EVENT:Think() + + if EVENT.ThinkTime < CurTime() then + + EVENT.ThinkTime = CurTime() + 3 + + if IsValid( GAMEMODE.Antidote ) and GAMEMODE.Antidote:CuresLeft() > 1 then + + GAMEMODE.Antidote:SetCures( 1 ) + + end + + end + +end + +function EVENT:EndThink() + + return EVENT.EndTime < CurTime() // true ends this immediately + +end + +function EVENT:End() + +end + +event.Register( EVENT ) diff --git a/gamemode/events/fallout.lua b/gamemode/events/fallout.lua new file mode 100644 index 0000000..b316523 --- /dev/null +++ b/gamemode/events/fallout.lua @@ -0,0 +1,84 @@ + +local EVENT = {} + +EVENT.Chance = 0.50 +EVENT.Type = EVENT_BAD +EVENT.TimeText = { "30 seconds", "1 minute" } +EVENT.Times = { 30, 60 } + +function EVENT:Start() + + local num = math.random(1,2) + + EVENT.Delay = CurTime() + 15 + EVENT.RadTime = CurTime() + EVENT.Times[ num ] + 15 + EVENT.RadDelay = 0 + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + v:Notice( "Nuclear fallout contamination is imminent", GAMEMODE.Colors.White, 7 ) + v:Notice( "Enter a building to avoid radiation poisoning", GAMEMODE.Colors.White, 7, 2 ) + v:Notice( "The atmospheric fallout will subside in " .. EVENT.TimeText[ num ], GAMEMODE.Colors.White, 7, 15 ) + v:Notice( "Atmospheric radioactivity levels are now safe", GAMEMODE.Colors.White, 7, EVENT.Times[ num ] + 15 ) + + end + + timer.Simple( 15, function() SetGlobalBool( "Radiation", true ) end ) + +end + +function EVENT:Think() + + if EVENT.Delay < CurTime() then + + if EVENT.RadDelay < CurTime() then + + EVENT.RadDelay = CurTime() + 1 + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + if not v:IsIndoors() then + + if math.random(1,2) == 1 then + + v:EmitSound( table.Random( GAMEMODE.Geiger ), 100, math.random(90,110) ) + + end + + if math.random(1,5) == 1 then + + v:AddRadiation( 1 ) + + end + + else + + if math.random(1,6) == 1 then + + v:EmitSound( table.Random( GAMEMODE.Geiger ), 100, math.random(120,140) ) + + end + + end + + end + + end + + end + +end + +function EVENT:EndThink() + + return EVENT.RadTime < CurTime() + +end + +function EVENT:End() + + SetGlobalBool( "Radiation", false ) + +end + +event.Register( EVENT ) diff --git a/gamemode/events/radio_blackout.lua b/gamemode/events/radio_blackout.lua new file mode 100644 index 0000000..27c5344 --- /dev/null +++ b/gamemode/events/radio_blackout.lua @@ -0,0 +1,38 @@ + +local EVENT = {} + +EVENT.Chance = 0.75 +EVENT.Type = EVENT_BAD +EVENT.TimeText = { "30 seconds", "1 minute", "90 seconds" } +EVENT.Times = { 30, 60, 90 } + +function EVENT:Start() + + local num = math.random(1,3) + + GAMEMODE.RadioBlock = CurTime() + EVENT.Times[ num ] + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + v:Notice( "Radio communications will be down for " .. EVENT.TimeText[ num ], GAMEMODE.Colors.Red, 5 ) + v:Notice( "Radio communications are back online", GAMEMODE.Colors.White, 5, EVENT.Times[ num ] ) + + end + +end + +function EVENT:Think() + +end + +function EVENT:EndThink() + + return true // true ends this immediately + +end + +function EVENT:End() + +end + +event.Register( EVENT ) diff --git a/gamemode/events/radioblackout.lua b/gamemode/events/radioblackout.lua new file mode 100644 index 0000000..27c5344 --- /dev/null +++ b/gamemode/events/radioblackout.lua @@ -0,0 +1,38 @@ + +local EVENT = {} + +EVENT.Chance = 0.75 +EVENT.Type = EVENT_BAD +EVENT.TimeText = { "30 seconds", "1 minute", "90 seconds" } +EVENT.Times = { 30, 60, 90 } + +function EVENT:Start() + + local num = math.random(1,3) + + GAMEMODE.RadioBlock = CurTime() + EVENT.Times[ num ] + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + v:Notice( "Radio communications will be down for " .. EVENT.TimeText[ num ], GAMEMODE.Colors.Red, 5 ) + v:Notice( "Radio communications are back online", GAMEMODE.Colors.White, 5, EVENT.Times[ num ] ) + + end + +end + +function EVENT:Think() + +end + +function EVENT:EndThink() + + return true // true ends this immediately + +end + +function EVENT:End() + +end + +event.Register( EVENT ) diff --git a/gamemode/events/scientist.lua b/gamemode/events/scientist.lua new file mode 100644 index 0000000..ce58fdf --- /dev/null +++ b/gamemode/events/scientist.lua @@ -0,0 +1,38 @@ + +local EVENT = {} + +EVENT.Chance = 0.75 +EVENT.Type = EVENT_BONUS + +function EVENT:Start() + + local spawns = ents.FindByClass( "info_evac" ) + local evac = table.Random( spawns ) + + local ent = ents.Create( "npc_scientist" ) + ent:SetPos( evac:GetPos() + Vector(0,0,10) ) + ent:Spawn() + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + v:Notice( "A surviving field researcher has been sighted", GAMEMODE.Colors.White, 5 ) + + end + +end + +function EVENT:Think() + +end + +function EVENT:EndThink() + + return true // true ends this immediately + +end + +function EVENT:End() + +end + +event.Register( EVENT ) diff --git a/gamemode/events/supply_crate.lua b/gamemode/events/supply_crate.lua new file mode 100644 index 0000000..35ca974 --- /dev/null +++ b/gamemode/events/supply_crate.lua @@ -0,0 +1,40 @@ + +local EVENT = {} + +EVENT.Chance = 0.95 +EVENT.Type = EVENT_BONUS + +function EVENT:Start() + + local spawns = ents.FindByClass( "info_lootspawn" ) + local loot = table.Random( spawns ) + + if not IsValid( loot ) then MsgN( "ERROR: Unable to locate loot spawns. Map not configured?" ) return end + + local ent = ents.Create( "sent_bonuscrate" ) + ent:SetPos( loot:GetPos() + Vector(0,0,10) ) + ent:Spawn() + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + v:Notice( "Keep an eye out for a civilian weapon cache", GAMEMODE.Colors.White, 5 ) + + end + +end + +function EVENT:Think() + +end + +function EVENT:EndThink() + + return true // true ends this immediately + +end + +function EVENT:End() + +end + +event.Register( EVENT ) diff --git a/gamemode/events/supplycrate.lua b/gamemode/events/supplycrate.lua new file mode 100644 index 0000000..35ca974 --- /dev/null +++ b/gamemode/events/supplycrate.lua @@ -0,0 +1,40 @@ + +local EVENT = {} + +EVENT.Chance = 0.95 +EVENT.Type = EVENT_BONUS + +function EVENT:Start() + + local spawns = ents.FindByClass( "info_lootspawn" ) + local loot = table.Random( spawns ) + + if not IsValid( loot ) then MsgN( "ERROR: Unable to locate loot spawns. Map not configured?" ) return end + + local ent = ents.Create( "sent_bonuscrate" ) + ent:SetPos( loot:GetPos() + Vector(0,0,10) ) + ent:Spawn() + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + v:Notice( "Keep an eye out for a civilian weapon cache", GAMEMODE.Colors.White, 5 ) + + end + +end + +function EVENT:Think() + +end + +function EVENT:EndThink() + + return true // true ends this immediately + +end + +function EVENT:End() + +end + +event.Register( EVENT ) diff --git a/gamemode/events/weather_event.lua b/gamemode/events/weather_event.lua new file mode 100644 index 0000000..f7640fe --- /dev/null +++ b/gamemode/events/weather_event.lua @@ -0,0 +1,39 @@ + +local EVENT = {} + +EVENT.Chance = 0.95 +EVENT.Type = EVENT_WEATHER + +EVENT.Types = {} +EVENT.Types[1] = "rain" +EVENT.Types[2] = "thunder" +EVENT.Types[3] = "lightning" +EVENT.Types[4] = "strong winds" + +function EVENT:Start() + + GAMEMODE:RandomizeWeather( true ) + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + v:Notice( "The weather conditions are worsening", GAMEMODE.Colors.White, 5 ) + + end + +end + +function EVENT:Think() + +end + +function EVENT:EndThink() + + return true // true ends this immediately + +end + +function EVENT:End() + +end + +event.Register( EVENT ) diff --git a/gamemode/init.lua b/gamemode/init.lua new file mode 100644 index 0000000..eafdfcb --- /dev/null +++ b/gamemode/init.lua @@ -0,0 +1,2103 @@ + +include( 'player_class/player_base.lua' ) +include( 'player_class/player_zombie.lua' ) +include( 'map_defaults.lua' ) +include( 'resource.lua' ) +include( 'enums.lua' ) +include( 'items.lua' ) +include( 'events.lua' ) +include( 'shared.lua' ) +include( 'moddable.lua' ) +include( 'ply_extension.lua' ) +include( 'tables.lua' ) +include( 'weather.lua' ) + +AddCSLuaFile( 'player_class/player_base.lua' ) +AddCSLuaFile( 'player_class/player_zombie.lua' ) +AddCSLuaFile( 'animations.lua' ) +AddCSLuaFile( 'enums.lua' ) +AddCSLuaFile( 'items.lua' ) +AddCSLuaFile( 'shared.lua' ) +AddCSLuaFile( 'moddable.lua' ) +AddCSLuaFile( 'cl_notice.lua' ) +AddCSLuaFile( 'cl_hudstains.lua' ) +AddCSLuaFile( 'cl_targetid.lua' ) +AddCSLuaFile( 'cl_spawnmenu.lua' ) +AddCSLuaFile( 'cl_inventory.lua' ) +AddCSLuaFile( 'cl_init.lua' ) +AddCSLuaFile( 'cl_postprocess.lua' ) +AddCSLuaFile( 'cl_scoreboard.lua' ) +AddCSLuaFile( 'ply_extension.lua' ) +AddCSLuaFile( 'tables.lua' ) +AddCSLuaFile( 'weather.lua' ) +AddCSLuaFile( 'vgui/vgui_panelbase.lua' ) +AddCSLuaFile( 'vgui/vgui_dialogue.lua' ) +AddCSLuaFile( 'vgui/vgui_shopmenu.lua' ) +AddCSLuaFile( 'vgui/vgui_classpicker.lua' ) +AddCSLuaFile( 'vgui/vgui_zombieclasses.lua' ) +AddCSLuaFile( 'vgui/vgui_itempanel.lua' ) +AddCSLuaFile( 'vgui/vgui_helpmenu.lua' ) +AddCSLuaFile( 'vgui/vgui_endgame.lua' ) +AddCSLuaFile( 'vgui/vgui_itemdisplay.lua' ) +AddCSLuaFile( 'vgui/vgui_playerdisplay.lua' ) +AddCSLuaFile( 'vgui/vgui_playerpanel.lua' ) +AddCSLuaFile( 'vgui/vgui_panelsheet.lua' ) +AddCSLuaFile( 'vgui/vgui_goodmodelpanel.lua' ) +AddCSLuaFile( 'vgui/vgui_categorybutton.lua' ) +AddCSLuaFile( 'vgui/vgui_sidebutton.lua' ) +AddCSLuaFile( 'vgui/vgui_scroller.lua' ) + +util.AddNetworkString( "InventorySynch" ) +util.AddNetworkString( "StashSynch" ) +util.AddNetworkString( "StatsSynch" ) +util.AddNetworkString( "ItemPlacerSynch" ) +util.AddNetworkString( "WeatherSynch" ) + +function GM:Initialize() + + GAMEMODE.NextZombieThink = CurTime() + GetConVar( "sv_redead_setup_time" ):GetInt() + GAMEMODE.RandomLoot = {} + GAMEMODE.PlayerIDs = {} + GAMEMODE.Lords = {} + GAMEMODE.Wave = 1 + GAMEMODE.NextWave = CurTime() + 60 * GetConVar( "sv_redead_wave_length" ):GetInt() + + local length = #GAMEMODE.Waves * ( GetConVar( "sv_redead_wave_length" ):GetInt() * 60 ) + + for i=1, #GAMEMODE.Waves - 1 do + + local remain = length - i * GetConVar( "sv_redead_wave_length" ):GetInt() * 60 + local num = i * GetConVar( "sv_redead_wave_length" ):GetInt() + + timer.Simple( remain, function() for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do v:Notice( num .. " minutes until evac arrives", GAMEMODE.Colors.White, 5 ) end end ) + + end + + timer.Simple( GetConVar( "sv_redead_setup_time" ):GetInt(), function() for k,v in pairs( player.GetAll() ) do v:Notice( "The undead onslaught has begun", GAMEMODE.Colors.White, 5 ) end end ) + + timer.Simple( GetConVar( "sv_redead_setup_time" ):GetInt() - 5, function() for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do v:Notice( "Press F4 if you want to be the zombie lord", GAMEMODE.Colors.White, 5 ) end end ) + + timer.Simple( GetConVar( "sv_redead_setup_time" ):GetInt() + 5, function() GAMEMODE:PickLord() GAMEMODE.EarlyPick = true end ) + + timer.Simple( length - 60, function() + + if GetGlobalBool( "GameOver", false ) then return end + + GAMEMODE.EvacAlert = true + + for k,v in pairs( player.GetAll() ) do + + v:ClientSound( GAMEMODE.LastMinute ) + v:Notice( "The evac chopper is en route", GAMEMODE.Colors.White, 5 ) + + end + + end ) + + timer.Simple( length - 40, function() + + if GetGlobalBool( "GameOver", false ) then return end + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + v:Notice( "The evac chopper has arrived", GAMEMODE.Colors.White, 5 ) + v:Notice( "You have 45 seconds to reach the evac zone", GAMEMODE.Colors.White, 5, 2 ) + v:Notice( "The location has been marked", GAMEMODE.Colors.White, 5, 4 ) + + end + + if IsValid( GAMEMODE.Antidote ) then + + GAMEMODE.Antidote:SetOverride() + + end + + GAMEMODE:SpawnEvac() + + end ) + + timer.Simple( length + 5, function() GAMEMODE:CheckGameOver( true ) end ) + + GAMEMODE:WeatherInit() + + if math.random( 1, 10 ) == 1 then + + GAMEMODE.RandomEvent = CurTime() + ( 60 * math.Rand( 1.5, 3.5 ) ) + + end + +end + +GM.Breakables = {} +GM.WoodLocations = {} +GM.WoodCount = 1 +GM.WoodPercent = 1 +GM.SpawnCounter = 0 +GM.LordExists = false +GM.EarlyPick = false + +function GM:InitPostEntity() + + GAMEMODE.Trader = ents.Create( "info_trader" ) + GAMEMODE.Trader:Spawn() + + GAMEMODE.SpecialTrader = ents.Create( "info_trader" ) + GAMEMODE.SpecialTrader:SetSpecial( true ) + GAMEMODE.SpecialTrader:Spawn() + + local badshit = ents.FindByClass( "npc_*" ) + badshit = table.Add( badshit, ents.FindByClass( "weapon_*" ) ) + badshit = table.Add( badshit, ents.FindByClass( "prop_ragdoll" ) ) + badshit = table.Add( badshit, ents.FindByClass( "item_*" ) ) + badshit = table.Add( badshit, ents.FindByClass( "point_servercommand" ) ) + badshit = table.Add( badshit, ents.FindByClass( "env_entity_maker" ) ) + badshit = table.Add( badshit, ents.FindByClass( "point_template" ) ) + badshit = table.Add( badshit, ents.FindByClass( "game_text" ) ) + + for k,v in pairs( ents.FindByClass( "prop_phys*" ) ) do + + if string.find( v:GetModel(), "explosive" ) or string.find( v:GetModel(), "propane" ) or string.find( v:GetModel(), "gascan" ) or string.find( v:GetModel(), "gib" ) then + + table.insert( badshit, v ) + + end + + local phys = v:GetPhysicsObject() + + if IsValid( phys ) and table.HasValue( { "wood", "wood_crate", "wood_furniture", "wood_plank", "default" }, phys:GetMaterial() ) and phys:GetMass() > 8 then + + table.insert( GAMEMODE.WoodLocations, { Pos = v:GetPos(), Ang = v:GetAngles(), Model = v:GetModel(), Health = v:Health() } ) + + GAMEMODE.WoodCount = GAMEMODE.WoodCount + 1 + + v.IsWooden = true + + if v:Health() == 0 then + + v:SetHealth( 100 ) + + end + + if phys:IsAsleep() then + + phys:Wake() + + end + + end + + end + + for k,v in pairs( badshit ) do + + v:Remove() + + end + + GAMEMODE.WoodPercent = math.floor( table.Count( ents.FindByClass( "prop_phys*" ) ) * GAMEMODE.WoodPercentage ) + + for k,v in pairs( ents.FindByClass( "prop_phys*" ) ) do + + local tbl = item.GetByModel( v:GetModel() ) + local phys = v:GetPhysicsObject() + + if tbl or ( IsValid( phys ) and phys:GetMass() <= 3 ) then + + v:Remove() + + end + + end + + GAMEMODE:LoadAllEnts() + + local tbl = ents.FindByClass( "prop_door_rotating" ) + tbl = table.Add( tbl, ents.FindByClass( "func_breakable*" ) ) + tbl = table.Add( tbl, ents.FindByClass( "func_door*" ) ) + + GAMEMODE.Breakables = tbl + GAMEMODE.NPCSpawns = ents.FindByClass( "info_npcspawn" ) + + local num = #ents.FindByClass( "point_radiation" ) + + if num < 5 then return end + + for i=1, math.floor( num * GAMEMODE.RadiationAmount ) do + + local rad = table.Random( ents.FindByClass( "point_radiation" ) ) + + while !rad:IsActive() do + + rad = table.Random( ents.FindByClass( "point_radiation" ) ) + + end + + rad:SetActive( false ) + + end + +end + +function GM:SaveAllEnts() + + MsgN( "Saving ReDead map config data..." ) + + local enttbl = { + info_player_zombie = {}, + info_player_army = {}, + info_lootspawn = {}, + info_npcspawn = {}, + info_evac = {}, + point_stash = {}, + point_radiation = {}, + prop_physics = {} + } + + for k,v in pairs( enttbl ) do + + for c,d in pairs( ents.FindByClass( k ) ) do + + if k == "prop_physics" then + + if d.AdminPlaced then + + local phys = d:GetPhysicsObject() + + if IsValid( phys ) then + + table.insert( enttbl[k], { d:GetPos(), d:GetModel(), d:GetAngles(), phys:IsMoveable() } ) + + end + + end + + elseif d.AdminPlaced then + + table.insert( enttbl[k], d:GetPos() ) + + end + + end + + end + + file.Write( "redead/" .. string.lower( game.GetMap() ) .. "_json.txt", util.TableToJSON( enttbl ) ) + +end + +function GM:LoadAllEnts() + + MsgN( "Loading ReDead map config data..." ) + + local read = file.Read( "redead/" .. string.lower( game.GetMap() ) .. "_json.txt", "DATA" ) + + if not read then + + MsgN( "No map config data found for " .. game.GetMap() .. "." ) + + return + + end + + local config = util.JSONToTable( read ) + + if not config then + + MsgN( "ERROR: ReDead map config data file was empty!" ) + + return + + end + + MsgN( "Loaded ReDead map config data successfully!" ) + + for k,v in pairs( config ) do + + if v[1] then + + if k == "prop_physics" then + + for c,d in pairs( v ) do + + local function spawnent() + + local ent = ents.Create( k ) + ent:SetPos( d[1] ) + ent:SetModel( d[2] ) + ent:SetAngles( d[3] ) + ent:SetSkin( math.random( 0, 6 ) ) + ent:Spawn() + ent.AdminPlaced = true + + local phys = ent:GetPhysicsObject() + + if IsValid( phys ) and not d[4] then + + phys:EnableMotion( false ) + + end + + end + + timer.Simple( c * 0.1, function() spawnent() end ) + + end + + else + + for c,d in pairs( ents.FindByClass( k ) ) do + + d:Remove() + + end + + for c,d in pairs( v ) do + + if k != "point_radiation" and k != "info_lootspawn" and k != "info_npcspawn" then + + local function spawnent() + + local ent = ents.Create( k ) + ent:SetPos( d ) + ent:Spawn() + ent.AdminPlaced = true + + end + + timer.Simple( c * 0.1, function() spawnent() end ) + + else + + local ent = ents.Create( k ) + ent:SetPos( d ) + ent:Spawn() + ent.AdminPlaced = true + + end + + end + + end + + end + + end + +end + +function GM:AddToZombieList( ply ) + + if team.NumPlayers( TEAM_ZOMBIES ) > 0 then + + ply:ClientSound( "HL1/fvox/buzz.wav", 100 ) + ply:Notice( "You cannot be the zombie lord now", GAMEMODE.Colors.Red, 5 ) + + return + + end + + if not table.HasValue( GAMEMODE.Lords, ply ) and not GAMEMODE.LordExists then + + table.insert( GAMEMODE.Lords, ply ) + + local snd = table.Random( GAMEMODE.AmbientScream ) + ply:ClientSound( snd, 100 ) + ply:Notice( "You have volunteered to be the zombie lord", GAMEMODE.Colors.White, 5 ) + + end + +end + +function GM:PickLord( force ) + + if table.Count( player.GetAll() ) < GetConVar( "sv_redead_minimum_players" ):GetInt() and not force then + + for k,v in pairs( player.GetAll() ) do + + v:Notice( "A zombie lord cannot be chosen at this time", GAMEMODE.Colors.White, 5 ) + + end + + return + + end + + local tbl = team.GetPlayers( TEAM_ZOMBIES ) + + for k,v in pairs( GAMEMODE.Lords ) do + + if IsValid( v ) then + + table.insert( tbl, v ) + + end + + end + + if table.Count( tbl ) < 1 then + + tbl = team.GetPlayers( TEAM_ARMY ) + + end + + local ply = table.Random( tbl ) + + local snd = table.Random( GAMEMODE.AmbientScream ) + ply:ClientSound( snd, 100 ) + + if ply:Team() == TEAM_ZOMBIES then + + ply:Notice( "You have become the zombie lord", GAMEMODE.Colors.White, 5 ) + + timer.Simple( 3, function() ply:Gib() ply:SetLord( true ) end ) + + else + + ply:Notice( "You will become the zombie lord", GAMEMODE.Colors.White, 5 ) + + timer.Simple( 3, function() ply:SetTeam( TEAM_ZOMBIES ) ply:SetPlayerClass( CLASS_RUNNER ) ply:SetCash( 0 ) ply:Gib() ply:SetLord( true ) end ) + + end + + for k,v in pairs( player.GetAll() ) do + + if v != ply and not force then + + v:Notice( "A zombie lord has been chosen", GAMEMODE.Colors.White, 5 ) + + end + + end + + GAMEMODE.LordExists = true + +end + +function GM:RespawnAntidote() + + if IsValid( ents.FindByClass( "sent_antidote" )[1] ) and ents.FindByClass( "sent_antidote" )[1]:CuresLeft() > 0 then return end + + if #ents.FindByClass( "info_lootspawn" ) < 3 then return end + + local ent = table.Random( ents.FindByClass( "info_lootspawn" ) ) + local pos = ent:GetPos() + local close = true + + while close do + + ent = table.Random( ents.FindByClass( "info_lootspawn" ) ) + pos = ent:GetPos() + close = false + + for k,v in pairs( ents.FindByClass( "sent_antidote" ) ) do + + if v:GetPos():Distance( pos ) < 500 then + + close = true + + end + + end + + end + + local ant = ents.Create( "sent_antidote" ) + ant:SetPos( pos ) + ant:Spawn() + + GAMEMODE.Antidote = ant + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + v:Notice( "The antidote resupply location has changed", GAMEMODE.Colors.White, 5 ) + + end + +end + +function GM:SpawnEvac() + + local pos = Vector(0,0,0) + + if #ents.FindByClass( "info_evac" ) < 1 then + + local loot = ents.FindByClass( "info_lootspawn" ) + + if #loot < 1 then + + MsgN( "ERROR: Map not configured properly." ) + + return + + end + + local prop = table.Random( loot ) + + pos = prop:GetPos() + + else + + local point = table.Random( ents.FindByClass( "info_evac" ) ) + pos = point:GetPos() + + end + + local evac = ents.Create( "point_evac" ) + evac:SetPos( pos ) + evac:Spawn() + +end + +function GM:GetGeneratedLoot() + + local tbl = {} + + for k,v in pairs( GAMEMODE.RandomLoot ) do + + if IsValid( v ) then + + table.insert( tbl, v ) + + end + + end + + for k,v in pairs( GAMEMODE.RandomLoot ) do + + if not IsValid( v ) then + + table.remove( tbl, k ) + + return tbl + + end + + end + + return tbl + +end + +function GM:LootThink() + + for k,v in pairs( ents.FindByClass( "prop_phys*" ) ) do + + if v.Removal and v.Removal < CurTime() and IsValid( v ) then + + v:Remove() + + end + + end + + if #ents.FindByClass( "info_lootspawn" ) < 10 then return end + + local amt = math.floor( GAMEMODE.MaxLoot * #ents.FindByClass( "info_lootspawn" ) ) + local total = 0 + + local loots = GAMEMODE:GetGeneratedLoot() + + local num = amt - #loots + + if num > 0 then + + local tbl = { ITEM_SUPPLY, ITEM_LOOT, ITEM_AMMO, ITEM_MISC, ITEM_SPECIAL, ITEM_WPN_COMMON, ITEM_WPN_SPECIAL, ITEM_EXPLOSIVE } + local chancetbl = { 0.60, 0.70, 0.70, 0.95, 0.05, 0.03, 0.02, 0.10 } + + for i=1, num do + + local ent = table.Random( ents.FindByClass( "info_lootspawn" ) ) + local pos = ent:GetPos() + local rnd = math.Rand(0,1) + local choice = math.random( 1, table.Count( tbl ) ) + + while rnd > chancetbl[ choice ] do + + rnd = math.Rand(0,1) + choice = math.random( 1, table.Count( tbl ) ) + + end + + local rand = item.RandomItem( tbl[choice] ) + local proptype = "prop_physics" + + if rand.TypeOverride then + + proptype = rand.TypeOverride + + end + + local loot = ents.Create( proptype ) + loot:SetPos( pos + Vector(0,0,5) ) + loot:SetAngles( VectorRand():Angle() ) + + if rand.DropModel then + + loot:SetModel( rand.DropModel ) + + else + + loot:SetModel( rand.Model ) + + end + + loot:Spawn() + loot.RandomLoot = true + loot.IsItem = true + + if not rand.CollisionOverride then + + loot:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + end + + table.insert( GAMEMODE.RandomLoot, loot ) + + end + + end + +end + +function GM:WoodThink() + + if table.Count( GAMEMODE.WoodLocations ) < 1 then return end + + if GAMEMODE.WoodCount < GAMEMODE.WoodPercent then + + local tbl = table.Random( GAMEMODE.WoodLocations ) + local prop = ents.Create( "prop_physics" ) + prop:SetPos( tbl.Pos ) + prop:SetAngles( tbl.Ang ) + prop:SetModel( tbl.Model ) + prop:SetHealth( math.Clamp( tbl.Health, 50, 500 ) ) + prop:Spawn() + prop.IsWooden = true + + GAMEMODE.WoodCount = GAMEMODE.WoodCount + 1 + + elseif GAMEMODE.WoodCount > GAMEMODE.WoodPercent then + + local ent = table.Random( ents.FindByClass( "prop_phys*" ) ) + local phys = ent:GetPhysicsObject() + + if IsValid( phys ) and not ent.IsItem and ent.IsWooden then + + ent:Remove() + + GAMEMODE.WoodCount = GAMEMODE.WoodCount - 1 + + end + + end + +end + +function GM:EventThink() + + if not GAMEMODE.RandomEvent then + + GAMEMODE.RandomEvent = CurTime() + ( 60 * math.Rand( 3.5, 9.5 ) ) + + end + + if GAMEMODE.RandomEvent and GAMEMODE.RandomEvent < CurTime() then + + local ev = event.GetRandom() + + while ( ( ev.Type == EVENT_WEATHER and GAMEMODE.WeatherHappened ) or ev.Chance < math.Rand(0,1) ) do + + ev = event.GetRandom() + + end + + if ev.Type == EVENT_WEATHER then + + GAMEMODE.WeatherHappened = true + + end + + ev.Start() + + GAMEMODE.Event = ev + GAMEMODE.RandomEvent = nil + + end + + if GAMEMODE.Event then + + GAMEMODE.Event:Think() + + if GAMEMODE.Event:EndThink() then + + GAMEMODE.Event:End() + GAMEMODE.Event = nil + + end + + end + +end + +function GM:WaveThink() + + if GAMEMODE.NextWave < CurTime() then + + GAMEMODE.NextWave = CurTime() + 60 * GetConVar( "sv_redead_wave_length" ):GetInt() + GAMEMODE.Wave = GAMEMODE.Wave + 1 + + if GAMEMODE.Wave > #GAMEMODE.Waves then return end + + for k,v in pairs( player.GetAll() ) do + + v:Notice( "New undead mutations have been spotted", GAMEMODE.Colors.White, 5 ) + v:ClientSound( table.Random( GAMEMODE.AmbientScream ) ) + + end + + end + +end + +function GM:GetZombieClass() + + local rand = math.Rand(0,1) + local class = table.Random( GAMEMODE.Waves[ GAMEMODE.Wave ] or { "npc_nb_common" } ) + + while #GAMEMODE.Waves[ GAMEMODE.Wave ] != 1 and rand > GAMEMODE.SpawnChance[ class ] do + + rand = math.Rand(0,1) + class = table.Random( GAMEMODE.Waves[ GAMEMODE.Wave ] or { "npc_nb_common" } ) + + end + + return class + +end + +function GM:NPCRespawnThink() + + for k,v in pairs( ( GAMEMODE.NPCSpawns or {} ) ) do + + if IsValid( v ) then + + local box = ents.FindInBox( v:GetPos() + Vector( -32, -32, 0 ), v:GetPos() + Vector( 32, 32, 64 ) ) + local can = true + + for k,v in pairs( box ) do + + if v.NextBot then + + can = false + + end + + end + + if can and GAMEMODE.SpawnCounter > 0 then + + local ent = ents.Create( GAMEMODE:GetZombieClass() ) + ent:SetPos( v:GetPos() ) + ent:Spawn() + + GAMEMODE.SpawnCounter = GAMEMODE.SpawnCounter - 1 + + end + + end + + end + +end + +function GM:NPCThink() + + if GAMEMODE.Wave > #GAMEMODE.Waves then return end + + local tbl = ents.FindByClass( "npc_nb*" ) + + if #tbl < GetConVar( "sv_redead_max_zombies" ):GetInt() and #tbl < GetConVar( "sv_redead_zombies_per_player" ):GetInt() * team.NumPlayers( TEAM_ARMY ) then + + local total = math.Round( GetConVar( "sv_redead_zombies_per_player" ):GetInt() * team.NumPlayers( TEAM_ARMY ) + GetConVar( "sv_redead_zombies_per_player_zombie" ):GetFloat() * team.NumPlayers( TEAM_ZOMBIES ) ) + local num = math.Clamp( total, 1, math.Min( GetConVar( "sv_redead_max_zombies" ):GetInt() - #tbl, total ) ) + + GAMEMODE.SpawnCounter = num + + --[[for i=1, num do + + local tbl = ents.FindByClass( "info_npcspawn" ) + + if #tbl < 1 then return end + + local spawn = table.Random( tbl ) + local vec = VectorRand() * 5 + + vec.z = 1 + + local ent = ents.Create( GAMEMODE:GetZombieClass() ) + ent:SetPos( spawn:GetPos() + vec ) + ent:Spawn() + + end]] + + end + +end + +function GM:Think() + + if ( GAMEMODE.NextGameThink or 0 ) < CurTime() then + + if ( GAMEMODE.NextZombieThink or 0 ) < CurTime() then + + GAMEMODE:NPCThink() + + GAMEMODE.NextZombieThink = CurTime() + GetConVar( "sv_redead_wave_time" ):GetInt() + + end + + GAMEMODE:NPCRespawnThink() + GAMEMODE:RespawnAntidote() + GAMEMODE:EventThink() + GAMEMODE:LootThink() + GAMEMODE:WoodThink() + GAMEMODE:WaveThink() + GAMEMODE:WeatherThink() + GAMEMODE:CheckGameOver( false ) + GAMEMODE.NextGameThink = CurTime() + 1 + + end + + for k,v in pairs( player.GetAll() ) do + + if v:Team() != TEAM_UNASSIGNED then + + v:Think() + + end + + end + +end + +function GM:PhysgunPickup( ply, ent ) + + if ply:IsAdmin() or ply:IsSuperAdmin() then return true end + + if ent:IsPlayer() then return false end + + if not ent.Placer or ent.Placer != ply then return false end + + return true + +end + +function GM:PlayerDisconnected( pl ) + + if pl:Alive() then + + pl:DropLoot() + + end + + if not table.HasValue( GAMEMODE.PlayerIDs, pl:SteamID() ) then + + table.insert( GAMEMODE.PlayerIDs, pl:SteamID() ) + + end + + if pl:IsLord() then + + GAMEMODE.LordExists = false + + end + +end + +function GM:PlayerInitialSpawn( pl ) + + pl:GiveAmmo( 200, "Pistol", false ) + + if table.HasValue( GAMEMODE.PlayerIDs, pl:SteamID() ) then + + pl:SetTeam( TEAM_ZOMBIES ) + + elseif pl:IsBot() then + + pl:SetTeam( TEAM_ARMY ) + pl:Spawn() + + else + + pl:SetTeam( TEAM_UNASSIGNED ) + pl:Spectate( OBS_MODE_ROAMING ) + + end + +end + +function GM:PlayerSpawn( pl ) + + if pl:Team() == TEAM_UNASSIGNED then + + pl:Spectate( OBS_MODE_ROAMING ) + pl:SetPos( pl:GetPos() + Vector( 0, 0, 50 ) ) + + return + + end + + GAMEMODE:RespawnAntidote() + + if pl:Team() == TEAM_ARMY then + + local music = table.Random( GAMEMODE.OpeningMusic ) + + pl:ClientSound( music, 100 ) + + end + + pl:NoticeOnce( "Press F1 to view the help menu", GAMEMODE.Colors.Blue, 7, 15 ) + pl:NoticeOnce( "Press F2 to buy items and weapons", GAMEMODE.Colors.Blue, 7, 17 ) + pl:NoticeOnce( "Press F3 to activate the panic button", GAMEMODE.Colors.Blue, 7, 19 ) + pl:InitializeInventory() + pl:OnSpawn() + pl:OnLoadout() + + local oldhands = pl:GetHands() + + if IsValid( oldhands ) then + + oldhands:Remove() + + end + + local hands = ents.Create( "gmod_hands" ) + + if IsValid( hands ) then + + hands:DoSetup( pl ) + hands:Spawn() + + end + +end + +function GM:PlayerSetModel( pl ) + +end + +function GM:PlayerLoadout( pl ) + +end + +function GM:PlayerJoinTeam( ply, teamid ) + + local oldteam = ply:Team() + + if ply:Alive() and ply:Team() != TEAM_UNASSIGNED then return end + + if teamid != TEAM_UNASSIGNED and ply:Team() == TEAM_UNASSIGNED then + + ply:UnSpectate() + + end + + if teamid == TEAM_SPECTATOR or teamid == TEAM_UNASSIGNED then + + teamid = TEAM_ARMY + + end + + ply:SetTeam( teamid ) + + if ply.NextSpawn and ply.NextSpawn > CurTime() then + + ply.NextSpawn = CurTime() + 5 + + else + + ply:Spawn() + + end + +end + +function GM:PlayerSwitchFlashlight( ply, on ) + + return ply:Team() == TEAM_ARMY + +end + +function GM:GetFallDamage( ply, speed ) + + if ply:Team() == TEAM_ZOMBIES then + + return 5 + + end + + local pain = speed * 0.12 + + ply:AddStamina( math.floor( pain * -0.25 ) ) + + return pain + +end + +function GM:PlayerDeathSound() + + return true + +end + +function GM:CanPlayerSuicide( ply ) + + return false + +end + +function GM:KeyRelease( ply, key ) + + if ply:Team() != TEAM_ARMY then return end + + if key == IN_JUMP then + + ply:AddStamina( -2 ) + + end + + if key != IN_USE then return end + + local trace = {} + trace.start = ply:GetShootPos() + trace.endpos = trace.start + ply:GetAimVector() * 80 + trace.filter = ply + + local tr = util.TraceLine( trace ) + + if IsValid( tr.Entity ) and tr.Entity:GetClass() == "prop_physics" then + + if IsValid( ply.Stash ) then + + ply.Stash:OnExit( ply ) + + return true + + end + + ply:AddToInventory( tr.Entity ) + + return true + + elseif IsValid( tr.Entity ) and tr.Entity:GetClass() == "point_stash" then + + if IsValid( ply.Stash ) then + + ply.Stash:OnExit( ply ) + + else + + tr.Entity:OnUsed( ply ) + + end + + elseif not IsValid( tr.Entity ) then + + if IsValid( ply.Stash ) then + + ply.Stash:OnExit( ply ) + + end + + end + + return true + +end + +function GM:PropBreak( att, prop ) + + local phys = prop:GetPhysicsObject() + + if IsValid( phys ) and prop:GetModel() != "models/props_debris/wood_board04a.mdl" then + + if prop.IsWooden then + + GAMEMODE:SpawnChunk( prop:LocalToWorld( prop:OBBCenter() ) ) + GAMEMODE.WoodCount = GAMEMODE.WoodCount - 1 + + end + + end + +end + +function GM:SpawnChunk( pos ) + + local ent = ents.Create( "prop_physics" ) + ent:SetPos( pos ) + ent:SetModel( "models/props_debris/wood_chunk04a.mdl" ) + ent:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + ent:Spawn() + ent.IsItem = true + +end + +function GM:AllowPlayerPickup( ply, ent ) + + local tbl = item.GetByModel( ent:GetModel() ) + + if tbl and tbl.AllowPickup then + + return true + + end + + return false + +end + +function GM:PlayerUse( ply, entity ) + + if ply:Team() == TEAM_ARMY and ( ply.LastUse or 0 ) < CurTime() then + + if table.HasValue( { "sent_propane_canister", "sent_propane_tank", "sent_fuel_diesel", "sent_fuel_gas" }, entity:GetClass() ) then + + ply.LastUse = CurTime() + 0.5 + + if not IsValid( ply.HeldObject ) and not IsValid( entity.Holder ) then + + ply:PickupObject( entity ) + ply.HeldObject = entity + entity.Holder = ply + entity:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + + elseif entity == ply.HeldObject then + + ply:DropObject( entity ) + ply.HeldObject = nil + entity.Holder = nil + entity:SetCollisionGroup( COLLISION_GROUP_NONE ) + + end + + end + + return true + + end + + if ply:Team() != TEAM_ZOMBIES then return false end + + local trace = {} + trace.start = ply:GetShootPos() + trace.endpos = trace.start + ply:GetAimVector() * 80 + trace.filter = ply + + local tr = util.TraceLine( trace ) + + if entity:GetClass() == "prop_door_rotating" or entity:GetClass() == "func_button" then + + return false + + end + + return true + +end + +function GM:EntityTakeDamage( ent, dmginfo ) + + if ent.IsWooden then + + ent.WoodHealth = ( ent.WoodHealth or 150 ) - dmginfo:GetDamage() + + if ent.WoodHealth < 1 then + + ent:Fire( "break", 0, 0 ) + + end + + end + + if not ent:IsPlayer() and ent:IsOnFire() then + + ent:Extinguish() + + end + + if not ent:IsPlayer() and ent.IsItem then + + dmginfo:ScaleDamage( 0 ) + + return + + end + + local attacker = dmginfo:GetAttacker() + + if ent:IsPlayer() and ent:Team() == TEAM_ARMY and IsValid( attacker ) and ( attacker:IsNPC() or ( ( attacker:IsPlayer() and attacker:Team() == TEAM_ZOMBIES ) or ( attacker:IsPlayer() and attacker == ent ) ) ) then + + if ent:Health() <= 50 then + + ent:NoticeOnce( "Your health has dropped below 30%", GAMEMODE.Colors.Red, 5 ) + ent:NoticeOnce( "Health doesn't regenerate when below 30%", GAMEMODE.Colors.Blue, 5, 2 ) + + end + + if dmginfo:IsDamageType( DMG_BURN ) then + + ent:ViewBounce( 30 ) + + else + + ent:ViewBounce( 25 ) + ent:RadioSound( VO_PAIN ) + ent:DrawBlood() + + end + + if ent:GetPlayerClass() == CLASS_COMMANDO then + + dmginfo:ScaleDamage( GetConVar( "sv_redead_dmg_scale" ):GetFloat() * 0.85 ) + + else + + dmginfo:ScaleDamage( GetConVar( "sv_redead_dmg_scale" ):GetFloat() ) + + end + + if dmginfo:IsExplosionDamage() and attacker:Team() == TEAM_ZOMBIES then + + dmginfo:ScaleDamage( 0 ) + + else + + ent:AddStat( "Damage", math.Round( dmginfo:GetDamage() ) ) + + --[[if attacker:IsPlayer() then + + attacker:AddZedDamage( math.Round( dmginfo:GetDamage() ) ) + + end]] + + end + + elseif ent:IsPlayer() and ent:Team() == TEAM_ZOMBIES and IsValid( attacker ) and attacker:IsPlayer() and dmginfo:GetDamage() > 30 then + + sound.Play( table.Random( GAMEMODE.GoreBullet ), ent:GetPos() + Vector(0,0,50), 75, math.random( 90, 110 ), 0.8 ) + + end + + return self.BaseClass:EntityTakeDamage( ent, dmginfo ) + +end + +function GM:ScaleNPCDamage( npc, hitgroup, dmginfo ) // obsolete! + + if hitgroup == HITGROUP_HEAD then + + npc:EmitSound( "Player.DamageHeadShot" ) + npc:SetHeadshotter( dmginfo:GetAttacker(), true ) + + local effectdata = EffectData() + effectdata:SetOrigin( dmginfo:GetDamagePosition() ) + util.Effect( "headshot", effectdata, true, true ) + + dmginfo:ScaleDamage( math.Rand( 2.50, 3.00 ) ) + dmginfo:GetAttacker():NoticeOnce( "Headshot combos earn you more " .. GAMEMODE.CurrencyName .. "s", GAMEMODE.Colors.Blue, 5 ) + dmginfo:GetAttacker():AddHeadshot() + + elseif hitgroup == HITGROUP_CHEST then + + dmginfo:ScaleDamage( 1.25 ) + + npc:SetHeadshotter( dmginfo:GetAttacker(), false ) + dmginfo:GetAttacker():ResetHeadshots() + + elseif hitgroup == HITGROUP_STOMACH then + + dmginfo:ScaleDamage( 0.75 ) + + npc:SetHeadshotter( dmginfo:GetAttacker(), false ) + dmginfo:GetAttacker():ResetHeadshots() + + else + + dmginfo:ScaleDamage( 0.50 ) + + npc:SetHeadshotter( dmginfo:GetAttacker(), false ) + dmginfo:GetAttacker():ResetHeadshots() + + end + + return dmginfo + +end + +function GM:ScalePlayerDamage( ply, hitgroup, dmginfo ) + + if IsValid( ply.Stash ) then + + return + + end + + if hitgroup == HITGROUP_HEAD then + + ply:EmitSound( "Player.DamageHeadShot" ) + ply:ViewBounce( 25 ) + + dmginfo:ScaleDamage( 1.75 * GetConVar( "sv_redead_dmg_scale" ):GetFloat() ) + + return + + elseif hitgroup == HITGROUP_CHEST then + + ply:ViewBounce( 15 ) + + dmginfo:ScaleDamage( 1.50 * GetConVar( "sv_redead_dmg_scale" ):GetFloat() ) + + return + + elseif hitgroup == HITGROUP_STOMACH then + + dmginfo:ScaleDamage( 1.25 * GetConVar( "sv_redead_dmg_scale" ):GetFloat() ) + + else + + dmginfo:ScaleDamage( 0.50 * GetConVar( "sv_redead_dmg_scale" ):GetFloat() ) + + end + + ply:ViewBounce( ( dmginfo:GetDamage() / 20 ) * 10 ) + +end + +function GM:PlayerShouldTakeDamage( ply, attacker ) + + if ply:Team() == TEAM_UNASSIGNED then return false end + + if IsValid( attacker ) and attacker:IsPlayer() and attacker != ply then + + return ( ply:Team() != attacker:Team() or GetConVar( "sv_redead_team_dmg" ):GetBool() ) + + end + + return true + +end + +function GM:OnDamagedByExplosion( ply, dmginfo ) + + if dmginfo:GetDamage() > 25 then + + ply:SetBleeding( true ) + + end + + ply:SetDSP( 35, false ) + + umsg.Start( "GrenadeHit", ply ) + umsg.End() + +end + +function GM:PlayerDeathThink( ply ) + + if ply.NextSpawn and ply.NextSpawn > CurTime() then return end + + if ply:KeyDown( IN_JUMP ) or ply:KeyDown( IN_ATTACK ) or ply:KeyDown( IN_ATTACK2 ) then + + ply:Spawn() + + end + +end + +function GM:DoPlayerDeath( ply, attacker, dmginfo ) + + ply:OnDeath() + + if ply:Team() == TEAM_ARMY then + + if team.NumPlayers( TEAM_ZOMBIES ) < 1 then + + ply:AddStat( "Martyr" ) + + end + + local music = table.Random( GAMEMODE.DeathMusic ) + + ply:ClientSound( music, 100 ) + ply:RadioSound( VO_DEATH ) + ply:SetTeam( TEAM_ZOMBIES ) + + if not GAMEMODE.LordExists and GAMEMODE.EarlyPick then + + GAMEMODE:PickLord( true ) + + end + + if IsValid( attacker ) and attacker:IsPlayer() and attacker != ply then + + attacker:AddZedDamage( 50 ) + + end + + elseif ply:Team() == TEAM_ZOMBIES then + + if IsValid( attacker ) and attacker:IsPlayer() then + + attacker:AddCash( GAMEMODE.PlayerZombieKillValue ) + attacker:AddFrags( 1 ) + + end + + if ply:IsLord() and ply:GetZedDamage() >= GAMEMODE.RedemptionDamage then + + ply:SetTeam( TEAM_ARMY ) + ply:Notice( "Prepare to respawn as a human", GAMEMODE.Colors.Blue, 5, 2 ) + + end + + end + + if dmginfo:IsExplosionDamage() then + + ply:SetModel( table.Random( GAMEMODE.Corpses ) ) + + local ed = EffectData() + ed:SetOrigin( ply:GetPos() ) + util.Effect( "gore_explosion", ed, true, true ) + + end + + ply:CreateRagdoll() + +end + +function GM:SynchStats() + + net.Start( "StatsSynch" ) + net.WriteInt( table.Count( player.GetAll() ), 8 ) + + for k,v in pairs( player.GetAll() ) do + + net.WriteEntity( v ) + net.WriteTable( v:GetStats() ) + + end + + net.Broadcast() + +end + +function GM:EndGame( winner ) + + GAMEMODE:SynchStats() + + SetGlobalBool( "GameOver", true ) + SetGlobalInt( "WinningTeam", winner ) + + for k,v in pairs( player.GetAll() ) do + + if winner == TEAM_ZOMBIES then + + v:NoticeOnce( "The undead have overwhelmed " .. team.GetName( TEAM_ARMY ) , GAMEMODE.Colors.White, 7, 2 ) + + elseif team.NumPlayers( TEAM_ARMY ) > 0 then + + v:NoticeOnce( team.GetName( TEAM_ARMY ) .. " has successfully evacuated", GAMEMODE.Colors.White, 7, 2 ) + + end + + if v:Team() == winner and winner == TEAM_ARMY then + + local music = table.Random( GAMEMODE.WinMusic ) + + v:ClientSound( music, 100 ) + v:GodEnable() + + else + + local music = table.Random( GAMEMODE.LoseMusic ) + + v:ClientSound( music, 100 ) + + end + + v:NoticeOnce( "Next map: " .. game.GetMapNext() , GAMEMODE.Colors.White, 7, 4 ) + + end + + timer.Simple( GetConVar( "sv_redead_post_game_time" ):GetInt(), function() game.LoadNextMap() end ) + +end + +function GM:CheckGameOver( canend ) + + if GetGlobalBool( "GameOver", false ) then return end + + if team.NumPlayers( TEAM_ARMY ) < 1 and team.NumPlayers( TEAM_ZOMBIES ) > 0 then + + GAMEMODE:EndGame( TEAM_ZOMBIES ) + + elseif GAMEMODE.Wave > #GAMEMODE.Waves and canend then + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + if not v:IsEvacuated() then + + v:Notice( "The evac chopper left without you", GAMEMODE.Colors.Red, 5 ) + v:SetTeam( TEAM_ZOMBIES ) + + end + + end + + GAMEMODE:EndGame( TEAM_ARMY ) + + end + +end + +function GM:ShowHelp( ply ) + + ply:SendLua( "GAMEMODE:ShowHelp()" ) + +end + +function GM:ShowTeam( ply ) + + if ply:Team() == TEAM_ZOMBIES then + + ply:SendLua( "GAMEMODE:ShowZombieClasses()" ) + + return + + end + + if not ply:Alive() then return end + + if ply:IsIndoors() then + + ply:Notice( "You cannot use your radio indoors", GAMEMODE.Colors.Red ) + + else + + if ply:GetPlayerClass() == CLASS_SPECIALIST then + + if IsValid( ply.Stash ) then + + GAMEMODE.SpecialTrader:OnExit( ply ) + + else + + if GAMEMODE.RadioBlock and GAMEMODE.RadioBlock > CurTime() then + + ply:Notice( "Radio communications are offline", GAMEMODE.Colors.Red ) + return + + end + + GAMEMODE.SpecialTrader:OnUsed( ply ) + + end + + else + + if IsValid( ply.Stash ) then + + GAMEMODE.Trader:OnExit( ply ) + + else + + if GAMEMODE.RadioBlock and GAMEMODE.RadioBlock > CurTime() then + + ply:Notice( "Radio communications are offline", GAMEMODE.Colors.Red ) + return + + end + + GAMEMODE.Trader:OnUsed( ply ) + + end + + end + + end + +end + +function GM:ShowSpare1( ply ) + + GAMEMODE:PanicButton( ply ) + +end + +function GM:ShowSpare2( ply ) + + GAMEMODE:AddToZombieList( ply ) + +end + +function GM:PanicButton( ply ) + + if ( ply.Panic or 0 ) > CurTime() or ply:Team() == TEAM_ZOMBIES then return end + + ply.Panic = CurTime() + 0.5 + + local panic = { { ply:IsBleeding(), { "Bandage" }, "bleeding" }, + { ply:GetRadiation() > 0, { "Vodka", "Moonshine Vodka", "Anti-Rad" }, "irradiated" }, + { ply:Health() < 50, { "Advanced Medikit", "Basic Medikit", "Canned Food" }, "severely wounded" }, + { ply:Health() < 100, { "Basic Medikit", "Canned Food" }, "wounded" }, + { ply:GetStamina() < 100, { "Energy Drink" }, "fatigued" }, + { ply:GetStamina() < 100, { "Water" }, "fatigued" } } + + for k,v in pairs( panic ) do + + if v[1] then + + for c,d in pairs( v[2] ) do + + local tbl = item.GetByName( d ) + + if tbl and ply:HasItem( tbl.ID ) then + + tbl.Functions[ 1 ]( ply, tbl.ID ) + + ply:Notice( "Panic button detected that you were " .. v[3], GAMEMODE.Colors.Blue ) + + return + + end + + end + + end + + end + + ply:Notice( "Panic button did not detect any usable items", GAMEMODE.Colors.Red ) + ply:ClientSound( "items/suitchargeno1.wav" ) + +end + +function DropItem( ply, cmd, args ) + + local id = tonumber( args[1] ) + local count = math.Clamp( tonumber( args[2] ), 1, 100 ) + + if not ply:HasItem( id ) then return end + + local tbl = item.GetByID( id ) + + if count == 1 then + + if ply:HasItem( id ) then + + local makeprop = true + + if tbl.DropFunction then + + makeprop = tbl.DropFunction( ply, id, true ) + + end + + if makeprop then + + local prop = ents.Create( "prop_physics" ) + prop:SetPos( ply:GetItemDropPos() ) + prop:SetAngles( ply:GetAimVector():Angle() ) + + if tbl.DropModel then + + prop:SetModel( tbl.DropModel ) + + else + + prop:SetModel( tbl.Model ) + + end + + prop:SetCollisionGroup( COLLISION_GROUP_WEAPON ) + prop:Spawn() + prop.IsItem = true + prop.Removal = CurTime() + 5 * 60 + + end + + ply:RemoveFromInventory( id, true ) + ply:EmitSound( Sound( "items/ammopickup.wav" ) ) + + end + + return + + end + + local itemcount = math.min( ply:GetItemCount( id ), count ) + local loot = ents.Create( "sent_lootbag" ) + + for i=1, itemcount do + + loot:AddItem( id ) + + end + + loot:SetAngles( ply:GetAimVector():Angle() ) + loot:SetPos( ply:GetItemDropPos() ) + loot:SetRemoval( 60 * 5 ) + loot:Spawn() + //loot:SetUser( ply ) + + ply:EmitSound( Sound( "items/ammopickup.wav" ) ) + ply:RemoveMultipleFromInventory( loot:GetItems() ) + + if tbl.DropFunction then + + tbl.DropFunction( ply, id ) + + end + +end + +concommand.Add( "inv_drop", DropItem ) + +function UseItem( ply, cmd, args ) + + local id = tonumber( args[1] ) + local pos = tonumber( args[2] ) + + if ply:HasItem( id ) then + + local tbl = item.GetByID( id ) + + if not tbl.Functions[pos] then return end + + tbl.Functions[pos]( ply, id ) + + end + +end + +concommand.Add( "inv_action", UseItem ) + +function TakeItem( ply, cmd, args ) + + local id = tonumber( args[1] ) + local count = math.Clamp( tonumber( args[2] ), 1, 100 ) + + if not IsValid( ply.Stash ) or not table.HasValue( ply.Stash:GetItems(), id ) or string.find( ply.Stash:GetClass(), "npc" ) then return end + + local tbl = item.GetByID( id ) + + if count == 1 then + + ply:AddIDToInventory( id ) + ply.Stash:RemoveItem( id ) + + return + + end + + local items = {} + + if IsValid( ply.Stash ) then + + for i=1, count do + + if table.HasValue( ply.Stash:GetItems(), id ) then + + table.insert( items, id ) + ply.Stash:RemoveItem( id ) + + end + + end + + ply:AddMultipleToInventory( items ) + ply:EmitSound( Sound( "items/itempickup.wav" ) ) + + end + +end + +concommand.Add( "inv_take", TakeItem ) + +function StoreItem( ply, cmd, args ) + + local id = tonumber( args[1] ) + local count = math.Clamp( tonumber( args[2] ), 1, 100 ) + + if not IsValid( ply.Stash ) or not ply:HasItem( id ) then return end + + local tbl = item.GetByID( id ) + + if count == 1 then + + ply.Stash:AddItem( id ) + + ply:RemoveFromInventory( id ) + ply:EmitSound( Sound( "c4.disarmfinish" ) ) + + if tbl.DropFunction then + + tbl.DropFunction( ply, id ) + + end + + return + + end + + local items = {} + + for i=1, count do + + if ply:HasItem( id ) then + + table.insert( items, id ) + ply.Stash:AddItem( id ) + + end + + end + + ply:RemoveMultipleFromInventory( items ) + ply:EmitSound( Sound( "c4.disarmfinish" ) ) + + if tbl.DropFunction then + + tbl.DropFunction( ply, id ) + + end + +end + +concommand.Add( "inv_store", StoreItem ) + +function SellbackItem( ply, cmd, args ) + + if not IsValid( ply ) then return end + + local id = tonumber( args[1] ) + + if not table.HasValue( ply:GetShipment(), id ) then return end + + local tbl = item.GetByID( id ) + + ply:AddCash( tbl.Price ) + ply:RemoveFromShipment( id ) + +end + +concommand.Add( "inv_refund", SellbackItem ) + +function OrderShipment( ply, cmd, args ) + + ply:SendShipment() + +end + +concommand.Add( "ordershipment", OrderShipment ) + +function BuyItem( ply, cmd, args ) + + local id = tonumber( args[1] ) + local count = tonumber( args[2] ) + + if not IsValid( ply.Stash ) or not ply.Stash:GetClass() == "info_trader" or not table.HasValue( ply.Stash:GetItems(), id ) or count < 0 then return end + + local tbl = item.GetByID( id ) + + if tbl.Price > ply:GetCash() then + + return + + end + + if tbl.Price > ply:GetStat( "Pricey" ) then + + ply:SetStat( "Pricey", tbl.Price ) + + end + + if count == 1 then + + ply:AddToShipment( { id } ) + ply:AddCash( -tbl.Price ) + + return + + end + + if ( tbl.Price * count ) > ply:GetCash() then + + return + + end + + local items = {} + + for i=1, count do + + table.insert( items, id ) + + end + + ply:AddToShipment( items ) + ply:AddCash( -tbl.Price * count ) + +end + +concommand.Add( "inv_buy", BuyItem ) + +function DropCash( ply, cmd, args ) + + local amt = tonumber( args[1] ) + + if amt > ply:GetCash() or amt < 5 then return end + + ply:AddCash( -amt ) + + local money = ents.Create( "sent_cash" ) + money:SetPos( ply:GetItemDropPos() ) + money:Spawn() + money:SetCash( amt ) + +end + +concommand.Add( "cash_drop", DropCash ) + +function StashCash( ply, cmd, args ) + + local amt = tonumber( args[1] ) + + if not IsValid( ply.Stash ) or amt > ply:GetCash() or amt < 5 or string.find( ply.Stash:GetClass(), "npc" ) then return end + + ply:AddCash( -amt ) + ply:SynchCash( ply.Stash:GetCash() + amt ) + ply.Stash:SetCash( ply.Stash:GetCash() + amt ) + +end + +concommand.Add( "cash_stash", StashCash ) + +function TakeCash( ply, cmd, args ) + + local amt = tonumber( args[1] ) + + if not IsValid( ply.Stash ) or amt > ply.Stash:GetCash() or amt < 5 or string.find( ply.Stash:GetClass(), "npc" ) then return end + + ply:AddCash( amt ) + ply:SynchCash( ply.Stash:GetCash() - amt ) + ply.Stash:SetCash( ply.Stash:GetCash() - amt ) + +end + +concommand.Add( "cash_take", TakeCash ) + +function SetPlyClass( ply, cmd, args ) + + local class = tonumber( args[1] ) + + if not GAMEMODE.ClassLogos[ class ] then return end + + if ply:Team() == TEAM_ARMY then return end + + if ply:Team() == TEAM_ZOMBIES then + + ply.NextClass = class + + else + + ply:SetPlayerClass( class ) + + end + +end + +concommand.Add( "changeclass", SetPlyClass ) + +function SaveGameItems( ply, cmd, args ) + + if ( !ply:IsAdmin() or !ply:IsSuperAdmin() ) then return end + + GAMEMODE:SaveAllEnts() + +end + +concommand.Add( "sv_redead_save_map_config", SaveGameItems ) + +function MapSetupMode( ply, cmd, args ) + + if not IsValid( ply ) then + + for k, ply in pairs( player.GetAll() ) do + + if ply:IsAdmin() or ply:IsSuperAdmin() then + + ply:Give( "rad_itemplacer" ) + ply:Give( "rad_propplacer" ) + ply:Give( "weapon_physgun" ) + + end + + end + + return + + end + + if ply:IsAdmin() or ply:IsSuperAdmin() then + + ply:Give( "rad_itemplacer" ) + ply:Give( "rad_propplacer" ) + ply:Give( "weapon_physgun" ) + ply:AddCash( 500 ) + + end + +end + +concommand.Add( "sv_redead_dev_mode", MapSetupMode ) + +function ItemListing( ply, cmd, args ) + + if IsValid( ply ) and ply:IsAdmin() then + + local itemlist = item.GetList() + + for k,v in pairs( itemlist ) do + + print( v.ID .. ": " .. v.Name ) + + end + + end + +end + +concommand.Add( "sv_redead_dev_itemlist", ItemListing ) + +function TestItem( ply, cmd, args ) + + if IsValid( ply ) and ply:IsAdmin() then + + local id = tonumber( args[1] ) + local tbl = item.GetByID( id ) + + if tbl then + + ply:AddIDToInventory( id ) + + end + + end + +end + +concommand.Add( "sv_redead_dev_give", TestItem ) diff --git a/gamemode/items.lua b/gamemode/items.lua new file mode 100644 index 0000000..7b3a057 --- /dev/null +++ b/gamemode/items.lua @@ -0,0 +1,116 @@ + +module( "item", package.seeall ) + +local ItemTables = {} +local ID = 1 + +function Register( tbl ) + + tbl.Functions = tbl.Functions or {} + tbl.ID = ID + ItemTables[ ID ] = tbl + + util.PrecacheModel( tbl.Model ) + + ID = ID + 1 + +end + +function GetList() + + return ItemTables + +end + +function GetByID( id ) + + if not id then return end + + if !ItemTables[ id ] then return end + + return ItemTables[ id ] + +end + +function GetByModel( model ) + + for k,v in pairs( ItemTables ) do + + if string.lower( v.Model ) == string.lower( model ) or ( v.DropModel and string.lower( v.DropModel ) == string.lower( model ) ) then + + return v + + end + + end + +end + +function GetByClass( class ) + + for k,v in pairs( ItemTables ) do + + if v.TypeOverride and string.lower( v.TypeOverride ) == string.lower( class ) then + + return v + + end + + end + +end + +function GetByName( name ) + + for k,v in pairs( ItemTables ) do + + if string.lower( v.Name ) == string.lower( name ) then + + return v + + end + + end + +end + +function GetByType( itemtype ) + + local tbl = {} + + for k,v in pairs( ItemTables ) do + + if v.Type == itemtype then + + table.insert( tbl, v ) + + end + + end + + return tbl + +end + +function RandomItem( itemtype ) + + if not itemtype then return table.Random( ItemTables ) end + + local tbl = GetByType( itemtype ) + local rand = table.Random( tbl ) + + while math.Rand(0,1) < rand.Rarity do + + rand = table.Random( tbl ) + + end + + return rand + +end + + + + + + diff --git a/gamemode/items/ammo.lua b/gamemode/items/ammo.lua new file mode 100644 index 0000000..a554382 --- /dev/null +++ b/gamemode/items/ammo.lua @@ -0,0 +1,138 @@ + +// This is the ID given to any item that is ammunition +ITEM_AMMO = 4 + +// ammo constant +PRICE_PISTOL = 5 +PRICE_BUCKSHOT = 8 +PRICE_SMGROUNDS = 5 +PRICE_RIFLEROUNDS = 10 +PRICE_SNIPERROUNDS = 10 +PRICE_ENERGYCELL = 8 + +function FUNC_AMMO( ply, id ) + + local tbl = item.GetByID( id ) + + if not tbl.Ammo then return true end + + ply:AddAmmo( tbl.Ammo, tbl.Amount ) + + return true + +end + +function FUNC_DROPAMMO( ply, id, drop ) + + local tbl = item.GetByID( id ) + + if not tbl.Ammo then return end + + ply:AddAmmo( tbl.Ammo, -tbl.Amount, true ) + + return true // we don't want to override spawning the prop + +end + +item.Register( { + Name = "Pistol Rounds", + Description = "40 pistol rounds per box.", + Stackable = true, + Type = ITEM_AMMO, + Weight = 0.75, + Price = PRICE_PISTOL, + Rarity = 0.20, + Model = "models/items/357ammo.mdl", + Ammo = "Pistol", + Amount = 40, + PickupFunction = FUNC_AMMO, + DropFunction = FUNC_DROPAMMO, + CamPos = Vector(14,13,4), + CamOrigin = Vector(0,0,3) +} ) + +item.Register( { + Name = "Buckshot", + Description = "20 shotgun rounds per box.", + Stackable = true, + Type = ITEM_AMMO, + Weight = 0.75, + Price = PRICE_BUCKSHOT, + Rarity = 0.20, + Model = "models/items/boxbuckshot.mdl", + Ammo = "Buckshot", + Amount = 20, + PickupFunction = FUNC_AMMO, + DropFunction = FUNC_DROPAMMO, + CamPos = Vector(21,15,8), + CamOrigin = Vector(0,0,4) +} ) + +item.Register( { + Name = "SMG Rounds", + Description = "60 SMG rounds per box.", + Stackable = true, + Type = ITEM_AMMO, + Weight = 0.75, + Price = PRICE_SMGROUNDS, + Rarity = 0.50, + Model = "models/items/boxsrounds.mdl", + Ammo = "SMG", + Amount = 60, + PickupFunction = FUNC_AMMO, + DropFunction = FUNC_DROPAMMO, + CamPos = Vector(27,15,10), + CamOrigin = Vector(0,0,4) +} ) + +item.Register( { + Name = "Rifle Rounds", + Description = "60 automatic rifle rounds per box.", + Stackable = true, + Type = ITEM_AMMO, + Weight = 0.75, + Price = PRICE_RIFLEROUNDS, + Rarity = 0.80, + Model = "models/items/boxmrounds.mdl", + Ammo = "Rifle", + Amount = 60, + PickupFunction = FUNC_AMMO, + DropFunction = FUNC_DROPAMMO, + CamPos = Vector(29,22,10), + CamOrigin = Vector(0,0,5) +} ) + +item.Register( { + Name = "Sniper Rounds", + Description = "30 sniper rounds per box.", + Stackable = true, + Type = ITEM_AMMO, + Weight = 0.75, + Price = PRICE_SNIPERROUNDS, + Rarity = 0.75, + Model = "models/items/boxqrounds.mdl", + Ammo = "Sniper", + Amount = 30, + PickupFunction = FUNC_AMMO, + DropFunction = FUNC_DROPAMMO, + CamPos = Vector(-18,-14,8), + CamOrigin = Vector(4,0,-1) +} ) + +item.Register( { + Name = "Prototype Energy Cell", + Description = "15 energy charges per cell.", + Stackable = true, + Type = ITEM_AMMO, + Weight = 1.25, + Price = PRICE_ENERGYCELL, + Rarity = 0.85, + Model = "models/items/battery.mdl", + Ammo = "Prototype", + Amount = 15, + PickupFunction = FUNC_AMMO, + DropFunction = FUNC_DROPAMMO, + CamPos = Vector(15,15,8), + CamOrigin = Vector(0,0,5) +} ) + diff --git a/gamemode/items/misc.lua b/gamemode/items/misc.lua new file mode 100644 index 0000000..b15db67 --- /dev/null +++ b/gamemode/items/misc.lua @@ -0,0 +1,546 @@ + +// This is the ID given to any item that doesnt fit in any other category - feel free to add your own items here +ITEM_MISC = 5 // Can be found in stores or in loot +ITEM_BUYABLE = 6 // Only found in stores +ITEM_LOOT = 7 // Only found in loot +ITEM_QUEST_ZOMBIE = 421 // obsolete? + +function FUNC_DRINK( ply, id, client, icon ) + + if icon then return "icon16/cup.png" end + if client then return "Drink" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( table.Random{ "npc/barnacle/barnacle_gulp1.wav", "npc/barnacle/barnacle_gulp2.wav" }, 100, math.random( 90, 110 ) ) + ply:AddHealth( 15 ) + ply:AddStamina( 25 ) + ply:Notice( "+15 Health", GAMEMODE.Colors.Green ) + ply:Notice( "+25 Stamina", GAMEMODE.Colors.Green ) + +end + +function FUNC_EAT( ply, id, client, icon ) + + if icon then return "icon16/cake.png" end + if client then return "Eat" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( "npc/barnacle/barnacle_crunch2.wav", 100, math.random( 90, 110 ) ) + ply:AddHealth( 25 ) + ply:AddStamina( 15 ) + ply:Notice( "+25 Health", GAMEMODE.Colors.Green ) + ply:Notice( "+15 Stamina", GAMEMODE.Colors.Green ) + +end + +function FUNC_BOOZE( ply, id, client, icon ) + + if icon then return "icon16/drink.png" end + if client then return "Drink" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( table.Random{ "npc/barnacle/barnacle_gulp1.wav", "npc/barnacle/barnacle_gulp2.wav" }, 100, math.random( 90, 110 ) ) + ply:AddRadiation( -2 ) + ply:AddStamina( 20 ) + ply:Notice( "+20 Stamina", GAMEMODE.Colors.Green ) + ply:Notice( "-2 Radiation", GAMEMODE.Colors.Green ) + ply:Notice( "+4 Intoxication", GAMEMODE.Colors.Red ) + + umsg.Start( "Drunk", ply ) + umsg.Short( 4 ) + umsg.End() + +end + +function FUNC_MOONSHINE( ply, id, client, icon ) + + if icon then return "icon16/drink.png" end + if client then return "Drink" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( table.Random{ "npc/barnacle/barnacle_gulp1.wav", "npc/barnacle/barnacle_gulp2.wav" }, 100, math.random( 90, 110 ) ) + ply:AddRadiation( -1 ) + ply:Notice( "-1 Radiation", GAMEMODE.Colors.Green ) + ply:Notice( "+6 Intoxication", GAMEMODE.Colors.Red ) + + umsg.Start( "Drunk", ply ) + umsg.Short( 6 ) + umsg.End() + +end + +function FUNC_BEER( ply, id, client, icon ) + + if icon then return "icon16/drink.png" end + if client then return "Drink" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( table.Random{ "npc/barnacle/barnacle_gulp1.wav", "npc/barnacle/barnacle_gulp2.wav" }, 100, math.random( 90, 110 ) ) + ply:AddStamina( 15 ) + ply:Notice( "+15 Stamina", GAMEMODE.Colors.Green ) + ply:Notice( "+2 Intoxication", GAMEMODE.Colors.Red ) + + umsg.Start( "Drunk", ply ) + umsg.Short( 2 ) + umsg.End() + +end + +function FUNC_SPACEBEER( ply, id, client, icon ) + + if icon then return "icon16/drink.png" end + if client then return "Drink" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( table.Random{ "npc/barnacle/barnacle_gulp1.wav", "npc/barnacle/barnacle_gulp2.wav" }, 100, math.random( 90, 110 ) ) + ply:Notice( "+15 Intoxication", GAMEMODE.Colors.Red ) + + umsg.Start( "Drunk", ply ) + umsg.Short( 15 ) + umsg.End() + +end + +function FUNC_UNMUTAGEN( ply, id, client, icon ) + + if icon then return "icon16/pill.png" end + if client then return "Inject" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( "Weapon_SMG1.Special1" ) + + local tbl = {} + local inc = 0 + + for i=1,math.random(1,3) do + + local rand = math.random(1,6) + + while table.HasValue( tbl, rand ) do + + rand = math.random(1,6) + + end + + table.insert( tbl, rand ) + + if rand == 1 then + + ply:Notice( "You feel extremely nauseous", GAMEMODE.Colors.Red, 5, inc * 2 ) + + umsg.Start( "Drunk", ply ) + umsg.Short( 20 ) + umsg.End() + + elseif rand == 2 then + + local rad = math.random(2,5) + + if math.random(1,2) == 1 then + + ply:Notice( "+" .. rad .. " Radiation", GAMEMODE.Colors.Red, 5, inc * 2 ) + ply:AddRadiation( rad ) + + else + + ply:Notice( "-" .. rad .. " Radiation", GAMEMODE.Colors.Green, 5, inc * 2 ) + ply:AddRadiation( -rad ) + + end + + elseif rand == 3 then + + if ply:IsInfected() then + + ply:Notice( "Your infection has been cured", GAMEMODE.Colors.Green, 5, inc * 2 ) + ply:SetInfected( false ) + + else + + ply:Notice( "You were infected by the drug", GAMEMODE.Colors.Red, 5, inc * 2 ) + ply:SetInfected( true ) + + end + + elseif rand == 4 then + + if math.random(1,2) == 1 then + + ply:Notice( "You feel exhausted", GAMEMODE.Colors.Red, 5, inc * 2 ) + ply:AddStamina( -50 ) + + else + + ply:Notice( "+20 Stamina", GAMEMODE.Colors.Green, 5, inc * 2 ) + ply:AddStamina( 20 ) + + end + + elseif rand == 5 then + + ply:Notice( "Your whole body aches", GAMEMODE.Colors.Red, 5, inc * 2 ) + + local dmg = math.random(1,5) + + ply:AddHealth( dmg * -10 ) + + if math.random(1,20) == 1 then + + local dietime = math.random( 30, 120 ) + + timer.Simple( dietime - 5, function() ply:Notice( "You feel a sharp pain in your chest", GAMEMODE.Colors.Red, 5 ) end ) + timer.Simple( dietime, function() ply:Kill() end ) + + end + + elseif rand == 6 then + + ply:Notice( "Your legs begin to feel weak", GAMEMODE.Colors.Red, 5, inc * 2 ) + ply:SetWalkSpeed( GAMEMODE.WalkSpeed - 80 ) + ply:SetRunSpeed( GAMEMODE.RunSpeed - 80 ) + + local legtime = math.random( 20, 60 ) + + timer.Simple( legtime - 5, function() if IsValid( ply ) and ply:Team() == TEAM_ARMY then ply:Notice( "Your legs start to feel better", GAMEMODE.Colors.Green, 5 ) end end ) + timer.Simple( legtime, function() if IsValid( ply ) and ply:Team() == TEAM_ARMY then ply:SetWalkSpeed( GAMEMODE.WalkSpeed ) ply:SetRunSpeed( GAMEMODE.RunSpeed ) end end ) + + end + + inc = inc + 1 + + end + +end + +function FUNC_WRENCH( ply, id, client, icon ) + + if icon then return "icon16/cake.png" end + if client then return "Eat" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( "npc/barnacle/barnacle_crunch2.wav", 100, math.random( 90, 110 ) ) + ply:EmitSound( "weapons/crowbar/crowbar_impact2.wav", 100, math.random( 90, 110 ) ) + ply:TakeDamage( 20 ) + ply:Notice( "-20 Health", GAMEMODE.Colors.Red ) + ply:Notice( "You just ate a fucking wrench", GAMEMODE.Colors.Red ) + +end + +function FUNC_OPENSUITCASE( ply, id ) + + ply:Notice( "You found some " .. GAMEMODE.CurrencyName .. "s", GAMEMODE.Colors.Green ) + ply:EmitSound( Sound( "Chain.ImpactSoft" ) ) + + if math.random(1,10) == 1 then + + ply:AddCash( math.random(5,50) ) + + else + + ply:AddCash( math.random(2,10) ) + + end + + return false + +end + +function FUNC_OPENBOX( ply, id ) + + local tbl = { ITEM_SUPPLY, ITEM_AMMO, ITEM_MISC, ITEM_SPECIAL, ITEM_WPN_COMMON, ITEM_WPN_SPECIAL } + local chancetbl = { 0.60, 0.20, 0.50, 0.20, 0.05, 0.03 } + + local rnd = math.Rand(0,1) + local choice = math.random( 1, table.Count( tbl ) ) + + while rnd > chancetbl[ choice ] do + + rnd = math.Rand(0,1) + choice = math.random( 1, table.Count( tbl ) ) + + end + + local rand = item.RandomItem( tbl[choice] ) + + ply:AddIDToInventory( rand.ID ) + ply:EmitSound( "Cardboard.Break" ) + + return false + +end + +item.Register( { + Name = "Cardboard Box", + CollisionOverride = true, + Type = ITEM_LOOT, + Rarity = 0.95, + Model = "models/props_junk/cardboard_box001a.mdl", + PickupFunction = FUNC_OPENBOX, + Functions = {} +} ) + +item.Register( { + Name = "Cardboard Box", + CollisionOverride = true, + Type = ITEM_LOOT, + Rarity = 0.95, + Model = "models/props_junk/cardboard_box001b.mdl", + PickupFunction = FUNC_OPENBOX, + Functions = {} +} ) + +item.Register( { + Name = "Cardboard Box", + CollisionOverride = true, + Type = ITEM_LOOT, + Rarity = 0.95, + Model = "models/props_junk/cardboard_box002a.mdl", + PickupFunction = FUNC_OPENBOX, + Functions = {} +} ) + +item.Register( { + Name = "Cardboard Box", + CollisionOverride = true, + Type = ITEM_LOOT, + Rarity = 0.95, + Model = "models/props_junk/cardboard_box002b.mdl", + PickupFunction = FUNC_OPENBOX, + Functions = {} +} ) + +item.Register( { + Name = "Cardboard Box", + CollisionOverride = true, + Type = ITEM_LOOT, + Rarity = 0.95, + Model = "models/props_junk/cardboard_box003a.mdl", + PickupFunction = FUNC_OPENBOX, + Functions = {} +} ) + +item.Register( { + Name = "Cardboard Box", + CollisionOverride = true, + Type = ITEM_LOOT, + Rarity = 0.95, + Model = "models/props_junk/cardboard_box003b.mdl", + PickupFunction = FUNC_OPENBOX, + Functions = {} +} ) + +item.Register( { + Name = "Suitcase", + CollisionOverride = true, + Type = ITEM_LOOT, + Rarity = 0.50, + Model = "models/props_c17/suitcase_passenger_physics.mdl", + PickupFunction = FUNC_OPENSUITCASE, + Functions = {} +} ) + +item.Register( { + Name = "Briefcase", + CollisionOverride = true, + Type = ITEM_LOOT, + Rarity = 0.50, + Model = "models/props_c17/briefcase001a.mdl", + PickupFunction = FUNC_OPENSUITCASE, + Functions = {} +} ) + +item.Register( { + Name = "Wood", + Description = "Used in building barricades.", + Stackable = true, + Type = ITEM_MISC, + Weight = 1.50, + Price = 15, + Rarity = 0.15, + Model = "models/props_debris/wood_chunk04a.mdl", + Functions = {}, + CamPos = Vector(42,15,0), + CamOrigin = Vector(0,0,-1) +} ) + +item.Register( { + Name = "Water", + Description = "Restores 25 stamina and 10 health.", + Stackable = true, + Type = ITEM_MISC, + Weight = 0.15, + Price = 3, + Rarity = 0.05, + Model = "models/props/cs_office/water_bottle.mdl", + Functions = { FUNC_DRINK }, + CamPos = Vector(12,12,1), + CamOrigin = Vector(0,0,0) +} ) + +item.Register( { + Name = "Canned Food", + Description = "Restores 25 health and 10 stamina.", + Stackable = true, + Type = ITEM_MISC, + Weight = 0.15, + Price = 3, + Rarity = 0.05, + Model = "models/props_junk/garbage_metalcan001a.mdl", + Functions = { FUNC_EAT }, + CamPos = Vector(10,10,0), + CamOrigin = Vector(0,0,0) +} ) + +item.Register( { + Name = "Wrench", + Description = "Why would you eat this?", + Stackable = true, + Type = ITEM_LOOT, + Weight = 0.15, + Price = 3, + Rarity = 0.99, + Model = "models/props_c17/tools_wrench01a.mdl", + Functions = { FUNC_WRENCH }, + CamPos = Vector(0,0,29), + CamOrigin = Vector(0,1,4) +} ) + +item.Register( { + Name = "Unstable Mutagen", + Description = "Prototype drug which may cure the infection.", + Stackable = true, + Type = ITEM_LOOT, + Weight = 0.30, + Price = 50, + Rarity = 0.95, + Model = "models/healthvial.mdl", + Functions = { FUNC_UNMUTAGEN }, + CamPos = Vector(-16,0,8), + CamOrigin = Vector(0,0,5) +} ) + +item.Register( { + Name = "Beer", + Description = "Restores 15 stamina.", + Stackable = true, + Type = ITEM_LOOT, + Weight = 0.30, + Price = 5, + Rarity = 0.30, + Model = "models/props_junk/glassbottle01a.mdl", + Functions = { FUNC_BEER }, + CamPos = Vector(16,12,1), + CamOrigin = Vector(0,0,0) +} ) + +item.Register( { + Name = "Tequila", + Description = "Don't drink this shit.", + Stackable = true, + Type = ITEM_LOOT, + Weight = 0.30, + Price = 5, + Rarity = 0.85, + Model = "models/props_junk/glassjug01.mdl", + Functions = { FUNC_SPACEBEER }, + CamPos = Vector(19,0,6), + CamOrigin = Vector(0,0,5) +} ) + +item.Register( { + Name = "Vodka", + Description = "Releives radiation poisoning.", + Stackable = true, + Type = ITEM_MISC, + Weight = 0.30, + Price = 10, + Rarity = 0.10, + Model = "models/props_junk/garbage_glassbottle002a.mdl", + Functions = { FUNC_BOOZE }, + CamPos = Vector(15,19,4), + CamOrigin = Vector(0,0,0) +} ) + +item.Register( { + Name = "Moonshine Vodka", + Description = "Weaker homebrewed vodka.", + Stackable = true, + Type = ITEM_BUYABLE, + Weight = 0.30, + Price = 5, + Rarity = 0.25, + Model = "models/props_junk/garbage_glassbottle003a.mdl", + Functions = { FUNC_MOONSHINE }, + CamPos = Vector(16,17,1), + CamOrigin = Vector(0,0,-1) +} ) + +--[[item.Register( { + Name = "Human Skull", + Description = "This human skull looks pretty old. You decided to name it Murray.", + Stackable = true, + Type = ITEM_QUEST_ZOMBIE, + Weight = 2.50, + Price = 1, + Rarity = 0.75, + Model = "models/gibs/hgibs.mdl", + Functions = { }, + CamPos = Vector(15,10,0), + CamOrigin = Vector(0,0,2) +} ) + +item.Register( { + Name = "Zombie Claw", + Description = "This is the claw of a zombie.", + Stackable = true, + Type = ITEM_QUEST_ZOMBIE, + Weight = 2.50, + Price = 1, + Rarity = 0.25, + Model = "models/gibs/antlion_gib_small_1.mdl", + Functions = { }, + CamPos = Vector(10,15,5), + CamOrigin = Vector(0,0,1) +} ) + +item.Register( { + Name = "Zombie Spine", + Description = "This is the spine of a zombie.", + Stackable = true, + Type = ITEM_QUEST_ZOMBIE, + Weight = 2.50, + Price = 1, + Rarity = 0.25, + Model = "models/gibs/HGIBS_spine.mdl", + Functions = { }, + CamPos = Vector(15,15,5), + CamOrigin = Vector(0,0,2) +} ) + +item.Register( { + Name = "Zombie Rib", + Description = "This is the rib of a zombie.", + Stackable = true, + Type = ITEM_QUEST_ZOMBIE, + Weight = 2.50, + Price = 1, + Rarity = 0.25, + Model = "models/gibs/HGIBS_rib.mdl", + Functions = { }, + CamPos = Vector(10,15,3), + CamOrigin = Vector(0,0,0) +} ) + +item.Register( { + Name = "Zombie Flesh", + Description = "This is a chunk of zombie flesh.", + Stackable = true, + Type = ITEM_QUEST_ZOMBIE, + Weight = 2.50, + Price = 1, + Rarity = 0.25, + Model = "models/props_junk/watermelon01_chunk02a.mdl", + Functions = { }, + CamPos = Vector(8,8,5), + CamOrigin = Vector(0,0,2.5) +} )]] diff --git a/gamemode/items/misc_explosive.lua b/gamemode/items/misc_explosive.lua new file mode 100644 index 0000000..9584feb --- /dev/null +++ b/gamemode/items/misc_explosive.lua @@ -0,0 +1,114 @@ + +ITEM_EXPLOSIVE = 345 + +function FUNC_OXYGEN( ply, id, client, icon ) + + if icon then return "icon16/arrow_turn_right.png" end + if client then return "Throw" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( Sound( "WeaponFrag.Throw" ) ) + + local oxy = ents.Create( "sent_oxygen" ) + oxy:SetPos( ply:GetItemDropPos() ) + oxy:SetAngles( ply:GetAimVector():Angle() ) + oxy:Spawn() + +end + +function FUNC_DROPOXYGEN( ply, id, drop ) + + + if not drop then return end + + local oxy = ents.Create( "sent_oxygen" ) + oxy:SetSpeed( 10 ) + oxy:SetPos( ply:GetItemDropPos() ) + oxy:SetAngles( ply:GetAimVector():Angle() ) + oxy:Spawn() + + return false // override spawning a prop for this item + +end + +item.Register( { + Name = "Liquid Oxygen", + Description = "Highly explosive liquid oxygen.", + TypeOverride = "sent_oxygen", + Stackable = true, + Type = ITEM_EXPLOSIVE, + Weight = 1.50, + Price = 50, + Rarity = 0.95, + Model = "models/props_phx/misc/potato_launcher_explosive.mdl", + Functions = { FUNC_OXYGEN }, + DropFunction = FUNC_DROPOXYGEN, + CamPos = Vector(24,0,8), + CamOrigin = Vector(0,0,6) +} ) + +item.Register( { + Name = "Gasoline", + TypeOverride = "sent_fuel_gas", + AllowPickup = true, + CollisionOverride = true, + Type = ITEM_EXPLOSIVE, + Rarity = 0.50, + Model = "models/props_junk/gascan001a.mdl", + Functions = {} +} ) + +item.Register( { + Name = "Diesel Fuel", + TypeOverride = "sent_fuel_diesel", + AllowPickup = true, + CollisionOverride = true, + Type = ITEM_EXPLOSIVE, + Rarity = 0.50, + Model = "models/props_junk/metalgascan.mdl", + Functions = {} +} ) + +item.Register( { + Name = "Propane Canister", + TypeOverride = "sent_propane_canister", + AllowPickup = true, + CollisionOverride = true, + Type = ITEM_EXPLOSIVE, + Rarity = 0.50, + Model = "models/props_junk/propane_tank001a.mdl", + Functions = {} +} ) + +item.Register( { + Name = "Propane Tank", + TypeOverride = "sent_propane_tank", + AllowPickup = true, + CollisionOverride = true, + Type = ITEM_EXPLOSIVE, + Rarity = 0.50, + Model = "models/props_junk/propanecanister001a.mdl", + Functions = {} +} ) + +item.Register( { + Name = "Radioactive Waste", + TypeOverride = "sent_barrel_radioactive", + AllowPickup = true, + CollisionOverride = true, + Type = ITEM_EXPLOSIVE, + Rarity = 0.10, + Model = "models/props/de_train/barrel.mdl", + Functions = {} +} ) + +item.Register( { + Name = "Toxic Waste", + TypeOverride = "sent_barrel_biohazard", + AllowPickup = true, + CollisionOverride = true, + Type = ITEM_EXPLOSIVE, + Rarity = 0.10, + Model = "models/props/de_train/barrel.mdl", + Functions = {} +} ) diff --git a/gamemode/items/special.lua b/gamemode/items/special.lua new file mode 100644 index 0000000..8dbab7f --- /dev/null +++ b/gamemode/items/special.lua @@ -0,0 +1,83 @@ + +// This is the ID given to any item that is a SPECIALIST supply +ITEM_SPECIAL = 3 + +function FUNC_ANTIRAD( ply, id, client, icon ) + + if icon then return "icon16/pill.png" end + if client then return "Inject" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( "Weapon_SMG1.Special1" ) + ply:SetRadiation( 0 ) + ply:Notice( "-5 Radiation", GAMEMODE.Colors.Green ) + +end + +--[[function FUNC_FLARE( ply, id, client, icon ) + + if icon then return "icon16/lightbulb.png" end + if client then return "Ignite" end + + ply:RemoveFromInventory( id ) + + local prop = ents.Create( "sent_flare" ) + prop:SetPos( ply:GetItemDropPos() ) + prop:Spawn() + +end]] + +item.Register( { + Name = "Anti-Rad", + Description = "Releives all radiation poisoning.", + Stackable = true, + Type = ITEM_SPECIAL, + Weight = 0.15, + Price = 10, + Rarity = 0.20, + Model = "models/props_lab/jar01b.mdl", + Functions = { FUNC_ANTIRAD }, + CamPos = Vector(-17,-9,0), + CamOrigin = Vector(0,0,-1) +} ) + +item.Register( { + Name = "Respirator", + Description = "Filters out chemicals and radiation.", + Stackable = true, + Type = ITEM_SPECIAL, + Weight = 1.75, + Price = 40, + Rarity = 0.95, + Model = "models/items/combine_rifle_cartridge01.mdl", + CamPos = Vector(13,-14,0), + CamOrigin = Vector(0,0,-1) +} ) + +--[[item.Register( { + Name = "Sonar Module", + Description = "Improves your radar detection range.", + Stackable = true, + Type = ITEM_SPECIAL, + Weight = 0.75, + Price = 30, + Rarity = 0.90, + Model = "models/gibs/shield_scanner_gib1.mdl", + Functions = {}, + CamPos = Vector(2,-9,7), + CamOrigin = Vector(0,1,-1) +} ) + +item.Register( { + Name = "Flare", + Description = "Emits a bright red light.", + Stackable = true, + Type = ITEM_SPECIAL, + Weight = 0.35, + Price = 3, + Rarity = 0.10, + Model = "models/props_c17/trappropeller_lever.mdl", + Functions = { FUNC_FLARE }, + CamPos = Vector(15,6,5), + CamOrigin = Vector(0,0,0) +} )]]
\ No newline at end of file diff --git a/gamemode/items/supplies.lua b/gamemode/items/supplies.lua new file mode 100644 index 0000000..122c6a5 --- /dev/null +++ b/gamemode/items/supplies.lua @@ -0,0 +1,219 @@ + +// This is the ID given to any item that is an essential supply for every faction +ITEM_SUPPLY = 2 + +function FUNC_ENERGY( ply, id, client, icon ) + + if icon then return "icon16/cup.png" end + if client then return "Drink" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( table.Random{ "npc/barnacle/barnacle_gulp1.wav", "npc/barnacle/barnacle_gulp2.wav" }, 100, math.random( 90, 110 ) ) + ply:AddStamina( 50 ) + ply:Notice( "+50 Stamina", GAMEMODE.Colors.Green ) + +end + +function FUNC_HEAL( ply, id, client, icon ) + + if icon then return "icon16/heart.png" end + if client then return "Use" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( "HealthVial.Touch" ) + ply:AddHealth( 75 ) + ply:Notice( "+75 Health", GAMEMODE.Colors.Green ) + +end + +function FUNC_SUPERHEAL( ply, id, client, icon ) + + if icon then return "icon16/heart.png" end + if client then return "Use" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( "HealthVial.Touch" ) + ply:AddHealth( 150 ) + ply:Notice( "+150 Health", GAMEMODE.Colors.Green ) + +end + +function FUNC_BANDAGE( ply, id, client, icon ) + + if icon then return "icon16/heart.png" end + if client then return "Use" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( "Cardboard.Strain" ) + ply:SetBleeding( false ) + ply:AddHealth( 20 ) + ply:Notice( "+20 Health", GAMEMODE.Colors.Green ) + ply:Notice( "Stopped bleeding", GAMEMODE.Colors.Green ) + +end + +function FUNC_MUTAGEN( ply, id, client, icon ) + + if icon then return "icon16/pill.png" end + if client then return "Inject" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( "Weapon_SMG1.Special1" ) + + if ply:IsInfected() then + + ply:Notice( "Your infection has been cured", GAMEMODE.Colors.Green, 5, 0 ) + ply:SetInfected( false ) + + end + + local tbl = {} + local inc = 0 + + for i=1,math.random(1,3) do + + local rand = math.random(1,5) + + while table.HasValue( tbl, rand ) do + + rand = math.random(1,5) + + end + + table.insert( tbl, rand ) + + if rand == 1 then + + ply:Notice( "You feel extremely nauseous", GAMEMODE.Colors.Red, 5, inc * 2 ) + + umsg.Start( "Drunk", ply ) + umsg.Short( math.random( 10, 20 ) ) + umsg.End() + + elseif rand == 2 then + + local rad = math.random(2,5) + + if math.random(1,2) == 1 and ply:GetRadiation() < 1 then + + ply:Notice( "+" .. rad .. " Radiation", GAMEMODE.Colors.Red, 5, inc * 2 ) + ply:AddRadiation( rad ) + + else + + ply:Notice( "-" .. rad .. " Radiation", GAMEMODE.Colors.Green, 5, inc * 2 ) + ply:AddRadiation( -rad ) + + end + + elseif rand == 3 then + + ply:Notice( "Your whole body aches", GAMEMODE.Colors.Red, 5, inc * 2 ) + + local dmg = math.random(2,5) + + ply:AddHealth( dmg * -10 ) + + elseif rand == 4 then + + if math.random(1,2) == 1 then + + ply:Notice( "You feel exhausted", GAMEMODE.Colors.Red, 5, inc * 2 ) + ply:AddStamina( -50 ) + + else + + ply:Notice( "+20 Stamina", GAMEMODE.Colors.Green, 5, inc * 2 ) + ply:AddStamina( 20 ) + + end + + elseif rand == 5 then + + ply:Notice( "Your legs begin to feel weak", GAMEMODE.Colors.Red, 5, inc * 2 ) + ply:SetWalkSpeed( GAMEMODE.WalkSpeed - 80 ) + ply:SetRunSpeed( GAMEMODE.RunSpeed - 80 ) + + local legtime = math.random( 20, 40 ) + + timer.Simple( legtime - 5, function() if IsValid( ply ) and ply:Team() == TEAM_ARMY then ply:Notice( "Your legs start to feel better", GAMEMODE.Colors.Green, 5 ) end end ) + timer.Simple( legtime, function() if IsValid( ply ) and ply:Team() == TEAM_ARMY then ply:SetWalkSpeed( GAMEMODE.WalkSpeed ) ply:SetRunSpeed( GAMEMODE.RunSpeed ) end end ) + + end + + inc = inc + 1 + + end + +end + +item.Register( { + Name = "Energy Drink", + Description = "Restores 50 stamina.", + Stackable = true, + Type = ITEM_SUPPLY, + Weight = 0.25, + Price = 5, + Rarity = 0.25, + Model = "models/props_junk/popcan01a.mdl", + Functions = { FUNC_ENERGY }, + CamPos = Vector(10,10,0), + CamOrigin = Vector(0,0,0) +} ) + +item.Register( { + Name = "Basic Medikit", + Description = "Restores 50% of your health.", + Stackable = true, + Type = ITEM_SUPPLY, + Weight = 1.25, + Price = 10, + Rarity = 0.65, + Model = "models/radbox/healthpack.mdl", + Functions = { FUNC_HEAL }, + CamPos = Vector(23,8,3), + CamOrigin = Vector(0,0,-1) +} ) + +item.Register( { + Name = "Advanced Medikit", + Description = "Restores 100% of your health.", + Stackable = true, + Type = ITEM_SUPPLY, + Weight = 1.25, + Price = 20, + Rarity = 0.85, + Model = "models/radbox/healthpack2.mdl", + Functions = { FUNC_SUPERHEAL }, + CamPos = Vector(23,8,3), + CamOrigin = Vector(0,0,-1) +} ) + +item.Register( { + Name = "Alpha Mutagen", + Description = "Prototype drug which cures the infection.", + Stackable = true, + Type = ITEM_SUPPLY, + Weight = 1.25, + Price = 50, + Rarity = 0.95, + Model = "models/items/healthkit.mdl", + Functions = { FUNC_MUTAGEN }, + CamPos = Vector(0,0,35), + CamOrigin = Vector(4,0,0) +} ) + +item.Register( { + Name = "Bandage", + Description = "Stops all bleeding.", + Stackable = true, + Type = ITEM_SUPPLY, + Weight = 0.35, + Price = 5, + Rarity = 0.50, + Model = "models/radbox/bandage.mdl", + Functions = { FUNC_BANDAGE }, + CamPos = Vector(18,10,5), + CamOrigin = Vector(0,0,0) +} ) + diff --git a/gamemode/items/weapons_common.lua b/gamemode/items/weapons_common.lua new file mode 100644 index 0000000..a32f498 --- /dev/null +++ b/gamemode/items/weapons_common.lua @@ -0,0 +1,532 @@ + +// This is the ID given to any weapon item for all teams +ITEM_WPN_COMMON = 11 + +function FUNC_DROPWEAPON( ply, id, client, icon ) + + if icon then return "icon16/arrow_down.png" end + if client then return "Drop" end + + local tbl = item.GetByID( id ) + + local prop = ents.Create( "sent_droppedgun" ) + prop:SetPos( ply:GetItemDropPos() ) + + if tbl.DropModel then + + prop:SetModel( tbl.DropModel ) + + else + + prop:SetModel( tbl.Model ) + + end + + prop:Spawn() + + ply:EmitSound( Sound( "items/ammopickup.wav" ) ) + ply:RemoveFromInventory( id ) + + if not ply:HasItem( id ) then + + ply:StripWeapon( tbl.Weapon ) + + end + +end + +function FUNC_REMOVEWEAPON( ply, id ) + + local tbl = item.GetByID( id ) + + if not ply:HasItem( id ) then + + ply:StripWeapon( tbl.Weapon ) + + end + +end + +function FUNC_GRABWEAPON( ply, id ) + + local tbl = item.GetByID( id ) + + ply:Give( tbl.Weapon ) + + return true + +end + +item.Register( { + Name = "Hammer", + Description = "Builds barricades and bashes skulls.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 3, + Price = 35, + Rarity = 0.40, + Model = "models/weapons/w_hammer.mdl", + Weapon = "rad_hammer", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,-28,0), + CamOrigin = Vector(0,0,5) +} ) + +item.Register( { + Name = "Axe", + Description = "The messiest melee weapon.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 5, + Price = 50, + Rarity = 0.60, + Model = "models/weapons/w_axe.mdl", + Weapon = "rad_axe", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,-42,0), + CamOrigin = Vector(0,0,8) +} ) + +item.Register( { + Name = "Crowbar", + Description = "Gordon's weapon of choice.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + SaleOverride = true, + Weight = 5, + Price = 50, + Rarity = 0.20, + Model = "models/weapons/w_crowbar.mdl", + Weapon = "rad_crowbar", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,0,-44), + CamOrigin = Vector(0,0,8) +} ) + +item.Register( { + Name = "FN Five-Seven", + Description = "A standard issue sidearm.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + SaleOverride = true, + Weight = 3, + Price = 8, + Rarity = 0.90, + Model = "models/weapons/w_pist_fiveseven.mdl", + Weapon = "rad_fiveseven", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,17,5), + CamOrigin = Vector(2,0,3) +} ) + +item.Register( { + Name = "USP Compact", + Description = "A standard issue sidearm.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + SaleOverride = true, + Weight = 3, + Price = 8, + Rarity = 0.90, + Model = "models/weapons/w_pistol.mdl", + Weapon = "rad_usp", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,-17,0), + CamOrigin = Vector(-1,0,-2) +} ) + +item.Register( { + Name = "P228 Compact", + Description = "A standard issue sidearm.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + SaleOverride = true, + Weight = 3, + Price = 8, + Rarity = 0.90, + Model = "models/weapons/w_pist_p228.mdl", + Weapon = "rad_p228", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,17,5), + CamOrigin = Vector(2,0,3) +} ) + +item.Register( { + Name = "Glock 19", + Description = "A standard issue sidearm.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + SaleOverride = true, + Weight = 3, + Price = 8, + Rarity = 0.90, + Model = "models/weapons/w_pist_glock18.mdl", + Weapon = "rad_glock", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,17,5), + CamOrigin = Vector(2,0,3) +} ) + +item.Register( { + Name = "Dual Berettas", + Description = "A gun for each hand.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 3, + Price = 35, + Rarity = 0.20, + Model = "models/weapons/w_pist_elite_single.mdl", + DropModel = "models/weapons/w_pist_elite_dropped.mdl", + Weapon = "rad_berettas", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,15,-5), + CamOrigin = Vector(2,0,3) +} ) + +item.Register( { + Name = "Colt Python", + Description = "A six shooter that packs a punch.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 4, + Price = 40, + Rarity = 0.20, + Model = "models/weapons/w_357.mdl", + Weapon = "rad_revolver", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,18,0), + CamOrigin = Vector(6,0,0) +} ) + +item.Register( { + Name = "Desert Eagle", + Description = "What are you compensating for?", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 4, + Price = 45, + Rarity = 0.20, + Model = "models/weapons/w_pist_deagle.mdl", + Weapon = "rad_deagle", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,15,2), + CamOrigin = Vector(3,0,4) +} ) + +item.Register( { + Name = "MAC-10", + Description = "A compact SMG with moderate recoil.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 4, + Price = 50, + Rarity = 0.20, + Model = "models/weapons/w_smg_mac10.mdl", + Weapon = "rad_mac10", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,20,5), + CamOrigin = Vector(2,0,3) +} ) + +item.Register( { + Name = "UMP45", + Description = "A powerful SMG with a smaller magazine.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 6, + Price = 55, + Rarity = 0.30, + Model = "models/weapons/w_smg_ump45.mdl", + Weapon = "rad_ump45", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,30,5), + CamOrigin = Vector(-2,0,4) +} ) + +item.Register( { + Name = "CMP250", + Description = "A prototype burst-fire SMG.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 4, + Price = 60, + Rarity = 0.30, + Model = "models/weapons/w_smg1.mdl", + Weapon = "rad_cmp", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,27,0), + CamOrigin = Vector(-1,0,-1) +} ) + +item.Register( { + Name = "Winchester 1887", + Description = "Zombies are in season.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 6, + Price = 65, + Rarity = 0.30, + Model = "models/weapons/w_annabelle.mdl", + Weapon = "rad_shotgun", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,-50,5), + CamOrigin = Vector(3,0,1) +} ) + +item.Register( { + Name = "TMP", + Description = "A silent but deadly SMG.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 4, + Price = 70, + Rarity = 0.40, + Model = "models/weapons/w_smg_tmp.mdl", + Weapon = "rad_tmp", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,31,5), + CamOrigin = Vector(5,0,3) +} ) + +item.Register( { + Name = "MP5", + Description = "A well-rounded, reliable SMG.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 6, + Price = 75, + Rarity = 0.40, + Model = "models/weapons/w_smg_mp5.mdl", + Weapon = "rad_mp5", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,38,5), + CamOrigin = Vector(2,0,5) +} ) + +item.Register( { + Name = "FAMAS", + Description = "The least expensive assault rifle.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 9, + Price = 80, + Rarity = 0.50, + Model = "models/weapons/w_rif_famas.mdl", + Weapon = "rad_famas", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(-7,39,5), + CamOrigin = Vector(-6,0,5) +} ) + +item.Register( { + Name = "FN P90", + Description = "A powerful SMG with a large magazine.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 4, + Price = 85, + Rarity = 0.50, + Model = "models/weapons/w_smg_p90.mdl", + Weapon = "rad_p90", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,35,5), + CamOrigin = Vector(1,0,5) +} ) + +item.Register( { + Name = "Steyr Scout", + Description = "A bolt-action sniper rifle.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 9, + Price = 90, + Rarity = 0.60, + Model = "models/weapons/w_snip_scout.mdl", + Weapon = "rad_scout", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,44,5), + CamOrigin = Vector(0,0,4) +} ) + +item.Register( { + Name = "IMI Galil", + Description = "Lower accuracy, larger magazine.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 8, + Price = 100, + Rarity = 0.60, + Model = "models/weapons/w_rif_galil.mdl", + Weapon = "rad_galil", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,42,5), + CamOrigin = Vector(-1,0,3) +} ) + +item.Register( { + Name = "SPAS-12", + Description = "Useful for crowd control.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 7, + Price = 110, + Rarity = 0.70, + Model = "models/weapons/w_shotgun.mdl", + Weapon = "rad_spas12", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,-34,0), + CamOrigin = Vector(0,0,0) +} ) + +item.Register( { + Name = "AK-47", + Description = "A well-rounded assault rifle.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 7, + Price = 130, + Rarity = 0.80, + Model = "models/weapons/w_rif_ak47.mdl", + Weapon = "rad_ak47", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,43,5), + CamOrigin = Vector(0,0,3) +} ) + +item.Register( { + Name = "SG 552", + Description = "Comes with a free scope.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 8, + Price = 150, + Rarity = 0.90, + Model = "models/weapons/w_rif_sg552.mdl", + Weapon = "rad_sg552", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,37,5), + CamOrigin = Vector(-4,0,5) +} ) + +item.Register( { + Name = "G3 SG1", + Description = "An automatic sniper rifle.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 9, + Price = 170, + Rarity = 0.90, + Model = "models/weapons/w_snip_g3sg1.mdl", + Weapon = "rad_g3", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,42,5), + CamOrigin = Vector(-3,0,5) +} ) + +item.Register( { + Name = "HEAT Cannon", + Description = "An experimental long range zombie cooker.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 9, + Price = 190, + Rarity = 0.70, + Model = "models/weapons/w_physics.mdl", + Weapon = "rad_firegun", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,35,0), + CamOrigin = Vector(10,0,-1) +} ) + +item.Register( { + Name = "PPW-952", + Description = "An experimental particle projectile weapon.", + Stackable = false, + Type = ITEM_WPN_COMMON, + TypeOverride = "sent_droppedgun", + Weight = 9, + Price = 200, + Rarity = 0.70, + Model = "models/weapons/w_irifle.mdl", + Weapon = "rad_experimental", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,-40,0), + CamOrigin = Vector(5,0,0) +} ) diff --git a/gamemode/items/weapons_special.lua b/gamemode/items/weapons_special.lua new file mode 100644 index 0000000..3d9a6c3 --- /dev/null +++ b/gamemode/items/weapons_special.lua @@ -0,0 +1,128 @@ + +// This is the ID given to any weapon item for SPECIAL +ITEM_WPN_SPECIAL = 10 + +--[[function FUNC_PLANTBOMB( ply, id, client ) + + if client then return "Arm" end + + ply:RemoveFromInventory( id ) + ply:EmitSound( "weapons/c4/c4_plant.wav" ) + + local trace = {} + trace.start = ply:GetShootPos() + trace.endpos = ply:GetShootPos() + ply:GetAimVector() * 50 + trace.filter = ply + local tr = util.TraceLine( trace ) + + local bomb = ents.Create( "sent_c4" ) + bomb:SetPos( tr.HitPos ) + bomb:SetOwner( ply ) + bomb:Spawn() + +end]] + +item.Register( { + Name = "M1014", + Description = "Turn everything into ground beef.", + Stackable = false, + Type = ITEM_WPN_SPECIAL, + TypeOverride = "sent_droppedgun", + Weight = 7, + Price = 160, + Rarity = 0.90, + Model = "models/weapons/w_shot_xm1014.mdl", + Weapon = "rad_m1014", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,38,5), + CamOrigin = Vector(1,0,4) +} ) + +item.Register( { + Name = "M249", + Description = "A belt-fed support machine gun.", + Stackable = false, + Type = ITEM_WPN_SPECIAL, + TypeOverride = "sent_droppedgun", + Weight = 10, + Price = 180, + Rarity = 0.90, + Model = "models/weapons/w_mach_m249para.mdl", + Weapon = "rad_m249", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,38,5), + CamOrigin = Vector(2,0,6) +} ) + +item.Register( { + Name = "AWP", + Description = "The very definition of overkill.", + Stackable = false, + Type = ITEM_WPN_SPECIAL, + TypeOverride = "sent_droppedgun", + Weight = 9, + Price = 200, + Rarity = 0.70, + Model = "models/weapons/w_snip_awp.mdl", + Weapon = "rad_awp", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(0,51,5), + CamOrigin = Vector(1,0,4) +} ) + +item.Register( { + Name = "HE Grenade", + Description = "The fuse lasts 3 seconds.", + Stackable = true, + Type = ITEM_WPN_SPECIAL, + TypeOverride = "sent_droppedgun", + Weight = 1, + Price = 5, + Rarity = 0.20, + Model = "models/weapons/w_eq_fraggrenade_thrown.mdl", + Weapon = "rad_grenade", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(1,12,4), + CamOrigin = Vector(0,0,1) +} ) + +item.Register( { + Name = "Incendiary Grenade", + Description = "Comes with free marshmallows.", + Stackable = true, + Type = ITEM_WPN_SPECIAL, + TypeOverride = "sent_droppedgun", + Weight = 1, + Price = 8, + Rarity = 0.40, + Model = "models/weapons/w_eq_flashbang.mdl", + Weapon = "rad_incendiarygrenade", + Functions = { FUNC_DROPWEAPON }, + PickupFunction = FUNC_GRABWEAPON, + DropFunction = FUNC_REMOVEWEAPON, + CamPos = Vector(3,16,3), + CamOrigin = Vector(0,0,5) +} ) + +--[[item.Register( { + Name = "Timed Explosives", + Description = "This is a homemade timed explosive.", + Stackable = true, + Type = ITEM_WPN_SPECIAL, + TypeOverride = "sent_droppedgun", + Weight = 3, + Price = 10, + Rarity = 0.80, + Model = "models/weapons/w_c4.mdl", + Functions = { FUNC_PLANTBOMB }, + CamPos = Vector(-12,-2,0), + CamOrigin = Vector(0,5,0) +} )]]
\ No newline at end of file diff --git a/gamemode/map_defaults.lua b/gamemode/map_defaults.lua new file mode 100644 index 0000000..dc5bbf1 --- /dev/null +++ b/gamemode/map_defaults.lua @@ -0,0 +1,25 @@ + +// eat shit garry + +local maps = { "redead/rd_apartmentcomplex_json.txt", + "redead/zombiesurvival_b5_json.txt" } + +local data = { + +[[{"info_lootspawn":{"1":"[728.2679 1204.6923 150.0313]","2":"[1144.7465 1178.7068 150.0313]","3":"[1505.1332 1130.7913 189.961]","4":"[1502.6437 826.1514 150.0313]","5":"[1310.3285 792.6308 150.0313]","6":"[941.4187 1122.0729 189.9808]","7":"[957.3593 832.7668 150.0313]","8":"[631.056 1110.2343 150.0313]","9":"[1315.9518 418.904 150.0313]","10":"[1207.6248 732.3971 150.0313]","11":"[981.574 744.1642 197.0781]","12":"[966.4352 431.9167 150.0313]","13":"[632.3114 217.6249 150.0313]","14":"[941.1967 -184.439 150.0313]","15":"[878.8295 180.3319 150.0313]","16":"[730.5721 -318.0413 150.0313]","17":"[743.6882 -740.4319 150.0313]","18":"[862.9421 -403.1872 150.0313]","19":"[1229.7266 -412.9471 150.0313]","20":"[1515.2794 -695.6165 150.0313]","21":"[1307.6687 -1115.9705 150.0313]","22":"[1503.6578 -793.3757 189.9749]","23":"[1132.3955 -1243.422 150.0313]","24":"[658.6079 -1228.7908 150.0313]","25":"[750.4007 -1121.0291 6.0313]","26":"[931.1493 -791.7018 45.9711]","27":"[947.8159 -709.5466 6.0313]","28":"[846.0848 -699.3538 6.0313]","29":"[1429.4917 -406.2503 6.0313]","30":"[1205.5308 -398.5325 6.0313]","31":"[813.7065 -412.2303 6.0313]","32":"[1016.3391 -367.6704 6.0313]","33":"[1483.894 -368.5908 150.0313]","34":"[874.3385 -61.6505 53.0313]","35":"[874.824 118.9456 53.0313]","36":"[903.7451 29.1854 6.0313]","37":"[756.9775 410.2665 6.0313]","38":"[1011.6741 406.0877 6.0313]","39":"[1536.3606 463.0686 6.0313]","40":"[1345.6189 749.3622 6.0313]","41":"[612.7742 403.4674 6.0313]","42":"[1021.6572 1104.1167 6.0313]","43":"[871.48 788.5372 6.0313]","44":"[907.0815 891.8474 6.0313]","45":"[1150.6467 -1163.4579 6.0313]","46":"[-1428.3389 -975.6552 109.0106]","47":"[-1423.7222 -918.0593 109.0105]","48":"[-1438.9113 -1123.002 108.9811]","49":"[-1289.6064 -1206.7279 70.0313]","50":"[-1103.8529 -1194.277 70.0313]","51":"[-1379.9244 -690.3006 104.0313]","52":"[-1374.4518 -591.9827 104.0313]","53":"[-1043.8094 -525.6351 103.8351]","54":"[-1477.3882 -551.8082 69.0313]","55":"[-1121.1296 -424.2845 101.0313]","56":"[-1392.5243 -11.1805 70.0313]","57":"[-1473.1445 -73.4212 116.078]","58":"[-881.5622 -180.8376 70.0313]","59":"[-888.7677 345.2978 70.0313]","60":"[-1149.3009 -170.9552 232.0486]","61":"[-1081.3892 352.8701 238.5686]","62":"[-942.4716 85.5578 201.0313]","63":"[-835.507 148.3815 69.0313]","64":"[-1169.558 406.1492 69.0313]","65":"[-1587.4739 351.5022 101.0313]","66":"[-1591.588 -180.1971 101.0313]","67":"[-1440.9125 875.4196 101.0313]","68":"[-1319.675 754.0405 108.9794]","69":"[-1240.9662 865.8846 70.0313]","70":"[-870.9526 1164.9552 70.0313]","71":"[-920.0687 851.8335 236.2341]","72":"[-1056.1483 1169.7148 231.0486]","73":"[-863.1475 1039.2596 200.0313]","74":"[-870.0542 890.3504 200.0313]","75":"[-1076.8447 1110.9702 106.975]","76":"[-884.3427 1238.3864 69.0313]","77":"[-1013.5281 532.6072 8.0312]","78":"[-898.6596 -540.4709 70.0313]","79":"[-772.3708 -346.5603 8.0313]","80":"[-59.9806 -1404.9617 5.0313]","81":"[-648.8461 -1365.5369 8.0313]","82":"[650.2933 -1341.6227 8.0313]","83":"[-6.0873 -376.5837 141.0313]","84":"[143.5577 72.6394 141.0313]","85":"[138.882 324.5521 141.0313]","86":"[-146.2948 -173.7491 141.0313]","87":"[1.8558 -406.8785 8.0313]","88":"[74.9934 316.431 8.0313]","89":"[-72.6895 318.8666 8.0313]","90":"[-1309.608 1146.5614 200.0313]","91":"[-796.6145 -1250.14 69.0313]"},"info_player_army":{"1":"[-1367.7357 -1177.1493 197.0313]","2":"[-1285.8579 -1172.001 197.0313]","3":"[-1203.6658 -1169.1372 197.0313]","4":"[-1126.5031 -1166.5089 197.0313]","5":"[-812.4174 -1182.7566 197.0313]","6":"[-862.3701 -1143.08 197.0313]","7":"[-929.8381 -1139.9736 197.0313]","8":"[-990.6744 -1140.7975 197.0313]","9":"[-1082.5376 -1130.9849 197.0313]","10":"[-1088.1488 -1074.5981 197.0313]","11":"[-1018.1358 -1066.804 197.0313]","12":"[-956.0265 -1064.2303 197.0313]","13":"[-884.0614 -1057.9478 197.0313]","14":"[-837.9715 -1013.6509 197.0313]","15":"[-818.4769 -951.3231 197.0313]","16":"[-812.8536 -885.5848 197.0313]","17":"[-880.3511 -881.7681 197.0313]","18":"[-890.6105 -935.2946 197.0313]","19":"[-920.6945 -994.3774 197.0313]","20":"[-988.0549 -992.7564 197.0313]","21":"[-992.2855 -927.2556 197.0313]","22":"[-967.7716 -866.439 197.0313]","23":"[-1052.7389 -998.5204 197.0313]","24":"[-1114.2504 -993.9272 197.0313]","25":"[-1158.3448 -1046.4697 197.0313]","26":"[-1167.5398 -1098.5654 197.0313]","27":"[-1237.3684 -1093.8457 197.0313]","28":"[-1304.9419 -1104.12 197.0313]","29":"[-1278.3973 -1040.1799 197.0313]","30":"[-1231.4478 -998.3747 197.0313]","31":"[-1279.0137 -971.1279 197.0313]","32":"[-1218.8285 -939.4406 197.0313]","33":"[-1159.2891 -923.3546 197.0313]","34":"[-1144.7931 -732.4555 197.0313]","35":"[-1043.0251 -742.0983 197.0313]","36":"[-968.4556 -741.0143 197.0313]","37":"[-929.0648 -676.615 197.0313]"},"point_radiation":[],"point_stash":[],"info_player_zombie":{"1":"[-723.4517 2078.134 8.0313]","2":"[-719.296 2162.2993 8.0313]","3":"[-708.5917 2220.8469 8.0313]","4":"[-619.8789 2220.8584 8.0313]","5":"[-623.3275 2163.1777 8.0313]","6":"[-627.5798 2087.5205 8.0313]","7":"[-562.2644 2088.834 8.0313]","8":"[-557.9258 2154.3428 8.0313]","9":"[-559.5195 2219.3147 8.0313]","10":"[-702.0791 1987.4875 8.0313]","11":"[-720.8421 1795.0205 8.0313]","12":"[-565.1263 1776.8129 8.0313]","13":"[-535.8591 1967.5879 8.0313]","14":"[707.0464 2094.0461 8.0313]","15":"[708.8925 2205.0862 8.0313]","16":"[618.3367 2206.2134 8.0313]","17":"[610.3018 2101.7134 8.0312]","18":"[540.1431 2204.8145 8.0313]","19":"[529.2364 2109.9885 8.0313]","20":"[442.8304 2145.7078 8.0313]"},"info_evac":{"1":"[-6.1673 1156.0032 8.0313]","2":"[-21.0202 -923.1101 8.0313]","3":"[-483.3858 -48.1653 8.0313]","4":"[388.1861 102.1153 8.0313]","5":"[-472.3137 262.0621 8.0312]","6":"[-469.5734 -482.7105 8.0312]"},"info_npcspawn":{"1":"[694.4854 1646.6602 8.0313]","2":"[693.1973 1554.5415 8.0313]","3":"[587.1055 1549.807 8.0313]","4":"[579.6001 1649.3862 8.0313]","5":"[-687.7419 1554.7095 8.0313]","6":"[-685.2443 1654.6686 8.0313]","7":"[-585.218 1659.2363 8.0313]","8":"[-575.3214 1559.7159 8.0313]","9":"[484.1852 1600.1304 8.0313]","10":"[457.184 1677.2731 8.0313]","11":"[397.903 1597.4854 8.0313]","12":"[-459.8139 1560.2728 8.0313]","13":"[-495.0093 1641.8805 8.0313]","14":"[-419.2628 1633.9351 8.0313]"},"prop_physics":{"1":{"1":"[-289.9543 1717.2734 -14.1487]","2":"models/props_c17/door01_left.mdl","3":"{-62.8363 91.2064 0.1306}","4":false}}}]], + +[[{"info_lootspawn":{"1":"[-1309.7611 -2109.2942 -576.9146]","2":"[-502.3158 -1461.2394 -597.0408]","3":"[-579.314 -1451.8135 -599.2006]","4":"[56.8793 -2341.5796 -586.9688]","5":"[-434.5696 -2398.0142 -586.9688]","6":"[158.976 -1009.9685 -522.9688]","7":"[670.7562 -448.6924 -554.9688]","8":"[937.1771 -981.1544 -554.9688]","9":"[774.163 -491.5866 -554.9688]","10":"[2086.8628 -518.7484 -442.9688]","11":"[1918.5142 -843.2439 -442.9688]","12":"[2088.916 -509.1649 -530.9751]","13":"[2290.0864 -799.98 -570.9688]","14":"[2019.8793 -476.7725 -570.9688]","15":"[2234.4473 -882.0463 -570.9688]","16":"[813.3882 -2198.3523 -586.9688]","17":"[700.569 -2161.0571 -586.9688]","18":"[1183.7118 -2208.4021 -586.9688]","19":"[665.8838 87.4443 -390.9688]","20":"[989.5206 227.6602 -390.9688]","21":"[742.718 -181.3165 -522.9688]","22":"[657.7302 70.2577 -522.9688]","23":"[1061.7212 -182.3531 -522.9688]","24":"[1518.5961 1317.5173 -587]","25":"[962.2952 1315.3857 -587]","26":"[58.1124 261.5126 -586.9688]","27":"[-143.9311 224.8594 -586.9688]","28":"[-149.0539 355.7635 -434.9688]","29":"[181.6674 349.2947 -434.9688]","30":"[434.9179 314.6129 -434.9688]","31":"[184.5212 340.6805 -298.9688]","32":"[-139.1549 351.1876 -298.9688]","33":"[265.7855 315.3242 -298.9688]","34":"[-917.4197 1809.3086 -426.9688]","35":"[-497.7445 1328.2443 -426.9688]","36":"[-725.3589 1326.1785 -426.9688]","37":"[-1002.528 1517.1238 -426.9688]","38":"[-436.3526 1549.8292 -570.9688]","39":"[-566.2977 1730.452 -531.022]","40":"[-561.0951 1687.981 -570.9688]","41":"[-690.972 1686.4412 -526.9688]","42":"[-621.6334 1560.3247 -526.9688]","43":"[-1056.7042 2851.1448 -586.9688]","44":"[-1210.7593 2291.239 -586.9688]","45":"[-1975.1171 167.4544 -586.9688]","46":"[-2003.6268 -33.3897 -586.9688]","47":"[-1101.946 -379.6512 -450.9688]","48":"[-1100.7886 -456.5605 -450.9688]","49":"[-151.5773 -304.094 -586.9688]","50":"[89.945 -278.263 -586.9688]","51":"[311.1924 -292.9703 -586.9688]","52":"[811.1868 -342.6861 -587.9688]","53":"[2106.3806 -243.3691 -586.9688]","54":"[1939.7889 -1640.1552 -602.9688]","55":"[1954.9285 -1362.4407 -602.9688]","56":"[240.0961 -30.0851 -586.9688]","57":"[-1935.017 1403.3256 -586.9688]","58":"[810.3748 296.5037 -586.9688]","59":"[-583.6614 2818.397 -586.9688]","60":"[-1085.6957 -188.7936 -586.9688]","61":"[-99.8942 1049.4402 -586.9688]","62":"[1046.1742 -36.8198 -522.9688]","63":"[-2003.2039 2650.2002 -586.9688]","64":"[2292.0117 -584.5168 -586.9688]","65":"[38.2886 -1014.0394 -586.9688]","66":"[-2135.8879 -1119.8534 -586.9688]","67":"[951.7985 -735.6447 -519.2308]","68":"[-1283.418 -2357.8735 -576.9146]"},"info_player_army":{"1":"[-2114.9988 -2561.917 -586.9688]","2":"[-2041.2007 -2560.9729 -586.9688]","3":"[-1972.1667 -2559.2524 -586.9688]","4":"[-1894.5385 -2557.2832 -586.9688]","5":"[-1804.6599 -2557.823 -586.9688]","6":"[-1707.2762 -2553.0691 -586.9688]","7":"[-2102.7915 -2454.3958 -586.9688]","8":"[-2024.6835 -2463.9412 -586.9688]","9":"[-1947.053 -2471.8152 -586.9688]","10":"[-1858.3237 -2468.8445 -586.9688]","11":"[-1770.816 -2465.1292 -586.9688]","12":"[-1666.6018 -2457.4316 -586.9688]","13":"[-1604.8453 -2548.9536 -586.9688]","14":"[-1504.2173 -2541.7935 -586.9688]","15":"[-1552.7557 -2457.4163 -586.9688]","16":"[-2100.4629 -2375.5876 -586.9688]","17":"[-2022.3632 -2379.5842 -586.9688]","18":"[-1944.4526 -2385.4082 -586.9688]","19":"[-1674.7952 -2362.2256 -586.9688]","20":"[-1782.8971 -2366.7207 -586.9688]","21":"[-1863.426 -2382.2466 -586.9688]","22":"[-1571.7196 -2369.6177 -586.9688]","23":"[-1429.7421 -2459.9233 -586.9688]","24":"[-1397.2052 -2559.2517 -586.9688]"},"point_radiation":[],"point_stash":[],"info_player_zombie":{"1":"[2082.979 2235.1667 -587]","2":"[1980.5236 2232.5234 -587]","3":"[2243.667 2034.2469 -587]","4":"[2201.012 2234.1313 -587]","5":"[2247.2703 2155.5291 -587]","6":"[2299.1055 2233.7334 -587]","7":"[2323.7229 2105.7351 -587]","8":"[2203.7339 1953.3639 -587]","9":"[2196.9131 1862.5906 -587]","10":"[2284.325 1864.9401 -587]","11":"[2297.2229 1930.7443 -587]","12":"[2333.3716 1979.7561 -587]","13":"[2399.0427 2023.291 -587]","14":"[2419.3948 2106.0608 -587]","15":"[2417.3069 2231.7563 -587]","16":"[2309.1414 2311.5139 -587]","17":"[2215.0808 2337.0093 -587]","18":"[2116.6843 2341.7559 -587]","19":"[1997.7557 2357.2109 -587]","20":"[1847.062 2195.3191 -587]","21":"[1890.1071 2354.6316 -587]","22":"[264.0211 2571.0825 -403.9167]","23":"[444.9329 1832.4081 -458.9688]","24":"[576.2989 1236.4056 -458.9688]","25":"[454.5056 1243.0625 -458.9688]"},"info_evac":{"1":"[1421.3696 -1422.2427 -602.9688]","2":"[-1901.8889 -2142.627 -586.9688]","3":"[-508.4947 680.2912 -602.9688]","4":"[-1513.2092 1410.3585 -602.9687]","5":"[-588.9512 -172.6187 -602.9688]","6":"[1416.2916 -739.1258 -602.9688]","7":"[1393.6287 723.0817 -602.9688]"},"info_npcspawn":{"1":"[1768.6964 1910.2103 -587]","2":"[666.5615 2210.1272 -587]","3":"[997.6447 2008.7366 -587]","4":"[1177.0903 2036.8326 -587]","5":"[1377.5498 2175.1833 -587]","6":"[1538.1113 2175.2078 -587]","7":"[1587.0107 1834.4586 -587]","8":"[1142.5812 2323.7883 -587]","9":"[1040.9902 2195.1147 -587]"},"prop_physics":{"1":{"1":"[505.8858 1037.4922 -533.7089]","2":"models/props_junk/trashdumpster02b.mdl","3":"{-0 0 -116.5652}","4":false},"2":{"1":"[526.7874 1330.5114 -463.5963]","2":"models/props_lab/lockers.mdl","3":"{0.0364 -65.9059 0.0013}","4":false},"3":{"1":"[226.775 2470.4885 -407.5161]","2":"models/props_c17/door01_left.mdl","3":"{89.9278 108.7258 2.8992}","4":false},"4":{"1":"[417.0268 341.2404 -567.559]","2":"models/props/cs_office/shelves_metal.mdl","3":"{-0.2443 -96.5858 0.0019}","4":false},"5":{"1":"[280.7473 341.6676 -523.9426]","2":"models/props_wasteland/controlroom_storagecloset001a.mdl","3":"{-0 81.1528 -0.1719}","4":false},"6":{"1":"[-1275.0845 -2212.2988 -401.5813]","2":"models/props_wasteland/cargo_container01.mdl","3":"{0.02 -0.4337 0.0056}","4":false},"7":{"1":"[-1419.3181 -2201.2813 -401.4044]","2":"models/props_wasteland/cargo_container01.mdl","3":"{-0.0156 -2.0899 -0.0031}","4":false},"8":{"1":"[736.8913 828.8593 -607.3658]","2":"models/props_c17/concrete_barrier001a.mdl","3":"{-0.271 -12.5051 -0.0001}","4":false},"9":{"1":"[529.5351 1138.1127 -462.2419]","2":"models/props_c17/door01_left.mdl","3":"{57.3153 -91.9871 90.0044}","4":false},"10":{"1":"[-999.0718 1788.7244 -377.7397]","2":"models/props_c17/fence01b.mdl","3":"{0 90 0.0001}","4":false},"11":{"1":"[-999.3907 1476.3683 -377.7028]","2":"models/props_c17/fence01b.mdl","3":"{0 -90 -0}","4":false},"12":{"1":"[-1036.63 1611.4601 -377.6093]","2":"models/props_c17/fence03a.mdl","3":"{-1.3311 0.0823 -0.0008}","4":false},"13":{"1":"[-1029.6052 1740.4259 -368.1152]","2":"models/props_junk/trashdumpster02b.mdl","3":"{0.0013 -89.9273 -84.3279}","4":false},"14":{"1":"[959.3414 -727.774 -558.913]","2":"models/props/cs_militia/table_kitchen.mdl","3":"{-2.5486 0.0237 0.0276}","4":false},"15":{"1":"[792.1609 -1007.3684 -543.0119]","2":"models/props_interiors/refrigerator01a.mdl","3":"{-0.0404 90.0612 90.0052}","4":false},"16":{"1":"[-877.3171 -1978.6816 -591.6464]","2":"models/props_c17/oildrum001.mdl","3":"{0.013 -62.5517 0.017}","4":true}}}]] + +} + +file.CreateDir( "redead" ) + +for k,v in pairs( maps ) do + + if not file.Exists( v, "DATA" ) then + + file.Write( v, data[k] ) + + end + +end
\ No newline at end of file diff --git a/gamemode/moddable.lua b/gamemode/moddable.lua new file mode 100644 index 0000000..a5cdfeb --- /dev/null +++ b/gamemode/moddable.lua @@ -0,0 +1,238 @@ + + +// Currency name + +GM.CurrencyName = "Bone" + +// BLOOD BLOOD BLOOD BLOOD + +GM.BloodName = "BLOOD" + +// Shop name and description - obsolete? + +GM.ShopName = "UNCLE VIKTOR'S RUSSKI WEAPON SHOPPE" +GM.ShopDesc = "A HAPPY CUSTOMER IS A DEAD ONE!" + +// Team names + +GM.ArmyTeamName = "Unit 9" +GM.ZombieTeamName = "The Undead" + +// Death Screen text shit + +GM.DeathScreenText = {} + +GM.DeathScreenText[ TEAM_ARMY ] = { "RUN FASTER NEXT TIME", +"DEATH IS THE FINAL UNKNOWN", +"LIFE'S A BITCH AND THEN YOU DIE", +"EVERYTHING HAS AN EXPIRATION DATE", +"THE UNDEAD ARMY GROWS STRONGER", +"YOU'VE GOT RED ON YOU", +"YOU'RE ZOMBIE BAIT" } + +GM.DeathScreenText[ TEAM_ZOMBIES ] = { "DEATH IS ONLY THE BEGINNING", +"GET UP AND TRY AGAIN", +"YOU'RE RAVEN FOOD", +"REST IN PEACE", +"DEATH IS A BITCH, AIN'T IT", +"LIFE IS OVERRATED", +"REST IS FOR THE LIVING" } + +GM.RedemptionCash = 250 // Amount of cash earned for redeeming yourself +GM.RedemptionDamage = 350 // Amount of damage that the zombie lord needs to deal before he is redeemed +GM.RadiationAmount = 0.6 // How much of the radiation on the map should be disabled on map startup? ( 0.6 means 60% will be disabled ) - OBSOLETE? +GM.MaxLoot = 0.35 // Maximum amount of loot to be generated ( 0.05 means 5% of the info_lootspawns will have loot at them. ) +GM.WoodPercentage = 0.15 // What percentage of props on the map should be wooden? + +// Player class models + weapons + item loadouts + +GM.ClassModels = {} +GM.ClassModels[CLASS_SCOUT] = "models/player/riot.mdl" +GM.ClassModels[CLASS_COMMANDO] = "models/player/swat.mdl" +GM.ClassModels[CLASS_SPECIALIST] = "models/player/gasmask.mdl" +GM.ClassModels[CLASS_ENGINEER] = "models/player/urban.mdl" + +GM.ClassWeapons = {} +GM.ClassWeapons[CLASS_SCOUT] = "models/weapons/w_pist_glock18.mdl" // use world model names since we have to use the old fucky inventory system +GM.ClassWeapons[CLASS_COMMANDO] = "models/weapons/w_pistol.mdl" +GM.ClassWeapons[CLASS_SPECIALIST] = "models/weapons/w_pist_p228.mdl" +GM.ClassWeapons[CLASS_ENGINEER] = "models/weapons/w_pist_fiveseven.mdl" + +GM.ClassLoadouts = {} +GM.ClassLoadouts[CLASS_SCOUT] = { ITEM_MISC, ITEM_MISC, ITEM_SUPPLY, ITEM_SUPPLY } +GM.ClassLoadouts[CLASS_COMMANDO] = { ITEM_MISC, ITEM_MISC, ITEM_SUPPLY, ITEM_SUPPLY } +GM.ClassLoadouts[CLASS_SPECIALIST] = { ITEM_MISC, ITEM_SPECIAL, ITEM_SUPPLY, ITEM_SUPPLY } +GM.ClassLoadouts[CLASS_ENGINEER] = { ITEM_MISC } + +GM.ZombieModels = {} +GM.ZombieModels[CLASS_RUNNER] = "models/player/corpse1.mdl" +GM.ZombieModels[CLASS_BANSHEE] = "models/player/charple.mdl" +GM.ZombieModels[CLASS_CONTAGION] = "models/player/zombie_classic.mdl" +GM.ZombieModels[CLASS_LEAPER] = "models/player/zombie_fast.mdl" + +GM.ZombieWeapons = {} +GM.ZombieWeapons[CLASS_RUNNER] = "rad_z_runner" +GM.ZombieWeapons[CLASS_BANSHEE] = "rad_z_banshee" +GM.ZombieWeapons[CLASS_CONTAGION] = "rad_z_contagion" +GM.ZombieWeapons[CLASS_LEAPER] = "rad_z_leaper" + +GM.ZombieHealth = {} +GM.ZombieHealth[CLASS_RUNNER] = 100 +GM.ZombieHealth[CLASS_BANSHEE] = 75 +GM.ZombieHealth[CLASS_CONTAGION] = 175 +GM.ZombieHealth[CLASS_LEAPER] = 50 + +GM.ZombieSpeed = {} +GM.ZombieSpeed[CLASS_RUNNER] = 250 +GM.ZombieSpeed[CLASS_BANSHEE] = 225 +GM.ZombieSpeed[CLASS_CONTAGION] = 200 +GM.ZombieSpeed[CLASS_LEAPER] = 275 + +// Class names, descriptions, logos + +GM.ClassDescriptions = {} +GM.ClassDescriptions[CLASS_SCOUT] = "The Scout: Wears lightweight kevlar armor, allowing for improved mobility. Starts off with extra " .. GM.CurrencyName .. "s." +GM.ClassDescriptions[CLASS_COMMANDO] = "The Commando: Wears prototype kevlar armor, allowing for improved damage resistance." +GM.ClassDescriptions[CLASS_SPECIALIST] = "The Specialist: Has access to restricted utilities and weaponry." +GM.ClassDescriptions[CLASS_ENGINEER] = "The Technician: Starts off with the tools needed for barricade construction." + +GM.ClassLogos = {} +GM.ClassLogos[CLASS_SCOUT] = "nuke/redead/scout" +GM.ClassLogos[CLASS_COMMANDO] = "nuke/redead/commando" +GM.ClassLogos[CLASS_SPECIALIST] = "nuke/redead/specialist" +GM.ClassLogos[CLASS_ENGINEER] = "nuke/redead/engineer" + +GM.ZombieNames = {} +GM.ZombieNames[CLASS_RUNNER] = "Runner" +GM.ZombieNames[CLASS_BANSHEE] = "Banshee" +GM.ZombieNames[CLASS_CONTAGION] = "Contagion" +GM.ZombieNames[CLASS_LEAPER] = "Leaper" + +GM.ZombieDescriptions = {} +GM.ZombieDescriptions[CLASS_RUNNER] = "The Runner: A resilient and agile zombie. Capable of infecting humans with its claws." +GM.ZombieDescriptions[CLASS_BANSHEE] = "The Banshee: A highly radioactive zombie. Capable of disorienting humans with its scream." +GM.ZombieDescriptions[CLASS_CONTAGION] = "The Contagion: A bloated, festering zombie. When killed it will burst into a shower of acid." +GM.ZombieDescriptions[CLASS_LEAPER] = "The Leaper: A bony, mutated zombie. Capable of jumping great distances and making humans bleed with its claws." + +GM.ZombieLogos = {} +GM.ZombieLogos[CLASS_RUNNER] = "nuke/redead/zomb_corpse" +GM.ZombieLogos[CLASS_BANSHEE] = "nuke/redead/zomb_banshee" +GM.ZombieLogos[CLASS_CONTAGION] = "nuke/redead/zomb_zombie" +GM.ZombieLogos[CLASS_LEAPER] = "nuke/redead/zomb_leaper" + +// Colors used by notices + +GM.Colors = {} +GM.Colors.Green = Color(70,250,170,255) +GM.Colors.Red = Color(250,120,100,255) +GM.Colors.Blue = Color(70,170,250,255) +GM.Colors.Yellow = Color(250,220,70,255) +GM.Colors.White = Color(250,250,250,255) + +// Music to play when a player spawns ( randomly picked in table ) + +GM.OpeningMusic = { "music/HL1_song5.mp3", +"music/HL1_song6.mp3", +"music/HL1_song9.mp3", +"music/HL1_song19.mp3", +"music/HL1_song20.mp3", +"music/HL1_song21.mp3", +"music/HL1_song24.mp3", +"music/HL1_song26.mp3", +"music/HL2_intro.mp3", +"music/HL2_song0.mp3", +"music/HL2_song1.mp3", +"music/HL2_song2.mp3", +"music/HL2_song3.mp3", +"music/HL2_song4.mp3", +"music/HL2_song8.mp3", +"music/HL2_song12_long.mp3", +"music/HL2_song13.mp3", +"music/HL2_song14.mp3", +"music/HL2_song15.mp3", +"music/HL2_song16.mp3", +"music/HL2_song17.mp3", +"music/HL2_song19.mp3", +"music/HL2_song26.mp3", +"music/HL2_song20_submix0.mp3", +"music/HL2_song20_submix4.mp3", +"music/HL2_song26_trainstation1.mp3", +"music/HL2_song27_trainstation2.mp3", +"music/HL2_song30.mp3", +"music/stingers/industrial_suspense1.wav" } + +// Music to play on death + +GM.DeathMusic = { "music/ravenholm_1.mp3", +"music/HL2_song28.mp3", +"music/stingers/HL1_stinger_song16.mp3", +"music/stingers/HL1_stinger_song7.mp3", +"music/stingers/HL1_stinger_song8.mp3", +"music/stingers/HL1_stinger_song27.mp3", +"music/stingers/HL1_stinger_song28.mp3", +"music/stingers/industrial_suspense2.wav" } + +// Win and lose tunes + +GM.WinMusic = { "music/HL2_song6.mp3", +"music/HL1_song17.mp3", +"music/HL2_song29.mp3", +"music/HL2_song31.mp3" } + +GM.LoseMusic = { "music/HL1_song14.mp3", +"music/HL2_song7.mp3", +"music/HL2_song32.mp3", +"music/HL2_song33.mp3" } + +// Last minute + +GM.LastMinute = Sound( "nuke/redead/lastminute.mp3" ) + +if CLIENT then return end // Serverside configuration stuff past this point. + +// Headshot combo values + +GM.HeadshotCombos = {} +GM.HeadshotCombos[5] = 2 // Get 2 points for 5 consecutive headshots +GM.HeadshotCombos[10] = 5 // Get 5 points for 10 consecutive headshots +GM.HeadshotCombos[15] = 10 +GM.HeadshotCombos[20] = 15 +GM.HeadshotCombos[50] = 20 + +// Point values + +GM.KillValues = {} +GM.KillValues[ "npc_nb_common" ] = 2 +GM.KillValues[ "npc_nb_leaper" ] = 2 +GM.KillValues[ "npc_nb_contagion" ] = 3 +GM.KillValues[ "npc_nb_poison" ] = 4 + +GM.AssistValues = {} +GM.AssistValues[ "npc_nb_common" ] = 1 +GM.AssistValues[ "npc_nb_leaper" ] = 1 +GM.AssistValues[ "npc_nb_contagion" ] = 1 +GM.AssistValues[ "npc_nb_poison" ] = 2 + +GM.PlayerZombieKillValue = 3 + +// Human movespeeds + +GM.WalkSpeed = 175 +GM.RunSpeed = 250 + +// Chances to spawn each zombie type ( from 100 to 0 %) + +GM.SpawnChance = {} +GM.SpawnChance[ "npc_nb_common" ] = 1.0 // 100% chance +GM.SpawnChance[ "npc_nb_contagion" ] = 0.1 // 10% chance +GM.SpawnChance[ "npc_nb_leaper" ] = 0.3 +GM.SpawnChance[ "npc_nb_poison" ] = 0.2 + +// The individual waves and the list of zombies that will spawn. ( more waves means a longer match ) + +GM.Waves = {} +GM.Waves[1] = { "npc_nb_common" } +GM.Waves[2] = { "npc_nb_common", "npc_nb_leaper" } +GM.Waves[3] = { "npc_nb_common", "npc_nb_contagion", "npc_nb_leaper" } +GM.Waves[4] = { "npc_nb_common", "npc_nb_contagion", "npc_nb_leaper", "npc_nb_poison" } + diff --git a/gamemode/npcfix.lua b/gamemode/npcfix.lua new file mode 100644 index 0000000..b27de8d --- /dev/null +++ b/gamemode/npcfix.lua @@ -0,0 +1,158 @@ + +local sharedtasks_e = { } +sharedtasks_e["TASK_INVALID"] = 0 +sharedtasks_e["TASK_RESET_ACTIVITY"] = 1 +sharedtasks_e["TASK_WAIT"] = 2 +sharedtasks_e["TASK_ANNOUNCE_ATTACK"] = 3 +sharedtasks_e["TASK_WAIT_FACE_ENEMY"] = 4 +sharedtasks_e["TASK_WAIT_FACE_ENEMY_RANDOM"] = 5 +sharedtasks_e["TASK_WAIT_PVS"] = 6 +sharedtasks_e["TASK_SUGGEST_STATE"] = 7 +sharedtasks_e["TASK_TARGET_PLAYER"] = 8 +sharedtasks_e["TASK_SCRIPT_WALK_TO_TARGET"] = 9 +sharedtasks_e["TASK_SCRIPT_RUN_TO_TARGET"] = 10 +sharedtasks_e["TASK_SCRIPT_CUSTOM_MOVE_TO_TARGET"] = 11 +sharedtasks_e["TASK_MOVE_TO_TARGET_RANGE"] = 12 +sharedtasks_e["TASK_MOVE_TO_GOAL_RANGE"] = 13 +sharedtasks_e["TASK_MOVE_AWAY_PATH"] = 14 +sharedtasks_e["TASK_GET_PATH_AWAY_FROM_BEST_SOUND"] = 15 +sharedtasks_e["TASK_SET_GOAL"] = 16 +sharedtasks_e["TASK_GET_PATH_TO_GOAL"] = 17 +sharedtasks_e["TASK_GET_PATH_TO_ENEMY"] = 18 +sharedtasks_e["TASK_GET_PATH_TO_ENEMY_LKP"] = 19 +sharedtasks_e["TASK_GET_CHASE_PATH_TO_ENEMY"] = 20 +sharedtasks_e["TASK_GET_PATH_TO_ENEMY_LKP_LOS"] = 21 +sharedtasks_e["TASK_GET_PATH_TO_ENEMY_CORPSE"] = 22 +sharedtasks_e["TASK_GET_PATH_TO_PLAYER"] = 23 +sharedtasks_e["TASK_GET_PATH_TO_ENEMY_LOS"] = 24 +sharedtasks_e["TASK_GET_FLANK_RADIUS_PATH_TO_ENEMY_LOS"] = 25 +sharedtasks_e["TASK_GET_FLANK_ARC_PATH_TO_ENEMY_LOS"] = 26 +sharedtasks_e["TASK_GET_PATH_TO_RANGE_ENEMY_LKP_LOS"] = 27 +sharedtasks_e["TASK_GET_PATH_TO_TARGET"] = 28 +sharedtasks_e["TASK_GET_PATH_TO_TARGET_WEAPON"] = 29 +sharedtasks_e["TASK_CREATE_PENDING_WEAPON"] = 30 +sharedtasks_e["TASK_GET_PATH_TO_HINTNODE"] = 31 +sharedtasks_e["TASK_STORE_LASTPOSITION"] = 32 +sharedtasks_e["TASK_CLEAR_LASTPOSITION"] = 33 +sharedtasks_e["TASK_STORE_POSITION_IN_SAVEPOSITION"] = 34 +sharedtasks_e["TASK_STORE_BESTSOUND_IN_SAVEPOSITION"] = 35 +sharedtasks_e["TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION"] = 36 +sharedtasks_e["TASK_REACT_TO_COMBAT_SOUND"] = 37 +sharedtasks_e["TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION"] = 38 +sharedtasks_e["TASK_GET_PATH_TO_COMMAND_GOAL"] = 39 +sharedtasks_e["TASK_MARK_COMMAND_GOAL_POS"] = 40 +sharedtasks_e["TASK_CLEAR_COMMAND_GOAL"] = 41 +sharedtasks_e["TASK_GET_PATH_TO_LASTPOSITION"] = 42 +sharedtasks_e["TASK_GET_PATH_TO_SAVEPOSITION"] = 43 +sharedtasks_e["TASK_GET_PATH_TO_SAVEPOSITION_LOS"] = 44 +sharedtasks_e["TASK_GET_PATH_TO_RANDOM_NODE"] = 45 +sharedtasks_e["TASK_GET_PATH_TO_BESTSOUND"] = 46 +sharedtasks_e["TASK_GET_PATH_TO_BESTSCENT"] = 47 +sharedtasks_e["TASK_RUN_PATH"] = 48 +sharedtasks_e["TASK_WALK_PATH"] = 49 +sharedtasks_e["TASK_WALK_PATH_TIMED"] = 50 +sharedtasks_e["TASK_WALK_PATH_WITHIN_DIST"] = 51 +sharedtasks_e["TASK_WALK_PATH_FOR_UNITS"] = 52 +sharedtasks_e["TASK_RUN_PATH_FLEE"] = 53 +sharedtasks_e["TASK_RUN_PATH_TIMED"] = 54 +sharedtasks_e["TASK_RUN_PATH_FOR_UNITS"] = 55 +sharedtasks_e["TASK_RUN_PATH_WITHIN_DIST"] = 56 +sharedtasks_e["TASK_STRAFE_PATH"] = 57 +sharedtasks_e["TASK_CLEAR_MOVE_WAIT"] = 58 +sharedtasks_e["TASK_SMALL_FLINCH"] = 59 +sharedtasks_e["TASK_BIG_FLINCH"] = 60 +sharedtasks_e["TASK_DEFER_DODGE"] = 61 +sharedtasks_e["TASK_FACE_IDEAL"] = 62 +sharedtasks_e["TASK_FACE_REASONABLE"] = 63 +sharedtasks_e["TASK_FACE_PATH"] = 64 +sharedtasks_e["TASK_FACE_PLAYER"] = 65 +sharedtasks_e["TASK_FACE_ENEMY"] = 66 +sharedtasks_e["TASK_FACE_HINTNODE"] = 67 +sharedtasks_e["TASK_PLAY_HINT_ACTIVITY"] = 68 +sharedtasks_e["TASK_FACE_TARGET"] = 69 +sharedtasks_e["TASK_FACE_LASTPOSITION"] = 70 +sharedtasks_e["TASK_FACE_SAVEPOSITION"] = 71 +sharedtasks_e["TASK_FACE_AWAY_FROM_SAVEPOSITION"] = 72 +sharedtasks_e["TASK_SET_IDEAL_YAW_TO_CURRENT"] = 73 +sharedtasks_e["TASK_RANGE_ATTACK1"] = 74 +sharedtasks_e["TASK_RANGE_ATTACK2"] = 75 +sharedtasks_e["TASK_MELEE_ATTACK1"] = 76 +sharedtasks_e["TASK_MELEE_ATTACK2"] = 77 +sharedtasks_e["TASK_RELOAD"] = 78 +sharedtasks_e["TASK_SPECIAL_ATTACK1"] = 79 +sharedtasks_e["TASK_SPECIAL_ATTACK2"] = 80 +sharedtasks_e["TASK_FIND_HINTNODE"] = 81 +sharedtasks_e["TASK_FIND_LOCK_HINTNODE"] = 82 +sharedtasks_e["TASK_CLEAR_HINTNODE"] = 83 +sharedtasks_e["TASK_LOCK_HINTNODE"] = 84 +sharedtasks_e["TASK_SOUND_ANGRY"] = 85 +sharedtasks_e["TASK_SOUND_DEATH"] = 86 +sharedtasks_e["TASK_SOUND_IDLE"] = 87 +sharedtasks_e["TASK_SOUND_WAKE"] = 88 +sharedtasks_e["TASK_SOUND_PAIN"] = 89 +sharedtasks_e["TASK_SOUND_DIE"] = 90 +sharedtasks_e["TASK_SPEAK_SENTENCE"] = 91 +sharedtasks_e["TASK_WAIT_FOR_SPEAK_FINISH"] = 92 +sharedtasks_e["TASK_SET_ACTIVITY"] = 93 +sharedtasks_e["TASK_RANDOMIZE_FRAMERATE"] = 94 +sharedtasks_e["TASK_SET_SCHEDULE"] = 95 +sharedtasks_e["TASK_SET_FAIL_SCHEDULE"] = 96 +sharedtasks_e["TASK_SET_TOLERANCE_DISTANCE"] = 97 +sharedtasks_e["TASK_SET_ROUTE_SEARCH_TIME"] = 98 +sharedtasks_e["TASK_CLEAR_FAIL_SCHEDULE"] = 99 +sharedtasks_e["TASK_PLAY_SEQUENCE"] = 100 +sharedtasks_e["TASK_PLAY_PRIVATE_SEQUENCE"] = 101 +sharedtasks_e["TASK_PLAY_PRIVATE_SEQUENCE_FACE_ENEMY"] = 102 +sharedtasks_e["TASK_PLAY_SEQUENCE_FACE_ENEMY"] = 103 +sharedtasks_e["TASK_PLAY_SEQUENCE_FACE_TARGET"] = 104 +sharedtasks_e["TASK_FIND_COVER_FROM_BEST_SOUND"] = 105 +sharedtasks_e["TASK_FIND_COVER_FROM_ENEMY"] = 106 +sharedtasks_e["TASK_FIND_LATERAL_COVER_FROM_ENEMY"] = 107 +sharedtasks_e["TASK_FIND_BACKAWAY_FROM_SAVEPOSITION"] = 108 +sharedtasks_e["TASK_FIND_NODE_COVER_FROM_ENEMY"] = 109 +sharedtasks_e["TASK_FIND_NEAR_NODE_COVER_FROM_ENEMY"] = 110 +sharedtasks_e["TASK_FIND_FAR_NODE_COVER_FROM_ENEMY"] = 111 +sharedtasks_e["TASK_FIND_COVER_FROM_ORIGIN"] = 112 +sharedtasks_e["TASK_DIE"] = 113 +sharedtasks_e["TASK_WAIT_FOR_SCRIPT"] = 114 +sharedtasks_e["TASK_PUSH_SCRIPT_ARRIVAL_ACTIVITY"] = 115 +sharedtasks_e["TASK_PLAY_SCRIPT"] = 116 +sharedtasks_e["TASK_PLAY_SCRIPT_POST_IDLE"] = 117 +sharedtasks_e["TASK_ENABLE_SCRIPT"] = 118 +sharedtasks_e["TASK_PLANT_ON_SCRIPT"] = 119 +sharedtasks_e["TASK_FACE_SCRIPT"] = 120 +sharedtasks_e["TASK_PLAY_SCENE"] = 121 +sharedtasks_e["TASK_WAIT_RANDOM"] = 122 +sharedtasks_e["TASK_WAIT_INDEFINITE"] = 123 +sharedtasks_e["TASK_STOP_MOVING"] = 124 +sharedtasks_e["TASK_TURN_LEFT"] = 125 +sharedtasks_e["TASK_TURN_RIGHT"] = 126 +sharedtasks_e["TASK_REMEMBER"] = 127 +sharedtasks_e["TASK_FORGET"] = 128 +sharedtasks_e["TASK_WAIT_FOR_MOVEMENT"] = 129 +sharedtasks_e["TASK_WAIT_FOR_MOVEMENT_STEP"] = 130 +sharedtasks_e["TASK_WAIT_UNTIL_NO_DANGER_SOUND"] = 131 +sharedtasks_e["TASK_WEAPON_FIND"] = 132 +sharedtasks_e["TASK_WEAPON_PICKUP"] = 133 +sharedtasks_e["TASK_WEAPON_RUN_PATH"] = 134 +sharedtasks_e["TASK_WEAPON_CREATE"] = 135 +sharedtasks_e["TASK_ITEM_PICKUP"] = 136 +sharedtasks_e["TASK_ITEM_RUN_PATH"] = 137 +sharedtasks_e["TASK_USE_SMALL_HULL"] = 138 +sharedtasks_e["TASK_FALL_TO_GROUND"] = 139 +sharedtasks_e["TASK_WANDER"] = 140 +sharedtasks_e["TASK_FREEZE"] = 141 +sharedtasks_e["TASK_GATHER_CONDITIONS"] = 142 +sharedtasks_e["TASK_IGNORE_OLD_ENEMIES"] = 143 +sharedtasks_e["TASK_DEBUG_BREAK"] = 144 +sharedtasks_e["TASK_ADD_HEALTH"] = 145 +sharedtasks_e["TASK_ADD_GESTURE_WAIT"] = 146 +sharedtasks_e["TASK_ADD_GESTURE"] = 147 +sharedtasks_e["TASK_GET_PATH_TO_INTERACTION_PARTNER"] = 148 +sharedtasks_e["TASK_PRE_SCRIPT"] = 149 + +ai.GetTaskID = function( taskName ) + + return sharedtasks_e[taskName] + +end
\ No newline at end of file diff --git a/gamemode/player_class/player_army.lua b/gamemode/player_class/player_army.lua new file mode 100644 index 0000000..7e20c13 --- /dev/null +++ b/gamemode/player_class/player_army.lua @@ -0,0 +1,16 @@ + +AddCSLuaFile() + +local PLAYER = {} + +function PLAYER:GetHandsModel() + + return { model = "models/weapons/c_arms_cstrike.mdl", skin = 1, body = "0100000" } + +end + +function PLAYER:Spawn() + +end + +player_manager.RegisterClass( "player_army", PLAYER, "player_baseclass" )
\ No newline at end of file diff --git a/gamemode/player_class/player_base.lua b/gamemode/player_class/player_base.lua new file mode 100644 index 0000000..a470104 --- /dev/null +++ b/gamemode/player_class/player_base.lua @@ -0,0 +1,338 @@ + +AddCSLuaFile() + +DEFINE_BASECLASS( "player_default" ) + +local PLAYER = {} + +function PLAYER:GetHandsModel() + + return { model = "models/weapons/c_arms_cstrike.mdl", skin = 1, body = "0100000" } + +end + +function PLAYER:HandlePlayerJumping( velocity ) + + if ( self.Player:GetMoveType() == MOVETYPE_NOCLIP ) then + self.Player.m_bJumping = false; + return + end + + -- airwalk more like hl2mp, we airwalk until we have 0 velocity, then it's the jump animation + -- underwater we're alright we airwalking + if ( !self.Player.m_bJumping && !self.Player:OnGround() && self.Player:WaterLevel() <= 0 ) then + + if ( !self.Player.m_fGroundTime ) then + + self.Player.m_fGroundTime = CurTime() + + elseif (CurTime() - self.Player.m_fGroundTime) > 0 && velocity:Length2D() < 0.5 then + + self.Player.m_bJumping = true + self.Player.m_bFirstJumpFrame = false + self.Player.m_flJumpStartTime = 0 + + end + end + + if self.Player.m_bJumping then + + if self.Player.m_bFirstJumpFrame then + + self.Player.m_bFirstJumpFrame = false + self.Player:AnimRestartMainSequence() + + end + + if ( self.Player:WaterLevel() >= 2 ) || ( (CurTime() - self.Player.m_flJumpStartTime) > 0.2 && self.Player:OnGround() ) then + + self.Player.m_bJumping = false + self.Player.m_fGroundTime = nil + self.Player:AnimRestartMainSequence() + + end + + if self.Player.m_bJumping then + self.Player.CalcIdeal = ACT_MP_JUMP + return true + end + end + + return false +end + +function PLAYER:HandlePlayerDucking( velocity ) + + if ( !self.Player:Crouching() ) then return false end + + if ( velocity:Length2D() > 0.5 ) then + self.Player.CalcIdeal = ACT_MP_CROUCHWALK + else + self.Player.CalcIdeal = ACT_MP_CROUCH_IDLE + end + + return true + +end + +function PLAYER:HandlePlayerNoClipping( velocity ) + + if ( self.Player:InVehicle() ) then return end + + if ( self.Player:GetMoveType() != MOVETYPE_NOCLIP ) then + + if ( self.Player.m_bWasNoclipping ) then + + self.Player.m_bWasNoclipping = nil + self.Player:AnimResetGestureSlot( GESTURE_SLOT_CUSTOM ) + if ( CLIENT ) then self.Player:SetIK( true ); end + + end + + return + + end + + if ( !self.Player.m_bWasNoclipping ) then + + self.Player:AnimRestartGesture( GESTURE_SLOT_CUSTOM, ACT_GMOD_NOCLIP_LAYER, false ) + if ( CLIENT ) then self.Player:SetIK( false ); end + + end + + + return true + +end + +function PLAYER:HandlePlayerVaulting( velocity ) + + if ( velocity:Length() < 1000 ) then return end + if ( self.Player:IsOnGround() ) then return end + + self.Player.CalcIdeal = ACT_MP_SWIM + return true + +end + +function PLAYER:HandlePlayerSwimming( velocity ) + + if ( self.Player:WaterLevel() < 2 ) then + self.Player.m_bInSwim = false + return false + end + + if ( velocity:Length2D() > 10 ) then + self.Player.CalcIdeal = ACT_MP_SWIM + else + self.Player.CalcIdeal = ACT_MP_SWIM_IDLE + end + + self.Player.m_bInSwim = true + + return true + +end + +function PLAYER:HandlePlayerLanding( velocity, WasOnGround ) + + if ( self.Player:GetMoveType() == MOVETYPE_NOCLIP ) then return end + + if ( self.Player:IsOnGround() && !WasOnGround ) then + self.Player:AnimRestartGesture( GESTURE_SLOT_JUMP, ACT_LAND, true ); + end + +end + +function PLAYER:HandlePlayerDriving() + + return false + +end + +function PLAYER:UpdateAnimation( velocity, maxseqgroundspeed ) + + local len = velocity:Length() + local movement = 1.0 + + if ( len > 0.2 ) then + movement = ( len / maxseqgroundspeed ) + end + + rate = math.min( movement, 2 ) + + -- if we're under water we want to constantly be swimming.. + if ( self.Player:WaterLevel() >= 2 ) then + rate = math.max( rate, 0.5 ) + elseif ( !self.Player:IsOnGround() && len >= 1000 ) then + rate = 0.1; + end + + self.Player:SetPlaybackRate( rate ) + + if ( CLIENT ) then + self:GrabEarAnimation() + self:MouthMoveAnimation() + end + +end + +function PLAYER:GrabEarAnimation() + + self.Player.ChatGestureWeight = self.Player.ChatGestureWeight or 0 + + -- Don't show this when we're playing a taunt! + if ( self.Player:IsPlayingTaunt() ) then return end + + if ( self.Player:IsTyping() ) then + self.Player.ChatGestureWeight = math.Approach( self.Player.ChatGestureWeight, 1, FrameTime() * 5.0 ); + else + self.Player.ChatGestureWeight = math.Approach( self.Player.ChatGestureWeight, 0, FrameTime() * 5.0 ); + end + + if ( self.Player.ChatGestureWeight > 0 ) then + + self.Player:AnimRestartGesture( GESTURE_SLOT_VCD, ACT_GMOD_IN_CHAT, true ) + self.Player:AnimSetGestureWeight( GESTURE_SLOT_VCD, self.Player.ChatGestureWeight ) + + end + +end + +function PLAYER:MouthMoveAnimation() + + local FlexNum = self.Player:GetFlexNum() - 1 + if ( FlexNum <= 0 ) then return end + + for i=0, FlexNum-1 do + + local Name = self.Player:GetFlexName( i ) + + if ( Name == "jaw_drop" || Name == "right_part" || Name == "left_part" || Name == "right_mouth_drop" || Name == "left_mouth_drop" ) then + + if ( self.Player:IsSpeaking() ) then + self.Player:SetFlexWeight( i, math.Clamp( self.Player:VoiceVolume() * 2, 0, 2 ) ) + else + self.Player:SetFlexWeight( i, 0 ) + end + end + + end + +end + +function PLAYER:CalcMainActivity( velocity ) + + self.Player.CalcIdeal = ACT_MP_STAND_IDLE + self.Player.CalcSeqOverride = -1 + + self:HandlePlayerLanding( velocity, self.Player.m_bWasOnGround ); + + if ( self:HandlePlayerNoClipping( velocity ) || + self:HandlePlayerDriving() || + self:HandlePlayerVaulting( velocity ) || + self:HandlePlayerJumping( velocity ) || + self:HandlePlayerDucking( velocity ) || + self:HandlePlayerSwimming( velocity ) ) then + + else + + local len2d = velocity:Length2D() + if ( len2d > 150 ) then self.Player.CalcIdeal = ACT_MP_RUN elseif ( len2d > 0.5 ) then self.Player.CalcIdeal = ACT_MP_WALK end + + end + + -- a bit of a hack because we're missing ACTs for a couple holdtypes + local weapon = self.Player:GetActiveWeapon() + local ht = "pistol" + + if ( IsValid( weapon ) ) then ht = weapon:GetHoldType() end + + if ( self.Player.CalcIdeal == ACT_MP_CROUCH_IDLE && ( ht == "knife" || ht == "melee2" ) ) then + self.Player.CalcSeqOverride = self.Player:LookupSequence("cidle_" .. ht) + end + + self.Player.m_bWasOnGround = self.Player:IsOnGround() + self.Player.m_bWasNoclipping = (self.Player:GetMoveType() == MOVETYPE_NOCLIP) + + return self.Player.CalcIdeal, self.Player.CalcSeqOverride + +end + +local IdleActivity = ACT_HL2MP_IDLE +local IdleActivityTranslate = {} + IdleActivityTranslate [ ACT_MP_STAND_IDLE ] = IdleActivity + IdleActivityTranslate [ ACT_MP_WALK ] = IdleActivity+1 + IdleActivityTranslate [ ACT_MP_RUN ] = IdleActivity+2 + IdleActivityTranslate [ ACT_MP_CROUCH_IDLE ] = IdleActivity+3 + IdleActivityTranslate [ ACT_MP_CROUCHWALK ] = IdleActivity+4 + IdleActivityTranslate [ ACT_MP_ATTACK_STAND_PRIMARYFIRE ] = IdleActivity+5 + IdleActivityTranslate [ ACT_MP_ATTACK_CROUCH_PRIMARYFIRE ] = IdleActivity+5 + IdleActivityTranslate [ ACT_MP_RELOAD_STAND ] = IdleActivity+6 + IdleActivityTranslate [ ACT_MP_RELOAD_CROUCH ] = IdleActivity+6 + IdleActivityTranslate [ ACT_MP_JUMP ] = ACT_HL2MP_JUMP_SLAM + IdleActivityTranslate [ ACT_MP_SWIM_IDLE ] = ACT_MP_SWIM_IDLE + IdleActivityTranslate [ ACT_MP_SWIM ] = ACT_MP_SWIM + IdleActivityTranslate [ ACT_LAND ] = ACT_LAND + +function PLAYER:TranslateActivity( act ) + + local act = act + local newact = self.Player:TranslateWeaponActivity( act ) + + -- select idle anims if the weapon didn't decide + if ( act == newact ) then + return IdleActivityTranslate[ act ] + end + + return newact + +end + +function PLAYER:DoAnimationEvent( event, data ) + if event == PLAYERANIMEVENT_ATTACK_PRIMARY then + + if self.Player:Crouching() then + self.Player:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, true ) + else + self.Player:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_PRIMARYFIRE, true ) + end + + return ACT_VM_PRIMARYATTACK + + elseif event == PLAYERANIMEVENT_ATTACK_SECONDARY then + + -- there is no gesture, so just fire off the VM event + return ACT_VM_SECONDARYATTACK + + elseif event == PLAYERANIMEVENT_RELOAD then + + if self.Player:Crouching() then + self.Player:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH, true ) + else + self.Player:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND, true ) + end + + return ACT_INVALID + + elseif event == PLAYERANIMEVENT_JUMP then + + self.Player.m_bJumping = true + self.Player.m_bFirstJumpFrame = true + self.Player.m_flJumpStartTime = CurTime() + + self.Player:AnimRestartMainSequence() + + return ACT_INVALID + + elseif event == PLAYERANIMEVENT_CANCEL_RELOAD then + + self.Player:AnimResetGestureSlot( GESTURE_SLOT_ATTACK_AND_RELOAD ) + + return ACT_INVALID + end + + return nil +end + +player_manager.RegisterClass( "player_base", PLAYER, "player_default" )
\ No newline at end of file diff --git a/gamemode/player_class/player_default.lua b/gamemode/player_class/player_default.lua new file mode 100644 index 0000000..1a5f9b3 --- /dev/null +++ b/gamemode/player_class/player_default.lua @@ -0,0 +1,340 @@ + +AddCSLuaFile() + +DEFINE_BASECLASS( "player_default" ) + +local PLAYER = {} + +function PLAYER:HandlePlayerJumping( velocity ) + + if ( self.Player:GetMoveType() == MOVETYPE_NOCLIP ) then + self.Player.m_bJumping = false; + return + end + + -- airwalk more like hl2mp, we airwalk until we have 0 velocity, then it's the jump animation + -- underwater we're alright we airwalking + if ( !self.Player.m_bJumping && !self.Player:OnGround() && self.Player:WaterLevel() <= 0 ) then + + if ( !self.Player.m_fGroundTime ) then + + self.Player.m_fGroundTime = CurTime() + + elseif (CurTime() - self.Player.m_fGroundTime) > 0 && velocity:Length2D() < 0.5 then + + self.Player.m_bJumping = true + self.Player.m_bFirstJumpFrame = false + self.Player.m_flJumpStartTime = 0 + + end + end + + if self.Player.m_bJumping then + + if self.Player.m_bFirstJumpFrame then + + self.Player.m_bFirstJumpFrame = false + self.Player:AnimRestartMainSequence() + + end + + if ( self.Player:WaterLevel() >= 2 ) || ( (CurTime() - self.Player.m_flJumpStartTime) > 0.2 && self.Player:OnGround() ) then + + self.Player.m_bJumping = false + self.Player.m_fGroundTime = nil + self.Player:AnimRestartMainSequence() + + end + + if self.Player.m_bJumping then + self.Player.CalcIdeal = ACT_MP_JUMP + return true + end + end + + return false +end + +function PLAYER:HandlePlayerDucking( velocity ) + + if ( !self.Player:Crouching() ) then return false end + + if ( velocity:Length2D() > 0.5 ) then + self.Player.CalcIdeal = ACT_MP_CROUCHWALK + else + self.Player.CalcIdeal = ACT_MP_CROUCH_IDLE + end + + return true + +end + +function PLAYER:HandlePlayerNoClipping( velocity ) + + if ( self.Player:InVehicle() ) then return end + + if ( self.Player:GetMoveType() != MOVETYPE_NOCLIP ) then + + if ( self.Player.m_bWasNoclipping ) then + + self.Player.m_bWasNoclipping = nil + self.Player:AnimResetGestureSlot( GESTURE_SLOT_CUSTOM ) + if ( CLIENT ) then self.Player:SetIK( true ); end + + end + + return + + end + + if ( !self.Player.m_bWasNoclipping ) then + + self.Player:AnimRestartGesture( GESTURE_SLOT_CUSTOM, ACT_GMOD_NOCLIP_LAYER, false ) + if ( CLIENT ) then self.Player:SetIK( false ); end + + end + + + return true + +end + +function PLAYER:HandlePlayerVaulting( velocity ) + + if ( velocity:Length() < 1000 ) then return end + if ( self.Player:IsOnGround() ) then return end + + self.Player.CalcIdeal = ACT_MP_SWIM + return true + +end + +function PLAYER:HandlePlayerSwimming( velocity ) + + if ( self.Player:WaterLevel() < 2 ) then + self.Player.m_bInSwim = false + return false + end + + if ( velocity:Length2D() > 10 ) then + self.Player.CalcIdeal = ACT_MP_SWIM + else + self.Player.CalcIdeal = ACT_MP_SWIM_IDLE + end + + self.Player.m_bInSwim = true + + return true + +end + +function PLAYER:HandlePlayerLanding( velocity, WasOnGround ) + + if ( self.Player:GetMoveType() == MOVETYPE_NOCLIP ) then return end + + if ( self.Player:IsOnGround() && !WasOnGround ) then + self.Player:AnimRestartGesture( GESTURE_SLOT_JUMP, ACT_LAND, true ); + end + +end + +function PLAYER:HandlePlayerDriving() + + return false + +end + +function PLAYER:UpdateAnimation( velocity, maxseqgroundspeed ) + + local len = velocity:Length() + local movement = 1.0 + + if ( len > 0.2 ) then + movement = ( len / maxseqgroundspeed ) + end + + rate = math.min( movement, 2 ) + + -- if we're under water we want to constantly be swimming.. + if ( self.Player:WaterLevel() >= 2 ) then + rate = math.max( rate, 0.5 ) + elseif ( !self.Player:IsOnGround() && len >= 1000 ) then + rate = 0.1; + end + + self.Player:SetPlaybackRate( rate ) + + if ( CLIENT ) then + self:GrabEarAnimation() + self:MouthMoveAnimation() + end + +end + +-- +-- If you don't want the player to grab his ear in your gamemode then +-- just override this. +-- +function PLAYER:GrabEarAnimation() + + self.Player.ChatGestureWeight = self.Player.ChatGestureWeight or 0 + + -- Don't show this when we're playing a taunt! + if ( self.Player:IsPlayingTaunt() ) then return end + + if ( self.Player:IsTyping() ) then + self.Player.ChatGestureWeight = math.Approach( self.Player.ChatGestureWeight, 1, FrameTime() * 5.0 ); + else + self.Player.ChatGestureWeight = math.Approach( self.Player.ChatGestureWeight, 0, FrameTime() * 5.0 ); + end + + if ( self.Player.ChatGestureWeight > 0 ) then + + self.Player:AnimRestartGesture( GESTURE_SLOT_VCD, ACT_GMOD_IN_CHAT, true ) + self.Player:AnimSetGestureWeight( GESTURE_SLOT_VCD, self.Player.ChatGestureWeight ) + + end + +end + +-- +-- Moves the mouth when talking on voicecom +-- +function PLAYER:MouthMoveAnimation() + + local FlexNum = self.Player:GetFlexNum() - 1 + if ( FlexNum <= 0 ) then return end + + for i=0, FlexNum-1 do + + local Name = self.Player:GetFlexName( i ) + + if ( Name == "jaw_drop" || Name == "right_part" || Name == "left_part" || Name == "right_mouth_drop" || Name == "left_mouth_drop" ) then + + if ( self.Player:IsSpeaking() ) then + self.Player:SetFlexWeight( i, math.Clamp( self.Player:VoiceVolume() * 2, 0, 2 ) ) + else + self.Player:SetFlexWeight( i, 0 ) + end + end + + end + +end + +function PLAYER:CalcMainActivity( velocity ) + + self.Player.CalcIdeal = ACT_MP_STAND_IDLE + self.Player.CalcSeqOverride = -1 + + self:HandlePlayerLanding( velocity, self.Player.m_bWasOnGround ); + + if ( self:HandlePlayerNoClipping( velocity ) || + self:HandlePlayerDriving() || + self:HandlePlayerVaulting( velocity ) || + self:HandlePlayerJumping( velocity ) || + self:HandlePlayerDucking( velocity ) || + self:HandlePlayerSwimming( velocity ) ) then + + else + + local len2d = velocity:Length2D() + if ( len2d > 150 ) then self.Player.CalcIdeal = ACT_MP_RUN elseif ( len2d > 0.5 ) then self.Player.CalcIdeal = ACT_MP_WALK end + + end + + -- a bit of a hack because we're missing ACTs for a couple holdtypes + local weapon = self.Player:GetActiveWeapon() + local ht = "pistol" + + if ( IsValid( weapon ) ) then ht = weapon:GetHoldType() end + + if ( self.Player.CalcIdeal == ACT_MP_CROUCH_IDLE && ( ht == "knife" || ht == "melee2" ) ) then + self.Player.CalcSeqOverride = self.Player:LookupSequence("cidle_" .. ht) + end + + self.Player.m_bWasOnGround = self.Player:IsOnGround() + self.Player.m_bWasNoclipping = (self.Player:GetMoveType() == MOVETYPE_NOCLIP) + + return self.Player.CalcIdeal, self.Player.CalcSeqOverride + +end + +local IdleActivity = ACT_HL2MP_IDLE +local IdleActivityTranslate = {} + IdleActivityTranslate [ ACT_MP_STAND_IDLE ] = IdleActivity + IdleActivityTranslate [ ACT_MP_WALK ] = IdleActivity+1 + IdleActivityTranslate [ ACT_MP_RUN ] = IdleActivity+2 + IdleActivityTranslate [ ACT_MP_CROUCH_IDLE ] = IdleActivity+3 + IdleActivityTranslate [ ACT_MP_CROUCHWALK ] = IdleActivity+4 + IdleActivityTranslate [ ACT_MP_ATTACK_STAND_PRIMARYFIRE ] = IdleActivity+5 + IdleActivityTranslate [ ACT_MP_ATTACK_CROUCH_PRIMARYFIRE ] = IdleActivity+5 + IdleActivityTranslate [ ACT_MP_RELOAD_STAND ] = IdleActivity+6 + IdleActivityTranslate [ ACT_MP_RELOAD_CROUCH ] = IdleActivity+6 + IdleActivityTranslate [ ACT_MP_JUMP ] = ACT_HL2MP_JUMP_SLAM + IdleActivityTranslate [ ACT_MP_SWIM_IDLE ] = ACT_MP_SWIM_IDLE + IdleActivityTranslate [ ACT_MP_SWIM ] = ACT_MP_SWIM + IdleActivityTranslate [ ACT_LAND ] = ACT_LAND + +-- it is preferred you return ACT_MP_* in CalcMainActivity, and if you have a specific need to not tranlsate through the weapon do it here +function PLAYER:TranslateActivity( act ) + + local act = act + local newact = self.Player:TranslateWeaponActivity( act ) + + -- select idle anims if the weapon didn't decide + if ( act == newact ) then + return IdleActivityTranslate[ act ] + end + + return newact + +end + +function PLAYER:DoAnimationEvent( event, data ) + if event == PLAYERANIMEVENT_ATTACK_PRIMARY then + + if self.Player:Crouching() then + self.Player:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, true ) + else + self.Player:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_PRIMARYFIRE, true ) + end + + return ACT_VM_PRIMARYATTACK + + elseif event == PLAYERANIMEVENT_ATTACK_SECONDARY then + + -- there is no gesture, so just fire off the VM event + return ACT_VM_SECONDARYATTACK + + elseif event == PLAYERANIMEVENT_RELOAD then + + if self.Player:Crouching() then + self.Player:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH, true ) + else + self.Player:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND, true ) + end + + return ACT_INVALID + + elseif event == PLAYERANIMEVENT_JUMP then + + self.Player.m_bJumping = true + self.Player.m_bFirstJumpFrame = true + self.Player.m_flJumpStartTime = CurTime() + + self.Player:AnimRestartMainSequence() + + return ACT_INVALID + + elseif event == PLAYERANIMEVENT_CANCEL_RELOAD then + + self.Player:AnimResetGestureSlot( GESTURE_SLOT_ATTACK_AND_RELOAD ) + + return ACT_INVALID + end + + return nil +end + +player_manager.RegisterClass( "player_baseclass", PLAYER, "player_default" )
\ No newline at end of file diff --git a/gamemode/player_class/player_zombie.lua b/gamemode/player_class/player_zombie.lua new file mode 100644 index 0000000..f8333b1 --- /dev/null +++ b/gamemode/player_class/player_zombie.lua @@ -0,0 +1,93 @@ + +AddCSLuaFile() + +local PLAYER = {} + +function PLAYER:UpdateAnimation( velocity, maxseqgroundspeed ) + + local len = velocity:Length() + local movement = 1.0 + + if len > 0.2 then + + movement = len / maxseqgroundspeed + + end + + rate = math.min( movement, 2 ) + + if self.Player:WaterLevel() >= 2 then + + rate = math.max( rate, 0.5 ) + + elseif !self.Player:IsOnGround() and len >= 1000 then + + rate = 0.1 + + end + + local weapon = self.Player:GetActiveWeapon() + + self.Player:SetPlaybackRate( rate ) + + if CLIENT then + + self:GrabEarAnimation() + self:MouthMoveAnimation() + + end + +end + +function PLAYER:CalcMainActivity( velocity ) + + self.Player.CalcIdeal = ACT_MP_STAND_IDLE + self.Player.CalcSeqOverride = self.Player:LookupSequence( "zombie_idle" ) + + local len2d = velocity:Length2D() + + if len2d > 1 then + + self.Player.CalcSeqOverride = self.Player:LookupSequence( "zombie_run" ) + + end + + return self.Player.CalcIdeal, self.Player.CalcSeqOverride + +end + +function PLAYER:DoAnimationEvent( event, data ) + + if event == PLAYERANIMEVENT_ATTACK_PRIMARY then + + self.Player:AnimRestartGesture( GESTURE_SLOT_CUSTOM, ACT_GMOD_GESTURE_RANGE_ZOMBIE, true ) + + return ACT_VM_PRIMARYATTACK + + elseif event == PLAYERANIMEVENT_ATTACK_SECONDARY then + + return ACT_VM_SECONDARYATTACK + + elseif event == PLAYERANIMEVENT_JUMP then + + self.Player.m_bJumping = true + self.Player.m_bFirstJumpFrame = true + self.Player.m_flJumpStartTime = CurTime() + + self.Player:AnimRestartMainSequence() + + return ACT_INVALID + + elseif event >= PLAYERANIMEVENT_FLINCH_CHEST and event <= PLAYERANIMEVENT_FLINCH_RIGHTLEG then + + self.Player:AnimRestartGesture( GESTURE_SLOT_FLINCH, ACT_FLINCH_PHYSICS, true ) + + return ACT_INVALID + + end + + return nil + +end + +player_manager.RegisterClass( "player_zombie", PLAYER, "player_base" )
\ No newline at end of file diff --git a/gamemode/ply_extension.lua b/gamemode/ply_extension.lua new file mode 100644 index 0000000..ba322df --- /dev/null +++ b/gamemode/ply_extension.lua @@ -0,0 +1,1386 @@ + +local meta = FindMetaTable( "Player" ) +if (!meta) then return end + +function meta:Notice( text, col, len, delay, once ) + if CLIENT then return end + if delay then + + local function Notice( ply, col, len ) + + if not IsValid( ply ) then return end + + umsg.Start( "ToxNotice", ply ) + umsg.String( text ) + umsg.Short( col.r ) + umsg.Short( col.g ) + umsg.Short( col.b ) + umsg.Short( len or 3 ) + umsg.Bool( tobool( once ) ) + umsg.End() + + end + + timer.Simple( delay, function() Notice( self, col, len ) end ) + + return + + end + + umsg.Start( "ToxNotice", self ) + umsg.String( text ) + umsg.Short( col.r ) + umsg.Short( col.g ) + umsg.Short( col.b ) + umsg.Short( len or 3 ) + umsg.Bool( tobool( once ) ) + umsg.End() + +end + +function meta:NoticeOnce( text, col, len, delay ) + + local crc = util.CRC( self:SteamID() .. text ) + + if not table.HasValue( self.NoticeList or {}, crc ) then + + self:Notice( text, col, len, delay, true ) + + self.NoticeList = self.NoticeList or {} + table.insert( self.NoticeList, crc ) + + end + +end + +function meta:DrawBlood( num ) + + num = num or math.random(1,3) + + umsg.Start( "BloodStain", self ) + umsg.Short( num ) + umsg.End() + +end + +function meta:ClientSound( snd, pitch ) + + umsg.Start( "Radio", self ) + umsg.Short( ( pitch or 100 ) ) + umsg.String( snd ) + umsg.End() + + //self:SendLua( "LocalPlayer():EmitSound( \"" .. snd .. "\", 100, " .. ( pitch or 100 ) .. " )" ) + +end + +function meta:VoiceSound( snd, lvl, pitch ) + + if ( self.SoundDelay or 0 ) < CurTime() then + + self.SoundDelay = CurTime() + 1.25 + self:EmitSound( snd, lvl, pitch ) + + end + +end + +function meta:RadioSound( vtype, override ) + + if not self:Alive() then return end + + if ( ( self.RadioTimer or 0 ) < CurTime() or override ) then + + local sound = table.Random( GAMEMODE.Radio[ vtype ] ) + + self:EmitSound( table.Random( GAMEMODE.VoiceStart ), math.random( 90, 110 ) ) + timer.Simple( 0.2, function() if IsValid( self ) then self:EmitSound( sound, 90 ) end end ) + timer.Simple( SoundDuration( sound ) + math.Rand( 0.6, 0.8 ), function() if IsValid( self ) then self:EmitSound( table.Random( GAMEMODE.VoiceEnd ), math.random( 90, 110 ) ) end end ) + + self.RadioTimer = CurTime() + SoundDuration( sound ) + 1 + + end + +end + +function meta:VoiceThink() + + if ( self.VoiceTbl[ VO_IDLE ] or 0 ) < CurTime() then + + if GAMEMODE.EvacAlert then + + self:RadioSound( VO_EVAC ) + + else + + self:RadioSound( VO_IDLE ) + + end + + self.VoiceTbl[ VO_IDLE ] = CurTime() + math.Rand( 120, 240 ) + + end + + if ( self.VoiceTbl[ VO_ALERT ] or 0 ) < CurTime() then + + self.VoiceTbl[ VO_ALERT ] = CurTime() + math.Rand( 120, 240 ) + + for k,v in pairs( ents.FindByClass( "npc_zombie*" ) ) do + + if v:GetPos():Distance( self:GetPos() ) < 100 then + + self:RadioSound( VO_ALERT ) + + end + + end + + end + +end + +function meta:GetWeight() + return 0//self:GetNWFloat( "Weight", 0 ) +end + +function meta:SetWeight( num ) + //self:SetNWFloat( "Weight", num ) +end + +function meta:AddWeight( num ) + //self:SetWeight( self:GetWeight() + num ) +end + +function meta:GetAmmo( ammotype ) + return self:GetNWInt( "Ammo"..ammotype, 0 ) +end + +function meta:SetAmmo( ammotype, num ) + self:SetNWInt( "Ammo"..ammotype, num ) +end + +function meta:AddAmmo( ammotype, num, dropfunc ) + + self:SetAmmo( ammotype, self:GetAmmo( ammotype ) + num ) + + for k,v in pairs( item.GetByType( ITEM_AMMO ) ) do + + if v.Ammo == ammotype and num < 0 and not dropfunc then + + local count = math.floor( self:GetAmmo( ammotype ) / v.Amount ) + + while self:HasItem( v.ID ) and self:GetItemCount( v.ID ) > count do + + self:RemoveFromInventory( v.ID ) + + end + + end + + end + +end + +function meta:GetStats() + + return self.Stats or {} + +end + +function meta:InitStats() + + self.Stats = {} + +end + +function meta:AddStat( name, count ) + + count = count or 1 + + self:SetStat( name, self:GetStat( name ) + count ) + +end + +function meta:GetStat( name ) + + if not self.Stats then + + self:InitStats() + + end + + return self.Stats[ name ] or 0 + +end + +function meta:SetStat( name, count ) + + self.Stats[ name ] = count + +end + +function meta:GetCash() + return self:GetNWInt( "Cash", 0 ) +end + +function meta:SetCash( num ) + self:SetNWInt( "Cash", math.Clamp( num, -32000, 32000 ) ) +end + +function meta:AddCash( num ) + + if self:Team() == TEAM_ZOMBIES then return end + + self:SetCash( self:GetCash() + num ) + + if num < 0 then + + self:EmitSound( Sound( "Chain.ImpactSoft" ), 100, math.random( 90, 110 ) ) + self:AddStat( "Spent", -num ) + + else + + if num > 1 then + + self:Notice( "+" .. num .. " " .. GAMEMODE.CurrencyName .. "s", GAMEMODE.Colors.Yellow ) + + elseif num != 0 then + + self:Notice( "+" .. num .. " " .. GAMEMODE.CurrencyName, GAMEMODE.Colors.Yellow ) + + end + + end + +end + +function meta:HasMelee() + + local wep = self:GetActiveWeapon() + + if IsValid( wep ) then + + if wep.WorldModel == "models/weapons/w_hammer.mdl" or wep.WorldModel == "models/weapons/w_knife_t.mdl" or wep.WorldModel == "models/weapons/w_axe.mdl" then + + return true + + end + + end + + return false + +end + +function meta:HasShotgun() + + local wep = self:GetActiveWeapon() + + if IsValid( wep ) then + + if wep.AmmoType == "Buckshot" or wep.WorldModel == "models/weapons/w_snip_awp.mdl" then + + return true + + end + + end + + return false + +end + +function meta:AddHeadshot() + + if self:HasShotgun() then return end + + self.Headshots = ( self.Headshots or 0 ) + 1 + + self:AddStat( "Headshot" ) + + if GAMEMODE.HeadshotCombos[ self.Headshots ] then + + self:Notice( self.Headshots .. " headshot combo", GAMEMODE.Colors.Blue ) + self:AddCash( GAMEMODE.HeadshotCombos[ self.Headshots ] ) + + end + +end + +function meta:ResetHeadshots() + + self.Headshots = 0 + +end + +function meta:ViewBounce( scale ) + self:ViewPunch( Angle( math.Rand( -0.2, -0.1 ) * scale, math.Rand( -0.05, 0.05 ) * scale, 0 ) ) +end + +function meta:GetStamina() + return self:GetNWInt( "Stamina", 0 ) +end + +function meta:SetStamina( num ) + self:SetNWInt( "Stamina", math.Clamp( num, 0, 150 ) ) +end + +function meta:AddStamina( num ) + self:SetStamina( self:GetStamina() + num ) +end + +function meta:GetRadiation() + return self:GetNWInt( "Radiation", 0 ) +end + +function meta:SetRadiation( num ) + + self:SetNWInt( "Radiation", math.Clamp( num, 0, 5 ) ) + +end + +function meta:AddRadiation( num ) + + if self:Team() != TEAM_ARMY then return end + + if self:HasItem( "models/items/combine_rifle_cartridge01.mdl" ) and num > 0 then return end + + if num > 0 then + + self.PoisonFade = CurTime() + 30 + + self:EmitSound( table.Random{ "Geiger.BeepLow", "Geiger.BeepHigh" }, 100, math.random( 90, 110 ) ) + + self:NoticeOnce( "You have been irradiated", GAMEMODE.Colors.Red, 7 ) + self:NoticeOnce( "Radiation sickness will fade over time", GAMEMODE.Colors.Blue, 7, 2 ) + + local ed = EffectData() + ed:SetEntity( self ) + util.Effect( "radiation", ed, true, true ) + + self:AddStat( "Rad", num ) + + end + + self:SetRadiation( self:GetRadiation() + num ) + +end + +function meta:AddHealth( num ) + + if self:Health() + num <= 0 then + + self:Kill() + return + + end + + self:SetHealth( math.Clamp( self:Health() + num, 1, self:GetMaxHealth() ) ) + +end + +function meta:SetInfected( bool ) + + if self:Team() != TEAM_ARMY then bool = false end + + if bool then + + self:NoticeOnce( "You have been infected", GAMEMODE.Colors.Red, 7 ) + self:NoticeOnce( "You can cure your infection with the antidote", GAMEMODE.Colors.Blue, 7, 2 ) + self:NoticeOnce( "The antidote location is marked on your screen", GAMEMODE.Colors.Blue, 7, 4 ) + + self:AddStat( "Infections" ) + + end + + self:SetNWBool( "Infected", bool ) + +end + +function meta:IsInfected() + return self:GetNWBool( "Infected", false ) +end + +function meta:SetBleeding( bool ) + + if self:Team() != TEAM_ARMY then bool = false end + + if bool and IsValid( self.Stash ) and ( string.find( self.Stash:GetClass(), "npc" ) or self.Stash:GetClass() == "info_storage" ) then return end + + if bool then + + self:NoticeOnce( "You are bleeding to death", GAMEMODE.Colors.Red, 7 ) + self:NoticeOnce( "You can cover wounds with bandages", GAMEMODE.Colors.Blue, 7, 2 ) + + end + + self:SetNWBool( "Bleeding", bool ) + +end + +function meta:IsBleeding() + return self:GetNWBool( "Bleeding", false ) +end + +function meta:SetPlayerClass( num ) + self.Class = num +end + +function meta:GetPlayerClass() + return self.Class or CLASS_SCOUT +end + +function meta:IsIndoors() + + local tr = util.TraceLine( util.GetPlayerTrace( self, Vector(0,0,1) ) ) + + if tr.HitSky or not tr.Hit then return false end + + return true + +end + +function meta:SetLord( bool ) + + self:SetNWBool( "Lord", bool ) + +end + +function meta:IsLord() + + return self:GetNWBool( "Lord", false ) + +end + +function meta:SetZedDamage( num ) + + self:SetNWInt( "ZedDamage", num ) + +end + +function meta:GetZedDamage() + + return self:GetNWInt( "ZedDamage", 0 ) + +end + +function meta:AddZedDamage( num ) + + self:AddStat( "ZedDamage", num ) + + if self:IsLord() then + + self:SetZedDamage( self:GetZedDamage() + num ) + + if self:GetZedDamage() >= GAMEMODE.RedemptionDamage then + + self:NoticeOnce( "You have redeemed yourself", GAMEMODE.Colors.Green, 5 ) + self:NoticeOnce( "You will respawn as a human", GAMEMODE.Colors.Green, 5, 2 ) + + else + + self:Notice( "+" .. num .. " " .. GAMEMODE.BloodName, GAMEMODE.Colors.Green, 5 ) + + end + + end + +end + +function meta:Gib() + + if not self:Alive() then return end + + local dmg = DamageInfo() + dmg:SetDamage( 500 ) + dmg:SetDamageType( DMG_BLAST ) + dmg:SetAttacker( self ) + dmg:SetInflictor( self ) + + self:TakeDamageInfo( dmg ) + +end + +function meta:OnSpawn() + + self.VoiceTbl = {} + self.VoiceTbl[ VO_IDLE ] = CurTime() + math.random( 30, 60 ) + self.VoiceTbl[ VO_ALERT ] = CurTime() + math.random( 30, 60 ) + + self:SetRadiation( 0 ) + self:SetInfected( false ) + self:SetBleeding( false ) + self:SetJumpPower( 200 ) + + if self:Team() == TEAM_ARMY then + + player_manager.SetPlayerClass( self, "player_base" ) + + if self:GetPlayerClass() == CLASS_SCOUT then + + self:SetCash( 25 ) + + else + + self:SetCash( 15 ) + + end + + if self:IsLord() then + + self:SetCash( 200 ) + + end + + self:InitStats() + self:SetEvacuated( false ) + self:SetLord( false ) + + self:SetMaxHealth( 150 ) + self:SetHealth( 150 ) + + self:SetStamina( 150 ) + + self:SetWalkSpeed( GAMEMODE.WalkSpeed ) + self:SetRunSpeed( GAMEMODE.RunSpeed ) + + self:SetModel( GAMEMODE.ClassModels[ self:GetPlayerClass() ] ) + + else + + player_manager.SetPlayerClass( self, "player_zombie" ) + + if self.NextClass then + + self:SetPlayerClass( self.NextClass ) + + self.NextClass = nil + + end + + if self:IsLord() then + + self:NoticeOnce( "Harm the humans to fill your blood meter", GAMEMODE.Colors.Blue, 7, 15 ) + self:NoticeOnce( "Once your meter is full you will be redeemed", GAMEMODE.Colors.Blue, 7, 17 ) + self:NoticeOnce( "Killing a human will fill your meter faster", GAMEMODE.Colors.Blue, 7, 19 ) + + end + + self:SetMaxHealth( GAMEMODE.ZombieHealth[ self:GetPlayerClass() ] ) + self:SetHealth( GAMEMODE.ZombieHealth[ self:GetPlayerClass() ] ) + + self:SetWalkSpeed( GAMEMODE.ZombieSpeed[ self:GetPlayerClass() ] ) + self:SetRunSpeed( GAMEMODE.ZombieSpeed[ self:GetPlayerClass() ] ) + + self:SetModel( GAMEMODE.ZombieModels[ self:GetPlayerClass() ] ) + + self:NoticeOnce( "You can choose your class by pressing F2", GAMEMODE.Colors.Blue, 7, 2 ) + + end + +end + +function meta:GetItemLoadout() + + return GAMEMODE.ClassLoadouts[ self:GetPlayerClass() ] + +end + +function meta:OnLoadout() // this code is terrible, i just cant be arsed to tidy it up + + if self:Team() == TEAM_ARMY then + + self:GiveAmmo( 200, "Pistol" ) + self:Give( "rad_knife" ) + //self:Give( "rad_inv" ) + + local gun = ents.Create( "prop_physics" ) + gun:SetPos( self:GetPos() ) + gun:SetModel( GAMEMODE.ClassWeapons[ self:GetPlayerClass() ] ) + gun:Spawn() + + self:AddToInventory( gun ) + + local ammobox = ents.Create( "prop_physics" ) + ammobox:SetPos( self:GetPos() ) + ammobox:SetModel( "models/items/357ammo.mdl" ) + ammobox:Spawn() + + self:AddToInventory( ammobox ) + + if self:GetPlayerClass() == CLASS_ENGINEER then + + local hammer = ents.Create( "prop_physics" ) + hammer:SetPos( self:GetPos() ) + hammer:SetModel( "models/weapons/w_hammer.mdl" ) + hammer:Spawn() + + self:AddToInventory( hammer ) + + end + + local load = self:GetItemLoadout() + local items = {} + + for k,v in pairs( load ) do + + local tbl = item.RandomItem( v ) + + table.insert( items, tbl.ID ) + + end + + self:AddMultipleToInventory( items ) + + else + + self:Give( GAMEMODE.ZombieWeapons[ self:GetPlayerClass() ] ) + + end + +end + +function meta:GetDroppedItems() + + local inv = self:GetInventory() + + if not inv[1] then + + local rand = item.RandomItem( ITEM_BUYABLE ) + + return { rand.ID } + + end + + return inv + +end + +function meta:DropLoot() + + if not self:GetInventory() then return end + + local tbl = self:GetDroppedItems() + local gun = nil + + for k,v in pairs( tbl ) do + + local itbl = item.GetByID( v ) + + if itbl.Weapon then + + gun = itbl.Model + table.remove( tbl, k ) + + break + + end + + end + + if gun then + + local prop = ents.Create( "sent_droppedgun" ) + prop:SetPos( self:GetPos() + Vector(0,0,40) ) + prop:SetModel( gun ) + prop:Spawn() + + local phys = prop:GetPhysicsObject() + + if IsValid( phys ) then + + phys:ApplyForceCenter( self:GetAngles():Forward() * 200 ) + + end + + end + + local ent = ents.Create( "sent_lootbag" ) + + for k,v in pairs( tbl ) do + + ent:AddItem( v ) + + end + + ent:SetPos( self:GetPos() + Vector(0,0,25) ) + ent:SetAngles( self:GetForward():Angle() ) + ent:SetRemoval( 60 * 5 ) + ent:Spawn() + ent:SetCash( self:GetCash() ) + +end + +function meta:DoIgnite( att ) + + if self:OnFire() then return end + + self.BurnTime = CurTime() + 5 + self.BurnAttacker = att + + local ed = EffectData() + ed:SetEntity( self ) + util.Effect( "immolate", ed, true, true ) + + self:EmitSound( table.Random( GAMEMODE.Burning ), 100, 80 ) + +end + +function meta:OnFire() + + return ( self.BurnTime or 0 ) > CurTime() + +end + +function meta:Think() + + if not self:Alive() then return end + + if self:OnFire() and ( self.BurnInt or 0 ) < CurTime() then + + self.BurnInt = CurTime() + 0.5 + + if self:Team() == TEAM_ARMY then + + local dmginfo = DamageInfo() + dmginfo:SetDamage( math.random(1,5) ) + dmginfo:SetDamageType( DMG_BURN ) + dmginfo:SetAttacker( self ) + + self:TakeDamageInfo( dmginfo ) + + elseif IsValid( self.BurnAttacker ) then + + self:TakeDamage( 5, self.BurnAttacker ) + + end + + end + + if self:Team() == TEAM_ZOMBIES then + + if ( self.HealTime or 0 ) < CurTime() then + + self.HealTime = CurTime() + 1.0 + + if self:IsLord() then + + self:AddHealth( 4 ) + + else + + self:AddHealth( 2 ) + + end + + end + + return + + end + + self:VoiceThink() + + if ( self.HealTime or 0 ) < CurTime() then // health regen - affected by bleeding and infection + + self.HealTime = CurTime() + 3.0 + + if self:IsInfected() and math.random(1,4) == 1 then + + if self:Health() > 75 then + + self:AddStamina( -4 ) + self:AddHealth( -4 ) + + else + + self:AddStamina( -3 ) + self:AddHealth( -3 ) + + end + + self:ViewBounce( math.random( 10, 20 ) ) + self:VoiceSound( table.Random( GAMEMODE.Coughs ), 100, math.random( 90, 100 ) ) + + end + + if self:IsBleeding() then + + self:AddHealth( -1 ) + self.HealTime = CurTime() + 2.0 + + elseif not self:IsBleeding() and not self:IsInfected() and self:GetRadiation() < 1 and self:Health() > 50 then // health regen only works if you arent affected by anything and >50 hp + + self:AddHealth( 1 ) + + end + + end + + if ( self.PoisonTime or 0 ) < CurTime() then // radiation + + self.PoisonTime = CurTime() + 1.5 + + if self:GetRadiation() > 0 then + + local paintbl = { 0, 0, -1, -2, -2 } + local stamtbl = { -1, -2, -2, -2, -3 } + + self:AddHealth( paintbl[ self:GetRadiation() ] ) + self:AddStamina( stamtbl[ self:GetRadiation() ] ) + + if ( self.PoisonFade or 0 ) < CurTime() then + + self:AddRadiation( -1 ) + + self.PoisonFade = CurTime() + 20 + + end + + end + + end + + if ( self.StamTime or 0 ) < CurTime() then + + self.StamTime = CurTime() + 1.0 + + if self:KeyDown( IN_SPEED ) and self:GetVelocity():Length() > 1 then + + self:AddStamina( -1 ) + self.StamTime = CurTime() + 0.2 + + elseif self:GetRadiation() < 1 then + + self:AddStamina( 1 ) + + if self:GetPlayerClass() == CLASS_SCOUT then + + self.StamTime = CurTime() + 0.85 + + end + + if self:GetStamina() <= 50 or self:IsInfected() then + + self.StamTime = CurTime() + 1.35 + + if self:IsInfected() then + + self:NoticeOnce( "The infection slows your stamina regeneration", GAMEMODE.Colors.Red, 5 ) + + else + + self:NoticeOnce( "Your stamina has dropped below 30%", GAMEMODE.Colors.Red, 5 ) + self:NoticeOnce( "Stamina replenishes slower when below 30%", GAMEMODE.Colors.Blue, 5, 2 ) + + end + + end + + end + + end + +end + +function meta:AddToShipment( tbl ) + + self.Shipment = table.Add( self.Shipment, tbl ) + +end + +function meta:RemoveFromShipment( id ) + + for k,v in pairs( self.Shipment or {} ) do + + if v == id then + + table.remove( self.Shipment, k ) + + return + + end + + end + +end + +function meta:GetShipment() + + return self.Shipment or {} + +end + +function meta:RefundAll() + + local tbl = self:GetShipment() + local cash = 0 + + for k,v in pairs( tbl ) do + + local itbl = item.GetByID( v ) + cash = cash + itbl.Price + + end + + if cash == 0 then return end + + self:AddCash( cash ) + self.Shipment = {} + +end + +function meta:SendShipment() + + if not self:GetShipment()[1] then + + self:Notice( "You haven't ordered any shipments", GAMEMODE.Colors.Red ) + return + + end + + if self:IsIndoors() then + + self:Notice( "You can't order shipments while indoors", GAMEMODE.Colors.Red ) + self:RefundAll() + + return + + end + + if GAMEMODE.RadioBlock and GAMEMODE.RadioBlock > CurTime() then + + self:Notice( "Radio communications are offline", GAMEMODE.Colors.Red ) + self:RefundAll() + + return + + end + + local droptime = math.Round( 9.5 + ( table.Count( self.Shipment ) * 0.5 ) ) + + self:Notice( "Your shipment is due in " .. droptime .. " seconds", GAMEMODE.Colors.Green ) + + local prop = ents.Create( "sent_dropflare" ) + prop:SetPos( self:GetPos() + Vector(0,0,10) ) + prop:SetDieTime( droptime ) + prop:Spawn() + + local function DropBox( ply, pos, tbl ) + + ply:Notice( "Your shipment has been airdropped", GAMEMODE.Colors.Green, 5 ) + + local box = ents.Create( "sent_supplycrate" ) + box:SetPos( pos ) + box:SetUser( ply ) + box:Spawn() + box:SetContents( tbl ) + + end + + local tr = util.TraceLine( util.GetPlayerTrace( self, Vector(0,0,1) ) ) + local ship = self:GetShipment() + + timer.Simple( droptime + 1, function() DropBox( self, tr.HitPos + Vector(0,0,-100), ship ) end ) + timer.Simple( droptime - 1, function() sound.Play( table.Random( GAMEMODE.Choppers ), self:GetPos(), 100, 100, 0.8 ) end ) + + self.Shipment = {} + +end + +function meta:InitializeInventory() + + self.Inventory = {} + self:SynchInventory() + +end + +function meta:GetInventory() + + return self.Inventory or {} + +end + +function meta:GetUniqueInventory() + + local tbl = {} + + for k,v in pairs( self.Inventory or {} ) do + + if not table.HasValue( tbl, v ) then + + table.insert( tbl, v ) + + end + + end + + return tbl + +end + +function meta:SynchInventory() + + //datastream.StreamToClients( { self }, "InventorySynch", self:GetInventory() ) + + net.Start( "InventorySynch" ) + + net.WriteTable( self:GetInventory() ) + + net.Send( self ) + +end + +function meta:AddMultipleToInventory( items ) + + for k,v in pairs( items ) do + + local tbl = item.GetByID( v ) + + if tbl then + + if ( tbl.PickupFunction and tbl.PickupFunction( self, tbl.ID ) ) or not tbl.PickupFunction then + + table.insert( self.Inventory, tbl.ID ) + self:AddWeight( tbl.Weight ) + + end + + self:Notice( "Picked up " .. tbl.Name, GAMEMODE.Colors.Green ) + + end + + end + + self:SynchInventory() + self:EmitSound( Sound( "items/itempickup.wav" ) ) + self:AddStat( "Loot", #items ) + +end + +function meta:RemoveMultipleFromInventory( items ) + + for k,v in pairs( items ) do + + local tbl = item.GetByID( v ) + + for c,d in pairs( self:GetInventory() ) do + + if d == v then + + self:AddWeight( -tbl.Weight ) + + table.remove( self.Inventory, c ) + + break + + end + + end + + end + + self:SynchInventory() + +end + +function meta:AddIDToInventory( id ) + + local tbl = item.GetByID( id ) + + if not tbl then return end + + if tbl.PickupFunction then + + if not tbl.PickupFunction( self, id ) then return end + + end + + table.insert( self.Inventory, id ) + self:AddWeight( tbl.Weight ) + self:Notice( "Picked up " .. tbl.Name, GAMEMODE.Colors.Green ) + + self:SynchInventory() + self:EmitSound( Sound( "items/itempickup.wav" ) ) + self:AddStat( "Loot" ) + +end + +function meta:AddToInventory( prop ) + + local tbl = item.GetByModel( prop:GetModel() ) + + if not tbl or ( tbl and tbl.AllowPickup ) then return end + + if tbl.PickupFunction then + + if not tbl.PickupFunction( self, tbl.ID ) then + + if IsValid( prop ) then + + prop:Remove() + + end + + return + + end + + end + + table.insert( self.Inventory, tbl.ID ) + self:AddWeight( tbl.Weight ) + self:Notice( "Picked up " .. tbl.Name, GAMEMODE.Colors.Green ) + + if IsValid( prop ) then + + prop:Remove() + + end + + self:SynchInventory() + self:EmitSound( Sound( "items/itempickup.wav" ) ) + self:AddStat( "Loot" ) + +end + +function meta:RemoveFromInventory( id ) + + for k,v in pairs( self:GetInventory() ) do + + if v == id then + + local tbl = item.GetByID( id ) + + table.remove( self.Inventory, k ) + + self:SynchInventory() + self:AddWeight( -tbl.Weight ) + + return + + end + + end + +end + +function meta:GetItemDropPos() + + local trace = {} + trace.start = self:GetShootPos() + Vector(0,0,-15) + trace.endpos = trace.start + self:GetAimVector() * 30 + trace.filter = self + + local tr = util.TraceLine( trace ) + + return tr.HitPos + +end + +function meta:GetItemCount( id ) + + local count = 0 + + for k,v in pairs( self:GetInventory() ) do + + if v == id then + + count = count + 1 + + end + + end + + return count + +end + +function meta:GetWood() + + local tbl = item.GetByName( "Wood" ) + + return self:HasItem( "Wood" ), tbl.ID + +end + +function meta:HasItem( thing ) + + for k,v in pairs( ( self:GetInventory() ) ) do + + local tbl = item.GetByID( v ) + + if ( type( thing ) == "number" and v == thing ) or ( type( thing ) == "string" and string.lower( tbl.Model ) == string.lower( thing ) ) or ( type( thing ) == "string" and string.lower( tbl.Name ) == string.lower( thing ) ) then + + return true + + end + + end + + return false + +end + +function meta:SynchCash( amt ) + + if not amt then return end + + umsg.Start( "CashSynch", self ) + umsg.Short( amt ) + umsg.End() + +end + +function meta:SynchStash( ent ) + + //datastream.StreamToClients( { self }, "StashSynch", ent:GetItems() ) + + net.Start( "StashSynch" ) + + net.WriteTable( ent:GetItems() ) + + net.Send( self ) + +end + +function meta:ToggleStashMenu( ent, open, menutype, pricemod ) + + if open then + + if menutype != "StoreMenu" then + + self:SetMoveType( MOVETYPE_NONE ) + + end + + self:SynchInventory() + self:SynchStash( ent ) + self.Stash = ent + + else + + self:SetMoveType( MOVETYPE_WALK ) + self.Stash = nil + + end + + umsg.Start( menutype, self ) + umsg.Bool( open ) + + if pricemod then + umsg.Float( pricemod ) + end + + umsg.End() + +end + +function meta:SetEvacuated( bool ) + + self.Evacuated = bool + +end + +function meta:IsEvacuated() + + return self.Evacuated + +end + +function meta:Evac() + + self:Notice( "You were successfully evacuated", GAMEMODE.Colors.Green, 5 ) + + self:SetEvacuated( true ) + self:Freeze( true ) + self:Flashlight( false ) + self:SetModel( "models/shells/shell_9mm.mdl" ) + self:Spectate( OBS_MODE_ROAMING ) + self:StripWeapons() + self:GodEnable() + +end + +function meta:OnDeath() + + umsg.Start( "DeathScreen", self ) + umsg.Short( self:Team() ) + umsg.End() + + self.NextSpawn = CurTime() + 10 + + if self:Team() == TEAM_ARMY then + + if IsValid( self.Stash ) then + + if self.Stash:GetClass() == "info_trader" then + + self.Stash:OnExit( self ) + + else + + self:ToggleStashMenu( self.Stash, false, "StashMenu" ) + + end + + end + + self.Stash = nil + + self:DropLoot() + self:SetWeight( 0 ) + self:SetCash( 0 ) + self:Flashlight( false ) + self:SetPlayerClass( CLASS_RUNNER ) + self.Inventory = {} + self:SynchInventory() + + for k,v in pairs{ "Buckshot", "Rifle", "SMG", "Pistol", "Sniper", "Prototype" } do + + self:SetAmmo( v, 0 ) + + end + + else + + if self:GetPlayerClass() == CLASS_CONTAGION then + + self:SetModel( "models/zombie/classic_legs.mdl" ) + self:EmitSound( table.Random( GAMEMODE.GoreSplash ), 90, math.random( 60, 80 ) ) + + local got = false + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + if v:GetPos():Distance( self:GetPos() ) < 200 then + + self:AddZedDamage( 20 ) + v:TakeDamage( 25, self ) + v:SetInfected( true ) + + umsg.Start( "Drunk", v ) + umsg.Short( 2 ) + umsg.End() + + got = true + + end + + end + + if got then + + self:Notice( "You infected a human", GAMEMODE.Colors.Green ) + + end + + local ed = EffectData() + ed:SetOrigin( self:GetPos() ) + util.Effect( "puke_explosion", ed, true, true ) + + end + + end + +end diff --git a/gamemode/resource.lua b/gamemode/resource.lua new file mode 100644 index 0000000..2aafc2f --- /dev/null +++ b/gamemode/resource.lua @@ -0,0 +1,170 @@ + +resource.AddFile( "materials/sprites/flareglow.vmt" ) +resource.AddFile( "resource/fonts/Graffiare.ttf" ) +resource.AddFile( "resource/fonts/typenoksidi.ttf" ) +resource.AddFile( "models/Zed/male_shared.mdl" ) +resource.AddFile( "sound/nuke/redead/lastminute.mp3" ) + +for i=1,4 do + + for e=1,5 do + + resource.AddFile( "materials/models/Zed/Male/g" .. i .. "_0" .. e .. "_sheet.vmt" ) + + end + +end + +local include_sound = { "heartbeat", +"geiger_1", +"geiger_2", +"geiger_3", +"geiger_4", +"geiger_5", +"geiger_6", +"geiger_7", +"geiger_8", +"gore/blood01", +"gore/blood02", +"gore/blood03", +"gore/flesh01", +"gore/flesh02", +"gore/flesh03", +"gore/flesh04", +"redead/attack_1", +"redead/attack_2", +"redead/attack_3", +"redead/attack_4", +"redead/attack_5", +"redead/attack_6", +"redead/attack_7", +"redead/attack_8", +"redead/attack_9", +"redead/attack_10", +"redead/death_1", +"redead/death_2", +"redead/death_3", +"redead/death_4", +"redead/death_5", +"redead/death_6", +"redead/death_7", +"redead/death_8", +"redead/death_9", +"redead/death_10", +"redead/pain_1", +"redead/pain_2", +"redead/pain_3", +"redead/pain_4", +"redead/pain_5", +"redead/pain_6", +"redead/pain_7", +"redead/pain_8", +"redead/pain_9", +"redead/pain_10", +"redead/idle_1", +"redead/idle_2", +"redead/idle_3", +"redead/idle_4", +"redead/idle_5", +"redead/idle_6", +"redead/idle_7", +"redead/idle_8", +"redead/idle_9", +"redead/idle_10" } + +for k,v in pairs( include_sound ) do + + resource.AddFile( "sound/nuke/" .. v .. ".wav" ) + +end + +local include_mat = { "models/weapons/v_models/shot_m3super91/shot_m3super91_norm", +"models/weapons/v_models/shot_m3super91/shot_m3super91_2_norm", +"models/weapons/v_models/shot_m3super91/shot_m3super91", +"models/weapons/v_models/shot_m3super91/shot_m3super91_2", +"models/weapons/temptexture/handsmesh1", +"models/weapons/axe", +"models/weapons/hammer", +"models/weapons/hammer2", +"models/ammoboxes/smg", +"models/Zed/Male/pupil_l", +"models/Zed/Male/pupil_r", +"models/Zed/Male/eyeball_r", +"models/Zed/Male/eyeball_l", +"models/Zed/Male/dark_eyeball_l", +"models/Zed/Male/dark_eyeball_r", +"models/Zed/Male/mouth", +"models/Zed/Male/glint", +"models/Zed/Male/citizen_sheet", +"models/Zed/Male/blood_sheet", +"models/Zed/Male/grey_sheet", +"models/Zed/Male/service_sheet", +"models/Zed/Male/plaid_sheet", +"models/Zed/Male/jackson_sheet", +"models/Zed/Male/sandro_facemap", +"models/Zed/Male/joe_facemap", +"models/Zed/Male/eric_facemap", +"models/Zed/Male/vance_facemap", +"effects/rain_cloud", +"effects/rain_warp", +"effects/rain_warp_normal", +"nuke/redead/noise01", +"nuke/redead/noise02", +"nuke/redead/noise03", +"nuke/redead/commando", +"nuke/redead/engineer", +"nuke/redead/scout", +"nuke/redead/specialist", +"nuke/redead/zomb_zombie", +"nuke/redead/zomb_corpse", +"nuke/redead/zomb_banshee", +"nuke/redead/zomb_leaper", +"nuke/redead/allyvision", +"nuke/gore1", +"nuke/gore2", +"nuke/blood/Blood1", +"nuke/blood/Blood2", +"nuke/blood/Blood3", +"nuke/blood/Blood4", +"nuke/blood/Blood5", +"nuke/blood/Blood6", +"nuke/blood/Blood7", +"radbox/img_radiation", +"radbox/img_blood", +"radbox/img_health", +"radbox/img_stamina", +"radbox/img_infect", +"radbox/healthpack", +"radbox/healthpack2", +"radbox/bandage" } + +for k,v in pairs( include_mat ) do + + resource.AddFile( "materials/" .. v .. ".vmt" ) + +end + +local include_model = { "weapons/v_shot_m3super91", +"weapons/w_hammer", +"weapons/w_axe", +"weapons/v_hammer/v_hammer", +"weapons/v_axe/v_axe", +"items/boxqrounds", +"radbox/bandage", +"radbox/geiger", +"radbox/healthpack", +"radbox/healthpack2", +"Zed/malezed_04", +"Zed/malezed_06", +"Zed/malezed_08", +"Zed/weapons/v_undead", +"Zed/weapons/v_ghoul", +"Zed/weapons/v_wretch", +"Zed/weapons/v_banshee" } + +for k,v in pairs( include_model ) do + + resource.AddFile( "models/" .. v .. ".mdl" ) + +end + diff --git a/gamemode/shared.lua b/gamemode/shared.lua new file mode 100644 index 0000000..e00c4a1 --- /dev/null +++ b/gamemode/shared.lua @@ -0,0 +1,122 @@ + +GM.Name = "ReDead" +GM.Author = "twoski" +GM.Email = "" +GM.Website = "" +GM.TeamBased = true + +CreateConVar( "sv_redead_max_zombies", "45", { FCVAR_ARCHIVE, FCVAR_NOTIFY, FCVAR_SERVER_CAN_EXECUTE }, "Controls the amount of zombie NPCs that can be spawned at any time. (def 45)" ) +CreateConVar( "sv_redead_zombies_per_player", "3", { FCVAR_ARCHIVE, FCVAR_NOTIFY, FCVAR_SERVER_CAN_EXECUTE }, "Controls the amount of zombie NPCs that spawn per player. (def 3)" ) +CreateConVar( "sv_redead_zombies_per_player_zombie", "2", { FCVAR_ARCHIVE, FCVAR_NOTIFY, FCVAR_SERVER_CAN_EXECUTE }, "Controls the amount of zombie NPCs that spawn per player zombie. (def 2)" ) +CreateConVar( "sv_redead_wave_length", "4", { FCVAR_ARCHIVE, FCVAR_NOTIFY, FCVAR_SERVER_CAN_EXECUTE }, "Controls how long each wave is. (def 4 minutes)" ) +CreateConVar( "sv_redead_wave_time", "25", { FCVAR_ARCHIVE, FCVAR_NOTIFY, FCVAR_SERVER_CAN_EXECUTE }, "Controls the delay between zombie group spawning. (def 25 seconds)" ) +CreateConVar( "sv_redead_team_dmg", "0", { FCVAR_ARCHIVE, FCVAR_NOTIFY, FCVAR_SERVER_CAN_EXECUTE }, "Controls whether teammates can hurt eachother. (def 0)" ) +CreateConVar( "sv_redead_dmg_scale", "1", { FCVAR_ARCHIVE, FCVAR_NOTIFY, FCVAR_SERVER_CAN_EXECUTE }, "Controls bullet damage scaling. (def 1.0)" ) +CreateConVar( "sv_redead_setup_time", "60", { FCVAR_ARCHIVE, FCVAR_NOTIFY, FCVAR_SERVER_CAN_EXECUTE }, "How much time before the first wave? (def 60 seconds)" ) +CreateConVar( "sv_redead_post_game_time", "45", { FCVAR_ARCHIVE, FCVAR_NOTIFY, FCVAR_SERVER_CAN_EXECUTE }, "How much time before the next map loads? (def 45 seconds)" ) +CreateConVar( "sv_redead_minimum_players", "6", { FCVAR_ARCHIVE, FCVAR_NOTIFY, FCVAR_SERVER_CAN_EXECUTE }, "How many players need to be present for a zombie lord to be picked? (def 6 players)" ) + +TEAM_ARMY = 1 +TEAM_ZOMBIES = 2 + +function GM:CreateTeams() + + team.SetUp( TEAM_ARMY, GAMEMODE.ArmyTeamName, Color( 80, 80, 255 ), true ) + team.SetSpawnPoint( TEAM_ARMY, "info_player_army" ) + + team.SetUp( TEAM_ZOMBIES, GAMEMODE.ZombieTeamName, Color( 255, 80, 80 ), true ) + team.SetSpawnPoint( TEAM_ZOMBIES, "info_player_zombie" ) + +end + +function GM:ShouldCollide( ent1, ent2 ) + + if ent1:IsPlayer() and ent1:Team() == TEAM_ARMY and ent2.IsWood then + + return false + + elseif ent2:IsPlayer() and ent2:Team() == TEAM_ARMY and ent1.IsWood then + + return false + + end + + return self.BaseClass:ShouldCollide( ent1, ent2 ) + +end + +function GM:Move( ply, mv ) + + if ply:Team() == TEAM_ARMY then + + if ply:GetNWFloat( "Stamina", 0 ) <= 5 then + + mv:SetMaxSpeed( 110 ) + + end + + else + + if mv:GetSideSpeed() > 0 then + + mv:SetSideSpeed( 175 ) + + elseif mv:GetSideSpeed() < 0 then + + mv:SetSideSpeed( -175 ) + + end + + end + + return self.BaseClass:Move( ply, mv ) + +end + +function GM:PlayerNoClip( pl, on ) + + if ( game.SinglePlayer() ) then return true end + + if pl:IsAdmin() or pl:IsSuperAdmin() then return true end + + return false + +end + +function IncludeItems() + + local folder = string.Replace( GM.Folder, "gamemodes/", "" ) + + for c,d in pairs( file.Find( folder.."/gamemode/items/*.lua", "LUA" ) ) do + + include( folder.."/gamemode/items/"..d ) + + if SERVER then + + AddCSLuaFile( folder.."/gamemode/items/"..d ) + + end + + end + +end + +IncludeItems() + +function IncludeEvents() + + local folder = string.Replace( GM.Folder, "gamemodes/", "" ) + + for c,d in pairs( file.Find( folder.."/gamemode/events/*.lua", "LUA" ) ) do + + if SERVER then + + include( folder.."/gamemode/events/"..d ) + + end + + end + +end + +IncludeEvents()
\ No newline at end of file diff --git a/gamemode/tables.lua b/gamemode/tables.lua new file mode 100644 index 0000000..c48305a --- /dev/null +++ b/gamemode/tables.lua @@ -0,0 +1,484 @@ + +GM.Radio = {} + +GM.Radio[ VO_DEATH ] = { "bot/aah.wav", +"bot/help.wav", +"bot/need_help.wav", +"bot/need_help2.wav", +"bot/noo.wav", +"bot/oh.wav", +"bot/ow.wav", +"bot/pain2.wav", +"bot/pain4.wav", +"bot/pain5.wav", +"bot/pain8.wav", +"bot/pain9.wav", +"bot/pain10.wav" } + +GM.Radio[ VO_PAIN ] = { "bot/cut_it_out.wav", +"bot/hey.wav", +"bot/hey2.wav", +"bot/i_cant_see.wav", +"bot/i_could_use_some_help.wav", +"bot/i_could_use_some_help_over_here.wav", +"bot/im_blind.wav", +"bot/im_in_trouble.wav", +"bot/im_pinned_down.wav", +"bot/ive_been_blinded.wav", +"bot/look_out_brag.wav", +"bot/my_eyes.wav", +"bot/naa.wav", +"bot/oh_boy.wav", +"bot/oh_boy2.wav", +"bot/oh_my_god.wav", +"bot/oh_no.wav", +"bot/oh_no_sad.wav", +"bot/ouch.wav", +"bot/stop_it.wav", +"bot/theres_too_many.wav", +"bot/theres_too_many_of_them.wav", +"bot/they_got_me_pinned_down_here.wav", +"bot/theyre_all_over_the_place2.wav", +"bot/theyre_everywhere2.wav", +"bot/too_many2.wav", +"bot/what_are_you_doing.wav", +"bot/what_happened.wav", +"bot/what_have_you_done.wav", +"bot/whoa.wav", +"bot/yikes.wav" } + +GM.Radio[ VO_TAUNT ] = { "bot/affirmative.wav", +"bot/all_clear_here.wav", +"bot/alright.wav", +"bot/alright2.wav", +"bot/and_thats_how_its_done.wav", +"bot/area_secure.wav", +"bot/clear.wav", +"bot/clear2.wav", +"bot/clear3.wav", +"bot/clear4.wav", +"bot/come_to_papa.wav", +"bot/do_not_mess_with_me.wav", +"bot/dropped_him.wav", +"bot/enemy_down.wav", +"bot/enemy_down2.wav", +"bot/good_job_team.wav", +"bot/good_one.wav", +"bot/good_one2.wav", +"bot/good_one_sir.wav", +"bot/good_one_sir2.wav", +"bot/good_shot.wav", +"bot/good_shot2.wav", +"bot/good_shot_commander.wav", +"bot/good_shot_commander2.wav", +"bot/got_him.wav", +"bot/hes_broken.wav", +"bot/hes_dead.wav", +"bot/hes_done.wav", +"bot/hes_down.wav", +"bot/i_am_dangerous.wav", +"bot/i_am_on_fire.wav", +"bot/i_got_more_where_that_came_from.wav", +"bot/i_wasnt_worried_for_a_minute.wav", +"bot/its_a_party.wav", +"bot/killed_him.wav", +"bot/made_him_cry.wav", +"bot/neutralized.wav", +"bot/nice.wav", +"bot/nice2.wav", +"bot/nice_one_commander.wav", +"bot/nice_one_sir.wav", +"bot/nice_shot.wav", +"bot/nice_shot2.wav", +"bot/nice_shot_sir.wav", +"bot/nice_shot_commander.wav", +"bot/nice_shot_commander2.wav", +"bot/nice_work_team.wav", +"bot/oh_yea.wav", +"bot/oh_yea2.wav", +"bot/ok.wav", +"bot/ok2.wav", +"bot/one_guy_left.wav", +"bot/owned.wav", +"bot/roger.wav", +"bot/roger_that.wav", +"bot/ruined_his_day.wav", +"bot/tag_them_and_bag_them.wav", +"bot/that_was_a_close_one.wav", +"bot/that_was_it.wav", +"bot/that_was_the_last_one.wav", +"bot/thats_right.wav", +"bot/thats_the_way_this_is_done.wav", +"bot/the_actions_hot_here.wav", +"bot/theres_one_left.wav", +"bot/they_never_knew_what_hit_them.wav", +"bot/this_is_my_house.wav", +"bot/three_left.wav", +"bot/three_to_go.wav", +"bot/three_to_go2.wav", +"bot/took_him_down.wav", +"bot/took_him_out.wav", +"bot/took_him_out2.wav", +"bot/two_to_go.wav", +"bot/very_nice.wav", +"bot/wasted_him.wav", +"bot/way_to_be_team.wav", +"bot/we_owned_them.wav", +"bot/well_done.wav", +"bot/weve_got_the_situation.wav", +"bot/whew_that_was_close.wav", +"bot/who_wants_some_more.wav", +"bot/whoo.wav", +"bot/whoo2.wav", +"bot/whos_the_man.wav", +"bot/yea_baby.wav", +"bot/yea_ok.wav", +"bot/yesss.wav", +"bot/yesss2.wav" } + +GM.Radio[ VO_ALERT ] = { "bot/alright_lets_do_this.wav", +"bot/attacking.wav", +"bot/attacking_enemies.wav", +"bot/aw_hell.wav", +"bot/aww_man.wav", +"bot/back.wav", +"bot/be_right_there.wav", +"bot/come_out_and_fight_like_a_man.wav", +"bot/come_out_wherever_you_are.wav", +"bot/cover_me.wav", +"bot/cover_me2.wav", +"bot/engaging_enemies.wav", +"bot/great.wav", +"bot/hang_on_i_heard_something.wav", +"bot/hang_on_im_coming.wav", +"bot/i_dont_know_where_he_went.wav", +"bot/i_got_nothing.wav", +"bot/i_got_your_back.wav", +"bot/i_got_your_back2.wav", +"bot/i_hear_something.wav", +"bot/i_hear_them.wav", +"bot/i_heard_them.wav", +"bot/i_heard_something_over_there.wav", +"bot/i_lost_him.wav", +"bot/i_see_our_target.wav", +"bot/ill_come_with_you.wav", +"bot/ill_go_with_you.wav", +"bot/in_combat.wav", +"bot/in_combat2.wav", +"bot/oh_man.wav", +"bot/sounds_like_a_plan.wav", +"bot/target_acquired.wav", +"bot/target_spotted.wav", +"bot/thats_not_good.wav", +"bot/theres_not_much_time_left.wav", +"bot/time_is_running_out.wav", +"bot/time_is_running_out2.wav", +"bot/uh_oh.wav", +"bot/where_are_they.wav", +"bot/where_could_they_be.wav", +"bot/you_heard_the_man_lets_go.wav" } + +GM.Radio[ VO_IDLE ] = { "bot/ahh_negative.wav", +"bot/all_quiet.wav", +"bot/anyone_see_anything.wav", +"bot/anyone_see_them.wav", +"bot/area_clear.wav", +"bot/far_side.wav", +"bot/ill_go_too.wav", +"bot/im_coming.wav", +"bot/im_going_to_wait_here.wav", +"bot/im_gonna_hang_back.wav", +"bot/im_waiting_here.wav", +"bot/im_with_you.wav", +"bot/its_all_up_to_you_sir.wav", +"bot/lead_on_commander.wav", +"bot/lead_on_sir.wav", +"bot/lead_the_way.wav", +"bot/lead_the_way_commander.wav", +"bot/lead_the_way_sir.wav", +"bot/lets_hold_up_here_for_a_minute.wav", +"bot/lets_wait_here.wav", +"bot/negative.wav", +"bot/negative2.wav", +"bot/nnno_sir.wav", +"bot/no.wav", +"bot/nothing_happening_over_here.wav", +"bot/nothing_here.wav", +"bot/nothing_moving_over_here.wav", +"bot/ok_cmdr_lets_go.wav", +"bot/ok_sir_lets_go.wav", +"bot/on_my_way.wav", +"bot/on_my_way2.wav", +"bot/report_in_team.wav", +"bot/reporting_in.wav", +"bot/theres_nobody_home.wav" } + +GM.Radio[ VO_EVAC ] = { "bot/guarding_the_escape_zone.wav", +"bot/guarding_the_escape_zone2.wav", +"bot/heading_to_the_escape_zone.wav", +"bot/heading_to_the_rescue_zone.wav", +"bot/im_going_to_cover_the_escape_zone.wav", +"bot/im_going_to_keep_an_eye_on_the_escape.wav", +"bot/im_going_to_keep_an_eye_on_the_rescue.wav", +"bot/im_going_to_watch_the_escape_zone.wav", +"bot/im_going_to_watch_the_rescue_zone.wav", +"bot/watching_the_escape_route.wav", +"bot/watching_the_escape_zone.wav", +"bot/rescue_zone.wav", +"bot/the_commander_is_down.wav", +"bot/the_commander_is_down_repeat.wav", +"bot/weve_lost_the_commander.wav" } + +GM.VoiceStart = { "npc/metropolice/vo/off1.wav", +"npc/metropolice/vo/off4.wav" } + +GM.VoiceEnd = { "npc/combine_soldier/vo/off1.wav", +"npc/combine_soldier/vo/off2.wav" } + +--[[GM.Pain = {"nuke/gore/pain01.wav", +"nuke/gore/pain02.wav", +"nuke/gore/pain03.wav", +"nuke/gore/pain04.wav", +"nuke/gore/pain05.wav", +"nuke/gore/die05.wav"} + +GM.Death = {"nuke/gore/die01.wav", +"nuke/gore/die02.wav", +"nuke/gore/die03.wav", +"nuke/gore/die04.wav", +"nuke/gore/carnage01.wav", +"nuke/gore/carnage02.wav", +"nuke/gore/carnage03.wav", +"nuke/gore/carnage04.wav", +"nuke/gore/carnage05.wav"}]] + +GM.Burning = { "player/pl_burnpain1.wav", +"player/pl_burnpain2.wav", +"player/pl_burnpain3.wav" } + +GM.BurnFlesh = Sound( "general.burningflesh" ) + +GM.AxeHit = { "ambient/machines/slicer1.wav", +"ambient/machines/slicer2.wav", +"ambient/machines/slicer3.wav", +"ambient/machines/slicer4.wav" } + +GM.BluntHit = { "ambient/machines/slicer2.wav", +"ambient/machines/slicer3.wav", +"weapons/crossbow/hitbod1.wav", +"weapons/crossbow/hitbod2.wav", +"Flesh.BulletImpact" } + +GM.HeadShot = { "player/headshot1.wav", +"player/headshot2.wav", +"physics/flesh/flesh_bloody_break.wav" } + +GM.GoreSplash = { "nuke/gore/blood01.wav", +"nuke/gore/blood02.wav", +"nuke/gore/blood03.wav", +"npc/antlion_grub/squashed.wav" } + +GM.GoreSplat = { "physics/flesh/flesh_squishy_impact_hard1.wav", +"physics/flesh/flesh_squishy_impact_hard2.wav", +"physics/flesh/flesh_squishy_impact_hard3.wav", +"physics/flesh/flesh_squishy_impact_hard4.wav", +"physics/flesh/flesh_bloody_impact_hard1.wav", +"physics/body/body_medium_break2.wav", +"physics/body/body_medium_break3.wav", +"physics/body/body_medium_break4.wav", +"ambient/levels/canals/toxic_slime_sizzle1.wav", +"ambient/levels/canals/toxic_slime_sizzle2.wav", +"ambient/levels/canals/toxic_slime_gurgle3.wav", +"ambient/levels/canals/toxic_slime_gurgle5.wav", +"ambient/levels/canals/toxic_slime_gurgle8.wav"} + +GM.GoreBullet = { "nuke/gore/flesh01.wav", +"nuke/gore/flesh02.wav", +"nuke/gore/flesh03.wav", +"nuke/gore/flesh04.wav" } + +GM.Drill = { "npc/dog/dog_servo6.wav", +"npc/dog/dog_servo7.wav", +"npc/dog/dog_servo10.wav", +"npc/dog/dog_servo12.wav", +"ambient/machines/pneumatic_drill_1.wav", +"ambient/machines/pneumatic_drill_2.wav", +"ambient/machines/pneumatic_drill_3.wav", +"ambient/machines/pneumatic_drill_4.wav" } + +GM.WoodHammer = { "physics/wood/wood_plank_impact_hard2.wav", +"physics/wood/wood_plank_impact_hard3.wav", +"physics/wood/wood_plank_impact_hard4.wav" } + +GM.Ricochet = { "weapons/fx/rics/ric1.wav", +"weapons/fx/rics/ric2.wav", +"weapons/fx/rics/ric3.wav", +"weapons/fx/rics/ric4.wav", +"weapons/fx/rics/ric5.wav" } + +GM.Geiger = { "nuke/geiger_1.wav", +"nuke/geiger_2.wav", +"nuke/geiger_3.wav", +"nuke/geiger_4.wav", +"nuke/geiger_5.wav", +"nuke/geiger_6.wav", +"nuke/geiger_7.wav", +"nuke/geiger_8.wav" } + +GM.RadioBeep = { "ambient/levels/prison/radio_random1.wav", +"ambient/levels/prison/radio_random2.wav", +"ambient/levels/prison/radio_random3.wav", +"ambient/levels/prison/radio_random4.wav", +"ambient/levels/prison/radio_random5.wav", +"ambient/levels/prison/radio_random6.wav", +"ambient/levels/prison/radio_random7.wav", +"ambient/levels/prison/radio_random8.wav", +"ambient/levels/prison/radio_random9.wav" } + +GM.AmbientScream = { "ambient/levels/prison/inside_battle_antlion3.wav", +"npc/combine_gunship/gunship_moan.wav", +"ambient/creatures/town_zombie_call1.wav", +"ambient/creatures/town_moan1.wav", +"ambient/creatures/town_child_scream1.wav", +"ambient/creatures/town_scared_sob1.wav", +"ambient/creatures/town_scared_sob2.wav", +"ambient/creatures/town_scared_breathing1.wav" } + +GM.Coughs = { "ambient/voices/cough1.wav", +"ambient/voices/cough2.wav", +"ambient/voices/cough3.wav", +"ambient/voices/cough4.wav", +"ambient/voices/citizen_beaten3.wav", +"ambient/voices/citizen_beaten4.wav" } + +GM.Choppers = { "ambient/overhead/hel1.wav", +"ambient/overhead/hel2.wav", +"ambient/machines/heli_pass1.wav", +"ambient/machines/heli_pass2.wav" } + +GM.Thunder = { "ambient/weather/thunder1.wav", +"ambient/weather/thunder2.wav", +"ambient/weather/thunder3.wav", +"ambient/weather/thunder4.wav", +"ambient/weather/thunder5.wav", +"ambient/weather/thunder6.wav", +"ambient/atmosphere/thunder1.wav", +"ambient/atmosphere/thunder2.wav", +"ambient/atmosphere/thunder3.wav", +"ambient/atmosphere/thunder4.wav", +"ambient/water/distant_wave1.wav", +"ambient/water/distant_wave2.wav", +"ambient/levels/streetwar/city_battle17.wav" } + +GM.Wind = { "ambient/water/distant_wave3.wav", +"ambient/wind/wind_hit1.wav", +"ambient/wind/wind_hit2.wav", +"ambient/wind/wind_hit3.wav", +"ambient/wind/wind_med1.wav", +"ambient/wind/wind_med2.wav", +"ambient/wind/wind_moan1.wav", +"ambient/wind/wind_moan2.wav", +"ambient/wind/wind_moan4.wav", +"ambient/wind/wind_snippet1.wav", +"ambient/wind/wind_snippet2.wav", +"ambient/wind/wind_snippet3.wav", +"ambient/wind/wind_snippet4.wav", +"ambient/wind/wind_snippet5.wav", +"ambient/wind/windgust.wav", +"ambient/wind/windgust_strong.wav", +"ambient/wind/smallgust.wav", +"ambient/wind/smallgust2.wav", +"ambient/wind/wind_gust_2.wav", +"ambient/wind/wind_gust_8.wav", +"ambient/wind/wind_gust_10.wav" } + +GM.Corpses = {"models/gibs/fast_zombie_torso.mdl", +"models/gibs/fast_zombie_legs.mdl", +"models/humans/charple02.mdl", +"models/humans/charple03.mdl", +"models/humans/charple04.mdl"} + +GM.SmallGibs = {"models/gibs/HGIBS_scapula.mdl", +"models/props_phx/misc/potato.mdl", +"models/gibs/antlion_gib_small_1.mdl", +"models/gibs/antlion_gib_small_2.mdl", +"models/gibs/shield_scanner_gib1.mdl", +"models/props_wasteland/prison_sinkchunk001h.mdl", +"models/props_wasteland/prison_toiletchunk01f.mdl", +"models/props_wasteland/prison_toiletchunk01i.mdl", +"models/props_wasteland/prison_toiletchunk01l.mdl", +"models/props_combine/breenbust_chunk02.mdl", +"models/props_combine/breenbust_chunk04.mdl", +"models/props_combine/breenbust_chunk05.mdl", +"models/props_combine/breenbust_chunk06.mdl", +"models/props_combine/breenbust_chunk07.mdl", +"models/props_junk/watermelon01_chunk02a.mdl", +"models/props_junk/watermelon01_chunk02b.mdl", +"models/props_junk/watermelon01_chunk02c.mdl", +"models/props/cs_office/computer_mouse.mdl", +"models/props/cs_office/trash_can_p5.mdl", +"models/props/cs_italy/banannagib1.mdl", +"models/props/cs_italy/banannagib2.mdl", +"models/props/cs_italy/orangegib1.mdl", +"models/props/cs_italy/orangegib2.mdl" } + +GM.BigGibs = {"models/gibs/HGIBS.mdl", +"models/gibs/HGIBS_spine.mdl", +"models/weapons/w_bugbait.mdl", +"models/gibs/antlion_gib_medium_1.mdl", +"models/gibs/antlion_gib_medium_2.mdl", +"models/gibs/shield_scanner_gib5.mdl", +"models/gibs/shield_scanner_gib6.mdl", +"models/props_junk/shoe001a.mdl", +"models/props_junk/Rock001a.mdl", +"models/props_junk/garbage_bag001a.mdl", +"models/props_debris/concrete_spawnchunk001g.mdl", +"models/props_combine/breenbust_chunk03.mdl", +"models/props_wasteland/prison_sinkchunk001c.mdl", +"models/props_wasteland/prison_toiletchunk01j.mdl", +"models/props_wasteland/prison_toiletchunk01k.mdl", +"models/props_junk/watermelon01_chunk01b.mdl", +"models/props_junk/watermelon01_chunk01c.mdl", +"models/props/cs_office/Snowman_arm.mdl", +"models/props/cs_italy/bananna.mdl" } + +GM.BarrelGibs = { "models/props_c17/oildrumchunk01a.mdl", +"models/props_c17/oildrumchunk01b.mdl", +"models/props_c17/oildrumchunk01c.mdl", +"models/props_c17/oildrumchunk01d.mdl", +"models/props_c17/oildrumchunk01e.mdl" } + + +for k, v in pairs( GM.Radio ) do + + for c,d in pairs( v ) do + + util.PrecacheSound( d ) + + end + +end + +for k, v in pairs( GM.BarrelGibs ) do + + util.PrecacheModel( v ) + +end + +for k, v in pairs( GM.SmallGibs ) do + + util.PrecacheModel( v ) + +end + +for k, v in pairs( GM.BigGibs ) do + + util.PrecacheModel( v ) + +end + +for k,v in pairs( GM.Corpses ) do + + util.PrecacheModel( v ) + +end
\ No newline at end of file diff --git a/gamemode/vgui/vgui_categorybutton.lua b/gamemode/vgui/vgui_categorybutton.lua new file mode 100644 index 0000000..0b45c97 --- /dev/null +++ b/gamemode/vgui/vgui_categorybutton.lua @@ -0,0 +1,144 @@ +local PANEL = {} + +PANEL.OnSound = Sound( "common/talk.wav" ) +PANEL.OffSound = Sound( "weapons/sniper/sniper_zoomin.wav" ) + +surface.CreateFont ( "CategoryButton", { size = 16, weight = 500, antialias = true, additive = false, font = "Typenoksidi" } ) + +function PANEL:Init() + + //self:SetTitle( "" ) + //self:ShowCloseButton( false ) + //self:SetDraggable( false ) + + self:SetCursor( "hand" ) + + self.Image = vgui.Create( "DImageButton", self ) + self.Image:SetImage( "icon16/car.png" ) + self.Image:SetStretchToFit( false ) + self.Image.DoClick = function() + + self:Toggle() + + end + + self.Selected = false + self.Text = "" + +end + +function PANEL:SetImage( img ) + + self.Image:SetImage( img ) + +end + +function PANEL:SetText( text ) + + self.Text = text + +end + +function PANEL:Toggle( bool ) + + self:SetSelectedState( bool or !self.Selected ) + + if not bool then + + self:OnToggle( self.Selected ) + + end + +end + +function PANEL:OnToggle( bool ) // override this + +end + +function PANEL:DoSound( bool ) + + if bool then + + surface.PlaySound( self.OnSound ) + + else + + surface.PlaySound( self.OffSound ) + + end + +end + +function PANEL:SetSelectedState( bool, ignore ) + + self.Selected = tobool( bool ) + + if ignore then return end + + self:DoSound( bool ) + +end + +function PANEL:OnMousePressed( mousecode ) + + self:MouseCapture( true ) + +end + +function PANEL:OnMouseReleased( mousecode ) + + self:MouseCapture( false ) + self:Toggle() + +end + +function PANEL:GetPadding() + return 5 +end + +function PANEL:PerformLayout() + + local imgsize = self:GetTall() - ( 2 * self:GetPadding() ) + + self.Image:SetSize( imgsize, imgsize ) + self.Image:SetPos( self:GetWide() - imgsize - self:GetPadding(), self:GetPadding() ) + + //self:SizeToContents() + +end + +function PANEL:Paint() + + local tx, ty = self:GetPadding() * 2, self:GetTall() * 0.5 - 8 + //local px, py = self.Image:GetPos() + local imgsize = self:GetTall() - ( 2 * self:GetPadding() ) + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 180 ) ) + + if self.Selected then + + draw.RoundedBox( 4, self:GetWide() - imgsize - self:GetPadding(), self:GetPadding(), imgsize, imgsize, Color( 100, 100, 100, 100 ) ) + + draw.SimpleText( self.Text, "CategoryButton", tx+1, ty+1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx-1, ty-1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx+1, ty-1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx-1, ty+1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + + draw.SimpleText( self.Text, "CategoryButton", tx, ty, Color( 255, 255, 255, 255 ), TEXT_ALIGN_LEFT ) + + else + + draw.RoundedBox( 4, self:GetWide() - imgsize - self:GetPadding(), self:GetPadding(), imgsize, imgsize, Color( 100, 100, 100, 100 ) ) + + draw.SimpleText( self.Text, "CategoryButton", tx+1, ty+1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx-1, ty-1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx+1, ty-1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx-1, ty+1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + + draw.SimpleText( self.Text, "CategoryButton", tx, ty, Color( 100, 100, 100, 255 ), TEXT_ALIGN_LEFT ) + + end + +end + +derma.DefineControl( "CategoryButton", "A shitty button thing.", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_classpicker.lua b/gamemode/vgui/vgui_classpicker.lua new file mode 100644 index 0000000..5954296 --- /dev/null +++ b/gamemode/vgui/vgui_classpicker.lua @@ -0,0 +1,76 @@ +local PANEL = {} + +function PANEL:Init() + + //self:SetTitle( "" ) + //self:ShowCloseButton( false ) + self:ChooseParent() + + self.Items = {} + + for k,v in pairs( { CLASS_SCOUT, CLASS_COMMANDO, CLASS_SPECIALIST, CLASS_ENGINEER } ) do + + local desc = GAMEMODE.ClassDescriptions[k] or "TEH" + local logo = GAMEMODE.ClassLogos[k] or "brick/brick_model" + + local button = vgui.Create( "DImageButton", self ) + button:SetImage( logo ) + button:SetSize( 100, 100 ) + button.OnMousePressed = function() RunConsoleCommand( "changeclass", k ) RunConsoleCommand( "changeteam", TEAM_ARMY ) self:Remove() end + button.ID = id + + local label = vgui.Create( "DLabel", self ) + label:SetWrap( true ) + label:SetText( desc ) + label:SetFont( "ItemDisplayFont" ) + label:SetSize( 300, 100 ) + + table.insert( self.Items, { button, label } ) + + end + +end + +function PANEL:Think() + + self.Dragging = false + +end + +function PANEL:ChooseParent() + +end + +function PANEL:GetPadding() + + return 5 + +end + +function PANEL:PerformLayout() + + local x,y = self:GetPadding(), self:GetPadding() + 50 + + for k,v in pairs( self.Items ) do + + v[1]:SetPos( x, y ) + v[2]:SetPos( x + 100 + self:GetPadding(), y ) + + y = y + 100 + self:GetPadding() + + end + + self:SizeToContents() + +end + +function PANEL:Paint() + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 255 ) ) + draw.RoundedBox( 4, 1, 1, self:GetWide() - 2, self:GetTall() - 2, Color( 150, 150, 150, 150 ) ) + + //draw.SimpleText( "Class Menu", "ItemDisplayFont", self:GetWide() * 0.5, 10, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + +end + +derma.DefineControl( "ClassPicker", "A class picker menu.", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_dialogue.lua b/gamemode/vgui/vgui_dialogue.lua new file mode 100644 index 0000000..ef76419 --- /dev/null +++ b/gamemode/vgui/vgui_dialogue.lua @@ -0,0 +1,114 @@ +local PANEL = {} + +function PANEL:Init() + + //self:ShowCloseButton( false ) + self:SetKeyboardInputEnabled( false ) + //self:SetDraggable( true ) + + self.Button = vgui.Create( "DButton", self ) + self.Button:SetText( "Close" ) + self.Button.OnMousePressed = function() + + if not InventoryScreen:IsVisible() and not SaleScreen:IsVisible() then + + gui.EnableScreenClicker( false ) + + end + + self:Remove() + + end + + self.TextSizeY = 20 + +end + +function PANEL:SetText( text ) + + self.Text = text + self:InvalidateLayout() + +end + +function PANEL:GetPadding() + + return 20 + +end + +function PANEL:Think() + + if self.Dragging then + + local x = gui.MouseX() - self.Dragging[1] + local y = gui.MouseY() - self.Dragging[2] + + x = math.Clamp( x, 0, ScrW() - self:GetWide() ) + y = math.Clamp( y, 0, ScrH() - self:GetTall() ) + + self:SetPos( x, y ) + + end + +end + +function PANEL:PerformLayout() + + if self.Button then + + self.Button:SetPos( self:GetWide() * 0.5 - self.Button:GetWide() * 0.5, self.TextSizeY + 16 ) + self.Button:SetSize( 48, 18 ) + + end + + self:SetSize( 400, self.TextSizeY + 42 ) + +end + +function PANEL:Paint() + + Derma_DrawBackgroundBlur( self ) + + surface.SetFont( "ItemDisplayFont" ) + + local tbl = string.Explode( " ", self.Text ) + local str = { "" } + local pos = 1 + + for k,v in pairs( tbl ) do + + local test = str[pos] .. " " .. v + local size = surface.GetTextSize( test ) + + if size > self:GetWide() - 40 then + + str[pos] = string.Trim( str[pos] ) + pos = pos + 1 + str[pos] = ( str[pos] or "" ) .. v + + else + + str[pos] = str[pos] .. " " .. v + + end + + end + + self.TextSizeY = 20 + ( pos - 1 ) * 15 + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 255 ) ) + draw.RoundedBox( 4, 1, 1, self:GetWide() - 2, self:GetTall() - 2, Color( 150, 150, 150, 100 ) ) + + draw.RoundedBox( 4, 10, 10, self:GetWide() - 20, self.TextSizeY, Color( 0, 0, 0, 255 ) ) + draw.RoundedBox( 4, 11, 11, self:GetWide() - 22, self.TextSizeY - 2, Color( 150, 150, 150, 150 ) ) + + for k,v in pairs( str ) do + + draw.SimpleText( v, "ItemDisplayFont", self:GetWide() * 0.5, 20 + ( ( k - 1 ) * 15 ), Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + end + +end + +derma.DefineControl( "Dialogue", "A HUD Element with a label and close buton.", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_endgame.lua b/gamemode/vgui/vgui_endgame.lua new file mode 100644 index 0000000..9ea2974 --- /dev/null +++ b/gamemode/vgui/vgui_endgame.lua @@ -0,0 +1,314 @@ +local PANEL = {} + +function PANEL:Init() + + self:PerformLayout() + + self.Wait = CurTime() + 5 + self.Pos = 1 + self.YPos = 220 + self.ListMode = true + self.DrawTbl = {} + self.Awards = {} + + self.Lists = {} + self.Lists[1] = { 5, ScrW() * 0.30, "Survivors", function() return self:GetSurvivors() end, "bot/whoo2.wav" } + self.Lists[2] = { ScrW() * 0.50 - ScrW() * 0.15, ScrW() * 0.30, "Top Killers", function() return self:GetTopKillers() end, "weapons/357_fire2.wav" } + self.Lists[3] = { ScrW() - ( ScrW() * 0.30 ) - 5, ScrW() * 0.30, "Big Spenders", function() return self:GetTopSpenders() end, "physics/metal/chain_impact_soft1.wav" } + + local x, w = ScrW() * 0.50 - ScrW() * 0.15, ScrW() * 0.65 - 5 + + self:ListNewAward( { x, w, "Grey Matter:", "got the most headshots.", function() return self:GetStatMax( "Headshot" ) end, "zombie craniums", "player/headshot1.wav" } ) + self:ListNewAward( { x, w, "Silent Partner:", "got the most kill assists.", function() return self:GetStatMax( "Assist" ) end, "assists", "weapons/357/357_spin1.wav" } ) + self:ListNewAward( { x, w, "Longshot:", "got the longest distance kill.", function() return self:GetStatMax( "Longshot" ) end, "feet", "weapons/fx/nearmiss/bulletLtoR05.wav" } ) + self:ListNewAward( { x, w, "Big Game Hunter:", "dismembered the most zombies with a shotgun.", function() return self:GetStatMax( "Meat" ) end, "zombies poached", "nuke/gore/blood01.wav", true } ) + self:ListNewAward( { x, w, "Bullet Hose:", "used the most ammunition.", function() return self:GetStatMax( "Bullets" ) end, "rounds fired", "player/pl_shell1.wav" } ) + self:ListNewAward( { x, w, "Meat Grinder:", "butchered the most zombies with a melee weapon.", function() return self:GetStatMax( "Knife" ) end, "melee kills", "weapons/knife/knife_hit2.wav", true } ) + self:ListNewAward( { x, w, "Demolitionist:", "killed the most zombies with explosives.", function() return self:GetStatMax( "Explode" ) end, "unidentified bodies", "weapons/underwater_explode3.wav", true } ) + self:ListNewAward( { x, w, "Firebug:", "ignited the most zombies.", function() return self:GetStatMax( "Igniter" ) end, "crispy corpses", "ambient/fire/mtov_flame2.wav", true } ) + self:ListNewAward( { x, w, "Kleptomaniac:", "picked up the most items.", function() return self:GetStatMax( "Loot" ) end, "items taken", "items/itempickup.wav" } ) + self:ListNewAward( { x, w, "Broke The Bank:", "bought the most expensive weapon.", function() return self:GetStatMax( "Pricey" ) end, GAMEMODE.CurrencyName .. "s spent", "ambient/office/coinslot1.wav" } ) + self:ListNewAward( { x, w, "Meet The Engineer:", "built the most barricades.", function() return self:GetStatMax( "Wood" ) end, "barricades built", "npc/dog/dog_servo6.wav", true } ) + self:ListNewAward( { x, w, "Brain Munch:", "dealt the most damage to humans.", function() return self:GetStatMax( "ZedDamage" ) end, "health points", "npc/zombie/zombie_voice_idle2.wav", true } ) + self:ListNewAward( { x, w, "Get To Ze Choppa:", "was the first to reach the evacuation zone.", function() return self:GetStatMax( "Evac" ) end, nil, "ambient/machines/spinup.wav", true } ) + self:ListNewAward( { x, w, "Martyr:", "was the first human to die.", function() return self:GetStatMax( "Martyr" ) end, nil, "npc/crow/alert1.wav", true } ) + self:ListNewAward( { x, w, "Unhealthy Glow:", "was irradiated the most.", function() return self:GetStatMax( "Rad" ) end, "malignant tumors", "player/geiger3.wav", true } ) + self:ListNewAward( { x, w, "Cum Dumpster:", "was infected by zombies the most.", function() return self:GetStatMax( "Infections" ) end, "infections", "ambient/voices/cough1.wav", true } ) + self:ListNewAward( { x, w, "Accident Prone:", "took the most damage from zombies.", function() return self:GetStatMax( "Damage" ) end, "damage", "bot/pain2.wav" } ) + self:ListNewAward( { x, w, "Roleplayer:", "did jack shit.", function() return self:GetWorstPlayer() end, "kills", "ambient/sheep.wav" } ) + //self:ListNewAward( { x, w, "Piss Poor:", "spent the least " .. GAMEMODE.CurrencyName .. "s.", function() return self:GetStatMin( "Spent" ) end, GAMEMODE.CurrencyName .. "s spent", "bot/i_got_nothing.wav" } ) + +end + +function PANEL:ListNewAward( tbl ) + + table.insert( self.Awards, tbl ) + +end + +function PANEL:GetWorstPlayer() + + local min = 9000 + local ply = NULL + + for k,v in pairs( player.GetAll() ) do + + if v:Frags() < min then + + min = v:Frags() + ply = v + + end + + end + + return ply, min + +end + +function PANEL:GetStatMin( name ) + + local min = 9000 + local ply = NULL + + for k,v in pairs( PlayerStats ) do + + if v.Stats and ( v.Stats[ name ] or 0 ) < min then + + min = ( v.Stats[ name ] or 0 ) + ply = v.Player + + end + + end + + return ply, min + +end + +function PANEL:GetStatMax( name ) + + local max = -1 + local ply = NULL + + for k,v in pairs( PlayerStats ) do + + if v.Stats and ( v.Stats[ name ] or 0 ) > max then + + max = ( v.Stats[ name ] or 0 ) + ply = v.Player + + end + + end + + return ply, max + +end + +function PANEL:GetSurvivors() + + local tbl = {} + + for k,v in pairs( team.GetPlayers( TEAM_ARMY ) ) do + + table.insert( tbl, { v } ) + + end + + return tbl + +end + +function PANEL:GetTopSpenders() + + local num = math.min( #player.GetAll(), 5 ) + local tbl = {} + local ignore = {} + + for i=1, num do + + local count = -1 + local ply = NULL + + for k,v in pairs( PlayerStats ) do + + if v.Stats and ( v.Stats[ "Spent" ] or 0 ) > count and not table.HasValue( ignore, v.Player ) then + + ply = v.Player + count = ( v.Stats[ "Spent" ] or 0 ) + + end + + end + + if ply != NULL then + + table.insert( tbl, { ply, count } ) + table.insert( ignore, ply ) + + end + + end + + return tbl + +end + +function PANEL:GetTopKillers() + + local num = math.min( #player.GetAll(), 5 ) + local plys = player.GetAll() + local tbl = {} + + for i=1, num do + + local count = -1 + local ply = NULL + local pos = 0 + + for k,v in pairs( plys ) do + + if v:Frags() > count then + + ply = v + pos = k + count = v:Frags() + + end + + end + + if ply != NULL then + + table.remove( plys, pos ) + table.insert( tbl, { ply, ply:Frags() } ) + + end + + end + + return tbl + +end + +function PANEL:PerformLayout() + + self:SetSize( ScrW(), ScrH() ) + +end + +function PANEL:AddList( pos, width, title, players, sound ) + + surface.PlaySound( sound ) + + table.insert( self.DrawTbl, { X = pos + width * 0.5, Y = 35, Text = title, Style = TEXT_ALIGN_CENTER, Font = "EndGameBig" } ) + + if not players[1] then return end + + local ypos = 60 + + for k,v in pairs( players ) do + + local list = vgui.Create( "PlayerPanel" ) + list:SetPlayerEnt( v[1] ) + list:SetCount( v[2] ) + list:SetTall( 26 ) + list:SetWide( width ) + list:SetPos( pos, ypos ) + + ypos = ypos + 31 + + end + +end + +function PANEL:AddAward( ypos, pos, width, title, desc, ply, amt, append, sound, condition ) + + if condition and amt < 1 then + + self.Wait = 0 + + return + + end + + surface.PlaySound( sound ) + + self.YPos = self.YPos + 31 + self.Wait = CurTime() + 1.5 + + table.insert( self.DrawTbl, { X = pos + 2, Y = ypos + 5, Text = title, Style = TEXT_ALIGN_LEFT, Font = "EndGame" } ) + + local offset = 150 + + local list = vgui.Create( "PlayerPanel" ) + list:SetPlayerEnt( ply ) + list:SetDescription( desc ) + list:SetTall( 26 ) + list:SetWide( width - offset ) + list:SetPos( pos + offset, ypos ) + + if append then + + list:SetCount( amt .. " " .. append ) + + end + +end + +function PANEL:Think() + + if self.Wait and self.Wait < CurTime() then + + self.Wait = CurTime() + 0.5 + + if self.ListMode then + + local alist = self.Lists[ self.Pos ] + + self:AddList( alist[1], alist[2], alist[3], alist[4](), alist[5] ) + + self.Pos = self.Pos + 1 + + if self.Pos > #self.Lists then + + self.ListMode = false + self.Wait = CurTime() + 1.5 + self.Pos = 1 + + end + + else + + local alist = self.Awards[ self.Pos ] + + local ply, amt = alist[5]() + + self:AddAward( self.YPos, alist[1], alist[2], alist[3], alist[4], ply, amt, alist[6], alist[7], alist[8] ) + + self.Pos = self.Pos + 1 + + if self.Pos > #self.Awards then + + self.Wait = nil + + end + + end + + end + +end + +function PANEL:Paint() + + for k,v in pairs( self.DrawTbl ) do + + draw.SimpleText( v.Text, v.Font, v.X, v.Y, Color( 255, 255, 255 ), v.Style, v.Style ) + + end + +end + +derma.DefineControl( "EndGame", "The end-game stat page", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_goodmodelpanel.lua b/gamemode/vgui/vgui_goodmodelpanel.lua new file mode 100644 index 0000000..4434e56 --- /dev/null +++ b/gamemode/vgui/vgui_goodmodelpanel.lua @@ -0,0 +1,202 @@ +/* _ + ( ) + _| | __ _ __ ___ ___ _ _ + /'_` | /'__`\( '__)/' _ ` _ `\ /'_` ) +( (_| |( ___/| | | ( ) ( ) |( (_| | +`\__,_)`\____)(_) (_) (_) (_)`\__,_) sucks shit + +*/ +local PANEL = {} + +AccessorFunc( PANEL, "m_fAnimSpeed", "AnimSpeed" ) +AccessorFunc( PANEL, "Entity", "Entity" ) +AccessorFunc( PANEL, "vCamPos", "CamPos" ) +AccessorFunc( PANEL, "fFOV", "FOV" ) +AccessorFunc( PANEL, "vLookatPos", "LookAt" ) +AccessorFunc( PANEL, "colAmbientLight", "AmbientLight" ) +AccessorFunc( PANEL, "colColor", "Color" ) +AccessorFunc( PANEL, "bAnimated", "Animated" ) + +function PANEL:Init() + + self.Entity = nil + self.NextModel = "" + self.StopRender = false + self.NextSetModel = nil + self.LastPaint = 0 + self.DirectionalLight = {} + + self:SetCamPos( Vector( 50, 50, 50 ) ) + self:SetLookAt( Vector( 0, 0, 40 ) ) + self:SetFOV( 70 ) + + self:SetText( "" ) + self:SetAnimSpeed( 0.5 ) + self:SetAnimated( false ) + + self:SetAmbientLight( Color( 50, 50, 50 ) ) + + self:SetDirectionalLight( BOX_TOP, Color( 255, 255, 255 ) ) + self:SetDirectionalLight( BOX_FRONT, Color( 255, 255, 255 ) ) + + self:SetColor( Color( 255, 255, 255, 255 ) ) + +end + +function PANEL:SetModel( model ) + + if self.NextModel == model then return end + + self.NextModel = model + self.StopRender = true + self.NextSetModel = CurTime() + 0.01 + +end + +function PANEL:Think() + + if self.NextSetModel and self.NextSetModel < CurTime() then + + self:SpecialSetModel( self.NextModel ) + self.StopRender = false + self.NextSetModel = nil + + end + +end + +function PANEL:SpecialSetModel( model ) + + if IsValid( self.Entity ) then + + self.Entity:Remove() + self.Entity = nil + + end + + if not ClientsideModel then return end + + self.LastModel = model + self.Entity = ClientsideModel( model, RENDERGROUP_OPAQUE ) + + if not IsValid( self.Entity ) then return end + + self.Entity:SetNoDraw( true ) + + local seq = self:ChooseSequence( model ) + + if seq > 0 then self.Entity:ResetSequence( seq ) end + +end + +function PANEL:GetSequenceList() + + return { "walk_all", "WalkUnarmed_all", "walk_all_moderate", "idle" } + +end + +function PANEL:ExcludedModels() + + return { "player", "models/human", "eli", "police" } + +end + +function PANEL:ChooseSequence( model ) + + local seq = 0 + + for k,v in pairs( self:ExcludedModels() ) do + + if string.find( model, v ) then + + return self.Entity:LookupSequence( "idle" ) + + end + + end + + for k,v in pairs( self:GetSequenceList() ) do + + if seq <= 0 then seq = self.Entity:LookupSequence( v ) end + + end + + return seq + +end + +function PANEL:Paint() + + if ( !IsValid( self.Entity ) ) then return end + if self.StopRender then return end + + local x, y = self:LocalToScreen( 0, 0 ) + local w, h = self:GetSize() + + local sl, st, sr, sb = x, y, x + w, y + h + + local p = self + + while p:GetParent() do + + p = p:GetParent() + + local pl, pt = p:LocalToScreen( 0, 0 ) + local pr, pb = pl + p:GetWide(), pt + p:GetTall() + + sl = sl < pl and pl or sl + st = st < pt and pt or st + sr = sr > pr and pr or sr + sb = sb > pb and pb or sb + + end + + render.SetScissorRect( sl, st, sr, sb, true ) + + self:LayoutEntity( self.Entity ) + + cam.Start3D( self.vCamPos, (self.vLookatPos-self.vCamPos):Angle(), self.fFOV, x, y, self:GetWide(), self:GetTall() ) + cam.IgnoreZ( true ) + + render.SuppressEngineLighting( true ) + render.SetLightingOrigin( self.Entity:GetPos() ) + render.ResetModelLighting( self.colAmbientLight.r / 255, self.colAmbientLight.g / 255, self.colAmbientLight.b / 255 ) + render.SetColorModulation( self.colColor.r / 255, self.colColor.g / 255, self.colColor.b / 255 ) + render.SetBlend( self.colColor.a / 255 ) + + for i=0, 6 do + local col = self.DirectionalLight[ i ] + if ( col ) then + render.SetModelLighting( i, col.r / 255, col.g / 255, col.b / 255 ) + end + end + + if IsValid( self.Entity ) and not GetGlobalBool( "GameOver", false ) then + + self.Entity:DrawModel() + + end + + render.SuppressEngineLighting( false ) + cam.IgnoreZ( false ) + cam.End3D() + + render.SetScissorRect( 0, 0, 0, 0, false ) + + self.LastPaint = RealTime() + +end + +function PANEL:LayoutEntity( Entity ) + + if self.StopRender then return end + + if ( self.bAnimated ) then + self:RunAnimation() + end + + Entity:SetAngles( Angle( 0, RealTime() * 10, 0) ) + +end + +derma.DefineControl( "GoodModelPanel", "A panel containing a model that isn't broken and gay", PANEL, "DModelPanel" ) diff --git a/gamemode/vgui/vgui_helpmenu.lua b/gamemode/vgui/vgui_helpmenu.lua new file mode 100644 index 0000000..6724302 --- /dev/null +++ b/gamemode/vgui/vgui_helpmenu.lua @@ -0,0 +1,104 @@ +local PANEL = {} + +PANEL.Text = { "<html><body style=\"background-color:DimGray;\">", +"<p style=\"font-family:tahoma;color:red;font-size:25;text-align:center\"><b>READ THIS!</b></p>", +"<p style=\"font-family:verdana;color:black;font-size:10px;text-align:left\"><b>The Inventory System:</b> ", +"To toggle your inventory, press your spawn menu button (default Q). Click an item in your inventory to interact with it. To interact with dropped items, press your USE key (default E) on them.<br><br>", +"<b>Purchasing Items:</b> Press F2 to purchase and order items to be airdropped to you. You can only order items outdoors.<br><br>", +"<b>The Panic Button:</b> Press F3 to activate the panic button. It automatically detects your ailments and attempts to fix them using what you have in your inventory.<br><br>", +"<b>The HUD:</b> The location of important locations and items are marked on your screen. Your teammates are highlighted through walls, as well as the antidote.", +"If you have radiation poisoning, an icon indicating the severity of the poisoning will appear on the bottom left of your screen. An icon will also appear if you are bleeding or infected.<br><br>", +"<b>Evacuation:</b> At the last minute of the round, a helicopter will come to rescue your squad. Run to the evac zone marked on your HUD to be rescued.<br><br>", +"<b>The Infection:</b> The common undead will infect you when they hit you. To cure infection, go to the antidote and press your USE key to access it. The antidote location is always marked on your HUD.<br><br>", +"<b>The Zombie Lord:</b> If there are more than 8 players then a zombie lord will be chosen. If the zombie lord manages to fill their blood meter, they will respawn as a human with a special reward.<br><br>", +"<b>Radiation:</b> Radiation is visually unnoticeable. When near radiation, your handheld geiger counter will make sounds indicating how close you are to a radioactive deposit. Radiation poisoning is cured by vodka or Anti-Rad.<br><br>" } + +PANEL.ButtonText = { "Holy Shit I Don't Care", +"I Didn't Read Any Of That", +"That's A Lot Of Words", +"I'd Rather Just Whine For Help", +"Just Wanna Play Video Games", +"Who Gives A Shit?", +"Help Menus Are For Nerds", +"I Thought This Was A Roleplay Server", +"How I Shoot Zobies", +"How Do I Buy Wepon", +"HEY GUYS WHERES ANTIDOTE this game suck", +"WHERE MY INVENTOREY", +"TL;DR", +"FUCK OFF" } + +function PANEL:Init() + + //self:SetTitle( "" ) + //self:ShowCloseButton( false ) + self:ChooseParent() + + local text = "" + + for k,v in pairs( self.Text ) do + + text = text .. v + + end + + self.Label = vgui.Create( "HTML", self ) + self.Label:SetHTML( text ) + + self.Button = vgui.Create( "DButton", self ) + self.Button:SetText( table.Random( self.ButtonText ) ) + self.Button.OnMousePressed = function() + + self:Remove() + + if LocalPlayer():Team() != TEAM_UNASSIGNED then return end + + local classmenu = vgui.Create( "ClassPicker" ) + classmenu:SetSize( 415, 475 ) + classmenu:Center() + classmenu:MakePopup() + + end + +end + +function PANEL:Think() + + self.Dragging = false + +end + +function PANEL:ChooseParent() + +end + +function PANEL:GetPadding() + + return 5 + +end + +function PANEL:PerformLayout() + + local x,y = self:GetPadding(), self:GetPadding() + 10 + + self.Label:SetSize( self:GetWide() - ( self:GetPadding() * 2 ) - 5, self:GetTall() - 50 ) + self.Label:SetPos( x + 5, y + 5 ) + + self.Button:SetSize( 250, 20 ) + self.Button:SetPos( self:GetWide() * 0.5 - self.Button:GetWide() * 0.5, self:GetTall() - 30 ) + + self:SizeToContents() + +end + +function PANEL:Paint() + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 255 ) ) + draw.RoundedBox( 4, 1, 1, self:GetWide() - 2, self:GetTall() - 2, Color( 150, 150, 150, 150 ) ) + + draw.SimpleText( "Help Menu", "ItemDisplayFont", self:GetWide() * 0.5, 10, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + +end + +derma.DefineControl( "HelpMenu", "A help menu.", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_itemdisplay.lua b/gamemode/vgui/vgui_itemdisplay.lua new file mode 100644 index 0000000..d4a734b --- /dev/null +++ b/gamemode/vgui/vgui_itemdisplay.lua @@ -0,0 +1,157 @@ +local PANEL = {} + +surface.CreateFont ( "ItemDisplayFont", { size = 12, weight = 300, antialias = true, additive = true, font = "Verdana" } ) + +function PANEL:Init() + + //self:ShowCloseButton( false ) + self:SetKeyboardInputEnabled( false ) + //self:SetDraggable( false ) + + self.Text = "Click an item to see its description." + self.Title = "N/A" + self.Style = "Stash" + self.PriceScale = 1 + self.Price = 0 + self.Weight = 0 + +end + +function PANEL:SetItemDesc( text, title, style, scale, price, weight ) + + self.Text = text + self.Title = title + self.Style = style + self.PriceScale = scale + self.Price = price + self.Weight = weight + +end + +function PANEL:SetModel( model, campos, origin ) + + if not self.ModelPanel then + + self.ModelPanel = vgui.Create( "GoodModelPanel", self ) + + end + + self.ModelPanel:SetModel( model ) + self.ModelPanel:SetCamPos( Vector(20,10,5) ) + self.ModelPanel:SetLookAt( Vector(0,0,0) ) + self.ModelPanel.LayoutEntity = function( this, ent ) end + + --[[if string.find( model, "models/weapons/w_" ) then + + self.ModelPanel.LayoutEntity = function( this, ent ) if IsValid( ent ) then ent:SetAngles( Angle( 0, 0, 0 ) ) end end + + else + + self.ModelPanel.LayoutEntity = function( this, ent ) if IsValid( ent ) then ent:SetAngles( Angle( 0, RealTime() * 10, 0 ) ) end end + + end]] + + if CamPosOverride then + + campos = CamPosOverride + + end + + if CamOrigOverride then + + origin = CamOrigOverride + + end + + if campos then + + self.ModelPanel:SetCamPos( campos ) + + end + + if origin then + + self.ModelPanel:SetLookAt( origin ) + + end + + self:InvalidateLayout() + +end + +function PANEL:OnMousePressed( mc ) + +end + +function PANEL:Think() + + local tbl, style, scale = GAMEMODE:GetItemToPreview() + + if tbl then + + self:SetModel( tbl.Model, tbl.CamPos, tbl.CamOrigin ) + self:SetItemDesc( tbl.Description, tbl.Name, style, scale, tbl.Price, tbl.Weight ) + + //GAMEMODE:SetItemToPreview() + + end + +end + +function PANEL:PerformLayout() + + if self.ModelPanel then + + local size = math.Min( self:GetWide(), self:GetTall() * 0.85 ) + local pos = ( self:GetWide() - size ) / 2 + + self.ModelPanel:SetPos( pos, 25 ) + self.ModelPanel:SetSize( size, size ) + + end + + self:SizeToContents() + +end + +function PANEL:GetPadding() + + return 5 + +end + +function PANEL:Paint() + + //draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 255 ) ) + //draw.RoundedBox( 4, 1, 1, self:GetWide() - 2, self:GetTall() - 2, Color( 150, 150, 150, 100 ) ) + + //draw.RoundedBox( 4, 10, ( self:GetTall() * 0.85 ) - 10, self:GetWide() - 20, self:GetTall() * 0.15, Color( 0, 0, 0, 255 ) ) + //draw.RoundedBox( 4, 11, ( self:GetTall() * 0.85 ) - 9, self:GetWide() - 22, self:GetTall() * 0.15 - 2, Color( 150, 150, 150, 150 ) ) + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 180 ) ) + draw.RoundedBox( 0, 35, 40, self:GetWide() - 70, self:GetTall() - 80, Color( 80, 80, 80, 50 ) ) + + surface.SetDrawColor( 200, 200, 200, 200 ) + surface.DrawOutlinedRect( 35, 40, self:GetWide() - 70, self:GetTall() - 80 ) + + draw.SimpleText( self.Title or "N/A", "ItemDisplayFont", self:GetWide() * 0.5, 10, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + if self.Style != "Stash" then + + if not self.Price or self.Price == 0 then + + draw.SimpleText( "Cost: N/A", "ItemDisplayFont", self:GetWide() * 0.5, 25, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + else + + draw.SimpleText( "Cost: "..self.Price.." "..GAMEMODE.CurrencyName.."s", "ItemDisplayFont", self:GetWide() * 0.5, 25, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + end + + end + + draw.SimpleText( self.Text or "N/A", "ItemDisplayFont", self:GetWide() * 0.5, self:GetTall() - 10, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + +end + +derma.DefineControl( "ItemDisplay", "A HUD Element with a big model in the middle and a label", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_itempanel.lua b/gamemode/vgui/vgui_itempanel.lua new file mode 100644 index 0000000..d017c71 --- /dev/null +++ b/gamemode/vgui/vgui_itempanel.lua @@ -0,0 +1,404 @@ +local PANEL = {} + +function PANEL:Init() + + //self:ShowCloseButton( false ) + self:SetKeyboardInputEnabled( false ) + //self:SetDraggable( true ) + self.FuncList = {} + + self.Stashable = false + self.StashStyle = "Take" + self.PriceScale = 1 + +end + +function PANEL:SetPriceScale( scale ) + + self.PriceScale = scale + +end + +function PANEL:SetStashable( bool, style ) + + self.Stashable = bool + self.StashStyle = style + +end + +function PANEL:Think() + +end + +function PANEL:OnMousePressed() + + self:MouseCapture( true ) + + if ( self.NextClick or 0 ) > CurTime() then + + if self.StashStyle == "Buy" then + + if LocalPlayer():GetNWInt( "Cash", 0 ) >= self.ItemTable.Price then + + RunConsoleCommand( "inv_buy", self.ID, 1 ) + GAMEMODE:AddToCart( self.ItemTable, 1 ) + //SaleScreen:AddItems( self.ID, 1 ) + + end + + end + + else + + GAMEMODE:SetItemToPreview( self.ID, self.StashStyle, self.PriceScale, self:GetCount() ) + + self.NextClick = CurTime() + 0.3 + + end + +end + +function PANEL:OnMouseReleased( mc ) + + self.Dragging = nil + self:MouseCapture( false ) + + if mc != MOUSE_RIGHT then return end + + self:MouseMenu() + +end + +function PANEL:MouseMenu() + + local menu = vgui.Create( "DMenu", self ) + menu:AddOption( "Cancel" ) + + if self.Stashable then + + if self.StashStyle == "Take" then + + menu:AddOption( self.StashStyle, function() RunConsoleCommand( "inv_take", self.ID, 1 ) end ) + + if self:GetCount() > 1 then + + if self:GetCount() > 3 then + + local submenu = menu:AddSubMenu( "Take Multiple" ) + + for k,v in pairs{ 3, 5, 10, 20 } do + + if self:GetCount() > v then + + submenu:AddOption( "Take "..v, function() RunConsoleCommand( "inv_take", self.ID, v ) end ) + + end + + end + + end + + menu:AddOption( "Take All", function() RunConsoleCommand( "inv_take", self.ID, self:GetCount() ) end ) + + end + + menu:Open() + return + + elseif self.StashStyle == "Buy" then + + menu:AddOption( self.StashStyle, function() if LocalPlayer():GetNWInt( "Cash", 0 ) >= self.ItemTable.Price then + + RunConsoleCommand( "inv_buy", self.ID, 1 ) + GAMEMODE:AddToCart( self.ItemTable, 1 ) + //SaleScreen:AddItems( self.ID, 1 ) + + end end ) + + local submenu = menu:AddSubMenu( "Buy Multiple" ) + + for k,v in pairs{ 3, 5, 10, 20 } do + + submenu:AddOption( "Buy "..v, function() if LocalPlayer():GetNWInt( "Cash", 0 ) >= self.ItemTable.Price * v then + + RunConsoleCommand( "inv_buy", self.ID, v ) + GAMEMODE:AddToCart( self.ItemTable, v ) + //SaleScreen:AddItems( self.ID, 1 ) + + end end ) + + end + + menu:Open() + return + + elseif self.StashStyle == "Sell" then + + if !self.NotSellable then + + menu:AddOption( self.StashStyle, function() RunConsoleCommand( "inv_sell", self.ID, 1 ) end ) + + if self:GetCount() > 1 then + + if self:GetCount() > 3 then + + local submenu = menu:AddSubMenu( "Sell Multiple" ) + + for k,v in pairs{ 3, 5, 10, 20 } do + + if self:GetCount() > v then + + submenu:AddOption( "Sell "..v, function() RunConsoleCommand( "inv_sell", self.ID, v ) end ) + + end + + end + + end + + menu:AddOption( "Sell All", function() RunConsoleCommand( "inv_sell", self.ID, self:GetCount() ) end ) + + end + + end + + else + + menu:AddOption( self.StashStyle, function() RunConsoleCommand( "inv_store", self.ID, 1 ) end ) + + if self:GetCount() > 1 then + + if self:GetCount() > 3 then + + local submenu = menu:AddSubMenu( "Stash Multiple" ) + + for k,v in pairs{ 3, 5, 10, 20 } do + + if self:GetCount() > v then + + submenu:AddOption( "Stash "..v, function() RunConsoleCommand( "inv_store", self.ID, v ) end ) + + end + + end + + end + + menu:AddOption( "Stash All", function() RunConsoleCommand( "inv_store", self.ID, self:GetCount() ) end ) + + end + + end + + end + + if not self.IsWeapon then + + menu:AddOption( "Drop", function() RunConsoleCommand( "inv_drop", self.ID, 1 ) end ) + + end + + if self:GetCount() > 1 and not self.IsWeapon then + + if self:GetCount() > 3 then + + local submenu = menu:AddSubMenu( "Drop Multiple" ) + + for k,v in pairs{ 3, 5, 10, 20 } do + + if self:GetCount() > v then + + submenu:AddOption( "Drop "..v, function() RunConsoleCommand( "inv_drop", self.ID, v ) end ) + + end + + end + + end + + menu:AddOption( "Drop All", function() RunConsoleCommand( "inv_drop", self.ID, self:GetCount() ) end ) + + end + + for k,v in pairs( self.FuncList ) do + + menu:AddOption( v( 0, 0, true ), function() RunConsoleCommand( "inv_action", self.ID, k ) end ) + + end + + menu:Open() + +end + +function PANEL:SetCount( num ) + + self.ItemCount = num + + if num > 1 then + + self:SetTitle( tostring( num ) ) + + else + + self:SetTitle( "" ) + + end + +end + +function PANEL:GetCount() + + return self.ItemCount or 0 + +end + +function PANEL:AddCount( num ) + + self:SetCount( self:GetCount() + num ) + +end + +function PANEL:GetID() + + return self.ID or 0 + +end + +function PANEL:IsStackable() + + return self.Stackable + +end + +function PANEL:SetItemTable( tbl ) + + self:SetModel( tbl.Model, tbl.CamPos, tbl.CamOrigin ) + self.FuncList = tbl.Functions + self.ID = tbl.ID + self.IsWeapon = tbl.Weapon + self.Stackable = tbl.Stackable + self.PanelModel = tbl.Model + self.ItemTable = tbl + self.ItemTable.Price = tbl.Price or 0 + + if tbl.Sellable != nil and tbl.Sellable == false then + + self.NotSellable = true + + end + +end + +function PANEL:SetModel( model, campos, origin ) + + self.ModelPanel = vgui.Create( "GoodModelPanel", self ) + self.ModelPanel:SetModel( model ) + self.ModelPanel.LayoutEntity = function( ent ) end + self.ModelPanel:SetCamPos( Vector(20,10,5) ) + self.ModelPanel:SetLookAt( Vector(0,0,0) ) + self.ModelPanel.OnMousePressed = function( mc ) self:OnMousePressed( mc ) end + self.ModelPanel.OnMouseReleased = function( mc ) self:OnMouseReleased( mc ) end + + if CamPosOverride then + + campos = CamPosOverride + + end + + if CamOrigOverride then + + origin = CamOrigOverride + + end + + if campos then + + self.ModelPanel:SetCamPos( campos ) + self.ModelPos = campos + + end + + if origin then + + self.ModelPanel:SetLookAt( origin ) + self.ModelOrigin = origin + + end + +end + +function PANEL:SetSizeOverride( size ) + + self.SizeOverride = size + +end + +function PANEL:PerformLayout() + + if self.ModelPanel then + + self.ModelPanel:SetPos( self:GetPadding(), self:GetPadding() ) + + if self.SizeOverride then + + self.ModelPanel:SetSize( self.SizeOverride - 2, self.SizeOverride - 2 ) + + else + + self.ModelPanel:SetSize( 62, 62 ) + + end + + end + + self:SizeToContents() + + if self.SizeOverride then + + self:SetSize( self.SizeOverride, self.SizeOverride ) + + else + + self:SetSize( 64, 64 ) + + end + +end + +function PANEL:Paint() + + if ( self.ItemCount or 1 ) > 1 then + + draw.SimpleText( self.ItemCount, "ItemDisplayFont", self:GetWide() / 8, self:GetTall() / 8, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + end + + //if self.SizeOverride then + + draw.RoundedBox( 0, 3, 3, self:GetWide() - 6, self:GetTall() - 6, Color( 80, 80, 80, 50 ) ) + + if self.StashStyle == "Buy" then + + if LocalPlayer():GetNWInt( "Cash", 0 ) >= self.ItemTable.Price then + + surface.SetDrawColor( 100, 200, 100, 200 ) + + else + + surface.SetDrawColor( 200, 100, 100, 200 ) + + end + + else + + surface.SetDrawColor( 200, 200, 200, 200 ) + + end + + + surface.DrawOutlinedRect( 3, 3, self:GetWide() - 6, self:GetTall() - 6 ) + + +end + +derma.DefineControl( "ItemPanel", "A HUD Element with a model in the middle", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_panelbase.lua b/gamemode/vgui/vgui_panelbase.lua new file mode 100644 index 0000000..b7a4d19 --- /dev/null +++ b/gamemode/vgui/vgui_panelbase.lua @@ -0,0 +1,78 @@ +local PANEL = {} + +function PANEL:Init() + + //self:SetTitle( "" ) + self:ChooseParent() + +end + +function PANEL:ChooseParent() + +end + +function PANEL:OnMousePressed( mc ) + + self.Dragging = { gui.MouseX() - self.x, gui.MouseY() - self.y } + self:MouseCapture( true ) + +end + +function PANEL:Think() + + if self.Dragging then + + local x = gui.MouseX() - self.Dragging[1] + local y = gui.MouseY() - self.Dragging[2] + + x = math.Clamp( x, 0, ScrW() - self:GetWide() ) + y = math.Clamp( y, 0, ScrH() - self:GetTall() ) + + self:SetPos( x, y ) + + end + +end + +function PANEL:GetPadding() + return 1 +end + +function PANEL:GetDefaultTextColor() + return Color( 255, 255, 255, 255 ) +end + +function PANEL:GetTextLabelColor() + return Color( 255, 255, 0 ) +end + +function PANEL:GetTextLabelFont() + return "PanelText" +end + +function PANEL:SetTitle( title ) + + self.Title = title + +end + +function PANEL:GetTitle() + + return self.Title + +end + +function PANEL:Paint() + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 255 ) ) + draw.RoundedBox( 4, 1, 1, self:GetWide() - 2, self:GetTall() - 2, Color( 150, 150, 150, 150 ) ) + + if self.Title then + + draw.SimpleText( self.Title, "ItemDisplayFont", 5, 5, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + end + +end + +derma.DefineControl( "PanelBase", "A HUD Base Element", PANEL, "DPanel" ) diff --git a/gamemode/vgui/vgui_panelsheet.lua b/gamemode/vgui/vgui_panelsheet.lua new file mode 100644 index 0000000..38771ed --- /dev/null +++ b/gamemode/vgui/vgui_panelsheet.lua @@ -0,0 +1,413 @@ +local PANEL = {} + +function PANEL:Init() + + self:ChooseParent() + self.Stashable = false + self.StashStyle = "Stash" + self.PriceScale = 1 + self.Categories = {} + + self:SetDraggableName( "GlobalDPanel" ); + + self.pnlCanvas = vgui.Create( "DPanel", self ) + self.pnlCanvas:SetPaintBackground( false ) + self.pnlCanvas.OnMousePressed = function( self, code ) self:GetParent():OnMousePressed( code ) end + self.pnlCanvas.OnChildRemoved = function() self:OnChildRemoved() end + self.pnlCanvas:SetMouseInputEnabled( true ) + self.pnlCanvas.InvalidateLayout = function() self:InvalidateLayout() end + + self.Items = {} + self.YOffset = 0 + self.m_fAnimTime = 0; + self.m_fAnimEase = -1; -- means ease in out + self.m_iBuilds = 0 + + self:SetSpacing( 0 ) + self:SetPadding( 0 ) + self:EnableHorizontal( false ) + self:SetAutoSize( false ) + self:SetDrawBackground( true ) + //self:SetBottomUp( false ) + self:SetNoSizing( false ) + + self:SetMouseInputEnabled( true ) + + -- This turns off the engine drawing + self:SetPaintBackgroundEnabled( false ) + self:SetPaintBorderEnabled( false ) + + self.ScrollAmt = 0 + +end + +function PANEL:ToggleVisible( tbl, bool ) + + if bool then + + local newtbl = {} + + for k,v in pairs( self.Categories ) do // remove all of tbl from categories + + if not table.HasValue( tbl, v ) then + + table.insert( newtbl, v ) + + end + + end + + self.Categories = newtbl + + else + + for k,v in pairs( tbl ) do // insert all of tbl into categories + + if not table.HasValue( self.Categories, v ) then + + table.insert( self.Categories, v ) + + end + + end + + end + +end + +function PANEL:ChooseParent() + +end + +function PANEL:SetPriceScale( scale ) + + self.PriceScale = scale + +end + +function PANEL:SetStashable( bool, style, localinv ) + + self.Stashable = bool + self.StashStyle = style + self.IsLocalInv = localinv + + for k,v in pairs( self:GetItems() ) do + + v:SetPriceScale( self.PriceScale ) + v:SetStashable( bool, style ) + + end + +end + +function PANEL:GetCash() + + return LocalPlayer():GetNWInt( "Cash", 0 ) + +end + +function PANEL:HasItem( id ) + + for k,v in pairs( self:GetItems() ) do + + if v:GetID() == id then + + return v + + end + + end + +end + +function PANEL:GetItemPnlSize() // determine the size of item panels, always needs to add up to 1.0 + + --[[if self.StashStyle == "Buy" then + + return ( self:GetWide() * 0.2 ) + + end]] + + return ( self:GetWide() * 0.25 ) + +end + +function PANEL:IsBlacklisted( id ) + + local tbl = item.GetByID( id ) + local cat = tbl.Type + + return table.HasValue( self.Categories, cat ) + +end + +function PANEL:RefreshItems( tbl ) + + self:Clear( true ) + + for k,v in pairs( tbl ) do + + local pnl = self:HasItem( v ) + + if pnl and pnl:IsStackable() then + + pnl:AddCount( 1 ) + + elseif not self:IsBlacklisted( v ) then + + local pnl = vgui.Create( "ItemPanel" ) + pnl:SetItemTable( item.GetByID( v ) ) + pnl:SetCount( 1 ) + pnl:SetPriceScale( self.PriceScale ) + pnl:SetStashable( self.Stashable, self.StashStyle ) + pnl:SetSizeOverride( self:GetItemPnlSize() ) //bigg0r + + self:AddItem( pnl ) + + end + + end + + if #tbl < 1 then + + self:InvalidateLayout() + + end + + if self.StashButton then + + self.StashButton:Remove() + self.StashButton = nil + + end + + if self.CashBox then + + self.CashBox:Remove() + self.CashBox = nil + + end + + if self.CashButton then + + self.CashButton:Remove() + self.CashButton = nil + + end + + if self.StashStyle != "Buy" then + + self.CashBox = vgui.Create( "DNumberWang", self ) + self.CashBox:SetDecimals( 0 ) + self.CashBox:SetValue( math.max( self:GetCash(), 5 ) ) + self.CashBox:SetMinMax( 5, math.max( self:GetCash(), 5 ) ) + self.CashBox:SetWide( 80 ) + + self.CashButton = vgui.Create( "DButton", self ) + + if self.StashStyle == "Take" then + + self.CashButton:SetText( self.StashStyle ) + self.CashButton.OnMousePressed = function() + + RunConsoleCommand( "cash_take", math.min( tonumber( self.CashBox:GetValue() ) or 0, self:GetCash() ) ) + + end + + elseif self.StashStyle == "Stash" and self.Stashable then + + self.CashButton:SetText( self.StashStyle ) + self.CashButton.OnMousePressed = function() + + RunConsoleCommand( "cash_stash", math.min( tonumber( self.CashBox:GetValue() ) or 0, self:GetCash() ) ) + + end + + else + + self.CashButton:SetText( "Drop" ) + self.CashButton.OnMousePressed = function() + + RunConsoleCommand( "cash_drop", math.min( tonumber( self.CashBox:GetValue() ) or 0, self:GetCash() ) ) + + end + + end + + end + + if ( self.StashStyle == "Stash" or self.StashStyle == "Take" ) and not self.IsLocalInv and #self:GetItems() > 0 then + + self.StashButton = vgui.Create( "DButton", self ) + self.StashButton:SetText( "Take All" ) + self.StashButton.OnMousePressed = function() + + if #self:GetItems() < 1 then return end + + for k,v in pairs( self:GetItems() ) do + + RunConsoleCommand( "inv_take", v:GetID(), v:GetCount() ) + + end + + end + + end + +end + +function PANEL:Think() + + if self.CashBox then + + if self:GetCash() < 5 then + + self.CashBox:SetMinMax( 5, 5 ) + self.CashBox:SetValue( 5 ) + self.CashButton:SetDisabled( true ) + + else + + self.CashBox:SetMinMax( 5, math.max( self:GetCash(), 5 ) ) + self.CashButton:SetDisabled( false ) + + end + + end + +end + +function PANEL:AddScroll( amt ) + + self.ScrollAmt = self.ScrollAmt + amt + + self.pnlCanvas:SetPos( 0, self.ScrollAmt * self:GetItemPnlSize() ) + +end + +function PANEL:OnVScroll( offset ) + + self.pnlCanvas:SetPos( 0, offset ) + +end + +function PANEL:PerformLayout() + + local wide = self:GetWide() + + if ( !self.Rebuild ) then + debug.Trace() + end + + self:Rebuild() + + self.pnlCanvas:SetPos( 0, self.ScrollAmt * self:GetItemPnlSize() ) + self.pnlCanvas:SetWide( wide ) + + self:Rebuild() + +end + +function PANEL:Rebuild() + + local Offset = 0 + + if ( self.Horizontal ) then + + local x, y = self.Padding, self.Padding + + for k, panel in pairs( self.Items ) do + + if ( panel:IsVisible() ) then + + local w = self:GetItemPnlSize() + local h = self:GetItemPnlSize() + + if ( x + w > self:GetWide() ) then // move down + + x = self.Padding + y = y + h + self.Spacing + + end + + panel:SetPos( x, y ) + + x = x + w + self.Spacing + Offset = y + h + self.Spacing + + end + + end + + else + + for k, panel in pairs( self.Items ) do + + if ( panel:IsVisible() ) then + + if ( self.m_bNoSizing ) then + panel:SizeToContents() + panel:SetPos( (self:GetCanvas():GetWide() - panel:GetWide()) * 0.5, self.Padding + Offset ) + else + panel:SetSize( self:GetCanvas():GetWide() - self.Padding * 2, panel:GetTall() ) + panel:SetPos( self.Padding, self.Padding + Offset ) + end + + panel:InvalidateLayout( true ) + + Offset = Offset + panel:GetTall() + self.Spacing + + end + + end + + Offset = Offset + self.Padding + + end + + self:GetCanvas():SetTall( self:GetTall() + Offset - self.Spacing ) + + if ( self.m_bNoSizing and self:GetCanvas():GetTall() < self:GetTall() ) then + + self:GetCanvas():SetPos( 0, (self:GetTall()-self:GetCanvas():GetTall()) * 0.5 ) + + end + + if self.StashButton then + + self.StashButton:SetSize( 48, 20 ) + self.StashButton:SetPos( self:GetWide() - self:GetPadding() * 2 - self.StashButton:GetWide(), self:GetTall() - self:GetPadding() * 2 - self.StashButton:GetTall() ) + + end + + if self.CashBox then + + self.CashBox:SetPos( self:GetPadding() * 2, self:GetTall() - ( self:GetPadding() * 2 ) - 20 ) + + end + + if self.CashButton then + + self.CashButton:SetSize( 48, 20 ) + self.CashButton:SetPos( ( self:GetPadding() * 2 ) + 5 + self.CashBox:GetWide(), self:GetTall() - ( self:GetPadding() * 2 ) - 20 ) + + end + +end + +function PANEL:Paint() + + //draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 255 ) ) + //draw.RoundedBox( 4, 1, 1, self:GetWide() - 2, self:GetTall() - 2, Color( 150, 150, 150, 100 ) ) + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 180 ) ) + + if self.StashStyle == "Buy" then return end + + draw.SimpleText( "Cash: $" .. self:GetCash(), "ItemDisplayFont", self:GetPadding() * 2, self:GetTall() - ( self:GetPadding() * 2 ) - 35, Color( 255, 255, 255 ), TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + + //draw.TexturedQuad( { texture = surface.GetTextureID( "radbox/menu_trade" ), x = self:GetPadding() * 2, y = self:GetTall() - ( self:GetPadding() * 2 ) - 40, w = 40, h = 40, color = Color( 200, 200, 200 ) } ) + +end + +derma.DefineControl( "ItemSheet", "A sheet for storing HUD elements", PANEL, "DPanelList" ) diff --git a/gamemode/vgui/vgui_playerdisplay.lua b/gamemode/vgui/vgui_playerdisplay.lua new file mode 100644 index 0000000..b508efb --- /dev/null +++ b/gamemode/vgui/vgui_playerdisplay.lua @@ -0,0 +1,166 @@ +local PANEL = {} + +function PANEL:Init() + + //self:ShowCloseButton( false ) + self:SetKeyboardInputEnabled( false ) + //self:SetDraggable( false ) + + self.Text = "" + self.Title = "" + self.LastModel = "" + +end + +function PANEL:SetupCam( campos, origin ) + + self.CamPos = campos + self.Origin = origin + +end + +function PANEL:SetModel( campos, origin ) + + if not self.ModelPanel then + + self.ModelPanel = vgui.Create( "GoodModelPanel", self ) + + end + + self.ModelPanel:SetModel( LocalPlayer():GetModel() ) + + if campos then + + self.ModelPanel:SetCamPos( campos ) + + end + + if origin then + + self.ModelPanel:SetLookAt( origin ) + + end + + self:InvalidateLayout() + +end + +function PANEL:Think() + + if not IsValid( LocalPlayer() ) then return end + + if self.LastModel != LocalPlayer():GetModel() then + + self:SetModel( self.CamPos, self.Origin ) + self.LastModel = LocalPlayer():GetModel() + + end + +end + +function PANEL:PerformLayout() + + if self.ModelPanel then + + local size = math.Min( self:GetWide(), self:GetTall() * 0.85 ) + local pos = ( self:GetWide() - size ) / 2 + + self.ModelPanel:SetPos( pos, 0 ) + self.ModelPanel:SetSize( size, size ) + + end + + self:SizeToContents() + +end + +function PANEL:GetStats() + + local tbl = {} + local weight = math.Round( LocalPlayer():GetNWFloat( "Weight", 0 ) * 100 ) / 100 + local cash = LocalPlayer():GetNWInt( "Cash", 0 ) + + if cash < 20 then + + table.insert( tbl, { GAMEMODE.CurrencyName .. "s: " .. cash, Color(255,150,50) } ) + + else + + table.insert( tbl, { GAMEMODE.CurrencyName .. "s: " .. cash, Color(255,255,255) } ) + + end + + if weight < GAMEMODE.OptimalWeight then + + table.insert( tbl, { "Weight: " .. weight .. " lbs", Color(255,255,255) } ) + + elseif weight < GAMEMODE.MaxWeight then + + table.insert( tbl, { "Weight: " .. weight .. " lbs", Color(255,150,50) } ) + + else + + table.insert( tbl, { "Weight: " .. weight .. " lbs", Color(255,100,100) } ) + + end + + if LocalPlayer():GetNWBool( "Infected", false ) then + + table.insert( tbl, { "Health Status: Infected", Color(255,100,100) } ) + + elseif LocalPlayer():GetNWBool( "Bleeding", false ) then + + table.insert( tbl, { "Health Status: Bleeding", Color(255,100,100) } ) + + elseif LocalPlayer():Health() < 75 then + + table.insert( tbl, { "Health Status: Critical", Color(255,100,100) } ) + + elseif LocalPlayer():Health() < 140 then + + table.insert( tbl, { "Health Status: Injured", Color(255,150,50) } ) + + else + + table.insert( tbl, { "Health Status: Normal", Color(255,255,255) } ) + + end + + if LocalPlayer():GetNWInt( "Radiation", 0 ) > 2 then + + table.insert( tbl, { "Radiation Levels: Lethal", Color(255,100,100) } ) + + elseif LocalPlayer():GetNWInt( "Radiation", 0 ) > 0 then + + table.insert( tbl, { "Radiation Levels: Elevated", Color(255,150,50) } ) + + else + + table.insert( tbl, { "Radiation Levels: Normal", Color(255,255,255) } ) + + end + + return tbl + +end + +function PANEL:Paint() + + if not IsValid( LocalPlayer() ) then return end + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 255 ) ) + draw.RoundedBox( 4, 1, 1, self:GetWide() - 2, self:GetTall() - 2, Color( 150, 150, 150, 100 ) ) + + surface.SetFont( "ItemDisplayFont" ) + + for k,v in pairs( self:GetStats() ) do + + draw.SimpleText( v[1], "ItemDisplayFont", self:GetWide() * 0.5, self:GetTall() * 0.83 + ( ( k - 1 ) * 15 ), v[2], TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + + end + + draw.SimpleText( LocalPlayer():Name(), "ItemDisplayFont", self:GetWide() * 0.5, 15, Color( 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + +end + +derma.DefineControl( "PlayerDisplay", "A HUD Element with a big model in the middle and player stats.", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_playerpanel.lua b/gamemode/vgui/vgui_playerpanel.lua new file mode 100644 index 0000000..9779466 --- /dev/null +++ b/gamemode/vgui/vgui_playerpanel.lua @@ -0,0 +1,68 @@ +local PANEL = {} + +function PANEL:Init() + + //self:ShowCloseButton( false ) + + self.Avatar = vgui.Create( "AvatarImage", self ) + self.PlayerName = "N/A" + self.Desc = "" + + self:PerformLayout() + +end + +function PANEL:SetPlayerEnt( ply ) + + self.Avatar:SetPlayer( ply ) + + if IsValid( ply ) then + + self.PlayerName = ply:Nick() + + end + +end + +function PANEL:SetCount( num ) + + self.Count = num + +end + +function PANEL:SetDescription( text ) + + self.Desc = text + +end + +function PANEL:GetPadding() + + return 5 + +end + +function PANEL:PerformLayout() + + self.Avatar:SetSize( 16, 16 ) + self.Avatar:SetPos( self:GetPadding(), self:GetPadding() ) + + self:SetTall( 16 + self:GetPadding() * 2 ) + +end + +function PANEL:Paint() + + draw.RoundedBox( 4, 2, 2, self:GetWide() - 4, self:GetTall() - 4, Color( 100, 100, 100, 255 ) ) + + draw.SimpleText( self.PlayerName .. " " .. self.Desc, "EndGame", self:GetPadding() * 3 + 16, self:GetTall() * 0.4 - self:GetPadding(), Color( 255, 255, 255 ), TEXT_ALIGN_LEFT, TEXT_ALIGN_LEFT ) + + if self.Count then + + draw.SimpleText( self.Count, "EndGame", self:GetWide() - self:GetPadding() * 2, self:GetTall() * 0.4 - self:GetPadding(), Color( 255, 50, 50 ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_RIGHT ) + + end + +end + +derma.DefineControl( "PlayerPanel", "A HUD Element with a player name and avatar", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_scroller.lua b/gamemode/vgui/vgui_scroller.lua new file mode 100644 index 0000000..0fb9e51 --- /dev/null +++ b/gamemode/vgui/vgui_scroller.lua @@ -0,0 +1,105 @@ +local PANEL = {} + +function PANEL:Init() + + //self:SetTitle( "" ) + //self:ShowCloseButton( false ) + //self:SetDraggable( false ) + + self.Image = vgui.Create( "DImageButton", self ) + self.Image:SetImage( "icon16/car.png" ) + self.Image:SetStretchToFit( false ) + self.Image.OnMousePressed = function() + + self.Depressed = true + + end + + self.Image.OnMouseReleased = function() + + self.Depressed = false + + end + + self:SetCursor( "hand" ) + self.Up = true + self.MoveTime = 0 + +end + +function PANEL:SetImage( img ) + + self.Image:SetImage( img ) + +end + +function PANEL:SetScrollUp( bool ) + + self.Up = bool + +end + +function PANEL:Think() + + if not self.Target then return end + + if self.Depressed and self.MoveTime < CurTime() then + + self.MoveTime = CurTime() + 0.2 + + if self.Up then + + self.Target:AddScroll( 1 ) + + else + + self.Target:AddScroll( -1 ) + + end + + surface.PlaySound( "buttons/lightswitch2.wav" ) + + end + +end + +function PANEL:SetTarget( pnl ) + + self.Target = pnl + +end + +function PANEL:OnMousePressed( mousecode ) + + self.Depressed = true + self:MouseCapture( true ) + +end + +function PANEL:OnMouseReleased( mousecode ) + + self.Depressed = false + self:MouseCapture( false ) + +end + +function PANEL:GetPadding() + return 5 +end + +function PANEL:PerformLayout() + + self.Image:SetSize( self:GetWide() - 10, self:GetTall() - 10 ) + self.Image:SetPos( 5, 5 ) + + //self:SizeToContents() + +end + +function PANEL:Paint() + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 180 ) ) + +end + +derma.DefineControl( "Scroller", "A shitty scroller thing.", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_shopmenu.lua b/gamemode/vgui/vgui_shopmenu.lua new file mode 100644 index 0000000..99a201e --- /dev/null +++ b/gamemode/vgui/vgui_shopmenu.lua @@ -0,0 +1,77 @@ +local PANEL = {} + +function PANEL:Init() + + //self:SetTitle( "" ) + //self:ShowCloseButton( false ) + //self:SetDraggable( false ) + + self.Items = {} + + self.List = vgui.Create( "DListView", self ) + + local col1 = self.List:AddColumn( "Ordered Item" ) + local col2 = self.List:AddColumn( "Cost" ) + + col1:SetMinWidth( 150 ) + col2:SetMinWidth( 50 ) + col2:SetMaxWidth( 100 ) + + self.Button = vgui.Create( "DImageButton", self ) + self.Button:SetImage( "toxsin/airdrop" ) + self.Button.OnMousePressed = function() self.List:Clear() self.Items = {} RunConsoleCommand( "ordershipment" ) RunConsoleCommand( "gm_showteam" ) end + +end + +function PANEL:AddItems( id, amt ) + + local tbl = item.GetByID( id ) + + if tbl.Price * amt > LocalPlayer():GetNWInt( "Cash", 0 ) then return end + + for i=1,amt do + + table.insert( self.Items, id ) + + end + + self.List:Clear() + + for k,v in pairs( self.Items ) do + + local tbl = item.GetByID( v ) + + self.List:AddLine( tbl.Name, tbl.Price ) + + end + +end + +function PANEL:GetPadding() + return 5 +end + +function PANEL:PerformLayout() + + local x,y = self:GetPadding(), self:GetPadding() + 30 + + self.List:SetSize( self:GetWide() * 0.5 - ( 2 * self:GetPadding() ), self:GetTall() - ( 2 * self:GetPadding() ) - 30 ) + self.List:SetPos( x, y ) + + self.Button:SetSize( self:GetWide() * 0.5 - ( 2 * self:GetPadding() ), self:GetTall() - ( 2 * self:GetPadding() ) - 30 ) + self.Button:SetPos( x + self.List:GetWide() + self:GetPadding(), self:GetPadding() + 30 ) + + self:SizeToContents() + +end + +function PANEL:Paint() + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 255 ) ) + draw.RoundedBox( 4, 1, 1, self:GetWide() - 2, self:GetTall() - 2, Color( 150, 150, 150, 150 ) ) + + draw.SimpleText( "Shipment Display", "ItemDisplayFont", self:GetWide() * 0.5, 10, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + +end + +derma.DefineControl( "ShopMenu", "A shop menu.", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_sidebutton.lua b/gamemode/vgui/vgui_sidebutton.lua new file mode 100644 index 0000000..f7de0e6 --- /dev/null +++ b/gamemode/vgui/vgui_sidebutton.lua @@ -0,0 +1,131 @@ +local PANEL = {} + +PANEL.Sound = Sound( "common/talk.wav" ) + +function PANEL:Init() + + //self:SetTitle( "" ) + //self:ShowCloseButton( false ) + //self:SetDraggable( false ) + + self.Image = vgui.Create( "DImageButton", self ) + self.Image:SetImage( "icon16/car.png" ) + self.Image:SetStretchToFit( false ) + self.Image.DoClick = function() + + self:DoClick() + + end + + self:SetCursor( "hand" ) + self.Text = "" + self.White = 255 + self.ColorTime = 0 + +end + +function PANEL:SetImage( img ) + + self.Image:SetImage( img ) + +end + +function PANEL:SetText( text ) + + self.Text = text + +end + +function PANEL:DoClick() + + self.Func() + surface.PlaySound( self.Sound ) + +end + +function PANEL:SetFunction( func ) + + self.Func = func + +end + +function PANEL:SetSelectedState( bool, ignore ) + + self.Selected = tobool( bool ) + + if ignore then return end + + self:DoSound( bool ) + +end + +function PANEL:OnMousePressed( mousecode ) + + self:MouseCapture( true ) + +end + +function PANEL:OnMouseReleased( mousecode ) + + self:MouseCapture( false ) + self:DoClick() + +end + +function PANEL:GetPadding() + return 5 +end + +function PANEL:PerformLayout() + + local imgsize = self:GetTall() - ( 2 * self:GetPadding() ) + + self.Image:SetSize( imgsize, imgsize ) + self.Image:SetPos( self:GetWide() - imgsize - self:GetPadding(), self:GetPadding() ) + + //self:SizeToContents() + +end + +function PANEL:Paint() + + local tx, ty = self:GetPadding() * 2, self:GetTall() * 0.5 - 8 + //local px, py = self.Image:GetPos() + local imgsize = self:GetTall() - ( 2 * self:GetPadding() ) + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 180 ) ) + + if self.Hovered then + + draw.RoundedBox( 4, self:GetWide() - imgsize - self:GetPadding(), self:GetPadding(), imgsize, imgsize, Color( 100, 100, 100, 100 ) ) + + draw.SimpleText( self.Text, "CategoryButton", tx+1, ty+1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx-1, ty-1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx+1, ty-1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx-1, ty+1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + + if self.ColorTime < CurTime() then + + self.ColorTime = CurTime() + math.Rand( 0, 0.3 ) + self.White = math.random( 150, 255 ) + + end + + draw.SimpleText( self.Text, "CategoryButton", tx, ty, Color( self.White, self.White, self.White, 255 ), TEXT_ALIGN_LEFT ) + + else + + draw.RoundedBox( 4, self:GetWide() - imgsize - self:GetPadding(), self:GetPadding(), imgsize, imgsize, Color( 100, 100, 100, 100 ) ) + + draw.SimpleText( self.Text, "CategoryButton", tx+1, ty+1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx-1, ty-1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx+1, ty-1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + draw.SimpleText( self.Text, "CategoryButton", tx-1, ty+1, Color( 0, 0, 0, 150 ), TEXT_ALIGN_LEFT ) + + draw.SimpleText( self.Text, "CategoryButton", tx, ty, Color( 100, 100, 100, 255 ), TEXT_ALIGN_LEFT ) + + end + +end + +derma.DefineControl( "SideButton", "A shitty action button thing.", PANEL, "PanelBase" ) diff --git a/gamemode/vgui/vgui_zombieclasses.lua b/gamemode/vgui/vgui_zombieclasses.lua new file mode 100644 index 0000000..057c1b6 --- /dev/null +++ b/gamemode/vgui/vgui_zombieclasses.lua @@ -0,0 +1,76 @@ +local PANEL = {} + +function PANEL:Init() + + //self:SetTitle( "" ) + //self:ShowCloseButton( false ) + self:ChooseParent() + + self.Items = {} + + for k,v in pairs( GAMEMODE.ZombieNames ) do + + local desc = GAMEMODE.ZombieDescriptions[k] or "TEH" + local logo = GAMEMODE.ZombieLogos[k] or "brick/brick_model" + + local button = vgui.Create( "DImageButton", self ) + button:SetImage( logo ) + button:SetSize( 100, 100 ) + button.OnMousePressed = function() RunConsoleCommand( "changeclass", k ) surface.PlaySound( "npc/zombie/claw_strike1.wav" ) self:Remove() end + button.ID = id + + local label = vgui.Create( "DLabel", self ) + label:SetWrap( true ) + label:SetText( desc ) + label:SetFont( "ItemDisplayFont" ) + label:SetSize( 300, 100 ) + + table.insert( self.Items, { button, label } ) + + end + +end + +function PANEL:Think() + + self.Dragging = false + +end + +function PANEL:ChooseParent() + +end + +function PANEL:GetPadding() + + return 5 + +end + +function PANEL:PerformLayout() + + local x,y = self:GetPadding(), self:GetPadding() + 50 + + for k,v in pairs( self.Items ) do + + v[1]:SetPos( x, y ) + v[2]:SetPos( x + 100 + self:GetPadding(), y ) + + y = y + 100 + self:GetPadding() + + end + + self:SizeToContents() + +end + +function PANEL:Paint() + + draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 255 ) ) + draw.RoundedBox( 4, 1, 1, self:GetWide() - 2, self:GetTall() - 2, Color( 150, 150, 150, 150 ) ) + + draw.SimpleText( "Class Menu", "ItemDisplayFont", self:GetWide() * 0.5, 10, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) + +end + +derma.DefineControl( "ZombieClassPicker", "A zombie class picker menu.", PANEL, "PanelBase" ) diff --git a/gamemode/weather.lua b/gamemode/weather.lua new file mode 100644 index 0000000..762ebd5 --- /dev/null +++ b/gamemode/weather.lua @@ -0,0 +1,703 @@ + +GM.Weather = {} +GM.Weather.Rain = 0 +GM.Weather.Thunder = 0 +GM.Weather.Lightning = 0 +GM.Weather.Wind = 0 +GM.Weather.TransitionTime = 60 // 1 minute for weather transitions + +GM.Weather.New = {} +GM.Weather.New.Rain = 0 +GM.Weather.New.Thunder = 0 +GM.Weather.New.Lightning = 0 +GM.Weather.New.Wind = 0 + +function GM:EntityKeyValue( ent, key, val ) + + if ent:GetClass() == "worldspawn" and key == "skyname" then + + SetGlobalString( "SkyName", val ) + + end + +end + +function GM:WeatherInit() + + if CLIENT then + + RainEmitter = ParticleEmitter( Vector(0,0,0) ) + + end + +end + +function GM:PlayerIndoors( ply ) + + if SERVER then + + return ply:IsIndoors() + + else + + local tr = util.TraceLine( util.GetPlayerTrace( LocalPlayer(), Vector(0,0,1) ) ) + + if tr.HitWorld and not tr.HitSky then + + GAMEMODE.PlayerIsIndoors = true + + return true + + end + + end + + GAMEMODE.PlayerIsIndoors = false + + return false + +end + +function GM:RandomizeWeather( force ) + + GAMEMODE.Weather.New.Rain = 0 + GAMEMODE.Weather.New.Thunder = 0 + GAMEMODE.Weather.New.Lightning = 0 + GAMEMODE.Weather.New.Wind = 0 + + if math.random(1,5) == 1 and not force then + + GAMEMODE:SynchWeather() + + return {0,0,0,0} + + end + + for k,v in pairs( GAMEMODE.Weather.New ) do + + if math.random(1,5) > 1 then + + GAMEMODE.Weather.New[k] = math.Rand(0,1) + + if math.random(1,3) == 1 then + + GAMEMODE.Weather.New[k] = 1 + + end + + end + + end + + local count = 0 + + for k,v in pairs( GAMEMODE.Weather.New ) do + + if v == 0 then + + count = count + 1 + + end + + end + + if count == 4 or math.random(1,10) == 1 then + + GAMEMODE.Weather.New.Rain = 1 + GAMEMODE.Weather.New.Thunder = 1 + GAMEMODE.Weather.New.Lightning = 1 + GAMEMODE.Weather.New.Wind = 1 + + end + + GAMEMODE:SynchWeather() + + return { GAMEMODE.Weather.New.Rain, GAMEMODE.Weather.New.Thunder, GAMEMODE.Weather.New.Lightning, GAMEMODE.Weather.New.Wind } + +end + +function GM:ManualWeather( rain, thunder, lightning, wind ) + + GAMEMODE.Weather.New.Rain = rain + GAMEMODE.Weather.New.Thunder = thunder + GAMEMODE.Weather.New.Lightning = lightning + GAMEMODE.Weather.New.Wind = wind + + GAMEMODE.Weather.NextShift = CurTime() + math.random( 240, 480 ) + + GAMEMODE:SynchWeather() + +end + +function GM:ShiftWeather() + + for k,v in pairs( GAMEMODE.Weather.New ) do + + if v < 0.2 and math.random(1,2) == 1 then + + GAMEMODE.Weather.New[k] = 0 + + else + + GAMEMODE.Weather.New[k] = math.Clamp( v + math.Rand( -0.2, math.Rand( 0.2, 0.3 ) ), 0, 1 ) + + end + + end + + GAMEMODE:SynchWeather() + +end + +function GM:WeatherThink() + + if not GAMEMODE.Weather.NextShift then + + GAMEMODE.Weather.NextShift = CurTime() + math.random( 120, 600 ) + + elseif GAMEMODE.Weather.NextShift < CurTime() then + + GAMEMODE.Weather.NextShift = nil + + GAMEMODE:ShiftWeather() + + end + +end + +function GM:SynchWeather() + + net.Start( "WeatherSynch" ) + + net.WriteTable( GAMEMODE.Weather.New ) + + net.Broadcast() + +end + +if SERVER then return end + +net.Receive( "WeatherSynch", function( len ) + + GAMEMODE.Weather.New = net.ReadTable() + GAMEMODE.Weather.Transition = true + GAMEMODE.Weather.Inc = 0 + + //PrintTable( GAMEMODE.Weather.New ) + +end ) + +function GM:ProcessWeather() + + GAMEMODE:RainThink() + GAMEMODE:ThunderThink() + GAMEMODE:LightningThink() + GAMEMODE:WindThink() + + if GAMEMODE.Weather.Transition then + + //local scale = 1 - ( ( GAMEMODE.Weather.Transition - CurTime() ) / GAMEMODE.Weather.TransitionTime ) + + if GAMEMODE.Weather.Inc <= CurTime() then + + GAMEMODE.Weather.Inc = CurTime() + 1 + local count = 0 + + for k,v in pairs( GAMEMODE.Weather.New ) do + + local diff = math.abs( GAMEMODE.Weather[k] - GAMEMODE.Weather.New[k] ) + local inc = diff / GAMEMODE.Weather.TransitionTime + + GAMEMODE.Weather[k] = math.Approach( GAMEMODE.Weather[k], GAMEMODE.Weather.New[k], inc ) + + if GAMEMODE.Weather[k] == GAMEMODE.Weather.New[k] then + + count = count + 1 + + end + + end + + if count == 4 then + + GAMEMODE.Weather.Transition = false + + end + + end + + end + +end + +RainMat = surface.GetTextureID( "effects/rain_warp" ) + +function GM:PaintWeather() + + if GAMEMODE.Weather.Rain > 0 and render.GetDXLevel() >= 90 then + + for k,v in pairs( GAMEMODE.RainDrops ) do + + local scale = math.Clamp( ( v.Time - CurTime() ) / v.Life, 0, 1 ) + + surface.SetDrawColor( 200, 200, 220, 255 * scale ) + surface.SetTexture( RainMat ) + surface.DrawTexturedRect( v.X, v.Y - v.Movement * scale, v.Size, v.Size ) + + end + + end + +end + +function GM:GetSky() + + local tr = util.TraceLine( util.GetPlayerTrace( LocalPlayer(), Vector(0,0,1) ) ) + + if tr.HitSky then + + GAMEMODE.LastSkyPos = tr.HitPos + GAMEMODE.PlayerIsIndoors = false + + GAMEMODE:ComputeSkyBounds() + + return tr.HitPos + + elseif GAMEMODE.LastSkyPos then + + GAMEMODE.PlayerIsIndoors = true + + return GAMEMODE.LastSkyPos + + else + + return LocalPlayer():GetPos() + + end + +end + +GM.RainDist = 1000 +GM.RainDrops = {} + +function GM:ComputeSkyBounds() + + local trace = {} + trace.start = GAMEMODE.LastSkyPos + trace.endpos = trace.start + Vector( GAMEMODE.RainDist, 0, 0 ) + + local tr = util.TraceLine( trace ) + + trace = {} + trace.start = tr.HitPos + trace.endpos = trace.start + Vector( 0, GAMEMODE.RainDist, 0 ) + + tr = util.TraceLine( trace ) + + GAMEMODE.RightSkyBound = tr.HitPos + + trace = {} + trace.start = GAMEMODE.LastSkyPos + trace.endpos = trace.start + Vector( GAMEMODE.RainDist * -1, 0, 0 ) + + tr = util.TraceLine( trace ) + + trace = {} + trace.start = tr.HitPos + trace.endpos = trace.start + Vector( 0, GAMEMODE.RainDist * -1, 0 ) + + tr = util.TraceLine( trace ) + + GAMEMODE.LeftSkyBound = tr.HitPos + +end + +function GM:GetClosestSkyPos() + + local skypos = GAMEMODE:GetSky() + local pos = LocalPlayer():GetPos() + + local trace = {} + trace.start = skypos + trace.endpos = Vector( pos.x, pos.y, skypos.z ) + + local tr = util.TraceLine( trace ) + + GAMEMODE.LastSkyPos = tr.HitPos + + GAMEMODE:ComputeSkyBounds() + + return tr.HitPos + +end + +GM.RainSound = Sound( "ambient/weather/rumble_rain_nowind.wav" ) + +function GM:RainThink() + + for k,v in pairs( GAMEMODE.RainDrops ) do + + if v.Time < CurTime() then + + table.remove( GAMEMODE.RainDrops, k ) + + break + + end + + end + + if GAMEMODE.Weather.Rain > 0 and ( GAMEMODE.NextRainDrop or 0 ) < CurTime() and not GAMEMODE.PlayerIsIndoors then + + GAMEMODE.NextRainDrop = CurTime() + math.Rand( 1 - GAMEMODE.Weather.Rain, ( 1.2 - GAMEMODE.Weather.Rain ) * 3 ) + + for i=1, math.random( 1, math.floor( GAMEMODE.Weather.Rain * 4 ) ) do + + local tbl = {} + + tbl.Size = math.random( 40, 80 ) + math.random( 0, GAMEMODE.Weather.Rain * 20 ) + tbl.X = math.random( 0, ScrW() - tbl.Size ) + tbl.Y = math.random( 0, ScrH() - tbl.Size ) + tbl.Movement = math.random( 20, 80 ) + tbl.Life = math.Rand( 1.0, 5.0 ) + tbl.Time = CurTime() + tbl.Life + + if math.random(1,5) == 1 then + + tbl.Movement = 10 + + end + + table.insert( GAMEMODE.RainDrops, tbl ) + + end + + end + + if ( GAMEMODE.NextRain or 0 ) < CurTime() then + + GAMEMODE.NextRain = CurTime() + 0.2 + + local amt = math.floor( GAMEMODE.Weather.Rain * 175 * CV_Density:GetFloat() ) + + GAMEMODE:SpawnRain( amt ) + + if not GAMEMODE.RainNoise then + + GAMEMODE.RainNoise = CreateSound( LocalPlayer(), GAMEMODE.RainSound ) + GAMEMODE.RainNoise:PlayEx( GAMEMODE.Weather.Rain * 0.3, 100 ) + GAMEMODE.RainVolume = GAMEMODE.Weather.Rain * 0.4 + + else + + if GAMEMODE.PlayerIsIndoors then + + GAMEMODE.RainVolume = math.Approach( ( GAMEMODE.RainVolume or 0 ), math.max( GAMEMODE.Weather.Rain * 0.05, 0.02 ), 0.01 ) + + elseif GAMEMODE.Weather.Rain == 0 then + + GAMEMODE.RainVolume = math.Approach( ( GAMEMODE.RainVolume or 0 ), 0, 0.002 ) + + else + + GAMEMODE.RainVolume = math.Approach( ( GAMEMODE.RainVolume or 0 ), math.max( GAMEMODE.Weather.Rain * 0.4, 0.02 ), 0.002 ) + + end + + GAMEMODE.RainNoise:ChangeVolume( GAMEMODE.RainVolume, GAMEMODE.RainVolume ) + + end + + end + +end + +function GM:SpawnRain( amt ) + + if amt == 0 and not GetGlobalBool( "Radiation", false ) then return end + + local function RainCollision( particle, pos, norm ) + + particle:SetDieTime( 0 ) + + if math.random(1,6) == 1 then + + local particle = RainEmitter:Add( "effects/blood", pos ) + particle:SetVelocity( Vector(0,0,0) ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( 0.25 ) + particle:SetStartAlpha( 100 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( 1 ) + particle:SetEndSize( math.Rand( 3, 10 + GAMEMODE.Weather.Rain * 5 ) ) + particle:SetRoll( math.Rand( -360, 360 ) ) + particle:SetAirResistance( 0 ) + particle:SetCollide( false ) + //particle:SetColor( Color( 200, 200, 250 ) ) + + end + + end + + local function CloudCollision( particle, pos, norm ) + + particle:SetDieTime( 0 ) + + end + + local function RadCollision( particle, pos, norm ) + + particle:SetDieTime( math.Rand( 1.0, 3.0 ) ) + + end + + local pos = GAMEMODE:GetClosestSkyPos() + + if not pos then return end + + if GetGlobalBool( "Radiation", false ) then + + for i=1, 10 do + + local vec = Vector( math.random( GAMEMODE.LeftSkyBound.x, GAMEMODE.RightSkyBound.x ), math.random( GAMEMODE.LeftSkyBound.y, GAMEMODE.RightSkyBound.y ), pos.z ) + + local particle = RainEmitter:Add( "effects/rain_cloud", vec ) + particle:SetVelocity( Vector( 0, 0, math.random( -1000, -800 ) ) + WindVector * math.Rand( 0, 2.0 ) ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( 10 ) + particle:SetStartAlpha( math.random( 5, 10 ) ) + particle:SetEndAlpha( 5 ) + particle:SetStartSize( math.random( 150, 250 ) ) + particle:SetEndSize( 250 ) + particle:SetAirResistance( 0 ) + particle:SetCollide( true ) + particle:SetBounce( 0 ) + particle:SetColor( Color( 100, 250, 50 ) ) + particle:SetCollideCallback( CloudCollision ) + + if i < 3 then + + local particle = RainEmitter:Add( "effects/rain_cloud", vec ) + particle:SetVelocity( Vector( 0, 0, math.random( -1000, -800 ) ) + WindVector * math.Rand( 0, 2.0 ) ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( 10 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.random( 1, 3 ) ) + particle:SetEndSize( 0 ) + particle:SetRoll( math.random( -180, 180 ) ) + particle:SetColor( 100, 200, 0 ) + particle:SetGravity( Vector( 0, 0, -300 ) + WindVector * ( math.sin( CurTime() * 0.01 ) * 20 ) ) + particle:SetCollide( true ) + particle:SetCollideCallback( RadCollision ) + particle:SetBounce( math.Rand( 0, 0.1 ) ) + + end + + end + + end + + if amt == 0 then return end + + for i=1, amt do + + local vec = Vector( math.random( GAMEMODE.LeftSkyBound.x, GAMEMODE.RightSkyBound.x ), math.random( GAMEMODE.LeftSkyBound.y, GAMEMODE.RightSkyBound.y ), pos.z ) + local len = math.random( 40, 80 ) + + local particle = RainEmitter:Add( "particle/Water/WaterDrop_001a", vec ) + particle:SetVelocity( Vector( 0, 0, math.random( -1000, -800 ) ) ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( 10 ) + particle:SetStartAlpha( math.random( 5, 20 ) ) + particle:SetEndAlpha( 20 ) + particle:SetStartSize( 2.0 ) + particle:SetEndSize( math.Rand( 3.0, 4.0 + GAMEMODE.Weather.Rain ) ) + particle:SetStartLength( len ) + particle:SetEndLength( len + 5 ) + particle:SetAirResistance( 0 ) + particle:SetCollide( true ) + particle:SetBounce( 0 ) + //particle:SetColor( Color( 200, 200, 250 ) ) + particle:SetCollideCallback( RainCollision ) + + end + + amt = math.floor( amt * 0.05 ) + 1 + + for i=1, amt do + + local vec = Vector( math.random( GAMEMODE.LeftSkyBound.x, GAMEMODE.RightSkyBound.x ), math.random( GAMEMODE.LeftSkyBound.y, GAMEMODE.RightSkyBound.y ), pos.z ) + + local particle = RainEmitter:Add( "effects/rain_cloud", vec ) + particle:SetVelocity( Vector( 0, 0, math.random( -1000, -800 ) ) + WindVector * math.Rand( 0, 2.0 ) ) + particle:SetLifeTime( 0 ) + particle:SetDieTime( 10 ) + particle:SetStartAlpha( 3 + math.Rand( 0, GAMEMODE.Weather.Rain * 5 ) ) + particle:SetEndAlpha( 5 ) + particle:SetStartSize( math.random( 100, 200 ) ) + particle:SetEndSize( 200 ) + particle:SetAirResistance( 0 ) + particle:SetCollide( true ) + particle:SetBounce( 0 ) + particle:SetColor( Color( 200, 200, 250 ) ) + particle:SetCollideCallback( CloudCollision ) + + end + +end + +function GM:LightningThink() + + if GAMEMODE.Weather.Lightning == 0 then + + if GAMEMODE.NextLightning and GAMEMODE.NextLightning > CurTime() then + + GAMEMODE:LightUpSky( false ) + GAMEMODE.NextLightning = 0 + + end + + return + + end + + local skyname = GetGlobalString( "SkyName" ) + + if skyname and not GAMEMODE.SkyMat then + + GAMEMODE.SkyMat = {} + GAMEMODE.SkyMat[1] = Material("skybox/" .. skyname .. "up") + GAMEMODE.SkyMat[2] = Material("skybox/" .. skyname .. "dn") + GAMEMODE.SkyMat[3] = Material("skybox/" .. skyname .. "lf") + GAMEMODE.SkyMat[4] = Material("skybox/" .. skyname .. "rt") + GAMEMODE.SkyMat[5] = Material("skybox/" .. skyname .. "bk") + GAMEMODE.SkyMat[6] = Material("skybox/" .. skyname .. "ft") + + GAMEMODE.OldSky = {} + GAMEMODE.LitUp = {} + + skyname = "sky_day01_01" + + GAMEMODE.NewSky = {} + GAMEMODE.NewSky[1] = Material("skybox/" .. skyname .. "up") + GAMEMODE.NewSky[2] = Material("skybox/" .. skyname .. "dn") + GAMEMODE.NewSky[3] = Material("skybox/" .. skyname .. "lf") + GAMEMODE.NewSky[4] = Material("skybox/" .. skyname .. "rt") + GAMEMODE.NewSky[5] = Material("skybox/" .. skyname .. "bk") + GAMEMODE.NewSky[6] = Material("skybox/" .. skyname .. "ft") + + end + + if ( GAMEMODE.NextLightning or 0 ) < CurTime() then + + if not GAMEMODE.FlashInterval then + + GAMEMODE.FlashInterval = CurTime() + math.Rand( 1.0, 2.5 ) + GAMEMODE.FlashTime = CurTime() + math.Rand( 0, 0.2 ) + GAMEMODE.FlashToggle = CurTime() + math.Rand( 0, 0.8 ) + + sound.Play( table.Random( GAMEMODE.Thunder ), LocalPlayer():GetShootPos(), 150, math.random( 80, 110 ), 0.2 ) + + end + + GAMEMODE:LightUpSky( GAMEMODE.FlashTime >= CurTime() ) + + if GAMEMODE.FlashToggle < CurTime() then + + GAMEMODE.FlashTime = CurTime() + math.Rand( 0, 0.2 ) + GAMEMODE.FlashToggle = CurTime() + math.Rand( 0, 0.8 ) + + end + + if GAMEMODE.FlashInterval < CurTime() then + + GAMEMODE.FlashInterval = nil + GAMEMODE.NextLightning = CurTime() + math.random( 4, 8 + ( 1.0 - GAMEMODE.Weather.Lightning ) * 50 ) + GAMEMODE:LightUpSky( false ) + + end + + end + +end + +function GM:LightUpSky( bool ) + + if bool then + + for k,v in pairs( GAMEMODE.SkyMat ) do + + if not GAMEMODE.LitUp[k] then + + GAMEMODE.OldSky[k] = v:GetTexture( "$basetexture" ) + GAMEMODE.LitUp[k] = true + + v:SetTexture( "$basetexture", GAMEMODE.NewSky[k]:GetTexture( "$basetexture" ) ) + + end + + end + + else + + for k,v in pairs( GAMEMODE.SkyMat ) do + + if GAMEMODE.LitUp and GAMEMODE.LitUp[k] then + + GAMEMODE.LitUp[k] = false + + v:SetTexture( "$basetexture", GAMEMODE.OldSky[k] ) + + end + + end + + end + +end + +function GM:WindThink() + + if GAMEMODE.Weather.Wind == 0 then return end + + if ( GAMEMODE.NextWind or 0 ) < CurTime() then + + local vol = math.max( GAMEMODE.Weather.Wind, 0.2 ) + local snd = table.Random( GAMEMODE.Wind ) + + if GAMEMODE.PlayerIsIndoors then + + vol = 0.1 + + end + + sound.Play( snd, LocalPlayer():GetShootPos(), 150, math.random( 80, 110 ), vol ) + + GAMEMODE.NextWind = CurTime() + math.random( 1, SoundDuration( snd ) + ( 1.0 - GAMEMODE.Weather.Wind ) * 30 + math.Rand( -2, 2 ) ) + + end + +end + +function GM:ThunderThink() + + if GAMEMODE.Weather.Thunder == 0 then return end + + if ( GAMEMODE.NextThunder or 0 ) < CurTime() then + + GAMEMODE.NextThunder = CurTime() + math.random( 4, 8 + ( 1.0 - GAMEMODE.Weather.Thunder ) * 50 ) + + local vol = math.max( GAMEMODE.Weather.Thunder, 0.2 ) + + if GAMEMODE.PlayerIsIndoors then + + vol = 0.1 + + end + + sound.Play( table.Random( GAMEMODE.Thunder ), LocalPlayer():GetShootPos(), 150, math.random( 80, 110 ), vol ) + + end + +end
\ No newline at end of file diff --git a/icon24.png b/icon24.png Binary files differnew file mode 100644 index 0000000..31d98a7 --- /dev/null +++ b/icon24.png diff --git a/logo.png b/logo.png Binary files differnew file mode 100644 index 0000000..404af2f --- /dev/null +++ b/logo.png diff --git a/redead.txt b/redead.txt new file mode 100644 index 0000000..72d08d0 --- /dev/null +++ b/redead.txt @@ -0,0 +1,91 @@ +"gamemode" +{ + "base" "base" + "title" "ReDead" + "workshopid" "147208196" + "maps" "^rd_" + "menusystem" "1" + "settings" + { + 1 + { + "name" "sv_redead_max_zombies" + "text" "Max NPCs:" + "help" "The maximum number of zombie NPCs." + "type" "Numeric" + "default" "45" + } + 2 + { + "name" "sv_redead_zombies_per_player" + "text" "Zombies per player:" + "help" "Number of NPCs to spawn per player." + "type" "Numeric" + "default" "3" + } + 3 + { + "name" "sv_redead_zombies_per_player_zombie" + "text" "Zombies per player:" + "help" "Number of NPCs to spawn per player zombie." + "type" "Numeric" + "default" "2" + } + 4 + { + "name" "sv_redead_wave_length" + "text" "Wave time:" + "help" "Length of each wave in minutes." + "type" "Numeric" + "default" "4" + } + 5 + { + "name" "sv_redead_wave_time" + "text" "Wave delay:" + "help" "Delay between each wave in seconds." + "type" "Numeric" + "default" "25" + } + 6 + { + "name" "sv_redead_team_dmg" + "text" "Team damage:" + "help" "Friendly fire." + "type" "CheckBox" + "default" "0" + } + 7 + { + "name" "sv_redead_dmg_scale" + "text" "Damage scale:" + "help" "Bullet damage scale." + "type" "Numeric" + "default" "1.0" + } + 8 + { + "name" "sv_redead_setup_time" + "text" "Setup Time:" + "help" "Time before first wave." + "type" "Numeric" + "default" "60" + } + 9 + { + "name" "sv_redead_minimum_players" + "text" "Minimum players:" + "help" "Number of players needed for a zombie lord to be chosen." + "type" "Numeric" + "default" "6" + } + 10 + { + "name" "sv_redead_post_game_time" + "text" "Minimum players:" + "help" "Amount of time before next map loads." + "type" "Numeric" + "default" "45" + } + } +}
\ No newline at end of file |
