Залив

This commit is contained in:
Refosel
2026-04-14 20:55:58 +03:00
commit e71aa57168
126 changed files with 24034 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 MiB

View File

@@ -0,0 +1,39 @@
--[[---------------------------------------------------------
Returns the right shoot start position for a tracer - based on 'data'.
-----------------------------------------------------------]]
function EFFECT:GetTracerShootPos( Position, Ent, Attachment )
self.ViewModelTracer = false
if ( !IsValid( Ent ) ) then return Position end
if ( !Ent:IsWeapon() ) then return Position end
-- Shoot from the viewmodel
if ( Ent:IsCarriedByLocalPlayer() && !LocalPlayer():ShouldDrawLocalPlayer() ) then
local ViewModel = LocalPlayer():GetViewModel()
if ( ViewModel:IsValid() ) then
local att = ViewModel:GetAttachment( Attachment )
if ( att ) then
Position = att.Pos
self.ViewModelTracer = true
end
end
-- Shoot from the world model
else
local att = Ent:GetAttachment( Attachment )
if ( att ) then
Position = att.Pos
end
end
return Position
end

View File

@@ -0,0 +1,55 @@
EFFECT.Mat = Material( "pp/dof" )
function EFFECT:Init( data )
table.insert( DOF_Ents, self.Entity )
self.Scale = data:GetScale()
local size = 32
self:SetCollisionBounds( Vector( -size, -size, -size ), Vector( size, size, size ) )
end
function EFFECT:Think( )
-- If the spacing or offset has changed we need to reconfigure our positions
local ply = LocalPlayer()
self.spacing = DOF_SPACING * self.Scale
self.offset = DOF_OFFSET
-- Just return if it hasn't
--if ( spacing == self.spacing && offset == self.offset ) then return true end
local pos = ply:EyePos()
local fwd = ply:EyeAngles():Forward()
if ( ply:GetViewEntity() != ply ) then
pos = ply:GetViewEntity():GetPos()
fwd = ply:GetViewEntity():GetForward()
end
pos = pos + ( fwd * self.spacing ) + ( fwd * self.offset )
self:SetParent( nil )
self:SetPos( pos )
self:SetParent( ply )
-- We don't kill this, the pp effect should
return true
end
function EFFECT:Render()
-- Note: UpdateScreenEffectTexture fucks up the water, RefractTexture is lower quality
render.UpdateRefractTexture()
//render.UpdateScreenEffectTexture()
local SpriteSize = ( self.spacing + self.offset ) * 8
render.SetMaterial( self.Mat )
render.DrawSprite( self:GetPos(), SpriteSize, SpriteSize, color_white )
end

View File

@@ -0,0 +1,58 @@
EFFECT.Mat = Material( "effects/tool_tracer" )
function EFFECT:Init( data )
self.Position = data:GetStart()
self.WeaponEnt = data:GetEntity()
self.Attachment = data:GetAttachment()
-- Keep the start and end pos - we're going to interpolate between them
self.StartPos = self:GetTracerShootPos( self.Position, self.WeaponEnt, self.Attachment )
self.EndPos = data:GetOrigin()
self.Alpha = 255
self.Life = 0
self:SetRenderBoundsWS( self.StartPos, self.EndPos )
end
function EFFECT:Think()
self.Life = self.Life + FrameTime() * 4
self.Alpha = 255 * ( 1 - self.Life )
return ( self.Life < 1 )
end
function EFFECT:Render()
if ( self.Alpha < 1 ) then return end
render.SetMaterial( self.Mat )
local texcoord = math.Rand( 0, 1 )
local norm = (self.StartPos - self.EndPos) * self.Life
self.Length = norm:Length()
for i = 1, 3 do
render.DrawBeam( self.StartPos - norm, -- Start
self.EndPos, -- End
8, -- Width
texcoord, -- Start tex coord
texcoord + self.Length / 128, -- End tex coord
color_white ) -- Color (optional)
end
render.DrawBeam( self.StartPos,
self.EndPos,
8,
texcoord,
texcoord + ( ( self.StartPos - self.EndPos ):Length() / 128 ),
Color( 255, 255, 255, 128 * ( 1 - self.Life ) ) )
end

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,25 @@
include( "shared.lua" )
ENT.RenderGroup = RENDERGROUP_OPAQUE
--[[---------------------------------------------------------
Name: Draw
Desc: Draw it!
-----------------------------------------------------------]]
function ENT:Draw()
self:DrawModel()
end
--[[---------------------------------------------------------
Name: DrawTranslucent
Desc: Draw translucent
-----------------------------------------------------------]]
function ENT:DrawTranslucent()
-- This is here just to make it backwards compatible.
-- You shouldn't really be drawing your model here unless it's translucent
self:Draw()
end

View File

@@ -0,0 +1,131 @@
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include( "shared.lua" )
include( "schedules.lua" )
include( "tasks.lua" )
-- Variables
ENT.m_fMaxYawSpeed = 200 -- Max turning speed
ENT.m_iClass = CLASS_CITIZEN_REBEL -- NPC Class
AccessorFunc( ENT, "m_iClass", "NPCClass" )
AccessorFunc( ENT, "m_fMaxYawSpeed", "MaxYawSpeed" )
function ENT:Initialize()
-- Some default calls to make the NPC function
self:SetModel( "models/alyx.mdl" )
self:SetHullType( HULL_HUMAN )
self:SetHullSizeNormal()
self:SetSolid( SOLID_BBOX )
self:SetMoveType( MOVETYPE_STEP )
self:CapabilitiesAdd( bit.bor( CAP_MOVE_GROUND, CAP_OPEN_DOORS, CAP_ANIMATEDFACE, CAP_SQUAD, CAP_USE_WEAPONS, CAP_DUCK, CAP_MOVE_SHOOT, CAP_TURN_HEAD, CAP_USE_SHOT_REGULATOR, CAP_AIM_GUN ) )
self:SetHealth( 100 )
end
--[[---------------------------------------------------------
Name: OnTakeDamage
Desc: Called when the NPC takes damage
-----------------------------------------------------------]]
function ENT:OnTakeDamage( dmginfo )
--[[
Msg( tostring(dmginfo) .. "\n" )
Msg( "Inflictor:\t" .. tostring(dmginfo:GetInflictor()) .. "\n" )
Msg( "Attacker:\t" .. tostring(dmginfo:GetAttacker()) .. "\n" )
Msg( "Damage:\t" .. tostring(dmginfo:GetDamage()) .. "\n" )
Msg( "Base Damage:\t" .. tostring(dmginfo:GetBaseDamage()) .. "\n" )
Msg( "Force:\t" .. tostring(dmginfo:GetDamageForce()) .. "\n" )
Msg( "Position:\t" .. tostring(dmginfo:GetDamagePosition()) .. "\n" )
Msg( "Reported Pos:\t" .. tostring(dmginfo:GetReportedPosition()) .. "\n" ) -- ??
--]]
-- return 1
end
--[[---------------------------------------------------------
Name: Use
-----------------------------------------------------------]]
function ENT:Use( activator, caller, type, value )
end
--[[---------------------------------------------------------
Name: StartTouch
-----------------------------------------------------------]]
function ENT:StartTouch( entity )
end
--[[---------------------------------------------------------
Name: EndTouch
-----------------------------------------------------------]]
function ENT:EndTouch( entity )
end
--[[---------------------------------------------------------
Name: Touch
-----------------------------------------------------------]]
function ENT:Touch( entity )
end
--[[---------------------------------------------------------
Name: GetRelationship
Return the relationship between this NPC and the
passed entity. If you don't return anything then
the default disposition will be used.
-----------------------------------------------------------]]
function ENT:GetRelationship( entity )
--return D_NU;
end
--[[---------------------------------------------------------
Name: ExpressionFinished
Called when an expression has finished. Duh.
-----------------------------------------------------------]]
function ENT:ExpressionFinished( strExp )
end
--[[---------------------------------------------------------
Name: OnChangeActivity
-----------------------------------------------------------]]
function ENT:OnChangeActivity( act )
end
--[[---------------------------------------------------------
Name: Think
-----------------------------------------------------------]]
function ENT:Think()
end
-- Called when NPC's movement fails
function ENT:OnMovementFailed()
end
-- Called when NPC's movement succeeds
function ENT:OnMovementComplete()
end
-- Called when the NPC's active weapon changes
function ENT:OnActiveWeaponChanged( old, new )
end
--[[---------------------------------------------------------
Name: GetAttackSpread
How good is the NPC with this weapon? Return the number
of degrees of inaccuracy for the NPC to use.
-----------------------------------------------------------]]
function ENT:GetAttackSpread( Weapon, Target )
return 0.1
end

View File

@@ -0,0 +1,199 @@
--[[---------------------------------------------------------
Name: RunAI - Called from the engine every 0.1 seconds
-----------------------------------------------------------]]
function ENT:RunAI( strExp )
-- If we're running an Engine Side behaviour
-- then return true and let it get on with it.
if ( self:IsRunningBehavior() ) then
return true
end
-- If we're doing an engine schedule then return true
-- This makes it do the normal AI stuff.
if ( self:DoingEngineSchedule() ) then
return true
end
-- If we're currently running a schedule then run it.
if ( self.CurrentSchedule ) then
self:DoSchedule( self.CurrentSchedule )
end
-- If we have no schedule (schedule is finished etc)
-- Then get the derived NPC to select what we should be doing
if ( !self.CurrentSchedule ) then
self:SelectSchedule()
end
-- Do animation system
self:MaintainActivity()
end
--[[---------------------------------------------------------
Name: SelectSchedule - Set the schedule we should be
playing right now.
-----------------------------------------------------------]]
function ENT:SelectSchedule( iNPCState )
self:SetSchedule( SCHED_IDLE_WANDER )
end
--[[---------------------------------------------------------
Name: StartSchedule - Start a Lua schedule. Not to be
confused with SetSchedule which starts an Engine based
schedule.
-----------------------------------------------------------]]
function ENT:StartSchedule( schedule )
self.CurrentSchedule = schedule
self.CurrentTaskID = 1
self:SetTask( schedule:GetTask( 1 ) )
end
--[[---------------------------------------------------------
Name: DoSchedule - Runs a Lua schedule.
-----------------------------------------------------------]]
function ENT:DoSchedule( schedule )
if ( self.CurrentTask ) then
self:RunTask( self.CurrentTask )
end
if ( self:TaskFinished() ) then
self:NextTask( schedule )
end
end
--[[---------------------------------------------------------
Name: ScheduleFinished
-----------------------------------------------------------]]
function ENT:ScheduleFinished()
self.CurrentSchedule = nil
self.CurrentTask = nil
self.CurrentTaskID = nil
end
--[[---------------------------------------------------------
Name: DoSchedule - Set the current task.
-----------------------------------------------------------]]
function ENT:SetTask( task )
self.CurrentTask = task
self.bTaskComplete = false
self.TaskStartTime = CurTime()
self:StartTask( self.CurrentTask )
end
--[[---------------------------------------------------------
Name: NextTask - Start the next task in specific schedule.
-----------------------------------------------------------]]
function ENT:NextTask( schedule )
-- Increment task id
self.CurrentTaskID = self.CurrentTaskID + 1
-- If this was the last task then finish up.
if ( self.CurrentTaskID > schedule:NumTasks() ) then
self:ScheduleFinished( schedule )
return
end
-- Switch to next task
self:SetTask( schedule:GetTask( self.CurrentTaskID ) )
end
--[[---------------------------------------------------------
Name: StartTask - called once on starting task
-----------------------------------------------------------]]
function ENT:StartTask( task )
task:Start( self.Entity )
end
--[[---------------------------------------------------------
Name: RunTask - called every think on running task.
The actual task function should tell us when
the task is finished.
-----------------------------------------------------------]]
function ENT:RunTask( task )
task:Run( self.Entity )
end
--[[---------------------------------------------------------
Name: TaskTime - Returns how many seconds we've been
doing this current task
-----------------------------------------------------------]]
function ENT:TaskTime()
return CurTime() - self.TaskStartTime
end
--[[---------------------------------------------------------
Name: OnTaskComplete - Called from the engine when
TaskComplete is called. This allows us to move
onto the next task - even when TaskComplete was
called from an engine side task.
-----------------------------------------------------------]]
function ENT:OnTaskComplete()
self.bTaskComplete = true
end
--[[---------------------------------------------------------
Name: TaskFinished - Returns true if the current
running Task is finished.
-----------------------------------------------------------]]
function ENT:TaskFinished()
return self.bTaskComplete
end
--[[---------------------------------------------------------
Name: StartTask
Start the task. You can use this to override engine
side tasks. Return true to not run default stuff.
-----------------------------------------------------------]]
function ENT:StartEngineTask( iTaskID, TaskData )
end
--[[---------------------------------------------------------
Name: RunTask
Run the task. You can use this to override engine
side tasks. Return true to not run default stuff.
-----------------------------------------------------------]]
function ENT:RunEngineTask( iTaskID, TaskData )
end
--[[---------------------------------------------------------
These functions handle the engine schedules
When an engine schedule is set the engine calls StartEngineSchedule
Then when it's finished it calls EngineScheduleFinishHelp me decide
-----------------------------------------------------------]]
function ENT:StartEngineSchedule( scheduleID ) self:ScheduleFinished() self.bDoingEngineSchedule = true end
function ENT:EngineScheduleFinish() self.bDoingEngineSchedule = nil end
function ENT:DoingEngineSchedule() return self.bDoingEngineSchedule end
function ENT:OnCondition( iCondition )
--Msg( self, " Condition: ", iCondition, " - ", self:ConditionName(iCondition), "\n" )
end

View File

@@ -0,0 +1,44 @@
ENT.Base = "base_entity"
ENT.Type = "ai"
ENT.PrintName = "Base SNPC"
ENT.Author = ""
ENT.Contact = ""
ENT.Purpose = ""
ENT.Instructions = ""
ENT.AutomaticFrameAdvance = false
--[[---------------------------------------------------------
Name: OnRemove
Desc: Called just before entity is deleted
-----------------------------------------------------------]]
function ENT:OnRemove()
end
--[[---------------------------------------------------------
Name: PhysicsCollide
Desc: Called when physics collides. The table contains
data on the collision
-----------------------------------------------------------]]
function ENT:PhysicsCollide( data, physobj )
end
--[[---------------------------------------------------------
Name: PhysicsUpdate
Desc: Called to update the physics .. or something.
-----------------------------------------------------------]]
function ENT:PhysicsUpdate( physobj )
end
--[[---------------------------------------------------------
Name: SetAutomaticFrameAdvance
Desc: If you're not using animation you should turn this
off - it will save lots of bandwidth.
-----------------------------------------------------------]]
function ENT:SetAutomaticFrameAdvance( bUsingAnim )
self.AutomaticFrameAdvance = bUsingAnim
end

View File

@@ -0,0 +1,81 @@
--[[---------------------------------------------------------
Task: PlaySequence
Accepts:
data.ID - sequence id
data.Name - sequence name (Must provide either id or name)
data.Wait - Optional. Should we wait for sequence to finish
data.Speed - Optional. Playback speed of sequence
data.Loop - Optional. Should the sequence be looped
-----------------------------------------------------------]]
function ENT:TaskStart_PlaySequence( data )
local SequenceID = data.ID
if ( data.Name ) then SequenceID = self:LookupSequence( data.Name ) end
self:ResetSequence( SequenceID )
self:SetNPCState( NPC_STATE_SCRIPT )
local Duration = self:SequenceDuration()
if ( data.Speed && data.Speed > 0 ) then
SequenceID = self:SetPlaybackRate( data.Speed )
Duration = Duration / data.Speed
end
self.TaskSequenceEnd = CurTime() + Duration
self.Loop = data.Loop or false
end
function ENT:Task_PlaySequence( data )
-- Wait until sequence is finished
if ( CurTime() < self.TaskSequenceEnd or self.Loop ) then return end
self:TaskComplete()
self:SetNPCState( NPC_STATE_NONE )
-- Clean up
self.TaskSequenceEnd = nil
end
--[[---------------------------------------------------------
Task: FindEnemy
Accepts:
data.ID - sequence id
data.Name - sequence name (Must provide either id or name)
data.Wait - Optional. Should we wait for sequence to finish
data.Speed - Optional. Playback speed of sequence
-----------------------------------------------------------]]
function ENT:TaskStart_FindEnemy( data )
local et = ents.FindInSphere( self:GetPos(), data.Radius or 512 )
for k, v in ipairs( et ) do
if ( v:IsValid() && v != self && v:GetClass() == data.Class ) then
self:SetEnemy( v, true )
self:UpdateEnemyMemory( v, v:GetPos() )
self:TaskComplete()
return
end
end
self:SetEnemy( NULL )
end
function ENT:Task_FindEnemy( data )
end

View File

@@ -0,0 +1,104 @@
AddCSLuaFile()
ENT.Base = "base_entity"
ENT.Type = "anim"
ENT.PrintName = ""
ENT.Author = ""
ENT.Contact = ""
ENT.Purpose = ""
ENT.Instructions = ""
-- Defaulting this to OFF. This will automatically save bandwidth
-- on stuff that is already out there, but might break a few things
-- that are out there. I'm choosing to break those things because
-- there are a lot less of them that are actually using the animtime
ENT.AutomaticFrameAdvance = false
function ENT:SetAutomaticFrameAdvance( bUsingAnim )
self.AutomaticFrameAdvance = bUsingAnim
end
function ENT:OnRemove()
end
function ENT:PhysicsCollide( data, physobj )
end
function ENT:PhysicsUpdate( physobj )
end
if ( CLIENT ) then
function ENT:Draw( flags )
self:DrawModel( flags )
end
function ENT:DrawTranslucent( flags )
-- This is here just to make it backwards compatible.
-- You shouldn't really be drawing your model here unless it's translucent
self:Draw( flags )
end
end
if ( SERVER ) then
function ENT:OnTakeDamage( dmginfo )
--[[
Msg( tostring(dmginfo) .. "\n" )
Msg( "Inflictor:\t" .. tostring(dmginfo:GetInflictor()) .. "\n" )
Msg( "Attacker:\t" .. tostring(dmginfo:GetAttacker()) .. "\n" )
Msg( "Damage:\t" .. tostring(dmginfo:GetDamage()) .. "\n" )
Msg( "Base Damage:\t" .. tostring(dmginfo:GetBaseDamage()) .. "\n" )
Msg( "Force:\t" .. tostring(dmginfo:GetDamageForce()) .. "\n" )
Msg( "Position:\t" .. tostring(dmginfo:GetDamagePosition()) .. "\n" )
Msg( "Reported Pos:\t" .. tostring(dmginfo:GetReportedPosition()) .. "\n" ) -- ??
--]]
end
function ENT:Use( activator, caller, type, value )
end
function ENT:StartTouch( entity )
end
function ENT:EndTouch( entity )
end
function ENT:Touch( entity )
end
--[[---------------------------------------------------------
Name: Simulate
Desc: Controls/simulates the physics on the entity.
Officially the most complicated callback in the whole mod.
Returns 3 variables..
1. A SIM_ enum
2. A vector representing the linear acceleration/force
3. A vector represending the angular acceleration/force
If you're doing nothing you can return SIM_NOTHING
Note that you need to call ent:StartMotionController to tell the entity
to start calling this function..
-----------------------------------------------------------]]
function ENT:PhysicsSimulate( phys, deltatime )
return SIM_NOTHING
end
end

View File

@@ -0,0 +1,56 @@
ENT.Base = "base_entity"
ENT.Type = "brush"
--[[---------------------------------------------------------
Name: Initialize
-----------------------------------------------------------]]
function ENT:Initialize()
end
--[[---------------------------------------------------------
Name: StartTouch
-----------------------------------------------------------]]
function ENT:StartTouch( entity )
end
--[[---------------------------------------------------------
Name: EndTouch
-----------------------------------------------------------]]
function ENT:EndTouch( entity )
end
--[[---------------------------------------------------------
Name: Touch
-----------------------------------------------------------]]
function ENT:Touch( entity )
end
--[[---------------------------------------------------------
Name: PassesTriggerFilters
Desc: Return true if this object should trigger us
-----------------------------------------------------------]]
function ENT:PassesTriggerFilters( entity )
return true
end
--[[---------------------------------------------------------
Name: KeyValue
Desc: Called when a keyvalue is added to us
-----------------------------------------------------------]]
function ENT:KeyValue( key, value )
end
--[[---------------------------------------------------------
Name: Think
Desc: Entity's think function.
-----------------------------------------------------------]]
function ENT:Think()
end
--[[---------------------------------------------------------
Name: OnRemove
Desc: Called just before entity is deleted
-----------------------------------------------------------]]
function ENT:OnRemove()
end

View File

@@ -0,0 +1,24 @@
include( "shared.lua" )
--[[---------------------------------------------------------
Name: Initialize
Desc: First function called. Use to set up your entity
-----------------------------------------------------------]]
function ENT:Initialize()
end
--[[---------------------------------------------------------
Name: Think
Desc: Client Think - called every frame
-----------------------------------------------------------]]
function ENT:Think()
end
--[[---------------------------------------------------------
Name: OnRestore
Desc: Called immediately after a "load"
-----------------------------------------------------------]]
function ENT:OnRestore()
end

View File

@@ -0,0 +1,77 @@
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include( "shared.lua" )
include( "outputs.lua" )
--[[---------------------------------------------------------
Name: Initialize
Desc: First function called. Use to set up your entity
-----------------------------------------------------------]]
function ENT:Initialize()
end
--[[---------------------------------------------------------
Name: KeyValue
Desc: Called when a keyvalue is added to us
-----------------------------------------------------------]]
function ENT:KeyValue( key, value )
end
--[[---------------------------------------------------------
Name: OnRestore
Desc: The game has just been reloaded. This is usually the right place
to call the GetNW* functions to restore the script's values.
-----------------------------------------------------------]]
function ENT:OnRestore()
end
--[[---------------------------------------------------------
Name: AcceptInput
Desc: Accepts input, return true to override/accept input
-----------------------------------------------------------]]
function ENT:AcceptInput( name, activator, caller, data )
return false
end
--[[---------------------------------------------------------
Name: UpdateTransmitState
Desc: Set the transmit state
-----------------------------------------------------------]]
function ENT:UpdateTransmitState()
return TRANSMIT_PVS
end
--[[---------------------------------------------------------
Name: Think
Desc: Entity's think function.
-----------------------------------------------------------]]
function ENT:Think()
end
--
-- Default generic spawn function
-- So you don't have to add one your entitie unless you want to.
--
function ENT:SpawnFunction( ply, tr, ClassName )
if ( !tr.Hit ) then return end
local SpawnPos = tr.HitPos + tr.HitNormal * 10
local SpawnAng = ply:EyeAngles()
SpawnAng.p = 0
SpawnAng.y = SpawnAng.y + 180
local ent = ents.Create( ClassName )
ent:SetCreator( ply )
ent:SetPos( SpawnPos )
ent:SetAngles( SpawnAng )
ent:Spawn()
ent:Activate()
ent:DropToFloor()
return ent
end

View File

@@ -0,0 +1,80 @@
-- This is called from ENT:KeyValue(key,value) to store the output from
-- the map, it could also be called from ENT:AcceptInput I think, so if
-- ent_fire addoutput is used, we can store that too (that hasn't been
-- tested though).
-- Usage: self:StoreOutput("<name of output>","<entities to fire>,<input name>,<param>,<delay>,<times to be used>")
-- If called from ENT:KeyValue, then the first parameter is the key, and
-- the second is value.
function ENT:StoreOutput( name, info )
-- Newer Source Engine games use this symbol as a delimiter
local rawData = string.Explode( "\x1B", info )
if ( #rawData < 2 ) then
rawData = string.Explode( ",", info )
end
local Output = {}
Output.entities = rawData[1] or ""
Output.input = rawData[2] or ""
Output.param = rawData[3] or ""
Output.delay = tonumber( rawData[4] ) or 0
Output.times = tonumber( rawData[5] ) or -1
self.m_tOutputs = self.m_tOutputs or {}
self.m_tOutputs[ name ] = self.m_tOutputs[ name ] or {}
table.insert( self.m_tOutputs[ name ], Output )
end
-- Nice helper function, this does all the work. Returns false if the
-- output should be removed from the list.
local function FireSingleOutput( output, this, activator, data )
if ( output.times == 0 ) then return false end
local entitiesToFire = {}
if ( output.entities == "!activator" ) then
entitiesToFire = { activator }
elseif ( output.entities == "!self" ) then
entitiesToFire = { this }
elseif ( output.entities == "!player" ) then
entitiesToFire = player.GetAll()
else
entitiesToFire = ents.FindByName( output.entities )
end
for _, ent in pairs( entitiesToFire ) do
ent:Fire( output.input, data or output.param, output.delay, activator, this )
end
if ( output.times ~= -1 ) then
output.times = output.times - 1
end
return ( output.times > 0 ) || ( output.times == -1 )
end
-- This function is used to trigger an output.
function ENT:TriggerOutput( name, activator, data )
if ( !self.m_tOutputs ) then return end
if ( !self.m_tOutputs[ name ] ) then return end
local OutputList = self.m_tOutputs[ name ]
for idx = #OutputList, 1, -1 do
if ( OutputList[ idx ] and !FireSingleOutput( OutputList[ idx ], self.Entity, activator, data ) ) then
-- Shift the indexes so this loop doesn't fail later
table.remove( self.m_tOutputs[ name ], idx )
end
end
end

View File

@@ -0,0 +1,6 @@
ENT.Base = "base_entity"
ENT.Type = "anim"
ENT.Spawnable = false
ENT.AdminOnly = false

View File

@@ -0,0 +1,44 @@
ENT.Base = "base_entity"
ENT.Type = "filter"
--[[---------------------------------------------------------
Name: Initialize
-----------------------------------------------------------]]
function ENT:Initialize()
end
--[[---------------------------------------------------------
Name: KeyValue
Desc: Called when a keyvalue is added to us
-----------------------------------------------------------]]
function ENT:KeyValue( key, value )
end
--[[---------------------------------------------------------
Name: Think
Desc: Entity's think function.
-----------------------------------------------------------]]
function ENT:Think()
end
--[[---------------------------------------------------------
Name: OnRemove
Desc: Called just before entity is deleted
-----------------------------------------------------------]]
function ENT:OnRemove()
end
--[[---------------------------------------------------------
Name: PassesFilter
-----------------------------------------------------------]]
function ENT:PassesFilter( trigger, ent )
return true
end
--[[---------------------------------------------------------
Name: PassesDamageFilter
-----------------------------------------------------------]]
function ENT:PassesDamageFilter( dmg )
return true
end

View File

@@ -0,0 +1,140 @@
AddCSLuaFile()
DEFINE_BASECLASS( "base_anim" )
ENT.Spawnable = false
if ( CLIENT ) then
ENT.MaxWorldTipDistance = 256
function ENT:BeingLookedAtByLocalPlayer()
local ply = LocalPlayer()
if ( !IsValid( ply ) ) then return false end
local view = ply:GetViewEntity()
local dist = self.MaxWorldTipDistance
dist = dist * dist
-- If we're spectating a player, perform an eye trace
if ( view:IsPlayer() ) then
return view:EyePos():DistToSqr( self:GetPos() ) <= dist && view:GetEyeTrace().Entity == self
end
-- If we're not spectating a player, perform a manual trace from the entity's position
local pos = view:GetPos()
if ( pos:DistToSqr( self:GetPos() ) <= dist ) then
return util.TraceLine( {
start = pos,
endpos = pos + ( view:GetAngles():Forward() * dist ),
filter = view
} ).Entity == self
end
return false
end
function ENT:Think()
local text = self:GetOverlayText()
if ( text != "" && self:BeingLookedAtByLocalPlayer() && !self:GetNoDraw() ) then
AddWorldTip( self:EntIndex(), text, 0.5, self:GetPos(), self )
halo.Add( { self }, color_white, 1, 1, 1, true, true )
end
end
end
function ENT:SetOverlayText( text )
self:SetNWString( "GModOverlayText", text )
end
function ENT:GetOverlayText()
local txt = self:GetNWString( "GModOverlayText" )
if ( txt == "" ) then
return ""
end
if ( game.SinglePlayer() ) then
return txt
end
local PlayerName = self:GetPlayerName()
return txt .. "\n(" .. PlayerName .. ")"
end
function ENT:SetPlayer( ply )
self.Founder = ply
if ( IsValid( ply ) ) then
self:SetNWString( "FounderName", ply:Nick() )
self.FounderSID = ply:SteamID64()
self.FounderIndex = ply:UniqueID()
else
self:SetNWString( "FounderName", "" )
self.FounderSID = nil
self.FounderIndex = nil
end
end
function ENT:GetPlayer()
if ( self.Founder == nil ) then
-- SetPlayer has not been called
return NULL
elseif ( IsValid( self.Founder ) ) then
-- Normal operations
return self.Founder
end
-- See if the player has left the server then rejoined
local ply = player.GetBySteamID64( self.FounderSID )
if ( not IsValid( ply ) ) then
-- Oh well
return NULL
end
-- Save us the check next time
self:SetPlayer( ply )
return ply
end
function ENT:GetPlayerIndex()
return self.FounderIndex or 0
end
function ENT:GetPlayerSteamID()
return self.FounderSID or ""
end
function ENT:GetPlayerName()
local ply = self:GetPlayer()
if ( IsValid( ply ) ) then
return ply:Nick()
end
return self:GetNWString( "FounderName" )
end

View File

@@ -0,0 +1,55 @@
AddCSLuaFile()
ENT.Base = "base_entity"
ENT.PrintName = ""
ENT.Author = ""
ENT.Contact = ""
ENT.Purpose = ""
ENT.Instructions = ""
ENT.RenderGroup = RENDERGROUP_OPAQUE
ENT.Type = "nextbot"
function ENT:Initialize()
end
if ( SERVER ) then
--
-- All of the AI logic is serverside - so we derive it from a
-- specialized class on the server.
--
include( "sv_nextbot.lua" )
else
--[[---------------------------------------------------------
Name: Draw
Desc: Draw it!
-----------------------------------------------------------]]
function ENT:Draw()
self:DrawModel()
end
--[[---------------------------------------------------------
Name: DrawTranslucent
Desc: Draw translucent
-----------------------------------------------------------]]
function ENT:DrawTranslucent()
-- This is here just to make it backwards compatible.
-- You shouldn't really be drawing your model here unless it's translucent
self:Draw()
end
--[[---------------------------------------------------------
Name: FireAnimationEvent
Desc: Called when an animation event is fired. Return true to suppress
-----------------------------------------------------------]]
function ENT:FireAnimationEvent( pos, ang, event, options )
end
end

View File

@@ -0,0 +1,403 @@
--
-- Name: NEXTBOT:BehaveStart
-- Desc: Called to initialize the behaviour.\n\n You shouldn't override this - it's used to kick off the coroutine that runs the bot's behaviour. \n\nThis is called automatically when the NPC is created, there should be no need to call it manually.
-- Arg1:
-- Ret1:
--
function ENT:BehaveStart()
self.BehaveThread = coroutine.create( function() self:RunBehaviour() end )
end
function ENT:RunBehaviour()
end
--
-- Name: NEXTBOT:BehaveUpdate
-- Desc: Called to update the bot's behaviour
-- Arg1: number|interval|How long since the last update
-- Ret1:
--
function ENT:BehaveUpdate( fInterval )
if ( !self.BehaveThread ) then return end
--
-- Give a silent warning to developers if RunBehaviour has returned
--
if ( coroutine.status( self.BehaveThread ) == "dead" ) then
self.BehaveThread = nil
Msg( self, " Warning: ENT:RunBehaviour() has finished executing\n" )
return
end
--
-- Continue RunBehaviour's execution
--
local ok, message = coroutine.resume( self.BehaveThread )
if ( ok == false ) then
self.BehaveThread = nil
ErrorNoHalt( self, " Error: ", message, "\n" )
end
end
--
-- Name: NEXTBOT:BodyUpdate
-- Desc: Called to update the bot's animation
-- Arg1:
-- Ret1:
--
function ENT:BodyUpdate()
local act = self:GetActivity()
--
-- This helper function does a lot of useful stuff for us.
-- It sets the bot's move_x move_y pose parameters, sets their animation speed relative to the ground speed, and calls FrameAdvance.
--
if ( act == ACT_RUN || act == ACT_WALK ) then
self:BodyMoveXY()
-- BodyMoveXY() already calls FrameAdvance, calling it twice will affect animation playback, specifically on layers
return
end
--
-- If we're not walking or running we probably just want to update the anim system
--
self:FrameAdvance()
end
--
-- Name: NEXTBOT:OnLeaveGround
-- Desc: Called when the bot's feet leave the ground - for whatever reason
-- Arg1: Entity|ent|Entity that the NextBot "jumped" from
-- Ret1:
--
function ENT:OnLeaveGround( ent )
--MsgN( "OnLeaveGround", ent )
end
--
-- Name: NEXTBOT:OnLeaveGround
-- Desc: Called when the bot's feet return to the ground
-- Arg1: Entity|ent|Entity that the NextBot landed on
-- Ret1:
--
function ENT:OnLandOnGround( ent )
--MsgN( "OnLandOnGround", ent )
end
--
-- Name: NEXTBOT:OnStuck
-- Desc: Called when the bot thinks it is stuck
-- Arg1:
-- Ret1:
--
function ENT:OnStuck()
--MsgN( "OnStuck" )
end
--
-- Name: NEXTBOT:OnUnStuck
-- Desc: Called when the bot thinks it is un-stuck
-- Arg1:
-- Ret1:
--
function ENT:OnUnStuck()
--MsgN( "OnUnStuck" )
end
--
-- Name: NEXTBOT:OnInjured
-- Desc: Called when the bot gets hurt
-- Arg1: CTakeDamageInfo|info|damage info
-- Ret1:
--
function ENT:OnInjured( damageinfo )
end
--
-- Name: NEXTBOT:OnKilled
-- Desc: Called when the bot gets killed
-- Arg1: CTakeDamageInfo|info|damage info
-- Ret1:
--
function ENT:OnKilled( dmginfo )
hook.Run( "OnNPCKilled", self, dmginfo:GetAttacker(), dmginfo:GetInflictor() )
self:BecomeRagdoll( dmginfo )
end
--
-- Name: NEXTBOT:OnOtherKilled
-- Desc: Called when someone else or something else has been killed
-- Arg1: Entity|victim|entity that was killed
-- Arg2: CTakeDamageInfo|info|damage info
-- Ret1:
--
function ENT:OnOtherKilled( victim, info )
--MsgN( "OnOtherKilled", victim, info )
end
function ENT:OnContact( ent )
--MsgN( "OnContact", ent )
end
function ENT:OnIgnite()
--MsgN( "OnIgnite" )
end
function ENT:OnNavAreaChanged( old, new )
--MsgN( "OnNavAreaChanged", old, new )
end
--
-- Name: NextBot:FindSpots
-- Desc: Returns a table of hiding spots.
-- Arg1: table|specs|This table should contain the search info.\n\n * 'type' - the type (either 'hiding')\n * 'pos' - the position to search.\n * 'radius' - the radius to search.\n * 'stepup' - the highest step to step up.\n * 'stepdown' - the highest we can step down without being hurt.
-- Ret1: table|An unsorted table of tables containing\n * 'vector' - the position of the hiding spot\n * 'distance' - the distance to that position
--
function ENT:FindSpots( tbl )
local tbl = tbl or {}
tbl.pos = tbl.pos or self:WorldSpaceCenter()
tbl.radius = tbl.radius or 1000
tbl.stepdown = tbl.stepdown or 20
tbl.stepup = tbl.stepup or 20
tbl.type = tbl.type or 'hiding'
-- Use a path to find the length
local path = Path( "Follow" )
-- Find a bunch of areas within this distance
local areas = navmesh.Find( tbl.pos, tbl.radius, tbl.stepdown, tbl.stepup )
local found = {}
-- In each area
for _, area in pairs( areas ) do
-- get the spots
local spots
if ( tbl.type == 'hiding' ) then spots = area:GetHidingSpots() end
for k, vec in pairs( spots ) do
-- Work out the length, and add them to a table
path:Invalidate()
path:Compute( self, vec, 1 ) -- TODO: This is bullshit - it's using 'self.pos' not tbl.pos
table.insert( found, { vector = vec, distance = path:GetLength() } )
end
end
return found
end
--
-- Name: NextBot:FindSpot
-- Desc: Like FindSpots but only returns a vector
-- Arg1: string|type|Either "random", "near", "far"
-- Arg2: table|options|A table containing a bunch of tweakable options. See the function definition for more details
-- Ret1: vector|If it finds a spot it will return a vector. If not it will return nil.
--
function ENT:FindSpot( type, options )
local spots = self:FindSpots( options )
if ( !spots || #spots == 0 ) then return end
if ( type == "near" ) then
table.SortByMember( spots, "distance", true )
return spots[1].vector
end
if ( type == "far" ) then
table.SortByMember( spots, "distance", false )
return spots[1].vector
end
-- random
return spots[ math.random( 1, #spots ) ].vector
end
--
-- Name: NextBot:HandleStuck
-- Desc: Called from Lua when the NPC is stuck. This should only be called from the behaviour coroutine - so if you want to override this function and do something special that yields - then go for it.\n\nYou should always call self.loco:ClearStuck() in this function to reset the stuck status - so it knows it's unstuck.
-- Arg1:
-- Ret1:
--
function ENT:HandleStuck()
--
-- Clear the stuck status
--
self.loco:ClearStuck()
end
--
-- Name: NextBot:MoveToPos
-- Desc: To be called in the behaviour coroutine only! Will yield until the bot has reached the goal or is stuck
-- Arg1: Vector|pos|The position we want to get to
-- Arg2: table|options|A table containing a bunch of tweakable options. See the function definition for more details
-- Ret1: string|Either "failed", "stuck", "timeout" or "ok" - depending on how the NPC got on
--
function ENT:MoveToPos( pos, options )
local options = options or {}
local path = Path( "Follow" )
path:SetMinLookAheadDistance( options.lookahead or 300 )
path:SetGoalTolerance( options.tolerance or 20 )
path:Compute( self, pos )
if ( !path:IsValid() ) then return "failed" end
while ( path:IsValid() ) do
path:Update( self )
-- Draw the path (only visible on listen servers or single player)
if ( options.draw ) then
path:Draw()
end
-- If we're stuck then call the HandleStuck function and abandon
if ( self.loco:IsStuck() ) then
self:HandleStuck()
return "stuck"
end
--
-- If they set maxage on options then make sure the path is younger than it
--
if ( options.maxage ) then
if ( path:GetAge() > options.maxage ) then return "timeout" end
end
--
-- If they set repath then rebuild the path every x seconds
--
if ( options.repath ) then
if ( path:GetAge() > options.repath ) then path:Compute( self, pos ) end
end
coroutine.yield()
end
return "ok"
end
--
-- Name: NextBot:PlaySequenceAndWait
-- Desc: To be called in the behaviour coroutine only! Plays an animation sequence and waits for it to end before returning.
-- Arg1: string|name|The sequence name
-- Arg2: number|the speed (default 1)
-- Ret1:
--
function ENT:PlaySequenceAndWait( name, speed )
local len = self:SetSequence( name )
speed = speed or 1
self:ResetSequenceInfo()
self:SetCycle( 0 )
self:SetPlaybackRate( speed )
-- wait for it to finish
coroutine.wait( len / speed )
end
--
-- Name: NEXTBOT:Use
-- Desc: Called when a player 'uses' the entity
-- Arg1: entity|activator|The entity that activated the use
-- Arg2: entity|called|The entity that called the use
-- Arg3: number|type|The type of use (USE_ON, USE_OFF, USE_TOGGLE, USE_SET)
-- Arg4: number|value|Any passed value
-- Ret1:
--
function ENT:Use( activator, caller, type, value )
end
--
-- Name: NEXTBOT:Think
-- Desc: Called periodically
-- Arg1:
-- Ret1:
--
function ENT:Think()
end
--
-- Name: NEXTBOT:HandleAnimEvent
-- Desc: Called for serverside events
--
function ENT:HandleAnimEvent( event, eventtime, cycle, typee, options )
end
--
-- Name: NEXTBOT:OnTraceAttack
-- Desc: Called serverside when the nextbot is attacked
--
function ENT:OnTraceAttack( dmginfo, dir, trace )
hook.Run( "ScaleNPCDamage", self, trace.HitGroup, dmginfo )
end
-- Called when we see a player or another nextbot
function ENT:OnEntitySight( subject )
end
-- Called when we see lose sight of a player or a nextbot we saw earlier
function ENT:OnEntitySightLost( subject )
end

View File

@@ -0,0 +1,45 @@
ENT.Base = "base_entity"
ENT.Type = "point"
--[[---------------------------------------------------------
Name: Initialize
Desc: First function called. Use to set up your entity
-----------------------------------------------------------]]
function ENT:Initialize()
end
--[[---------------------------------------------------------
Name: KeyValue
Desc: Called when a keyvalue is added to us
-----------------------------------------------------------]]
function ENT:KeyValue( key, value )
end
--[[---------------------------------------------------------
Name: Think
Desc: Entity's think function.
-----------------------------------------------------------]]
function ENT:Think()
end
--
-- Name: OnRemove
-- Desc: Called just before entity is deleted
--
function ENT:OnRemove()
end
--
-- UpdateTransmitState
--
function ENT:UpdateTransmitState()
--
-- The default behaviour for point entities is to not be networked.
-- If you're deriving an entity and want it to appear clientside, override this
-- TRANSMIT_ALWAYS = always send, TRANSMIT_PVS = send if in PVS
--
return TRANSMIT_NEVER
end

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,135 @@
AddCSLuaFile()
ENT.Type = "point"
ENT.DisableDuplicator = true
--
-- Make this entity always networked
--
function ENT:UpdateTransmitState() return TRANSMIT_ALWAYS end
--
-- Networked / Saved Data
--
function ENT:SetupDataTables()
self:NetworkVar( "Vector", 0, "TopColor", { KeyName = "topcolor", Edit = { type = "VectorColor", category = "Main", order = 1 } } )
self:NetworkVar( "Vector", 1, "BottomColor", { KeyName = "bottomcolor", Edit = { type = "VectorColor", category = "Main", title = "Color Bottom", order = 2 } } )
self:NetworkVar( "Float", 0, "FadeBias", { KeyName = "fadebias", Edit = { type = "Float", category = "Main", min = 0, max = 1, order = 3 } } )
self:NetworkVar( "Float", 4, "SunSize", { KeyName = "sunsize", Edit = { type = "Float", min = 0, max = 10, category = "Sun" } } )
self:NetworkVar( "Vector", 2, "SunNormal", { KeyName = "sunnormal" } ) -- No editing this - it's for coders only
self:NetworkVar( "Vector", 3, "SunColor", { KeyName = "suncolor", Edit = { type = "VectorColor", category = "Sun" } } )
self:NetworkVar( "Float", 2, "DuskScale", { KeyName = "duskscale", Edit = { type = "Float", min = 0, max = 1, category = "Dusk" } } )
self:NetworkVar( "Float", 3, "DuskIntensity", { KeyName = "duskintensity", Edit = { type = "Float", min = 0, max = 10, category = "Dusk" } } )
self:NetworkVar( "Vector", 4, "DuskColor", { KeyName = "duskcolor", Edit = { type = "VectorColor", category = "Dusk" } } )
self:NetworkVar( "Bool", 0, "DrawStars", { KeyName = "drawstars", Edit = { type = "Boolean", category = "Stars", order = 10 } } )
self:NetworkVar( "String", 0, "StarTexture", { KeyName = "startexture", Edit = { type = "Texture", group = "Stars", category = "Stars", order = 11 } } )
self:NetworkVar( "Int", 0, "StarLayers", { KeyName = "starlayers", Edit = { type = "Int", min = 1, max = 3, category = "Stars", order = 12 } } )
self:NetworkVarElement( "Angle", 0, 'p', "StarScale", { KeyName = "starscale", Edit = { type = "Float", min = 0, max = 5, category = "Stars", order = 13 } } )
self:NetworkVarElement( "Angle", 0, 'y', "StarFade", { KeyName = "starfade", Edit = { type = "Float", min = 0, max = 5, category = "Stars", order = 14 } } )
self:NetworkVarElement( "Angle", 0, 'r', "StarSpeed", { KeyName = "starspeed", Edit = { type = "Float", min = 0, max = 2, category = "Stars", order = 15 } } )
self:NetworkVar( "Float", 1, "HDRScale", { KeyName = "hdrscale", Edit = { type = "Float", category = "Main", min = 0, max = 1, order = 4 } } )
--
-- Entity defaults
--
if ( SERVER ) then
self:SetTopColor( Vector( 0.2, 0.5, 1.0 ) )
self:SetBottomColor( Vector( 0.8, 1.0, 1.0 ) )
self:SetFadeBias( 1 )
self:SetSunNormal( Vector( 0.4, 0.0, 0.01 ) )
self:SetSunColor( Vector( 0.2, 0.1, 0.0 ) )
self:SetSunSize( 2.0 )
self:SetDuskColor( Vector( 1.0, 0.2, 0.0 ) )
self:SetDuskScale( 1 )
self:SetDuskIntensity( 1 )
self:SetDrawStars( true )
self:SetStarLayers( 1 )
self:SetStarSpeed( 0.01 )
self:SetStarScale( 0.5 )
self:SetStarFade( 1.5 )
self:SetStarTexture( "skybox/starfield" )
self:SetHDRScale( 0.66 )
end
end
function ENT:Initialize()
end
function ENT:KeyValue( key, value )
if ( self:SetNetworkKeyValue( key, value ) ) then
return
end
-- TODO: sunposmethod
-- 0 : "Custom - Use the Sun Normal to position the sun"
-- 1 : "Automatic - Find a env_sun entity and use that"
end
function ENT:Think()
--
-- Find an env_sun - if we don't already have one.
--
if ( SERVER && self.EnvSun == nil ) then
-- so this closure only gets called once - even if it fails
self.EnvSun = false
local list = ents.FindByClass( "env_sun" )
if ( #list > 0 ) then
self.EnvSun = list[1]
end
end
--
-- If we have a sun - force our sun normal to its value
--
if ( SERVER && IsValid( self.EnvSun ) ) then
local vec = self.EnvSun:GetInternalVariable( "m_vDirection" )
if ( isvector( vec ) ) then
self:SetSunNormal( vec )
end
end
--
-- Become the active sky again if we're not already
--
if ( CLIENT && g_SkyPaint != self ) then
if ( !IsValid( g_SkyPaint ) ) then
g_SkyPaint = self
end
end
end
--
-- To prevent server insanity - only let admins edit the sky.
--
function ENT:CanEditVariables( ply )
return ply:IsAdmin()
end

View File

@@ -0,0 +1,67 @@
AddCSLuaFile()
ENT.Type = "anim"
ENT.RenderGroup = RENDERGROUP_OTHER
function ENT:Initialize()
hook.Add( "OnViewModelChanged", self, self.ViewModelChanged )
self:SetNotSolid( true )
self:DrawShadow( false )
self:SetTransmitWithParent( true ) -- Transmit only when the viewmodel does!
end
function ENT:DoSetup( ply, spec )
-- Set these hands to the player
ply:SetHands( self )
self:SetOwner( ply )
-- Which hands should we use? Let the gamemode decide
hook.Call( "PlayerSetHandsModel", GAMEMODE, spec or ply, self )
-- Attach them to the viewmodel
local vm = ( spec or ply ):GetViewModel( 0 )
self:AttachToViewmodel( vm )
vm:DeleteOnRemove( self )
ply:DeleteOnRemove( self )
end
function ENT:GetPlayerColor()
--
-- Make sure there's an owner and they have this function
-- before trying to call it!
--
local owner = self:GetOwner()
if ( !IsValid( owner ) ) then return end
if ( !owner.GetPlayerColor ) then return end
return owner:GetPlayerColor()
end
function ENT:ViewModelChanged( vm, old, new )
-- Ignore other peoples viewmodel changes!
if ( vm:GetOwner() != self:GetOwner() ) then return end
self:AttachToViewmodel( vm )
end
function ENT:AttachToViewmodel( vm )
self:AddEffects( EF_BONEMERGE )
self:SetParent( vm )
self:SetMoveType( MOVETYPE_NONE )
self:SetPos( vector_origin )
self:SetAngles( angle_zero )
end

View File

@@ -0,0 +1,81 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"
function ENT:Initialize()
if ( self.RedTeam or self.GreenTeam or self.YellowTeam or self.BlueTeam ) then
-- If any of these are set to true then
-- make sure that any that aren't setup are
-- set to false.
self.BlueTeam = self.BlueTeam or false
self.GreenTeam = self.GreenTeam or false
self.YellowTeam = self.YellowTeam or false
self.RedTeam = self.RedTeam or false
else
-- If none are set then make it so that they all
-- are set to true since any team can spawn here.
-- This will also happen if we don't have the "spawnflags"
-- keyvalue setup.
self.BlueTeam = true
self.GreenTeam = true
self.YellowTeam = true
self.RedTeam = true
end
end
function ENT:KeyValue( key, value )
if ( key == "spawnflags" ) then
local sf = tonumber( value )
for i = 15, 0, -1 do
local bit = math.pow( 2, i )
-- Quick bit if bitwise math to figure out if the spawnflags
-- represent red/blue/green or yellow.
-- We have to use booleans since the TEAM_ identifiers
-- aren't setup at this point.
-- (this would be easier if we had bitwise operators in Lua)
if ( ( sf - bit ) >= 0 ) then
if ( bit == 8 ) then self.RedTeam = true
elseif ( bit == 4 ) then self.GreenTeam = true
elseif ( bit == 2 ) then self.YellowTeam = true
elseif ( bit == 1 ) then self.BlueTeam = true
end
sf = sf - bit
else
if ( bit == 8 ) then self.RedTeam = false
elseif ( bit == 4 ) then self.GreenTeam = false
elseif ( bit == 2 ) then self.YellowTeam = false
elseif ( bit == 1 ) then self.BlueTeam = false
end
end
end
end
end

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,10 @@
-- This is just a simple point entity.
-- We only use it to represent the position and angle of a spawn point
-- So we don't have to do anything here because the baseclass will
-- take care of the basics
-- This file only exists so that the entity is created
ENT.Type = "point"

View File

@@ -0,0 +1,63 @@
-- A spawnflag constant for addons
SF_LUA_RUN_ON_SPAWN = 1
ENT.Type = "point"
ENT.DisableDuplicator = true
AccessorFunc( ENT, "m_bDefaultCode", "DefaultCode" )
function ENT:Initialize()
-- If the entity has its first spawnflag set, run the code automatically
if ( self:HasSpawnFlags( SF_LUA_RUN_ON_SPAWN ) ) then
self:RunCode( self, self, self:GetDefaultCode() )
end
end
function ENT:KeyValue( key, value )
if ( key == "Code" ) then
self:SetDefaultCode( value )
end
end
function ENT:SetupGlobals( activator, caller )
ACTIVATOR = activator
CALLER = caller
if ( IsValid( activator ) && activator:IsPlayer() ) then
TRIGGER_PLAYER = activator
end
end
function ENT:KillGlobals()
ACTIVATOR = nil
CALLER = nil
TRIGGER_PLAYER = nil
end
function ENT:RunCode( activator, caller, code )
self:SetupGlobals( activator, caller )
RunString( code, "lua_run#" .. self:EntIndex() )
self:KillGlobals()
end
function ENT:AcceptInput( name, activator, caller, data )
if ( name == "RunCode" ) then self:RunCode( activator, caller, self:GetDefaultCode() ) return true end
if ( name == "RunPassedCode" ) then self:RunCode( activator, caller, data ) return true end
return false
end

View File

@@ -0,0 +1,72 @@
AddCSLuaFile()
ENT.Base = "base_nextbot"
ENT.Spawnable = false
function ENT:Initialize()
--self:SetModel( "models/props_halloween/ghost_no_hat.mdl" )
--self:SetModel( "models/props_wasteland/controlroom_filecabinet002a.mdl" )
self:SetModel( "models/mossman.mdl" )
end
function ENT:RunBehaviour()
while ( true ) do
self:StartActivity( ACT_WALK ) -- walk anims
self.loco:SetDesiredSpeed( 100 ) -- walk speeds
-- Choose a random location within 400 units of our position
local targetPos = self:GetPos() + Vector( math.Rand( -1, 1 ), math.Rand( -1, 1 ), 0 ) * 400
-- Search for walkable space there, or nearby
local area = navmesh.GetNearestNavArea( targetPos )
-- We found walkable space, get the closest point on that area to where we want to be
if ( IsValid( area ) ) then targetPos = area:GetClosestPointOnArea( targetPos ) end
-- walk to the target place (yielding)
self:MoveToPos( targetPos )
self:StartActivity( ACT_IDLE ) -- revert to idle activity
self:PlaySequenceAndWait( "idle_to_sit_ground" ) -- Sit on the floor
self:SetSequence( "sit_ground" ) -- Stay sitting
coroutine.wait( self:PlayScene( "scenes/eli_lab/mo_gowithalyx01.vcd" ) ) -- play a scene and wait for it to finish before progressing
self:PlaySequenceAndWait( "sit_ground_to_idle" ) -- Get up
-- find the furthest away hiding spot
local pos = self:FindSpot( "random", { type = 'hiding', radius = 5000 } )
-- if the position is valid
if ( pos ) then
self:StartActivity( ACT_RUN ) -- run anim
self.loco:SetDesiredSpeed( 200 ) -- run speed
self:PlayScene( "scenes/npc/female01/watchout.vcd" ) -- shout something while we run just for a laugh
self:MoveToPos( pos ) -- move to position (yielding)
self:PlaySequenceAndWait( "fear_reaction" ) -- play a fear animation
self:StartActivity( ACT_IDLE ) -- when we finished, go into the idle anim
else
-- some activity to signify that we didn't find shit
end
coroutine.yield()
end
end
--
-- List the NPC as spawnable
--
list.Set( "NPC", "npc_tf2_ghost", {
Name = "Example NPC",
Class = "npc_tf2_ghost",
Category = "Nextbot"
} )

View File

@@ -0,0 +1,125 @@
/*--------------------------------------------------
*** Copyright (c) 2012-2024 by DrVrej, All rights reserved. ***
No parts of this code or any of its contents may be reproduced, copied, modified or adapted,
without the prior written consent of the author, unless otherwise indicated for stand-alone materials.
--------------------------------------------------*/
AddCSLuaFile()
ENT.Type = "anim"
ENT.Base = "obj_vj_projectile_base"
ENT.PrintName = "Grenade"
ENT.Author = "DrVrej"
ENT.Contact = "http://steamcommunity.com/groups/vrejgaming"
ENT.Information = "Projectiles for my addons"
ENT.Category = "VJ Base"
ENT.Spawnable = true
ENT.AdminOnly = false
ENT.VJTag_ID_Grenade = true
ENT.VJTag_IsPickupable = true
---------------------------------------------------------------------------------------------------------------------------------------------
if CLIENT then
local Name = "Grenade"
local LangName = "obj_vj_grenade"
language.Add(LangName, Name)
killicon.Add(LangName,"HUD/killicons/default",Color(255,80,0,255))
language.Add("#"..LangName, Name)
killicon.Add("#"..LangName,"HUD/killicons/default",Color(255,80,0,255))
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
if !SERVER then return end
ENT.Model = {"models/vj_weapons/w_grenade.mdl"} -- The models it should spawn with | Picks a random one from the table
ENT.MoveCollideType = nil
ENT.CollisionGroupType = nil
ENT.SolidType = SOLID_VPHYSICS
ENT.RemoveOnHit = false -- Should it remove itself when it touches something? | It will run the hit sound, place a decal, etc.
ENT.DoesRadiusDamage = true -- Should it do a blast damage when it hits something?
ENT.RadiusDamageRadius = 256 -- How far the damage go? The farther away it's from its enemy, the less damage it will do | Counted in world units
ENT.RadiusDamage = 256 -- How much damage should it deal? Remember this is a radius damage, therefore it will do less damage the farther away the entity is from its enemy
ENT.RadiusDamageUseRealisticRadius = true -- Should the damage decrease the farther away the enemy is from the position that the projectile hit?
ENT.RadiusDamageType = DMG_BLAST -- Damage type
ENT.RadiusDamageForce = 90 -- Put the force amount it should apply | false = Don't apply any force
ENT.DecalTbl_DeathDecals = {"Scorch"}
ENT.SoundTbl_OnCollide = {"weapons/hegrenade/he_bounce-1.wav"}
-- Custom
ENT.FuseTime = 3
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:CustomPhysicsObjectOnInitialize(phys)
phys:Wake()
phys:EnableGravity(true)
phys:SetBuoyancyRatio(0)
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:CustomOnInitialize()
timer.Simple(self.FuseTime, function()
if IsValid(self) then
self:DeathEffects()
end
end)
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:CustomOnTakeDamage(dmginfo)
local phys = self:GetPhysicsObject()
if IsValid(phys) then
phys:AddVelocity(dmginfo:GetDamageForce() * 0.1)
end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:CustomOnPhysicsCollide(data, phys)
local getVel = phys:GetVelocity()
local curVelSpeed = getVel:Length()
//print(curVelSpeed)
if curVelSpeed > 500 then -- Or else it will go flying!
phys:SetVelocity(getVel * 0.9)
end
if curVelSpeed > 100 then -- If the grenade is going faster than 100, then play the touch sound
self:OnCollideSoundCode()
end
end
---------------------------------------------------------------------------------------------------------------------------------------------
local defAngle = Angle(0, 0, 0)
local vecZ4 = Vector(0, 0, 4)
local vezZ100 = Vector(0, 0, 100)
--
function ENT:DeathEffects()
local selfPos = self:GetPos()
ParticleEffect("vj_explosion1", self:GetPos(), defAngle, nil)
local effectData = EffectData()
effectData:SetOrigin(self:GetPos())
//effectData:SetScale(500)
//util.Effect("HelicopterMegaBomb", effectData)
//util.Effect("ThumperDust", effectData)
util.Effect("Explosion", effectData)
//util.Effect("VJ_Small_Explosion1", effectData)
local expLight = ents.Create("light_dynamic")
expLight:SetKeyValue("brightness", "4")
expLight:SetKeyValue("distance", "300")
expLight:SetLocalPos(selfPos)
expLight:SetLocalAngles(self:GetAngles())
expLight:Fire("Color", "255 150 0")
expLight:SetParent(self)
expLight:Spawn()
expLight:Activate()
expLight:Fire("TurnOn", "", 0)
self:DeleteOnRemove(expLight)
util.ScreenShake(self:GetPos(), 100, 200, 1, 2500)
self:SetLocalPos(selfPos + vecZ4) -- Because the entity is too close to the ground
local tr = util.TraceLine({
start = self:GetPos(),
endpos = self:GetPos() - vezZ100,
filter = self
})
util.Decal("Scorch", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal)
self:DoDamageCode()
self:SetDeathVariablesTrue(nil, nil, false)
self:Remove()
end

View File

@@ -0,0 +1,178 @@
AddCSLuaFile()
if ( CLIENT ) then
CreateConVar( "cl_draweffectrings", "1", 0, "Should the effect green rings be visible?" )
end
ENT.Type = "anim"
ENT.Spawnable = false
function ENT:Initialize()
local Radius = 6
local mins = Vector( 1, 1, 1 ) * Radius * -0.5
local maxs = Vector( 1, 1, 1 ) * Radius * 0.5
if ( SERVER ) then
self.AttachedEntity = ents.Create( "prop_dynamic" )
self.AttachedEntity:SetModel( self:GetModel() )
self.AttachedEntity:SetAngles( self:GetAngles() )
self.AttachedEntity:SetPos( self:GetPos() )
self.AttachedEntity:SetSkin( self:GetSkin() )
self.AttachedEntity:Spawn()
self.AttachedEntity:SetParent( self )
self.AttachedEntity:DrawShadow( false )
self:SetModel( "models/props_junk/watermelon01.mdl" )
self:DeleteOnRemove( self.AttachedEntity )
self.AttachedEntity:DeleteOnRemove( self )
-- Don't use the model's physics - create a box instead
self:PhysicsInitBox( mins, maxs )
self:SetSolid( SOLID_VPHYSICS )
-- Set up our physics object here
local phys = self:GetPhysicsObject()
if ( IsValid( phys ) ) then
phys:Wake()
phys:EnableGravity( false )
phys:EnableDrag( false )
end
self:DrawShadow( false )
self:SetCollisionGroup( COLLISION_GROUP_WEAPON )
else
-- So addons can override this
self.GripMaterial = Material( "sprites/grip" )
self.GripMaterialHover = Material( "sprites/grip_hover" )
-- Get the attached entity so that clientside functions like properties can interact with it
local tab = ents.FindByClassAndParent( "prop_dynamic", self )
if ( tab && IsValid( tab[ 1 ] ) ) then self.AttachedEntity = tab[ 1 ] end
end
-- Set collision bounds exactly
self:SetCollisionBounds( mins, maxs )
end
function ENT:Draw()
if ( halo.RenderedEntity() == self ) then
self.AttachedEntity:DrawModel()
return
end
if ( GetConVarNumber( "cl_draweffectrings" ) == 0 ) then return end
-- Don't draw the grip if there's no chance of us picking it up
local ply = LocalPlayer()
local wep = ply:GetActiveWeapon()
if ( !IsValid( wep ) ) then return end
local weapon_name = wep:GetClass()
if ( weapon_name != "weapon_physgun" && weapon_name != "weapon_physcannon" && weapon_name != "gmod_tool" ) then
return
end
if ( self:BeingLookedAtByLocalPlayer() ) then
render.SetMaterial( self.GripMaterialHover )
else
render.SetMaterial( self.GripMaterial )
end
render.DrawSprite( self:GetPos(), 16, 16, color_white )
end
-- Copied from base_gmodentity.lua
ENT.MaxWorldTipDistance = 256
function ENT:BeingLookedAtByLocalPlayer()
local ply = LocalPlayer()
if ( !IsValid( ply ) ) then return false end
local view = ply:GetViewEntity()
local dist = self.MaxWorldTipDistance
dist = dist * dist
-- If we're spectating a player, perform an eye trace
if ( view:IsPlayer() ) then
return view:EyePos():DistToSqr( self:GetPos() ) <= dist && view:GetEyeTrace().Entity == self
end
-- If we're not spectating a player, perform a manual trace from the entity's position
local pos = view:GetPos()
if ( pos:DistToSqr( self:GetPos() ) <= dist ) then
return util.TraceLine( {
start = pos,
endpos = pos + ( view:GetAngles():Forward() * dist ),
filter = view
} ).Entity == self
end
return false
end
function ENT:PhysicsUpdate( physobj )
if ( CLIENT ) then return end
-- Don't do anything if the player isn't holding us
if ( !self:IsPlayerHolding() && !self:IsConstrained() ) then
physobj:SetVelocity( vector_origin )
physobj:Sleep()
end
end
function ENT:OnEntityCopyTableFinish( tab )
-- We need to store the model of the attached entity
-- Not the one we have here.
tab.Model = self.AttachedEntity:GetModel()
-- Store the attached entity's table so we can restore it after being pasted
tab.AttachedEntityInfo = table.Copy( duplicator.CopyEntTable( self.AttachedEntity ) )
tab.AttachedEntityInfo.Pos = nil -- Don't even save angles and position, we are a parented entity
tab.AttachedEntityInfo.Angle = nil
-- Do NOT store the attached entity itself in our table!
-- Otherwise, if we copy-paste the prop with the duplicator, its AttachedEntity value will point towards the original prop's attached entity instead, and that'll break stuff
tab.AttachedEntity = nil
end
function ENT:PostEntityPaste( ply )
-- Restore the attached entity using the information we've saved
if ( IsValid( self.AttachedEntity ) && self.AttachedEntityInfo ) then
-- Apply skin, bodygroups, bone manipulator, etc.
duplicator.DoGeneric( self.AttachedEntity, self.AttachedEntityInfo )
if ( self.AttachedEntityInfo.EntityMods ) then
self.AttachedEntity.EntityMods = table.Copy( self.AttachedEntityInfo.EntityMods )
duplicator.ApplyEntityModifiers( ply, self.AttachedEntity )
end
if ( self.AttachedEntityInfo.BoneMods ) then
self.AttachedEntity.BoneMods = table.Copy( self.AttachedEntityInfo.BoneMods )
duplicator.ApplyBoneModifiers( ply, self.AttachedEntity )
end
self.AttachedEntityInfo = nil
end
end

View File

@@ -0,0 +1,304 @@
AddCSLuaFile()
ENT.Type = "anim"
ENT.Spawnable = false
ENT.AdminOnly = false
ENT.Editable = true
function ENT:SetupDataTables()
--
-- Scale - how far the ragdoll will move in the game world in relation to how far it moved in the real world
--
self:NetworkVar( "Float", 0, "Scale", { KeyName = "scale", Edit = { type = "Float", min=1, max=512, order = 1 } } )
--
-- Normalize - if enabled the limbs aren't stretched
--
self:NetworkVar( "Bool", 0, "Normalize", { KeyName = "normalize", Edit = { type = "Boolean", order = 2 } } )
--
-- Debug - Shows some debug info - only available on a listen server
--
self:NetworkVar( "Bool", 1, "Debug", { KeyName = "debug", Edit = { type = "Boolean", order = 100 } } )
--
-- Controller - the entity that is currently controlling the ragdoll
--
self:NetworkVar( "Entity", 0, "Controller" )
self:NetworkVar( "Entity", 1, "Target" )
--
-- Defaults
--
if ( SERVER ) then
self:SetScale( 36 )
self:SetDebug( false )
self:SetNormalize( true )
end
end
function ENT:Initialize()
if ( SERVER ) then
self:SetModel( "models/maxofs2d/motion_sensor.mdl" )
self:PhysicsInit( SOLID_VPHYSICS )
-- Don't collide with the player
self:SetCollisionGroup( COLLISION_GROUP_WEAPON )
self:DrawShadow( false )
local phys = self:GetPhysicsObject()
if ( IsValid( phys ) ) then
phys:Wake()
phys:EnableGravity( false )
phys:EnableDrag( false )
end
local colors = {
Color( 180, 255, 50 ),
Color( 0, 150, 255 ),
Color( 255, 255, 0 ),
Color( 255, 50, 255 )
}
self:SetColor( table.Random( colors ) )
end
end
--
-- We don't want to move unless the player moves us or we're constrained to something.
--
function ENT:PhysicsUpdate( physobj )
if ( self:IsPlayerHolding() ) then return end
if ( self:IsConstrained() ) then return end
physobj:SetVelocity( vector_origin )
physobj:Sleep()
end
--
-- Clean up on remove
--
function ENT:OnRemove()
if ( SERVER ) then
local ragdoll = self:GetTarget()
if ( IsValid( ragdoll ) ) then
ragdoll:SetRagdollBuildFunction( nil )
end
end
end
function ENT:Draw()
--
-- Don't draw if we're holding the camera
--
local ply = LocalPlayer()
local wep = ply:GetActiveWeapon()
if ( wep:IsValid() ) then
if ( wep:GetClass() == "gmod_camera" ) then return end
end
self:DrawModel()
end
function ENT:DrawDebug( ragdoll, controller, pos, ang, rotation, scale, center, changed_sensor )
local UpdateTime = 0.1
local StayTime = 0.15
if ( self.LastDebugUpdate && CurTime() - self.LastDebugUpdate < UpdateTime ) then return end
self.LastDebugUpdate = CurTime()
center = center
local col_bone = color_white
local col_point = Color( 255, 0, 0, 255 )
local col_tran_bn = Color( 0, 255, 0, 255 )
local realbonepos = {}
local fixedbonepos = {}
local min = Vector( 1, 1, 1 ) * -0.5
local max = Vector( 1, 1, 1 ) * 0.5
--
-- Draw Points
--
for i = 0, 19 do
realbonepos[i] = controller:MotionSensorPos( i ) * scale
realbonepos[i]:Rotate( rotation )
realbonepos[i] = realbonepos[i] + center
fixedbonepos[i] = changed_sensor[ i ] * scale
-- (already rotated)
fixedbonepos[i] = fixedbonepos[i] + center
debugoverlay.Box( realbonepos[i], min, max, StayTime, col_point, true )
debugoverlay.Box( fixedbonepos[i], min, max, StayTime, col_tran_bn, true )
end
--
-- Draw bones
--
for k, v in pairs( motionsensor.DebugBones ) do
debugoverlay.Line( realbonepos[ v[1] ], realbonepos[ v[2] ], StayTime, col_bone, true )
end
--
-- Draw translated sensor bones
--
for k, v in pairs( motionsensor.DebugBones ) do
debugoverlay.Line( fixedbonepos[ v[1] ], fixedbonepos[ v[2] ], StayTime, col_tran_bn, true )
end
--
-- Draw ragdoll physics bones
--
for i=0, ragdoll:GetPhysicsObjectCount() - 1 do
local phys = ragdoll:GetPhysicsObjectNum( i )
local pos = phys:GetPos()
local angle = phys:GetAngles()
local txt = i
if ( ang[i] == nil ) then
txt = i .. " (UNSET)"
end
debugoverlay.Text( pos, txt, StayTime )
debugoverlay.Axis( pos, angle, 5, StayTime, true )
end
end
function ENT:SetRagdoll( ragdoll )
self:SetTarget( ragdoll )
ragdoll:PhysWake()
local buildername = motionsensor.ChooseBuilderFromEntity( ragdoll )
--
-- Set the ragdoll build function.
-- This function is called whenever the ragdoll bones are built.
-- in this function is the one place you can successfully call ent:SetRagdollBone
--
ragdoll:SetRagdollBuildFunction( function( ragdoll )
local controller = self:GetController()
if ( !IsValid( controller ) ) then return end
local builder = list.Get( "SkeletonConvertor" )[ buildername ]
local scale = self:GetScale()
local rotation = self:GetAngles()
local center = self:GetPos()
local normalize = self:GetNormalize()
local debug = self:GetDebug()
--
-- Call the build skeleton function.
-- This is thrown out to a pseudo class because we want to be
-- able to add new skeleton types nice and easily.
--
local pos, ang, changed_sensor = motionsensor.BuildSkeleton( builder, controller, rotation )
--
-- For development
--
if ( debug ) then
self:DrawDebug( ragdoll, controller, pos, ang, rotation, scale, center, changed_sensor )
end
--
-- If we don't have 85% of the points, just drop dead
--
local iSkipped = 0
local iMaxSkip = table.Count( pos ) * 0.25
for k, v in pairs( pos ) do
if ( math.abs( v.x ) > 0.05 ) then continue end
if ( math.abs( v.y ) > 0.05 ) then continue end
pos[k] = nil -- don't use this point to control the ragdoll
ang[k] = nil -- (use the ragdoll point)
iSkipped = iSkipped + 1
if ( iSkipped > iMaxSkip ) then
ragdoll:RagdollStopControlling()
return
end
end
--
-- Loop each returned position
--
for k, v in pairs( pos ) do
--
-- Set the bone angle
--
if ( ang[ k ] != nil ) then
ragdoll:SetRagdollAng( k, ang[ k ] )
end
--
-- The root bone, we directly set the position of this one.
--
if ( k == 0 || !normalize ) then
local new_position = center + v * scale
ragdoll:SetRagdollPos( k, new_position )
end
end
--
-- Normalize the ragdoll
--
if ( normalize ) then
ragdoll:RagdollSolve()
end
--
-- Makes the physics objects follow the set bone positions
--
ragdoll:RagdollUpdatePhysics()
end )
end

View File

@@ -0,0 +1,4 @@
include('shared.lua')
function ENT:Draw() self:DrawModel() end
function ENT:DrawTranslucent() self:Draw() end

View File

@@ -0,0 +1,42 @@
AddCSLuaFile('shared.lua')
AddCSLuaFile('cl_init.lua')
include("shared.lua")
function ENT:Think()
if self.enable_ent and (!IsValid(self.ent) or self.ent:Health() <= 0) then
self:Remove()
return
end
if self:GetCycle() >= 1 then
self:SetCycle(0)
end
local ent = self.ent
if IsValid(ent) then
local bone = self:LookupBone("root") or self:LookupBone("ValveBiped.Bip01_Pelvis")
local att = self:GetBonePosition(bone)
local tr = util.TraceLine({
start = att,
endpos = att - Vector(0,0,100),
filter = ent,
})
ent:SetPos(tr.HitPos)
end
if self.push or IsValid(ent) then
local bone = self:LookupBone("root") or self:LookupBone("ValveBiped.Bip01_Pelvis")
local att = self:GetBonePosition(bone)
for k, v in pairs(ents.FindInSphere(att, 100)) do
if v:IsNPC() and v != ent then
local pos1 = att
local pos2 = v:GetPos()
local dir = (pos1 - pos2):GetNormalized()
v:SetVelocity(-dir * 100)
end
end
end
self:NextThink(CurTime())
return true
end

View File

@@ -0,0 +1,4 @@
ENT.Base = "base_anim"
ENT.Type = "anim"
ENT.RenderGroup = RENDERGROUP_BOTH
ENT.AutomaticFrameAdvance = true

View File

@@ -0,0 +1,101 @@
include("shared.lua")
function ENT:Initialize()
self.TableProp = {
{
prop = "models/props_fortifications/concrete_barrier001_96_reference.mdl",
health = 2500,
damage = 0,
breaksound = "physics/concrete/concrete_break"..math.random(2,3)..".wav",
},
{
prop = "models/props_fortifications/barricade_razorwire001_128_reference.mdl",
health = 250,
damage = 10,
breaksound = "physics/metal/metal_chainlink_impact_hard"..math.random(1,3)..".wav",
},
{
prop = "models/props_wasteland/dockplank01b.mdl",
health = 500,
damage = 0,
breaksound = "physics/wood/wood_plank_break"..math.random(1,4)..".wav",
},
{
prop = "models/props_debris/metal_panel01a.mdl",
health = 1125,
damage = 0,
breaksound = "physics/metal/metal_chainlink_impact_hard"..math.random(1,3)..".wav",
},
{
prop = "models/props_combine/combine_light001a.mdl",
health = 100,
damage = 0,
breaksound = "physics/glass/glass_bottle_impact_hard"..math.random(1,3)..".wav",
},
{
prop = "",
health = self.healthmax,
damage = 0,
breaksound = "physics/concrete/concrete_break"..math.random(2,3)..".wav",
},
}
if not self.MapCade then
if not self.id then
self.id = 1
end
self.barricade = true
self:SetModel(self.TableProp[self.id].prop)
if self.id != 2 then
self:SetSolid(SOLID_VPHYSICS)
if self.id == 5 then
self:SetNWBool('lamp', true)
end
end
self.health = self.TableProp[self.id].health
else
self:SetSolid(SOLID_VPHYSICS)
end
self:SetNWFloat('healthmax', self.TableProp[self.id].health)
self:SetCustomCollisionCheck(true)
end
function ENT:Think()
self:SetColor(Color(255,255*(self.health/self.TableProp[self.id].health),255*(self.health/self.TableProp[self.id].health)))
self:SetHealth(self.health)
if self.TableProp[self.id].damage > 0 and not self.cantdamage then
self.cantdamage = true
for _, ent in ipairs(ents.FindInSphere(self:GetPos(), 40)) do
if (ent:IsPlayer() or ent:IsNextBot()) then
local d = DamageInfo()
if ent:IsNextBot() then
d:SetDamage(self.TableProp[self.id].damage)
end
d:SetAttacker(self)
d:SetDamageType(DMG_FALL)
if d:GetDamage() > 0 then
ent:TakeDamageInfo(d)
self:EmitSound('physics/metal/metal_barrel_impact_soft'..math.random(1,4)..'.wav')
self:TakeDamage(10)
end
end
end
timer.Simple(0.5, function()
if IsValid(self) then
self.cantdamage = false
end
end)
end
end
function ENT:OnTakeDamage(dmg)
if dmg:GetAttacker():IsPlayer() and dmg:GetAttacker():IsSurvivor() then
return 0
end
self.health = self.health - dmg:GetDamage()
if self.health <= 0 then
self:EmitSound(self.TableProp[self.id].breaksound)
self:Remove()
end
end

View File

@@ -0,0 +1,74 @@
AddCSLuaFile()
ENT.Type = "anim"
ENT.Base = "base_anim"
ENT.PrintName = "Barricade"
ENT.Category = "BWA"
ENT.Spawnable = true
if CLIENT then
function ENT:Think()
if self:GetNWBool('lamp') then
local dlight = DynamicLight( self:EntIndex() )
if ( dlight ) then
dlight.pos = self:GetPos()+Vector(0,0,16)
dlight.r = 200
dlight.g = 200
dlight.b = 255
dlight.brightness = 0.01
dlight.Decay = 1000
dlight.Size = 64
dlight.DieTime = CurTime() + 0.1
end
end
if ( IsValid( self.lamp ) ) and self:GetNWBool('lamp') then
self.lamp:SetPos( self:GetPos()+Vector(0,0,16) )
self.lamp:SetAngles( self:GetAngles()+Angle(180,0,0) )
self.lamp:Update()
end
end
function ENT:OnRemove()
if ( IsValid( self.lamp ) ) then
self.lamp:Remove()
end
end
function ENT:Initialize()
timer.Simple(1, function()
if self:GetNWBool('lamp') then
local lamp = ProjectedTexture()
self.lamp = lamp
lamp:SetTexture( "effects/flashlight001" )
lamp:SetFarZ( 1024 )
lamp:SetColor(Color(175,175,255,255))
lamp:SetEnableShadows(true)
lamp:SetPos( self:GetPos()+Vector(0,0,16)+self:GetForward()*32 )
lamp:SetAngles( self:GetAngles()+Angle(180,0,0) )
lamp:SetNearZ(8)
lamp:Update()
end
end)
end
hook.Add("HUDPaint", "HPBarricadeFS", function()
local ent = LocalPlayer():GetEyeTrace().Entity
if IsValid(ent) then
local bool = ent:GetClass() == "sur_barricade"
if bool then
local pos = ent:WorldSpaceCenter():ToScreen()
local tab = {
w = 200,
h = 20,
}
surface.SetDrawColor(0,0,0,200)
surface.DrawRect(pos.x-tab.w/2, pos.y-tab.h/2, tab.w, tab.h)
surface.SetDrawColor(25,125,25)
surface.DrawRect(pos.x-tab.w/2+4, pos.y-tab.h/2+2, (tab.w-8)*(ent:Health('health')/ent:GetNWFloat('healthmax')), tab.h-4)
draw.SimpleText("Barricade", "SuR_SmallFont1", pos.x, pos.y-20, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
draw.SimpleText(math.floor(ent:Health()).."/"..math.floor(ent:GetNWFloat('healthmax')), "Trebuchet18", pos.x, pos.y, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
end
end)
end

View File

@@ -0,0 +1,311 @@
include("shared.lua")
AddCSLuaFile("shared.lua")
function ENT:Initialize()
self:SetModel("models/exfil/palfa.mdl")
self:SetSolid(SOLID_VPHYSICS)
self:PhysicsInit(SOLID_VPHYSICS)
self:SetBodygroup(1, 1)
self:SetBodygroup(2, 1)
self.DeltaTime = 0
self.PickingTime = 0
self.MaxSpeed = 10000
self.CurrentSpeed = 10000
self.Mayday = false
self.Heli = true
local phys = self:GetPhysicsObject()
phys:Wake()
phys:EnableCollisions(false)
if !istable(self.Points) or #self.Points < 5 then
self:Remove()
return
end
---CREW MODELS---
if self.Heli then
local crew = ents.Create("base_anim")
crew:SetModel("models/exfil/mw22_crew_pm.mdl")
crew:SetPos(self:GetPos()+self:GetForward()*234+self:GetRight()*28+self:GetUp()*-172)
crew:SetAngles(self:GetAngles())
crew:Spawn()
crew:SetParent(self)
crew:ResetSequence("sit")
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_R_Upperarm"), Angle(20, -60, 0), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_R_Forearm"), Angle(-45, 30, 0), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_R_Hand"), Angle(-140, 90, -30), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_R_Calf"), Angle(0, -55, 0), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_L_Calf"), Angle(0, -55, 0), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_R_Foot"), Angle(0, 20, 0), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_L_Foot"), Angle(0, 20, 0), true)
self:DeleteOnRemove(crew)
local crew = ents.Create("base_anim")
crew:SetModel("models/exfil/mw22_crew_pm.mdl")
crew:SetPos(self:GetPos()+self:GetForward()*234-self:GetRight()*28+self:GetUp()*-172)
crew:SetAngles(self:GetAngles())
crew:Spawn()
crew:SetParent(self)
crew:ResetSequence("sit")
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_R_Upperarm"), Angle(20, -60, 0), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_R_Forearm"), Angle(-45, 30, 0), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_R_Hand"), Angle(-140, 90, -30), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_R_Calf"), Angle(0, -55, 0), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_L_Calf"), Angle(0, -55, 0), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_R_Foot"), Angle(0, 20, 0), true)
crew:ManipulateBoneAngles(crew:LookupBone("ValveBiped.Bip01_L_Foot"), Angle(0, 20, 0), true)
self:DeleteOnRemove(crew)
else
end
-----------------
self:SetPos(self.Points[1].pos)
self:SetAngles(self.Points[1].ang)
self.CurrentPoint = 2
end
function ENT:GetPlayersInHeli()
local tab = {}
for _, ent in pairs(ents.FindInSphere(self:GetPos(), 500)) do
if ent:IsPlayer() and ent:IsSurvivor() then
local tr = util.TraceLine({
start = ent:GetPos()+Vector(0,0,4),
entpos = ent:GetPos()-Vector(0,0,32),
filter = ent,
})
if tr.Entity == self or ent:GetGroundEntity() == self then
tab[#tab+1] = ent
else
continue
end
end
end
return tab
end
function ENT:Exfil()
for _, ent in ipairs(self:GetPlayersInHeli()) do
ent:GodEnable()
end
self.Skipping = false
self.Exfilling = true
self.DamageLine = CurTime()+10
self.CurrentPoint = self.CurrentPoint+1
local num = #self:GetPlayersInHeli()
if num == 0 then
SuR:PlaySoundOnClient("surrounded/other/pilot1/helinone_0"..math.random(1,3)..".mp3")
elseif num == SuR:CurrentFighters(true) then
SuR:PlaySoundOnClient("surrounded/other/pilot1/helileave_0"..math.random(1,3)..".mp3")
else
SuR:PlaySoundOnClient("surrounded/other/pilot1/helisome_0"..math.random(1,3)..".mp3")
end
timer.Simple(0.01, function()
if !IsValid(self) then return end
local phys = self:GetPhysicsObject()
if !IsValid(phys) then return end
phys:EnableMotion(true)
phys:AddVelocity(Vector(0,0,1))
end)
end
function ENT:Complete()
self.Skipping = true
if #self:GetPlayersInHeli() > 0 then
SuR.ExfilSuccess = true
for _, ply in ipairs(self:GetPlayersInHeli()) do
ply.ExfilItems = {
main = ply:GetNWString('MainWeapon'),
sec = ply:GetNWString('SecWeapon'),
melee = ply:GetNWString('MeleeWeapon'),
extra = ply:GetNWString('OtherWeapon'),
bandages = ply:GetNWFloat('Bandages'),
sprays = ply:GetNWFloat('Sprays'),
}
ply:AddXP(SuR.Config.XP_Giving["evac_success"])
end
end
for _, ply in ipairs(player.GetAll()) do
if table.HasValue(self:GetPlayersInHeli(), ply) then
ply:KillSilent()
ply:ScreenFade(SCREENFADE.IN, color_black, 1, 1)
else
ply:SuR_MakeZombie()
end
end
if IsValid(self.CallEnt) then
self.CallEnt:SetNWBool('Ready', true)
end
hook.Call("SuR.ExfilFinished", nil, SuR.ExfilSuccess)
end
function ENT:KillNPC()
for _, ent in pairs(ents.FindInSphere(self:GetPos(), 400)) do
if ent:IsNPC() or ent:IsPlayer() and ent:IsZombie() then
ent:TakeDamage(100)
self:EmitSound("physics/metal/metal_barrel_impact_soft"..math.random(1,4)..".wav", 70, math.random(80,120))
if not self.DamageLine or self.DamageLine < CurTime() then
self.DamageLine = CurTime()+9
SuR:PlaySoundOnClient("surrounded/other/pilot1/helihurt_0"..math.random(1,3)..".mp3")
end
end
end
end
hook.Add("SuR.Helo_Exfil_Reached", "SuR_FixExfil", function(heli, point)
if point == 2 then
heli:GetPhysicsObject():EnableCollisions(true)
heli.PickingTime = CurTime()+heli.WaitTime-4
heli.DamageLine = CurTime()+12
SuR:Countdown(heli.WaitTime)
if heli.LastExfil then
SuR:PlaySoundOnClient("surrounded/other/pilot1/gashurry"..math.random(1,4)..".mp3")
else
SuR:PlaySoundOnClient("surrounded/other/pilot1/helihere_0"..math.random(1,3)..".mp3")
end
timer.Create("HeliExfilVoice1"..heli:EntIndex(), 8, 1, function()
if !IsValid(heli) then return end
SuR:PlaySoundOnClient("surrounded/other/pilot1/heligather_0"..math.random(1,3)..".mp3")
end)
timer.Create("HeliExfil"..heli:EntIndex(), heli.WaitTime-4, 1, function()
if !IsValid(heli) then return end
if heli.Heli then
heli:EmitSound("surrounded/vehicles/palfa/engine_start.wav")
else
heli:EmitSound("surrounded/vehicles/van/engine_start.wav")
end
timer.Simple(4, function()
if !IsValid(heli) then return end
heli:Exfil()
end)
end)
elseif point == 4 then
heli:Complete()
heli:GetPhysicsObject():EnableCollisions(false)
end
end)
function ENT:PhysicsCollide(col, data)
if self.Mayday then
self.Disabled = true
if self.Heli then
self:StopSound("surrounded/vehicles/palfa/engine_idle.wav")
else
self:StopSound("surrounded/vehicles/van/engine_idle.wav")
end
end
local tar = col.HitEntity
if self.CurrentPoint == 3 and tar:IsWorld() then
local phys = self:GetPhysicsObject()
if IsValid(phys) then
phys:EnableMotion(false)
end
end
end
function ENT:Think()
local phys = self:GetPhysicsObject()
if self.Disabled then return end
---ROTOR PART---
local bone = 63
self:ManipulateBoneAngles(bone, self:GetManipulateBoneAngles(bone)+Angle(0,10,0))
local bone = self:LookupBone("tag_tail_rotor_rot")
self:ManipulateBoneAngles(bone, self:GetManipulateBoneAngles(bone)+Angle(0,10,0))
----------------
---MOVE PART---
local point = self.Points[self.CurrentPoint]
self.CurrentSpeed = math.min(self.CurrentSpeed+FrameTime()/0.01, self.MaxSpeed)
if point.pos:Distance(self:GetPos()) < point.dist and (not point.wait or self.Skipping) then
hook.Run("SuR.Helo_Exfil_Reached", self, self.CurrentPoint)
timer.Simple(0.01, function()
if !IsValid(phys) then return end
phys:EnableMotion(true)
phys:AddVelocity(Vector(0,0,1))
end)
self.CurrentPoint = self.CurrentPoint+1
if self.CurrentPoint > #self.Points then
self:Remove()
return
end
self.Skipping = false
self.CurrentSpeed = 0
end
self:KillNPC()
if phys:IsMotionEnabled() then
if self.Mayday then
local tab = {}
tab.secondstoarrive = 1
tab.pos = self:GetPos()-Vector(0,0,100)
tab.angle = self:GetAngles()+Angle(0.01,90,0)
tab.maxangular = 5000
tab.maxangulardamp = 10000
tab.maxspeed = 1000000
tab.maxspeeddamp = 10000
tab.dampfactor = 0.5
tab.teleportdistance = 0
tab.deltatime = CurTime()-self.DeltaTime
phys:ComputeShadowControl(tab)
else
local tab = {}
tab.secondstoarrive = point.sec
tab.pos = point.pos
tab.angle = self:GetAngles()
tab.maxangular = 500
tab.maxangulardamp = 10000
tab.maxspeed = 1000000
tab.maxspeeddamp = 10000
tab.dampfactor = point.damp
tab.teleportdistance = 0
tab.deltatime = CurTime()-self.DeltaTime
phys:ComputeShadowControl(tab)
local tab = {}
tab.secondstoarrive = point.sec/5
if point.smoothrotate then
tab.secondstoarrive = point.sec
end
tab.pos = self:GetPos()
tab.angle = point.ang
tab.maxangular = 5000
tab.maxangulardamp = 10000
tab.maxspeed = 0
tab.maxspeeddamp = 0
tab.dampfactor = point.damp
tab.teleportdistance = 0
tab.deltatime = CurTime()-self.DeltaTime
phys:ComputeShadowControl(tab)
local vel = phys:GetVelocity()
vel.x = math.Clamp(vel.x, -self.CurrentSpeed, self.CurrentSpeed)
vel.y = math.Clamp(vel.y, -self.CurrentSpeed, self.CurrentSpeed)
vel.z = math.Clamp(vel.z, -self.CurrentSpeed, self.CurrentSpeed)
phys:SetVelocity(vel)
end
end
--------------
self.DeltaTime = CurTime()
self:NextThink(CurTime())
return true
end

View File

@@ -0,0 +1,72 @@
AddCSLuaFile()
ENT.Base = "base_gmodentity"
ENT.Type = "anim"
ENT.PrintName = "Exfil Vehicle"
ENT.Spawnable = true
ENT.AutomaticFrameAdvance = true
if CLIENT then
function ENT:OnRemove()
if self:GetModel() == "models/exfil/deliveryvan_armored_driveable.mdl" then
self:StopSound("surrounded/vehicles/van/engine_idle.wav")
else
self:StopSound("surrounded/vehicles/palfa/engine_idle.wav")
end
end
function ENT:Initialize()
if self:GetModel() == "models/exfil/deliveryvan_armored_driveable.mdl" then
self:EmitSound("surrounded/vehicles/van/engine_idle.wav", 100, 95, 1, CHAN_STATIC)
else
self:EmitSound("surrounded/vehicles/palfa/engine_idle.wav", 100, 95, 1, CHAN_STATIC)
end
end
function ENT:Think()
local dlight = DynamicLight(self:EntIndex())
if dlight then
dlight.pos = self:GetPos()-Vector(0,0,128)
dlight.r = 255
dlight.g = 255
dlight.b = 200
dlight.brightness = 2
dlight.decay = 1000
dlight.size = 1000
dlight.dietime = CurTime() + 1
end
end
local exfil_icon = Material("surrounded/exfil.png")
local last_exfil_icon = Material("surrounded/lastexfil.png")
net.Receive("SuR.ExfilIcon", function()
local bool = net.ReadBool()
local alpha = 0
local hide = false
timer.Simple(8, function()
hide = true
end)
local text = SuR.Language["evac_start"]
local mat = exfil_icon
if bool then
text = SuR.Language["evac_last_start"]
mat = last_exfil_icon
end
hook.Add("HUDPaint", "SuR_Exfil_Info", function()
if hide then
alpha = math.Clamp(alpha-FrameTime()/0.002, 0, 255)
if alpha <= 0 then
hook.Remove("HUDPaint", "SuR_Exfil_Info")
end
else
alpha = math.Clamp(alpha+FrameTime()/0.002, 0, 255)
end
surface.SetDrawColor(255,255,255,alpha)
surface.SetMaterial(mat)
surface.DrawTexturedRect(ScrW()/2-We(100), ScrH()/2-He(350), We(200), He(200))
draw.SimpleText(text, "SuR_SmallFont2", ScrW()/2, ScrH()/2-He(140), Color(255,255,255,alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
end)
end)
end

View File

@@ -0,0 +1,54 @@
include("shared.lua")
AddCSLuaFile("shared.lua")
function ENT:Initialize()
self:SetModel("models/hunter/blocks/cube025x025x025.mdl")
self:SetNoDraw(true)
self:DrawShadow(false)
self:SetNWBool('Ready', true)
if !istable(DMZ_ExfilPoints[game.GetMap()][self.ID]) then
self:Remove()
return
end
self:SetPos(DMZ_ExfilPoints[game.GetMap()][self.ID]["Main"])
end
hook.Add("PlayerButtonDown", "DMZ_Exfil", function(ply, but)
local ent = nil
for _, en in ipairs(ents.FindInSphere(ply:GetPos(), 500)) do
if en:GetClass() == "dmz_exfil_point" then
ent = en
break
end
end
if IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():GetClass() == "agrp_flare_gun" then
if but == KEY_G and IsValid(ent) and ent:GetNWBool('Ready') then
ply:GetActiveWeapon():Remove()
CallExfil(ent, ply)
end
end
end)
function CallExfil(ent, ply)
ent:EmitSound("weapons/flaregun/fire.wav")
ent:SetNWBool('Ready', false)
net.Start("DMZ_Exfil_Info")
net.Send(ply)
BroadcastLua([[
local part = EffectData()
part:SetOrigin(Entity(]]..ply:EntIndex()..[[):GetPos()+Vector(0,0,100))
util.Effect("dmz_signal_rocket", part)
]])
local he = ents.Create("dmz_exfil_helo")
he.Caller = ply
he.Points = DMZ_ExfilPoints[game.GetMap()][ent.ID]
he.CallEnt = ent
timer.Simple(30, function()
if !IsValid(he) then return end
he:Spawn()
end)
end

View File

@@ -0,0 +1,63 @@
AddCSLuaFile()
ENT.Base = "base_gmodentity"
ENT.Type = "anim"
ENT.PrintName = "Exfil Point"
ENT.Spawnable = true
ENT.AutomaticFrameAdvance = true
if CLIENT then
local exfil_icon = Material("dmz/exfil.png", "smooth")
hook.Add("HUDPaint", "DMZ_Exfil_Point", function()
if IsValid(LocalPlayer():GetActiveWeapon()) and LocalPlayer():GetActiveWeapon():GetClass() == "agrp_flare_gun" then
for _, ent in ipairs(ents.FindByClass("dmz_exfil_point")) do
if not ent.alpha then
ent.alpha = 0
end
if ent:GetNWBool('Ready') then
local pos = ent:GetPos():ToScreen()
surface.SetDrawColor(255,255,255,ent.alpha)
surface.SetMaterial(exfil_icon)
surface.DrawTexturedRect(pos.x-36, pos.y-48, 72, 72)
local num = math.Round(LocalPlayer():GetPos():Distance(ent:GetPos()) * 2/100)
if num < 10 or num > 500 then
ent.alpha = math.Clamp(ent.alpha-FrameTime()/0.005, 0, 255)
else
ent.alpha = math.Clamp(ent.alpha+FrameTime()/0.005, 0, 255)
end
if num < 10 then
draw.SimpleText("[G] Вызвать эвакуацию", "GModToolSubtitle", ScrW()/2-20, ScrH()/2+150, color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
end
draw.SimpleText(num.."m", "Trebuchet24", pos.x, pos.y+12, Color(255,255,255,ent.alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
end
end
end
end)
net.Receive("DMZ_Exfil_Info", function()
local alpha = 0
local hide = false
timer.Simple(5, function()
hide = true
end)
hook.Add("HUDPaint", "DMZ_Exfil_Info", function()
if hide then
alpha = math.Clamp(alpha-FrameTime()/0.001, 0, 255)
if alpha <= 0 then
hook.Remove("HUDPaint", "DMZ_Exfil_Info")
end
else
alpha = math.Clamp(alpha+FrameTime()/0.001, 0, 255)
end
surface.SetDrawColor(255,255,255,alpha)
surface.SetMaterial(exfil_icon)
surface.DrawTexturedRect(ScrW()/2-64, ScrH()/2-270, 128, 128)
draw.SimpleText("ЭВАКУАЦИОННЫЙ ВЕРТОЛЕТ ВЫЛЕТЕЛ", "DermaLarge", ScrW()/2, ScrH()/2-150, Color(255,255,255,alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
end)
end)
end

View File

@@ -0,0 +1,92 @@
AddCSLuaFile()
ENT.PrintName = "Gas Zone"
ENT.Base = "base_anim"
if SERVER then
function ENT:Initialize()
self:SetModel("models/hunter/blocks/cube025x025x025.mdl")
self:SetNoDraw(true)
self:SetNWFloat('radius', 1)
self.DelayGasDamage = 0
self.Dist = self.Dist or 5000
end
function ENT:Think()
local newnum = self:GetNWFloat('radius')+(self.Dist/120/10)
self:SetNWFloat('radius', newnum)
if self.DelayGasDamage < CurTime() then
self.DelayGasDamage = CurTime()+1
local tab = player.GetAll()
for i=1,#tab do
local ply = tab[i]
if ply:GetPos():DistToSqr(self:GetPos()) > self:GetNWFloat('radius')^2 or !ply:Alive() then continue end
if ply:Health() > 5 then
ply:TakeDamage(5, self)
else
ply:SuR_MakeZombie()
end
ply:PlayVoiceLine("infected", 20)
end
end
self:NextThink(CurTime()+0.1)
return true
end
else
local function create_particle(self)
local size = math.Clamp(math.random(self:GetNWFloat('radius')/2,self:GetNWFloat('radius')), 10, self:GetNWFloat('radius')/2)
local rad = self:GetNWFloat('radius')-size/2
if not self.gasEmitter then
self.gasEmitter = ParticleEmitter(self:GetPos())
end
local particles = self.gasEmitter:Add("particle/particle_smokegrenade", self:GetPos() + VectorRand(-rad, rad))
particles:SetVelocity(Vector(0, 0, 0))
particles:SetDieTime(10)
particles:SetStartAlpha(200)
particles:SetEndAlpha(0)
particles:SetStartSize(size)
particles:SetEndSize(size)
particles:SetRoll(math.Rand(-180, 180))
particles:SetRollDelta(math.Rand(-0.5, 0.5))
particles:SetColor(0,50,0)
end
local alpha = 0
local draw_gas_effect = false
hook.Add("PostDrawTranslucentRenderables", "SuR_Zone_Draw", function()
local tab = ents.FindByClass("sur_gas_zone")
for _, ent in ipairs(tab) do
render.SetColorMaterial()
render.CullMode(1)
render.DrawSphere(ent:GetPos(), ent:GetNWFloat('radius'), 50 , 50 , Color(0,120,0,20))
render.CullMode(0)
render.DrawSphere(ent:GetPos(), ent:GetNWFloat('radius'), 50 , 50 , Color(0,120,0,20))
render.BorderSphereUnit(Color(0,120,0,200), ent:GetPos(), ent:GetNWFloat('radius'), 64, 16)
if not ent.Gas or ent.Gas < CurTime() then
ent.Gas = CurTime()+0.01
create_particle(ent)
end
draw_gas_effect = ent:GetPos():DistToSqr(LocalPlayer():GetPos()) <= ent:GetNWFloat('radius')^2 and LocalPlayer():Alive()
end
if #tab == 0 then
draw_gas_effect = false
alpha = 0
end
end)
hook.Add("HUDPaint", "SuR_Zone_Draw", function()
if draw_gas_effect then
alpha = math.min(alpha+FrameTime()/0.002, 200)
else
alpha = math.max(alpha-FrameTime()/0.002, 0)
end
surface.SetDrawColor(0,80,0,alpha)
surface.DrawRect(0,0,ScrW(),ScrH())
end)
end

View File

@@ -0,0 +1,48 @@
AddCSLuaFile()
ENT.Base = "base_gmodentity"
ENT.Type = "anim"
ENT.PrintName = "Generator"
if SERVER then
function ENT:Initialize()
self:SetModel("models/surrounded/obj/w_QuestGenerator.mdl")
self:PhysicsInit(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetUseType(SIMPLE_USE)
self.FuelAmount = 0
self:SetNWBool('HaveFuel', false)
end
function ENT:Fuel()
if self:GetNWBool('HaveFuel') then return end
self.FuelAmount = self.FuelAmount + 1
SuR.ObjectiveFuel = SuR.ObjectiveFuel + 1
if SuR.ObjectiveFuel >= SuR.ObjectiveFuelNeed then
SuR:MessageOnClient(20)
timer.Simple(15, function()
SuR:StartObjectiveExfil()
end)
end
if self.FuelAmount >= self.ToFuel then
self:SetNWBool('HaveFuel', true)
self.loop = self:StartLoopingSound("ambient/machines/diesel_engine_idle1.wav")
end
end
function ENT:OnRemove()
if isnumber(self.loop) then
self:StopLoopingSound(self.loop)
end
end
function ENT:Think()
local phys = self:GetPhysicsObject()
if IsValid(phys) then
phys:EnableMotion(false)
end
end
end

View File

@@ -0,0 +1,44 @@
AddCSLuaFile()
ENT.Base = "base_gmodentity"
ENT.Type = "anim"
ENT.PrintName = "Landmine"
ENT.Spawnable = true
function ENT:Initialize()
self:SetModel("models/surrounded/equipment/fieldupgrade_proximitymine.mdl")
self:SetSolid(SOLID_VPHYSICS)
self:PhysicsInit(SOLID_VPHYSICS)
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS_TRIGGER)
timer.Simple(2, function()
if !IsValid(self) then return end
self:SetAngles(Angle(0,self:GetAngles().y,0))
end)
end
function ENT:Think()
if CLIENT then return end
if not self.Done then
for _, ent in ipairs(ents.FindInSphere(self:GetPos(), 72)) do
if ent:IsNPC() and ent.IsZombie then
self.Done = true
self:GetPhysicsObject():SetVelocity(Vector(0,0,256))
timer.Simple(0.7, function()
local effectData = EffectData()
effectData:SetOrigin(self:GetPos())
util.Effect("Explosion", effectData)
util.BlastDamage(self, self, self:GetPos(), 192, 512)
self:Remove()
end)
end
end
end
self:NextThink(CurTime())
return true
end

View File

@@ -0,0 +1,129 @@
AddCSLuaFile()
ENT.Base = "base_gmodentity"
ENT.Type = "anim"
ENT.PrintName = "Loot"
if SERVER then
function ENT:Initialize()
if not self.LootType and not self.Weapon then
self:Remove()
return
end
local type_set = 2
local tab = LootItems[self.LootType]
if istable(self.Weapon) then
tab = self.Weapon
self:SetNWBool('Weapon', true)
local cl = tab.class
if cl then
local t = SuR.Config.TierWeapons
if table.HasValue(t["Tier1"], cl) then
type_set = 1
elseif table.HasValue(t["Tier3"], cl) or table.HasValue(t["Other"], cl) then
type_set = 3
elseif table.HasValue(t["Tier4"], cl) then
type_set = 4
elseif table.HasValue(t["Tier5"], cl) then
type_set = 5
end
end
end
if tab.tier then
type_set = tab.tier
end
self.FuncUse = tab.usefunc
self:SetNWFloat("Type", type_set)
self:SetNWString("LootName", tab.name)
self:SetModel(tab.model)
self:PhysicsInit(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetUseType(SIMPLE_USE)
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS_TRIGGER)
local phys = self:GetPhysicsObject()
if IsValid(phys) then
phys:EnableMotion(true)
phys:Wake()
end
timer.Simple(SuR.Config.Loot_Remove_Delay, function()
if !IsValid(self) or self.NoRemove then return end
self:Remove()
end)
end
function ENT:Use(ply)
if not istable(self.Weapon) then
if !IsValid(ply.LastPickupWeapon) then
ply.LastPickupWeapon = ply:GetActiveWeapon()
end
ply:SetActiveWeapon(nil)
timer.Create("PlyTakeAnim"..ply:EntIndex(), 1.5, 1, function()
if !IsValid(ply) or !IsValid(ply.LastPickupWeapon) then return end
local class = ply.LastPickupWeapon:GetClass()
ply:SelectWeapon(class)
ply.LastPickupWeapon = nil
end)
end
if istable(self.Weapon) then
if self.Weapon.class and ply:HasWeapon(self.Weapon.class) then return end
self.Weapon.usefunc(self, ply)
if self.Weapon.class then
ply:SelectWeapon(self.Weapon.class)
end
if self.Weapon.class == "sur_hammer" then
SuR:ShowTips("hammer", ply)
end
else
self.FuncUse(self, ply)
SuR:ShowTips("items", ply)
end
local dif = self:GetPos().z-ply:GetPos().z
if dif > 30 then
ply:SetSVAnimation("sur_itemgrab_normal", true, true)
elseif dif > 15 then
ply:SetSVAnimation("sur_itemgrab_crouch", true, true)
else
ply:SetSVAnimation("sur_itemgrab_floor", true, true)
end
ply:DropButtons()
ply:EmitSound("items/ammo_pickup.wav", 70)
ply:PlayVoiceLine("pickup")
self:Remove()
end
else
local arrow = Material('surrounded/arrow.png')
hook.Add("PostDrawTranslucentRenderables", "LootShow", function()
for _, self in ipairs(ents.FindByClass("sur_loot")) do
local angle = EyeAngles()
angle = Angle(angle.x, angle.y, 0)
angle:RotateAroundAxis(angle:Up(), -90)
angle:RotateAroundAxis(angle:Forward(), 90)
cam.Start3D2D(self:GetPos()+Vector(0,0,24+(math.cos(CurTime())*2)), angle, 0.1)
surface.SetMaterial(arrow)
surface.SetDrawColor(255,255,255)
surface.DrawTexturedRect(-32,16,64,64)
local loot = self:GetNWString("LootName", "")
local type = self:GetNWFloat("Type")
local name = SuR.Language[loot]
if not name then
name = loot
end
draw.SimpleText(name, "SuR_SmallFont2", 0, 0, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
if type > 0 and SuR.Config.Tier_Colors[type] then
draw.SimpleText(SuR.Language["loot_tier"..type], "SuR_SmallFont1", 0, 20, SuR.Config.Tier_Colors[type], TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
cam.End3D2D()
end
end)
end

View File

@@ -0,0 +1,300 @@
AddCSLuaFile()
ENT.Base = "base_gmodentity"
ENT.Type = "anim"
ENT.PrintName = "MI24"
ENT.AutomaticFrameAdvance = true
ENT.Spawnable = true
if SERVER then
function ENT:Initialize()
self:SetModel("models/surrounded/mi24d.mdl")
self:SetHealth(50000)
self.Velo = {x = 0, y = 0}
self:SetSolid(SOLID_VPHYSICS)
self:PhysicsInit(SOLID_VPHYSICS)
self.MultSpeed = 100
self.MaxSpeed = 100
self.Height = SuR.Config.Height_Of_Air
self.Smoking = false
self.DisableThinkPart = false
self.CantBeDamaged = true
self.RocketDelay = CurTime() + 10
self.FireDelay = CurTime() + 1
self.SeekDelay = CurTime() + 2
self.ControlDelay = CurTime() + 1
self:SetNWFloat('RemoveTime', CurTime() + 120)
self.Removing = false
self.Target = nil
self.Team = 1
self.Actions = {
["MoveForward"] = false,
["MoveBack"] = false,
["MoveLeft"] = false,
["MoveRight"] = false,
}
self:SetBodygroup(3, 1)
self:SetBodygroup(4, 1)
self:ManipulateBoneScale(10, Vector(0,0,0))
self:ManipulateBoneScale(11, Vector(0,0,0))
self:ManipulateBoneScale(7, Vector(0,0,0))
self:ManipulateBoneAngles(5, Angle(0,40,0))
timer.Simple(1, function()
if !IsValid(self) then return end
self:EmitSound("ambient/levels/streetwar/heli_distant1.wav", 90, 90, 1)
end)
self:PlaySeq("arrive", 5, function()
self:EmitSound(")npc/attack_helicopter/aheli_rotor_loop1.wav", 90, 90, 1)
end)
end
function ENT:PlaySeq(name, long, onfinish)
self:SetCycle(0)
self:ResetSequence(name)
self.CantBeDamaged = true
self:SetNotSolid(true)
if !isfunction(onfinish) then
onfinish = function() end
end
timer.Create("MI24Anim"..self:EntIndex(), long, 1, function()
if !IsValid(self) then return end
self:ResetSequence("idle")
self:SetNotSolid(false)
self.CantBeDamaged = false
onfinish()
end)
end
function ENT:OnRemove()
self:StopSound(")npc/attack_helicopter/aheli_rotor_loop1.wav")
end
function ENT:GetTurretPos()
local bone = self:GetBonePosition(8)
return bone
end
function ENT:Rockets(angle)
if self.RocketDelay > CurTime() then return end
self.RocketDelay = CurTime()+math.random(15,30)
for i=1,8 do
timer.Simple(i/4, function()
if !IsValid(self) then return end
self:EmitSound(")weapons/rpg/rocketfire1.wav", 90, 90, 1)
local pos1, pos2 = self:GetPos()+self:GetRight()*100, self:GetPos()-self:GetRight()*100
local r = ents.Create("sur_mi24_rocket")
if i%2 == 0 then
r:SetPos(pos1)
else
r:SetPos(pos2)
end
r:SetAngles(angle+AngleRand(-5,5))
r.Heli = self
r:Spawn()
end)
end
end
function ENT:Attack()
local tar = self.Target
if !IsValid(tar) then
local tab = ents.FindInSphere(self:GetPos(), 32000)
table.Shuffle(tab)
for _, ent in ipairs(tab) do
if self:VisibleVec(ent:GetPos()) then
if ent:IsNPC() and ent:GetClass() != "sur_support_npc" and ent:Health() > 0 then
self.Target = ent
break
end
end
end
end
if IsValid(tar) and self.FireDelay < CurTime() then
self.FireDelay = CurTime() + 0.06
if self:AngleToEnemy(tar) < 45 and self.SeekDelay < CurTime() then
local dir = (tar:WorldSpaceCenter()-self:GetTurretPos()):GetNormalized()
local ang1 = (tar:WorldSpaceCenter()-self:GetPos()):GetNormalized():Angle()
self:Rockets(ang1)
self:EmitSound("weapons/ar2/fire1.wav", 90, 80, 1, CHAN_WEAPON)
self:FireBullets({
IgnoreEntity = self,
Spread = VectorRand(-0.06, 0.06),
Damage = 30,
Dir = dir,
Src = self:GetTurretPos(),
})
end
if not self:VisibleVec(tar:GetPos()) or tar:Health() <= 0 then
self.ControlDelay = CurTime() + 4
self.SeekDelay = CurTime() + 0.5
self.Target = nil
end
end
end
function ENT:AngleToEnemy(enemy)
local selfAngles = self:GetAngles()
local enemyPos = enemy:GetPos()
local angleToEnemy = (enemyPos - self:GetPos()):Angle()
angleToEnemy.x = 0
angleToEnemy.z = 0
local diff = math.AngleDifference(angleToEnemy.y, selfAngles.y)
return math.abs(diff)
end
function ENT:RotateToEntity(ent2, divisor)
local ent1Angles = self:GetAngles()
local targetAngles = (ent2:GetPos() - self:GetPos()):Angle()
local yawDiff = math.NormalizeAngle(targetAngles.y - ent1Angles.y)
self:SetAngles(Angle(0, ent1Angles.y + yawDiff / divisor, 0))
end
function ENT:Controls()
local tar = self.Target
if IsValid(tar) then
if self.ControlDelay < CurTime() then
self.ControlDelay = CurTime() + math.Rand(1,5)
self.Actions = {
["MoveForward"] = math.random(1,2) == 1,
["MoveBack"] = math.random(1,6) == 1,
["MoveLeft"] = math.random(1,4) == 1,
["MoveRight"] = math.random(1,4) == 1,
}
end
self:RotateToEntity(tar, 75)
else
if self.ControlDelay < CurTime() then
self.Actions = {
["MoveForward"] = false,
["MoveBack"] = false,
["MoveLeft"] = false,
["MoveRight"] = false,
}
end
end
end
function ENT:Think()
local mu = self.MultSpeed
local ms = self.MaxSpeed
local vel = self:GetPhysicsObject():GetVelocity()
vel.z = 0
if not self.DisableThinkPart then
if not self.CantBeDamaged then
self:Attack()
self:Controls()
self:GetPhysicsObject():SetVelocity(-vel+self:GetForward()*self.Velo.x+self:GetRight()*self.Velo.y)
end
local pos = self:GetPos()
self:SetPos(Vector(pos.x, pos.y, self.Height))
local ang = self:GetAngles().y
self:SetAngles(Angle(0,ang,0))
if self.Actions["MoveRight"] then
self.Velo.x = math.Clamp(self.Velo.x+FrameTime()*mu, -ms, ms)
elseif self.Actions["MoveLeft"] then
self.Velo.x = math.Clamp(self.Velo.x-FrameTime()*mu, -ms, ms)
end
if self.Actions["MoveForward"] then
self.Velo.y = math.Clamp(self.Velo.y-FrameTime()*mu, -ms, ms)
elseif self.Actions["MoveBack"] then
self.Velo.y = math.Clamp(self.Velo.y+FrameTime()*mu, -ms, ms)
end
if not self.Actions["MoveLeft"] and not self.Actions["MoveRight"] then
if self.Velo.x > 5 or self.Velo.x < -5 then
if self.Velo.x > 0 then
self.Velo.x = math.Clamp(self.Velo.x-FrameTime()*mu, -ms, ms)
elseif self.Velo.x < 0 then
self.Velo.x = math.Clamp(self.Velo.x+FrameTime()*mu, -ms, ms)
end
else
self.Velo.x = 0
end
end
if not self.Actions["MoveForward"] and not self.Actions["MoveBack"] then
if self.Velo.y > 5 or self.Velo.y < -5 then
if self.Velo.y > 0 then
self.Velo.y = math.Clamp(self.Velo.y-FrameTime()*mu, -ms, ms)
elseif self.Velo.y < 0 then
self.Velo.y = math.Clamp(self.Velo.y+FrameTime()*mu, -ms, ms)
end
else
self.Velo.y = 0
end
end
if self:GetNWFloat('RemoveTime') < CurTime() and not self.Removing and not self.DisableThinkPart then
self.Removing = true
self:EmitSound("ambient/levels/streetwar/heli_distant1.wav", 90, 90, 1)
self:StopSound("npc/attack_helicopter/aheli_rotor_loop1.wav")
self:PlaySeq("finish", 8, function()
self:StopSound("npc/attack_helicopter/aheli_rotor_loop1.wav")
self:Remove()
end)
end
if self:Health() <= 1000 and not self.Smoking then
self.Smoking = true
ParticleEffectAttach("Rocket_Smoke_Trail", 4, self, 2)
end
if self:Health() <= 0 then
self:DestroyHeli()
end
end
self:ManipulateBoneAngles(0, Angle(0,(math.sin(CurTime())*4),(math.sin(CurTime()*2)*4)))
self:ManipulateBonePosition(0, Vector(0,0,(math.sin(CurTime())*10)))
self:NextThink(CurTime())
return true
end
function ENT:OnTakeDamage(dmgt)
if self.CantBeDamaged then return end
local dmg = dmgt:GetDamage()
local att = dmgt:GetAttacker()
if att != self or att:IsPlayer() and att:Team() != self.Team then
self:SetHealth(self:Health()-dmg)
if IsValid(self:GetCreator()) then
self:GetCreator():ViewPunch(AngleRand(-1,1))
self:EmitSound("physics/metal/metal_box_impact_bullet"..math.random(1,3)..".wav")
end
end
end
function ENT:DestroyHeli()
self.DisableThinkPart = true
self.DestroyVelocity = 2500
self:EmitSound("tdmg/mi24/spindown.wav")
self.PhysicsCollide = function(self)
ParticleEffect("explosion_huge_h", self:GetPos()+Vector(0,0,32), Angle(0,0,0))
self:EmitSound("tdmg/a10_explosion.wav", 0)
self:StopSound("tdmg/mi24/spindown.wav")
self:Remove()
end
self.Think = function(self)
local RPM = self.DestroyVelocity
local p = self:GetPhysicsObject()
if IsValid(p) then
local angvel = p:GetAngleVelocity()
p:AddAngleVelocity(Vector(angvel.x > 100 and 0 or RPM*0.01,0,angvel.z > 200 and 0 or math.Clamp(RPM,0,4000)*0.04))
local vel = p:GetVelocity()
p:SetVelocity(-vel-Vector(0,0,750))
end
self:NextThink(CurTime())
return true
end
end
end

View File

@@ -0,0 +1,44 @@
AddCSLuaFile()
ENT.Base = "base_gmodentity"
ENT.Type = "anim"
ENT.PrintName = "MI24 Rocket"
ENT.AutomaticFrameAdvance = true
ENT.Spawnable = true
if SERVER then
function ENT:Initialize()
self:SetModel("models/props_phx/amraam.mdl")
self:SetSolid(SOLID_VPHYSICS)
self:PhysicsInit(SOLID_VPHYSICS)
self:SetModelScale(0.5, 0)
end
function ENT:PhysicsCollide(data, col)
self:Explode()
end
function ENT:Explode()
if self.Exploded then return end
self.Exploded = true
if IsValid(self.Heli) then
util.BlastDamage(self.Heli, self.Heli, self:GetPos(), 200, 200)
else
util.BlastDamage(self, self, self:GetPos(), 200, 100)
end
self:EmitSound(")ambient/explosions/explode_4.wav", 100, math.random(60,90))
local eff = EffectData()
eff:SetFlags(4)
eff:SetOrigin(self:GetPos())
util.Effect("Explosion", eff)
self:Remove()
end
function ENT:Think()
local phys = self:GetPhysicsObject()
phys:SetVelocity(-phys:GetVelocity()+self:GetForward()*4000)
self:NextThink(CurTime())
return true
end
end

View File

@@ -0,0 +1,5 @@
include("shared.lua")
function ENT:DrawTranslucent(flags)
self:DrawModel(flags)
end

View File

@@ -0,0 +1,4 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")

View File

@@ -0,0 +1,165 @@
ENT.Base = "base_gmodentity"
ENT.Type = "anim"
ENT.PrintName = "Helicoper"
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
ENT.Model = Model("models/tdmg/heli.mdl")
ENT.AutomaticFrameAdvance = true
function ENT:Initialize()
self:SetModel(self.Model)
if SERVER then
self:SetHealth(1)
self:SetPos(self:GetPos() + Vector(0, 0, 10))
local tr = {
start = self:GetPos(),
endpos = self:GetPos() + Vector(0, 0, 512)
}
if tr.HitSky then
self:SetAngles(Angle(0, math.Rand(0, 360), 0))
else
local testpos = self:GetPos() + Vector(0, 0, 512)
local amt = 15
local best = 0
local best_dist = math.huge
local offset = math.Rand(0, 360)
for i = 1, amt do
local angle = math.Rand(0, 360)
local str = util.TraceLine({
start = testpos,
endpos = testpos + Angle(0, angle + offset, 0):Forward() * 10000
})
if str.HitSky then
best = angle
break
elseif str.Fraction == 1 then
best = angle
break
elseif str.Fraction * 10000 > best_dist then
best = angle
best_dist = str.Fraction * 10000
end
end
self:SetAngles(Angle(0, best + offset + 180 - 10, 0))
self:SetPos(self:LocalToWorld(-Vector(107.472321, -70.542793, 0)))
end
end
timer.Simple(14, function()
if !IsValid(self) then return end
self:Finish()
end)
timer.Simple(31.6, function()
if !IsValid(self) then return end
self:SetRenderFX(kRenderFxFadeSlow)
end)
timer.Simple(36.6, function()
if !IsValid(self) then return end
if SERVER then
self:Remove()
end
end)
if CLIENT then return end
self:ResetSequence("spawn")
self.mod1, self.mod1_1 = self:CreateSoldierModel(1)
self.mod2, self.mod2_1 = self:CreateSoldierModel(2)
self.mod3, self.mod3_1 = self:CreateSoldierModel(3)
self.mod4, self.mod4_1 = self:CreateSoldierModel(4)
timer.Simple(11.5, function()
if IsValid(self.mod1) then
self:CreateSoldierNPCFromModel(1)
self.mod1:Remove()
end
end)
timer.Simple(12.5, function()
if IsValid(self.mod2) then
self:CreateSoldierNPCFromModel(2)
self.mod2:Remove()
end
end)
timer.Simple(14, function()
if IsValid(self.mod3) then
self:CreateSoldierNPCFromModel(3)
self.mod3:Remove()
end
end)
end
function ENT:Finish()
if CLIENT then return end
self:SetBodygroup(3, 1)
if IsValid(self.mod4) then
self.mod4:Remove()
end
end
function ENT:CreateSoldierModel(type)
local friend = ents.Create("prop_dynamic")
local friend2 = ents.Create("base_anim")
if type == 1 then
friend:SetModel("models/tdmg/guy01.mdl")
elseif type == 2 then
friend:SetModel("models/tdmg/guy02.mdl")
elseif type == 3 then
friend:SetModel("models/tdmg/guy03.mdl")
elseif type == 4 then
friend:SetModel("models/tdmg/chiefl.mdl")
end
friend:SetPos(self:GetPos())
friend:SetAngles(self:GetAngles())
friend:SetParent(self)
friend:Spawn()
friend:ResetSequence('spawn')
friend2:SetModel("models/player/swat.mdl")
friend2:SetPos(self:GetPos())
friend2:SetAngles(self:GetAngles())
friend2:SetParent(friend)
friend2:AddEffects(1)
friend2:Spawn()
return friend, friend2
end
function ENT:CreateSoldierNPCFromModel(type)
local pos = self:GetPos()
local ang = self:GetAngles()
local bgs = self
if type == 1 then
pos = self:LocalToWorld(Vector(112.3, -73.6, -10))
ang = self.mod1:GetAngles()+Angle(0,180,0)
bgs = self.mod1_1
elseif type == 2 then
pos = self:LocalToWorld(Vector(66.85, -115.5, -10))
ang = self.mod2:GetAngles()+Angle(0,180,0)
bgs = self.mod2_1
elseif type == 3 then
pos = self:LocalToWorld(Vector(73.1, -40.8, -10))
ang = self.mod3:GetAngles()+Angle(0,180,0)
bgs = self.mod3_1
end
local class = "sur_support_npc"
local friend = ents.Create(class)
friend:SetPos(pos)
friend:SetAngles(ang)
friend:Spawn()
end
function ENT:Think()
self:NextThink(CurTime())
return true
end

View File

@@ -0,0 +1,66 @@
AddCSLuaFile()
ENT.Base = "base_gmodentity"
ENT.Type = "anim"
ENT.PrintName = "Loot"
if SERVER then
function ENT:Initialize()
self:SetModel("models/props_junk/wood_crate002a.mdl")
self:PhysicsInit(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetUseType(SIMPLE_USE)
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS_TRIGGER)
local phys = self:GetPhysicsObject()
if IsValid(phys) then
phys:EnableMotion(true)
phys:Wake()
end
end
function ENT:Use(ply)
self:EmitSound("items/ammocrate_open.wav", 70)
ply:PlayVoiceLine("pickup")
if SuR.ActiveMutator != 7 then
for i=1, math.random(4,8) do
local class = SuR:GetRandomClass("loot")
if class != 6 then
local ent = ents.Create("sur_loot")
ent.LootType = class
ent:SetPos(self:WorldSpaceCenter())
ent:SetAngles(AngleRand())
ent:Spawn()
if IsValid(ent:GetPhysicsObject()) then
ent:GetPhysicsObject():SetVelocity(VectorRand(-250,250))
end
end
end
for i=1, math.random(1,2) do
local class = SuR:GetRandomClass("weapon")
local weapon = nil
local tab = weapons.Get(class)
if tab then
weapon = {
name = tab.PrintName,
model = tab.WorldModel,
usefunc = function(self, ply)
ply:Give(class)
end
}
end
local ent = ents.Create("sur_loot")
ent.Weapon = weapon
ent:SetPos(self:WorldSpaceCenter())
ent:SetAngles(AngleRand())
ent:Spawn()
if IsValid(ent:GetPhysicsObject()) then
ent:GetPhysicsObject():SetVelocity(VectorRand(-250,250))
end
end
end
SuR:MessageOnClient(18, ply:Nick())
self:Remove()
end
end

View File

@@ -0,0 +1,66 @@
AddCSLuaFile("shared.lua")
include('shared.lua')
/*-----------------------------------------------
*** Copyright (c) 2012-2022 by DrVrej, All rights reserved. ***
No parts of this code or any of its contents may be reproduced, copied, modified or adapted,
without the prior written consent of the author, unless otherwise indicated for stand-alone materials.
-----------------------------------------------*/
ENT.StartHealth = 200
ENT.UsePlayerModelMovement = true
ENT.Model = {"models/player/swat.mdl"}
ENT.IsHuman = true
ENT.BloodColor = "Red"
ENT.VJ_NPC_Class = {"VJ_PLAYER_ALLY"}
ENT.PlayerFriendly = true
ENT.HasMeleeAttack = true
ENT.AnimTbl_MeleeAttack = {"vjseq_seq_meleeattack01"}
ENT.HasCallForHelpAnimation = false
ENT.MeleeAttackDamage = 50
ENT.FootStepTimeRun = 0.3
ENT.FootStepTimeWalk = 0.5
ENT.DropWeaponOnDeath = false
ENT.SightDistance = 3000
ENT.SoundTbl_FootStep = {"npc/footsteps/hardboot_generic1.wav","npc/footsteps/hardboot_generic2.wav","npc/footsteps/hardboot_generic3.wav","npc/footsteps/hardboot_generic4.wav","npc/footsteps/hardboot_generic5.wav","npc/footsteps/hardboot_generic6.wav","npc/footsteps/hardboot_generic8.wav"}
ENT.HasItemDropsOnDeath = false
ENT.DeathCorpseFade = true
ENT.DeathCorpseFadeTime = 120
ENT.InvestigateSoundDistance = 20
ENT.HasItemDropsOnDeath = false
ENT.DropWeaponOnDeath = false
---------------------------------------------------------------------------------------------------------------------------------------------
function ENT:CustomOnPreInitialize()
local rnd = math.random(1,4)
if rnd == 1 then
self.WaitForEnemyToComeOutTime = VJ_Set(10, 30)
elseif rnd == 2 then
self.HasGrenadeAttack = true
self.ThrowGrenadeChance = 5
elseif rnd == 3 then
self.IsMedicSNPC = true
end
end
function ENT:CustomOnInitialize()
self.SearchTime = 0
self.SearchWalkTime = 0
local rnd = math.random(1,3)
if rnd == 1 then
self:Give("weapon_vj_m16a1")
elseif rnd == 2 then
self:Give("weapon_vj_spas12")
else
self:Give("weapon_vj_ssg08")
end
self:SetCustomCollisionCheck(true)
end

View File

@@ -0,0 +1,3 @@
ENT.Base = "npc_vj_human_base"
ENT.Type = "ai"
ENT.PrintName = "Human"

View File

@@ -0,0 +1,100 @@
AddCSLuaFile()
ENT.PrintName = "Zone"
ENT.Base = "base_anim"
if SERVER then
function ENT:Initialize()
self:SetModel("models/hunter/blocks/cube025x025x025.mdl")
self:SetNoDraw(true)
self:SetNWFloat('radius', SuR.Config.Zone_Radius)
self.DelayGasDamage = 0
end
function ENT:Think()
self:SetNWFloat('radius', SuR.Config.Zone_Radius)
if self.DelayGasDamage < CurTime() then
self.DelayGasDamage = CurTime()+1
local tab = player.GetAll()
for i=1,#tab do
local ply = tab[i]
if ply:GetPos():DistToSqr(self:GetPos()) < SuR.Config.Zone_Radius^2 or !ply:Alive() then continue end
if ply:Health() > 10 then
ply:TakeDamage(10, self)
else
ply:SuR_MakeZombie()
end
ply:PlayVoiceLine("lowhp", 10)
end
end
end
else
function ENT:Think()
if not self.GasEffect then
self.GasEffect = 0
end
if self.GasEffect < CurTime() then
self.GasEffect = CurTime()+0.5
local gasEmitter = ParticleEmitter(self:GetPos())
local radius = self:GetNWFloat('radius', 0)
if IsValid(gasEmitter) and radius > 0 then
for i=0, 360 do
local rad = radius+100
local angle = math.rad(i)
local x = rad * math.cos(angle)
local y = rad * math.sin(angle)
local particles = gasEmitter:Add("particle/particle_smokegrenade", self:GetPos() + Vector(x, y, 100))
particles:SetVelocity(Vector(0, 0, 0))
particles:SetDieTime(5)
particles:SetStartAlpha(100)
particles:SetEndAlpha(0)
particles:SetStartSize(200)
particles:SetEndSize(200)
particles:SetRoll(math.Rand(-180, 180))
particles:SetRollDelta(math.Rand(-0.5, 0.5))
particles:SetColor(0,50,0)
end
for i=0, 360, 10 do
local rad = radius+1000
local angle = math.rad(i)
local x = rad * math.cos(angle)
local y = rad * math.sin(angle)
local particles = gasEmitter:Add("particle/particle_smokegrenade", self:GetPos() + Vector(x, y, 500))
particles:SetVelocity(Vector(0, 0, 0))
particles:SetDieTime(10)
particles:SetStartAlpha(175)
particles:SetEndAlpha(0)
particles:SetStartSize(1000)
particles:SetEndSize(1000)
particles:SetRoll(math.Rand(-180, 180))
particles:SetRollDelta(math.Rand(-0.5, 0.5))
particles:SetColor(0,50,0)
end
for i=0, 360, 25 do
local rad = radius+3000
local angle = math.rad(i)
local x = rad * math.cos(angle)
local y = rad * math.sin(angle)
local particles = gasEmitter:Add("particle/particle_smokegrenade", self:GetPos() + Vector(x, y, 1500))
particles:SetVelocity(Vector(0, 0, 0))
particles:SetDieTime(10)
particles:SetStartAlpha(200)
particles:SetEndAlpha(0)
particles:SetStartSize(2500)
particles:SetEndSize(2500)
particles:SetRoll(math.Rand(-180, 180))
particles:SetRollDelta(math.Rand(-0.5, 0.5))
particles:SetColor(0,50,0)
end
gasEmitter:Finish()
end
end
end
end

View File

@@ -0,0 +1,297 @@
AddCSLuaFile()
SWEP.PrintName = "Claws"
SWEP.Slot = 0
SWEP.SlotPos = 4
SWEP.Spawnable = true
SWEP.ViewModel = Model( "models/weapons/c_zombieswep.mdl" )
SWEP.WorldModel = ""
SWEP.ViewModelFOV = 90
SWEP.UseHands = true
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = -1
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "none"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = true
SWEP.Secondary.Ammo = "none"
SWEP.DrawAmmo = false
SWEP.HitDistance = 48
local SwingSound = Sound( "npc/fast_zombie/claw_miss1.wav" )
local HitSound = Sound( "npc/fast_zombie/claw_strike1.wav" )
function SWEP:Initialize()
self:SetHoldType( "fist" )
end
function SWEP:SetupDataTables()
self:NetworkVar( "Float", 0, "NextMeleeAttack" )
self:NetworkVar( "Float", 1, "NextIdle" )
self:NetworkVar( "Int", 2, "Combo" )
end
function SWEP:UpdateNextIdle()
local vm = self:GetOwner():GetViewModel()
self:SetNextIdle( CurTime() + vm:SequenceDuration() / vm:GetPlaybackRate() )
end
function SWEP:PrimaryAttack( right )
local anim = "anim_fire"..math.random(1,4)
local owner = self:GetOwner()
local vm = owner:GetViewModel()
vm:SendViewModelMatchingSequence( vm:LookupSequence( anim ) )
self:EmitSound(SwingSound, 60, math.random(110,130), 0.5)
self:UpdateNextIdle()
self:SetNextMeleeAttack( CurTime() + 0.4 )
self:SetNextPrimaryFire( CurTime() + 1 )
if SERVER then
if owner:Crouching() then
owner:PlayFastGesture(ACT_SPECIAL_ATTACK2, true)
else
owner:PlayFastGesture(ACT_GESTURE_MELEE_ATTACK1, true)
end
owner:PlayVoiceLine("zombie_attack", 50)
end
end
function SWEP:SecondaryAttack()
if CLIENT then return end
local ent = self:GetOwner()
if ent.ZombieClass == "Spitter" then
self:SetNextSecondaryFire(CurTime()+8)
ent:SetSVAnimation("range_spit", true, true, true)
timer.Simple(0.2, function()
if !IsValid(ent) or !ent:Alive() then return end
local pr = ents.Create("obj_vj_lnr_spit")
pr:SetPos(ent:EyePos()+ent:GetForward()*32)
pr:Spawn()
pr:GetPhysicsObject():SetVelocity(ent:GetAimVector()*1000+Vector(0,0,100))
timer.Simple(0.4, function()
if !IsValid(ent) or !ent:Alive() then return end
local pr = ents.Create("obj_vj_lnr_spit")
pr:SetPos(ent:EyePos()+ent:GetForward()*32)
pr:Spawn()
pr:GetPhysicsObject():SetVelocity(ent:GetAimVector()*1000+Vector(0,0,100))
timer.Simple(0.6, function()
if !IsValid(ent) or !ent:Alive() then return end
local pr = ents.Create("obj_vj_lnr_spit")
pr:SetPos(ent:EyePos()+ent:GetForward()*32)
pr:Spawn()
pr:GetPhysicsObject():SetVelocity(ent:GetAimVector()*1000+Vector(0,0,100))
end)
end)
end)
elseif ent.ZombieClass == "Hazmat" then
self:SetNextSecondaryFire(CurTime()+999)
local anim = "nz_napalm_explode_"..math.random(1,3)
local _, time = ent:LookupSequence(anim)
ent:SetSVAnimation(anim, true, true, true)
ent:EmitSound("vj_lnrspecials/explosivegasleak.wav", 80)
timer.Simple(time, function()
if !IsValid(ent) or !ent:Alive() or !IsValid(self) then return end
ParticleEffect("vj_explosion2",ent:GetPos() + ent:GetUp()*48 + ent:GetForward()*1,Angle(0,0,0),nil)
ParticleEffect("vj_explosion1",ent:GetPos() + ent:GetUp()*15,Angle(0,0,0),nil)
ParticleEffect("vj_explosionfire2",ent:GetPos() + ent:GetUp()*20,Angle(0,0,0),nil)
ParticleEffect("vj_explosionfire1",ent:GetPos() + ent:GetUp()*20,Angle(0,0,0),nil)
util.ScreenShake(ent:GetPos(),100,200,1,2500)
util.VJ_SphereDamage(ent,ent,ent:GetPos(),250,75,DMG_BLAST,false,true,{Force=100})
ent:EmitSound("ambient/explosions/explode_"..math.random(1,9)..".wav", 90)
ent:Kill()
end)
elseif ent.ZombieClass == "Evo" then
self:SetNextSecondaryFire(CurTime()+6)
ent:SetSVAnimation("jump_attack", true, true, true)
ent:SetVelocity(ent:GetAimVector()*200+Vector(0,0,600))
elseif ent.ZombieClass == "Bomber" then
self:SetNextSecondaryFire(CurTime()+10)
ent:SetSVAnimation("range_throw", true, true, true)
timer.Simple(0.6, function()
if !IsValid(ent) or !ent:Alive() then return end
local pr = ents.Create("obj_vj_grenade")
pr:SetPos(ent:EyePos()+ent:GetForward()*32)
pr:Spawn()
pr:GetPhysicsObject():SetVelocity(ent:GetAimVector()*800+Vector(0,0,100))
ent:EmitSound("vj_lnrspecials/bomber/zombine_readygrenade"..math.random(1,2)..".wav", 60)
end)
else
self:SetNextSecondaryFire(CurTime()+10)
ent:PlayVoiceLine("zombie_idle")
ent:SetSVAnimation("nz_taunt_"..math.random(1,9), true, true, true)
ent:SetHealth(math.min(ent:GetMaxHealth(), ent:Health()+25))
end
end
local phys_pushscale = GetConVar( "phys_pushscale" )
function SWEP:DealDamage()
local owner = self:GetOwner()
local anim = self:GetSequenceName(owner:GetViewModel():GetSequence())
owner:LagCompensation( true )
local tr = util.TraceLine( {
start = owner:GetShootPos(),
endpos = owner:GetShootPos() + owner:GetAimVector() * self.HitDistance,
filter = owner,
mask = MASK_SHOT_HULL
} )
if ( !IsValid( tr.Entity ) ) then
tr = util.TraceHull( {
start = owner:GetShootPos(),
endpos = owner:GetShootPos() + owner:GetAimVector() * self.HitDistance,
filter = owner,
mins = Vector( -10, -10, -8 ),
maxs = Vector( 10, 10, 8 ),
mask = MASK_SHOT_HULL
} )
end
-- We need the second part for single player because SWEP:Think is ran shared in SP
if ( tr.Hit && !( game.SinglePlayer() && CLIENT ) ) then
self:EmitSound( HitSound )
end
local hit = false
local scale = phys_pushscale:GetFloat()
if ( SERVER && IsValid( tr.Entity ) && ( tr.Entity:IsNPC() || tr.Entity:IsPlayer() || tr.Entity:Health() > 0 ) ) then
local dmginfo = DamageInfo()
local attacker = owner
if ( !IsValid( attacker ) ) then attacker = self end
dmginfo:SetAttacker( attacker )
dmginfo:SetInflictor( self )
dmginfo:SetDamage( math.random( 10, 20 ) )
if ( anim == "fists_left" ) then
dmginfo:SetDamageForce( owner:GetRight() * 4912 * scale + owner:GetForward() * 9998 * scale ) -- Yes we need those specific numbers
elseif ( anim == "fists_right" ) then
dmginfo:SetDamageForce( owner:GetRight() * -4912 * scale + owner:GetForward() * 9989 * scale )
elseif ( anim == "fists_uppercut" ) then
dmginfo:SetDamageForce( owner:GetUp() * 5158 * scale + owner:GetForward() * 10012 * scale )
dmginfo:SetDamage( math.random( 12, 24 ) )
end
SuppressHostEvents( NULL ) -- Let the breakable gibs spawn in multiplayer on client
tr.Entity:TakeDamageInfo( dmginfo )
SuppressHostEvents( owner )
hit = true
end
if ( IsValid( tr.Entity ) ) then
local phys = tr.Entity:GetPhysicsObject()
if ( IsValid( phys ) ) then
phys:ApplyForceOffset( owner:GetAimVector() * 80 * phys:GetMass() * scale, tr.HitPos )
end
end
if ( SERVER ) then
if ( hit && anim != "fists_uppercut" ) then
self:SetCombo( self:GetCombo() + 1 )
else
self:SetCombo( 0 )
end
end
owner:LagCompensation( false )
end
function SWEP:OnDrop()
self:Remove() -- You can't drop fists
end
function SWEP:Deploy()
local speed = GetConVarNumber( "sv_defaultdeployspeed" )
local vm = self:GetOwner():GetViewModel()
vm:SendViewModelMatchingSequence( vm:LookupSequence( "fists_draw" ) )
vm:SetPlaybackRate( speed )
self:SetNextPrimaryFire( CurTime() + vm:SequenceDuration() / speed )
self:SetNextSecondaryFire( CurTime() + vm:SequenceDuration() / speed )
self:UpdateNextIdle()
if ( SERVER ) then
self:SetCombo( 0 )
end
return true
end
function SWEP:Holster()
self:SetNextMeleeAttack( 0 )
return true
end
function SWEP:Think()
local vm = self:GetOwner():GetViewModel()
local curtime = CurTime()
local idletime = self:GetNextIdle()
if ( idletime > 0 && CurTime() > idletime ) then
vm:SendViewModelMatchingSequence( vm:LookupSequence( "fists_idle_0" .. math.random( 1, 2 ) ) )
self:UpdateNextIdle()
end
local meleetime = self:GetNextMeleeAttack()
if ( meleetime > 0 && CurTime() > meleetime ) then
self:DealDamage()
self:SetNextMeleeAttack( 0 )
end
if ( SERVER && CurTime() > self:GetNextPrimaryFire() + 0.1 ) then
self:SetCombo( 0 )
end
end

View File

@@ -0,0 +1,109 @@
AddCSLuaFile()
SWEP.PrintName = "Jerry Can"
SWEP.Slot = 0
SWEP.SlotPos = 4
SWEP.Instructions = ""
SWEP.Spawnable = true
SWEP.ViewModel = "models/surrounded/obj/v_JerryCan.mdl"
SWEP.WorldModel = "models/surrounded/obj/w_JerryCanBlue.mdl"
SWEP.ViewModelFOV = 90
SWEP.UseHands = true
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = -1
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "none"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.DrawAmmo = false
function SWEP:Initialize()
self:SetHoldType("slam")
end
function SWEP:PrimaryAttack()
if CLIENT then return end
local ply = self:GetOwner()
local tr = util.TraceLine({
start = ply:EyePos(),
endpos = ply:EyePos() + ply:GetAimVector()*64,
filter = ply,
})
local ent = tr.Entity
if IsValid(ent) and ent:GetClass() == "sur_generator" and !ent:GetNWBool('HaveFuel') then
self:SetNextPrimaryFire(CurTime()+10)
local anim = "sur_fuel_up"
local time = select(2, ply:LookupSequence(anim))
ply:SetSVAnimation(anim, true, true, true)
ply:EmitSound("surrounded/weapons/fuel/sfx_sequence_fuel.wav", 60, math.random(80,110))
ply:Freeze(true)
timer.Simple(time-0.1, function()
if !IsValid(ply) or ply:GetSVAnim() != anim then return end
ply:Freeze(false)
if !IsValid(ent) then return end
ent:Fuel()
if !IsValid(self) then return end
self:Remove()
ply:AddXP(SuR.Config.XP_Giving["fuel"])
SuR:MessageOnClient(19, ply:Nick())
end)
end
end
function SWEP:SecondaryAttack()
if CLIENT then return end
local ply = self:GetOwner()
ply:ConCommand("sur_dropweapon sur_fuel")
self:SetNextSecondaryFire(CurTime()+2)
end
function SWEP:Holster()
return false
end
function SWEP:Reload() end
if CLIENT then
local wm = ClientsideModel(SWEP.WorldModel)
wm:SetNoDraw(true)
function SWEP:DrawWorldModel()
local owner = self:GetOwner()
if IsValid(owner) then
local offsetVec = Vector(5, -4, 16)
local offsetAng = Angle(180, 90, 10)
local boneid = owner:LookupBone("ValveBiped.Bip01_R_Hand")
if !boneid then return end
local matrix = owner:GetBoneMatrix(boneid)
if !matrix then return end
local newPos, newAng = LocalToWorld(offsetVec, offsetAng, matrix:GetTranslation(), matrix:GetAngles())
wm:SetPos(newPos)
wm:SetAngles(newAng)
wm:SetupBones()
else
wm:SetPos(self:GetPos())
wm:SetAngles(self:GetAngles())
end
wm:DrawModel()
end
end

View File

@@ -0,0 +1,245 @@
AddCSLuaFile()
SWEP.PrintName = "Cade Hammer"
SWEP.Slot = 0
SWEP.SlotPos = 4
SWEP.Instructions = "LMB - Build/Repair, RMB - Unbuild, R - Drag Prop"
SWEP.Spawnable = true
SWEP.ViewModel = Model( "models/weapons/c_arms.mdl" )
SWEP.WorldModel = "models/weapons/w_buzzhammer.mdl"
SWEP.ViewModelFOV = 54
SWEP.UseHands = true
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = -1
SWEP.Primary.Automatic = true
SWEP.Primary.Ammo = "none"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.DrawAmmo = false
SWEP.Offset = {
Pos = {Up = -5, Right = 1, Forward = 3, },
Ang = {Up = 0, Right = 0, Forward = 90,}
}
function SWEP:DrawWorldModel()
local hand, offset, rotate
local pl = self:GetOwner()
if IsValid( pl ) then
local boneIndex = pl:LookupBone( "ValveBiped.Bip01_R_Hand" )
if boneIndex then
local pos, ang = pl:GetBonePosition( boneIndex )
pos = pos + ang:Forward() * self.Offset.Pos.Forward + ang:Right() * self.Offset.Pos.Right + ang:Up() * self.Offset.Pos.Up
ang:RotateAroundAxis( ang:Up(), self.Offset.Ang.Up)
ang:RotateAroundAxis( ang:Right(), self.Offset.Ang.Right )
ang:RotateAroundAxis( ang:Forward(), self.Offset.Ang.Forward )
self:SetRenderOrigin( pos )
self:SetRenderAngles( ang )
self:DrawModel()
end
else
self:SetRenderOrigin( nil )
self:SetRenderAngles( nil )
self:DrawModel()
end
end
function SWEP:Initialize()
self:SetHoldType("melee")
end
function SWEP:PrimaryAttack()
if SERVER then
local ply = self.Owner
local tr = ply:GetEyeTrace()
if tr.HitPos:DistToSqr(ply:EyePos()) < 128^2 and IsValid(tr.Entity) and tr.Entity:GetClass() == "prop_physics" and ply:GetNWFloat('buildercost') >= 1 then
local e = tr.Entity
local tr2 = util.TraceLine({
start = tr.HitPos,
endpos = tr.HitPos+ply:GetAimVector()*16,
filter = function(ent) if !ent:IsWorld() then return end end
})
if e:GetPhysicsObject():GetMass() < 1000 and tr.Hit and tr2.Hit then
local ent = ents.Create("sur_barricade")
ent.MapCade = true
ent.id = 6
ent:SetModel(e:GetModel())
ent:SetPos(e:GetPos())
ent:SetAngles(e:GetAngles())
ent:SetSkin(e:GetSkin())
ent:SetNWEntity('builder', ply)
local mult = 1
if ply:GetPlayerClass() == "engineer" and ply:GetLevelState() >= 4 then
mult = 2
elseif ply:GetPlayerClass() == "engineer" and ply:GetLevelState() >= 3 then
mult = 1.5
elseif ply:GetPlayerClass() == "engineer" and ply:GetLevelState() >= 1 then
mult = 1.1
end
ent.health = e.Healthbefore or e:GetPhysicsObject():GetMass()*5*mult
ent.healthmax = e:GetPhysicsObject():GetMass()*5*mult
ent:Spawn()
local bolt = ents.Create("prop_dynamic")
bolt:SetModel("models/crossbow_bolt.mdl")
bolt:SetAngles(ply:EyeAngles())
bolt:SetPos(tr.HitPos-ply:GetAimVector()*4)
bolt:Spawn()
ent:DeleteOnRemove(bolt)
e:EmitSound('weapons/crowbar/crowbar_impact1.wav')
e:Remove()
ply:SetNWFloat('buildercost', ply:GetNWFloat('buildercost')-1)
ply:ViewPunch(Angle(25,25,25))
BroadcastLua([[Entity(]]..ply:EntIndex()..[[):SetAnimation( PLAYER_ATTACK1 )]])
self:SetNextPrimaryFire( CurTime() + 1 )
end
end
end
end
function SWEP:SecondaryAttack()
if SERVER then
local ply = self.Owner
local tr = ply:GetEyeTrace()
local tr2 = util.TraceLine( {
start = tr.HitPos,
endpos = tr.HitPos-Vector(0,0,4)
} )
if tr.HitPos:DistToSqr(ply:EyePos()) < 72^2 and tr.Entity and tr.Entity.MapCade then
local e = tr.Entity
local ent = ents.Create("prop_physics")
ent:SetModel(e:GetModel())
ent:SetPos(e:GetPos())
ent:SetAngles(e:GetAngles())
ent:SetSkin(e:GetSkin())
ent.Healthbefore = tr.Entity.health
ent:Spawn()
ent:TakeDamage(0)
ent:GetPhysicsObject():EnableMotion(true)
e:EmitSound('weapons/crowbar/crowbar_impact2.wav')
e:Remove()
ply:ViewPunch(Angle(25,25,25))
ply:SetAnimation( PLAYER_ATTACK1 )
end
end
end
function SWEP:Reload()
if SERVER then
local ply = self.Owner
local tr = ply:GetEyeTrace()
local center = ply:EyePos()+ply:GetAimVector()*128
if !IsValid(self.propt) and tr.Entity and tr.Entity:GetClass() == "prop_physics" and IsValid(tr.Entity:GetPhysicsObject()) and tr.HitPos:DistToSqr(ply:EyePos()) < 72^2 and tr.Entity:GetPhysicsObject():GetMass() < 500 then
self.propt = tr.Entity
end
end
end
function SWEP:OnDrop()
if SERVER then
self.propt = nil
end
self:Remove()
end
function SWEP:Deploy()
if SERVER then
self.propt = nil
end
return true
end
function SWEP:Holster()
if SERVER then
self.propt = nil
end
return true
end
local function RotateProp(ply, prop, x, y)
local sense = 10/1
local ang = prop:GetAngles()
ang:RotateAroundAxis(Vector(0, 0, 1), x / sense)
ang:RotateAroundAxis(Vector(0, 1, 0), y / sense)
prop:SetAngles(ang)
end
function SWEP:Think()
if SERVER then
local ply = self.Owner
if not IsValid(ply) then return end
local tr = ply:GetEyeTrace()
self:SetNWEntity('drawthis', nil)
if tr.HitPos:DistToSqr(ply:EyePos()) < 128^2 and IsValid(tr.Entity) and tr.Entity:GetClass() == "prop_physics" then
local tr2 = util.TraceLine({
start = tr.HitPos,
endpos = tr.HitPos+ply:GetAimVector()*16,
filter = function(ent) if !ent:IsWorld() then return end end
})
self:SetNWFloat('colormode', 1)
if tr2.Hit then
self:SetNWFloat('colormode', 2)
end
if tr.Entity:GetPhysicsObject():GetMass() >= 1000 then
self:SetNWFloat('colormode', 0)
end
self:SetNWEntity('drawthis', tr.Entity)
else
self:SetNWEntity('drawthis', NULL)
end
if IsValid(self.propt) then
local tr = ply:GetEyeTrace()
local center = ply:EyePos()+ply:GetAimVector()*72
if not ply:KeyDown(IN_SPEED) then
self.propt:GetPhysicsObject():EnableMotion(true)
else
self.propt:GetPhysicsObject():EnableMotion(false)
end
self.propt:GetPhysicsObject():SetVelocity((center-self.propt:GetPos())*4)
self.propt:GetPhysicsObject():SetAngleVelocity(Vector())
local ucmd = ply:GetCurrentCommand()
if ply:KeyDown(IN_WALK) then
RotateProp(ply, self.propt, ucmd:GetMouseX(), ucmd:GetMouseY())
ply:SetEyeAngles(ply.RotatePropAngWep)
else
ply.RotatePropAngWep = ply:EyeAngles()
end
if center:Distance(self.propt:GetPos()) > 72 or not ply:KeyDown(IN_RELOAD) then
self.propt:GetPhysicsObject():EnableMotion(true)
self.propt:GetPhysicsObject():SetVelocity((center-self.propt:GetPos()))
self.propt = nil
end
end
end
end
function SWEP:DrawHUD()
draw.SimpleText(SuR.Language["hammer_parts"]..LocalPlayer():GetNWFloat('buildercost'), "SuR_MediumFont1", ScrW()/2, ScrH()-He(250), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, 3, color_black)
draw.SimpleText(SuR.Language["hammer_controls"], "SuR_SmallFont1", ScrW()/2, ScrH()-He(220), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, 3, color_black)
local tr = self:GetNWEntity('drawthis')
local colors = Color(200,20,20)
if self:GetNWFloat('colormode') == 1 then
colors = Color(200,200,20)
elseif self:GetNWFloat('colormode') == 2 then
colors = Color(20,200,20)
end
if IsValid(tr) then
halo.Add( {tr}, colors, 5, 5, 2 )
end
end

View File

@@ -0,0 +1,128 @@
AddCSLuaFile()
SWEP.PrintName = "Landmines"
SWEP.Slot = 0
SWEP.SlotPos = 4
SWEP.Instructions = "LMB - Build, RMB - Rotate, R - Menu"
SWEP.Spawnable = true
SWEP.ViewModel = "models/surrounded/equipment/fieldupgrade_proximitymine.mdl"
SWEP.WorldModel = "models/surrounded/equipment/fieldupgrade_proximitymine.mdl"
SWEP.ViewModelFOV = 54
SWEP.UseHands = true
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = -1
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "none"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.DrawAmmo = false
function SWEP:Initialize()
self:SetHoldType("slam")
self:SetNWBool('Ready', true)
end
function SWEP:ReloadMine()
self:SetNWBool('Ready', false)
self:SetHoldType("normal")
self.Owner:EmitSound("buttons/combine_button1.wav")
timer.Create("ReloadMineTime"..math.random(0,99999999), 15, 1, function()
if !IsValid(self) or !IsValid(self.Owner) then return end
self:SetNWBool('Ready', true)
self:SetHoldType("slam")
self.Owner:EmitSound("buttons/combine_button_locked.wav")
end)
end
function SWEP:PrimaryAttack()
if SERVER then
local ply = self.Owner
if !self:GetNWBool('Ready') then return end
local ent = ents.Create("sur_landmine")
ent:SetPos(ply:EyePos()+ply:GetForward()*32)
ent:Spawn()
ent:GetPhysicsObject():SetVelocity(ply:GetAimVector()*256)
self:ReloadMine()
end
end
function SWEP:SecondaryAttack()
end
function SWEP:Reload()
end
if CLIENT then
local WorldModel = ClientsideModel(SWEP.WorldModel)
WorldModel:SetNoDraw(true)
function SWEP:DrawWorldModel()
local _Owner = self:GetOwner()
if (IsValid(_Owner)) then
local offsetVec = Vector(5, -2.7, -3.4)
local offsetAng = Angle(180, 90, 0)
local boneid = _Owner:LookupBone("ValveBiped.Bip01_R_Hand")
if !boneid then return end
local matrix = _Owner:GetBoneMatrix(boneid)
if !matrix then return end
local newPos, newAng = LocalToWorld(offsetVec, offsetAng, matrix:GetTranslation(), matrix:GetAngles())
WorldModel:SetPos(newPos)
WorldModel:SetAngles(newAng)
WorldModel:SetupBones()
else
WorldModel:SetPos(self:GetPos())
WorldModel:SetAngles(self:GetAngles())
end
if self:GetNWBool('Ready') then
WorldModel:DrawModel()
end
end
SWEP.IronSightsPos = Vector(0, 25, -12)
SWEP.IronSightsAng = Vector(10, 0, 0)
function SWEP:GetViewModelPosition(EyePos, EyeAng)
local Mul = 1.0
local Offset = self.IronSightsPos
if !self:GetNWBool('Ready') then
Offset = Vector(0,0,999)
end
if (self.IronSightsAng) then
EyeAng = EyeAng * 1
EyeAng:RotateAroundAxis(EyeAng:Right(), self.IronSightsAng.x * Mul)
EyeAng:RotateAroundAxis(EyeAng:Up(), self.IronSightsAng.y * Mul)
EyeAng:RotateAroundAxis(EyeAng:Forward(), self.IronSightsAng.z * Mul)
end
local Right = EyeAng:Right()
local Up = EyeAng:Up()
local Forward = EyeAng:Forward()
EyePos = EyePos + Offset.x * Right * Mul
EyePos = EyePos + Offset.y * Forward * Mul
EyePos = EyePos + Offset.z * Up * Mul
return EyePos, EyeAng
end
end

View File

@@ -0,0 +1,192 @@
--[[---------------------------------------------------------
Name: SetupWeaponHoldTypeForAI
Desc: Sets up ACT translations from generic activities to NPC specific activies. In a seperate file to clean up the init.lua
Not all NPCs have support for all animations (for example Citizens don't have pistol animations)
This only supports the holdtypes the default NPC models can support
All of these are taken directly from IMPLEMENT_ACTTABLE() macro of the C++ weapons
-----------------------------------------------------------]]
function SWEP:SetupWeaponHoldTypeForAI( t )
self.ActivityTranslateAI = {}
-- Default is pistol/revolver for reasons
self.ActivityTranslateAI[ ACT_IDLE ] = ACT_IDLE_PISTOL
self.ActivityTranslateAI[ ACT_IDLE_ANGRY ] = ACT_IDLE_ANGRY_PISTOL
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1 ] = ACT_RANGE_ATTACK_PISTOL
self.ActivityTranslateAI[ ACT_RELOAD ] = ACT_RELOAD_PISTOL
self.ActivityTranslateAI[ ACT_WALK_AIM ] = ACT_WALK_AIM_PISTOL
self.ActivityTranslateAI[ ACT_RUN_AIM ] = ACT_RUN_AIM_PISTOL
self.ActivityTranslateAI[ ACT_GESTURE_RANGE_ATTACK1 ] = ACT_GESTURE_RANGE_ATTACK_PISTOL
self.ActivityTranslateAI[ ACT_RELOAD_LOW ] = ACT_RELOAD_PISTOL_LOW
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1_LOW ] = ACT_RANGE_ATTACK_PISTOL_LOW
self.ActivityTranslateAI[ ACT_COVER_LOW ] = ACT_COVER_PISTOL_LOW
self.ActivityTranslateAI[ ACT_RANGE_AIM_LOW ] = ACT_RANGE_AIM_PISTOL_LOW
self.ActivityTranslateAI[ ACT_GESTURE_RELOAD ] = ACT_GESTURE_RELOAD_PISTOL
self.ActivityTranslateAI[ ACT_WALK ] = ACT_WALK_PISTOL
self.ActivityTranslateAI[ ACT_RUN ] = ACT_RUN_PISTOL
self.ActivityTranslateAI[ ACT_IDLE_RELAXED ] = ACT_IDLE_PISTOL
self.ActivityTranslateAI[ ACT_IDLE_STIMULATED ] = ACT_IDLE_STIMULATED
self.ActivityTranslateAI[ ACT_IDLE_AGITATED ] = ACT_IDLE_ANGRY_PISTOL
self.ActivityTranslateAI[ ACT_IDLE_STEALTH ] = ACT_IDLE_STEALTH_PISTOL
self.ActivityTranslateAI[ ACT_WALK_RELAXED ] = ACT_WALK
self.ActivityTranslateAI[ ACT_WALK_STIMULATED ] = ACT_WALK_STIMULATED
self.ActivityTranslateAI[ ACT_WALK_AGITATED ] = ACT_WALK_AIM_PISTOL
self.ActivityTranslateAI[ ACT_WALK_STEALTH ] = ACT_WALK_STEALTH_PISTOL
self.ActivityTranslateAI[ ACT_RUN_RELAXED ] = ACT_RUN
self.ActivityTranslateAI[ ACT_RUN_STIMULATED ] = ACT_RUN_STIMULATED
self.ActivityTranslateAI[ ACT_RUN_AGITATED ] = ACT_RUN_AIM_PISTOL
self.ActivityTranslateAI[ ACT_RUN_STEALTH ] = ACT_RUN_STEALTH_PISTOL
self.ActivityTranslateAI[ ACT_IDLE_AIM_RELAXED ] = ACT_IDLE_PISTOL
self.ActivityTranslateAI[ ACT_IDLE_AIM_STIMULATED ] = ACT_IDLE_ANGRY_PISTOL
self.ActivityTranslateAI[ ACT_IDLE_AIM_AGITATED ] = ACT_IDLE_ANGRY_PISTOL
self.ActivityTranslateAI[ ACT_IDLE_AIM_STEALTH ] = ACT_IDLE_STEALTH_PISTOL
self.ActivityTranslateAI[ ACT_WALK_AIM_RELAXED ] = ACT_WALK
self.ActivityTranslateAI[ ACT_WALK_AIM_STIMULATED ] = ACT_WALK_AIM_PISTOL
self.ActivityTranslateAI[ ACT_WALK_AIM_AGITATED ] = ACT_WALK_AIM_PISTOL
self.ActivityTranslateAI[ ACT_WALK_AIM_STEALTH ] = ACT_WALK_AIM_STEALTH_PISTOL
self.ActivityTranslateAI[ ACT_RUN_AIM_RELAXED ] = ACT_RUN
self.ActivityTranslateAI[ ACT_RUN_AIM_STIMULATED ] = ACT_RUN_AIM_PISTOL
self.ActivityTranslateAI[ ACT_RUN_AIM_AGITATED ] = ACT_RUN_AIM_PISTOL
self.ActivityTranslateAI[ ACT_RUN_AIM_STEALTH ] = ACT_RUN_AIM_STEALTH_PISTOL
self.ActivityTranslateAI[ ACT_CROUCHIDLE_STIMULATED] = ACT_CROUCHIDLE_STIMULATED
self.ActivityTranslateAI[ ACT_CROUCHIDLE_AIM_STIMULATED ] = ACT_RANGE_AIM_PISTOL_LOW
self.ActivityTranslateAI[ ACT_CROUCHIDLE_AGITATED ] = ACT_RANGE_AIM_PISTOL_LOW
self.ActivityTranslateAI[ ACT_READINESS_RELAXED_TO_STIMULATED ] = ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED
self.ActivityTranslateAI[ ACT_READINESS_RELAXED_TO_STIMULATED_WALK ] = ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK
self.ActivityTranslateAI[ ACT_READINESS_AGITATED_TO_STIMULATED ] = ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED
self.ActivityTranslateAI[ ACT_READINESS_STIMULATED_TO_RELAXED ] = ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED
if ( t == "ar2" || t == "smg" ) then
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1 ] = ACT_RANGE_ATTACK_AR2
self.ActivityTranslateAI[ ACT_RELOAD ] = ACT_RELOAD_SMG1
self.ActivityTranslateAI[ ACT_IDLE ] = ACT_IDLE_SMG1
self.ActivityTranslateAI[ ACT_IDLE_ANGRY ] = ACT_IDLE_ANGRY_SMG1
self.ActivityTranslateAI[ ACT_WALK ] = ACT_WALK_RIFLE
self.ActivityTranslateAI[ ACT_WALK_AIM ] = ACT_WALK_AIM_RIFLE
self.ActivityTranslateAI[ ACT_IDLE_RELAXED ] = ACT_IDLE_SMG1_RELAXED
self.ActivityTranslateAI[ ACT_IDLE_STIMULATED ] = ACT_IDLE_SMG1_STIMULATED
self.ActivityTranslateAI[ ACT_IDLE_AGITATED ] = ACT_IDLE_ANGRY_SMG1
self.ActivityTranslateAI[ ACT_WALK_RELAXED ] = ACT_WALK_RIFLE_RELAXED
self.ActivityTranslateAI[ ACT_WALK_STIMULATED ] = ACT_WALK_RIFLE_STIMULATED
self.ActivityTranslateAI[ ACT_WALK_AGITATED ] = ACT_WALK_AIM_RIFLE
self.ActivityTranslateAI[ ACT_RUN_RELAXED ] = ACT_RUN_RIFLE_RELAXED
self.ActivityTranslateAI[ ACT_RUN_STIMULATED ] = ACT_RUN_RIFLE_STIMULATED
self.ActivityTranslateAI[ ACT_RUN_AGITATED ] = ACT_RUN_AIM_RIFLE
self.ActivityTranslateAI[ ACT_IDLE_AIM_RELAXED ] = ACT_IDLE_SMG1_RELAXED
self.ActivityTranslateAI[ ACT_IDLE_AIM_STIMULATED ] = ACT_IDLE_AIM_RIFLE_STIMULATED
self.ActivityTranslateAI[ ACT_IDLE_AIM_AGITATED ] = ACT_IDLE_ANGRY_SMG1
self.ActivityTranslateAI[ ACT_WALK_AIM_RELAXED ] = ACT_WALK_RIFLE_RELAXED
self.ActivityTranslateAI[ ACT_WALK_AIM_STIMULATED ] = ACT_WALK_AIM_RIFLE_STIMULATED
self.ActivityTranslateAI[ ACT_WALK_AIM_AGITATED ] = ACT_WALK_AIM_RIFLE
self.ActivityTranslateAI[ ACT_RUN_AIM_RELAXED ] = ACT_RUN_RIFLE_RELAXED
self.ActivityTranslateAI[ ACT_RUN_AIM_STIMULATED ] = ACT_RUN_AIM_RIFLE_STIMULATED
self.ActivityTranslateAI[ ACT_RUN_AIM_AGITATED ] = ACT_RUN_AIM_RIFLE
self.ActivityTranslateAI[ ACT_WALK_CROUCH ] = ACT_WALK_CROUCH_RIFLE
self.ActivityTranslateAI[ ACT_WALK_CROUCH_AIM ] = ACT_WALK_CROUCH_AIM_RIFLE
self.ActivityTranslateAI[ ACT_RUN ] = ACT_RUN_RIFLE
self.ActivityTranslateAI[ ACT_RUN_AIM ] = ACT_RUN_AIM_RIFLE
self.ActivityTranslateAI[ ACT_RUN_CROUCH ] = ACT_RUN_CROUCH_RIFLE
self.ActivityTranslateAI[ ACT_RUN_CROUCH_AIM ] = ACT_RUN_CROUCH_AIM_RIFLE
self.ActivityTranslateAI[ ACT_GESTURE_RANGE_ATTACK1 ] = ACT_GESTURE_RANGE_ATTACK_AR2
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1_LOW ] = ACT_RANGE_ATTACK_SMG1_LOW
self.ActivityTranslateAI[ ACT_COVER_LOW ] = ACT_COVER_SMG1_LOW
self.ActivityTranslateAI[ ACT_RANGE_AIM_LOW ] = ACT_RANGE_AIM_AR2_LOW
self.ActivityTranslateAI[ ACT_RELOAD_LOW ] = ACT_RELOAD_SMG1_LOW
self.ActivityTranslateAI[ ACT_GESTURE_RELOAD ] = ACT_GESTURE_RELOAD_SMG1
-- Extra overrides for SMG holdtype
if ( t == "smg" ) then
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1 ] = ACT_RANGE_ATTACK_SMG1
self.ActivityTranslateAI[ ACT_GESTURE_RANGE_ATTACK1 ] = ACT_GESTURE_RANGE_ATTACK_SMG1
self.ActivityTranslateAI[ ACT_RANGE_AIM_LOW ] = ACT_RANGE_AIM_SMG1_LOW
end
return
end
if ( t == "shotgun" || t == "crossbow" ) then
self.ActivityTranslateAI[ ACT_IDLE ] = ACT_IDLE_SMG1
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1 ] = ACT_RANGE_ATTACK_SHOTGUN
self.ActivityTranslateAI[ ACT_RELOAD ] = ACT_RELOAD_SHOTGUN
self.ActivityTranslateAI[ ACT_WALK ] = ACT_WALK_RIFLE
self.ActivityTranslateAI[ ACT_IDLE_ANGRY ] = ACT_IDLE_ANGRY_SHOTGUN
self.ActivityTranslateAI[ ACT_IDLE_RELAXED ] = ACT_IDLE_SHOTGUN_RELAXED
self.ActivityTranslateAI[ ACT_IDLE_STIMULATED ] = ACT_IDLE_SHOTGUN_STIMULATED
self.ActivityTranslateAI[ ACT_IDLE_AGITATED ] = ACT_IDLE_SHOTGUN_AGITATED
self.ActivityTranslateAI[ ACT_WALK_RELAXED ] = ACT_WALK_RIFLE_RELAXED
self.ActivityTranslateAI[ ACT_WALK_STIMULATED ] = ACT_WALK_RIFLE_STIMULATED
self.ActivityTranslateAI[ ACT_WALK_AGITATED ] = ACT_WALK_AIM_RIFLE
self.ActivityTranslateAI[ ACT_RUN_RELAXED ] = ACT_RUN_RIFLE_RELAXED
self.ActivityTranslateAI[ ACT_RUN_STIMULATED ] = ACT_RUN_RIFLE_STIMULATED
self.ActivityTranslateAI[ ACT_RUN_AGITATED ] = ACT_RUN_AIM_RIFLE
self.ActivityTranslateAI[ ACT_IDLE_AIM_RELAXED ] = ACT_IDLE_SMG1_RELAXED
self.ActivityTranslateAI[ ACT_IDLE_AIM_STIMULATED ] = ACT_IDLE_AIM_RIFLE_STIMULATED
self.ActivityTranslateAI[ ACT_IDLE_AIM_AGITATED ] = ACT_IDLE_ANGRY_SMG1
self.ActivityTranslateAI[ ACT_WALK_AIM_RELAXED ] = ACT_WALK_RIFLE_RELAXED
self.ActivityTranslateAI[ ACT_WALK_AIM_STIMULATED ] = ACT_WALK_AIM_RIFLE_STIMULATED
self.ActivityTranslateAI[ ACT_WALK_AIM_AGITATED ] = ACT_WALK_AIM_RIFLE
self.ActivityTranslateAI[ ACT_RUN_AIM_RELAXED ] = ACT_RUN_RIFLE_RELAXED
self.ActivityTranslateAI[ ACT_RUN_AIM_STIMULATED ] = ACT_RUN_AIM_RIFLE_STIMULATED
self.ActivityTranslateAI[ ACT_RUN_AIM_AGITATED ] = ACT_RUN_AIM_RIFLE
self.ActivityTranslateAI[ ACT_WALK_AIM ] = ACT_WALK_AIM_SHOTGUN
self.ActivityTranslateAI[ ACT_WALK_CROUCH ] = ACT_WALK_CROUCH_RIFLE
self.ActivityTranslateAI[ ACT_WALK_CROUCH_AIM ] = ACT_WALK_CROUCH_AIM_RIFLE
self.ActivityTranslateAI[ ACT_RUN ] = ACT_RUN_RIFLE
self.ActivityTranslateAI[ ACT_RUN_AIM ] = ACT_RUN_AIM_SHOTGUN
self.ActivityTranslateAI[ ACT_RUN_CROUCH ] = ACT_RUN_CROUCH_RIFLE
self.ActivityTranslateAI[ ACT_RUN_CROUCH_AIM ] = ACT_RUN_CROUCH_AIM_RIFLE
self.ActivityTranslateAI[ ACT_GESTURE_RANGE_ATTACK1 ] = ACT_GESTURE_RANGE_ATTACK_SHOTGUN
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1_LOW ] = ACT_RANGE_ATTACK_SHOTGUN_LOW
self.ActivityTranslateAI[ ACT_RELOAD_LOW ] = ACT_RELOAD_SHOTGUN_LOW
self.ActivityTranslateAI[ ACT_GESTURE_RELOAD ] = ACT_GESTURE_RELOAD_SHOTGUN
return
end
if ( t == "rpg" ) then
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1 ] = ACT_RANGE_ATTACK_RPG
self.ActivityTranslateAI[ ACT_IDLE_RELAXED ] = ACT_IDLE_RPG_RELAXED
self.ActivityTranslateAI[ ACT_IDLE_STIMULATED ] = ACT_IDLE_ANGRY_RPG
self.ActivityTranslateAI[ ACT_IDLE_AGITATED ] = ACT_IDLE_ANGRY_RPG
self.ActivityTranslateAI[ ACT_IDLE ] = ACT_IDLE_RPG
self.ActivityTranslateAI[ ACT_IDLE_ANGRY ] = ACT_IDLE_ANGRY_RPG
self.ActivityTranslateAI[ ACT_WALK ] = ACT_WALK_RPG
self.ActivityTranslateAI[ ACT_WALK_CROUCH ] = ACT_WALK_CROUCH_RPG
self.ActivityTranslateAI[ ACT_RUN ] = ACT_RUN_RPG
self.ActivityTranslateAI[ ACT_RUN_CROUCH ] = ACT_RUN_CROUCH_RPG
self.ActivityTranslateAI[ ACT_COVER_LOW ] = ACT_COVER_LOW_RPG
return
end
end

View File

@@ -0,0 +1,212 @@
include( "ai_translations.lua" )
include( "sh_anim.lua" )
include( "shared.lua" )
SWEP.Slot = 0 -- Slot in the weapon selection menu
SWEP.SlotPos = 10 -- Position in the slot
SWEP.DrawAmmo = true -- Should draw the default HL2 ammo counter
SWEP.DrawCrosshair = true -- Should draw the default crosshair
SWEP.DrawWeaponInfoBox = true -- Should draw the weapon info box
SWEP.BounceWeaponIcon = true -- Should the weapon icon bounce?
SWEP.SwayScale = 1.0 -- The scale of the viewmodel sway
SWEP.BobScale = 1.0 -- The scale of the viewmodel bob
SWEP.RenderGroup = RENDERGROUP_OPAQUE
-- Override this in your SWEP to set the icon in the weapon selection
SWEP.WepSelectIcon = surface.GetTextureID( "weapons/swep" )
-- This is the corner of the speech bubble
SWEP.SpeechBubbleLid = surface.GetTextureID( "gui/speech_lid" )
--[[---------------------------------------------------------
You can draw to the HUD here - it will only draw when
the client has the weapon deployed..
-----------------------------------------------------------]]
function SWEP:DrawHUD()
end
--[[---------------------------------------------------------
Checks the objects before any action is taken
This is to make sure that the entities haven't been removed
-----------------------------------------------------------]]
function SWEP:DrawWeaponSelection( x, y, wide, tall, alpha )
-- Set us up the texture
surface.SetDrawColor( 255, 255, 255, alpha )
surface.SetTexture( self.WepSelectIcon )
-- Lets get a sin wave to make it bounce
local fsin = 0
if ( self.BounceWeaponIcon == true ) then
fsin = math.sin( CurTime() * 10 ) * 5
end
-- Borders
y = y + 10
x = x + 10
wide = wide - 20
-- Draw that mother
surface.DrawTexturedRect( x + fsin, y - fsin, wide - fsin * 2 , ( wide / 2 ) + fsin )
-- Draw weapon info box
self:PrintWeaponInfo( x + wide + 20, y + tall * 0.95, alpha )
end
--[[---------------------------------------------------------
This draws the weapon info box
-----------------------------------------------------------]]
function SWEP:PrintWeaponInfo( x, y, alpha )
if ( self.DrawWeaponInfoBox == false ) then return end
if (self.InfoMarkup == nil ) then
local str
local title_color = "<color=230,230,230,255>"
local text_color = "<color=150,150,150,255>"
str = "<font=HudSelectionText>"
if ( self.Author != "" ) then str = str .. title_color .. "Author:</color>\t" .. text_color .. self.Author .. "</color>\n" end
if ( self.Contact != "" ) then str = str .. title_color .. "Contact:</color>\t" .. text_color .. self.Contact .. "</color>\n\n" end
if ( self.Purpose != "" ) then str = str .. title_color .. "Purpose:</color>\n" .. text_color .. self.Purpose .. "</color>\n\n" end
if ( self.Instructions != "" ) then str = str .. title_color .. "Instructions:</color>\n" .. text_color .. self.Instructions .. "</color>\n" end
str = str .. "</font>"
self.InfoMarkup = markup.Parse( str, 250 )
end
surface.SetDrawColor( 60, 60, 60, alpha )
surface.SetTexture( self.SpeechBubbleLid )
surface.DrawTexturedRect( x, y - 64 - 5, 128, 64 )
draw.RoundedBox( 8, x - 5, y - 6, 260, self.InfoMarkup:GetHeight() + 18, Color( 60, 60, 60, alpha ) )
self.InfoMarkup:Draw( x + 5, y + 5, nil, nil, alpha )
end
--[[---------------------------------------------------------
Name: SWEP:FreezeMovement()
Desc: Return true to freeze moving the view
-----------------------------------------------------------]]
function SWEP:FreezeMovement()
return false
end
--[[---------------------------------------------------------
Name: SWEP:ViewModelDrawn( viewModel )
Desc: Called straight after the viewmodel has been drawn
-----------------------------------------------------------]]
function SWEP:ViewModelDrawn( vm )
end
--[[---------------------------------------------------------
Name: OnRestore
Desc: Called immediately after a "load"
-----------------------------------------------------------]]
function SWEP:OnRestore()
end
--[[---------------------------------------------------------
Name: CustomAmmoDisplay
Desc: Return a table
-----------------------------------------------------------]]
function SWEP:CustomAmmoDisplay()
end
--[[---------------------------------------------------------
Name: GetViewModelPosition
Desc: Allows you to re-position the view model
-----------------------------------------------------------]]
function SWEP:GetViewModelPosition( pos, ang )
return pos, ang
end
--[[---------------------------------------------------------
Name: TranslateFOV
Desc: Allows the weapon to translate the player's FOV (clientside)
-----------------------------------------------------------]]
function SWEP:TranslateFOV( current_fov )
return current_fov
end
--[[---------------------------------------------------------
Name: DrawWorldModel
Desc: Draws the world model (not the viewmodel)
-----------------------------------------------------------]]
function SWEP:DrawWorldModel()
self:DrawModel()
end
--[[---------------------------------------------------------
Name: DrawWorldModelTranslucent
Desc: Draws the world model (not the viewmodel)
-----------------------------------------------------------]]
function SWEP:DrawWorldModelTranslucent()
self:DrawModel()
end
--[[---------------------------------------------------------
Name: AdjustMouseSensitivity
Desc: Allows you to adjust the mouse sensitivity.
-----------------------------------------------------------]]
function SWEP:AdjustMouseSensitivity()
return nil
end
--[[---------------------------------------------------------
Name: GetTracerOrigin
Desc: Allows you to override where the tracer comes from (in first person view)
returning anything but a vector indicates that you want the default action
-----------------------------------------------------------]]
function SWEP:GetTracerOrigin()
--[[
local ply = self:GetOwner()
local pos = ply:EyePos() + ply:EyeAngles():Right() * -5
return pos
--]]
end
--[[---------------------------------------------------------
Name: FireAnimationEvent
Desc: Allows you to override weapon animation events
-----------------------------------------------------------]]
function SWEP:FireAnimationEvent( pos, ang, event, options )
if ( !self.CSMuzzleFlashes ) then return end
-- CS Muzzle flashes
if ( event == 5001 or event == 5011 or event == 5021 or event == 5031 ) then
local data = EffectData()
data:SetFlags( 0 )
data:SetEntity( self.Owner:GetViewModel() )
data:SetAttachment( math.floor( ( event - 4991 ) / 10 ) )
data:SetScale( 1 )
if ( self.CSMuzzleX ) then
util.Effect( "CS_MuzzleFlash_X", data )
else
util.Effect( "CS_MuzzleFlash", data )
end
return true
end
end

View File

@@ -0,0 +1,104 @@
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "ai_translations.lua" )
AddCSLuaFile( "sh_anim.lua" )
AddCSLuaFile( "shared.lua" )
include( "ai_translations.lua" )
include( "sh_anim.lua" )
include( "shared.lua" )
SWEP.Weight = 5 -- Decides whether we should switch from/to this
SWEP.AutoSwitchTo = true -- Auto switch to if we pick it up
SWEP.AutoSwitchFrom = true -- Auto switch from if you pick up a better weapon
--[[---------------------------------------------------------
Name: OnRestore
Desc: The game has just been reloaded. This is usually the right place
to call the GetNW* functions to restore the script's values.
-----------------------------------------------------------]]
function SWEP:OnRestore()
end
--[[---------------------------------------------------------
Name: AcceptInput
Desc: Accepts input, return true to override/accept input
-----------------------------------------------------------]]
function SWEP:AcceptInput( name, activator, caller, data )
return false
end
--[[---------------------------------------------------------
Name: KeyValue
Desc: Called when a keyvalue is added to us
-----------------------------------------------------------]]
function SWEP:KeyValue( key, value )
end
--[[---------------------------------------------------------
Name: Equip
Desc: A player or NPC has picked the weapon up
-----------------------------------------------------------]]
function SWEP:Equip( newOwner )
end
--[[---------------------------------------------------------
Name: EquipAmmo
Desc: The player has picked up the weapon and has taken the ammo from it
The weapon will be removed immidiately after this call.
-----------------------------------------------------------]]
function SWEP:EquipAmmo( newOwner )
end
--[[---------------------------------------------------------
Name: OnDrop
Desc: Weapon was dropped
-----------------------------------------------------------]]
function SWEP:OnDrop()
end
--[[---------------------------------------------------------
Name: ShouldDropOnDie
Desc: Should this weapon be dropped when its owner dies?
-----------------------------------------------------------]]
function SWEP:ShouldDropOnDie()
return true
end
--[[---------------------------------------------------------
Name: GetCapabilities
Desc: For NPCs, returns what they should try to do with it.
-----------------------------------------------------------]]
function SWEP:GetCapabilities()
return CAP_WEAPON_RANGE_ATTACK1
end
--[[---------------------------------------------------------
Name: NPCShoot_Secondary
Desc: NPC tried to fire secondary attack
-----------------------------------------------------------]]
function SWEP:NPCShoot_Secondary( shootPos, shootDir )
self:SecondaryAttack()
end
--[[---------------------------------------------------------
Name: NPCShoot_Secondary
Desc: NPC tried to fire primary attack
-----------------------------------------------------------]]
function SWEP:NPCShoot_Primary( shootPos, shootDir )
self:PrimaryAttack()
end
-- These tell the NPC how to use the weapon
AccessorFunc( SWEP, "fNPCMinBurst", "NPCMinBurst" )
AccessorFunc( SWEP, "fNPCMaxBurst", "NPCMaxBurst" )
AccessorFunc( SWEP, "fNPCFireRate", "NPCFireRate" )
AccessorFunc( SWEP, "fNPCMinRestTime", "NPCMinRest" )
AccessorFunc( SWEP, "fNPCMaxRestTime", "NPCMaxRest" )

View File

@@ -0,0 +1,87 @@
local ActIndex = {
[ "pistol" ] = ACT_HL2MP_IDLE_PISTOL,
[ "smg" ] = ACT_HL2MP_IDLE_SMG1,
[ "grenade" ] = ACT_HL2MP_IDLE_GRENADE,
[ "ar2" ] = ACT_HL2MP_IDLE_AR2,
[ "shotgun" ] = ACT_HL2MP_IDLE_SHOTGUN,
[ "rpg" ] = ACT_HL2MP_IDLE_RPG,
[ "physgun" ] = ACT_HL2MP_IDLE_PHYSGUN,
[ "crossbow" ] = ACT_HL2MP_IDLE_CROSSBOW,
[ "melee" ] = ACT_HL2MP_IDLE_MELEE,
[ "slam" ] = ACT_HL2MP_IDLE_SLAM,
[ "normal" ] = ACT_HL2MP_IDLE,
[ "fist" ] = ACT_HL2MP_IDLE_FIST,
[ "melee2" ] = ACT_HL2MP_IDLE_MELEE2,
[ "passive" ] = ACT_HL2MP_IDLE_PASSIVE,
[ "knife" ] = ACT_HL2MP_IDLE_KNIFE,
[ "duel" ] = ACT_HL2MP_IDLE_DUEL,
[ "camera" ] = ACT_HL2MP_IDLE_CAMERA,
[ "magic" ] = ACT_HL2MP_IDLE_MAGIC,
[ "revolver" ] = ACT_HL2MP_IDLE_REVOLVER
}
--[[---------------------------------------------------------
Name: SetWeaponHoldType
Desc: Sets up the translation table, to translate from normal
standing idle pose, to holding weapon pose.
-----------------------------------------------------------]]
function SWEP:SetWeaponHoldType( t )
t = string.lower( t )
local index = ActIndex[ t ]
if ( index == nil ) then
Msg( "SWEP:SetWeaponHoldType - ActIndex[ \"" .. t .. "\" ] isn't set! (defaulting to normal)\n" )
t = "normal"
index = ActIndex[ t ]
end
self.ActivityTranslate = {}
self.ActivityTranslate[ ACT_MP_STAND_IDLE ] = index
self.ActivityTranslate[ ACT_MP_WALK ] = index + 1
self.ActivityTranslate[ ACT_MP_RUN ] = index + 2
self.ActivityTranslate[ ACT_MP_CROUCH_IDLE ] = index + 3
self.ActivityTranslate[ ACT_MP_CROUCHWALK ] = index + 4
self.ActivityTranslate[ ACT_MP_ATTACK_STAND_PRIMARYFIRE ] = index + 5
self.ActivityTranslate[ ACT_MP_ATTACK_CROUCH_PRIMARYFIRE ] = index + 5
self.ActivityTranslate[ ACT_MP_RELOAD_STAND ] = index + 6
self.ActivityTranslate[ ACT_MP_RELOAD_CROUCH ] = index + 6
self.ActivityTranslate[ ACT_MP_JUMP ] = index + 7
self.ActivityTranslate[ ACT_RANGE_ATTACK1 ] = index + 8
self.ActivityTranslate[ ACT_MP_SWIM ] = index + 9
-- "normal" jump animation doesn't exist
if ( t == "normal" ) then
self.ActivityTranslate[ ACT_MP_JUMP ] = ACT_HL2MP_JUMP_SLAM
end
self:SetupWeaponHoldTypeForAI( t )
end
-- Default hold pos is the pistol
SWEP:SetWeaponHoldType( "pistol" )
--[[---------------------------------------------------------
Name: weapon:TranslateActivity()
Desc: Translate a player's Activity into a weapon's activity
So for example, ACT_HL2MP_RUN becomes ACT_HL2MP_RUN_PISTOL
Depending on how you want the player to be holding the weapon
-----------------------------------------------------------]]
function SWEP:TranslateActivity( act )
if ( self.Owner:IsNPC() ) then
if ( self.ActivityTranslateAI[ act ] ) then
return self.ActivityTranslateAI[ act ]
end
return -1
end
if ( self.ActivityTranslate[ act ] != nil ) then
return self.ActivityTranslate[ act ]
end
return -1
end

View File

@@ -0,0 +1,273 @@
-- Variables that are used on both client and server
SWEP.PrintName = "Scripted Weapon" -- 'Nice' Weapon name (Shown on HUD)
SWEP.Author = ""
SWEP.Contact = ""
SWEP.Purpose = ""
SWEP.Instructions = ""
SWEP.ViewModelFOV = 62
SWEP.ViewModelFlip = false
SWEP.ViewModel = "models/weapons/v_pistol.mdl"
SWEP.WorldModel = "models/weapons/w_357.mdl"
SWEP.Spawnable = false
SWEP.AdminOnly = false
SWEP.Primary.ClipSize = 8 -- Size of a clip
SWEP.Primary.DefaultClip = 32 -- Default number of bullets in a clip
SWEP.Primary.Automatic = false -- Automatic/Semi Auto
SWEP.Primary.Ammo = "Pistol"
SWEP.Secondary.ClipSize = 8 -- Size of a clip
SWEP.Secondary.DefaultClip = 32 -- Default number of bullets in a clip
SWEP.Secondary.Automatic = false -- Automatic/Semi Auto
SWEP.Secondary.Ammo = "Pistol"
--[[---------------------------------------------------------
Name: SWEP:Initialize()
Desc: Called when the weapon is first loaded
-----------------------------------------------------------]]
function SWEP:Initialize()
self:SetHoldType( "pistol" )
end
--[[---------------------------------------------------------
Name: SWEP:PrimaryAttack()
Desc: +attack1 has been pressed
-----------------------------------------------------------]]
function SWEP:PrimaryAttack()
-- Make sure we can shoot first
if ( !self:CanPrimaryAttack() ) then return end
-- Play shoot sound
self:EmitSound( "Weapon_AR2.Single" )
-- Shoot 9 bullets, 150 damage, 0.75 aimcone
self:ShootBullet( 150, 1, 0.01, self.Primary.Ammo )
-- Remove 1 bullet from our clip
self:TakePrimaryAmmo( 1 )
-- Punch the player's view
if ( !self.Owner:IsNPC() ) then self.Owner:ViewPunch( Angle( -1, 0, 0 ) ) end
end
--[[---------------------------------------------------------
Name: SWEP:SecondaryAttack()
Desc: +attack2 has been pressed
-----------------------------------------------------------]]
function SWEP:SecondaryAttack()
-- Make sure we can shoot first
if ( !self:CanSecondaryAttack() ) then return end
-- Play shoot sound
self:EmitSound("Weapon_Shotgun.Single")
-- Shoot 9 bullets, 150 damage, 0.75 aimcone
self:ShootBullet( 150, 9, 0.2, self.Secondary.Ammo )
-- Remove 1 bullet from our clip
self:TakeSecondaryAmmo( 1 )
-- Punch the player's view
if ( !self.Owner:IsNPC() ) then self.Owner:ViewPunch( Angle( -10, 0, 0 ) ) end
end
--[[---------------------------------------------------------
Name: SWEP:Reload()
Desc: Reload is being pressed
-----------------------------------------------------------]]
function SWEP:Reload()
self:DefaultReload( ACT_VM_RELOAD )
end
--[[---------------------------------------------------------
Name: SWEP:Think()
Desc: Called every frame
-----------------------------------------------------------]]
function SWEP:Think()
end
--[[---------------------------------------------------------
Name: SWEP:Holster( weapon_to_swap_to )
Desc: Weapon wants to holster
RetV: Return true to allow the weapon to holster
-----------------------------------------------------------]]
function SWEP:Holster( wep )
return true
end
--[[---------------------------------------------------------
Name: SWEP:Deploy()
Desc: Whip it out
-----------------------------------------------------------]]
function SWEP:Deploy()
return true
end
--[[---------------------------------------------------------
Name: SWEP:ShootEffects()
Desc: A convenience function to create shoot effects
-----------------------------------------------------------]]
function SWEP:ShootEffects()
self:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) -- View model animation
self.Owner:MuzzleFlash() -- Crappy muzzle light
self.Owner:SetAnimation( PLAYER_ATTACK1 ) -- 3rd Person Animation
end
--[[---------------------------------------------------------
Name: SWEP:ShootBullet()
Desc: A convenience function to shoot bullets
-----------------------------------------------------------]]
function SWEP:ShootBullet( damage, num_bullets, aimcone, ammo_type, force, tracer )
local bullet = {}
bullet.Num = num_bullets
bullet.Src = self.Owner:GetShootPos() -- Source
bullet.Dir = self.Owner:GetAimVector() -- Dir of bullet
bullet.Spread = Vector( aimcone, aimcone, 0 ) -- Aim Cone
bullet.Tracer = tracer || 5 -- Show a tracer on every x bullets
bullet.Force = force || 1 -- Amount of force to give to phys objects
bullet.Damage = damage
bullet.AmmoType = ammo_type || self.Primary.Ammo
self.Owner:FireBullets( bullet )
self:ShootEffects()
end
--[[---------------------------------------------------------
Name: SWEP:TakePrimaryAmmo()
Desc: A convenience function to remove ammo
-----------------------------------------------------------]]
function SWEP:TakePrimaryAmmo( num )
-- Doesn't use clips
if ( self:Clip1() <= 0 ) then
if ( self:Ammo1() <= 0 ) then return end
self.Owner:RemoveAmmo( num, self:GetPrimaryAmmoType() )
return end
self:SetClip1( self:Clip1() - num )
end
--[[---------------------------------------------------------
Name: SWEP:TakeSecondaryAmmo()
Desc: A convenience function to remove ammo
-----------------------------------------------------------]]
function SWEP:TakeSecondaryAmmo( num )
-- Doesn't use clips
if ( self:Clip2() <= 0 ) then
if ( self:Ammo2() <= 0 ) then return end
self.Owner:RemoveAmmo( num, self:GetSecondaryAmmoType() )
return end
self:SetClip2( self:Clip2() - num )
end
--[[---------------------------------------------------------
Name: SWEP:CanPrimaryAttack()
Desc: Helper function for checking for no ammo
-----------------------------------------------------------]]
function SWEP:CanPrimaryAttack()
if ( self:Clip1() <= 0 ) then
self:EmitSound( "Weapon_Pistol.Empty" )
self:SetNextPrimaryFire( CurTime() + 0.2 )
self:Reload()
return false
end
return true
end
--[[---------------------------------------------------------
Name: SWEP:CanSecondaryAttack()
Desc: Helper function for checking for no ammo
-----------------------------------------------------------]]
function SWEP:CanSecondaryAttack()
if ( self:Clip2() <= 0 ) then
self:EmitSound( "Weapon_Pistol.Empty" )
self:SetNextSecondaryFire( CurTime() + 0.2 )
return false
end
return true
end
--[[---------------------------------------------------------
Name: OnRemove
Desc: Called just before entity is deleted
-----------------------------------------------------------]]
function SWEP:OnRemove()
end
--[[---------------------------------------------------------
Name: OwnerChanged
Desc: When weapon is dropped or picked up by a new player
-----------------------------------------------------------]]
function SWEP:OwnerChanged()
end
--[[---------------------------------------------------------
Name: Ammo1
Desc: Returns how much of ammo1 the player has
-----------------------------------------------------------]]
function SWEP:Ammo1()
return self.Owner:GetAmmoCount( self:GetPrimaryAmmoType() )
end
--[[---------------------------------------------------------
Name: Ammo2
Desc: Returns how much of ammo2 the player has
-----------------------------------------------------------]]
function SWEP:Ammo2()
return self.Owner:GetAmmoCount( self:GetSecondaryAmmoType() )
end
--[[---------------------------------------------------------
Name: SetDeploySpeed
Desc: Sets the weapon deploy speed.
This value needs to match on client and server.
-----------------------------------------------------------]]
function SWEP:SetDeploySpeed( speed )
self.m_WeaponDeploySpeed = tonumber( speed )
end
--[[---------------------------------------------------------
Name: DoImpactEffect
Desc: Callback so the weapon can override the impact effects it makes
return true to not do the default thing - which is to call UTIL_ImpactTrace in c++
-----------------------------------------------------------]]
function SWEP:DoImpactEffect( tr, nDamageType )
return false
end

View File

@@ -0,0 +1,16 @@
function We(x)
return x/1920*ScrW()
end
function He(y)
return y/1080*ScrH()
end
include('shared.lua')
include('client/cl_hud.lua')
include('client/cl_menu.lua')
include("client/cl_abilities.lua")
include("client/cl_cutscenes.lua")
include("client/cl_outline.lua")
include("client/cl_other.lua")
include("client/cl_buymenu.lua")

View File

@@ -0,0 +1,699 @@
local meta = FindMetaTable("Player")
net.Receive("SuR.ClientRunString", function()
local str = net.ReadString()
RunString(str)
end)
net.Receive("SuR.PlaySoundOnClient", function()
local str = net.ReadString()
if string.match(str, "https://") then
sound.PlayURL(str, "", function(st)
if IsValid(st) then
st:Play()
end
end)
else
surface.PlaySound(str)
end
end)
function SuR:GetRandomSound(path)
local fil, dir = file.Find("sound/"..path.."*", "GAME")
if #fil > 0 then
local snd = path..fil[math.random(1,#fil)]
return snd
else
return ""
end
end
function meta:PlayVoiceLine(type, chance)
if chance and chance < math.random(1,100) then return end
local snd = ""
local nodelay = false
local death = !self:Alive()
local voice = self:GetNWString("VoicePack")
local tab = SuR.Config.VoicePacks[voice]
if istable(tab) then
if type == "pain" then
snd = SuR:GetRandomSound(tab["pain"])
nodelay = true
elseif type == "death" then
snd = SuR:GetRandomSound(tab["death"])
nodelay = true
death = false
elseif type == "reload" then
snd = SuR:GetRandomSound(tab["reload"])
elseif type == "enemyback" then
snd = SuR:GetRandomSound(tab["enemyback"])
nodelay = true
elseif type == "enemydown" then
snd = SuR:GetRandomSound(tab["enemydown"])
elseif type == "pickup" then
snd = SuR:GetRandomSound(tab["pickup"])
elseif type == "noammo" then
snd = SuR:GetRandomSound(tab["noammo"])
elseif type == "downed" then
snd = SuR:GetRandomSound(tab["downed"])
nodelay = true
elseif type == "friendlyfire" then
snd = SuR:GetRandomSound(tab["friendlyfire"])
elseif type == "frienddied" then
snd = SuR:GetRandomSound(tab["frienddied"])
elseif type == "lowhp" then
snd = SuR:GetRandomSound(tab["lowhp"])
elseif type == "infected" then
snd = SuR:GetRandomSound(tab["infected"])
nodelay = true
elseif type == "enemyspotted" then
snd = SuR:GetRandomSound(tab["enemyspotted"])
nodelay = true
elseif type == "thanks" then
snd = SuR:GetRandomSound(tab["thanks"])
elseif type == "cover" then
snd = SuR:GetRandomSound(tab["cover"])
end
end
if type == "zombie_death" then
local str = "vj_lnrhl2/walker_male/die0"..math.random(1,5)..".wav"
snd = str
nodelay = true
death = false
elseif type == "zombie_idle" then
local str = "vj_lnrhl2/infected/zomb_runner_male1-idle-0"..math.random(1,9)..".wav"
snd = str
elseif type == "zombie_attack" then
local rnd = math.random(1,22)
local str = "vj_lnrhl2/walker_male/attack_sham_m_"
if rnd > 9 then
str = str..rnd..".wav"
else
str = str.."0"..rnd..".wav"
end
snd = str
snd = str
elseif type == "zombie_pain" then
local str = "vj_lnrhl2/walker_male/pain0"..math.random(1,5)..".wav"
snd = str
nodelay = true
end
if death then return end
if not self.PreviousVoiceLine then
self.PreviousVoiceLine = 0
end
if not self.PreviousVoiceLineString then
self.PreviousVoiceLineString = ""
end
if snd != "" and (self.PreviousVoiceLine < CurTime() or nodelay) then
snd = ")"..snd
self.PreviousVoiceLine = CurTime()+4
self:StopSound(self.PreviousVoiceLineString)
self.PreviousVoiceLineString = snd
self:EmitSound(snd)
end
end
net.Receive("SuR.VoiceLines", function(len, ply)
local data = net.ReadTable()
if IsEntity(data[1]) and data[1].PlayVoiceLine then
data[1]:PlayVoiceLine(data[2], data[3])
end
end)
local arrowMat = Material('surrounded/arrow.png')
net.Receive("SuR.PointMarker", function()
local vec = net.ReadVector()
local str = net.ReadString()
local delay = CurTime()+120
hook.Add("HUDPaint", "SuR_PointMarker", function()
local pos = vec:ToScreen()
surface.SetMaterial(arrowMat)
surface.SetDrawColor(255,255,255)
surface.DrawTexturedRect(pos.x-16,pos.y-16,32,32)
draw.SimpleText(math.Round(LocalPlayer():GetPos():Distance(vec) * 2/100) .. " m", "SuR_SmallFont1", pos.x+20, pos.y, color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
if str != "" then
draw.SimpleText(str, "SuR_SmallFont1", pos.x, pos.y-20, Color(240,220,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
end
if delay < CurTime() or !SuR.Data["DrawHUD"] then
hook.Remove("HUDPaint", "SuR_PointMarker")
end
end)
end)
------------------------------------------------------------------------JUMP PART
local jumpDelay = 1
local lastJumpTime = 0
hook.Add("PlayerBindPress", "JumpDelay", function(ply, key)
if ply:Alive() and key == "+jump" and lastJumpTime < CurTime() then
lastJumpTime = CurTime()+jumpDelay
return false
elseif ply:Alive() and key == "+jump" and ply:OnGround() and lastJumpTime >= CurTime() then
return true
end
end)
------------------------------------------------------------------------CAM PART
local currentpos = Vector(0,0,0)
local currentang = Angle(0,0,0)
local changeview = true
local viewbob_speed = 10
local viewbob_amount = 0.01
local viewbob_offset = 0
local last_velocity = 0
local left_side = false
local FPOffsetAngles = Angle(0,0,0)
local fp_offset = {x = 0, y = 0, z = 0}
hook.Add("PlayerButtonDown", "MainCamButtons", function(ply, but)
if but == KEY_CAPSLOCK and not ply:IsTyping() then
left_side = !left_side
end
end)
hook.Add("CalcView", "MainCam", function( ply, pos, angles, fov )
if ply:Alive() then
local body = ply
if IsValid(ply:GetNWEntity("CameraEnt")) then
body = ply:GetNWEntity("CameraEnt")
end
local curmask = MASK_SHOT_HULL
local plyang = ply:EyeAngles()
local headpos = body:GetBonePosition(body:LookupBone("ValveBiped.Bip01_Head1"))
local needpos = headpos - angles:Forward()*18 + angles:Right()*16 - angles:Up()*2
if ply:IsZombie() then
needpos = headpos - angles:Forward()*32 + angles:Right()*20 - angles:Up()*2
if left_side then
needpos = headpos - angles:Forward()*32 - angles:Right()*20 - angles:Up()*2
end
elseif not ply:IsZombie() and left_side then
needpos = headpos - angles:Forward()*18 - angles:Right()*16 - angles:Up()*2
end
local limitpos = headpos
local cutscene = ply:GetNWBool('SVAnimStopCutscene')
local person = GetConVar("sur_viewmod"):GetFloat()
local person_cutscene = GetConVar("sur_viewmod_cutscene"):GetFloat()
local person_da = GetConVar("sur_viewmod_deathanims"):GetFloat()
local wep = ply:GetActiveWeapon()
local person_da_check = false
if ply:KeyDown(IN_ATTACK2) and changeview and IsValid(wep) and isstring(wep.Base) and string.match(wep.Base, "tfa") and wep:GetMaxClip1() > 0 and person > 0 then
changeview = false
ply:ScreenFade(SCREENFADE.IN, color_black, 0.3, 0)
elseif not ply:KeyDown(IN_ATTACK2) and not changeview then
changeview = true
ply:ScreenFade(SCREENFADE.IN, color_black, 0.3, 0)
end
local tp_enable = person == 2 and not cutscene or (cutscene or ply:IsDowned()) and person_cutscene == 1
local fp_enable = person == 1 and not cutscene or (cutscene or ply:IsDowned()) and person_cutscene == 0
if person_da == 0 and (string.match(ply:GetSVAnim(), "killmove") or string.match(ply:GetSVAnim(), "executions")) then
fp_enable = true
tp_enable = false
person_da_check = true
elseif person_da == 1 and (string.match(ply:GetSVAnim(), "killmove") or string.match(ply:GetSVAnim(), "executions")) then
tp_enable = true
fp_enable = false
person_da_check = true
end
if fp_enable and not tp_enable then
ply:ManipulateBoneScale(ply:LookupBone("ValveBiped.Bip01_Head1"), Vector(0,0,0))
else
ply:ManipulateBoneScale(ply:LookupBone("ValveBiped.Bip01_Head1"), Vector(1,1,1))
end
if tp_enable then
if cutscene or ply:IsDowned() or person_da_check then
local pos2 = pos
if string.match(ply:GetSVAnim(), "killmove") or string.match(ply:GetSVAnim(), "executions") or string.match(ply:GetSVAnim(), "killanim") then
pos2 = body:GetBonePosition(body:LookupBone("ValveBiped.Bip01_Head1"))
pos2.z = ply:EyePos().z-16
curmask = MASK_SOLID_BRUSHONLY
end
needpos = pos2 - angles:Forward()*64 + angles:Right()*32 + ply:GetNWVector('CutsceneAddPos')
if left_side then
needpos = pos2 - angles:Forward()*64 - angles:Right()*32 + ply:GetNWVector('CutsceneAddPos')
plyang = plyang + Angle(10,-20,0)
if string.match(ply:GetSVAnim(), "closeencounter") then
needpos = pos2 - angles:Forward()*32 - angles:Right()*48 + ply:GetNWVector('CutsceneAddPos')
plyang = plyang + Angle(15,-30,0)
plyang.z = math.Clamp(ply:GetAttachment(ply:LookupAttachment('eyes')).Ang.z/2, -45, 45)
curmask = MASK_SOLID_BRUSHONLY
elseif string.match(ply:GetSVAnim(), "killanim") then
local att = ply:GetAttachment(ply:LookupAttachment('eyes'))
needpos = pos2 - angles:Forward()*32 - angles:Right()*48 + ply:GetNWVector('CutsceneAddPos')
plyang = plyang + Angle(0,-20,0)
plyang.x = -(needpos-att.Pos):GetNormalized():Angle().x+15
plyang.z = math.Clamp(att.Ang.z/4, -45, 45)
curmask = MASK_SOLID_BRUSHONLY
end
else
plyang = plyang + Angle(10,20,0)
if string.match(ply:GetSVAnim(), "closeencounter") then
needpos = pos2 - angles:Forward()*32 + angles:Right()*48 + ply:GetNWVector('CutsceneAddPos')
plyang = plyang + Angle(15,30,0)
plyang.z = math.Clamp(ply:GetAttachment(ply:LookupAttachment('eyes')).Ang.z/2, -45, 45)
curmask = MASK_SOLID_BRUSHONLY
elseif string.match(ply:GetSVAnim(), "killanim") then
local att = ply:GetAttachment(ply:LookupAttachment('eyes'))
needpos = pos2 - angles:Forward()*32 + angles:Right()*48 + ply:GetNWVector('CutsceneAddPos')
plyang = plyang + Angle(0,20,0)
plyang.x = -(needpos-att.Pos):GetNormalized():Angle().x+15
plyang.z = math.Clamp(att.Ang.z/4, -45, 45)
curmask = MASK_SOLID_BRUSHONLY
end
end
if ply:IsDowned() and ply:GetSVAnim() == "" then
needpos = needpos + angles:Up()*36
end
end
currentpos = LerpVector(FrameTime()*6, currentpos, needpos)
currentang = LerpAngle(FrameTime()*12, currentang, plyang)
local tr = util.TraceLine({
start = limitpos,
endpos = currentpos,
mask = curmask,
filter = ply,
})
local wep = ply:GetActiveWeapon()
if changeview then
local view = {
origin = tr.HitPos,
angles = currentang,
fov = fov,
drawviewer = true,
nearz = 1
}
return view
else
currentpos = limitpos
end
elseif fp_enable then
local ang1 = angles
currentpos = limitpos
if changeview then
local eye = body:GetAttachment(body:LookupAttachment('eyes'))
if string.match(ply:GetSVAnim(), "sur_executions_") and body:LookupAttachment('custom_eyes') > 0 then
eye = body:GetAttachment(body:LookupAttachment('custom_eyes'))
end
if cutscene then
ang1 = eye.Ang
end
local view = {
origin = eye.Pos,
angles = ang1,
fov = fov,
drawviewer = true,
nearz = 1
}
return view
end
else
currentpos = limitpos
currentang = angles
if ply:Alive() and not ply:ShouldDrawLocalPlayer() then
local velocity = ply:GetVelocity():Length()
if velocity > 0 and last_velocity == 0 then
viewbob_offset = 0
end
last_velocity = velocity
viewbob_offset = viewbob_offset + (viewbob_speed * FrameTime())
local bob_x = math.sin(viewbob_offset) * viewbob_amount * last_velocity
local bob_y = math.cos(viewbob_offset) * viewbob_amount * last_velocity
angles.roll = angles.roll + bob_y/2
angles.x = angles.x + bob_x/4
local view = {}
view.origin = pos
view.angles = angles+FPOffsetAngles
view.fov = fov
local power = ply:GetVelocity():Length()/25
local num1 = math.Clamp(power, 0, 10)
if ply:KeyDown(IN_MOVELEFT) then
fp_offset.z = -num1
elseif ply:KeyDown(IN_MOVERIGHT) then
fp_offset.z = num1
else
fp_offset.z = 0
end
if ply:KeyDown(IN_FORWARD) and !ply:KeyDown(IN_ATTACK2) then
fp_offset.x = num1
elseif ply:KeyDown(IN_BACK) and !ply:KeyDown(IN_ATTACK2) then
fp_offset.x = -num1
else
fp_offset.x = 0
end
FPOffsetAngles = LerpAngle(FrameTime()*4, FPOffsetAngles, Angle(fp_offset.x, fp_offset.y, fp_offset.z))
return view
end
end
end
end)
------------------------------------------------------------------------BOSS PART
local barMat = Material('surrounded/bar.png', 'smooth')
net.Receive("SuR.Boss", function()
local name = SuR.Language[net.ReadString()]
local ent = net.ReadEntity()
local alpha = 0
local morealpha = true
hook.Add("HUDPaint", "SuR_Boss", function()
surface.SetMaterial(barMat)
surface.SetDrawColor(0,0,0,alpha)
surface.DrawTexturedRect(ScrW()/2-We(240), He(30), We(480), He(50))
if IsValid(ent) then
local mult = (ent:Health()/ent:GetMaxHealth())
surface.SetMaterial(barMat)
surface.SetDrawColor(150,0,0,alpha)
render.SetScissorRect( ScrW()/2-We(240), He(30), ScrW()/2+We(480*mult-240), He(80), true )
surface.DrawTexturedRect(ScrW()/2-We(235), He(35), We(470), He(40))
render.SetScissorRect( 0, 0, 0, 0, false )
else
morealpha = false
end
draw.SimpleText(name, "SuR_SmallFont2", ScrW()/2, He(25), Color(255,255,255,alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
if morealpha then
alpha = math.Clamp(alpha+FrameTime()/0.01, 0, 255)
else
alpha = math.Clamp(alpha-FrameTime()/0.01, 0, 255)
if alpha == 0 then
hook.Remove("HUDPaint", "SuR_Boss")
end
end
end)
end)
------------------------------------------------------------------------MUSIC PART
local rndmusic = ""
local musicname = ""
local currentchannel = nil
local otherchannel = nil
local function RandomizeTrack()
local tab = SuR.Config.MusicWave
local wave = SuR.Data["Wave"]
if SuR.Data["ExfilWave"] and SuR.Data["WaveState"] then
rndmusic = tab["Exfil"][math.random(1,#tab["Exfil"])]
return
end
if SuR.Config.Objective_Mode then
rndmusic = tab["Objective"][math.random(1,#tab["Objective"])]
return
end
for k, v in pairs(tab) do
local allow = false
if (k == "Easy" and wave < 3) or (k == "Medium" and wave >= 3 and wave < 6) or (k == "Hard" and wave >= 6 and wave < 10) or (k == "Chaos" and wave >= 10 and wave < 15) or (k == "Extreme" and wave >= 15) then
allow = true
end
if allow then
rndmusic = v[math.random(1,#v)]
break
end
end
end
hook.Add("Think", "MainMusic", function()
local wave = SuR.Data["Wave"]
local wavest = SuR.Data["WaveState"]
if wavest and wave > 0 and not SuR.Data["DisableMusic"] then
SuR:PlayMusic(rndmusic)
if IsValid(currentchannel) then
local maxtime = currentchannel:GetLength()
local time = currentchannel:GetTime()
currentchannel:SetVolume(GetConVar("sur_music_volume"):GetFloat())
if time >= maxtime or currentchannel:GetState() == 0 or currentchannel:GetState() == 2 or (SuR.Data["ExfilWave"] and SuR.Data["WaveState"] and !table.HasValue(SuR.Config.MusicWave["Exfil"], rndmusic)) then
RandomizeTrack()
SuR:PlayMusic("")
end
end
else
if IsValid(currentchannel) then
local volume = currentchannel:GetVolume()
currentchannel:SetVolume(math.max(volume-FrameTime()/2, 0))
if volume == 0 then
SuR:PlayMusic("")
end
end
RandomizeTrack()
end
if IsValid(otherchannel) then
otherchannel:SetVolume(GetConVar("sur_music_volume"):GetFloat())
end
end)
function SuR:PlayMusicOther(str)
if IsValid(otherchannel) then
otherchannel:Stop()
end
sound.PlayFile("sound/"..str, "noblock", function(station, s1, s2)
if IsValid(station) then
station:Play()
station:SetVolume(GetConVar("sur_music_volume"):GetFloat())
otherchannel = station
end
end)
end
function SuR:PlayMusic(music1, rnd)
local music = "sound/"..music1
if rnd then
RandomizeTrack()
music1 = rndmusic
end
if music1 != "" then
if musicname == music1 then
return
else
if IsValid(currentchannel) then
currentchannel:Stop()
currentchannel = nil
end
timer.Simple(1, function()
sound.PlayFile(music, "noblock", function(station, s1, s2)
if IsValid(station) then
station:Play()
currentchannel = station
end
end)
end)
end
musicname = music1
else
musicname = ""
if IsValid(currentchannel) then
currentchannel:Stop()
currentchannel = nil
end
end
end
timer.Simple(0.5, function()
local f = file.Read("surrounded/music_replacement.lua", "LUA")
if !isstring(f) then return end
local pattern = "start_config.-end_config"
local musicWaveTable = string.match(f, pattern)
if !musicWaveTable then return end
musicWaveTable = string.Replace(musicWaveTable, "start_config", "SuR.Config.MusicWave = {")
musicWaveTable = string.Replace(musicWaveTable, "end_config", "}")
RunString(musicWaveTable)
end)
------------------------------------------------------------------------ANIM PART
local disable_tab = {
["sur_helpup_trials_follower_try"] = true,
["sur_helpup_trials_leader_try"] = true,
["sur_helpup_trials_follower_success"] = true,
["sur_helpup_trials_leader_success"] = true,
["sur_helpup_trials_follower_drophigh"] = true,
["sur_helpup_trials_leader_leave"] = true,
}
hook.Add("AdjustMouseSensitivity", "SuR_Sens", function()
local ply = LocalPlayer()
local downed = ply:IsDowned()
local disable = disable_tab[ply:GetSVAnim()]
if downed then
return 0.1
end
if disable then
return 0.001
end
if ply:IsZombie() and ply:Alive() then
return 0.5
end
end)
hook.Add("CalcMainActivity", "MainAnims", function(ply, vel)
local str = ply:GetSVAnim()
local num = ply:GetNWFloat('SVAnimDelay')
local st = ply:GetNWFloat('SVAnimStartTime')
local downed = ply:IsDowned()
local dir = ply:GetNWString("MoveDirection")
if str != "" then
ply:SetCycle((CurTime()-st)/num)
return -1, ply:LookupSequence(str)
end
if downed then
if ply:GetCycle() == 1 then
ply:SetCycle(0)
end
local speed = ply:GetVelocity():Length()
if speed > 5 then
if dir == "forward" then
return -1, ply:LookupSequence("sur_downed_trials_forward")
elseif dir == "backward" then
return -1, ply:LookupSequence("sur_downed_trials_backward")
elseif dir == "left" then
return -1, ply:LookupSequence("sur_downed_trials_left")
elseif dir == "right" then
return -1, ply:LookupSequence("sur_downed_trials_right")
else
return -1, ply:LookupSequence("sur_downed_trials_idle")
end
else
return -1, ply:LookupSequence("sur_downed_trials_idle")
end
end
if ply:IsZombie() then
local speed = vel:Length()
local cr = ply:Crouching()
if !ply:OnGround() then
return ACT_JUMP, -1
elseif speed > 200 and not cr then
return ACT_SPRINT, -1
elseif speed > 75 and not cr or cr and speed > 25 then
if cr then
return ACT_WALK_AGITATED, -1
else
return ACT_RUN, -1
end
elseif speed > 10 then
if cr then
return ACT_WALK_STIMULATED, -1
else
if ply:GetModel() == "models/vj_lnrspecials/brute.mdl" then
return ACT_WALK_AIM, -1
else
return ACT_WALK, -1
end
end
else
if cr then
return ACT_IDLE_STIMULATED, -1
else
return ACT_IDLE, -1
end
end
end
end)
------------------------------------------------------------------------MARK PART
local num_marks = 0
local mat_markpoint = Material("surrounded/marks/point.png")
local mat_markitem = Material("surrounded/marks/item.png")
local mat_markenemy = Material("surrounded/marks/enemy.png")
function screen_distance(x1, y1, x2, y2)
local dif = Vector(x1, y1):Distance(Vector(x2, y2))
return dif
end
net.Receive("SuR.PointMark", function()
local type = net.ReadString()
local ply = net.ReadEntity()
local data = net.ReadTable()[1]
if not data then return end
local mat = mat_markpoint
if type == "item" then
mat = mat_markitem
surface.PlaySound("surrounded/sfx/mark_item.mp3")
elseif type == "enemy" then
mat = mat_markenemy
surface.PlaySound("surrounded/sfx/mark_enemy.mp3")
else
surface.PlaySound("surrounded/sfx/mark_point.mp3")
end
num_marks = num_marks + 1
local name = "SuR_PointMark"..num_marks
local nick = ply:Nick()
local alpha = 255
local height = ScrH()/2
hook.Add("HUDPaint", name.."n", function()
draw.SimpleText(nick .. SuR.Language["message_mark"], "SuR_SmallFont1", We(50), height, Color(255,255,255,alpha), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
height = height - FrameTime()/0.01
alpha = alpha - FrameTime()/0.005
if alpha <= 0 then
hook.Remove("HUDPaint", name.."n")
end
end)
hook.Add("HUDPaint", name, function()
if !LocalPlayer():Alive() then
hook.Remove("HUDPaint", name)
return
end
local pos = Vector()
if isvector(data) then
pos = data
else
if !IsValid(data) then
hook.Remove("HUDPaint", name)
return
end
pos = data:WorldSpaceCenter()
end
local spos = pos:ToScreen()
local dist = screen_distance(ScrW()/2, ScrH()/2, spos.x, spos.y) < 50
if dist then
surface.SetDrawColor(255,255,255,230)
surface.SetMaterial(mat)
surface.DrawTexturedRect(spos.x-We(32), spos.y-He(32), We(64), He(64))
draw.SimpleText(nick, "SuR_PixelFont", spos.x, spos.y+He(40), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
draw.SimpleText(math.Round(LocalPlayer():GetPos():Distance(pos) * 2/100) .. " m", "SuR_SmallFont1", spos.x, spos.y+He(55), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
else
surface.SetDrawColor(255,255,255,150)
surface.SetMaterial(mat)
surface.DrawTexturedRect(spos.x-We(12), spos.y-He(12), We(24), He(24))
draw.SimpleText(math.Round(LocalPlayer():GetPos():Distance(pos) * 2/100) .. " m", "SuR_PixelFont", spos.x, spos.y+He(20), Color(255,255,255,150), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
end)
timer.Simple(30, function()
hook.Remove("HUDPaint", name)
end)
end)

View File

@@ -0,0 +1,119 @@
local bg = Material('surrounded/vgui_bg.png')
local lang = SuR.Language
function SuR:OpenBuyMenu()
local df = vgui.Create("DFrame")
df:SetSize(We(600), He(425))
df:Center()
df:SetTitle("")
df:MakePopup()
df:ShowCloseButton(false)
df.Paint = function(self, w, h)
surface.SetMaterial(bg)
surface.SetDrawColor(0,0,0,230)
surface.DrawTexturedRect(0, 0, w, h)
draw.SimpleText(lang["buymenu_main"], "SuR_SmallFont2", We(30), He(15), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
end
local db = vgui.Create("DButton", df)
db:SetSize(We(32), He(32))
db:SetPos(We(540),He(15))
db:SetText("")
function db:Paint(w, h)
if self:IsHovered() then
draw.SimpleText("X", "SuR_MediumFont1", w/2, h/2, Color(200,255,200), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
else
draw.SimpleText("X", "SuR_MediumFont1", w/2, h/2, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
end
function db:DoClick()
surface.PlaySound("surrounded/click.mp3")
df:Remove()
end
function db:OnCursorEntered()
surface.PlaySound("surrounded/tick.wav")
end
local frame = vgui.Create("DPanel", df)
frame:SetPos(We(30), He(50))
frame:SetSize(We(530), He(350))
function frame:Paint(w, h) end
local propertySheet = vgui.Create("DPropertySheet", frame)
propertySheet:Dock(FILL)
for categoryName, items in SortedPairs(SuR.Config.TierWeapons) do
if categoryName == "Melee" or categoryName == "Other" or categoryName == "Tier1" then continue end
local panel = vgui.Create("DPanel", frame)
panel:Dock(FILL)
panel.Paint = function(self, w, h)
surface.SetDrawColor(0,0,0)
surface.DrawRect(0, 0, w, h)
end
local scrollPanel = vgui.Create("DScrollPanel", panel)
scrollPanel:Dock(FILL)
local list = vgui.Create("DIconLayout", scrollPanel)
list:Dock(FILL)
list:SetSpaceY(5)
list:SetSpaceX(5)
for _, item in ipairs(items) do
local wep = weapons.Get(item)
if !wep then continue end
local price = 50
if categoryName == "Tier2" then price = SuR.Config.Tier2_Price end
if categoryName == "Tier3" then price = SuR.Config.Tier3_Price end
if categoryName == "Tier4" then price = SuR.Config.Tier4_Price end
if categoryName == "Tier5" then price = SuR.Config.Tier5_Price end
local itemPanel = list:Add("DPanel")
itemPanel:SetSize(530, 100)
itemPanel.Paint = function(self, w, h)
surface.SetDrawColor(50,50,50)
surface.DrawRect(0, 0, w, h)
end
local icon = vgui.Create("DImage", itemPanel)
icon:SetImage("entities/"..item..".png")
icon:SetSize(We(88), He(88))
icon:SetPos(We(5), He(5))
local nameLabel = vgui.Create("DLabel", itemPanel)
nameLabel:SetText(wep.PrintName)
nameLabel:SetFont("SuR_SmallFont2")
nameLabel:SizeToContents()
nameLabel:SetPos(We(100), He(10))
local priceLabel = vgui.Create("DLabel", itemPanel)
priceLabel:SetText("Price: $" .. price)
priceLabel:SetFont("SuR_SmallFont1")
priceLabel:SizeToContents()
priceLabel:SetPos(We(100), He(35))
local buyButton = vgui.Create("DButton", itemPanel)
buyButton:SetText(lang["buymenu_buy"])
buyButton:SetFont("SuR_SmallFont1")
buyButton:SetPos(We(100), He(60))
buyButton:SetSize(100, 30)
buyButton.DoClick = function()
net.Start("SuR.BuyMenu")
net.WriteString(item)
net.SendToServer()
if LocalPlayer():GetNWInt('Money') < price then
surface.PlaySound("buttons/combine_button_locked.wav")
else
surface.PlaySound("buttons/lightswitch2.wav")
end
end
end
propertySheet:AddSheet(categoryName, panel, "icon16/folder.png")
end
end

View File

@@ -0,0 +1,237 @@
local lang = SuR.Language
local vinMat = Material('surrounded/vin.png')
local anims_tab = {
"sur_idles_m_armsback_",
"sur_idles_m_armsfront_",
"sur_idles_m_headache_",
"sur_idles_m_hipleft_",
"sur_idles_m_hipright_",
"sur_idles_m_hips_",
"sur_idles_m_neckache_",
}
local currentPointIndex = 1
local startTime = 0
local lastdatacam = {}
local modelcamtab = {}
local last_count_number = 0
local function CreateCamModels(data)
for _, e in pairs(modelcamtab) do
if !IsValid(e) then continue end
e:Remove()
end
modelcamtab = {}
local ply_tab, ply_index = player.GetAll(), 0
for k, v in pairs(data.model) do
ply_index = ply_index + 1
local tar = ply_tab[ply_index]
if !IsValid(tar) then continue end
local anim = anims_tab[math.random(1,#anims_tab)]
local model = ClientsideModel(tar:GetModel())
modelcamtab[#modelcamtab+1] = model
model.active_seq = anim.."loop"
model.next_seq = anim.."toready"
model.active_seq_noloop = false
model.player = tar
model:ResetSequence(anim.."loop")
model:SetPos(v.pos)
model:SetAngles(v.ang)
model:SetEyeTarget(data.cam[#data.cam].pos)
model:SetCycle(math.Rand(0,1))
end
end
local function ready_up_anim()
for k, v in pairs(modelcamtab) do
v:SetCycle(0)
v:ResetSequence(v.next_seq)
v.active_seq = v.next_seq
v.active_seq_noloop = true
end
timer.Simple(4, function()
LocalPlayer():ScreenFade(SCREENFADE.OUT, color_black, 1, 2)
end)
timer.Simple(5, function()
surface.PlaySound("surrounded/sfx/deploy_begin.mp3")
SuR:StopDeployCutscene()
end)
end
function SuR:StartDeployCutscene(cdata)
local data = table.Copy(cdata)
table.Shuffle(data.model)
if !data.cam then return end
SuR:PlayMusicOther(table.Random(SuR.Config.MusicWave["Deploy"]))
SuR:StopDeployCutscene()
table.insert(data.cam, 1, data.cam[1])
LocalPlayer():ScreenFade(SCREENFADE.IN, color_black, 1, 1)
CreateCamModels(data)
local mode = "survival"
if SuR.Config.Objective_Mode then
mode = "objective"
elseif SuR.Config.Versus_Mode then
mode = "versus"
end
local team_ready = false
hook.Add("HUDPaint", "SuR_DeployCutscene", function()
surface.SetMaterial(vinMat)
surface.SetDrawColor(0,0,0,200)
surface.DrawTexturedRect(0, 0, ScrW(), ScrH())
local ortime = SuR.Data["DeployTime"]-CurTime()
local dtime = math.floor(ortime)
if SuR.Data["Deploying"] and dtime >= 0 and SuR.Data["DrawHUD"] then
if dtime > 5 then
draw.SimpleText(lang["mode"]..lang["mode_"..mode], "SuR_SmallFont1", ScrW()/2, ScrH()-He(160), Color(200,200,50), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
draw.SimpleText(string.format(lang["deploy_time"], dtime), "SuR_MediumFont1", ScrW()/2, ScrH()-He(130), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
else
draw.SimpleText(dtime, "SuR_LargeFont1", ScrW()/2, ScrH()-He(200), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
draw.SimpleText(lang["deploy_hint"], "SuR_SmallFont1", ScrW()/2, ScrH()-He(100), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
if player.GetCount() > #modelcamtab then
draw.SimpleText(lang["deploy_big"], "SuR_SmallFont1", ScrW()/2, ScrH()-He(75), Color(255,255,255,200), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
end
for k, v in pairs(modelcamtab) do
if !IsValid(v.player) then continue end
if v.player:GetModel() != v:GetModel() then
local model = v.player:GetModel()
v:SetModel(model)
v:ResetSequence(v.active_seq)
end
local pos = v:GetBonePosition(v:LookupBone("ValveBiped.Bip01_Head1"))
pos = (pos+Vector(0,0,16)):ToScreen()
local icon = SuR.Config.ClassIcons[v.player:GetPlayerClass()]
surface.SetMaterial(icon)
surface.SetDrawColor(255,255,255,alpha)
surface.DrawTexturedRect(pos.x-We(40), pos.y-He(16), We(32), He(32))
draw.SimpleTextOutlined(v.player:Nick(), "SuR_SmallFont1", pos.x, pos.y-He(4), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, 1, color_black)
draw.SimpleTextOutlined(lang["class_lvl_"..v.player:GetLevel()], "SuR_PixelFont", pos.x, pos.y+He(8), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, 1, color_black)
end
end)
hook.Add("CalcView", "SuR_DeployCutscene", function(ply, pos, ang, fov)
local tab = data.cam
local currentTime = CurTime() - startTime
local currentPoint = tab[currentPointIndex]
local nextPoint = tab[currentPointIndex + 1]
if player.GetCount() != #modelcamtab and #data.model >= player.GetCount() then
surface.PlaySound("surrounded/sfx/deploy_new.mp3")
CreateCamModels(data)
end
local ortime = SuR.Data["DeployTime"]-CurTime()
local dtime = math.floor(ortime)
if dtime <= 5 and last_count_number != dtime and dtime != 0 then
surface.PlaySound("surrounded/sfx/deploy_tick.mp3")
if not team_ready then
team_ready = true
ready_up_anim()
end
end
last_count_number = dtime
for k, v in pairs(modelcamtab) do
if !v.active_seq then continue end
local cycle = v:GetCycle()+FrameTime()/select(2, v:LookupSequence(v.active_seq))
v:SetCycle(cycle)
if cycle > 1 and not v.active_seq_noloop then
v:SetCycle(0)
end
if !IsValid(v.player) then
v:Remove()
end
end
if nextPoint then
local lerpedPos = LerpVector(currentTime / currentPoint.time, currentPoint.pos, nextPoint.pos)
local lerpedAng = LerpAngle(currentTime / currentPoint.time, currentPoint.ang, nextPoint.ang)
local lerpedFov = Lerp(currentTime / currentPoint.time, currentPoint.fov, nextPoint.fov)
if currentTime >= currentPoint.time then
currentPointIndex = currentPointIndex + 1
startTime = CurTime()
end
lastdatacam = {lerpedPos, lerpedAng, lerpedFov}
return {
origin = lerpedPos,
angles = lerpedAng,
fov = lerpedFov,
drawviewer = true,
}
else
return {
origin = lastdatacam[1],
angles = lastdatacam[2],
fov = lastdatacam[3],
drawviewer = true,
}
end
end)
end
function SuR:StopDeployCutscene()
hook.Remove("CalcView", "SuR_DeployCutscene")
hook.Remove("HUDPaint", "SuR_DeployCutscene")
currentPointIndex = 1
startTime = 0
last_count_number = 0
lastdatacam = {}
for _, e in pairs(modelcamtab) do
if !IsValid(e) then continue end
e:Remove()
end
modelcamtab = {}
end
net.Receive("SuR.DeployCutscene", function()
local bool = net.ReadBool()
if bool then
if !SuR.Config.Deploy_Cutscene then return end
SuR:StartDeployCutscene(SuR.Config.Deploy_Cutscene)
else
SuR:StopDeployCutscene()
end
end)
net.Receive("SuR.DeathView", function()
local ent = net.ReadEntity()
hook.Add("CalcView", "SuR_DeathView", function(ply, pos, angles, fov)
if !IsValid(ent) or !ent:LookupAttachment('eyes') then
hook.Remove("CalcView", "SuR_DeathView")
return
end
local eye = ent:GetAttachment(ent:LookupAttachment('eyes'))
if isvector(eye.Pos) then
local view = {
origin = eye.Pos,
angles = eye.Ang,
fov = fov,
drawviewer = true,
nearz = 1
}
return view
end
end)
timer.Simple(2, function()
LocalPlayer():ScreenFade(SCREENFADE.OUT, color_black, 1, 1)
end)
timer.Simple(3.5, function()
hook.Remove("CalcView", "SuR_DeathView")
LocalPlayer():ScreenFade(SCREENFADE.IN, color_black, 2, 1)
end)
end)

View File

@@ -0,0 +1,976 @@
------------------------------------------------------------------------OTHER PART
SuR.Data = {}
SuR.Data["Wave"] = 0
SuR.Data["WaveState"] = false
SuR.Data["Enemies"] = 0
SuR.Data["DrawHUD"] = true
SuR.Data["DeployTime"] = 0
SuR.Data["Deploying"] = false
SuR.Data["Mutator"] = 0
SuR.Data["Fuel"] = 0
SuR.Data["MaxFuel"] = 0
SuR.Data["DisableMusic"] = false
local lang = SuR.Language
local hide = {
["CHudHealth"] = true,
["CHudAmmo"] = true,
["CHudSecondaryAmmo"] = true,
["CHudBattery"] = true,
["CHudCrosshair"] = true,
["CHudDamageIndicator"] = true,
["CHudWeaponSelection"] = true,
}
hook.Add("HUDShouldDraw", "HideHUD", function( name )
if hide[name] then
return false
end
end)
hook.Add("DrawDeathNotice", "DisableKillfeed", function()
return 0,0
end)
net.Receive("SuR.SendDataToClient", function()
local str = net.ReadString()
local value = net.ReadTable()[1]
SuR.Data[str] = value
end)
net.Receive("SuR.MessageOnClient", function()
local fl = net.ReadFloat()
local value = net.ReadTable()[1]
message = ""
message2 = ""
if fl == 1 then
message = lang["message_main1"]
message2 = lang["message_main2"]
surface.PlaySound("surrounded/tick.wav")
elseif fl == 2 then
message = string.format(lang["message_wavestart1"], SuR.Data["Wave"])
message2 = lang["message_wavestart2"]
elseif fl == 3 then
message = string.format(lang["message_waveend1"], SuR.Data["Wave"])
message2 = lang["message_waveend2"]
elseif fl == 4 then
message = value:Nick()..lang["message_thelp1"]
message2 = lang["message_thelp2"]
surface.PlaySound("surrounded/sfx/player_downed.mp3")
elseif fl == 5 then
message = lang["message_tdied1"]
message2 = value:Nick()..lang["message_tdied2"]
surface.PlaySound("trials/player_death_02.wav")
elseif fl == 6 then
message = lang["message_radio_accept"]
message2 = lang["message_radio_support"]
elseif fl == 7 then
message = lang["message_radio_accept"]
message2 = lang["message_radio_mortar"]
elseif fl == 8 then
message = lang["message_radio_accept"]
message2 = lang["message_radio_away"]
elseif fl == 9 then
message = lang["message_radio_accept"]
message2 = lang["message_radio_supply"]
elseif fl == 10 then
message = lang["message_radio_accept"]
message2 = lang["message_radio_heli"]
elseif fl == 11 then
message = lang["message_warn"]
local data = 2
if SuR.Data["Wave"] >= 14 then
data = 5
elseif SuR.Data["Wave"] >= 9 then
data = 4
elseif SuR.Data["Wave"] >= 5 then
data = 3
end
message2 = string.format(lang["message_zombie_phase"], data)
elseif fl == 12 then
message = lang["message_warn"]
message2 = lang["mutator_appear"]
elseif fl == 13 then
message = lang["message_radio_accept"]
message2 = lang["message_radio_exfil"]
elseif fl == 14 then
message = lang["message_warn"]
message2 = lang["zombie_choose"]
elseif fl == 14 then
message = lang["message_warn"]
message2 = lang["zombie_choose"]
elseif fl == 15 then
message = lang["message_info"]
message2 = value..lang["message_radio_found"]
elseif fl == 16 then
message = lang["message_info"]
message2 = lang["message_healed"]..value
elseif fl == 17 then
message = lang["message_info"]
message2 = lang["message_healing"]..value
elseif fl == 18 then
message = lang["message_info"]
message2 = value..lang["message_open_box"]
elseif fl == 19 then
message = lang["message_info"]
message2 = value..lang["message_fuel"]
elseif fl == 20 then
message = lang["message_info"]
message2 = lang["message_obj_done"]
end
GiveMessageOnScreen(message, message2)
end)
------------------------------------------------------------------------VOICE PART
local icon_voiceMat = Material('surrounded/voice.png')
local havevoices = 0
local function CreateVoicePanel(ply, bool)
if bool then
havevoices = havevoices + 1
local max = 0+(havevoices*He(36))
local nick = ""
if IsValid(ply) then
nick = ply:Nick()
end
hook.Add("HUDPaint", "ImageOnVoice"..ply:EntIndex(), function()
surface.SetMaterial(icon_voiceMat)
surface.SetDrawColor(255,255,255)
surface.DrawTexturedRect(We(10), He(320)-He(24)+max, We(48), He(48))
draw.SimpleText(nick, "SuR_SmallFont1", We(64), He(320)+max, color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
end)
else
havevoices = havevoices - 1
hook.Remove("HUDPaint", "ImageOnVoice"..ply:EntIndex())
end
end
hook.Add("PlayerStartVoice", "ImageOnVoice", function(ply)
CreateVoicePanel(ply, true)
return false
end)
hook.Add("PlayerEndVoice", "ImageOnVoice", function(ply)
CreateVoicePanel(ply, false)
end)
------------------------------------------------------------------------HUD PART
local function create_fonts()
surface.CreateFont("SuR_PixelFont",{
font = "sur_font1",
extended = true,
size = He(10),
antialias = true,
})
surface.CreateFont("SuR_SmallFont1",{
font = "sur_font1",
extended = true,
size = He(16),
antialias = true,
})
surface.CreateFont("SuR_SmallFont2",{
font = "sur_font1",
extended = true,
size = He(24),
antialias = true,
})
surface.CreateFont("SuR_MediumFont1",{
font = "sur_font1",
extended = true,
size = He(32),
antialias = true,
})
surface.CreateFont("SuR_MediumFont2",{
font = "sur_font1",
extended = true,
size = He(48),
antialias = true,
})
surface.CreateFont("SuR_LargeFont1",{
font = "sur_font1",
extended = true,
size = He(64),
antialias = true,
})
end
create_fonts()
hook.Add("OnScreenSizeChanged", "ChangeFonts", create_fonts)
local aMat = Material('surrounded/ammo_bg.png')
local vMat = Material('surrounded/wave_bg.png')
local gMat = Material('surrounded/gradient.png')
local cMat = Material('surrounded/crosshair.png')
local killMat = Material('surrounded/kill.png')
local icon_kickMat = Material('surrounded/kick.png')
local icon_vaultMat = Material('surrounded/vault.png')
local icon_ammoMat = Material('surrounded/ammo.png')
local icon_healMat = Material('surrounded/heal.png')
local icon_grenadeMat = Material('surrounded/grenade.png')
local icon_sprayMat = Material('surrounded/spray.png')
local icon_radioMat = Material('surrounded/radio_ab.png')
local icon_srkMat = Material('surrounded/srk.png')
local icon_spaceMat = Material('surrounded/space.png')
local icon_mutatorMat = Material('surrounded/mutator.png')
local vinMat = Material('surrounded/vin.png')
function GiveMessageOnScreen(m1, m2)
local long = 600
local longstate = true
timer.Simple(8, function()
longstate = false
end)
hook.Add("HUDPaint", "MainHUDMessage1", function()
local ply = LocalPlayer()
surface.SetMaterial(vMat)
surface.SetDrawColor(255,255,255,250)
surface.DrawTexturedRectRotated(ScrW()-We(300)+long, He(130), We(600), He(120), 180)
draw.SimpleText(m1, "SuR_SmallFont2", ScrW()-We(260)+long, He(110), Color(200,200,200), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText(m2, "SuR_SmallFont1", ScrW()-We(260)+long, He(135), Color(200,20,20), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
if not longstate then
long = math.min(long+FrameTime()/0.001, 600)
if long == 600 then
hook.Remove("HUDPaint", "MainHUDMessage1")
end
else
long = math.max(long-FrameTime()/0.001, 0)
end
end)
end
local function ShowGameOverScreen()
local alpha = 0
local morealpha = true
local wave = net.ReadFloat()
local success = net.ReadBool()
local ply = LocalPlayer()
local maintext = ""
SuR.Data["DrawHUD"] = false
if success then
SuR:PlayMusicOther(table.Random(SuR.Config.MusicWave["ExfilOver"]))
maintext = SuR.Language["game_over_success"]
else
SuR:PlayMusicOther(table.Random(SuR.Config.MusicWave["GameOver"]))
maintext = SuR.Language["game_over_main"]
end
ply:ScreenFade(SCREENFADE.OUT, color_black, 1, 1)
timer.Simple(2, function()
ply:ScreenFade(SCREENFADE.IN, color_black, 1, 0)
hook.Add("HUDPaint", "Surrounded_TheEnd", function()
draw.SimpleText(maintext, "SuR_LargeFont1", ScrW()/2, ScrH()/2-He(300), Color(255,255,255,alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
if not SuR.Config.Objective_Mode then
draw.SimpleText(string.format(SuR.Language["game_over_wave"], wave), "SuR_MediumFont1", ScrW()/2, ScrH()/2-He(180), Color(255,255,255,alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
end
if morealpha then
alpha = math.Clamp(alpha+FrameTime()/0.01, 0, 255)
else
alpha = math.Clamp(alpha-FrameTime()/0.01, 0, 255)
end
end)
hook.Add("CalcView", "Surrounded_TheEnd",function(ply, pos, angles, fov)
local view = {
origin = SuR.Config.Camera_Position[1],
angles = SuR.Config.Camera_Position[2],
fov = fov,
drawviewer = false
}
return view
end)
timer.Simple(SuR.Config.Game_Over_Screen_Delay-6, function()
ply:ScreenFade(SCREENFADE.OUT, color_black, 4, 1)
morealpha = false
timer.Simple(4, function()
ply:ScreenFade(SCREENFADE.IN, color_black, 1, 0)
hook.Remove("CalcView", "Surrounded_TheEnd")
hook.Remove("HUDPaint", "Surrounded_TheEnd")
SuR.Data["DrawHUD"] = true
end)
end)
end)
end
net.Receive("SuR.GameOverScreen", ShowGameOverScreen)
function SuR:StartPhrase()
local alpha = 0
local add1, add2, add3 = 0, 0, 0
local adddelay = 0
local morealpha = true
local text = lang["start_message1"]
if SuR.Config.Objective_Mode then
text = lang["start_message_fuel"]
end
timer.Simple(2, function()
hook.Add("HUDPaint", "Surrounded_Phrase", function()
draw.SimpleText(text, "SuR_SmallFont1", ScrW()/2+We(add1), ScrH()/2+He(200)+He(add2), Color(255,255,255,alpha+add3), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
if adddelay < CurTime() then
adddelay = CurTime()+0.05
add1, add2, add3 = math.Rand(-2,2), math.Rand(-2,2), math.Rand(-25,25)
end
if morealpha then
alpha = math.Clamp(alpha+FrameTime()/0.02, -25, 200)
else
alpha = math.Clamp(alpha-FrameTime()/0.02, -25, 200)
if alpha <= -25 then
hook.Remove("HUDPaint", "Surrounded_Phrase")
end
end
end)
timer.Simple(15, function()
morealpha = false
end)
end)
end
local screen_kills = 0
local rndnum = 0
local alpha = 255
local function GiveKillsOnScreen()
local bool = net.ReadBool()
screen_kills = screen_kills + 1
alpha = 255
local alphaminus = false
local text = ""
if bool then
text = lang["killstreak_exec"]
rndnum = 10
elseif screen_kills == 2 then
text = lang["killstreak_1"]
rndnum = 8
elseif screen_kills == 3 then
text = lang["killstreak_2"]
rndnum = 12
elseif screen_kills == 4 then
text = lang["killstreak_3"]
rndnum = 16
elseif screen_kills == 5 then
text = lang["killstreak_4"]
rndnum = 20
end
hook.Add("HUDPaint", "MainHUDKills", function()
local w, h = ScrW(), ScrH()
local mat = Matrix()
rndnum = math.max(rndnum-FrameTime()/0.1, 0)
if alphaminus then
alpha = math.max(alpha-FrameTime()/0.001, 0)
end
mat:Translate(Vector(w/2+math.random(-rndnum,rndnum), 250+math.random(-rndnum,rndnum)))
mat:Rotate(Angle(0,math.random(-rndnum,rndnum),0))
mat:Scale(Vector(1,1,1))
mat:Translate(-Vector(w/2, h/2))
cam.PushModelMatrix(mat)
draw.SimpleTextOutlined(text, "SuR_SmallFont2", w/2, h/2, Color(255,255,255,alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 2, Color(0, 0, 0, alpha))
cam.PopModelMatrix()
end)
timer.Simple(3.25, function()
alphaminus = true
end)
timer.Create("TimerScreenKills", 4, 1, function()
screen_kills = 0
hook.Remove("HUDPaint", "MainHUDKills")
end)
end
net.Receive("SuR.KillStatus", GiveKillsOnScreen)
local alpha = 255
local countdown_time = 0
local function Countdown(num)
countdown_time = countdown_time + 1
local mytime = countdown_time
for i=0,num-1 do
timer.Simple(i, function()
if mytime != countdown_time then return end
alpha = 255
surface.PlaySound("surrounded/tick.wav")
hook.Add("HUDPaint", "MainHUDTimer", function()
alpha = math.max(alpha-FrameTime()/0.004, 0)
if alpha == 0 then
hook.Remove("HUDPaint", "MainHUDTimer")
end
draw.SimpleTextOutlined(num-i, "SuR_LargeFont1", ScrW()/2, He(250), Color(255,255,255,alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 2, Color(0, 0, 0, alpha))
end)
end)
end
end
net.Receive("SuR.Countdown", function()
local f = net.ReadFloat()
Countdown(f)
end)
cvars.AddChangeCallback("sur_disable_hud", function(convar_name, value_old, value_new)
if tonumber(value_new) == 0 then
SuR.Data["DrawHUD"] = true
end
end)
local wave_long = 300
local wave_longstate = false
local player_health_alpha = 0
local player_health_alphab = false
local player_infected_alpha = 0
local player_infected_alphab = false
local mut_we = 650
hook.Add("HUDPaint", "MainHUD", function()
local ply = LocalPlayer()
if SuR.Data["GameplayBlockNode"] == true then
surface.SetFont("SuR_SmallFont2")
local x = surface.GetTextSize(lang["deploy_error_node"])
surface.SetDrawColor(0,0,0,200)
surface.DrawRect(ScrW()/2-(x/2+5), He(385), (x+10), He(30))
draw.SimpleText(lang["deploy_error_node"], "SuR_SmallFont2", ScrW()/2, He(400), Color(200,20,20,255*math.abs(math.cos(CurTime()))), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
if SuR.Data["GameplayBlockConfig"] == true then
surface.SetFont("SuR_SmallFont2")
local x = surface.GetTextSize(lang["deploy_error_config"])
surface.SetDrawColor(0,0,0,200)
surface.DrawRect(ScrW()/2-(x/2+5), He(415), (x+10), He(30))
draw.SimpleText(lang["deploy_error_config"], "SuR_SmallFont2", ScrW()/2, He(430), Color(200,20,20,255*math.abs(math.cos(CurTime()))), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
if not SuR.Config.Deploy_Cutscene.cam and SuR.Data["Deploying"] and SuR.Data["DeployTime"]-CurTime() > 0 then
local dtime = math.floor(SuR.Data["DeployTime"]-CurTime())
draw.SimpleText(string.format(lang["deploy_time"], dtime), "SuR_MediumFont1", ScrW()/2, ScrH()-He(130), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
draw.SimpleText(lang["deploy_hint"], "SuR_SmallFont1", ScrW()/2, ScrH()-He(100), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
if GetConVar("sur_disable_hud"):GetBool() then
SuR.Data["DrawHUD"] = false
end
local drawhud = ply:Alive() and !ply:IsDowned() and SuR.Data["DrawHUD"]
if drawhud then
local see = ply:GetEyeTrace()
local bug = ply:GetNWFloat('BuggedPos')
if bug > 0.3 then
draw.SimpleText(lang["unreachable"], "SuR_SmallFont1", ScrW()/2, 200, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
local tr = see.Entity
if !ply:IsLockedAbilities() and IsValid(tr) and string.match(tr:GetClass(), "vj") and tr:GetPos():DistToSqr(ply:GetPos()) < 10000 and tr:GetNWBool('flinching', false) and tr:Health() <= 200 then
local pos = (tr:EyePos()):ToScreen()
if tr:LookupAttachment("eyes") > 0 then
pos = (tr:GetAttachment(tr:LookupAttachment("eyes")).Pos):ToScreen()
end
surface.SetMaterial(killMat)
surface.SetDrawColor(255,255,255,240)
surface.DrawTexturedRect(pos.x-48,pos.y-160,96,96)
end
if !ply:IsLockedAbilities() and ply:IsSurvivor() then
local tr2 = util.TraceLine({
start = ply:EyePos(),
endpos = ply:EyePos() + ply:GetAimVector() * 72,
filter = ply,
})
if IsValid(tr2.Entity) and tr2.Entity:IsPlayer() and not tr2.Entity:IsDowned() and tr2.Entity:GetNWBool("IsInfected") and ply:GetNWFloat('Sprays') > 0 then
draw.SimpleText(lang["heal_spray"], "SuR_SmallFont2", ScrW()/2, ScrH()-He(300), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
elseif IsValid(tr2.Entity) and tr2.Entity:IsPlayer() and not tr2.Entity:IsDowned() and tr2.Entity:Health() < 100 and ply:GetNWFloat("Bandages") > 0 then
draw.SimpleText(lang["heal_bandages"], "SuR_SmallFont2", ScrW()/2, ScrH()-He(300), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
end
local h = ply:GetInfection()
if h > 0 then
surface.SetMaterial(vinMat)
surface.SetDrawColor(70,0,125,player_infected_alpha)
surface.DrawTexturedRect(0, 0, ScrW(), ScrH())
surface.SetDrawColor(0,0,0,(h+1-1)*250)
surface.DrawRect(0, 0, ScrW(), ScrH())
if player_infected_alpha <= 0 then
player_infected_alphab = true
elseif player_infected_alpha >= (h+1-1)*125 then
player_infected_alphab = false
end
if player_infected_alphab then
player_infected_alpha = player_infected_alpha+FrameTime()/0.05
else
player_infected_alpha = player_infected_alpha-FrameTime()/0.05
end
end
local h = ply:Health()
if h < 80 then
surface.SetMaterial(vinMat)
surface.SetDrawColor(75,0,0,player_health_alpha)
surface.DrawTexturedRect(0, 0, ScrW(), ScrH())
if player_health_alpha <= 0 then
player_health_alphab = true
elseif player_health_alpha >= (80-h)*1.5 then
player_health_alphab = false
end
if player_health_alphab then
player_health_alpha = player_health_alpha+(FrameTime()/(ply:Health()/ply:GetMaxHealth()))/0.1
else
player_health_alpha = player_health_alpha-(FrameTime()/(ply:Health()/ply:GetMaxHealth()))/0.1
end
end
------------------------------
local ent1 = see.Entity
if IsValid(ent1) and see.HitPos:Distance(ply:EyePos()) < 96 then
local loot = ent1:GetNWString("LootName", "")
local name = SuR.Language[loot]
if not name then
name = loot
end
if name != '' then
draw.SimpleText(lang["main_pickup"]..name, "SuR_SmallFont2", ScrW()/2, ScrH()-He(150), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
end
------------------------------
surface.SetMaterial(gMat)
surface.SetDrawColor(255,255,255,150)
surface.DrawTexturedRect(We(15), ScrH()-He(130), We(240), He(60))
draw.SimpleText("+ "..ply:Health(), "SuR_MediumFont2", We(25), ScrH()-He(75), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_BOTTOM)
------------------------------
surface.SetMaterial(gMat)
surface.SetDrawColor(255,255,255,150)
surface.DrawTexturedRect(We(15), He(35), We(300), He(80))
local icon = SuR.Config.ClassIcons[ply:GetPlayerClass()]
surface.SetMaterial(icon)
surface.SetDrawColor(255,255,255)
surface.DrawTexturedRect(We(20), He(39), We(72), He(72))
draw.SimpleText(lang["class_"..ply:GetPlayerClass()], "SuR_SmallFont2", We(100), We(70), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_BOTTOM)
draw.SimpleText(lang["class_lvl_"..ply:GetLevel()], "SuR_SmallFont1", We(100), He(85), Color(200,200,200), TEXT_ALIGN_LEFT, TEXT_ALIGN_BOTTOM)
surface.SetDrawColor(120,120,120,50)
surface.DrawRect(We(100), He(95), We(120), He(3))
local mult = ((ply:GetXPToLevel()/ply:GetXPToLevel(true))*-1+1)
if ply:GetLevel() == 21 then
mult = 1
end
surface.SetDrawColor(240,240,120,150)
surface.DrawRect(We(100), He(95), We(120)*mult, He(3))
------------------------------
local mut = SuR.Data["Mutator"]
if mut > 0 then
mut_we = math.max(mut_we-FrameTime()/0.005, 0)
else
mut_we = math.min(mut_we+FrameTime()/0.005, 650)
end
surface.SetMaterial(aMat)
surface.SetDrawColor(Color(0,0,0,200))
surface.DrawTexturedRect(We(15-mut_we), ScrH()-He(275), We(560), He(130))
surface.SetMaterial(icon_mutatorMat)
surface.SetDrawColor(255,255,255)
surface.DrawTexturedRect(We(60-mut_we), ScrH()-He(260), We(60), He(60))
draw.SimpleText(lang["mutator_main"], "SuR_SmallFont1", We(145-mut_we), ScrH()-He(250), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
if mut > 0 then
draw.SimpleText(lang["mutator_"..mut], "SuR_SmallFont2", We(145-mut_we), ScrH()-He(230), Color(200,200,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
draw.SimpleText(lang["mutator_"..mut.."_desc"], "SuR_SmallFont1", We(80-mut_we), ScrH()-He(190), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
end
------------------------------
local tr = (see.HitPos):ToScreen()
local wep = ply:GetActiveWeapon()
local drawcrosshair = IsValid(wep) and !ply:IsDowned() and !ply:GetNWBool('SVAnimStopCutscene') and ply:ShouldDrawLocalPlayer()
if drawcrosshair then
surface.SetMaterial(cMat)
surface.SetDrawColor(255,255,255)
surface.DrawTexturedRect(tr.x-16, tr.y-16, We(32), He(32))
end
------------------------------
local drawweapon = IsValid(wep) and wep:GetPrintName()
if drawweapon and ply:IsSurvivor() then
local tier = 0
local clip = wep:Clip1()
local maxclip = wep:GetMaxClip1()
local ammo = ply:GetAmmoCount(wep:GetPrimaryAmmoType())
local color = color_white
local color2 = color_white
if clip == -1 then
clip = 0
end
if clip == 0 then
color = Color(200,20,20)
end
if ammo == 0 then
color2 = Color(200,20,20)
elseif ammo <= maxclip then
color2 = Color(200,150,20)
end
if maxclip > 0 then
surface.SetMaterial(aMat)
surface.SetDrawColor(Color(255,255,255,240))
surface.DrawTexturedRect(ScrW()-We(550), ScrH()-He(250), We(400), He(220))
draw.SimpleText(clip, "SuR_MediumFont2", ScrW()-We(430), ScrH()-He(130), color, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP)
draw.SimpleText("/", "SuR_MediumFont2", ScrW()-We(420), ScrH()-He(120), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText(maxclip, "SuR_MediumFont2", ScrW()-We(410), ScrH()-He(110), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
surface.SetMaterial(icon_ammoMat)
surface.SetDrawColor(Color(255,255,255,240))
surface.DrawTexturedRect(ScrW()-We(275), ScrH()-He(160), We(48), He(48))
draw.SimpleText(ammo, "SuR_SmallFont2", ScrW()-We(250), ScrH()-He(100), color2, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
else
surface.SetMaterial(aMat)
surface.SetDrawColor(Color(255,255,255,240))
surface.DrawTexturedRect(ScrW()-We(550), ScrH()-He(240), We(400), He(110))
end
draw.SimpleText(wep:GetPrintName(), "SuR_SmallFont2", ScrW()-We(500), ScrH()-He(205), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
local t = SuR.Config.TierWeapons
local cl = wep:GetClass()
if table.HasValue(t["Tier1"], cl) then
tier = 1
elseif table.HasValue(t["Tier2"], cl) or table.HasValue(t["Melee"], cl) then
tier = 2
elseif table.HasValue(t["Tier3"], cl) or table.HasValue(t["Other"], cl) then
tier = 3
elseif table.HasValue(t["Tier4"], cl) then
tier = 4
elseif table.HasValue(t["Tier5"], cl) then
tier = 5
end
if wep:GetNWFloat('Tier') > 0 then
tier = wep:GetNWFloat('Tier')
end
if tier > 0 then
draw.SimpleText(lang["loot_tier"..tier], "SuR_SmallFont1", ScrW()-We(500), ScrH()-He(180), SuR.Config.Tier_Colors[tier], TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
end
end
------------------------------
if ply:IsSurvivor() then
surface.SetMaterial(gMat)
surface.SetDrawColor(255,255,255,150)
surface.DrawTexturedRect(We(15), He(230), We(150), He(50))
draw.SimpleText("$ "..ply:GetNWInt('Money'), "SuR_SmallFont2", We(25), He(240), SuR.Config.Tier_Colors[tier], TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
if string.match(ply:GetSVAnim(), "grappleloop") or ply:IsStunned(true) then
surface.SetMaterial(icon_spaceMat)
if input.IsKeyDown(KEY_SPACE) then
surface.SetDrawColor(100,255,100)
else
surface.SetDrawColor(255,255,255)
end
if ply:IsStunned(true) then
surface.DrawTexturedRectRotated(ScrW()/2, ScrH()-He(150), We(350), He(350), 8*math.sin(CurTime()*4))
else
surface.DrawTexturedRectRotated(ScrW()/2+math.Rand(-5,5), ScrH()-He(150)+math.Rand(-5,5), We(350), He(350), 10*math.sin(CurTime()*4))
end
end
if ply:GetNWFloat('SelfRevive') > 0 then
surface.SetMaterial(icon_srkMat)
surface.SetDrawColor(255,255,255,150)
surface.DrawTexturedRect(We(10), ScrH()-He(75), We(80), He(75))
draw.SimpleText(ply:GetNWFloat('SelfRevive'), "SuR_SmallFont2", We(85), ScrH()-He(10), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_BOTTOM)
else
surface.SetMaterial(icon_srkMat)
surface.SetDrawColor(0,0,0,100)
surface.DrawTexturedRect(We(10), ScrH()-He(75), We(80), He(75))
draw.SimpleText(ply:GetNWFloat('SelfRevive'), "SuR_SmallFont2", We(85), ScrH()-He(10), Color(0,0,0,100), TEXT_ALIGN_LEFT, TEXT_ALIGN_BOTTOM)
end
if ply:GetNWFloat('CanCallSupport') > 0 and !ply:IsLockedAbilities() then
surface.SetMaterial(icon_radioMat)
surface.SetDrawColor(255,255,255,240)
surface.DrawTexturedRect(ScrW()-We(125), ScrH()-He(800), We(100), He(100))
draw.SimpleText("M", "SuR_MediumFont1", ScrW()-We(75), ScrH()-He(700), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText("x"..ply:GetNWFloat('CanCallSupport'), "SuR_SmallFont1", ScrW()-We(60), ScrH()-He(685), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
else
surface.SetMaterial(icon_radioMat)
surface.SetDrawColor(100,0,0,240)
surface.DrawTexturedRect(ScrW()-We(125), ScrH()-He(800), We(100), He(100))
draw.SimpleText("M", "SuR_MediumFont1", ScrW()-We(75), ScrH()-He(700), Color(100,0,0), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText("x"..ply:GetNWFloat('CanCallSupport'), "SuR_SmallFont1", ScrW()-We(60), ScrH()-He(685), Color(100,0,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
end
if ply:GetInfection() > 0 and ply:GetNWFloat('Sprays') > 0 and !ply:IsLockedAbilities() then
surface.SetMaterial(icon_sprayMat)
surface.SetDrawColor(255,255,255,240)
surface.DrawTexturedRect(ScrW()-We(125), ScrH()-He(650), We(100), He(100))
draw.SimpleText("H", "SuR_MediumFont1", ScrW()-We(75), ScrH()-He(550), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText("x"..ply:GetNWFloat('Sprays'), "SuR_SmallFont1", ScrW()-We(60), ScrH()-He(535), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
else
surface.SetMaterial(icon_sprayMat)
surface.SetDrawColor(100,0,0,240)
surface.DrawTexturedRect(ScrW()-We(125), ScrH()-He(650), We(100), He(100))
draw.SimpleText("H", "SuR_MediumFont1", ScrW()-We(75), ScrH()-He(550), Color(100,0,0), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText("x"..ply:GetNWFloat('Sprays'), "SuR_SmallFont1", ScrW()-We(60), ScrH()-He(535), Color(100,0,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
end
if ply:GetNWBool('CanHeal') and !ply:IsLockedAbilities() and ply:GetNWFloat("Bandages") > 0 then
surface.SetMaterial(icon_healMat)
surface.SetDrawColor(255,255,255,240)
surface.DrawTexturedRect(ScrW()-We(125), ScrH()-He(500), We(100), He(100))
draw.SimpleText("B", "SuR_MediumFont1", ScrW()-We(75), ScrH()-He(400), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText("x"..ply:GetNWFloat("Bandages"), "SuR_SmallFont1", ScrW()-We(60), ScrH()-He(385), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
else
surface.SetMaterial(icon_healMat)
surface.SetDrawColor(100,0,0,240)
surface.DrawTexturedRect(ScrW()-We(125), ScrH()-He(500), We(100), He(100))
draw.SimpleText("B", "SuR_MediumFont1", ScrW()-We(75), ScrH()-He(400), Color(100,0,0), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText("x"..ply:GetNWFloat("Bandages"), "SuR_SmallFont1", ScrW()-We(60), ScrH()-He(385), Color(100,0,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
end
if ply:GetNWInt('Grenades') > 0 and !ply:IsLockedAbilities() then
surface.SetMaterial(icon_grenadeMat)
surface.SetDrawColor(255,255,255,240)
surface.DrawTexturedRect(ScrW()-We(125), ScrH()-He(350), We(100), He(100))
draw.SimpleText("L", "SuR_MediumFont1", ScrW()-We(75), ScrH()-He(250), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText("x"..ply:GetNWInt('Grenades'), "SuR_SmallFont1", ScrW()-We(60), ScrH()-He(235), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
else
surface.SetMaterial(icon_grenadeMat)
surface.SetDrawColor(100,0,0,240)
surface.DrawTexturedRect(ScrW()-We(125), ScrH()-He(350), We(100), He(100))
draw.SimpleText("L", "SuR_MediumFont1", ScrW()-We(75), ScrH()-He(250), Color(100,0,0), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText("x"..ply:GetNWInt('Grenades'), "SuR_SmallFont1", ScrW()-We(60), ScrH()-He(235), Color(100,0,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
end
if ply:GetNWBool('CanVault') and !ply:IsLockedAbilities() then
surface.SetMaterial(icon_vaultMat)
surface.SetDrawColor(255,255,255,240)
surface.DrawTexturedRect(ScrW()-We(250), ScrH()-He(350), We(100), He(100))
draw.SimpleText("V", "SuR_MediumFont1", ScrW()-We(200), ScrH()-He(250), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
end
if !ply:IsLockedAbilities() then
surface.SetMaterial(icon_kickMat)
surface.SetDrawColor(255,255,255,240)
surface.DrawTexturedRect(ScrW()-We(125), ScrH()-He(200), We(100), He(100))
draw.SimpleText("G", "SuR_MediumFont1", ScrW()-We(75), ScrH()-He(100), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
else
surface.SetMaterial(icon_kickMat)
surface.SetDrawColor(100,0,0,240)
surface.DrawTexturedRect(ScrW()-We(125), ScrH()-He(200), We(100), He(100))
draw.SimpleText("G", "SuR_MediumFont1", ScrW()-We(75), ScrH()-He(100), Color(100,0,0), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
end
local tr = util.TraceLine({
start = ply:EyePos(),
endpos = ply:EyePos() + ply:GetAimVector() * 50,
filter = ply,
mask = MASK_SHOT_HULL
})
local ent = tr.Entity
if IsValid(ent) and ent:IsPlayer() and ent:IsDowned() and !ply:IsDowned() and ply:Alive() and ply:GetVelocity():Length() < 10 then
draw.SimpleText(lang["revive_help"], "SuR_MediumFont1", ScrW()/2, ScrH()-He(150), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
else
surface.SetMaterial(vinMat)
surface.SetDrawColor(70,0,125,100)
surface.DrawTexturedRect(0, 0, ScrW(), ScrH())
draw.SimpleText(lang["zombie_attack1"], "SuR_MediumFont1", ScrW()-We(100), ScrH()-He(140), color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP)
draw.SimpleText(lang["zombie_attack2"], "SuR_MediumFont1", ScrW()-We(100), ScrH()-He(110), color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP)
end
elseif not drawhud and ply:IsZombie() then
if !ply:Alive() and SuR.Data["WaveState"] then
draw.SimpleText(lang["zombie_spawn"], "SuR_MediumFont1", ScrW()/2, ScrH()-He(200), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText(lang["zombie_menu"], "SuR_SmallFont2", ScrW()/2, ScrH()-He(230), Color(225,200,0), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
elseif !ply:Alive() and not SuR.Data["WaveState"] then
draw.SimpleText(lang["zombie_wait"], "SuR_MediumFont1", ScrW()/2, ScrH()-He(200), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText(lang["zombie_menu"], "SuR_SmallFont2", ScrW()/2, ScrH()-He(230), Color(225,200,0), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
end
end
draw.SimpleText("SURROUNDED - v"..SuR.Version.." ["..SuR.Build.."]", "SuR_SmallFont1", 5, 5, color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
draw.SimpleText(lang["hud_discord_join"], "SuR_PixelFont", 5, He(22), Color(225, 200, 0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
surface.SetMaterial(vMat)
surface.SetDrawColor(255,255,255,250)
surface.DrawTexturedRect(0-wave_long, He(130), We(230), He(70))
if SuR.Data["ExfilWave"] then
draw.SimpleText(lang["evac"], "SuR_MediumFont1", We(15)-wave_long, He(145), Color(200,200*math.cos(CurTime()*3),200*math.cos(CurTime()*3)), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
elseif SuR.Config.Objective_Mode then
local fuel, maxfuel = SuR.Data["Fuel"], SuR.Data["MaxFuel"]
draw.SimpleText(lang["fuel"], "SuR_SmallFont1", We(110)-wave_long, He(145), Color(200,200,200), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
draw.SimpleText(fuel.."/"..maxfuel, "SuR_MediumFont1", We(110)-wave_long, He(160), Color(200,200,200), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
else
draw.SimpleText(lang["main_wave"]..SuR.Data["Wave"], "SuR_MediumFont1", We(15)-wave_long, He(140), Color(200,200,200), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
if wave_longstate then
draw.SimpleText(lang["main_count"]..SuR.Data["Enemies"], "SuR_SmallFont1", We(15)-wave_long, He(175), Color(100,20,20), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
end
end
wave_longstate = SuR.Data["WaveState"]
if not wave_longstate then
wave_long = math.min(wave_long+FrameTime()/0.005, 300)
else
wave_long = math.max(wave_long-FrameTime()/0.005, 0)
end
local tab = player.GetAll()
for i=1,#tab do
local ent = tab[i]
if ent:Team() != ply:Team() then continue end
if ent != ply and ent:Alive() and ent:IsLineOfSightClear(ply) then
local pos = (ent:GetBonePosition(ent:LookupBone("ValveBiped.Bip01_Head1"))+Vector(0,0,20)):ToScreen()
if string.match(ent:GetSVAnim(), "executions") or string.match(ent:GetSVAnim(), "killmove") or string.match(ent:GetSVAnim(), "grappleloop") then
draw.SimpleText(ent:Nick(), "SuR_SmallFont1", pos.x, pos.y-He(16), Color(200,120,20), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
draw.SimpleText("[HELP]", "SuR_SmallFont1", pos.x, pos.y, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
elseif ent:IsDowned() then
draw.SimpleText(ent:Nick(), "SuR_SmallFont1", pos.x, pos.y-He(16), Color(200,20,20), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
draw.SimpleText("[+]", "SuR_SmallFont1", pos.x, pos.y, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
else
local alpha = 255/(ent:EyePos():Distance(EyePos())/500)
if alpha > 200 then
draw.SimpleText(ent:Nick(), "SuR_SmallFont1", pos.x, pos.y, Color(255,255,255,alpha), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
local icon = SuR.Config.ClassIcons[ent:GetPlayerClass()]
surface.SetMaterial(icon)
surface.SetDrawColor(255,255,255,alpha)
surface.DrawTexturedRect(pos.x-We(40), pos.y-He(16), We(32), He(32))
else
draw.SimpleText(ent:Nick(), "SuR_PixelFont", pos.x, pos.y, Color(255,255,255,alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
end
end
end
if ply:IsDowned() then
draw.SimpleText(lang["revive_main"], "SuR_MediumFont1", ScrW()/2, ScrH()-He(150), Color(200,20,20), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
draw.SimpleText(lang["revive_wait"], "SuR_SmallFont2", ScrW()/2, ScrH()-He(110), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
if ply:GetNWFloat('SelfRevive') > 0 and ply:GetSVAnim() != "sur_selfrevive" then
draw.SimpleText(lang["revive_self"], "SuR_SmallFont1", ScrW()/2, ScrH()-He(300), color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
surface.SetMaterial(icon_srkMat)
surface.SetDrawColor(255,255,255,150)
surface.DrawTexturedRect(ScrW()/2-We(35), ScrH()-He(300), We(80), He(75))
draw.SimpleText(ply:GetNWFloat('SelfRevive'), "SuR_SmallFont2", ScrW()/2+We(35), ScrH()-He(235), color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_BOTTOM)
end
end
end)
local addmat_r = Material("surrounded/add_r")
local addmat_g = Material("surrounded/add_g")
local addmat_b = Material("surrounded/add_b")
local vgbm = Material("vgui/black")
function DrawCA(rx, gx, bx, ry, gy, by)
render.UpdateScreenEffectTexture()
addmat_r:SetTexture("$basetexture", render.GetScreenEffectTexture())
addmat_g:SetTexture("$basetexture", render.GetScreenEffectTexture())
addmat_b:SetTexture("$basetexture", render.GetScreenEffectTexture())
render.SetMaterial(vgbm)
render.DrawScreenQuad()
render.SetMaterial(addmat_r)
render.DrawScreenQuadEx(-rx / 2, -ry / 2, ScrW() + rx, ScrH() + ry)
render.SetMaterial(addmat_g)
render.DrawScreenQuadEx(-gx / 2, -gy / 2, ScrW() + gx, ScrH() + gy)
render.SetMaterial(addmat_b)
render.DrawScreenQuadEx(-bx / 2, -by / 2, ScrW() + bx, ScrH() + by)
end
hook.Add("RenderScreenspaceEffects", "MainColorHP", function()
local ply = LocalPlayer()
local death = isfunction(hook.GetTable()["CalcView"]["SuR_DeathView"])
if ply:Alive() or death then
local tab = {
["$pp_colour_contrast"] = (ply:Health()/ply:GetMaxHealth())/4+0.75,
["$pp_colour_colour"] = (ply:Health()/ply:GetMaxHealth()),
}
if ply:IsDowned() or death then
tab = {
["$pp_colour_contrast"] = 0.75,
["$pp_colour_colour"] = 0.1,
}
end
DrawColorModify(tab)
local num = ply:IsDowned() and 25 or ( (1-(ply:Health()/ply:GetMaxHealth()))*10 )
if ply:Health() < 50 or ply:IsDowned() or death then
num = num*math.abs(math.sin(CurTime()))+0.1
if num > 0 then
DrawCA(4 * num, 2 * num, 0, 2 * num, 1 * num, 0)
end
end
end
end)
------------------------------------------------------------------------WORK PART
hook.Add("InitPostEntity", "MainDeleter", function()
function GAMEMODE:HUDDrawTargetID() end
function GAMEMODE:HUDDrawPickupHistory() end
end)
local bindfalse = {
["-voicerecord"] = true,
["+voicerecord"] = true,
["messagemode"] = true,
}
local movebind = {
["-forward"] = true,
["+forward"] = true,
["-moveleft"] = true,
["+moveleft"] = true,
["-moveright"] = true,
["+moveright"] = true,
["-back"] = true,
["+back"] = true,
}
hook.Add("PlayerBindPress", "Main_PlayerBindPress", function(ply, bind, pressed)
local ply = LocalPlayer()
local cutscene = ply:GetNWBool('SVAnimStopCutscene')
if (ply:KeyDown(IN_DUCK) or !ply:OnGround()) and bind == "+jump" then return true end
if (ply:KeyDown(IN_JUMP) or !ply:OnGround()) and bind == "+duck" then return true end
if cutscene and not bindfalse[bind] then
return true
end
if ply:IsDowned() and not bindfalse[bind] and not movebind[bind] then
return true
end
end)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,732 @@
function render.BorderSphereUnit( color, pos, radius, detail, thickness, dds )
local snr = {[0]=2,[1]=1,[3]=2,[5]=1,[7]=2,[9]=1}
local lens = string.len( tostring( radius ) )
local thickness = math.floor( thickness ) or 24
local detail = math.min( math.floor( detail ), 100 ) or 32
local radius = math.floor( radius )
local ds = 0
if thickness >= radius then thickness = radius end
if dds ~= true then
if snr[tonumber( string.sub( tostring( radius ), lens, lens ) )] == 1 then ds = 1 end
if snr[tonumber( string.sub( tostring( radius ), lens, lens ) )] == 2 then ds = 0.50 end
end
cam.IgnoreZ(false)
render.SetStencilEnable(true)
render.SetStencilReferenceValue( 0x55 )
render.SetStencilTestMask( 0x1C )
render.SetStencilWriteMask( 0x1C )
render.ClearStencil()
render.SetColorMaterial()
render.SetStencilReferenceValue( 1 )
render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_ALWAYS )
render.SetStencilZFailOperation( STENCILOPERATION_INVERT )
render.DrawSphere( pos, -radius, detail, detail, Color( 0, 0, 0, 0 ) )
render.DrawSphere( pos, radius, detail, detail, Color( 0, 0, 0, 0 ) )
render.DrawSphere( pos, -( radius -thickness ), detail +ds, detail +ds, Color( 0, 0, 0, 0 ) )
render.DrawSphere( pos, ( radius -thickness ), detail +ds, detail +ds, Color( 0, 0, 0, 0 ) )
if dds ~= true then
render.SetStencilZFailOperation( STENCILOPERATION_REPLACE )
render.DrawSphere( pos, radius +0.25, detail +ds, detail +ds, Color( 0, 0, 0, 0 ) )
end
render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_NOTEQUAL )
local cam_pos = LocalPlayer():EyePos()
local cam_angle = LocalPlayer():EyeAngles()
if LocalPlayer():GetViewEntity() ~= LocalPlayer() then
cam_pos = ( LocalPlayer():GetViewEntity() ):GetPos()
cam_angle = ( LocalPlayer():GetViewEntity() ):GetAngles()
end
local cam_normal = cam_angle:Forward()
cam.IgnoreZ(true)
render.SetStencilReferenceValue( 1 )
render.DrawQuadEasy( cam_pos + cam_normal * 10, -cam_normal, 10000, 10000, color, cam_angle.roll )
cam.IgnoreZ(false)
render.SetStencilEnable(false)
end
local delay = 0
hook.Add("Think", "SuR.ClearErrorModels", function()
if delay > CurTime() then return end
delay = CurTime()+15
for _, ent in ipairs(ents.GetAll()) do
if !ent:IsPlayer() and !ent:IsNPC() and ent:GetModel() == "models/error.mdl" then
ent:SetRenderMode(10)
ent:SetMaterial("null")
ent:SetNoDraw(true)
end
end
end)
net.Receive("SuR.PrecacheModels", function()
local tab = net.ReadTable()
for _, m in ipairs(tab) do
util.PrecacheModel(m)
end
end)
net.Receive("SuR.BecomeRagdoll", function()
local ent = net.ReadEntity()
if IsValid(ent) then
local base = ent:BecomeRagdollOnClient()
if IsValid(base) then
local rag = ClientsideRagdoll(base:GetModel())
rag:SetPos(base:GetPos())
SuR:TransferModelData(base, rag)
SuR:TransferBones(base, rag)
rag:SetNoDraw(false)
base:Remove()
SafeRemoveEntityDelayed(rag, 60)
end
end
end)
concommand.Add("sur_debug_animations", function(ply)
MsgC(Color(150,250,150), "Debug Tool Info:\n\n----------------\n\n")
MsgC(Color(250,250,250), "Count of Sequences: "..ply:GetSequenceCount().."\n")
MsgC(Color(200,200,200), "List of Sequences: \n\n")
for i=0,ply:GetSequenceCount()-1 do
timer.Simple(3+(i/100), function()
local name = ply:GetSequenceName(i)
local long = math.Round(select(2, ply:LookupSequence(name)), 3)
MsgC(Color(250,250,250), "ID: "..i.." Name:"..name.." Duration:"..long.."\n")
end)
end
end)
-----------------------FIRST PERSON BODY, TAKED FROM WORKSHOP, DONT BEAT ME PLS
local cache = {}
local _GetChildBonesRecursive
local mdl = ""
_GetChildBonesRecursive = function(ent, bone, src)
local t = src or {}
table.insert(t, bone)
local cbones = ent:GetChildBones(bone)
if cbones then
for _, bone in next, cbones do
_GetChildBonesRecursive(ent, bone, t)
end
end
return t
end
local function GetChildBonesRecursive(ent, bone)
local mdl = ent:GetModel()
local mdlbones = cache[mdl]
if not mdlbones then
mdlbones = {}
cache[mdl] = mdlbones
end
local ret = mdlbones[bone]
if ret then return ret end
ret = _GetChildBonesRecursive(ent, bone)
mdlbones[bone] = ret
return ret
end
local bones = {}
local bonesName = {}
local forwardDistance = 16
local queue = {}
local work = false
local lowerbody = false
SuR.EnableFPBody = true
local MarkToRemove = function(ent)
if not IsValid(ent) then
return
end
work = true
ent:SetNoDraw(true)
table.insert(queue, ent)
end
hook.Add("Think", "legs.MarkToRemove", function()
if not work then
return
end
for key, ent in pairs(queue) do
if ent:IsValid() then
ent:Remove()
end
queue[key] = nil
end
if not next(queue) then
work = false
end
end)
hook.Add("LocalPlayer_Validated", "sur_gmod_legs", function(ply)
hook.Remove("LocalPlayer_Validated", "sur_gmod_legs")
local pairs, ipairs = pairs, ipairs
local playermodelbones = {"ValveBiped.Bip01_Head1","ValveBiped.Bip01_R_Trapezius","ValveBiped.Bip01_R_Bicep","ValveBiped.Bip01_R_Shoulder", "ValveBiped.Bip01_R_Elbow","ValveBiped.Bip01_R_Wrist","ValveBiped.Bip01_R_Ulna","ValveBiped.Bip01_L_Trapezius","ValveBiped.Bip01_L_Bicep","ValveBiped.Bip01_L_Shoulder", "ValveBiped.Bip01_L_Elbow","ValveBiped.Bip01_L_Wrist","ValveBiped.Bip01_L_Ulna", "ValveBiped.Bip01_Neck1","ValveBiped.Bip01_Hair1","ValveBiped.Bip01_Hair2","ValveBiped.Bip01_L_Clavicle","ValveBiped.Bip01_R_Clavicle","ValveBiped.Bip01_R_UpperArm", "ValveBiped.Bip01_R_Forearm", "ValveBiped.Bip01_R_Hand", "ValveBiped.Bip01_L_UpperArm", "ValveBiped.Bip01_L_Forearm", "ValveBiped.Bip01_L_Hand", "ValveBiped.Bip01_L_Wrist", "ValveBiped.Bip01_R_Wrist", "ValveBiped.Bip01_L_Finger4", "ValveBiped.Bip01_L_Finger41", "ValveBiped.Bip01_L_Finger42", "ValveBiped.Bip01_L_Finger3", "ValveBiped.Bip01_L_Finger31", "ValveBiped.Bip01_L_Finger32", "ValveBiped.Bip01_L_Finger2", "ValveBiped.Bip01_L_Finger21", "ValveBiped.Bip01_L_Finger22", "ValveBiped.Bip01_L_Finger1", "ValveBiped.Bip01_L_Finger11", "ValveBiped.Bip01_L_Finger12", "ValveBiped.Bip01_L_Finger0", "ValveBiped.Bip01_L_Finger01", "ValveBiped.Bip01_L_Finger02", "ValveBiped.Bip01_R_Finger4", "ValveBiped.Bip01_R_Finger41", "ValveBiped.Bip01_R_Finger42", "ValveBiped.Bip01_R_Finger3", "ValveBiped.Bip01_R_Finger31", "ValveBiped.Bip01_R_Finger32", "ValveBiped.Bip01_R_Finger2", "ValveBiped.Bip01_R_Finger21", "ValveBiped.Bip01_R_Finger22", "ValveBiped.Bip01_R_Finger1", "ValveBiped.Bip01_R_Finger11", "ValveBiped.Bip01_R_Finger12", "ValveBiped.Bip01_R_Finger0", "ValveBiped.Bip01_R_Finger01", "ValveBiped.Bip01_R_Finger02"}
local a = {}
for key, v in pairs(playermodelbones) do
a[v] = true
end
local ply = ply or LocalPlayer()
local vec9999 = Vector(9999, 9999, 9999)
local ENTITY, PLAYER = FindMetaTable("Entity"), FindMetaTable("Player")
local GetBoneName = ENTITY.GetBoneName
local LookupBone = ENTITY.LookupBone
local MATRIX = FindMetaTable("VMatrix")
local Scale, Translate, SetTranslation, SetAngles = MATRIX.Scale, MATRIX.Translate, MATRIX.SetTranslation, MATRIX.SetAngles
local GetTranslation, GetAngles = MATRIX.GetTranslation, MATRIX.GetAngles
local SetBoneMatrix = ENTITY.SetBoneMatrix
local cam_Start3D, render_EnableClipping, render_PushCustomClipPlane, render_PopCustomClipPlane, render_EnableClipping, cam_End3D =
cam.Start3D, render.EnableClipping, render.PushCustomClipPlane, render.PopCustomClipPlane, render.EnableClipping, cam.End3D
local SetupBones = ENTITY.SetupBones
local _EyePos = ENTITY.EyePos
MarkToRemove(ply.Body)
MarkToRemove(ply.Body_NoDraw)
local remap = math.Remap
local eyeAngles = Angle()
local suppress = false
local isDucking = false
local finalPos = Vector()
local limit_check = 0
local timeCache = 0.1
local vector_origin = Vector(0, 0, 0)
local find, insert = string.find, table.insert
local SetPoseParameter, GetPoseParameter = ENTITY.SetPoseParameter, ENTITY.GetPoseParameter
local SetPlaybackRate, GetPlaybackRate = ENTITY.SetPlaybackRate, ENTITY.GetPlaybackRate
local GetBoneMatrix = ENTITY.GetBoneMatrix
local a1, b1, c1 = 0, 0, 0
local headPos = Vector(0,10000,0)
local limitJump = 0
local onGround = true
local JUMPING_ = false
hook.Add("SetupMove", "legs.SetupMove", function(ply, move)
if not IsFirstTimePredicted() then
return
end
if bit.band(move:GetButtons(), IN_JUMP) ~= 0
and bit.band(move:GetOldButtons(), IN_JUMP) == 0
and ply:OnGround() then
JUMPING, onGround = true, false
if IsFirstTimePredicted() then
JUMPING_ = not JUMPING_
end
end
end)
hook.Add("FinishMove", "legs.FinishMove", function(ply, move)
if not IsFirstTimePredicted() then
return
end
JUMPING = nil
local isOnGround = ply:OnGround()
if onGround ~= isOnGround then
onGround = isOnGround
if onGround then
limitJump = CurTime() + FrameTime()
end
end
end)
local validBones = {}
local removeHead = function()
local legs = ply.Body
local h = LookupBone(legs, "ValveBiped.Bip01_Head1")
if h then
legs:ManipulateBonePosition(h, headPos)
end
end
local GetPos, GetViewOffset = ENTITY.GetPos, PLAYER.GetViewOffset
local removeGarbage = function(bonesSuccess, boneCount)
local ent = ply.Body
local goofyUhhPosition = GetPos(ply) + GetViewOffset(ply) - eyeAngles:Forward() * 32
for i = 0, boneCount - 1 do
local boneName = GetBoneName(ent, i)
local mat = GetBoneMatrix(ent, i)
if mat then
if a[boneName] then
SetTranslation(mat, goofyUhhPosition)
bonesSuccess[i] = true
local recursive = GetChildBonesRecursive(ent, i)
for key = 1, #recursive do
local bone = recursive[key]
if not bonesSuccess[bone] then
bonesSuccess[bone] = true
local mat = GetBoneMatrix(ent, bone)
if mat then
SetTranslation(mat, goofyUhhPosition)
SetBoneMatrix(ent, bone, mat)
end
end
end
elseif not bonesSuccess[i] then
local bone = LookupBone(ply, boneName)
if bone then
local mat2 = GetBoneMatrix(ply, bone)
if mat2 then
SetTranslation(mat, GetTranslation(mat2))
SetAngles(mat, GetAngles(mat2))
end
end
end
SetBoneMatrix(ent, i, mat)
end
end
end
local Legs_NoDraw_Angle = Angle(0, 0, 0)
local potentionalBones, timeCacheBones = {}, 0
local spineBones = {
["ValveBiped.Bip01_Spine2"] = true,
["ValveBiped.Bip01_Spine4"] = true
}
local GetNumPoseParameters, GetPoseParameterRange = ENTITY.GetNumPoseParameters, ENTITY.GetPoseParameterRange
local GetPoseParameterName, GetSequence = ENTITY.GetPoseParameterName, ENTITY.GetSequence
local GetRenderAngles, SetRenderAngles = PLAYER.GetRenderAngles, PLAYER.SetRenderAngles
local buildBonePosition = function()
ply.Body.Callback = ply.Body:AddCallback("BuildBonePositions", function(ent, boneCount)
if not SuR.EnableFPBody then
return ent:RemoveCallback("BuildBonePositions", ent.Callback)
end
if not ply.TimeToDuck
or suppress then
return
end
local ang = GetRenderAngles(ply)
SetRenderAngles(ply, eyeAngles)
a1, b1, c1 = GetPoseParameter(ply, "body_yaw", 0), GetPoseParameter(ply, "aim_yaw", 0), GetPoseParameter(ply, "aim_pitch", 0)
SetPoseParameter(ply, "body_yaw", 0)
SetPoseParameter(ply, "aim_yaw", 0)
SetPoseParameter(ply, "aim_pitch", 0)
SetupBones(ply)
local seq = GetSequence(ply)
if ent.Seq ~= seq then
ent.Seq = seq
ent:ResetSequence(seq)
end
local legsNoDraw = ply.Body_NoDraw
for i = 0, GetNumPoseParameters(ply) - 1 do
local flMin, flMax = GetPoseParameterRange(ply, i)
local sPose = GetPoseParameterName(ply, i)
local remap = remap(GetPoseParameter(ply, sPose), 0, 1, flMin, flMax)
SetPoseParameter(legsNoDraw, sPose, remap)
SetPoseParameter(ent, sPose, remap)
end
local bonesSuccess = {}
removeGarbage(bonesSuccess, boneCount)
SetPoseParameter(ply, "body_yaw", a1)
SetPoseParameter(ply, "aim_yaw", b1)
SetPoseParameter(ply, "aim_pitch", c1)
removeHead()
SetupBones(legsNoDraw)
local this = (2 - (0.8 * ply.TimeToDuck))
local cacheThis = this
local CT = CurTime()
if timeCacheBones < CT then
timeCacheBones, potentionalBones = CT + timeCache, {}
for i = 1, #validBones do
local array = validBones[i]
local bone, isPelvis = array[2], array[1]
if bonesSuccess[bone] then
continue
end
local recursive = GetChildBonesRecursive(ent, bone)
for key = 1, #recursive do
local i = recursive[key]
if not bonesSuccess[i]
and (isPelvis and i == bone or not isPelvis) then
bonesSuccess[i] = true
local boneName = GetBoneName(ent, i)
local mat = GetBoneMatrix(ent, i)
if mat then
local b = LookupBone(legsNoDraw, boneName)
if b then
local mat2 = GetBoneMatrix(legsNoDraw, b)
if mat2 then
local matTR, mat2TR = GetTranslation(mat), GetTranslation(mat2)
if boneName == "ValveBiped.Bip01_Pelvis" then
Legs_NoDraw_Angle.y = (math.NormalizeAngle(ply:EyeAngles().y - GetAngles(mat).y) + 90) / 1.25
elseif spineBones[boneName] then
this = 20 - (16 * ply.TimeToDuck)
end
if not lowerbody then
SetTranslation(mat, mat2TR - (mat2TR - matTR) / this)
this = cacheThis
SetAngles(mat, GetAngles(mat2))
SetBoneMatrix(ent, i, mat)
end
potentionalBones[#potentionalBones + 1] = {
[1] = i,
[2] = boneName
}
end
end
end
end
end
end
else
for key = 1, #potentionalBones do
local array = potentionalBones[key]
local i, boneName = array[1], array[2]
local mat = GetBoneMatrix(ent, i)
if mat then
local b = LookupBone(legsNoDraw, boneName)
if b then
local mat2 = GetBoneMatrix(legsNoDraw, b)
if mat2 then
if boneName == "ValveBiped.Bip01_Pelvis" then
Legs_NoDraw_Angle.y = (math.NormalizeAngle(ply:EyeAngles().y - GetAngles(mat).y) + 90) / 1.25
elseif spineBones[boneName] then
this = 20 - (16 * ply.TimeToDuck)
end
local matTR, mat2TR = GetTranslation(mat), GetTranslation(mat2)
if not lowerbody then
SetTranslation(mat, mat2TR - (mat2TR - matTR) / this)
this = cacheThis
SetAngles(mat, GetAngles(mat2))
SetBoneMatrix(ent, i, mat)
end
end
end
end
end
end
SetRenderAngles(ply, ang)
end)
ply.Body.FullyLoaded = true
end
local faggot = Vector()
local SetParent, SetPos, SetAngles, SetCycle = ENTITY.SetParent, ENTITY.SetPos, ENTITY.SetAngles, ENTITY.SetCycle
local GetCycle = ENTITY.GetCycle
local lowerbodyseq = {
["sur_dropkick"] = {0.2, 1},
["sur_fall_idle"] = {0, 1},
["sur_fall_down"] = {0.2, 1},
["sur_fall_standup"] = {0, 0.4},
}
hook.Add("RenderScene", "firstperson.RenderScene", function(vec, ee)
if not SuR.EnableFPBody then
return
end
local anim = ply:GetSVAnim()
local tab = lowerbodyseq[anim]
if istable(tab) then
local cycle = math.Clamp((CurTime()-ply:GetNWFloat('SVAnimStartTime'))/ply:GetNWFloat('SVAnimDelay'), 0, 1)
if cycle >= tab[1] and cycle <= tab[2] then
lowerbody = true
else
lowerbody = false
end
else
lowerbody = false
end
if lowerbody then
forwardDistance = Lerp(FrameTime()/0.1, forwardDistance, 0)
else
forwardDistance = Lerp(FrameTime()/0.1, forwardDistance, 16)
end
eyePos = vec
eyeAngles = ply:EyeAngles()
eyeAngles.p = 0
local onGround = ply:OnGround()
isDucking = bit.band(ply:GetFlags(), FL_ANIMDUCKING) > 0
and onGround
local FT = FrameTime()
ply.TimeToDuck = math.Clamp((ply.TimeToDuck or 0) + FT * 3.5 * (isDucking and 1 or -1), 0, 1)
local realEyeAngles = EyeAngles()
local legs = ply.Body
suppress = ply:ShouldDrawLocalPlayer()
or not ply:Alive()
or not IsValid(ply.Body)
or not ply.Body.FullyLoaded
or not IsValid(ply.Body_NoDraw)
or ply:GetRagdollEntity():IsValid()
or ply:InVehicle()
or ply:GetObserverMode() ~= 0
or realEyeAngles.p > 110
or realEyeAngles.p < -110
or ply:GetNWBool('SVAnimStopCutscene')
local CT = SysTime()
if limit_check < CT and IsValid(ply.Body) then
limit_check = CT + timeCache
if ply.Body.Callback then
local getCallbacks = ply.Body:GetCallbacks("BuildBonePositions")
if not getCallbacks[ply.Body.Callback] then
buildBonePosition()
end
else
buildBonePosition()
end
ply.Body:SetSkin(ply:GetSkin())
ply.Body:SetMaterial(ply:GetMaterial())
if not suppress then
for k, v in ipairs(ply:GetBodyGroups()) do
local bg = ply:GetBodygroup(v.id)
ply.Body:SetBodygroup(v.id, bg)
ply.Body_NoDraw:SetBodygroup(v.id, bg)
end
end
validBones = {}
for i = 0, ply.Body:GetBoneCount() - 1 do
local boneName = GetBoneName(ply.Body, i)
local isPelvis = find(boneName, "Pelvis", 1, true) or false
if find(boneName, "Spine", 1, true)
or isPelvis
or find(boneName, "Jacket", 1, true) then
validBones[#validBones + 1] = {
[1] = isPelvis,
[2] = i
}
end
end
end
if suppress then
return
end
local getPos = GetPos(ply)
local getView = GetViewOffset(ply)
local cycle = GetCycle(ply)
SetParent(ply.Body, ply)
SetPos(ply.Body, getPos)
SetAngles(ply.Body, eyeAngles)
SetPlaybackRate(ply.Body, GetPlaybackRate(ply))
SetCycle(ply.Body, cycle)
local currentView = ply:GetCurrentViewOffset()
local forward = eyeAngles:Forward() * forwardDistance
ply.TimeToFaggot = math.Clamp((ply.TimeToFaggot or 0) + FT * (ply:Crouching() and 4 or 10000) * (not onGround and 1 or -1), 0, 1)
SetParent(ply.Body_NoDraw, ply)
SetPos(ply.Body_NoDraw, getPos)
SetAngles(ply.Body_NoDraw, eyeAngles - Legs_NoDraw_Angle)
faggot = (not onGround or limitJump > CurTime()) and getView - currentView or vector_origin
finalPos = getPos
+ currentView
+ forward
+ (faggot * ply.TimeToFaggot)
end)
local vector_down = Vector(0, 0, -1)
local vec1 = Vector(0, 0, 1)
local erroredModels = {}
hook.Add("PreDrawViewModels", "firstperson.PreDrawViewModel", function(depth, skybox, isDraw3DSkybox)
if not SuR.EnableFPBody then
return
end
local current = ply.wardrobe or ply:GetModel()
if not erroredModels[current]
and (not IsValid(ply.Body)
or ply.Body:GetModel() ~= current) then
MarkToRemove(ply.Body)
MarkToRemove(ply.Body_NoDraw)
ply.Body = ClientsideModel(current)
ply.Body:SetNoDraw(true)
ply.Body:SetIK(false)
SetupBones(ply.Body)
ply.Body.GetPlayerColor = function()
return ply:GetPlayerColor()
end
local seq = ply.Body:LookupSequence("idle_all_01")
if seq < 0 then
MarkToRemove(ply.Body)
erroredModels[current] = true
return
end
ply.Body_NoDraw = ClientsideModel(current)
ply.Body_NoDraw:SetNoDraw(true)
ply.Body_NoDraw:SetIK(false)
ply.Body_NoDraw.GetPlayerColor = function()
return ply:GetPlayerColor()
end
ply.Body_NoDraw:SetSequence(seq)
ply.Body.FullyLoaded, timeCacheBones = false, 0
end
if suppress then
return
end
local RT = render.GetRenderTarget()
if RT then
return
end
if hook.Run("ShouldDisableLegs", ply.Body) == true then
return
end
local ret = hook.Run("PreDrawBody", ply.Body)
if ret == false then
return
end
local shootPos, getPos = _EyePos(ply), GetPos(ply)
shootPos.z = 0
getPos.z = 0
local color = ply:GetColor()
local m1, m2, m3 = render.GetColorModulation()
cam_Start3D(finalPos + (shootPos - getPos), nil, nil, 0, 0, nil, nil, 0.5, -1)
local bEnabled = render_EnableClipping(true)
render_PushCustomClipPlane(vector_down, vector_down:Dot(finalPos + vec1))
render.SetColorModulation(color.r / 255, color.g / 255, color.b / 255)
ply.Body:DrawModel()
render.SetColorModulation(m1, m2, m3)
render_PopCustomClipPlane()
render_EnableClipping(bEnabled)
cam_End3D()
hook.Run("PostDrawBody", ply.Body)
end)
hook.Add("PreDrawBody", "sur_body.PreDrawBody_Compat", function()
if VWallrunning
or inmantle then
return false
end
end)
end)
hook.Add("Think", "sur_legs.Load", function()
local ply = LocalPlayer()
if IsValid(ply) then
hook.Remove("Think", "sur_legs.Load")
hook.Run("LocalPlayer_Validated", ply)
end
end)

View File

@@ -0,0 +1,377 @@
--By Shadow Bonnie from GitHub
OUTLINE_MODE_BOTH = 0 -- Render always
OUTLINE_MODE_NOTVISIBLE = 1
OUTLINE_MODE_VISIBLE = 2
OUTLINE_RENDERTYPE_BEFORE_VM = 0 -- Render before drawing the view model
OUTLINE_RENDERTYPE_BEFORE_EF = 1 -- Render before drawing all effects (after drawing the viewmodel)
OUTLINE_RENDERTYPE_AFTER_EF = 2 -- Render after drawing all effects
local istable = istable
local render = render
local Material = Material
local CreateMaterial = CreateMaterial
local hook = hook
local cam = cam
local ScrW = ScrW
local ScrH = ScrH
local IsValid = IsValid
local surface = surface
module( "outline", package.seeall )
local List, ListSize = {}, 0
local RenderEnt = NULL
local RenderType = OUTLINE_RENDERTYPE_AFTER_EF
local OutlineThickness = 1
local StoreTexture = render.GetScreenEffectTexture( 0 )
local DrawTexture = render.GetScreenEffectTexture( 1 )
local OutlineMatSettings = {
[ "$basetexture" ] = DrawTexture:GetName(),
[ "$ignorez" ] = 1,
[ "$alphatest" ] = 1
}
local CopyMat = Material( "pp/copy" )
local OutlineMat = CreateMaterial( "outline", "UnlitGeneric", OutlineMatSettings )
local ENTS, COLOR, MODE = 1, 2, 3
function Add( ents, color, mode )
if ( ListSize >= 255 ) then return end --Maximum 255 reference values
if ( !istable( ents ) ) then ents = { ents } end --Support for passing Entity as first argument
if ( ents[ 1 ] == nil ) then return end --Do not pass empty tables
if (
mode != OUTLINE_MODE_BOTH &&
mode != OUTLINE_MODE_NOTVISIBLE &&
mode != OUTLINE_MODE_VISIBLE
) then
mode = OUTLINE_MODE_BOTH
end
local data = {
[ ENTS ] = ents,
[ COLOR ] = color,
[ MODE ] = mode
}
ListSize = ListSize + 1
List[ ListSize ] = data
end
function RenderedEntity()
return RenderEnt
end
function SetRenderType( render_type )
if (
render_type != OUTLINE_RENDERTYPE_BEFORE_VM &&
render_type != OUTLINE_RENDERTYPE_BEFORE_EF &&
render_type != OUTLINE_RENDERTYPE_AFTER_EF
) then
return
end
local old_type = RenderType
RenderType = render_type
return old_type
end
function GetRenderType()
return RenderType
end
function SetDoubleThickness( thickness )
local old_thickness = OutlineThickness == 2
OutlineThickness = thickness && 2 || 1
return old_thickness
end
function IsDoubleThickness()
return OutlineThickness == 2
end
local function Render()
local scene = render.GetRenderTarget()
render.CopyRenderTargetToTexture( StoreTexture )
local w, h = ScrW(), ScrH()
render.ClearStencil()
render.SetStencilEnable( true )
render.SuppressEngineLighting( true )
render.SetStencilWriteMask( 0xFF )
render.SetStencilTestMask( 0xFF )
render.SetStencilCompareFunction( STENCIL_GREATER )
render.SetStencilFailOperation( STENCIL_KEEP )
cam.Start3D()
render.SetBlend(1)
for i = 1, ListSize do
local reference = 0xFF - ( i - 1 )
local data = List[ i ]
local mode = data[ MODE ]
local ents = data[ ENTS ]
render.SetStencilReferenceValue( reference )
if ( mode == OUTLINE_MODE_BOTH || mode == OUTLINE_MODE_VISIBLE ) then
render.SetStencilZFailOperation( mode == OUTLINE_MODE_BOTH && STENCIL_REPLACE || STENCIL_KEEP )
render.SetStencilPassOperation( STENCIL_REPLACE )
for j = 1, #ents do
local ent = ents[ j ]
if ( IsValid( ent ) ) then
RenderEnt = ent
ent:DrawModel()
end
end
elseif ( mode == OUTLINE_MODE_NOTVISIBLE ) then
render.SetStencilZFailOperation( STENCIL_REPLACE )
render.SetStencilPassOperation( STENCIL_KEEP )
for j = 1, #ents do
local ent = ents[ j ]
if ( IsValid( ent ) ) then
RenderEnt = ent
ent:DrawModel()
end
end
render.SetStencilCompareFunction( STENCIL_EQUAL )
render.SetStencilZFailOperation( STENCIL_KEEP )
render.SetStencilPassOperation( STENCIL_ZERO )
for j = 1, #ents do
local ent = ents[ j ]
if ( IsValid( ent ) ) then
RenderEnt = ent
ent:DrawModel()
end
end
render.SetStencilCompareFunction( STENCIL_GREATER )
end
end
RenderEnt = NULL
render.SetBlend(1)
cam.End3D()
render.SetStencilCompareFunction( STENCIL_EQUAL )
render.SetStencilZFailOperation( STENCIL_KEEP )
render.SetStencilPassOperation( STENCIL_KEEP )
render.Clear( 0, 0, 0, 0, false, false )
cam.Start2D()
for i = 1, ListSize do
local reference = 0xFF - ( i - 1 )
render.SetStencilReferenceValue( reference )
surface.SetDrawColor( List[ i ][ COLOR ] )
surface.DrawRect( 0, 0, w, h )
end
cam.End2D()
render.SuppressEngineLighting( false )
render.SetStencilEnable( false )
render.CopyRenderTargetToTexture( DrawTexture )
render.SetRenderTarget( scene )
CopyMat:SetTexture( "$basetexture", StoreTexture )
render.SetMaterial( CopyMat )
render.DrawScreenQuad()
render.SetStencilEnable( true )
render.SetStencilReferenceValue( 0 )
render.SetStencilCompareFunction( STENCIL_EQUAL )
OutlineMat:SetTexture( "$basetexture", DrawTexture )
render.SetMaterial( OutlineMat )
render.DrawScreenQuadEx( -OutlineThickness, -OutlineThickness, w ,h )
render.DrawScreenQuadEx( -OutlineThickness, 0, w, h )
render.DrawScreenQuadEx( -OutlineThickness, OutlineThickness, w, h )
render.DrawScreenQuadEx( 0, -OutlineThickness, w, h )
render.DrawScreenQuadEx( 0, OutlineThickness, w, h )
render.DrawScreenQuadEx( OutlineThickness, -OutlineThickness, w, h )
render.DrawScreenQuadEx( OutlineThickness, 0, w, h )
render.DrawScreenQuadEx( OutlineThickness, OutlineThickness, w, h )
render.SetStencilEnable( false )
render.ClearDepth() -- Allows to render view model and other stuff in front of outline
end
local function RenderOutlines()
hook.Run( "SetupOutlines", Add )
if ( ListSize == 0 ) then return end
Render()
List, ListSize = {}, 0
end
hook.Add( "PreDrawViewModels", "RenderOutlines", function()
if ( RenderType == OUTLINE_RENDERTYPE_BEFORE_VM ) then
RenderOutlines()
end
end )
hook.Add( "PreDrawEffects", "RenderOutlines", function()
if ( RenderType == OUTLINE_RENDERTYPE_BEFORE_EF ) then
RenderOutlines()
end
end )
hook.Add( "PostDrawEffects", "RenderOutlines", function()
if ( RenderType == OUTLINE_RENDERTYPE_AFTER_EF ) then
RenderOutlines()
end
end )
-----------------------------------------------------------------------------------
hook.Add("SetupOutlines", "SuR_ScoutAbility", function()
local ply = LocalPlayer()
--------------------------
if ply:Alive() and ply:IsSurvivor() then
local tab1 = {}
local tab2 = {}
local tab3 = {}
local tab4 = {}
for _, ent in pairs(player.GetAll()) do
if ent:IsZombie() or !ent:Alive() or ply:IsLineOfSightClear(ent) then continue end
local alpha = 255/(ent:EyePos():Distance(EyePos())/500)
if string.match(ent:GetSVAnim(), "executions") or string.match(ent:GetSVAnim(), "killmove") or string.match(ent:GetSVAnim(), "grappleloop") then
tab4[#tab4+1] = ent
elseif ent:IsDowned() then
tab3[#tab3+1] = ent
elseif alpha > 200 then
tab1[#tab1+1] = ent
else
tab2[#tab2+1] = ent
end
end
outline.Add(tab1, Color(200,200,200), 1)
outline.Add(tab2, Color(120,120,120,180), 1)
outline.Add(tab3, Color(200,20,20), 1)
outline.Add(tab4, Color(200,120,20), 1)
local tr = ply:GetEyeTrace().Entity
if !ply:IsLockedAbilities() and IsValid(tr) and string.match(tr:GetClass(), "vj") and tr:GetPos():DistToSqr(ply:GetPos()) < 10000 and tr:GetNWBool('flinching', false) and tr:Health() <= 200 then
outline.Add({tr}, Color(180,0,0), 2)
end
end
--------------------------
if not SuR.Config.Objective_Mode and ply:GetPlayerClass() == "scout" and ply:GetLevelState() >= 1 and ply:Alive() then
local tab = {}
for _, ent in pairs(ents.FindInSphere(ply:GetPos(), 400)) do
if ent:GetClass() == "sur_loot" or ent:GetClass() == "sur_resupply" then
tab[#tab+1] = ent
end
end
outline.Add(tab, Color(150,200,150), 1)
end
--------------------------
if SuR.Config.Objective_Mode and ply:Alive() then
local wep = ply:GetWeapon("sur_fuel")
if IsValid(wep) then
local tab = {}
local ftab = ents.FindByClass("sur_generator")
for i = 1, #ftab do
local v = ftab[i]
if !v:GetNWBool('HaveFuel', false) then
tab[#tab+1] = v
end
end
outline.Add(tab, Color(220,200,0), 1)
else
local tab = {}
local ftab = ents.FindByClass("sur_loot")
for i = 1, #ftab do
local v = ftab[i]
if v:GetModel() == "models/surrounded/obj/w_jerrycanblue.mdl" then
tab[#tab+1] = v
end
end
outline.Add(tab, Color(240,160,0), 1)
end
end
end)

View File

@@ -0,0 +1,31 @@
AddCSLuaFile("shared.lua")
AddCSLuaFile("client/cl_hud.lua")
AddCSLuaFile("client/cl_menu.lua")
AddCSLuaFile("client/cl_abilities.lua")
AddCSLuaFile("client/cl_cutscenes.lua")
AddCSLuaFile("client/cl_outline.lua")
AddCSLuaFile("client/cl_other.lua")
AddCSLuaFile("client/cl_buymenu.lua")
include("shared.lua")
include("server/sv_nets.lua")
include("server/sv_abilities.lua")
include("server/sv_functions.lua")
include("server/sv_revive.lua")
include("server/sv_nodegraph.lua")
include("server/sv_waves.lua")
include("server/sv_lnr.lua")
include("server/sv_executions.lua")
include("server/sv_exfil.lua")
include("server/sv_qte.lua")
include("server/sv_classes.lua")
include("server/sv_other.lua")
include("server/sv_buymenu.lua")
local url = SuR.Config.LoadingURL
if isstring(url) and url != "" then
RunConsoleCommand("sv_loadingurl", url)
end
hook.Add("ShutDown", "SuR.ShutDown", function()
RunConsoleCommand("sv_loadingurl", "")
end)

View File

@@ -0,0 +1,280 @@
SuR.Language = {
["settings_main"] = "Client Settings",
["settings_vm"] = "View mode",
["settings_vmc"] = "3rd person cutscenes?",
["settings_vmd"] = "3rd person death animations?",
["settings_mv"] = "Music Volume",
["settings_rus"] = "Enable russian voicelines",
["settings_zc"] = "Disable interface",
["settings_dh"] = "Disable tips",
["mode"] = "Mode: ",
["mode_survival"] = "Survival",
["mode_versus"] = "Versus",
["mode_objective"] = "Objective",
["pmsettings_main"] = "Character Model",
["pmsettings_wep"] = "Character Weapon",
["pmsettings_voice"] = "Character Voice",
["pmsettings_mes1"] = "You can't edit your character, while the wave has started.",
["pmsettings_mes2"] = "You changed the settings for your character.",
["pmsettings_mes3"] = "You can only change character settings when you are in spectator mode.",
["pmsettings_info"] = "Settings will be saved after closing",
["classmenu_choose"] = "Viewing class: %s, class level - %s",
["classmenu_current"] = "Your current class: ",
["classmenu_info"] = "Ability Information",
["classmenu_state"] = "Unlock level - ",
["adminsettings_main"] = "Admin Settings",
["adminsettings_startgame"] = "Start Game",
["adminsettings_skipwave"] = "Skip Wave",
["adminsettings_spawnmenu"] = "Open Spawnmenu",
["fuel"] = "Fuel",
["evac"] = "Evacuation",
["evac_start"] = "EXFIL HELICOPTER INBOUND",
["evac_last_start"] = "LAST EXFIL HELICOPTER INBOUND",
["radio_main"] = "RADIO",
["radio_1"] = "Call supply drop",
["radio_2"] = "Request artillery support",
["radio_3"] = "Call reinforcements",
["radio_4"] = "Deploy bait",
["radio_5"] = "Call assault helicopter",
["radio_6"] = "Start exfil",
["radio_6_warn"] = "Exfil will be allowed on %i wave.",
["radio_6_disable"] = "Exfil is not allowed on this map.",
["radio_7"] = "Buy weapon",
["revive_main"] = "You are heavily wounded",
["revive_wait"] = "Wait for your teammates to revive you",
["revive_help"] = "Hold [E] to help your teammate",
["revive_self"] = "Press [E] to use self revive kit",
["main_count"] = "Enemies remaining: ",
["main_wave"] = "WAVE ",
["main_pickup"] = "Press [E] to pick up ",
["killstreak_exec"] = "EXECUTION",
["killstreak_1"] = "DOUBLE KILL",
["killstreak_2"] = "TRIPLE KILL",
["killstreak_3"] = "ULTRA KILL",
["killstreak_4"] = "MEAT GRINDER",
["message_main1"] = "Survive",
["message_main2"] = "You can find loot in buildings every wave",
["message_wavestart1"] = "Wave %i has started",
["message_wavestart2"] = "Each wave will become more difficult",
["message_waveend1"] = "Wave %i has ended",
["message_waveend2"] = "You have time to search for loot and catch your breath",
["message_thelp1"] = " has been critically wounded",
["message_thelp2"] = "Help your teammate before he bleeds out",
["message_tdied1"] = "You have suffered a loss",
["message_tdied2"] = " was killed in action",
["message_radio_accept"] = "Radio request accepted",
["message_radio_support"] = "New reinforcements have arrived in your sector",
["message_radio_mortar"] = "Mark targets for artillery support using markers",
["message_radio_away"] = "Bait will be deployed in 15 seconds",
["message_radio_supply"] = "Supply drop will be delivered in 30 seconds",
["message_radio_heli"] = "Assault helicopter will be arrived in 30 seconds",
["message_radio_exfil"] = "Exfil will start in 2 minutes",
["message_warn"] = "Warning",
["message_zombie_phase"] = "The horde has mutated to the %i stage, get ready",
["message_mark"] = " placed a mark",
["message_info"] = "Information",
["message_radio_found"] = " found a radio",
["message_healed"] = "You were healed by ",
["message_healing"] = "You have healed ",
["message_open_box"] = " opened the supply box",
["message_fuel"] = " used a fuel canister",
["message_obj_done"] = "The task has been completed, move to the evacuation point",
["loot_pistol"] = "Pistol Rounds",
["loot_smg"] = "SMG Rounds",
["loot_bucks"] = "Buckshot",
["loot_ar"] = "AR Rounds",
["loot_sr"] = "SR Rounds",
["loot_radio"] = "Radio",
["loot_bandages"] = "Bandages",
["loot_antidote"] = "Antidote",
["loot_nails"] = "Nails",
["loot_fak"] = "First Aid Kit",
["loot_gr"] = "Explosive Round",
["loot_ammocrate"] = "Ammo Crate",
["loot_selfrevive"] = "Self Revive Kit",
["loot_capsule"] = "XP Capsule",
["loot_grenades"] = "Grenade Crate",
["loot_money"] = "Money",
["loot_tier1"] = "Common",
["loot_tier2"] = "Uncommon",
["loot_tier3"] = "Rare",
["loot_tier4"] = "Epic",
["loot_tier5"] = "Legendary",
["game_over_main"] = "The Survivor Squad was overrun",
["game_over_success"] = "Exfil was successful",
["game_over_wave"] = "You survived %i wave",
["deploy_big"] = "There are more people in the squad than you see, when you deploy you will see them.",
["deploy_hint"] = "By pressing ESC, you can open the main menu and customize your character",
["deploy_time"] = "Time to deployment: %i sec.",
["deploy_error_node"] = "[Gamemode Error] There are no AI Nodes on the map, please install AI nodes for the map",
["deploy_error_config"] = "[Gamemode Error] There is no config on the map, please create a config for the map",
["main_menu_1"] = "Continue",
["main_menu_2"] = "Character",
["main_menu_3"] = "Classes",
["main_menu_4"] = "Settings",
["main_menu_discord"] = "Discord Community",
["main_menu_site"] = "Our Website",
["main_menu_5"] = "Main Menu",
["hud_discord_join"] = "Join us on Discord!",
["menu_drop"] = "Drop Items",
["menu_nodrop"] = "You don't have any items.",
["heal_bandages"] = "Press [B] to patch up your teammate",
["heal_spray"] = "Press [H] to cure your infected teammate",
["unreachable"] = "You are in a position where the NPCs can't reach you, you will be teleported if you don't get out of there.",
["start_message1"] = "Objective: Kill as many zombies as possible, in extreme cases - evacuate.",
["start_message_fuel"] = "Objective: Refuel the generators and retreat to the evacuation zone.",
["hammer_parts"] = "Nails: ",
["hammer_controls"] = "Controls: LMB - Attach, RMB - Unattach, R - Drag, Shift - Hold, Alt - Rotate",
["boss_punk"] = "Punk",
["boss_butcher"] = "Butcher",
["boss_tyrant"] = "Tyrant",
["boss_tank"] = "Tank",
["mutator_main"] = "Mutator",
["mutator_appear"] = "A mutator has been discovered for this wave, get ready",
["mutator_1"] = "Explosive Burst",
["mutator_2"] = "Mutator Breakthrough",
["mutator_3"] = "Strong Grip",
["mutator_4"] = "Fragile organs",
["mutator_5"] = "Berserker",
["mutator_6"] = "Necrosis",
["mutator_7"] = "Loser",
["mutator_8"] = "Airstrike",
["mutator_9"] = "Scavenger",
["mutator_10"] = "Pain Shock",
["mutator_11"] = "Gas Leak",
["mutator_12"] = "Weakness",
["mutator_1_desc"] = "Zombies may explode when killed",
["mutator_2_desc"] = "All zombies mutated into special variants",
["mutator_3_desc"] = "Zombies grab the player more often",
["mutator_4_desc"] = "Zombie health reduced to 25%",
["mutator_5_desc"] = "Melee damage will instakill zombies",
["mutator_6_desc"] = "Any melee hit by a zombie will cause a infection",
["mutator_7_desc"] = "Items stopped spawning, until next wave",
["mutator_8_desc"] = "Permanent supply drop every minute",
["mutator_9_desc"] = "Zombies may drop loot upon death",
["mutator_10_desc"] = "Players immediately die upon losing all their health",
["mutator_11_desc"] = "A deadly gas leak has been discovered, get ready to exfil",
["mutator_12_desc"] = "Players move slowly, as if injured",
["zombiemenu_choose"] = "Choose Zombie Class",
["zombiemenu_unlock"] = "Unlock on %i wave",
["zombiemenu_unlocked"] = "Unlocked",
["zombie_attack1"] = "Attack - LMB",
["zombie_attack2"] = "Ability - RMB",
["zombie_spawn"] = "LMB - Spawn as a zombie",
["zombie_wait"] = "Wait for the wave to start attack again",
["zombie_choose"] = "The game has chosen you to be infected, kill all humans",
["zombie_menu"] = "F1 - Select zombie class",
["tip_main"] = "Tips",
["tip_survival"] = "Beginning",
["tip_survival_desc"] = "Greetings, survivor! Quite a long time has passed since the virus spread across the planet, now your main task is to survive. You can find things most often in buildings, they will help you fight off attacks. If you don't need hints, you can turn them off. Good luck!",
["tip_waves"] = "Waves",
["tip_waves_desc"] = "The further you survive in this place, the more and more difficult the infected become, so look for equipment as quickly as possible! With each wave of them, the onslaught increases. Their evolution does not stand still...",
["tip_items"] = "Items",
["tip_items_desc"] = "Equipment scattered around the location is an important part of your survival. The higher the wave, the greater the chances of finding rare equipment. By the way, on F1 you can share things with your teammates, on F2 you can mark positions, items and enemies.",
["tip_bosses"] = "Leaders",
["tip_bosses_desc"] = "On some waves, you can meet the so-called leaders. Leaders are the most powerful infected who lead the main crowd. I hope you have already found the equipment, since the battle with him will be extremely difficult...",
["tip_revive"] = "Revive",
["tip_revive_desc"] = "Someday, you or your partner will be seriously injured, causing you to fall to the ground. Try to help your partner as soon as possible, with each wave the zombies react better to those who have fallen.",
["tip_radio"] = "Radio",
["tip_radio_desc"] = "Finally, you were able to find contact with the military. Now you can request reinforcements or evacuation from them. I advise you to take care of the radios, as they are very rare. They play a key role in your survival...",
["tip_cade"] = "Hammer",
["tip_cade_desc"] = "This find greatly increases your chances of survival. By picking up a hammer and finding some nails, you can build a barricade from movable objects. To nail an object, you need to aim at its edge and hammer in a nail. Unfortunately, the strength items have limits, be careful!",
["tip_evac"] = "Evacuation",
["tip_evac_desc"] = "Well, survivor, it's time to leave here. You have to fight a huge horde of zombies to hold out and make your way to the helicopter. Usually the helicopter flight to the landing site takes 2 minutes. I hope we see you alive, I wish you Good luck.",
["class_survivor"] = "Survivor",
["class_scout"] = "Scout",
["class_medic"] = "Medic",
["class_engineer"] = "Engineer",
["class_marksman"] = "Shooter",
["class_berserker"] = "Berserker",
["class_demoman"] = "Demoman",
["class_survivor_state_1"] = "At start, 1 emergency kit is given",
["class_survivor_state_2"] = "You can now escape from grabs much easier",
["class_survivor_state_3"] = "Damage from firearms weapons increased by 10%",
["class_survivor_state_4"] = "Damage from firearms weapons increased by 20%",
["class_survivor_state_5"] = "Damage from firearms weapons increased by 30%",
["class_scout_state_1"] = "Ability to see nearby items through the wall",
["class_scout_state_2"] = "Running speed increased by 20%",
["class_scout_state_3"] = "At start you are given 2 radios",
["class_scout_state_4"] = "Running speed increased by 40%",
["class_scout_state_5"] = "At start you are given 5 radios",
["class_medic_state_1"] = "At start you are given 9 bandages and 3 antidotes",
["class_medic_state_2"] = "Bandages now heal full health",
["class_medic_state_3"] = "At start you are given 18 bandages, 6 antidotes, 3 emergency kits",
["class_medic_state_4"] = "You can now instantly revive downed players",
["class_medic_state_5"] = "At start you are given 100 bandages and 50 antidotes, 5 emergency kits",
["class_engineer_state_1"] = "The strength of the barricades is increased by 10%",
["class_engineer_state_2"] = "At start you are given a hammer and nails",
["class_engineer_state_3"] = "Barricade strength increased by 50%",
["class_engineer_state_4"] = "Barricade strength increased by 100%",
["class_engineer_state_5"] = "A landmines is given at startup",
["class_marksman_state_1"] = "Additional ammo is given at start",
["class_marksman_state_2"] = "Sniper rifle damage increased by 25%",
["class_marksman_state_3"] = "Sniper rifle damage increased by 50%",
["class_marksman_state_4"] = "At start, you are given a random weapon of rarity 3",
["class_marksman_state_5"] = "Sniper rifle damage increased by 100%",
["class_berserker_state_1"] = "Melee weapon damage increased by 50%",
["class_berserker_state_2"] = "Kick damage increased by 4 times",
["class_berserker_state_3"] = "Melee weapon damage increased by 100%, random melee weapon on spawn",
["class_berserker_state_4"] = "Reducing damage at half to player",
["class_berserker_state_5"] = "Melee weapon damage increased by 200%",
["class_demoman_state_1"] = "Stun by damage is disabled, damage from explosions reduced",
["class_demoman_state_2"] = "Double ammo for grenade launchers",
["class_demoman_state_3"] = "M79 giving at start",
["class_demoman_state_4"] = "Damage from explosions increased by 50%",
["class_demoman_state_5"] = "Damage from explosions increased by 100%",
["class_lvl_1"] = "Beginner I",
["class_lvl_2"] = "Beginner II",
["class_lvl_3"] = "Beginner III",
["class_lvl_4"] = "Beginner IV",
["class_lvl_5"] = "Beginner V",
["class_lvl_6"] = "Average I",
["class_lvl_7"] = "Average II",
["class_lvl_8"] = "Average III",
["class_lvl_9"] = "Average IV",
["class_lvl_10"] = "Average V",
["class_lvl_11"] = "Experienced I",
["class_lvl_12"] = "Experienced II",
["class_lvl_13"] = "Experienced III",
["class_lvl_14"] = "Experienced IV",
["class_lvl_15"] = "Experienced V",
["class_lvl_16"] = "Veteran I",
["class_lvl_17"] = "Veteran II",
["class_lvl_18"] = "Veteran III",
["class_lvl_19"] = "Veteran IV",
["class_lvl_20"] = "Veteran V",
["class_lvl_21"] = "Expert",
["buymenu_main"] = "Shop",
["buymenu_buy"] = "Buy",
}

View File

@@ -0,0 +1,280 @@
SuR.Language = {
["settings_main"] = "Клиентские настройки",
["settings_vm"] = "Режим камеры",
["settings_vmc"] = "Катсцены от 3 лица?",
["settings_vmd"] = "Анимации смерти от 3 лица?",
["settings_mv"] = "Громкость музыки",
["settings_rus"] = "Включить русскую озвучку",
["settings_zc"] = "Отключить интерфейс",
["settings_dh"] = "Отключить советы",
["mode"] = "Режим: ",
["mode_survival"] = "Выживание",
["mode_versus"] = "Сражение",
["mode_objective"] = "Операция",
["pmsettings_main"] = "Модель персонажа",
["pmsettings_wep"] = "Оружие персонажа",
["pmsettings_voice"] = "Голос персонажа",
["pmsettings_mes1"] = "Вы можете поменять настройки персонажа только во время передышки.",
["pmsettings_mes2"] = "Вы изменили настройки персонажа на новые.",
["pmsettings_mes3"] = "Вы можете поменять настройки персонажа только, когда вы не играете за персонажа.",
["pmsettings_info"] = "Настройки сохранятся после закрытия",
["classmenu_choose"] = "Просмотр класса: %s, его уровень - %s",
["classmenu_current"] = "Ваш текущий класс: ",
["classmenu_info"] = "Информация о способностях",
["classmenu_state"] = "Уровень разблокировки - ",
["adminsettings_main"] = "Админ настройки",
["adminsettings_startgame"] = "Начать игру",
["adminsettings_skipwave"] = "Пропустить волну",
["adminsettings_spawnmenu"] = "Открыть спавнменю",
["fuel"] = "Топливо",
["evac"] = "Эвакуация",
["evac_start"] = "ЭВАКУАЦИОННЫЙ ВЕРТОЛЁТ ВЫЛЕТЕЛ",
["evac_last_start"] = "ПОСЛЕДНИЙ ЭВАКУАЦИОННЫЙ ВЕРТОЛЁТ ВЫЛЕТЕЛ",
["radio_main"] = "РАДИО",
["radio_1"] = "Вызвать посылку с припасами",
["radio_2"] = "Указать цель для артобстрела",
["radio_3"] = "Доставить подкрепление",
["radio_4"] = "Запустить приманку",
["radio_5"] = "Вызвать вертолёт поддержки",
["radio_6"] = "Начать эвакуацию",
["radio_6_warn"] = "Эвакуацию можно начать только с %i волны.",
["radio_6_disable"] = "Эвакуация невозможна на этой карте.",
["radio_7"] = "Купить оружие",
["revive_main"] = "Вы тяжело ранены",
["revive_wait"] = "Подождите пока вас поднимут напарники",
["revive_help"] = "Зажмите [E] чтобы помочь напарнику",
["revive_self"] = "Нажмите [E] чтобы использовать набор самореанимации",
["main_count"] = "Осталось врагов: ",
["main_wave"] = "ВОЛНА ",
["main_pickup"] = "Нажмите [E] чтобы подобрать ",
["killstreak_exec"] = "ДОБИВАНИЕ",
["killstreak_1"] = "ДВОЙНОЕ УБИЙСТВО",
["killstreak_2"] = "ТРОЙНОЕ УБИЙСТВО",
["killstreak_3"] = "УЛЬТРА УБИЙСТВО",
["killstreak_4"] = "МЯСОРУБКА",
["message_main1"] = "Выживите",
["message_main2"] = "Вы можете найти лут в доме каждую волну",
["message_wavestart1"] = "Волна %i началась",
["message_wavestart2"] = "С каждой волной становится всё сложней",
["message_waveend1"] = "Волна %i закончилась",
["message_waveend2"] = "У вас есть время на поиск лута и передышку",
["message_thelp1"] = " получил тяжелое ранение",
["message_thelp2"] = "Помогите напарнику до того как он истечет кровью",
["message_tdied1"] = "Вы несете потери",
["message_tdied2"] = " погиб в бою",
["message_radio_accept"] = "Запрос по рации принят",
["message_radio_support"] = "Новые бойцы прибыли в ваш сектор",
["message_radio_mortar"] = "Укажите цели для артобстрела с помощью маркеров",
["message_radio_away"] = "Сброс приманки будет в течении 15 секунд",
["message_radio_supply"] = "Сброс припасов будет в течении 30 секунд",
["message_radio_heli"] = "Вертолёт поддержки будет в течении 30 секунд",
["message_radio_exfil"] = "Эвакуация начнется через 2 минуты",
["message_warn"] = "Внимание",
["message_zombie_phase"] = "Орда развилась до %i стадии, будьте готовы",
["message_mark"] = " поставил метку",
["message_info"] = "Информация",
["message_radio_found"] = " нашел рацию",
["message_healed"] = "Вас вылечил ",
["message_healing"] = "Вы вылечили ",
["message_open_box"] = " открыл ящик с припасами",
["message_fuel"] = " использовал канистру с топливом",
["message_obj_done"] = "Задача была выполнена, бегите в точку эвакуации",
["loot_pistol"] = "Патроны для пистолетов",
["loot_smg"] = "Патроны для СМГ",
["loot_bucks"] = "Патроны для дробовика",
["loot_ar"] = "Патроны для автом. винтовок",
["loot_sr"] = "Патроны для снайп. винтовок",
["loot_radio"] = "Рация",
["loot_bandages"] = "Бинты",
["loot_antidote"] = "Антидот",
["loot_nails"] = "Гвозди",
["loot_fak"] = "Аптечка",
["loot_gr"] = "Снаряд",
["loot_ammocrate"] = "Ящик с патронами",
["loot_selfrevive"] = "Набор самореанимации",
["loot_capsule"] = "Капсула опыта",
["loot_grenades"] = "Ящик с гранатами",
["loot_money"] = "Деньги",
["loot_tier1"] = "Стартовый",
["loot_tier2"] = "Обычный",
["loot_tier3"] = "Редкий",
["loot_tier4"] = "Раритетный",
["loot_tier5"] = "Легендарный",
["game_over_main"] = "Группа Выживших была уничтожена",
["game_over_success"] = "Эвакуация завершилась успешно",
["game_over_wave"] = "Вы прожили %i волн",
["deploy_big"] = "В отряде больше человек, чем вы видите, при высадке вы их увидите.",
["deploy_hint"] = "На клавишу ESC, вы можете открыть главное меню и настроить вашего персонажа",
["deploy_time"] = "Время до высадки: %i сек.",
["deploy_error_node"] = "[Режим Остановлен] На карте нет AI Nodes, пожалуйста установите сетку на карту",
["deploy_error_config"] = "[Режим Остановлен] На карте нет config файла, пожалуйста сделайте config файл для карты",
["main_menu_1"] = "Продолжить",
["main_menu_2"] = "Персонаж",
["main_menu_3"] = "Классы",
["main_menu_4"] = "Настройки",
["main_menu_discord"] = "Сообщество Discord",
["main_menu_site"] = "Наш сайт",
["main_menu_5"] = "Главное меню",
["hud_discord_join"] = "Присоединяйтесь к нам в Discord!",
["menu_drop"] = "Выбросить предмет",
["menu_nodrop"] = "У вас нету вещей.",
["heal_spray"] = "Нажмите [H] чтобы вылечить инфекцию напарника",
["heal_bandages"] = "Нажмите [B] чтобы завязать раны напарника",
["unreachable"] = "Вы находитесь в позиции, где вас не могут достать нпс, вы будете телепортированы, если не выберитесь оттуда.",
["start_message1"] = "Ваша задача: Убить как можно больше зомби, в крайнем случае - эвакуироваться.",
["start_message_fuel"] = "Ваша задача: Заправить генераторы и отступить в зону эвакуации.",
["hammer_parts"] = "Гвозди: ",
["hammer_controls"] = "Управление: ЛКМ - Прибить, ПКМ - Открепить, R - Перетаскивать, Shift - Удерживать, Alt - Вращать",
["boss_punk"] = "Панк",
["boss_butcher"] = "Мясник",
["boss_tyrant"] = "Тиран",
["boss_tank"] = "Танк",
["mutator_main"] = "Мутатор",
["mutator_appear"] = "На эту волну был обнаружен мутатор, готовтесь",
["mutator_1"] = "Взрывная серия",
["mutator_2"] = "Прорыв мутаций",
["mutator_3"] = "Сильный хват",
["mutator_4"] = "Хрупкие органы",
["mutator_5"] = "Берсерк",
["mutator_6"] = "Некроз",
["mutator_7"] = "Неудачник",
["mutator_8"] = "Авианалет",
["mutator_9"] = "Падальщик",
["mutator_10"] = "Болевой шок",
["mutator_11"] = "Утечка газа",
["mutator_12"] = "Слабость",
["mutator_1_desc"] = "После смерти зомби могут взорваться",
["mutator_2_desc"] = "Все обычные зомби мутировали в специальных",
["mutator_3_desc"] = "Зомби чаще хватают игрока",
["mutator_4_desc"] = "Жизни зомби уменьшены до 25%",
["mutator_5_desc"] = "Любой удар с рукопашного оружия, убивает зомби",
["mutator_6_desc"] = "Любой удар зомби приведёт к инфекции",
["mutator_7_desc"] = "На локации и в посылках больше нету вещей",
["mutator_8_desc"] = "Постоянный сброс припасов каждую минуту",
["mutator_9_desc"] = "С зомби может упасть лут после смерти",
["mutator_10_desc"] = "Игроки умирают сразу без падения",
["mutator_11_desc"] = "Произошла утечка смертельного газа, готовтесь",
["mutator_12_desc"] = "Игроки ходят медленно, как при ранении",
["zombiemenu_choose"] = "Выбор класса зомби",
["zombiemenu_unlock"] = "Доступ на %i волне",
["zombiemenu_unlocked"] = "Разблокирован",
["zombie_attack1"] = "Удар - ЛКМ",
["zombie_attack2"] = "Способность - ПКМ",
["zombie_spawn"] = "ЛКМ - Возродиться за зомби",
["zombie_wait"] = "Ожидайте начало волны, чтобы возобновить атаку",
["zombie_choose"] = "Игра выбрала вас зараженным, убейте всех людей",
["zombie_menu"] = "F1 - Выбрать класс зомби",
["tip_main"] = "Советы",
["tip_survival"] = "Начало",
["tip_survival_desc"] = "Приветствую тебя, выживший! Прошло довольно много времени с распространения вируса по планете, теперь твоя основная задача - выжить. Ты можешь найти вещи чаще всего в зданиях, они помогут тебе отбиться от атак. Если тебе не нужны подсказки, ты можешь их отключить. Удачи!",
["tip_waves"] = "Волны",
["tip_waves_desc"] = "Чем дальше ты выживаешь в этом месте, тем больше и сложнее идут зараженные, поэтому как можно быстрее ищи экипировку! С каждой их волной, натиск возрастает. Их эволюция не стоит на месте...",
["tip_items"] = "Вещи",
["tip_items_desc"] = "Экипировка, разбросанная на локации - важная часть твоего выживания. Чем выше волна, тем больше шансов найти редкое снаряжение. Кстати, на F1 ты можешь делиться вещами со своими напарниками, на F2 ты можешь пометить позицию, вещи или противника.",
["tip_bosses"] = "Главари",
["tip_bosses_desc"] = "На некоторых волнах, ты можешь встретить так называемых главарей. Главари - это самые сильные зараженные, которые руководят основной толпой. Надеюсь ты уже нашел снаряжение, так как сражение с ним будет крайне тяжелым...",
["tip_revive"] = "Реанимация",
["tip_revive_desc"] = "Когда нибудь, ты или твой напарник получит тяжелые ранения, из-за чего упадут на землю. Как можно скорее постарайся помочь своему напарнику, с каждой волной зомби лучше реагируют на упавших.",
["tip_radio"] = "Рация",
["tip_radio_desc"] = "Наконец-то ты смог найти связь с военными. Теперь ты можешь запросить у них подкрепление или эвакуацию. Советую беречь рации, так как они очень редкие. Они играют ключевую роль в твоём выживании...",
["tip_cade"] = "Молоток",
["tip_cade_desc"] = "Эта находка сильно увеличивает твои шансы выживания. Взяв в руки молоток, найдя немного гвоздей, ты сможешь построить баррикаду из подвижных подручных предметов. Чтобы приколотить предмет, нужно навестись на его край и забить гвоздь. К сожалению, прочность предметов имеет пределы, будь аккуратен!",
["tip_evac"] = "Эвакуация",
["tip_evac_desc"] = "Ну что, выживший, пора уходить отсюда. Тебе предстоит сразиться с огромной ордой зомби, чтобы продержаться и пробиться к вертолёту. Обычно полет вертолета до место посадки занимает 2 минуты. Я надеюсь мы увидим тебя живым, желаю тебе удачи.",
["class_survivor"] = "Выживший",
["class_scout"] = "Разведчик",
["class_medic"] = "Медик",
["class_engineer"] = "Инженер",
["class_marksman"] = "Стрелок",
["class_berserker"] = "Берсерк",
["class_demoman"] = "Подрывник",
["class_survivor_state_1"] = "При старте дается 1 набор экстренной помощи",
["class_survivor_state_2"] = "Теперь вы намного легче вырывайтесь из захватов",
["class_survivor_state_3"] = "Урон от огнестрельных оружий повышен на 10%",
["class_survivor_state_4"] = "Урон от огнестрельных оружий повышен на 20%",
["class_survivor_state_5"] = "Урон от огнестрельных оружий повышен на 30%",
["class_scout_state_1"] = "Возможность видеть ближайшие предметы сквозь стены",
["class_scout_state_2"] = "Скорость бега повышена на 20%",
["class_scout_state_3"] = "При старте дается 2 рации",
["class_scout_state_4"] = "Скорость бега повышена на 40%",
["class_scout_state_5"] = "При старте дается 5 раций",
["class_medic_state_1"] = "При старте дается 9 бинтов и 3 антидота",
["class_medic_state_2"] = "Теперь бинты лечат полное здоровье",
["class_medic_state_3"] = "При старте дается 18 бинтов, 6 антидотов, 3 набора экстренной помощи",
["class_medic_state_4"] = "Теперь вы моментально поднимаете упавших игроков",
["class_medic_state_5"] = "Бинты и антидоты теперь в большом количестве",
["class_engineer_state_1"] = "Прочность баррикад повышена на 10%",
["class_engineer_state_2"] = "При старте дается молоток и гвозди",
["class_engineer_state_3"] = "Прочность баррикад повышена на 50%",
["class_engineer_state_4"] = "Прочность баррикад повышена на 100%",
["class_engineer_state_5"] = "При старте даются мины",
["class_marksman_state_1"] = "При старте даются дополнительные патроны",
["class_marksman_state_2"] = "Урон со снайперских винтовок повышен на 25%",
["class_marksman_state_3"] = "Урон со снайперских винтовок повышен на 50%",
["class_marksman_state_4"] = "При старте дается случайное оружие 3 редкости",
["class_marksman_state_5"] = "Урон со снайперских винтовок повышен на 100%",
["class_berserker_state_1"] = "Урон от рукопашного оружия повышен на 50%",
["class_berserker_state_2"] = "Урон от пинка повышен в 4 раза",
["class_berserker_state_3"] = "Урон от рукопашного оружия повышен на 100%, случайное холодное оружие при спавне",
["class_berserker_state_4"] = "Уменьшение получаемого урона вдвое",
["class_berserker_state_5"] = "Урон от рукопашного оружия повышен на 200%",
["class_demoman_state_1"] = "Оглушение от урона отсутствует, уменьшен урон от взрывов",
["class_demoman_state_2"] = "Удвоенные патроны для гранатомётов",
["class_demoman_state_3"] = "Выдача M79 при старте",
["class_demoman_state_4"] = "Урон от взрывов повышен на 50%",
["class_demoman_state_5"] = "Урон от взрывов повышен на 100%",
["class_lvl_1"] = "Новичок I",
["class_lvl_2"] = "Новичок II",
["class_lvl_3"] = "Новичок III",
["class_lvl_4"] = "Новичок IV",
["class_lvl_5"] = "Новичок V",
["class_lvl_6"] = "Средний I",
["class_lvl_7"] = "Средний II",
["class_lvl_8"] = "Средний III",
["class_lvl_9"] = "Средний IV",
["class_lvl_10"] = "Средний V",
["class_lvl_11"] = "Опытный I",
["class_lvl_12"] = "Опытный II",
["class_lvl_13"] = "Опытный III",
["class_lvl_14"] = "Опытный IV",
["class_lvl_15"] = "Опытный V",
["class_lvl_16"] = "Ветеран I",
["class_lvl_17"] = "Ветеран II",
["class_lvl_18"] = "Ветеран III",
["class_lvl_19"] = "Ветеран IV",
["class_lvl_20"] = "Ветеран V",
["class_lvl_21"] = "Эксперт",
["buymenu_main"] = "Закупка",
["buymenu_buy"] = "Купить",
}

View File

@@ -0,0 +1,495 @@
local meta = FindMetaTable("Player")
function meta:PlayVoiceLine(type, chance)
net.Start("SuR.VoiceLines")
net.WriteTable({self, type, chance})
net.Broadcast()
end
function meta:CheckHitbox(pos)
pos = pos or self:GetPos()
local tr = util.TraceHull({
start = pos,
endpos = pos,
filter = self,
mins = self:OBBMins(),
maxs = self:OBBMaxs(),
mask = MASK_PLAYERSOLID
})
return !tr.Hit
end
function meta:PlaceMark()
if not self.MarkDelay then
self.MarkDelay = 0
end
if !self:Alive() or self.MarkDelay > CurTime() then return end
local type = "point"
local tr = self:GetEyeTrace()
local data = tr.HitPos
local ent = tr.Entity
if IsValid(ent) and (ent:GetClass() == "sur_loot" or ent:GetClass() == "sur_resupply") then
type = "item"
data = ent
elseif IsValid(ent) and ent.IsZombie and ent:IsNPC() then
type = "enemy"
data = ent
end
net.Start("SuR.PointMark")
net.WriteString(type)
net.WriteEntity(self)
net.WriteTable({data})
net.Send(team.GetPlayers(self:Team()))
self.MarkDelay = CurTime()+10
end
function meta:AbilityKick()
if !self:Alive() or self:GetNWString('SVAnim') != "" or self:IsLockedAbilities() then return end
local anim = "sur_kick"..math.random(1,3)
local _, ddelay = self:LookupSequence("sur_dropkick")
local delay = 0.4
if !self:OnGround() then
anim = "sur_dropkick"
delay = 0.3
end
local isdropkick = anim == "sur_dropkick"
self:SetSVAnimation(anim, true, true)
self:DropButtons()
timer.Simple(0.1, function()
if !IsValid(self) then return end
self:EmitSound("bsmod/EvilDead/punch/punch_swing_2d_0"..math.random(1,4)..".wav", 70, math.random(80,120))
end)
if isdropkick then
timer.Simple(ddelay, function()
if !IsValid(self) then return end
self:Stun(true)
end)
end
timer.Simple(delay, function()
if !IsValid(self) then return end
local tr = util.TraceLine({
start = self:GetShootPos(),
endpos = self:GetShootPos() + self:GetAimVector() * 64,
filter = self,
mask = MASK_SHOT_HULL
})
if !IsValid(tr.Entity) then
tr = util.TraceHull({
start = self:GetShootPos(),
endpos = self:GetShootPos() + self:GetAimVector() * 64,
filter = self,
mins = Vector( -10, -10, -8 ),
maxs = Vector( 10, 10, 8 ),
mask = MASK_SHOT_HULL
})
end
local ent = tr.Entity
if IsValid(ent) then
local dmg = math.random(20,40)
local npc_vel = isdropkick and ent:IsNPC()
if isdropkick then
dmg = dmg*3
self:EmitSound("bsmod/EvilDead/punch/punch_impact_face_2d_0"..math.random(1,9)..".wav", 70, math.random(80,120))
else
self:EmitSound("bsmod/EvilDead/punch/punch_impact_body_2d_0"..math.random(1,6)..".wav", 70, math.random(80,120))
end
if self:GetPlayerClass() == "berserker" and self:GetLevelState() >= 2 then
ent:TakeDamage(dmg*4, self, self)
else
ent:TakeDamage(dmg, self, self)
end
self:ViewPunch(Angle(10,0,0))
local phys = ent:GetPhysicsObject()
if IsValid(phys) then
phys:SetVelocity(self:GetForward()*150+Vector(0,0,50))
end
if npc_vel then
ent:SetPos(ent:GetPos()+Vector(0,0,8))
ent:SetVelocity(self:GetForward()*1000)
end
if ent.IsVJBaseSNPC and (ent:Health() < 250 or isdropkick and ent:Health() < 1000) and not ent.LNR_Crawler then
ent.Flinching = true
ent:StopAttacks(true)
ent.PlayingAttackAnimation = false
local animTbl = ent.AnimTbl_Flinch
if HitgroupInfo != nil then animTbl = HitgroupInfo.Animation end
local anim = istable(animTbl) and VJ_PICK(animTbl) or animTbl
local animDur = ent.NextMoveAfterFlinchTime
if animDur == false and anim then
animDur = ent:DecideAnimationLength(anim, false, ent.FlinchAnimationDecreaseLengthAmount)
end
animDur = tonumber(animDur) or 0.1
if animDur <= 0 then
animDur = 0.1
end
if anim then
ent:VJ_ACT_PLAYACTIVITY(anim, true, animDur, false, 0, {SequenceDuration=animDur, PlayBackRateCalculated=true})
end
timer.Create("timer_act_flinching"..ent:EntIndex(), tonumber(animDur) or 0.1, 1, function() ent.Flinching = false end)
if isfunction(ent.CustomOnFlinch_AfterFlinch) then
ent:CustomOnFlinch_AfterFlinch(dmginfo, hitgroup)
end
ent.NextFlinchT = CurTime() + (tonumber(ent.NextFlinchTime) or 0)
end
if ent:IsPlayer() and ent:IsZombie() then
ent:Stun()
end
end
end)
end
function meta:AbilityGrenade()
if !self:Alive() or self:GetNWString('SVAnim') != "" or self:IsLockedAbilities() or self:GetNWInt('Grenades') <= 0 then return end
self:SetSVAnimation("sur_throw_grenade", true, true, true)
self:DropButtons()
self:SetNWInt('Grenades', self:GetNWInt('Grenades')-1)
timer.Simple(1.6, function()
if !IsValid(self) then return end
local grenade = ents.Create("obj_vj_grenade_sur")
grenade:SetPos(self:GetBonePosition(self:LookupBone("ValveBiped.Bip01_L_Hand")))
grenade:SetAngles(self:EyeAngles())
grenade:Spawn()
grenade:Activate()
grenade:GetPhysicsObject():ApplyForceCenter(self:GetAimVector() * 512 + Vector(0,0,128))
end)
end
function meta:AbilityVault()
if !self:Alive() or self:GetNWString('SVAnim') != "" or self:IsLockedAbilities() or !self:GetNWBool('CanVault') then return end
self:SetSVAnimation("sur_vault1", true, true, true)
self:Freeze(true)
self:DropButtons()
local i = 0
timer.Create("Vaulting"..self:EntIndex(), 0.033, 60, function()
if !IsValid(self) then return end
i = i + 1
if i == 20 then
self:EmitSound("npc/footsteps/hardboot_generic"..math.random(1,6)..".wav", 70, 80)
end
if i == 60 then
self:SetPos(self:GetPos()+self:GetForward()*60)
self:Freeze(false)
end
end)
end
function meta:AbilityHealing(teammate)
if IsValid(teammate) then
if !self:Alive() or self:GetNWString('SVAnim') != "" or self:IsLockedAbilities() or self:GetNWFloat("Bandages") <= 0 then return end
if !IsValid(self.LastPickupWeapon) then
self.LastPickupWeapon = self:GetActiveWeapon()
end
self:SetActiveWeapon(nil)
local _, dur = self:LookupSequence("sur_heal_friend")
self:SetSVAnimation("sur_heal_friend", true, true, true)
self:EmitSound("surrounded/player/healing.wav", 70)
self:PlayVoiceLine("cover", 10)
self:SetNWFloat("Bandages", self:GetNWFloat("Bandages")-1)
self:Freeze(true)
teammate:SetSVAnimation("idle_all_scared", false, true, false)
teammate:DropButtons()
timer.Simple(dur, function()
if !IsValid(self) then return end
self:Freeze(false)
if IsValid(self.LastPickupWeapon) then
local class = self.LastPickupWeapon:GetClass()
self:SelectWeapon(class)
self.LastPickupWeapon = nil
end
SuR:MessageOnClient(17, teammate:Nick(), self)
if !IsValid(teammate) then return end
SuR:MessageOnClient(16, self:Nick(), teammate)
if self:GetPlayerClass() == "medic" and self:GetLevelState() >= 2 then
teammate:SetHealth(teammate:GetMaxHealth())
else
teammate:SetHealth(math.Clamp(teammate:Health()+50, 1, 100))
end
teammate:PlayVoiceLine("thanks")
teammate:SetSVAnimation("")
end)
else
if !self:Alive() or self:GetNWString('SVAnim') != "" or self:IsLockedAbilities() or !self:GetNWBool('CanHeal') or self:GetNWFloat("Bandages") <= 0 then return end
if !IsValid(self.LastPickupWeapon) then
self.LastPickupWeapon = self:GetActiveWeapon()
end
self:SetActiveWeapon(nil)
local _, dur = self:LookupSequence("sur_healing")
self:SetSVAnimation("sur_healing", true, true, true)
self:EmitSound("surrounded/player/healing.wav", 70)
self:PlayVoiceLine("cover", 10)
self:SetNWFloat("Bandages", self:GetNWFloat("Bandages")-1)
self:DropButtons()
timer.Simple(dur, function()
if !IsValid(self) then return end
if self:GetPlayerClass() == "medic" and self:GetLevelState() >= 2 then
self:SetHealth(self:GetMaxHealth())
else
self:SetHealth(math.Clamp(self:Health()+50, 1, 100))
end
if IsValid(self.LastPickupWeapon) then
local class = self.LastPickupWeapon:GetClass()
self:SelectWeapon(class)
self.LastPickupWeapon = nil
end
end)
end
end
function meta:AbilitySpray(teammate)
if IsValid(teammate) then
if !self:Alive() or self:GetNWString('SVAnim') != "" or self:IsLockedAbilities() or !teammate:GetNWBool("IsInfected") or self:GetNWFloat("Sprays") <= 0 then return end
if !IsValid(self.LastPickupWeapon) then
self.LastPickupWeapon = self:GetActiveWeapon()
end
self:SetActiveWeapon(nil)
local _, dur = self:LookupSequence("sur_heal_friend")
self:SetSVAnimation("sur_heal_friend", true, true, true)
self:EmitSound("surrounded/player/spray.mp3", 70)
self:PlayVoiceLine("cover", 10)
self:SetNWFloat("Sprays", self:GetNWFloat("Sprays")-1)
self:Freeze(true)
teammate:SetSVAnimation("idle_all_scared", false, true, false)
teammate:DropButtons()
timer.Simple(dur, function()
if !IsValid(self) then return end
self:Freeze(false)
if IsValid(self.LastPickupWeapon) then
local class = self.LastPickupWeapon:GetClass()
self:SelectWeapon(class)
self.LastPickupWeapon = nil
end
SuR:MessageOnClient(17, teammate:Nick(), self)
if !IsValid(teammate) then return end
teammate:SetSVAnimation("")
teammate:PlayVoiceLine("thanks")
SuR:MessageOnClient(16, self:Nick(), teammate)
SuR:StopInfection(teammate)
end)
else
if !self:Alive() or self:GetNWString('SVAnim') != "" or self:IsLockedAbilities() or !self:GetNWBool("IsInfected") or self:GetNWFloat("Sprays") <= 0 then return end
if !IsValid(self.LastPickupWeapon) then
self.LastPickupWeapon = self:GetActiveWeapon()
end
self:SetActiveWeapon(nil)
local _, dur = self:LookupSequence("sur_healing")
self:SetSVAnimation("sur_healing", true, true, true)
self:EmitSound("surrounded/player/spray.mp3", 70)
self:PlayVoiceLine("cover", 10)
self:SetNWFloat("Sprays", self:GetNWFloat("Sprays")-1)
self:DropButtons()
timer.Simple(dur, function()
if !IsValid(self) then return end
SuR:StopInfection(self)
if IsValid(self.LastPickupWeapon) then
local class = self.LastPickupWeapon:GetClass()
self:SelectWeapon(class)
self.LastPickupWeapon = nil
end
end)
end
end
function meta:Stun(nofall, count)
if !self:Alive() or self:IsDowned() or self:IsStunned() or self:Health() > 250 or self.ExecutingTarget or self:GetPlayerClass() == "demoman" and self:GetLevelState() >= 1 then return end
if self:IsZombie() then
local anim = "shove_backwards_10"
local _, dur = self:LookupSequence(anim)
self:SetSVAnimation(anim, false, true, true)
self:Freeze(true)
self:EmitSound("physics/body/body_medium_impact_hard"..math.random(1,6)..".wav", 70, 90)
timer.Create("StunAnim"..self:EntIndex(), dur, 1, function()
if !IsValid(self) then return end
if anim == self:GetNWString('SVAnim') then
self:SetSVAnimation(sanim, true, true)
end
local _, dur = self:LookupSequence(sanim)
timer.Create("StunAnim"..self:EntIndex(), dur, 1, function()
if !IsValid(self) then return end
self:Freeze(false)
end)
end)
else
if not count then
count = 0
end
self.FallPressCount = 0
self.FallPressMax = count
if nofall then
if count > 0 then
self:SetSVAnimation("sur_fall_idle", false, true)
else
self:SetSVAnimation("sur_fall_standup", true, true)
end
else
local anim = "sur_fall_down"
local _, dur = self:LookupSequence(anim)
self:SetSVAnimation(anim, false, true)
self:EmitSound("physics/body/body_medium_impact_hard"..math.random(1,6)..".wav", 70, 90)
timer.Create("StunAnim"..self:EntIndex(), dur, 1, function()
if !IsValid(self) then return end
if count > 0 then
self:SetSVAnimation("sur_fall_idle", false, true)
else
self:SetSVAnimation("sur_fall_standup", true, true)
end
end)
end
end
end
hook.Add("PlayerButtonDown", "SuR_ButtonHookQTEStun", function(ply, but)
if ply:IsStunned(true) and but == KEY_SPACE and ply:OnGround() then
if ply.FallPressCount < ply.FallPressMax then
if ply:GetPlayerClass() == "survivor" and ply:GetLevelState() >= 2 then
ply.FallPressCount = ply.FallPressCount + 2
else
ply.FallPressCount = ply.FallPressCount + 1
end
else
ply:SetSVAnimation("sur_fall_standup", true, true)
end
end
end)
hook.Add("OnPlayerJump", "SuR.BlockJump", function(ply, speed)
if ply:IsDowned() or ply:IsStunned() then
ply:SetVelocity(-Vector(0,0,speed))
end
end)
net.Receive("SuR.SelectPlayerModel", function(len, ply)
local model = net.ReadString()
if #SuR.Config.Allowed_PlayerModels > 0 then
if file.Exists(model, "GAME") and table.HasValue(player_manager.AllValidModels(), model) and table.HasValue(SuR.Config.Allowed_PlayerModels, model) and (not SuR.Wave_Started or !ply:Alive()) then
ply:SetNWString('SuR_PlayerModel', model)
if not ply:Alive() then
ply:SetModel(model)
end
end
else
if file.Exists(model, "GAME") and table.HasValue(player_manager.AllValidModels(), model) and not table.HasValue(SuR.Config.Blocked_PlayerModels, model) and (not SuR.Wave_Started or !ply:Alive()) then
ply:SetNWString('SuR_PlayerModel', model)
if not ply:Alive() then
ply:SetModel(model)
end
end
end
end)
net.Receive("SuR.ChooseVoicePack", function(len, ply)
local voice = net.ReadString()
if istable(SuR.Config.VoicePacks[voice]) and (not SuR.Wave_Started or !ply:Alive()) then
ply:SetNWString('VoicePack', voice)
end
end)
net.Receive("SuR.RadioSupport", function(len, ply)
local fl = net.ReadFloat()
if ply:GetNWFloat('CanCallSupport') > 0 then
ply:SetNWFloat('CanCallSupport', ply:GetNWFloat('CanCallSupport')-1)
SuR:CallSupport(ply, fl)
end
end)
net.Receive("SuR.ChooseStartWeapon", function(len, ply)
local str = net.ReadString()
if (table.HasValue(SuR.Config.TierWeapons["Tier1"], str) or table.HasValue(SuR.Config.TierWeapons["Tier2"], str) and ply:GetNWBool("ExtendedStartWeapons")) and (not SuR.Wave_Started or !ply:Alive()) then
ply:SetNWString('StartWeapon', str)
end
end)
local function create_item(self, id)
local tr = util.TraceLine( {
start = self:EyePos(),
endpos = self:EyePos() + self:GetAimVector() * 50,
filter = self,
mask = MASK_SOLID,
})
local ent = ents.Create("sur_loot")
ent.LootType = id
ent:SetPos(tr.HitPos)
ent:Spawn()
ent.IsLoot = true
end
concommand.Add("sur_dropweapon", function(ply, cmd, args)
if not args[1] or !ply:Alive() or ply:IsLockedAbilities() or ply:IsZombie() then return end
local arg = args[1]
BroadcastLua([[Entity(]]..ply:EntIndex()..[[):AnimRestartGesture(6, ACT_GMOD_GESTURE_ITEM_DROP, true)]])
local type = "weapon"
if arg == "bandage" or arg == "antidote" or arg == "selfrevive" or arg == "radio" then
type = arg
end
timer.Simple(0.2, function()
if !IsValid(ply) then return end
if type == "weapon" then
ply:CreateDroppedWeapon(arg)
if arg == ply:GetNWString('MeleeWeapon') then
ply:Give(SuR.Config.EmptyWeapon)
ply:SelectWeapon(SuR.Config.EmptyWeapon)
ply:SetNWString('MeleeWeapon', SuR.Config.EmptyWeapon)
end
elseif type == "bandage" and ply:GetNWFloat('Bandages') > 2 then
create_item(ply, 8)
ply:SetNWFloat('Bandages', ply:GetNWFloat('Bandages')-3)
elseif type == "antidote" and ply:GetNWFloat('Sprays') > 0 then
create_item(ply, 7)
ply:SetNWFloat('Sprays', ply:GetNWFloat('Sprays')-1)
elseif type == "selfrevive" and ply:GetNWFloat('SelfRevive') > 0 then
create_item(ply, 12)
ply:SetNWFloat('SelfRevive', ply:GetNWFloat('SelfRevive')-1)
elseif type == "radio" and ply:GetNWFloat('CanCallSupport') > 0 then
create_item(ply, 6)
ply:SetNWFloat('CanCallSupport', ply:GetNWFloat('CanCallSupport')-1)
end
ply:EmitSound("npc/vort/claw_swing"..math.random(1,2)..".wav", 60, math.random(80,100))
end)
end)

View File

@@ -0,0 +1,15 @@
net.Receive("SuR.BuyMenu", function(len, ply)
local item = net.ReadString()
if ply:GetNWFloat('CanCallSupport') <= 0 then return end
local price = 0
if table.HasValue(SuR.Config.TierWeapons["Tier2"], item) then price = SuR.Config.Tier2_Price end
if table.HasValue(SuR.Config.TierWeapons["Tier3"], item) then price = SuR.Config.Tier3_Price end
if table.HasValue(SuR.Config.TierWeapons["Tier4"], item) then price = SuR.Config.Tier4_Price end
if table.HasValue(SuR.Config.TierWeapons["Tier5"], item) then price = SuR.Config.Tier5_Price end
if price == 0 or ply:GetNWInt('Money') < price then return end
ply:SetNWFloat('CanCallSupport', ply:GetNWFloat('CanCallSupport')-1)
ply:SetNWInt('Money', ply:GetNWInt('Money')-price)
ply:Give(item)
end)

View File

@@ -0,0 +1,99 @@
local meta = FindMetaTable("Player")
local start_xp = SuR.Config.Start_Level_XP
local lvl_mult = SuR.Config.Level_Progress_Mult
file.CreateDir("surrounded/level/")
function meta:SetPlayerClass(id)
id = id or "survivor"
self:SetNWString("PlayerClass", id)
local lvl, xp = unpack(self.LevelTab[id])
local class = self:GetPlayerClass()
self:SetLevel(lvl)
self:AddXP(xp)
end
function meta:SetLevel(lvl)
if !isnumber(lvl) or lvl < 1 then return end
self:SetNWFloat("PlayerLevel", math.min(lvl, 21))
self:SetNWFloat("PlayerXP", 0)
local class = self:GetPlayerClass()
local lvl, cur_xp = self:GetLevel()
self.LevelTab[class] = {lvl, cur_xp}
end
function meta:AddXP(num)
if !isnumber(num) or self:GetLevel() >= 21 then return end
local lvl, cur_xp = self:GetLevel()
self:SetNWFloat("PlayerXP", math.max(cur_xp+num, 0))
local need = self:GetXPToLevel()
if need == 0 then
self:SetLevel(lvl+1)
end
local class = self:GetPlayerClass()
local lvl, cur_xp = self:GetLevel()
self.LevelTab[class] = {lvl, cur_xp}
end
function meta:LoadLevelProgress()
local id = self:SteamID64()
local f = file.Read("surrounded/level/"..id..".json", "DATA")
local tab = {
["survivor"] = {1, 0},
["scout"] = {1, 0},
["medic"] = {1, 0},
["engineer"] = {1, 0},
["marksman"] = {1, 0},
["berserker"] = {1, 0},
["demoman"] = {1, 0},
cur_class = "survivor"
}
if isstring(f) then
f = util.JSONToTable(f)
tab = f
end
self.LevelTab = tab
self:SetPlayerClass(tab.cur_class)
end
function meta:SaveLevelProgress()
local id = self:SteamID64()
local lvl, cur_xp = self:GetLevel()
local tab = {}
for k, v in pairs(self.LevelTab) do
tab[k] = v
end
tab.cur_class = self:GetPlayerClass()
file.Write("surrounded/level/"..id..".json", util.TableToJSON(tab, true))
end
hook.Add("PlayerDisconnected", "SuR.SaveProgress", function(ply)
ply:SaveLevelProgress()
end)
hook.Add("ShutDown", "SuR.SaveProgress", function()
for _, ply in ipairs(player.GetAll()) do
ply:SaveLevelProgress()
end
end)
concommand.Add("sur_selectclass", function(ply, cmd, args)
local str = args[1]
if not str or ply:Alive() then return end
if not SuR.Config.ClassIcons[str] then return end
ply:SetPlayerClass(str)
end)
net.Receive("SuR.OpenClassMenu", function(len, ply)
net.Start("SuR.OpenClassMenu")
net.WriteTable(ply.LevelTab)
net.Send(ply)
end)

Some files were not shown because too many files have changed in this diff Show More